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