1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
4 ////////////////////////////////////////////////////////////////////
6 Module Name: Phys_lib.cpp
8 Execution: Kernel mode only
12 Contains code that implement read/write operations for physical device
17 static const char Signature
[16] = {CDRW_SIGNATURE_v1
};
38 IN OUT uint32
* retry
);
44 IN PVCB Vcb
, // Volume control block from this DevObj
55 KdPrint(("UDFSyncCache:\n"));
57 RC
= UDFPhSendIOCTL( IOCTL_CDRW_SYNC_CACHE
, Vcb
->TargetDeviceObject
,
58 NULL
,0, NULL
,0, FALSE
, NULL
);
60 // clear LAST_WRITE flag
61 Vcb
->VCBFlags
&= ~UDF_VCB_LAST_WRITE
;
64 } // end UDFSyncCache()
75 MyFreePool__(Vcb
->TrackMap
);
78 Vcb
->TrackMap
= (PUDFTrackMap
)
79 MyAllocatePool__(NonPagedPool
, TrackNum
*sizeof(UDFTrackMap
));
81 return STATUS_INSUFFICIENT_RESOURCES
;
84 RtlZeroMemory(Vcb
->TrackMap
,TrackNum
*sizeof(UDFTrackMap
));
85 return STATUS_SUCCESS
;
86 } // end UDFReallocTrackMap()
95 IN
void* Buffer
, // Target buffer
102 OSSTATUS RC
= STATUS_SUCCESS
;
105 uint32 lba0
, len
, lba1
;
111 OSSTATUS final_RC
= STATUS_SUCCESS
;
115 BOOLEAN free_tmp
= FALSE
;
116 BOOLEAN single_packet
= FALSE
;
118 #define Vcb ((PVCB)_Vcb)
119 // ATTENTION! Do not touch bad block bitmap here, since it describes PHYSICAL addresses WITHOUT remapping,
120 // while here we work with LOGICAL addresses
122 if(Vcb
->VerifyCtx
.ItemCount
> UDF_MAX_VERIFY_CACHE
) {
123 UDFVVerify(Vcb
, 0/*UFD_VERIFY_FLAG_WAIT*/);
126 UDFAcquireResourceExclusive(&(Vcb
->IoResource
), TRUE
);
127 Flags
|= PH_IO_LOCKED
;
129 tmp_wb
= (uint32
)_Vcb
;
130 if(Flags
& PH_EX_WRITE
) {
131 KdPrint(("IO-Write-Verify\n"));
132 RC
= UDFTWrite(_Vcb
, Buffer
, Length
, LBA
, &tmp_wb
, Flags
| PH_VCB_IN_RETLEN
);
134 KdPrint(("IO-Read-Verify\n"));
135 RC
= UDFTRead(_Vcb
, Buffer
, Length
, LBA
, &tmp_wb
, Flags
| PH_VCB_IN_RETLEN
);
141 UDFReleaseResource(&(Vcb
->IoResource
));
143 case STATUS_FT_WRITE_RECOVERY
:
144 case STATUS_DEVICE_DATA_ERROR
:
145 case STATUS_IO_DEVICE_ERROR
:
150 if(!Vcb
->SparingCount
||
151 !Vcb
->SparingCountFree
||
153 KdPrint(("Can't remap\n"));
154 UDFReleaseResource(&(Vcb
->IoResource
));
158 if(Flags
& PH_EX_WRITE
) {
159 KdPrint(("Write failed, try relocation\n"));
162 KdPrint(("Read failed, try relocation\n"));
164 KdPrint(("no remap on not modified volume\n"));
165 UDFReleaseResource(&(Vcb
->IoResource
));
169 if(Flags
& PH_LOCK_CACHE
) {
170 UDFReleaseResource(&(Vcb
->IoResource
));
171 WCacheStartDirect__(&(Vcb
->FastCache
), Vcb
, TRUE
);
172 UDFAcquireResourceExclusive(&(Vcb
->IoResource
), TRUE
);
175 Flags
&= ~PH_KEEP_VERIFY_CACHE
;
177 // NOTE: SparingBlockSize may be not equal to PacketSize
179 mask
= Vcb
->SparingBlockSize
-1;
181 len
= ((LBA
+(Length
>>Vcb
->BlockSizeBits
)+mask
) & ~mask
) - lba0
;
183 if((lba0
== LBA
) && (len
== mask
+1) && (len
== (Length
>>Vcb
->BlockSizeBits
))) {
184 single_packet
= TRUE
;
187 tmp_buff
= (PUCHAR
)DbgAllocatePoolWithTag(NonPagedPool
, Vcb
->SparingBlockSize
<< Vcb
->BlockSizeBits
, 'bNWD');
189 KdPrint((" can't alloc tmp\n"));
190 UDFReleaseResource(&(Vcb
->IoResource
));
191 return STATUS_DEVICE_DATA_ERROR
;
196 for(i
=0; i
<len
; i
++) {
197 if(!Vcb
->SparingCountFree
) {
198 KdPrint((" no more free spare blocks, abort verification\n"));
201 KdPrint((" read LBA %x (%x)\n", lba0
+i
, j
));
207 // single packet requested
208 tmp_buff
= (PUCHAR
)Buffer
;
209 if(Flags
& PH_EX_WRITE
) {
210 KdPrint((" remap single write\n"));
211 KdPrint((" try del from verify cache @ %x, %x\n", lba0
, len
));
212 UDFVForget(Vcb
, len
, UDFRelocateSector(Vcb
, lba0
), 0);
215 KdPrint((" recover and remap single read\n"));
219 p
= tmp_buff
+(j
<<Vcb
->BlockSizeBits
);
220 // not cached, try to read
221 // prepare for error, if block cannot be read, assume it is zero-filled
222 RtlZeroMemory(p
, Vcb
->BlockSize
);
224 // check if block valid
225 if(Vcb
->BSBM_Bitmap
) {
226 if(UDFGetBit__((uint32
*)(Vcb
->BSBM_Bitmap
), UDFRelocateSector(Vcb
, lba0
+i
))) {
227 KdPrint((" remap: known BB @ %x, mapped to %x\n", lba0
+i
, UDFRelocateSector(Vcb
, lba0
+i
)));
232 if(Vcb
->FSBM_Bitmap
) {
233 if(UDFGetFreeBit((uint32
*)(Vcb
->FSBM_Bitmap
), lba0
+i
)) {
234 KdPrint((" unused @ %x\n", lba0
+i
));
238 if(!zero
&& Vcb
->ZSBM_Bitmap
) {
239 if(UDFGetZeroBit((uint32
*)(Vcb
->ZSBM_Bitmap
), lba0
+i
)) {
240 KdPrint((" unused @ %x (Z)\n", lba0
+i
));
249 // try to read entire packet, this returs error more often then sequential reading of all blocks one by one
250 tmp_wb
= (uint32
)_Vcb
;
251 RC
= UDFTRead(_Vcb
, p
, Vcb
->SparingBlockSize
<< Vcb
->BlockSizeBits
, lba0
+i
, &tmp_wb
,
252 Flags
| PH_READ_VERIFY_CACHE
| PH_TMP_BUFFER
| PH_VCB_IN_RETLEN
);
254 // Note: we get here ONLY if original request failed
255 // do not retry if it was single-packet request
256 RC
= STATUS_UNSUCCESSFUL
;
258 if(RC
== STATUS_SUCCESS
) {
259 KdPrint((" packet ok @ %x\n", lba0
+i
));
261 i
+= Vcb
->SparingBlockSize
-1;
269 if(WCacheIsCached__(&(Vcb
->FastCache
), lba0
+i
, 1)) {
270 // even if block is cached, we have to verify if it is readable
271 if(!packet_ok
&& !UDFVIsStored(Vcb
, lba0
+i
)) {
273 tmp_wb
= (uint32
)_Vcb
;
274 RC
= UDFTRead(_Vcb
, p
, Vcb
->BlockSize
, lba0
+i
, &tmp_wb
,
275 Flags
| PH_FORGET_VERIFIED
| PH_READ_VERIFY_CACHE
| PH_TMP_BUFFER
| PH_VCB_IN_RETLEN
);
276 if(!OS_SUCCESS(RC
)) {
277 KdPrint((" Found BB @ %x\n", lba0
+i
));
281 RC
= WCacheDirect__(&(Vcb
->FastCache
), _Vcb
, lba0
+i
, FALSE
, &cached_block
, TRUE
/* cached only */);
285 RC
= STATUS_UNSUCCESSFUL
;
291 // cached or successfully read
293 // we can get from cache the most fresh data
294 RtlCopyMemory(p
, cached_block
, Vcb
->BlockSize
);
298 if(!UDFVIsStored(Vcb
, lba0
+i
)) {
299 tmp_wb
= (uint32
)_Vcb
;
300 RC
= UDFTRead(_Vcb
, p
, Vcb
->BlockSize
, lba0
+i
, &tmp_wb
,
301 Flags
| PH_FORGET_VERIFIED
| PH_READ_VERIFY_CACHE
| PH_TMP_BUFFER
| PH_VCB_IN_RETLEN
);
303 // get it from verify-cache
304 RC
= STATUS_UNSUCCESSFUL
;
306 if(!OS_SUCCESS(RC
)) {
308 KdPrint((" retry @ %x\n", lba0+i));
309 tmp_wb = (uint32)_Vcb;
310 RC = UDFTRead(_Vcb, p, Vcb->BlockSize, lba0+i, &tmp_wb,
311 Flags | PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN);
313 KdPrint((" try get from verify cache @ %x\n", lba0
+i
));
314 RC
= UDFVRead(Vcb
, p
, 1, UDFRelocateSector(Vcb
, lba0
+i
),
315 Flags
| PH_FORGET_VERIFIED
| PH_READ_VERIFY_CACHE
| PH_TMP_BUFFER
);
320 RtlZeroMemory(p
, Vcb
->BlockSize
);
323 KdPrint((" try del from verify cache @ %x\n", lba0
+i
));
324 RC
= UDFVForget(Vcb
, 1, UDFRelocateSector(Vcb
, lba0
+i
), 0);
327 if(!packet_ok
|| need_remap
) {
328 KdPrint((" block in bad packet @ %x\n", lba0
+i
));
329 if(Vcb
->BSBM_Bitmap
) {
330 UDFSetBit(Vcb
->BSBM_Bitmap
, lba0
+i
);
332 if(Vcb
->FSBM_Bitmap
) {
333 UDFSetUsedBit(Vcb
->FSBM_Bitmap
, lba0
+i
);
338 if(j
>= Vcb
->SparingBlockSize
) {
343 KdPrint((" forget Z packet @ %x\n", lba1
));
344 UDFUnmapRange(Vcb
, lba1
, Vcb
->SparingBlockSize
);
349 KdPrint((" remap packet @ %x\n", lba1
));
350 RC
= UDFRemapPacket(Vcb
, lba1
, FALSE
);
351 if(!OS_SUCCESS(RC
)) {
352 if(RC
== STATUS_SHARING_VIOLATION
) {
353 KdPrint((" remap2\n"));
354 // remapped location have died
355 RC
= UDFRemapPacket(Vcb
, lba1
, TRUE
);
357 if(!OS_SUCCESS(RC
)) {
358 // packet cannot be remapped :(
359 RC
= STATUS_DEVICE_DATA_ERROR
;
362 KdPrint((" remap status %x\n", RC
));
364 // write to remapped area
365 tmp_wb
= (uint32
)_Vcb
;
366 RC
= UDFTWrite(_Vcb
, tmp_buff
, Vcb
->SparingBlockSize
<< Vcb
->BlockSizeBits
, lba1
, &tmp_wb
,
367 Flags
| PH_FORGET_VERIFIED
| PH_READ_VERIFY_CACHE
| PH_TMP_BUFFER
| PH_VCB_IN_RETLEN
);
368 KdPrint((" write status %x\n", RC
));
369 if(RC
!= STATUS_SUCCESS
) {
371 KdPrint((" retry remap\n"));
373 // Note: when remap of already remapped block is requested, verify of
374 // entire sparing are will be performed.
377 KdPrint((" remap OK\n"));
381 KdPrint((" failed remap\n"));
386 if(!OS_SUCCESS(RC
) && !OS_SUCCESS(final_RC
)) {
390 KdPrint((" NO remap for @ %x\n", (lba0
+i
) & ~mask
));
396 DbgFreePool(tmp_buff
);
399 tmp_wb
= (uint32
)_Vcb
;
400 if(Flags
& PH_EX_WRITE
) {
401 KdPrint(("IO-Write-Verify (2)\n"));
402 //RC = UDFTWrite(_Vcb, Buffer, Length, LBA, &tmp_wb, Flags | PH_FORGET_VERIFIED | PH_VCB_IN_RETLEN);
404 KdPrint(("IO-Read-Verify (2)\n"));
405 RC
= UDFTRead(_Vcb
, Buffer
, Length
, LBA
, &tmp_wb
, Flags
| PH_FORGET_VERIFIED
| PH_VCB_IN_RETLEN
);
408 KdPrint(("Final %x\n", RC
));
410 UDFReleaseResource(&(Vcb
->IoResource
));
411 if(Flags
& PH_LOCK_CACHE
) {
412 WCacheEODirect__(&(Vcb
->FastCache
), Vcb
);
416 } // end UDFTIOVerify()
421 IN
void* Buffer
, // Target buffer
424 OUT uint32
* WrittenBytes
,
428 return UDFTIOVerify(_Vcb
, Buffer
, Length
, LBA
, WrittenBytes
, Flags
| PH_VCB_IN_RETLEN
| PH_EX_WRITE
| PH_KEEP_VERIFY_CACHE
);
429 } // end UDFTWriteVerify()
434 IN
void* Buffer
, // Target buffer
437 OUT uint32
* ReadBytes
,
441 return UDFTIOVerify(_Vcb
, Buffer
, Length
, LBA
, ReadBytes
, Flags
| PH_VCB_IN_RETLEN
| PH_KEEP_VERIFY_CACHE
);
442 } // end UDFTReadVerify()
443 #endif //_BROWSE_UDF_
446 This routine performs low-level write
448 ATTENTION! When we are in Variable-Packet mode (CDR_Mode = TRUE)
449 LBA is ignored and assumed to be equal to NWA by CD-R(W) driver
454 IN
void* Buffer
, // Target buffer
457 OUT uint32
* WrittenBytes
,
461 #ifndef UDF_READ_ONLY_BUILD
462 #define Vcb ((PVCB)_Vcb)
465 PEXTENT_MAP RelocExtent
;
466 PEXTENT_MAP RelocExtent_saved
= NULL
;
467 #endif //_BROWSE_UDF_
469 BOOLEAN res_acq
= FALSE
;
471 OSSTATUS RC
= STATUS_SUCCESS
;
477 //ASSERT(!(LBA & (32-1)));
481 BCount
= Length
>>Vcb
->BlockSizeBits
;
483 KdPrint(("TWrite %x (%x)\n", LBA
, BCount
));
485 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_DEAD
) {
487 return STATUS_NO_SUCH_DEVICE
;
490 Vcb
->VCBFlags
|= (UDF_VCB_SKIP_EJECT_CHECK
| UDF_VCB_LAST_WRITE
);
492 RelocExtent
= UDFRelocateSectors(Vcb
, LBA
, BCount
);
494 KdPrint(("can't relocate\n"));
495 return STATUS_INSUFFICIENT_RESOURCES
;
499 RelocExtent
= UDF_NO_EXTENT_MAP
;
504 #endif //_BROWSE_UDF_
507 //ASSERT(!(rLba & (32-1)));
513 if(!(Flags
& PH_IO_LOCKED
)) {
514 UDFAcquireResourceExclusive(&(Vcb
->IoResource
), TRUE
);
518 if(RelocExtent
== UDF_NO_EXTENT_MAP
) {
519 #endif //_BROWSE_UDF_
520 retry
= UDF_WRITE_MAX_RETRY
;
522 RC
= UDFPrepareForWriteOperation(Vcb
, rLba
, BCount
);
523 if(!OS_SUCCESS(RC
)) {
524 KdPrint(("prepare failed\n"));
527 if(Flags
& PH_VCB_IN_RETLEN
) {
528 (*WrittenBytes
) = (ULONG
)Vcb
;
530 RC
= UDFPhWriteVerifySynchronous(Vcb
->TargetDeviceObject
, Buffer
, Length
,
531 ((uint64
)rLba
) << Vcb
->BlockSizeBits
, WrittenBytes
, Flags
);
533 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
534 #endif //_BROWSE_UDF_
535 if(!OS_SUCCESS(RC
) &&
536 OS_SUCCESS(RC
= UDFRecoverFromError(Vcb
, TRUE
, RC
, rLba
, BCount
, &retry
)) )
538 UDFUpdateNWA((PVCB
)_Vcb
, rLba
, BCount
, RC
);
542 // write according to relocation table
543 RelocExtent_saved
= RelocExtent
;
544 for(i
=0; RelocExtent
->extLength
; i
++, RelocExtent
++) {
545 uint32 _WrittenBytes
;
546 rLba
= RelocExtent
->extLocation
;
547 BCount
= RelocExtent
->extLength
>>Vcb
->BlockSizeBits
;
548 retry
= UDF_WRITE_MAX_RETRY
;
550 RC
= UDFPrepareForWriteOperation(Vcb
, rLba
, BCount
);
551 if(!OS_SUCCESS(RC
)) {
552 KdPrint(("prepare failed (2)\n"));
555 if(Flags
& PH_VCB_IN_RETLEN
) {
556 _WrittenBytes
= (ULONG
)Vcb
;
558 RC
= UDFPhWriteVerifySynchronous(Vcb
->TargetDeviceObject
, Buffer
, RelocExtent
->extLength
,
559 ((uint64
)rLba
) << Vcb
->BlockSizeBits
, &_WrittenBytes
, Flags
);
560 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
561 if(!OS_SUCCESS(RC
) &&
562 OS_SUCCESS(RC
= UDFRecoverFromError(Vcb
, TRUE
, RC
, rLba
, BCount
, &retry
)) )
564 UDFUpdateNWA((PVCB
)_Vcb
, rLba
, BCount
, RC
);
566 (*WrittenBytes
) += _WrittenBytes
;
567 if(!OS_SUCCESS(RC
)) break;
568 *((uint32
*)&Buffer
) += RelocExtent
->extLength
;
570 #endif //_BROWSE_UDF_
574 UDFReleaseResource(&(Vcb
->IoResource
));
577 if(RelocExtent_saved
) {
578 MyFreePool__(RelocExtent_saved
);
580 #endif //_BROWSE_UDF_
582 KdPrint(("TWrite: %x\n", RC
));
586 #else //UDF_READ_ONLY_BUILD
587 return STATUS_ACCESS_DENIED
;
588 #endif //UDF_READ_ONLY_BUILD
592 This routine performs low-level read
597 IN
void* Buffer
, // Target buffer
600 OUT uint32
* ReadBytes
,
605 OSSTATUS RC
= STATUS_SUCCESS
;
607 PVCB Vcb
= (PVCB
)_Vcb
;
608 uint32 BCount
= Length
>> Vcb
->BlockSizeBits
;
611 PEXTENT_MAP RelocExtent
;
612 PEXTENT_MAP RelocExtent_saved
= NULL
;
613 BOOLEAN res_acq
= FALSE
;
614 // LARGE_INTEGER delay;
615 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
621 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_DEAD
)
622 return STATUS_NO_SUCH_DEVICE
;
624 RelocExtent
= UDFRelocateSectors(Vcb
, LBA
, BCount
);
625 if(!RelocExtent
) return STATUS_INSUFFICIENT_RESOURCES
;
629 if(!(Flags
& PH_IO_LOCKED
)) {
630 UDFAcquireResourceExclusive(&(Vcb
->IoResource
), TRUE
);
634 if(RelocExtent
== UDF_NO_EXTENT_MAP
) {
636 if(rLba
>= (Vcb
->CDR_Mode
? Vcb
->NWA
: Vcb
->LastLBA
+ 1)) {
637 RtlZeroMemory(Buffer
, Length
);
638 try_return(RC
= STATUS_SUCCESS
);
640 retry
= UDF_WRITE_MAX_RETRY
;
642 RC
= UDFPrepareForReadOperation(Vcb
, rLba
, Length
>> Vcb
->BlockSizeBits
);
643 if(!OS_SUCCESS(RC
)) try_return(RC
);
644 rLba
= UDFFixFPAddress(Vcb
, rLba
);
647 retry
= UDF_WRITE_MAX_RETRY
;
649 RC
= UDFPrepareForReadOperation(Vcb
, rLba
, Length
>> Vcb
->BlockSizeBits
);
650 if(!OS_SUCCESS(RC
)) return RC
; // this is for !_BROWSE_UDF only
651 #endif //_BROWSE_UDF_
652 if(Flags
& PH_VCB_IN_RETLEN
) {
653 (*ReadBytes
) = (ULONG
)Vcb
;
655 RC
= UDFPhReadSynchronous(Vcb
->TargetDeviceObject
, Buffer
, Length
,
656 ((uint64
)rLba
) << Vcb
->BlockSizeBits
, ReadBytes
, Flags
);
657 Vcb
->VCBFlags
&= ~UDF_VCB_LAST_WRITE
;
659 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
660 #endif //_BROWSE_UDF_
661 if(!OS_SUCCESS(RC
) &&
662 OS_SUCCESS(RC
= UDFRecoverFromError(Vcb
, FALSE
, RC
, rLba
, BCount
, &retry
)) ) {
663 if(RC
!= STATUS_BUFFER_ALL_ZEROS
) {
666 RtlZeroMemory(Buffer
, Length
);
667 (*ReadBytes
) = Length
;
673 // read according to relocation table
674 RelocExtent_saved
= RelocExtent
;
675 for(i
=0; RelocExtent
->extLength
; i
++, RelocExtent
++) {
677 rLba
= RelocExtent
->extLocation
;
678 if(rLba
>= (Vcb
->CDR_Mode
? Vcb
->NWA
: Vcb
->LastLBA
+ 1)) {
679 RtlZeroMemory(Buffer
, _ReadBytes
= RelocExtent
->extLength
);
683 BCount
= RelocExtent
->extLength
>>Vcb
->BlockSizeBits
;
684 retry
= UDF_WRITE_MAX_RETRY
;
686 RC
= UDFPrepareForReadOperation(Vcb
, rLba
, RelocExtent
->extLength
>> Vcb
->BlockSizeBits
);
687 if(!OS_SUCCESS(RC
)) break;
688 rLba
= UDFFixFPAddress(Vcb
, rLba
);
689 if(Flags
& PH_VCB_IN_RETLEN
) {
690 _ReadBytes
= (ULONG
)Vcb
;
692 RC
= UDFPhReadSynchronous(Vcb
->TargetDeviceObject
, Buffer
, RelocExtent
->extLength
,
693 ((uint64
)rLba
) << Vcb
->BlockSizeBits
, &_ReadBytes
, Flags
);
694 Vcb
->VCBFlags
&= ~UDF_VCB_LAST_WRITE
;
695 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
696 if(!OS_SUCCESS(RC
) &&
697 OS_SUCCESS(RC
= UDFRecoverFromError(Vcb
, FALSE
, RC
, rLba
, BCount
, &retry
)) ) {
698 if(RC
!= STATUS_BUFFER_ALL_ZEROS
) {
701 RtlZeroMemory(Buffer
, RelocExtent
->extLength
);
702 _ReadBytes
= RelocExtent
->extLength
;
706 (*ReadBytes
) += _ReadBytes
;
707 if(!OS_SUCCESS(RC
)) break;
708 *((uint32
*)&Buffer
) += RelocExtent
->extLength
;
713 UDFReleaseResource(&(Vcb
->IoResource
));
715 if(RelocExtent_saved
) {
716 MyFreePool__(RelocExtent_saved
);
719 #endif //_BROWSE_UDF_
725 This routine performs asynchronous low-level read
732 IN
void* Buffer
, // Target buffer
735 OUT uint32
* ReadBytes
738 PEXTENT_MAP RelocExtent
;
739 PEXTENT_MAP RelocExtent_saved
;
740 OSSTATUS RC
= STATUS_SUCCESS
;
741 // LARGE_INTEGER delay;
742 uint32 retry
= UDF_READ_MAX_RETRY
;
743 PVCB Vcb
= (PVCB
)_Vcb
;
744 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
752 RelocExtent
= UDFRelocateSectors(Vcb
, LBA
, BCount
= Length
>> Vcb
->BlockSizeBits
);
753 if(!RelocExtent
) return STATUS_INSUFFICIENT_RESOURCES
;
754 if(RelocExtent
== UDF_NO_EXTENT_MAP
) {
756 if(rLba
>= (Vcb
->CDR_Mode
? Vcb
->NWA
: Vcb
->LastLBA
+ 1)) {
757 RtlZeroMemory(Buffer
, Length
);
758 return STATUS_SUCCESS
;
761 RC
= UDFPrepareForReadOperation(Vcb
, rLba
, BCount
);
762 if(!OS_SUCCESS(RC
)) return RC
;
763 rLba
= UDFFixFPAddress(Vcb
, rLba
);
764 RC
= UDFPhReadSynchronous(Vcb
->TargetDeviceObject
, Buffer
, Length
,
765 ((uint64
)rLba
) << Vcb
->BlockSizeBits
, ReadBytes
, 0);
766 Vcb
->VCBFlags
&= ~UDF_VCB_LAST_WRITE
;
767 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
768 if(!OS_SUCCESS(RC
) &&
769 OS_SUCCESS(RC
= UDFRecoverFromError(Vcb
, FALSE
, RC
, rLba
, BCount
, &retry
)) )
773 // read according to relocation table
774 RelocExtent_saved
= RelocExtent
;
775 for(uint32 i
=0; RelocExtent
->extLength
; i
++, RelocExtent
++) {
777 rLba
= RelocExtent
->extLocation
;
778 if(rLba
>= (Vcb
->CDR_Mode
? Vcb
->NWA
: Vcb
->LastLBA
+ 1)) {
779 RtlZeroMemory(Buffer
, _ReadBytes
= RelocExtent
->extLength
);
783 BCount
= RelocExtent
->extLength
>>Vcb
->BlockSizeBits
;
785 RC
= UDFPrepareForReadOperation(Vcb
, rLba
, RelocExtent
->extLength
>> Vcb
->BlockSizeBits
);
786 if(!OS_SUCCESS(RC
)) break;
787 rLba
= UDFFixFPAddress(Vcb
, rLba
);
788 RC
= UDFPhReadSynchronous(Vcb
->TargetDeviceObject
, Buffer
, RelocExtent
->extLength
,
789 ((uint64
)rLba
) << Vcb
->BlockSizeBits
, &_ReadBytes
, 0);
790 Vcb
->VCBFlags
&= ~UDF_VCB_LAST_WRITE
;
791 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
792 if(!OS_SUCCESS(RC
) &&
793 OS_SUCCESS(RC
= UDFRecoverFromError(Vcb
, FALSE
, RC
, rLba
, BCount
, &retry
)) )
796 (*ReadBytes
) += _ReadBytes
;
797 if(!OS_SUCCESS(RC
)) break;
798 *((uint32
*)&Buffer
) += RelocExtent
->extLength
;
800 MyFreePool__(RelocExtent_saved
);
802 } // end UDFTReadAsync()
804 #endif //UDF_ASYNC_IO
814 GET_MRW_MODE_USER_OUT MRWPage
;
817 if(Vcb
->MediaClassEx
!= CdMediaClass_CDRW
)
818 return STATUS_SUCCESS
;
819 //#ifdef _BROWSE_UDF_
820 if(Vcb
->CompatFlags
& UDF_VCB_IC_MRW_ADDR_PROBLEM
)
821 return STATUS_SUCCESS
;
822 //#endif //_BROWSE_UDF_
824 if(!Vcb
->MRWStatus
) {
825 KdPrint(("Non-MRW disk. Skip setting MRW_MODE\n"));
826 return STATUS_SUCCESS
;
828 KdPrint(("try set MRW_MODE\n"));
829 RC
= UDFPhSendIOCTL(IOCTL_CDRW_GET_MRW_MODE
, Vcb
->TargetDeviceObject
,
831 (PVOID
)&MRWPage
,sizeof(MRWPage
),
833 if(!NT_SUCCESS(RC
)) {
836 KdPrint(("GET_MRW_MODE ok (current %x)\n", MRWPage
.AddressMode
));
837 MRWPage
.AddressMode
= Vcb
->MRWStatus
? 0 : MrwPage_use_GAA
;
838 KdPrint(("SET_MRW_MODE %x\n", MRWPage
.AddressMode
));
839 RC
= UDFPhSendIOCTL(IOCTL_CDRW_SET_MRW_MODE
, Vcb
->TargetDeviceObject
,
840 (PVOID
)&MRWPage
,sizeof(MRWPage
),
843 KdPrint(("SET_MRW_MODE status %x\n", RC
));
845 return STATUS_SUCCESS
;
846 } // end UDFSetMRWMode()
854 if(Vcb
->OPCNum
&& !Vcb
->OPCDone
) {
855 KdPrint(("UDFDoOPC\n"));
858 (PSEND_OPC_INFO_HEADER_USER_IN
)MyAllocatePool__(NonPagedPool
,
859 sizeof(SEND_OPC_INFO_HEADER_USER_IN
) );
862 return STATUS_INSUFFICIENT_RESOURCES
;
863 Vcb
->OPCh
->DoOpc
= TRUE
;
864 Vcb
->OPCh
->OpcBlocksNumber
= 0;
865 RC
= UDFPhSendIOCTL(IOCTL_CDRW_SEND_OPC_INFO
, Vcb
->TargetDeviceObject
,
866 (void*)(Vcb
->OPCh
),sizeof(SEND_OPC_INFO_HEADER_USER_IN
),
869 if(!OS_SUCCESS(RC
)) {
870 KdPrint(("UDFDoOPC failed\n"));
872 // Vcb->VCBFlags |= UDF_VCB_FLAGS_OPC_FAILED;
880 This routine performs media-type dependent preparations
883 For CDR/RW it sets WriteParameters according to track parameters,
884 in some cases issues SYNC_CACHE command.
885 It can also send OPC info if requered.
886 If write-requested block is located beyond last formatted LBA
887 on incompletely formatted DVD media, this routine performs
888 all neccessary formatting operations in order to satisfy
889 subsequent write request.
892 UDFPrepareForWriteOperation(
898 #ifndef UDF_READ_ONLY_BUILD
899 #ifdef UDF_FORMAT_MEDIA
900 PUDFFmtState fms
= Vcb
->fms
;
903 #endif //UDF_FORMAT_MEDIA
905 #ifdef _UDF_STRUCTURES_H_
906 if(Vcb
->BSBM_Bitmap
) {
908 for(i
=0; i
<BCount
; i
++) {
909 if(UDFGetBit__((uint32
*)(Vcb
->BSBM_Bitmap
), Lba
+i
)) {
910 KdPrint(("W: Known BB @ %#x\n", Lba
));
911 //return STATUS_FT_WRITE_RECOVERY; // this shall not be treated as error and
912 // we shall get IO request to BAD block
913 return STATUS_DEVICE_DATA_ERROR
;
917 #endif //_UDF_STRUCTURES_H_
919 Vcb
->VCBFlags
|= UDF_VCB_LAST_WRITE
;
923 (((Vcb
->FsDeviceType
!= FILE_DEVICE_CD_ROM_FILE_SYSTEM
) ||
924 !(Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_MOUNTED
) ||
925 (Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
))
928 #endif //_BROWSE_UDF_
929 #ifdef UDF_FORMAT_MEDIA
930 (fms
&& fms
->SkipPrepareW
) ||
931 #endif //UDF_FORMAT_MEDIA
932 !(Vcb
->VCBFlags
& UDF_VCB_FLAGS_OUR_DEVICE_DRIVER
)
934 KdPrint(("Skip prepare for Write @%x\n", Lba
));
935 return STATUS_SUCCESS
;
938 // check if the device requires OPC before each write operation
941 if(Vcb
->SyncCacheState
== SYNC_CACHE_RECOVERY_ATTEMPT
) {
942 Vcb
->SyncCacheState
= SYNC_CACHE_RECOVERY_RETRY
;
944 Vcb
->SyncCacheState
= SYNC_CACHE_RECOVERY_NONE
;
946 if(Vcb
->LastModifiedTrack
&&
947 (Vcb
->TrackMap
[Vcb
->LastModifiedTrack
].FirstLba
<= Lba
) &&
948 (Vcb
->TrackMap
[Vcb
->LastModifiedTrack
].LastLba
>= Lba
) &&
949 !( (Vcb
->MediaClassEx
== CdMediaClass_DVDRW
||
950 Vcb
->MediaClassEx
== CdMediaClass_DVDpRW
||
951 Vcb
->MediaClassEx
== CdMediaClass_DVDRAM
||
952 Vcb
->MRWStatus
== DiscInfo_BGF_Interrupted
||
953 Vcb
->MRWStatus
== DiscInfo_BGF_InProgress
) && (Lba
> Vcb
->LastLBA
))
955 // Ok, we needn't change Write Parameters
956 // if(Vcb->TrackMap[Vcb->LastModifiedTrack].Flags & TrackMap_Try_variation)
957 // Vcb->TrackMap[Vcb->LastModifiedTrack].Flags |= TrackMap_Use_variation;
958 KdPrint(("Skip prepare for Write (2) @%x\n", Lba
));
959 return STATUS_SUCCESS
;
964 if(!UDFIsWriteParamsReq(Vcb
)) {
965 #ifdef UDF_FORMAT_MEDIA
967 return STATUS_SUCCESS
;
969 #endif //UDF_FORMAT_MEDIA
972 for(uint32 i
=Vcb
->FirstTrackNum
; i
<=Vcb
->LastTrackNum
; i
++) {
973 if((Vcb
->TrackMap
[i
].FirstLba
> Lba
) ||
974 (Vcb
->TrackMap
[i
].LastLba
< Lba
)) {
975 //KdPrint(("not in track %d\n"));
979 PGET_WRITE_MODE_USER_OUT WParams
;
981 if(!UDFIsWriteParamsReq(Vcb
)) {
983 goto check_dvd_bg_format
;
988 (PGET_WRITE_MODE_USER_OUT
)MyAllocatePool__(NonPagedPool
, 512);
990 if(!(WParams
= Vcb
->WParams
)) {
991 KdPrint(("!WParams\n"));
992 return STATUS_INSUFFICIENT_RESOURCES
;
995 RC
= UDFPhSendIOCTL(IOCTL_CDRW_GET_WRITE_MODE
, Vcb
->TargetDeviceObject
,
997 (void*)(Vcb
->WParams
),sizeof(GET_WRITE_MODE_USER_OUT
),
999 if(!OS_SUCCESS(RC
)) {
1000 #ifdef UDF_FORMAT_MEDIA
1002 fms
->SkipPrepareW
= 1;
1003 MyFreePool__(WParams
);
1004 return STATUS_SUCCESS
;
1006 #endif //UDF_FORMAT_MEDIA
1007 KdPrint(("!get WParams\n"));
1010 // clear unnecassary flags
1011 WParams
->Byte2
.Flags
&= ~WParam_TestWrite
;
1012 WParams
->Byte2
.Flags
&= ~WParam_WType_Mask
;
1013 // select packet writing
1014 WParams
->Byte2
.Flags
|= WParam_WType_Packet
;
1016 WParams
->Byte3
.Flags
&= ~(WParam_TrkMode_Mask
|
1017 WParam_TrkMode_AllowCpy
|
1019 WParams
->Byte3
.Flags
|= Vcb
->TrackMap
[i
].TrackParam
&
1020 (WParam_TrkMode_Mask
|
1021 WParam_TrkMode_AllowCpy
|
1024 // set packet type (VP/FP)
1025 // if(opt_partition == PT_VAT15 ||
1027 if(WParams
->Byte2
.Flags
& WParam_LS_V
) {
1028 WParams
->LinkSize
= 7;
1031 if(Vcb
->TrackMap
[i
].DataParam
& TrkInfo_Packet
) {
1032 if((Vcb
->TrackMap
[i
].DataParam
& TrkInfo_FP
) &&
1034 WParams
->Byte3
.Flags
|= WParam_FP
;
1036 WParams
->Byte3
.Flags
&= ~WParam_FP
;
1039 if(!Vcb
->CDR_Mode
) {
1040 WParams
->Byte3
.Flags
|= WParam_FP
;
1042 WParams
->Byte3
.Flags
&= ~WParam_FP
;
1046 // select multisession mode
1047 WParams
->Byte3
.Flags
&= ~WParam_MultiSes_Mask
;
1048 if((Vcb
->DiscStat
& DiscInfo_Disk_Mask
) == DiscInfo_Disk_Appendable
) {
1049 WParams
->Byte3
.Flags
|= WParam_Multises_Multi
;
1051 if(Vcb
->LastSession
> 1) {
1052 WParams
->Byte3
.Flags
|= WParam_Multises_Final
;
1054 WParams
->Byte3
.Flags
|= WParam_Multises_None
;
1056 // set sector mode (Mode1/XA)
1057 WParams
->Byte4
.Flags
&= ~WParam_BlkType_Mask
;
1058 if((Vcb
->TrackMap
[i
].DataParam
& TrkInfo_Dat_Mask
) == TrkInfo_Dat_XA
) {
1060 WParams
->Byte4
.Flags
|= WParam_BlkType_M2XAF1_2048
;
1061 WParams
->SesFmt
= WParam_SesFmt_CdRomXa
;
1062 } else if((Vcb
->TrackMap
[i
].DataParam
& TrkInfo_Dat_Mask
) == TrkInfo_Dat_Mode1
) {
1064 WParams
->Byte4
.Flags
|= WParam_BlkType_M1_2048
;
1065 WParams
->SesFmt
= WParam_SesFmt_CdRom
;
1067 #ifdef UDF_FORMAT_MEDIA
1069 fms
->SkipPrepareW
= 1;
1070 MyFreePool__(WParams
);
1071 return STATUS_SUCCESS
;
1073 #endif //UDF_FORMAT_MEDIA
1074 KdPrint((" inv sector mode\n"));
1075 return STATUS_INVALID_PARAMETER
;
1078 *((uint32
*)&(WParams
->PacketSize
)) = BCount
;
1079 *((uint32
*)&(WParams
->SubHeader
)) = 0;
1080 // set additional flags for VP
1083 // if(opt_partition == PT_VAT15)
1084 WParams
->SubHeader
.Params
.Params1
.SubMode
= WParam_SubHdr_SubMode1
;
1086 WParams
->PageLength
= sizeof(GET_WRITE_MODE_USER_OUT
)-2;
1087 WParams
->PageCode
= MODE_PAGE_WRITE_PARAMS
;
1088 // apply write parameters
1089 RC
= UDFPhSendIOCTL(IOCTL_CDRW_SET_WRITE_MODE
, Vcb
->TargetDeviceObject
,
1090 (void*)WParams
,sizeof(SET_WRITE_MODE_USER_IN
),
1093 #ifdef UDF_FORMAT_MEDIA
1095 if(!NT_SUCCESS(RC
)) {
1096 fms
->SkipPrepareW
= 1;
1097 MyFreePool__(WParams
);
1098 return STATUS_SUCCESS
;
1101 RC
= UDFPhSendIOCTL(IOCTL_CDRW_GET_WRITE_MODE
, Vcb
->TargetDeviceObject
,
1103 (PVOID
)WParams
,sizeof(GET_WRITE_MODE_USER_OUT
),
1105 if(!NT_SUCCESS(RC
)) {
1106 MyFreePool__(WParams
);
1110 if(fms
->opt_partition
== PT_VAT15
||
1111 fms
->opt_blank_vat15
) {
1112 if(WParams
->Byte3
.Flags
& WParam_FP
) {
1113 MyFreePool__(WParams
);
1114 return STATUS_INVALID_DEVICE_STATE
;
1117 if(!(WParams
->Byte3
.Flags
& WParam_FP
)) {
1118 MyFreePool__(WParams
);
1119 return STATUS_INVALID_DEVICE_STATE
;
1123 #endif //UDF_FORMAT_MEDIA
1125 // switch to random access mode
1126 ((PSET_RANDOM_ACCESS_USER_IN
)WParams
)->RandomAccessMode
= Vcb
->CDR_Mode
? FALSE
: TRUE
;
1127 // ((PSET_RANDOM_ACCESS_USER_IN)WParams)->RandomAccessMode = (opt_partition != PT_VAT15) ? TRUE : FALSE;
1128 RC
= UDFPhSendIOCTL(IOCTL_CDRW_SET_RANDOM_ACCESS
, Vcb
->TargetDeviceObject
,
1129 (void*)WParams
,sizeof(SET_RANDOM_ACCESS_USER_IN
),
1130 NULL
,0,FALSE
, NULL
);
1132 check_dvd_bg_format
:
1134 KdPrint((" check BGF\n"));
1135 if(!Vcb
->CDR_Mode
) {
1136 if(OS_SUCCESS(RC
)) {
1137 Vcb
->LastModifiedTrack
= i
;
1138 if(!(Vcb
->TrackMap
[i
].Flags
& TrackMap_Use_variation
)) {
1139 if(Vcb
->TrackMap
[i
].Flags
& TrackMap_Try_variation
) {
1140 Vcb
->TrackMap
[i
].Flags
|= TrackMap_Use_variation
;
1142 Vcb
->TrackMap
[i
].Flags
|= TrackMap_Try_variation
;
1147 Vcb
->LastModifiedTrack
= 0;
1149 // fms->SkipPrepareW = 1;
1152 if((Vcb
->MediaClassEx
== CdMediaClass_DVDRW
||
1153 Vcb
->MediaClassEx
== CdMediaClass_DVDpRW
||
1154 Vcb
->MediaClassEx
== CdMediaClass_DVDRAM
||
1155 Vcb
->MRWStatus
== DiscInfo_BGF_Interrupted
)
1156 && (Lba
> Vcb
->LastLBA
)) {
1160 ULONG PSz
= BCount
<< Vcb
->BlockSizeBits
;
1163 #endif //_BROWSE_UDF_
1164 PFORMAT_CDRW_PARAMETERS_USER_IN ForBuf
;
1166 ASSERT((Vcb
->LastLBA
+1) == Vcb
->NWA
);
1168 if(Lba
+BCount
<= (Vcb
->LastLBA
+1) ) {
1169 KdPrint(("DVD cont. fmt, LBA+BCount<=NWA, exiting\n"));
1170 return STATUS_SUCCESS
;
1172 if((Vcb
->MRWStatus
!= DiscInfo_BGF_Interrupted
) &&
1173 (Lba
<= (Vcb
->LastLBA
+1)) ) {
1174 KdPrint(("!PausedBGF + DVD cont. fmt, LBA<=NWA, exiting\n"));
1175 return STATUS_SUCCESS
;
1178 if(Vcb
->MRWStatus
== DiscInfo_BGF_Interrupted
) {
1179 // This code also can restart background MRW formatting
1180 KdPrint(("DVD cont. fmt, LastLBA %x, Lba %x\n", Vcb
->LastLBA
, Lba
));
1182 ForBuf
= (PFORMAT_CDRW_PARAMETERS_USER_IN
)DbgAllocatePoolWithTag(NonPagedPool
, sizeof(FORMAT_CDRW_PARAMETERS_USER_IN
), 'zNWD');
1184 RtlZeroMemory(ForBuf
, sizeof(FORMAT_CDRW_PARAMETERS_USER_IN
));
1185 ForBuf
->Flags
.FlagsEx
= FORMAT_UNIT_RESTART_MRW
;
1186 ForBuf
->BlockCount
= 0xffffffff;
1188 RC
= UDFPhSendIOCTL(IOCTL_CDRW_FORMAT_UNIT
, Vcb
->TargetDeviceObject
,
1189 ForBuf
,sizeof(FORMAT_CDRW_PARAMETERS_USER_IN
),
1190 NULL
,0,FALSE
, NULL
);
1191 DbgFreePool(ForBuf
);
1192 if(OS_SUCCESS(RC
)) {
1193 KdPrint(("BGFormat restarted Interrupted->InProgress\n"));
1194 Vcb
->MRWStatus
= DiscInfo_BGF_InProgress
;
1196 PGET_LAST_ERROR_USER_OUT Error
= NULL
;
1198 Vcb
->Error
= (PGET_LAST_ERROR_USER_OUT
)
1199 MyAllocatePool__(NonPagedPool
, sizeof(GET_LAST_ERROR_USER_OUT
));
1203 UDFPhSendIOCTL( IOCTL_CDRW_GET_LAST_ERROR
, Vcb
->TargetDeviceObject
,
1205 Error
,sizeof(GET_LAST_ERROR_USER_OUT
),
1207 KdPrint(("SK=%x ASC=%x, ASCQ=%x, IE=%x\n",
1208 Error
->SenseKey
, Error
->AdditionalSenseCode
, Error
->AdditionalSenseCodeQualifier
, Error
->LastError
));
1209 // check for Long Write In Progress
1210 if( (Error
->SenseKey
== SCSI_SENSE_NOT_READY
) &&
1211 (Error
->AdditionalSenseCode
== SCSI_ADSENSE_LUN_NOT_READY
) &&
1212 ((Error
->AdditionalSenseCodeQualifier
== SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS
) ||
1213 (Error
->AdditionalSenseCodeQualifier
== SCSI_SENSEQ_FORMAT_IN_PROGRESS
)) ) {
1214 RC
= STATUS_SUCCESS
;
1215 KdPrint(("Seems, BGFormat already restarted\n"));
1216 Vcb
->MRWStatus
= DiscInfo_BGF_InProgress
;
1222 RC
= STATUS_SUCCESS
;
1225 KdPrint(("DVD cont. write, LastLBA %x, Lba %x\n", Vcb
->LastLBA
, Lba
));
1227 ASSERT(Vcb
->MediaClassEx
== CdMediaClass_DVDRW
);
1228 if(!Vcb
->fZBuffer
) {
1229 Vcb
->fZBuffer
= (PCHAR
)DbgAllocatePoolWithTag(NonPagedPool
, PSz
, 'zNWD');
1230 RtlZeroMemory(Vcb
->fZBuffer
, PSz
);
1231 Vcb
->fZBufferSize
= PSz
;
1233 if(Vcb
->fZBufferSize
< PSz
) {
1234 PSz
= Vcb
->fZBufferSize
;
1236 if(!Vcb
->fZBuffer
) {
1238 RC
= STATUS_INSUFFICIENT_RESOURCES
;
1240 for(fLba
= Vcb
->NWA
; fLba
< Lba
; fLba
+=BCount
) {
1242 retry
= UDF_WRITE_MAX_RETRY
;
1244 #endif //_BROWSE_UDF_
1245 RC
= UDFPhWriteVerifySynchronous(Vcb
->TargetDeviceObject
, Vcb
->fZBuffer
, PSz
,
1246 ((uint64
)fLba
) << Vcb
->BlockSizeBits
, &WrittenBytes
, PH_TMP_BUFFER
);
1247 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
1248 KdPrint(("Fmt status: %x\n", RC
));
1250 if(!OS_SUCCESS(RC
) &&
1251 OS_SUCCESS(RC
= UDFRecoverFromError(Vcb
, TRUE
, RC
, fLba
, BCount
, &retry
)) ) {
1253 KdPrint(("Fmt retry\n"));
1255 #endif //_BROWSE_UDF_
1256 if(!OS_SUCCESS(RC
)) {
1258 KdPrint(("Fmt break on ERROR\n"));
1261 UDFUpdateNWA(Vcb
, fLba
, BCount
, RC
);
1265 KdPrint((" no special processing\n"));
1270 #endif //UDF_READ_ONLY_BUILD
1271 KdPrint((" no suitable track!\n"));
1272 return STATUS_INVALID_PARAMETER
;
1273 } // end UDFPrepareForWriteOperation()
1275 //#ifdef _BROWSE_UDF_
1277 This routine tries to recover from hardware error
1278 Return: STATUS_SUCCESS - retry requst
1279 STATUS_XXX - unrecoverable error
1282 UDFRecoverFromError(
1288 IN OUT uint32
* retry
1291 PGET_LAST_ERROR_USER_OUT Error
= NULL
;
1292 LARGE_INTEGER delay
;
1295 BOOLEAN UpdateBB
= FALSE
;
1298 !(Vcb
->VCBFlags
& UDF_VCB_FLAGS_OUR_DEVICE_DRIVER
) ||
1299 (Vcb
->FsDeviceType
!= FILE_DEVICE_CD_ROM_FILE_SYSTEM
))
1302 // allocate tmp buffer
1305 if(!(Vcb
->Error
= (PGET_LAST_ERROR_USER_OUT
)
1306 MyAllocatePool__(NonPagedPool
, sizeof(GET_LAST_ERROR_USER_OUT
))))
1309 if(status
== STATUS_NO_SUCH_DEVICE
) {
1310 KdPrint(("Error recovery: STATUS_NO_SUCH_DEVICE, die.....\n"));
1311 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_UNSAFE_IOCTL
| UDF_VCB_FLAGS_DEAD
;
1315 #ifdef _UDF_STRUCTURES_H_
1316 if(status
== STATUS_NO_MEDIA_IN_DEVICE
&& !Vcb
->EjectWaiter
) {
1317 KdPrint(("Error recovery: STATUS_NO_MEDIA_IN_DEVICE, prevent further remount.....\n"));
1318 // Make sure, that volume will never be quick-remounted
1319 // It is very important for ChkUdf utility and
1320 // some CD-recording libraries
1321 Vcb
->SerialNumber
--;
1324 #endif //_UDF_STRUCTURES_H_
1327 UDFPhSendIOCTL( IOCTL_CDRW_GET_LAST_ERROR
, Vcb
->TargetDeviceObject
,
1329 Error
,sizeof(GET_LAST_ERROR_USER_OUT
),
1331 KdPrint(("SK=%x ASC=%x, ASCQ=%x, IE=%x\n",
1332 Error
->SenseKey
, Error
->AdditionalSenseCode
, Error
->AdditionalSenseCodeQualifier
, Error
->LastError
));
1333 // check for Long Write In Progress
1334 if( ((Error
->SenseKey
== SCSI_SENSE_NOT_READY
) &&
1335 (Error
->AdditionalSenseCode
== SCSI_ADSENSE_LUN_NOT_READY
) &&
1336 (Error
->AdditionalSenseCodeQualifier
== SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS
)) ) {
1337 // we should wait...
1339 if((*retry
) == UDF_WRITE_MAX_RETRY
-1) {
1340 KdPrint(("Error recovery: reserve retry count for write retries\n"));
1341 (*retry
) = UDF_WRITE_MAX_RETRY
*3;
1343 if((*retry
) == UDF_WRITE_MAX_RETRY
) {
1344 KdPrint(("Error recovery: jump over UDF_WRITE_MAX_RETRY\n"));
1347 delay
.QuadPart
= -500000; // 0.05 sec
1348 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1349 if(WriteOp
&& ((*retry
) > UDF_WRITE_MAX_RETRY
-1)) {
1350 KdPrint(("Error recovery: simple write retry with delay\n"));
1351 try_return(status
= STATUS_SUCCESS
);
1354 delay
.QuadPart
= -500000; // 0.05 sec
1355 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1356 if((*retry
) == UDF_WRITE_MAX_RETRY
-1) {
1357 KdPrint(("Error recovery: retry read after small delay\n"));
1358 try_return(status
= STATUS_SUCCESS
);
1361 KdPrint(("Error recovery: sync cache\n"));
1362 // ...flush device cache...
1363 RC
= UDFSyncCache(Vcb
);
1364 // wait again & retry
1365 delay
.QuadPart
= -1000000; // 0.1 sec
1366 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1367 #ifdef _UDF_STRUCTURES_H_
1368 if(Vcb
->BGWriters
) (*retry
)++;
1369 #endif //_UDF_STRUCTURES_H_
1370 try_return(status
= STATUS_SUCCESS
);
1372 // check for Long Write In Progress
1373 if((Error
->SenseKey
== SCSI_SENSE_NOT_READY
) &&
1374 (Error
->AdditionalSenseCode
== SCSI_ADSENSE_LUN_NOT_READY
) &&
1375 ((Error
->AdditionalSenseCodeQualifier
== SCSI_SENSEQ_FORMAT_IN_PROGRESS
) ||
1376 (Error
->AdditionalSenseCodeQualifier
== SCSI_SENSEQ_BECOMING_READY
) ||
1377 (Error
->AdditionalSenseCodeQualifier
== SCSI_SENSEQ_OPERATION_IN_PROGRESS
) ) ) {
1378 // we should wait & retry
1379 KdPrint(("Error recovery: op. in progress, waiting 0.3 sec\n"));
1380 delay
.QuadPart
= -3000000; // 0.3 sec
1381 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1382 #ifdef _UDF_STRUCTURES_H_
1383 if(Vcb
->BGWriters
) (*retry
)++;
1384 #endif //_UDF_STRUCTURES_H_
1385 Vcb
->SyncCacheState
= SYNC_CACHE_RECOVERY_ATTEMPT
;
1386 try_return(status
= STATUS_SUCCESS
);
1388 // check for non empty cache special case
1389 if((Error
->SenseKey
== SCSI_SENSE_ILLEGAL_REQUEST
) &&
1390 (Error
->AdditionalSenseCode
== SCSI_ADSENSE_INVALID_CMD_SEQUENCE
)) {
1391 // we should wait & retry
1393 KdPrint(("Error recovery: invalid command sequence on read\n"));
1394 delay
.QuadPart
= -1000000; // 0.1 sec
1395 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1396 KdPrint(("Error recovery: sync cache\n"));
1397 // ...flush device cache...
1398 RC
= UDFSyncCache(Vcb
);
1399 // wait again & retry
1400 delay
.QuadPart
= -1000000; // 0.1 sec
1401 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1402 #ifdef _UDF_STRUCTURES_H_
1403 if(Vcb
->BGWriters
) (*retry
)++;
1404 #endif //_UDF_STRUCTURES_H_
1405 try_return(status
= STATUS_SUCCESS
);
1407 goto reinit_sector_mode
;
1409 // check for Bus Reset (sometimes it happends...)
1410 if((Error
->SenseKey
== SCSI_SENSE_UNIT_ATTENTION
) &&
1411 (Error
->AdditionalSenseCode
== SCSI_ADSENSE_BUS_RESET
) ) {
1413 KdPrint(("Error recovery: bus reset...\n"));
1414 Vcb
->MediaChangeCount
= Error
->MediaChangeCount
;
1415 delay
.QuadPart
= -1000000; // 0.1 sec
1416 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1418 UDFResetDeviceDriver(Vcb
, Vcb
->TargetDeviceObject
, FALSE
);
1419 delay
.QuadPart
= -1000000; // 0.1 sec
1420 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1422 /* ((PPREVENT_MEDIA_REMOVAL_USER_IN)(Error))->PreventMediaRemoval = TRUE;
1423 UDFPhSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL,
1424 Vcb->TargetDeviceObject,
1425 Error,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN),
1428 delay.QuadPart = -1000000; // 0.1 sec
1429 KeDelayExecutionThread(KernelMode, FALSE, &delay);*/
1431 // reinit write mode the following is performed inside UDFResetDeviceDriver()
1432 //Vcb->LastModifiedTrack = 0;
1433 //Vcb->OPCDone = FALSE;
1436 // reinit sector mode
1437 Vcb
->LastModifiedTrack
= 0;
1438 UDFPrepareForWriteOperation(Vcb
, Lba
, BCount
);
1439 try_return(status
= STATUS_SUCCESS
);
1441 // check for Illegal Sector Mode.
1442 // We can get this error 'cause of 2 reasons:
1443 // a) Bus reset occured. We should reinit
1444 // b) CopyProtection settings missmatch
1445 // c) preblems with DNA of firmware developer, some TEACs fall into such state
1446 // after failed streaming read
1447 if((Error
->SenseKey
== SCSI_SENSE_ILLEGAL_REQUEST
) &&
1448 (Error
->AdditionalSenseCode
== SCSI_ADSENSE_ILLEGAL_MODE_FOR_THIS_TRACK
)) {
1449 bad_rw_seek_recovery
:
1453 // Variate CopyProtection...
1454 for(i
=Vcb
->FirstTrackNum
; i
<=Vcb
->LastTrackNum
; i
++) {
1455 if((Vcb
->TrackMap
[i
].FirstLba
> Lba
) ||
1456 (Vcb
->TrackMap
[i
].LastLba
< Lba
))
1458 /* if(Vcb->TrackMap[i].Flags & TrackMap_CopyBit_variated)
1460 goto reinit_sector_mode;*/
1462 // check if we have successuflly completed WriteOp
1464 // We should not variate these bits again in this case.
1465 if(Vcb
->TrackMap
[i
].Flags
& TrackMap_Use_variation
)
1467 Vcb
->TrackMap
[i
].Flags
&= ~TrackMap_Try_variation
;
1468 /* if((Vcb->TrackMap[i].Flags & TrackMap_Try_variation) &&
1469 (Vcb->TrackMap[i].Flags & (TrackMap_AllowCopyBit_variated |
1470 TrackMap_CopyBit_variated)))
1472 /* if(Vcb->TrackMap[i].Flags & TrackMap_Use_variation)
1474 Vcb
->TrackMap
[i
].Flags
|= TrackMap_Try_variation
;
1476 if(!(Vcb
->TrackMap
[i
].Flags
^= TrackMap_AllowCopyBit_variated
))
1477 Vcb
->TrackMap
[i
].Flags
^= TrackMap_CopyBit_variated
;
1478 if(Vcb
->TrackMap
[i
].Flags
& (TrackMap_AllowCopyBit_variated
|
1479 TrackMap_CopyBit_variated
) ) {
1482 Vcb
->TrackMap
[i
].Flags
&= ~TrackMap_Try_variation
;
1484 // reinit sector mode
1485 Vcb
->LastModifiedTrack
= 0;
1486 UDFPrepareForWriteOperation(Vcb
, Lba
, BCount
);
1491 //reinit_sector_mode:
1493 delay
.QuadPart
= -1000000; // 0.1 sec
1494 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1495 // reinit sector mode
1496 goto reinit_sector_mode
;
1498 Vcb->LastModifiedTrack = 0;
1499 UDFPrepareForWriteOperation(Vcb, Lba, BCount);
1500 try_return(status = STATUS_SUCCESS);
1504 if((Vcb
->CompatFlags
& UDF_VCB_IC_BAD_RW_SEEK
) &&
1505 (Vcb
->IncrementalSeekState
!= INCREMENTAL_SEEK_DONE
)) {
1506 KdPrint(("Using incremental seek workaround...\n"));
1507 Vcb
->IncrementalSeekState
= INCREMENTAL_SEEK_WORKAROUND
;
1508 try_return(status
= STATUS_SUCCESS
);
1510 KdPrint(("Seems to be BB @ %x\n", Lba
));
1514 if((Error
->SenseKey
== SCSI_SENSE_ILLEGAL_REQUEST
) &&
1515 (Error
->AdditionalSenseCode
== SCSI_ADSENSE_INVALID_SESSION_MODE
)) {
1517 (Vcb
->SavedFeatures
& CDRW_FEATURE_STREAMING
) &&
1518 Lba
+BCount
<= Vcb
->LastLBA
+1) {
1519 KdPrint(("bad Session in streaming mode. Lba %x, try fix-up\n", Lba
));
1520 // ...flush device cache...
1521 RC
= UDFSyncCache(Vcb
);
1523 delay
.QuadPart
= -10000000; // 1 sec
1524 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1525 try_return(status
= STATUS_SUCCESS
);
1528 if((Error
->LastError
== CDRW_ERR_WRITE_IN_PROGRESS_BUSY
) ||
1529 (status
== STATUS_DEVICE_BUSY
)) {
1530 delay
.QuadPart
= -5000000; // 0.5 sec
1531 KdPrint(("CDRW_ERR_WRITE_IN_PROGRESS_BUSY || STATUS_DEVICE_BUSY\n"));
1532 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1533 #ifdef _UDF_STRUCTURES_H_
1534 if(Vcb
->BGWriters
) (*retry
)++;
1535 #endif //_UDF_STRUCTURES_H_
1536 try_return(status
= STATUS_SUCCESS
);
1538 // some devices (SONY) return such a strange sequence....
1539 if( ((Error
->SenseKey
== SCSI_SENSE_ILLEGAL_REQUEST
) &&
1540 (Error
->AdditionalSenseCode
== SCSI_ADSENSE_INVALID_CDB
)) &&
1542 // reinit write mode
1543 Vcb
->LastModifiedTrack
= 0;
1544 UDFPrepareForWriteOperation(Vcb
, Lba
, BCount
);
1545 try_return(status
= STATUS_SUCCESS
);
1547 // No seek on Read... to morgue, I'm afraid
1548 if((Error
->SenseKey
== SCSI_SENSE_MEDIUM_ERROR
) /*&&
1549 ((Error->AdditionalSenseCode == SCSI_ADSENSE_CD_READ_ERROR) ||
1550 (Error->AdditionalSenseCode == SCSI_ADSENSE_NO_SENSE) ||
1551 (Error->AdditionalSenseCode == SCSI_ADSENSE_FORMAT_CORRUPTED) ||
1552 (Error->AdditionalSenseCode == SCSI_ADSENSE_SEEK_ERROR))*/ &&
1554 if(Error
->AdditionalSenseCode
== SCSI_ADSENSE_SEEK_ERROR
) {
1555 KdPrint(("Seek error\n"));
1556 if(Vcb
->CompatFlags
& UDF_VCB_IC_BAD_RW_SEEK
) {
1557 KdPrint(("try recovery\n"));
1558 goto bad_rw_seek_recovery
;
1560 KdPrint(("map error to STATUS_NONEXISTENT_SECTOR\n"));
1561 status
= STATUS_NONEXISTENT_SECTOR
;
1563 KdPrint(("Seems to be BB @ %x (read 2)\n", Lba
));
1566 // handle invalid block address
1567 if( ((Error
->SenseKey
== SCSI_SENSE_ILLEGAL_REQUEST
) &&
1568 (Error
->AdditionalSenseCode
== SCSI_ADSENSE_ILLEGAL_BLOCK
)) ) {
1570 (Vcb
->SavedFeatures
& CDRW_FEATURE_STREAMING
) &&
1571 Lba
+BCount
<= Vcb
->LastLBA
+1) {
1572 KdPrint(("bad LBA %x in streaming mode, try fix-up\n", Lba
));
1573 // ...flush device cache...
1574 RC
= UDFSyncCache(Vcb
);
1575 try_return(status
= STATUS_SUCCESS
);
1578 if((Lba
+BCount
>= Vcb
->LastLBA
) &&
1579 (Vcb
->MRWStatus
== DiscInfo_BGF_Interrupted
)) {
1580 KdPrint(("stupid drive, cannot read beyond formatted area on DiscInfo_BGF_Interrupted\n"));
1582 try_return(status
= STATUS_BUFFER_ALL_ZEROS
);
1584 // prevent Bad Block Bitmap modification
1591 if(OS_SUCCESS(status
)) {
1592 KdPrint(("Retry\n"));
1596 if(!OS_SUCCESS(status
)) {
1597 if((Vcb
->MountPhErrorCount
!= -1) &&
1598 (Vcb
->MountPhErrorCount
< 0x7fffffff)) {
1599 Vcb
->MountPhErrorCount
++;
1601 //#ifdef _UDF_STRUCTURES_H_
1602 if(UpdateBB
&& (BCount
== 1)) {
1604 if(!(bm
= (uint32
*)(Vcb
->BSBM_Bitmap
))) {
1605 bm
= (uint32
*)(Vcb
->BSBM_Bitmap
= (int8
*)DbgAllocatePoolWithTag(NonPagedPool
, (i
= (Vcb
->LastPossibleLBA
+1+7)>>3), 'mNWD' ));
1607 RtlZeroMemory(bm
, i
);
1609 KdPrint(("Can't alloc BSBM for %x blocks\n", Vcb
->LastPossibleLBA
));
1613 UDFSetBit__(bm
, Lba
);
1614 KdPrint(("Set BB @ %#x\n", Lba
));
1617 bm
= (uint32
*)(Vcb
->FSBM_Bitmap
);
1619 UDFSetUsedBit(bm
, Lba
);
1620 KdPrint(("Set BB @ %#x as used\n", Lba
));
1622 #endif //_BROWSE_UDF_
1624 //#endif //_UDF_STRUCTURES_H_
1627 } // end UDFRecoverFromError()
1629 //#endif //_BROWSE_UDF_
1631 This routine attempts to read disk layout using ReadDisk/Track info cmd
1634 UDFReadDiscTrackInfo(
1635 PDEVICE_OBJECT DeviceObject
, // the target device object
1636 PVCB Vcb
// Volume Control Block for ^ DevObj
1639 OSSTATUS RC
= STATUS_SUCCESS
;
1640 PDISC_INFO_BLOCK_USER_OUT DiscInfo
= (PDISC_INFO_BLOCK_USER_OUT
)MyAllocatePool__(NonPagedPool
,sizeof(DISC_INFO_BLOCK_USER_OUT
) );
1641 PTRACK_INFO_BLOCK_USER_OUT TrackInfoOut
= (PTRACK_INFO_BLOCK_USER_OUT
)MyAllocatePool__(NonPagedPool
,sizeof(TRACK_INFO_BLOCK_USER_OUT
) );
1642 PTRACK_INFO_BLOCK_USER_IN TrackInfoIn
= (PTRACK_INFO_BLOCK_USER_IN
)TrackInfoOut
;
1643 READ_CAPACITY_USER_OUT CapacityBuffer
;
1645 BOOLEAN NotFP
= FALSE
;
1646 BOOLEAN ForceFP
= FALSE
;
1647 BOOLEAN PacketTrack
= FALSE
;
1648 BOOLEAN MRWRetry
= FALSE
;
1649 BOOLEAN ReadCapacityOk
= FALSE
;
1650 #ifdef UDF_FORMAT_MEDIA
1651 PUDFFmtState fms
= Vcb
->fms
;
1655 if(!DiscInfo
|| !TrackInfoOut
)
1656 try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
1660 RC
= UDFPhSendIOCTL(IOCTL_CDRW_READ_DISC_INFO
, DeviceObject
,
1662 DiscInfo
,sizeof(DISC_INFO_BLOCK_USER_OUT
), TRUE
, NULL
);
1663 if(!OS_SUCCESS(RC
)) {
1664 KdPrint(("ReadDiskInfo failed. Use default.\n"));
1665 if(Vcb
->MediaClassEx
== CdMediaClass_DVDRW
||
1666 Vcb
->MediaClassEx
== CdMediaClass_DVDpRW
||
1667 Vcb
->MediaClassEx
== CdMediaClass_DVDRAM
) {
1668 Vcb
->LastPossibleLBA
= DEFAULT_LAST_LBA_DVD
;
1670 if(Vcb
->MediaClassEx
== CdMediaClass_BDRE
) {
1671 Vcb
->LastPossibleLBA
= DEFAULT_LAST_LBA_BD
;
1673 Vcb
->LastPossibleLBA
= DEFAULT_LAST_LBA_FP_CD
;
1677 #ifdef UDF_FORMAT_MEDIA
1678 if(fms
&& fms
->opt_disk_info
) {
1679 UserPrint(("ReadDiskInfo OK\n"));
1681 #endif //UDF_FORMAT_MEDIA
1683 RC
= UDFPhSendIOCTL(IOCTL_CDRW_READ_CAPACITY
, DeviceObject
,
1685 &CapacityBuffer
,sizeof(READ_CAPACITY_USER_OUT
), TRUE
, NULL
);
1686 if(!OS_SUCCESS(RC
)) {
1687 KdPrint(("ReadCapacity failed.\n"));
1688 if(Vcb
->MediaClassEx
== CdMediaClass_DVDpRW
) {
1689 Vcb
->LastPossibleLBA
= DEFAULT_LAST_LBA_DVD
;
1692 KdPrint(("ReadCapacity ok.\n"));
1693 KdPrint(("Last possible LBA %#x.\n", CapacityBuffer
.LogicalBlockAddress
));
1694 if(!(CapacityBuffer
.LogicalBlockAddress
& 0xc0000000) &&
1695 (CapacityBuffer
.LogicalBlockAddress
!= 0x7fffffff)) {
1696 // good value from ReadCapacity
1697 KdPrint(("Update Last possible LBA %#x.\n", CapacityBuffer
.LogicalBlockAddress
));
1698 Vcb
->LastPossibleLBA
= CapacityBuffer
.LogicalBlockAddress
;
1699 ReadCapacityOk
= TRUE
;
1700 #ifdef UDF_FORMAT_MEDIA
1701 if(fms
&& fms
->opt_disk_info
) {
1702 UserPrint(("ReadCapacity OK\n"));
1704 #endif //UDF_FORMAT_MEDIA
1709 Vcb
->PhDeviceType
= FILE_DEVICE_CD_ROM
;
1711 Vcb
->PhSerialNumber
= *((uint32
*)&(DiscInfo
->DiskId
));
1712 Vcb
->PhErasable
= DiscInfo
->DiscStat
.Flags
& DiscInfo_Disk_Erasable
;
1713 Vcb
->PhDiskType
= DiscInfo
->DiskType
;
1715 if(DiscInfo
->OPCNum
)
1716 Vcb
->OPCNum
= DiscInfo
->OPCNum
;
1717 KdPrint(("DiskInfo: SN %x, OPCn %x(%x), Stat %x, Flg: %x\n",
1718 Vcb
->PhSerialNumber
, Vcb
->OPCNum
, DiscInfo
->OPCNum
, DiscInfo
->DiscStat
.Flags
, DiscInfo
->Flags
.Flags
));
1719 #ifdef UDF_FORMAT_MEDIA
1720 if(fms
&& fms
->opt_disk_info
) {
1721 UserPrint(("Media type: "));
1722 switch(Vcb
->MediaClassEx
) {
1723 case CdMediaClass_CDROM
: UserPrint(("CD-ROM \n")); break;
1724 case CdMediaClass_CDR
: UserPrint(("CD-R \n")); break;
1725 case CdMediaClass_CDRW
: UserPrint(("CD-RW \n")); break;
1726 case CdMediaClass_DVDROM
: UserPrint(("DVD-ROM \n")); break;
1727 case CdMediaClass_DVDRAM
: UserPrint(("DVD-RAM \n")); break;
1728 case CdMediaClass_DVDR
: UserPrint(("DVD-R \n")); break;
1729 case CdMediaClass_DVDRW
: UserPrint(("DVD-RW \n")); break;
1730 case CdMediaClass_DVDpR
: UserPrint(("DVD+R \n")); break;
1731 case CdMediaClass_DVDpRW
: UserPrint(("DVD+RW \n")); break;
1732 case CdMediaClass_DDCDROM
: UserPrint(("DDCD-ROM \n")); break;
1733 case CdMediaClass_DDCDR
: UserPrint(("DDCD-R \n")); break;
1734 case CdMediaClass_DDCDRW
: UserPrint(("DDCD-RW \n")); break;
1735 case CdMediaClass_BDROM
: UserPrint(("BD-ROM \n")); break;
1736 case CdMediaClass_BDRE
: UserPrint(("BD-RE \n")); break;
1737 case CdMediaClass_BDR
: UserPrint(("BD-R \n")); break;
1738 case CdMediaClass_HD_DVDROM
: UserPrint(("HD DVD-ROM \n")); break;
1739 case CdMediaClass_HD_DVDRAM
: UserPrint(("HD DVD-RAM \n")); break;
1740 case CdMediaClass_HD_DVDR
: UserPrint(("HD DVD-R \n")); break;
1741 case CdMediaClass_HD_DVDRW
: UserPrint(("HD DVD-RW \n")); break;
1742 default: UserPrint(("Unknown\n")); break;
1744 UserPrint(("SN %#x, OPCn %#x\n",
1745 Vcb
->PhSerialNumber
, Vcb
->OPCNum
, DiscInfo
->OPCNum
));
1746 UserPrint(("Disk State: "));
1747 switch(DiscInfo
->DiscStat
.Flags
& DiscInfo_Disk_Mask
) {
1748 case DiscInfo_Disk_Empty
:
1749 UserPrint(("Empty\n"));
1751 case DiscInfo_Disk_Appendable
:
1752 UserPrint(("Appendable\n"));
1754 case DiscInfo_Disk_Complete
:
1755 UserPrint(("Complete\n"));
1757 case DiscInfo_Disk_OtherRW
:
1758 UserPrint(("RW in unknown state\n"));
1761 UserPrint(("Last Session State: "));
1762 switch(DiscInfo
->DiscStat
.Flags
& DiscInfo_Ses_Mask
) {
1763 case DiscInfo_Ses_Empty
:
1764 UserPrint(("Empty\n"));
1766 case DiscInfo_Ses_Incomplete
:
1767 UserPrint(("Incomplete\n"));
1769 case DiscInfo_Ses_Complete
:
1770 UserPrint(("Complete\n"));
1773 UserPrint(("unknown state\n"));
1776 UserPrint(("Erasable: %s\n",
1777 (DiscInfo
->DiscStat
.Flags
& DiscInfo_Disk_Erasable
) ? "yes" : "no"
1780 #endif //UDF_FORMAT_MEDIA
1782 Vcb
->DiscStat
= DiscInfo
->DiscStat
.Flags
;
1783 if((DiscInfo
->DiscStat
.Flags
& DiscInfo_Disk_Mask
) == DiscInfo_Disk_Empty
) {
1784 KdPrint(("Blank\n"));
1785 Vcb
->BlankCD
= TRUE
;
1787 if( (DiscInfo
->DiscStat
.Flags
& DiscInfo_Disk_Mask
) == DiscInfo_Disk_Empty
||
1788 (DiscInfo
->DiscStat
.Flags
& DiscInfo_Ses_Mask
) == DiscInfo_Ses_Incomplete
) {
1789 // we shall mount empty disk to make it possible for
1790 // external applications to perform format operation
1791 // or something like this
1792 KdPrint(("Try RAW_MOUNT\n"));
1793 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_RAW_DISK
;
1797 #ifndef _BROWSE_UDF_
1798 // If drive returned reasonable value from ReadCapacity, do not use
1799 // last LeadIn/LeadOut
1800 if(Vcb
->MediaClassEx
!= CdMediaClass_DVDpRW
&&
1802 // +RW returns bad value
1803 KdPrint(("+RW returns bad value\n"));
1804 Vcb
->LastPossibleLBA
= (DiscInfo
->LastSesLeadOutLBA
& 0x80000000) ?
1805 0 : DiscInfo
->LastSesLeadOutLBA
;
1806 if(!(DiscInfo
->LastSesLeadInLBA
& 0x80000000)) {
1807 Vcb
->LastPossibleLBA
= max(DiscInfo
->LastSesLeadInLBA
, Vcb
->LastPossibleLBA
);
1810 #endif // _BROWSE_UDF_
1811 if((DiscInfo
->Flags
.Flags
& DiscInfo_BGF_Mask
) != 0) {
1812 KdPrint(("ForceFP + MRW\n"));
1814 Vcb
->MRWStatus
= DiscInfo
->Flags
.Flags
& DiscInfo_BGF_Mask
;
1815 // update addressing mode
1819 goto MRWRetry_label
;
1822 KdPrint(("MRW state %x\n", Vcb
->MRWStatus
));
1823 if(Vcb
->MediaClassEx
== CdMediaClass_DVDRW
) {
1824 if(Vcb
->PhMediaCapFlags
& CdCapFlags_RandomWritable
) {
1825 KdPrint(("DVD-RW Rewritable\n"));
1828 if((DiscInfo
->DiscStat
.Flags
& DiscInfo_Disk_Mask
) == DiscInfo_Disk_Empty
) {
1829 KdPrint(("Blank DVD-RW\n"));
1832 KdPrint(("DVD-RW Sequential\n"));
1836 if(CdrwIsDvdOverwritable(Vcb
->MediaClassEx
)) {
1837 KdPrint(("force Rewritable (2)\n"));
1840 // We have incomplete last session, so process each track from last to first
1841 // Vcb->LastPossibleLBA = DiscInfo->LastSesLeadInLBA;
1843 Vcb
->LastSession
= DiscInfo
->Status
.NumOfSes
;
1844 Vcb
->LastTrackNum
= DiscInfo
->Status
.LastTrackNumLastSes
;
1845 Vcb
->FirstTrackNum
= DiscInfo
->FirstTrackNum
;
1846 // some devices report LastTrackNum=0 for full disks
1847 Vcb
->LastTrackNum
= max(Vcb
->LastTrackNum
, Vcb
->FirstTrackNum
);
1848 if(!Vcb
->LastTrackNum
) {
1849 KdPrint(("Try read 1st track...\n"));
1850 Vcb
->LastTrackNum
= 1;
1852 KdPrint(("DiskInfo: 1st trk %x, last trk %x\n", Vcb
->FirstTrackNum
, Vcb
->LastTrackNum
));
1853 #ifdef UDF_FORMAT_MEDIA
1854 if(fms
&& fms
->opt_disk_info
) {
1855 UserPrint(("First track: %d\n"
1856 "Last track: %d\n", Vcb
->FirstTrackNum
, Vcb
->LastTrackNum
));
1857 UserPrint(("------------------------------------------\n"));
1859 #endif //UDF_FORMAT_MEDIA
1861 RC
= UDFReallocTrackMap(Vcb
, Vcb
->LastTrackNum
+1);
1865 // Get last LBA from invisible track (if any)
1866 RtlZeroMemory(TrackInfoOut
,sizeof(TRACK_INFO_BLOCK_USER_OUT
));
1868 TrackInfoIn
->LBA_TrkNum
= 0; // invisible track
1869 TrackInfoIn
->Track
= TRUE
;
1871 RC
= UDFPhSendIOCTL(IOCTL_CDRW_READ_TRACK_INFO
, DeviceObject
,
1872 TrackInfoIn
, sizeof(TRACK_INFO_BLOCK_USER_IN
),
1873 TrackInfoOut
,sizeof(TRACK_INFO_BLOCK_USER_OUT
), TRUE
, NULL
);
1874 if(OS_SUCCESS(RC
)) {
1875 if((Vcb
->LastTrackNum
< TrackInfoOut
->TrackNum
) &&
1876 TrackInfoOut
->TrackLength
&&
1877 (TrackInfoOut
->TrackStartLBA
!= TrackInfoOut
->NextWriteLBA
)) {
1878 Vcb
->LastTrackNum
= TrackInfoOut
->TrackNum
;
1879 if(!(TrackInfoOut
->NextWriteLBA
& 0x80000000))
1880 Vcb
->NWA
= TrackInfoOut
->NextWriteLBA
;
1881 if(TrackInfoOut
->TrackLength
> 1) {
1882 Vcb
->LastPossibleLBA
=
1883 TrackInfoOut
->TrackStartLBA
+ TrackInfoOut
->TrackLength
- (TrackInfoOut
->TrackLength
? 1 : 0);
1884 KdPrint((" set LastPossibleLBA=%x\n", Vcb
->LastPossibleLBA
));
1888 KdPrint(("Ses %d, Track %d (%x, len %x) PckSize %x: \n"
1889 " NWA: %x (%s) DatType:%x, %s %s %s %s TrkType:%x %s %s\n"
1890 " LRA: %x (%s) RC_LBA:%x\n",
1891 TrackInfoOut
->SesNum
,
1893 TrackInfoOut
->TrackStartLBA
,
1894 TrackInfoOut
->TrackLength
,
1895 TrackInfoOut
->FixPacketSize
,
1897 TrackInfoOut
->NextWriteLBA
,
1898 TrackInfoOut
->NWA_V
& TrkInfo_NWA_V
? "vld" : "inv",
1899 TrackInfoOut
->DataParam
.Flags
& TrkInfo_Dat_Mask
,
1900 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_Packet
) ? "Pck" : "",
1901 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_FP
) ? "FP" : "",
1902 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_Blank
) ? "Blank" : "",
1903 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_RT
) ? "RT" : "",
1905 TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Trk_Mask
,
1906 (TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Copy
) ? "Cpy" : "",
1907 (TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Damage
) ? "Damage" : "",
1909 TrackInfoOut
->LastRecordedAddr
,
1910 (TrackInfoOut
->NWA_V
& TrkInfo_LRA_V
) ? "vld" : "inv",
1912 TrackInfoOut
->ReadCompatLBA
1914 #ifdef UDF_FORMAT_MEDIA
1915 if(fms
&& fms
->opt_disk_info
) {
1916 UserPrint(("Invisible track: \n"));
1917 UserPrint((" Ses %d, Track %d (%x, len %x) PckSize %x: \n"
1918 " NWA: %x (%s) DatType:%x, %s %s %s %s TrkType:%x %s %s\n"
1919 " LRA: %x (%s) RC_LBA:%x\n",
1920 TrackInfoOut
->SesNum
,
1922 TrackInfoOut
->TrackStartLBA
,
1923 TrackInfoOut
->TrackLength
,
1924 TrackInfoOut
->FixPacketSize
,
1926 TrackInfoOut
->NextWriteLBA
,
1927 TrackInfoOut
->NWA_V
& TrkInfo_NWA_V
? "vld" : "inv",
1928 TrackInfoOut
->DataParam
.Flags
& TrkInfo_Dat_Mask
,
1929 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_Packet
) ? "Pck" : "",
1930 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_FP
) ? "FP" : "",
1931 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_Blank
) ? "Blank" : "",
1932 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_RT
) ? "RT" : "",
1934 TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Trk_Mask
,
1935 (TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Copy
) ? "Cpy" : "",
1936 (TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Damage
) ? "Damage" : "",
1938 TrackInfoOut
->LastRecordedAddr
,
1939 (TrackInfoOut
->NWA_V
& TrkInfo_LRA_V
) ? "vld" : "inv",
1941 TrackInfoOut
->ReadCompatLBA
1944 #endif //UDF_FORMAT_MEDIA
1948 for (TrackNumber
=(LONG
)DiscInfo
->FirstTrackNum
;TrackNumber
<= (LONG
)Vcb
->LastTrackNum
;TrackNumber
++) {
1950 RtlZeroMemory(TrackInfoOut
,sizeof(TRACK_INFO_BLOCK_USER_OUT
));
1951 TrackInfoIn
->LBA_TrkNum
= TrackNumber
;
1952 TrackInfoIn
->Track
= TRUE
;
1954 RC
= UDFPhSendIOCTL(IOCTL_CDRW_READ_TRACK_INFO
, DeviceObject
,
1955 TrackInfoIn
, sizeof(TRACK_INFO_BLOCK_USER_IN
),
1956 TrackInfoOut
,sizeof(TRACK_INFO_BLOCK_USER_OUT
), TRUE
, NULL
);
1957 // fill sector type map
1958 if(TrackInfoOut
->TrackStartLBA
& 0x80000000) {
1959 KdPrint(("TrkInfo: Bad FirstLba (%x), change to %x\n", TrackInfoOut
->TrackStartLBA
, 0));
1960 Vcb
->TrackMap
[TrackNumber
].FirstLba
= 0;
1962 Vcb
->TrackMap
[TrackNumber
].FirstLba
= TrackInfoOut
->TrackStartLBA
;
1964 if(TrackInfoOut
->TrackLength
& 0x80000000) {
1965 KdPrint(("TrkInfo: Bad TrackLength (%x), change to %x\n", TrackInfoOut
->TrackLength
,
1966 Vcb
->LastPossibleLBA
- Vcb
->TrackMap
[TrackNumber
].FirstLba
+ 1));
1967 TrackInfoOut
->TrackLength
= Vcb
->LastPossibleLBA
- Vcb
->TrackMap
[TrackNumber
].FirstLba
+ 1;
1969 Vcb
->TrackMap
[TrackNumber
].LastLba
= TrackInfoOut
->TrackStartLBA
+
1970 TrackInfoOut
->TrackLength
-
1971 (TrackInfoOut
->TrackLength
? 1 : 0);
1973 Vcb
->TrackMap
[TrackNumber
].TrackParam
= TrackInfoOut
->TrackParam
.Flags
;
1974 Vcb
->TrackMap
[TrackNumber
].DataParam
= TrackInfoOut
->DataParam
.Flags
;
1975 Vcb
->TrackMap
[TrackNumber
].NWA_V
= TrackInfoOut
->NWA_V
;
1976 if((TrackInfoOut
->NextWriteLBA
& 0x80000000) ||
1977 (TrackInfoOut
->NextWriteLBA
< TrackInfoOut
->TrackStartLBA
)) {
1978 if(!(Vcb
->TrackMap
[TrackNumber
].LastLba
& 0x8000000)) {
1979 KdPrint(("TrkInfo: set NWA to LastLba (%x)\n", Vcb
->TrackMap
[TrackNumber
].LastLba
));
1980 Vcb
->TrackMap
[TrackNumber
].NWA
=
1981 Vcb
->TrackMap
[TrackNumber
].LastLba
;
1983 KdPrint(("TrkInfo: set NWA to INV (1)\n"));
1984 Vcb
->TrackMap
[TrackNumber
].NWA
= 0;
1985 Vcb
->TrackMap
[TrackNumber
].NWA_V
= 0;
1988 if(!(TrackInfoOut
->NextWriteLBA
& 0x80000000)) {
1989 KdPrint(("TrkInfo: Good NWA (%x)\n", TrackInfoOut
->NextWriteLBA
));
1990 Vcb
->TrackMap
[TrackNumber
].NWA
=
1991 TrackInfoOut
->NextWriteLBA
;
1993 KdPrint(("TrkInfo: set NWA to INV (2)\n"));
1994 Vcb
->TrackMap
[TrackNumber
].NWA
= 0;
1995 Vcb
->TrackMap
[TrackNumber
].NWA_V
= 0;
1998 Vcb
->TrackMap
[TrackNumber
].Session
= TrackInfoOut
->SesNum
;
1999 // for FP tracks we shall get PacketSize from returned info
2000 // otherwise set to default UDF value (0x20)
2002 KdPrint(("Apply NotFP\n"));
2003 Vcb
->TrackMap
[TrackNumber
].DataParam
&= ~TrkInfo_FP
;
2005 TrackInfoOut
->DataParam
.Flags
&= ~TrkInfo_FP
;
2009 KdPrint(("Apply ForceFP\n"));
2011 Vcb
->TrackMap
[TrackNumber
].DataParam
|= TrkInfo_FP
;
2013 TrackInfoOut
->DataParam
.Flags
|= TrkInfo_FP
;
2016 if(Vcb
->TrackMap
[TrackNumber
].DataParam
& TrkInfo_FP
) {
2017 Vcb
->TrackMap
[TrackNumber
].PacketSize
= TrackInfoOut
->FixPacketSize
;
2018 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_RAW_DISK
;
2019 Vcb
->FP_disc
= TRUE
;
2021 Vcb
->TrackMap
[TrackNumber
].PacketSize
= PACKETSIZE_UDF
;
2023 // presence of Damaged track means, that we should mount this disk in RAW mode
2024 if(Vcb
->TrackMap
[TrackNumber
].TrackParam
& TrkInfo_Damage
) {
2025 KdPrint(("TrkInfo_Damage, Try RAW_MOUNT\n"));
2026 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_RAW_DISK
;
2028 // presence of track with Unknown data type means, that we should mount
2029 // this disk in RAW mode
2030 if((TrackInfoOut
->DataParam
.Flags
& TrkInfo_Dat_Mask
) == TrkInfo_Trk_unknown
) {
2031 KdPrint(("Unknown DatType, Try RAW_MOUNT\n"));
2032 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_RAW_DISK
;
2035 PacketTrack
|= ((TrackInfoOut
->DataParam
.Flags
& TrkInfo_Packet
) != 0);
2037 KdPrint(("Ses %d, Track %d (%x - %x) PckSize %x: \n"
2038 " NWA: %x (%s) DatType:%x, %s %s %s %s TrkType:%x %s %s\n"
2039 " LRA: %x (%s) RC_LBA:%x\n",
2040 TrackInfoOut
->SesNum
,
2042 Vcb
->TrackMap
[TrackNumber
].FirstLba
,
2043 Vcb
->TrackMap
[TrackNumber
].LastLba
,
2044 TrackInfoOut
->FixPacketSize
,
2046 TrackInfoOut
->NextWriteLBA
,
2047 TrackInfoOut
->NWA_V
& TrkInfo_NWA_V
? "vld" : "inv",
2048 TrackInfoOut
->DataParam
.Flags
& TrkInfo_Dat_Mask
,
2049 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_Packet
) ? "Pck" : "",
2050 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_FP
) ? "FP" : "",
2051 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_Blank
) ? "Blank" : "",
2052 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_RT
) ? "RT" : "",
2054 TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Trk_Mask
,
2055 (TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Copy
) ? "Cpy" : "",
2056 (TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Damage
) ? "Damage" : "",
2058 TrackInfoOut
->LastRecordedAddr
,
2059 (TrackInfoOut
->NWA_V
& TrkInfo_LRA_V
) ? "vld" : "inv",
2061 TrackInfoOut
->ReadCompatLBA
2063 #ifdef UDF_FORMAT_MEDIA
2064 if(fms
&& fms
->opt_disk_info
) {
2065 UserPrint(("Track %d: \n", TrackNumber
));
2066 UserPrint((" Ses %d, Track %d (%x, len %x) PckSize %x: \n"
2067 " NWA: %x (%s) DatType:%x, %s %s %s %s TrkType:%x %s %s\n"
2068 " LRA: %x (%s) RC_LBA:%x\n",
2069 TrackInfoOut
->SesNum
,
2071 TrackInfoOut
->TrackStartLBA
,
2072 TrackInfoOut
->TrackLength
,
2073 TrackInfoOut
->FixPacketSize
,
2075 TrackInfoOut
->NextWriteLBA
,
2076 TrackInfoOut
->NWA_V
& TrkInfo_NWA_V
? "vld" : "inv",
2077 TrackInfoOut
->DataParam
.Flags
& TrkInfo_Dat_Mask
,
2078 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_Packet
) ? "Pck" : "",
2079 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_FP
) ? "FP" : "",
2080 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_Blank
) ? "Blank" : "",
2081 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_RT
) ? "RT" : "",
2083 TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Trk_Mask
,
2084 (TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Copy
) ? "Cpy" : "",
2085 (TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Damage
) ? "Damage" : "",
2087 TrackInfoOut
->LastRecordedAddr
,
2088 (TrackInfoOut
->NWA_V
& TrkInfo_LRA_V
) ? "vld" : "inv",
2090 TrackInfoOut
->ReadCompatLBA
2093 #endif //UDF_FORMAT_MEDIA
2095 if(TrackNumber
== DiscInfo
->FirstTrackNum
) {
2096 if(!(Vcb
->TrackMap
[TrackNumber
].FirstLba
& 0x80000000)) {
2097 KdPrint(("TrkInfo: Update FirstLBA (%x)\n", Vcb
->TrackMap
[TrackNumber
].FirstLba
));
2098 Vcb
->FirstLBA
= Vcb
->TrackMap
[TrackNumber
].FirstLba
;
2101 if((TrackInfoOut
->SesNum
== Vcb
->LastSession
) && !Vcb
->FirstTrackNumLastSes
) {
2102 if(!(Vcb
->TrackMap
[TrackNumber
].FirstLba
& 0x80000000)) {
2103 KdPrint(("TrkInfo: Update FirstLBALastSes (%x)\n", Vcb
->TrackMap
[TrackNumber
].FirstLba
));
2104 Vcb
->FirstLBALastSes
= Vcb
->TrackMap
[TrackNumber
].FirstLba
;
2106 Vcb
->FirstTrackNumLastSes
= TrackNumber
;
2110 if(!(TrackInfoOut
->NextWriteLBA
& 0x80000000) &&
2111 !(TrackInfoOut
->TrackLength
& 0x80000000) &&
2112 (Vcb
->NWA
< TrackInfoOut
->NextWriteLBA
)
2114 KdPrint((" set NWA to %x\n", TrackInfoOut
->NextWriteLBA
));
2115 if(Vcb
->MediaClassEx
!= CdMediaClass_DVDpRW
) {
2116 Vcb
->NWA
= TrackInfoOut
->NextWriteLBA
;
2119 TrackInfoOut
->TrackStartLBA
+ TrackInfoOut
->TrackLength
- (TrackInfoOut
->TrackLength
? 1 : 0);
2122 if(Vcb
->MediaClassEx
!= CdMediaClass_DVDpRW
&&
2123 !(TrackInfoOut
->TrackLength
& 0x80000000) &&
2124 TrackInfoOut
->TrackLength
> 1) {
2125 Vcb
->LastPossibleLBA
=
2126 TrackInfoOut
->TrackStartLBA
+ TrackInfoOut
->TrackLength
- (TrackInfoOut
->TrackLength
? 1 : 0);
2127 KdPrint((" set LastPossibleLBA=%x\n", Vcb
->LastPossibleLBA
));
2129 TrackNumber
= Vcb
->LastTrackNum
;
2130 // quick formatted +RW returns bogus value
2131 if(Vcb
->MediaClassEx
== CdMediaClass_DVDpRW
) {
2132 KdPrint((" check quick formatted +RW\n"));
2133 if(Vcb
->TrackMap
[TrackNumber
].LastLba
&&
2134 !(Vcb
->TrackMap
[TrackNumber
].LastLba
& 0x80000000) &&
2135 Vcb
->TrackMap
[TrackNumber
].LastLba
< Vcb
->LastPossibleLBA
/*&&
2136 Vcb->TrackMap[TrackNumber].LastLba != Vcb->LastPossibleLBA*/
2138 KdPrint((" track LastLBA %x != LastPossibleLBA %x, verify\n",
2139 Vcb
->TrackMap
[TrackNumber
].LastLba
, Vcb
->LastPossibleLBA
));
2141 if(Vcb
->MRWStatus
== DiscInfo_BGF_Complete
) {
2142 KdPrint((" complete MRW state\n"));
2144 Vcb
->LastPossibleLBA
=
2147 Vcb
->TrackMap
[TrackNumber
].LastLba
;
2148 goto valid_track_length
;
2149 #endif // _BROWSE_UDF_
2151 if(Vcb
->MRWStatus
) {
2155 KdPrint((" MRW state %x\n", Vcb
->MRWStatus
));
2157 buff
= (uint8
*)DbgAllocatePoolWithTag(NonPagedPool
, Vcb
->WriteBlockSize
, 'bNWD' );
2161 Vcb
->WriteBlockSize
,
2162 Vcb
->TrackMap
[TrackNumber
].LastLba
+1,
2166 if(!OS_SUCCESS(RC
)) {
2167 KdPrint((" Can't read beyond track LastLBA (%x)\n", Vcb
->TrackMap
[TrackNumber
].LastLba
+1));
2168 Vcb
->LastLBA
= Vcb
->TrackMap
[TrackNumber
].LastLba
;
2169 Vcb
->NWA
= Vcb
->LastLBA
+1;
2170 Vcb
->TrackMap
[TrackNumber
].NWA_V
= 1;
2171 Vcb
->TrackMap
[TrackNumber
].NWA
= Vcb
->NWA
;
2172 Vcb
->TrackMap
[TrackNumber
].LastLba
= Vcb
->LastPossibleLBA
;
2173 RC
= STATUS_SUCCESS
;
2174 goto valid_track_length
;
2179 KdPrint((" set track LastLBA %x\n", Vcb
->LastPossibleLBA
));
2182 Vcb
->TrackMap
[TrackNumber
].LastLba
=
2183 Vcb
->LastPossibleLBA
;
2186 // Test for last empty session
2187 if((Vcb
->TrackMap
[TrackNumber
].Session
!=
2188 Vcb
->TrackMap
[TrackNumber
-1].Session
) &&
2189 (Vcb
->LastSession
> 1)) {
2190 // Note: some devices return negative track length
2191 if((Vcb
->TrackMap
[TrackNumber
].LastLba
<=
2192 Vcb
->TrackMap
[TrackNumber
].FirstLba
) ||
2193 (Vcb
->TrackMap
[TrackNumber
].FirstLba
==
2194 Vcb
->TrackMap
[TrackNumber
].NWA
)) {
2195 // empty last session...
2196 Vcb
->LastTrackNum
--;
2198 /* for(SesNum = Vcb->TrackMap[TrackNumber].Session;
2199 Vcb->TrackMap[TrackNumber].Session == SesNum;
2203 Vcb
->LastSession
= Vcb
->TrackMap
[TrackNumber
-1].Session
;
2207 TrackNumber
= Vcb
->LastTrackNum
;
2209 Vcb
->LastLBA
= min(Vcb
->TrackMap
[TrackNumber
].LastLba
, Vcb
->TrackMap
[TrackNumber
].NWA
);
2210 #endif //_BROWSE_UDF_
2212 if(Vcb
->TrackMap
[TrackNumber
].NWA_V
& TrkInfo_NWA_V
) {
2213 KdPrint((" NWA ok, set LastLBA to min(Last %x, NWA %x\n",
2214 Vcb
->TrackMap
[TrackNumber
].LastLba
,
2215 Vcb
->TrackMap
[TrackNumber
].NWA
));
2216 Vcb
->LastLBA
= min(Vcb
->TrackMap
[TrackNumber
].LastLba
, Vcb
->TrackMap
[TrackNumber
].NWA
);
2218 KdPrint((" no NWA, set LastLBA to Last %x\n", Vcb
->TrackMap
[TrackNumber
].LastLba
));
2219 Vcb
->LastLBA
= Vcb
->TrackMap
[TrackNumber
].LastLba
;
2222 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_TRACKMAP
;
2223 if(!PacketTrack
&& Vcb
->MediaClassEx
!= CdMediaClass_DVDRAM
) {
2224 KdPrint((" disable Raw mount\n"));
2225 Vcb
->VCBFlags
&= ~UDF_VCB_FLAGS_RAW_DISK
;
2231 if(DiscInfo
) MyFreePool__(DiscInfo
);
2232 if(TrackInfoOut
) MyFreePool__(TrackInfoOut
);
2236 } // end UDFReadDiscTrackInfo()
2239 This routine attempts to read disk layout using ReadFullTOC cmd
2242 UDFReadAndProcessFullToc(
2243 PDEVICE_OBJECT DeviceObject
, // the target device object
2247 OSSTATUS RC
= STATUS_SUCCESS
;
2248 PREAD_FULL_TOC_USER_OUT toc
= (PREAD_FULL_TOC_USER_OUT
)MyAllocatePool__(NonPagedPool
,sizeof(READ_FULL_TOC_USER_OUT
) );
2252 uint32 LastLeadOut
= 0;
2253 // BOOLEAN IsMRW = FALSE;
2255 KdPrint(("UDFReadAndProcessFullToc\n"));
2257 if(!toc
) return STATUS_INSUFFICIENT_RESOURCES
;
2258 Vcb
->FirstTrackNum
= 0xFF;
2260 RtlZeroMemory(toc
,sizeof(READ_FULL_TOC_USER_OUT
));
2262 RC
= UDFPhSendIOCTL(IOCTL_CDRW_READ_FULL_TOC
,DeviceObject
,
2264 toc
,sizeof(READ_FULL_TOC_USER_OUT
),
2267 if(!OS_SUCCESS(RC
)) {
2274 Vcb
->PhDeviceType
= FILE_DEVICE_CD_ROM
;
2276 Vcb
->LastSession
= toc
->Sessions
.Last_TrackSes
;
2278 RC
= UDFReallocTrackMap(Vcb
, 0x100);
2279 if(!OS_SUCCESS(RC
)) {
2284 // get LastPossibleLBA
2286 // Note: some drives return Full TOC items unordered.
2287 // So, LeadOut position may come before Track definition.
2288 // In order to handle such situation, we must initialize
2289 // CurTrack when First or Last Track descriptor comes
2290 for (index
=0;(index
<MAXIMUM_NUMBER_OF_SESSIONS
);index
++) {
2291 /* if((toc->SessionData[index].Adr == TOC_ADR_TrackInfo) &&
2292 ((toc->SessionData[index].Control == TOC_CTL_MRWTrackInfo) || (toc->SessionData[index].Control == TOC_CTL_MRWLastSes))) {
2295 if(toc
->SessionData
[index
].Adr
== 1) {
2296 switch (POINT
= toc
->SessionData
[index
].POINT
) {
2297 case POINT_FirstTrackNum
: {
2298 Vcb
->FirstTrackNum
= toc
->SessionData
[index
].Params
.FirstTrackNum
.FirstTrackNum
;
2300 CurTrack
= (uint8
)(Vcb
->FirstTrackNum
);
2303 case POINT_LastTrackNum
: {
2304 Vcb
->LastTrackNum
= toc
->SessionData
[index
].Params
.LastTrackNum
.LastTrackNum
;
2305 if(CurTrack
< Vcb
->LastTrackNum
)
2306 CurTrack
= (uint8
)(Vcb
->FirstTrackNum
);
2309 case POINT_StartPositionOfLeadOut
: {
2310 #define TempMSF toc->SessionData[index].Params.StartPositionOfLeadOut.MSF
2311 Vcb
->TrackMap
[CurTrack
].LastLba
= MSF_TO_LBA(TempMSF
[0],TempMSF
[1],TempMSF
[2]);
2312 LastLeadOut
= max(LastLeadOut
, Vcb
->TrackMap
[CurTrack
].LastLba
);
2317 if( (Vcb
->FirstTrackNum
!= 0x0FF) &&
2318 (toc
->SessionData
[index
].POINT
== Vcb
->FirstTrackNum
) ) {
2319 #define TempMSF toc->SessionData[index].Params.StartPositionOfTrack.MSF
2320 Vcb
->FirstLBA
= MSF_TO_LBA(TempMSF
[0],TempMSF
[1],TempMSF
[2]);
2321 if(Vcb
->FirstLBA
& 0x80000000) {
2329 if((POINT
>= POINT_StartPositionOfTrack_Min
) &&
2330 (POINT
<= POINT_StartPositionOfTrack_Max
)) {
2331 #define TempMSF toc->SessionData[index].Params.StartPositionOfTrack.MSF
2332 Vcb
->TrackMap
[POINT
].FirstLba
= MSF_TO_LBA(TempMSF
[0],TempMSF
[1],TempMSF
[2])-1;
2333 if(Vcb
->TrackMap
[POINT
].FirstLba
& 0x80000000) {
2335 Vcb
->TrackMap
[POINT
].FirstLba
= 0;
2337 if(Vcb
->TrackMap
[POINT
-1].LastLba
) {
2338 Vcb
->TrackMap
[POINT
].FirstLba
= Vcb
->TrackMap
[POINT
-1].LastLba
+1;
2343 if(POINT
> POINT_StartPositionOfTrack_Min
) {
2344 Vcb
->TrackMap
[POINT
-1].LastLba
= Vcb
->TrackMap
[POINT
].FirstLba
-1;
2349 if(toc
->SessionData
[index
].Adr
== 5) {
2350 switch (POINT
= toc
->SessionData
[index
].POINT
) {
2351 case POINT_StartPositionOfNextProgramArea
: {
2352 #define TempMSF toc->SessionData[index].Params.StartPositionOfNextProgramArea.MaxLeadOut_MSF
2353 Vcb
->LastPossibleLBA
= MSF_TO_LBA(TempMSF
[0],TempMSF
[1],TempMSF
[2]);
2366 KdPrint(("No MRW\n"));
2367 Vcb->CompatFlags &= ~UDF_VCB_IC_MRW_ADDR_PROBLEM;
2369 // Vcb->CompatFlags &= ~UDF_VCB_IC_MRW_ADDR_PROBLEM;
2370 // some devices report LastTrackNum=0 for full disks
2371 Vcb
->LastTrackNum
= max(Vcb
->LastTrackNum
, Vcb
->FirstTrackNum
);
2372 Vcb
->TrackMap
[Vcb
->LastTrackNum
].LastLba
= max(LastLeadOut
, Vcb
->TrackMap
[Vcb
->LastTrackNum
].LastLba
);
2374 Vcb
->LastLBA
= Vcb
->TrackMap
[Vcb
->LastTrackNum
].LastLba
;
2377 // Vcb->LastLBA=PacketVariable2Fixed(Vcb->LastLBA)-2;
2378 return STATUS_SUCCESS
;
2379 } // end UDFReadAndProcessFullToc()
2382 use standard way to determine disk layout (ReadTOC cmd)
2386 PDEVICE_OBJECT DeviceObject
, // the target device object
2387 PVCB Vcb
// Volume control block from this DevObj
2390 OSSTATUS RC
= STATUS_SUCCESS
;
2391 PREAD_TOC_USER_OUT toc
= (PREAD_TOC_USER_OUT
)MyAllocatePool__(NonPagedPool
,max(Vcb
->BlockSize
, sizeof(READ_TOC_USER_OUT
)) );
2392 PGET_LAST_SESSION_USER_OUT LastSes
= (PGET_LAST_SESSION_USER_OUT
)MyAllocatePool__(NonPagedPool
,sizeof(GET_LAST_SESSION_USER_OUT
) );
2393 uint32 LocalTrackCount
;
2394 uint32 LocalTocLength
;
2399 uint32 ReadBytes
, i
, len
;
2400 #endif //_BROWSE_UDF_
2401 #ifdef UDF_FORMAT_MEDIA
2402 PUDFFmtState fms
= Vcb
->fms
;
2405 #endif //UDF_FORMAT_MEDIA
2407 KdPrint(("UDFUseStandard\n"));
2411 if(!toc
|| !LastSes
) {
2412 try_return (RC
= STATUS_INSUFFICIENT_RESOURCES
);
2414 RtlZeroMemory(toc
,sizeof(READ_TOC_TOC
));
2416 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_USE_STD
;
2418 RC
= UDFPhSendIOCTL(IOCTL_CDROM_READ_TOC
,DeviceObject
,
2419 toc
,sizeof(READ_TOC_USER_OUT
),
2420 toc
,sizeof(READ_TOC_USER_OUT
),
2423 if((RC
== STATUS_DEVICE_NOT_READY
) || (RC
== STATUS_NO_MEDIA_IN_DEVICE
)) {
2426 #ifdef UDF_FORMAT_MEDIA
2427 if(fms
->opt_media
== MT_none
) {
2428 try_return(RC
= STATUS_NO_MEDIA_IN_DEVICE
);
2430 #endif //UDF_FORMAT_MEDIA
2432 // If even standard read toc does not work, then use default values
2433 if(!OS_SUCCESS(RC
)) {
2435 RC
= UDFReallocTrackMap(Vcb
, 2);
2436 if(!OS_SUCCESS(RC
)) {
2441 Vcb
->FirstTrackNum
=1;
2443 Vcb
->LastTrackNum
=1;
2444 Vcb
->TrackMap
[1].FirstLba
= Vcb
->FirstLBA
;
2445 Vcb
->TrackMap
[1].LastLba
= Vcb
->LastLBA
;
2446 Vcb
->TrackMap
[1].PacketSize
= PACKETSIZE_UDF
;
2447 #ifdef UDF_FORMAT_MEDIA
2449 #endif //UDF_FORMAT_MEDIA
2452 #ifdef UDF_HDD_SUPPORT
2453 if(UDFGetDevType(DeviceObject
) == FILE_DEVICE_DISK
) {
2454 try_return(RC
= STATUS_SUCCESS
);
2456 #endif //UDF_HDD_SUPPORT
2457 #endif //_BROWSE_UDF_
2459 #ifdef UDF_FORMAT_MEDIA
2462 if(fms
->opt_media
== MT_HD
) {
2463 Vcb
->LastPossibleLBA
= Vcb
->LastLBA
;
2464 try_return(RC
= STATUS_SUCCESS
);
2467 #endif //UDF_FORMAT_MEDIA
2468 Vcb
->LastPossibleLBA
= max(Vcb
->LastLBA
, DEFAULT_LAST_LBA_FP_CD
);
2469 Vcb
->TrackMap
[1].DataParam
= TrkInfo_Dat_XA
| TrkInfo_FP
| TrkInfo_Packet
;
2470 Vcb
->TrackMap
[1].TrackParam
= TrkInfo_Trk_XA
;
2471 Vcb
->TrackMap
[1].NWA
= 0xffffffff;
2472 Vcb
->NWA
= DEFAULT_LAST_LBA_FP_CD
+ 7 + 1;
2473 try_return(RC
= STATUS_SUCCESS
);
2477 Vcb
->PhDeviceType
= FILE_DEVICE_CD_ROM
;
2480 LocalTrackCount
= toc
->Tracks
.Last_TrackSes
- toc
->Tracks
.First_TrackSes
+ 1;
2481 LocalTocLength
= PtrOffset( toc
, &(toc
->TrackData
[LocalTrackCount
+ 1]) );
2483 // Get out if there is an immediate problem with the TOC.
2484 if(toc
->Tracks
.First_TrackSes
> toc
->Tracks
.Last_TrackSes
) {
2485 try_return(RC
= STATUS_DISK_CORRUPT_ERROR
);
2489 Vcb
->LastTrackNum
=toc
->Tracks
.Last_TrackSes
;
2490 Vcb
->FirstTrackNum
=toc
->Tracks
.First_TrackSes
;
2491 // some devices report LastTrackNum=0 for full disks
2492 Vcb
->LastTrackNum
= max(Vcb
->LastTrackNum
, Vcb
->FirstTrackNum
);
2494 RC
= UDFReallocTrackMap(Vcb
, MAXIMUM_NUMBER_OF_TRACKS
+1);
2495 /* if(Vcb->TrackMap) {
2496 MyFreePool__(Vcb->TrackMap);
2497 Vcb->TrackMap = NULL;
2499 Vcb->TrackMap = (PUDFTrackMap)
2500 MyAllocatePool__(NonPagedPool, (MAXIMUM_NUMBER_OF_TRACKS+1)*sizeof(UDFTrackMap));
2501 if(!Vcb->TrackMap) {
2503 return STATUS_INSUFFICIENT_RESOURCES;
2505 RtlZeroMemory(Vcb->TrackMap,(MAXIMUM_NUMBER_OF_TRACKS+1)*sizeof(UDFTrackMap));
2507 if(!OS_SUCCESS(RC
)) {
2511 // find 1st and last session
2512 RC
= UDFPhSendIOCTL(IOCTL_CDROM_GET_LAST_SESSION
,DeviceObject
,
2513 LastSes
,sizeof(GET_LAST_SESSION_USER_OUT
),
2514 LastSes
,sizeof(GET_LAST_SESSION_USER_OUT
),
2517 if(OS_SUCCESS(RC
)) {
2518 TrkNum
= LastSes
->LastSes_1stTrack
.TrackNum
;
2519 Vcb
->LastSession
= LastSes
->Sessions
.First_TrackSes
;
2520 for(TocEntry
=0;TocEntry
<LocalTrackCount
+ 1;TocEntry
++) {
2521 if(toc
->TrackData
[TocEntry
].TrackNum
== TrkNum
) {
2522 Vcb
->TrackMap
[TrkNum
].Session
= Vcb
->LastSession
;
2528 // Scan toc for first & last LBA
2529 for(TocEntry
=0;TocEntry
<LocalTrackCount
+ 1;TocEntry
++) {
2530 #define TempMSF toc->TrackData[TocEntry].LBA
2531 TrkNum
= toc
->TrackData
[TocEntry
].TrackNum
;
2533 if (TrkNum
>= MAXIMUM_NUMBER_OF_TRACKS
&&
2534 TrkNum
!= TOC_LastTrack_ID
) {
2535 KdPrint(("UDFUseStandard: Array out of bounds\n"));
2537 try_return(RC
= STATUS_SUCCESS
);
2539 KdPrint(("Track N %d (0x%x) first LBA %ld (%lx) \n",TrkNum
,TrkNum
,
2540 MSF_TO_LBA(TempMSF
[1],TempMSF
[2],TempMSF
[3]),
2541 MSF_TO_LBA(TempMSF
[1],TempMSF
[2],TempMSF
[3])));
2543 if(Vcb
->FirstTrackNum
== TrkNum
) {
2544 Vcb
->FirstLBA
= MSF_TO_LBA(TempMSF
[1],TempMSF
[2],TempMSF
[3]);
2545 if(Vcb
->FirstLBA
& 0x80000000) {
2549 if(TOC_LastTrack_ID
== TrkNum
) {
2550 Vcb
->LastLBA
= MSF_TO_LBA(TempMSF
[1],TempMSF
[2],TempMSF
[3])-1;
2551 Vcb
->TrackMap
[OldTrkNum
].LastLba
= Vcb
->LastLBA
-1;
2552 KdPrint(("UDFUseStandard: Last track entry, break TOC scan\n"));
2556 Vcb
->TrackMap
[TrkNum
].FirstLba
= MSF_TO_LBA(TempMSF
[1],TempMSF
[2],TempMSF
[3]);
2557 if(Vcb
->TrackMap
[TrkNum
].FirstLba
& 0x80000000)
2558 Vcb
->TrackMap
[TrkNum
].FirstLba
= 0;
2560 if (TOC_LastTrack_ID
== OldTrkNum
) {
2561 KdPrint(("UDFUseStandard: Wrong previous track number\n"));
2564 Vcb
->TrackMap
[OldTrkNum
].LastLba
= Vcb
->TrackMap
[TrkNum
].FirstLba
-1;
2569 switch(toc
->TrackData
[TocEntry
].Control
& TocControl_TrkMode_Mask
) {
2570 case TocControl_TrkMode_Data
:
2571 case TocControl_TrkMode_IncrData
:
2572 Vcb
->TrackMap
[TrkNum
].DataParam
= TrkInfo_Dat_XA
;
2573 Vcb
->TrackMap
[TrkNum
].TrackParam
= TrkInfo_Trk_XA
;
2576 Vcb
->TrackMap
[TrkNum
].DataParam
= TrkInfo_Dat_unknown
;
2577 Vcb
->TrackMap
[TrkNum
].TrackParam
= TrkInfo_Trk_unknown
;
2583 TrkNum
= Vcb
->LastTrackNum
;
2584 RC
= STATUS_SUCCESS
;
2585 // find last _valid_ track
2586 for(;TrkNum
;TrkNum
--) {
2587 if((Vcb
->TrackMap
[TrkNum
].DataParam
!= TrkInfo_Dat_unknown
) &&
2588 (Vcb
->TrackMap
[TrkNum
].TrackParam
!= TrkInfo_Trk_unknown
)) {
2589 RC
= STATUS_UNSUCCESSFUL
;
2590 Vcb
->LastTrackNum
= TrkNum
;
2594 // no valid tracks...
2596 KdPrint(("UDFUseStandard: no valid tracks...\n"));
2597 try_return(RC
= STATUS_UNRECOGNIZED_VOLUME
);
2601 // Check for last VP track. Some last sectors may belong to Link-data &
2602 // be unreadable. We should forget about them, because UDF needs
2603 // last _readable_ sector.
2604 while(!OS_SUCCESS(RC
) && (i
<8)) {
2605 RC
= UDFPhReadSynchronous(Vcb
->TargetDeviceObject
, (int8
*)toc
, Vcb
->BlockSize
,
2606 ((uint64
)(Vcb
->TrackMap
[TrkNum
].LastLba
-i
)) << Vcb
->BlockSizeBits
, &ReadBytes
, PH_TMP_BUFFER
);
2609 if(OS_SUCCESS(RC
)) {
2610 Vcb
->LastLBA
= Vcb
->TrackMap
[TrkNum
].LastLba
-i
+1;
2612 Vcb->TrackMap[TrkNum].PacketSize = PACKETSIZE_UDF;
2613 Vcb->TrackMap[TrkNum].;
2617 // Check for FP track. READ_TOC reports actual track length, but
2618 // Link-data is hidden & unreadable for us. So, available track
2619 // length may be less than actual. Here we assume that Packet-size
2620 // is PACKETSIZE_UDF.
2622 len
= Vcb
->TrackMap
[TrkNum
].LastLba
- Vcb
->TrackMap
[TrkNum
].FirstLba
+ 1;
2623 len
= (uint32
)(((int64
)len
*PACKETSIZE_UDF
) / (PACKETSIZE_UDF
+7));
2625 while(!OS_SUCCESS(RC
) && (i
<9)) {
2626 RC
= UDFPhReadSynchronous(Vcb
->TargetDeviceObject
, (int8
*)toc
, Vcb
->BlockSize
,
2627 ((uint64
)(Vcb
->TrackMap
[TrkNum
].FirstLba
-i
+len
)) << Vcb
->BlockSizeBits
, &ReadBytes
, PH_TMP_BUFFER
);
2630 if(OS_SUCCESS(RC
)) {
2632 Vcb
->TrackMap
[TrkNum
].LastLba
= Vcb
->TrackMap
[TrkNum
].FirstLba
-i
+len
+1;
2633 Vcb
->TrackMap
[TrkNum
].PacketSize
= PACKETSIZE_UDF
;
2634 // Vcb->TrackMap[TrkNum].;
2636 if(RC
== STATUS_INVALID_DEVICE_REQUEST
) {
2637 // wrap return code from Audio-disk
2638 RC
= STATUS_SUCCESS
;
2642 #ifdef UDF_CDRW_EMULATION_ON_ROM
2643 Vcb
->LastPossibleLBA
= Vcb
->LastLBA
+7+1+1024;
2644 Vcb
->NWA
= Vcb
->LastLBA
+7+1;
2646 Vcb
->LastPossibleLBA
=
2647 Vcb
->NWA
= Vcb
->LastLBA
+7+1;
2648 #endif //UDF_CDRW_EMULATION_ON_ROM
2650 #else //_BROWSE_UDF_
2652 Vcb
->FirstTrackNum
=toc
->Tracks
.Last_TrackSes
;
2653 Vcb
->LastTrackNum
=toc
->Tracks
.First_TrackSes
;
2655 // Scan toc for first & last LBA
2656 for(TocEntry
=0;TocEntry
<LocalTrackCount
+ 1;TocEntry
++) {
2657 #define TempMSF toc->TrackData[TocEntry].LBA
2658 if(Vcb
->FirstTrackNum
== toc
->TrackData
[TocEntry
].TrackNum
) {
2659 Vcb
->FirstLBA
= MSF_TO_LBA(TempMSF
[1],TempMSF
[2],TempMSF
[3]);
2660 if(Vcb
->FirstLBA
& 0x80000000) {
2664 if(TOC_LastTrack_ID
== toc
->TrackData
[TocEntry
].TrackNum
) {
2665 Vcb
->LastLBA
= MSF_TO_LBA(TempMSF
[1],TempMSF
[2],TempMSF
[3])-1;
2670 // Vcb->LastLBA=PacketVariable2Fixed(Vcb->LastLBA)-2;
2671 Vcb
->LastPossibleLBA
= DEFAULT_LAST_LBA_FP_CD
;
2672 #endif //_BROWSE_UDF_
2675 if(toc
) MyFreePool__(toc
);
2676 if(LastSes
) MyFreePool__(LastSes
);
2680 } // end UDFUseStandard()
2683 Get block size (for read operation)
2687 IN PDEVICE_OBJECT DeviceObject
, // the target device object
2688 IN PVCB Vcb
// Volume control block from this DevObj
2691 OSSTATUS RC
= STATUS_SUCCESS
;
2692 PDISK_GEOMETRY DiskGeometry
= (PDISK_GEOMETRY
)MyAllocatePool__(NonPagedPool
,sizeof(DISK_GEOMETRY
));
2693 PPARTITION_INFORMATION PartitionInfo
= (PPARTITION_INFORMATION
)MyAllocatePool__(NonPagedPool
,sizeof(PARTITION_INFORMATION
)*2);
2694 #ifdef UDF_FORMAT_MEDIA
2695 PUDFFmtState fms
= Vcb
->fms
;
2698 #endif //UDF_FORMAT_MEDIA
2700 if(!DiskGeometry
|| !PartitionInfo
)
2701 try_return (RC
= STATUS_INSUFFICIENT_RESOURCES
);
2705 #ifdef UDF_HDD_SUPPORT
2707 if(UDFGetDevType(DeviceObject
) == FILE_DEVICE_DISK
) {
2708 KdPrint(("UDFGetBlockSize: HDD\n"));
2709 RC
= UDFPhSendIOCTL(IOCTL_DISK_GET_DRIVE_GEOMETRY
,DeviceObject
,
2711 DiskGeometry
,sizeof(DISK_GEOMETRY
),
2713 Vcb
->BlockSize
= (OS_SUCCESS(RC
)) ? DiskGeometry
->BytesPerSector
: 512;
2716 RC
= UDFPhSendIOCTL(IOCTL_DISK_GET_PARTITION_INFO
,DeviceObject
,
2718 PartitionInfo
,sizeof(PARTITION_INFORMATION
),
2720 if(!NT_SUCCESS(RC
)) {
2721 KdPrint(("UDFGetBlockSize: IOCTL_DISK_GET_PARTITION_INFO failed\n"));
2722 if(RC
= STATUS_INVALID_DEVICE_REQUEST
)
2723 RC
= STATUS_UNRECOGNIZED_VOLUME
;
2726 if(PartitionInfo
->PartitionType
!= PARTITION_IFS
) {
2727 KdPrint(("UDFGetBlockSize: PartitionInfo->PartitionType != PARTITION_IFS\n"));
2728 try_return(RC
= STATUS_UNRECOGNIZED_VOLUME
);
2731 #endif //UDF_HDD_SUPPORT
2732 RC
= UDFPhSendIOCTL(IOCTL_CDROM_GET_DRIVE_GEOMETRY
,DeviceObject
,
2733 DiskGeometry
,sizeof(DISK_GEOMETRY
),
2734 DiskGeometry
,sizeof(DISK_GEOMETRY
),
2737 if(RC
== STATUS_DEVICE_NOT_READY
) {
2738 // probably, the device is really busy, may be by CD/DVD recording
2739 UserPrint((" busy (0)\n"));
2743 Vcb
->BlockSize
= (OS_SUCCESS(RC
)) ? DiskGeometry
->BytesPerSector
: 2048;
2744 #ifdef UDF_HDD_SUPPORT
2747 #endif //UDF_HDD_SUPPORT
2749 #endif //_BROWSE_UDF_
2751 #ifdef UDF_FORMAT_MEDIA
2753 RC
= UDFPhSendIOCTL(IOCTL_CDROM_GET_DRIVE_GEOMETRY
,DeviceObject
,
2754 DiskGeometry
,sizeof(DISK_GEOMETRY
),
2755 DiskGeometry
,sizeof(DISK_GEOMETRY
),
2758 if(!NT_SUCCESS(RC
)) {
2759 RC
= UDFPhSendIOCTL(IOCTL_DISK_GET_DRIVE_GEOMETRY
,DeviceObject
,
2760 DiskGeometry
,sizeof(DISK_GEOMETRY
),
2761 DiskGeometry
,sizeof(DISK_GEOMETRY
),
2763 if(NT_SUCCESS(RC
)) {
2764 fms
->opt_media
= MT_HD
;
2765 RC
= UDFPhSendIOCTL(IOCTL_DISK_GET_PARTITION_INFO
,DeviceObject
,
2767 PartitionInfo
,sizeof(PARTITION_INFORMATION
)*2,
2769 if(!NT_SUCCESS(RC
)) {
2771 RC
= SetFilePointer(DeviceObject
->h
,0,&HiOffs
,FILE_END
);
2776 if(RC
== STATUS_DEVICE_NOT_READY
) {
2777 // probably, the device is really busy, may be by CD/DVD recording
2778 UserPrint((" busy\n"));
2782 Vcb
->BlockSize
= (NT_SUCCESS(RC
)) ? DiskGeometry
->BytesPerSector
: 2048;
2784 #endif //UDF_FORMAT_MEDIA
2786 // Block size must be an even multiple of 512
2787 switch (Vcb
->BlockSize
) {
2788 case 2048: Vcb
->BlockSizeBits
= 11; break;
2789 #ifdef UDF_HDD_SUPPORT
2790 case 512: Vcb
->BlockSizeBits
= 9; break;
2791 case 1024: Vcb
->BlockSizeBits
= 10; break;
2792 case 4096: Vcb
->BlockSizeBits
= 12; break;
2793 case 8192: Vcb
->BlockSizeBits
= 13; break;
2794 #endif //UDF_HDD_SUPPORT
2797 UserPrint(("UDF: Bad block size (%ld)\n", Vcb
->BlockSize
));
2798 try_return(RC
= STATUS_UNSUCCESSFUL
);
2802 #ifdef UDF_HDD_SUPPORT
2805 (!fms
&& (UDFGetDevType(DeviceObject
) == FILE_DEVICE_DISK
))
2807 #endif //_BROWSE_UDF_
2808 #ifdef UDF_FORMAT_MEDIA
2809 (fms
&& fms
->opt_media
== MT_HD
)
2811 #endif //UDF_FORMAT_MEDIA
2814 #ifdef UDF_FORMAT_MEDIA
2815 if(fms
&& !NT_SUCCESS(RC
))
2816 try_return(STATUS_UNSUCCESSFUL
);
2817 #endif //UDF_FORMAT_MEDIA
2819 Vcb
->FirstLBA
=0;//(ULONG)(PartitionInfo->StartingOffset.QuadPart >> Vcb->BlockSizeBits);
2820 Vcb
->LastPossibleLBA
=
2821 Vcb
->LastLBA
= (uint32
)(PartitionInfo
->PartitionLength
.QuadPart
>> Vcb
->BlockSizeBits
)/* + Vcb->FirstLBA*/ - 1;
2823 #endif //UDF_HDD_SUPPORT
2825 if(OS_SUCCESS(RC
)) {
2826 Vcb
->LastLBA
= (uint32
)(DiskGeometry
->Cylinders
.QuadPart
*
2827 DiskGeometry
->TracksPerCylinder
*
2828 DiskGeometry
->SectorsPerTrack
- 1);
2829 if(Vcb
->LastLBA
== 0x7fffffff) {
2830 Vcb
->LastLBA
= UDFIsDvdMedia(Vcb
) ? DEFAULT_LAST_LBA_DVD
: DEFAULT_LAST_LBA_FP_CD
;
2833 Vcb
->LastLBA
= UDFIsDvdMedia(Vcb
) ? DEFAULT_LAST_LBA_DVD
: DEFAULT_LAST_LBA_FP_CD
;
2835 Vcb
->LastPossibleLBA
= Vcb
->LastLBA
;
2836 #ifdef UDF_HDD_SUPPORT
2838 #endif //UDF_HDD_SUPPORT
2841 // if(UDFGetDevType(DeviceObject) == FILE_DEVICE_DISK) {
2842 Vcb
->WriteBlockSize
= PACKETSIZE_UDF
*Vcb
->BlockSize
;
2844 // Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->BlockSize;
2846 #else //_BROWSE_UDF_
2847 if(fms
->opt_media
== MT_HD
) {
2848 Vcb
->WriteBlockSize
= Vcb
->BlockSize
;
2850 Vcb
->WriteBlockSize
= PACKETSIZE_UDF
*Vcb
->BlockSize
;
2852 #endif //_BROWSE_UDF_
2854 RC
= STATUS_SUCCESS
;
2858 KdPrint(("UDFGetBlockSize:\nBlock size is %x, Block size bits %x, Last LBA is %x\n",
2859 Vcb
->BlockSize
, Vcb
->BlockSizeBits
, Vcb
->LastLBA
));
2861 MyFreePool__(PartitionInfo
);
2862 MyFreePool__(DiskGeometry
);
2865 } // end UDFGetBlockSize()
2870 UDFCheckTrackFPAddressing(
2871 // IN PDEVICE_OBJECT DeviceObject, // the target device object
2872 IN PVCB Vcb
, // Volume control block from this DevObj
2876 OSSTATUS RC
= STATUS_SUCCESS
;
2877 // OSSTATUS RC2 = STATUS_UNSUCCESSFUL;
2881 // uint32 ReadBytes;
2885 ULONG FirstChunkLen
= 0;
2887 ULONG NextChunkLen
= 0;
2888 ULONG NextChunkLenCount
= 0;
2890 ULONG NextChunkLenOth
= 0;
2891 ULONG NextChunkLenOthCount
= 0;
2892 // ULONG MRW_Offset = 0;
2894 PLL_READ_USER_IN pLLR_in
;
2895 PCD_SECTOR_HEADER pHdr
;
2896 /* uint8 cMSF[3] = {0,2,0};
2897 uint8 cMSF1[3] = {0,2,1};*/
2900 if(!Vcb
->TrackMap
) {
2901 Vcb
->CompatFlags
&= ~UDF_VCB_IC_FP_ADDR_PROBLEM
;
2902 return STATUS_SUCCESS
;
2905 Buffer
= (uint8
*)DbgAllocatePoolWithTag(NonPagedPool
, max(Vcb
->BlockSize
,
2906 sizeof(LL_READ_USER_IN
)+16), 'pNWD');
2908 return STATUS_INSUFFICIENT_RESOURCES
;
2909 pLLR_in
= (PLL_READ_USER_IN
)Buffer
;
2910 pHdr
= (PCD_SECTOR_HEADER
)(Buffer
+sizeof(LL_READ_USER_IN
));
2912 /* if(Vcb->CompatFlags & UDF_VCB_IC_MRW_ADDR_PROBLEM) {
2913 MRW_Offset = (MRW_DMA_OFFSET/32)*39;
2917 for(i
=0; i
<=0x200; i
++) {
2919 RtlZeroMemory(pLLR_in
, sizeof(pLLR_in
)+16);
2920 pLLR_in
->ExpectedBlkType
= ReadCd_BlkType_Any
;
2922 pLLR_in
->NumOfBlocks
= 1;
2923 pLLR_in
->Flags
.Flags
= ReadCd_Header_Hdr
;
2924 // pLLR_in->UseMFS = FALSE; // already zero
2925 // MOV_MSF(pLLR_in->Starting_MSF, cMSF);
2926 // MOV_MSF(pLLR_in->Ending_MSF, cMSF1);
2927 RtlZeroMemory(pHdr
, sizeof(CD_SECTOR_HEADER
));
2928 RC
= UDFPhSendIOCTL(IOCTL_CDRW_LL_READ
, Vcb
->TargetDeviceObject
,
2929 pLLR_in
, sizeof(LL_READ_USER_IN
),
2930 pHdr
, sizeof(CD_SECTOR_HEADER
),
2933 /* RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, Buffer, Vcb->BlockSize,
2934 ((uint64)(i+MRW_Offset)) << Vcb->BlockSizeBits, &ReadBytes, 0);*/
2937 if(!OS_SUCCESS(RC
)) {
2938 KdPrint((" Read error at lba %x\n", i
));
2942 // skip strange (damaged ?) blocks
2943 if((pHdr
->Mode
.Flags
& WParam_SubHdr_Mode_Mask
) != WParam_SubHdr_Mode1
&&
2944 (pHdr
->Mode
.Flags
& WParam_SubHdr_Mode_Mask
) != WParam_SubHdr_Mode2
) {
2945 KdPrint((" Unexpected data type (%x) at lba %x\n", pHdr
->Mode
.Flags
& WParam_SubHdr_Mode_Mask
, i
));
2949 if((pHdr
->Mode
.Flags
& WParam_SubHdr_Format_Mask
) == WParam_SubHdr_Format_UserData
&&
2954 /* if(OS_SUCCESS(RC) && !OS_SUCCESS(RC2)) {
2958 if((pHdr
->Mode
.Flags
& WParam_SubHdr_Format_Mask
) != WParam_SubHdr_Format_UserData
&&
2960 // if(!OS_SUCCESS(RC) && OS_SUCCESS(RC2)) {
2961 KdPrint((" %x - %x (%x sectors)\n", lba
, i
-1, i
-lba
));
2962 if(!FirstChunkLen
) {
2963 FirstChunkLen
= i
-lba
;
2966 NextChunkLen
= i
-lba
;
2967 NextChunkLenCount
++;
2969 if(NextChunkLen
== i
-lba
) {
2970 NextChunkLenCount
++;
2972 if((NextChunkLenOth
+1) % (NextChunkLen
+1)) {
2973 NextChunkLenOth
= i
-lba
;
2974 NextChunkLenOthCount
++;
2976 NextChunkLenCount
++;
2982 user_data
= ((pHdr
->Mode
.Flags
& WParam_SubHdr_Format_Mask
) == WParam_SubHdr_Format_UserData
);
2986 DbgFreePool(Buffer
);
2988 if(!NextChunkLenCount
&& !NextChunkLenOthCount
) {
2989 Vcb
->CompatFlags
&= ~UDF_VCB_IC_FP_ADDR_PROBLEM
;
2990 return STATUS_SUCCESS
;
2992 if(NextChunkLenOthCount
> NextChunkLenCount
) {
2993 NextChunkLen
= NextChunkLenOth
;
2995 if(NextChunkLen
> PACKETSIZE_UDF
+7) {
2996 Vcb
->CompatFlags
&= ~UDF_VCB_IC_FP_ADDR_PROBLEM
;
2997 return STATUS_SUCCESS
;
2999 Vcb
->TrackMap
[TrackNum
].DataParam
&= ~TrkInfo_Dat_Mask
;
3000 Vcb
->TrackMap
[TrackNum
].DataParam
|= TrkInfo_Dat_XA
;
3001 Vcb
->TrackMap
[TrackNum
].Flags
|= TrackMap_FixFPAddressing
;
3002 Vcb
->TrackMap
[TrackNum
].PacketSize
= 1;
3003 while(NextChunkLen
>> Vcb
->TrackMap
[TrackNum
].PacketSize
) {
3004 Vcb
->TrackMap
[TrackNum
].PacketSize
++;
3006 Vcb
->TrackMap
[TrackNum
].PacketSize
= 1 << (Vcb
->TrackMap
[TrackNum
].PacketSize
-1);
3007 Vcb
->TrackMap
[TrackNum
].TrackFPOffset
= NextChunkLen
- FirstChunkLen
; // !!!!!
3008 Vcb
->TrackMap
[TrackNum
].PacketFPOffset
= Vcb
->TrackMap
[TrackNum
].TrackFPOffset
;//0;//NextChunkLenOth - FirstChunkLen;
3009 Vcb
->TrackMap
[TrackNum
].LastLba
= (Vcb
->TrackMap
[TrackNum
].LastLba
*Vcb
->TrackMap
[TrackNum
].PacketSize
) /
3010 (Vcb
->TrackMap
[TrackNum
].PacketSize
+ 7);
3012 return STATUS_SUCCESS
;
3013 } // end UDFCheckTrackFPAddressing()
3017 IN PVCB Vcb
, // Volume control block from this DevObj
3021 uint32 i
= Vcb
->LastReadTrack
;
3025 // if(Vcb->CompatFlags & UDF_VCB_IC_MRW_ADDR_PROBLEM) {
3026 if(Vcb
->TrackMap
[i
].Flags
& TrackMap_FixMRWAddressing
) {
3027 pk
= Lba
/ MRW_DA_SIZE
;
3028 rel
= Lba
% MRW_DA_SIZE
;
3029 Lba
= pk
*MRW_DMA_SEGMENT_SIZE
+ rel
;
3030 Lba
+= MRW_DMA_OFFSET
;
3032 if(Vcb
->TrackMap
[i
].Flags
& TrackMap_FixFPAddressing
) {
3035 pk
= Lba
/ Vcb
->TrackMap
[i
].PacketSize
;
3036 rel
= Lba
% Vcb
->TrackMap
[i
].PacketSize
;
3037 KdPrint(("FixFPAddr: %x -> %x\n", Lba
, pk
*(Vcb
->TrackMap
[i
].PacketSize
+7) + rel
));
3038 return pk
*(Vcb
->TrackMap
[i
].PacketSize
+7) + rel
/*- Vcb->TrackMap[i].PacketFPOffset*/;
3041 } // end UDFFixFPAddress()
3043 #endif //_BROWSE_UDF_
3046 detect device driver & try to read disk layout (use all methods)
3050 IN PDEVICE_OBJECT DeviceObject
, // the target device object
3051 IN PVCB Vcb
// Volume control block from this DevObj
3054 OSSTATUS RC
= STATUS_UNRECOGNIZED_VOLUME
;
3055 int8
* ioBuf
= (int8
*)MyAllocatePool__(NonPagedPool
,4096);
3057 PLUN_WRITE_PERF_DESC_USER WPerfDesc
;
3059 // BOOLEAN MRW_problem = FALSE;
3060 uint32 SavedFeatures
= 0;
3061 #ifdef UDF_FORMAT_MEDIA
3062 PUDFFmtState fms
= Vcb
->fms
;
3065 #endif //UDF_FORMAT_MEDIA
3067 KdPrint(("UDFGetDiskInfo\n"));
3070 return STATUS_INSUFFICIENT_RESOURCES
;
3074 RC
= UDFGetBlockSize(DeviceObject
, Vcb
);
3075 if(!OS_SUCCESS(RC
)) try_return(RC
);
3078 // Get lower driver signature
3079 RC
= UDFPhSendIOCTL(IOCTL_CDRW_GET_SIGNATURE
,DeviceObject
,
3080 ioBuf
,sizeof(GET_SIGNATURE_USER_OUT
),
3081 ioBuf
,sizeof(GET_SIGNATURE_USER_OUT
),
3084 if(!OS_SUCCESS(RC
)) {
3086 RC
= UDFUseStandard(DeviceObject
, Vcb
);
3088 if(!NT_SUCCESS(RC
) || fms
)
3091 // assume Device Recordable for now
3092 goto GetSignatureFailed
;
3093 #endif //_BROWSE_UDF_
3096 KdPrint(("UDF: Signature of low driver is : %s \n",
3097 ((PGET_SIGNATURE_USER_OUT
)(ioBuf
))->VendorId
));
3099 if(!strncmp( (const char *)(&( ((PGET_SIGNATURE_USER_OUT
)(ioBuf
))->VendorId
[0]) ),
3100 Signature
,strlen(Signature
) )) {
3101 KdPrint(("UDF: *****************************************\n"));
3102 KdPrint(("UDF: ********* Our Device Driver Found ******\n"));
3103 KdPrint(("UDF: *****************************************\n"));
3105 (Vcb
->VCBFlags
) |= UDF_VCB_FLAGS_OUR_DEVICE_DRIVER
;
3106 #ifndef _BROWSE_UDF_
3108 #ifdef UDF_FORMAT_MEDIA
3109 if(!fms
->opt_probe
) {
3110 #endif //UDF_FORMAT_MEDIA
3111 UDFResetDeviceDriver(Vcb
, Vcb
->TargetDeviceObject
, FALSE
);
3113 ((PPREVENT_MEDIA_REMOVAL_USER_IN
)(ioBuf
))->PreventMediaRemoval
= TRUE
;
3114 UDFPhSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL
,
3116 ioBuf
,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN
),
3119 #ifdef UDF_FORMAT_MEDIA
3121 #endif //UDF_FORMAT_MEDIA
3122 #endif //_BROWSE_UDF_
3123 //#else //_BROWSE_UDF_
3124 // get device features
3125 UDFPhSendIOCTL( IOCTL_CDRW_GET_DEVICE_INFO
,
3128 ioBuf
,sizeof(GET_DEVICE_INFO_USER_OUT
),
3131 Vcb
->SavedFeatures
=
3132 SavedFeatures
= ((PGET_DEVICE_INFO_USER_OUT
)ioBuf
)->Features
;
3133 if(!(SavedFeatures
& CDRW_FEATURE_SYNC_ON_WRITE
)) {
3134 KdPrint(("UDFGetDiskInfo: UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE\n"));
3135 Vcb
->CompatFlags
|= UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE
;
3137 if(!(SavedFeatures
& CDRW_FEATURE_FORCE_SYNC_BEFORE_READ
)) {
3138 KdPrint(("UDFGetDiskInfo: UDF_VCB_IC_SYNCCACHE_BEFORE_READ\n"));
3139 Vcb
->CompatFlags
|= UDF_VCB_IC_SYNCCACHE_BEFORE_READ
;
3141 if(SavedFeatures
& CDRW_FEATURE_BAD_RW_SEEK
) {
3142 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_BAD_RW_SEEK\n"));
3143 Vcb
->CompatFlags
|= UDF_VCB_IC_BAD_RW_SEEK
;
3145 // we must check if this is FP-formatted disk in old devices
3146 // independently of MediaType they report
3147 if(SavedFeatures
& CDRW_FEATURE_FP_ADDRESSING_PROBLEM
) {
3148 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_FP_ADDRESSING_PROBLEM ?\n"));
3149 Vcb
->CompatFlags
|= UDF_VCB_IC_FP_ADDR_PROBLEM
;
3151 if(SavedFeatures
& CDRW_FEATURE_MRW_ADDRESSING_PROBLEM
) {
3152 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM ?\n"));
3154 if(SavedFeatures
& CDRW_FEATURE_FORCE_SYNC_ON_WRITE
) {
3155 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_FORCE_SYNC_ON_WRITE\n"));
3156 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_FORCE_SYNC_CACHE
;
3158 if(SavedFeatures
& CDRW_FEATURE_BAD_DVD_LAST_LBA
) {
3159 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_BAD_DVD_LAST_LBA\n"));
3160 Vcb
->CompatFlags
|= UDF_VCB_IC_BAD_DVD_LAST_LBA
;
3162 if(SavedFeatures
& CDRW_FEATURE_STREAMING
) {
3163 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_STREAMING\n"));
3165 if(SavedFeatures
& CDRW_FEATURE_OPC
) {
3166 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_OPC -> assume OPCNum=1\n"));
3169 #ifdef UDF_FORMAT_MEDIA
3170 if(SavedFeatures
& CDRW_FEATURE_FULL_BLANK_ON_FORMAT
) {
3171 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_FULL_BLANK_ON_FORMAT\n"));
3172 if((fms
->opt_probe
|| fms
->opt_smart_f
)/* &&
3173 (fms->format_media && fms->blank_media*/) {
3174 KdPrint(("UDFGetDiskInfo: force Full Erase\n"));
3175 fms
->opt_qblank
= FALSE
;
3178 #endif //UDF_FORMAT_MEDIA
3180 // get device buffer size
3181 RC
= UDFPhSendIOCTL( IOCTL_CDRW_BUFFER_CAPACITY
,
3184 ioBuf
,sizeof(BUFFER_CAPACITY_BLOCK_USER_OUT
),
3186 if(NT_SUCCESS(RC
)) {
3187 Vcb
->CdrwBufferSize
= ((PBUFFER_CAPACITY_BLOCK_USER_OUT
)ioBuf
)->BufferLength
;
3189 Vcb
->CdrwBufferSize
= 0;
3191 KdPrint(("UDFGetDiskInfo: CdrwBufferSize = %dKb\n", Vcb
->CdrwBufferSize
/ 1024));
3192 Vcb
->CdrwBufferSizeCounter
= 0;
3193 #endif //_BROWSE_UDF_
3195 RC
= UDFPhSendIOCTL(IOCTL_CDRW_GET_MEDIA_TYPE
,DeviceObject
,
3196 NULL
,0,ioBuf
,sizeof(GET_MEDIA_TYPE_USER_OUT
),
3198 if(!OS_SUCCESS(RC
)) goto Try_FullToc
;
3200 MediaType
= ((PGET_MEDIA_TYPE_USER_OUT
)ioBuf
)->MediaType
;
3201 KdPrint(("UDFGetDiskInfo: MediaType %x\n", MediaType
));
3203 #ifndef UDF_FORMAT_MEDIA
3204 // we shall ignore audio-disks
3206 case MediaType_120mm_CDROM_AudioOnly
:
3207 case MediaType_80mm_CDROM_AudioOnly
:
3208 case MediaType_120mm_CDR_AudioOnly
:
3209 case MediaType_80mm_CDR_AudioOnly
:
3210 case MediaType_120mm_CDRW_AudioOnly
:
3211 case MediaType_80mm_CDRW_AudioOnly
:
3213 KdPrint(("UDFGetDiskInfo: we shall ignore audio-disks...\n"));
3214 try_return(RC
= STATUS_UNRECOGNIZED_VOLUME
);
3216 #endif //UDF_FORMAT_MEDIA
3218 KdPrint(("UDFGetDiskInfo: Check DVD-disks...\n"));
3219 RC
= UDFPhSendIOCTL(IOCTL_CDRW_GET_MEDIA_TYPE_EX
,DeviceObject
,
3220 NULL
,0,ioBuf
,sizeof(GET_MEDIA_TYPE_EX_USER_OUT
),
3222 if(!OS_SUCCESS(RC
)) goto Try_FullToc
;
3224 MediaType
= (((PGET_MEDIA_TYPE_EX_USER_OUT
)ioBuf
)->MediaClass
);
3225 KdPrint(("UDFGetDiskInfo: MediaClassEx %x\n", MediaType
));
3232 case CdMediaClass_CDR
:
3233 case CdMediaClass_DVDR
:
3234 case CdMediaClass_DVDpR
:
3235 case CdMediaClass_HD_DVDR
:
3236 case CdMediaClass_BDR
:
3237 KdPrint(("UDFGetDiskInfo: MediaClass R\n"));
3238 Vcb
->MediaType
= MediaType_UnknownSize_CDR
;
3240 case CdMediaClass_CDRW
:
3242 if(SavedFeatures
& CDRW_FEATURE_MRW_ADDRESSING_PROBLEM
) {
3243 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM on CD-RW\n"));
3244 Vcb
->CompatFlags
|= UDF_VCB_IC_MRW_ADDR_PROBLEM
;
3247 case CdMediaClass_DVDRW
:
3248 case CdMediaClass_DVDpRW
:
3249 case CdMediaClass_DVDRAM
:
3250 case CdMediaClass_HD_DVDRW
:
3251 case CdMediaClass_HD_DVDRAM
:
3252 case CdMediaClass_BDRE
:
3253 KdPrint(("UDFGetDiskInfo: MediaClass RW\n"));
3254 Vcb
->MediaType
= MediaType_UnknownSize_CDRW
;
3256 case CdMediaClass_CDROM
:
3257 case CdMediaClass_DVDROM
:
3258 case CdMediaClass_HD_DVDROM
:
3259 case CdMediaClass_BDROM
:
3260 KdPrint(("UDFGetDiskInfo: MediaClass ROM\n"));
3261 Vcb
->MediaType
= MediaType_Unknown
;
3262 // Vcb->MediaType = MediaType_UnknownSize_CDROM;
3265 KdPrint(("UDFGetDiskInfo: MediaClass Unknown\n"));
3266 Vcb
->MediaType
= MediaType_Unknown
;
3269 MediaType
= Vcb
->MediaType
;
3272 #endif //_BROWSE_UDF_
3274 #ifdef UDF_FORMAT_MEDIA
3279 case CdMediaClass_CDR
:
3280 KdPrint(("CdMediaClass_CDR\n"));
3281 MediaType
= MediaType_UnknownSize_CDR
;
3282 if(fms
->opt_media
== MT_AUTO
)
3283 fms
->opt_media
= MT_CDR
;
3285 case CdMediaClass_DVDR
:
3286 KdPrint(("CdMediaClass_DVDR -> MediaType_UnknownSize_CDR\n"));
3287 MediaType
= MediaType_UnknownSize_CDR
;
3288 if(fms
->opt_media
== MT_AUTO
)
3289 fms
->opt_media
= MT_DVDR
;
3291 case CdMediaClass_DVDpR
:
3292 KdPrint(("CdMediaClass_DVDpR -> MediaType_UnknownSize_CDR\n"));
3293 MediaType
= MediaType_UnknownSize_CDR
;
3294 if(fms
->opt_media
== MT_AUTO
)
3295 fms
->opt_media
= MT_DVDpR
;
3297 case CdMediaClass_HD_DVDR
:
3298 KdPrint(("CdMediaClass_HD_DVDR -> MediaType_UnknownSize_CDR\n"));
3299 MediaType
= MediaType_UnknownSize_CDR
;
3300 if(fms
->opt_media
== MT_AUTO
)
3301 fms
->opt_media
= MT_DVDR
;
3303 case CdMediaClass_BDR
:
3304 KdPrint(("CdMediaClass_BDR -> MediaType_UnknownSize_CDR\n"));
3305 MediaType
= MediaType_UnknownSize_CDR
;
3306 if(fms
->opt_media
== MT_AUTO
)
3307 fms
->opt_media
= MT_DVDR
;
3309 case CdMediaClass_CDRW
:
3310 KdPrint(("CdMediaClass_CDRW\n"));
3311 MediaType
= MediaType_UnknownSize_CDRW
;
3312 if(fms
->opt_media
== MT_AUTO
)
3313 fms
->opt_media
= MT_CDRW
;
3314 if(SavedFeatures
& CDRW_FEATURE_MRW_ADDRESSING_PROBLEM
) {
3315 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM on CD-RW\n"));
3316 Vcb
->CompatFlags
|= UDF_VCB_IC_MRW_ADDR_PROBLEM
;
3319 case CdMediaClass_DVDRW
:
3320 KdPrint((" CdMediaClass_DVDRW -> MediaType_UnknownSize_CDRW\n"));
3321 if(fms
->opt_media
== MT_AUTO
)
3322 fms
->opt_media
= MT_DVDRW
;
3323 MediaType
= MediaType_UnknownSize_CDRW
;
3325 case CdMediaClass_DVDpRW
:
3326 KdPrint((" CdMediaClass_DVDpRW -> MediaType_UnknownSize_CDRW\n"));
3327 if(fms
->opt_media
== MT_AUTO
)
3328 fms
->opt_media
= MT_DVDpRW
;
3329 MediaType
= MediaType_UnknownSize_CDRW
;
3331 case CdMediaClass_DVDRAM
:
3332 KdPrint((" CdMediaClass_DVDRAM -> MediaType_UnknownSize_CDRW\n"));
3333 if(fms
->opt_media
== MT_AUTO
)
3334 fms
->opt_media
= MT_DVDRAM
;
3335 MediaType
= MediaType_UnknownSize_CDRW
;
3337 case CdMediaClass_HD_DVDRW
:
3338 KdPrint((" CdMediaClass_HD_DVDRW -> MediaType_UnknownSize_CDRW\n"));
3339 if(fms
->opt_media
== MT_AUTO
)
3340 fms
->opt_media
= MT_DVDRW
;
3341 MediaType
= MediaType_UnknownSize_CDRW
;
3343 case CdMediaClass_HD_DVDRAM
:
3344 KdPrint((" CdMediaClass_HD_DVDRAM -> MediaType_UnknownSize_CDRW\n"));
3345 if(fms
->opt_media
== MT_AUTO
)
3346 fms
->opt_media
= MT_DVDRAM
;
3347 MediaType
= MediaType_UnknownSize_CDRW
;
3349 case CdMediaClass_BDRE
:
3350 KdPrint((" CdMediaClass_BDRE -> MediaType_UnknownSize_CDRW\n"));
3351 if(fms
->opt_media
== MT_AUTO
)
3352 fms
->opt_media
= MT_DVDRW
;
3353 MediaType
= MediaType_UnknownSize_CDRW
;
3355 case CdMediaClass_NoDiscPresent
:
3356 KdPrint((" CdMediaClass_NoDiscPresent -> MediaType_NoDiscPresent\n"));
3357 MediaType
= MediaType_NoDiscPresent
;
3358 fms
->opt_media
= MT_none
;
3360 case CdMediaClass_DoorOpen
:
3361 KdPrint((" CdMediaClass_DoorOpen -> MediaType_DoorOpen\n"));
3362 MediaType
= MediaType_DoorOpen
;
3363 fms
->opt_media
= MT_none
;
3366 KdPrint((" MediaType_Unknown\n"));
3367 MediaType
= MediaType_Unknown
;
3370 if(!apply_force_r(fms
)) {
3371 my_exit(fms
, MKUDF_CANT_APPLY_R
);
3375 #endif //UDF_FORMAT_MEDIA
3377 Vcb
->DVD_Mode
= (((PGET_MEDIA_TYPE_EX_USER_OUT
)ioBuf
)->MediaClassEx
== CdMediaClassEx_DVD
);
3378 Vcb
->PhMediaCapFlags
= ((PGET_MEDIA_TYPE_EX_USER_OUT
)ioBuf
)->CapFlags
;
3379 Vcb
->WriteParamsReq
= (Vcb
->PhMediaCapFlags
& CdCapFlags_WriteParamsReq
) ? TRUE
: FALSE
;
3381 !(Vcb
->PhMediaCapFlags
& CdCapFlags_RandomWritable
)) {
3382 KdPrint(("UDFGetDiskInfo: DVD && !CdCapFlags_RandomWritable\n"));
3383 KdPrint((" Read-only volume\n"));
3385 #ifndef UDF_CDRW_EMULATION_ON_ROM
3386 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_READ_ONLY
;
3389 #ifdef UDF_FORMAT_MEDIA
3391 if((MediaType
== MediaType_NoDiscPresent
) ||
3392 (MediaType
== MediaType_DoorOpen
)) {
3393 UserPrint(("No media in device\n"));
3394 my_exit(fms
, MKUDF_NO_MEDIA_IN_DEVICE
);
3397 #endif //UDF_FORMAT_MEDIA
3398 if(!Vcb
->WriteParamsReq
) {
3399 KdPrint(("UDFGetDiskInfo: do not use WriteParams\n"));
3401 if(Vcb
->PhMediaCapFlags
& CdCapFlags_Cav
) {
3402 KdPrint(("UDFGetDiskInfo: Use CAV (1)\n"));
3403 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_USE_CAV
;
3408 // check if this device is capable to write on such media
3409 if(UDFIsDvdMedia(Vcb
)) {
3411 KdPrint(("UDFGetDiskInfo: update defaulted LastLBA\n"));
3412 UDFGetBlockSize(DeviceObject
,Vcb
);
3413 //if(!OS_SUCCESS(RC)) goto Try_FullToc;
3415 if((SavedFeatures
& CDRW_FEATURE_MRW_ADDRESSING_PROBLEM
) &&
3416 (SavedFeatures
& UDF_VCB_IC_FP_ADDR_PROBLEM
)) {
3417 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM on old CD-ROM\n"));
3418 Vcb
->CompatFlags
|= UDF_VCB_IC_MRW_ADDR_PROBLEM
;
3422 #endif //_BROWSE_UDF_
3424 /*#ifdef UDF_FORMAT_MEDIA
3426 if(MediaType == CdMediaClass_DVDRW) {
3427 UserPrint(("Not empty media. Erase required.\n"));
3428 my_exit(fms, MKUDF_BLANK_FORMAT_REQUIRED);
3431 #endif //UDF_FORMAT_MEDIA*/
3433 #define cap ((PGET_CAPABILITIES_3_USER_OUT)ioBuf)
3434 // get device capabilities
3435 RC
= UDFPhSendIOCTL(IOCTL_CDRW_GET_CAPABILITIES
,DeviceObject
,
3436 NULL
,0,ioBuf
,sizeof(GET_CAPABILITIES_3_USER_OUT
),
3438 if(!OS_SUCCESS(RC
)) goto Try_FullToc
;
3440 // check if this device is capable to write on such media
3441 RC
= UDFPhSendIOCTL(IOCTL_DISK_IS_WRITABLE
,DeviceObject
,
3442 NULL
,0,NULL
,0,FALSE
, NULL
);
3443 if(RC
!= STATUS_SUCCESS
) {
3444 KdPrint(("IS_WRITABLE - false, doing additional check...\n"));
3445 if( ((MediaType
>= MediaType_UnknownSize_CDRW
) && !(cap
->WriteCap
& DevCap_write_cd_rw
)) ||
3446 ((MediaType
>= MediaType_UnknownSize_CDR
) && !(cap
->WriteCap
& DevCap_write_cd_r
)) ||
3447 (MediaType
< MediaType_UnknownSize_CDR
) ) {
3448 UserPrint(("Hardware Read-only volume\n"));
3449 #ifndef UDF_CDRW_EMULATION_ON_ROM
3450 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_READ_ONLY
;
3451 #endif //UDF_CDRW_EMULATION_ON_ROM
3452 #ifdef UDF_FORMAT_MEDIA
3453 if(fms
&& !fms
->opt_read_iso
)
3454 my_exit(fms
, MKUDF_HW_READ_ONLY
);
3455 #endif //UDF_FORMAT_MEDIA
3458 KdPrint(("Writable disk\n"));
3460 Vcb
->MaxWriteSpeed
= cap
->MaximumWriteSpeedSupported
;
3461 Vcb
->MaxReadSpeed
= cap
->MaximumSpeedSupported
;
3462 if(cap
->PageLength
>= (sizeof(GET_CAPABILITIES_3_USER_OUT
)-2)) {
3463 Vcb
->CurSpeed
= max(cap
->CurrentSpeed
, cap
->CurrentWriteSpeed3
);
3464 if(cap
->LunWPerfDescriptorCount
&& cap
->LunWPerfDescriptorCount
!= 0xffff) {
3466 KdPrint(("Write performance descriptor(s) found: %x\n", cap
->LunWPerfDescriptorCount
));
3467 n
= (4096 - sizeof(GET_CAPABILITIES_3_USER_OUT
)) / sizeof(LUN_WRITE_PERF_DESC_USER
);
3468 n
= min(n
, cap
->LunWPerfDescriptorCount
);
3469 // get device capabilities
3470 RC
= UDFPhSendIOCTL(IOCTL_CDRW_GET_CAPABILITIES
,DeviceObject
,
3471 ioBuf
,sizeof(GET_CAPABILITIES_3_USER_OUT
)+n
*sizeof(LUN_WRITE_PERF_DESC_USER
),
3472 ioBuf
,sizeof(GET_CAPABILITIES_3_USER_OUT
)+n
*sizeof(LUN_WRITE_PERF_DESC_USER
),
3474 if(OS_SUCCESS(RC
)) {
3475 WPerfDesc
= (PLUN_WRITE_PERF_DESC_USER
)(ioBuf
+ sizeof(GET_CAPABILITIES_3_USER_OUT
));
3477 for(i
= 0; i
<n
; i
++) {
3478 if((WPerfDesc
[i
].RotationControl
& LunWPerf_RotCtrl_Mask
) == LunWPerf_RotCtrl_CAV
) {
3479 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_USE_CAV
;
3481 Vcb
->CurSpeed
= WPerfDesc
[i
].WriteSpeedSupported
;
3483 KdPrint(("Use CAV\n"));
3485 Vcb
->CurSpeed
= max(WPerfDesc
[i
].WriteSpeedSupported
, Vcb
->CurSpeed
);
3487 KdPrint(("supports speed %dX\n", Vcb
->CurSpeed
/176));
3492 KdPrint(("Set r/w speeds to %dX\n", Vcb
->CurSpeed
/176));
3493 Vcb
->MaxWriteSpeed
=
3494 Vcb
->MaxReadSpeed
= Vcb
->CurSpeed
;
3499 Vcb
->CurSpeed
= max(cap
->CurrentSpeed
, cap
->CurrentWriteSpeed
);
3501 KdPrint((" Speeds r/w %dX/%dX\n", Vcb
->CurSpeed
/176, cap
->CurrentWriteSpeed
/176));
3503 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_USE_CAV
) {
3504 // limit both read & write speed to last write speed for CAV mode
3505 // some drives damage data when speed is adjusted during recording process
3506 // even in packet mode
3512 #ifdef UDF_FORMAT_MEDIA
3514 if( (fms
->auto_media
|| (fms
->opt_media
== MT_AUTO
)) &&
3515 (fms
->opt_media
< MT_DVDR
) ) {
3516 if(MediaType
< MediaType_UnknownSize_CDRW
) {
3517 fms
->opt_media
= MT_CDR
;
3519 fms
->opt_media
= MT_CDRW
;
3522 if(!apply_force_r(fms
)) {
3523 my_exit(fms
, MKUDF_CANT_APPLY_R
);
3526 #endif //UDF_FORMAT_MEDIA
3527 RC
= UDFReadDiscTrackInfo(DeviceObject
, Vcb
);
3529 if(!OS_SUCCESS(RC
)) {
3530 // may be we have a CD-ROM device
3532 KdPrint(("Hardware Read-only volume (2)\n"));
3534 #ifndef UDF_CDRW_EMULATION_ON_ROM
3535 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_READ_ONLY
;
3538 RC
= UDFReadAndProcessFullToc(DeviceObject
, Vcb
);
3540 if(!OS_SUCCESS(RC
)) {
3541 RC
= UDFUseStandard(DeviceObject
,Vcb
);
3542 if(!OS_SUCCESS(RC
)) try_return(RC
);
3550 RC
= UDFUseStandard(DeviceObject
, Vcb
);
3551 if(!OS_SUCCESS(RC
)) try_return(RC
);
3558 if(ioBuf
) MyFreePool__(ioBuf
);
3560 if(UDFIsDvdMedia(Vcb
) &&
3561 (Vcb
->CompatFlags
& UDF_VCB_IC_BAD_DVD_LAST_LBA
) &&
3562 (Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_READ_ONLY
) &&
3564 (Vcb
->LastLBA
< DEFAULT_LAST_LBA_DVD
)) {
3565 KdPrint(("UDF: Bad DVD last LBA %x, fixup!\n", Vcb
->LastLBA
));
3566 Vcb
->LastLBA
= DEFAULT_LAST_LBA_DVD
;
3571 if(UDFIsDvdMedia(Vcb
) && !Vcb
->FirstLBA
&& !Vcb
->LastPossibleLBA
) {
3572 KdPrint(("UDF: Empty DVD. Use bogus values for now\n"));
3573 Vcb
->LastPossibleLBA
= DEFAULT_LAST_LBA_DVD
;
3577 if((Vcb
->LastPossibleLBA
& 0x80000000) || (Vcb
->LastPossibleLBA
< Vcb
->LastLBA
)) {
3578 KdPrint(("UDF: bad LastPossibleLBA %x -> %x\n", Vcb
->LastPossibleLBA
, Vcb
->LastLBA
));
3579 Vcb
->LastPossibleLBA
= Vcb
->LastLBA
;
3581 if(!Vcb
->WriteBlockSize
)
3582 Vcb
->WriteBlockSize
= PACKETSIZE_UDF
*Vcb
->BlockSize
;
3586 if(Vcb
->TrackMap
[Vcb
->LastTrackNum
].LastLba
> Vcb
->NWA
) {
3588 if(Vcb
->TrackMap
[Vcb
->LastTrackNum
].DataParam
& TrkInfo_FP
) {
3589 Vcb
->LastLBA
= Vcb
->NWA
-1;
3591 Vcb
->LastLBA
= Vcb
->NWA
-7-1;
3595 if((Vcb
->LastTrackNum
> 1) &&
3596 (Vcb
->TrackMap
[Vcb
->LastTrackNum
-1].FirstLba
>= Vcb
->TrackMap
[Vcb
->LastTrackNum
-1].LastLba
)) {
3597 Vcb
->LastLBA
= Vcb
->TrackMap
[Vcb
->LastTrackNum
-1].LastLba
;
3602 for(i
=0; i
<32; i
++) {
3603 if(!(Vcb
->LastPossibleLBA
>> i
))
3607 Vcb
->WCacheBlocksPerFrameSh
= max(Vcb
->WCacheBlocksPerFrameSh
, (2*i
)/5+2);
3608 Vcb
->WCacheBlocksPerFrameSh
= min(Vcb
->WCacheBlocksPerFrameSh
, 16);
3611 if(Vcb
->CompatFlags
& UDF_VCB_IC_FP_ADDR_PROBLEM
) {
3612 // Check first 0x200 blocks
3613 UDFCheckTrackFPAddressing(Vcb
, Vcb
->FirstTrackNum
);
3614 // if we really have such a problem, fix LastLBA
3615 if(Vcb
->CompatFlags
& UDF_VCB_IC_FP_ADDR_PROBLEM
) {
3616 KdPrint(("UDF: Fix LastLBA: %x -> %x\n", Vcb
->LastLBA
, (Vcb
->LastLBA
*32) / 39));
3617 Vcb
->LastLBA
= (Vcb
->LastLBA
*32) / 39;
3620 #endif //_BROWSE_UDF_
3622 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_READ_ONLY
) {
3623 if(!Vcb
->BlankCD
&& Vcb
->MediaType
!= MediaType_UnknownSize_CDRW
) {
3624 KdPrint(("UDFGetDiskInfo: R/O+!Blank+!RW -> !RAW\n"));
3625 Vcb
->VCBFlags
&= ~UDF_VCB_FLAGS_RAW_DISK
;
3627 KdPrint(("UDFGetDiskInfo: Blank or RW\n"));
3631 KdPrint(("UDF: ------------------------------------------\n"));
3632 KdPrint(("UDF: Media characteristics\n"));
3633 KdPrint(("UDF: Last session: %d\n",Vcb
->LastSession
));
3634 KdPrint(("UDF: First track in first session: %d\n",Vcb
->FirstTrackNum
));
3635 KdPrint(("UDF: First track in last session: %d\n",Vcb
->FirstTrackNumLastSes
));
3636 KdPrint(("UDF: Last track in last session: %d\n",Vcb
->LastTrackNum
));
3637 KdPrint(("UDF: First LBA in first session: %x\n",Vcb
->FirstLBA
));
3638 KdPrint(("UDF: First LBA in last session: %x\n",Vcb
->FirstLBALastSes
));
3639 KdPrint(("UDF: Last LBA in last session: %x\n",Vcb
->LastLBA
));
3640 KdPrint(("UDF: First writable LBA (NWA) in last session: %x\n",Vcb
->NWA
));
3641 KdPrint(("UDF: Last available LBA beyond end of last session: %x\n",Vcb
->LastPossibleLBA
));
3642 KdPrint(("UDF: blocks per frame: %x\n",1 << Vcb
->WCacheBlocksPerFrameSh
));
3643 KdPrint(("UDF: Flags: %s%s\n",
3644 Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
? "RAW " : "",
3645 Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_READ_ONLY
? "R/O " : "WR "
3647 KdPrint(("UDF: ------------------------------------------\n"));
3649 #ifdef UDF_FORMAT_MEDIA
3650 if(fms
&& fms
->opt_disk_info
) {
3651 UserPrint(("------------------------------------------\n"));
3652 UserPrint(("Media characteristics:\n"));
3653 UserPrint((" First writable LBA (NWA) in last session: %x\n",Vcb
->NWA
));
3654 UserPrint((" Last available LBA beyond end of last session: %x\n",Vcb
->LastPossibleLBA
));
3655 UserPrint(("------------------------------------------\n"));
3657 #endif //UDF_FORMAT_MEDIA
3661 KdPrint(("UDFGetDiskInfo: %x\n", RC
));
3664 } // end UDFGetDiskInfo()
3666 //#ifdef _BROWSE_UDF_
3669 UDFPrepareForReadOperation(
3675 if( (Vcb
->FsDeviceType
!= FILE_DEVICE_CD_ROM_FILE_SYSTEM
) ) {
3676 Vcb
->VCBFlags
&= ~UDF_VCB_LAST_WRITE
;
3677 return STATUS_SUCCESS
;
3679 uint32 i
= Vcb
->LastReadTrack
;
3680 BOOLEAN speed_changed
= FALSE
;
3685 #endif //_BROWSE_UDF_
3687 #ifdef _UDF_STRUCTURES_H_
3688 if(Vcb
->BSBM_Bitmap
) {
3690 for(i
=0; i
<BCount
; i
++) {
3691 if(UDFGetBit__((uint32
*)(Vcb
->BSBM_Bitmap
), Lba
+i
)) {
3692 KdPrint(("R: Known BB @ %#x\n", Lba
));
3693 //return STATUS_FT_WRITE_RECOVERY; // this shall not be treated as error and
3694 // we shall get IO request to BAD block
3695 return STATUS_DEVICE_DATA_ERROR
;
3699 #endif //_UDF_STRUCTURES_H_
3701 if(!UDFIsDvdMedia(Vcb
) &&
3702 (Vcb
->VCBFlags
& UDF_VCB_LAST_WRITE
) &&
3703 !(Vcb
->VCBFlags
& UDF_VCB_FLAGS_NO_SYNC_CACHE
) &&
3704 !(Vcb
->CompatFlags
& UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE
)){
3708 RC
= UDFSyncCache(Vcb
);
3710 if( (Vcb
->VCBFlags
& UDF_VCB_LAST_WRITE
) &&
3711 !(Vcb
->VCBFlags
& UDF_VCB_FLAGS_NO_SYNC_CACHE
) &&
3712 #ifndef UDF_FORMAT_MEDIA
3713 (Vcb
->CompatFlags
& UDF_VCB_IC_SYNCCACHE_BEFORE_READ
) &&
3714 #endif //UDF_FORMAT_MEDIA
3718 RC
= UDFSyncCache(Vcb
);
3722 if(!UDFIsDvdMedia(Vcb
)) {
3723 // limit read speed after write operation
3724 // to avoid performance degrade durring speed-up/down
3725 // on read/write mode switching
3726 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_USE_CAV
) {
3727 // limit both read & write speed to last write speed for CAV mode
3728 // some drives damage data when speed is adjusted during recording process
3729 // even in packet mode
3730 if(Vcb
->CurSpeed
!= Vcb
->MaxWriteSpeed
||
3731 Vcb
->CurSpeed
!= Vcb
->MaxReadSpeed
) {
3732 Vcb
->CurSpeed
= Vcb
->MaxWriteSpeed
;
3733 speed_changed
= TRUE
;
3736 if(Vcb
->VCBFlags
& UDF_VCB_LAST_WRITE
) {
3737 // limit read speed to last write speed
3738 if(Vcb
->CurSpeed
> Vcb
->MaxWriteSpeed
) {
3739 Vcb
->CurSpeed
= Vcb
->MaxWriteSpeed
;
3740 speed_changed
= TRUE
;
3743 if(Vcb
->CurSpeed
< Vcb
->MaxReadSpeed
) {
3744 // increment read speed (+1X)
3745 Vcb
->CurSpeed
+= 176/1;
3746 speed_changed
= TRUE
;
3749 if(Vcb
->CurSpeed
> Vcb
->MaxReadSpeed
) {
3750 Vcb
->CurSpeed
= Vcb
->MaxReadSpeed
;
3752 // send speed limits to drive
3754 RtlZeroMemory(&(Vcb
->SpeedBuf
), sizeof(SET_CD_SPEED_EX_USER_IN
));
3755 Vcb
->SpeedBuf
.ReadSpeed
= Vcb
->CurSpeed
;
3756 Vcb
->SpeedBuf
.WriteSpeed
= Vcb
->MaxWriteSpeed
;
3757 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_USE_CAV
) {
3758 Vcb
->SpeedBuf
.RotCtrl
= CdSpeed_RotCtrl_CAV
;
3760 KdPrint((" UDFPrepareForReadOperation: set speed to %s %dX/%dX\n",
3761 (Vcb
->VCBFlags
& UDF_VCB_FLAGS_USE_CAV
) ? "CAV" : "CLV",
3762 Vcb
->SpeedBuf
.ReadSpeed
,
3763 Vcb
->SpeedBuf
.WriteSpeed
));
3764 UDFPhSendIOCTL(IOCTL_CDRW_SET_SPEED
,
3765 Vcb
->TargetDeviceObject
,
3766 &(Vcb
->SpeedBuf
),sizeof(SET_CD_SPEED_EX_USER_IN
),
3771 if(UDFIsDvdMedia(Vcb
))
3772 return STATUS_SUCCESS
;
3774 if(Vcb
->LastReadTrack
&&
3775 ((Vcb
->TrackMap
[i
].FirstLba
<= Lba
) || (Vcb
->TrackMap
[i
].FirstLba
& 0x80000000)) &&
3776 (Vcb
->TrackMap
[i
].LastLba
>= Lba
)) {
3777 check_for_data_track
:
3778 // check track mode (Mode1/XA)
3779 switch((Vcb
->TrackMap
[i
].DataParam
& TrkInfo_Dat_Mask
)) {
3780 case TrkInfo_Dat_Mode1
: // Mode1
3781 case TrkInfo_Dat_XA
: // XA Mode2
3782 case TrkInfo_Dat_Unknown
: // for some stupid irons
3786 Vcb
->IncrementalSeekState
= INCREMENTAL_SEEK_NONE
;
3787 return STATUS_INVALID_PARAMETER
;
3790 for(i
=Vcb
->FirstTrackNum
; i
<=Vcb
->LastTrackNum
; i
++) {
3791 if(((Vcb
->TrackMap
[i
].FirstLba
> Lba
) && !(Vcb
->TrackMap
[i
].FirstLba
& 0x80000000)) ||
3792 (Vcb
->TrackMap
[i
].LastLba
< Lba
))
3794 Vcb
->LastReadTrack
= i
;
3795 goto check_for_data_track
;
3797 Vcb
->LastReadTrack
= 0;
3799 if(Vcb
->IncrementalSeekState
!= INCREMENTAL_SEEK_WORKAROUND
) {
3800 Vcb
->IncrementalSeekState
= INCREMENTAL_SEEK_NONE
;
3801 return STATUS_SUCCESS
;
3803 KdPrint((" UDFPrepareForReadOperation: seek workaround...\n"));
3804 Vcb
->IncrementalSeekState
= INCREMENTAL_SEEK_DONE
;
3806 tmp
= (PUCHAR
)DbgAllocatePoolWithTag(NonPagedPool
, Vcb
->BlockSize
, 'bNWD');
3808 Vcb
->IncrementalSeekState
= INCREMENTAL_SEEK_NONE
;
3809 return STATUS_INSUFFICIENT_RESOURCES
;
3811 for(i
=0x1000; i
<=Lba
; i
+=0x1000) {
3812 RC
= UDFPhReadSynchronous(Vcb
->TargetDeviceObject
, tmp
, Vcb
->BlockSize
,
3813 ((uint64
)UDFFixFPAddress(Vcb
,i
)) << Vcb
->BlockSizeBits
, &ReadBytes
, 0);
3814 KdPrint((" seek workaround, LBA %x, status %x\n", i
, RC
));
3817 #endif //_BROWSE_UDF_
3819 return STATUS_SUCCESS
;
3820 } // end UDFPrepareForReadOperation()
3822 //#endif //_BROWSE_UDF_
3827 uint32 LBA
, // physical
3832 #ifndef UDF_READ_ONLY_BUILD
3834 if(!OS_SUCCESS(RC
)) {
3837 if(!Vcb
->CDR_Mode
) {
3839 if((Vcb
->MediaClassEx
== CdMediaClass_DVDRW
||
3840 Vcb
->MediaClassEx
== CdMediaClass_DVDpRW
||
3841 Vcb
->MediaClassEx
== CdMediaClass_DVDRAM
||
3842 Vcb
->MRWStatus
== DiscInfo_BGF_Interrupted
||
3843 Vcb
->MRWStatus
== DiscInfo_BGF_InProgress
)
3844 && (LBA
+BCount
-1) > Vcb
->LastLBA
) {
3845 ASSERT(Vcb
->NWA
> Vcb
->LastLBA
);
3846 Vcb
->NWA
= LBA
+BCount
;
3847 Vcb
->LastLBA
= Vcb
->NWA
-1;
3849 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_FORCE_SYNC_CACHE
)
3851 /* if(Vcb->CdrwBufferSize) {
3852 Vcb->CdrwBufferSizeCounter += BCount * 2048;
3853 if(Vcb->CdrwBufferSizeCounter >= Vcb->CdrwBufferSize + 2*2048) {
3854 KdPrint((" UDFUpdateNWA: buffer is full, sync...\n"));
3855 Vcb->CdrwBufferSizeCounter = 0;
3859 if(Vcb
->SyncCacheState
== SYNC_CACHE_RECOVERY_RETRY
) {
3860 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_FORCE_SYNC_CACHE
;
3862 Vcb
->SyncCacheState
= SYNC_CACHE_RECOVERY_NONE
;
3865 if(Vcb
->LastLBA
< (LBA
+BCount
))
3866 Vcb
->LastLBA
= LBA
+BCount
;
3870 if(!(Vcb
->CompatFlags
& UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE
)) {
3871 KdPrint((" UDFUpdateNWA: syncing...\n"));
3872 RC
= UDFSyncCache(Vcb
);
3874 #endif //_BROWSE_UDF_
3875 #endif //UDF_READ_ONLY_BUILD
3876 } // end UDFUpdateNWA()
3880 This routine reads physical sectors
3885 IN BOOLEAN Translate, // Translate Logical to Physical
3889 OUT uint32* ReadBytes
3893 if(Vcb->FastCache.ReadProc && (KeGetCurrentIrql() < DISPATCH_LEVEL)) {
3894 return WCacheReadBlocks__(&(Vcb->FastCache), Vcb, Buffer, Lba, BCount, ReadBytes);
3896 return UDFTRead(Vcb, Buffer, BCount*Vcb->BlockSize, Lba, ReadBytes);
3897 } // end UDFReadSectors()*/
3902 This routine reads physical sectors
3907 IN BOOLEAN Translate
, // Translate Logical to Physical
3909 IN uint32 i
, // offset in sector
3910 IN uint32 l
, // transfer length
3911 IN BOOLEAN Direct
, // Disable access to non-cached data
3913 OUT uint32
* ReadBytes
3921 if(WCacheIsInitialized__(&(Vcb
->FastCache
)) && (KeGetCurrentIrql() < DISPATCH_LEVEL
)) {
3922 status
= WCacheDirect__(&(Vcb
->FastCache
), Vcb
, Lba
, FALSE
, &tmp_buff
, Direct
);
3923 if(OS_SUCCESS(status
)) {
3925 RtlCopyMemory(Buffer
, tmp_buff
+i
, l
);
3927 if(!Direct
) WCacheEODirect__(&(Vcb
->FastCache
), Vcb
);
3930 return STATUS_INVALID_PARAMETER
;
3932 tmp_buff
= (int8
*)MyAllocatePool__(NonPagedPool
, Vcb
->BlockSize
);
3933 if(!tmp_buff
) return STATUS_INSUFFICIENT_RESOURCES
;
3934 status
= UDFReadSectors(Vcb
, Translate
, Lba
, 1, FALSE
, tmp_buff
, &_ReadBytes
);
3935 if(OS_SUCCESS(status
)) {
3937 RtlCopyMemory(Buffer
, tmp_buff
+i
, l
);
3939 MyFreePool__(tmp_buff
);
3942 } // end UDFReadInSector()
3945 This routine reads data of unaligned offset & length
3950 IN BOOLEAN Translate
, // Translate Logical to Physical
3953 IN BOOLEAN Direct
, // Disable access to non-cached data
3955 OUT uint32
* ReadBytes
3958 uint32 i
, l
, Lba
, BS
=Vcb
->BlockSize
;
3959 uint32 BSh
=Vcb
->BlockSizeBits
;
3961 uint32 _ReadBytes
= 0;
3962 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
3966 if(!Length
) return STATUS_SUCCESS
;
3967 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_DEAD
)
3968 return STATUS_NO_SUCH_DEVICE
;
3969 // read tail of the 1st sector if Offset is not sector_size-aligned
3970 Lba
= (uint32
)(Offset
>> BSh
);
3971 if(i
= (uint32
)(Offset
& (BS
-1))) {
3972 l
= (BS
- i
) < Length
?
3974 // here we use 'ReadBytes' 'cause now it's set to zero
3975 status
= UDFReadInSector(Vcb
, Translate
, Lba
, i
, l
, Direct
, Buffer
, ReadBytes
);
3976 if(!OS_SUCCESS(status
)) return status
;
3977 if(!(Length
= Length
- l
)) return STATUS_SUCCESS
;
3981 // read sector_size-aligned part
3984 to_read
= min(i
, 64);
3985 status
= UDFReadSectors(Vcb
, Translate
, Lba
, to_read
, Direct
, Buffer
, &_ReadBytes
);
3986 (*ReadBytes
) += _ReadBytes
;
3987 if(!OS_SUCCESS(status
)) {
3990 Buffer
+= to_read
<<BSh
;
3991 Length
-= to_read
<<BSh
;
3995 // read head of the last sector
3996 if(!Length
) return STATUS_SUCCESS
;
3997 status
= UDFReadInSector(Vcb
, Translate
, Lba
, 0, Length
, Direct
, Buffer
, &_ReadBytes
);
3998 (*ReadBytes
) += _ReadBytes
;
4001 } // end UDFReadData()
4003 #endif //_BROWSE_UDF_
4005 #ifndef UDF_READ_ONLY_BUILD
4007 This routine writes physical sectors. This routine supposes Lba & Length
4008 alignment on WriteBlock (packet) size.
4013 IN BOOLEAN Translate
, // Translate Logical to Physical
4016 IN BOOLEAN Direct
, // Disable access to non-cached data
4018 OUT uint32
* WrittenBytes
4024 if(!Vcb
->Modified
|| (Vcb
->IntegrityType
== INTEGRITY_TYPE_CLOSE
)) {
4025 UDFSetModified(Vcb
);
4026 if(Vcb
->LVid
&& !Direct
) {
4027 status
= UDFUpdateLogicalVolInt(Vcb
,FALSE
);
4032 if(Vcb
->LastLBA
< Lba
+BCount
-1)
4033 Vcb
->LastLBA
= Lba
+BCount
-1;
4035 #endif //_BROWSE_UDF_
4037 if(Vcb
->FastCache
.WriteProc
&& (KeGetCurrentIrql() < DISPATCH_LEVEL
)) {
4038 status
= WCacheWriteBlocks__(&(Vcb
->FastCache
), Vcb
, Buffer
, Lba
, BCount
, WrittenBytes
, Direct
);
4039 ASSERT(OS_SUCCESS(status
));
4041 UDFClrZeroBits(Vcb
->ZSBM_Bitmap
, Lba
, BCount
);
4042 #endif //_BROWSE_UDF_
4048 (*WrittenBytes) = 0;
4049 buffer = DbgAllocatePool(NonPagedPool, Vcb->WriteBlockSize);
4050 if(!buffer) return STATUS_INSUFFICIENT_RESOURCES;
4051 status = UDFTRead(Vcb, Buffer, BCount<<Vcb->BlockSizeBits, (Lba&~(Vcb->WriteBlockSize-1), _WrittenBytes);*/
4053 status
= UDFTWrite(Vcb
, Buffer
, BCount
<<Vcb
->BlockSizeBits
, Lba
, WrittenBytes
);
4054 ASSERT(OS_SUCCESS(status
));
4057 return UDFTWrite(Vcb
, Buffer
, BCount
<<Vcb
->BlockSizeBits
, Lba
, WrittenBytes
);
4059 } // end UDFWriteSectors()
4064 IN BOOLEAN Translate
, // Translate Logical to Physical
4066 IN uint32 i
, // offset in sector
4067 IN uint32 l
, // transfer length
4068 IN BOOLEAN Direct
, // Disable access to non-cached data
4070 OUT uint32
* WrittenBytes
4076 uint32 _WrittenBytes
;
4079 if(!Vcb
->Modified
) {
4080 UDFSetModified(Vcb
);
4082 status
= UDFUpdateLogicalVolInt(Vcb
,FALSE
);
4086 if(Vcb
->LastLBA
< Lba
)
4089 #endif //_BROWSE_UDF_
4091 (*WrittenBytes
) = 0;
4093 if(WCacheIsInitialized__(&(Vcb
->FastCache
)) && (KeGetCurrentIrql() < DISPATCH_LEVEL
)) {
4094 #endif //_BROWSE_UDF_
4095 status
= WCacheDirect__(&(Vcb
->FastCache
), Vcb
, Lba
, TRUE
, &tmp_buff
, Direct
);
4096 if(OS_SUCCESS(status
)) {
4098 UDFClrZeroBit(Vcb
->ZSBM_Bitmap
, Lba
);
4099 #endif //_BROWSE_UDF_
4100 (*WrittenBytes
) += l
;
4101 RtlCopyMemory(tmp_buff
+i
, Buffer
, l
);
4103 if(!Direct
) WCacheEODirect__(&(Vcb
->FastCache
), Vcb
);
4106 // If Direct = TRUE we should never get here, but...
4109 return STATUS_INVALID_PARAMETER
;
4111 tmp_buff
= (int8
*)MyAllocatePool__(NonPagedPool
, Vcb
->BlockSize
);
4114 return STATUS_INSUFFICIENT_RESOURCES
;
4117 status
= UDFReadSectors(Vcb
, Translate
, Lba
, 1, FALSE
, tmp_buff
, &ReadBytes
);
4118 if(!OS_SUCCESS(status
)) goto EO_WrSctD
;
4120 RtlCopyMemory(tmp_buff
+i
, Buffer
, l
);
4121 // write modified packet
4122 status
= UDFWriteSectors(Vcb
, Translate
, Lba
, 1, FALSE
, tmp_buff
, &_WrittenBytes
);
4123 if(OS_SUCCESS(status
))
4124 (*WrittenBytes
) += l
;
4126 MyFreePool__(tmp_buff
);
4128 ASSERT(OS_SUCCESS(status
));
4129 if(!OS_SUCCESS(status
)) {
4130 KdPrint(("UDFWriteInSector() for LBA %x failed\n", Lba
));
4132 #endif //_BROWSE_UDF_
4134 } // end UDFWriteInSector()
4137 This routine writes data at unaligned offset & length
4142 IN BOOLEAN Translate
, // Translate Logical to Physical
4145 IN BOOLEAN Direct
, // setting this flag delays flushing of given
4146 // data to indefinite term
4148 OUT uint32
* WrittenBytes
4151 uint32 i
, l
, Lba
, BS
=Vcb
->BlockSize
;
4152 uint32 BSh
=Vcb
->BlockSizeBits
;
4154 uint32 _WrittenBytes
;
4155 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
4157 (*WrittenBytes
) = 0;
4158 if(!Length
) return STATUS_SUCCESS
;
4159 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_DEAD
)
4160 return STATUS_NO_SUCH_DEVICE
;
4161 // write tail of the 1st sector if Offset is not sector_size-aligned
4162 Lba
= (uint32
)(Offset
>> BSh
);
4163 if(i
= ((uint32
)Offset
& (BS
-1))) {
4164 l
= (BS
- i
) < Length
?
4166 status
= UDFWriteInSector(Vcb
, Translate
, Lba
, i
, l
, Direct
, Buffer
, WrittenBytes
);
4167 if(!OS_SUCCESS(status
)) return status
;
4168 if(!(Length
= Length
- l
)) return STATUS_SUCCESS
;
4172 // write sector_size-aligned part
4175 status
= UDFWriteSectors(Vcb
, Translate
, Lba
, i
, Direct
, Buffer
, &_WrittenBytes
);
4176 (*WrittenBytes
) += _WrittenBytes
;
4177 if(!OS_SUCCESS(status
)) return status
;
4180 UDFClrZeroBits(Vcb
->ZSBM_Bitmap
, Lba
, i
);
4181 #endif //_BROWSE_UDF_
4182 if(!(Length
= Length
- l
)) return STATUS_SUCCESS
;
4186 status
= UDFWriteInSector(Vcb
, Translate
, Lba
, 0, Length
, Direct
, Buffer
, &_WrittenBytes
);
4187 (*WrittenBytes
) += _WrittenBytes
;
4189 UDFClrZeroBit(Vcb
->ZSBM_Bitmap
, Lba
);
4190 #endif //_BROWSE_UDF_
4193 } // end UDFWriteData()
4195 #endif //UDF_READ_ONLY_BUILD
4198 UDFResetDeviceDriver(
4200 IN PDEVICE_OBJECT TargetDeviceObject
,
4204 PCDRW_RESET_DRIVER_USER_IN tmp
= (PCDRW_RESET_DRIVER_USER_IN
)
4205 MyAllocatePool__(NonPagedPool
, sizeof(CDRW_RESET_DRIVER_USER_IN
));
4208 return STATUS_INSUFFICIENT_RESOURCES
;
4209 RtlZeroMemory(tmp
, sizeof(CDRW_RESET_DRIVER_USER_IN
));
4210 tmp
->UnlockTray
= (Unlock
? 1 : 0);
4211 tmp
->MagicWord
= 0x3a6 | (Unlock
? 1 : 0);
4212 RC
= UDFPhSendIOCTL(IOCTL_CDRW_RESET_DRIVER_EX
, TargetDeviceObject
,
4213 tmp
, sizeof(CDRW_RESET_DRIVER_USER_IN
), NULL
, 0, TRUE
,NULL
);
4215 Vcb
->LastReadTrack
= 0;
4216 Vcb
->LastModifiedTrack
= 0;
4217 Vcb
->OPCDone
= FALSE
;
4218 if((Vcb
->VCBFlags
& UDF_VCB_FLAGS_USE_CAV
) &&
4219 Vcb
->TargetDeviceObject
) {
4220 // limit both read & write speed to last write speed for CAV mode
4221 // some drives damage data when speed is adjusted during recording process
4222 // even in packet mode
4230 } // end UDFResetDeviceDriver()
4239 RtlZeroMemory(&(Vcb
->SpeedBuf
), sizeof(SET_CD_SPEED_EX_USER_IN
));
4240 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_USE_CAV
) {
4241 Vcb
->SpeedBuf
.RotCtrl
= CdSpeed_RotCtrl_CAV
;
4243 Vcb
->SpeedBuf
.ReadSpeed
=
4244 Vcb
->SpeedBuf
.WriteSpeed
= Vcb
->MaxWriteSpeed
;
4246 Vcb
->SpeedBuf
.ReadSpeed
= Vcb
->CurSpeed
;
4247 Vcb
->SpeedBuf
.WriteSpeed
= Vcb
->MaxWriteSpeed
;
4249 KdPrint((" UDFSetSpeeds: set speed to %s %dX/%dX\n",
4250 (Vcb
->VCBFlags
& UDF_VCB_FLAGS_USE_CAV
) ? "CAV" : "CLV",
4251 Vcb
->SpeedBuf
.ReadSpeed
/ 176,
4252 Vcb
->SpeedBuf
.WriteSpeed
/ 176));
4253 RC
= UDFPhSendIOCTL(IOCTL_CDRW_SET_SPEED
,
4254 Vcb
->TargetDeviceObject
,
4255 &(Vcb
->SpeedBuf
),sizeof(SET_CD_SPEED_EX_USER_IN
),
4257 KdPrint(("UDFSetSpeeds: %x\n", RC
));
4259 } // end UDFSetSpeeds()
4266 #pragma pack(push,1)
4268 MODE_PARAMETER_HEADER Header
;
4269 MODE_CACHING_PAGE Data
;
4274 MODE_PARAMETER_HEADER Header
;
4275 MODE_READ_WRITE_RECOVERY_PAGE Data
;
4280 MODE_SENSE_USER_IN ModeSenseCtl
;
4283 KdPrint(("UDFSetCaching:\n"));
4285 ModeSenseCtl
.PageCode
.Byte
= MODE_PAGE_ERROR_RECOVERY
;
4286 RC
= UDFPhSendIOCTL(IOCTL_CDRW_MODE_SENSE
, Vcb
->TargetDeviceObject
,
4287 &ModeSenseCtl
,sizeof(ModeSenseCtl
),
4288 (PVOID
)&RecoveryPage
,sizeof(RecoveryPage
),
4290 if(OS_SUCCESS(RC
)) {
4291 KdPrint((" Error recovery page:\n"
4304 "ReadRetryCount %d\n"
4305 "CorrectionSpan %d\n"
4306 "HeadOffsetCount %d\n"
4307 "DataStrobOffsetCount %d\n"
4309 "ErrorRecoveryParam2.Fields.EMCDR %d\n"
4311 "WriteRetryCount %d\n",
4313 RecoveryPage
.Data
.PageCode
,
4314 RecoveryPage
.Data
.PageLength
,
4316 RecoveryPage
.Data
.ErrorRecoveryParam
.Fields
.DCRBit
,
4317 RecoveryPage
.Data
.ErrorRecoveryParam
.Fields
.DTEBit
,
4318 RecoveryPage
.Data
.ErrorRecoveryParam
.Fields
.PERBit
,
4319 RecoveryPage
.Data
.ErrorRecoveryParam
.Fields
.EERBit
,
4320 RecoveryPage
.Data
.ErrorRecoveryParam
.Fields
.RCBit
,
4321 RecoveryPage
.Data
.ErrorRecoveryParam
.Fields
.TBBit
,
4322 RecoveryPage
.Data
.ErrorRecoveryParam
.Fields
.ARRE
,
4323 RecoveryPage
.Data
.ErrorRecoveryParam
.Fields
.AWRE
,
4325 RecoveryPage
.Data
.ReadRetryCount
,
4326 RecoveryPage
.Data
.CorrectionSpan
,
4327 RecoveryPage
.Data
.HeadOffsetCount
,
4328 RecoveryPage
.Data
.DataStrobOffsetCount
,
4330 RecoveryPage
.Data
.ErrorRecoveryParam2
.Fields
.EMCDR
,
4332 RecoveryPage
.Data
.WriteRetryCount
4337 ModeSenseCtl
.PageCode
.Byte
= MODE_PAGE_CACHING
;
4338 RC
= UDFPhSendIOCTL(IOCTL_CDRW_MODE_SENSE
, Vcb
->TargetDeviceObject
,
4339 &ModeSenseCtl
,sizeof(ModeSenseCtl
),
4340 (PVOID
)&CachingPage
,sizeof(CachingPage
),
4342 if(!OS_SUCCESS(RC
)) {
4346 KdPrint((" Caching page:\n"
4349 "ReadDisableCache %d\n"
4350 "MultiplicationFactor %d\n"
4351 "WriteCacheEnable %d\n"
4352 "WriteRetensionPriority %d\n"
4353 "ReadRetensionPriority %d\n",
4355 CachingPage
.Data
.PageCode
,
4356 CachingPage
.Data
.PageLength
,
4357 CachingPage
.Data
.ReadDisableCache
,
4358 CachingPage
.Data
.MultiplicationFactor
,
4359 CachingPage
.Data
.WriteCacheEnable
,
4360 CachingPage
.Data
.WriteRetensionPriority
,
4361 CachingPage
.Data
.ReadRetensionPriority
4364 RtlZeroMemory(&CachingPage
.Header
, sizeof(CachingPage
.Header
));
4365 CachingPage
.Data
.PageCode
= MODE_PAGE_CACHING
;
4366 CachingPage
.Data
.PageSavable
= 0;
4367 if( CachingPage
.Data
.ReadDisableCache
||
4368 !CachingPage
.Data
.WriteCacheEnable
) {
4369 CachingPage
.Data
.ReadDisableCache
= 0;
4370 CachingPage
.Data
.WriteCacheEnable
= 1;
4371 RC
= UDFPhSendIOCTL(IOCTL_CDRW_MODE_SELECT
, Vcb
->TargetDeviceObject
,
4372 (PVOID
)&CachingPage
,sizeof(CachingPage
.Header
) + 2 + CachingPage
.Data
.PageLength
,
4376 RC
= STATUS_SUCCESS
;
4378 KdPrint(("UDFSetCaching: %x\n", RC
));
4380 } // end UDFSetCaching()