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 // fill the Packet data structure
339 Read10Packet
->opcode
= READ_10
;
342 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
343 // Lba0 is MSB, Lba3 is LSB
345 Read10Packet
->Lba3
= (UINT8
) (Lba32
& 0xff);
346 Read10Packet
->Lba2
= (UINT8
) (Lba32
>> 8);
347 Read10Packet
->Lba1
= (UINT8
) (Lba32
>> 16);
348 Read10Packet
->Lba0
= (UINT8
) (Lba32
>> 24);
351 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
352 // TranLen0 is MSB, TranLen is LSB
354 Read10Packet
->TranLen1
= (UINT8
) (SectorCount
& 0xff);
355 Read10Packet
->TranLen0
= (UINT8
) (SectorCount
>> 8);
357 ByteCount
= SectorCount
* BlockSize
;
359 TimeOut
= (UINT16
) (SectorCount
* USBFLPTIMEOUT
);
361 Status
= USBFloppyPacketCommand (
364 sizeof (ATAPI_PACKET_COMMAND
),
370 if (EFI_ERROR (Status
)) {
372 Status
= UsbFloppyRequestSense (UsbFloppyDevice
, &SenseCounts
);
373 if (!EFI_ERROR (Status
)) {
374 if (IsLogicalUnitCommunicationOverRun (
375 UsbFloppyDevice
->SenseData
,
378 Lba32
= (UINT32
) Lba
;
380 BlocksRemaining
= (UINT16
) NumberOfBlocks
;
381 MaxBlock
= (UINT16
) (MaxBlock
/ 4);
389 return EFI_DEVICE_ERROR
;
392 // retry read10 command
394 Status
= USBFloppyPacketCommand (
397 sizeof (ATAPI_PACKET_COMMAND
),
403 if (EFI_ERROR (Status
)) {
404 return EFI_DEVICE_ERROR
;
408 Lba32
+= SectorCount
;
409 ptrBuffer
= (UINT8
*) ptrBuffer
+ SectorCount
* BlockSize
;
410 BlocksRemaining
= (UINT16
) (BlocksRemaining
- SectorCount
);
417 USBFloppyReadCapacity (
418 IN USB_FLOPPY_DEV
*UsbFloppyDevice
423 Retrieves media capacity information via
424 sending Read Capacity Packet Command.
427 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
430 EFI_DEVICE_ERROR - Hardware error
431 EFI_SUCCESS - Success
435 // status returned by Read Capacity Packet Command
438 ATAPI_PACKET_COMMAND Packet
;
439 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
442 // used for capacity data returned from Usb Floppy
444 READ_CAPACITY_DATA Data
;
446 ZeroMem (&Data
, sizeof (Data
));
448 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
450 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
451 Packet
.Inquiry
.opcode
= READ_CAPACITY
;
452 Status
= USBFloppyPacketCommand (
455 sizeof (ATAPI_PACKET_COMMAND
),
457 sizeof (READ_CAPACITY_DATA
),
462 if (EFI_ERROR (Status
)) {
463 return EFI_DEVICE_ERROR
;
466 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= (Data
.LastLba3
<< 24) |
467 (Data
.LastLba2
<< 16) |
468 (Data
.LastLba1
<< 8) |
471 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= TRUE
;
473 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= 0x800;
480 USBFloppyReadFormatCapacity (
481 IN USB_FLOPPY_DEV
*UsbFloppyDevice
486 Retrieves media capacity information via sending Read Format
487 Capacity Packet Command.
490 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
493 EFI_DEVICE_ERROR - Hardware error
494 EFI_SUCCESS - Success
498 // status returned by Read Capacity Packet Command
501 ATAPI_PACKET_COMMAND Packet
;
502 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
505 // used for capacity data returned from Usb Floppy
507 READ_FORMAT_CAPACITY_DATA FormatData
;
509 ZeroMem (&FormatData
, sizeof (FormatData
));
511 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
513 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
514 Packet
.ReadFormatCapacity
.opcode
= READ_FORMAT_CAPACITY
;
515 Packet
.ReadFormatCapacity
.allocation_length_lo
= 12;
516 Status
= USBFloppyPacketCommand (
519 sizeof (ATAPI_PACKET_COMMAND
),
520 (VOID
*) &FormatData
,
521 sizeof (READ_FORMAT_CAPACITY_DATA
),
526 if (EFI_ERROR (Status
)) {
527 return EFI_DEVICE_ERROR
;
530 if (FormatData
.DesCode
== 3) {
532 // Media is not present
534 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
535 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
536 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
539 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= (FormatData
.LastLba3
<< 24) |
540 (FormatData
.LastLba2
<< 16) |
541 (FormatData
.LastLba1
<< 8) |
544 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
--;
546 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= (FormatData
.BlockSize2
<< 16) |
547 (FormatData
.BlockSize1
<< 8) |
548 FormatData
.BlockSize0
;
550 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= TRUE
;
552 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= 0x200;
561 UsbFloppyRequestSense (
562 IN USB_FLOPPY_DEV
*UsbFloppyDevice
,
563 OUT UINTN
*SenseCounts
568 Retrieves Sense Data from device via
569 sending Request Sense Packet Command.
572 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
573 SenseCounts - A pointer to the number of Sense Data returned.
576 EFI_DEVICE_ERROR - Hardware error
577 EFI_SUCCESS - Success
581 REQUEST_SENSE_DATA
*Sense
;
584 ATAPI_PACKET_COMMAND Packet
;
585 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
587 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
592 UsbFloppyDevice
->SenseData
,
593 sizeof (REQUEST_SENSE_DATA
) * (UsbFloppyDevice
->SenseDataNumber
)
596 // fill command packet for Request Sense Packet Command
598 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
599 Packet
.RequestSense
.opcode
= REQUEST_SENSE
;
600 Packet
.RequestSense
.allocation_length
= sizeof (REQUEST_SENSE_DATA
);
603 // initialize pointer
605 Ptr
= (UINT8
*) (UsbFloppyDevice
->SenseData
);
608 // request sense data from device continuously
609 // until no sense data exists in the device.
611 for (SenseReq
= TRUE
; SenseReq
;) {
613 Sense
= (REQUEST_SENSE_DATA
*) Ptr
;
616 // send out Request Sense Packet Command and get one Sense
619 Status
= USBFloppyPacketCommand (
622 sizeof (ATAPI_PACKET_COMMAND
),
624 sizeof (REQUEST_SENSE_DATA
),
629 // failed to get Sense data
631 if (EFI_ERROR (Status
)) {
633 // Recovery the device back to normal state.
635 UsbFloppyDevice
->AtapiProtocol
->UsbAtapiReset (
636 UsbFloppyDevice
->AtapiProtocol
,
640 if (*SenseCounts
== 0) {
642 // never retrieved any sense data from device,
643 // just return error.
645 return EFI_DEVICE_ERROR
;
648 // has retrieved some sense data from device,
649 // so return success.
655 if (Sense
->sense_key
!= SK_NO_SENSE
) {
657 // Ptr is byte based pointer
659 Ptr
+= sizeof (REQUEST_SENSE_DATA
);
665 // when no sense key, skip out the loop
671 // If the sense key numbers exceed Sense Data Buffer size,
672 // just skip the loop and do not fetch the sense key in this function.
674 if (*SenseCounts
== UsbFloppyDevice
->SenseDataNumber
) {
683 UsbFloppyTestUnitReady (
684 IN USB_FLOPPY_DEV
*UsbFloppyDevice
689 Sends Test Unit ReadyPacket Command to the device.
692 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
695 EFI_DEVICE_ERROR - Hardware error
696 EFI_SUCCESS - Success
699 ATAPI_PACKET_COMMAND Packet
;
701 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
703 UINT32 MaximumRetryTimes
;
705 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
706 MaximumRetryTimes
= 2;
708 // fill command packet
710 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
711 Packet
.TestUnitReady
.opcode
= TEST_UNIT_READY
;
714 // send command packet
716 Status
= EFI_DEVICE_ERROR
;
718 for (RetryIndex
= 0; RetryIndex
< MaximumRetryTimes
&& EFI_ERROR (Status
); RetryIndex
++) {
720 Status
= USBFloppyPacketCommand (
723 sizeof (ATAPI_PACKET_COMMAND
),
730 if (EFI_ERROR (Status
)) {
731 gBS
->Stall (100 * STALL_1_MILLI_SECOND
);
740 IN USB_FLOPPY_DEV
*UsbFloppyDevice
,
743 IN UINTN NumberOfBlocks
748 Sends Write10 Packet Command to device to perform data transfer
752 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
753 Buffer - A pointer to the source buffer for the data.
754 The caller is responsible for either having implicit
755 or explicit ownership of the buffer.
756 Lba - The starting logical block address to written to
758 NumberOfBlocks - Indicates the number of blocks that the write
762 EFI_DEVICE_ERROR - Hardware error
763 EFI_SUCCESS - Success
766 ATAPI_PACKET_COMMAND Packet
;
767 READ10_CMD
*Write10Packet
;
769 UINT16 BlocksRemaining
;
777 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
780 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
783 // prepare command packet for the Write10 Packet Command.
785 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
786 Write10Packet
= &Packet
.Read10
;
787 Lba32
= (UINT32
) Lba
;
789 BlockSize
= UsbFloppyDevice
->BlkIo
.Media
->BlockSize
;
791 MaxBlock
= (UINT16
) (65536 / BlockSize
);
792 BlocksRemaining
= (UINT16
) NumberOfBlocks
;
794 Status
= EFI_SUCCESS
;
795 while (BlocksRemaining
> 0) {
797 if (BlocksRemaining
<= MaxBlock
) {
799 SectorCount
= BlocksRemaining
;
802 SectorCount
= MaxBlock
;
805 // fill the Packet data structure
807 Write10Packet
->opcode
= WRITE_10
;
810 // Lba0 ~ Lba3 specify the start logical block address
811 // of the data transfer.
812 // Lba0 is MSB, Lba3 is LSB
814 Write10Packet
->Lba3
= (UINT8
) (Lba32
& 0xff);
815 Write10Packet
->Lba2
= (UINT8
) (Lba32
>> 8);
816 Write10Packet
->Lba1
= (UINT8
) (Lba32
>> 16);
817 Write10Packet
->Lba0
= (UINT8
) (Lba32
>> 24);
820 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
821 // TranLen0 is MSB, TranLen is LSB
823 Write10Packet
->TranLen1
= (UINT8
) (SectorCount
& 0xff);
824 Write10Packet
->TranLen0
= (UINT8
) (SectorCount
>> 8);
826 ByteCount
= SectorCount
* BlockSize
;
828 TimeOut
= (UINT16
) (SectorCount
* USBFLPTIMEOUT
);
830 Status
= USBFloppyPacketCommand (
833 sizeof (ATAPI_PACKET_COMMAND
),
839 if (EFI_ERROR (Status
)) {
840 Status
= UsbFloppyRequestSense (UsbFloppyDevice
, &SenseCounts
);
841 if (!EFI_ERROR (Status
)) {
842 if (IsLogicalUnitCommunicationOverRun (
843 UsbFloppyDevice
->SenseData
,
846 Lba32
= (UINT32
) Lba
;
848 BlocksRemaining
= (UINT16
) NumberOfBlocks
;
849 MaxBlock
= (UINT16
) (MaxBlock
/ 4);
858 // retry write10 command
860 Status
= USBFloppyPacketCommand (
863 sizeof (ATAPI_PACKET_COMMAND
),
869 if (EFI_ERROR (Status
)) {
870 return EFI_DEVICE_ERROR
;
874 Lba32
+= SectorCount
;
875 ptrBuffer
= (UINT8
*) ptrBuffer
+ SectorCount
* BlockSize
;
876 BlocksRemaining
= (UINT16
) (BlocksRemaining
- SectorCount
);
883 UsbFloppyDetectMedia (
884 IN USB_FLOPPY_DEV
*UsbFloppyDevice
,
885 OUT BOOLEAN
*MediaChange
890 Retrieves media information.
893 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
894 MediaChange - Indicates whether media was changed.
897 EFI_DEVICE_ERROR - Hardware error
898 EFI_SUCCESS - Success
899 EFI_INVALID_PARAMETER - Parameter is error
903 EFI_STATUS FloppyStatus
;
905 // the following variables are used to record previous media information
907 EFI_BLOCK_IO_MEDIA OldMediaInfo
;
911 UINTN MaximumRetryTimes
;
915 // a flag used to determine whether need to perform Read Capacity command.
917 BOOLEAN NeedReadCapacity
;
919 REQUEST_SENSE_DATA
*SensePtr
;
924 Status
= EFI_SUCCESS
;
925 FloppyStatus
= EFI_SUCCESS
;
926 CopyMem (&OldMediaInfo
, UsbFloppyDevice
->BlkIo
.Media
, sizeof (OldMediaInfo
));
927 *MediaChange
= FALSE
;
928 NeedReadCapacity
= TRUE
;
931 // if there is no media present,or media not changed,
932 // the request sense command will detect faster than read capacity command.
933 // read capacity command can be bypassed, thus improve performance.
936 Status
= UsbFloppyRequestSense (UsbFloppyDevice
, &SenseCounts
);
938 if (!EFI_ERROR (Status
)) {
940 SensePtr
= UsbFloppyDevice
->SenseData
;
945 if (IsNoMedia (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
947 NeedReadCapacity
= FALSE
;
948 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
949 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
950 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
955 if (IsMediaChange (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
956 UsbFloppyDevice
->BlkIo
.Media
->MediaId
++;
960 // Media Write-protected
962 if (IsMediaWriteProtected (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
963 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= TRUE
;
969 if (IsMediaError (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
971 // if media error encountered, make it look like no media present.
973 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
974 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
975 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
982 if (NeedReadCapacity
) {
984 // at most retry 5 times
986 MaximumRetryTimes
= 5;
988 // initial retry twice
992 for (RetryIndex
= 0; (RetryIndex
< RetryTimes
) && (RetryIndex
< MaximumRetryTimes
); RetryIndex
++) {
994 // Using different command to retrieve media capacity.
996 switch (UsbFloppyDevice
->DeviceType
) {
999 Status
= USBFloppyReadCapacity (UsbFloppyDevice
);
1003 UsbMassStorageModeSense (UsbFloppyDevice
);
1004 Status
= USBFloppyReadFormatCapacity (UsbFloppyDevice
);
1005 if (EFI_ERROR (Status
) || !UsbFloppyDevice
->BlkMedia
.MediaPresent
) {
1007 // retry the ReadCapacity command
1009 UsbFloppyDevice
->DeviceType
= USBFLOPPY
;
1010 Status
= EFI_DEVICE_ERROR
;
1015 UsbMassStorageModeSense (UsbFloppyDevice
);
1016 Status
= USBFloppyReadCapacity (UsbFloppyDevice
);
1017 if (EFI_ERROR (Status
)) {
1019 // retry the ReadFormatCapacity command
1021 UsbFloppyDevice
->DeviceType
= USBFLOPPY2
;
1024 // force the BlockSize to be 0x200.
1026 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= 0x200;
1030 return EFI_INVALID_PARAMETER
;
1033 if (!EFI_ERROR (Status
)) {
1035 // skip the loop when read capacity succeeds.
1042 FloppyStatus
= UsbFloppyRequestSense (UsbFloppyDevice
, &SenseCounts
);
1045 // If Request Sense data failed,retry.
1047 if (EFI_ERROR (FloppyStatus
)) {
1057 if (IsNoMedia (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
1059 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
1060 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
1061 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
1065 if (IsMediaError (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
1067 // if media error encountered, make it look like no media present.
1069 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
1070 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
1071 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
1075 if (IsMediaWriteProtected (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
1076 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= TRUE
;
1080 if (!IsDriveReady (UsbFloppyDevice
->SenseData
, SenseCounts
, &NeedRetry
)) {
1083 // Drive not ready: if NeedRetry, then retry once more;
1084 // else return error
1088 // Stall 0.1 second to wait for drive becoming ready
1090 gBS
->Stall (100 * STALL_1_MILLI_SECOND
);
1092 // reset retry variable to zero,
1093 // to make it retry for "drive in progress of becoming ready".
1098 return EFI_DEVICE_ERROR
;
1102 // if read capacity fail not for above reasons, retry once more
1112 // tell whether the readcapacity process is successful or not
1113 // ("Status" variable record the latest status returned
1114 // by ReadCapacity AND "FloppyStatus" record the latest status
1115 // returned by RequestSense)
1117 if (EFI_ERROR (Status
) && EFI_ERROR (FloppyStatus
)) {
1118 return EFI_DEVICE_ERROR
;
1123 if (UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
!= OldMediaInfo
.MediaPresent
) {
1125 if (UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
) {
1126 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 1;
1129 *MediaChange
= TRUE
;
1132 if (UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
!= OldMediaInfo
.ReadOnly
) {
1133 *MediaChange
= TRUE
;
1134 UsbFloppyDevice
->BlkIo
.Media
->MediaId
+= 1;
1137 if (UsbFloppyDevice
->BlkIo
.Media
->BlockSize
!= OldMediaInfo
.BlockSize
) {
1138 *MediaChange
= TRUE
;
1139 UsbFloppyDevice
->BlkIo
.Media
->MediaId
+= 1;
1142 if (UsbFloppyDevice
->BlkIo
.Media
->LastBlock
!= OldMediaInfo
.LastBlock
) {
1143 *MediaChange
= TRUE
;
1144 UsbFloppyDevice
->BlkIo
.Media
->MediaId
+= 1;
1147 if (UsbFloppyDevice
->BlkIo
.Media
->MediaId
!= OldMediaInfo
.MediaId
) {
1148 *MediaChange
= TRUE
;
1157 UsbFloppyModeSense5APage5 (
1158 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1162 Routine Description:
1163 Retrieves media capacity information via sending Read Format
1164 Capacity Packet Command.
1167 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1170 EFI_DEVICE_ERROR - Hardware error
1171 EFI_SUCCESS - Success
1176 // status returned by Read Capacity Packet Command
1179 ATAPI_PACKET_COMMAND Packet
;
1180 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
1181 UFI_MODE_PARAMETER_PAGE_5 ModePage5
;
1183 UINT32 SectorsPerTrack
;
1184 UINT32 NumberOfCylinders
;
1185 UINT32 NumberOfHeads
;
1186 UINT32 DataBytesPerSector
;
1188 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
1190 ZeroMem (&ModePage5
, sizeof (UFI_MODE_PARAMETER_PAGE_5
));
1192 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1193 Packet
.ModeSenseUFI
.opcode
= UFI_MODE_SENSE5A
;
1195 // Flexible Disk Page
1197 Packet
.ModeSenseUFI
.page_code
= 5;
1201 Packet
.ModeSenseUFI
.page_control
= 0;
1202 Packet
.ModeSenseUFI
.parameter_list_length_hi
= 0;
1203 Packet
.ModeSenseUFI
.parameter_list_length_lo
= sizeof (UFI_MODE_PARAMETER_PAGE_5
);
1204 Status
= USBFloppyPacketCommand (
1207 sizeof (ATAPI_PACKET_COMMAND
),
1208 (VOID
*) &ModePage5
,
1209 sizeof (UFI_MODE_PARAMETER_PAGE_5
),
1214 if (EFI_ERROR (Status
)) {
1215 return EFI_DEVICE_ERROR
;
1218 NumberOfHeads
= ModePage5
.flex_disk_page
.number_of_heads
;
1219 SectorsPerTrack
= ModePage5
.flex_disk_page
.sectors_per_track
;
1220 NumberOfCylinders
= ModePage5
.flex_disk_page
.number_of_cylinders_msb
<< 8 |
1221 ModePage5
.flex_disk_page
.number_of_cylinders_lsb
;
1223 LastBlock
= SectorsPerTrack
* NumberOfHeads
* NumberOfCylinders
;
1224 DataBytesPerSector
= ModePage5
.flex_disk_page
.databytes_per_sector_msb
<< 8 |
1225 ModePage5
.flex_disk_page
.databytes_per_sector_lsb
;
1227 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= LastBlock
;
1229 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
--;
1231 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= DataBytesPerSector
;
1233 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= TRUE
;
1235 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
=
1236 ModePage5
.mode_param_header
.write_protected
;
1243 UsbFloppyModeSense5APage1C (
1244 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1248 Routine Description:
1249 Retrieves media capacity information via sending Read Format
1250 Capacity Packet Command.
1253 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1256 EFI_DEVICE_ERROR - Hardware error
1257 EFI_SUCCESS - Success
1262 // status returned by Read Capacity Packet Command
1265 ATAPI_PACKET_COMMAND Packet
;
1266 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
1267 UFI_MODE_PARAMETER_PAGE_1C ModePage1C
;
1269 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
1271 ZeroMem (&ModePage1C
, sizeof (UFI_MODE_PARAMETER_PAGE_1C
));
1273 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1274 Packet
.ModeSenseUFI
.opcode
= UFI_MODE_SENSE5A
;
1276 // Flexible Disk Page
1278 Packet
.ModeSenseUFI
.page_code
= 0x1C;
1282 Packet
.ModeSenseUFI
.page_control
= 0;
1283 Packet
.ModeSenseUFI
.parameter_list_length_hi
= 0;
1284 Packet
.ModeSenseUFI
.parameter_list_length_lo
= sizeof (UFI_MODE_PARAMETER_PAGE_1C
);
1285 Status
= USBFloppyPacketCommand (
1288 sizeof (ATAPI_PACKET_COMMAND
),
1289 (VOID
*) &ModePage1C
,
1290 sizeof (UFI_MODE_PARAMETER_PAGE_1C
),
1295 if (EFI_ERROR (Status
)) {
1296 return EFI_DEVICE_ERROR
;
1299 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= ModePage1C
.mode_param_header
.write_protected
;
1306 UsbMassStorageModeSense (
1307 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1310 if (UsbFloppyDevice
->AtapiProtocol
->CommandProtocol
== EFI_USB_SUBCLASS_SCSI
) {
1311 return UsbSCSIModeSense1APage3F (UsbFloppyDevice
);
1313 return UsbFloppyModeSense5APage3F (UsbFloppyDevice
);
1318 UsbFloppyModeSense5APage3F (
1319 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1323 Routine Description:
1324 Retrieves mode sense information via sending Mode Sense
1328 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1331 EFI_DEVICE_ERROR - Hardware error
1332 EFI_SUCCESS - Success
1337 // status returned by Read Capacity Packet Command
1340 ATAPI_PACKET_COMMAND Packet
;
1341 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
1342 UFI_MODE_PARAMETER_HEADER Header
;
1345 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
1347 Size
= sizeof (UFI_MODE_PARAMETER_HEADER
);
1349 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1350 Packet
.ModeSenseUFI
.opcode
= UFI_MODE_SENSE5A
;
1351 Packet
.ModeSenseUFI
.page_code
= 0x3F;
1352 Packet
.ModeSenseUFI
.page_control
= 0;
1353 Packet
.ModeSenseUFI
.parameter_list_length_hi
= 0;
1354 Packet
.ModeSenseUFI
.parameter_list_length_lo
= (UINT8
) Size
;
1355 Status
= USBFloppyPacketCommand (
1358 sizeof (ATAPI_PACKET_COMMAND
),
1365 if (EFI_ERROR (Status
)) {
1366 return EFI_DEVICE_ERROR
;
1369 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= Header
.write_protected
;
1376 UsbSCSIModeSense1APage3F (
1377 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1381 Routine Description:
1382 Retrieves mode sense information via sending Mode Sense
1386 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1389 EFI_DEVICE_ERROR - Hardware error
1390 EFI_SUCCESS - Success
1395 // status returned by Read Capacity Packet Command
1398 ATAPI_PACKET_COMMAND Packet
;
1399 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
1400 SCSI_MODE_PARAMETER_HEADER6 Header
;
1403 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
1405 Size
= sizeof (SCSI_MODE_PARAMETER_HEADER6
);
1407 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1408 Packet
.ModeSenseSCSI
.opcode
= SCSI_MODE_SENSE1A
;
1409 Packet
.ModeSenseSCSI
.page_code
= 0x3F;
1410 Packet
.ModeSenseSCSI
.page_control
= 0;
1411 Packet
.ModeSenseSCSI
.allocation_length
= (UINT8
) Size
;
1412 Status
= USBFloppyPacketCommand (
1415 sizeof (MODE_SENSE_CMD_SCSI
),
1422 if (EFI_ERROR (Status
)) {
1423 return EFI_DEVICE_ERROR
;
1426 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= Header
.write_protected
;
1433 The following functions are a set of helper functions,
1434 which are used to parse sense key returned by the device.
1439 IN REQUEST_SENSE_DATA
*SenseData
,
1440 IN UINTN SenseCounts
1443 REQUEST_SENSE_DATA
*SensePtr
;
1449 SensePtr
= SenseData
;
1451 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1453 if ((SensePtr
->sense_key
== SK_NOT_READY
) &&
1454 (SensePtr
->addnl_sense_code
== ASC_NO_MEDIA
)) {
1468 IN REQUEST_SENSE_DATA
*SenseData
,
1469 IN UINTN SenseCounts
1472 REQUEST_SENSE_DATA
*SensePtr
;
1477 SensePtr
= SenseData
;
1479 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1481 switch (SensePtr
->sense_key
) {
1484 // Medium error case
1486 case SK_MEDIUM_ERROR
:
1487 switch (SensePtr
->addnl_sense_code
) {
1489 case ASC_MEDIA_ERR1
:
1490 case ASC_MEDIA_ERR2
:
1491 case ASC_MEDIA_ERR3
:
1492 case ASC_MEDIA_ERR4
:
1503 // Medium upside-down case
1506 switch (SensePtr
->addnl_sense_code
) {
1507 case ASC_MEDIA_UPSIDE_DOWN
:
1528 IN REQUEST_SENSE_DATA
*SenseData
,
1529 IN UINTN SenseCounts
1532 REQUEST_SENSE_DATA
*SensePtr
;
1534 BOOLEAN MediaChanged
;
1536 MediaChanged
= FALSE
;
1537 SensePtr
= SenseData
;
1539 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1541 if ((SensePtr
->sense_key
== SK_UNIT_ATTENTION
) &&
1542 (SensePtr
->addnl_sense_code
== ASC_MEDIA_CHANGE
)) {
1544 MediaChanged
= TRUE
;
1550 return MediaChanged
;
1555 IN REQUEST_SENSE_DATA
*SenseData
,
1556 IN UINTN SenseCounts
,
1557 OUT BOOLEAN
*NeedRetry
1560 REQUEST_SENSE_DATA
*SensePtr
;
1566 SensePtr
= SenseData
;
1568 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1570 if ((SensePtr
->sense_key
== SK_NOT_READY
) &&
1571 (SensePtr
->addnl_sense_code
== ASC_NOT_READY
)) {
1573 switch (SensePtr
->addnl_sense_code_qualifier
) {
1575 case ASCQ_IN_PROGRESS
:
1576 case ASCQ_DEVICE_BUSY
:
1583 // Drive is in error condition,
1584 // no need to retry.
1599 IsMediaWriteProtected (
1600 IN REQUEST_SENSE_DATA
*SenseData
,
1601 IN UINTN SenseCounts
1604 REQUEST_SENSE_DATA
*SensePtr
;
1606 BOOLEAN IsWriteProtected
;
1608 IsWriteProtected
= FALSE
;
1609 SensePtr
= SenseData
;
1611 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1613 // catch media write-protected condition.
1615 if ((SensePtr
->sense_key
== SK_DATA_PROTECT
) &&
1616 (SensePtr
->addnl_sense_code
== ASC_WRITE_PROTECTED
)) {
1618 IsWriteProtected
= TRUE
;
1624 return IsWriteProtected
;
1628 IsLogicalUnitCommunicationOverRun (
1629 IN REQUEST_SENSE_DATA
*SenseData
,
1630 IN UINTN SenseCounts
1633 REQUEST_SENSE_DATA
*SensePtr
;
1638 SensePtr
= SenseData
;
1640 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1642 if ((SensePtr
->sense_key
== SK_NOT_READY
) &&
1643 (SensePtr
->addnl_sense_code
== ASC_LOGICAL_UNIT_STATUS
) &&
1644 (SensePtr
->addnl_sense_code_qualifier
== ASCQ_LOGICAL_UNIT_OVERRUN
)) {