2 Pei USB ATATPI 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
) {
204 Ptr
+= sizeof (ATAPI_REQUEST_SENSE_DATA
);
206 // Ptr is byte based pointer
210 if (*SenseCounts
== MAXSENSEKEY
) {
216 // when no sense key, skip out the loop
226 Sends out ATAPI Read Capacity Packet Command to the specified device.
227 This command will return the information regarding the capacity of the
230 @param PeiServices The pointer of EFI_PEI_SERVICES.
231 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
233 @retval EFI_SUCCESS Command executed successfully.
234 @retval EFI_DEVICE_ERROR Some device errors happen.
239 IN EFI_PEI_SERVICES
**PeiServices
,
240 IN PEI_BOT_DEVICE
*PeiBotDevice
244 ATAPI_PACKET_COMMAND Packet
;
245 ATAPI_READ_CAPACITY_DATA Data
;
248 ZeroMem (&Data
, sizeof (ATAPI_READ_CAPACITY_DATA
));
249 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
251 Packet
.Inquiry
.opcode
= ATA_CMD_READ_CAPACITY
;
254 // send command packet
256 Status
= PeiAtapiCommand (
260 (UINT8
) sizeof (ATAPI_PACKET_COMMAND
),
262 sizeof (ATAPI_READ_CAPACITY_DATA
),
267 if (EFI_ERROR (Status
)) {
268 return EFI_DEVICE_ERROR
;
270 LastBlock
= ((UINT32
) Data
.LastLba3
<< 24) | (Data
.LastLba2
<< 16) | (Data
.LastLba1
<< 8) | Data
.LastLba0
;
272 if (LastBlock
== 0xFFFFFFFF) {
273 DEBUG ((EFI_D_INFO
, "The usb device LBA count is larger than 0xFFFFFFFF!\n"));
276 PeiBotDevice
->Media
.LastBlock
= LastBlock
;
277 PeiBotDevice
->Media
.MediaPresent
= TRUE
;
279 PeiBotDevice
->Media2
.LastBlock
= LastBlock
;
280 PeiBotDevice
->Media2
.MediaPresent
= TRUE
;
286 Sends out ATAPI Read Format Capacity Data Command to the specified device.
287 This command will return the information regarding the capacity of the
290 @param PeiServices The pointer of EFI_PEI_SERVICES.
291 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
293 @retval EFI_SUCCESS Command executed successfully.
294 @retval EFI_DEVICE_ERROR Some device errors happen.
298 PeiUsbReadFormattedCapacity (
299 IN EFI_PEI_SERVICES
**PeiServices
,
300 IN PEI_BOT_DEVICE
*PeiBotDevice
304 ATAPI_PACKET_COMMAND Packet
;
305 ATAPI_READ_FORMAT_CAPACITY_DATA FormatData
;
308 ZeroMem (&FormatData
, sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA
));
309 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
311 Packet
.ReadFormatCapacity
.opcode
= ATA_CMD_READ_FORMAT_CAPACITY
;
312 Packet
.ReadFormatCapacity
.allocation_length_lo
= 12;
315 // send command packet
317 Status
= PeiAtapiCommand (
321 (UINT8
) sizeof (ATAPI_PACKET_COMMAND
),
322 (VOID
*) &FormatData
,
323 sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA
),
328 if (EFI_ERROR (Status
)) {
329 return EFI_DEVICE_ERROR
;
332 if (FormatData
.DesCode
== 3) {
334 // Media is not present
336 PeiBotDevice
->Media
.MediaPresent
= FALSE
;
337 PeiBotDevice
->Media
.LastBlock
= 0;
338 PeiBotDevice
->Media2
.MediaPresent
= FALSE
;
339 PeiBotDevice
->Media2
.LastBlock
= 0;
342 LastBlock
= ((UINT32
) FormatData
.LastLba3
<< 24) | (FormatData
.LastLba2
<< 16) | (FormatData
.LastLba1
<< 8) | FormatData
.LastLba0
;
343 if (LastBlock
== 0xFFFFFFFF) {
344 DEBUG ((EFI_D_INFO
, "The usb device LBA count is larger than 0xFFFFFFFF!\n"));
347 PeiBotDevice
->Media
.LastBlock
= LastBlock
;
349 PeiBotDevice
->Media
.LastBlock
--;
351 PeiBotDevice
->Media
.MediaPresent
= TRUE
;
353 PeiBotDevice
->Media2
.MediaPresent
= TRUE
;
354 PeiBotDevice
->Media2
.LastBlock
= PeiBotDevice
->Media
.LastBlock
;
361 Execute Read(10) ATAPI command on a specific SCSI target.
363 Executes the ATAPI Read(10) command on the ATAPI target specified by PeiBotDevice.
365 @param PeiServices The pointer of EFI_PEI_SERVICES.
366 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
367 @param Buffer The pointer to data buffer.
368 @param Lba The start logic block address of reading.
369 @param NumberOfBlocks The block number of reading.
371 @retval EFI_SUCCESS Command executed successfully.
372 @retval EFI_DEVICE_ERROR Some device errors happen.
377 IN EFI_PEI_SERVICES
**PeiServices
,
378 IN PEI_BOT_DEVICE
*PeiBotDevice
,
381 IN UINTN NumberOfBlocks
384 ATAPI_PACKET_COMMAND Packet
;
385 ATAPI_READ10_CMD
*Read10Packet
;
387 UINT16 BlocksRemaining
;
397 // prepare command packet for the Inquiry Packet Command.
399 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
400 Read10Packet
= &Packet
.Read10
;
401 Lba32
= (UINT32
) Lba
;
404 BlockSize
= (UINT32
) PeiBotDevice
->Media
.BlockSize
;
406 MaxBlock
= (UINT16
) (65535 / BlockSize
);
407 BlocksRemaining
= (UINT16
) NumberOfBlocks
;
409 Status
= EFI_SUCCESS
;
410 while (BlocksRemaining
> 0) {
412 if (BlocksRemaining
<= MaxBlock
) {
414 SectorCount
= BlocksRemaining
;
418 SectorCount
= MaxBlock
;
421 // fill the Packet data structure
423 Read10Packet
->opcode
= ATA_CMD_READ_10
;
426 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
427 // Lba0 is MSB, Lba3 is LSB
429 Read10Packet
->Lba3
= (UINT8
) (Lba32
& 0xff);
430 Read10Packet
->Lba2
= (UINT8
) (Lba32
>> 8);
431 Read10Packet
->Lba1
= (UINT8
) (Lba32
>> 16);
432 Read10Packet
->Lba0
= (UINT8
) (Lba32
>> 24);
435 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
436 // TranLen0 is MSB, TranLen is LSB
438 Read10Packet
->TranLen1
= (UINT8
) (SectorCount
& 0xff);
439 Read10Packet
->TranLen0
= (UINT8
) (SectorCount
>> 8);
441 ByteCount
= SectorCount
* BlockSize
;
443 TimeOut
= (UINT16
) (SectorCount
* 2000);
446 // send command packet
448 Status
= PeiAtapiCommand (
452 (UINT8
) sizeof (ATAPI_PACKET_COMMAND
),
459 if (Status
!= EFI_SUCCESS
) {
463 Lba32
+= SectorCount
;
464 PtrBuffer
= (UINT8
*) PtrBuffer
+ SectorCount
* BlockSize
;
465 BlocksRemaining
= (UINT16
) (BlocksRemaining
- SectorCount
);
472 Check if there is media according to sense data.
474 @param SenseData Pointer to sense data.
475 @param SenseCounts Count of sense data.
477 @retval TRUE No media
478 @retval FALSE Media exists
483 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
487 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
492 SensePtr
= SenseData
;
494 for (Index
= 0; Index
< SenseCounts
; Index
++) {
496 switch (SensePtr
->sense_key
) {
498 case ATA_SK_NOT_READY
:
499 switch (SensePtr
->addnl_sense_code
) {
501 // if no media, fill IdeDev parameter with specific info.
503 case ATA_ASC_NO_MEDIA
:
523 Check if there is media error according to sense data.
525 @param SenseData Pointer to sense data.
526 @param SenseCounts Count of sense data.
528 @retval TRUE Media error
529 @retval FALSE No media error
534 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
538 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
542 SensePtr
= SenseData
;
545 for (Index
= 0; Index
< SenseCounts
; Index
++) {
547 switch (SensePtr
->sense_key
) {
551 case ATA_SK_MEDIUM_ERROR
:
552 switch (SensePtr
->addnl_sense_code
) {
553 case ATA_ASC_MEDIA_ERR1
:
557 case ATA_ASC_MEDIA_ERR2
:
561 case ATA_ASC_MEDIA_ERR3
:
565 case ATA_ASC_MEDIA_ERR4
:
576 // Medium upside-down case
578 case ATA_SK_NOT_READY
:
579 switch (SensePtr
->addnl_sense_code
) {
580 case ATA_ASC_MEDIA_UPSIDE_DOWN
:
600 Check if media is changed according to sense data.
602 @param SenseData Pointer to sense data.
603 @param SenseCounts Count of sense data.
605 @retval TRUE There is media change event.
606 @retval FALSE media is NOT changed.
611 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
615 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
621 SensePtr
= SenseData
;
623 for (Index
= 0; Index
< SenseCounts
; Index
++) {
625 // catch media change sense key and addition sense data
627 switch (SensePtr
->sense_key
) {
628 case ATA_SK_UNIT_ATTENTION
:
629 switch (SensePtr
->addnl_sense_code
) {
630 case ATA_ASC_MEDIA_CHANGE
: