2 Pei USB ATAPI command implementations.
4 Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "UsbBotPeim.h"
16 Sends out ATAPI Inquiry Packet Command to the specified device. This command will
17 return INQUIRY data of the device.
19 @param PeiServices The pointer of EFI_PEI_SERVICES.
20 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
22 @retval EFI_SUCCESS Inquiry command completes successfully.
23 @retval EFI_DEVICE_ERROR Inquiry command failed.
28 IN EFI_PEI_SERVICES
**PeiServices
,
29 IN PEI_BOT_DEVICE
*PeiBotDevice
32 ATAPI_PACKET_COMMAND Packet
;
34 ATAPI_INQUIRY_DATA Idata
;
37 // fill command packet
39 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
40 ZeroMem (&Idata
, sizeof (ATAPI_INQUIRY_DATA
));
42 Packet
.Inquiry
.opcode
= ATA_CMD_INQUIRY
;
43 Packet
.Inquiry
.page_code
= 0;
44 Packet
.Inquiry
.allocation_length
= 36;
47 // Send scsi INQUIRY command packet.
48 // According to SCSI Primary Commands-2 spec, host only needs to
49 // retrieve the first 36 bytes for standard INQUIRY data.
51 Status
= PeiAtapiCommand (
55 (UINT8
)sizeof (ATAPI_PACKET_COMMAND
),
62 if (EFI_ERROR (Status
)) {
63 return EFI_DEVICE_ERROR
;
66 if ((Idata
.peripheral_type
& 0x1f) == 0x05) {
67 PeiBotDevice
->DeviceType
= USBCDROM
;
68 PeiBotDevice
->Media
.BlockSize
= 0x800;
69 PeiBotDevice
->Media2
.ReadOnly
= TRUE
;
70 PeiBotDevice
->Media2
.RemovableMedia
= TRUE
;
71 PeiBotDevice
->Media2
.BlockSize
= 0x800;
73 PeiBotDevice
->DeviceType
= USBFLOPPY
;
74 PeiBotDevice
->Media
.BlockSize
= 0x200;
75 PeiBotDevice
->Media2
.ReadOnly
= FALSE
;
76 PeiBotDevice
->Media2
.RemovableMedia
= TRUE
;
77 PeiBotDevice
->Media2
.BlockSize
= 0x200;
84 Sends out ATAPI Test Unit Ready Packet Command to the specified device
85 to find out whether device is accessible.
87 @param PeiServices The pointer of EFI_PEI_SERVICES.
88 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
90 @retval EFI_SUCCESS TestUnit command executed successfully.
91 @retval EFI_DEVICE_ERROR Device cannot be executed TestUnit command successfully.
96 IN EFI_PEI_SERVICES
**PeiServices
,
97 IN PEI_BOT_DEVICE
*PeiBotDevice
100 ATAPI_PACKET_COMMAND Packet
;
104 // fill command packet
106 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
107 Packet
.TestUnitReady
.opcode
= ATA_CMD_TEST_UNIT_READY
;
110 // send command packet
112 Status
= PeiAtapiCommand (
116 (UINT8
)sizeof (ATAPI_PACKET_COMMAND
),
123 if (EFI_ERROR (Status
)) {
124 return EFI_DEVICE_ERROR
;
131 Sends out ATAPI Request Sense Packet Command to the specified device.
133 @param PeiServices The pointer of EFI_PEI_SERVICES.
134 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
135 @param SenseCounts Length of sense buffer.
136 @param SenseKeyBuffer Pointer to sense buffer.
138 @retval EFI_SUCCESS Command executed successfully.
139 @retval EFI_DEVICE_ERROR Some device errors happen.
144 IN EFI_PEI_SERVICES
**PeiServices
,
145 IN PEI_BOT_DEVICE
*PeiBotDevice
,
146 OUT UINTN
*SenseCounts
,
147 IN UINT8
*SenseKeyBuffer
151 ATAPI_PACKET_COMMAND Packet
;
154 ATAPI_REQUEST_SENSE_DATA
*Sense
;
159 // fill command packet for Request Sense Packet Command
161 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
162 Packet
.RequestSence
.opcode
= ATA_CMD_REQUEST_SENSE
;
163 Packet
.RequestSence
.allocation_length
= (UINT8
)sizeof (ATAPI_REQUEST_SENSE_DATA
);
165 Ptr
= SenseKeyBuffer
;
170 // request sense data from device continuously
171 // until no sense data exists in the device.
174 Sense
= (ATAPI_REQUEST_SENSE_DATA
*)Ptr
;
177 // send out Request Sense Packet Command and get one Sense
180 Status
= PeiAtapiCommand (
184 (UINT8
)sizeof (ATAPI_PACKET_COMMAND
),
186 sizeof (ATAPI_REQUEST_SENSE_DATA
),
192 // failed to get Sense data
194 if (EFI_ERROR (Status
)) {
195 if (*SenseCounts
== 0) {
196 return EFI_DEVICE_ERROR
;
202 if (Sense
->sense_key
!= ATA_SK_NO_SENSE
) {
203 Ptr
+= sizeof (ATAPI_REQUEST_SENSE_DATA
);
205 // Ptr is byte based pointer
209 if (*SenseCounts
== MAXSENSEKEY
) {
214 // when no sense key, skip out the loop
224 Sends out ATAPI Read Capacity Packet Command to the specified device.
225 This command will return the information regarding the capacity of the
228 @param PeiServices The pointer of EFI_PEI_SERVICES.
229 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
231 @retval EFI_SUCCESS Command executed successfully.
232 @retval EFI_DEVICE_ERROR Some device errors happen.
237 IN EFI_PEI_SERVICES
**PeiServices
,
238 IN PEI_BOT_DEVICE
*PeiBotDevice
242 ATAPI_PACKET_COMMAND Packet
;
243 ATAPI_READ_CAPACITY_DATA Data
;
246 ZeroMem (&Data
, sizeof (ATAPI_READ_CAPACITY_DATA
));
247 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
249 Packet
.Inquiry
.opcode
= ATA_CMD_READ_CAPACITY
;
252 // send command packet
254 Status
= PeiAtapiCommand (
258 (UINT8
)sizeof (ATAPI_PACKET_COMMAND
),
260 sizeof (ATAPI_READ_CAPACITY_DATA
),
265 if (EFI_ERROR (Status
)) {
266 return EFI_DEVICE_ERROR
;
269 LastBlock
= ((UINT32
)Data
.LastLba3
<< 24) | (Data
.LastLba2
<< 16) | (Data
.LastLba1
<< 8) | Data
.LastLba0
;
271 if (LastBlock
== 0xFFFFFFFF) {
272 DEBUG ((DEBUG_INFO
, "The usb device LBA count is larger than 0xFFFFFFFF!\n"));
275 PeiBotDevice
->Media
.LastBlock
= LastBlock
;
276 PeiBotDevice
->Media
.MediaPresent
= TRUE
;
278 PeiBotDevice
->Media2
.LastBlock
= LastBlock
;
279 PeiBotDevice
->Media2
.MediaPresent
= TRUE
;
285 Sends out ATAPI Read Format Capacity Data Command to the specified device.
286 This command will return the information regarding the capacity of the
289 @param PeiServices The pointer of EFI_PEI_SERVICES.
290 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
292 @retval EFI_SUCCESS Command executed successfully.
293 @retval EFI_DEVICE_ERROR Some device errors happen.
297 PeiUsbReadFormattedCapacity (
298 IN EFI_PEI_SERVICES
**PeiServices
,
299 IN PEI_BOT_DEVICE
*PeiBotDevice
303 ATAPI_PACKET_COMMAND Packet
;
304 ATAPI_READ_FORMAT_CAPACITY_DATA FormatData
;
307 ZeroMem (&FormatData
, sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA
));
308 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
310 Packet
.ReadFormatCapacity
.opcode
= ATA_CMD_READ_FORMAT_CAPACITY
;
311 Packet
.ReadFormatCapacity
.allocation_length_lo
= 12;
314 // send command packet
316 Status
= PeiAtapiCommand (
320 (UINT8
)sizeof (ATAPI_PACKET_COMMAND
),
322 sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA
),
327 if (EFI_ERROR (Status
)) {
328 return EFI_DEVICE_ERROR
;
331 if (FormatData
.DesCode
== 3) {
333 // Media is not present
335 PeiBotDevice
->Media
.MediaPresent
= FALSE
;
336 PeiBotDevice
->Media
.LastBlock
= 0;
337 PeiBotDevice
->Media2
.MediaPresent
= FALSE
;
338 PeiBotDevice
->Media2
.LastBlock
= 0;
340 LastBlock
= ((UINT32
)FormatData
.LastLba3
<< 24) | (FormatData
.LastLba2
<< 16) | (FormatData
.LastLba1
<< 8) | FormatData
.LastLba0
;
341 if (LastBlock
== 0xFFFFFFFF) {
342 DEBUG ((DEBUG_INFO
, "The usb device LBA count is larger than 0xFFFFFFFF!\n"));
345 PeiBotDevice
->Media
.LastBlock
= LastBlock
;
347 PeiBotDevice
->Media
.LastBlock
--;
349 PeiBotDevice
->Media
.MediaPresent
= TRUE
;
351 PeiBotDevice
->Media2
.MediaPresent
= TRUE
;
352 PeiBotDevice
->Media2
.LastBlock
= PeiBotDevice
->Media
.LastBlock
;
359 Execute Read(10) ATAPI command on a specific SCSI target.
361 Executes the ATAPI Read(10) command on the ATAPI target specified by PeiBotDevice.
363 @param PeiServices The pointer of EFI_PEI_SERVICES.
364 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
365 @param Buffer The pointer to data buffer.
366 @param Lba The start logic block address of reading.
367 @param NumberOfBlocks The block number of reading.
369 @retval EFI_SUCCESS Command executed successfully.
370 @retval EFI_DEVICE_ERROR Some device errors happen.
375 IN EFI_PEI_SERVICES
**PeiServices
,
376 IN PEI_BOT_DEVICE
*PeiBotDevice
,
379 IN UINTN NumberOfBlocks
382 ATAPI_PACKET_COMMAND Packet
;
383 ATAPI_READ10_CMD
*Read10Packet
;
385 UINT16 BlocksRemaining
;
395 // prepare command packet for the Inquiry Packet Command.
397 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
398 Read10Packet
= &Packet
.Read10
;
402 BlockSize
= (UINT32
)PeiBotDevice
->Media
.BlockSize
;
404 MaxBlock
= (UINT16
)(65535 / BlockSize
);
405 BlocksRemaining
= (UINT16
)NumberOfBlocks
;
407 Status
= EFI_SUCCESS
;
408 while (BlocksRemaining
> 0) {
409 if (BlocksRemaining
<= MaxBlock
) {
410 SectorCount
= BlocksRemaining
;
412 SectorCount
= MaxBlock
;
416 // fill the Packet data structure
418 Read10Packet
->opcode
= ATA_CMD_READ_10
;
421 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
422 // Lba0 is MSB, Lba3 is LSB
424 Read10Packet
->Lba3
= (UINT8
)(Lba32
& 0xff);
425 Read10Packet
->Lba2
= (UINT8
)(Lba32
>> 8);
426 Read10Packet
->Lba1
= (UINT8
)(Lba32
>> 16);
427 Read10Packet
->Lba0
= (UINT8
)(Lba32
>> 24);
430 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
431 // TranLen0 is MSB, TranLen is LSB
433 Read10Packet
->TranLen1
= (UINT8
)(SectorCount
& 0xff);
434 Read10Packet
->TranLen0
= (UINT8
)(SectorCount
>> 8);
436 ByteCount
= SectorCount
* BlockSize
;
438 TimeOut
= (UINT16
)(SectorCount
* 2000);
441 // send command packet
443 Status
= PeiAtapiCommand (
447 (UINT8
)sizeof (ATAPI_PACKET_COMMAND
),
454 if (Status
!= EFI_SUCCESS
) {
458 Lba32
+= SectorCount
;
459 PtrBuffer
= (UINT8
*)PtrBuffer
+ SectorCount
* BlockSize
;
460 BlocksRemaining
= (UINT16
)(BlocksRemaining
- SectorCount
);
467 Check if there is media according to sense data.
469 @param SenseData Pointer to sense data.
470 @param SenseCounts Count of sense data.
472 @retval TRUE No media
473 @retval FALSE Media exists
478 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
482 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
487 SensePtr
= SenseData
;
489 for (Index
= 0; Index
< SenseCounts
; Index
++) {
490 switch (SensePtr
->sense_key
) {
491 case ATA_SK_NOT_READY
:
492 switch (SensePtr
->addnl_sense_code
) {
494 // if no media, fill IdeDev parameter with specific info.
496 case ATA_ASC_NO_MEDIA
:
517 Check if there is media error according to sense data.
519 @param SenseData Pointer to sense data.
520 @param SenseCounts Count of sense data.
522 @retval TRUE Media error
523 @retval FALSE No media error
528 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
532 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
536 SensePtr
= SenseData
;
539 for (Index
= 0; Index
< SenseCounts
; Index
++) {
540 switch (SensePtr
->sense_key
) {
544 case ATA_SK_MEDIUM_ERROR
:
545 switch (SensePtr
->addnl_sense_code
) {
546 case ATA_ASC_MEDIA_ERR1
:
550 case ATA_ASC_MEDIA_ERR2
:
554 case ATA_ASC_MEDIA_ERR3
:
558 case ATA_ASC_MEDIA_ERR4
:
569 // Medium upside-down case
571 case ATA_SK_NOT_READY
:
572 switch (SensePtr
->addnl_sense_code
) {
573 case ATA_ASC_MEDIA_UPSIDE_DOWN
:
594 Check if media is changed according to sense data.
596 @param SenseData Pointer to sense data.
597 @param SenseCounts Count of sense data.
599 @retval TRUE There is media change event.
600 @retval FALSE media is NOT changed.
605 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
609 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
615 SensePtr
= SenseData
;
617 for (Index
= 0; Index
< SenseCounts
; Index
++) {
619 // catch media change sense key and addition sense data
621 switch (SensePtr
->sense_key
) {
622 case ATA_SK_UNIT_ATTENTION
:
623 switch (SensePtr
->addnl_sense_code
) {
624 case ATA_ASC_MEDIA_CHANGE
: