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
;
237 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
239 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
242 // prepare command packet for the Inquiry Packet Command.
244 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
245 Packet
.Inquiry
.opcode
= INQUIRY
;
246 Packet
.Inquiry
.page_code
= 0;
247 Packet
.Inquiry
.allocation_length
= sizeof (USB_INQUIRY_DATA
);
249 *Idata
= AllocateZeroPool (sizeof (USB_INQUIRY_DATA
));
250 if (*Idata
== NULL
) {
251 return EFI_DEVICE_ERROR
;
254 // Send command packet and retrieve requested Inquiry Data.
256 Status
= USBFloppyPacketCommand (
259 sizeof (ATAPI_PACKET_COMMAND
),
261 sizeof (USB_INQUIRY_DATA
),
265 if (EFI_ERROR (Status
)) {
266 gBS
->FreePool (*Idata
);
267 return EFI_DEVICE_ERROR
;
275 IN USB_FLOPPY_DEV
*UsbFloppyDevice
,
278 IN UINTN NumberOfBlocks
283 Sends Read10 Packet Command to device to perform data transfer
287 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
288 Buffer - A pointer to the destination buffer for the data.
289 The caller is responsible for either having implicit
290 or explicit ownership of the buffer.
291 Lba - The starting logical block address to read from
293 NumberOfBlocks - Indicates the number of blocks that the read
297 EFI_DEVICE_ERROR - Hardware error
298 EFI_SUCCESS - Success
301 ATAPI_PACKET_COMMAND Packet
;
302 READ10_CMD
*Read10Packet
;
304 UINT16 BlocksRemaining
;
312 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
315 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
318 // prepare command packet for the Inquiry Packet Command.
320 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
321 Read10Packet
= &Packet
.Read10
;
322 Lba32
= (UINT32
) Lba
;
324 BlockSize
= UsbFloppyDevice
->BlkIo
.Media
->BlockSize
;
326 MaxBlock
= (UINT16
) (65536 / BlockSize
);
327 BlocksRemaining
= (UINT16
) NumberOfBlocks
;
329 Status
= EFI_SUCCESS
;
330 while (BlocksRemaining
> 0) {
331 if (BlocksRemaining
<= MaxBlock
) {
332 SectorCount
= BlocksRemaining
;
334 SectorCount
= MaxBlock
;
337 for (Index
= 0; Index
< 3; Index
++) {
340 // fill the Packet data structure
342 Read10Packet
->opcode
= READ_10
;
344 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
345 // Lba0 is MSB, Lba3 is LSB
347 Read10Packet
->Lba3
= (UINT8
) (Lba32
& 0xff);
348 Read10Packet
->Lba2
= (UINT8
) (Lba32
>> 8);
349 Read10Packet
->Lba1
= (UINT8
) (Lba32
>> 16);
350 Read10Packet
->Lba0
= (UINT8
) (Lba32
>> 24);
353 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
354 // TranLen0 is MSB, TranLen is LSB
356 Read10Packet
->TranLen1
= (UINT8
) (SectorCount
& 0xff);
357 Read10Packet
->TranLen0
= (UINT8
) (SectorCount
>> 8);
359 ByteCount
= SectorCount
* BlockSize
;
361 TimeOut
= (UINT16
) (SectorCount
* USBFLPTIMEOUT
);
364 Status
= USBFloppyPacketCommand (
367 sizeof (ATAPI_PACKET_COMMAND
),
373 if (!EFI_ERROR (Status
)) {
379 return EFI_DEVICE_ERROR
;
382 Lba32
+= SectorCount
;
383 ptrBuffer
= (UINT8
*) ptrBuffer
+ SectorCount
* BlockSize
;
384 BlocksRemaining
= (UINT16
) (BlocksRemaining
- SectorCount
);
391 USBFloppyReadCapacity (
392 IN USB_FLOPPY_DEV
*UsbFloppyDevice
397 Retrieves media capacity information via
398 sending Read Capacity Packet Command.
401 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
404 EFI_DEVICE_ERROR - Hardware error
405 EFI_SUCCESS - Success
409 // status returned by Read Capacity Packet Command
412 ATAPI_PACKET_COMMAND Packet
;
413 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
416 // used for capacity data returned from Usb Floppy
418 READ_CAPACITY_DATA Data
;
420 ZeroMem (&Data
, sizeof (Data
));
422 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
424 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
425 Packet
.Inquiry
.opcode
= READ_CAPACITY
;
426 Status
= USBFloppyPacketCommand (
429 sizeof (ATAPI_PACKET_COMMAND
),
431 sizeof (READ_CAPACITY_DATA
),
436 if (EFI_ERROR (Status
)) {
437 return EFI_DEVICE_ERROR
;
440 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= (Data
.LastLba3
<< 24) |
441 (Data
.LastLba2
<< 16) |
442 (Data
.LastLba1
<< 8) |
445 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= TRUE
;
447 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= 0x800;
454 USBFloppyReadFormatCapacity (
455 IN USB_FLOPPY_DEV
*UsbFloppyDevice
460 Retrieves media capacity information via sending Read Format
461 Capacity Packet Command.
464 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
467 EFI_DEVICE_ERROR - Hardware error
468 EFI_SUCCESS - Success
472 // status returned by Read Capacity Packet Command
475 ATAPI_PACKET_COMMAND Packet
;
476 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
479 // used for capacity data returned from Usb Floppy
481 READ_FORMAT_CAPACITY_DATA FormatData
;
483 ZeroMem (&FormatData
, sizeof (FormatData
));
485 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
487 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
488 Packet
.ReadFormatCapacity
.opcode
= READ_FORMAT_CAPACITY
;
489 Packet
.ReadFormatCapacity
.allocation_length_lo
= 12;
490 Status
= USBFloppyPacketCommand (
493 sizeof (ATAPI_PACKET_COMMAND
),
494 (VOID
*) &FormatData
,
495 sizeof (READ_FORMAT_CAPACITY_DATA
),
500 if (EFI_ERROR (Status
)) {
501 return EFI_DEVICE_ERROR
;
504 if (FormatData
.DesCode
== 3) {
506 // Media is not present
508 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
509 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
510 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
513 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= (FormatData
.LastLba3
<< 24) |
514 (FormatData
.LastLba2
<< 16) |
515 (FormatData
.LastLba1
<< 8) |
518 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
--;
520 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= (FormatData
.BlockSize2
<< 16) |
521 (FormatData
.BlockSize1
<< 8) |
522 FormatData
.BlockSize0
;
524 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= TRUE
;
526 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= 0x200;
535 UsbFloppyRequestSense (
536 IN USB_FLOPPY_DEV
*UsbFloppyDevice
,
537 OUT UINTN
*SenseCounts
542 Retrieves Sense Data from device via
543 sending Request Sense Packet Command.
546 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
547 SenseCounts - A pointer to the number of Sense Data returned.
550 EFI_DEVICE_ERROR - Hardware error
551 EFI_SUCCESS - Success
555 REQUEST_SENSE_DATA
*Sense
;
558 ATAPI_PACKET_COMMAND Packet
;
559 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
561 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
566 UsbFloppyDevice
->SenseData
,
567 sizeof (REQUEST_SENSE_DATA
) * (UsbFloppyDevice
->SenseDataNumber
)
570 // fill command packet for Request Sense Packet Command
572 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
573 Packet
.RequestSense
.opcode
= REQUEST_SENSE
;
574 Packet
.RequestSense
.allocation_length
= sizeof (REQUEST_SENSE_DATA
);
577 // initialize pointer
579 Ptr
= (UINT8
*) (UsbFloppyDevice
->SenseData
);
582 // request sense data from device continuously
583 // until no sense data exists in the device.
585 for (SenseReq
= TRUE
; SenseReq
;) {
587 Sense
= (REQUEST_SENSE_DATA
*) Ptr
;
590 // send out Request Sense Packet Command and get one Sense
593 Status
= USBFloppyPacketCommand (
596 sizeof (ATAPI_PACKET_COMMAND
),
598 sizeof (REQUEST_SENSE_DATA
),
603 // failed to get Sense data
605 if (EFI_ERROR (Status
)) {
607 // Recovery the device back to normal state.
609 UsbFloppyDevice
->AtapiProtocol
->UsbAtapiReset (
610 UsbFloppyDevice
->AtapiProtocol
,
614 if (*SenseCounts
== 0) {
616 // never retrieved any sense data from device,
617 // just return error.
619 return EFI_DEVICE_ERROR
;
622 // has retrieved some sense data from device,
623 // so return success.
629 if (Sense
->sense_key
!= SK_NO_SENSE
) {
631 // Ptr is byte based pointer
633 Ptr
+= sizeof (REQUEST_SENSE_DATA
);
639 // when no sense key, skip out the loop
645 // If the sense key numbers exceed Sense Data Buffer size,
646 // just skip the loop and do not fetch the sense key in this function.
648 if (*SenseCounts
== UsbFloppyDevice
->SenseDataNumber
) {
657 UsbFloppyTestUnitReady (
658 IN USB_FLOPPY_DEV
*UsbFloppyDevice
663 Sends Test Unit ReadyPacket Command to the device.
666 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
669 EFI_DEVICE_ERROR - Hardware error
670 EFI_SUCCESS - Success
673 ATAPI_PACKET_COMMAND Packet
;
675 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
677 UINT32 MaximumRetryTimes
;
679 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
680 MaximumRetryTimes
= 2;
682 // fill command packet
684 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
685 Packet
.TestUnitReady
.opcode
= TEST_UNIT_READY
;
688 // send command packet
690 Status
= EFI_DEVICE_ERROR
;
692 for (RetryIndex
= 0; RetryIndex
< MaximumRetryTimes
&& EFI_ERROR (Status
); RetryIndex
++) {
694 Status
= USBFloppyPacketCommand (
697 sizeof (ATAPI_PACKET_COMMAND
),
704 if (EFI_ERROR (Status
)) {
705 gBS
->Stall (100 * STALL_1_MILLI_SECOND
);
714 IN USB_FLOPPY_DEV
*UsbFloppyDevice
,
717 IN UINTN NumberOfBlocks
722 Sends Write10 Packet Command to device to perform data transfer
726 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
727 Buffer - A pointer to the source buffer for the data.
728 The caller is responsible for either having implicit
729 or explicit ownership of the buffer.
730 Lba - The starting logical block address to written to
732 NumberOfBlocks - Indicates the number of blocks that the write
736 EFI_DEVICE_ERROR - Hardware error
737 EFI_SUCCESS - Success
740 ATAPI_PACKET_COMMAND Packet
;
741 READ10_CMD
*Write10Packet
;
743 UINT16 BlocksRemaining
;
751 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
754 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
757 // prepare command packet for the Write10 Packet Command.
759 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
760 Write10Packet
= &Packet
.Read10
;
761 Lba32
= (UINT32
) Lba
;
763 BlockSize
= UsbFloppyDevice
->BlkIo
.Media
->BlockSize
;
765 MaxBlock
= (UINT16
) (65536 / BlockSize
);
766 BlocksRemaining
= (UINT16
) NumberOfBlocks
;
768 Status
= EFI_SUCCESS
;
769 while (BlocksRemaining
> 0) {
771 if (BlocksRemaining
<= MaxBlock
) {
772 SectorCount
= BlocksRemaining
;
774 SectorCount
= MaxBlock
;
777 for (Index
= 0; Index
< 3; Index
++) {
779 // fill the Packet data structure
781 Write10Packet
->opcode
= WRITE_10
;
784 // Lba0 ~ Lba3 specify the start logical block address
785 // of the data transfer.
786 // Lba0 is MSB, Lba3 is LSB
788 Write10Packet
->Lba3
= (UINT8
) (Lba32
& 0xff);
789 Write10Packet
->Lba2
= (UINT8
) (Lba32
>> 8);
790 Write10Packet
->Lba1
= (UINT8
) (Lba32
>> 16);
791 Write10Packet
->Lba0
= (UINT8
) (Lba32
>> 24);
794 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
795 // TranLen0 is MSB, TranLen is LSB
797 Write10Packet
->TranLen1
= (UINT8
) (SectorCount
& 0xff);
798 Write10Packet
->TranLen0
= (UINT8
) (SectorCount
>> 8);
800 ByteCount
= SectorCount
* BlockSize
;
802 TimeOut
= (UINT16
) (SectorCount
* USBFLPTIMEOUT
);
804 Status
= USBFloppyPacketCommand (
807 sizeof (ATAPI_PACKET_COMMAND
),
813 if (!EFI_ERROR (Status
)) {
819 return EFI_DEVICE_ERROR
;
822 Lba32
+= SectorCount
;
823 ptrBuffer
= (UINT8
*) ptrBuffer
+ SectorCount
* BlockSize
;
824 BlocksRemaining
= (UINT16
) (BlocksRemaining
- SectorCount
);
831 UsbFloppyDetectMedia (
832 IN USB_FLOPPY_DEV
*UsbFloppyDevice
,
833 OUT BOOLEAN
*MediaChange
838 Retrieves media information.
841 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
842 MediaChange - Indicates whether media was changed.
845 EFI_DEVICE_ERROR - Hardware error
846 EFI_SUCCESS - Success
847 EFI_INVALID_PARAMETER - Parameter is error
851 EFI_STATUS FloppyStatus
;
853 // the following variables are used to record previous media information
855 EFI_BLOCK_IO_MEDIA OldMediaInfo
;
859 UINTN MaximumRetryTimes
;
861 BOOLEAN NeedReadCapacity
;
863 // a flag used to determine whether need to perform Read Capacity command.
866 REQUEST_SENSE_DATA
*SensePtr
;
871 Status
= EFI_SUCCESS
;
872 FloppyStatus
= EFI_SUCCESS
;
873 CopyMem (&OldMediaInfo
, UsbFloppyDevice
->BlkIo
.Media
, sizeof (OldMediaInfo
));
874 *MediaChange
= FALSE
;
875 NeedReadCapacity
= TRUE
;
878 // if there is no media present,or media not changed,
879 // the request sense command will detect faster than read capacity command.
880 // read capacity command can be bypassed, thus improve performance.
883 Status
= UsbFloppyRequestSense (UsbFloppyDevice
, &SenseCounts
);
885 if (!EFI_ERROR (Status
)) {
887 SensePtr
= UsbFloppyDevice
->SenseData
;
892 if (IsNoMedia (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
894 NeedReadCapacity
= FALSE
;
895 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
896 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
897 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
902 if (IsMediaChange (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
903 UsbFloppyDevice
->BlkIo
.Media
->MediaId
++;
907 // Media Write-protected
909 if (IsMediaWriteProtected (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
910 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= TRUE
;
916 if (IsMediaError (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
918 // if media error encountered, make it look like no media present.
920 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
921 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
922 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
929 if (NeedReadCapacity
) {
931 // at most retry 5 times
933 MaximumRetryTimes
= 5;
935 // initial retry twice
939 for (RetryIndex
= 0; (RetryIndex
< RetryTimes
) && (RetryIndex
< MaximumRetryTimes
); RetryIndex
++) {
941 // Using different command to retrieve media capacity.
943 switch (UsbFloppyDevice
->DeviceType
) {
946 Status
= USBFloppyReadCapacity (UsbFloppyDevice
);
950 UsbMassStorageModeSense (UsbFloppyDevice
);
951 Status
= USBFloppyReadFormatCapacity (UsbFloppyDevice
);
952 if (EFI_ERROR (Status
) || !UsbFloppyDevice
->BlkMedia
.MediaPresent
) {
954 // retry the ReadCapacity command
956 UsbFloppyDevice
->DeviceType
= USBFLOPPY
;
957 Status
= EFI_DEVICE_ERROR
;
962 UsbMassStorageModeSense (UsbFloppyDevice
);
963 Status
= USBFloppyReadCapacity (UsbFloppyDevice
);
964 if (EFI_ERROR (Status
)) {
966 // retry the ReadFormatCapacity command
968 UsbFloppyDevice
->DeviceType
= USBFLOPPY2
;
971 // force the BlockSize to be 0x200.
973 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= 0x200;
977 return EFI_INVALID_PARAMETER
;
980 if (!EFI_ERROR (Status
)) {
982 // skip the loop when read capacity succeeds.
989 FloppyStatus
= UsbFloppyRequestSense (UsbFloppyDevice
, &SenseCounts
);
992 // If Request Sense data failed,retry.
994 if (EFI_ERROR (FloppyStatus
)) {
1004 if (IsNoMedia (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
1006 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
1007 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
1008 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
1012 if (IsMediaError (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
1014 // if media error encountered, make it look like no media present.
1016 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
1017 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
1018 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
1022 if (IsMediaWriteProtected (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
1023 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= TRUE
;
1027 if (!IsDriveReady (UsbFloppyDevice
->SenseData
, SenseCounts
, &NeedRetry
)) {
1030 // Drive not ready: if NeedRetry, then retry once more;
1031 // else return error
1035 // Stall 0.1 second to wait for drive becoming ready
1037 gBS
->Stall (100 * STALL_1_MILLI_SECOND
);
1039 // reset retry variable to zero,
1040 // to make it retry for "drive in progress of becoming ready".
1045 return EFI_DEVICE_ERROR
;
1049 // if read capacity fail not for above reasons, retry once more
1059 // tell whether the readcapacity process is successful or not
1060 // ("Status" variable record the latest status returned
1061 // by ReadCapacity AND "FloppyStatus" record the latest status
1062 // returned by RequestSense)
1064 if (EFI_ERROR (Status
) && EFI_ERROR (FloppyStatus
)) {
1065 return EFI_DEVICE_ERROR
;
1070 if (UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
!= OldMediaInfo
.MediaPresent
) {
1072 if (UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
) {
1073 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 1;
1076 *MediaChange
= TRUE
;
1079 if (UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
!= OldMediaInfo
.ReadOnly
) {
1080 *MediaChange
= TRUE
;
1081 UsbFloppyDevice
->BlkIo
.Media
->MediaId
+= 1;
1084 if (UsbFloppyDevice
->BlkIo
.Media
->BlockSize
!= OldMediaInfo
.BlockSize
) {
1085 *MediaChange
= TRUE
;
1086 UsbFloppyDevice
->BlkIo
.Media
->MediaId
+= 1;
1089 if (UsbFloppyDevice
->BlkIo
.Media
->LastBlock
!= OldMediaInfo
.LastBlock
) {
1090 *MediaChange
= TRUE
;
1091 UsbFloppyDevice
->BlkIo
.Media
->MediaId
+= 1;
1094 if (UsbFloppyDevice
->BlkIo
.Media
->MediaId
!= OldMediaInfo
.MediaId
) {
1095 *MediaChange
= TRUE
;
1104 UsbFloppyModeSense5APage5 (
1105 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1109 Routine Description:
1110 Retrieves media capacity information via sending Read Format
1111 Capacity Packet Command.
1114 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1117 EFI_DEVICE_ERROR - Hardware error
1118 EFI_SUCCESS - Success
1123 // status returned by Read Capacity Packet Command
1126 ATAPI_PACKET_COMMAND Packet
;
1127 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
1128 UFI_MODE_PARAMETER_PAGE_5 ModePage5
;
1130 UINT32 SectorsPerTrack
;
1131 UINT32 NumberOfCylinders
;
1132 UINT32 NumberOfHeads
;
1133 UINT32 DataBytesPerSector
;
1135 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
1137 ZeroMem (&ModePage5
, sizeof (UFI_MODE_PARAMETER_PAGE_5
));
1139 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1140 Packet
.ModeSenseUFI
.opcode
= UFI_MODE_SENSE5A
;
1142 // Flexible Disk Page
1144 Packet
.ModeSenseUFI
.page_code
= 5;
1148 Packet
.ModeSenseUFI
.page_control
= 0;
1149 Packet
.ModeSenseUFI
.parameter_list_length_hi
= 0;
1150 Packet
.ModeSenseUFI
.parameter_list_length_lo
= sizeof (UFI_MODE_PARAMETER_PAGE_5
);
1151 Status
= USBFloppyPacketCommand (
1154 sizeof (ATAPI_PACKET_COMMAND
),
1155 (VOID
*) &ModePage5
,
1156 sizeof (UFI_MODE_PARAMETER_PAGE_5
),
1161 if (EFI_ERROR (Status
)) {
1162 return EFI_DEVICE_ERROR
;
1165 NumberOfHeads
= ModePage5
.flex_disk_page
.number_of_heads
;
1166 SectorsPerTrack
= ModePage5
.flex_disk_page
.sectors_per_track
;
1167 NumberOfCylinders
= ModePage5
.flex_disk_page
.number_of_cylinders_msb
<< 8 |
1168 ModePage5
.flex_disk_page
.number_of_cylinders_lsb
;
1170 LastBlock
= SectorsPerTrack
* NumberOfHeads
* NumberOfCylinders
;
1171 DataBytesPerSector
= ModePage5
.flex_disk_page
.databytes_per_sector_msb
<< 8 |
1172 ModePage5
.flex_disk_page
.databytes_per_sector_lsb
;
1174 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= LastBlock
;
1176 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
--;
1178 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= DataBytesPerSector
;
1180 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= TRUE
;
1182 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
=
1183 ModePage5
.mode_param_header
.write_protected
;
1190 UsbFloppyModeSense5APage1C (
1191 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1195 Routine Description:
1196 Retrieves media capacity information via sending Read Format
1197 Capacity Packet Command.
1200 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1203 EFI_DEVICE_ERROR - Hardware error
1204 EFI_SUCCESS - Success
1209 // status returned by Read Capacity Packet Command
1212 ATAPI_PACKET_COMMAND Packet
;
1213 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
1214 UFI_MODE_PARAMETER_PAGE_1C ModePage1C
;
1216 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
1218 ZeroMem (&ModePage1C
, sizeof (UFI_MODE_PARAMETER_PAGE_1C
));
1220 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1221 Packet
.ModeSenseUFI
.opcode
= UFI_MODE_SENSE5A
;
1223 // Flexible Disk Page
1225 Packet
.ModeSenseUFI
.page_code
= 0x1C;
1229 Packet
.ModeSenseUFI
.page_control
= 0;
1230 Packet
.ModeSenseUFI
.parameter_list_length_hi
= 0;
1231 Packet
.ModeSenseUFI
.parameter_list_length_lo
= sizeof (UFI_MODE_PARAMETER_PAGE_1C
);
1232 Status
= USBFloppyPacketCommand (
1235 sizeof (ATAPI_PACKET_COMMAND
),
1236 (VOID
*) &ModePage1C
,
1237 sizeof (UFI_MODE_PARAMETER_PAGE_1C
),
1242 if (EFI_ERROR (Status
)) {
1243 return EFI_DEVICE_ERROR
;
1246 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= ModePage1C
.mode_param_header
.write_protected
;
1253 UsbMassStorageModeSense (
1254 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1257 if (UsbFloppyDevice
->AtapiProtocol
->CommandProtocol
== EFI_USB_SUBCLASS_SCSI
) {
1258 return UsbSCSIModeSense1APage3F (UsbFloppyDevice
);
1260 return UsbFloppyModeSense5APage3F (UsbFloppyDevice
);
1265 UsbFloppyModeSense5APage3F (
1266 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1270 Routine Description:
1271 Retrieves mode sense information via sending Mode Sense
1275 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1278 EFI_DEVICE_ERROR - Hardware error
1279 EFI_SUCCESS - Success
1284 // status returned by Read Capacity Packet Command
1287 ATAPI_PACKET_COMMAND Packet
;
1288 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
1289 UFI_MODE_PARAMETER_HEADER Header
;
1292 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
1294 Size
= sizeof (UFI_MODE_PARAMETER_HEADER
);
1296 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1297 Packet
.ModeSenseUFI
.opcode
= UFI_MODE_SENSE5A
;
1298 Packet
.ModeSenseUFI
.page_code
= 0x3F;
1299 Packet
.ModeSenseUFI
.page_control
= 0;
1300 Packet
.ModeSenseUFI
.parameter_list_length_hi
= 0;
1301 Packet
.ModeSenseUFI
.parameter_list_length_lo
= (UINT8
) Size
;
1302 Status
= USBFloppyPacketCommand (
1305 sizeof (ATAPI_PACKET_COMMAND
),
1312 if (EFI_ERROR (Status
)) {
1313 return EFI_DEVICE_ERROR
;
1316 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= Header
.write_protected
;
1323 UsbSCSIModeSense1APage3F (
1324 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1328 Routine Description:
1329 Retrieves mode sense information via sending Mode Sense
1333 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1336 EFI_DEVICE_ERROR - Hardware error
1337 EFI_SUCCESS - Success
1342 // status returned by Read Capacity Packet Command
1345 ATAPI_PACKET_COMMAND Packet
;
1346 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
1347 SCSI_MODE_PARAMETER_HEADER6 Header
;
1350 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
1352 Size
= sizeof (SCSI_MODE_PARAMETER_HEADER6
);
1354 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1355 Packet
.ModeSenseSCSI
.opcode
= SCSI_MODE_SENSE1A
;
1356 Packet
.ModeSenseSCSI
.page_code
= 0x3F;
1357 Packet
.ModeSenseSCSI
.page_control
= 0;
1358 Packet
.ModeSenseSCSI
.allocation_length
= (UINT8
) Size
;
1359 Status
= USBFloppyPacketCommand (
1362 sizeof (MODE_SENSE_CMD_SCSI
),
1369 if (EFI_ERROR (Status
)) {
1370 return EFI_DEVICE_ERROR
;
1373 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= Header
.write_protected
;
1380 The following functions are a set of helper functions,
1381 which are used to parse sense key returned by the device.
1386 IN REQUEST_SENSE_DATA
*SenseData
,
1387 IN UINTN SenseCounts
1390 REQUEST_SENSE_DATA
*SensePtr
;
1396 SensePtr
= SenseData
;
1398 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1400 if ((SensePtr
->sense_key
== SK_NOT_READY
) &&
1401 (SensePtr
->addnl_sense_code
== ASC_NO_MEDIA
)) {
1415 IN REQUEST_SENSE_DATA
*SenseData
,
1416 IN UINTN SenseCounts
1419 REQUEST_SENSE_DATA
*SensePtr
;
1424 SensePtr
= SenseData
;
1426 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1428 switch (SensePtr
->sense_key
) {
1431 // Medium error case
1433 case SK_MEDIUM_ERROR
:
1434 switch (SensePtr
->addnl_sense_code
) {
1436 case ASC_MEDIA_ERR1
:
1437 case ASC_MEDIA_ERR2
:
1438 case ASC_MEDIA_ERR3
:
1439 case ASC_MEDIA_ERR4
:
1450 // Medium upside-down case
1453 switch (SensePtr
->addnl_sense_code
) {
1454 case ASC_MEDIA_UPSIDE_DOWN
:
1475 IN REQUEST_SENSE_DATA
*SenseData
,
1476 IN UINTN SenseCounts
1479 REQUEST_SENSE_DATA
*SensePtr
;
1481 BOOLEAN MediaChanged
;
1483 MediaChanged
= FALSE
;
1484 SensePtr
= SenseData
;
1486 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1488 if ((SensePtr
->sense_key
== SK_UNIT_ATTENTION
) &&
1489 (SensePtr
->addnl_sense_code
== ASC_MEDIA_CHANGE
)) {
1491 MediaChanged
= TRUE
;
1497 return MediaChanged
;
1502 IN REQUEST_SENSE_DATA
*SenseData
,
1503 IN UINTN SenseCounts
,
1504 OUT BOOLEAN
*NeedRetry
1507 REQUEST_SENSE_DATA
*SensePtr
;
1513 SensePtr
= SenseData
;
1515 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1517 if ((SensePtr
->sense_key
== SK_NOT_READY
) &&
1518 (SensePtr
->addnl_sense_code
== ASC_NOT_READY
)) {
1520 switch (SensePtr
->addnl_sense_code_qualifier
) {
1522 case ASCQ_IN_PROGRESS
:
1523 case ASCQ_DEVICE_BUSY
:
1530 // Drive is in error condition,
1531 // no need to retry.
1546 IsMediaWriteProtected (
1547 IN REQUEST_SENSE_DATA
*SenseData
,
1548 IN UINTN SenseCounts
1551 REQUEST_SENSE_DATA
*SensePtr
;
1553 BOOLEAN IsWriteProtected
;
1555 IsWriteProtected
= FALSE
;
1556 SensePtr
= SenseData
;
1558 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1560 // catch media write-protected condition.
1562 if ((SensePtr
->sense_key
== SK_DATA_PROTECT
) &&
1563 (SensePtr
->addnl_sense_code
== ASC_WRITE_PROTECTED
)) {
1565 IsWriteProtected
= TRUE
;
1571 return IsWriteProtected
;
1575 IsLogicalUnitCommunicationOverRun (
1576 IN REQUEST_SENSE_DATA
*SenseData
,
1577 IN UINTN SenseCounts
1580 REQUEST_SENSE_DATA
*SensePtr
;
1585 SensePtr
= SenseData
;
1587 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1589 if ((SensePtr
->sense_key
== SK_NOT_READY
) &&
1590 (SensePtr
->addnl_sense_code
== ASC_LOGICAL_UNIT_STATUS
) &&
1591 (SensePtr
->addnl_sense_code_qualifier
== ASCQ_LOGICAL_UNIT_OVERRUN
)) {