[UDFS]
[reactos.git] / reactos / drivers / filesystems / udfs / Include / phys_lib.cpp
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
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
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
94 UDFTIOVerify(
95 IN void* _Vcb,
96 IN void* Buffer, // Target buffer
97 IN uint32 Length,
98 IN uint32 LBA,
99 OUT uint32* IOBytes,
100 IN uint32 Flags
101 )
102 {
103 OSSTATUS RC = STATUS_SUCCESS;
104 uint32 i, j;
105 uint32 mask;
106 uint32 lba0, len, lba1;
107 PUCHAR tmp_buff;
108 PUCHAR p;
109 PCHAR cached_block;
110 uint32 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 = (uint32)_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 = (uint32)_Vcb;
252 RC = UDFTRead(_Vcb, p, Vcb->SparingBlockSize << Vcb->BlockSizeBits, lba0+i, &tmp_wb,
253 Flags | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN);
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 = (uint32)_Vcb;
275 RC = UDFTRead(_Vcb, p, Vcb->BlockSize, lba0+i, &tmp_wb,
276 Flags | PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN);
277 if(!OS_SUCCESS(RC)) {
278 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 = (uint32)_Vcb;
301 RC = UDFTRead(_Vcb, p, Vcb->BlockSize, lba0+i, &tmp_wb,
302 Flags | PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN);
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 = (uint32)_Vcb;
367 RC = UDFTWrite(_Vcb, tmp_buff, Vcb->SparingBlockSize << Vcb->BlockSizeBits, lba1, &tmp_wb,
368 Flags | PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN);
369 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 = (uint32)_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
420 UDFTWriteVerify(
421 IN void* _Vcb,
422 IN void* Buffer, // Target buffer
423 IN uint32 Length,
424 IN uint32 LBA,
425 OUT uint32* 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
433 UDFTReadVerify(
434 IN void* _Vcb,
435 IN void* Buffer, // Target buffer
436 IN uint32 Length,
437 IN uint32 LBA,
438 OUT uint32* 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
453 UDFTWrite(
454 IN void* _Vcb,
455 IN void* Buffer, // Target buffer
456 IN uint32 Length,
457 IN uint32 LBA,
458 OUT uint32* 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)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 uint32 _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)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
596 UDFTRead(
597 IN void* _Vcb,
598 IN void* Buffer, // Target buffer
599 IN uint32 Length,
600 IN uint32 LBA,
601 OUT uint32* 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) = (ULONG)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 uint32 _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 = (ULONG)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
730 UDFTReadAsync(
731 IN void* _Vcb,
732 IN void* _WContext,
733 IN void* Buffer, // Target buffer
734 IN uint32 Length,
735 IN uint32 LBA,
736 OUT uint32* 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 uint32 _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
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
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
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 ULONG 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
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
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 uint32 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
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
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 uint32 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
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