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 //OldMediaInfo = *UsbFloppyDevice->BlkIo.Media;
928 *MediaChange
= FALSE
;
929 NeedReadCapacity
= TRUE
;
932 // if there is no media present,or media not changed,
933 // the request sense command will detect faster than read capacity command.
934 // read capacity command can be bypassed, thus improve performance.
937 Status
= UsbFloppyRequestSense (UsbFloppyDevice
, &SenseCounts
);
939 if (!EFI_ERROR (Status
)) {
941 SensePtr
= UsbFloppyDevice
->SenseData
;
946 if (IsNoMedia (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
948 NeedReadCapacity
= FALSE
;
949 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
950 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
951 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
956 if (IsMediaChange (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
957 UsbFloppyDevice
->BlkIo
.Media
->MediaId
++;
961 // Media Write-protected
963 if (IsMediaWriteProtected (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
964 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= TRUE
;
970 if (IsMediaError (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
972 // if media error encountered, make it look like no media present.
974 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
975 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
976 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
983 if (NeedReadCapacity
) {
985 // at most retry 5 times
987 MaximumRetryTimes
= 5;
989 // initial retry twice
993 for (RetryIndex
= 0; (RetryIndex
< RetryTimes
) && (RetryIndex
< MaximumRetryTimes
); RetryIndex
++) {
995 // Using different command to retrieve media capacity.
997 switch (UsbFloppyDevice
->DeviceType
) {
1000 Status
= USBFloppyReadCapacity (UsbFloppyDevice
);
1004 UsbMassStorageModeSense (UsbFloppyDevice
);
1005 Status
= USBFloppyReadFormatCapacity (UsbFloppyDevice
);
1006 if (EFI_ERROR (Status
) || !UsbFloppyDevice
->BlkMedia
.MediaPresent
) {
1008 // retry the ReadCapacity command
1010 UsbFloppyDevice
->DeviceType
= USBFLOPPY2
;
1011 Status
= EFI_DEVICE_ERROR
;
1016 UsbMassStorageModeSense (UsbFloppyDevice
);
1017 Status
= USBFloppyReadCapacity (UsbFloppyDevice
);
1018 if (EFI_ERROR (Status
)) {
1020 // retry the ReadFormatCapacity command
1022 UsbFloppyDevice
->DeviceType
= USBFLOPPY
;
1025 // force the BlockSize to be 0x200.
1027 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= 0x200;
1031 return EFI_INVALID_PARAMETER
;
1034 if (!EFI_ERROR (Status
)) {
1036 // skip the loop when read capacity succeeds.
1043 FloppyStatus
= UsbFloppyRequestSense (UsbFloppyDevice
, &SenseCounts
);
1046 // If Request Sense data failed,retry.
1048 if (EFI_ERROR (FloppyStatus
)) {
1058 if (IsNoMedia (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
1060 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
1061 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
1062 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
1066 if (IsMediaError (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
1068 // if media error encountered, make it look like no media present.
1070 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
1071 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
1072 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
1076 if (IsMediaWriteProtected (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
1077 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= TRUE
;
1081 if (!IsDriveReady (UsbFloppyDevice
->SenseData
, SenseCounts
, &NeedRetry
)) {
1084 // Drive not ready: if NeedRetry, then retry once more;
1085 // else return error
1089 // Stall 0.1 second to wait for drive becoming ready
1091 gBS
->Stall (100 * STALL_1_MILLI_SECOND
);
1093 // reset retry variable to zero,
1094 // to make it retry for "drive in progress of becoming ready".
1099 return EFI_DEVICE_ERROR
;
1103 // if read capacity fail not for above reasons, retry once more
1113 // tell whether the readcapacity process is successful or not
1114 // ("Status" variable record the latest status returned
1115 // by ReadCapacity AND "FloppyStatus" record the latest status
1116 // returned by RequestSense)
1118 if (EFI_ERROR (Status
) && EFI_ERROR (FloppyStatus
)) {
1119 return EFI_DEVICE_ERROR
;
1124 if (UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
!= OldMediaInfo
.MediaPresent
) {
1126 if (UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
) {
1127 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 1;
1130 *MediaChange
= TRUE
;
1133 if (UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
!= OldMediaInfo
.ReadOnly
) {
1134 *MediaChange
= TRUE
;
1135 UsbFloppyDevice
->BlkIo
.Media
->MediaId
+= 1;
1138 if (UsbFloppyDevice
->BlkIo
.Media
->BlockSize
!= OldMediaInfo
.BlockSize
) {
1139 *MediaChange
= TRUE
;
1140 UsbFloppyDevice
->BlkIo
.Media
->MediaId
+= 1;
1143 if (UsbFloppyDevice
->BlkIo
.Media
->LastBlock
!= OldMediaInfo
.LastBlock
) {
1144 *MediaChange
= TRUE
;
1145 UsbFloppyDevice
->BlkIo
.Media
->MediaId
+= 1;
1148 if (UsbFloppyDevice
->BlkIo
.Media
->MediaId
!= OldMediaInfo
.MediaId
) {
1149 *MediaChange
= TRUE
;
1158 UsbFloppyModeSense5APage5 (
1159 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1163 Routine Description:
1164 Retrieves media capacity information via sending Read Format
1165 Capacity Packet Command.
1168 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1171 EFI_DEVICE_ERROR - Hardware error
1172 EFI_SUCCESS - Success
1177 // status returned by Read Capacity Packet Command
1180 ATAPI_PACKET_COMMAND Packet
;
1181 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
1182 UFI_MODE_PARAMETER_PAGE_5 ModePage5
;
1184 UINT32 SectorsPerTrack
;
1185 UINT32 NumberOfCylinders
;
1186 UINT32 NumberOfHeads
;
1187 UINT32 DataBytesPerSector
;
1189 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
1191 ZeroMem (&ModePage5
, sizeof (UFI_MODE_PARAMETER_PAGE_5
));
1193 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1194 Packet
.ModeSenseUFI
.opcode
= UFI_MODE_SENSE5A
;
1196 // Flexible Disk Page
1198 Packet
.ModeSenseUFI
.page_code
= 5;
1202 Packet
.ModeSenseUFI
.page_control
= 0;
1203 Packet
.ModeSenseUFI
.parameter_list_length_hi
= 0;
1204 Packet
.ModeSenseUFI
.parameter_list_length_lo
= sizeof (UFI_MODE_PARAMETER_PAGE_5
);
1205 Status
= USBFloppyPacketCommand (
1208 sizeof (ATAPI_PACKET_COMMAND
),
1209 (VOID
*) &ModePage5
,
1210 sizeof (UFI_MODE_PARAMETER_PAGE_5
),
1215 if (EFI_ERROR (Status
)) {
1216 return EFI_DEVICE_ERROR
;
1219 NumberOfHeads
= ModePage5
.flex_disk_page
.number_of_heads
;
1220 SectorsPerTrack
= ModePage5
.flex_disk_page
.sectors_per_track
;
1221 NumberOfCylinders
= ModePage5
.flex_disk_page
.number_of_cylinders_msb
<< 8 |
1222 ModePage5
.flex_disk_page
.number_of_cylinders_lsb
;
1224 LastBlock
= SectorsPerTrack
* NumberOfHeads
* NumberOfCylinders
;
1225 DataBytesPerSector
= ModePage5
.flex_disk_page
.databytes_per_sector_msb
<< 8 |
1226 ModePage5
.flex_disk_page
.databytes_per_sector_lsb
;
1228 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= LastBlock
;
1230 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
--;
1232 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= DataBytesPerSector
;
1234 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= TRUE
;
1236 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
=
1237 ModePage5
.mode_param_header
.write_protected
;
1244 UsbFloppyModeSense5APage1C (
1245 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1249 Routine Description:
1250 Retrieves media capacity information via sending Read Format
1251 Capacity Packet Command.
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 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
1268 UFI_MODE_PARAMETER_PAGE_1C ModePage1C
;
1270 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
1272 ZeroMem (&ModePage1C
, sizeof (UFI_MODE_PARAMETER_PAGE_1C
));
1274 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1275 Packet
.ModeSenseUFI
.opcode
= UFI_MODE_SENSE5A
;
1277 // Flexible Disk Page
1279 Packet
.ModeSenseUFI
.page_code
= 0x1C;
1283 Packet
.ModeSenseUFI
.page_control
= 0;
1284 Packet
.ModeSenseUFI
.parameter_list_length_hi
= 0;
1285 Packet
.ModeSenseUFI
.parameter_list_length_lo
= sizeof (UFI_MODE_PARAMETER_PAGE_1C
);
1286 Status
= USBFloppyPacketCommand (
1289 sizeof (ATAPI_PACKET_COMMAND
),
1290 (VOID
*) &ModePage1C
,
1291 sizeof (UFI_MODE_PARAMETER_PAGE_1C
),
1296 if (EFI_ERROR (Status
)) {
1297 return EFI_DEVICE_ERROR
;
1300 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= ModePage1C
.mode_param_header
.write_protected
;
1307 UsbMassStorageModeSense (
1308 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1311 if (UsbFloppyDevice
->AtapiProtocol
->CommandProtocol
== EFI_USB_SUBCLASS_SCSI
) {
1312 return UsbSCSIModeSense1APage3F (UsbFloppyDevice
);
1314 return UsbFloppyModeSense5APage3F (UsbFloppyDevice
);
1319 UsbFloppyModeSense5APage3F (
1320 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1324 Routine Description:
1325 Retrieves mode sense information via sending Mode Sense
1329 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1332 EFI_DEVICE_ERROR - Hardware error
1333 EFI_SUCCESS - Success
1338 // status returned by Read Capacity Packet Command
1341 ATAPI_PACKET_COMMAND Packet
;
1342 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
1343 UFI_MODE_PARAMETER_HEADER Header
;
1346 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
1348 Size
= sizeof (UFI_MODE_PARAMETER_HEADER
);
1350 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1351 Packet
.ModeSenseUFI
.opcode
= UFI_MODE_SENSE5A
;
1352 Packet
.ModeSenseUFI
.page_code
= 0x3F;
1353 Packet
.ModeSenseUFI
.page_control
= 0;
1354 Packet
.ModeSenseUFI
.parameter_list_length_hi
= 0;
1355 Packet
.ModeSenseUFI
.parameter_list_length_lo
= (UINT8
) Size
;
1356 Status
= USBFloppyPacketCommand (
1359 sizeof (ATAPI_PACKET_COMMAND
),
1366 if (EFI_ERROR (Status
)) {
1367 return EFI_DEVICE_ERROR
;
1370 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= Header
.write_protected
;
1377 UsbSCSIModeSense1APage3F (
1378 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1382 Routine Description:
1383 Retrieves mode sense information via sending Mode Sense
1387 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1390 EFI_DEVICE_ERROR - Hardware error
1391 EFI_SUCCESS - Success
1396 // status returned by Read Capacity Packet Command
1399 ATAPI_PACKET_COMMAND Packet
;
1400 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
1401 SCSI_MODE_PARAMETER_HEADER6 Header
;
1404 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
1406 Size
= sizeof (SCSI_MODE_PARAMETER_HEADER6
);
1408 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1409 Packet
.ModeSenseSCSI
.opcode
= SCSI_MODE_SENSE1A
;
1410 Packet
.ModeSenseSCSI
.page_code
= 0x3F;
1411 Packet
.ModeSenseSCSI
.page_control
= 0;
1412 Packet
.ModeSenseSCSI
.allocation_length
= (UINT8
) Size
;
1413 Status
= USBFloppyPacketCommand (
1416 sizeof (MODE_SENSE_CMD_SCSI
),
1423 if (EFI_ERROR (Status
)) {
1424 return EFI_DEVICE_ERROR
;
1427 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= Header
.write_protected
;
1434 The following functions are a set of helper functions,
1435 which are used to parse sense key returned by the device.
1440 IN REQUEST_SENSE_DATA
*SenseData
,
1441 IN UINTN SenseCounts
1444 REQUEST_SENSE_DATA
*SensePtr
;
1450 SensePtr
= SenseData
;
1452 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1454 if ((SensePtr
->sense_key
== SK_NOT_READY
) &&
1455 (SensePtr
->addnl_sense_code
== ASC_NO_MEDIA
)) {
1469 IN REQUEST_SENSE_DATA
*SenseData
,
1470 IN UINTN SenseCounts
1473 REQUEST_SENSE_DATA
*SensePtr
;
1478 SensePtr
= SenseData
;
1480 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1482 switch (SensePtr
->sense_key
) {
1485 // Medium error case
1487 case SK_MEDIUM_ERROR
:
1488 switch (SensePtr
->addnl_sense_code
) {
1490 case ASC_MEDIA_ERR1
:
1491 case ASC_MEDIA_ERR2
:
1492 case ASC_MEDIA_ERR3
:
1493 case ASC_MEDIA_ERR4
:
1504 // Medium upside-down case
1507 switch (SensePtr
->addnl_sense_code
) {
1508 case ASC_MEDIA_UPSIDE_DOWN
:
1529 IN REQUEST_SENSE_DATA
*SenseData
,
1530 IN UINTN SenseCounts
1533 REQUEST_SENSE_DATA
*SensePtr
;
1535 BOOLEAN MediaChanged
;
1537 MediaChanged
= FALSE
;
1538 SensePtr
= SenseData
;
1540 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1542 if ((SensePtr
->sense_key
== SK_UNIT_ATTENTION
) &&
1543 (SensePtr
->addnl_sense_code
== ASC_MEDIA_CHANGE
)) {
1545 MediaChanged
= TRUE
;
1551 return MediaChanged
;
1556 IN REQUEST_SENSE_DATA
*SenseData
,
1557 IN UINTN SenseCounts
,
1558 OUT BOOLEAN
*NeedRetry
1561 REQUEST_SENSE_DATA
*SensePtr
;
1567 SensePtr
= SenseData
;
1569 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1571 if ((SensePtr
->sense_key
== SK_NOT_READY
) &&
1572 (SensePtr
->addnl_sense_code
== ASC_NOT_READY
)) {
1574 switch (SensePtr
->addnl_sense_code_qualifier
) {
1576 case ASCQ_IN_PROGRESS
:
1577 case ASCQ_DEVICE_BUSY
:
1584 // Drive is in error condition,
1585 // no need to retry.
1600 IsMediaWriteProtected (
1601 IN REQUEST_SENSE_DATA
*SenseData
,
1602 IN UINTN SenseCounts
1605 REQUEST_SENSE_DATA
*SensePtr
;
1607 BOOLEAN IsWriteProtected
;
1609 IsWriteProtected
= FALSE
;
1610 SensePtr
= SenseData
;
1612 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1614 // catch media write-protected condition.
1616 if ((SensePtr
->sense_key
== SK_DATA_PROTECT
) &&
1617 (SensePtr
->addnl_sense_code
== ASC_WRITE_PROTECTED
)) {
1619 IsWriteProtected
= TRUE
;
1625 return IsWriteProtected
;
1629 IsLogicalUnitCommunicationOverRun (
1630 IN REQUEST_SENSE_DATA
*SenseData
,
1631 IN UINTN SenseCounts
1634 REQUEST_SENSE_DATA
*SensePtr
;
1639 SensePtr
= SenseData
;
1641 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1643 if ((SensePtr
->sense_key
== SK_NOT_READY
) &&
1644 (SensePtr
->addnl_sense_code
== ASC_LOGICAL_UNIT_STATUS
) &&
1645 (SensePtr
->addnl_sense_code_qualifier
== ASCQ_LOGICAL_UNIT_OVERRUN
)) {