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
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.
14 UsbMassStorageHelper.c
18 Helper functions for USB Mass Storage Driver
24 #include "UsbMassStorageHelper.h"
29 IN REQUEST_SENSE_DATA
*SenseData
,
36 IN REQUEST_SENSE_DATA
*SenseData
,
43 IN REQUEST_SENSE_DATA
*SenseData
,
50 IN REQUEST_SENSE_DATA
*SenseData
,
52 OUT BOOLEAN
*NeedRetry
57 IsMediaWriteProtected (
58 IN REQUEST_SENSE_DATA
*SenseData
,
64 IsLogicalUnitCommunicationOverRun (
65 IN REQUEST_SENSE_DATA
*SenseData
,
70 USBFloppyPacketCommand (
71 USB_FLOPPY_DEV
*UsbFloppyDevice
,
76 EFI_USB_DATA_DIRECTION Direction
,
77 UINT16 TimeOutInMilliSeconds
82 Sends Packet Command to USB Floppy Drive.
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
97 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
100 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
102 // Directly calling EFI_USB_ATAPI_PROTOCOL.UsbAtapiPacketCmd()
103 // to perform the command request.
105 Status
= UsbAtapiInterface
->UsbAtapiPacketCmd (
112 TimeOutInMilliSeconds
120 IN USB_FLOPPY_DEV
*UsbFloppyDevice
125 Retrieves device information to tell the device type.
128 UsbFloppyDevice The USB_FLOPPY_DEV instance.
131 EFI_DEVICE_ERROR - Hardware error
132 EFI_SUCCESS - Success
137 USB_INQUIRY_DATA
*Idata
;
141 // Send Inquiry Packet Command to get INQUIRY data.
143 Status
= USBFloppyInquiry (UsbFloppyDevice
, &Idata
);
144 if (EFI_ERROR (Status
)) {
145 return EFI_DEVICE_ERROR
;
149 // Get media removable info from INQUIRY data.
151 UsbFloppyDevice
->BlkIo
.Media
->RemovableMedia
= (UINT8
) ((Idata
->RMB
& 0x80) == 0x80);
154 // Identify device type via INQUIRY data.
156 switch ((Idata
->peripheral_type
) & 0x1f) {
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;
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
;
181 gBS
->FreePool (Idata
);
182 return EFI_DEVICE_ERROR
;
186 // Initialize some device specific data.
189 // original sense data numbers
191 UsbFloppyDevice
->SenseDataNumber
= 6;
193 if (UsbFloppyDevice
->SenseData
!= NULL
) {
194 gBS
->FreePool (UsbFloppyDevice
->SenseData
);
195 UsbFloppyDevice
->SenseData
= NULL
;
198 UsbFloppyDevice
->SenseData
= AllocatePool (UsbFloppyDevice
->SenseDataNumber
* sizeof (REQUEST_SENSE_DATA
));
200 if (UsbFloppyDevice
->SenseData
== NULL
) {
201 gBS
->FreePool (Idata
);
202 return EFI_DEVICE_ERROR
;
206 // Get media information.
208 UsbFloppyDetectMedia (UsbFloppyDevice
, &MediaChange
);
210 gBS
->FreePool (Idata
);
217 IN USB_FLOPPY_DEV
*UsbFloppyDevice
,
218 OUT USB_INQUIRY_DATA
**Idata
223 Send Inquiry Packet Command to device and retrieve Inquiry Data.
226 UsbFloppyDevice The USB_FLOPPY_DEV instance.
227 Idata A pointer pointing to the address of
231 EFI_DEVICE_ERROR - Hardware error
232 EFI_SUCCESS - Success
235 ATAPI_PACKET_COMMAND Packet
;
240 // prepare command packet for the Inquiry Packet Command.
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
);
247 *Idata
= AllocateZeroPool (sizeof (USB_INQUIRY_DATA
));
248 if (*Idata
== NULL
) {
249 return EFI_DEVICE_ERROR
;
252 // Send command packet and retrieve requested Inquiry Data.
254 Status
= USBFloppyPacketCommand (
257 sizeof (ATAPI_PACKET_COMMAND
),
259 sizeof (USB_INQUIRY_DATA
),
263 if (EFI_ERROR (Status
)) {
264 gBS
->FreePool (*Idata
);
265 return EFI_DEVICE_ERROR
;
273 IN USB_FLOPPY_DEV
*UsbFloppyDevice
,
276 IN UINTN NumberOfBlocks
281 Sends Read10 Packet Command to device to perform data transfer
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
291 NumberOfBlocks - Indicates the number of blocks that the read
295 EFI_DEVICE_ERROR - Hardware error
296 EFI_SUCCESS - Success
299 ATAPI_PACKET_COMMAND Packet
;
300 READ10_CMD
*Read10Packet
;
302 UINT16 BlocksRemaining
;
314 // prepare command packet for the Inquiry Packet Command.
316 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
317 Read10Packet
= &Packet
.Read10
;
318 Lba32
= (UINT32
) Lba
;
320 BlockSize
= UsbFloppyDevice
->BlkIo
.Media
->BlockSize
;
322 MaxBlock
= (UINT16
) (65536 / BlockSize
);
323 BlocksRemaining
= (UINT16
) NumberOfBlocks
;
325 Status
= EFI_SUCCESS
;
326 while (BlocksRemaining
> 0) {
327 if (BlocksRemaining
<= MaxBlock
) {
328 SectorCount
= BlocksRemaining
;
330 SectorCount
= MaxBlock
;
333 for (Index
= 0; Index
< 3; Index
++) {
336 // fill the Packet data structure
338 Read10Packet
->opcode
= READ_10
;
340 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
341 // Lba0 is MSB, Lba3 is LSB
343 Read10Packet
->Lba3
= (UINT8
) (Lba32
& 0xff);
344 Read10Packet
->Lba2
= (UINT8
) (Lba32
>> 8);
345 Read10Packet
->Lba1
= (UINT8
) (Lba32
>> 16);
346 Read10Packet
->Lba0
= (UINT8
) (Lba32
>> 24);
349 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
350 // TranLen0 is MSB, TranLen is LSB
352 Read10Packet
->TranLen1
= (UINT8
) (SectorCount
& 0xff);
353 Read10Packet
->TranLen0
= (UINT8
) (SectorCount
>> 8);
355 ByteCount
= SectorCount
* BlockSize
;
357 TimeOut
= (UINT16
) (SectorCount
* USBFLPTIMEOUT
);
360 Status
= USBFloppyPacketCommand (
363 sizeof (ATAPI_PACKET_COMMAND
),
369 if (!EFI_ERROR (Status
)) {
375 return EFI_DEVICE_ERROR
;
378 Lba32
+= SectorCount
;
379 ptrBuffer
= (UINT8
*) ptrBuffer
+ SectorCount
* BlockSize
;
380 BlocksRemaining
= (UINT16
) (BlocksRemaining
- SectorCount
);
388 USBFloppyReadCapacity (
389 IN USB_FLOPPY_DEV
*UsbFloppyDevice
394 Retrieves media capacity information via
395 sending Read Capacity Packet Command.
398 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
401 EFI_DEVICE_ERROR - Hardware error
402 EFI_SUCCESS - Success
406 // status returned by Read Capacity Packet Command
409 ATAPI_PACKET_COMMAND Packet
;
412 // used for capacity data returned from Usb Floppy
414 READ_CAPACITY_DATA Data
;
416 ZeroMem (&Data
, sizeof (Data
));
419 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
420 Packet
.Inquiry
.opcode
= READ_CAPACITY
;
421 Status
= USBFloppyPacketCommand (
424 sizeof (ATAPI_PACKET_COMMAND
),
426 sizeof (READ_CAPACITY_DATA
),
431 if (EFI_ERROR (Status
)) {
432 return EFI_DEVICE_ERROR
;
435 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= (Data
.LastLba3
<< 24) |
436 (Data
.LastLba2
<< 16) |
437 (Data
.LastLba1
<< 8) |
440 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= TRUE
;
442 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= 0x800;
449 USBFloppyReadFormatCapacity (
450 IN USB_FLOPPY_DEV
*UsbFloppyDevice
455 Retrieves media capacity information via sending Read Format
456 Capacity Packet Command.
459 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
462 EFI_DEVICE_ERROR - Hardware error
463 EFI_SUCCESS - Success
467 // status returned by Read Capacity Packet Command
470 ATAPI_PACKET_COMMAND Packet
;
473 // used for capacity data returned from Usb Floppy
475 READ_FORMAT_CAPACITY_DATA FormatData
;
477 ZeroMem (&FormatData
, sizeof (FormatData
));
480 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
481 Packet
.ReadFormatCapacity
.opcode
= READ_FORMAT_CAPACITY
;
482 Packet
.ReadFormatCapacity
.allocation_length_lo
= 12;
483 Status
= USBFloppyPacketCommand (
486 sizeof (ATAPI_PACKET_COMMAND
),
487 (VOID
*) &FormatData
,
488 sizeof (READ_FORMAT_CAPACITY_DATA
),
493 if (EFI_ERROR (Status
)) {
494 return EFI_DEVICE_ERROR
;
497 if (FormatData
.DesCode
== 3) {
499 // Media is not present
501 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
502 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
503 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
506 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= (FormatData
.LastLba3
<< 24) |
507 (FormatData
.LastLba2
<< 16) |
508 (FormatData
.LastLba1
<< 8) |
511 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
--;
513 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= (FormatData
.BlockSize2
<< 16) |
514 (FormatData
.BlockSize1
<< 8) |
515 FormatData
.BlockSize0
;
517 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= TRUE
;
519 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= 0x200;
528 UsbFloppyRequestSense (
529 IN USB_FLOPPY_DEV
*UsbFloppyDevice
,
530 OUT UINTN
*SenseCounts
535 Retrieves Sense Data from device via
536 sending Request Sense Packet Command.
539 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
540 SenseCounts - A pointer to the number of Sense Data returned.
543 EFI_DEVICE_ERROR - Hardware error
544 EFI_SUCCESS - Success
548 REQUEST_SENSE_DATA
*Sense
;
551 ATAPI_PACKET_COMMAND Packet
;
557 UsbFloppyDevice
->SenseData
,
558 sizeof (REQUEST_SENSE_DATA
) * (UsbFloppyDevice
->SenseDataNumber
)
561 // fill command packet for Request Sense Packet Command
563 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
564 Packet
.RequestSense
.opcode
= REQUEST_SENSE
;
565 Packet
.RequestSense
.allocation_length
= sizeof (REQUEST_SENSE_DATA
);
568 // initialize pointer
570 Ptr
= (UINT8
*) (UsbFloppyDevice
->SenseData
);
573 // request sense data from device continuously
574 // until no sense data exists in the device.
576 for (SenseReq
= TRUE
; SenseReq
;) {
578 Sense
= (REQUEST_SENSE_DATA
*) Ptr
;
581 // send out Request Sense Packet Command and get one Sense
584 Status
= USBFloppyPacketCommand (
587 sizeof (ATAPI_PACKET_COMMAND
),
589 sizeof (REQUEST_SENSE_DATA
),
594 // failed to get Sense data
596 if (EFI_ERROR (Status
)) {
598 // Recovery the device back to normal state.
600 UsbFloppyDevice
->AtapiProtocol
->UsbAtapiReset (
601 UsbFloppyDevice
->AtapiProtocol
,
605 if (*SenseCounts
== 0) {
607 // never retrieved any sense data from device,
608 // just return error.
610 return EFI_DEVICE_ERROR
;
613 // has retrieved some sense data from device,
614 // so return success.
620 if (Sense
->sense_key
!= SK_NO_SENSE
) {
622 // Ptr is byte based pointer
624 Ptr
+= sizeof (REQUEST_SENSE_DATA
);
630 // when no sense key, skip out the loop
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.
639 if (*SenseCounts
== UsbFloppyDevice
->SenseDataNumber
) {
648 UsbFloppyTestUnitReady (
649 IN USB_FLOPPY_DEV
*UsbFloppyDevice
654 Sends Test Unit ReadyPacket Command to the device.
657 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
660 EFI_DEVICE_ERROR - Hardware error
661 EFI_SUCCESS - Success
664 ATAPI_PACKET_COMMAND Packet
;
667 UINT32 MaximumRetryTimes
;
669 MaximumRetryTimes
= 2;
671 // fill command packet
673 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
674 Packet
.TestUnitReady
.opcode
= TEST_UNIT_READY
;
677 // send command packet
679 Status
= EFI_DEVICE_ERROR
;
681 for (RetryIndex
= 0; RetryIndex
< MaximumRetryTimes
&& EFI_ERROR (Status
); RetryIndex
++) {
683 Status
= USBFloppyPacketCommand (
686 sizeof (ATAPI_PACKET_COMMAND
),
693 if (EFI_ERROR (Status
)) {
694 gBS
->Stall (100 * STALL_1_MILLI_SECOND
);
703 IN USB_FLOPPY_DEV
*UsbFloppyDevice
,
706 IN UINTN NumberOfBlocks
711 Sends Write10 Packet Command to device to perform data transfer
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
721 NumberOfBlocks - Indicates the number of blocks that the write
725 EFI_DEVICE_ERROR - Hardware error
726 EFI_SUCCESS - Success
729 ATAPI_PACKET_COMMAND Packet
;
730 READ10_CMD
*Write10Packet
;
732 UINT16 BlocksRemaining
;
744 // prepare command packet for the Write10 Packet Command.
746 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
747 Write10Packet
= &Packet
.Read10
;
748 Lba32
= (UINT32
) Lba
;
750 BlockSize
= UsbFloppyDevice
->BlkIo
.Media
->BlockSize
;
752 MaxBlock
= (UINT16
) (65536 / BlockSize
);
753 BlocksRemaining
= (UINT16
) NumberOfBlocks
;
755 Status
= EFI_SUCCESS
;
756 while (BlocksRemaining
> 0) {
758 if (BlocksRemaining
<= MaxBlock
) {
759 SectorCount
= BlocksRemaining
;
761 SectorCount
= MaxBlock
;
764 for (Index
= 0; Index
< 3; Index
++) {
766 // fill the Packet data structure
768 Write10Packet
->opcode
= WRITE_10
;
771 // Lba0 ~ Lba3 specify the start logical block address
772 // of the data transfer.
773 // Lba0 is MSB, Lba3 is LSB
775 Write10Packet
->Lba3
= (UINT8
) (Lba32
& 0xff);
776 Write10Packet
->Lba2
= (UINT8
) (Lba32
>> 8);
777 Write10Packet
->Lba1
= (UINT8
) (Lba32
>> 16);
778 Write10Packet
->Lba0
= (UINT8
) (Lba32
>> 24);
781 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
782 // TranLen0 is MSB, TranLen is LSB
784 Write10Packet
->TranLen1
= (UINT8
) (SectorCount
& 0xff);
785 Write10Packet
->TranLen0
= (UINT8
) (SectorCount
>> 8);
787 ByteCount
= SectorCount
* BlockSize
;
789 TimeOut
= (UINT16
) (SectorCount
* USBFLPTIMEOUT
);
791 Status
= USBFloppyPacketCommand (
794 sizeof (ATAPI_PACKET_COMMAND
),
800 if (!EFI_ERROR (Status
)) {
806 return EFI_DEVICE_ERROR
;
809 Lba32
+= SectorCount
;
810 ptrBuffer
= (UINT8
*) ptrBuffer
+ SectorCount
* BlockSize
;
811 BlocksRemaining
= (UINT16
) (BlocksRemaining
- SectorCount
);
818 UsbFloppyDetectMedia (
819 IN USB_FLOPPY_DEV
*UsbFloppyDevice
,
820 OUT BOOLEAN
*MediaChange
825 Retrieves media information.
828 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
829 MediaChange - Indicates whether media was changed.
832 EFI_DEVICE_ERROR - Hardware error
833 EFI_SUCCESS - Success
834 EFI_INVALID_PARAMETER - Parameter is error
838 EFI_STATUS FloppyStatus
;
840 // the following variables are used to record previous media information
842 EFI_BLOCK_IO_MEDIA OldMediaInfo
;
846 UINTN MaximumRetryTimes
;
848 BOOLEAN NeedReadCapacity
;
850 // a flag used to determine whether need to perform Read Capacity command.
856 Status
= EFI_SUCCESS
;
857 FloppyStatus
= EFI_SUCCESS
;
858 CopyMem (&OldMediaInfo
, UsbFloppyDevice
->BlkIo
.Media
, sizeof (OldMediaInfo
));
859 *MediaChange
= FALSE
;
860 NeedReadCapacity
= TRUE
;
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.
868 Status
= UsbFloppyRequestSense (UsbFloppyDevice
, &SenseCounts
);
870 if (!EFI_ERROR (Status
)) {
875 if (IsNoMedia (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
877 NeedReadCapacity
= FALSE
;
878 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
879 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
880 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
885 if (IsMediaChange (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
886 UsbFloppyDevice
->BlkIo
.Media
->MediaId
++;
890 // Media Write-protected
892 if (IsMediaWriteProtected (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
893 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= TRUE
;
899 if (IsMediaError (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
901 // if media error encountered, make it look like no media present.
903 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
904 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
905 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
912 if (NeedReadCapacity
) {
914 // at most retry 5 times
916 MaximumRetryTimes
= 5;
918 // initial retry twice
922 for (RetryIndex
= 0; (RetryIndex
< RetryTimes
) && (RetryIndex
< MaximumRetryTimes
); RetryIndex
++) {
924 // Using different command to retrieve media capacity.
926 switch (UsbFloppyDevice
->DeviceType
) {
929 Status
= USBFloppyReadCapacity (UsbFloppyDevice
);
933 UsbMassStorageModeSense (UsbFloppyDevice
);
934 Status
= USBFloppyReadFormatCapacity (UsbFloppyDevice
);
935 if (EFI_ERROR (Status
) || !UsbFloppyDevice
->BlkMedia
.MediaPresent
) {
937 // retry the ReadCapacity command
939 UsbFloppyDevice
->DeviceType
= USBFLOPPY
;
940 Status
= EFI_DEVICE_ERROR
;
945 UsbMassStorageModeSense (UsbFloppyDevice
);
946 Status
= USBFloppyReadCapacity (UsbFloppyDevice
);
947 if (EFI_ERROR (Status
)) {
949 // retry the ReadFormatCapacity command
951 UsbFloppyDevice
->DeviceType
= USBFLOPPY2
;
954 // force the BlockSize to be 0x200.
956 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= 0x200;
960 return EFI_INVALID_PARAMETER
;
963 if (!EFI_ERROR (Status
)) {
965 // skip the loop when read capacity succeeds.
972 FloppyStatus
= UsbFloppyRequestSense (UsbFloppyDevice
, &SenseCounts
);
975 // If Request Sense data failed,retry.
977 if (EFI_ERROR (FloppyStatus
)) {
987 if (IsNoMedia (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
989 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
990 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
991 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
995 if (IsMediaError (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
997 // if media error encountered, make it look like no media present.
999 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
1000 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
1001 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
1005 if (IsMediaWriteProtected (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
1006 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= TRUE
;
1010 if (!IsDriveReady (UsbFloppyDevice
->SenseData
, SenseCounts
, &NeedRetry
)) {
1013 // Drive not ready: if NeedRetry, then retry once more;
1014 // else return error
1018 // Stall 0.1 second to wait for drive becoming ready
1020 gBS
->Stall (100 * STALL_1_MILLI_SECOND
);
1022 // reset retry variable to zero,
1023 // to make it retry for "drive in progress of becoming ready".
1028 return EFI_DEVICE_ERROR
;
1032 // if read capacity fail not for above reasons, retry once more
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)
1047 if (EFI_ERROR (Status
) && EFI_ERROR (FloppyStatus
)) {
1048 return EFI_DEVICE_ERROR
;
1053 if (UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
!= OldMediaInfo
.MediaPresent
) {
1055 if (UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
) {
1056 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 1;
1059 *MediaChange
= TRUE
;
1062 if (UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
!= OldMediaInfo
.ReadOnly
) {
1063 *MediaChange
= TRUE
;
1064 UsbFloppyDevice
->BlkIo
.Media
->MediaId
+= 1;
1067 if (UsbFloppyDevice
->BlkIo
.Media
->BlockSize
!= OldMediaInfo
.BlockSize
) {
1068 *MediaChange
= TRUE
;
1069 UsbFloppyDevice
->BlkIo
.Media
->MediaId
+= 1;
1072 if (UsbFloppyDevice
->BlkIo
.Media
->LastBlock
!= OldMediaInfo
.LastBlock
) {
1073 *MediaChange
= TRUE
;
1074 UsbFloppyDevice
->BlkIo
.Media
->MediaId
+= 1;
1077 if (UsbFloppyDevice
->BlkIo
.Media
->MediaId
!= OldMediaInfo
.MediaId
) {
1078 *MediaChange
= TRUE
;
1087 UsbFloppyModeSense5APage5 (
1088 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1092 Routine Description:
1093 Retrieves media capacity information via sending Read Format
1094 Capacity Packet Command.
1097 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1100 EFI_DEVICE_ERROR - Hardware error
1101 EFI_SUCCESS - Success
1106 // status returned by Read Capacity Packet Command
1109 ATAPI_PACKET_COMMAND Packet
;
1110 UFI_MODE_PARAMETER_PAGE_5 ModePage5
;
1112 UINT32 SectorsPerTrack
;
1113 UINT32 NumberOfCylinders
;
1114 UINT32 NumberOfHeads
;
1115 UINT32 DataBytesPerSector
;
1118 ZeroMem (&ModePage5
, sizeof (UFI_MODE_PARAMETER_PAGE_5
));
1120 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1121 Packet
.ModeSenseUFI
.opcode
= UFI_MODE_SENSE5A
;
1123 // Flexible Disk Page
1125 Packet
.ModeSenseUFI
.page_code
= 5;
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 (
1135 sizeof (ATAPI_PACKET_COMMAND
),
1136 (VOID
*) &ModePage5
,
1137 sizeof (UFI_MODE_PARAMETER_PAGE_5
),
1142 if (EFI_ERROR (Status
)) {
1143 return EFI_DEVICE_ERROR
;
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
;
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
;
1155 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= LastBlock
;
1157 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
--;
1159 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= DataBytesPerSector
;
1161 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= TRUE
;
1163 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
=
1164 ModePage5
.mode_param_header
.write_protected
;
1171 UsbFloppyModeSense5APage1C (
1172 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1176 Routine Description:
1177 Retrieves media capacity information via sending Read Format
1178 Capacity Packet Command.
1181 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1184 EFI_DEVICE_ERROR - Hardware error
1185 EFI_SUCCESS - Success
1190 // status returned by Read Capacity Packet Command
1193 ATAPI_PACKET_COMMAND Packet
;
1194 UFI_MODE_PARAMETER_PAGE_1C ModePage1C
;
1197 ZeroMem (&ModePage1C
, sizeof (UFI_MODE_PARAMETER_PAGE_1C
));
1199 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1200 Packet
.ModeSenseUFI
.opcode
= UFI_MODE_SENSE5A
;
1202 // Flexible Disk Page
1204 Packet
.ModeSenseUFI
.page_code
= 0x1C;
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 (
1214 sizeof (ATAPI_PACKET_COMMAND
),
1215 (VOID
*) &ModePage1C
,
1216 sizeof (UFI_MODE_PARAMETER_PAGE_1C
),
1221 if (EFI_ERROR (Status
)) {
1222 return EFI_DEVICE_ERROR
;
1225 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= ModePage1C
.mode_param_header
.write_protected
;
1232 UsbMassStorageModeSense (
1233 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1236 if (UsbFloppyDevice
->AtapiProtocol
->CommandProtocol
== EFI_USB_SUBCLASS_SCSI
) {
1237 return UsbSCSIModeSense1APage3F (UsbFloppyDevice
);
1239 return UsbFloppyModeSense5APage3F (UsbFloppyDevice
);
1244 UsbFloppyModeSense5APage3F (
1245 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1249 Routine Description:
1250 Retrieves mode sense information via sending Mode Sense
1254 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1257 EFI_DEVICE_ERROR - Hardware error
1258 EFI_SUCCESS - Success
1263 // status returned by Read Capacity Packet Command
1266 ATAPI_PACKET_COMMAND Packet
;
1267 UFI_MODE_PARAMETER_HEADER Header
;
1271 Size
= sizeof (UFI_MODE_PARAMETER_HEADER
);
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 (
1282 sizeof (ATAPI_PACKET_COMMAND
),
1289 if (EFI_ERROR (Status
)) {
1290 return EFI_DEVICE_ERROR
;
1293 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= Header
.write_protected
;
1300 UsbSCSIModeSense1APage3F (
1301 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1305 Routine Description:
1306 Retrieves mode sense information via sending Mode Sense
1310 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1313 EFI_DEVICE_ERROR - Hardware error
1314 EFI_SUCCESS - Success
1319 // status returned by Read Capacity Packet Command
1322 ATAPI_PACKET_COMMAND Packet
;
1323 SCSI_MODE_PARAMETER_HEADER6 Header
;
1327 Size
= sizeof (SCSI_MODE_PARAMETER_HEADER6
);
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 (
1337 sizeof (MODE_SENSE_CMD_SCSI
),
1344 if (EFI_ERROR (Status
)) {
1345 return EFI_DEVICE_ERROR
;
1348 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= Header
.write_protected
;
1355 The following functions are a set of helper functions,
1356 which are used to parse sense key returned by the device.
1361 IN REQUEST_SENSE_DATA
*SenseData
,
1362 IN UINTN SenseCounts
1365 REQUEST_SENSE_DATA
*SensePtr
;
1371 SensePtr
= SenseData
;
1373 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1375 if ((SensePtr
->sense_key
== SK_NOT_READY
) &&
1376 (SensePtr
->addnl_sense_code
== ASC_NO_MEDIA
)) {
1390 IN REQUEST_SENSE_DATA
*SenseData
,
1391 IN UINTN SenseCounts
1394 REQUEST_SENSE_DATA
*SensePtr
;
1399 SensePtr
= SenseData
;
1401 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1403 switch (SensePtr
->sense_key
) {
1406 // Medium error case
1408 case SK_MEDIUM_ERROR
:
1409 switch (SensePtr
->addnl_sense_code
) {
1411 case ASC_MEDIA_ERR1
:
1412 case ASC_MEDIA_ERR2
:
1413 case ASC_MEDIA_ERR3
:
1414 case ASC_MEDIA_ERR4
:
1425 // Medium upside-down case
1428 switch (SensePtr
->addnl_sense_code
) {
1429 case ASC_MEDIA_UPSIDE_DOWN
:
1450 IN REQUEST_SENSE_DATA
*SenseData
,
1451 IN UINTN SenseCounts
1454 REQUEST_SENSE_DATA
*SensePtr
;
1456 BOOLEAN MediaChanged
;
1458 MediaChanged
= FALSE
;
1459 SensePtr
= SenseData
;
1461 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1463 if ((SensePtr
->sense_key
== SK_UNIT_ATTENTION
) &&
1464 (SensePtr
->addnl_sense_code
== ASC_MEDIA_CHANGE
)) {
1466 MediaChanged
= TRUE
;
1472 return MediaChanged
;
1477 IN REQUEST_SENSE_DATA
*SenseData
,
1478 IN UINTN SenseCounts
,
1479 OUT BOOLEAN
*NeedRetry
1482 REQUEST_SENSE_DATA
*SensePtr
;
1488 SensePtr
= SenseData
;
1490 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1492 if ((SensePtr
->sense_key
== SK_NOT_READY
) &&
1493 (SensePtr
->addnl_sense_code
== ASC_NOT_READY
)) {
1495 switch (SensePtr
->addnl_sense_code_qualifier
) {
1497 case ASCQ_IN_PROGRESS
:
1498 case ASCQ_DEVICE_BUSY
:
1505 // Drive is in error condition,
1506 // no need to retry.
1521 IsMediaWriteProtected (
1522 IN REQUEST_SENSE_DATA
*SenseData
,
1523 IN UINTN SenseCounts
1526 REQUEST_SENSE_DATA
*SensePtr
;
1528 BOOLEAN IsWriteProtected
;
1530 IsWriteProtected
= FALSE
;
1531 SensePtr
= SenseData
;
1533 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1535 // catch media write-protected condition.
1537 if ((SensePtr
->sense_key
== SK_DATA_PROTECT
) &&
1538 (SensePtr
->addnl_sense_code
== ASC_WRITE_PROTECTED
)) {
1540 IsWriteProtected
= TRUE
;
1546 return IsWriteProtected
;
1550 IsLogicalUnitCommunicationOverRun (
1551 IN REQUEST_SENSE_DATA
*SenseData
,
1552 IN UINTN SenseCounts
1555 REQUEST_SENSE_DATA
*SensePtr
;
1560 SensePtr
= SenseData
;
1562 for (Index
= 0; Index
< SenseCounts
; Index
++) {
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
)) {