3 Copyright (c) 2006 - 2007, 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 USBFloppyPacketCommand (
65 USB_FLOPPY_DEV
*UsbFloppyDevice
,
70 EFI_USB_DATA_DIRECTION Direction
,
71 UINT16 TimeOutInMilliSeconds
76 Sends Packet Command to USB Floppy Drive.
79 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
80 Command - A pointer to the command packet.
81 CommandSize - Indicates the size of the command packet.
82 DataBuffer - A pointer to the buffer for the data transfer
83 after the command packet.
84 BufferLength - Indicates the size of the Data Buffer.
85 Direction - Transfer Direction
86 TimeOutInMilliSeconds - Timeout Value
91 EFI_USB_ATAPI_PROTOCOL
*UsbAtapiInterface
;
94 UsbAtapiInterface
= UsbFloppyDevice
->AtapiProtocol
;
96 // Directly calling EFI_USB_ATAPI_PROTOCOL.UsbAtapiPacketCmd()
97 // to perform the command request.
99 Status
= UsbAtapiInterface
->UsbAtapiPacketCmd (
106 TimeOutInMilliSeconds
114 IN USB_FLOPPY_DEV
*UsbFloppyDevice
119 Retrieves device information to tell the device type.
122 UsbFloppyDevice The USB_FLOPPY_DEV instance.
125 EFI_DEVICE_ERROR - Hardware error
126 EFI_SUCCESS - Success
131 USB_INQUIRY_DATA
*Idata
;
135 // Send Inquiry Packet Command to get INQUIRY data.
137 Status
= USBFloppyInquiry (UsbFloppyDevice
, &Idata
);
138 if (EFI_ERROR (Status
)) {
139 return EFI_DEVICE_ERROR
;
143 // Get media removable info from INQUIRY data.
145 UsbFloppyDevice
->BlkIo
.Media
->RemovableMedia
= (UINT8
) ((Idata
->RMB
& 0x80) == 0x80);
148 // Identify device type via INQUIRY data.
150 switch ((Idata
->peripheral_type
) & 0x1f) {
155 UsbFloppyDevice
->DeviceType
= USBFLOPPY
;
156 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
157 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
158 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
159 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= 0x200;
166 UsbFloppyDevice
->DeviceType
= USBCDROM
;
167 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
168 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
169 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
170 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= 0x800;
171 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= TRUE
;
175 gBS
->FreePool (Idata
);
176 return EFI_DEVICE_ERROR
;
180 // Initialize some device specific data.
183 // original sense data numbers
185 UsbFloppyDevice
->SenseDataNumber
= 6;
187 if (UsbFloppyDevice
->SenseData
!= NULL
) {
188 gBS
->FreePool (UsbFloppyDevice
->SenseData
);
189 UsbFloppyDevice
->SenseData
= NULL
;
192 UsbFloppyDevice
->SenseData
= AllocatePool (UsbFloppyDevice
->SenseDataNumber
* sizeof (REQUEST_SENSE_DATA
));
194 if (UsbFloppyDevice
->SenseData
== NULL
) {
195 gBS
->FreePool (Idata
);
196 return EFI_DEVICE_ERROR
;
200 // Get media information.
202 UsbFloppyDetectMedia (UsbFloppyDevice
, &MediaChange
);
204 gBS
->FreePool (Idata
);
211 IN USB_FLOPPY_DEV
*UsbFloppyDevice
,
212 OUT USB_INQUIRY_DATA
**Idata
217 Send Inquiry Packet Command to device and retrieve Inquiry Data.
220 UsbFloppyDevice The USB_FLOPPY_DEV instance.
221 Idata A pointer pointing to the address of
225 EFI_DEVICE_ERROR - Hardware error
226 EFI_SUCCESS - Success
229 ATAPI_PACKET_COMMAND Packet
;
234 // prepare command packet for the Inquiry Packet Command.
236 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
237 Packet
.Inquiry
.opcode
= INQUIRY
;
238 Packet
.Inquiry
.page_code
= 0;
239 Packet
.Inquiry
.allocation_length
= sizeof (USB_INQUIRY_DATA
);
241 *Idata
= AllocateZeroPool (sizeof (USB_INQUIRY_DATA
));
242 if (*Idata
== NULL
) {
243 return EFI_DEVICE_ERROR
;
246 // Send command packet and retrieve requested Inquiry Data.
248 Status
= USBFloppyPacketCommand (
251 sizeof (ATAPI_PACKET_COMMAND
),
253 sizeof (USB_INQUIRY_DATA
),
257 if (EFI_ERROR (Status
)) {
258 gBS
->FreePool (*Idata
);
259 return EFI_DEVICE_ERROR
;
267 IN USB_FLOPPY_DEV
*UsbFloppyDevice
,
270 IN UINTN NumberOfBlocks
275 Sends Read10 Packet Command to device to perform data transfer
279 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
280 Buffer - A pointer to the destination buffer for the data.
281 The caller is responsible for either having implicit
282 or explicit ownership of the buffer.
283 Lba - The starting logical block address to read from
285 NumberOfBlocks - Indicates the number of blocks that the read
289 EFI_DEVICE_ERROR - Hardware error
290 EFI_SUCCESS - Success
293 ATAPI_PACKET_COMMAND Packet
;
294 READ10_CMD
*Read10Packet
;
296 UINT16 BlocksRemaining
;
308 // prepare command packet for the Inquiry Packet Command.
310 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
311 Read10Packet
= &Packet
.Read10
;
312 Lba32
= (UINT32
) Lba
;
314 BlockSize
= UsbFloppyDevice
->BlkIo
.Media
->BlockSize
;
316 MaxBlock
= (UINT16
) (65536 / BlockSize
);
317 BlocksRemaining
= (UINT16
) NumberOfBlocks
;
319 Status
= EFI_SUCCESS
;
320 while (BlocksRemaining
> 0) {
321 if (BlocksRemaining
<= MaxBlock
) {
322 SectorCount
= BlocksRemaining
;
324 SectorCount
= MaxBlock
;
327 for (Index
= 0; Index
< 3; Index
++) {
330 // fill the Packet data structure
332 Read10Packet
->opcode
= READ_10
;
334 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
335 // Lba0 is MSB, Lba3 is LSB
337 Read10Packet
->Lba3
= (UINT8
) (Lba32
& 0xff);
338 Read10Packet
->Lba2
= (UINT8
) (Lba32
>> 8);
339 Read10Packet
->Lba1
= (UINT8
) (Lba32
>> 16);
340 Read10Packet
->Lba0
= (UINT8
) (Lba32
>> 24);
343 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
344 // TranLen0 is MSB, TranLen is LSB
346 Read10Packet
->TranLen1
= (UINT8
) (SectorCount
& 0xff);
347 Read10Packet
->TranLen0
= (UINT8
) (SectorCount
>> 8);
349 ByteCount
= SectorCount
* BlockSize
;
351 TimeOut
= (UINT16
) (SectorCount
* USBDATATIMEOUT
);
354 Status
= USBFloppyPacketCommand (
357 sizeof (ATAPI_PACKET_COMMAND
),
363 if (!EFI_ERROR (Status
)) {
369 return EFI_DEVICE_ERROR
;
372 Lba32
+= SectorCount
;
373 ptrBuffer
= (UINT8
*) ptrBuffer
+ SectorCount
* BlockSize
;
374 BlocksRemaining
= (UINT16
) (BlocksRemaining
- SectorCount
);
382 USBFloppyReadCapacity (
383 IN USB_FLOPPY_DEV
*UsbFloppyDevice
388 Retrieves media capacity information via
389 sending Read Capacity Packet Command.
392 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
395 EFI_DEVICE_ERROR - Hardware error
396 EFI_SUCCESS - Success
400 // status returned by Read Capacity Packet Command
403 ATAPI_PACKET_COMMAND Packet
;
406 // used for capacity data returned from Usb Floppy
408 READ_CAPACITY_DATA Data
;
410 ZeroMem (&Data
, sizeof (Data
));
413 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
414 Packet
.Inquiry
.opcode
= READ_CAPACITY
;
415 Status
= USBFloppyPacketCommand (
418 sizeof (ATAPI_PACKET_COMMAND
),
420 sizeof (READ_CAPACITY_DATA
),
425 if (EFI_ERROR (Status
)) {
426 return EFI_DEVICE_ERROR
;
429 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= (Data
.LastLba3
<< 24) |
430 (Data
.LastLba2
<< 16) |
431 (Data
.LastLba1
<< 8) |
434 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= TRUE
;
436 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= 0x800;
443 USBFloppyReadFormatCapacity (
444 IN USB_FLOPPY_DEV
*UsbFloppyDevice
449 Retrieves media capacity information via sending Read Format
450 Capacity Packet Command.
453 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
456 EFI_DEVICE_ERROR - Hardware error
457 EFI_SUCCESS - Success
461 // status returned by Read Capacity Packet Command
464 ATAPI_PACKET_COMMAND Packet
;
467 // used for capacity data returned from Usb Floppy
469 READ_FORMAT_CAPACITY_DATA FormatData
;
471 ZeroMem (&FormatData
, sizeof (FormatData
));
474 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
475 Packet
.ReadFormatCapacity
.opcode
= READ_FORMAT_CAPACITY
;
476 Packet
.ReadFormatCapacity
.allocation_length_lo
= 12;
477 Status
= USBFloppyPacketCommand (
480 sizeof (ATAPI_PACKET_COMMAND
),
481 (VOID
*) &FormatData
,
482 sizeof (READ_FORMAT_CAPACITY_DATA
),
487 if (EFI_ERROR (Status
)) {
488 return EFI_DEVICE_ERROR
;
491 if (FormatData
.DesCode
== 3) {
493 // Media is not present
495 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
496 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
497 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
500 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= (FormatData
.LastLba3
<< 24) |
501 (FormatData
.LastLba2
<< 16) |
502 (FormatData
.LastLba1
<< 8) |
505 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
--;
507 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= (FormatData
.BlockSize2
<< 16) |
508 (FormatData
.BlockSize1
<< 8) |
509 FormatData
.BlockSize0
;
511 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= TRUE
;
513 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= 0x200;
522 UsbFloppyRequestSense (
523 IN USB_FLOPPY_DEV
*UsbFloppyDevice
,
524 OUT UINTN
*SenseCounts
529 Retrieves Sense Data from device via
530 sending Request Sense Packet Command.
533 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
534 SenseCounts - A pointer to the number of Sense Data returned.
537 EFI_DEVICE_ERROR - Hardware error
538 EFI_SUCCESS - Success
542 REQUEST_SENSE_DATA
*Sense
;
545 ATAPI_PACKET_COMMAND Packet
;
551 UsbFloppyDevice
->SenseData
,
552 sizeof (REQUEST_SENSE_DATA
) * (UsbFloppyDevice
->SenseDataNumber
)
555 // fill command packet for Request Sense Packet Command
557 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
558 Packet
.RequestSense
.opcode
= REQUEST_SENSE
;
559 Packet
.RequestSense
.allocation_length
= sizeof (REQUEST_SENSE_DATA
);
562 // initialize pointer
564 Ptr
= (UINT8
*) (UsbFloppyDevice
->SenseData
);
567 // request sense data from device continuously
568 // until no sense data exists in the device.
570 for (SenseReq
= TRUE
; SenseReq
;) {
572 Sense
= (REQUEST_SENSE_DATA
*) Ptr
;
575 // send out Request Sense Packet Command and get one Sense
578 Status
= USBFloppyPacketCommand (
581 sizeof (ATAPI_PACKET_COMMAND
),
583 sizeof (REQUEST_SENSE_DATA
),
588 // failed to get Sense data
590 if (EFI_ERROR (Status
)) {
592 // Recovery the device back to normal state.
594 UsbFloppyDevice
->AtapiProtocol
->UsbAtapiReset (
595 UsbFloppyDevice
->AtapiProtocol
,
599 if (*SenseCounts
== 0) {
601 // never retrieved any sense data from device,
602 // just return error.
604 return EFI_DEVICE_ERROR
;
607 // has retrieved some sense data from device,
608 // so return success.
614 if (Sense
->sense_key
!= SK_NO_SENSE
) {
616 // Ptr is byte based pointer
618 Ptr
+= sizeof (REQUEST_SENSE_DATA
);
624 // when no sense key, skip out the loop
630 // If the sense key numbers exceed Sense Data Buffer size,
631 // just skip the loop and do not fetch the sense key in this function.
633 if (*SenseCounts
== UsbFloppyDevice
->SenseDataNumber
) {
642 UsbFloppyTestUnitReady (
643 IN USB_FLOPPY_DEV
*UsbFloppyDevice
648 Sends Test Unit ReadyPacket Command to the device.
651 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
654 EFI_DEVICE_ERROR - Hardware error
655 EFI_SUCCESS - Success
658 ATAPI_PACKET_COMMAND Packet
;
661 UINT32 MaximumRetryTimes
;
663 MaximumRetryTimes
= 2;
665 // fill command packet
667 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
668 Packet
.TestUnitReady
.opcode
= TEST_UNIT_READY
;
671 // send command packet
673 Status
= EFI_DEVICE_ERROR
;
675 for (RetryIndex
= 0; RetryIndex
< MaximumRetryTimes
&& EFI_ERROR (Status
); RetryIndex
++) {
677 Status
= USBFloppyPacketCommand (
680 sizeof (ATAPI_PACKET_COMMAND
),
687 if (EFI_ERROR (Status
)) {
688 gBS
->Stall (100 * STALL_1_MILLI_SECOND
);
697 IN USB_FLOPPY_DEV
*UsbFloppyDevice
,
700 IN UINTN NumberOfBlocks
705 Sends Write10 Packet Command to device to perform data transfer
709 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
710 Buffer - A pointer to the source buffer for the data.
711 The caller is responsible for either having implicit
712 or explicit ownership of the buffer.
713 Lba - The starting logical block address to written to
715 NumberOfBlocks - Indicates the number of blocks that the write
719 EFI_DEVICE_ERROR - Hardware error
720 EFI_SUCCESS - Success
723 ATAPI_PACKET_COMMAND Packet
;
724 READ10_CMD
*Write10Packet
;
726 UINT16 BlocksRemaining
;
738 // prepare command packet for the Write10 Packet Command.
740 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
741 Write10Packet
= &Packet
.Read10
;
742 Lba32
= (UINT32
) Lba
;
744 BlockSize
= UsbFloppyDevice
->BlkIo
.Media
->BlockSize
;
746 MaxBlock
= (UINT16
) (65536 / BlockSize
);
747 BlocksRemaining
= (UINT16
) NumberOfBlocks
;
749 Status
= EFI_SUCCESS
;
750 while (BlocksRemaining
> 0) {
752 if (BlocksRemaining
<= MaxBlock
) {
753 SectorCount
= BlocksRemaining
;
755 SectorCount
= MaxBlock
;
758 for (Index
= 0; Index
< 3; Index
++) {
760 // fill the Packet data structure
762 Write10Packet
->opcode
= WRITE_10
;
765 // Lba0 ~ Lba3 specify the start logical block address
766 // of the data transfer.
767 // Lba0 is MSB, Lba3 is LSB
769 Write10Packet
->Lba3
= (UINT8
) (Lba32
& 0xff);
770 Write10Packet
->Lba2
= (UINT8
) (Lba32
>> 8);
771 Write10Packet
->Lba1
= (UINT8
) (Lba32
>> 16);
772 Write10Packet
->Lba0
= (UINT8
) (Lba32
>> 24);
775 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
776 // TranLen0 is MSB, TranLen is LSB
778 Write10Packet
->TranLen1
= (UINT8
) (SectorCount
& 0xff);
779 Write10Packet
->TranLen0
= (UINT8
) (SectorCount
>> 8);
781 ByteCount
= SectorCount
* BlockSize
;
783 TimeOut
= (UINT16
) (SectorCount
* USBDATATIMEOUT
);
785 Status
= USBFloppyPacketCommand (
788 sizeof (ATAPI_PACKET_COMMAND
),
794 if (!EFI_ERROR (Status
)) {
800 return EFI_DEVICE_ERROR
;
803 Lba32
+= SectorCount
;
804 ptrBuffer
= (UINT8
*) ptrBuffer
+ SectorCount
* BlockSize
;
805 BlocksRemaining
= (UINT16
) (BlocksRemaining
- SectorCount
);
812 UsbFloppyDetectMedia (
813 IN USB_FLOPPY_DEV
*UsbFloppyDevice
,
814 OUT BOOLEAN
*MediaChange
819 Retrieves media information.
822 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
823 MediaChange - Indicates whether media was changed.
826 EFI_DEVICE_ERROR - Hardware error
827 EFI_SUCCESS - Success
828 EFI_INVALID_PARAMETER - Parameter is error
832 EFI_STATUS FloppyStatus
;
834 // the following variables are used to record previous media information
836 EFI_BLOCK_IO_MEDIA OldMediaInfo
;
840 UINTN MaximumRetryTimes
;
842 BOOLEAN NeedReadCapacity
;
844 // a flag used to determine whether need to perform Read Capacity command.
850 Status
= EFI_SUCCESS
;
851 FloppyStatus
= EFI_SUCCESS
;
852 CopyMem (&OldMediaInfo
, UsbFloppyDevice
->BlkIo
.Media
, sizeof (OldMediaInfo
));
853 *MediaChange
= FALSE
;
854 NeedReadCapacity
= TRUE
;
857 // if there is no media present,or media not changed,
858 // the request sense command will detect faster than read capacity command.
859 // read capacity command can be bypassed, thus improve performance.
862 Status
= UsbFloppyRequestSense (UsbFloppyDevice
, &SenseCounts
);
864 if (!EFI_ERROR (Status
)) {
869 if (IsNoMedia (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
871 NeedReadCapacity
= FALSE
;
872 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
873 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
874 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
879 if (IsMediaChange (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
880 UsbFloppyDevice
->BlkIo
.Media
->MediaId
++;
884 // Media Write-protected
886 if (IsMediaWriteProtected (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
887 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= TRUE
;
893 if (IsMediaError (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
895 // if media error encountered, make it look like no media present.
897 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
898 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
899 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
906 if (NeedReadCapacity
) {
908 // at most retry 5 times
910 MaximumRetryTimes
= 5;
912 // initial retry twice
916 for (RetryIndex
= 0; (RetryIndex
< RetryTimes
) && (RetryIndex
< MaximumRetryTimes
); RetryIndex
++) {
918 // Using different command to retrieve media capacity.
920 switch (UsbFloppyDevice
->DeviceType
) {
923 Status
= USBFloppyReadCapacity (UsbFloppyDevice
);
927 UsbMassStorageModeSense (UsbFloppyDevice
);
928 Status
= USBFloppyReadFormatCapacity (UsbFloppyDevice
);
929 if (EFI_ERROR (Status
) || !UsbFloppyDevice
->BlkMedia
.MediaPresent
) {
931 // retry the ReadCapacity command
933 UsbFloppyDevice
->DeviceType
= USBFLOPPY
;
934 Status
= EFI_DEVICE_ERROR
;
939 UsbMassStorageModeSense (UsbFloppyDevice
);
940 Status
= USBFloppyReadCapacity (UsbFloppyDevice
);
941 if (EFI_ERROR (Status
)) {
943 // retry the ReadFormatCapacity command
945 UsbFloppyDevice
->DeviceType
= USBFLOPPY2
;
948 // force the BlockSize to be 0x200.
950 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= 0x200;
954 return EFI_INVALID_PARAMETER
;
957 if (!EFI_ERROR (Status
)) {
959 // skip the loop when read capacity succeeds.
966 FloppyStatus
= UsbFloppyRequestSense (UsbFloppyDevice
, &SenseCounts
);
969 // If Request Sense data failed,retry.
971 if (EFI_ERROR (FloppyStatus
)) {
981 if (IsNoMedia (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
983 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
984 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
985 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
989 if (IsMediaError (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
991 // if media error encountered, make it look like no media present.
993 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 0;
994 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= FALSE
;
995 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= 0;
999 if (IsMediaWriteProtected (UsbFloppyDevice
->SenseData
, SenseCounts
)) {
1000 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= TRUE
;
1004 if (!IsDriveReady (UsbFloppyDevice
->SenseData
, SenseCounts
, &NeedRetry
)) {
1007 // Drive not ready: if NeedRetry, then retry once more;
1008 // else return error
1012 // Stall 0.1 second to wait for drive becoming ready
1014 gBS
->Stall (100 * STALL_1_MILLI_SECOND
);
1016 // reset retry variable to zero,
1017 // to make it retry for "drive in progress of becoming ready".
1022 return EFI_DEVICE_ERROR
;
1026 // if read capacity fail not for above reasons, retry once more
1036 // tell whether the readcapacity process is successful or not
1037 // ("Status" variable record the latest status returned
1038 // by ReadCapacity AND "FloppyStatus" record the latest status
1039 // returned by RequestSense)
1041 if (EFI_ERROR (Status
) && EFI_ERROR (FloppyStatus
)) {
1042 return EFI_DEVICE_ERROR
;
1047 if (UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
!= OldMediaInfo
.MediaPresent
) {
1049 if (UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
) {
1050 UsbFloppyDevice
->BlkIo
.Media
->MediaId
= 1;
1053 *MediaChange
= TRUE
;
1056 if (UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
!= OldMediaInfo
.ReadOnly
) {
1057 *MediaChange
= TRUE
;
1058 UsbFloppyDevice
->BlkIo
.Media
->MediaId
+= 1;
1061 if (UsbFloppyDevice
->BlkIo
.Media
->BlockSize
!= OldMediaInfo
.BlockSize
) {
1062 *MediaChange
= TRUE
;
1063 UsbFloppyDevice
->BlkIo
.Media
->MediaId
+= 1;
1066 if (UsbFloppyDevice
->BlkIo
.Media
->LastBlock
!= OldMediaInfo
.LastBlock
) {
1067 *MediaChange
= TRUE
;
1068 UsbFloppyDevice
->BlkIo
.Media
->MediaId
+= 1;
1071 if (UsbFloppyDevice
->BlkIo
.Media
->MediaId
!= OldMediaInfo
.MediaId
) {
1072 *MediaChange
= TRUE
;
1081 UsbFloppyModeSense5APage5 (
1082 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1086 Routine Description:
1087 Retrieves media capacity information via sending Read Format
1088 Capacity Packet Command.
1091 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1094 EFI_DEVICE_ERROR - Hardware error
1095 EFI_SUCCESS - Success
1100 // status returned by Read Capacity Packet Command
1103 ATAPI_PACKET_COMMAND Packet
;
1104 UFI_MODE_PARAMETER_PAGE_5 ModePage5
;
1106 UINT32 SectorsPerTrack
;
1107 UINT32 NumberOfCylinders
;
1108 UINT32 NumberOfHeads
;
1109 UINT32 DataBytesPerSector
;
1112 ZeroMem (&ModePage5
, sizeof (UFI_MODE_PARAMETER_PAGE_5
));
1114 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1115 Packet
.ModeSenseUFI
.opcode
= UFI_MODE_SENSE5A
;
1117 // Flexible Disk Page
1119 Packet
.ModeSenseUFI
.page_code
= 5;
1123 Packet
.ModeSenseUFI
.page_control
= 0;
1124 Packet
.ModeSenseUFI
.parameter_list_length_hi
= 0;
1125 Packet
.ModeSenseUFI
.parameter_list_length_lo
= sizeof (UFI_MODE_PARAMETER_PAGE_5
);
1126 Status
= USBFloppyPacketCommand (
1129 sizeof (ATAPI_PACKET_COMMAND
),
1130 (VOID
*) &ModePage5
,
1131 sizeof (UFI_MODE_PARAMETER_PAGE_5
),
1136 if (EFI_ERROR (Status
)) {
1137 return EFI_DEVICE_ERROR
;
1140 NumberOfHeads
= ModePage5
.flex_disk_page
.number_of_heads
;
1141 SectorsPerTrack
= ModePage5
.flex_disk_page
.sectors_per_track
;
1142 NumberOfCylinders
= ModePage5
.flex_disk_page
.number_of_cylinders_msb
<< 8 |
1143 ModePage5
.flex_disk_page
.number_of_cylinders_lsb
;
1145 LastBlock
= SectorsPerTrack
* NumberOfHeads
* NumberOfCylinders
;
1146 DataBytesPerSector
= ModePage5
.flex_disk_page
.databytes_per_sector_msb
<< 8 |
1147 ModePage5
.flex_disk_page
.databytes_per_sector_lsb
;
1149 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
= LastBlock
;
1151 UsbFloppyDevice
->BlkIo
.Media
->LastBlock
--;
1153 UsbFloppyDevice
->BlkIo
.Media
->BlockSize
= DataBytesPerSector
;
1155 UsbFloppyDevice
->BlkIo
.Media
->MediaPresent
= TRUE
;
1157 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
=
1158 ModePage5
.mode_param_header
.write_protected
;
1165 UsbFloppyModeSense5APage1C (
1166 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1170 Routine Description:
1171 Retrieves media capacity information via sending Read Format
1172 Capacity Packet Command.
1175 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1178 EFI_DEVICE_ERROR - Hardware error
1179 EFI_SUCCESS - Success
1184 // status returned by Read Capacity Packet Command
1187 ATAPI_PACKET_COMMAND Packet
;
1188 UFI_MODE_PARAMETER_PAGE_1C ModePage1C
;
1191 ZeroMem (&ModePage1C
, sizeof (UFI_MODE_PARAMETER_PAGE_1C
));
1193 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1194 Packet
.ModeSenseUFI
.opcode
= UFI_MODE_SENSE5A
;
1196 // Flexible Disk Page
1198 Packet
.ModeSenseUFI
.page_code
= 0x1C;
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_1C
);
1205 Status
= USBFloppyPacketCommand (
1208 sizeof (ATAPI_PACKET_COMMAND
),
1209 (VOID
*) &ModePage1C
,
1210 sizeof (UFI_MODE_PARAMETER_PAGE_1C
),
1215 if (EFI_ERROR (Status
)) {
1216 return EFI_DEVICE_ERROR
;
1219 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= ModePage1C
.mode_param_header
.write_protected
;
1226 UsbMassStorageModeSense (
1227 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1230 if (UsbFloppyDevice
->AtapiProtocol
->CommandProtocol
== EFI_USB_SUBCLASS_SCSI
) {
1231 return UsbSCSIModeSense1APage3F (UsbFloppyDevice
);
1233 return UsbFloppyModeSense5APage3F (UsbFloppyDevice
);
1238 UsbFloppyModeSense5APage3F (
1239 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1243 Routine Description:
1244 Retrieves mode sense information via sending Mode Sense
1248 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1251 EFI_DEVICE_ERROR - Hardware error
1252 EFI_SUCCESS - Success
1257 // status returned by Read Capacity Packet Command
1260 ATAPI_PACKET_COMMAND Packet
;
1261 UFI_MODE_PARAMETER_HEADER Header
;
1265 Size
= sizeof (UFI_MODE_PARAMETER_HEADER
);
1267 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1268 Packet
.ModeSenseUFI
.opcode
= UFI_MODE_SENSE5A
;
1269 Packet
.ModeSenseUFI
.page_code
= 0x3F;
1270 Packet
.ModeSenseUFI
.page_control
= 0;
1271 Packet
.ModeSenseUFI
.parameter_list_length_hi
= 0;
1272 Packet
.ModeSenseUFI
.parameter_list_length_lo
= (UINT8
) Size
;
1273 Status
= USBFloppyPacketCommand (
1276 sizeof (ATAPI_PACKET_COMMAND
),
1283 if (EFI_ERROR (Status
)) {
1284 return EFI_DEVICE_ERROR
;
1287 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= Header
.write_protected
;
1294 UsbSCSIModeSense1APage3F (
1295 IN USB_FLOPPY_DEV
*UsbFloppyDevice
1299 Routine Description:
1300 Retrieves mode sense information via sending Mode Sense
1304 UsbFloppyDevice - The USB_FLOPPY_DEV instance.
1307 EFI_DEVICE_ERROR - Hardware error
1308 EFI_SUCCESS - Success
1313 // status returned by Read Capacity Packet Command
1316 ATAPI_PACKET_COMMAND Packet
;
1317 SCSI_MODE_PARAMETER_HEADER6 Header
;
1321 Size
= sizeof (SCSI_MODE_PARAMETER_HEADER6
);
1323 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1324 Packet
.ModeSenseSCSI
.opcode
= SCSI_MODE_SENSE1A
;
1325 Packet
.ModeSenseSCSI
.page_code
= 0x3F;
1326 Packet
.ModeSenseSCSI
.page_control
= 0;
1327 Packet
.ModeSenseSCSI
.allocation_length
= (UINT8
) Size
;
1328 Status
= USBFloppyPacketCommand (
1331 sizeof (MODE_SENSE_CMD_SCSI
),
1338 if (EFI_ERROR (Status
)) {
1339 return EFI_DEVICE_ERROR
;
1342 UsbFloppyDevice
->BlkIo
.Media
->ReadOnly
= Header
.write_protected
;
1349 The following functions are a set of helper functions,
1350 which are used to parse sense key returned by the device.
1355 IN REQUEST_SENSE_DATA
*SenseData
,
1356 IN UINTN SenseCounts
1359 REQUEST_SENSE_DATA
*SensePtr
;
1365 SensePtr
= SenseData
;
1367 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1369 if ((SensePtr
->sense_key
== SK_NOT_READY
) &&
1370 (SensePtr
->addnl_sense_code
== ASC_NO_MEDIA
)) {
1384 IN REQUEST_SENSE_DATA
*SenseData
,
1385 IN UINTN SenseCounts
1388 REQUEST_SENSE_DATA
*SensePtr
;
1393 SensePtr
= SenseData
;
1395 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1397 switch (SensePtr
->sense_key
) {
1400 // Medium error case
1402 case SK_MEDIUM_ERROR
:
1403 switch (SensePtr
->addnl_sense_code
) {
1405 case ASC_MEDIA_ERR1
:
1406 case ASC_MEDIA_ERR2
:
1407 case ASC_MEDIA_ERR3
:
1408 case ASC_MEDIA_ERR4
:
1419 // Medium upside-down case
1422 switch (SensePtr
->addnl_sense_code
) {
1423 case ASC_MEDIA_UPSIDE_DOWN
:
1444 IN REQUEST_SENSE_DATA
*SenseData
,
1445 IN UINTN SenseCounts
1448 REQUEST_SENSE_DATA
*SensePtr
;
1450 BOOLEAN MediaChanged
;
1452 MediaChanged
= FALSE
;
1453 SensePtr
= SenseData
;
1455 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1457 if ((SensePtr
->sense_key
== SK_UNIT_ATTENTION
) &&
1458 (SensePtr
->addnl_sense_code
== ASC_MEDIA_CHANGE
)) {
1460 MediaChanged
= TRUE
;
1466 return MediaChanged
;
1471 IN REQUEST_SENSE_DATA
*SenseData
,
1472 IN UINTN SenseCounts
,
1473 OUT BOOLEAN
*NeedRetry
1476 REQUEST_SENSE_DATA
*SensePtr
;
1482 SensePtr
= SenseData
;
1484 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1486 if ((SensePtr
->sense_key
== SK_NOT_READY
) &&
1487 (SensePtr
->addnl_sense_code
== ASC_NOT_READY
)) {
1489 switch (SensePtr
->addnl_sense_code_qualifier
) {
1491 case ASCQ_IN_PROGRESS
:
1492 case ASCQ_DEVICE_BUSY
:
1499 // Drive is in error condition,
1500 // no need to retry.
1515 IsMediaWriteProtected (
1516 IN REQUEST_SENSE_DATA
*SenseData
,
1517 IN UINTN SenseCounts
1520 REQUEST_SENSE_DATA
*SensePtr
;
1522 BOOLEAN IsWriteProtected
;
1524 IsWriteProtected
= FALSE
;
1525 SensePtr
= SenseData
;
1527 for (Index
= 0; Index
< SenseCounts
; Index
++) {
1529 // catch media write-protected condition.
1531 if ((SensePtr
->sense_key
== SK_DATA_PROTECT
) &&
1532 (SensePtr
->addnl_sense_code
== ASC_WRITE_PROTECTED
)) {
1534 IsWriteProtected
= TRUE
;
1540 return IsWriteProtected
;