1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
7 Module Name: Phys_lib.cpp
9 Execution: Kernel mode only
13 Contains code that implement read/write operations for physical device
18 static const char Signature
[16] = {CDRW_SIGNATURE_v1
};
39 IN OUT uint32
* retry
);
45 IN PVCB Vcb
, // Volume control block from this DevObj
56 KdPrint(("UDFSyncCache:\n"));
58 RC
= UDFPhSendIOCTL( IOCTL_CDRW_SYNC_CACHE
, Vcb
->TargetDeviceObject
,
59 NULL
,0, NULL
,0, FALSE
, NULL
);
61 // clear LAST_WRITE flag
62 Vcb
->VCBFlags
&= ~UDF_VCB_LAST_WRITE
;
65 } // end UDFSyncCache()
76 MyFreePool__(Vcb
->TrackMap
);
79 Vcb
->TrackMap
= (PUDFTrackMap
)
80 MyAllocatePool__(NonPagedPool
, TrackNum
*sizeof(UDFTrackMap
));
82 return STATUS_INSUFFICIENT_RESOURCES
;
85 RtlZeroMemory(Vcb
->TrackMap
,TrackNum
*sizeof(UDFTrackMap
));
86 return STATUS_SUCCESS
;
87 } // end UDFReallocTrackMap()
96 IN
void* Buffer
, // Target buffer
103 OSSTATUS RC
= STATUS_SUCCESS
;
106 uint32 lba0
, len
, lba1
;
112 OSSTATUS final_RC
= STATUS_SUCCESS
;
116 BOOLEAN free_tmp
= FALSE
;
117 BOOLEAN single_packet
= FALSE
;
119 #define Vcb ((PVCB)_Vcb)
120 // ATTENTION! Do not touch bad block bitmap here, since it describes PHYSICAL addresses WITHOUT remapping,
121 // while here we work with LOGICAL addresses
123 if(Vcb
->VerifyCtx
.ItemCount
> UDF_MAX_VERIFY_CACHE
) {
124 UDFVVerify(Vcb
, 0/*UFD_VERIFY_FLAG_WAIT*/);
127 UDFAcquireResourceExclusive(&(Vcb
->IoResource
), TRUE
);
128 Flags
|= PH_IO_LOCKED
;
130 tmp_wb
= (uint32
)_Vcb
;
131 if(Flags
& PH_EX_WRITE
) {
132 KdPrint(("IO-Write-Verify\n"));
133 RC
= UDFTWrite(_Vcb
, Buffer
, Length
, LBA
, &tmp_wb
, Flags
| PH_VCB_IN_RETLEN
);
135 KdPrint(("IO-Read-Verify\n"));
136 RC
= UDFTRead(_Vcb
, Buffer
, Length
, LBA
, &tmp_wb
, Flags
| PH_VCB_IN_RETLEN
);
142 UDFReleaseResource(&(Vcb
->IoResource
));
144 case STATUS_FT_WRITE_RECOVERY
:
145 case STATUS_DEVICE_DATA_ERROR
:
146 case STATUS_IO_DEVICE_ERROR
:
151 if(!Vcb
->SparingCount
||
152 !Vcb
->SparingCountFree
||
154 KdPrint(("Can't remap\n"));
155 UDFReleaseResource(&(Vcb
->IoResource
));
159 if(Flags
& PH_EX_WRITE
) {
160 KdPrint(("Write failed, try relocation\n"));
163 KdPrint(("Read failed, try relocation\n"));
165 KdPrint(("no remap on not modified volume\n"));
166 UDFReleaseResource(&(Vcb
->IoResource
));
170 if(Flags
& PH_LOCK_CACHE
) {
171 UDFReleaseResource(&(Vcb
->IoResource
));
172 WCacheStartDirect__(&(Vcb
->FastCache
), Vcb
, TRUE
);
173 UDFAcquireResourceExclusive(&(Vcb
->IoResource
), TRUE
);
176 Flags
&= ~PH_KEEP_VERIFY_CACHE
;
178 // NOTE: SparingBlockSize may be not equal to PacketSize
180 mask
= Vcb
->SparingBlockSize
-1;
182 len
= ((LBA
+(Length
>>Vcb
->BlockSizeBits
)+mask
) & ~mask
) - lba0
;
184 if((lba0
== LBA
) && (len
== mask
+1) && (len
== (Length
>>Vcb
->BlockSizeBits
))) {
185 single_packet
= TRUE
;
188 tmp_buff
= (PUCHAR
)DbgAllocatePoolWithTag(NonPagedPool
, Vcb
->SparingBlockSize
<< Vcb
->BlockSizeBits
, 'bNWD');
190 KdPrint((" can't alloc tmp\n"));
191 UDFReleaseResource(&(Vcb
->IoResource
));
192 return STATUS_DEVICE_DATA_ERROR
;
197 for(i
=0; i
<len
; i
++) {
198 if(!Vcb
->SparingCountFree
) {
199 KdPrint((" no more free spare blocks, abort verification\n"));
202 KdPrint((" read LBA %x (%x)\n", lba0
+i
, j
));
208 // single packet requested
209 tmp_buff
= (PUCHAR
)Buffer
;
210 if(Flags
& PH_EX_WRITE
) {
211 KdPrint((" remap single write\n"));
212 KdPrint((" try del from verify cache @ %x, %x\n", lba0
, len
));
213 UDFVForget(Vcb
, len
, UDFRelocateSector(Vcb
, lba0
), 0);
216 KdPrint((" recover and remap single read\n"));
220 p
= tmp_buff
+(j
<<Vcb
->BlockSizeBits
);
221 // not cached, try to read
222 // prepare for error, if block cannot be read, assume it is zero-filled
223 RtlZeroMemory(p
, Vcb
->BlockSize
);
225 // check if block valid
226 if(Vcb
->BSBM_Bitmap
) {
227 if(UDFGetBit((uint32
*)(Vcb
->BSBM_Bitmap
), UDFRelocateSector(Vcb
, lba0
+i
))) {
228 KdPrint((" remap: known BB @ %x, mapped to %x\n", lba0
+i
, UDFRelocateSector(Vcb
, lba0
+i
)));
233 if(Vcb
->FSBM_Bitmap
) {
234 if(UDFGetFreeBit((uint32
*)(Vcb
->FSBM_Bitmap
), lba0
+i
)) {
235 KdPrint((" unused @ %x\n", lba0
+i
));
239 if(!zero
&& Vcb
->ZSBM_Bitmap
) {
240 if(UDFGetZeroBit((uint32
*)(Vcb
->ZSBM_Bitmap
), lba0
+i
)) {
241 KdPrint((" unused @ %x (Z)\n", lba0
+i
));
250 // try to read entire packet, this returs error more often then sequential reading of all blocks one by one
251 tmp_wb
= (uint32
)_Vcb
;
252 RC
= UDFTRead(_Vcb
, p
, Vcb
->SparingBlockSize
<< Vcb
->BlockSizeBits
, lba0
+i
, &tmp_wb
,
253 Flags
| PH_READ_VERIFY_CACHE
| PH_TMP_BUFFER
| PH_VCB_IN_RETLEN
);
255 // Note: we get here ONLY if original request failed
256 // do not retry if it was single-packet request
257 RC
= STATUS_UNSUCCESSFUL
;
259 if(RC
== STATUS_SUCCESS
) {
260 KdPrint((" packet ok @ %x\n", lba0
+i
));
262 i
+= Vcb
->SparingBlockSize
-1;
270 if(WCacheIsCached__(&(Vcb
->FastCache
), lba0
+i
, 1)) {
271 // even if block is cached, we have to verify if it is readable
272 if(!packet_ok
&& !UDFVIsStored(Vcb
, lba0
+i
)) {
274 tmp_wb
= (uint32
)_Vcb
;
275 RC
= UDFTRead(_Vcb
, p
, Vcb
->BlockSize
, lba0
+i
, &tmp_wb
,
276 Flags
| PH_FORGET_VERIFIED
| PH_READ_VERIFY_CACHE
| PH_TMP_BUFFER
| PH_VCB_IN_RETLEN
);
277 if(!OS_SUCCESS(RC
)) {
278 KdPrint((" Found BB @ %x\n", lba0
+i
));
282 RC
= WCacheDirect__(&(Vcb
->FastCache
), _Vcb
, lba0
+i
, FALSE
, &cached_block
, TRUE
/* cached only */);
286 RC
= STATUS_UNSUCCESSFUL
;
292 // cached or successfully read
294 // we can get from cache the most fresh data
295 RtlCopyMemory(p
, cached_block
, Vcb
->BlockSize
);
299 if(!UDFVIsStored(Vcb
, lba0
+i
)) {
300 tmp_wb
= (uint32
)_Vcb
;
301 RC
= UDFTRead(_Vcb
, p
, Vcb
->BlockSize
, lba0
+i
, &tmp_wb
,
302 Flags
| PH_FORGET_VERIFIED
| PH_READ_VERIFY_CACHE
| PH_TMP_BUFFER
| PH_VCB_IN_RETLEN
);
304 // get it from verify-cache
305 RC
= STATUS_UNSUCCESSFUL
;
307 if(!OS_SUCCESS(RC
)) {
309 KdPrint((" retry @ %x\n", lba0+i));
310 tmp_wb = (uint32)_Vcb;
311 RC = UDFTRead(_Vcb, p, Vcb->BlockSize, lba0+i, &tmp_wb,
312 Flags | PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN);
314 KdPrint((" try get from verify cache @ %x\n", lba0
+i
));
315 RC
= UDFVRead(Vcb
, p
, 1, UDFRelocateSector(Vcb
, lba0
+i
),
316 Flags
| PH_FORGET_VERIFIED
| PH_READ_VERIFY_CACHE
| PH_TMP_BUFFER
);
321 RtlZeroMemory(p
, Vcb
->BlockSize
);
324 KdPrint((" try del from verify cache @ %x\n", lba0
+i
));
325 RC
= UDFVForget(Vcb
, 1, UDFRelocateSector(Vcb
, lba0
+i
), 0);
328 if(!packet_ok
|| need_remap
) {
329 KdPrint((" block in bad packet @ %x\n", lba0
+i
));
330 if(Vcb
->BSBM_Bitmap
) {
331 UDFSetBit(Vcb
->BSBM_Bitmap
, lba0
+i
);
333 if(Vcb
->FSBM_Bitmap
) {
334 UDFSetUsedBit(Vcb
->FSBM_Bitmap
, lba0
+i
);
339 if(j
>= Vcb
->SparingBlockSize
) {
344 KdPrint((" forget Z packet @ %x\n", lba1
));
345 UDFUnmapRange(Vcb
, lba1
, Vcb
->SparingBlockSize
);
350 KdPrint((" remap packet @ %x\n", lba1
));
351 RC
= UDFRemapPacket(Vcb
, lba1
, FALSE
);
352 if(!OS_SUCCESS(RC
)) {
353 if(RC
== STATUS_SHARING_VIOLATION
) {
354 KdPrint((" remap2\n"));
355 // remapped location have died
356 RC
= UDFRemapPacket(Vcb
, lba1
, TRUE
);
358 if(!OS_SUCCESS(RC
)) {
359 // packet cannot be remapped :(
360 RC
= STATUS_DEVICE_DATA_ERROR
;
363 KdPrint((" remap status %x\n", RC
));
365 // write to remapped area
366 tmp_wb
= (uint32
)_Vcb
;
367 RC
= UDFTWrite(_Vcb
, tmp_buff
, Vcb
->SparingBlockSize
<< Vcb
->BlockSizeBits
, lba1
, &tmp_wb
,
368 Flags
| PH_FORGET_VERIFIED
| PH_READ_VERIFY_CACHE
| PH_TMP_BUFFER
| PH_VCB_IN_RETLEN
);
369 KdPrint((" write status %x\n", RC
));
370 if(RC
!= STATUS_SUCCESS
) {
372 KdPrint((" retry remap\n"));
374 // Note: when remap of already remapped block is requested, verify of
375 // entire sparing are will be performed.
378 KdPrint((" remap OK\n"));
382 KdPrint((" failed remap\n"));
387 if(!OS_SUCCESS(RC
) && !OS_SUCCESS(final_RC
)) {
391 KdPrint((" NO remap for @ %x\n", (lba0
+i
) & ~mask
));
397 DbgFreePool(tmp_buff
);
400 tmp_wb
= (uint32
)_Vcb
;
401 if(Flags
& PH_EX_WRITE
) {
402 KdPrint(("IO-Write-Verify (2)\n"));
403 //RC = UDFTWrite(_Vcb, Buffer, Length, LBA, &tmp_wb, Flags | PH_FORGET_VERIFIED | PH_VCB_IN_RETLEN);
405 KdPrint(("IO-Read-Verify (2)\n"));
406 RC
= UDFTRead(_Vcb
, Buffer
, Length
, LBA
, &tmp_wb
, Flags
| PH_FORGET_VERIFIED
| PH_VCB_IN_RETLEN
);
409 KdPrint(("Final %x\n", RC
));
411 UDFReleaseResource(&(Vcb
->IoResource
));
412 if(Flags
& PH_LOCK_CACHE
) {
413 WCacheEODirect__(&(Vcb
->FastCache
), Vcb
);
417 } // end UDFTIOVerify()
422 IN
void* Buffer
, // Target buffer
425 OUT uint32
* WrittenBytes
,
429 return UDFTIOVerify(_Vcb
, Buffer
, Length
, LBA
, WrittenBytes
, Flags
| PH_VCB_IN_RETLEN
| PH_EX_WRITE
| PH_KEEP_VERIFY_CACHE
);
430 } // end UDFTWriteVerify()
435 IN
void* Buffer
, // Target buffer
438 OUT uint32
* ReadBytes
,
442 return UDFTIOVerify(_Vcb
, Buffer
, Length
, LBA
, ReadBytes
, Flags
| PH_VCB_IN_RETLEN
| PH_KEEP_VERIFY_CACHE
);
443 } // end UDFTReadVerify()
444 #endif //_BROWSE_UDF_
447 This routine performs low-level write
449 ATTENTION! When we are in Variable-Packet mode (CDR_Mode = TRUE)
450 LBA is ignored and assumed to be equal to NWA by CD-R(W) driver
455 IN
void* Buffer
, // Target buffer
458 OUT uint32
* WrittenBytes
,
462 #ifndef UDF_READ_ONLY_BUILD
463 #define Vcb ((PVCB)_Vcb)
466 PEXTENT_MAP RelocExtent
;
467 PEXTENT_MAP RelocExtent_saved
= NULL
;
468 #endif //_BROWSE_UDF_
470 BOOLEAN res_acq
= FALSE
;
472 OSSTATUS RC
= STATUS_SUCCESS
;
478 //ASSERT(!(LBA & (32-1)));
482 BCount
= Length
>>Vcb
->BlockSizeBits
;
484 KdPrint(("TWrite %x (%x)\n", LBA
, BCount
));
486 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_DEAD
) {
488 return STATUS_NO_SUCH_DEVICE
;
491 Vcb
->VCBFlags
|= (UDF_VCB_SKIP_EJECT_CHECK
| UDF_VCB_LAST_WRITE
);
493 RelocExtent
= UDFRelocateSectors(Vcb
, LBA
, BCount
);
495 KdPrint(("can't relocate\n"));
496 return STATUS_INSUFFICIENT_RESOURCES
;
500 RelocExtent
= UDF_NO_EXTENT_MAP
;
505 #endif //_BROWSE_UDF_
508 //ASSERT(!(rLba & (32-1)));
514 if(!(Flags
& PH_IO_LOCKED
)) {
515 UDFAcquireResourceExclusive(&(Vcb
->IoResource
), TRUE
);
519 if(RelocExtent
== UDF_NO_EXTENT_MAP
) {
520 #endif //_BROWSE_UDF_
521 retry
= UDF_WRITE_MAX_RETRY
;
523 RC
= UDFPrepareForWriteOperation(Vcb
, rLba
, BCount
);
524 if(!OS_SUCCESS(RC
)) {
525 KdPrint(("prepare failed\n"));
528 if(Flags
& PH_VCB_IN_RETLEN
) {
529 (*WrittenBytes
) = (ULONG
)Vcb
;
531 RC
= UDFPhWriteVerifySynchronous(Vcb
->TargetDeviceObject
, Buffer
, Length
,
532 ((uint64
)rLba
) << Vcb
->BlockSizeBits
, WrittenBytes
, Flags
);
534 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
535 #endif //_BROWSE_UDF_
536 if(!OS_SUCCESS(RC
) &&
537 OS_SUCCESS(RC
= UDFRecoverFromError(Vcb
, TRUE
, RC
, rLba
, BCount
, &retry
)) )
539 UDFUpdateNWA((PVCB
)_Vcb
, rLba
, BCount
, RC
);
543 // write according to relocation table
544 RelocExtent_saved
= RelocExtent
;
545 for(i
=0; RelocExtent
->extLength
; i
++, RelocExtent
++) {
546 uint32 _WrittenBytes
;
547 rLba
= RelocExtent
->extLocation
;
548 BCount
= RelocExtent
->extLength
>>Vcb
->BlockSizeBits
;
549 retry
= UDF_WRITE_MAX_RETRY
;
551 RC
= UDFPrepareForWriteOperation(Vcb
, rLba
, BCount
);
552 if(!OS_SUCCESS(RC
)) {
553 KdPrint(("prepare failed (2)\n"));
556 if(Flags
& PH_VCB_IN_RETLEN
) {
557 _WrittenBytes
= (ULONG
)Vcb
;
559 RC
= UDFPhWriteVerifySynchronous(Vcb
->TargetDeviceObject
, Buffer
, RelocExtent
->extLength
,
560 ((uint64
)rLba
) << Vcb
->BlockSizeBits
, &_WrittenBytes
, Flags
);
561 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
562 if(!OS_SUCCESS(RC
) &&
563 OS_SUCCESS(RC
= UDFRecoverFromError(Vcb
, TRUE
, RC
, rLba
, BCount
, &retry
)) )
565 UDFUpdateNWA((PVCB
)_Vcb
, rLba
, BCount
, RC
);
567 (*WrittenBytes
) += _WrittenBytes
;
568 if(!OS_SUCCESS(RC
)) break;
569 *((uint32
*)&Buffer
) += RelocExtent
->extLength
;
571 #endif //_BROWSE_UDF_
575 UDFReleaseResource(&(Vcb
->IoResource
));
578 if(RelocExtent_saved
) {
579 MyFreePool__(RelocExtent_saved
);
581 #endif //_BROWSE_UDF_
583 KdPrint(("TWrite: %x\n", RC
));
587 #else //UDF_READ_ONLY_BUILD
588 return STATUS_ACCESS_DENIED
;
589 #endif //UDF_READ_ONLY_BUILD
593 This routine performs low-level read
598 IN
void* Buffer
, // Target buffer
601 OUT uint32
* ReadBytes
,
606 OSSTATUS RC
= STATUS_SUCCESS
;
608 PVCB Vcb
= (PVCB
)_Vcb
;
609 uint32 BCount
= Length
>> Vcb
->BlockSizeBits
;
612 PEXTENT_MAP RelocExtent
;
613 PEXTENT_MAP RelocExtent_saved
= NULL
;
614 BOOLEAN res_acq
= FALSE
;
615 // LARGE_INTEGER delay;
616 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
622 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_DEAD
)
623 return STATUS_NO_SUCH_DEVICE
;
625 RelocExtent
= UDFRelocateSectors(Vcb
, LBA
, BCount
);
626 if(!RelocExtent
) return STATUS_INSUFFICIENT_RESOURCES
;
630 if(!(Flags
& PH_IO_LOCKED
)) {
631 UDFAcquireResourceExclusive(&(Vcb
->IoResource
), TRUE
);
635 if(RelocExtent
== UDF_NO_EXTENT_MAP
) {
637 if(rLba
>= (Vcb
->CDR_Mode
? Vcb
->NWA
: Vcb
->LastLBA
+ 1)) {
638 RtlZeroMemory(Buffer
, Length
);
639 try_return(RC
= STATUS_SUCCESS
);
641 retry
= UDF_WRITE_MAX_RETRY
;
643 RC
= UDFPrepareForReadOperation(Vcb
, rLba
, Length
>> Vcb
->BlockSizeBits
);
644 if(!OS_SUCCESS(RC
)) try_return(RC
);
645 rLba
= UDFFixFPAddress(Vcb
, rLba
);
648 retry
= UDF_WRITE_MAX_RETRY
;
650 RC
= UDFPrepareForReadOperation(Vcb
, rLba
, Length
>> Vcb
->BlockSizeBits
);
651 if(!OS_SUCCESS(RC
)) return RC
; // this is for !_BROWSE_UDF only
652 #endif //_BROWSE_UDF_
653 if(Flags
& PH_VCB_IN_RETLEN
) {
654 (*ReadBytes
) = (ULONG
)Vcb
;
656 RC
= UDFPhReadSynchronous(Vcb
->TargetDeviceObject
, Buffer
, Length
,
657 ((uint64
)rLba
) << Vcb
->BlockSizeBits
, ReadBytes
, Flags
);
658 Vcb
->VCBFlags
&= ~UDF_VCB_LAST_WRITE
;
660 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
661 #endif //_BROWSE_UDF_
662 if(!OS_SUCCESS(RC
) &&
663 OS_SUCCESS(RC
= UDFRecoverFromError(Vcb
, FALSE
, RC
, rLba
, BCount
, &retry
)) ) {
664 if(RC
!= STATUS_BUFFER_ALL_ZEROS
) {
667 RtlZeroMemory(Buffer
, Length
);
668 (*ReadBytes
) = Length
;
674 // read according to relocation table
675 RelocExtent_saved
= RelocExtent
;
676 for(i
=0; RelocExtent
->extLength
; i
++, RelocExtent
++) {
678 rLba
= RelocExtent
->extLocation
;
679 if(rLba
>= (Vcb
->CDR_Mode
? Vcb
->NWA
: Vcb
->LastLBA
+ 1)) {
680 RtlZeroMemory(Buffer
, _ReadBytes
= RelocExtent
->extLength
);
684 BCount
= RelocExtent
->extLength
>>Vcb
->BlockSizeBits
;
685 retry
= UDF_WRITE_MAX_RETRY
;
687 RC
= UDFPrepareForReadOperation(Vcb
, rLba
, RelocExtent
->extLength
>> Vcb
->BlockSizeBits
);
688 if(!OS_SUCCESS(RC
)) break;
689 rLba
= UDFFixFPAddress(Vcb
, rLba
);
690 if(Flags
& PH_VCB_IN_RETLEN
) {
691 _ReadBytes
= (ULONG
)Vcb
;
693 RC
= UDFPhReadSynchronous(Vcb
->TargetDeviceObject
, Buffer
, RelocExtent
->extLength
,
694 ((uint64
)rLba
) << Vcb
->BlockSizeBits
, &_ReadBytes
, Flags
);
695 Vcb
->VCBFlags
&= ~UDF_VCB_LAST_WRITE
;
696 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
697 if(!OS_SUCCESS(RC
) &&
698 OS_SUCCESS(RC
= UDFRecoverFromError(Vcb
, FALSE
, RC
, rLba
, BCount
, &retry
)) ) {
699 if(RC
!= STATUS_BUFFER_ALL_ZEROS
) {
702 RtlZeroMemory(Buffer
, RelocExtent
->extLength
);
703 _ReadBytes
= RelocExtent
->extLength
;
707 (*ReadBytes
) += _ReadBytes
;
708 if(!OS_SUCCESS(RC
)) break;
709 *((uint32
*)&Buffer
) += RelocExtent
->extLength
;
714 UDFReleaseResource(&(Vcb
->IoResource
));
716 if(RelocExtent_saved
) {
717 MyFreePool__(RelocExtent_saved
);
720 #endif //_BROWSE_UDF_
726 This routine performs asynchronous low-level read
733 IN
void* Buffer
, // Target buffer
736 OUT uint32
* ReadBytes
739 PEXTENT_MAP RelocExtent
;
740 PEXTENT_MAP RelocExtent_saved
;
741 OSSTATUS RC
= STATUS_SUCCESS
;
742 // LARGE_INTEGER delay;
743 uint32 retry
= UDF_READ_MAX_RETRY
;
744 PVCB Vcb
= (PVCB
)_Vcb
;
745 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
753 RelocExtent
= UDFRelocateSectors(Vcb
, LBA
, BCount
= Length
>> Vcb
->BlockSizeBits
);
754 if(!RelocExtent
) return STATUS_INSUFFICIENT_RESOURCES
;
755 if(RelocExtent
== UDF_NO_EXTENT_MAP
) {
757 if(rLba
>= (Vcb
->CDR_Mode
? Vcb
->NWA
: Vcb
->LastLBA
+ 1)) {
758 RtlZeroMemory(Buffer
, Length
);
759 return STATUS_SUCCESS
;
762 RC
= UDFPrepareForReadOperation(Vcb
, rLba
, BCount
);
763 if(!OS_SUCCESS(RC
)) return RC
;
764 rLba
= UDFFixFPAddress(Vcb
, rLba
);
765 RC
= UDFPhReadSynchronous(Vcb
->TargetDeviceObject
, Buffer
, Length
,
766 ((uint64
)rLba
) << Vcb
->BlockSizeBits
, ReadBytes
, 0);
767 Vcb
->VCBFlags
&= ~UDF_VCB_LAST_WRITE
;
768 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
769 if(!OS_SUCCESS(RC
) &&
770 OS_SUCCESS(RC
= UDFRecoverFromError(Vcb
, FALSE
, RC
, rLba
, BCount
, &retry
)) )
774 // read according to relocation table
775 RelocExtent_saved
= RelocExtent
;
776 for(uint32 i
=0; RelocExtent
->extLength
; i
++, RelocExtent
++) {
778 rLba
= RelocExtent
->extLocation
;
779 if(rLba
>= (Vcb
->CDR_Mode
? Vcb
->NWA
: Vcb
->LastLBA
+ 1)) {
780 RtlZeroMemory(Buffer
, _ReadBytes
= RelocExtent
->extLength
);
784 BCount
= RelocExtent
->extLength
>>Vcb
->BlockSizeBits
;
786 RC
= UDFPrepareForReadOperation(Vcb
, rLba
, RelocExtent
->extLength
>> Vcb
->BlockSizeBits
);
787 if(!OS_SUCCESS(RC
)) break;
788 rLba
= UDFFixFPAddress(Vcb
, rLba
);
789 RC
= UDFPhReadSynchronous(Vcb
->TargetDeviceObject
, Buffer
, RelocExtent
->extLength
,
790 ((uint64
)rLba
) << Vcb
->BlockSizeBits
, &_ReadBytes
, 0);
791 Vcb
->VCBFlags
&= ~UDF_VCB_LAST_WRITE
;
792 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
793 if(!OS_SUCCESS(RC
) &&
794 OS_SUCCESS(RC
= UDFRecoverFromError(Vcb
, FALSE
, RC
, rLba
, BCount
, &retry
)) )
797 (*ReadBytes
) += _ReadBytes
;
798 if(!OS_SUCCESS(RC
)) break;
799 *((uint32
*)&Buffer
) += RelocExtent
->extLength
;
801 MyFreePool__(RelocExtent_saved
);
803 } // end UDFTReadAsync()
805 #endif //UDF_ASYNC_IO
815 GET_MRW_MODE_USER_OUT MRWPage
;
818 if(Vcb
->MediaClassEx
!= CdMediaClass_CDRW
)
819 return STATUS_SUCCESS
;
820 //#ifdef _BROWSE_UDF_
821 if(Vcb
->CompatFlags
& UDF_VCB_IC_MRW_ADDR_PROBLEM
)
822 return STATUS_SUCCESS
;
823 //#endif //_BROWSE_UDF_
825 if(!Vcb
->MRWStatus
) {
826 KdPrint(("Non-MRW disk. Skip setting MRW_MODE\n"));
827 return STATUS_SUCCESS
;
829 KdPrint(("try set MRW_MODE\n"));
830 RC
= UDFPhSendIOCTL(IOCTL_CDRW_GET_MRW_MODE
, Vcb
->TargetDeviceObject
,
832 (PVOID
)&MRWPage
,sizeof(MRWPage
),
834 if(!NT_SUCCESS(RC
)) {
837 KdPrint(("GET_MRW_MODE ok (current %x)\n", MRWPage
.AddressMode
));
838 MRWPage
.AddressMode
= Vcb
->MRWStatus
? 0 : MrwPage_use_GAA
;
839 KdPrint(("SET_MRW_MODE %x\n", MRWPage
.AddressMode
));
840 RC
= UDFPhSendIOCTL(IOCTL_CDRW_SET_MRW_MODE
, Vcb
->TargetDeviceObject
,
841 (PVOID
)&MRWPage
,sizeof(MRWPage
),
844 KdPrint(("SET_MRW_MODE status %x\n", RC
));
846 return STATUS_SUCCESS
;
847 } // end UDFSetMRWMode()
855 if(Vcb
->OPCNum
&& !Vcb
->OPCDone
) {
856 KdPrint(("UDFDoOPC\n"));
859 (PSEND_OPC_INFO_HEADER_USER_IN
)MyAllocatePool__(NonPagedPool
,
860 sizeof(SEND_OPC_INFO_HEADER_USER_IN
) );
863 return STATUS_INSUFFICIENT_RESOURCES
;
864 Vcb
->OPCh
->DoOpc
= TRUE
;
865 Vcb
->OPCh
->OpcBlocksNumber
= 0;
866 RC
= UDFPhSendIOCTL(IOCTL_CDRW_SEND_OPC_INFO
, Vcb
->TargetDeviceObject
,
867 (void*)(Vcb
->OPCh
),sizeof(SEND_OPC_INFO_HEADER_USER_IN
),
870 if(!OS_SUCCESS(RC
)) {
871 KdPrint(("UDFDoOPC failed\n"));
873 // Vcb->VCBFlags |= UDF_VCB_FLAGS_OPC_FAILED;
881 This routine performs media-type dependent preparations
884 For CDR/RW it sets WriteParameters according to track parameters,
885 in some cases issues SYNC_CACHE command.
886 It can also send OPC info if requered.
887 If write-requested block is located beyond last formatted LBA
888 on incompletely formatted DVD media, this routine performs
889 all neccessary formatting operations in order to satisfy
890 subsequent write request.
893 UDFPrepareForWriteOperation(
899 #ifndef UDF_READ_ONLY_BUILD
900 #ifdef UDF_FORMAT_MEDIA
901 PUDFFmtState fms
= Vcb
->fms
;
904 #endif //UDF_FORMAT_MEDIA
906 #ifdef _UDF_STRUCTURES_H_
907 if(Vcb
->BSBM_Bitmap
) {
909 for(i
=0; i
<BCount
; i
++) {
910 if(UDFGetBit((uint32
*)(Vcb
->BSBM_Bitmap
), Lba
+i
)) {
911 KdPrint(("W: Known BB @ %#x\n", Lba
));
912 //return STATUS_FT_WRITE_RECOVERY; // this shall not be treated as error and
913 // we shall get IO request to BAD block
914 return STATUS_DEVICE_DATA_ERROR
;
918 #endif //_UDF_STRUCTURES_H_
920 Vcb
->VCBFlags
|= UDF_VCB_LAST_WRITE
;
924 (((Vcb
->FsDeviceType
!= FILE_DEVICE_CD_ROM_FILE_SYSTEM
) ||
925 !(Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_MOUNTED
) ||
926 (Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
))
929 #endif //_BROWSE_UDF_
930 #ifdef UDF_FORMAT_MEDIA
931 (fms
&& fms
->SkipPrepareW
) ||
932 #endif //UDF_FORMAT_MEDIA
933 !(Vcb
->VCBFlags
& UDF_VCB_FLAGS_OUR_DEVICE_DRIVER
)
935 KdPrint(("Skip prepare for Write @%x\n", Lba
));
936 return STATUS_SUCCESS
;
939 // check if the device requires OPC before each write operation
942 if(Vcb
->SyncCacheState
== SYNC_CACHE_RECOVERY_ATTEMPT
) {
943 Vcb
->SyncCacheState
= SYNC_CACHE_RECOVERY_RETRY
;
945 Vcb
->SyncCacheState
= SYNC_CACHE_RECOVERY_NONE
;
947 if(Vcb
->LastModifiedTrack
&&
948 (Vcb
->TrackMap
[Vcb
->LastModifiedTrack
].FirstLba
<= Lba
) &&
949 (Vcb
->TrackMap
[Vcb
->LastModifiedTrack
].LastLba
>= Lba
) &&
950 !( (Vcb
->MediaClassEx
== CdMediaClass_DVDRW
||
951 Vcb
->MediaClassEx
== CdMediaClass_DVDpRW
||
952 Vcb
->MediaClassEx
== CdMediaClass_DVDRAM
||
953 Vcb
->MRWStatus
== DiscInfo_BGF_Interrupted
||
954 Vcb
->MRWStatus
== DiscInfo_BGF_InProgress
) && (Lba
> Vcb
->LastLBA
))
956 // Ok, we needn't change Write Parameters
957 // if(Vcb->TrackMap[Vcb->LastModifiedTrack].Flags & TrackMap_Try_variation)
958 // Vcb->TrackMap[Vcb->LastModifiedTrack].Flags |= TrackMap_Use_variation;
959 KdPrint(("Skip prepare for Write (2) @%x\n", Lba
));
960 return STATUS_SUCCESS
;
965 if(!UDFIsWriteParamsReq(Vcb
)) {
966 #ifdef UDF_FORMAT_MEDIA
968 return STATUS_SUCCESS
;
970 #endif //UDF_FORMAT_MEDIA
973 for(uint32 i
=Vcb
->FirstTrackNum
; i
<=Vcb
->LastTrackNum
; i
++) {
974 if((Vcb
->TrackMap
[i
].FirstLba
> Lba
) ||
975 (Vcb
->TrackMap
[i
].LastLba
< Lba
)) {
976 //KdPrint(("not in track %d\n"));
980 PGET_WRITE_MODE_USER_OUT WParams
;
982 if(!UDFIsWriteParamsReq(Vcb
)) {
984 goto check_dvd_bg_format
;
989 (PGET_WRITE_MODE_USER_OUT
)MyAllocatePool__(NonPagedPool
, 512);
991 if(!(WParams
= Vcb
->WParams
)) {
992 KdPrint(("!WParams\n"));
993 return STATUS_INSUFFICIENT_RESOURCES
;
996 RC
= UDFPhSendIOCTL(IOCTL_CDRW_GET_WRITE_MODE
, Vcb
->TargetDeviceObject
,
998 (void*)(Vcb
->WParams
),sizeof(GET_WRITE_MODE_USER_OUT
),
1000 if(!OS_SUCCESS(RC
)) {
1001 #ifdef UDF_FORMAT_MEDIA
1003 fms
->SkipPrepareW
= 1;
1004 MyFreePool__(WParams
);
1005 return STATUS_SUCCESS
;
1007 #endif //UDF_FORMAT_MEDIA
1008 KdPrint(("!get WParams\n"));
1011 // clear unnecassary flags
1012 WParams
->Byte2
.Flags
&= ~WParam_TestWrite
;
1013 WParams
->Byte2
.Flags
&= ~WParam_WType_Mask
;
1014 // select packet writing
1015 WParams
->Byte2
.Flags
|= WParam_WType_Packet
;
1017 WParams
->Byte3
.Flags
&= ~(WParam_TrkMode_Mask
|
1018 WParam_TrkMode_AllowCpy
|
1020 WParams
->Byte3
.Flags
|= Vcb
->TrackMap
[i
].TrackParam
&
1021 (WParam_TrkMode_Mask
|
1022 WParam_TrkMode_AllowCpy
|
1025 // set packet type (VP/FP)
1026 // if(opt_partition == PT_VAT15 ||
1028 if(WParams
->Byte2
.Flags
& WParam_LS_V
) {
1029 WParams
->LinkSize
= 7;
1032 if(Vcb
->TrackMap
[i
].DataParam
& TrkInfo_Packet
) {
1033 if((Vcb
->TrackMap
[i
].DataParam
& TrkInfo_FP
) &&
1035 WParams
->Byte3
.Flags
|= WParam_FP
;
1037 WParams
->Byte3
.Flags
&= ~WParam_FP
;
1040 if(!Vcb
->CDR_Mode
) {
1041 WParams
->Byte3
.Flags
|= WParam_FP
;
1043 WParams
->Byte3
.Flags
&= ~WParam_FP
;
1047 // select multisession mode
1048 WParams
->Byte3
.Flags
&= ~WParam_MultiSes_Mask
;
1049 if((Vcb
->DiscStat
& DiscInfo_Disk_Mask
) == DiscInfo_Disk_Appendable
) {
1050 WParams
->Byte3
.Flags
|= WParam_Multises_Multi
;
1052 if(Vcb
->LastSession
> 1) {
1053 WParams
->Byte3
.Flags
|= WParam_Multises_Final
;
1055 WParams
->Byte3
.Flags
|= WParam_Multises_None
;
1057 // set sector mode (Mode1/XA)
1058 WParams
->Byte4
.Flags
&= ~WParam_BlkType_Mask
;
1059 if((Vcb
->TrackMap
[i
].DataParam
& TrkInfo_Dat_Mask
) == TrkInfo_Dat_XA
) {
1061 WParams
->Byte4
.Flags
|= WParam_BlkType_M2XAF1_2048
;
1062 WParams
->SesFmt
= WParam_SesFmt_CdRomXa
;
1063 } else if((Vcb
->TrackMap
[i
].DataParam
& TrkInfo_Dat_Mask
) == TrkInfo_Dat_Mode1
) {
1065 WParams
->Byte4
.Flags
|= WParam_BlkType_M1_2048
;
1066 WParams
->SesFmt
= WParam_SesFmt_CdRom
;
1068 #ifdef UDF_FORMAT_MEDIA
1070 fms
->SkipPrepareW
= 1;
1071 MyFreePool__(WParams
);
1072 return STATUS_SUCCESS
;
1074 #endif //UDF_FORMAT_MEDIA
1075 KdPrint((" inv sector mode\n"));
1076 return STATUS_INVALID_PARAMETER
;
1079 *((uint32
*)&(WParams
->PacketSize
)) = BCount
;
1080 *((uint32
*)&(WParams
->SubHeader
)) = 0;
1081 // set additional flags for VP
1084 // if(opt_partition == PT_VAT15)
1085 WParams
->SubHeader
.Params
.Params1
.SubMode
= WParam_SubHdr_SubMode1
;
1087 WParams
->PageLength
= sizeof(GET_WRITE_MODE_USER_OUT
)-2;
1088 WParams
->PageCode
= MODE_PAGE_WRITE_PARAMS
;
1089 // apply write parameters
1090 RC
= UDFPhSendIOCTL(IOCTL_CDRW_SET_WRITE_MODE
, Vcb
->TargetDeviceObject
,
1091 (void*)WParams
,sizeof(SET_WRITE_MODE_USER_IN
),
1094 #ifdef UDF_FORMAT_MEDIA
1096 if(!NT_SUCCESS(RC
)) {
1097 fms
->SkipPrepareW
= 1;
1098 MyFreePool__(WParams
);
1099 return STATUS_SUCCESS
;
1102 RC
= UDFPhSendIOCTL(IOCTL_CDRW_GET_WRITE_MODE
, Vcb
->TargetDeviceObject
,
1104 (PVOID
)WParams
,sizeof(GET_WRITE_MODE_USER_OUT
),
1106 if(!NT_SUCCESS(RC
)) {
1107 MyFreePool__(WParams
);
1111 if(fms
->opt_partition
== PT_VAT15
||
1112 fms
->opt_blank_vat15
) {
1113 if(WParams
->Byte3
.Flags
& WParam_FP
) {
1114 MyFreePool__(WParams
);
1115 return STATUS_INVALID_DEVICE_STATE
;
1118 if(!(WParams
->Byte3
.Flags
& WParam_FP
)) {
1119 MyFreePool__(WParams
);
1120 return STATUS_INVALID_DEVICE_STATE
;
1124 #endif //UDF_FORMAT_MEDIA
1126 // switch to random access mode
1127 ((PSET_RANDOM_ACCESS_USER_IN
)WParams
)->RandomAccessMode
= Vcb
->CDR_Mode
? FALSE
: TRUE
;
1128 // ((PSET_RANDOM_ACCESS_USER_IN)WParams)->RandomAccessMode = (opt_partition != PT_VAT15) ? TRUE : FALSE;
1129 RC
= UDFPhSendIOCTL(IOCTL_CDRW_SET_RANDOM_ACCESS
, Vcb
->TargetDeviceObject
,
1130 (void*)WParams
,sizeof(SET_RANDOM_ACCESS_USER_IN
),
1131 NULL
,0,FALSE
, NULL
);
1133 check_dvd_bg_format
:
1135 KdPrint((" check BGF\n"));
1136 if(!Vcb
->CDR_Mode
) {
1137 if(OS_SUCCESS(RC
)) {
1138 Vcb
->LastModifiedTrack
= i
;
1139 if(!(Vcb
->TrackMap
[i
].Flags
& TrackMap_Use_variation
)) {
1140 if(Vcb
->TrackMap
[i
].Flags
& TrackMap_Try_variation
) {
1141 Vcb
->TrackMap
[i
].Flags
|= TrackMap_Use_variation
;
1143 Vcb
->TrackMap
[i
].Flags
|= TrackMap_Try_variation
;
1148 Vcb
->LastModifiedTrack
= 0;
1150 // fms->SkipPrepareW = 1;
1153 if((Vcb
->MediaClassEx
== CdMediaClass_DVDRW
||
1154 Vcb
->MediaClassEx
== CdMediaClass_DVDpRW
||
1155 Vcb
->MediaClassEx
== CdMediaClass_DVDRAM
||
1156 Vcb
->MRWStatus
== DiscInfo_BGF_Interrupted
)
1157 && (Lba
> Vcb
->LastLBA
)) {
1161 ULONG PSz
= BCount
<< Vcb
->BlockSizeBits
;
1164 #endif //_BROWSE_UDF_
1165 PFORMAT_CDRW_PARAMETERS_USER_IN ForBuf
;
1167 ASSERT((Vcb
->LastLBA
+1) == Vcb
->NWA
);
1169 if(Lba
+BCount
<= (Vcb
->LastLBA
+1) ) {
1170 KdPrint(("DVD cont. fmt, LBA+BCount<=NWA, exiting\n"));
1171 return STATUS_SUCCESS
;
1173 if((Vcb
->MRWStatus
!= DiscInfo_BGF_Interrupted
) &&
1174 (Lba
<= (Vcb
->LastLBA
+1)) ) {
1175 KdPrint(("!PausedBGF + DVD cont. fmt, LBA<=NWA, exiting\n"));
1176 return STATUS_SUCCESS
;
1179 if(Vcb
->MRWStatus
== DiscInfo_BGF_Interrupted
) {
1180 // This code also can restart background MRW formatting
1181 KdPrint(("DVD cont. fmt, LastLBA %x, Lba %x\n", Vcb
->LastLBA
, Lba
));
1183 ForBuf
= (PFORMAT_CDRW_PARAMETERS_USER_IN
)DbgAllocatePoolWithTag(NonPagedPool
, sizeof(FORMAT_CDRW_PARAMETERS_USER_IN
), 'zNWD');
1185 RtlZeroMemory(ForBuf
, sizeof(FORMAT_CDRW_PARAMETERS_USER_IN
));
1186 ForBuf
->Flags
.FlagsEx
= FORMAT_UNIT_RESTART_MRW
;
1187 ForBuf
->BlockCount
= 0xffffffff;
1189 RC
= UDFPhSendIOCTL(IOCTL_CDRW_FORMAT_UNIT
, Vcb
->TargetDeviceObject
,
1190 ForBuf
,sizeof(FORMAT_CDRW_PARAMETERS_USER_IN
),
1191 NULL
,0,FALSE
, NULL
);
1192 DbgFreePool(ForBuf
);
1193 if(OS_SUCCESS(RC
)) {
1194 KdPrint(("BGFormat restarted Interrupted->InProgress\n"));
1195 Vcb
->MRWStatus
= DiscInfo_BGF_InProgress
;
1197 PGET_LAST_ERROR_USER_OUT Error
= NULL
;
1199 Vcb
->Error
= (PGET_LAST_ERROR_USER_OUT
)
1200 MyAllocatePool__(NonPagedPool
, sizeof(GET_LAST_ERROR_USER_OUT
));
1204 UDFPhSendIOCTL( IOCTL_CDRW_GET_LAST_ERROR
, Vcb
->TargetDeviceObject
,
1206 Error
,sizeof(GET_LAST_ERROR_USER_OUT
),
1208 KdPrint(("SK=%x ASC=%x, ASCQ=%x, IE=%x\n",
1209 Error
->SenseKey
, Error
->AdditionalSenseCode
, Error
->AdditionalSenseCodeQualifier
, Error
->LastError
));
1210 // check for Long Write In Progress
1211 if( (Error
->SenseKey
== SCSI_SENSE_NOT_READY
) &&
1212 (Error
->AdditionalSenseCode
== SCSI_ADSENSE_LUN_NOT_READY
) &&
1213 ((Error
->AdditionalSenseCodeQualifier
== SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS
) ||
1214 (Error
->AdditionalSenseCodeQualifier
== SCSI_SENSEQ_FORMAT_IN_PROGRESS
)) ) {
1215 RC
= STATUS_SUCCESS
;
1216 KdPrint(("Seems, BGFormat already restarted\n"));
1217 Vcb
->MRWStatus
= DiscInfo_BGF_InProgress
;
1223 RC
= STATUS_SUCCESS
;
1226 KdPrint(("DVD cont. write, LastLBA %x, Lba %x\n", Vcb
->LastLBA
, Lba
));
1228 ASSERT(Vcb
->MediaClassEx
== CdMediaClass_DVDRW
);
1229 if(!Vcb
->fZBuffer
) {
1230 Vcb
->fZBuffer
= (PCHAR
)DbgAllocatePoolWithTag(NonPagedPool
, PSz
, 'zNWD');
1231 RtlZeroMemory(Vcb
->fZBuffer
, PSz
);
1232 Vcb
->fZBufferSize
= PSz
;
1234 if(Vcb
->fZBufferSize
< PSz
) {
1235 PSz
= Vcb
->fZBufferSize
;
1237 if(!Vcb
->fZBuffer
) {
1239 RC
= STATUS_INSUFFICIENT_RESOURCES
;
1241 for(fLba
= Vcb
->NWA
; fLba
< Lba
; fLba
+=BCount
) {
1243 retry
= UDF_WRITE_MAX_RETRY
;
1245 #endif //_BROWSE_UDF_
1246 RC
= UDFPhWriteVerifySynchronous(Vcb
->TargetDeviceObject
, Vcb
->fZBuffer
, PSz
,
1247 ((uint64
)fLba
) << Vcb
->BlockSizeBits
, &WrittenBytes
, PH_TMP_BUFFER
);
1248 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
1249 KdPrint(("Fmt status: %x\n", RC
));
1251 if(!OS_SUCCESS(RC
) &&
1252 OS_SUCCESS(RC
= UDFRecoverFromError(Vcb
, TRUE
, RC
, fLba
, BCount
, &retry
)) ) {
1254 KdPrint(("Fmt retry\n"));
1256 #endif //_BROWSE_UDF_
1257 if(!OS_SUCCESS(RC
)) {
1259 KdPrint(("Fmt break on ERROR\n"));
1262 UDFUpdateNWA(Vcb
, fLba
, BCount
, RC
);
1266 KdPrint((" no special processing\n"));
1271 #endif //UDF_READ_ONLY_BUILD
1272 KdPrint((" no suitable track!\n"));
1273 return STATUS_INVALID_PARAMETER
;
1274 } // end UDFPrepareForWriteOperation()
1276 //#ifdef _BROWSE_UDF_
1278 This routine tries to recover from hardware error
1279 Return: STATUS_SUCCESS - retry requst
1280 STATUS_XXX - unrecoverable error
1283 UDFRecoverFromError(
1289 IN OUT uint32
* retry
1292 PGET_LAST_ERROR_USER_OUT Error
= NULL
;
1293 LARGE_INTEGER delay
;
1296 BOOLEAN UpdateBB
= FALSE
;
1299 !(Vcb
->VCBFlags
& UDF_VCB_FLAGS_OUR_DEVICE_DRIVER
) ||
1300 (Vcb
->FsDeviceType
!= FILE_DEVICE_CD_ROM_FILE_SYSTEM
))
1303 // allocate tmp buffer
1306 if(!(Vcb
->Error
= (PGET_LAST_ERROR_USER_OUT
)
1307 MyAllocatePool__(NonPagedPool
, sizeof(GET_LAST_ERROR_USER_OUT
))))
1310 if(status
== STATUS_NO_SUCH_DEVICE
) {
1311 KdPrint(("Error recovery: STATUS_NO_SUCH_DEVICE, die.....\n"));
1312 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_UNSAFE_IOCTL
| UDF_VCB_FLAGS_DEAD
;
1316 #ifdef _UDF_STRUCTURES_H_
1317 if(status
== STATUS_NO_MEDIA_IN_DEVICE
&& !Vcb
->EjectWaiter
) {
1318 KdPrint(("Error recovery: STATUS_NO_MEDIA_IN_DEVICE, prevent further remount.....\n"));
1319 // Make sure, that volume will never be quick-remounted
1320 // It is very important for ChkUdf utility and
1321 // some CD-recording libraries
1322 Vcb
->SerialNumber
--;
1325 #endif //_UDF_STRUCTURES_H_
1328 UDFPhSendIOCTL( IOCTL_CDRW_GET_LAST_ERROR
, Vcb
->TargetDeviceObject
,
1330 Error
,sizeof(GET_LAST_ERROR_USER_OUT
),
1332 KdPrint(("SK=%x ASC=%x, ASCQ=%x, IE=%x\n",
1333 Error
->SenseKey
, Error
->AdditionalSenseCode
, Error
->AdditionalSenseCodeQualifier
, Error
->LastError
));
1334 // check for Long Write In Progress
1335 if( ((Error
->SenseKey
== SCSI_SENSE_NOT_READY
) &&
1336 (Error
->AdditionalSenseCode
== SCSI_ADSENSE_LUN_NOT_READY
) &&
1337 (Error
->AdditionalSenseCodeQualifier
== SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS
)) ) {
1338 // we should wait...
1340 if((*retry
) == UDF_WRITE_MAX_RETRY
-1) {
1341 KdPrint(("Error recovery: reserve retry count for write retries\n"));
1342 (*retry
) = UDF_WRITE_MAX_RETRY
*3;
1344 if((*retry
) == UDF_WRITE_MAX_RETRY
) {
1345 KdPrint(("Error recovery: jump over UDF_WRITE_MAX_RETRY\n"));
1348 delay
.QuadPart
= -500000; // 0.05 sec
1349 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1350 if(WriteOp
&& ((*retry
) > UDF_WRITE_MAX_RETRY
-1)) {
1351 KdPrint(("Error recovery: simple write retry with delay\n"));
1352 try_return(status
= STATUS_SUCCESS
);
1355 delay
.QuadPart
= -500000; // 0.05 sec
1356 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1357 if((*retry
) == UDF_WRITE_MAX_RETRY
-1) {
1358 KdPrint(("Error recovery: retry read after small delay\n"));
1359 try_return(status
= STATUS_SUCCESS
);
1362 KdPrint(("Error recovery: sync cache\n"));
1363 // ...flush device cache...
1365 // wait again & retry
1366 delay
.QuadPart
= -1000000; // 0.1 sec
1367 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1368 #ifdef _UDF_STRUCTURES_H_
1369 if(Vcb
->BGWriters
) (*retry
)++;
1370 #endif //_UDF_STRUCTURES_H_
1371 try_return(status
= STATUS_SUCCESS
);
1373 // check for Long Write In Progress
1374 if((Error
->SenseKey
== SCSI_SENSE_NOT_READY
) &&
1375 (Error
->AdditionalSenseCode
== SCSI_ADSENSE_LUN_NOT_READY
) &&
1376 ((Error
->AdditionalSenseCodeQualifier
== SCSI_SENSEQ_FORMAT_IN_PROGRESS
) ||
1377 (Error
->AdditionalSenseCodeQualifier
== SCSI_SENSEQ_BECOMING_READY
) ||
1378 (Error
->AdditionalSenseCodeQualifier
== SCSI_SENSEQ_OPERATION_IN_PROGRESS
) ) ) {
1379 // we should wait & retry
1380 KdPrint(("Error recovery: op. in progress, waiting 0.3 sec\n"));
1381 delay
.QuadPart
= -3000000; // 0.3 sec
1382 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1383 #ifdef _UDF_STRUCTURES_H_
1384 if(Vcb
->BGWriters
) (*retry
)++;
1385 #endif //_UDF_STRUCTURES_H_
1386 Vcb
->SyncCacheState
= SYNC_CACHE_RECOVERY_ATTEMPT
;
1387 try_return(status
= STATUS_SUCCESS
);
1389 // check for non empty cache special case
1390 if((Error
->SenseKey
== SCSI_SENSE_ILLEGAL_REQUEST
) &&
1391 (Error
->AdditionalSenseCode
== SCSI_ADSENSE_INVALID_CMD_SEQUENCE
)) {
1392 // we should wait & retry
1394 KdPrint(("Error recovery: invalid command sequence on read\n"));
1395 delay
.QuadPart
= -1000000; // 0.1 sec
1396 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1397 KdPrint(("Error recovery: sync cache\n"));
1398 // ...flush device cache...
1400 // wait again & retry
1401 delay
.QuadPart
= -1000000; // 0.1 sec
1402 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1403 #ifdef _UDF_STRUCTURES_H_
1404 if(Vcb
->BGWriters
) (*retry
)++;
1405 #endif //_UDF_STRUCTURES_H_
1406 try_return(status
= STATUS_SUCCESS
);
1408 goto reinit_sector_mode
;
1410 // check for Bus Reset (sometimes it happends...)
1411 if((Error
->SenseKey
== SCSI_SENSE_UNIT_ATTENTION
) &&
1412 (Error
->AdditionalSenseCode
== SCSI_ADSENSE_BUS_RESET
) ) {
1414 KdPrint(("Error recovery: bus reset...\n"));
1415 Vcb
->MediaChangeCount
= Error
->MediaChangeCount
;
1416 delay
.QuadPart
= -1000000; // 0.1 sec
1417 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1419 UDFResetDeviceDriver(Vcb
, Vcb
->TargetDeviceObject
, FALSE
);
1420 delay
.QuadPart
= -1000000; // 0.1 sec
1421 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1423 /* ((PPREVENT_MEDIA_REMOVAL_USER_IN)(Error))->PreventMediaRemoval = TRUE;
1424 UDFPhSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL,
1425 Vcb->TargetDeviceObject,
1426 Error,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN),
1429 delay.QuadPart = -1000000; // 0.1 sec
1430 KeDelayExecutionThread(KernelMode, FALSE, &delay);*/
1432 // reinit write mode the following is performed inside UDFResetDeviceDriver()
1433 //Vcb->LastModifiedTrack = 0;
1434 //Vcb->OPCDone = FALSE;
1437 // reinit sector mode
1438 Vcb
->LastModifiedTrack
= 0;
1439 UDFPrepareForWriteOperation(Vcb
, Lba
, BCount
);
1440 try_return(status
= STATUS_SUCCESS
);
1442 // check for Illegal Sector Mode.
1443 // We can get this error 'cause of 2 reasons:
1444 // a) Bus reset occured. We should reinit
1445 // b) CopyProtection settings missmatch
1446 // c) preblems with DNA of firmware developer, some TEACs fall into such state
1447 // after failed streaming read
1448 if((Error
->SenseKey
== SCSI_SENSE_ILLEGAL_REQUEST
) &&
1449 (Error
->AdditionalSenseCode
== SCSI_ADSENSE_ILLEGAL_MODE_FOR_THIS_TRACK
)) {
1450 bad_rw_seek_recovery
:
1454 // Variate CopyProtection...
1455 for(i
=Vcb
->FirstTrackNum
; i
<=Vcb
->LastTrackNum
; i
++) {
1456 if((Vcb
->TrackMap
[i
].FirstLba
> Lba
) ||
1457 (Vcb
->TrackMap
[i
].LastLba
< Lba
))
1459 /* if(Vcb->TrackMap[i].Flags & TrackMap_CopyBit_variated)
1461 goto reinit_sector_mode;*/
1463 // check if we have successuflly completed WriteOp
1465 // We should not variate these bits again in this case.
1466 if(Vcb
->TrackMap
[i
].Flags
& TrackMap_Use_variation
)
1468 Vcb
->TrackMap
[i
].Flags
&= ~TrackMap_Try_variation
;
1469 /* if((Vcb->TrackMap[i].Flags & TrackMap_Try_variation) &&
1470 (Vcb->TrackMap[i].Flags & (TrackMap_AllowCopyBit_variated |
1471 TrackMap_CopyBit_variated)))
1473 /* if(Vcb->TrackMap[i].Flags & TrackMap_Use_variation)
1475 Vcb
->TrackMap
[i
].Flags
|= TrackMap_Try_variation
;
1477 if(!(Vcb
->TrackMap
[i
].Flags
^= TrackMap_AllowCopyBit_variated
))
1478 Vcb
->TrackMap
[i
].Flags
^= TrackMap_CopyBit_variated
;
1479 if(Vcb
->TrackMap
[i
].Flags
& (TrackMap_AllowCopyBit_variated
|
1480 TrackMap_CopyBit_variated
) ) {
1483 Vcb
->TrackMap
[i
].Flags
&= ~TrackMap_Try_variation
;
1485 // reinit sector mode
1486 Vcb
->LastModifiedTrack
= 0;
1487 UDFPrepareForWriteOperation(Vcb
, Lba
, BCount
);
1492 //reinit_sector_mode:
1494 delay
.QuadPart
= -1000000; // 0.1 sec
1495 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1496 // reinit sector mode
1497 goto reinit_sector_mode
;
1499 Vcb->LastModifiedTrack = 0;
1500 UDFPrepareForWriteOperation(Vcb, Lba, BCount);
1501 try_return(status = STATUS_SUCCESS);
1505 if((Vcb
->CompatFlags
& UDF_VCB_IC_BAD_RW_SEEK
) &&
1506 (Vcb
->IncrementalSeekState
!= INCREMENTAL_SEEK_DONE
)) {
1507 KdPrint(("Using incremental seek workaround...\n"));
1508 Vcb
->IncrementalSeekState
= INCREMENTAL_SEEK_WORKAROUND
;
1509 try_return(status
= STATUS_SUCCESS
);
1511 KdPrint(("Seems to be BB @ %x\n", Lba
));
1515 if((Error
->SenseKey
== SCSI_SENSE_ILLEGAL_REQUEST
) &&
1516 (Error
->AdditionalSenseCode
== SCSI_ADSENSE_INVALID_SESSION_MODE
)) {
1518 (Vcb
->SavedFeatures
& CDRW_FEATURE_STREAMING
) &&
1519 Lba
+BCount
<= Vcb
->LastLBA
+1) {
1520 KdPrint(("bad Session in streaming mode. Lba %x, try fix-up\n", Lba
));
1521 // ...flush device cache...
1524 delay
.QuadPart
= -10000000; // 1 sec
1525 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1526 try_return(status
= STATUS_SUCCESS
);
1529 if((Error
->LastError
== CDRW_ERR_WRITE_IN_PROGRESS_BUSY
) ||
1530 (status
== STATUS_DEVICE_BUSY
)) {
1531 delay
.QuadPart
= -5000000; // 0.5 sec
1532 KdPrint(("CDRW_ERR_WRITE_IN_PROGRESS_BUSY || STATUS_DEVICE_BUSY\n"));
1533 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
1534 #ifdef _UDF_STRUCTURES_H_
1535 if(Vcb
->BGWriters
) (*retry
)++;
1536 #endif //_UDF_STRUCTURES_H_
1537 try_return(status
= STATUS_SUCCESS
);
1539 // some devices (SONY) return such a strange sequence....
1540 if( ((Error
->SenseKey
== SCSI_SENSE_ILLEGAL_REQUEST
) &&
1541 (Error
->AdditionalSenseCode
== SCSI_ADSENSE_INVALID_CDB
)) &&
1543 // reinit write mode
1544 Vcb
->LastModifiedTrack
= 0;
1545 UDFPrepareForWriteOperation(Vcb
, Lba
, BCount
);
1546 try_return(status
= STATUS_SUCCESS
);
1548 // No seek on Read... to morgue, I'm afraid
1549 if((Error
->SenseKey
== SCSI_SENSE_MEDIUM_ERROR
) /*&&
1550 ((Error->AdditionalSenseCode == SCSI_ADSENSE_CD_READ_ERROR) ||
1551 (Error->AdditionalSenseCode == SCSI_ADSENSE_NO_SENSE) ||
1552 (Error->AdditionalSenseCode == SCSI_ADSENSE_FORMAT_CORRUPTED) ||
1553 (Error->AdditionalSenseCode == SCSI_ADSENSE_SEEK_ERROR))*/ &&
1555 if(Error
->AdditionalSenseCode
== SCSI_ADSENSE_SEEK_ERROR
) {
1556 KdPrint(("Seek error\n"));
1557 if(Vcb
->CompatFlags
& UDF_VCB_IC_BAD_RW_SEEK
) {
1558 KdPrint(("try recovery\n"));
1559 goto bad_rw_seek_recovery
;
1561 KdPrint(("map error to STATUS_NONEXISTENT_SECTOR\n"));
1562 status
= STATUS_NONEXISTENT_SECTOR
;
1564 KdPrint(("Seems to be BB @ %x (read 2)\n", Lba
));
1567 // handle invalid block address
1568 if( ((Error
->SenseKey
== SCSI_SENSE_ILLEGAL_REQUEST
) &&
1569 (Error
->AdditionalSenseCode
== SCSI_ADSENSE_ILLEGAL_BLOCK
)) ) {
1571 (Vcb
->SavedFeatures
& CDRW_FEATURE_STREAMING
) &&
1572 Lba
+BCount
<= Vcb
->LastLBA
+1) {
1573 KdPrint(("bad LBA %x in streaming mode, try fix-up\n", Lba
));
1574 // ...flush device cache...
1576 try_return(status
= STATUS_SUCCESS
);
1579 if((Lba
+BCount
>= Vcb
->LastLBA
) &&
1580 (Vcb
->MRWStatus
== DiscInfo_BGF_Interrupted
)) {
1581 KdPrint(("stupid drive, cannot read beyond formatted area on DiscInfo_BGF_Interrupted\n"));
1583 try_return(status
= STATUS_BUFFER_ALL_ZEROS
);
1585 // prevent Bad Block Bitmap modification
1592 if(OS_SUCCESS(status
)) {
1593 KdPrint(("Retry\n"));
1597 if(!OS_SUCCESS(status
)) {
1598 if((Vcb
->MountPhErrorCount
!= (ULONG
)-1) &&
1599 (Vcb
->MountPhErrorCount
< 0x7fffffff)) {
1600 Vcb
->MountPhErrorCount
++;
1602 //#ifdef _UDF_STRUCTURES_H_
1603 if(UpdateBB
&& (BCount
== 1)) {
1605 if(!(bm
= (uint32
*)(Vcb
->BSBM_Bitmap
))) {
1606 bm
= (uint32
*)(Vcb
->BSBM_Bitmap
= (int8
*)DbgAllocatePoolWithTag(NonPagedPool
, (i
= (Vcb
->LastPossibleLBA
+1+7)>>3), 'mNWD' ));
1608 RtlZeroMemory(bm
, i
);
1610 KdPrint(("Can't alloc BSBM for %x blocks\n", Vcb
->LastPossibleLBA
));
1615 KdPrint(("Set BB @ %#x\n", Lba
));
1618 bm
= (uint32
*)(Vcb
->FSBM_Bitmap
);
1620 UDFSetUsedBit(bm
, Lba
);
1621 KdPrint(("Set BB @ %#x as used\n", Lba
));
1623 #endif //_BROWSE_UDF_
1625 //#endif //_UDF_STRUCTURES_H_
1628 } // end UDFRecoverFromError()
1630 //#endif //_BROWSE_UDF_
1632 This routine attempts to read disk layout using ReadDisk/Track info cmd
1635 UDFReadDiscTrackInfo(
1636 PDEVICE_OBJECT DeviceObject
, // the target device object
1637 PVCB Vcb
// Volume Control Block for ^ DevObj
1640 OSSTATUS RC
= STATUS_SUCCESS
;
1641 PDISC_INFO_BLOCK_USER_OUT DiscInfo
= (PDISC_INFO_BLOCK_USER_OUT
)MyAllocatePool__(NonPagedPool
,sizeof(DISC_INFO_BLOCK_USER_OUT
) );
1642 PTRACK_INFO_BLOCK_USER_OUT TrackInfoOut
= (PTRACK_INFO_BLOCK_USER_OUT
)MyAllocatePool__(NonPagedPool
,sizeof(TRACK_INFO_BLOCK_USER_OUT
) );
1643 PTRACK_INFO_BLOCK_USER_IN TrackInfoIn
= (PTRACK_INFO_BLOCK_USER_IN
)TrackInfoOut
;
1644 READ_CAPACITY_USER_OUT CapacityBuffer
;
1646 BOOLEAN NotFP
= FALSE
;
1647 BOOLEAN ForceFP
= FALSE
;
1648 BOOLEAN PacketTrack
= FALSE
;
1649 BOOLEAN MRWRetry
= FALSE
;
1650 // BOOLEAN ReadCapacityOk = FALSE;
1651 #ifdef UDF_FORMAT_MEDIA
1652 PUDFFmtState fms
= Vcb
->fms
;
1656 if(!DiscInfo
|| !TrackInfoOut
)
1657 try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
1661 RC
= UDFPhSendIOCTL(IOCTL_CDRW_READ_DISC_INFO
, DeviceObject
,
1663 DiscInfo
,sizeof(DISC_INFO_BLOCK_USER_OUT
), TRUE
, NULL
);
1664 if(!OS_SUCCESS(RC
)) {
1665 KdPrint(("ReadDiskInfo failed. Use default.\n"));
1666 if(Vcb
->MediaClassEx
== CdMediaClass_DVDRW
||
1667 Vcb
->MediaClassEx
== CdMediaClass_DVDpRW
||
1668 Vcb
->MediaClassEx
== CdMediaClass_DVDRAM
) {
1669 Vcb
->LastPossibleLBA
= DEFAULT_LAST_LBA_DVD
;
1671 if(Vcb
->MediaClassEx
== CdMediaClass_BDRE
) {
1672 Vcb
->LastPossibleLBA
= DEFAULT_LAST_LBA_BD
;
1674 Vcb
->LastPossibleLBA
= DEFAULT_LAST_LBA_FP_CD
;
1678 #ifdef UDF_FORMAT_MEDIA
1679 if(fms
&& fms
->opt_disk_info
) {
1680 UserPrint(("ReadDiskInfo OK\n"));
1682 #endif //UDF_FORMAT_MEDIA
1684 RC
= UDFPhSendIOCTL(IOCTL_CDRW_READ_CAPACITY
, DeviceObject
,
1686 &CapacityBuffer
,sizeof(READ_CAPACITY_USER_OUT
), TRUE
, NULL
);
1687 if(!OS_SUCCESS(RC
)) {
1688 KdPrint(("ReadCapacity failed.\n"));
1689 if(Vcb
->MediaClassEx
== CdMediaClass_DVDpRW
) {
1690 Vcb
->LastPossibleLBA
= DEFAULT_LAST_LBA_DVD
;
1693 KdPrint(("ReadCapacity ok.\n"));
1694 KdPrint(("Last possible LBA %#x.\n", CapacityBuffer
.LogicalBlockAddress
));
1695 if(!(CapacityBuffer
.LogicalBlockAddress
& 0xc0000000) &&
1696 (CapacityBuffer
.LogicalBlockAddress
!= 0x7fffffff)) {
1697 // good value from ReadCapacity
1698 KdPrint(("Update Last possible LBA %#x.\n", CapacityBuffer
.LogicalBlockAddress
));
1699 Vcb
->LastPossibleLBA
= CapacityBuffer
.LogicalBlockAddress
;
1700 // ReadCapacityOk = TRUE;
1701 #ifdef UDF_FORMAT_MEDIA
1702 if(fms
&& fms
->opt_disk_info
) {
1703 UserPrint(("ReadCapacity OK\n"));
1705 #endif //UDF_FORMAT_MEDIA
1710 Vcb
->PhDeviceType
= FILE_DEVICE_CD_ROM
;
1712 Vcb
->PhSerialNumber
= *((uint32
*)&(DiscInfo
->DiskId
));
1713 Vcb
->PhErasable
= DiscInfo
->DiscStat
.Flags
& DiscInfo_Disk_Erasable
;
1714 Vcb
->PhDiskType
= DiscInfo
->DiskType
;
1716 if(DiscInfo
->OPCNum
)
1717 Vcb
->OPCNum
= DiscInfo
->OPCNum
;
1718 KdPrint(("DiskInfo: SN %x, OPCn %x(%x), Stat %x, Flg: %x\n",
1719 Vcb
->PhSerialNumber
, Vcb
->OPCNum
, DiscInfo
->OPCNum
, DiscInfo
->DiscStat
.Flags
, DiscInfo
->Flags
.Flags
));
1720 #ifdef UDF_FORMAT_MEDIA
1721 if(fms
&& fms
->opt_disk_info
) {
1722 UserPrint(("Media type: "));
1723 switch(Vcb
->MediaClassEx
) {
1724 case CdMediaClass_CDROM
: UserPrint(("CD-ROM \n")); break;
1725 case CdMediaClass_CDR
: UserPrint(("CD-R \n")); break;
1726 case CdMediaClass_CDRW
: UserPrint(("CD-RW \n")); break;
1727 case CdMediaClass_DVDROM
: UserPrint(("DVD-ROM \n")); break;
1728 case CdMediaClass_DVDRAM
: UserPrint(("DVD-RAM \n")); break;
1729 case CdMediaClass_DVDR
: UserPrint(("DVD-R \n")); break;
1730 case CdMediaClass_DVDRW
: UserPrint(("DVD-RW \n")); break;
1731 case CdMediaClass_DVDpR
: UserPrint(("DVD+R \n")); break;
1732 case CdMediaClass_DVDpRW
: UserPrint(("DVD+RW \n")); break;
1733 case CdMediaClass_DDCDROM
: UserPrint(("DDCD-ROM \n")); break;
1734 case CdMediaClass_DDCDR
: UserPrint(("DDCD-R \n")); break;
1735 case CdMediaClass_DDCDRW
: UserPrint(("DDCD-RW \n")); break;
1736 case CdMediaClass_BDROM
: UserPrint(("BD-ROM \n")); break;
1737 case CdMediaClass_BDRE
: UserPrint(("BD-RE \n")); break;
1738 case CdMediaClass_BDR
: UserPrint(("BD-R \n")); break;
1739 case CdMediaClass_HD_DVDROM
: UserPrint(("HD DVD-ROM \n")); break;
1740 case CdMediaClass_HD_DVDRAM
: UserPrint(("HD DVD-RAM \n")); break;
1741 case CdMediaClass_HD_DVDR
: UserPrint(("HD DVD-R \n")); break;
1742 case CdMediaClass_HD_DVDRW
: UserPrint(("HD DVD-RW \n")); break;
1743 default: UserPrint(("Unknown\n")); break;
1745 UserPrint(("SN %#x, OPCn %#x\n",
1746 Vcb
->PhSerialNumber
, Vcb
->OPCNum
, DiscInfo
->OPCNum
));
1747 UserPrint(("Disk State: "));
1748 switch(DiscInfo
->DiscStat
.Flags
& DiscInfo_Disk_Mask
) {
1749 case DiscInfo_Disk_Empty
:
1750 UserPrint(("Empty\n"));
1752 case DiscInfo_Disk_Appendable
:
1753 UserPrint(("Appendable\n"));
1755 case DiscInfo_Disk_Complete
:
1756 UserPrint(("Complete\n"));
1758 case DiscInfo_Disk_OtherRW
:
1759 UserPrint(("RW in unknown state\n"));
1762 UserPrint(("Last Session State: "));
1763 switch(DiscInfo
->DiscStat
.Flags
& DiscInfo_Ses_Mask
) {
1764 case DiscInfo_Ses_Empty
:
1765 UserPrint(("Empty\n"));
1767 case DiscInfo_Ses_Incomplete
:
1768 UserPrint(("Incomplete\n"));
1770 case DiscInfo_Ses_Complete
:
1771 UserPrint(("Complete\n"));
1774 UserPrint(("unknown state\n"));
1777 UserPrint(("Erasable: %s\n",
1778 (DiscInfo
->DiscStat
.Flags
& DiscInfo_Disk_Erasable
) ? "yes" : "no"
1781 #endif //UDF_FORMAT_MEDIA
1783 Vcb
->DiscStat
= DiscInfo
->DiscStat
.Flags
;
1784 if((DiscInfo
->DiscStat
.Flags
& DiscInfo_Disk_Mask
) == DiscInfo_Disk_Empty
) {
1785 KdPrint(("Blank\n"));
1786 Vcb
->BlankCD
= TRUE
;
1788 if( (DiscInfo
->DiscStat
.Flags
& DiscInfo_Disk_Mask
) == DiscInfo_Disk_Empty
||
1789 (DiscInfo
->DiscStat
.Flags
& DiscInfo_Ses_Mask
) == DiscInfo_Ses_Incomplete
) {
1790 // we shall mount empty disk to make it possible for
1791 // external applications to perform format operation
1792 // or something like this
1793 KdPrint(("Try RAW_MOUNT\n"));
1794 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_RAW_DISK
;
1798 #ifndef _BROWSE_UDF_
1799 // If drive returned reasonable value from ReadCapacity, do not use
1800 // last LeadIn/LeadOut
1801 if(Vcb
->MediaClassEx
!= CdMediaClass_DVDpRW
&&
1803 // +RW returns bad value
1804 KdPrint(("+RW returns bad value\n"));
1805 Vcb
->LastPossibleLBA
= (DiscInfo
->LastSesLeadOutLBA
& 0x80000000) ?
1806 0 : DiscInfo
->LastSesLeadOutLBA
;
1807 if(!(DiscInfo
->LastSesLeadInLBA
& 0x80000000)) {
1808 Vcb
->LastPossibleLBA
= max(DiscInfo
->LastSesLeadInLBA
, Vcb
->LastPossibleLBA
);
1811 #endif // _BROWSE_UDF_
1812 if((DiscInfo
->Flags
.Flags
& DiscInfo_BGF_Mask
) != 0) {
1813 KdPrint(("ForceFP + MRW\n"));
1815 Vcb
->MRWStatus
= DiscInfo
->Flags
.Flags
& DiscInfo_BGF_Mask
;
1816 // update addressing mode
1820 goto MRWRetry_label
;
1823 KdPrint(("MRW state %x\n", Vcb
->MRWStatus
));
1824 if(Vcb
->MediaClassEx
== CdMediaClass_DVDRW
) {
1825 if(Vcb
->PhMediaCapFlags
& CdCapFlags_RandomWritable
) {
1826 KdPrint(("DVD-RW Rewritable\n"));
1829 if((DiscInfo
->DiscStat
.Flags
& DiscInfo_Disk_Mask
) == DiscInfo_Disk_Empty
) {
1830 KdPrint(("Blank DVD-RW\n"));
1833 KdPrint(("DVD-RW Sequential\n"));
1837 if(CdrwIsDvdOverwritable(Vcb
->MediaClassEx
)) {
1838 KdPrint(("force Rewritable (2)\n"));
1841 // We have incomplete last session, so process each track from last to first
1842 // Vcb->LastPossibleLBA = DiscInfo->LastSesLeadInLBA;
1844 Vcb
->LastSession
= DiscInfo
->Status
.NumOfSes
;
1845 Vcb
->LastTrackNum
= DiscInfo
->Status
.LastTrackNumLastSes
;
1846 Vcb
->FirstTrackNum
= DiscInfo
->FirstTrackNum
;
1847 // some devices report LastTrackNum=0 for full disks
1848 Vcb
->LastTrackNum
= max(Vcb
->LastTrackNum
, Vcb
->FirstTrackNum
);
1849 if(!Vcb
->LastTrackNum
) {
1850 KdPrint(("Try read 1st track...\n"));
1851 Vcb
->LastTrackNum
= 1;
1853 KdPrint(("DiskInfo: 1st trk %x, last trk %x\n", Vcb
->FirstTrackNum
, Vcb
->LastTrackNum
));
1854 #ifdef UDF_FORMAT_MEDIA
1855 if(fms
&& fms
->opt_disk_info
) {
1856 UserPrint(("First track: %d\n"
1857 "Last track: %d\n", Vcb
->FirstTrackNum
, Vcb
->LastTrackNum
));
1858 UserPrint(("------------------------------------------\n"));
1860 #endif //UDF_FORMAT_MEDIA
1862 RC
= UDFReallocTrackMap(Vcb
, Vcb
->LastTrackNum
+1);
1866 // Get last LBA from invisible track (if any)
1867 RtlZeroMemory(TrackInfoOut
,sizeof(TRACK_INFO_BLOCK_USER_OUT
));
1869 TrackInfoIn
->LBA_TrkNum
= 0; // invisible track
1870 TrackInfoIn
->Track
= TRUE
;
1872 RC
= UDFPhSendIOCTL(IOCTL_CDRW_READ_TRACK_INFO
, DeviceObject
,
1873 TrackInfoIn
, sizeof(TRACK_INFO_BLOCK_USER_IN
),
1874 TrackInfoOut
,sizeof(TRACK_INFO_BLOCK_USER_OUT
), TRUE
, NULL
);
1875 if(OS_SUCCESS(RC
)) {
1876 if((Vcb
->LastTrackNum
< TrackInfoOut
->TrackNum
) &&
1877 TrackInfoOut
->TrackLength
&&
1878 (TrackInfoOut
->TrackStartLBA
!= TrackInfoOut
->NextWriteLBA
)) {
1879 Vcb
->LastTrackNum
= TrackInfoOut
->TrackNum
;
1880 if(!(TrackInfoOut
->NextWriteLBA
& 0x80000000))
1881 Vcb
->NWA
= TrackInfoOut
->NextWriteLBA
;
1882 if(TrackInfoOut
->TrackLength
> 1) {
1883 Vcb
->LastPossibleLBA
=
1884 TrackInfoOut
->TrackStartLBA
+ TrackInfoOut
->TrackLength
- (TrackInfoOut
->TrackLength
? 1 : 0);
1885 KdPrint((" set LastPossibleLBA=%x\n", Vcb
->LastPossibleLBA
));
1889 KdPrint(("Ses %d, Track %d (%x, len %x) PckSize %x: \n"
1890 " NWA: %x (%s) DatType:%x, %s %s %s %s TrkType:%x %s %s\n"
1891 " LRA: %x (%s) RC_LBA:%x\n",
1892 TrackInfoOut
->SesNum
,
1894 TrackInfoOut
->TrackStartLBA
,
1895 TrackInfoOut
->TrackLength
,
1896 TrackInfoOut
->FixPacketSize
,
1898 TrackInfoOut
->NextWriteLBA
,
1899 TrackInfoOut
->NWA_V
& TrkInfo_NWA_V
? "vld" : "inv",
1900 TrackInfoOut
->DataParam
.Flags
& TrkInfo_Dat_Mask
,
1901 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_Packet
) ? "Pck" : "",
1902 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_FP
) ? "FP" : "",
1903 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_Blank
) ? "Blank" : "",
1904 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_RT
) ? "RT" : "",
1906 TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Trk_Mask
,
1907 (TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Copy
) ? "Cpy" : "",
1908 (TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Damage
) ? "Damage" : "",
1910 TrackInfoOut
->LastRecordedAddr
,
1911 (TrackInfoOut
->NWA_V
& TrkInfo_LRA_V
) ? "vld" : "inv",
1913 TrackInfoOut
->ReadCompatLBA
1915 #ifdef UDF_FORMAT_MEDIA
1916 if(fms
&& fms
->opt_disk_info
) {
1917 UserPrint(("Invisible track: \n"));
1918 UserPrint((" Ses %d, Track %d (%x, len %x) PckSize %x: \n"
1919 " NWA: %x (%s) DatType:%x, %s %s %s %s TrkType:%x %s %s\n"
1920 " LRA: %x (%s) RC_LBA:%x\n",
1921 TrackInfoOut
->SesNum
,
1923 TrackInfoOut
->TrackStartLBA
,
1924 TrackInfoOut
->TrackLength
,
1925 TrackInfoOut
->FixPacketSize
,
1927 TrackInfoOut
->NextWriteLBA
,
1928 TrackInfoOut
->NWA_V
& TrkInfo_NWA_V
? "vld" : "inv",
1929 TrackInfoOut
->DataParam
.Flags
& TrkInfo_Dat_Mask
,
1930 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_Packet
) ? "Pck" : "",
1931 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_FP
) ? "FP" : "",
1932 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_Blank
) ? "Blank" : "",
1933 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_RT
) ? "RT" : "",
1935 TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Trk_Mask
,
1936 (TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Copy
) ? "Cpy" : "",
1937 (TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Damage
) ? "Damage" : "",
1939 TrackInfoOut
->LastRecordedAddr
,
1940 (TrackInfoOut
->NWA_V
& TrkInfo_LRA_V
) ? "vld" : "inv",
1942 TrackInfoOut
->ReadCompatLBA
1945 #endif //UDF_FORMAT_MEDIA
1949 for (TrackNumber
=(LONG
)DiscInfo
->FirstTrackNum
;TrackNumber
<= (LONG
)Vcb
->LastTrackNum
;TrackNumber
++) {
1951 RtlZeroMemory(TrackInfoOut
,sizeof(TRACK_INFO_BLOCK_USER_OUT
));
1952 TrackInfoIn
->LBA_TrkNum
= TrackNumber
;
1953 TrackInfoIn
->Track
= TRUE
;
1955 RC
= UDFPhSendIOCTL(IOCTL_CDRW_READ_TRACK_INFO
, DeviceObject
,
1956 TrackInfoIn
, sizeof(TRACK_INFO_BLOCK_USER_IN
),
1957 TrackInfoOut
,sizeof(TRACK_INFO_BLOCK_USER_OUT
), TRUE
, NULL
);
1958 // fill sector type map
1959 if(TrackInfoOut
->TrackStartLBA
& 0x80000000) {
1960 KdPrint(("TrkInfo: Bad FirstLba (%x), change to %x\n", TrackInfoOut
->TrackStartLBA
, 0));
1961 Vcb
->TrackMap
[TrackNumber
].FirstLba
= 0;
1963 Vcb
->TrackMap
[TrackNumber
].FirstLba
= TrackInfoOut
->TrackStartLBA
;
1965 if(TrackInfoOut
->TrackLength
& 0x80000000) {
1966 KdPrint(("TrkInfo: Bad TrackLength (%x), change to %x\n", TrackInfoOut
->TrackLength
,
1967 Vcb
->LastPossibleLBA
- Vcb
->TrackMap
[TrackNumber
].FirstLba
+ 1));
1968 TrackInfoOut
->TrackLength
= Vcb
->LastPossibleLBA
- Vcb
->TrackMap
[TrackNumber
].FirstLba
+ 1;
1970 Vcb
->TrackMap
[TrackNumber
].LastLba
= TrackInfoOut
->TrackStartLBA
+
1971 TrackInfoOut
->TrackLength
-
1972 (TrackInfoOut
->TrackLength
? 1 : 0);
1974 Vcb
->TrackMap
[TrackNumber
].TrackParam
= TrackInfoOut
->TrackParam
.Flags
;
1975 Vcb
->TrackMap
[TrackNumber
].DataParam
= TrackInfoOut
->DataParam
.Flags
;
1976 Vcb
->TrackMap
[TrackNumber
].NWA_V
= TrackInfoOut
->NWA_V
;
1977 if((TrackInfoOut
->NextWriteLBA
& 0x80000000) ||
1978 (TrackInfoOut
->NextWriteLBA
< TrackInfoOut
->TrackStartLBA
)) {
1979 if(!(Vcb
->TrackMap
[TrackNumber
].LastLba
& 0x8000000)) {
1980 KdPrint(("TrkInfo: set NWA to LastLba (%x)\n", Vcb
->TrackMap
[TrackNumber
].LastLba
));
1981 Vcb
->TrackMap
[TrackNumber
].NWA
=
1982 Vcb
->TrackMap
[TrackNumber
].LastLba
;
1984 KdPrint(("TrkInfo: set NWA to INV (1)\n"));
1985 Vcb
->TrackMap
[TrackNumber
].NWA
= 0;
1986 Vcb
->TrackMap
[TrackNumber
].NWA_V
= 0;
1989 if(!(TrackInfoOut
->NextWriteLBA
& 0x80000000)) {
1990 KdPrint(("TrkInfo: Good NWA (%x)\n", TrackInfoOut
->NextWriteLBA
));
1991 Vcb
->TrackMap
[TrackNumber
].NWA
=
1992 TrackInfoOut
->NextWriteLBA
;
1994 KdPrint(("TrkInfo: set NWA to INV (2)\n"));
1995 Vcb
->TrackMap
[TrackNumber
].NWA
= 0;
1996 Vcb
->TrackMap
[TrackNumber
].NWA_V
= 0;
1999 Vcb
->TrackMap
[TrackNumber
].Session
= TrackInfoOut
->SesNum
;
2000 // for FP tracks we shall get PacketSize from returned info
2001 // otherwise set to default UDF value (0x20)
2003 KdPrint(("Apply NotFP\n"));
2004 Vcb
->TrackMap
[TrackNumber
].DataParam
&= ~TrkInfo_FP
;
2006 TrackInfoOut
->DataParam
.Flags
&= ~TrkInfo_FP
;
2010 KdPrint(("Apply ForceFP\n"));
2012 Vcb
->TrackMap
[TrackNumber
].DataParam
|= TrkInfo_FP
;
2014 TrackInfoOut
->DataParam
.Flags
|= TrkInfo_FP
;
2017 if(Vcb
->TrackMap
[TrackNumber
].DataParam
& TrkInfo_FP
) {
2018 Vcb
->TrackMap
[TrackNumber
].PacketSize
= TrackInfoOut
->FixPacketSize
;
2019 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_RAW_DISK
;
2020 Vcb
->FP_disc
= TRUE
;
2022 Vcb
->TrackMap
[TrackNumber
].PacketSize
= PACKETSIZE_UDF
;
2024 // presence of Damaged track means, that we should mount this disk in RAW mode
2025 if(Vcb
->TrackMap
[TrackNumber
].TrackParam
& TrkInfo_Damage
) {
2026 KdPrint(("TrkInfo_Damage, Try RAW_MOUNT\n"));
2027 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_RAW_DISK
;
2029 // presence of track with Unknown data type means, that we should mount
2030 // this disk in RAW mode
2031 if((TrackInfoOut
->DataParam
.Flags
& TrkInfo_Dat_Mask
) == TrkInfo_Trk_unknown
) {
2032 KdPrint(("Unknown DatType, Try RAW_MOUNT\n"));
2033 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_RAW_DISK
;
2036 PacketTrack
|= ((TrackInfoOut
->DataParam
.Flags
& TrkInfo_Packet
) != 0);
2038 KdPrint(("Ses %d, Track %d (%x - %x) PckSize %x: \n"
2039 " NWA: %x (%s) DatType:%x, %s %s %s %s TrkType:%x %s %s\n"
2040 " LRA: %x (%s) RC_LBA:%x\n",
2041 TrackInfoOut
->SesNum
,
2043 Vcb
->TrackMap
[TrackNumber
].FirstLba
,
2044 Vcb
->TrackMap
[TrackNumber
].LastLba
,
2045 TrackInfoOut
->FixPacketSize
,
2047 TrackInfoOut
->NextWriteLBA
,
2048 TrackInfoOut
->NWA_V
& TrkInfo_NWA_V
? "vld" : "inv",
2049 TrackInfoOut
->DataParam
.Flags
& TrkInfo_Dat_Mask
,
2050 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_Packet
) ? "Pck" : "",
2051 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_FP
) ? "FP" : "",
2052 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_Blank
) ? "Blank" : "",
2053 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_RT
) ? "RT" : "",
2055 TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Trk_Mask
,
2056 (TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Copy
) ? "Cpy" : "",
2057 (TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Damage
) ? "Damage" : "",
2059 TrackInfoOut
->LastRecordedAddr
,
2060 (TrackInfoOut
->NWA_V
& TrkInfo_LRA_V
) ? "vld" : "inv",
2062 TrackInfoOut
->ReadCompatLBA
2064 #ifdef UDF_FORMAT_MEDIA
2065 if(fms
&& fms
->opt_disk_info
) {
2066 UserPrint(("Track %d: \n", TrackNumber
));
2067 UserPrint((" Ses %d, Track %d (%x, len %x) PckSize %x: \n"
2068 " NWA: %x (%s) DatType:%x, %s %s %s %s TrkType:%x %s %s\n"
2069 " LRA: %x (%s) RC_LBA:%x\n",
2070 TrackInfoOut
->SesNum
,
2072 TrackInfoOut
->TrackStartLBA
,
2073 TrackInfoOut
->TrackLength
,
2074 TrackInfoOut
->FixPacketSize
,
2076 TrackInfoOut
->NextWriteLBA
,
2077 TrackInfoOut
->NWA_V
& TrkInfo_NWA_V
? "vld" : "inv",
2078 TrackInfoOut
->DataParam
.Flags
& TrkInfo_Dat_Mask
,
2079 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_Packet
) ? "Pck" : "",
2080 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_FP
) ? "FP" : "",
2081 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_Blank
) ? "Blank" : "",
2082 (TrackInfoOut
->DataParam
.Flags
& TrkInfo_RT
) ? "RT" : "",
2084 TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Trk_Mask
,
2085 (TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Copy
) ? "Cpy" : "",
2086 (TrackInfoOut
->TrackParam
.Flags
& TrkInfo_Damage
) ? "Damage" : "",
2088 TrackInfoOut
->LastRecordedAddr
,
2089 (TrackInfoOut
->NWA_V
& TrkInfo_LRA_V
) ? "vld" : "inv",
2091 TrackInfoOut
->ReadCompatLBA
2094 #endif //UDF_FORMAT_MEDIA
2096 if(TrackNumber
== DiscInfo
->FirstTrackNum
) {
2097 if(!(Vcb
->TrackMap
[TrackNumber
].FirstLba
& 0x80000000)) {
2098 KdPrint(("TrkInfo: Update FirstLBA (%x)\n", Vcb
->TrackMap
[TrackNumber
].FirstLba
));
2099 Vcb
->FirstLBA
= Vcb
->TrackMap
[TrackNumber
].FirstLba
;
2102 if((TrackInfoOut
->SesNum
== Vcb
->LastSession
) && !Vcb
->FirstTrackNumLastSes
) {
2103 if(!(Vcb
->TrackMap
[TrackNumber
].FirstLba
& 0x80000000)) {
2104 KdPrint(("TrkInfo: Update FirstLBALastSes (%x)\n", Vcb
->TrackMap
[TrackNumber
].FirstLba
));
2105 Vcb
->FirstLBALastSes
= Vcb
->TrackMap
[TrackNumber
].FirstLba
;
2107 Vcb
->FirstTrackNumLastSes
= TrackNumber
;
2111 if(!(TrackInfoOut
->NextWriteLBA
& 0x80000000) &&
2112 !(TrackInfoOut
->TrackLength
& 0x80000000) &&
2113 (Vcb
->NWA
< TrackInfoOut
->NextWriteLBA
)
2115 KdPrint((" set NWA to %x\n", TrackInfoOut
->NextWriteLBA
));
2116 if(Vcb
->MediaClassEx
!= CdMediaClass_DVDpRW
) {
2117 Vcb
->NWA
= TrackInfoOut
->NextWriteLBA
;
2120 TrackInfoOut
->TrackStartLBA
+ TrackInfoOut
->TrackLength
- (TrackInfoOut
->TrackLength
? 1 : 0);
2123 if(Vcb
->MediaClassEx
!= CdMediaClass_DVDpRW
&&
2124 !(TrackInfoOut
->TrackLength
& 0x80000000) &&
2125 TrackInfoOut
->TrackLength
> 1) {
2126 Vcb
->LastPossibleLBA
=
2127 TrackInfoOut
->TrackStartLBA
+ TrackInfoOut
->TrackLength
- (TrackInfoOut
->TrackLength
? 1 : 0);
2128 KdPrint((" set LastPossibleLBA=%x\n", Vcb
->LastPossibleLBA
));
2130 TrackNumber
= Vcb
->LastTrackNum
;
2131 // quick formatted +RW returns bogus value
2132 if(Vcb
->MediaClassEx
== CdMediaClass_DVDpRW
) {
2133 KdPrint((" check quick formatted +RW\n"));
2134 if(Vcb
->TrackMap
[TrackNumber
].LastLba
&&
2135 !(Vcb
->TrackMap
[TrackNumber
].LastLba
& 0x80000000) &&
2136 Vcb
->TrackMap
[TrackNumber
].LastLba
< Vcb
->LastPossibleLBA
/*&&
2137 Vcb->TrackMap[TrackNumber].LastLba != Vcb->LastPossibleLBA*/
2139 KdPrint((" track LastLBA %x != LastPossibleLBA %x, verify\n",
2140 Vcb
->TrackMap
[TrackNumber
].LastLba
, Vcb
->LastPossibleLBA
));
2142 if(Vcb
->MRWStatus
== DiscInfo_BGF_Complete
) {
2143 KdPrint((" complete MRW state\n"));
2145 Vcb
->LastPossibleLBA
=
2148 Vcb
->TrackMap
[TrackNumber
].LastLba
;
2149 goto valid_track_length
;
2150 #endif // _BROWSE_UDF_
2152 if(Vcb
->MRWStatus
) {
2156 KdPrint((" MRW state %x\n", Vcb
->MRWStatus
));
2158 buff
= (uint8
*)DbgAllocatePoolWithTag(NonPagedPool
, Vcb
->WriteBlockSize
, 'bNWD' );
2162 Vcb
->WriteBlockSize
,
2163 Vcb
->TrackMap
[TrackNumber
].LastLba
+1,
2167 if(!OS_SUCCESS(RC
)) {
2168 KdPrint((" Can't read beyond track LastLBA (%x)\n", Vcb
->TrackMap
[TrackNumber
].LastLba
+1));
2169 Vcb
->LastLBA
= Vcb
->TrackMap
[TrackNumber
].LastLba
;
2170 Vcb
->NWA
= Vcb
->LastLBA
+1;
2171 Vcb
->TrackMap
[TrackNumber
].NWA_V
= 1;
2172 Vcb
->TrackMap
[TrackNumber
].NWA
= Vcb
->NWA
;
2173 Vcb
->TrackMap
[TrackNumber
].LastLba
= Vcb
->LastPossibleLBA
;
2174 RC
= STATUS_SUCCESS
;
2175 goto valid_track_length
;
2180 KdPrint((" set track LastLBA %x\n", Vcb
->LastPossibleLBA
));
2183 Vcb
->TrackMap
[TrackNumber
].LastLba
=
2184 Vcb
->LastPossibleLBA
;
2187 // Test for last empty session
2188 if((Vcb
->TrackMap
[TrackNumber
].Session
!=
2189 Vcb
->TrackMap
[TrackNumber
-1].Session
) &&
2190 (Vcb
->LastSession
> 1)) {
2191 // Note: some devices return negative track length
2192 if((Vcb
->TrackMap
[TrackNumber
].LastLba
<=
2193 Vcb
->TrackMap
[TrackNumber
].FirstLba
) ||
2194 (Vcb
->TrackMap
[TrackNumber
].FirstLba
==
2195 Vcb
->TrackMap
[TrackNumber
].NWA
)) {
2196 // empty last session...
2197 Vcb
->LastTrackNum
--;
2199 /* for(SesNum = Vcb->TrackMap[TrackNumber].Session;
2200 Vcb->TrackMap[TrackNumber].Session == SesNum;
2204 Vcb
->LastSession
= Vcb
->TrackMap
[TrackNumber
-1].Session
;
2208 TrackNumber
= Vcb
->LastTrackNum
;
2210 Vcb
->LastLBA
= min(Vcb
->TrackMap
[TrackNumber
].LastLba
, Vcb
->TrackMap
[TrackNumber
].NWA
);
2211 #endif //_BROWSE_UDF_
2213 if(Vcb
->TrackMap
[TrackNumber
].NWA_V
& TrkInfo_NWA_V
) {
2214 KdPrint((" NWA ok, set LastLBA to min(Last %x, NWA %x\n",
2215 Vcb
->TrackMap
[TrackNumber
].LastLba
,
2216 Vcb
->TrackMap
[TrackNumber
].NWA
));
2217 Vcb
->LastLBA
= min(Vcb
->TrackMap
[TrackNumber
].LastLba
, Vcb
->TrackMap
[TrackNumber
].NWA
);
2219 KdPrint((" no NWA, set LastLBA to Last %x\n", Vcb
->TrackMap
[TrackNumber
].LastLba
));
2220 Vcb
->LastLBA
= Vcb
->TrackMap
[TrackNumber
].LastLba
;
2223 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_TRACKMAP
;
2224 if(!PacketTrack
&& Vcb
->MediaClassEx
!= CdMediaClass_DVDRAM
) {
2225 KdPrint((" disable Raw mount\n"));
2226 Vcb
->VCBFlags
&= ~UDF_VCB_FLAGS_RAW_DISK
;
2232 if(DiscInfo
) MyFreePool__(DiscInfo
);
2233 if(TrackInfoOut
) MyFreePool__(TrackInfoOut
);
2237 } // end UDFReadDiscTrackInfo()
2240 This routine attempts to read disk layout using ReadFullTOC cmd
2243 UDFReadAndProcessFullToc(
2244 PDEVICE_OBJECT DeviceObject
, // the target device object
2248 OSSTATUS RC
= STATUS_SUCCESS
;
2249 PREAD_FULL_TOC_USER_OUT toc
= (PREAD_FULL_TOC_USER_OUT
)MyAllocatePool__(NonPagedPool
,sizeof(READ_FULL_TOC_USER_OUT
) );
2253 uint32 LastLeadOut
= 0;
2254 // BOOLEAN IsMRW = FALSE;
2256 KdPrint(("UDFReadAndProcessFullToc\n"));
2258 if(!toc
) return STATUS_INSUFFICIENT_RESOURCES
;
2259 Vcb
->FirstTrackNum
= 0xFF;
2261 RtlZeroMemory(toc
,sizeof(READ_FULL_TOC_USER_OUT
));
2263 RC
= UDFPhSendIOCTL(IOCTL_CDRW_READ_FULL_TOC
,DeviceObject
,
2265 toc
,sizeof(READ_FULL_TOC_USER_OUT
),
2268 if(!OS_SUCCESS(RC
)) {
2275 Vcb
->PhDeviceType
= FILE_DEVICE_CD_ROM
;
2277 Vcb
->LastSession
= toc
->Sessions
.Last_TrackSes
;
2279 RC
= UDFReallocTrackMap(Vcb
, 0x100);
2280 if(!OS_SUCCESS(RC
)) {
2285 // get LastPossibleLBA
2287 // Note: some drives return Full TOC items unordered.
2288 // So, LeadOut position may come before Track definition.
2289 // In order to handle such situation, we must initialize
2290 // CurTrack when First or Last Track descriptor comes
2291 for (index
=0;(index
<MAXIMUM_NUMBER_OF_SESSIONS
);index
++) {
2292 /* if((toc->SessionData[index].Adr == TOC_ADR_TrackInfo) &&
2293 ((toc->SessionData[index].Control == TOC_CTL_MRWTrackInfo) || (toc->SessionData[index].Control == TOC_CTL_MRWLastSes))) {
2296 if(toc
->SessionData
[index
].Adr
== 1) {
2297 switch (POINT
= toc
->SessionData
[index
].POINT
) {
2298 case POINT_FirstTrackNum
: {
2299 Vcb
->FirstTrackNum
= toc
->SessionData
[index
].Params
.FirstTrackNum
.FirstTrackNum
;
2301 CurTrack
= (uint8
)(Vcb
->FirstTrackNum
);
2304 case POINT_LastTrackNum
: {
2305 Vcb
->LastTrackNum
= toc
->SessionData
[index
].Params
.LastTrackNum
.LastTrackNum
;
2306 if(CurTrack
< Vcb
->LastTrackNum
)
2307 CurTrack
= (uint8
)(Vcb
->FirstTrackNum
);
2310 case POINT_StartPositionOfLeadOut
: {
2311 #define TempMSF toc->SessionData[index].Params.StartPositionOfLeadOut.MSF
2312 Vcb
->TrackMap
[CurTrack
].LastLba
= MSF_TO_LBA(TempMSF
[0],TempMSF
[1],TempMSF
[2]);
2313 LastLeadOut
= max(LastLeadOut
, Vcb
->TrackMap
[CurTrack
].LastLba
);
2318 if( (Vcb
->FirstTrackNum
!= 0x0FF) &&
2319 (toc
->SessionData
[index
].POINT
== Vcb
->FirstTrackNum
) ) {
2320 #define TempMSF toc->SessionData[index].Params.StartPositionOfTrack.MSF
2321 Vcb
->FirstLBA
= MSF_TO_LBA(TempMSF
[0],TempMSF
[1],TempMSF
[2]);
2322 if(Vcb
->FirstLBA
& 0x80000000) {
2330 if((POINT
>= POINT_StartPositionOfTrack_Min
) &&
2331 (POINT
<= POINT_StartPositionOfTrack_Max
)) {
2332 #define TempMSF toc->SessionData[index].Params.StartPositionOfTrack.MSF
2333 Vcb
->TrackMap
[POINT
].FirstLba
= MSF_TO_LBA(TempMSF
[0],TempMSF
[1],TempMSF
[2])-1;
2334 if(Vcb
->TrackMap
[POINT
].FirstLba
& 0x80000000) {
2336 Vcb
->TrackMap
[POINT
].FirstLba
= 0;
2338 if(Vcb
->TrackMap
[POINT
-1].LastLba
) {
2339 Vcb
->TrackMap
[POINT
].FirstLba
= Vcb
->TrackMap
[POINT
-1].LastLba
+1;
2344 if(POINT
> POINT_StartPositionOfTrack_Min
) {
2345 Vcb
->TrackMap
[POINT
-1].LastLba
= Vcb
->TrackMap
[POINT
].FirstLba
-1;
2350 if(toc
->SessionData
[index
].Adr
== 5) {
2351 switch (POINT
= toc
->SessionData
[index
].POINT
) {
2352 case POINT_StartPositionOfNextProgramArea
: {
2353 #define TempMSF toc->SessionData[index].Params.StartPositionOfNextProgramArea.MaxLeadOut_MSF
2354 Vcb
->LastPossibleLBA
= MSF_TO_LBA(TempMSF
[0],TempMSF
[1],TempMSF
[2]);
2367 KdPrint(("No MRW\n"));
2368 Vcb->CompatFlags &= ~UDF_VCB_IC_MRW_ADDR_PROBLEM;
2370 // Vcb->CompatFlags &= ~UDF_VCB_IC_MRW_ADDR_PROBLEM;
2371 // some devices report LastTrackNum=0 for full disks
2372 Vcb
->LastTrackNum
= max(Vcb
->LastTrackNum
, Vcb
->FirstTrackNum
);
2373 Vcb
->TrackMap
[Vcb
->LastTrackNum
].LastLba
= max(LastLeadOut
, Vcb
->TrackMap
[Vcb
->LastTrackNum
].LastLba
);
2375 Vcb
->LastLBA
= Vcb
->TrackMap
[Vcb
->LastTrackNum
].LastLba
;
2378 // Vcb->LastLBA=PacketVariable2Fixed(Vcb->LastLBA)-2;
2379 return STATUS_SUCCESS
;
2380 } // end UDFReadAndProcessFullToc()
2383 use standard way to determine disk layout (ReadTOC cmd)
2387 PDEVICE_OBJECT DeviceObject
, // the target device object
2388 PVCB Vcb
// Volume control block from this DevObj
2391 OSSTATUS RC
= STATUS_SUCCESS
;
2392 PREAD_TOC_USER_OUT toc
= (PREAD_TOC_USER_OUT
)MyAllocatePool__(NonPagedPool
,max(Vcb
->BlockSize
, sizeof(READ_TOC_USER_OUT
)) );
2393 PGET_LAST_SESSION_USER_OUT LastSes
= (PGET_LAST_SESSION_USER_OUT
)MyAllocatePool__(NonPagedPool
,sizeof(GET_LAST_SESSION_USER_OUT
) );
2394 uint32 LocalTrackCount
;
2395 // uint32 LocalTocLength;
2400 uint32 ReadBytes
, i
, len
;
2401 #endif //_BROWSE_UDF_
2402 #ifdef UDF_FORMAT_MEDIA
2403 PUDFFmtState fms
= Vcb
->fms
;
2406 #endif //UDF_FORMAT_MEDIA
2408 KdPrint(("UDFUseStandard\n"));
2412 if(!toc
|| !LastSes
) {
2413 try_return (RC
= STATUS_INSUFFICIENT_RESOURCES
);
2415 RtlZeroMemory(toc
,sizeof(READ_TOC_TOC
));
2417 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_USE_STD
;
2419 RC
= UDFPhSendIOCTL(IOCTL_CDROM_READ_TOC
,DeviceObject
,
2420 toc
,sizeof(READ_TOC_USER_OUT
),
2421 toc
,sizeof(READ_TOC_USER_OUT
),
2424 if((RC
== STATUS_DEVICE_NOT_READY
) || (RC
== STATUS_NO_MEDIA_IN_DEVICE
)) {
2427 #ifdef UDF_FORMAT_MEDIA
2428 if(fms
->opt_media
== MT_none
) {
2429 try_return(RC
= STATUS_NO_MEDIA_IN_DEVICE
);
2431 #endif //UDF_FORMAT_MEDIA
2433 // If even standard read toc does not work, then use default values
2434 if(!OS_SUCCESS(RC
)) {
2436 RC
= UDFReallocTrackMap(Vcb
, 2);
2437 if(!OS_SUCCESS(RC
)) {
2442 Vcb
->FirstTrackNum
=1;
2444 Vcb
->LastTrackNum
=1;
2445 Vcb
->TrackMap
[1].FirstLba
= Vcb
->FirstLBA
;
2446 Vcb
->TrackMap
[1].LastLba
= Vcb
->LastLBA
;
2447 Vcb
->TrackMap
[1].PacketSize
= PACKETSIZE_UDF
;
2448 #ifdef UDF_FORMAT_MEDIA
2450 #endif //UDF_FORMAT_MEDIA
2453 #ifdef UDF_HDD_SUPPORT
2454 if(UDFGetDevType(DeviceObject
) == FILE_DEVICE_DISK
) {
2455 try_return(RC
= STATUS_SUCCESS
);
2457 #endif //UDF_HDD_SUPPORT
2458 #endif //_BROWSE_UDF_
2460 #ifdef UDF_FORMAT_MEDIA
2463 if(fms
->opt_media
== MT_HD
) {
2464 Vcb
->LastPossibleLBA
= Vcb
->LastLBA
;
2465 try_return(RC
= STATUS_SUCCESS
);
2468 #endif //UDF_FORMAT_MEDIA
2469 Vcb
->LastPossibleLBA
= max(Vcb
->LastLBA
, DEFAULT_LAST_LBA_FP_CD
);
2470 Vcb
->TrackMap
[1].DataParam
= TrkInfo_Dat_XA
| TrkInfo_FP
| TrkInfo_Packet
;
2471 Vcb
->TrackMap
[1].TrackParam
= TrkInfo_Trk_XA
;
2472 Vcb
->TrackMap
[1].NWA
= 0xffffffff;
2473 Vcb
->NWA
= DEFAULT_LAST_LBA_FP_CD
+ 7 + 1;
2474 try_return(RC
= STATUS_SUCCESS
);
2478 Vcb
->PhDeviceType
= FILE_DEVICE_CD_ROM
;
2481 LocalTrackCount
= toc
->Tracks
.Last_TrackSes
- toc
->Tracks
.First_TrackSes
+ 1;
2482 // LocalTocLength = PtrOffset( toc, &(toc->TrackData[LocalTrackCount + 1]) ); /* FIXME ReactOS Assume PtrOffset is not changing it's arguments? */
2484 // Get out if there is an immediate problem with the TOC.
2485 if(toc
->Tracks
.First_TrackSes
> toc
->Tracks
.Last_TrackSes
) {
2486 try_return(RC
= STATUS_DISK_CORRUPT_ERROR
);
2490 Vcb
->LastTrackNum
=toc
->Tracks
.Last_TrackSes
;
2491 Vcb
->FirstTrackNum
=toc
->Tracks
.First_TrackSes
;
2492 // some devices report LastTrackNum=0 for full disks
2493 Vcb
->LastTrackNum
= max(Vcb
->LastTrackNum
, Vcb
->FirstTrackNum
);
2495 RC
= UDFReallocTrackMap(Vcb
, MAXIMUM_NUMBER_OF_TRACKS
+1);
2496 /* if(Vcb->TrackMap) {
2497 MyFreePool__(Vcb->TrackMap);
2498 Vcb->TrackMap = NULL;
2500 Vcb->TrackMap = (PUDFTrackMap)
2501 MyAllocatePool__(NonPagedPool, (MAXIMUM_NUMBER_OF_TRACKS+1)*sizeof(UDFTrackMap));
2502 if(!Vcb->TrackMap) {
2504 return STATUS_INSUFFICIENT_RESOURCES;
2506 RtlZeroMemory(Vcb->TrackMap,(MAXIMUM_NUMBER_OF_TRACKS+1)*sizeof(UDFTrackMap));
2508 if(!OS_SUCCESS(RC
)) {
2512 // find 1st and last session
2513 RC
= UDFPhSendIOCTL(IOCTL_CDROM_GET_LAST_SESSION
,DeviceObject
,
2514 LastSes
,sizeof(GET_LAST_SESSION_USER_OUT
),
2515 LastSes
,sizeof(GET_LAST_SESSION_USER_OUT
),
2518 if(OS_SUCCESS(RC
)) {
2519 TrkNum
= LastSes
->LastSes_1stTrack
.TrackNum
;
2520 Vcb
->LastSession
= LastSes
->Sessions
.First_TrackSes
;
2521 for(TocEntry
=0;TocEntry
<LocalTrackCount
+ 1;TocEntry
++) {
2522 if(toc
->TrackData
[TocEntry
].TrackNum
== TrkNum
) {
2523 Vcb
->TrackMap
[TrkNum
].Session
= Vcb
->LastSession
;
2529 // Scan toc for first & last LBA
2530 for(TocEntry
=0;TocEntry
<LocalTrackCount
+ 1;TocEntry
++) {
2531 #define TempMSF toc->TrackData[TocEntry].LBA
2532 TrkNum
= toc
->TrackData
[TocEntry
].TrackNum
;
2534 if (TrkNum
>= MAXIMUM_NUMBER_OF_TRACKS
&&
2535 TrkNum
!= TOC_LastTrack_ID
) {
2536 KdPrint(("UDFUseStandard: Array out of bounds\n"));
2538 try_return(RC
= STATUS_SUCCESS
);
2540 KdPrint(("Track N %d (0x%x) first LBA %ld (%lx) \n",TrkNum
,TrkNum
,
2541 MSF_TO_LBA(TempMSF
[1],TempMSF
[2],TempMSF
[3]),
2542 MSF_TO_LBA(TempMSF
[1],TempMSF
[2],TempMSF
[3])));
2544 if(Vcb
->FirstTrackNum
== TrkNum
) {
2545 Vcb
->FirstLBA
= MSF_TO_LBA(TempMSF
[1],TempMSF
[2],TempMSF
[3]);
2546 if(Vcb
->FirstLBA
& 0x80000000) {
2550 if(TOC_LastTrack_ID
== TrkNum
) {
2551 Vcb
->LastLBA
= MSF_TO_LBA(TempMSF
[1],TempMSF
[2],TempMSF
[3])-1;
2552 Vcb
->TrackMap
[OldTrkNum
].LastLba
= Vcb
->LastLBA
-1;
2553 KdPrint(("UDFUseStandard: Last track entry, break TOC scan\n"));
2557 Vcb
->TrackMap
[TrkNum
].FirstLba
= MSF_TO_LBA(TempMSF
[1],TempMSF
[2],TempMSF
[3]);
2558 if(Vcb
->TrackMap
[TrkNum
].FirstLba
& 0x80000000)
2559 Vcb
->TrackMap
[TrkNum
].FirstLba
= 0;
2561 if (TOC_LastTrack_ID
== OldTrkNum
) {
2562 KdPrint(("UDFUseStandard: Wrong previous track number\n"));
2565 Vcb
->TrackMap
[OldTrkNum
].LastLba
= Vcb
->TrackMap
[TrkNum
].FirstLba
-1;
2570 switch(toc
->TrackData
[TocEntry
].Control
& TocControl_TrkMode_Mask
) {
2571 case TocControl_TrkMode_Data
:
2572 case TocControl_TrkMode_IncrData
:
2573 Vcb
->TrackMap
[TrkNum
].DataParam
= TrkInfo_Dat_XA
;
2574 Vcb
->TrackMap
[TrkNum
].TrackParam
= TrkInfo_Trk_XA
;
2577 Vcb
->TrackMap
[TrkNum
].DataParam
= TrkInfo_Dat_unknown
;
2578 Vcb
->TrackMap
[TrkNum
].TrackParam
= TrkInfo_Trk_unknown
;
2584 TrkNum
= Vcb
->LastTrackNum
;
2585 RC
= STATUS_SUCCESS
;
2586 // find last _valid_ track
2587 for(;TrkNum
;TrkNum
--) {
2588 if((Vcb
->TrackMap
[TrkNum
].DataParam
!= TrkInfo_Dat_unknown
) &&
2589 (Vcb
->TrackMap
[TrkNum
].TrackParam
!= TrkInfo_Trk_unknown
)) {
2590 RC
= STATUS_UNSUCCESSFUL
;
2591 Vcb
->LastTrackNum
= TrkNum
;
2595 // no valid tracks...
2597 KdPrint(("UDFUseStandard: no valid tracks...\n"));
2598 try_return(RC
= STATUS_UNRECOGNIZED_VOLUME
);
2602 // Check for last VP track. Some last sectors may belong to Link-data &
2603 // be unreadable. We should forget about them, because UDF needs
2604 // last _readable_ sector.
2605 while(!OS_SUCCESS(RC
) && (i
<8)) {
2606 RC
= UDFPhReadSynchronous(Vcb
->TargetDeviceObject
, (int8
*)toc
, Vcb
->BlockSize
,
2607 ((uint64
)(Vcb
->TrackMap
[TrkNum
].LastLba
-i
)) << Vcb
->BlockSizeBits
, &ReadBytes
, PH_TMP_BUFFER
);
2610 if(OS_SUCCESS(RC
)) {
2611 Vcb
->LastLBA
= Vcb
->TrackMap
[TrkNum
].LastLba
-i
+1;
2613 Vcb->TrackMap[TrkNum].PacketSize = PACKETSIZE_UDF;
2614 Vcb->TrackMap[TrkNum].;
2618 // Check for FP track. READ_TOC reports actual track length, but
2619 // Link-data is hidden & unreadable for us. So, available track
2620 // length may be less than actual. Here we assume that Packet-size
2621 // is PACKETSIZE_UDF.
2623 len
= Vcb
->TrackMap
[TrkNum
].LastLba
- Vcb
->TrackMap
[TrkNum
].FirstLba
+ 1;
2624 len
= (uint32
)(((int64
)len
*PACKETSIZE_UDF
) / (PACKETSIZE_UDF
+7));
2626 while(!OS_SUCCESS(RC
) && (i
<9)) {
2627 RC
= UDFPhReadSynchronous(Vcb
->TargetDeviceObject
, (int8
*)toc
, Vcb
->BlockSize
,
2628 ((uint64
)(Vcb
->TrackMap
[TrkNum
].FirstLba
-i
+len
)) << Vcb
->BlockSizeBits
, &ReadBytes
, PH_TMP_BUFFER
);
2631 if(OS_SUCCESS(RC
)) {
2633 Vcb
->TrackMap
[TrkNum
].LastLba
= Vcb
->TrackMap
[TrkNum
].FirstLba
-i
+len
+1;
2634 Vcb
->TrackMap
[TrkNum
].PacketSize
= PACKETSIZE_UDF
;
2635 // Vcb->TrackMap[TrkNum].;
2637 if(RC
== STATUS_INVALID_DEVICE_REQUEST
) {
2638 // wrap return code from Audio-disk
2639 RC
= STATUS_SUCCESS
;
2643 #ifdef UDF_CDRW_EMULATION_ON_ROM
2644 Vcb
->LastPossibleLBA
= Vcb
->LastLBA
+7+1+1024;
2645 Vcb
->NWA
= Vcb
->LastLBA
+7+1;
2647 Vcb
->LastPossibleLBA
=
2648 Vcb
->NWA
= Vcb
->LastLBA
+7+1;
2649 #endif //UDF_CDRW_EMULATION_ON_ROM
2651 #else //_BROWSE_UDF_
2653 Vcb
->FirstTrackNum
=toc
->Tracks
.Last_TrackSes
;
2654 Vcb
->LastTrackNum
=toc
->Tracks
.First_TrackSes
;
2656 // Scan toc for first & last LBA
2657 for(TocEntry
=0;TocEntry
<LocalTrackCount
+ 1;TocEntry
++) {
2658 #define TempMSF toc->TrackData[TocEntry].LBA
2659 if(Vcb
->FirstTrackNum
== toc
->TrackData
[TocEntry
].TrackNum
) {
2660 Vcb
->FirstLBA
= MSF_TO_LBA(TempMSF
[1],TempMSF
[2],TempMSF
[3]);
2661 if(Vcb
->FirstLBA
& 0x80000000) {
2665 if(TOC_LastTrack_ID
== toc
->TrackData
[TocEntry
].TrackNum
) {
2666 Vcb
->LastLBA
= MSF_TO_LBA(TempMSF
[1],TempMSF
[2],TempMSF
[3])-1;
2671 // Vcb->LastLBA=PacketVariable2Fixed(Vcb->LastLBA)-2;
2672 Vcb
->LastPossibleLBA
= DEFAULT_LAST_LBA_FP_CD
;
2673 #endif //_BROWSE_UDF_
2676 if(toc
) MyFreePool__(toc
);
2677 if(LastSes
) MyFreePool__(LastSes
);
2681 } // end UDFUseStandard()
2684 Get block size (for read operation)
2688 IN PDEVICE_OBJECT DeviceObject
, // the target device object
2689 IN PVCB Vcb
// Volume control block from this DevObj
2692 OSSTATUS RC
= STATUS_SUCCESS
;
2693 PDISK_GEOMETRY DiskGeometry
= (PDISK_GEOMETRY
)MyAllocatePool__(NonPagedPool
,sizeof(DISK_GEOMETRY
));
2694 PPARTITION_INFORMATION PartitionInfo
= (PPARTITION_INFORMATION
)MyAllocatePool__(NonPagedPool
,sizeof(PARTITION_INFORMATION
)*2);
2695 #ifdef UDF_FORMAT_MEDIA
2696 PUDFFmtState fms
= Vcb
->fms
;
2699 #endif //UDF_FORMAT_MEDIA
2701 if(!DiskGeometry
|| !PartitionInfo
)
2702 try_return (RC
= STATUS_INSUFFICIENT_RESOURCES
);
2706 #ifdef UDF_HDD_SUPPORT
2708 if(UDFGetDevType(DeviceObject
) == FILE_DEVICE_DISK
) {
2709 KdPrint(("UDFGetBlockSize: HDD\n"));
2710 RC
= UDFPhSendIOCTL(IOCTL_DISK_GET_DRIVE_GEOMETRY
,DeviceObject
,
2712 DiskGeometry
,sizeof(DISK_GEOMETRY
),
2714 Vcb
->BlockSize
= (OS_SUCCESS(RC
)) ? DiskGeometry
->BytesPerSector
: 512;
2717 RC
= UDFPhSendIOCTL(IOCTL_DISK_GET_PARTITION_INFO
,DeviceObject
,
2719 PartitionInfo
,sizeof(PARTITION_INFORMATION
),
2721 if(!NT_SUCCESS(RC
)) {
2722 KdPrint(("UDFGetBlockSize: IOCTL_DISK_GET_PARTITION_INFO failed\n"));
2723 if(RC
== STATUS_INVALID_DEVICE_REQUEST
) /* ReactOS Code Change (was =) */
2724 RC
= STATUS_UNRECOGNIZED_VOLUME
;
2727 if(PartitionInfo
->PartitionType
!= PARTITION_IFS
) {
2728 KdPrint(("UDFGetBlockSize: PartitionInfo->PartitionType != PARTITION_IFS\n"));
2729 try_return(RC
= STATUS_UNRECOGNIZED_VOLUME
);
2732 #endif //UDF_HDD_SUPPORT
2733 RC
= UDFPhSendIOCTL(IOCTL_CDROM_GET_DRIVE_GEOMETRY
,DeviceObject
,
2734 DiskGeometry
,sizeof(DISK_GEOMETRY
),
2735 DiskGeometry
,sizeof(DISK_GEOMETRY
),
2738 if(RC
== STATUS_DEVICE_NOT_READY
) {
2739 // probably, the device is really busy, may be by CD/DVD recording
2740 UserPrint((" busy (0)\n"));
2744 Vcb
->BlockSize
= (OS_SUCCESS(RC
)) ? DiskGeometry
->BytesPerSector
: 2048;
2745 #ifdef UDF_HDD_SUPPORT
2748 #endif //UDF_HDD_SUPPORT
2750 #endif //_BROWSE_UDF_
2752 #ifdef UDF_FORMAT_MEDIA
2754 RC
= UDFPhSendIOCTL(IOCTL_CDROM_GET_DRIVE_GEOMETRY
,DeviceObject
,
2755 DiskGeometry
,sizeof(DISK_GEOMETRY
),
2756 DiskGeometry
,sizeof(DISK_GEOMETRY
),
2759 if(!NT_SUCCESS(RC
)) {
2760 RC
= UDFPhSendIOCTL(IOCTL_DISK_GET_DRIVE_GEOMETRY
,DeviceObject
,
2761 DiskGeometry
,sizeof(DISK_GEOMETRY
),
2762 DiskGeometry
,sizeof(DISK_GEOMETRY
),
2764 if(NT_SUCCESS(RC
)) {
2765 fms
->opt_media
= MT_HD
;
2766 RC
= UDFPhSendIOCTL(IOCTL_DISK_GET_PARTITION_INFO
,DeviceObject
,
2768 PartitionInfo
,sizeof(PARTITION_INFORMATION
)*2,
2770 if(!NT_SUCCESS(RC
)) {
2772 RC
= SetFilePointer(DeviceObject
->h
,0,&HiOffs
,FILE_END
);
2777 if(RC
== STATUS_DEVICE_NOT_READY
) {
2778 // probably, the device is really busy, may be by CD/DVD recording
2779 UserPrint((" busy\n"));
2783 Vcb
->BlockSize
= (NT_SUCCESS(RC
)) ? DiskGeometry
->BytesPerSector
: 2048;
2785 #endif //UDF_FORMAT_MEDIA
2787 // Block size must be an even multiple of 512
2788 switch (Vcb
->BlockSize
) {
2789 case 2048: Vcb
->BlockSizeBits
= 11; break;
2790 #ifdef UDF_HDD_SUPPORT
2791 case 512: Vcb
->BlockSizeBits
= 9; break;
2792 case 1024: Vcb
->BlockSizeBits
= 10; break;
2793 case 4096: Vcb
->BlockSizeBits
= 12; break;
2794 case 8192: Vcb
->BlockSizeBits
= 13; break;
2795 #endif //UDF_HDD_SUPPORT
2798 UserPrint(("UDF: Bad block size (%ld)\n", Vcb
->BlockSize
));
2799 try_return(RC
= STATUS_UNSUCCESSFUL
);
2803 #ifdef UDF_HDD_SUPPORT
2806 (!fms
&& (UDFGetDevType(DeviceObject
) == FILE_DEVICE_DISK
))
2808 #endif //_BROWSE_UDF_
2809 #ifdef UDF_FORMAT_MEDIA
2810 (fms
&& fms
->opt_media
== MT_HD
)
2812 #endif //UDF_FORMAT_MEDIA
2815 #ifdef UDF_FORMAT_MEDIA
2816 if(fms
&& !NT_SUCCESS(RC
))
2817 try_return(STATUS_UNSUCCESSFUL
);
2818 #endif //UDF_FORMAT_MEDIA
2820 Vcb
->FirstLBA
=0;//(ULONG)(PartitionInfo->StartingOffset.QuadPart >> Vcb->BlockSizeBits);
2821 Vcb
->LastPossibleLBA
=
2822 Vcb
->LastLBA
= (uint32
)(PartitionInfo
->PartitionLength
.QuadPart
>> Vcb
->BlockSizeBits
)/* + Vcb->FirstLBA*/ - 1;
2824 #endif //UDF_HDD_SUPPORT
2826 if(OS_SUCCESS(RC
)) {
2827 Vcb
->LastLBA
= (uint32
)(DiskGeometry
->Cylinders
.QuadPart
*
2828 DiskGeometry
->TracksPerCylinder
*
2829 DiskGeometry
->SectorsPerTrack
- 1);
2830 if(Vcb
->LastLBA
== 0x7fffffff) {
2831 Vcb
->LastLBA
= UDFIsDvdMedia(Vcb
) ? DEFAULT_LAST_LBA_DVD
: DEFAULT_LAST_LBA_FP_CD
;
2834 Vcb
->LastLBA
= UDFIsDvdMedia(Vcb
) ? DEFAULT_LAST_LBA_DVD
: DEFAULT_LAST_LBA_FP_CD
;
2836 Vcb
->LastPossibleLBA
= Vcb
->LastLBA
;
2837 #ifdef UDF_HDD_SUPPORT
2839 #endif //UDF_HDD_SUPPORT
2842 // if(UDFGetDevType(DeviceObject) == FILE_DEVICE_DISK) {
2843 Vcb
->WriteBlockSize
= PACKETSIZE_UDF
*Vcb
->BlockSize
;
2845 // Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->BlockSize;
2847 #else //_BROWSE_UDF_
2848 if(fms
->opt_media
== MT_HD
) {
2849 Vcb
->WriteBlockSize
= Vcb
->BlockSize
;
2851 Vcb
->WriteBlockSize
= PACKETSIZE_UDF
*Vcb
->BlockSize
;
2853 #endif //_BROWSE_UDF_
2855 RC
= STATUS_SUCCESS
;
2859 KdPrint(("UDFGetBlockSize:\nBlock size is %x, Block size bits %x, Last LBA is %x\n",
2860 Vcb
->BlockSize
, Vcb
->BlockSizeBits
, Vcb
->LastLBA
));
2862 MyFreePool__(PartitionInfo
);
2863 MyFreePool__(DiskGeometry
);
2866 } // end UDFGetBlockSize()
2871 UDFCheckTrackFPAddressing(
2872 // IN PDEVICE_OBJECT DeviceObject, // the target device object
2873 IN PVCB Vcb
, // Volume control block from this DevObj
2877 OSSTATUS RC
= STATUS_SUCCESS
;
2878 // OSSTATUS RC2 = STATUS_UNSUCCESSFUL;
2882 // uint32 ReadBytes;
2886 ULONG FirstChunkLen
= 0;
2888 ULONG NextChunkLen
= 0;
2889 ULONG NextChunkLenCount
= 0;
2891 ULONG NextChunkLenOth
= 0;
2892 ULONG NextChunkLenOthCount
= 0;
2893 // ULONG MRW_Offset = 0;
2895 PLL_READ_USER_IN pLLR_in
;
2896 PCD_SECTOR_HEADER pHdr
;
2897 /* uint8 cMSF[3] = {0,2,0};
2898 uint8 cMSF1[3] = {0,2,1};*/
2901 if(!Vcb
->TrackMap
) {
2902 Vcb
->CompatFlags
&= ~UDF_VCB_IC_FP_ADDR_PROBLEM
;
2903 return STATUS_SUCCESS
;
2906 Buffer
= (uint8
*)DbgAllocatePoolWithTag(NonPagedPool
, max(Vcb
->BlockSize
,
2907 sizeof(LL_READ_USER_IN
)+16), 'pNWD');
2909 return STATUS_INSUFFICIENT_RESOURCES
;
2910 pLLR_in
= (PLL_READ_USER_IN
)Buffer
;
2911 pHdr
= (PCD_SECTOR_HEADER
)(Buffer
+sizeof(LL_READ_USER_IN
));
2913 /* if(Vcb->CompatFlags & UDF_VCB_IC_MRW_ADDR_PROBLEM) {
2914 MRW_Offset = (MRW_DMA_OFFSET/32)*39;
2918 for(i
=0; i
<=0x200; i
++) {
2920 RtlZeroMemory(pLLR_in
, sizeof(pLLR_in
)+16);
2921 pLLR_in
->ExpectedBlkType
= ReadCd_BlkType_Any
;
2923 pLLR_in
->NumOfBlocks
= 1;
2924 pLLR_in
->Flags
.Flags
= ReadCd_Header_Hdr
;
2925 // pLLR_in->UseMFS = FALSE; // already zero
2926 // MOV_MSF(pLLR_in->Starting_MSF, cMSF);
2927 // MOV_MSF(pLLR_in->Ending_MSF, cMSF1);
2928 RtlZeroMemory(pHdr
, sizeof(CD_SECTOR_HEADER
));
2929 RC
= UDFPhSendIOCTL(IOCTL_CDRW_LL_READ
, Vcb
->TargetDeviceObject
,
2930 pLLR_in
, sizeof(LL_READ_USER_IN
),
2931 pHdr
, sizeof(CD_SECTOR_HEADER
),
2934 /* RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, Buffer, Vcb->BlockSize,
2935 ((uint64)(i+MRW_Offset)) << Vcb->BlockSizeBits, &ReadBytes, 0);*/
2938 if(!OS_SUCCESS(RC
)) {
2939 KdPrint((" Read error at lba %x\n", i
));
2943 // skip strange (damaged ?) blocks
2944 if((pHdr
->Mode
.Flags
& WParam_SubHdr_Mode_Mask
) != WParam_SubHdr_Mode1
&&
2945 (pHdr
->Mode
.Flags
& WParam_SubHdr_Mode_Mask
) != WParam_SubHdr_Mode2
) {
2946 KdPrint((" Unexpected data type (%x) at lba %x\n", pHdr
->Mode
.Flags
& WParam_SubHdr_Mode_Mask
, i
));
2950 if((pHdr
->Mode
.Flags
& WParam_SubHdr_Format_Mask
) == WParam_SubHdr_Format_UserData
&&
2955 /* if(OS_SUCCESS(RC) && !OS_SUCCESS(RC2)) {
2959 if((pHdr
->Mode
.Flags
& WParam_SubHdr_Format_Mask
) != WParam_SubHdr_Format_UserData
&&
2961 // if(!OS_SUCCESS(RC) && OS_SUCCESS(RC2)) {
2962 KdPrint((" %x - %x (%x sectors)\n", lba
, i
-1, i
-lba
));
2963 if(!FirstChunkLen
) {
2964 FirstChunkLen
= i
-lba
;
2967 NextChunkLen
= i
-lba
;
2968 NextChunkLenCount
++;
2970 if(NextChunkLen
== i
-lba
) {
2971 NextChunkLenCount
++;
2973 if((NextChunkLenOth
+1) % (NextChunkLen
+1)) {
2974 NextChunkLenOth
= i
-lba
;
2975 NextChunkLenOthCount
++;
2977 NextChunkLenCount
++;
2983 user_data
= ((pHdr
->Mode
.Flags
& WParam_SubHdr_Format_Mask
) == WParam_SubHdr_Format_UserData
);
2987 DbgFreePool(Buffer
);
2989 if(!NextChunkLenCount
&& !NextChunkLenOthCount
) {
2990 Vcb
->CompatFlags
&= ~UDF_VCB_IC_FP_ADDR_PROBLEM
;
2991 return STATUS_SUCCESS
;
2993 if(NextChunkLenOthCount
> NextChunkLenCount
) {
2994 NextChunkLen
= NextChunkLenOth
;
2996 if(NextChunkLen
> PACKETSIZE_UDF
+7) {
2997 Vcb
->CompatFlags
&= ~UDF_VCB_IC_FP_ADDR_PROBLEM
;
2998 return STATUS_SUCCESS
;
3000 Vcb
->TrackMap
[TrackNum
].DataParam
&= ~TrkInfo_Dat_Mask
;
3001 Vcb
->TrackMap
[TrackNum
].DataParam
|= TrkInfo_Dat_XA
;
3002 Vcb
->TrackMap
[TrackNum
].Flags
|= TrackMap_FixFPAddressing
;
3003 Vcb
->TrackMap
[TrackNum
].PacketSize
= 1;
3004 while(NextChunkLen
>> Vcb
->TrackMap
[TrackNum
].PacketSize
) {
3005 Vcb
->TrackMap
[TrackNum
].PacketSize
++;
3007 Vcb
->TrackMap
[TrackNum
].PacketSize
= 1 << (Vcb
->TrackMap
[TrackNum
].PacketSize
-1);
3008 Vcb
->TrackMap
[TrackNum
].TrackFPOffset
= NextChunkLen
- FirstChunkLen
; // !!!!!
3009 Vcb
->TrackMap
[TrackNum
].PacketFPOffset
= Vcb
->TrackMap
[TrackNum
].TrackFPOffset
;//0;//NextChunkLenOth - FirstChunkLen;
3010 Vcb
->TrackMap
[TrackNum
].LastLba
= (Vcb
->TrackMap
[TrackNum
].LastLba
*Vcb
->TrackMap
[TrackNum
].PacketSize
) /
3011 (Vcb
->TrackMap
[TrackNum
].PacketSize
+ 7);
3013 return STATUS_SUCCESS
;
3014 } // end UDFCheckTrackFPAddressing()
3018 IN PVCB Vcb
, // Volume control block from this DevObj
3022 uint32 i
= Vcb
->LastReadTrack
;
3026 // if(Vcb->CompatFlags & UDF_VCB_IC_MRW_ADDR_PROBLEM) {
3027 if(Vcb
->TrackMap
[i
].Flags
& TrackMap_FixMRWAddressing
) {
3028 pk
= Lba
/ MRW_DA_SIZE
;
3029 rel
= Lba
% MRW_DA_SIZE
;
3030 Lba
= pk
*MRW_DMA_SEGMENT_SIZE
+ rel
;
3031 Lba
+= MRW_DMA_OFFSET
;
3033 if(Vcb
->TrackMap
[i
].Flags
& TrackMap_FixFPAddressing
) {
3036 pk
= Lba
/ Vcb
->TrackMap
[i
].PacketSize
;
3037 rel
= Lba
% Vcb
->TrackMap
[i
].PacketSize
;
3038 KdPrint(("FixFPAddr: %x -> %x\n", Lba
, pk
*(Vcb
->TrackMap
[i
].PacketSize
+7) + rel
));
3039 return pk
*(Vcb
->TrackMap
[i
].PacketSize
+7) + rel
/*- Vcb->TrackMap[i].PacketFPOffset*/;
3042 } // end UDFFixFPAddress()
3044 #endif //_BROWSE_UDF_
3047 detect device driver & try to read disk layout (use all methods)
3051 IN PDEVICE_OBJECT DeviceObject
, // the target device object
3052 IN PVCB Vcb
// Volume control block from this DevObj
3055 OSSTATUS RC
= STATUS_UNRECOGNIZED_VOLUME
;
3056 int8
* ioBuf
= (int8
*)MyAllocatePool__(NonPagedPool
,4096);
3058 PLUN_WRITE_PERF_DESC_USER WPerfDesc
;
3060 // BOOLEAN MRW_problem = FALSE;
3061 uint32 SavedFeatures
= 0;
3062 #ifdef UDF_FORMAT_MEDIA
3063 PUDFFmtState fms
= Vcb
->fms
;
3066 #endif //UDF_FORMAT_MEDIA
3068 KdPrint(("UDFGetDiskInfo\n"));
3071 return STATUS_INSUFFICIENT_RESOURCES
;
3075 RC
= UDFGetBlockSize(DeviceObject
, Vcb
);
3076 if(!OS_SUCCESS(RC
)) try_return(RC
);
3079 // Get lower driver signature
3080 RC
= UDFPhSendIOCTL(IOCTL_CDRW_GET_SIGNATURE
,DeviceObject
,
3081 ioBuf
,sizeof(GET_SIGNATURE_USER_OUT
),
3082 ioBuf
,sizeof(GET_SIGNATURE_USER_OUT
),
3085 if(!OS_SUCCESS(RC
)) {
3087 RC
= UDFUseStandard(DeviceObject
, Vcb
);
3089 if(!NT_SUCCESS(RC
) || fms
)
3092 // assume Device Recordable for now
3093 goto GetSignatureFailed
;
3094 #endif //_BROWSE_UDF_
3097 KdPrint(("UDF: Signature of low driver is : %s \n",
3098 ((PGET_SIGNATURE_USER_OUT
)(ioBuf
))->VendorId
));
3100 if(!strncmp( (const char *)(&( ((PGET_SIGNATURE_USER_OUT
)(ioBuf
))->VendorId
[0]) ),
3101 Signature
,strlen(Signature
) )) {
3102 KdPrint(("UDF: *****************************************\n"));
3103 KdPrint(("UDF: ********* Our Device Driver Found ******\n"));
3104 KdPrint(("UDF: *****************************************\n"));
3106 (Vcb
->VCBFlags
) |= UDF_VCB_FLAGS_OUR_DEVICE_DRIVER
;
3107 #ifndef _BROWSE_UDF_
3109 #ifdef UDF_FORMAT_MEDIA
3110 if(!fms
->opt_probe
) {
3111 #endif //UDF_FORMAT_MEDIA
3112 UDFResetDeviceDriver(Vcb
, Vcb
->TargetDeviceObject
, FALSE
);
3114 ((PPREVENT_MEDIA_REMOVAL_USER_IN
)(ioBuf
))->PreventMediaRemoval
= TRUE
;
3115 UDFPhSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL
,
3117 ioBuf
,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN
),
3120 #ifdef UDF_FORMAT_MEDIA
3122 #endif //UDF_FORMAT_MEDIA
3123 #endif //_BROWSE_UDF_
3124 //#else //_BROWSE_UDF_
3125 // get device features
3126 UDFPhSendIOCTL( IOCTL_CDRW_GET_DEVICE_INFO
,
3129 ioBuf
,sizeof(GET_DEVICE_INFO_USER_OUT
),
3132 Vcb
->SavedFeatures
=
3133 SavedFeatures
= ((PGET_DEVICE_INFO_USER_OUT
)ioBuf
)->Features
;
3134 if(!(SavedFeatures
& CDRW_FEATURE_SYNC_ON_WRITE
)) {
3135 KdPrint(("UDFGetDiskInfo: UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE\n"));
3136 Vcb
->CompatFlags
|= UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE
;
3138 if(!(SavedFeatures
& CDRW_FEATURE_FORCE_SYNC_BEFORE_READ
)) {
3139 KdPrint(("UDFGetDiskInfo: UDF_VCB_IC_SYNCCACHE_BEFORE_READ\n"));
3140 Vcb
->CompatFlags
|= UDF_VCB_IC_SYNCCACHE_BEFORE_READ
;
3142 if(SavedFeatures
& CDRW_FEATURE_BAD_RW_SEEK
) {
3143 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_BAD_RW_SEEK\n"));
3144 Vcb
->CompatFlags
|= UDF_VCB_IC_BAD_RW_SEEK
;
3146 // we must check if this is FP-formatted disk in old devices
3147 // independently of MediaType they report
3148 if(SavedFeatures
& CDRW_FEATURE_FP_ADDRESSING_PROBLEM
) {
3149 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_FP_ADDRESSING_PROBLEM ?\n"));
3150 Vcb
->CompatFlags
|= UDF_VCB_IC_FP_ADDR_PROBLEM
;
3152 if(SavedFeatures
& CDRW_FEATURE_MRW_ADDRESSING_PROBLEM
) {
3153 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM ?\n"));
3155 if(SavedFeatures
& CDRW_FEATURE_FORCE_SYNC_ON_WRITE
) {
3156 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_FORCE_SYNC_ON_WRITE\n"));
3157 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_FORCE_SYNC_CACHE
;
3159 if(SavedFeatures
& CDRW_FEATURE_BAD_DVD_LAST_LBA
) {
3160 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_BAD_DVD_LAST_LBA\n"));
3161 Vcb
->CompatFlags
|= UDF_VCB_IC_BAD_DVD_LAST_LBA
;
3163 if(SavedFeatures
& CDRW_FEATURE_STREAMING
) {
3164 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_STREAMING\n"));
3166 if(SavedFeatures
& CDRW_FEATURE_OPC
) {
3167 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_OPC -> assume OPCNum=1\n"));
3170 #ifdef UDF_FORMAT_MEDIA
3171 if(SavedFeatures
& CDRW_FEATURE_FULL_BLANK_ON_FORMAT
) {
3172 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_FULL_BLANK_ON_FORMAT\n"));
3173 if((fms
->opt_probe
|| fms
->opt_smart_f
)/* &&
3174 (fms->format_media && fms->blank_media*/) {
3175 KdPrint(("UDFGetDiskInfo: force Full Erase\n"));
3176 fms
->opt_qblank
= FALSE
;
3179 #endif //UDF_FORMAT_MEDIA
3181 // get device buffer size
3182 RC
= UDFPhSendIOCTL( IOCTL_CDRW_BUFFER_CAPACITY
,
3185 ioBuf
,sizeof(BUFFER_CAPACITY_BLOCK_USER_OUT
),
3187 if(NT_SUCCESS(RC
)) {
3188 Vcb
->CdrwBufferSize
= ((PBUFFER_CAPACITY_BLOCK_USER_OUT
)ioBuf
)->BufferLength
;
3190 Vcb
->CdrwBufferSize
= 0;
3192 KdPrint(("UDFGetDiskInfo: CdrwBufferSize = %dKb\n", Vcb
->CdrwBufferSize
/ 1024));
3193 Vcb
->CdrwBufferSizeCounter
= 0;
3194 #endif //_BROWSE_UDF_
3196 RC
= UDFPhSendIOCTL(IOCTL_CDRW_GET_MEDIA_TYPE
,DeviceObject
,
3197 NULL
,0,ioBuf
,sizeof(GET_MEDIA_TYPE_USER_OUT
),
3199 if(!OS_SUCCESS(RC
)) goto Try_FullToc
;
3201 MediaType
= ((PGET_MEDIA_TYPE_USER_OUT
)ioBuf
)->MediaType
;
3202 KdPrint(("UDFGetDiskInfo: MediaType %x\n", MediaType
));
3204 #ifndef UDF_FORMAT_MEDIA
3205 // we shall ignore audio-disks
3207 case MediaType_120mm_CDROM_AudioOnly
:
3208 case MediaType_80mm_CDROM_AudioOnly
:
3209 case MediaType_120mm_CDR_AudioOnly
:
3210 case MediaType_80mm_CDR_AudioOnly
:
3211 case MediaType_120mm_CDRW_AudioOnly
:
3212 case MediaType_80mm_CDRW_AudioOnly
:
3214 KdPrint(("UDFGetDiskInfo: we shall ignore audio-disks...\n"));
3215 try_return(RC
= STATUS_UNRECOGNIZED_VOLUME
);
3217 #endif //UDF_FORMAT_MEDIA
3219 KdPrint(("UDFGetDiskInfo: Check DVD-disks...\n"));
3220 RC
= UDFPhSendIOCTL(IOCTL_CDRW_GET_MEDIA_TYPE_EX
,DeviceObject
,
3221 NULL
,0,ioBuf
,sizeof(GET_MEDIA_TYPE_EX_USER_OUT
),
3223 if(!OS_SUCCESS(RC
)) goto Try_FullToc
;
3225 MediaType
= (((PGET_MEDIA_TYPE_EX_USER_OUT
)ioBuf
)->MediaClass
);
3226 KdPrint(("UDFGetDiskInfo: MediaClassEx %x\n", MediaType
));
3233 case CdMediaClass_CDR
:
3234 case CdMediaClass_DVDR
:
3235 case CdMediaClass_DVDpR
:
3236 case CdMediaClass_HD_DVDR
:
3237 case CdMediaClass_BDR
:
3238 KdPrint(("UDFGetDiskInfo: MediaClass R\n"));
3239 Vcb
->MediaType
= MediaType_UnknownSize_CDR
;
3241 case CdMediaClass_CDRW
:
3243 if(SavedFeatures
& CDRW_FEATURE_MRW_ADDRESSING_PROBLEM
) {
3244 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM on CD-RW\n"));
3245 Vcb
->CompatFlags
|= UDF_VCB_IC_MRW_ADDR_PROBLEM
;
3248 case CdMediaClass_DVDRW
:
3249 case CdMediaClass_DVDpRW
:
3250 case CdMediaClass_DVDRAM
:
3251 case CdMediaClass_HD_DVDRW
:
3252 case CdMediaClass_HD_DVDRAM
:
3253 case CdMediaClass_BDRE
:
3254 KdPrint(("UDFGetDiskInfo: MediaClass RW\n"));
3255 Vcb
->MediaType
= MediaType_UnknownSize_CDRW
;
3257 case CdMediaClass_CDROM
:
3258 case CdMediaClass_DVDROM
:
3259 case CdMediaClass_HD_DVDROM
:
3260 case CdMediaClass_BDROM
:
3261 KdPrint(("UDFGetDiskInfo: MediaClass ROM\n"));
3262 Vcb
->MediaType
= MediaType_Unknown
;
3263 // Vcb->MediaType = MediaType_UnknownSize_CDROM;
3266 KdPrint(("UDFGetDiskInfo: MediaClass Unknown\n"));
3267 Vcb
->MediaType
= MediaType_Unknown
;
3270 MediaType
= Vcb
->MediaType
;
3273 #endif //_BROWSE_UDF_
3275 #ifdef UDF_FORMAT_MEDIA
3280 case CdMediaClass_CDR
:
3281 KdPrint(("CdMediaClass_CDR\n"));
3282 MediaType
= MediaType_UnknownSize_CDR
;
3283 if(fms
->opt_media
== MT_AUTO
)
3284 fms
->opt_media
= MT_CDR
;
3286 case CdMediaClass_DVDR
:
3287 KdPrint(("CdMediaClass_DVDR -> MediaType_UnknownSize_CDR\n"));
3288 MediaType
= MediaType_UnknownSize_CDR
;
3289 if(fms
->opt_media
== MT_AUTO
)
3290 fms
->opt_media
= MT_DVDR
;
3292 case CdMediaClass_DVDpR
:
3293 KdPrint(("CdMediaClass_DVDpR -> MediaType_UnknownSize_CDR\n"));
3294 MediaType
= MediaType_UnknownSize_CDR
;
3295 if(fms
->opt_media
== MT_AUTO
)
3296 fms
->opt_media
= MT_DVDpR
;
3298 case CdMediaClass_HD_DVDR
:
3299 KdPrint(("CdMediaClass_HD_DVDR -> MediaType_UnknownSize_CDR\n"));
3300 MediaType
= MediaType_UnknownSize_CDR
;
3301 if(fms
->opt_media
== MT_AUTO
)
3302 fms
->opt_media
= MT_DVDR
;
3304 case CdMediaClass_BDR
:
3305 KdPrint(("CdMediaClass_BDR -> MediaType_UnknownSize_CDR\n"));
3306 MediaType
= MediaType_UnknownSize_CDR
;
3307 if(fms
->opt_media
== MT_AUTO
)
3308 fms
->opt_media
= MT_DVDR
;
3310 case CdMediaClass_CDRW
:
3311 KdPrint(("CdMediaClass_CDRW\n"));
3312 MediaType
= MediaType_UnknownSize_CDRW
;
3313 if(fms
->opt_media
== MT_AUTO
)
3314 fms
->opt_media
= MT_CDRW
;
3315 if(SavedFeatures
& CDRW_FEATURE_MRW_ADDRESSING_PROBLEM
) {
3316 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM on CD-RW\n"));
3317 Vcb
->CompatFlags
|= UDF_VCB_IC_MRW_ADDR_PROBLEM
;
3320 case CdMediaClass_DVDRW
:
3321 KdPrint((" CdMediaClass_DVDRW -> MediaType_UnknownSize_CDRW\n"));
3322 if(fms
->opt_media
== MT_AUTO
)
3323 fms
->opt_media
= MT_DVDRW
;
3324 MediaType
= MediaType_UnknownSize_CDRW
;
3326 case CdMediaClass_DVDpRW
:
3327 KdPrint((" CdMediaClass_DVDpRW -> MediaType_UnknownSize_CDRW\n"));
3328 if(fms
->opt_media
== MT_AUTO
)
3329 fms
->opt_media
= MT_DVDpRW
;
3330 MediaType
= MediaType_UnknownSize_CDRW
;
3332 case CdMediaClass_DVDRAM
:
3333 KdPrint((" CdMediaClass_DVDRAM -> MediaType_UnknownSize_CDRW\n"));
3334 if(fms
->opt_media
== MT_AUTO
)
3335 fms
->opt_media
= MT_DVDRAM
;
3336 MediaType
= MediaType_UnknownSize_CDRW
;
3338 case CdMediaClass_HD_DVDRW
:
3339 KdPrint((" CdMediaClass_HD_DVDRW -> MediaType_UnknownSize_CDRW\n"));
3340 if(fms
->opt_media
== MT_AUTO
)
3341 fms
->opt_media
= MT_DVDRW
;
3342 MediaType
= MediaType_UnknownSize_CDRW
;
3344 case CdMediaClass_HD_DVDRAM
:
3345 KdPrint((" CdMediaClass_HD_DVDRAM -> MediaType_UnknownSize_CDRW\n"));
3346 if(fms
->opt_media
== MT_AUTO
)
3347 fms
->opt_media
= MT_DVDRAM
;
3348 MediaType
= MediaType_UnknownSize_CDRW
;
3350 case CdMediaClass_BDRE
:
3351 KdPrint((" CdMediaClass_BDRE -> MediaType_UnknownSize_CDRW\n"));
3352 if(fms
->opt_media
== MT_AUTO
)
3353 fms
->opt_media
= MT_DVDRW
;
3354 MediaType
= MediaType_UnknownSize_CDRW
;
3356 case CdMediaClass_NoDiscPresent
:
3357 KdPrint((" CdMediaClass_NoDiscPresent -> MediaType_NoDiscPresent\n"));
3358 MediaType
= MediaType_NoDiscPresent
;
3359 fms
->opt_media
= MT_none
;
3361 case CdMediaClass_DoorOpen
:
3362 KdPrint((" CdMediaClass_DoorOpen -> MediaType_DoorOpen\n"));
3363 MediaType
= MediaType_DoorOpen
;
3364 fms
->opt_media
= MT_none
;
3367 KdPrint((" MediaType_Unknown\n"));
3368 MediaType
= MediaType_Unknown
;
3371 if(!apply_force_r(fms
)) {
3372 my_exit(fms
, MKUDF_CANT_APPLY_R
);
3376 #endif //UDF_FORMAT_MEDIA
3378 Vcb
->DVD_Mode
= (((PGET_MEDIA_TYPE_EX_USER_OUT
)ioBuf
)->MediaClassEx
== CdMediaClassEx_DVD
);
3379 Vcb
->PhMediaCapFlags
= ((PGET_MEDIA_TYPE_EX_USER_OUT
)ioBuf
)->CapFlags
;
3380 Vcb
->WriteParamsReq
= (Vcb
->PhMediaCapFlags
& CdCapFlags_WriteParamsReq
) ? TRUE
: FALSE
;
3382 !(Vcb
->PhMediaCapFlags
& CdCapFlags_RandomWritable
)) {
3383 KdPrint(("UDFGetDiskInfo: DVD && !CdCapFlags_RandomWritable\n"));
3384 KdPrint((" Read-only volume\n"));
3386 #ifndef UDF_CDRW_EMULATION_ON_ROM
3387 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_READ_ONLY
;
3390 #ifdef UDF_FORMAT_MEDIA
3392 if((MediaType
== MediaType_NoDiscPresent
) ||
3393 (MediaType
== MediaType_DoorOpen
)) {
3394 UserPrint(("No media in device\n"));
3395 my_exit(fms
, MKUDF_NO_MEDIA_IN_DEVICE
);
3398 #endif //UDF_FORMAT_MEDIA
3399 if(!Vcb
->WriteParamsReq
) {
3400 KdPrint(("UDFGetDiskInfo: do not use WriteParams\n"));
3402 if(Vcb
->PhMediaCapFlags
& CdCapFlags_Cav
) {
3403 KdPrint(("UDFGetDiskInfo: Use CAV (1)\n"));
3404 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_USE_CAV
;
3409 // check if this device is capable to write on such media
3410 if(UDFIsDvdMedia(Vcb
)) {
3412 KdPrint(("UDFGetDiskInfo: update defaulted LastLBA\n"));
3413 UDFGetBlockSize(DeviceObject
,Vcb
);
3414 //if(!OS_SUCCESS(RC)) goto Try_FullToc;
3416 if((SavedFeatures
& CDRW_FEATURE_MRW_ADDRESSING_PROBLEM
) &&
3417 (SavedFeatures
& UDF_VCB_IC_FP_ADDR_PROBLEM
)) {
3418 KdPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM on old CD-ROM\n"));
3419 Vcb
->CompatFlags
|= UDF_VCB_IC_MRW_ADDR_PROBLEM
;
3423 #endif //_BROWSE_UDF_
3425 /*#ifdef UDF_FORMAT_MEDIA
3427 if(MediaType == CdMediaClass_DVDRW) {
3428 UserPrint(("Not empty media. Erase required.\n"));
3429 my_exit(fms, MKUDF_BLANK_FORMAT_REQUIRED);
3432 #endif //UDF_FORMAT_MEDIA*/
3434 #define cap ((PGET_CAPABILITIES_3_USER_OUT)ioBuf)
3435 // get device capabilities
3436 RC
= UDFPhSendIOCTL(IOCTL_CDRW_GET_CAPABILITIES
,DeviceObject
,
3437 NULL
,0,ioBuf
,sizeof(GET_CAPABILITIES_3_USER_OUT
),
3439 if(!OS_SUCCESS(RC
)) goto Try_FullToc
;
3441 // check if this device is capable to write on such media
3442 RC
= UDFPhSendIOCTL(IOCTL_DISK_IS_WRITABLE
,DeviceObject
,
3443 NULL
,0,NULL
,0,FALSE
, NULL
);
3444 if(RC
!= STATUS_SUCCESS
) {
3445 KdPrint(("IS_WRITABLE - false, doing additional check...\n"));
3446 if( ((MediaType
>= MediaType_UnknownSize_CDRW
) && !(cap
->WriteCap
& DevCap_write_cd_rw
)) ||
3447 ((MediaType
>= MediaType_UnknownSize_CDR
) && !(cap
->WriteCap
& DevCap_write_cd_r
)) ||
3448 (MediaType
< MediaType_UnknownSize_CDR
) ) {
3449 UserPrint(("Hardware Read-only volume\n"));
3450 #ifndef UDF_CDRW_EMULATION_ON_ROM
3451 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_READ_ONLY
;
3452 #endif //UDF_CDRW_EMULATION_ON_ROM
3453 #ifdef UDF_FORMAT_MEDIA
3454 if(fms
&& !fms
->opt_read_iso
)
3455 my_exit(fms
, MKUDF_HW_READ_ONLY
);
3456 #endif //UDF_FORMAT_MEDIA
3459 KdPrint(("Writable disk\n"));
3461 Vcb
->MaxWriteSpeed
= cap
->MaximumWriteSpeedSupported
;
3462 Vcb
->MaxReadSpeed
= cap
->MaximumSpeedSupported
;
3463 if(cap
->PageLength
>= (sizeof(GET_CAPABILITIES_3_USER_OUT
)-2)) {
3464 Vcb
->CurSpeed
= max(cap
->CurrentSpeed
, cap
->CurrentWriteSpeed3
);
3465 if(cap
->LunWPerfDescriptorCount
&& cap
->LunWPerfDescriptorCount
!= 0xffff) {
3467 KdPrint(("Write performance descriptor(s) found: %x\n", cap
->LunWPerfDescriptorCount
));
3468 n
= (4096 - sizeof(GET_CAPABILITIES_3_USER_OUT
)) / sizeof(LUN_WRITE_PERF_DESC_USER
);
3469 n
= min(n
, cap
->LunWPerfDescriptorCount
);
3470 // get device capabilities
3471 RC
= UDFPhSendIOCTL(IOCTL_CDRW_GET_CAPABILITIES
,DeviceObject
,
3472 ioBuf
,sizeof(GET_CAPABILITIES_3_USER_OUT
)+n
*sizeof(LUN_WRITE_PERF_DESC_USER
),
3473 ioBuf
,sizeof(GET_CAPABILITIES_3_USER_OUT
)+n
*sizeof(LUN_WRITE_PERF_DESC_USER
),
3475 if(OS_SUCCESS(RC
)) {
3476 WPerfDesc
= (PLUN_WRITE_PERF_DESC_USER
)(ioBuf
+ sizeof(GET_CAPABILITIES_3_USER_OUT
));
3478 for(i
= 0; i
<n
; i
++) {
3479 if((WPerfDesc
[i
].RotationControl
& LunWPerf_RotCtrl_Mask
) == LunWPerf_RotCtrl_CAV
) {
3480 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_USE_CAV
;
3482 Vcb
->CurSpeed
= WPerfDesc
[i
].WriteSpeedSupported
;
3484 KdPrint(("Use CAV\n"));
3486 Vcb
->CurSpeed
= max(WPerfDesc
[i
].WriteSpeedSupported
, Vcb
->CurSpeed
);
3488 KdPrint(("supports speed %dX\n", Vcb
->CurSpeed
/176));
3493 KdPrint(("Set r/w speeds to %dX\n", Vcb
->CurSpeed
/176));
3494 Vcb
->MaxWriteSpeed
=
3495 Vcb
->MaxReadSpeed
= Vcb
->CurSpeed
;
3500 Vcb
->CurSpeed
= max(cap
->CurrentSpeed
, cap
->CurrentWriteSpeed
);
3502 KdPrint((" Speeds r/w %dX/%dX\n", Vcb
->CurSpeed
/176, cap
->CurrentWriteSpeed
/176));
3504 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_USE_CAV
) {
3505 // limit both read & write speed to last write speed for CAV mode
3506 // some drives damage data when speed is adjusted during recording process
3507 // even in packet mode
3513 #ifdef UDF_FORMAT_MEDIA
3515 if( (fms
->auto_media
|| (fms
->opt_media
== MT_AUTO
)) &&
3516 (fms
->opt_media
< MT_DVDR
) ) {
3517 if(MediaType
< MediaType_UnknownSize_CDRW
) {
3518 fms
->opt_media
= MT_CDR
;
3520 fms
->opt_media
= MT_CDRW
;
3523 if(!apply_force_r(fms
)) {
3524 my_exit(fms
, MKUDF_CANT_APPLY_R
);
3527 #endif //UDF_FORMAT_MEDIA
3528 RC
= UDFReadDiscTrackInfo(DeviceObject
, Vcb
);
3530 if(!OS_SUCCESS(RC
)) {
3531 // may be we have a CD-ROM device
3533 KdPrint(("Hardware Read-only volume (2)\n"));
3535 #ifndef UDF_CDRW_EMULATION_ON_ROM
3536 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_READ_ONLY
;
3539 RC
= UDFReadAndProcessFullToc(DeviceObject
, Vcb
);
3541 if(!OS_SUCCESS(RC
)) {
3542 RC
= UDFUseStandard(DeviceObject
,Vcb
);
3543 if(!OS_SUCCESS(RC
)) try_return(RC
);
3551 RC
= UDFUseStandard(DeviceObject
, Vcb
);
3552 if(!OS_SUCCESS(RC
)) try_return(RC
);
3559 if(ioBuf
) MyFreePool__(ioBuf
);
3561 if(UDFIsDvdMedia(Vcb
) &&
3562 (Vcb
->CompatFlags
& UDF_VCB_IC_BAD_DVD_LAST_LBA
) &&
3563 (Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_READ_ONLY
) &&
3565 (Vcb
->LastLBA
< DEFAULT_LAST_LBA_DVD
)) {
3566 KdPrint(("UDF: Bad DVD last LBA %x, fixup!\n", Vcb
->LastLBA
));
3567 Vcb
->LastLBA
= DEFAULT_LAST_LBA_DVD
;
3572 if(UDFIsDvdMedia(Vcb
) && !Vcb
->FirstLBA
&& !Vcb
->LastPossibleLBA
) {
3573 KdPrint(("UDF: Empty DVD. Use bogus values for now\n"));
3574 Vcb
->LastPossibleLBA
= DEFAULT_LAST_LBA_DVD
;
3578 if((Vcb
->LastPossibleLBA
& 0x80000000) || (Vcb
->LastPossibleLBA
< Vcb
->LastLBA
)) {
3579 KdPrint(("UDF: bad LastPossibleLBA %x -> %x\n", Vcb
->LastPossibleLBA
, Vcb
->LastLBA
));
3580 Vcb
->LastPossibleLBA
= Vcb
->LastLBA
;
3582 if(!Vcb
->WriteBlockSize
)
3583 Vcb
->WriteBlockSize
= PACKETSIZE_UDF
*Vcb
->BlockSize
;
3587 if(Vcb
->TrackMap
[Vcb
->LastTrackNum
].LastLba
> Vcb
->NWA
) {
3589 if(Vcb
->TrackMap
[Vcb
->LastTrackNum
].DataParam
& TrkInfo_FP
) {
3590 Vcb
->LastLBA
= Vcb
->NWA
-1;
3592 Vcb
->LastLBA
= Vcb
->NWA
-7-1;
3596 if((Vcb
->LastTrackNum
> 1) &&
3597 (Vcb
->TrackMap
[Vcb
->LastTrackNum
-1].FirstLba
>= Vcb
->TrackMap
[Vcb
->LastTrackNum
-1].LastLba
)) {
3598 Vcb
->LastLBA
= Vcb
->TrackMap
[Vcb
->LastTrackNum
-1].LastLba
;
3603 for(i
=0; i
<32; i
++) {
3604 if(!(Vcb
->LastPossibleLBA
>> i
))
3608 Vcb
->WCacheBlocksPerFrameSh
= max(Vcb
->WCacheBlocksPerFrameSh
, (2*i
)/5+2);
3609 Vcb
->WCacheBlocksPerFrameSh
= min(Vcb
->WCacheBlocksPerFrameSh
, 16);
3612 if(Vcb
->CompatFlags
& UDF_VCB_IC_FP_ADDR_PROBLEM
) {
3613 // Check first 0x200 blocks
3614 UDFCheckTrackFPAddressing(Vcb
, Vcb
->FirstTrackNum
);
3615 // if we really have such a problem, fix LastLBA
3616 if(Vcb
->CompatFlags
& UDF_VCB_IC_FP_ADDR_PROBLEM
) {
3617 KdPrint(("UDF: Fix LastLBA: %x -> %x\n", Vcb
->LastLBA
, (Vcb
->LastLBA
*32) / 39));
3618 Vcb
->LastLBA
= (Vcb
->LastLBA
*32) / 39;
3621 #endif //_BROWSE_UDF_
3623 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_READ_ONLY
) {
3624 if(!Vcb
->BlankCD
&& Vcb
->MediaType
!= MediaType_UnknownSize_CDRW
) {
3625 KdPrint(("UDFGetDiskInfo: R/O+!Blank+!RW -> !RAW\n"));
3626 Vcb
->VCBFlags
&= ~UDF_VCB_FLAGS_RAW_DISK
;
3628 KdPrint(("UDFGetDiskInfo: Blank or RW\n"));
3632 KdPrint(("UDF: ------------------------------------------\n"));
3633 KdPrint(("UDF: Media characteristics\n"));
3634 KdPrint(("UDF: Last session: %d\n",Vcb
->LastSession
));
3635 KdPrint(("UDF: First track in first session: %d\n",Vcb
->FirstTrackNum
));
3636 KdPrint(("UDF: First track in last session: %d\n",Vcb
->FirstTrackNumLastSes
));
3637 KdPrint(("UDF: Last track in last session: %d\n",Vcb
->LastTrackNum
));
3638 KdPrint(("UDF: First LBA in first session: %x\n",Vcb
->FirstLBA
));
3639 KdPrint(("UDF: First LBA in last session: %x\n",Vcb
->FirstLBALastSes
));
3640 KdPrint(("UDF: Last LBA in last session: %x\n",Vcb
->LastLBA
));
3641 KdPrint(("UDF: First writable LBA (NWA) in last session: %x\n",Vcb
->NWA
));
3642 KdPrint(("UDF: Last available LBA beyond end of last session: %x\n",Vcb
->LastPossibleLBA
));
3643 KdPrint(("UDF: blocks per frame: %x\n",1 << Vcb
->WCacheBlocksPerFrameSh
));
3644 KdPrint(("UDF: Flags: %s%s\n",
3645 Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
? "RAW " : "",
3646 Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_READ_ONLY
? "R/O " : "WR "
3648 KdPrint(("UDF: ------------------------------------------\n"));
3650 #ifdef UDF_FORMAT_MEDIA
3651 if(fms
&& fms
->opt_disk_info
) {
3652 UserPrint(("------------------------------------------\n"));
3653 UserPrint(("Media characteristics:\n"));
3654 UserPrint((" First writable LBA (NWA) in last session: %x\n",Vcb
->NWA
));
3655 UserPrint((" Last available LBA beyond end of last session: %x\n",Vcb
->LastPossibleLBA
));
3656 UserPrint(("------------------------------------------\n"));
3658 #endif //UDF_FORMAT_MEDIA
3662 KdPrint(("UDFGetDiskInfo: %x\n", RC
));
3665 } // end UDFGetDiskInfo()
3667 //#ifdef _BROWSE_UDF_
3670 UDFPrepareForReadOperation(
3676 if( (Vcb
->FsDeviceType
!= FILE_DEVICE_CD_ROM_FILE_SYSTEM
) ) {
3677 Vcb
->VCBFlags
&= ~UDF_VCB_LAST_WRITE
;
3678 return STATUS_SUCCESS
;
3680 uint32 i
= Vcb
->LastReadTrack
;
3681 BOOLEAN speed_changed
= FALSE
;
3686 #endif //_BROWSE_UDF_
3688 #ifdef _UDF_STRUCTURES_H_
3689 if(Vcb
->BSBM_Bitmap
) {
3691 for(i
=0; i
<BCount
; i
++) {
3692 if(UDFGetBit((uint32
*)(Vcb
->BSBM_Bitmap
), Lba
+i
)) {
3693 KdPrint(("R: Known BB @ %#x\n", Lba
));
3694 //return STATUS_FT_WRITE_RECOVERY; // this shall not be treated as error and
3695 // we shall get IO request to BAD block
3696 return STATUS_DEVICE_DATA_ERROR
;
3700 #endif //_UDF_STRUCTURES_H_
3702 if(!UDFIsDvdMedia(Vcb
) &&
3703 (Vcb
->VCBFlags
& UDF_VCB_LAST_WRITE
) &&
3704 !(Vcb
->VCBFlags
& UDF_VCB_FLAGS_NO_SYNC_CACHE
) &&
3705 !(Vcb
->CompatFlags
& UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE
)){
3709 RC
= UDFSyncCache(Vcb
);
3711 if( (Vcb
->VCBFlags
& UDF_VCB_LAST_WRITE
) &&
3712 !(Vcb
->VCBFlags
& UDF_VCB_FLAGS_NO_SYNC_CACHE
) &&
3713 #ifndef UDF_FORMAT_MEDIA
3714 (Vcb
->CompatFlags
& UDF_VCB_IC_SYNCCACHE_BEFORE_READ
) &&
3715 #endif //UDF_FORMAT_MEDIA
3723 if(!UDFIsDvdMedia(Vcb
)) {
3724 // limit read speed after write operation
3725 // to avoid performance degrade durring speed-up/down
3726 // on read/write mode switching
3727 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_USE_CAV
) {
3728 // limit both read & write speed to last write speed for CAV mode
3729 // some drives damage data when speed is adjusted during recording process
3730 // even in packet mode
3731 if(Vcb
->CurSpeed
!= Vcb
->MaxWriteSpeed
||
3732 Vcb
->CurSpeed
!= Vcb
->MaxReadSpeed
) {
3733 Vcb
->CurSpeed
= Vcb
->MaxWriteSpeed
;
3734 speed_changed
= TRUE
;
3737 if(Vcb
->VCBFlags
& UDF_VCB_LAST_WRITE
) {
3738 // limit read speed to last write speed
3739 if(Vcb
->CurSpeed
> Vcb
->MaxWriteSpeed
) {
3740 Vcb
->CurSpeed
= Vcb
->MaxWriteSpeed
;
3741 speed_changed
= TRUE
;
3744 if(Vcb
->CurSpeed
< Vcb
->MaxReadSpeed
) {
3745 // increment read speed (+1X)
3746 Vcb
->CurSpeed
+= 176/1;
3747 speed_changed
= TRUE
;
3750 if(Vcb
->CurSpeed
> Vcb
->MaxReadSpeed
) {
3751 Vcb
->CurSpeed
= Vcb
->MaxReadSpeed
;
3753 // send speed limits to drive
3755 RtlZeroMemory(&(Vcb
->SpeedBuf
), sizeof(SET_CD_SPEED_EX_USER_IN
));
3756 Vcb
->SpeedBuf
.ReadSpeed
= Vcb
->CurSpeed
;
3757 Vcb
->SpeedBuf
.WriteSpeed
= Vcb
->MaxWriteSpeed
;
3758 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_USE_CAV
) {
3759 Vcb
->SpeedBuf
.RotCtrl
= CdSpeed_RotCtrl_CAV
;
3761 KdPrint((" UDFPrepareForReadOperation: set speed to %s %dX/%dX\n",
3762 (Vcb
->VCBFlags
& UDF_VCB_FLAGS_USE_CAV
) ? "CAV" : "CLV",
3763 Vcb
->SpeedBuf
.ReadSpeed
,
3764 Vcb
->SpeedBuf
.WriteSpeed
));
3765 UDFPhSendIOCTL(IOCTL_CDRW_SET_SPEED
,
3766 Vcb
->TargetDeviceObject
,
3767 &(Vcb
->SpeedBuf
),sizeof(SET_CD_SPEED_EX_USER_IN
),
3772 if(UDFIsDvdMedia(Vcb
))
3773 return STATUS_SUCCESS
;
3775 if(Vcb
->LastReadTrack
&&
3776 ((Vcb
->TrackMap
[i
].FirstLba
<= Lba
) || (Vcb
->TrackMap
[i
].FirstLba
& 0x80000000)) &&
3777 (Vcb
->TrackMap
[i
].LastLba
>= Lba
)) {
3778 check_for_data_track
:
3779 // check track mode (Mode1/XA)
3780 switch((Vcb
->TrackMap
[i
].DataParam
& TrkInfo_Dat_Mask
)) {
3781 case TrkInfo_Dat_Mode1
: // Mode1
3782 case TrkInfo_Dat_XA
: // XA Mode2
3783 case TrkInfo_Dat_Unknown
: // for some stupid irons
3787 Vcb
->IncrementalSeekState
= INCREMENTAL_SEEK_NONE
;
3788 return STATUS_INVALID_PARAMETER
;
3791 for(i
=Vcb
->FirstTrackNum
; i
<=Vcb
->LastTrackNum
; i
++) {
3792 if(((Vcb
->TrackMap
[i
].FirstLba
> Lba
) && !(Vcb
->TrackMap
[i
].FirstLba
& 0x80000000)) ||
3793 (Vcb
->TrackMap
[i
].LastLba
< Lba
))
3795 Vcb
->LastReadTrack
= i
;
3796 goto check_for_data_track
;
3798 Vcb
->LastReadTrack
= 0;
3800 if(Vcb
->IncrementalSeekState
!= INCREMENTAL_SEEK_WORKAROUND
) {
3801 Vcb
->IncrementalSeekState
= INCREMENTAL_SEEK_NONE
;
3802 return STATUS_SUCCESS
;
3804 KdPrint((" UDFPrepareForReadOperation: seek workaround...\n"));
3805 Vcb
->IncrementalSeekState
= INCREMENTAL_SEEK_DONE
;
3807 tmp
= (PUCHAR
)DbgAllocatePoolWithTag(NonPagedPool
, Vcb
->BlockSize
, 'bNWD');
3809 Vcb
->IncrementalSeekState
= INCREMENTAL_SEEK_NONE
;
3810 return STATUS_INSUFFICIENT_RESOURCES
;
3812 for(i
=0x1000; i
<=Lba
; i
+=0x1000) {
3813 RC
= UDFPhReadSynchronous(Vcb
->TargetDeviceObject
, tmp
, Vcb
->BlockSize
,
3814 ((uint64
)UDFFixFPAddress(Vcb
,i
)) << Vcb
->BlockSizeBits
, &ReadBytes
, 0);
3815 KdPrint((" seek workaround, LBA %x, status %x\n", i
, RC
));
3818 #endif //_BROWSE_UDF_
3820 return STATUS_SUCCESS
;
3821 } // end UDFPrepareForReadOperation()
3823 //#endif //_BROWSE_UDF_
3828 uint32 LBA
, // physical
3833 #ifndef UDF_READ_ONLY_BUILD
3835 if(!OS_SUCCESS(RC
)) {
3838 if(!Vcb
->CDR_Mode
) {
3840 if((Vcb
->MediaClassEx
== CdMediaClass_DVDRW
||
3841 Vcb
->MediaClassEx
== CdMediaClass_DVDpRW
||
3842 Vcb
->MediaClassEx
== CdMediaClass_DVDRAM
||
3843 Vcb
->MRWStatus
== DiscInfo_BGF_Interrupted
||
3844 Vcb
->MRWStatus
== DiscInfo_BGF_InProgress
)
3845 && (LBA
+BCount
-1) > Vcb
->LastLBA
) {
3846 ASSERT(Vcb
->NWA
> Vcb
->LastLBA
);
3847 Vcb
->NWA
= LBA
+BCount
;
3848 Vcb
->LastLBA
= Vcb
->NWA
-1;
3850 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_FORCE_SYNC_CACHE
)
3852 /* if(Vcb->CdrwBufferSize) {
3853 Vcb->CdrwBufferSizeCounter += BCount * 2048;
3854 if(Vcb->CdrwBufferSizeCounter >= Vcb->CdrwBufferSize + 2*2048) {
3855 KdPrint((" UDFUpdateNWA: buffer is full, sync...\n"));
3856 Vcb->CdrwBufferSizeCounter = 0;
3860 if(Vcb
->SyncCacheState
== SYNC_CACHE_RECOVERY_RETRY
) {
3861 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_FORCE_SYNC_CACHE
;
3863 Vcb
->SyncCacheState
= SYNC_CACHE_RECOVERY_NONE
;
3866 if(Vcb
->LastLBA
< (LBA
+BCount
))
3867 Vcb
->LastLBA
= LBA
+BCount
;
3871 if(!(Vcb
->CompatFlags
& UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE
)) {
3872 KdPrint((" UDFUpdateNWA: syncing...\n"));
3873 RC
= UDFSyncCache(Vcb
);
3875 #endif //_BROWSE_UDF_
3876 #endif //UDF_READ_ONLY_BUILD
3877 } // end UDFUpdateNWA()
3881 This routine reads physical sectors
3886 IN BOOLEAN Translate, // Translate Logical to Physical
3890 OUT uint32* ReadBytes
3894 if(Vcb->FastCache.ReadProc && (KeGetCurrentIrql() < DISPATCH_LEVEL)) {
3895 return WCacheReadBlocks__(&(Vcb->FastCache), Vcb, Buffer, Lba, BCount, ReadBytes);
3897 return UDFTRead(Vcb, Buffer, BCount*Vcb->BlockSize, Lba, ReadBytes);
3898 } // end UDFReadSectors()*/
3903 This routine reads physical sectors
3908 IN BOOLEAN Translate
, // Translate Logical to Physical
3910 IN uint32 i
, // offset in sector
3911 IN uint32 l
, // transfer length
3912 IN BOOLEAN Direct
, // Disable access to non-cached data
3914 OUT uint32
* ReadBytes
3922 if(WCacheIsInitialized__(&(Vcb
->FastCache
)) && (KeGetCurrentIrql() < DISPATCH_LEVEL
)) {
3923 status
= WCacheDirect__(&(Vcb
->FastCache
), Vcb
, Lba
, FALSE
, &tmp_buff
, Direct
);
3924 if(OS_SUCCESS(status
)) {
3926 RtlCopyMemory(Buffer
, tmp_buff
+i
, l
);
3928 if(!Direct
) WCacheEODirect__(&(Vcb
->FastCache
), Vcb
);
3931 return STATUS_INVALID_PARAMETER
;
3933 tmp_buff
= (int8
*)MyAllocatePool__(NonPagedPool
, Vcb
->BlockSize
);
3934 if(!tmp_buff
) return STATUS_INSUFFICIENT_RESOURCES
;
3935 status
= UDFReadSectors(Vcb
, Translate
, Lba
, 1, FALSE
, tmp_buff
, &_ReadBytes
);
3936 if(OS_SUCCESS(status
)) {
3938 RtlCopyMemory(Buffer
, tmp_buff
+i
, l
);
3940 MyFreePool__(tmp_buff
);
3943 } // end UDFReadInSector()
3946 This routine reads data of unaligned offset & length
3951 IN BOOLEAN Translate
, // Translate Logical to Physical
3954 IN BOOLEAN Direct
, // Disable access to non-cached data
3956 OUT uint32
* ReadBytes
3959 uint32 i
, l
, Lba
, BS
=Vcb
->BlockSize
;
3960 uint32 BSh
=Vcb
->BlockSizeBits
;
3962 uint32 _ReadBytes
= 0;
3963 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
3967 if(!Length
) return STATUS_SUCCESS
;
3968 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_DEAD
)
3969 return STATUS_NO_SUCH_DEVICE
;
3970 // read tail of the 1st sector if Offset is not sector_size-aligned
3971 Lba
= (uint32
)(Offset
>> BSh
);
3972 if((i
= (uint32
)(Offset
& (BS
-1)))) {
3973 l
= (BS
- i
) < Length
?
3975 // here we use 'ReadBytes' 'cause now it's set to zero
3976 status
= UDFReadInSector(Vcb
, Translate
, Lba
, i
, l
, Direct
, Buffer
, ReadBytes
);
3977 if(!OS_SUCCESS(status
)) return status
;
3978 if(!(Length
= Length
- l
)) return STATUS_SUCCESS
;
3982 // read sector_size-aligned part
3985 to_read
= min(i
, 64);
3986 status
= UDFReadSectors(Vcb
, Translate
, Lba
, to_read
, Direct
, Buffer
, &_ReadBytes
);
3987 (*ReadBytes
) += _ReadBytes
;
3988 if(!OS_SUCCESS(status
)) {
3991 Buffer
+= to_read
<<BSh
;
3992 Length
-= to_read
<<BSh
;
3996 // read head of the last sector
3997 if(!Length
) return STATUS_SUCCESS
;
3998 status
= UDFReadInSector(Vcb
, Translate
, Lba
, 0, Length
, Direct
, Buffer
, &_ReadBytes
);
3999 (*ReadBytes
) += _ReadBytes
;
4002 } // end UDFReadData()
4004 #endif //_BROWSE_UDF_
4006 #ifndef UDF_READ_ONLY_BUILD
4008 This routine writes physical sectors. This routine supposes Lba & Length
4009 alignment on WriteBlock (packet) size.
4014 IN BOOLEAN Translate
, // Translate Logical to Physical
4017 IN BOOLEAN Direct
, // Disable access to non-cached data
4019 OUT uint32
* WrittenBytes
4025 if(!Vcb
->Modified
|| (Vcb
->IntegrityType
== INTEGRITY_TYPE_CLOSE
)) {
4026 UDFSetModified(Vcb
);
4027 if(Vcb
->LVid
&& !Direct
) {
4028 status
= UDFUpdateLogicalVolInt(Vcb
,FALSE
);
4033 if(Vcb
->LastLBA
< Lba
+BCount
-1)
4034 Vcb
->LastLBA
= Lba
+BCount
-1;
4036 #endif //_BROWSE_UDF_
4038 if(Vcb
->FastCache
.WriteProc
&& (KeGetCurrentIrql() < DISPATCH_LEVEL
)) {
4039 status
= WCacheWriteBlocks__(&(Vcb
->FastCache
), Vcb
, Buffer
, Lba
, BCount
, WrittenBytes
, Direct
);
4040 ASSERT(OS_SUCCESS(status
));
4042 UDFClrZeroBits(Vcb
->ZSBM_Bitmap
, Lba
, BCount
);
4043 #endif //_BROWSE_UDF_
4049 (*WrittenBytes) = 0;
4050 buffer = DbgAllocatePool(NonPagedPool, Vcb->WriteBlockSize);
4051 if(!buffer) return STATUS_INSUFFICIENT_RESOURCES;
4052 status = UDFTRead(Vcb, Buffer, BCount<<Vcb->BlockSizeBits, (Lba&~(Vcb->WriteBlockSize-1), _WrittenBytes);*/
4054 status
= UDFTWrite(Vcb
, Buffer
, BCount
<<Vcb
->BlockSizeBits
, Lba
, WrittenBytes
);
4055 ASSERT(OS_SUCCESS(status
));
4058 return UDFTWrite(Vcb
, Buffer
, BCount
<<Vcb
->BlockSizeBits
, Lba
, WrittenBytes
);
4060 } // end UDFWriteSectors()
4065 IN BOOLEAN Translate
, // Translate Logical to Physical
4067 IN uint32 i
, // offset in sector
4068 IN uint32 l
, // transfer length
4069 IN BOOLEAN Direct
, // Disable access to non-cached data
4071 OUT uint32
* WrittenBytes
4077 uint32 _WrittenBytes
;
4080 if(!Vcb
->Modified
) {
4081 UDFSetModified(Vcb
);
4083 status
= UDFUpdateLogicalVolInt(Vcb
,FALSE
);
4087 if(Vcb
->LastLBA
< Lba
)
4090 #endif //_BROWSE_UDF_
4092 (*WrittenBytes
) = 0;
4094 if(WCacheIsInitialized__(&(Vcb
->FastCache
)) && (KeGetCurrentIrql() < DISPATCH_LEVEL
)) {
4095 #endif //_BROWSE_UDF_
4096 status
= WCacheDirect__(&(Vcb
->FastCache
), Vcb
, Lba
, TRUE
, &tmp_buff
, Direct
);
4097 if(OS_SUCCESS(status
)) {
4099 UDFClrZeroBit(Vcb
->ZSBM_Bitmap
, Lba
);
4100 #endif //_BROWSE_UDF_
4101 (*WrittenBytes
) += l
;
4102 RtlCopyMemory(tmp_buff
+i
, Buffer
, l
);
4104 if(!Direct
) WCacheEODirect__(&(Vcb
->FastCache
), Vcb
);
4107 // If Direct = TRUE we should never get here, but...
4110 return STATUS_INVALID_PARAMETER
;
4112 tmp_buff
= (int8
*)MyAllocatePool__(NonPagedPool
, Vcb
->BlockSize
);
4115 return STATUS_INSUFFICIENT_RESOURCES
;
4118 status
= UDFReadSectors(Vcb
, Translate
, Lba
, 1, FALSE
, tmp_buff
, &ReadBytes
);
4119 if(!OS_SUCCESS(status
)) goto EO_WrSctD
;
4121 RtlCopyMemory(tmp_buff
+i
, Buffer
, l
);
4122 // write modified packet
4123 status
= UDFWriteSectors(Vcb
, Translate
, Lba
, 1, FALSE
, tmp_buff
, &_WrittenBytes
);
4124 if(OS_SUCCESS(status
))
4125 (*WrittenBytes
) += l
;
4127 MyFreePool__(tmp_buff
);
4129 ASSERT(OS_SUCCESS(status
));
4130 if(!OS_SUCCESS(status
)) {
4131 KdPrint(("UDFWriteInSector() for LBA %x failed\n", Lba
));
4133 #endif //_BROWSE_UDF_
4135 } // end UDFWriteInSector()
4138 This routine writes data at unaligned offset & length
4143 IN BOOLEAN Translate
, // Translate Logical to Physical
4146 IN BOOLEAN Direct
, // setting this flag delays flushing of given
4147 // data to indefinite term
4149 OUT uint32
* WrittenBytes
4152 uint32 i
, l
, Lba
, BS
=Vcb
->BlockSize
;
4153 uint32 BSh
=Vcb
->BlockSizeBits
;
4155 uint32 _WrittenBytes
;
4156 Vcb
->VCBFlags
|= UDF_VCB_SKIP_EJECT_CHECK
;
4158 (*WrittenBytes
) = 0;
4159 if(!Length
) return STATUS_SUCCESS
;
4160 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_DEAD
)
4161 return STATUS_NO_SUCH_DEVICE
;
4162 // write tail of the 1st sector if Offset is not sector_size-aligned
4163 Lba
= (uint32
)(Offset
>> BSh
);
4164 if((i
= ((uint32
)Offset
& (BS
-1)))) {
4165 l
= (BS
- i
) < Length
?
4167 status
= UDFWriteInSector(Vcb
, Translate
, Lba
, i
, l
, Direct
, Buffer
, WrittenBytes
);
4168 if(!OS_SUCCESS(status
)) return status
;
4169 if(!(Length
= Length
- l
)) return STATUS_SUCCESS
;
4173 // write sector_size-aligned part
4176 status
= UDFWriteSectors(Vcb
, Translate
, Lba
, i
, Direct
, Buffer
, &_WrittenBytes
);
4177 (*WrittenBytes
) += _WrittenBytes
;
4178 if(!OS_SUCCESS(status
)) return status
;
4181 UDFClrZeroBits(Vcb
->ZSBM_Bitmap
, Lba
, i
);
4182 #endif //_BROWSE_UDF_
4183 if(!(Length
= Length
- l
)) return STATUS_SUCCESS
;
4187 status
= UDFWriteInSector(Vcb
, Translate
, Lba
, 0, Length
, Direct
, Buffer
, &_WrittenBytes
);
4188 (*WrittenBytes
) += _WrittenBytes
;
4190 UDFClrZeroBit(Vcb
->ZSBM_Bitmap
, Lba
);
4191 #endif //_BROWSE_UDF_
4194 } // end UDFWriteData()
4196 #endif //UDF_READ_ONLY_BUILD
4199 UDFResetDeviceDriver(
4201 IN PDEVICE_OBJECT TargetDeviceObject
,
4205 PCDRW_RESET_DRIVER_USER_IN tmp
= (PCDRW_RESET_DRIVER_USER_IN
)
4206 MyAllocatePool__(NonPagedPool
, sizeof(CDRW_RESET_DRIVER_USER_IN
));
4209 return STATUS_INSUFFICIENT_RESOURCES
;
4210 RtlZeroMemory(tmp
, sizeof(CDRW_RESET_DRIVER_USER_IN
));
4211 tmp
->UnlockTray
= (Unlock
? 1 : 0);
4212 tmp
->MagicWord
= 0x3a6 | (Unlock
? 1 : 0);
4213 RC
= UDFPhSendIOCTL(IOCTL_CDRW_RESET_DRIVER_EX
, TargetDeviceObject
,
4214 tmp
, sizeof(CDRW_RESET_DRIVER_USER_IN
), NULL
, 0, TRUE
,NULL
);
4216 Vcb
->LastReadTrack
= 0;
4217 Vcb
->LastModifiedTrack
= 0;
4218 Vcb
->OPCDone
= FALSE
;
4219 if((Vcb
->VCBFlags
& UDF_VCB_FLAGS_USE_CAV
) &&
4220 Vcb
->TargetDeviceObject
) {
4221 // limit both read & write speed to last write speed for CAV mode
4222 // some drives damage data when speed is adjusted during recording process
4223 // even in packet mode
4231 } // end UDFResetDeviceDriver()
4240 RtlZeroMemory(&(Vcb
->SpeedBuf
), sizeof(SET_CD_SPEED_EX_USER_IN
));
4241 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_USE_CAV
) {
4242 Vcb
->SpeedBuf
.RotCtrl
= CdSpeed_RotCtrl_CAV
;
4244 Vcb
->SpeedBuf
.ReadSpeed
=
4245 Vcb
->SpeedBuf
.WriteSpeed
= Vcb
->MaxWriteSpeed
;
4247 Vcb
->SpeedBuf
.ReadSpeed
= Vcb
->CurSpeed
;
4248 Vcb
->SpeedBuf
.WriteSpeed
= Vcb
->MaxWriteSpeed
;
4250 KdPrint((" UDFSetSpeeds: set speed to %s %dX/%dX\n",
4251 (Vcb
->VCBFlags
& UDF_VCB_FLAGS_USE_CAV
) ? "CAV" : "CLV",
4252 Vcb
->SpeedBuf
.ReadSpeed
/ 176,
4253 Vcb
->SpeedBuf
.WriteSpeed
/ 176));
4254 RC
= UDFPhSendIOCTL(IOCTL_CDRW_SET_SPEED
,
4255 Vcb
->TargetDeviceObject
,
4256 &(Vcb
->SpeedBuf
),sizeof(SET_CD_SPEED_EX_USER_IN
),
4258 KdPrint(("UDFSetSpeeds: %x\n", RC
));
4260 } // end UDFSetSpeeds()
4267 #pragma pack(push,1)
4269 MODE_PARAMETER_HEADER Header
;
4270 MODE_CACHING_PAGE Data
;
4275 MODE_PARAMETER_HEADER Header
;
4276 MODE_READ_WRITE_RECOVERY_PAGE Data
;
4285 MODE_SENSE_USER_IN ModeSenseCtl
;
4288 KdPrint(("UDFSetCaching:\n"));
4290 ModeSenseCtl
.PageCode
.Byte
= MODE_PAGE_ERROR_RECOVERY
;
4291 RC
= UDFPhSendIOCTL(IOCTL_CDRW_MODE_SENSE
, Vcb
->TargetDeviceObject
,
4292 &ModeSenseCtl
,sizeof(ModeSenseCtl
),
4293 (PVOID
)&RecoveryPage
,sizeof(RecoveryPage
),
4295 if(OS_SUCCESS(RC
)) {
4296 KdPrint((" Error recovery page:\n"
4309 "ReadRetryCount %d\n"
4310 "CorrectionSpan %d\n"
4311 "HeadOffsetCount %d\n"
4312 "DataStrobOffsetCount %d\n"
4314 "ErrorRecoveryParam2.Fields.EMCDR %d\n"
4316 "WriteRetryCount %d\n",
4318 RecoveryPage
.Data
.PageCode
,
4319 RecoveryPage
.Data
.PageLength
,
4321 RecoveryPage
.Data
.ErrorRecoveryParam
.Fields
.DCRBit
,
4322 RecoveryPage
.Data
.ErrorRecoveryParam
.Fields
.DTEBit
,
4323 RecoveryPage
.Data
.ErrorRecoveryParam
.Fields
.PERBit
,
4324 RecoveryPage
.Data
.ErrorRecoveryParam
.Fields
.EERBit
,
4325 RecoveryPage
.Data
.ErrorRecoveryParam
.Fields
.RCBit
,
4326 RecoveryPage
.Data
.ErrorRecoveryParam
.Fields
.TBBit
,
4327 RecoveryPage
.Data
.ErrorRecoveryParam
.Fields
.ARRE
,
4328 RecoveryPage
.Data
.ErrorRecoveryParam
.Fields
.AWRE
,
4330 RecoveryPage
.Data
.ReadRetryCount
,
4331 RecoveryPage
.Data
.CorrectionSpan
,
4332 RecoveryPage
.Data
.HeadOffsetCount
,
4333 RecoveryPage
.Data
.DataStrobOffsetCount
,
4335 RecoveryPage
.Data
.ErrorRecoveryParam2
.Fields
.EMCDR
,
4337 RecoveryPage
.Data
.WriteRetryCount
4342 ModeSenseCtl
.PageCode
.Byte
= MODE_PAGE_CACHING
;
4343 RC
= UDFPhSendIOCTL(IOCTL_CDRW_MODE_SENSE
, Vcb
->TargetDeviceObject
,
4344 &ModeSenseCtl
,sizeof(ModeSenseCtl
),
4345 (PVOID
)&CachingPage
,sizeof(CachingPage
),
4347 if(!OS_SUCCESS(RC
)) {
4351 KdPrint((" Caching page:\n"
4354 "ReadDisableCache %d\n"
4355 "MultiplicationFactor %d\n"
4356 "WriteCacheEnable %d\n"
4357 "WriteRetensionPriority %d\n"
4358 "ReadRetensionPriority %d\n",
4360 CachingPage
.Data
.PageCode
,
4361 CachingPage
.Data
.PageLength
,
4362 CachingPage
.Data
.ReadDisableCache
,
4363 CachingPage
.Data
.MultiplicationFactor
,
4364 CachingPage
.Data
.WriteCacheEnable
,
4365 CachingPage
.Data
.WriteRetensionPriority
,
4366 CachingPage
.Data
.ReadRetensionPriority
4369 RtlZeroMemory(&CachingPage
.Header
, sizeof(CachingPage
.Header
));
4370 CachingPage
.Data
.PageCode
= MODE_PAGE_CACHING
;
4371 CachingPage
.Data
.PageSavable
= 0;
4372 if( CachingPage
.Data
.ReadDisableCache
||
4373 !CachingPage
.Data
.WriteCacheEnable
) {
4374 CachingPage
.Data
.ReadDisableCache
= 0;
4375 CachingPage
.Data
.WriteCacheEnable
= 1;
4376 RC
= UDFPhSendIOCTL(IOCTL_CDRW_MODE_SELECT
, Vcb
->TargetDeviceObject
,
4377 (PVOID
)&CachingPage
,sizeof(CachingPage
.Header
) + 2 + CachingPage
.Data
.PageLength
,
4381 RC
= STATUS_SUCCESS
;
4383 KdPrint(("UDFSetCaching: %x\n", RC
));
4385 } // end UDFSetCaching()