1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3 // All rights reserved
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
6 /*
7 Module Name: Phys_lib.cpp
8
9 Execution: Kernel mode only
10
11 Description:
12
13 Contains code that implement read/write operations for physical device
14 */
15
16 #include "phys_lib.h"
17
18 static const char Signature [16] = {CDRW_SIGNATURE_v1};
19
20 // Local functions:
21
22 OSSTATUS
23 UDFSetSpeeds(
24 IN PVCB Vcb
25 );
26
27 NTSTATUS
28 UDFSetCaching(
29 IN PVCB Vcb
30 );
31
32 OSSTATUS
33 UDFRecoverFromError(
34 IN PVCB Vcb,
35 IN BOOLEAN WriteOp,
36 IN OSSTATUS status,
37 IN uint32 Lba,
38 IN uint32 BCount,
39 IN OUT uint32* retry);
40
41 #ifdef _BROWSE_UDF_
42
43 uint32
44 UDFFixFPAddress(
45 IN PVCB Vcb, // Volume control block from this DevObj
46 IN uint32 Lba
47 );
48
49 #endif //_BROWSE_UDF_
50
51 NTSTATUS
UDFSyncCache(IN PVCB Vcb)52 UDFSyncCache(
53 IN PVCB Vcb
54 )
55 {
56 UDFPrint(("UDFSyncCache:\n"));
57 OSSTATUS RC;
58 RC = UDFPhSendIOCTL( IOCTL_CDRW_SYNC_CACHE, Vcb->TargetDeviceObject,
59 NULL,0, NULL,0, FALSE, NULL);
60 if(OS_SUCCESS(RC)) {
61 // clear LAST_WRITE flag
62 Vcb->VCBFlags &= ~UDF_VCB_LAST_WRITE;
63 }
64 return RC;
65 } // end UDFSyncCache()
66
67
68 OSSTATUS
UDFReallocTrackMap(IN PVCB Vcb,IN uint32 TrackNum)69 UDFReallocTrackMap(
70 IN PVCB Vcb,
71 IN uint32 TrackNum
72 )
73 {
74 #ifdef _BROWSE_UDF_
75 if(Vcb->TrackMap) {
76 MyFreePool__(Vcb->TrackMap);
77 Vcb->TrackMap = NULL;
78 }
79 Vcb->TrackMap = (PUDFTrackMap)
80 MyAllocatePool__(NonPagedPool, TrackNum*sizeof(UDFTrackMap));
81 if(!Vcb->TrackMap) {
82 return STATUS_INSUFFICIENT_RESOURCES;
83 }
84 #endif //_BROWSE_UDF_
85 RtlZeroMemory(Vcb->TrackMap,TrackNum*sizeof(UDFTrackMap));
86 return STATUS_SUCCESS;
87 } // end UDFReallocTrackMap()
88
89 #ifdef _BROWSE_UDF_
90
91
92 OSSTATUS
93 __fastcall
UDFTIOVerify(IN void * _Vcb,IN void * Buffer,IN SIZE_T Length,IN uint32 LBA,OUT PSIZE_T IOBytes,IN uint32 Flags)94 UDFTIOVerify(
95 IN void* _Vcb,
96 IN void* Buffer, // Target buffer
97 IN SIZE_T Length,
98 IN uint32 LBA,
99 OUT PSIZE_T IOBytes,
100 IN uint32 Flags
101 )
102 {
103 OSSTATUS RC = STATUS_SUCCESS;
104 uint32 i, j;
105 SIZE_T mask;
106 uint32 lba0, len, lba1;
107 PUCHAR tmp_buff;
108 PUCHAR p;
109 PCHAR cached_block;
110 SIZE_T tmp_wb;
111 BOOLEAN need_remap;
112 OSSTATUS final_RC = STATUS_SUCCESS;
113 BOOLEAN zero;
114 BOOLEAN non_zero;
115 BOOLEAN packet_ok;
116 BOOLEAN free_tmp = FALSE;
117 BOOLEAN single_packet = FALSE;
118
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
122
123 if(Vcb->VerifyCtx.ItemCount > UDF_MAX_VERIFY_CACHE) {
124 UDFVVerify(Vcb, 0/*UFD_VERIFY_FLAG_WAIT*/);
125 }
126
127 UDFAcquireResourceExclusive(&(Vcb->IoResource), TRUE);
128 Flags |= PH_IO_LOCKED;
129
130 tmp_wb = (SIZE_T)_Vcb;
131 if(Flags & PH_EX_WRITE) {
132 UDFPrint(("IO-Write-Verify\n"));
133 RC = UDFTWrite(_Vcb, Buffer, Length, LBA, &tmp_wb, Flags | PH_VCB_IN_RETLEN);
134 } else {
135 UDFPrint(("IO-Read-Verify\n"));
136 RC = UDFTRead(_Vcb, Buffer, Length, LBA, &tmp_wb, Flags | PH_VCB_IN_RETLEN);
137 }
138 (*IOBytes) = tmp_wb;
139
140 switch(RC) {
141 default:
142 UDFReleaseResource(&(Vcb->IoResource));
143 return RC;
144 case STATUS_FT_WRITE_RECOVERY:
145 case STATUS_DEVICE_DATA_ERROR:
146 case STATUS_IO_DEVICE_ERROR:
147 break;
148 /* FALL THROUGH */
149 } // end switch(RC)
150
151 if(!Vcb->SparingCount ||
152 !Vcb->SparingCountFree ||
153 Vcb->CDR_Mode) {
154 UDFPrint(("Can't remap\n"));
155 UDFReleaseResource(&(Vcb->IoResource));
156 return RC;
157 }
158
159 if(Flags & PH_EX_WRITE) {
160 UDFPrint(("Write failed, try relocation\n"));
161 } else {
162 if(Vcb->Modified) {
163 UDFPrint(("Read failed, try relocation\n"));
164 } else {
165 UDFPrint(("no remap on not modified volume\n"));
166 UDFReleaseResource(&(Vcb->IoResource));
167 return RC;
168 }
169 }
170 if(Flags & PH_LOCK_CACHE) {
171 UDFReleaseResource(&(Vcb->IoResource));
172 WCacheStartDirect__(&(Vcb->FastCache), Vcb, TRUE);
173 UDFAcquireResourceExclusive(&(Vcb->IoResource), TRUE);
174 }
175
176 Flags &= ~PH_KEEP_VERIFY_CACHE;
177
178 // NOTE: SparingBlockSize may be not equal to PacketSize
179 // perform recovery
180 mask = Vcb->SparingBlockSize-1;
181 lba0 = LBA & ~mask;
182 len = ((LBA+(Length>>Vcb->BlockSizeBits)+mask) & ~mask) - lba0;
183 j=0;
184 if((lba0 == LBA) && (len == mask+1) && (len == (Length>>Vcb->BlockSizeBits))) {
185 single_packet = TRUE;
186 tmp_buff = NULL;
187 } else {
188 tmp_buff = (PUCHAR)DbgAllocatePoolWithTag(NonPagedPool, Vcb->SparingBlockSize << Vcb->BlockSizeBits, 'bNWD');
189 if(!tmp_buff) {
190 UDFPrint((" can't alloc tmp\n"));
191 UDFReleaseResource(&(Vcb->IoResource));
192 return STATUS_DEVICE_DATA_ERROR;
193 }
194 free_tmp = TRUE;
195 }
196
197 for(i=0; i<len; i++) {
198 if(!Vcb->SparingCountFree) {
199 UDFPrint((" no more free spare blocks, abort verification\n"));
200 break;
201 }
202 UDFPrint((" read LBA %x (%x)\n", lba0+i, j));
203 if(!j) {
204 need_remap = FALSE;
205 lba1 = lba0+i;
206 non_zero = FALSE;
207 if(single_packet) {
208 // single packet requested
209 tmp_buff = (PUCHAR)Buffer;
210 if(Flags & PH_EX_WRITE) {
211 UDFPrint((" remap single write\n"));
212 UDFPrint((" try del from verify cache @ %x, %x\n", lba0, len));
213 UDFVForget(Vcb, len, UDFRelocateSector(Vcb, lba0), 0);
214 goto do_remap;
215 } else {
216 UDFPrint((" recover and remap single read\n"));
217 }
218 }
219 }
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);
224
225 // check if block valid
226 if(Vcb->BSBM_Bitmap) {
227 if(UDFGetBit((uint32*)(Vcb->BSBM_Bitmap), UDFRelocateSector(Vcb, lba0+i))) {
228 UDFPrint((" remap: known BB @ %x, mapped to %x\n", lba0+i, UDFRelocateSector(Vcb, lba0+i)));
229 need_remap = TRUE;
230 }
231 }
232 zero = FALSE;
233 if(Vcb->FSBM_Bitmap) {
234 if(UDFGetFreeBit((uint32*)(Vcb->FSBM_Bitmap), lba0+i)) {
235 UDFPrint((" unused @ %x\n", lba0+i));
236 zero = TRUE;
237 }
238 }
239 if(!zero && Vcb->ZSBM_Bitmap) {
240 if(UDFGetZeroBit((uint32*)(Vcb->ZSBM_Bitmap), lba0+i)) {
241 UDFPrint((" unused @ %x (Z)\n", lba0+i));
242 zero = TRUE;
243 }
244 }
245 non_zero |= !zero;
246
247 if(!j) {
248 packet_ok = FALSE;
249 if(!single_packet) {
250 // try to read entire packet, this returs error more often then sequential reading of all blocks one by one
251 tmp_wb = (SIZE_T)_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);
254 } else {
255 // Note: we get here ONLY if original request failed
256 // do not retry if it was single-packet request
257 RC = STATUS_UNSUCCESSFUL;
258 }
259 if(RC == STATUS_SUCCESS) {
260 UDFPrint((" packet ok @ %x\n", lba0+i));
261 packet_ok = TRUE;
262 i += Vcb->SparingBlockSize-1;
263 continue;
264 } else {
265 need_remap = TRUE;
266 }
267 }
268
269 if(!zero) {
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)) {
273
274 tmp_wb = (SIZE_T)_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 UDFPrint((" Found BB @ %x\n", lba0+i));
279 }
280
281 }
282 RC = WCacheDirect__(&(Vcb->FastCache), _Vcb, lba0+i, FALSE, &cached_block, TRUE/* cached only */);
283 } else {
284 cached_block = NULL;
285 if(!packet_ok) {
286 RC = STATUS_UNSUCCESSFUL;
287 } else {
288 RC = STATUS_SUCCESS;
289 }
290 }
291 if(OS_SUCCESS(RC)) {
292 // cached or successfully read
293 if(cached_block) {
294 // we can get from cache the most fresh data
295 RtlCopyMemory(p, cached_block, Vcb->BlockSize);
296 }
297
298 } else {
299 if(!UDFVIsStored(Vcb, lba0+i)) {
300 tmp_wb = (SIZE_T)_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);
303 } else {
304 // get it from verify-cache
305 RC = STATUS_UNSUCCESSFUL;
306 }
307 if(!OS_SUCCESS(RC)) {
308 /*
309 UDFPrint((" 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);
313 */
314 UDFPrint((" 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);
317 need_remap = TRUE;
318 }
319 }
320 } else {
321 RtlZeroMemory(p, Vcb->BlockSize);
322 }
323 if(!packet_ok) {
324 UDFPrint((" try del from verify cache @ %x\n", lba0+i));
325 RC = UDFVForget(Vcb, 1, UDFRelocateSector(Vcb, lba0+i), 0);
326 }
327
328 if(!packet_ok || need_remap) {
329 UDFPrint((" block in bad packet @ %x\n", lba0+i));
330 if(Vcb->BSBM_Bitmap) {
331 UDFSetBit(Vcb->BSBM_Bitmap, lba0+i);
332 }
333 if(Vcb->FSBM_Bitmap) {
334 UDFSetUsedBit(Vcb->FSBM_Bitmap, lba0+i);
335 }
336 }
337
338 j++;
339 if(j >= Vcb->SparingBlockSize) {
340 // remap this packet
341 if(need_remap) {
342 ASSERT(!packet_ok);
343 if(!non_zero) {
344 UDFPrint((" forget Z packet @ %x\n", lba1));
345 UDFUnmapRange(Vcb, lba1, Vcb->SparingBlockSize);
346 RC = STATUS_SUCCESS;
347 } else {
348 do_remap:
349 for(j=0; j<3; j++) {
350 UDFPrint((" remap packet @ %x\n", lba1));
351 RC = UDFRemapPacket(Vcb, lba1, FALSE);
352 if(!OS_SUCCESS(RC)) {
353 if(RC == STATUS_SHARING_VIOLATION) {
354 UDFPrint((" remap2\n"));
355 // remapped location have died
356 RC = UDFRemapPacket(Vcb, lba1, TRUE);
357 }
358 if(!OS_SUCCESS(RC)) {
359 // packet cannot be remapped :(
360 RC = STATUS_DEVICE_DATA_ERROR;
361 }
362 }
363 UDFPrint((" remap status %x\n", RC));
364 if(OS_SUCCESS(RC)) {
365 // write to remapped area
366 tmp_wb = (SIZE_T)_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 UDFPrint((" write status %x\n", RC));
370 if(RC != STATUS_SUCCESS) {
371 // will be remapped
372 UDFPrint((" retry remap\n"));
373
374 // Note: when remap of already remapped block is requested, verify of
375 // entire sparing are will be performed.
376
377 } else {
378 UDFPrint((" remap OK\n"));
379 break;
380 }
381 } else {
382 UDFPrint((" failed remap\n"));
383 break;
384 }
385 } // for
386 }
387 if(!OS_SUCCESS(RC) && !OS_SUCCESS(final_RC)) {
388 final_RC = RC;
389 }
390 } else {
391 UDFPrint((" NO remap for @ %x\n", (lba0+i) & ~mask));
392 }
393 j=0;
394 }
395 }
396 if(free_tmp) {
397 DbgFreePool(tmp_buff);
398 }
399
400 tmp_wb = (SIZE_T)_Vcb;
401 if(Flags & PH_EX_WRITE) {
402 UDFPrint(("IO-Write-Verify (2)\n"));
403 //RC = UDFTWrite(_Vcb, Buffer, Length, LBA, &tmp_wb, Flags | PH_FORGET_VERIFIED | PH_VCB_IN_RETLEN);
404 } else {
405 UDFPrint(("IO-Read-Verify (2)\n"));
406 RC = UDFTRead(_Vcb, Buffer, Length, LBA, &tmp_wb, Flags | PH_FORGET_VERIFIED | PH_VCB_IN_RETLEN);
407 }
408 (*IOBytes) = tmp_wb;
409 UDFPrint(("Final %x\n", RC));
410
411 UDFReleaseResource(&(Vcb->IoResource));
412 if(Flags & PH_LOCK_CACHE) {
413 WCacheEODirect__(&(Vcb->FastCache), Vcb);
414 }
415
416 return RC;
417 } // end UDFTIOVerify()
418
419 OSSTATUS
UDFTWriteVerify(IN void * _Vcb,IN void * Buffer,IN SIZE_T Length,IN uint32 LBA,OUT PSIZE_T WrittenBytes,IN uint32 Flags)420 UDFTWriteVerify(
421 IN void* _Vcb,
422 IN void* Buffer, // Target buffer
423 IN SIZE_T Length,
424 IN uint32 LBA,
425 OUT PSIZE_T WrittenBytes,
426 IN uint32 Flags
427 )
428 {
429 return UDFTIOVerify(_Vcb, Buffer, Length, LBA, WrittenBytes, Flags | PH_VCB_IN_RETLEN | PH_EX_WRITE | PH_KEEP_VERIFY_CACHE);
430 } // end UDFTWriteVerify()
431
432 OSSTATUS
UDFTReadVerify(IN void * _Vcb,IN void * Buffer,IN SIZE_T Length,IN uint32 LBA,OUT PSIZE_T ReadBytes,IN uint32 Flags)433 UDFTReadVerify(
434 IN void* _Vcb,
435 IN void* Buffer, // Target buffer
436 IN SIZE_T Length,
437 IN uint32 LBA,
438 OUT PSIZE_T ReadBytes,
439 IN uint32 Flags
440 )
441 {
442 return UDFTIOVerify(_Vcb, Buffer, Length, LBA, ReadBytes, Flags | PH_VCB_IN_RETLEN | PH_KEEP_VERIFY_CACHE);
443 } // end UDFTReadVerify()
444 #endif //_BROWSE_UDF_
445
446 /*
447 This routine performs low-level write
448
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
451 */
452 OSSTATUS
UDFTWrite(IN void * _Vcb,IN void * Buffer,IN SIZE_T Length,IN uint32 LBA,OUT PSIZE_T WrittenBytes,IN uint32 Flags)453 UDFTWrite(
454 IN void* _Vcb,
455 IN void* Buffer, // Target buffer
456 IN SIZE_T Length,
457 IN uint32 LBA,
458 OUT PSIZE_T WrittenBytes,
459 IN uint32 Flags
460 )
461 {
462 #ifndef UDF_READ_ONLY_BUILD
463 #define Vcb ((PVCB)_Vcb)
464
465 #ifdef _BROWSE_UDF_
466 PEXTENT_MAP RelocExtent;
467 PEXTENT_MAP RelocExtent_saved = NULL;
468 #endif //_BROWSE_UDF_
469 uint32 retry;
470 BOOLEAN res_acq = FALSE;
471
472 OSSTATUS RC = STATUS_SUCCESS;
473 uint32 rLba;
474 uint32 BCount;
475 uint32 i;
476
477 #ifdef DBG
478 //ASSERT(!(LBA & (32-1)));
479 #endif //DBG
480
481 (*WrittenBytes) = 0;
482 BCount = Length>>Vcb->BlockSizeBits;
483
484 UDFPrint(("TWrite %x (%x)\n", LBA, BCount));
485 #ifdef _BROWSE_UDF_
486 if(Vcb->VCBFlags & UDF_VCB_FLAGS_DEAD) {
487 UDFPrint(("DEAD\n"));
488 return STATUS_NO_SUCH_DEVICE;
489 }
490
491 Vcb->VCBFlags |= (UDF_VCB_SKIP_EJECT_CHECK | UDF_VCB_LAST_WRITE);
492 if(!Vcb->CDR_Mode) {
493 RelocExtent = UDFRelocateSectors(Vcb, LBA, BCount);
494 if(!RelocExtent) {
495 UDFPrint(("can't relocate\n"));
496 return STATUS_INSUFFICIENT_RESOURCES;
497 }
498 rLba = LBA;
499 } else {
500 RelocExtent = UDF_NO_EXTENT_MAP;
501 rLba = Vcb->NWA;
502 }
503 #else //_BROWSE_UDF_
504 rLba = LBA;
505 #endif //_BROWSE_UDF_
506
507 #ifdef DBG
508 //ASSERT(!(rLba & (32-1)));
509 #endif //DBG
510
511 _SEH2_TRY {
512 #ifdef _BROWSE_UDF_
513
514 if(!(Flags & PH_IO_LOCKED)) {
515 UDFAcquireResourceExclusive(&(Vcb->IoResource), TRUE);
516 res_acq = TRUE;
517 }
518
519 if(RelocExtent == UDF_NO_EXTENT_MAP) {
520 #endif //_BROWSE_UDF_
521 retry = UDF_WRITE_MAX_RETRY;
522 retry_1:
523 RC = UDFPrepareForWriteOperation(Vcb, rLba, BCount);
524 if(!OS_SUCCESS(RC)) {
525 UDFPrint(("prepare failed\n"));
526 try_return(RC);
527 }
528 if(Flags & PH_VCB_IN_RETLEN) {
529 (*WrittenBytes) = (ULONG_PTR)Vcb;
530 }
531 RC = UDFPhWriteVerifySynchronous(Vcb->TargetDeviceObject, Buffer, Length,
532 ((uint64)rLba) << Vcb->BlockSizeBits, WrittenBytes, Flags);
533 #ifdef _BROWSE_UDF_
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)) )
538 goto retry_1;
539 UDFUpdateNWA((PVCB)_Vcb, rLba, BCount, RC);
540 try_return(RC);
541 #ifdef _BROWSE_UDF_
542 }
543 // write according to relocation table
544 RelocExtent_saved = RelocExtent;
545 for(i=0; RelocExtent->extLength; i++, RelocExtent++) {
546 SIZE_T _WrittenBytes;
547 rLba = RelocExtent->extLocation;
548 BCount = RelocExtent->extLength>>Vcb->BlockSizeBits;
549 retry = UDF_WRITE_MAX_RETRY;
550 retry_2:
551 RC = UDFPrepareForWriteOperation(Vcb, rLba, BCount);
552 if(!OS_SUCCESS(RC)) {
553 UDFPrint(("prepare failed (2)\n"));
554 break;
555 }
556 if(Flags & PH_VCB_IN_RETLEN) {
557 _WrittenBytes = (ULONG_PTR)Vcb;
558 }
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)) )
564 goto retry_2;
565 UDFUpdateNWA((PVCB)_Vcb, rLba, BCount, RC);
566 LBA += BCount;
567 (*WrittenBytes) += _WrittenBytes;
568 if(!OS_SUCCESS(RC)) break;
569 *((uint32*)&Buffer) += RelocExtent->extLength;
570 }
571 #endif //_BROWSE_UDF_
572 try_exit: NOTHING;
573 } _SEH2_FINALLY {
574 if(res_acq) {
575 UDFReleaseResource(&(Vcb->IoResource));
576 }
577 #ifdef _BROWSE_UDF_
578 if(RelocExtent_saved) {
579 MyFreePool__(RelocExtent_saved);
580 }
581 #endif //_BROWSE_UDF_
582 } _SEH2_END;
583 UDFPrint(("TWrite: %x\n", RC));
584 return RC;
585
586 #undef Vcb
587 #else //UDF_READ_ONLY_BUILD
588 return STATUS_ACCESS_DENIED;
589 #endif //UDF_READ_ONLY_BUILD
590 } // end UDFTWrite()
591
592 /*
593 This routine performs low-level read
594 */
595 OSSTATUS
UDFTRead(IN void * _Vcb,IN void * Buffer,IN SIZE_T Length,IN uint32 LBA,OUT PSIZE_T ReadBytes,IN uint32 Flags)596 UDFTRead(
597 IN void* _Vcb,
598 IN void* Buffer, // Target buffer
599 IN SIZE_T Length,
600 IN uint32 LBA,
601 OUT PSIZE_T ReadBytes,
602 IN uint32 Flags
603 )
604 {
605 uint32 rLba;
606 OSSTATUS RC = STATUS_SUCCESS;
607 uint32 retry;
608 PVCB Vcb = (PVCB)_Vcb;
609 uint32 BCount = Length >> Vcb->BlockSizeBits;
610 uint32 i;
611 #ifdef _BROWSE_UDF_
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;
617
618 ASSERT(Buffer);
619
620 (*ReadBytes) = 0;
621
622 if(Vcb->VCBFlags & UDF_VCB_FLAGS_DEAD)
623 return STATUS_NO_SUCH_DEVICE;
624
625 RelocExtent = UDFRelocateSectors(Vcb, LBA, BCount);
626 if(!RelocExtent) return STATUS_INSUFFICIENT_RESOURCES;
627
628 _SEH2_TRY {
629
630 if(!(Flags & PH_IO_LOCKED)) {
631 UDFAcquireResourceExclusive(&(Vcb->IoResource), TRUE);
632 res_acq = TRUE;
633 }
634
635 if(RelocExtent == UDF_NO_EXTENT_MAP) {
636 rLba = LBA;
637 if(rLba >= (Vcb->CDR_Mode ? Vcb->NWA : Vcb->LastLBA + 1)) {
638 RtlZeroMemory(Buffer, Length);
639 try_return(RC = STATUS_SUCCESS);
640 }
641 retry = UDF_WRITE_MAX_RETRY;
642 retry_1:
643 RC = UDFPrepareForReadOperation(Vcb, rLba, Length >> Vcb->BlockSizeBits);
644 if(!OS_SUCCESS(RC)) try_return(RC);
645 rLba = UDFFixFPAddress(Vcb, rLba);
646 #else
647 rLba = LBA;
648 retry = UDF_WRITE_MAX_RETRY;
649 retry_1:
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) = (SIZE_T)Vcb;
655 }
656 RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, Buffer, Length,
657 ((uint64)rLba) << Vcb->BlockSizeBits, ReadBytes, Flags);
658 Vcb->VCBFlags &= ~UDF_VCB_LAST_WRITE;
659 #ifdef _BROWSE_UDF_
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) {
665 goto retry_1;
666 }
667 RtlZeroMemory(Buffer, Length);
668 (*ReadBytes) = Length;
669 RC = STATUS_SUCCESS;
670 }
671 #ifdef _BROWSE_UDF_
672 try_return(RC);
673 }
674 // read according to relocation table
675 RelocExtent_saved = RelocExtent;
676 for(i=0; RelocExtent->extLength; i++, RelocExtent++) {
677 SIZE_T _ReadBytes;
678 rLba = RelocExtent->extLocation;
679 if(rLba >= (Vcb->CDR_Mode ? Vcb->NWA : Vcb->LastLBA + 1)) {
680 RtlZeroMemory(Buffer, _ReadBytes = RelocExtent->extLength);
681 RC = STATUS_SUCCESS;
682 goto TR_continue;
683 }
684 BCount = RelocExtent->extLength>>Vcb->BlockSizeBits;
685 retry = UDF_WRITE_MAX_RETRY;
686 retry_2:
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 = (SIZE_T)Vcb;
692 }
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) {
700 goto retry_2;
701 }
702 RtlZeroMemory(Buffer, RelocExtent->extLength);
703 _ReadBytes = RelocExtent->extLength;
704 RC = STATUS_SUCCESS;
705 }
706 TR_continue:
707 (*ReadBytes) += _ReadBytes;
708 if(!OS_SUCCESS(RC)) break;
709 *((uint32*)&Buffer) += RelocExtent->extLength;
710 }
711 try_exit: NOTHING;
712 } _SEH2_FINALLY {
713 if(res_acq) {
714 UDFReleaseResource(&(Vcb->IoResource));
715 }
716 if(RelocExtent_saved) {
717 MyFreePool__(RelocExtent_saved);
718 }
719 } _SEH2_END;
720 #endif //_BROWSE_UDF_
721 return RC;
722 } // end UDFTRead()
723
724 #ifdef UDF_ASYNC_IO
725 /*
726 This routine performs asynchronous low-level read
727 Is not used now.
728 */
729 OSSTATUS
UDFTReadAsync(IN void * _Vcb,IN void * _WContext,IN void * Buffer,IN SIZE_T Length,IN uint32 LBA,OUT PSIZE_T ReadBytes)730 UDFTReadAsync(
731 IN void* _Vcb,
732 IN void* _WContext,
733 IN void* Buffer, // Target buffer
734 IN SIZE_T Length,
735 IN uint32 LBA,
736 OUT PSIZE_T ReadBytes
737 )
738 {
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;
746 uint32 rLba;
747 uint32 BCount;
748
749 ASSERT(Buffer);
750
751 (*ReadBytes) = 0;
752
753 RelocExtent = UDFRelocateSectors(Vcb, LBA, BCount = Length >> Vcb->BlockSizeBits);
754 if(!RelocExtent) return STATUS_INSUFFICIENT_RESOURCES;
755 if(RelocExtent == UDF_NO_EXTENT_MAP) {
756 rLba = LBA;
757 if(rLba >= (Vcb->CDR_Mode ? Vcb->NWA : Vcb->LastLBA + 1)) {
758 RtlZeroMemory(Buffer, Length);
759 return STATUS_SUCCESS;
760 }
761 retry_1:
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)) )
771 goto retry_1;
772 return RC;
773 }
774 // read according to relocation table
775 RelocExtent_saved = RelocExtent;
776 for(uint32 i=0; RelocExtent->extLength; i++, RelocExtent++) {
777 SIZE_T _ReadBytes;
778 rLba = RelocExtent->extLocation;
779 if(rLba >= (Vcb->CDR_Mode ? Vcb->NWA : Vcb->LastLBA + 1)) {
780 RtlZeroMemory(Buffer, _ReadBytes = RelocExtent->extLength);
781 RC = STATUS_SUCCESS;
782 goto TR_continue;
783 }
784 BCount = RelocExtent->extLength>>Vcb->BlockSizeBits;
785 retry_2:
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)) )
795 goto retry_2;
796 TR_continue:
797 (*ReadBytes) += _ReadBytes;
798 if(!OS_SUCCESS(RC)) break;
799 *((uint32*)&Buffer) += RelocExtent->extLength;
800 }
801 MyFreePool__(RelocExtent_saved);
802 return RC;
803 } // end UDFTReadAsync()
804
805 #endif //UDF_ASYNC_IO
806
807 /*
808
809 */
810 NTSTATUS
UDFSetMRWMode(IN PVCB Vcb)811 UDFSetMRWMode(
812 IN PVCB Vcb
813 )
814 {
815 GET_MRW_MODE_USER_OUT MRWPage;
816 OSSTATUS RC;
817
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_
824
825 if(!Vcb->MRWStatus) {
826 UDFPrint(("Non-MRW disk. Skip setting MRW_MODE\n"));
827 return STATUS_SUCCESS;
828 }
829 UDFPrint(("try set MRW_MODE\n"));
830 RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_MRW_MODE, Vcb->TargetDeviceObject,
831 NULL,0,
832 (PVOID)&MRWPage,sizeof(MRWPage),
833 FALSE, NULL);
834 if(!NT_SUCCESS(RC)) {
835 return RC;
836 }
837 UDFPrint(("GET_MRW_MODE ok (current %x)\n", MRWPage.AddressMode));
838 MRWPage.AddressMode = Vcb->MRWStatus ? 0 : MrwPage_use_GAA;
839 UDFPrint(("SET_MRW_MODE %x\n", MRWPage.AddressMode));
840 RC = UDFPhSendIOCTL(IOCTL_CDRW_SET_MRW_MODE, Vcb->TargetDeviceObject,
841 (PVOID)&MRWPage,sizeof(MRWPage),
842 NULL,0,
843 FALSE, NULL);
844 UDFPrint(("SET_MRW_MODE status %x\n", RC));
845
846 return STATUS_SUCCESS;
847 } // end UDFSetMRWMode()
848
849 OSSTATUS
UDFDoOPC(IN PVCB Vcb)850 UDFDoOPC(
851 IN PVCB Vcb
852 )
853 {
854 OSSTATUS RC;
855 if(Vcb->OPCNum && !Vcb->OPCDone) {
856 UDFPrint(("UDFDoOPC\n"));
857 if(!Vcb->OPCh) {
858 Vcb->OPCh =
859 (PSEND_OPC_INFO_HEADER_USER_IN)MyAllocatePool__(NonPagedPool,
860 sizeof(SEND_OPC_INFO_HEADER_USER_IN) );
861 }
862 if(!Vcb->OPCh)
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),
868 NULL,0,
869 FALSE, NULL);
870 if(!OS_SUCCESS(RC)) {
871 UDFPrint(("UDFDoOPC failed\n"));
872 Vcb->OPCNum = 0;
873 // Vcb->VCBFlags |= UDF_VCB_FLAGS_OPC_FAILED;
874 }
875 Vcb->OPCDone = TRUE;
876 }
877 return RC;
878 } // end UDFDoOPC()
879
880 /*
881 This routine performs media-type dependent preparations
882 for write operation.
883
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.
891 */
892 OSSTATUS
UDFPrepareForWriteOperation(IN PVCB Vcb,IN uint32 Lba,IN uint32 BCount)893 UDFPrepareForWriteOperation(
894 IN PVCB Vcb,
895 IN uint32 Lba,
896 IN uint32 BCount
897 )
898 {
899 #ifndef UDF_READ_ONLY_BUILD
900 #ifdef UDF_FORMAT_MEDIA
901 PUDFFmtState fms = Vcb->fms;
902 #else
903 #define fms FALSE
904 #endif //UDF_FORMAT_MEDIA
905
906 #ifdef _UDF_STRUCTURES_H_
907 if(Vcb->BSBM_Bitmap) {
908 ULONG i;
909 for(i=0; i<BCount; i++) {
910 if(UDFGetBit((uint32*)(Vcb->BSBM_Bitmap), Lba+i)) {
911 UDFPrint(("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;
915 }
916 }
917 }
918 #endif //_UDF_STRUCTURES_H_
919
920 Vcb->VCBFlags |= UDF_VCB_LAST_WRITE;
921
922 if(
923 #ifdef _BROWSE_UDF_
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))
927 && !fms
928 ) ||
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)
934 ) {
935 UDFPrint(("Skip prepare for Write @%x\n", Lba));
936 return STATUS_SUCCESS;
937 }
938
939 // check if the device requires OPC before each write operation
940 UDFDoOPC(Vcb);
941
942 if(Vcb->SyncCacheState == SYNC_CACHE_RECOVERY_ATTEMPT) {
943 Vcb->SyncCacheState = SYNC_CACHE_RECOVERY_RETRY;
944 } else {
945 Vcb->SyncCacheState = SYNC_CACHE_RECOVERY_NONE;
946 }
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))
955 ) {
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 UDFPrint(("Skip prepare for Write (2) @%x\n", Lba));
960 return STATUS_SUCCESS;
961 }
962
963 UDFSetMRWMode(Vcb);
964
965 if(!UDFIsWriteParamsReq(Vcb)) {
966 #ifdef UDF_FORMAT_MEDIA
967 if(fms) {
968 return STATUS_SUCCESS;
969 }
970 #endif //UDF_FORMAT_MEDIA
971 }
972
973 for(uint32 i=Vcb->FirstTrackNum; i<=Vcb->LastTrackNum; i++) {
974 if((Vcb->TrackMap[i].FirstLba > Lba) ||
975 (Vcb->TrackMap[i].LastLba < Lba)) {
976 //UDFPrint(("not in track %d\n"));
977 continue;
978 }
979 OSSTATUS RC;
980 PGET_WRITE_MODE_USER_OUT WParams;
981
982 if(!UDFIsWriteParamsReq(Vcb)) {
983 RC = STATUS_SUCCESS;
984 goto check_dvd_bg_format;
985 }
986
987 if(!Vcb->WParams) {
988 Vcb->WParams =
989 (PGET_WRITE_MODE_USER_OUT)MyAllocatePool__(NonPagedPool, 512);
990 }
991 if(!(WParams = Vcb->WParams)) {
992 UDFPrint(("!WParams\n"));
993 return STATUS_INSUFFICIENT_RESOURCES;
994 }
995
996 RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_WRITE_MODE, Vcb->TargetDeviceObject,
997 NULL,0,
998 (void*)(Vcb->WParams),sizeof(GET_WRITE_MODE_USER_OUT),
999 FALSE, NULL);
1000 if(!OS_SUCCESS(RC)) {
1001 #ifdef UDF_FORMAT_MEDIA
1002 if(fms) {
1003 fms->SkipPrepareW = 1;
1004 MyFreePool__(WParams);
1005 return STATUS_SUCCESS;
1006 }
1007 #endif //UDF_FORMAT_MEDIA
1008 UDFPrint(("!get WParams\n"));
1009 return RC;
1010 }
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;
1016
1017 WParams->Byte3.Flags &= ~(WParam_TrkMode_Mask |
1018 WParam_TrkMode_AllowCpy |
1019 WParam_Copy);
1020 WParams->Byte3.Flags |= Vcb->TrackMap[i].TrackParam &
1021 (WParam_TrkMode_Mask |
1022 WParam_TrkMode_AllowCpy |
1023 WParam_Copy);
1024
1025 // set packet type (VP/FP)
1026 // if(opt_partition == PT_VAT15 ||
1027 // opt_blank_vat15)
1028 if(WParams->Byte2.Flags & WParam_LS_V) {
1029 WParams->LinkSize = 7;
1030 }
1031
1032 if(Vcb->TrackMap[i].DataParam & TrkInfo_Packet) {
1033 if((Vcb->TrackMap[i].DataParam & TrkInfo_FP) &&
1034 !Vcb->CDR_Mode) {
1035 WParams->Byte3.Flags |= WParam_FP;
1036 } else {
1037 WParams->Byte3.Flags &= ~WParam_FP;
1038 }
1039 } else {
1040 if(!Vcb->CDR_Mode) {
1041 WParams->Byte3.Flags |= WParam_FP;
1042 } else {
1043 WParams->Byte3.Flags &= ~WParam_FP;
1044 }
1045 }
1046
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;
1051 } else
1052 if(Vcb->LastSession > 1) {
1053 WParams->Byte3.Flags |= WParam_Multises_Final;
1054 } else {
1055 WParams->Byte3.Flags |= WParam_Multises_None;
1056 }
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) {
1060 // XA Mode2
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) {
1064 // Mode1
1065 WParams->Byte4.Flags |= WParam_BlkType_M1_2048;
1066 WParams->SesFmt = WParam_SesFmt_CdRom;
1067 } else {
1068 #ifdef UDF_FORMAT_MEDIA
1069 if(fms) {
1070 fms->SkipPrepareW = 1;
1071 MyFreePool__(WParams);
1072 return STATUS_SUCCESS;
1073 }
1074 #endif //UDF_FORMAT_MEDIA
1075 UDFPrint((" inv sector mode\n"));
1076 return STATUS_INVALID_PARAMETER;
1077 }
1078 // set packet size
1079 *((uint32*)&(WParams->PacketSize)) = BCount;
1080 *((uint32*)&(WParams->SubHeader)) = 0;
1081 // set additional flags for VP
1082
1083 if(Vcb->CDR_Mode) {
1084 // if(opt_partition == PT_VAT15)
1085 WParams->SubHeader.Params.Params1.SubMode = WParam_SubHdr_SubMode1;
1086 }
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),
1092 NULL,0,FALSE,NULL);
1093
1094 #ifdef UDF_FORMAT_MEDIA
1095 if(fms) {
1096 if(!NT_SUCCESS(RC)) {
1097 fms->SkipPrepareW = 1;
1098 MyFreePool__(WParams);
1099 return STATUS_SUCCESS;
1100 }
1101
1102 RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_WRITE_MODE, Vcb->TargetDeviceObject,
1103 NULL,0,
1104 (PVOID)WParams,sizeof(GET_WRITE_MODE_USER_OUT),
1105 FALSE, NULL);
1106 if(!NT_SUCCESS(RC)) {
1107 MyFreePool__(WParams);
1108 return RC;
1109 }
1110
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;
1116 }
1117 } else {
1118 if(!(WParams->Byte3.Flags & WParam_FP)) {
1119 MyFreePool__(WParams);
1120 return STATUS_INVALID_DEVICE_STATE;
1121 }
1122 }
1123 }
1124 #endif //UDF_FORMAT_MEDIA
1125
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);
1132
1133 check_dvd_bg_format:
1134
1135 UDFPrint((" 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;
1142 } else {
1143 Vcb->TrackMap[i].Flags |= TrackMap_Try_variation;
1144 }
1145 }
1146 }
1147 } else {
1148 Vcb->LastModifiedTrack = 0;
1149 }
1150 // fms->SkipPrepareW = 1;
1151
1152
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)) {
1158
1159 ULONG fLba;
1160 SIZE_T WrittenBytes;
1161 ULONG PSz = BCount << Vcb->BlockSizeBits;
1162 #ifdef _BROWSE_UDF_
1163 ULONG retry;
1164 #endif //_BROWSE_UDF_
1165 PFORMAT_CDRW_PARAMETERS_USER_IN ForBuf;
1166
1167 ASSERT((Vcb->LastLBA+1) == Vcb->NWA);
1168
1169 if(Lba+BCount <= (Vcb->LastLBA+1) ) {
1170 UDFPrint(("DVD cont. fmt, LBA+BCount<=NWA, exiting\n"));
1171 return STATUS_SUCCESS;
1172 }
1173 if((Vcb->MRWStatus != DiscInfo_BGF_Interrupted) &&
1174 (Lba <= (Vcb->LastLBA+1)) ) {
1175 UDFPrint(("!PausedBGF + DVD cont. fmt, LBA<=NWA, exiting\n"));
1176 return STATUS_SUCCESS;
1177 }
1178
1179 if(Vcb->MRWStatus == DiscInfo_BGF_Interrupted) {
1180 // This code also can restart background MRW formatting
1181 UDFPrint(("DVD cont. fmt, LastLBA %x, Lba %x\n", Vcb->LastLBA, Lba));
1182
1183 ForBuf = (PFORMAT_CDRW_PARAMETERS_USER_IN)DbgAllocatePoolWithTag(NonPagedPool, sizeof(FORMAT_CDRW_PARAMETERS_USER_IN), 'zNWD');
1184 if(ForBuf) {
1185 RtlZeroMemory(ForBuf, sizeof(FORMAT_CDRW_PARAMETERS_USER_IN));
1186 ForBuf->Flags.FlagsEx = FORMAT_UNIT_RESTART_MRW;
1187 ForBuf->BlockCount = 0xffffffff;
1188
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 UDFPrint(("BGFormat restarted Interrupted->InProgress\n"));
1195 Vcb->MRWStatus = DiscInfo_BGF_InProgress;
1196 } else {
1197 PGET_LAST_ERROR_USER_OUT Error = NULL;
1198 if(!Vcb->Error) {
1199 Vcb->Error = (PGET_LAST_ERROR_USER_OUT)
1200 MyAllocatePool__(NonPagedPool, sizeof(GET_LAST_ERROR_USER_OUT));
1201 }
1202 Error = Vcb->Error;
1203 if(Error) {
1204 UDFPhSendIOCTL( IOCTL_CDRW_GET_LAST_ERROR, Vcb->TargetDeviceObject,
1205 NULL,0,
1206 Error,sizeof(GET_LAST_ERROR_USER_OUT),
1207 TRUE,NULL);
1208 UDFPrint(("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 UDFPrint(("Seems, BGFormat already restarted\n"));
1217 Vcb->MRWStatus = DiscInfo_BGF_InProgress;
1218 }
1219 }
1220 }
1221 }
1222 } else {
1223 RC = STATUS_SUCCESS;
1224 }
1225
1226 UDFPrint(("DVD cont. write, LastLBA %x, Lba %x\n", Vcb->LastLBA, Lba));
1227
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;
1233 } else
1234 if(Vcb->fZBufferSize < PSz) {
1235 PSz = Vcb->fZBufferSize;
1236 }
1237 if(!Vcb->fZBuffer) {
1238 BrutePoint();
1239 RC = STATUS_INSUFFICIENT_RESOURCES;
1240 } else {
1241 for(fLba = Vcb->NWA; fLba < Lba; fLba+=BCount) {
1242 #ifdef _BROWSE_UDF_
1243 retry = UDF_WRITE_MAX_RETRY;
1244 retry_1:
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 UDFPrint(("Fmt status: %x\n", RC));
1250 #ifdef _BROWSE_UDF_
1251 if(!OS_SUCCESS(RC) &&
1252 OS_SUCCESS(RC = UDFRecoverFromError(Vcb, TRUE, RC, fLba, BCount, &retry)) ) {
1253 goto retry_1;
1254 UDFPrint(("Fmt retry\n"));
1255 }
1256 #endif //_BROWSE_UDF_
1257 if(!OS_SUCCESS(RC)) {
1258 BrutePoint();
1259 UDFPrint(("Fmt break on ERROR\n"));
1260 break;
1261 }
1262 UDFUpdateNWA(Vcb, fLba, BCount, RC);
1263 }
1264 }
1265 } else {
1266 UDFPrint((" no special processing\n"));
1267 }
1268
1269 return RC;
1270 }
1271 #endif //UDF_READ_ONLY_BUILD
1272 UDFPrint((" no suitable track!\n"));
1273 return STATUS_INVALID_PARAMETER;
1274 } // end UDFPrepareForWriteOperation()
1275
1276 //#ifdef _BROWSE_UDF_
1277 /*
1278 This routine tries to recover from hardware error
1279 Return: STATUS_SUCCESS - retry requst
1280 STATUS_XXX - unrecoverable error
1281 */
1282 OSSTATUS
UDFRecoverFromError(IN PVCB Vcb,IN BOOLEAN WriteOp,IN OSSTATUS status,IN uint32 Lba,IN uint32 BCount,IN OUT uint32 * retry)1283 UDFRecoverFromError(
1284 IN PVCB Vcb,
1285 IN BOOLEAN WriteOp,
1286 IN OSSTATUS status,
1287 IN uint32 Lba,
1288 IN uint32 BCount,
1289 IN OUT uint32* retry
1290 )
1291 {
1292 PGET_LAST_ERROR_USER_OUT Error = NULL;
1293 LARGE_INTEGER delay;
1294 // OSSTATUS RC;
1295 uint32 i;
1296 BOOLEAN UpdateBB = FALSE;
1297
1298 if(!(*retry) ||
1299 !(Vcb->VCBFlags & UDF_VCB_FLAGS_OUR_DEVICE_DRIVER) ||
1300 (Vcb->FsDeviceType != FILE_DEVICE_CD_ROM_FILE_SYSTEM))
1301 return status;
1302 (*retry)--;
1303 // allocate tmp buffer
1304 _SEH2_TRY {
1305 if(!Vcb->Error) {
1306 if(!(Vcb->Error = (PGET_LAST_ERROR_USER_OUT)
1307 MyAllocatePool__(NonPagedPool, sizeof(GET_LAST_ERROR_USER_OUT))))
1308 try_return(status);
1309 }
1310 if(status == STATUS_NO_SUCH_DEVICE) {
1311 UDFPrint(("Error recovery: STATUS_NO_SUCH_DEVICE, die.....\n"));
1312 Vcb->VCBFlags |= UDF_VCB_FLAGS_UNSAFE_IOCTL | UDF_VCB_FLAGS_DEAD;
1313 try_return(status);
1314 }
1315
1316 #ifdef _UDF_STRUCTURES_H_
1317 if(status == STATUS_NO_MEDIA_IN_DEVICE && !Vcb->EjectWaiter) {
1318 UDFPrint(("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--;
1323 try_return(status);
1324 }
1325 #endif //_UDF_STRUCTURES_H_
1326
1327 Error = Vcb->Error;
1328 UDFPhSendIOCTL( IOCTL_CDRW_GET_LAST_ERROR, Vcb->TargetDeviceObject,
1329 NULL,0,
1330 Error,sizeof(GET_LAST_ERROR_USER_OUT),
1331 TRUE,NULL);
1332 UDFPrint(("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...
1339 if(WriteOp) {
1340 if((*retry) == UDF_WRITE_MAX_RETRY-1) {
1341 UDFPrint(("Error recovery: reserve retry count for write retries\n"));
1342 (*retry) = UDF_WRITE_MAX_RETRY*3;
1343 } else
1344 if((*retry) == UDF_WRITE_MAX_RETRY) {
1345 UDFPrint(("Error recovery: jump over UDF_WRITE_MAX_RETRY\n"));
1346 (*retry)--;
1347 }
1348 delay.QuadPart = -500000; // 0.05 sec
1349 KeDelayExecutionThread(KernelMode, FALSE, &delay);
1350 if(WriteOp && ((*retry) > UDF_WRITE_MAX_RETRY-1)) {
1351 UDFPrint(("Error recovery: simple write retry with delay\n"));
1352 try_return(status = STATUS_SUCCESS);
1353 }
1354 } else {
1355 delay.QuadPart = -500000; // 0.05 sec
1356 KeDelayExecutionThread(KernelMode, FALSE, &delay);
1357 if((*retry) == UDF_WRITE_MAX_RETRY-1) {
1358 UDFPrint(("Error recovery: retry read after small delay\n"));
1359 try_return(status = STATUS_SUCCESS);
1360 }
1361 }
1362 UDFPrint(("Error recovery: sync cache\n"));
1363 // ...flush device cache...
1364 UDFSyncCache(Vcb);
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);
1372 } else
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 UDFPrint(("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);
1388 } else
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
1393 if(!WriteOp) {
1394 UDFPrint(("Error recovery: invalid command sequence on read\n"));
1395 delay.QuadPart = -1000000; // 0.1 sec
1396 KeDelayExecutionThread(KernelMode, FALSE, &delay);
1397 UDFPrint(("Error recovery: sync cache\n"));
1398 // ...flush device cache...
1399 UDFSyncCache(Vcb);
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);
1407 }
1408 goto reinit_sector_mode;
1409 } else
1410 // check for Bus Reset (sometimes it happends...)
1411 if((Error->SenseKey == SCSI_SENSE_UNIT_ATTENTION) &&
1412 (Error->AdditionalSenseCode == SCSI_ADSENSE_BUS_RESET) ) {
1413 // we should wait
1414 UDFPrint(("Error recovery: bus reset...\n"));
1415 Vcb->MediaChangeCount = Error->MediaChangeCount;
1416 delay.QuadPart = -1000000; // 0.1 sec
1417 KeDelayExecutionThread(KernelMode, FALSE, &delay);
1418 // reset driver
1419 UDFResetDeviceDriver(Vcb, Vcb->TargetDeviceObject, FALSE);
1420 delay.QuadPart = -1000000; // 0.1 sec
1421 KeDelayExecutionThread(KernelMode, FALSE, &delay);
1422 // lock it
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),
1427 NULL,0,
1428 FALSE,NULL);
1429 delay.QuadPart = -1000000; // 0.1 sec
1430 KeDelayExecutionThread(KernelMode, FALSE, &delay);*/
1431
1432 // reinit write mode the following is performed inside UDFResetDeviceDriver()
1433 //Vcb->LastModifiedTrack = 0;
1434 //Vcb->OPCDone = FALSE;
1435
1436 reinit_sector_mode:
1437 // reinit sector mode
1438 Vcb->LastModifiedTrack = 0;
1439 UDFPrepareForWriteOperation(Vcb, Lba, BCount);
1440 try_return(status = STATUS_SUCCESS);
1441 } else
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:
1451 if(WriteOp) {
1452
1453 if((*retry) <= 1) {
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))
1458 continue;
1459 /* if(Vcb->TrackMap[i].Flags & TrackMap_CopyBit_variated)
1460 // Last chance....
1461 goto reinit_sector_mode;*/
1462
1463 // check if we have successuflly completed WriteOp
1464 // using Variation.
1465 // We should not variate these bits again in this case.
1466 if(Vcb->TrackMap[i].Flags & TrackMap_Use_variation)
1467 break;
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)))
1472 break;*/
1473 /* if(Vcb->TrackMap[i].Flags & TrackMap_Use_variation)
1474 break;*/
1475 Vcb->TrackMap[i].Flags |= TrackMap_Try_variation;
1476 // 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) ) {
1481 (*retry) = 1;
1482 } else {
1483 Vcb->TrackMap[i].Flags &= ~TrackMap_Try_variation;
1484 }
1485 // reinit sector mode
1486 Vcb->LastModifiedTrack = 0;
1487 UDFPrepareForWriteOperation(Vcb, Lba, BCount);
1488 break;
1489 }
1490 } else {
1491 // Reinit...
1492 //reinit_sector_mode:
1493 // we should wait
1494 delay.QuadPart = -1000000; // 0.1 sec
1495 KeDelayExecutionThread(KernelMode, FALSE, &delay);
1496 // reinit sector mode
1497 goto reinit_sector_mode;
1498 /*
1499 Vcb->LastModifiedTrack = 0;
1500 UDFPrepareForWriteOperation(Vcb, Lba, BCount);
1501 try_return(status = STATUS_SUCCESS);
1502 */
1503 }
1504 } else
1505 if((Vcb->CompatFlags & UDF_VCB_IC_BAD_RW_SEEK) &&
1506 (Vcb->IncrementalSeekState != INCREMENTAL_SEEK_DONE)) {
1507 UDFPrint(("Using incremental seek workaround...\n"));
1508 Vcb->IncrementalSeekState = INCREMENTAL_SEEK_WORKAROUND;
1509 try_return(status = STATUS_SUCCESS);
1510 } else {
1511 UDFPrint(("Seems to be BB @ %x\n", Lba));
1512 UpdateBB = TRUE;
1513 }
1514 } else
1515 if((Error->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) &&
1516 (Error->AdditionalSenseCode == SCSI_ADSENSE_INVALID_SESSION_MODE)) {
1517 if(WriteOp &&
1518 (Vcb->SavedFeatures & CDRW_FEATURE_STREAMING) &&
1519 Lba+BCount <= Vcb->LastLBA+1) {
1520 UDFPrint(("bad Session in streaming mode. Lba %x, try fix-up\n", Lba));
1521 // ...flush device cache...
1522 UDFSyncCache(Vcb);
1523 // we should wait
1524 delay.QuadPart = -10000000; // 1 sec
1525 KeDelayExecutionThread(KernelMode, FALSE, &delay);
1526 try_return(status = STATUS_SUCCESS);
1527 }
1528 } else
1529 if((Error->LastError == CDRW_ERR_WRITE_IN_PROGRESS_BUSY) ||
1530 (status == STATUS_DEVICE_BUSY)) {
1531 delay.QuadPart = -5000000; // 0.5 sec
1532 UDFPrint(("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);
1538 } else
1539 // some devices (SONY) return such a strange sequence....
1540 if( ((Error->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) &&
1541 (Error->AdditionalSenseCode == SCSI_ADSENSE_INVALID_CDB)) &&
1542 WriteOp) {
1543 // reinit write mode
1544 Vcb->LastModifiedTrack = 0;
1545 UDFPrepareForWriteOperation(Vcb, Lba, BCount);
1546 try_return(status = STATUS_SUCCESS);
1547 } else
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))*/ &&
1554 !WriteOp) {
1555 if(Error->AdditionalSenseCode == SCSI_ADSENSE_SEEK_ERROR) {
1556 UDFPrint(("Seek error\n"));
1557 if(Vcb->CompatFlags & UDF_VCB_IC_BAD_RW_SEEK) {
1558 UDFPrint(("try recovery\n"));
1559 goto bad_rw_seek_recovery;
1560 }
1561 UDFPrint(("map error to STATUS_NONEXISTENT_SECTOR\n"));
1562 status = STATUS_NONEXISTENT_SECTOR;
1563 }
1564 UDFPrint(("Seems to be BB @ %x (read 2)\n", Lba));
1565 UpdateBB = TRUE;
1566 } else
1567 // handle invalid block address
1568 if( ((Error->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) &&
1569 (Error->AdditionalSenseCode == SCSI_ADSENSE_ILLEGAL_BLOCK)) ) {
1570 if(!WriteOp &&
1571 (Vcb->SavedFeatures & CDRW_FEATURE_STREAMING) &&
1572 Lba+BCount <= Vcb->LastLBA+1) {
1573 UDFPrint(("bad LBA %x in streaming mode, try fix-up\n", Lba));
1574 // ...flush device cache...
1575 UDFSyncCache(Vcb);
1576 try_return(status = STATUS_SUCCESS);
1577 }
1578
1579 if((Lba+BCount >= Vcb->LastLBA) &&
1580 (Vcb->MRWStatus == DiscInfo_BGF_Interrupted)) {
1581 UDFPrint(("stupid drive, cannot read beyond formatted area on DiscInfo_BGF_Interrupted\n"));
1582 UpdateBB = FALSE;
1583 try_return(status = STATUS_BUFFER_ALL_ZEROS);
1584 }
1585 // prevent Bad Block Bitmap modification
1586 }
1587
1588 try_exit: NOTHING;
1589
1590 } _SEH2_FINALLY {
1591 #ifdef UDF_DBG
1592 if(OS_SUCCESS(status)) {
1593 UDFPrint(("Retry\n"));
1594 }
1595 #endif //UDF_DBG
1596 } _SEH2_END;
1597 if(!OS_SUCCESS(status)) {
1598 if((Vcb->MountPhErrorCount != (ULONG)-1) &&
1599 (Vcb->MountPhErrorCount < 0x7fffffff)) {
1600 Vcb->MountPhErrorCount++;
1601 }
1602 //#ifdef _UDF_STRUCTURES_H_
1603 if(UpdateBB && (BCount == 1)) {
1604 uint32* bm;
1605 if(!(bm = (uint32*)(Vcb->BSBM_Bitmap))) {
1606 bm = (uint32*)(Vcb->BSBM_Bitmap = (int8*)DbgAllocatePoolWithTag(NonPagedPool, (i = (Vcb->LastPossibleLBA+1+7)>>3), 'mNWD' ));
1607 if(bm) {
1608 RtlZeroMemory(bm, i);
1609 } else {
1610 UDFPrint(("Can't alloc BSBM for %x blocks\n", Vcb->LastPossibleLBA));
1611 }
1612 }
1613 if(bm) {
1614 UDFSetBit(bm, Lba);
1615 UDFPrint(("Set BB @ %#x\n", Lba));
1616 }
1617 #ifdef _BROWSE_UDF_
1618 bm = (uint32*)(Vcb->FSBM_Bitmap);
1619 if(bm) {
1620 UDFSetUsedBit(bm, Lba);
1621 UDFPrint(("Set BB @ %#x as used\n", Lba));
1622 }
1623 #endif //_BROWSE_UDF_
1624 }
1625 //#endif //_UDF_STRUCTURES_H_
1626 }
1627 return status;
1628 } // end UDFRecoverFromError()
1629
1630 //#endif //_BROWSE_UDF_
1631 /*
1632 This routine attempts to read disk layout using ReadDisk/Track info cmd
1633 */
1634 OSSTATUS
UDFReadDiscTrackInfo(PDEVICE_OBJECT DeviceObject,PVCB Vcb)1635 UDFReadDiscTrackInfo(
1636 PDEVICE_OBJECT DeviceObject, // the target device object
1637 PVCB Vcb // Volume Control Block for ^ DevObj
1638 )
1639 {
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;
1645 LONG TrackNumber;
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;
1653 #endif
1654
1655 _SEH2_TRY {
1656 if(!DiscInfo || !TrackInfoOut)
1657 try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
1658
1659 MRWRetry_label:
1660
1661 RC = UDFPhSendIOCTL(IOCTL_CDRW_READ_DISC_INFO, DeviceObject,
1662 NULL, 0,
1663 DiscInfo,sizeof(DISC_INFO_BLOCK_USER_OUT), TRUE, NULL);
1664 if(!OS_SUCCESS(RC)) {
1665 UDFPrint(("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;
1670 } else
1671 if(Vcb->MediaClassEx == CdMediaClass_BDRE) {
1672 Vcb->LastPossibleLBA = DEFAULT_LAST_LBA_BD;
1673 } else {
1674 Vcb->LastPossibleLBA = DEFAULT_LAST_LBA_FP_CD;
1675 }
1676 try_return(RC);
1677 }
1678 #ifdef UDF_FORMAT_MEDIA
1679 if(fms && fms->opt_disk_info) {
1680 UserPrint(("ReadDiskInfo OK\n"));
1681 }
1682 #endif //UDF_FORMAT_MEDIA
1683
1684 RC = UDFPhSendIOCTL(IOCTL_CDRW_READ_CAPACITY, DeviceObject,
1685 NULL, 0,
1686 &CapacityBuffer,sizeof(READ_CAPACITY_USER_OUT), TRUE, NULL);
1687 if(!OS_SUCCESS(RC)) {
1688 UDFPrint(("ReadCapacity failed.\n"));
1689 if(Vcb->MediaClassEx == CdMediaClass_DVDpRW) {
1690 Vcb->LastPossibleLBA = DEFAULT_LAST_LBA_DVD;
1691 }
1692 } else {
1693 UDFPrint(("ReadCapacity ok.\n"));
1694 UDFPrint(("Last possible LBA %#x.\n", CapacityBuffer.LogicalBlockAddress));
1695 if(!(CapacityBuffer.LogicalBlockAddress & 0xc0000000) &&
1696 (CapacityBuffer.LogicalBlockAddress != 0x7fffffff)) {
1697 // good value from ReadCapacity
1698 UDFPrint(("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"));
1704 }
1705 #endif //UDF_FORMAT_MEDIA
1706 }
1707 }
1708
1709 #ifdef _CONSOLE
1710 Vcb->PhDeviceType = FILE_DEVICE_CD_ROM;
1711 #endif //_CONSOLE
1712 Vcb->PhSerialNumber = *((uint32*)&(DiscInfo->DiskId));
1713 Vcb->PhErasable = DiscInfo->DiscStat.Flags & DiscInfo_Disk_Erasable;
1714 Vcb->PhDiskType = DiscInfo->DiskType;
1715 // save OPC info
1716 if(DiscInfo->OPCNum)
1717 Vcb->OPCNum = DiscInfo->OPCNum;
1718 UDFPrint(("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;
1744 }
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"));
1751 break;
1752 case DiscInfo_Disk_Appendable:
1753 UserPrint(("Appendable\n"));
1754 break;
1755 case DiscInfo_Disk_Complete:
1756 UserPrint(("Complete\n"));
1757 break;
1758 case DiscInfo_Disk_OtherRW:
1759 UserPrint(("RW in unknown state\n"));
1760 break;
1761 }
1762 UserPrint(("Last Session State: "));
1763 switch(DiscInfo->DiscStat.Flags & DiscInfo_Ses_Mask) {
1764 case DiscInfo_Ses_Empty:
1765 UserPrint(("Empty\n"));
1766 break;
1767 case DiscInfo_Ses_Incomplete:
1768 UserPrint(("Incomplete\n"));
1769 break;
1770 case DiscInfo_Ses_Complete:
1771 UserPrint(("Complete\n"));
1772 break;
1773 default:
1774 UserPrint(("unknown state\n"));
1775 break;
1776 }
1777 UserPrint(("Erasable: %s\n",
1778 (DiscInfo->DiscStat.Flags & DiscInfo_Disk_Erasable) ? "yes" : "no"
1779 ));
1780 }
1781 #endif //UDF_FORMAT_MEDIA
1782 // Save disk status
1783 Vcb->DiscStat = DiscInfo->DiscStat.Flags;
1784 if((DiscInfo->DiscStat.Flags & DiscInfo_Disk_Mask) == DiscInfo_Disk_Empty) {
1785 UDFPrint(("Blank\n"));
1786 Vcb->BlankCD = TRUE;
1787 }
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 UDFPrint(("Try RAW_MOUNT\n"));
1794 Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK;
1795 PacketTrack = TRUE;
1796 }
1797
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 &&
1802 !ReadCapacityOk) {
1803 // +RW returns bad value
1804 UDFPrint(("+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);
1809 }
1810 }
1811 #endif // _BROWSE_UDF_
1812 if((DiscInfo->Flags.Flags & DiscInfo_BGF_Mask) != 0) {
1813 UDFPrint(("ForceFP + MRW\n"));
1814 ForceFP = TRUE;
1815 Vcb->MRWStatus = DiscInfo->Flags.Flags & DiscInfo_BGF_Mask;
1816 // update addressing mode
1817 if(!MRWRetry) {
1818 UDFSetMRWMode(Vcb);
1819 MRWRetry = TRUE;
1820 goto MRWRetry_label;
1821 }
1822 }
1823 UDFPrint(("MRW state %x\n", Vcb->MRWStatus));
1824 if(Vcb->MediaClassEx == CdMediaClass_DVDRW) {
1825 if(Vcb->PhMediaCapFlags & CdCapFlags_RandomWritable) {
1826 UDFPrint(("DVD-RW Rewritable\n"));
1827 ForceFP = TRUE;
1828 } else
1829 if((DiscInfo->DiscStat.Flags & DiscInfo_Disk_Mask) == DiscInfo_Disk_Empty) {
1830 UDFPrint(("Blank DVD-RW\n"));
1831 ForceFP = TRUE;
1832 } else {
1833 UDFPrint(("DVD-RW Sequential\n"));
1834 NotFP = TRUE;
1835 }
1836 } else
1837 if(CdrwIsDvdOverwritable(Vcb->MediaClassEx)) {
1838 UDFPrint(("force Rewritable (2)\n"));
1839 ForceFP = TRUE;
1840 }
1841 // We have incomplete last session, so process each track from last to first
1842 // Vcb->LastPossibleLBA = DiscInfo->LastSesLeadInLBA;
1843
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 UDFPrint(("Try read 1st track...\n"));
1851 Vcb->LastTrackNum = 1;
1852 }
1853 UDFPrint(("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"));
1859 }
1860 #endif //UDF_FORMAT_MEDIA
1861
1862 RC = UDFReallocTrackMap(Vcb, Vcb->LastTrackNum+1);
1863 if(!OS_SUCCESS(RC))
1864 try_return(RC);
1865
1866 // Get last LBA from invisible track (if any)
1867 RtlZeroMemory(TrackInfoOut,sizeof(TRACK_INFO_BLOCK_USER_OUT));
1868
1869 TrackInfoIn->LBA_TrkNum = 0; // invisible track
1870 TrackInfoIn->Track = TRUE;
1871
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 UDFPrint((" set LastPossibleLBA=%x\n", Vcb->LastPossibleLBA));
1886 }
1887 }
1888
1889 UDFPrint(("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,
1893 0,
1894 TrackInfoOut->TrackStartLBA,
1895 TrackInfoOut->TrackLength,
1896 TrackInfoOut->FixPacketSize,
1897
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" : "",
1905
1906 TrackInfoOut->TrackParam.Flags & TrkInfo_Trk_Mask,
1907 (TrackInfoOut->TrackParam.Flags & TrkInfo_Copy) ? "Cpy" : "",
1908 (TrackInfoOut->TrackParam.Flags & TrkInfo_Damage) ? "Damage" : "",
1909
1910 TrackInfoOut->LastRecordedAddr,
1911 (TrackInfoOut->NWA_V & TrkInfo_LRA_V) ? "vld" : "inv",
1912
1913 TrackInfoOut->ReadCompatLBA
1914 ));
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,
1922 0,
1923 TrackInfoOut->TrackStartLBA,
1924 TrackInfoOut->TrackLength,
1925 TrackInfoOut->FixPacketSize,
1926
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" : "",
1934
1935 TrackInfoOut->TrackParam.Flags & TrkInfo_Trk_Mask,
1936 (TrackInfoOut->TrackParam.Flags & TrkInfo_Copy) ? "Cpy" : "",
1937 (TrackInfoOut->TrackParam.Flags & TrkInfo_Damage) ? "Damage" : "",
1938
1939 TrackInfoOut->LastRecordedAddr,
1940 (TrackInfoOut->NWA_V & TrkInfo_LRA_V) ? "vld" : "inv",
1941
1942 TrackInfoOut->ReadCompatLBA
1943 ));
1944 }
1945 #endif //UDF_FORMAT_MEDIA
1946
1947 }
1948
1949 for (TrackNumber=(LONG)DiscInfo->FirstTrackNum;TrackNumber <= (LONG)Vcb->LastTrackNum;TrackNumber++) {
1950
1951 RtlZeroMemory(TrackInfoOut,sizeof(TRACK_INFO_BLOCK_USER_OUT));
1952 TrackInfoIn->LBA_TrkNum = TrackNumber;
1953 TrackInfoIn->Track = TRUE;
1954
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 UDFPrint(("TrkInfo: Bad FirstLba (%x), change to %x\n", TrackInfoOut->TrackStartLBA, 0));
1961 Vcb->TrackMap[TrackNumber].FirstLba = 0;
1962 } else {
1963 Vcb->TrackMap[TrackNumber].FirstLba = TrackInfoOut->TrackStartLBA;
1964 }
1965 if(TrackInfoOut->TrackLength & 0x80000000) {
1966 UDFPrint(("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;
1969 }
1970 Vcb->TrackMap[TrackNumber].LastLba = TrackInfoOut->TrackStartLBA +
1971 TrackInfoOut->TrackLength -
1972 (TrackInfoOut->TrackLength ? 1 : 0);
1973
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 UDFPrint(("TrkInfo: set NWA to LastLba (%x)\n", Vcb->TrackMap[TrackNumber].LastLba));
1981 Vcb->TrackMap[TrackNumber].NWA =
1982 Vcb->TrackMap[TrackNumber].LastLba;
1983 } else {
1984 UDFPrint(("TrkInfo: set NWA to INV (1)\n"));
1985 Vcb->TrackMap[TrackNumber].NWA = 0;
1986 Vcb->TrackMap[TrackNumber].NWA_V = 0;
1987 }
1988 } else {
1989 if(!(TrackInfoOut->NextWriteLBA & 0x80000000)) {
1990 UDFPrint(("TrkInfo: Good NWA (%x)\n", TrackInfoOut->NextWriteLBA));
1991 Vcb->TrackMap[TrackNumber].NWA =
1992 TrackInfoOut->NextWriteLBA;
1993 } else {
1994 UDFPrint(("TrkInfo: set NWA to INV (2)\n"));
1995 Vcb->TrackMap[TrackNumber].NWA = 0;
1996 Vcb->TrackMap[TrackNumber].NWA_V = 0;
1997 }
1998 }
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)
2002 if(NotFP) {
2003 UDFPrint(("Apply NotFP\n"));
2004 Vcb->TrackMap[TrackNumber].DataParam &= ~TrkInfo_FP;
2005 #ifdef DBG
2006 TrackInfoOut->DataParam.Flags &= ~TrkInfo_FP;
2007 #endif //DBG
2008 } else
2009 if(ForceFP) {
2010 UDFPrint(("Apply ForceFP\n"));
2011 PacketTrack = TRUE;
2012 Vcb->TrackMap[TrackNumber].DataParam |= TrkInfo_FP;
2013 #ifdef DBG
2014 TrackInfoOut->DataParam.Flags |= TrkInfo_FP;
2015 #endif //DBG
2016 }
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;
2021 } else {
2022 Vcb->TrackMap[TrackNumber].PacketSize = PACKETSIZE_UDF;
2023 }
2024 // presence of Damaged track means, that we should mount this disk in RAW mode
2025 if(Vcb->TrackMap[TrackNumber].TrackParam & TrkInfo_Damage) {
2026 UDFPrint(("TrkInfo_Damage, Try RAW_MOUNT\n"));
2027 Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK;
2028 }
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 UDFPrint(("Unknown DatType, Try RAW_MOUNT\n"));
2033 Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK;
2034 }
2035
2036 PacketTrack |= ((TrackInfoOut->DataParam.Flags & TrkInfo_Packet) != 0);
2037
2038 UDFPrint(("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,
2042 TrackNumber,
2043 Vcb->TrackMap[TrackNumber].FirstLba,
2044 Vcb->TrackMap[TrackNumber].LastLba,
2045 TrackInfoOut->FixPacketSize,
2046
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" : "",
2054
2055 TrackInfoOut->TrackParam.Flags & TrkInfo_Trk_Mask,
2056 (TrackInfoOut->TrackParam.Flags & TrkInfo_Copy) ? "Cpy" : "",
2057 (TrackInfoOut->TrackParam.Flags & TrkInfo_Damage) ? "Damage" : "",
2058
2059 TrackInfoOut->LastRecordedAddr,
2060 (TrackInfoOut->NWA_V & TrkInfo_LRA_V) ? "vld" : "inv",
2061
2062 TrackInfoOut->ReadCompatLBA
2063 ));
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,
2071 TrackNumber,
2072 TrackInfoOut->TrackStartLBA,
2073 TrackInfoOut->TrackLength,
2074 TrackInfoOut->FixPacketSize,
2075
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" : "",
2083
2084 TrackInfoOut->TrackParam.Flags & TrkInfo_Trk_Mask,
2085 (TrackInfoOut->TrackParam.Flags & TrkInfo_Copy) ? "Cpy" : "",
2086 (TrackInfoOut->TrackParam.Flags & TrkInfo_Damage) ? "Damage" : "",
2087
2088 TrackInfoOut->LastRecordedAddr,
2089 (TrackInfoOut->NWA_V & TrkInfo_LRA_V) ? "vld" : "inv",
2090
2091 TrackInfoOut->ReadCompatLBA
2092 ));
2093 }
2094 #endif //UDF_FORMAT_MEDIA
2095
2096 if(TrackNumber == DiscInfo->FirstTrackNum) {
2097 if(!(Vcb->TrackMap[TrackNumber].FirstLba & 0x80000000)) {
2098 UDFPrint(("TrkInfo: Update FirstLBA (%x)\n", Vcb->TrackMap[TrackNumber].FirstLba));
2099 Vcb->FirstLBA = Vcb->TrackMap[TrackNumber].FirstLba;
2100 }
2101 }
2102 if((TrackInfoOut->SesNum == Vcb->LastSession) && !Vcb->FirstTrackNumLastSes) {
2103 if(!(Vcb->TrackMap[TrackNumber].FirstLba & 0x80000000)) {
2104 UDFPrint(("TrkInfo: Update FirstLBALastSes (%x)\n", Vcb->TrackMap[TrackNumber].FirstLba));
2105 Vcb->FirstLBALastSes = Vcb->TrackMap[TrackNumber].FirstLba;
2106 }
2107 Vcb->FirstTrackNumLastSes = TrackNumber;
2108 }
2109 }
2110
2111 if(!(TrackInfoOut->NextWriteLBA & 0x80000000) &&
2112 !(TrackInfoOut->TrackLength & 0x80000000) &&
2113 (Vcb->NWA < TrackInfoOut->NextWriteLBA)
2114 ) {
2115 UDFPrint((" set NWA to %x\n", TrackInfoOut->NextWriteLBA));
2116 if(Vcb->MediaClassEx != CdMediaClass_DVDpRW) {
2117 Vcb->NWA = TrackInfoOut->NextWriteLBA;
2118 } else {
2119 Vcb->NWA =
2120 TrackInfoOut->TrackStartLBA + TrackInfoOut->TrackLength - (TrackInfoOut->TrackLength ? 1 : 0);
2121 }
2122 }
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 UDFPrint((" set LastPossibleLBA=%x\n", Vcb->LastPossibleLBA));
2129 }
2130 TrackNumber = Vcb->LastTrackNum;
2131 // quick formatted +RW returns bogus value
2132 if(Vcb->MediaClassEx == CdMediaClass_DVDpRW) {
2133 UDFPrint((" 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*/
2138 ) {
2139 UDFPrint((" track LastLBA %x != LastPossibleLBA %x, verify\n",
2140 Vcb->TrackMap[TrackNumber].LastLba, Vcb->LastPossibleLBA));
2141
2142 if(Vcb->MRWStatus == DiscInfo_BGF_Complete) {
2143 UDFPrint((" complete MRW state\n"));
2144 #ifdef _BROWSE_UDF_
2145 Vcb->LastPossibleLBA =
2146 Vcb->NWA =
2147 Vcb->LastLBA =
2148 Vcb->TrackMap[TrackNumber].LastLba;
2149 goto valid_track_length;
2150 #endif // _BROWSE_UDF_
2151 } else
2152 if(Vcb->MRWStatus) {
2153 uint8* buff;
2154 SIZE_T ReadBytes;
2155
2156 UDFPrint((" MRW state %x\n", Vcb->MRWStatus));
2157
2158 buff = (uint8*)DbgAllocatePoolWithTag(NonPagedPool, Vcb->WriteBlockSize, 'bNWD' );
2159 if(buff) {
2160 RC = UDFTRead(Vcb,
2161 buff,
2162 Vcb->WriteBlockSize,
2163 Vcb->TrackMap[TrackNumber].LastLba+1,
2164 &ReadBytes,
2165 PH_TMP_BUFFER);
2166 DbgFreePool(buff);
2167 if(!OS_SUCCESS(RC)) {
2168 UDFPrint((" 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;
2176 }
2177 }
2178 }
2179 }
2180 UDFPrint((" set track LastLBA %x\n", Vcb->LastPossibleLBA));
2181 Vcb->NWA =
2182 Vcb->LastLBA =
2183 Vcb->TrackMap[TrackNumber].LastLba =
2184 Vcb->LastPossibleLBA;
2185 }
2186 valid_track_length:
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--;
2198 // TrackNumber--;
2199 /* for(SesNum = Vcb->TrackMap[TrackNumber].Session;
2200 Vcb->TrackMap[TrackNumber].Session == SesNum;
2201 TrackNumber--) {
2202 }*/
2203 if(TrackNumber>1)
2204 Vcb->LastSession = Vcb->TrackMap[TrackNumber-1].Session;
2205 }
2206 }
2207
2208 TrackNumber = Vcb->LastTrackNum;
2209 #ifdef _BROWSE_UDF_
2210 Vcb->LastLBA = min(Vcb->TrackMap[TrackNumber].LastLba, Vcb->TrackMap[TrackNumber].NWA);
2211 #endif //_BROWSE_UDF_
2212
2213 if(Vcb->TrackMap[TrackNumber].NWA_V & TrkInfo_NWA_V) {
2214 UDFPrint((" 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);
2218 } else {
2219 UDFPrint((" no NWA, set LastLBA to Last %x\n", Vcb->TrackMap[TrackNumber].LastLba));
2220 Vcb->LastLBA = Vcb->TrackMap[TrackNumber].LastLba;
2221 }
2222
2223 Vcb->VCBFlags |= UDF_VCB_FLAGS_TRACKMAP;
2224 if(!PacketTrack && Vcb->MediaClassEx != CdMediaClass_DVDRAM ) {
2225 UDFPrint((" disable Raw mount\n"));
2226 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_RAW_DISK;
2227 }
2228
2229 try_exit: NOTHING;
2230
2231 } _SEH2_FINALLY {
2232 if(DiscInfo) MyFreePool__(DiscInfo);
2233 if(TrackInfoOut) MyFreePool__(TrackInfoOut);
2234 } _SEH2_END;
2235
2236 return RC;
2237 } // end UDFReadDiscTrackInfo()
2238
2239 /*
2240 This routine attempts to read disk layout using ReadFullTOC cmd
2241 */
2242 OSSTATUS
UDFReadAndProcessFullToc(PDEVICE_OBJECT DeviceObject,PVCB Vcb)2243 UDFReadAndProcessFullToc(
2244 PDEVICE_OBJECT DeviceObject, // the target device object
2245 PVCB Vcb
2246 )
2247 {
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) );
2250 uint32 index;
2251 uint8 POINT;
2252 uint8 CurTrack = 0;
2253 uint32 LastLeadOut = 0;
2254 // BOOLEAN IsMRW = FALSE;
2255
2256 UDFPrint(("UDFReadAndProcessFullToc\n"));
2257
2258 if(!toc) return STATUS_INSUFFICIENT_RESOURCES;
2259 Vcb->FirstTrackNum = 0xFF;
2260
2261 RtlZeroMemory(toc,sizeof(READ_FULL_TOC_USER_OUT));
2262
2263 RC = UDFPhSendIOCTL(IOCTL_CDRW_READ_FULL_TOC,DeviceObject,
2264 NULL,0,
2265 toc,sizeof(READ_FULL_TOC_USER_OUT),
2266 TRUE,NULL);
2267
2268 if(!OS_SUCCESS(RC)) {
2269
2270 MyFreePool__(toc);
2271 return RC;
2272 }
2273
2274 #ifdef _CONSOLE
2275 Vcb->PhDeviceType = FILE_DEVICE_CD_ROM;
2276 #endif //_CONSOLE
2277 Vcb->LastSession = toc->Sessions.Last_TrackSes;
2278
2279 RC = UDFReallocTrackMap(Vcb, 0x100);
2280 if(!OS_SUCCESS(RC)) {
2281 MyFreePool__(toc);
2282 return RC;
2283 }
2284
2285 // get LastPossibleLBA
2286
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))) {
2294 IsMRW = TRUE;
2295 }*/
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;
2300 if(!CurTrack)
2301 CurTrack = (uint8)(Vcb->FirstTrackNum);
2302 break;
2303 }
2304 case POINT_LastTrackNum: {
2305 Vcb->LastTrackNum = toc->SessionData[index].Params.LastTrackNum.LastTrackNum;
2306 if(CurTrack < Vcb->LastTrackNum)
2307 CurTrack = (uint8)(Vcb->FirstTrackNum);
2308 break;
2309 }
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);
2314 #undef TempMSF
2315 break;
2316 }
2317 default: {
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) {
2323 Vcb->FirstLBA = 0;
2324 }
2325 #undef TempMSF
2326 }
2327 break;
2328 }
2329 }
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) {
2335 if(POINT == 1) {
2336 Vcb->TrackMap[POINT].FirstLba = 0;
2337 } else {
2338 if(Vcb->TrackMap[POINT-1].LastLba) {
2339 Vcb->TrackMap[POINT].FirstLba = Vcb->TrackMap[POINT-1].LastLba+1;
2340 }
2341 }
2342 }
2343 #undef TempMSF
2344 if(POINT > POINT_StartPositionOfTrack_Min) {
2345 Vcb->TrackMap[POINT-1].LastLba = Vcb->TrackMap[POINT].FirstLba-1;
2346 }
2347 CurTrack = POINT;
2348 }
2349 } else
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]);
2355 #undef TempMSF
2356 break;
2357 }
2358 default: {
2359 break;
2360 }
2361 }
2362 }
2363
2364 }
2365
2366 /* if(!IsMRW) {
2367 UDFPrint(("No MRW\n"));
2368 Vcb->CompatFlags &= ~UDF_VCB_IC_MRW_ADDR_PROBLEM;
2369 }*/
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);
2374
2375 Vcb->LastLBA = Vcb->TrackMap[Vcb->LastTrackNum].LastLba;
2376
2377 MyFreePool__(toc);
2378 // Vcb->LastLBA=PacketVariable2Fixed(Vcb->LastLBA)-2;
2379 return STATUS_SUCCESS;
2380 } // end UDFReadAndProcessFullToc()
2381
2382 /*
2383 use standard way to determine disk layout (ReadTOC cmd)
2384 */
2385 OSSTATUS
UDFUseStandard(PDEVICE_OBJECT DeviceObject,PVCB Vcb)2386 UDFUseStandard(
2387 PDEVICE_OBJECT DeviceObject, // the target device object
2388 PVCB Vcb // Volume control block from this DevObj
2389 )
2390 {
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;
2396 uint32 TocEntry;
2397 #ifdef _BROWSE_UDF_
2398 uint32 OldTrkNum;
2399 uint32 TrkNum;
2400 SIZE_T ReadBytes, i, len;
2401 #endif //_BROWSE_UDF_
2402 #ifdef UDF_FORMAT_MEDIA
2403 PUDFFmtState fms = Vcb->fms;
2404 #else
2405 #define fms FALSE
2406 #endif //UDF_FORMAT_MEDIA
2407
2408 UDFPrint(("UDFUseStandard\n"));
2409
2410 _SEH2_TRY {
2411
2412 if(!toc || !LastSes) {
2413 try_return (RC = STATUS_INSUFFICIENT_RESOURCES);
2414 }
2415 RtlZeroMemory(toc,sizeof(READ_TOC_TOC));
2416
2417 Vcb->VCBFlags |= UDF_VCB_FLAGS_USE_STD;
2418
2419 RC = UDFPhSendIOCTL(IOCTL_CDROM_READ_TOC,DeviceObject,
2420 toc,sizeof(READ_TOC_USER_OUT),
2421 toc,sizeof(READ_TOC_USER_OUT),
2422 TRUE,NULL );
2423
2424 if((RC == STATUS_DEVICE_NOT_READY) || (RC == STATUS_NO_MEDIA_IN_DEVICE)) {
2425 try_return(RC);
2426 }
2427 #ifdef UDF_FORMAT_MEDIA
2428 if(fms->opt_media == MT_none) {
2429 try_return(RC = STATUS_NO_MEDIA_IN_DEVICE);
2430 }
2431 #endif //UDF_FORMAT_MEDIA
2432
2433 // If even standard read toc does not work, then use default values
2434 if(!OS_SUCCESS(RC)) {
2435
2436 RC = UDFReallocTrackMap(Vcb, 2);
2437 if(!OS_SUCCESS(RC)) {
2438 try_return(RC);
2439 }
2440
2441 Vcb->LastSession=1;
2442 Vcb->FirstTrackNum=1;
2443 // Vcb->FirstLBA=0;
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
2449 if(!fms) {
2450 #endif //UDF_FORMAT_MEDIA
2451
2452 #ifdef _BROWSE_UDF_
2453 #ifdef UDF_HDD_SUPPORT
2454 if(UDFGetDevType(DeviceObject) == FILE_DEVICE_DISK) {
2455 try_return(RC = STATUS_SUCCESS);
2456 }
2457 #endif //UDF_HDD_SUPPORT
2458 #endif //_BROWSE_UDF_
2459
2460 #ifdef UDF_FORMAT_MEDIA
2461 } else {
2462
2463 if(fms->opt_media == MT_HD) {
2464 Vcb->LastPossibleLBA = Vcb->LastLBA;
2465 try_return(RC = STATUS_SUCCESS);
2466 }
2467 }
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);
2475 }
2476
2477 #ifdef _CONSOLE
2478 Vcb->PhDeviceType = FILE_DEVICE_CD_ROM;
2479 #endif //_CONSOLE
2480
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? */
2483
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);
2487 }
2488
2489 #ifdef _BROWSE_UDF_
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);
2494
2495 RC = UDFReallocTrackMap(Vcb, MAXIMUM_NUMBER_OF_TRACKS+1);
2496 /* if(Vcb->TrackMap) {
2497 MyFreePool__(Vcb->TrackMap);
2498 Vcb->TrackMap = NULL;
2499 }
2500 Vcb->TrackMap = (PUDFTrackMap)
2501 MyAllocatePool__(NonPagedPool, (MAXIMUM_NUMBER_OF_TRACKS+1)*sizeof(UDFTrackMap));
2502 if(!Vcb->TrackMap) {
2503 MyFreePool__(toc);
2504 return STATUS_INSUFFICIENT_RESOURCES;
2505 }
2506 RtlZeroMemory(Vcb->TrackMap,(MAXIMUM_NUMBER_OF_TRACKS+1)*sizeof(UDFTrackMap));
2507 */
2508 if(!OS_SUCCESS(RC)) {
2509 BrutePoint();
2510 try_return(RC);
2511 }
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),
2516 TRUE,NULL );
2517
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;
2524 }
2525 }
2526 }
2527
2528 OldTrkNum = 0;
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;
2533 #ifdef UDF_DBG
2534 if (TrkNum >= MAXIMUM_NUMBER_OF_TRACKS &&
2535 TrkNum != TOC_LastTrack_ID) {
2536 UDFPrint(("UDFUseStandard: Array out of bounds\n"));
2537 BrutePoint();
2538 try_return(RC = STATUS_SUCCESS);
2539 }
2540 UDFPrint(("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])));
2543 #endif // UDF_DBG
2544 if(Vcb->FirstTrackNum == TrkNum) {
2545 Vcb->FirstLBA = MSF_TO_LBA(TempMSF[1],TempMSF[2],TempMSF[3]);
2546 if(Vcb->FirstLBA & 0x80000000) {
2547 Vcb->FirstLBA = 0;
2548 }
2549 }
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 UDFPrint(("UDFUseStandard: Last track entry, break TOC scan\n"));
2554 // continue;
2555 break;
2556 } else {
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;
2560 if(TrkNum) {
2561 if (TOC_LastTrack_ID == OldTrkNum) {
2562 UDFPrint(("UDFUseStandard: Wrong previous track number\n"));
2563 BrutePoint();
2564 } else {
2565 Vcb->TrackMap[OldTrkNum].LastLba = Vcb->TrackMap[TrkNum].FirstLba-1;
2566 }
2567 }
2568 }
2569 // check track type
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;
2575 break;
2576 default:
2577 Vcb->TrackMap[TrkNum].DataParam = TrkInfo_Dat_unknown;
2578 Vcb->TrackMap[TrkNum].TrackParam = TrkInfo_Trk_unknown;
2579 }
2580 OldTrkNum = TrkNum;
2581 #undef TempMSF
2582 }
2583
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;
2592 break;
2593 }
2594 }
2595 // no valid tracks...
2596 if(!TrkNum) {
2597 UDFPrint(("UDFUseStandard: no valid tracks...\n"));
2598 try_return(RC = STATUS_UNRECOGNIZED_VOLUME);
2599 }
2600 i = 0;
2601
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);
2608 i++;
2609 }
2610 if(OS_SUCCESS(RC)) {
2611 Vcb->LastLBA = Vcb->TrackMap[TrkNum].LastLba-i+1;
2612 /* if(i) {
2613 Vcb->TrackMap[TrkNum].PacketSize = PACKETSIZE_UDF;
2614 Vcb->TrackMap[TrkNum].;
2615 }*/
2616 } else {
2617
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.
2622 i = 0;
2623 len = Vcb->TrackMap[TrkNum].LastLba - Vcb->TrackMap[TrkNum].FirstLba + 1;
2624 len = (uint32)(((int64)len*PACKETSIZE_UDF) / (PACKETSIZE_UDF+7));
2625
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);
2629 i++;
2630 }
2631 if(OS_SUCCESS(RC)) {
2632 Vcb->LastLBA =
2633 Vcb->TrackMap[TrkNum].LastLba = Vcb->TrackMap[TrkNum].FirstLba-i+len+1;
2634 Vcb->TrackMap[TrkNum].PacketSize = PACKETSIZE_UDF;
2635 // Vcb->TrackMap[TrkNum].;
2636 } else
2637 if(RC == STATUS_INVALID_DEVICE_REQUEST) {
2638 // wrap return code from Audio-disk
2639 RC = STATUS_SUCCESS;
2640 }
2641 }
2642
2643 #ifdef UDF_CDRW_EMULATION_ON_ROM
2644 Vcb->LastPossibleLBA = Vcb->LastLBA+7+1+1024;
2645 Vcb->NWA = Vcb->LastLBA+7+1;
2646 #else
2647 Vcb->LastPossibleLBA =
2648 Vcb->NWA = Vcb->LastLBA+7+1;
2649 #endif //UDF_CDRW_EMULATION_ON_ROM
2650
2651 #else //_BROWSE_UDF_
2652
2653 Vcb->FirstTrackNum=toc->Tracks.Last_TrackSes;
2654 Vcb->LastTrackNum=toc->Tracks.First_TrackSes;
2655
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) {
2662 Vcb->FirstLBA = 0;
2663 }
2664 }
2665 if(TOC_LastTrack_ID == toc->TrackData[TocEntry].TrackNum) {
2666 Vcb->LastLBA = MSF_TO_LBA(TempMSF[1],TempMSF[2],TempMSF[3])-1;
2667 }
2668 #undef TempMSF
2669 }
2670
2671 // Vcb->LastLBA=PacketVariable2Fixed(Vcb->LastLBA)-2;
2672 Vcb->LastPossibleLBA = DEFAULT_LAST_LBA_FP_CD;
2673 #endif //_BROWSE_UDF_
2674 try_exit: NOTHING;
2675 } _SEH2_FINALLY {
2676 if(toc) MyFreePool__(toc);
2677 if(LastSes) MyFreePool__(LastSes);
2678 } _SEH2_END;
2679
2680 return RC;
2681 } // end UDFUseStandard()
2682
2683 /*
2684 Get block size (for read operation)
2685 */
2686 OSSTATUS
UDFGetBlockSize(IN PDEVICE_OBJECT DeviceObject,IN PVCB Vcb)2687 UDFGetBlockSize(
2688 IN PDEVICE_OBJECT DeviceObject, // the target device object
2689 IN PVCB Vcb // Volume control block from this DevObj
2690 )
2691 {
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;
2697 #else
2698 #define fms FALSE
2699 #endif //UDF_FORMAT_MEDIA
2700
2701 if(!DiskGeometry || !PartitionInfo)
2702 try_return (RC = STATUS_INSUFFICIENT_RESOURCES);
2703
2704 #ifdef _BROWSE_UDF_
2705
2706 #ifdef UDF_HDD_SUPPORT
2707 if(!fms) {
2708 if(UDFGetDevType(DeviceObject) == FILE_DEVICE_DISK) {
2709 UDFPrint(("UDFGetBlockSize: HDD\n"));
2710 RC = UDFPhSendIOCTL(IOCTL_DISK_GET_DRIVE_GEOMETRY,DeviceObject,
2711 0,NULL,
2712 DiskGeometry,sizeof(DISK_GEOMETRY),
2713 TRUE,NULL );
2714 Vcb->BlockSize = (OS_SUCCESS(RC)) ? DiskGeometry->BytesPerSector : 512;
2715 if(!NT_SUCCESS(RC))
2716 try_return(RC);
2717 RC = UDFPhSendIOCTL(IOCTL_DISK_GET_PARTITION_INFO,DeviceObject,
2718 0,NULL,
2719 PartitionInfo,sizeof(PARTITION_INFORMATION),
2720 TRUE,NULL );
2721 if(!NT_SUCCESS(RC)) {
2722 UDFPrint(("UDFGetBlockSize: IOCTL_DISK_GET_PARTITION_INFO failed\n"));
2723 if(RC == STATUS_INVALID_DEVICE_REQUEST) /* ReactOS Code Change (was =) */
2724 RC = STATUS_UNRECOGNIZED_VOLUME;
2725 try_return(RC);
2726 }
2727 if(PartitionInfo->PartitionType != PARTITION_IFS) {
2728 UDFPrint(("UDFGetBlockSize: PartitionInfo->PartitionType != PARTITION_IFS\n"));
2729 try_return(RC = STATUS_UNRECOGNIZED_VOLUME);
2730 }
2731 } else {
2732 #endif //UDF_HDD_SUPPORT
2733 RC = UDFPhSendIOCTL(IOCTL_CDROM_GET_DRIVE_GEOMETRY,DeviceObject,
2734 DiskGeometry,sizeof(DISK_GEOMETRY),
2735 DiskGeometry,sizeof(DISK_GEOMETRY),
2736 TRUE,NULL );
2737
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"));
2741 try_return(RC);
2742 }
2743
2744 Vcb->BlockSize = (OS_SUCCESS(RC)) ? DiskGeometry->BytesPerSector : 2048;
2745 #ifdef UDF_HDD_SUPPORT
2746 }
2747 }
2748 #endif //UDF_HDD_SUPPORT
2749
2750 #endif //_BROWSE_UDF_
2751
2752 #ifdef UDF_FORMAT_MEDIA
2753 if(fms) {
2754 RC = UDFPhSendIOCTL(IOCTL_CDROM_GET_DRIVE_GEOMETRY,DeviceObject,
2755 DiskGeometry,sizeof(DISK_GEOMETRY),
2756 DiskGeometry,sizeof(DISK_GEOMETRY),
2757 FALSE, NULL );
2758
2759 if(!NT_SUCCESS(RC)) {
2760 RC = UDFPhSendIOCTL(IOCTL_DISK_GET_DRIVE_GEOMETRY,DeviceObject,
2761 DiskGeometry,sizeof(DISK_GEOMETRY),
2762 DiskGeometry,sizeof(DISK_GEOMETRY),
2763 FALSE, NULL );
2764 if(NT_SUCCESS(RC)) {
2765 fms->opt_media = MT_HD;
2766 RC = UDFPhSendIOCTL(IOCTL_DISK_GET_PARTITION_INFO,DeviceObject,
2767 NULL,0,
2768 PartitionInfo,sizeof(PARTITION_INFORMATION)*2,
2769 FALSE, NULL );
2770 if(!NT_SUCCESS(RC)) {
2771 LONG HiOffs=0;
2772 RC = SetFilePointer(DeviceObject->h,0,&HiOffs,FILE_END);
2773 }
2774 }
2775 }
2776
2777 if(RC == STATUS_DEVICE_NOT_READY) {
2778 // probably, the device is really busy, may be by CD/DVD recording
2779 UserPrint((" busy\n"));
2780 try_return(RC );
2781 }
2782
2783 Vcb->BlockSize = (NT_SUCCESS(RC)) ? DiskGeometry->BytesPerSector : 2048;
2784 }
2785 #endif //UDF_FORMAT_MEDIA
2786
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
2796 default:
2797 {
2798 UserPrint(("UDF: Bad block size (%ld)\n", Vcb->BlockSize));
2799 try_return(RC = STATUS_UNSUCCESSFUL);
2800 }
2801 }
2802
2803 #ifdef UDF_HDD_SUPPORT
2804 if(
2805 #ifdef _BROWSE_UDF_
2806 (!fms && (UDFGetDevType(DeviceObject) == FILE_DEVICE_DISK))
2807 ||
2808 #endif //_BROWSE_UDF_
2809 #ifdef UDF_FORMAT_MEDIA
2810 (fms && fms->opt_media == MT_HD)
2811 ||
2812 #endif //UDF_FORMAT_MEDIA
2813 FALSE ) {
2814
2815 #ifdef UDF_FORMAT_MEDIA
2816 if(fms && !NT_SUCCESS(RC))
2817 try_return(STATUS_UNSUCCESSFUL);
2818 #endif //UDF_FORMAT_MEDIA
2819
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;
2823 } else {
2824 #endif //UDF_HDD_SUPPORT
2825 Vcb->FirstLBA=0;
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;
2832 }
2833 } else {
2834 Vcb->LastLBA = UDFIsDvdMedia(Vcb) ? DEFAULT_LAST_LBA_DVD : DEFAULT_LAST_LBA_FP_CD;
2835 }
2836 Vcb->LastPossibleLBA = Vcb->LastLBA;
2837 #ifdef UDF_HDD_SUPPORT
2838 }
2839 #endif //UDF_HDD_SUPPORT
2840
2841 #ifdef _BROWSE_UDF_
2842 // if(UDFGetDevType(DeviceObject) == FILE_DEVICE_DISK) {
2843 Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->BlockSize;
2844 // } else {
2845 // Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->BlockSize;
2846 // }
2847 #else //_BROWSE_UDF_
2848 if(fms->opt_media == MT_HD) {
2849 Vcb->WriteBlockSize = Vcb->BlockSize;
2850 } else {
2851 Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->BlockSize;
2852 }
2853 #endif //_BROWSE_UDF_
2854
2855 RC = STATUS_SUCCESS;
2856
2857 try_exit: NOTHING;
2858
2859 UDFPrint(("UDFGetBlockSize:\nBlock size is %x, Block size bits %x, Last LBA is %x\n",
2860 Vcb->BlockSize, Vcb->BlockSizeBits, Vcb->LastLBA));
2861
2862 MyFreePool__(PartitionInfo);
2863 MyFreePool__(DiskGeometry);
2864 return RC;
2865
2866 } // end UDFGetBlockSize()
2867
2868 #ifdef _BROWSE_UDF_
2869
2870 OSSTATUS
UDFCheckTrackFPAddressing(IN PVCB Vcb,IN ULONG TrackNum)2871 UDFCheckTrackFPAddressing(
2872 // IN PDEVICE_OBJECT DeviceObject, // the target device object
2873 IN PVCB Vcb, // Volume control block from this DevObj
2874 IN ULONG TrackNum
2875 )
2876 {
2877 OSSTATUS RC = STATUS_SUCCESS;
2878 // OSSTATUS RC2 = STATUS_UNSUCCESSFUL;
2879 uint32 lba=0;
2880 uint32 i;
2881 uint8* Buffer;
2882 // SIZE_T ReadBytes;
2883
2884 uint8 user_data;
2885
2886 ULONG FirstChunkLen = 0;
2887
2888 ULONG NextChunkLen = 0;
2889 ULONG NextChunkLenCount = 0;
2890
2891 ULONG NextChunkLenOth = 0;
2892 ULONG NextChunkLenOthCount = 0;
2893 // ULONG MRW_Offset = 0;
2894
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};*/
2899
2900
2901 if(!Vcb->TrackMap) {
2902 Vcb->CompatFlags &= ~UDF_VCB_IC_FP_ADDR_PROBLEM;
2903 return STATUS_SUCCESS;
2904 }
2905
2906 Buffer = (uint8*)DbgAllocatePoolWithTag(NonPagedPool, max(Vcb->BlockSize,
2907 sizeof(LL_READ_USER_IN)+16), 'pNWD');
2908 if(!Buffer)
2909 return STATUS_INSUFFICIENT_RESOURCES;
2910 pLLR_in = (PLL_READ_USER_IN)Buffer;
2911 pHdr = (PCD_SECTOR_HEADER)(Buffer+sizeof(LL_READ_USER_IN));
2912
2913 /* if(Vcb->CompatFlags & UDF_VCB_IC_MRW_ADDR_PROBLEM) {
2914 MRW_Offset = (MRW_DMA_OFFSET/32)*39;
2915 }*/
2916
2917 user_data = 0;
2918 for(i=0; i<=0x200; i++) {
2919
2920 RtlZeroMemory(pLLR_in, sizeof(pLLR_in)+16);
2921 pLLR_in->ExpectedBlkType = ReadCd_BlkType_Any;
2922 pLLR_in->LBA = i;
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),
2932 TRUE, NULL );
2933
2934 /* RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, Buffer, Vcb->BlockSize,
2935 ((uint64)(i+MRW_Offset)) << Vcb->BlockSizeBits, &ReadBytes, 0);*/
2936
2937 // skip unreadable
2938 if(!OS_SUCCESS(RC)) {
2939 UDFPrint((" Read error at lba %x\n", i));
2940 continue;
2941 }
2942
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 UDFPrint((" Unexpected data type (%x) at lba %x\n", pHdr->Mode.Flags & WParam_SubHdr_Mode_Mask, i));
2947 continue;
2948 }
2949
2950 if((pHdr->Mode.Flags & WParam_SubHdr_Format_Mask) == WParam_SubHdr_Format_UserData &&
2951 !user_data) {
2952 lba = i;
2953 }
2954
2955 /* if(OS_SUCCESS(RC) && !OS_SUCCESS(RC2)) {
2956 lba = i;
2957 }*/
2958
2959 if((pHdr->Mode.Flags & WParam_SubHdr_Format_Mask) != WParam_SubHdr_Format_UserData &&
2960 user_data) {
2961 // if(!OS_SUCCESS(RC) && OS_SUCCESS(RC2)) {
2962 UDFPrint((" %x - %x (%x sectors)\n", lba, i-1, i-lba));
2963 if(!FirstChunkLen) {
2964 FirstChunkLen = i-lba;
2965 } else {
2966 if(!NextChunkLen) {
2967 NextChunkLen = i-lba;
2968 NextChunkLenCount++;
2969 } else {
2970 if(NextChunkLen == i-lba) {
2971 NextChunkLenCount++;
2972 } else {
2973 if((NextChunkLenOth+1) % (NextChunkLen+1)) {
2974 NextChunkLenOth = i-lba;
2975 NextChunkLenOthCount++;
2976 } else {
2977 NextChunkLenCount++;
2978 }
2979 }
2980 }
2981 }
2982 }
2983 user_data = ((pHdr->Mode.Flags & WParam_SubHdr_Format_Mask) == WParam_SubHdr_Format_UserData);
2984 // RC2 = RC;
2985 }
2986
2987 DbgFreePool(Buffer);
2988
2989 if(!NextChunkLenCount && !NextChunkLenOthCount) {
2990 Vcb->CompatFlags &= ~UDF_VCB_IC_FP_ADDR_PROBLEM;
2991 return STATUS_SUCCESS;
2992 }
2993 if(NextChunkLenOthCount > NextChunkLenCount) {
2994 NextChunkLen = NextChunkLenOth;
2995 }
2996 if(NextChunkLen > PACKETSIZE_UDF+7) {
2997 Vcb->CompatFlags &= ~UDF_VCB_IC_FP_ADDR_PROBLEM;
2998 return STATUS_SUCCESS;
2999 }
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++;
3006 }
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);
3012
3013 return STATUS_SUCCESS;
3014 } // end UDFCheckTrackFPAddressing()
3015
3016 uint32
UDFFixFPAddress(IN PVCB Vcb,IN uint32 Lba)3017 UDFFixFPAddress(
3018 IN PVCB Vcb, // Volume control block from this DevObj
3019 IN uint32 Lba
3020 )
3021 {
3022 uint32 i = Vcb->LastReadTrack;
3023 uint32 pk;
3024 uint32 rel;
3025
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;
3032 }
3033 if(Vcb->TrackMap[i].Flags & TrackMap_FixFPAddressing) {
3034 if(Lba < 0x20)
3035 return Lba;
3036 pk = Lba / Vcb->TrackMap[i].PacketSize;
3037 rel = Lba % Vcb->TrackMap[i].PacketSize;
3038 UDFPrint(("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*/;
3040 }
3041 return Lba;
3042 } // end UDFFixFPAddress()
3043
3044 #endif //_BROWSE_UDF_
3045
3046 /*
3047 detect device driver & try to read disk layout (use all methods)
3048 */
3049 OSSTATUS
UDFGetDiskInfo(IN PDEVICE_OBJECT DeviceObject,IN PVCB Vcb)3050 UDFGetDiskInfo(
3051 IN PDEVICE_OBJECT DeviceObject, // the target device object
3052 IN PVCB Vcb // Volume control block from this DevObj
3053 )
3054 {
3055 OSSTATUS RC = STATUS_UNRECOGNIZED_VOLUME;
3056 int8* ioBuf = (int8*)MyAllocatePool__(NonPagedPool,4096);
3057 uint8 MediaType;
3058 PLUN_WRITE_PERF_DESC_USER WPerfDesc;
3059 uint32 i;
3060 // BOOLEAN MRW_problem = FALSE;
3061 uint32 SavedFeatures = 0;
3062 #ifdef UDF_FORMAT_MEDIA
3063 PUDFFmtState fms = Vcb->fms;
3064 #else
3065 #define fms FALSE
3066 #endif //UDF_FORMAT_MEDIA
3067
3068 UDFPrint(("UDFGetDiskInfo\n"));
3069
3070 if(!ioBuf) {
3071 return STATUS_INSUFFICIENT_RESOURCES;
3072 }
3073
3074 _SEH2_TRY {
3075 RC = UDFGetBlockSize(DeviceObject, Vcb);
3076 if(!OS_SUCCESS(RC)) try_return(RC);
3077
3078
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),
3083 TRUE,NULL);
3084
3085 if(!OS_SUCCESS(RC)) {
3086
3087 RC = UDFUseStandard(DeviceObject, Vcb);
3088 #ifdef _BROWSE_UDF_
3089 if(!NT_SUCCESS(RC) || fms)
3090 try_return(RC);
3091
3092 // assume Device Recordable for now
3093 goto GetSignatureFailed;
3094 #endif //_BROWSE_UDF_
3095 }
3096
3097 UDFPrint(("UDF: Signature of low driver is : %s \n",
3098 ((PGET_SIGNATURE_USER_OUT)(ioBuf))->VendorId));
3099
3100 if(!strncmp( (const char *)(&( ((PGET_SIGNATURE_USER_OUT)(ioBuf))->VendorId[0]) ),
3101 Signature,strlen(Signature) )) {
3102 UDFPrint(("UDF: *****************************************\n"));
3103 UDFPrint(("UDF: ********* Our Device Driver Found ******\n"));
3104 UDFPrint(("UDF: *****************************************\n"));
3105
3106 (Vcb->VCBFlags) |= UDF_VCB_FLAGS_OUR_DEVICE_DRIVER;
3107 #ifndef _BROWSE_UDF_
3108 // reset driver
3109 #ifdef UDF_FORMAT_MEDIA
3110 if(!fms->opt_probe) {
3111 #endif //UDF_FORMAT_MEDIA
3112 UDFResetDeviceDriver(Vcb, Vcb->TargetDeviceObject, FALSE);
3113 // lock it
3114 ((PPREVENT_MEDIA_REMOVAL_USER_IN)(ioBuf))->PreventMediaRemoval = TRUE;
3115 UDFPhSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL,
3116 DeviceObject,
3117 ioBuf,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN),
3118 NULL,0,
3119 FALSE, NULL);
3120 #ifdef UDF_FORMAT_MEDIA
3121 }
3122 #endif //UDF_FORMAT_MEDIA
3123 #endif //_BROWSE_UDF_
3124 //#else //_BROWSE_UDF_
3125 // get device features
3126 UDFPhSendIOCTL( IOCTL_CDRW_GET_DEVICE_INFO,
3127 DeviceObject,
3128 NULL,0,
3129 ioBuf,sizeof(GET_DEVICE_INFO_USER_OUT),
3130 FALSE,NULL);
3131
3132 Vcb->SavedFeatures =
3133 SavedFeatures = ((PGET_DEVICE_INFO_USER_OUT)ioBuf)->Features;
3134 if(!(SavedFeatures & CDRW_FEATURE_SYNC_ON_WRITE)) {
3135 UDFPrint(("UDFGetDiskInfo: UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE\n"));
3136 Vcb->CompatFlags |= UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE;
3137 }
3138 if(!(SavedFeatures & CDRW_FEATURE_FORCE_SYNC_BEFORE_READ)) {
3139 UDFPrint(("UDFGetDiskInfo: UDF_VCB_IC_SYNCCACHE_BEFORE_READ\n"));
3140 Vcb->CompatFlags |= UDF_VCB_IC_SYNCCACHE_BEFORE_READ;
3141 }
3142 if(SavedFeatures & CDRW_FEATURE_BAD_RW_SEEK) {
3143 UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_BAD_RW_SEEK\n"));
3144 Vcb->CompatFlags |= UDF_VCB_IC_BAD_RW_SEEK;
3145 }
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 UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_FP_ADDRESSING_PROBLEM ?\n"));
3150 Vcb->CompatFlags |= UDF_VCB_IC_FP_ADDR_PROBLEM;
3151 }
3152 if(SavedFeatures & CDRW_FEATURE_MRW_ADDRESSING_PROBLEM) {
3153 UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM ?\n"));
3154 }
3155 if(SavedFeatures & CDRW_FEATURE_FORCE_SYNC_ON_WRITE) {
3156 UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_FORCE_SYNC_ON_WRITE\n"));
3157 Vcb->VCBFlags |= UDF_VCB_FLAGS_FORCE_SYNC_CACHE;
3158 }
3159 if(SavedFeatures & CDRW_FEATURE_BAD_DVD_LAST_LBA) {
3160 UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_BAD_DVD_LAST_LBA\n"));
3161 Vcb->CompatFlags |= UDF_VCB_IC_BAD_DVD_LAST_LBA;
3162 }
3163 if(SavedFeatures & CDRW_FEATURE_STREAMING) {
3164 UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_STREAMING\n"));
3165 }
3166 if(SavedFeatures & CDRW_FEATURE_OPC) {
3167 UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_OPC -> assume OPCNum=1\n"));
3168 Vcb->OPCNum = 1;
3169 }
3170 #ifdef UDF_FORMAT_MEDIA
3171 if(SavedFeatures & CDRW_FEATURE_FULL_BLANK_ON_FORMAT) {
3172 UDFPrint(("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 UDFPrint(("UDFGetDiskInfo: force Full Erase\n"));
3176 fms->opt_qblank = FALSE;
3177 }
3178 }
3179 #endif //UDF_FORMAT_MEDIA
3180 #ifdef _BROWSE_UDF_
3181 // get device buffer size
3182 RC = UDFPhSendIOCTL( IOCTL_CDRW_BUFFER_CAPACITY,
3183 DeviceObject,
3184 NULL,0,
3185 ioBuf,sizeof(BUFFER_CAPACITY_BLOCK_USER_OUT),
3186 FALSE,NULL);
3187 if(NT_SUCCESS(RC)) {
3188 Vcb->CdrwBufferSize = ((PBUFFER_CAPACITY_BLOCK_USER_OUT)ioBuf)->BufferLength;
3189 } else {
3190 Vcb->CdrwBufferSize = 0;
3191 }
3192 UDFPrint(("UDFGetDiskInfo: CdrwBufferSize = %dKb\n", Vcb->CdrwBufferSize / 1024));
3193 Vcb->CdrwBufferSizeCounter = 0;
3194 #endif //_BROWSE_UDF_
3195 // get media type
3196 RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_MEDIA_TYPE,DeviceObject,
3197 NULL,0,ioBuf,sizeof(GET_MEDIA_TYPE_USER_OUT),
3198 FALSE, NULL);
3199 if(!OS_SUCCESS(RC)) goto Try_FullToc;
3200 Vcb->MediaType =
3201 MediaType = ((PGET_MEDIA_TYPE_USER_OUT)ioBuf)->MediaType;
3202 UDFPrint(("UDFGetDiskInfo: MediaType %x\n", MediaType));
3203
3204 #ifndef UDF_FORMAT_MEDIA
3205 // we shall ignore audio-disks
3206 switch(MediaType) {
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:
3213 // case :
3214 UDFPrint(("UDFGetDiskInfo: we shall ignore audio-disks...\n"));
3215 try_return(RC = STATUS_UNRECOGNIZED_VOLUME);
3216 }
3217 #endif //UDF_FORMAT_MEDIA
3218
3219 UDFPrint(("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),
3222 FALSE, NULL);
3223 if(!OS_SUCCESS(RC)) goto Try_FullToc;
3224 Vcb->MediaClassEx =
3225 MediaType = (((PGET_MEDIA_TYPE_EX_USER_OUT)ioBuf)->MediaClass);
3226 UDFPrint(("UDFGetDiskInfo: MediaClassEx %x\n", MediaType));
3227
3228 #ifdef _BROWSE_UDF_
3229 if(!fms) {
3230
3231 switch(MediaType) {
3232
3233 case CdMediaClass_CDR:
3234 case CdMediaClass_DVDR:
3235 case CdMediaClass_DVDpR:
3236 case CdMediaClass_HD_DVDR:
3237 case CdMediaClass_BDR:
3238 UDFPrint(("UDFGetDiskInfo: MediaClass R\n"));
3239 Vcb->MediaType = MediaType_UnknownSize_CDR;
3240 break;
3241 case CdMediaClass_CDRW:
3242
3243 if(SavedFeatures & CDRW_FEATURE_MRW_ADDRESSING_PROBLEM) {
3244 UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM on CD-RW\n"));
3245 Vcb->CompatFlags |= UDF_VCB_IC_MRW_ADDR_PROBLEM;
3246 }
3247
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 UDFPrint(("UDFGetDiskInfo: MediaClass RW\n"));
3255 Vcb->MediaType = MediaType_UnknownSize_CDRW;
3256 break;
3257 case CdMediaClass_CDROM:
3258 case CdMediaClass_DVDROM:
3259 case CdMediaClass_HD_DVDROM:
3260 case CdMediaClass_BDROM:
3261 UDFPrint(("UDFGetDiskInfo: MediaClass ROM\n"));
3262 Vcb->MediaType = MediaType_Unknown;
3263 // Vcb->MediaType = MediaType_UnknownSize_CDROM;
3264 break;
3265 default:
3266 UDFPrint(("UDFGetDiskInfo: MediaClass Unknown\n"));
3267 Vcb->MediaType = MediaType_Unknown;
3268 break;
3269 }
3270 MediaType = Vcb->MediaType;
3271
3272 }
3273 #endif //_BROWSE_UDF_
3274
3275 #ifdef UDF_FORMAT_MEDIA
3276
3277 if(fms) {
3278
3279 switch(MediaType) {
3280 case CdMediaClass_CDR:
3281 UDFPrint(("CdMediaClass_CDR\n"));
3282 MediaType = MediaType_UnknownSize_CDR;
3283 if(fms->opt_media == MT_AUTO)
3284 fms->opt_media = MT_CDR;
3285 break;
3286 case CdMediaClass_DVDR:
3287 UDFPrint(("CdMediaClass_DVDR -> MediaType_UnknownSize_CDR\n"));
3288 MediaType = MediaType_UnknownSize_CDR;
3289 if(fms->opt_media == MT_AUTO)
3290 fms->opt_media = MT_DVDR;
3291 break;
3292 case CdMediaClass_DVDpR:
3293 UDFPrint(("CdMediaClass_DVDpR -> MediaType_UnknownSize_CDR\n"));
3294 MediaType = MediaType_UnknownSize_CDR;
3295 if(fms->opt_media == MT_AUTO)
3296 fms->opt_media = MT_DVDpR;
3297 break;
3298 case CdMediaClass_HD_DVDR:
3299 UDFPrint(("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;
3303 break;
3304 case CdMediaClass_BDR:
3305 UDFPrint(("CdMediaClass_BDR -> MediaType_UnknownSize_CDR\n"));
3306 MediaType = MediaType_UnknownSize_CDR;
3307 if(fms->opt_media == MT_AUTO)
3308 fms->opt_media = MT_DVDR;
3309 break;
3310 case CdMediaClass_CDRW:
3311 UDFPrint(("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 UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM on CD-RW\n"));
3317 Vcb->CompatFlags |= UDF_VCB_IC_MRW_ADDR_PROBLEM;
3318 }
3319 break;
3320 case CdMediaClass_DVDRW:
3321 UDFPrint((" CdMediaClass_DVDRW -> MediaType_UnknownSize_CDRW\n"));
3322 if(fms->opt_media == MT_AUTO)
3323 fms->opt_media = MT_DVDRW;
3324 MediaType = MediaType_UnknownSize_CDRW;
3325 break;
3326 case CdMediaClass_DVDpRW:
3327 UDFPrint((" CdMediaClass_DVDpRW -> MediaType_UnknownSize_CDRW\n"));
3328 if(fms->opt_media == MT_AUTO)
3329 fms->opt_media = MT_DVDpRW;
3330 MediaType = MediaType_UnknownSize_CDRW;
3331 break;
3332 case CdMediaClass_DVDRAM:
3333 UDFPrint((" CdMediaClass_DVDRAM -> MediaType_UnknownSize_CDRW\n"));
3334 if(fms->opt_media == MT_AUTO)
3335 fms->opt_media = MT_DVDRAM;
3336 MediaType = MediaType_UnknownSize_CDRW;
3337 break;
3338 case CdMediaClass_HD_DVDRW:
3339 UDFPrint((" 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;
3343 break;
3344 case CdMediaClass_HD_DVDRAM:
3345 UDFPrint((" 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;
3349 break;
3350 case CdMediaClass_BDRE:
3351 UDFPrint((" CdMediaClass_BDRE -> MediaType_UnknownSize_CDRW\n"));
3352 if(fms->opt_media == MT_AUTO)
3353 fms->opt_media = MT_DVDRW;
3354 MediaType = MediaType_UnknownSize_CDRW;
3355 break;
3356 case CdMediaClass_NoDiscPresent:
3357 UDFPrint((" CdMediaClass_NoDiscPresent -> MediaType_NoDiscPresent\n"));
3358 MediaType = MediaType_NoDiscPresent;
3359 fms->opt_media = MT_none;
3360 break;
3361 case CdMediaClass_DoorOpen:
3362 UDFPrint((" CdMediaClass_DoorOpen -> MediaType_DoorOpen\n"));
3363 MediaType = MediaType_DoorOpen;
3364 fms->opt_media = MT_none;
3365 break;
3366 default:
3367 UDFPrint((" MediaType_Unknown\n"));
3368 MediaType = MediaType_Unknown;
3369 break;
3370 }
3371 if(!apply_force_r(fms)) {
3372 my_exit(fms, MKUDF_CANT_APPLY_R);
3373 }
3374 }
3375
3376 #endif //UDF_FORMAT_MEDIA
3377
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;
3381 if(Vcb->DVD_Mode &&
3382 !(Vcb->PhMediaCapFlags & CdCapFlags_RandomWritable)) {
3383 UDFPrint(("UDFGetDiskInfo: DVD && !CdCapFlags_RandomWritable\n"));
3384 UDFPrint((" Read-only volume\n"));
3385 // BrutePoint();
3386 #ifndef UDF_CDRW_EMULATION_ON_ROM
3387 Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
3388 #endif
3389 }
3390 #ifdef UDF_FORMAT_MEDIA
3391 if(fms) {
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);
3396 }
3397 }
3398 #endif //UDF_FORMAT_MEDIA
3399 if(!Vcb->WriteParamsReq) {
3400 UDFPrint(("UDFGetDiskInfo: do not use WriteParams\n"));
3401 }
3402 if(Vcb->PhMediaCapFlags & CdCapFlags_Cav) {
3403 UDFPrint(("UDFGetDiskInfo: Use CAV (1)\n"));
3404 Vcb->VCBFlags |= UDF_VCB_FLAGS_USE_CAV;
3405 }
3406
3407 #ifdef _BROWSE_UDF_
3408 if(!fms) {
3409 // check if this device is capable to write on such media
3410 if(UDFIsDvdMedia(Vcb)) {
3411 //RC =
3412 UDFPrint(("UDFGetDiskInfo: update defaulted LastLBA\n"));
3413 UDFGetBlockSize(DeviceObject,Vcb);
3414 //if(!OS_SUCCESS(RC)) goto Try_FullToc;
3415 } else {
3416 if((SavedFeatures & CDRW_FEATURE_MRW_ADDRESSING_PROBLEM) &&
3417 (SavedFeatures & UDF_VCB_IC_FP_ADDR_PROBLEM)) {
3418 UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM on old CD-ROM\n"));
3419 Vcb->CompatFlags |= UDF_VCB_IC_MRW_ADDR_PROBLEM;
3420 }
3421 }
3422 }
3423 #endif //_BROWSE_UDF_
3424
3425 /*#ifdef UDF_FORMAT_MEDIA
3426 if(fms) {
3427 if(MediaType == CdMediaClass_DVDRW) {
3428 UserPrint(("Not empty media. Erase required.\n"));
3429 my_exit(fms, MKUDF_BLANK_FORMAT_REQUIRED);
3430 }
3431 }
3432 #endif //UDF_FORMAT_MEDIA*/
3433
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),
3438 FALSE, NULL);
3439 if(!OS_SUCCESS(RC)) goto Try_FullToc;
3440
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 UDFPrint(("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
3457 }
3458 } else {
3459 UDFPrint(("Writable disk\n"));
3460 }
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) {
3466 ULONG n;
3467 UDFPrint(("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),
3474 TRUE,NULL);
3475 if(OS_SUCCESS(RC)) {
3476 WPerfDesc = (PLUN_WRITE_PERF_DESC_USER)(ioBuf + sizeof(GET_CAPABILITIES_3_USER_OUT));
3477 n = FALSE;
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;
3481 if(!n) {
3482 Vcb->CurSpeed = WPerfDesc[i].WriteSpeedSupported;
3483 n = TRUE;
3484 UDFPrint(("Use CAV\n"));
3485 } else {
3486 Vcb->CurSpeed = max(WPerfDesc[i].WriteSpeedSupported, Vcb->CurSpeed);
3487 }
3488 UDFPrint(("supports speed %dX\n", Vcb->CurSpeed/176));
3489 //break;
3490 }
3491 }
3492 if(n) {
3493 UDFPrint(("Set r/w speeds to %dX\n", Vcb->CurSpeed/176));
3494 Vcb->MaxWriteSpeed =
3495 Vcb->MaxReadSpeed = Vcb->CurSpeed;
3496 }
3497 }
3498 }
3499 } else {
3500 Vcb->CurSpeed = max(cap->CurrentSpeed, cap->CurrentWriteSpeed);
3501 }
3502 UDFPrint((" Speeds r/w %dX/%dX\n", Vcb->CurSpeed/176, cap->CurrentWriteSpeed/176));
3503
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
3508 UDFSetSpeeds(Vcb);
3509 }
3510 UDFSetCaching(Vcb);
3511
3512 #undef cap
3513 #ifdef UDF_FORMAT_MEDIA
3514 if(fms) {
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;
3519 } else {
3520 fms->opt_media = MT_CDRW;
3521 }
3522 }
3523 if(!apply_force_r(fms)) {
3524 my_exit(fms, MKUDF_CANT_APPLY_R);
3525 }
3526 }
3527 #endif //UDF_FORMAT_MEDIA
3528 RC = UDFReadDiscTrackInfo(DeviceObject, Vcb);
3529
3530 if(!OS_SUCCESS(RC)) {
3531 // may be we have a CD-ROM device
3532 Try_FullToc:
3533 UDFPrint(("Hardware Read-only volume (2)\n"));
3534 // BrutePoint();
3535 #ifndef UDF_CDRW_EMULATION_ON_ROM
3536 Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
3537 #endif
3538
3539 RC = UDFReadAndProcessFullToc(DeviceObject, Vcb);
3540
3541 if(!OS_SUCCESS(RC)) {
3542 RC = UDFUseStandard(DeviceObject,Vcb);
3543 if(!OS_SUCCESS(RC)) try_return(RC);
3544 }
3545
3546 }
3547 } else {
3548 #ifdef _BROWSE_UDF_
3549 GetSignatureFailed:
3550 #endif
3551 RC = UDFUseStandard(DeviceObject, Vcb);
3552 if(!OS_SUCCESS(RC)) try_return(RC);
3553 }
3554
3555 try_exit: NOTHING;
3556
3557 } _SEH2_FINALLY {
3558
3559 if(ioBuf) MyFreePool__(ioBuf);
3560
3561 if(UDFIsDvdMedia(Vcb) &&
3562 (Vcb->CompatFlags & UDF_VCB_IC_BAD_DVD_LAST_LBA) &&
3563 (Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY) &&
3564 Vcb->LastLBA &&
3565 (Vcb->LastLBA < DEFAULT_LAST_LBA_DVD)) {
3566 UDFPrint(("UDF: Bad DVD last LBA %x, fixup!\n", Vcb->LastLBA));
3567 Vcb->LastLBA = DEFAULT_LAST_LBA_DVD;
3568 Vcb->NWA = 0;
3569 }
3570
3571
3572 if(UDFIsDvdMedia(Vcb) && !Vcb->FirstLBA && !Vcb->LastPossibleLBA) {
3573 UDFPrint(("UDF: Empty DVD. Use bogus values for now\n"));
3574 Vcb->LastPossibleLBA = DEFAULT_LAST_LBA_DVD;
3575 Vcb->LastLBA = 0;
3576 }
3577
3578 if((Vcb->LastPossibleLBA & 0x80000000) || (Vcb->LastPossibleLBA < Vcb->LastLBA)) {
3579 UDFPrint(("UDF: bad LastPossibleLBA %x -> %x\n", Vcb->LastPossibleLBA, Vcb->LastLBA));
3580 Vcb->LastPossibleLBA = Vcb->LastLBA;
3581 }
3582 if(!Vcb->WriteBlockSize)
3583 Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->BlockSize;
3584
3585 #ifdef _BROWSE_UDF_
3586 if(Vcb->TrackMap) {
3587 if(Vcb->TrackMap[Vcb->LastTrackNum].LastLba > Vcb->NWA) {
3588 if(Vcb->NWA) {
3589 if(Vcb->TrackMap[Vcb->LastTrackNum].DataParam & TrkInfo_FP) {
3590 Vcb->LastLBA = Vcb->NWA-1;
3591 } else {
3592 Vcb->LastLBA = Vcb->NWA-7-1;
3593 }
3594 }
3595 } else {
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;
3599 }
3600 }
3601 }
3602
3603 for(i=0; i<32; i++) {
3604 if(!(Vcb->LastPossibleLBA >> i))
3605 break;
3606 }
3607 if(i > 20) {
3608 Vcb->WCacheBlocksPerFrameSh = max(Vcb->WCacheBlocksPerFrameSh, (2*i)/5+2);
3609 Vcb->WCacheBlocksPerFrameSh = min(Vcb->WCacheBlocksPerFrameSh, 16);
3610 }
3611
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 UDFPrint(("UDF: Fix LastLBA: %x -> %x\n", Vcb->LastLBA, (Vcb->LastLBA*32) / 39));
3618 Vcb->LastLBA = (Vcb->LastLBA*32) / 39;
3619 }
3620 }
3621 #endif //_BROWSE_UDF_
3622
3623 if(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY) {
3624 if(!Vcb->BlankCD && Vcb->MediaType != MediaType_UnknownSize_CDRW) {
3625 UDFPrint(("UDFGetDiskInfo: R/O+!Blank+!RW -> !RAW\n"));
3626 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_RAW_DISK;
3627 } else {
3628 UDFPrint(("UDFGetDiskInfo: Blank or RW\n"));
3629 }
3630 }
3631
3632 UDFPrint(("UDF: ------------------------------------------\n"));
3633 UDFPrint(("UDF: Media characteristics\n"));
3634 UDFPrint(("UDF: Last session: %d\n",Vcb->LastSession));
3635 UDFPrint(("UDF: First track in first session: %d\n",Vcb->FirstTrackNum));
3636 UDFPrint(("UDF: First track in last session: %d\n",Vcb->FirstTrackNumLastSes));
3637 UDFPrint(("UDF: Last track in last session: %d\n",Vcb->LastTrackNum));
3638 UDFPrint(("UDF: First LBA in first session: %x\n",Vcb->FirstLBA));
3639 UDFPrint(("UDF: First LBA in last session: %x\n",Vcb->FirstLBALastSes));
3640 UDFPrint(("UDF: Last LBA in last session: %x\n",Vcb->LastLBA));
3641 UDFPrint(("UDF: First writable LBA (NWA) in last session: %x\n",Vcb->NWA));
3642 UDFPrint(("UDF: Last available LBA beyond end of last session: %x\n",Vcb->LastPossibleLBA));
3643 UDFPrint(("UDF: blocks per frame: %x\n",1 << Vcb->WCacheBlocksPerFrameSh));
3644 UDFPrint(("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 "
3647 ));
3648 UDFPrint(("UDF: ------------------------------------------\n"));
3649
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"));
3657 }
3658 #endif //UDF_FORMAT_MEDIA
3659
3660 } _SEH2_END;
3661
3662 UDFPrint(("UDFGetDiskInfo: %x\n", RC));
3663 return(RC);
3664
3665 } // end UDFGetDiskInfo()
3666
3667 //#ifdef _BROWSE_UDF_
3668
3669 OSSTATUS
UDFPrepareForReadOperation(IN PVCB Vcb,IN uint32 Lba,IN uint32 BCount)3670 UDFPrepareForReadOperation(
3671 IN PVCB Vcb,
3672 IN uint32 Lba,
3673 IN uint32 BCount
3674 )
3675 {
3676 if( (Vcb->FsDeviceType != FILE_DEVICE_CD_ROM_FILE_SYSTEM) ) {
3677 Vcb->VCBFlags &= ~UDF_VCB_LAST_WRITE;
3678 return STATUS_SUCCESS;
3679 }
3680 uint32 i = Vcb->LastReadTrack;
3681 BOOLEAN speed_changed = FALSE;
3682 #ifdef _BROWSE_UDF_
3683 PUCHAR tmp;
3684 OSSTATUS RC;
3685 SIZE_T ReadBytes;
3686 #endif //_BROWSE_UDF_
3687
3688 #ifdef _UDF_STRUCTURES_H_
3689 if(Vcb->BSBM_Bitmap) {
3690 ULONG i;
3691 for(i=0; i<BCount; i++) {
3692 if(UDFGetBit((uint32*)(Vcb->BSBM_Bitmap), Lba+i)) {
3693 UDFPrint(("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;
3697 }
3698 }
3699 }
3700 #endif //_UDF_STRUCTURES_H_
3701
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)){
3706
3707 // OSSTATUS RC;
3708
3709 RC = UDFSyncCache(Vcb);
3710 }
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
3716 TRUE)
3717 {
3718 // OSSTATUS RC;
3719 UDFSyncCache(Vcb);
3720 }
3721
3722 #ifdef _BROWSE_UDF_
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;
3735 }
3736 } else
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;
3742 }
3743 } else
3744 if(Vcb->CurSpeed < Vcb->MaxReadSpeed ) {
3745 // increment read speed (+1X)
3746 Vcb->CurSpeed += 176/1;
3747 speed_changed = TRUE;
3748 }
3749
3750 if(Vcb->CurSpeed > Vcb->MaxReadSpeed) {
3751 Vcb->CurSpeed = Vcb->MaxReadSpeed;
3752 }
3753 // send speed limits to drive
3754 if(speed_changed) {
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;
3760 }
3761 UDFPrint((" 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),
3768 NULL,0,TRUE,NULL);
3769 }
3770 }
3771
3772 if(UDFIsDvdMedia(Vcb))
3773 return STATUS_SUCCESS;
3774
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
3784 UDFSetMRWMode(Vcb);
3785 break;
3786 default:
3787 Vcb->IncrementalSeekState = INCREMENTAL_SEEK_NONE;
3788 return STATUS_INVALID_PARAMETER;
3789 }
3790 } else {
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))
3794 continue;
3795 Vcb->LastReadTrack = i;
3796 goto check_for_data_track;
3797 }
3798 Vcb->LastReadTrack = 0;
3799 }
3800 if(Vcb->IncrementalSeekState != INCREMENTAL_SEEK_WORKAROUND) {
3801 Vcb->IncrementalSeekState = INCREMENTAL_SEEK_NONE;
3802 return STATUS_SUCCESS;
3803 }
3804 UDFPrint((" UDFPrepareForReadOperation: seek workaround...\n"));
3805 Vcb->IncrementalSeekState = INCREMENTAL_SEEK_DONE;
3806
3807 tmp = (PUCHAR)DbgAllocatePoolWithTag(NonPagedPool, Vcb->BlockSize, 'bNWD');
3808 if(!tmp) {
3809 Vcb->IncrementalSeekState = INCREMENTAL_SEEK_NONE;
3810 return STATUS_INSUFFICIENT_RESOURCES;
3811 }
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 UDFPrint((" seek workaround, LBA %x, status %x\n", i, RC));
3816 }
3817 DbgFreePool(tmp);
3818 #endif //_BROWSE_UDF_
3819
3820 return STATUS_SUCCESS;
3821 } // end UDFPrepareForReadOperation()
3822
3823 //#endif //_BROWSE_UDF_
3824
3825 void
UDFUpdateNWA(PVCB Vcb,uint32 LBA,uint32 BCount,OSSTATUS RC)3826 UDFUpdateNWA(
3827 PVCB Vcb,
3828 uint32 LBA, // physical
3829 uint32 BCount,
3830 OSSTATUS RC
3831 )
3832 {
3833 #ifndef UDF_READ_ONLY_BUILD
3834 #ifdef _BROWSE_UDF_
3835 if(!OS_SUCCESS(RC)) {
3836 return;
3837 }
3838 if(!Vcb->CDR_Mode) {
3839
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;
3849 }
3850 if(Vcb->VCBFlags & UDF_VCB_FLAGS_FORCE_SYNC_CACHE)
3851 goto sync_cache;
3852 /* if(Vcb->CdrwBufferSize) {
3853 Vcb->CdrwBufferSizeCounter += BCount * 2048;
3854 if(Vcb->CdrwBufferSizeCounter >= Vcb->CdrwBufferSize + 2*2048) {
3855 UDFPrint((" UDFUpdateNWA: buffer is full, sync...\n"));
3856 Vcb->CdrwBufferSizeCounter = 0;
3857 goto sync_cache;
3858 }
3859 }*/
3860 if(Vcb->SyncCacheState == SYNC_CACHE_RECOVERY_RETRY) {
3861 Vcb->VCBFlags |= UDF_VCB_FLAGS_FORCE_SYNC_CACHE;
3862 }
3863 Vcb->SyncCacheState = SYNC_CACHE_RECOVERY_NONE;
3864 return;
3865 }
3866 if(Vcb->LastLBA < (LBA+BCount))
3867 Vcb->LastLBA = LBA+BCount;
3868 if(Vcb->NWA)
3869 Vcb->NWA+=BCount+7;
3870 sync_cache:
3871 if(!(Vcb->CompatFlags & UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE)) {
3872 UDFPrint((" UDFUpdateNWA: syncing...\n"));
3873 RC = UDFSyncCache(Vcb);
3874 }
3875 #endif //_BROWSE_UDF_
3876 #endif //UDF_READ_ONLY_BUILD
3877 } // end UDFUpdateNWA()
3878
3879
3880 /*
3881 This routine reads physical sectors
3882 */
3883 /*OSSTATUS
3884 UDFReadSectors(
3885 IN PVCB Vcb,
3886 IN BOOLEAN Translate, // Translate Logical to Physical
3887 IN uint32 Lba,
3888 IN uint32 BCount,
3889 OUT int8* Buffer,
3890 OUT PSIZE_T ReadBytes
3891 )
3892 {
3893
3894 if(Vcb->FastCache.ReadProc && (KeGetCurrentIrql() < DISPATCH_LEVEL)) {
3895 return WCacheReadBlocks__(&(Vcb->FastCache), Vcb, Buffer, Lba, BCount, ReadBytes);
3896 }
3897 return UDFTRead(Vcb, Buffer, BCount*Vcb->BlockSize, Lba, ReadBytes);
3898 } // end UDFReadSectors()*/
3899
3900 #ifdef _BROWSE_UDF_
3901
3902 /*
3903 This routine reads physical sectors
3904 */
3905 OSSTATUS
UDFReadInSector(IN PVCB Vcb,IN BOOLEAN Translate,IN uint32 Lba,IN uint32 i,IN uint32 l,IN BOOLEAN Direct,OUT int8 * Buffer,OUT PSIZE_T ReadBytes)3906 UDFReadInSector(
3907 IN PVCB Vcb,
3908 IN BOOLEAN Translate, // Translate Logical to Physical
3909 IN uint32 Lba,
3910 IN uint32 i, // offset in sector
3911 IN uint32 l, // transfer length
3912 IN BOOLEAN Direct, // Disable access to non-cached data
3913 OUT int8* Buffer,
3914 OUT PSIZE_T ReadBytes
3915 )
3916 {
3917 int8* tmp_buff;
3918 OSSTATUS status;
3919 SIZE_T _ReadBytes;
3920
3921 (*ReadBytes) = 0;
3922 if(WCacheIsInitialized__(&(Vcb->FastCache)) && (KeGetCurrentIrql() < DISPATCH_LEVEL)) {
3923 status = WCacheDirect__(&(Vcb->FastCache), Vcb, Lba, FALSE, &tmp_buff, Direct);
3924 if(OS_SUCCESS(status)) {
3925 (*ReadBytes) += l;
3926 RtlCopyMemory(Buffer, tmp_buff+i, l);
3927 }
3928 if(!Direct) WCacheEODirect__(&(Vcb->FastCache), Vcb);
3929 } else {
3930 if(Direct) {
3931 return STATUS_INVALID_PARAMETER;
3932 }
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)) {
3937 (*ReadBytes) += l;
3938 RtlCopyMemory(Buffer, tmp_buff+i, l);
3939 }
3940 MyFreePool__(tmp_buff);
3941 }
3942 return status;
3943 } // end UDFReadInSector()
3944
3945 /*
3946 This routine reads data of unaligned offset & length
3947 */
3948 OSSTATUS
UDFReadData(IN PVCB Vcb,IN BOOLEAN Translate,IN int64 Offset,IN uint32 Length,IN BOOLEAN Direct,OUT int8 * Buffer,OUT PSIZE_T ReadBytes)3949 UDFReadData(
3950 IN PVCB Vcb,
3951 IN BOOLEAN Translate, // Translate Logical to Physical
3952 IN int64 Offset,
3953 IN uint32 Length,
3954 IN BOOLEAN Direct, // Disable access to non-cached data
3955 OUT int8* Buffer,
3956 OUT PSIZE_T ReadBytes
3957 )
3958 {
3959 uint32 i, l, Lba, BS=Vcb->BlockSize;
3960 uint32 BSh=Vcb->BlockSizeBits;
3961 OSSTATUS status;
3962 SIZE_T _ReadBytes = 0;
3963 Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
3964 uint32 to_read;
3965
3966 (*ReadBytes) = 0;
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 ?
3974 (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;
3979 Lba ++;
3980 Buffer += l;
3981 }
3982 // read sector_size-aligned part
3983 i = Length >> BSh;
3984 while(i) {
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)) {
3989 return status;
3990 }
3991 Buffer += to_read<<BSh;
3992 Length -= to_read<<BSh;
3993 Lba += to_read;
3994 i -= to_read;
3995 }
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;
4000
4001 return status;
4002 } // end UDFReadData()
4003
4004 #endif //_BROWSE_UDF_
4005
4006 #ifndef UDF_READ_ONLY_BUILD
4007 /*
4008 This routine writes physical sectors. This routine supposes Lba & Length
4009 alignment on WriteBlock (packet) size.
4010 */
4011 OSSTATUS
UDFWriteSectors(IN PVCB Vcb,IN BOOLEAN Translate,IN uint32 Lba,IN uint32 BCount,IN BOOLEAN Direct,IN int8 * Buffer,OUT PSIZE_T WrittenBytes)4012 UDFWriteSectors(
4013 IN PVCB Vcb,
4014 IN BOOLEAN Translate, // Translate Logical to Physical
4015 IN uint32 Lba,
4016 IN uint32 BCount,
4017 IN BOOLEAN Direct, // Disable access to non-cached data
4018 IN int8* Buffer,
4019 OUT PSIZE_T WrittenBytes
4020 )
4021 {
4022 OSSTATUS status;
4023
4024 #ifdef _BROWSE_UDF_
4025 if(!Vcb->Modified || (Vcb->IntegrityType == INTEGRITY_TYPE_CLOSE)) {
4026 UDFSetModified(Vcb);
4027 if(Vcb->LVid && !Direct) {
4028 status = UDFUpdateLogicalVolInt(Vcb,FALSE);
4029 }
4030 }
4031
4032 if(Vcb->CDR_Mode) {
4033 if(Vcb->LastLBA < Lba+BCount-1)
4034 Vcb->LastLBA = Lba+BCount-1;
4035 }
4036 #endif //_BROWSE_UDF_
4037
4038 if(Vcb->FastCache.WriteProc && (KeGetCurrentIrql() < DISPATCH_LEVEL)) {
4039 status = WCacheWriteBlocks__(&(Vcb->FastCache), Vcb, Buffer, Lba, BCount, WrittenBytes, Direct);
4040 ASSERT(OS_SUCCESS(status));
4041 #ifdef _BROWSE_UDF_
4042 UDFClrZeroBits(Vcb->ZSBM_Bitmap, Lba, BCount);
4043 #endif //_BROWSE_UDF_
4044 return status;
4045 }
4046 /* void* buffer;
4047 OSSTATUS status;
4048 SIZE_T _ReadBytes;
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);*/
4053 #ifdef UDF_DBG
4054 status = UDFTWrite(Vcb, Buffer, BCount<<Vcb->BlockSizeBits, Lba, WrittenBytes);
4055 ASSERT(OS_SUCCESS(status));
4056 return status;
4057 #else // UDF_DBG
4058 return UDFTWrite(Vcb, Buffer, BCount<<Vcb->BlockSizeBits, Lba, WrittenBytes);
4059 #endif // UDF_DBG
4060 } // end UDFWriteSectors()
4061
4062 OSSTATUS
UDFWriteInSector(IN PVCB Vcb,IN BOOLEAN Translate,IN uint32 Lba,IN uint32 i,IN uint32 l,IN BOOLEAN Direct,OUT int8 * Buffer,OUT PSIZE_T WrittenBytes)4063 UDFWriteInSector(
4064 IN PVCB Vcb,
4065 IN BOOLEAN Translate, // Translate Logical to Physical
4066 IN uint32 Lba,
4067 IN uint32 i, // offset in sector
4068 IN uint32 l, // transfer length
4069 IN BOOLEAN Direct, // Disable access to non-cached data
4070 OUT int8* Buffer,
4071 OUT PSIZE_T WrittenBytes
4072 )
4073 {
4074 int8* tmp_buff;
4075 OSSTATUS status;
4076 #ifdef _BROWSE_UDF_
4077 SIZE_T _WrittenBytes;
4078 SIZE_T ReadBytes;
4079
4080 if(!Vcb->Modified) {
4081 UDFSetModified(Vcb);
4082 if(Vcb->LVid)
4083 status = UDFUpdateLogicalVolInt(Vcb,FALSE);
4084 }
4085
4086 if(Vcb->CDR_Mode) {
4087 if(Vcb->LastLBA < Lba)
4088 Vcb->LastLBA = Lba;
4089 }
4090 #endif //_BROWSE_UDF_
4091
4092 (*WrittenBytes) = 0;
4093 #ifdef _BROWSE_UDF_
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)) {
4098 #ifdef _BROWSE_UDF_
4099 UDFClrZeroBit(Vcb->ZSBM_Bitmap, Lba);
4100 #endif //_BROWSE_UDF_
4101 (*WrittenBytes) += l;
4102 RtlCopyMemory(tmp_buff+i, Buffer, l);
4103 }
4104 if(!Direct) WCacheEODirect__(&(Vcb->FastCache), Vcb);
4105 #ifdef _BROWSE_UDF_
4106 } else {
4107 // If Direct = TRUE we should never get here, but...
4108 if(Direct) {
4109 BrutePoint();
4110 return STATUS_INVALID_PARAMETER;
4111 }
4112 tmp_buff = (int8*)MyAllocatePool__(NonPagedPool, Vcb->BlockSize);
4113 if(!tmp_buff) {
4114 BrutePoint();
4115 return STATUS_INSUFFICIENT_RESOURCES;
4116 }
4117 // read packet
4118 status = UDFReadSectors(Vcb, Translate, Lba, 1, FALSE, tmp_buff, &ReadBytes);
4119 if(!OS_SUCCESS(status)) goto EO_WrSctD;
4120 // modify packet
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;
4126 EO_WrSctD:
4127 MyFreePool__(tmp_buff);
4128 }
4129 ASSERT(OS_SUCCESS(status));
4130 if(!OS_SUCCESS(status)) {
4131 UDFPrint(("UDFWriteInSector() for LBA %x failed\n", Lba));
4132 }
4133 #endif //_BROWSE_UDF_
4134 return status;
4135 } // end UDFWriteInSector()
4136
4137 /*
4138 This routine writes data at unaligned offset & length
4139 */
4140 OSSTATUS
UDFWriteData(IN PVCB Vcb,IN BOOLEAN Translate,IN int64 Offset,IN SIZE_T Length,IN BOOLEAN Direct,IN int8 * Buffer,OUT PSIZE_T WrittenBytes)4141 UDFWriteData(
4142 IN PVCB Vcb,
4143 IN BOOLEAN Translate, // Translate Logical to Physical
4144 IN int64 Offset,
4145 IN SIZE_T Length,
4146 IN BOOLEAN Direct, // setting this flag delays flushing of given
4147 // data to indefinite term
4148 IN int8* Buffer,
4149 OUT PSIZE_T WrittenBytes
4150 )
4151 {
4152 uint32 i, l, Lba, BS=Vcb->BlockSize;
4153 uint32 BSh=Vcb->BlockSizeBits;
4154 OSSTATUS status;
4155 SIZE_T _WrittenBytes;
4156 Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
4157
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 ?
4166 (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;
4170 Lba ++;
4171 Buffer += l;
4172 }
4173 // write sector_size-aligned part
4174 i = Length >> BSh;
4175 if(i) {
4176 status = UDFWriteSectors(Vcb, Translate, Lba, i, Direct, Buffer, &_WrittenBytes);
4177 (*WrittenBytes) += _WrittenBytes;
4178 if(!OS_SUCCESS(status)) return status;
4179 l = i<<BSh;
4180 #ifdef _BROWSE_UDF_
4181 UDFClrZeroBits(Vcb->ZSBM_Bitmap, Lba, i);
4182 #endif //_BROWSE_UDF_
4183 if(!(Length = Length - l)) return STATUS_SUCCESS;
4184 Lba += i;
4185 Buffer += l;
4186 }
4187 status = UDFWriteInSector(Vcb, Translate, Lba, 0, Length, Direct, Buffer, &_WrittenBytes);
4188 (*WrittenBytes) += _WrittenBytes;
4189 #ifdef _BROWSE_UDF_
4190 UDFClrZeroBit(Vcb->ZSBM_Bitmap, Lba);
4191 #endif //_BROWSE_UDF_
4192
4193 return status;
4194 } // end UDFWriteData()
4195
4196 #endif //UDF_READ_ONLY_BUILD
4197
4198 OSSTATUS
UDFResetDeviceDriver(IN PVCB Vcb,IN PDEVICE_OBJECT TargetDeviceObject,IN BOOLEAN Unlock)4199 UDFResetDeviceDriver(
4200 IN PVCB Vcb,
4201 IN PDEVICE_OBJECT TargetDeviceObject,
4202 IN BOOLEAN Unlock
4203 )
4204 {
4205 PCDRW_RESET_DRIVER_USER_IN tmp = (PCDRW_RESET_DRIVER_USER_IN)
4206 MyAllocatePool__(NonPagedPool, sizeof(CDRW_RESET_DRIVER_USER_IN));
4207 OSSTATUS RC;
4208 if(!tmp)
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);
4215 if(Vcb) {
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
4224 UDFSetSpeeds(Vcb);
4225 }
4226 UDFSetCaching(Vcb);
4227 }
4228
4229 MyFreePool__(tmp);
4230 return RC;
4231 } // end UDFResetDeviceDriver()
4232
4233 OSSTATUS
UDFSetSpeeds(IN PVCB Vcb)4234 UDFSetSpeeds(
4235 IN PVCB Vcb
4236 )
4237 {
4238 OSSTATUS RC;
4239
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;
4243 Vcb->CurSpeed =
4244 Vcb->SpeedBuf.ReadSpeed =
4245 Vcb->SpeedBuf.WriteSpeed = Vcb->MaxWriteSpeed;
4246 } else {
4247 Vcb->SpeedBuf.ReadSpeed = Vcb->CurSpeed;
4248 Vcb->SpeedBuf.WriteSpeed = Vcb->MaxWriteSpeed;
4249 }
4250 UDFPrint((" 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),
4257 NULL,0,TRUE,NULL);
4258 UDFPrint(("UDFSetSpeeds: %x\n", RC));
4259 return RC;
4260 } // end UDFSetSpeeds()
4261
4262 NTSTATUS
UDFSetCaching(IN PVCB Vcb)4263 UDFSetCaching(
4264 IN PVCB Vcb
4265 )
4266 {
4267 #pragma pack(push,1)
4268 struct {
4269 MODE_PARAMETER_HEADER Header;
4270 MODE_CACHING_PAGE Data;
4271 CHAR Padding [16];
4272 } CachingPage;
4273
4274 struct {
4275 MODE_PARAMETER_HEADER Header;
4276 MODE_READ_WRITE_RECOVERY_PAGE Data;
4277 CHAR Padding [16];
4278 } RecoveryPage;
4279 #ifdef _MSC_VER
4280 #pragma pack(pop,1)
4281 #else
4282 #pragma pack(pop)
4283 #endif
4284
4285 MODE_SENSE_USER_IN ModeSenseCtl;
4286 OSSTATUS RC;
4287
4288 UDFPrint(("UDFSetCaching:\n"));
4289
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),
4294 FALSE, NULL);
4295 if(OS_SUCCESS(RC)) {
4296 UDFPrint((" Error recovery page:\n"
4297 "PageCode %d\n"
4298 "PageLength %d\n"
4299
4300 "DCRBit %d\n"
4301 "DTEBit %d\n"
4302 "PERBit %d\n"
4303 "EERBit %d\n"
4304 "RCBit %d\n"
4305 "TBBit %d\n"
4306 "ARRE %d\n"
4307 "AWRE %d\n"
4308
4309 "ReadRetryCount %d\n"
4310 "CorrectionSpan %d\n"
4311 "HeadOffsetCount %d\n"
4312 "DataStrobOffsetCount %d\n"
4313
4314 "ErrorRecoveryParam2.Fields.EMCDR %d\n"
4315
4316 "WriteRetryCount %d\n",
4317
4318 RecoveryPage.Data.PageCode,
4319 RecoveryPage.Data.PageLength,
4320
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,
4329
4330 RecoveryPage.Data.ReadRetryCount,
4331 RecoveryPage.Data.CorrectionSpan,
4332 RecoveryPage.Data.HeadOffsetCount,
4333 RecoveryPage.Data.DataStrobOffsetCount,
4334
4335 RecoveryPage.Data.ErrorRecoveryParam2.Fields.EMCDR,
4336
4337 RecoveryPage.Data.WriteRetryCount
4338
4339 ));
4340 }
4341
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),
4346 FALSE, NULL);
4347 if(!OS_SUCCESS(RC)) {
4348 return RC;
4349 }
4350
4351 UDFPrint((" Caching page:\n"
4352 "PageCode %d\n"
4353 "PageLength %d\n"
4354 "ReadDisableCache %d\n"
4355 "MultiplicationFactor %d\n"
4356 "WriteCacheEnable %d\n"
4357 "WriteRetensionPriority %d\n"
4358 "ReadRetensionPriority %d\n",
4359
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
4367 ));
4368
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,
4378 NULL,0,
4379 FALSE, NULL);
4380 } else {
4381 RC = STATUS_SUCCESS;
4382 }
4383 UDFPrint(("UDFSetCaching: %x\n", RC));
4384 return RC;
4385 } // end UDFSetCaching()
4386