2 Pei USB ATATPI command implementations.
4 Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions
8 of the BSD License which accompanies this distribution. The
9 full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "UsbBotPeim.h"
23 Sends out ATAPI Inquiry Packet Command to the specified device. This command will
24 return INQUIRY data of the device.
26 @param PeiServices The pointer of EFI_PEI_SERVICES.
27 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
29 @retval EFI_SUCCESS Inquiry command completes successfully.
30 @retval EFI_DEVICE_ERROR Inquiry command failed.
35 IN EFI_PEI_SERVICES
**PeiServices
,
36 IN PEI_BOT_DEVICE
*PeiBotDevice
39 ATAPI_PACKET_COMMAND Packet
;
41 ATAPI_INQUIRY_DATA Idata
;
44 // fill command packet
46 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
47 ZeroMem (&Idata
, sizeof (ATAPI_INQUIRY_DATA
));
49 Packet
.Inquiry
.opcode
= ATA_CMD_INQUIRY
;
50 Packet
.Inquiry
.page_code
= 0;
51 Packet
.Inquiry
.allocation_length
= 36;
54 // Send scsi INQUIRY command packet.
55 // According to SCSI Primary Commands-2 spec, host only needs to
56 // retrieve the first 36 bytes for standard INQUIRY data.
58 Status
= PeiAtapiCommand (
62 (UINT8
) sizeof (ATAPI_PACKET_COMMAND
),
69 if (EFI_ERROR (Status
)) {
70 return EFI_DEVICE_ERROR
;
73 if ((Idata
.peripheral_type
& 0x1f) == 0x05) {
74 PeiBotDevice
->DeviceType
= USBCDROM
;
75 PeiBotDevice
->Media
.BlockSize
= 0x800;
76 PeiBotDevice
->Media2
.ReadOnly
= TRUE
;
77 PeiBotDevice
->Media2
.RemovableMedia
= TRUE
;
78 PeiBotDevice
->Media2
.BlockSize
= 0x800;
80 PeiBotDevice
->DeviceType
= USBFLOPPY
;
81 PeiBotDevice
->Media
.BlockSize
= 0x200;
82 PeiBotDevice
->Media2
.ReadOnly
= FALSE
;
83 PeiBotDevice
->Media2
.RemovableMedia
= TRUE
;
84 PeiBotDevice
->Media2
.BlockSize
= 0x200;
91 Sends out ATAPI Test Unit Ready Packet Command to the specified device
92 to find out whether device is accessible.
94 @param PeiServices The pointer of EFI_PEI_SERVICES.
95 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
97 @retval EFI_SUCCESS TestUnit command executed successfully.
98 @retval EFI_DEVICE_ERROR Device cannot be executed TestUnit command successfully.
102 PeiUsbTestUnitReady (
103 IN EFI_PEI_SERVICES
**PeiServices
,
104 IN PEI_BOT_DEVICE
*PeiBotDevice
107 ATAPI_PACKET_COMMAND Packet
;
111 // fill command packet
113 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
114 Packet
.TestUnitReady
.opcode
= ATA_CMD_TEST_UNIT_READY
;
117 // send command packet
119 Status
= PeiAtapiCommand (
123 (UINT8
) sizeof (ATAPI_PACKET_COMMAND
),
130 if (EFI_ERROR (Status
)) {
131 return EFI_DEVICE_ERROR
;
138 Sends out ATAPI Request Sense Packet Command to the specified device.
140 @param PeiServices The pointer of EFI_PEI_SERVICES.
141 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
142 @param SenseCounts Length of sense buffer.
143 @param SenseKeyBuffer Pointer to sense buffer.
145 @retval EFI_SUCCESS Command executed successfully.
146 @retval EFI_DEVICE_ERROR Some device errors happen.
151 IN EFI_PEI_SERVICES
**PeiServices
,
152 IN PEI_BOT_DEVICE
*PeiBotDevice
,
153 OUT UINTN
*SenseCounts
,
154 IN UINT8
*SenseKeyBuffer
158 ATAPI_PACKET_COMMAND Packet
;
161 ATAPI_REQUEST_SENSE_DATA
*Sense
;
166 // fill command packet for Request Sense Packet Command
168 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
169 Packet
.RequestSence
.opcode
= ATA_CMD_REQUEST_SENSE
;
170 Packet
.RequestSence
.allocation_length
= (UINT8
) sizeof (ATAPI_REQUEST_SENSE_DATA
);
172 Ptr
= SenseKeyBuffer
;
177 // request sense data from device continuously
178 // until no sense data exists in the device.
181 Sense
= (ATAPI_REQUEST_SENSE_DATA
*) Ptr
;
184 // send out Request Sense Packet Command and get one Sense
187 Status
= PeiAtapiCommand (
191 (UINT8
) sizeof (ATAPI_PACKET_COMMAND
),
193 sizeof (ATAPI_REQUEST_SENSE_DATA
),
199 // failed to get Sense data
201 if (EFI_ERROR (Status
)) {
202 if (*SenseCounts
== 0) {
203 return EFI_DEVICE_ERROR
;
209 if (Sense
->sense_key
!= ATA_SK_NO_SENSE
) {
211 Ptr
+= sizeof (ATAPI_REQUEST_SENSE_DATA
);
213 // Ptr is byte based pointer
217 if (*SenseCounts
== MAXSENSEKEY
) {
223 // when no sense key, skip out the loop
233 Sends out ATAPI Read Capacity Packet Command to the specified device.
234 This command will return the information regarding the capacity of the
237 @param PeiServices The pointer of EFI_PEI_SERVICES.
238 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
240 @retval EFI_SUCCESS Command executed successfully.
241 @retval EFI_DEVICE_ERROR Some device errors happen.
246 IN EFI_PEI_SERVICES
**PeiServices
,
247 IN PEI_BOT_DEVICE
*PeiBotDevice
251 ATAPI_PACKET_COMMAND Packet
;
252 ATAPI_READ_CAPACITY_DATA Data
;
255 ZeroMem (&Data
, sizeof (ATAPI_READ_CAPACITY_DATA
));
256 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
258 Packet
.Inquiry
.opcode
= ATA_CMD_READ_CAPACITY
;
261 // send command packet
263 Status
= PeiAtapiCommand (
267 (UINT8
) sizeof (ATAPI_PACKET_COMMAND
),
269 sizeof (ATAPI_READ_CAPACITY_DATA
),
274 if (EFI_ERROR (Status
)) {
275 return EFI_DEVICE_ERROR
;
277 LastBlock
= ((UINT32
) Data
.LastLba3
<< 24) | (Data
.LastLba2
<< 16) | (Data
.LastLba1
<< 8) | Data
.LastLba0
;
279 if (LastBlock
== 0xFFFFFFFF) {
280 DEBUG ((EFI_D_INFO
, "The usb device LBA count is larger than 0xFFFFFFFF!\n"));
283 PeiBotDevice
->Media
.LastBlock
= LastBlock
;
284 PeiBotDevice
->Media
.MediaPresent
= TRUE
;
286 PeiBotDevice
->Media2
.LastBlock
= LastBlock
;
287 PeiBotDevice
->Media2
.MediaPresent
= TRUE
;
293 Sends out ATAPI Read Format Capacity Data Command to the specified device.
294 This command will return the information regarding the capacity of the
297 @param PeiServices The pointer of EFI_PEI_SERVICES.
298 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
300 @retval EFI_SUCCESS Command executed successfully.
301 @retval EFI_DEVICE_ERROR Some device errors happen.
305 PeiUsbReadFormattedCapacity (
306 IN EFI_PEI_SERVICES
**PeiServices
,
307 IN PEI_BOT_DEVICE
*PeiBotDevice
311 ATAPI_PACKET_COMMAND Packet
;
312 ATAPI_READ_FORMAT_CAPACITY_DATA FormatData
;
315 ZeroMem (&FormatData
, sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA
));
316 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
318 Packet
.ReadFormatCapacity
.opcode
= ATA_CMD_READ_FORMAT_CAPACITY
;
319 Packet
.ReadFormatCapacity
.allocation_length_lo
= 12;
322 // send command packet
324 Status
= PeiAtapiCommand (
328 (UINT8
) sizeof (ATAPI_PACKET_COMMAND
),
329 (VOID
*) &FormatData
,
330 sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA
),
335 if (EFI_ERROR (Status
)) {
336 return EFI_DEVICE_ERROR
;
339 if (FormatData
.DesCode
== 3) {
341 // Media is not present
343 PeiBotDevice
->Media
.MediaPresent
= FALSE
;
344 PeiBotDevice
->Media
.LastBlock
= 0;
345 PeiBotDevice
->Media2
.MediaPresent
= FALSE
;
346 PeiBotDevice
->Media2
.LastBlock
= 0;
349 LastBlock
= ((UINT32
) FormatData
.LastLba3
<< 24) | (FormatData
.LastLba2
<< 16) | (FormatData
.LastLba1
<< 8) | FormatData
.LastLba0
;
350 if (LastBlock
== 0xFFFFFFFF) {
351 DEBUG ((EFI_D_INFO
, "The usb device LBA count is larger than 0xFFFFFFFF!\n"));
354 PeiBotDevice
->Media
.LastBlock
= LastBlock
;
356 PeiBotDevice
->Media
.LastBlock
--;
358 PeiBotDevice
->Media
.MediaPresent
= TRUE
;
360 PeiBotDevice
->Media2
.MediaPresent
= TRUE
;
361 PeiBotDevice
->Media2
.LastBlock
= PeiBotDevice
->Media
.LastBlock
;
368 Execute Read(10) ATAPI command on a specific SCSI target.
370 Executes the ATAPI Read(10) command on the ATAPI target specified by PeiBotDevice.
372 @param PeiServices The pointer of EFI_PEI_SERVICES.
373 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
374 @param Buffer The pointer to data buffer.
375 @param Lba The start logic block address of reading.
376 @param NumberOfBlocks The block number of reading.
378 @retval EFI_SUCCESS Command executed successfully.
379 @retval EFI_DEVICE_ERROR Some device errors happen.
384 IN EFI_PEI_SERVICES
**PeiServices
,
385 IN PEI_BOT_DEVICE
*PeiBotDevice
,
388 IN UINTN NumberOfBlocks
391 ATAPI_PACKET_COMMAND Packet
;
392 ATAPI_READ10_CMD
*Read10Packet
;
394 UINT16 BlocksRemaining
;
404 // prepare command packet for the Inquiry Packet Command.
406 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
407 Read10Packet
= &Packet
.Read10
;
408 Lba32
= (UINT32
) Lba
;
411 BlockSize
= (UINT32
) PeiBotDevice
->Media
.BlockSize
;
413 MaxBlock
= (UINT16
) (65535 / BlockSize
);
414 BlocksRemaining
= (UINT16
) NumberOfBlocks
;
416 Status
= EFI_SUCCESS
;
417 while (BlocksRemaining
> 0) {
419 if (BlocksRemaining
<= MaxBlock
) {
421 SectorCount
= BlocksRemaining
;
425 SectorCount
= MaxBlock
;
428 // fill the Packet data structure
430 Read10Packet
->opcode
= ATA_CMD_READ_10
;
433 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
434 // Lba0 is MSB, Lba3 is LSB
436 Read10Packet
->Lba3
= (UINT8
) (Lba32
& 0xff);
437 Read10Packet
->Lba2
= (UINT8
) (Lba32
>> 8);
438 Read10Packet
->Lba1
= (UINT8
) (Lba32
>> 16);
439 Read10Packet
->Lba0
= (UINT8
) (Lba32
>> 24);
442 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
443 // TranLen0 is MSB, TranLen is LSB
445 Read10Packet
->TranLen1
= (UINT8
) (SectorCount
& 0xff);
446 Read10Packet
->TranLen0
= (UINT8
) (SectorCount
>> 8);
448 ByteCount
= SectorCount
* BlockSize
;
450 TimeOut
= (UINT16
) (SectorCount
* 2000);
453 // send command packet
455 Status
= PeiAtapiCommand (
459 (UINT8
) sizeof (ATAPI_PACKET_COMMAND
),
466 if (Status
!= EFI_SUCCESS
) {
470 Lba32
+= SectorCount
;
471 PtrBuffer
= (UINT8
*) PtrBuffer
+ SectorCount
* BlockSize
;
472 BlocksRemaining
= (UINT16
) (BlocksRemaining
- SectorCount
);
479 Check if there is media according to sense data.
481 @param SenseData Pointer to sense data.
482 @param SenseCounts Count of sense data.
484 @retval TRUE No media
485 @retval FALSE Media exists
490 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
494 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
499 SensePtr
= SenseData
;
501 for (Index
= 0; Index
< SenseCounts
; Index
++) {
503 switch (SensePtr
->sense_key
) {
505 case ATA_SK_NOT_READY
:
506 switch (SensePtr
->addnl_sense_code
) {
508 // if no media, fill IdeDev parameter with specific info.
510 case ATA_ASC_NO_MEDIA
:
530 Check if there is media error according to sense data.
532 @param SenseData Pointer to sense data.
533 @param SenseCounts Count of sense data.
535 @retval TRUE Media error
536 @retval FALSE No media error
541 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
545 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
549 SensePtr
= SenseData
;
552 for (Index
= 0; Index
< SenseCounts
; Index
++) {
554 switch (SensePtr
->sense_key
) {
558 case ATA_SK_MEDIUM_ERROR
:
559 switch (SensePtr
->addnl_sense_code
) {
560 case ATA_ASC_MEDIA_ERR1
:
564 case ATA_ASC_MEDIA_ERR2
:
568 case ATA_ASC_MEDIA_ERR3
:
572 case ATA_ASC_MEDIA_ERR4
:
583 // Medium upside-down case
585 case ATA_SK_NOT_READY
:
586 switch (SensePtr
->addnl_sense_code
) {
587 case ATA_ASC_MEDIA_UPSIDE_DOWN
:
607 Check if media is changed according to sense data.
609 @param SenseData Pointer to sense data.
610 @param SenseCounts Count of sense data.
612 @retval TRUE There is media change event.
613 @retval FALSE media is NOT changed.
618 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
622 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
628 SensePtr
= SenseData
;
630 for (Index
= 0; Index
< SenseCounts
; Index
++) {
632 // catch media change sense key and addition sense data
634 switch (SensePtr
->sense_key
) {
635 case ATA_SK_UNIT_ATTENTION
:
636 switch (SensePtr
->addnl_sense_code
) {
637 case ATA_ASC_MEDIA_CHANGE
: