]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.c
1. UsbMassStorage: Increase the timeout of USBFloppyRead10 and USBFloppyWrite10 for...
[mirror_edk2.git] / EdkModulePkg / Bus / Usb / UsbMassStorage / Dxe / UsbMassStorageHelper.c
1 /*++
2
3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 UsbMassStorageHelper.c
15
16 Abstract:
17
18 Helper functions for USB Mass Storage Driver
19
20 Revision History
21
22 --*/
23
24 #include "UsbMassStorageHelper.h"
25
26 STATIC
27 BOOLEAN
28 IsNoMedia (
29 IN REQUEST_SENSE_DATA *SenseData,
30 IN UINTN SenseCounts
31 );
32
33 STATIC
34 BOOLEAN
35 IsMediaError (
36 IN REQUEST_SENSE_DATA *SenseData,
37 IN UINTN SenseCounts
38 );
39
40 STATIC
41 BOOLEAN
42 IsMediaChange (
43 IN REQUEST_SENSE_DATA *SenseData,
44 IN UINTN SenseCounts
45 );
46
47 STATIC
48 BOOLEAN
49 IsDriveReady (
50 IN REQUEST_SENSE_DATA *SenseData,
51 IN UINTN SenseCounts,
52 OUT BOOLEAN *NeedRetry
53 );
54
55 STATIC
56 BOOLEAN
57 IsMediaWriteProtected (
58 IN REQUEST_SENSE_DATA *SenseData,
59 IN UINTN SenseCounts
60 );
61
62
63 EFI_STATUS
64 USBFloppyPacketCommand (
65 USB_FLOPPY_DEV *UsbFloppyDevice,
66 VOID *Command,
67 UINT8 CommandSize,
68 VOID *DataBuffer,
69 UINT32 BufferLength,
70 EFI_USB_DATA_DIRECTION Direction,
71 UINT16 TimeOutInMilliSeconds
72 )
73 /*++
74
75 Routine Description:
76 Sends Packet Command to USB Floppy Drive.
77
78 Arguments:
79 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
80 Command - A pointer to the command packet.
81 CommandSize - Indicates the size of the command packet.
82 DataBuffer - A pointer to the buffer for the data transfer
83 after the command packet.
84 BufferLength - Indicates the size of the Data Buffer.
85 Direction - Transfer Direction
86 TimeOutInMilliSeconds - Timeout Value
87 Returns:
88 EFI_SUCCESS - Success
89 --*/
90 {
91 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
92 EFI_STATUS Status;
93
94 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
95 //
96 // Directly calling EFI_USB_ATAPI_PROTOCOL.UsbAtapiPacketCmd()
97 // to perform the command request.
98 //
99 Status = UsbAtapiInterface->UsbAtapiPacketCmd (
100 UsbAtapiInterface,
101 Command,
102 CommandSize,
103 DataBuffer,
104 BufferLength,
105 Direction,
106 TimeOutInMilliSeconds
107 );
108
109 return Status;
110 }
111
112 EFI_STATUS
113 USBFloppyIdentify (
114 IN USB_FLOPPY_DEV *UsbFloppyDevice
115 )
116 /*++
117
118 Routine Description:
119 Retrieves device information to tell the device type.
120
121 Arguments:
122 UsbFloppyDevice The USB_FLOPPY_DEV instance.
123
124 Returns:
125 EFI_DEVICE_ERROR - Hardware error
126 EFI_SUCCESS - Success
127 --*/
128 {
129
130 EFI_STATUS Status;
131 USB_INQUIRY_DATA *Idata;
132 BOOLEAN MediaChange;
133
134 //
135 // Send Inquiry Packet Command to get INQUIRY data.
136 //
137 Status = USBFloppyInquiry (UsbFloppyDevice, &Idata);
138 if (EFI_ERROR (Status)) {
139 return EFI_DEVICE_ERROR;
140 }
141
142 //
143 // Get media removable info from INQUIRY data.
144 //
145 UsbFloppyDevice->BlkIo.Media->RemovableMedia = (UINT8) ((Idata->RMB & 0x80) == 0x80);
146
147 //
148 // Identify device type via INQUIRY data.
149 //
150 switch ((Idata->peripheral_type) & 0x1f) {
151 //
152 // Floppy
153 //
154 case 0x00:
155 UsbFloppyDevice->DeviceType = USBFLOPPY;
156 UsbFloppyDevice->BlkIo.Media->MediaId = 0;
157 UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
158 UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
159 UsbFloppyDevice->BlkIo.Media->BlockSize = 0x200;
160 break;
161
162 //
163 // CD-ROM
164 //
165 case 0x05:
166 UsbFloppyDevice->DeviceType = USBCDROM;
167 UsbFloppyDevice->BlkIo.Media->MediaId = 0;
168 UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
169 UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
170 UsbFloppyDevice->BlkIo.Media->BlockSize = 0x800;
171 UsbFloppyDevice->BlkIo.Media->ReadOnly = TRUE;
172 break;
173
174 default:
175 gBS->FreePool (Idata);
176 return EFI_DEVICE_ERROR;
177 };
178
179 //
180 // Initialize some device specific data.
181 //
182 //
183 // original sense data numbers
184 //
185 UsbFloppyDevice->SenseDataNumber = 6;
186
187 if (UsbFloppyDevice->SenseData != NULL) {
188 gBS->FreePool (UsbFloppyDevice->SenseData);
189 UsbFloppyDevice->SenseData = NULL;
190 }
191
192 UsbFloppyDevice->SenseData = AllocatePool (UsbFloppyDevice->SenseDataNumber * sizeof (REQUEST_SENSE_DATA));
193
194 if (UsbFloppyDevice->SenseData == NULL) {
195 gBS->FreePool (Idata);
196 return EFI_DEVICE_ERROR;
197 }
198
199 //
200 // Get media information.
201 //
202 UsbFloppyDetectMedia (UsbFloppyDevice, &MediaChange);
203
204 gBS->FreePool (Idata);
205
206 return EFI_SUCCESS;
207 }
208
209 EFI_STATUS
210 USBFloppyInquiry (
211 IN USB_FLOPPY_DEV *UsbFloppyDevice,
212 OUT USB_INQUIRY_DATA **Idata
213 )
214 /*++
215
216 Routine Description:
217 Send Inquiry Packet Command to device and retrieve Inquiry Data.
218
219 Arguments:
220 UsbFloppyDevice The USB_FLOPPY_DEV instance.
221 Idata A pointer pointing to the address of
222 Inquiry Data.
223
224 Returns:
225 EFI_DEVICE_ERROR - Hardware error
226 EFI_SUCCESS - Success
227 --*/
228 {
229 ATAPI_PACKET_COMMAND Packet;
230 EFI_STATUS Status;
231
232
233 //
234 // prepare command packet for the Inquiry Packet Command.
235 //
236 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
237 Packet.Inquiry.opcode = INQUIRY;
238 Packet.Inquiry.page_code = 0;
239 Packet.Inquiry.allocation_length = sizeof (USB_INQUIRY_DATA);
240
241 *Idata = AllocateZeroPool (sizeof (USB_INQUIRY_DATA));
242 if (*Idata == NULL) {
243 return EFI_DEVICE_ERROR;
244 }
245 //
246 // Send command packet and retrieve requested Inquiry Data.
247 //
248 Status = USBFloppyPacketCommand (
249 UsbFloppyDevice,
250 &Packet,
251 sizeof (ATAPI_PACKET_COMMAND),
252 (VOID *) (*Idata),
253 sizeof (USB_INQUIRY_DATA),
254 EfiUsbDataIn,
255 USBFLPTIMEOUT * 3
256 );
257 if (EFI_ERROR (Status)) {
258 gBS->FreePool (*Idata);
259 return EFI_DEVICE_ERROR;
260 }
261
262 return EFI_SUCCESS;
263 }
264
265 EFI_STATUS
266 USBFloppyRead10 (
267 IN USB_FLOPPY_DEV *UsbFloppyDevice,
268 IN VOID *Buffer,
269 IN EFI_LBA Lba,
270 IN UINTN NumberOfBlocks
271 )
272 /*++
273
274 Routine Description:
275 Sends Read10 Packet Command to device to perform data transfer
276 from device to host.
277
278 Arguments:
279 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
280 Buffer - A pointer to the destination buffer for the data.
281 The caller is responsible for either having implicit
282 or explicit ownership of the buffer.
283 Lba - The starting logical block address to read from
284 on the device.
285 NumberOfBlocks - Indicates the number of blocks that the read
286 operation requests.
287
288 Returns:
289 EFI_DEVICE_ERROR - Hardware error
290 EFI_SUCCESS - Success
291 --*/
292 {
293 ATAPI_PACKET_COMMAND Packet;
294 READ10_CMD *Read10Packet;
295 UINT16 MaxBlock;
296 UINT16 BlocksRemaining;
297 UINT16 SectorCount;
298 UINT32 Lba32;
299 UINT32 BlockSize;
300 UINT32 ByteCount;
301 VOID *ptrBuffer;
302 EFI_STATUS Status;
303 UINT16 TimeOut;
304 UINT8 Index;
305
306
307 //
308 // prepare command packet for the Inquiry Packet Command.
309 //
310 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
311 Read10Packet = &Packet.Read10;
312 Lba32 = (UINT32) Lba;
313 ptrBuffer = Buffer;
314 BlockSize = UsbFloppyDevice->BlkIo.Media->BlockSize;
315
316 MaxBlock = (UINT16) (65536 / BlockSize);
317 BlocksRemaining = (UINT16) NumberOfBlocks;
318
319 Status = EFI_SUCCESS;
320 while (BlocksRemaining > 0) {
321 if (BlocksRemaining <= MaxBlock) {
322 SectorCount = BlocksRemaining;
323 } else {
324 SectorCount = MaxBlock;
325 }
326
327 for (Index = 0; Index < 3; Index ++) {
328
329 //
330 // fill the Packet data structure
331 //
332 Read10Packet->opcode = READ_10;
333 //
334 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
335 // Lba0 is MSB, Lba3 is LSB
336 //
337 Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff);
338 Read10Packet->Lba2 = (UINT8) (Lba32 >> 8);
339 Read10Packet->Lba1 = (UINT8) (Lba32 >> 16);
340 Read10Packet->Lba0 = (UINT8) (Lba32 >> 24);
341
342 //
343 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
344 // TranLen0 is MSB, TranLen is LSB
345 //
346 Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);
347 Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8);
348
349 ByteCount = SectorCount * BlockSize;
350
351 TimeOut = (UINT16) (SectorCount * USBDATATIMEOUT);
352
353
354 Status = USBFloppyPacketCommand (
355 UsbFloppyDevice,
356 &Packet,
357 sizeof (ATAPI_PACKET_COMMAND),
358 (VOID *) ptrBuffer,
359 ByteCount,
360 EfiUsbDataIn,
361 TimeOut
362 );
363 if (!EFI_ERROR (Status)) {
364 break;
365 }
366 }
367
368 if (Index == 3) {
369 return EFI_DEVICE_ERROR;
370 }
371
372 Lba32 += SectorCount;
373 ptrBuffer = (UINT8 *) ptrBuffer + SectorCount * BlockSize;
374 BlocksRemaining = (UINT16) (BlocksRemaining - SectorCount);
375 }
376
377 return Status;
378 }
379
380 STATIC
381 EFI_STATUS
382 USBFloppyReadCapacity (
383 IN USB_FLOPPY_DEV *UsbFloppyDevice
384 )
385 /*++
386
387 Routine Description:
388 Retrieves media capacity information via
389 sending Read Capacity Packet Command.
390
391 Arguments:
392 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
393
394 Returns:
395 EFI_DEVICE_ERROR - Hardware error
396 EFI_SUCCESS - Success
397 --*/
398 {
399 //
400 // status returned by Read Capacity Packet Command
401 //
402 EFI_STATUS Status;
403 ATAPI_PACKET_COMMAND Packet;
404
405 //
406 // used for capacity data returned from Usb Floppy
407 //
408 READ_CAPACITY_DATA Data;
409
410 ZeroMem (&Data, sizeof (Data));
411
412
413 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
414 Packet.Inquiry.opcode = READ_CAPACITY;
415 Status = USBFloppyPacketCommand (
416 UsbFloppyDevice,
417 &Packet,
418 sizeof (ATAPI_PACKET_COMMAND),
419 (VOID *) &Data,
420 sizeof (READ_CAPACITY_DATA),
421 EfiUsbDataIn,
422 USBFLPTIMEOUT
423 );
424
425 if (EFI_ERROR (Status)) {
426 return EFI_DEVICE_ERROR;
427 }
428
429 UsbFloppyDevice->BlkIo.Media->LastBlock = (Data.LastLba3 << 24) |
430 (Data.LastLba2 << 16) |
431 (Data.LastLba1 << 8) |
432 Data.LastLba0;
433
434 UsbFloppyDevice->BlkIo.Media->MediaPresent = TRUE;
435
436 UsbFloppyDevice->BlkIo.Media->BlockSize = 0x800;
437
438 return EFI_SUCCESS;
439
440 }
441
442 EFI_STATUS
443 USBFloppyReadFormatCapacity (
444 IN USB_FLOPPY_DEV *UsbFloppyDevice
445 )
446 /*++
447
448 Routine Description:
449 Retrieves media capacity information via sending Read Format
450 Capacity Packet Command.
451
452 Arguments:
453 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
454
455 Returns:
456 EFI_DEVICE_ERROR - Hardware error
457 EFI_SUCCESS - Success
458 --*/
459 {
460 //
461 // status returned by Read Capacity Packet Command
462 //
463 EFI_STATUS Status;
464 ATAPI_PACKET_COMMAND Packet;
465
466 //
467 // used for capacity data returned from Usb Floppy
468 //
469 READ_FORMAT_CAPACITY_DATA FormatData;
470
471 ZeroMem (&FormatData, sizeof (FormatData));
472
473
474 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
475 Packet.ReadFormatCapacity.opcode = READ_FORMAT_CAPACITY;
476 Packet.ReadFormatCapacity.allocation_length_lo = 12;
477 Status = USBFloppyPacketCommand (
478 UsbFloppyDevice,
479 &Packet,
480 sizeof (ATAPI_PACKET_COMMAND),
481 (VOID *) &FormatData,
482 sizeof (READ_FORMAT_CAPACITY_DATA),
483 EfiUsbDataIn,
484 USBFLPTIMEOUT
485 );
486
487 if (EFI_ERROR (Status)) {
488 return EFI_DEVICE_ERROR;
489 }
490
491 if (FormatData.DesCode == 3) {
492 //
493 // Media is not present
494 //
495 UsbFloppyDevice->BlkIo.Media->MediaId = 0;
496 UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
497 UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
498 } else {
499
500 UsbFloppyDevice->BlkIo.Media->LastBlock = (FormatData.LastLba3 << 24) |
501 (FormatData.LastLba2 << 16) |
502 (FormatData.LastLba1 << 8) |
503 FormatData.LastLba0;
504
505 UsbFloppyDevice->BlkIo.Media->LastBlock--;
506
507 UsbFloppyDevice->BlkIo.Media->BlockSize = (FormatData.BlockSize2 << 16) |
508 (FormatData.BlockSize1 << 8) |
509 FormatData.BlockSize0;
510
511 UsbFloppyDevice->BlkIo.Media->MediaPresent = TRUE;
512
513 UsbFloppyDevice->BlkIo.Media->BlockSize = 0x200;
514
515 }
516
517 return EFI_SUCCESS;
518
519 }
520
521 EFI_STATUS
522 UsbFloppyRequestSense (
523 IN USB_FLOPPY_DEV *UsbFloppyDevice,
524 OUT UINTN *SenseCounts
525 )
526 /*++
527
528 Routine Description:
529 Retrieves Sense Data from device via
530 sending Request Sense Packet Command.
531
532 Arguments:
533 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
534 SenseCounts - A pointer to the number of Sense Data returned.
535
536 Returns:
537 EFI_DEVICE_ERROR - Hardware error
538 EFI_SUCCESS - Success
539 --*/
540 {
541 EFI_STATUS Status;
542 REQUEST_SENSE_DATA *Sense;
543 UINT8 *Ptr;
544 BOOLEAN SenseReq;
545 ATAPI_PACKET_COMMAND Packet;
546
547
548 *SenseCounts = 0;
549
550 ZeroMem (
551 UsbFloppyDevice->SenseData,
552 sizeof (REQUEST_SENSE_DATA) * (UsbFloppyDevice->SenseDataNumber)
553 );
554 //
555 // fill command packet for Request Sense Packet Command
556 //
557 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
558 Packet.RequestSense.opcode = REQUEST_SENSE;
559 Packet.RequestSense.allocation_length = sizeof (REQUEST_SENSE_DATA);
560
561 //
562 // initialize pointer
563 //
564 Ptr = (UINT8 *) (UsbFloppyDevice->SenseData);
565
566 //
567 // request sense data from device continuously
568 // until no sense data exists in the device.
569 //
570 for (SenseReq = TRUE; SenseReq;) {
571
572 Sense = (REQUEST_SENSE_DATA *) Ptr;
573
574 //
575 // send out Request Sense Packet Command and get one Sense
576 // data from device.
577 //
578 Status = USBFloppyPacketCommand (
579 UsbFloppyDevice,
580 &Packet,
581 sizeof (ATAPI_PACKET_COMMAND),
582 (VOID *) Ptr,
583 sizeof (REQUEST_SENSE_DATA),
584 EfiUsbDataIn,
585 USBFLPTIMEOUT
586 );
587 //
588 // failed to get Sense data
589 //
590 if (EFI_ERROR (Status)) {
591 //
592 // Recovery the device back to normal state.
593 //
594 UsbFloppyDevice->AtapiProtocol->UsbAtapiReset (
595 UsbFloppyDevice->AtapiProtocol,
596 TRUE
597 );
598
599 if (*SenseCounts == 0) {
600 //
601 // never retrieved any sense data from device,
602 // just return error.
603 //
604 return EFI_DEVICE_ERROR;
605 } else {
606 //
607 // has retrieved some sense data from device,
608 // so return success.
609 //
610 return EFI_SUCCESS;
611 }
612 }
613
614 if (Sense->sense_key != SK_NO_SENSE) {
615 //
616 // Ptr is byte based pointer
617 //
618 Ptr += sizeof (REQUEST_SENSE_DATA);
619
620 (*SenseCounts)++;
621
622 } else {
623 //
624 // when no sense key, skip out the loop
625 //
626 SenseReq = FALSE;
627 }
628
629 //
630 // If the sense key numbers exceed Sense Data Buffer size,
631 // just skip the loop and do not fetch the sense key in this function.
632 //
633 if (*SenseCounts == UsbFloppyDevice->SenseDataNumber) {
634 SenseReq = FALSE;
635 }
636 }
637
638 return EFI_SUCCESS;
639 }
640
641 EFI_STATUS
642 UsbFloppyTestUnitReady (
643 IN USB_FLOPPY_DEV *UsbFloppyDevice
644 )
645 /*++
646
647 Routine Description:
648 Sends Test Unit ReadyPacket Command to the device.
649
650 Arguments:
651 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
652
653 Returns:
654 EFI_DEVICE_ERROR - Hardware error
655 EFI_SUCCESS - Success
656 --*/
657 {
658 ATAPI_PACKET_COMMAND Packet;
659 EFI_STATUS Status;
660 UINT32 RetryIndex;
661 UINT32 MaximumRetryTimes;
662
663 MaximumRetryTimes = 2;
664 //
665 // fill command packet
666 //
667 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
668 Packet.TestUnitReady.opcode = TEST_UNIT_READY;
669
670 //
671 // send command packet
672 //
673 Status = EFI_DEVICE_ERROR;
674
675 for (RetryIndex = 0; RetryIndex < MaximumRetryTimes && EFI_ERROR (Status); RetryIndex++) {
676
677 Status = USBFloppyPacketCommand (
678 UsbFloppyDevice,
679 &Packet,
680 sizeof (ATAPI_PACKET_COMMAND),
681 NULL,
682 0,
683 EfiUsbNoData,
684 USBFLPTIMEOUT
685 );
686
687 if (EFI_ERROR (Status)) {
688 gBS->Stall (100 * STALL_1_MILLI_SECOND);
689 }
690 }
691
692 return Status;
693 }
694
695 EFI_STATUS
696 USBFloppyWrite10 (
697 IN USB_FLOPPY_DEV *UsbFloppyDevice,
698 IN VOID *Buffer,
699 IN EFI_LBA Lba,
700 IN UINTN NumberOfBlocks
701 )
702 /*++
703
704 Routine Description:
705 Sends Write10 Packet Command to device to perform data transfer
706 from host to device.
707
708 Arguments:
709 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
710 Buffer - A pointer to the source buffer for the data.
711 The caller is responsible for either having implicit
712 or explicit ownership of the buffer.
713 Lba - The starting logical block address to written to
714 the device.
715 NumberOfBlocks - Indicates the number of blocks that the write
716 operation requests.
717
718 Returns:
719 EFI_DEVICE_ERROR - Hardware error
720 EFI_SUCCESS - Success
721 --*/
722 {
723 ATAPI_PACKET_COMMAND Packet;
724 READ10_CMD *Write10Packet;
725 UINT16 MaxBlock;
726 UINT16 BlocksRemaining;
727 UINT16 SectorCount;
728 UINT32 Lba32;
729 UINT32 BlockSize;
730 UINT32 ByteCount;
731 VOID *ptrBuffer;
732 EFI_STATUS Status;
733 UINT16 TimeOut;
734 UINT8 Index;
735
736
737 //
738 // prepare command packet for the Write10 Packet Command.
739 //
740 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
741 Write10Packet = &Packet.Read10;
742 Lba32 = (UINT32) Lba;
743 ptrBuffer = Buffer;
744 BlockSize = UsbFloppyDevice->BlkIo.Media->BlockSize;
745
746 MaxBlock = (UINT16) (65536 / BlockSize);
747 BlocksRemaining = (UINT16) NumberOfBlocks;
748
749 Status = EFI_SUCCESS;
750 while (BlocksRemaining > 0) {
751
752 if (BlocksRemaining <= MaxBlock) {
753 SectorCount = BlocksRemaining;
754 } else {
755 SectorCount = MaxBlock;
756 }
757
758 for (Index = 0; Index < 3; Index ++) {
759 //
760 // fill the Packet data structure
761 //
762 Write10Packet->opcode = WRITE_10;
763
764 //
765 // Lba0 ~ Lba3 specify the start logical block address
766 // of the data transfer.
767 // Lba0 is MSB, Lba3 is LSB
768 //
769 Write10Packet->Lba3 = (UINT8) (Lba32 & 0xff);
770 Write10Packet->Lba2 = (UINT8) (Lba32 >> 8);
771 Write10Packet->Lba1 = (UINT8) (Lba32 >> 16);
772 Write10Packet->Lba0 = (UINT8) (Lba32 >> 24);
773
774 //
775 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
776 // TranLen0 is MSB, TranLen is LSB
777 //
778 Write10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);
779 Write10Packet->TranLen0 = (UINT8) (SectorCount >> 8);
780
781 ByteCount = SectorCount * BlockSize;
782
783 TimeOut = (UINT16) (SectorCount * USBDATATIMEOUT);
784
785 Status = USBFloppyPacketCommand (
786 UsbFloppyDevice,
787 &Packet,
788 sizeof (ATAPI_PACKET_COMMAND),
789 (VOID *) ptrBuffer,
790 ByteCount,
791 EfiUsbDataOut,
792 TimeOut
793 );
794 if (!EFI_ERROR (Status)) {
795 break;
796 }
797 }
798
799 if (Index == 3) {
800 return EFI_DEVICE_ERROR;
801 }
802
803 Lba32 += SectorCount;
804 ptrBuffer = (UINT8 *) ptrBuffer + SectorCount * BlockSize;
805 BlocksRemaining = (UINT16) (BlocksRemaining - SectorCount);
806 }
807
808 return Status;
809 }
810
811 EFI_STATUS
812 UsbFloppyDetectMedia (
813 IN USB_FLOPPY_DEV *UsbFloppyDevice,
814 OUT BOOLEAN *MediaChange
815 )
816 /*++
817
818 Routine Description:
819 Retrieves media information.
820
821 Arguments:
822 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
823 MediaChange - Indicates whether media was changed.
824
825 Returns:
826 EFI_DEVICE_ERROR - Hardware error
827 EFI_SUCCESS - Success
828 EFI_INVALID_PARAMETER - Parameter is error
829 --*/
830 {
831 EFI_STATUS Status;
832 EFI_STATUS FloppyStatus;
833 //
834 // the following variables are used to record previous media information
835 //
836 EFI_BLOCK_IO_MEDIA OldMediaInfo;
837 UINTN SenseCounts;
838 UINTN RetryIndex;
839 UINTN RetryTimes;
840 UINTN MaximumRetryTimes;
841 BOOLEAN NeedRetry;
842 BOOLEAN NeedReadCapacity;
843 //
844 // a flag used to determine whether need to perform Read Capacity command.
845 //
846
847 //
848 // init
849 //
850 Status = EFI_SUCCESS;
851 FloppyStatus = EFI_SUCCESS;
852 CopyMem (&OldMediaInfo, UsbFloppyDevice->BlkIo.Media, sizeof (OldMediaInfo));
853 *MediaChange = FALSE;
854 NeedReadCapacity = TRUE;
855
856 //
857 // if there is no media present,or media not changed,
858 // the request sense command will detect faster than read capacity command.
859 // read capacity command can be bypassed, thus improve performance.
860 //
861 SenseCounts = 0;
862 Status = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts);
863
864 if (!EFI_ERROR (Status)) {
865
866 //
867 // No Media
868 //
869 if (IsNoMedia (UsbFloppyDevice->SenseData, SenseCounts)) {
870
871 NeedReadCapacity = FALSE;
872 UsbFloppyDevice->BlkIo.Media->MediaId = 0;
873 UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
874 UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
875 } else {
876 //
877 // Media Changed
878 //
879 if (IsMediaChange (UsbFloppyDevice->SenseData, SenseCounts)) {
880 UsbFloppyDevice->BlkIo.Media->MediaId++;
881 }
882
883 //
884 // Media Write-protected
885 //
886 if (IsMediaWriteProtected (UsbFloppyDevice->SenseData, SenseCounts)) {
887 UsbFloppyDevice->BlkIo.Media->ReadOnly = TRUE;
888 }
889
890 //
891 // Media Error
892 //
893 if (IsMediaError (UsbFloppyDevice->SenseData, SenseCounts)) {
894 //
895 // if media error encountered, make it look like no media present.
896 //
897 UsbFloppyDevice->BlkIo.Media->MediaId = 0;
898 UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
899 UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
900 }
901
902 }
903
904 }
905
906 if (NeedReadCapacity) {
907 //
908 // at most retry 5 times
909 //
910 MaximumRetryTimes = 5;
911 //
912 // initial retry twice
913 //
914 RetryTimes = 2;
915
916 for (RetryIndex = 0; (RetryIndex < RetryTimes) && (RetryIndex < MaximumRetryTimes); RetryIndex++) {
917 //
918 // Using different command to retrieve media capacity.
919 //
920 switch (UsbFloppyDevice->DeviceType) {
921
922 case USBCDROM:
923 Status = USBFloppyReadCapacity (UsbFloppyDevice);
924 break;
925
926 case USBFLOPPY2:
927 UsbMassStorageModeSense (UsbFloppyDevice);
928 Status = USBFloppyReadFormatCapacity (UsbFloppyDevice);
929 if (EFI_ERROR (Status) || !UsbFloppyDevice->BlkMedia.MediaPresent) {
930 //
931 // retry the ReadCapacity command
932 //
933 UsbFloppyDevice->DeviceType = USBFLOPPY;
934 Status = EFI_DEVICE_ERROR;
935 }
936 break;
937
938 case USBFLOPPY:
939 UsbMassStorageModeSense (UsbFloppyDevice);
940 Status = USBFloppyReadCapacity (UsbFloppyDevice);
941 if (EFI_ERROR (Status)) {
942 //
943 // retry the ReadFormatCapacity command
944 //
945 UsbFloppyDevice->DeviceType = USBFLOPPY2;
946 }
947 //
948 // force the BlockSize to be 0x200.
949 //
950 UsbFloppyDevice->BlkIo.Media->BlockSize = 0x200;
951 break;
952
953 default:
954 return EFI_INVALID_PARAMETER;
955 }
956
957 if (!EFI_ERROR (Status)) {
958 //
959 // skip the loop when read capacity succeeds.
960 //
961 break;
962 }
963
964 SenseCounts = 0;
965
966 FloppyStatus = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts);
967
968 //
969 // If Request Sense data failed,retry.
970 //
971 if (EFI_ERROR (FloppyStatus)) {
972 //
973 // retry once more
974 //
975 RetryTimes++;
976 continue;
977 }
978 //
979 // No Media
980 //
981 if (IsNoMedia (UsbFloppyDevice->SenseData, SenseCounts)) {
982
983 UsbFloppyDevice->BlkIo.Media->MediaId = 0;
984 UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
985 UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
986 break;
987 }
988
989 if (IsMediaError (UsbFloppyDevice->SenseData, SenseCounts)) {
990 //
991 // if media error encountered, make it look like no media present.
992 //
993 UsbFloppyDevice->BlkIo.Media->MediaId = 0;
994 UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
995 UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
996 break;
997 }
998
999 if (IsMediaWriteProtected (UsbFloppyDevice->SenseData, SenseCounts)) {
1000 UsbFloppyDevice->BlkIo.Media->ReadOnly = TRUE;
1001 continue;
1002 }
1003
1004 if (!IsDriveReady (UsbFloppyDevice->SenseData, SenseCounts, &NeedRetry)) {
1005
1006 //
1007 // Drive not ready: if NeedRetry, then retry once more;
1008 // else return error
1009 //
1010 if (NeedRetry) {
1011 //
1012 // Stall 0.1 second to wait for drive becoming ready
1013 //
1014 gBS->Stall (100 * STALL_1_MILLI_SECOND);
1015 //
1016 // reset retry variable to zero,
1017 // to make it retry for "drive in progress of becoming ready".
1018 //
1019 RetryIndex = 0;
1020 continue;
1021 } else {
1022 return EFI_DEVICE_ERROR;
1023 }
1024 }
1025 //
1026 // if read capacity fail not for above reasons, retry once more
1027 //
1028 RetryTimes++;
1029
1030 }
1031 //
1032 // ENDFOR
1033 //
1034
1035 //
1036 // tell whether the readcapacity process is successful or not
1037 // ("Status" variable record the latest status returned
1038 // by ReadCapacity AND "FloppyStatus" record the latest status
1039 // returned by RequestSense)
1040 //
1041 if (EFI_ERROR (Status) && EFI_ERROR (FloppyStatus)) {
1042 return EFI_DEVICE_ERROR;
1043 }
1044
1045 }
1046
1047 if (UsbFloppyDevice->BlkIo.Media->MediaPresent != OldMediaInfo.MediaPresent) {
1048
1049 if (UsbFloppyDevice->BlkIo.Media->MediaPresent) {
1050 UsbFloppyDevice->BlkIo.Media->MediaId = 1;
1051 }
1052
1053 *MediaChange = TRUE;
1054 }
1055
1056 if (UsbFloppyDevice->BlkIo.Media->ReadOnly != OldMediaInfo.ReadOnly) {
1057 *MediaChange = TRUE;
1058 UsbFloppyDevice->BlkIo.Media->MediaId += 1;
1059 }
1060
1061 if (UsbFloppyDevice->BlkIo.Media->BlockSize != OldMediaInfo.BlockSize) {
1062 *MediaChange = TRUE;
1063 UsbFloppyDevice->BlkIo.Media->MediaId += 1;
1064 }
1065
1066 if (UsbFloppyDevice->BlkIo.Media->LastBlock != OldMediaInfo.LastBlock) {
1067 *MediaChange = TRUE;
1068 UsbFloppyDevice->BlkIo.Media->MediaId += 1;
1069 }
1070
1071 if (UsbFloppyDevice->BlkIo.Media->MediaId != OldMediaInfo.MediaId) {
1072 *MediaChange = TRUE;
1073 }
1074
1075 return EFI_SUCCESS;
1076 }
1077
1078
1079
1080 EFI_STATUS
1081 UsbFloppyModeSense5APage5 (
1082 IN USB_FLOPPY_DEV *UsbFloppyDevice
1083 )
1084 /*++
1085
1086 Routine Description:
1087 Retrieves media capacity information via sending Read Format
1088 Capacity Packet Command.
1089
1090 Arguments:
1091 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1092
1093 Returns:
1094 EFI_DEVICE_ERROR - Hardware error
1095 EFI_SUCCESS - Success
1096
1097 --*/
1098 {
1099 //
1100 // status returned by Read Capacity Packet Command
1101 //
1102 EFI_STATUS Status;
1103 ATAPI_PACKET_COMMAND Packet;
1104 UFI_MODE_PARAMETER_PAGE_5 ModePage5;
1105 EFI_LBA LastBlock;
1106 UINT32 SectorsPerTrack;
1107 UINT32 NumberOfCylinders;
1108 UINT32 NumberOfHeads;
1109 UINT32 DataBytesPerSector;
1110
1111
1112 ZeroMem (&ModePage5, sizeof (UFI_MODE_PARAMETER_PAGE_5));
1113
1114 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
1115 Packet.ModeSenseUFI.opcode = UFI_MODE_SENSE5A;
1116 //
1117 // Flexible Disk Page
1118 //
1119 Packet.ModeSenseUFI.page_code = 5;
1120 //
1121 // current values
1122 //
1123 Packet.ModeSenseUFI.page_control = 0;
1124 Packet.ModeSenseUFI.parameter_list_length_hi = 0;
1125 Packet.ModeSenseUFI.parameter_list_length_lo = sizeof (UFI_MODE_PARAMETER_PAGE_5);
1126 Status = USBFloppyPacketCommand (
1127 UsbFloppyDevice,
1128 &Packet,
1129 sizeof (ATAPI_PACKET_COMMAND),
1130 (VOID *) &ModePage5,
1131 sizeof (UFI_MODE_PARAMETER_PAGE_5),
1132 EfiUsbDataIn,
1133 USBFLPTIMEOUT
1134 );
1135
1136 if (EFI_ERROR (Status)) {
1137 return EFI_DEVICE_ERROR;
1138 }
1139
1140 NumberOfHeads = ModePage5.flex_disk_page.number_of_heads;
1141 SectorsPerTrack = ModePage5.flex_disk_page.sectors_per_track;
1142 NumberOfCylinders = ModePage5.flex_disk_page.number_of_cylinders_msb << 8 |
1143 ModePage5.flex_disk_page.number_of_cylinders_lsb;
1144
1145 LastBlock = SectorsPerTrack * NumberOfHeads * NumberOfCylinders;
1146 DataBytesPerSector = ModePage5.flex_disk_page.databytes_per_sector_msb << 8 |
1147 ModePage5.flex_disk_page.databytes_per_sector_lsb;
1148
1149 UsbFloppyDevice->BlkIo.Media->LastBlock = LastBlock;
1150
1151 UsbFloppyDevice->BlkIo.Media->LastBlock--;
1152
1153 UsbFloppyDevice->BlkIo.Media->BlockSize = DataBytesPerSector;
1154
1155 UsbFloppyDevice->BlkIo.Media->MediaPresent = TRUE;
1156
1157 UsbFloppyDevice->BlkIo.Media->ReadOnly =
1158 ModePage5.mode_param_header.write_protected;
1159
1160 return EFI_SUCCESS;
1161
1162 }
1163
1164 EFI_STATUS
1165 UsbFloppyModeSense5APage1C (
1166 IN USB_FLOPPY_DEV *UsbFloppyDevice
1167 )
1168 /*++
1169
1170 Routine Description:
1171 Retrieves media capacity information via sending Read Format
1172 Capacity Packet Command.
1173
1174 Arguments:
1175 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1176
1177 Returns:
1178 EFI_DEVICE_ERROR - Hardware error
1179 EFI_SUCCESS - Success
1180
1181 --*/
1182 {
1183 //
1184 // status returned by Read Capacity Packet Command
1185 //
1186 EFI_STATUS Status;
1187 ATAPI_PACKET_COMMAND Packet;
1188 UFI_MODE_PARAMETER_PAGE_1C ModePage1C;
1189
1190
1191 ZeroMem (&ModePage1C, sizeof (UFI_MODE_PARAMETER_PAGE_1C));
1192
1193 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
1194 Packet.ModeSenseUFI.opcode = UFI_MODE_SENSE5A;
1195 //
1196 // Flexible Disk Page
1197 //
1198 Packet.ModeSenseUFI.page_code = 0x1C;
1199 //
1200 // current values
1201 //
1202 Packet.ModeSenseUFI.page_control = 0;
1203 Packet.ModeSenseUFI.parameter_list_length_hi = 0;
1204 Packet.ModeSenseUFI.parameter_list_length_lo = sizeof (UFI_MODE_PARAMETER_PAGE_1C);
1205 Status = USBFloppyPacketCommand (
1206 UsbFloppyDevice,
1207 &Packet,
1208 sizeof (ATAPI_PACKET_COMMAND),
1209 (VOID *) &ModePage1C,
1210 sizeof (UFI_MODE_PARAMETER_PAGE_1C),
1211 EfiUsbDataIn,
1212 USBFLPTIMEOUT
1213 );
1214
1215 if (EFI_ERROR (Status)) {
1216 return EFI_DEVICE_ERROR;
1217 }
1218
1219 UsbFloppyDevice->BlkIo.Media->ReadOnly = ModePage1C.mode_param_header.write_protected;
1220
1221 return EFI_SUCCESS;
1222
1223 }
1224
1225 EFI_STATUS
1226 UsbMassStorageModeSense (
1227 IN USB_FLOPPY_DEV *UsbFloppyDevice
1228 )
1229 {
1230 if (UsbFloppyDevice->AtapiProtocol->CommandProtocol == EFI_USB_SUBCLASS_SCSI) {
1231 return UsbSCSIModeSense1APage3F (UsbFloppyDevice);
1232 } else {
1233 return UsbFloppyModeSense5APage3F (UsbFloppyDevice);
1234 }
1235 }
1236
1237 EFI_STATUS
1238 UsbFloppyModeSense5APage3F (
1239 IN USB_FLOPPY_DEV *UsbFloppyDevice
1240 )
1241 /*++
1242
1243 Routine Description:
1244 Retrieves mode sense information via sending Mode Sense
1245 Packet Command.
1246
1247 Arguments:
1248 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1249
1250 Returns:
1251 EFI_DEVICE_ERROR - Hardware error
1252 EFI_SUCCESS - Success
1253
1254 --*/
1255 {
1256 //
1257 // status returned by Read Capacity Packet Command
1258 //
1259 EFI_STATUS Status;
1260 ATAPI_PACKET_COMMAND Packet;
1261 UFI_MODE_PARAMETER_HEADER Header;
1262 UINT32 Size;
1263
1264
1265 Size = sizeof (UFI_MODE_PARAMETER_HEADER);
1266
1267 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
1268 Packet.ModeSenseUFI.opcode = UFI_MODE_SENSE5A;
1269 Packet.ModeSenseUFI.page_code = 0x3F;
1270 Packet.ModeSenseUFI.page_control = 0;
1271 Packet.ModeSenseUFI.parameter_list_length_hi = 0;
1272 Packet.ModeSenseUFI.parameter_list_length_lo = (UINT8) Size;
1273 Status = USBFloppyPacketCommand (
1274 UsbFloppyDevice,
1275 &Packet,
1276 sizeof (ATAPI_PACKET_COMMAND),
1277 &Header,
1278 Size,
1279 EfiUsbDataIn,
1280 USBFLPTIMEOUT
1281 );
1282
1283 if (EFI_ERROR (Status)) {
1284 return EFI_DEVICE_ERROR;
1285 }
1286
1287 UsbFloppyDevice->BlkIo.Media->ReadOnly = Header.write_protected;
1288
1289 return EFI_SUCCESS;
1290
1291 }
1292
1293 EFI_STATUS
1294 UsbSCSIModeSense1APage3F (
1295 IN USB_FLOPPY_DEV *UsbFloppyDevice
1296 )
1297 /*++
1298
1299 Routine Description:
1300 Retrieves mode sense information via sending Mode Sense
1301 Packet Command.
1302
1303 Arguments:
1304 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1305
1306 Returns:
1307 EFI_DEVICE_ERROR - Hardware error
1308 EFI_SUCCESS - Success
1309
1310 --*/
1311 {
1312 //
1313 // status returned by Read Capacity Packet Command
1314 //
1315 EFI_STATUS Status;
1316 ATAPI_PACKET_COMMAND Packet;
1317 SCSI_MODE_PARAMETER_HEADER6 Header;
1318 UINT32 Size;
1319
1320
1321 Size = sizeof (SCSI_MODE_PARAMETER_HEADER6);
1322
1323 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
1324 Packet.ModeSenseSCSI.opcode = SCSI_MODE_SENSE1A;
1325 Packet.ModeSenseSCSI.page_code = 0x3F;
1326 Packet.ModeSenseSCSI.page_control = 0;
1327 Packet.ModeSenseSCSI.allocation_length = (UINT8) Size;
1328 Status = USBFloppyPacketCommand (
1329 UsbFloppyDevice,
1330 &Packet,
1331 sizeof (MODE_SENSE_CMD_SCSI),
1332 &Header,
1333 Size,
1334 EfiUsbDataIn,
1335 USBFLPTIMEOUT
1336 );
1337
1338 if (EFI_ERROR (Status)) {
1339 return EFI_DEVICE_ERROR;
1340 }
1341
1342 UsbFloppyDevice->BlkIo.Media->ReadOnly = Header.write_protected;
1343 return EFI_SUCCESS;
1344
1345 }
1346
1347 /*++
1348
1349 The following functions are a set of helper functions,
1350 which are used to parse sense key returned by the device.
1351
1352 --*/
1353 BOOLEAN
1354 IsNoMedia (
1355 IN REQUEST_SENSE_DATA *SenseData,
1356 IN UINTN SenseCounts
1357 )
1358 {
1359 REQUEST_SENSE_DATA *SensePtr;
1360 UINTN Index;
1361 BOOLEAN NoMedia;
1362
1363 NoMedia = FALSE;
1364
1365 SensePtr = SenseData;
1366
1367 for (Index = 0; Index < SenseCounts; Index++) {
1368
1369 if ((SensePtr->sense_key == SK_NOT_READY) &&
1370 (SensePtr->addnl_sense_code == ASC_NO_MEDIA)) {
1371
1372 NoMedia = TRUE;
1373 }
1374
1375 SensePtr++;
1376 }
1377
1378 return NoMedia;
1379 }
1380
1381
1382 BOOLEAN
1383 IsMediaError (
1384 IN REQUEST_SENSE_DATA *SenseData,
1385 IN UINTN SenseCounts
1386 )
1387 {
1388 REQUEST_SENSE_DATA *SensePtr;
1389 UINTN Index;
1390 BOOLEAN IsError;
1391
1392 IsError = FALSE;
1393 SensePtr = SenseData;
1394
1395 for (Index = 0; Index < SenseCounts; Index++) {
1396
1397 switch (SensePtr->sense_key) {
1398
1399 //
1400 // Medium error case
1401 //
1402 case SK_MEDIUM_ERROR:
1403 switch (SensePtr->addnl_sense_code) {
1404
1405 case ASC_MEDIA_ERR1:
1406 case ASC_MEDIA_ERR2:
1407 case ASC_MEDIA_ERR3:
1408 case ASC_MEDIA_ERR4:
1409 IsError = TRUE;
1410 break;
1411
1412 default:
1413 break;
1414 }
1415
1416 break;
1417
1418 //
1419 // Medium upside-down case
1420 //
1421 case SK_NOT_READY:
1422 switch (SensePtr->addnl_sense_code) {
1423 case ASC_MEDIA_UPSIDE_DOWN:
1424 IsError = TRUE;
1425 break;
1426
1427 default:
1428 break;
1429 }
1430 break;
1431
1432 default:
1433 break;
1434 }
1435
1436 SensePtr++;
1437 }
1438
1439 return IsError;
1440 }
1441
1442 BOOLEAN
1443 IsMediaChange (
1444 IN REQUEST_SENSE_DATA *SenseData,
1445 IN UINTN SenseCounts
1446 )
1447 {
1448 REQUEST_SENSE_DATA *SensePtr;
1449 UINTN Index;
1450 BOOLEAN MediaChanged;
1451
1452 MediaChanged = FALSE;
1453 SensePtr = SenseData;
1454
1455 for (Index = 0; Index < SenseCounts; Index++) {
1456
1457 if ((SensePtr->sense_key == SK_UNIT_ATTENTION) &&
1458 (SensePtr->addnl_sense_code == ASC_MEDIA_CHANGE)) {
1459
1460 MediaChanged = TRUE;
1461 }
1462
1463 SensePtr++;
1464 }
1465
1466 return MediaChanged;
1467 }
1468
1469 BOOLEAN
1470 IsDriveReady (
1471 IN REQUEST_SENSE_DATA *SenseData,
1472 IN UINTN SenseCounts,
1473 OUT BOOLEAN *NeedRetry
1474 )
1475 {
1476 REQUEST_SENSE_DATA *SensePtr;
1477 UINTN Index;
1478 BOOLEAN IsReady;
1479
1480 IsReady = TRUE;
1481 *NeedRetry = FALSE;
1482 SensePtr = SenseData;
1483
1484 for (Index = 0; Index < SenseCounts; Index++) {
1485
1486 if ((SensePtr->sense_key == SK_NOT_READY) &&
1487 (SensePtr->addnl_sense_code == ASC_NOT_READY)) {
1488
1489 switch (SensePtr->addnl_sense_code_qualifier) {
1490
1491 case ASCQ_IN_PROGRESS:
1492 case ASCQ_DEVICE_BUSY:
1493 IsReady = FALSE;
1494 *NeedRetry = TRUE;
1495 break;
1496
1497 default:
1498 //
1499 // Drive is in error condition,
1500 // no need to retry.
1501 //
1502 IsReady = FALSE;
1503 *NeedRetry = FALSE;
1504 break;
1505 }
1506 }
1507
1508 SensePtr++;
1509 }
1510
1511 return IsReady;
1512 }
1513
1514 BOOLEAN
1515 IsMediaWriteProtected (
1516 IN REQUEST_SENSE_DATA *SenseData,
1517 IN UINTN SenseCounts
1518 )
1519 {
1520 REQUEST_SENSE_DATA *SensePtr;
1521 UINTN Index;
1522 BOOLEAN IsWriteProtected;
1523
1524 IsWriteProtected = FALSE;
1525 SensePtr = SenseData;
1526
1527 for (Index = 0; Index < SenseCounts; Index++) {
1528 //
1529 // catch media write-protected condition.
1530 //
1531 if ((SensePtr->sense_key == SK_DATA_PROTECT) &&
1532 (SensePtr->addnl_sense_code == ASC_WRITE_PROTECTED)) {
1533
1534 IsWriteProtected = TRUE;
1535 }
1536
1537 SensePtr++;
1538 }
1539
1540 return IsWriteProtected;
1541 }
1542