2 Pei USB ATATPI command implementations.
4 Copyright (c) 1999 - 2010, 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;
77 PeiBotDevice
->DeviceType
= USBFLOPPY
;
78 PeiBotDevice
->Media
.BlockSize
= 0x200;
85 Sends out ATAPI Test Unit Ready Packet Command to the specified device
86 to find out whether device is accessible.
88 @param PeiServices The pointer of EFI_PEI_SERVICES.
89 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
91 @retval EFI_SUCCESS TestUnit command executed successfully.
92 @retval EFI_DEVICE_ERROR Device cannot be executed TestUnit command successfully.
97 IN EFI_PEI_SERVICES
**PeiServices
,
98 IN PEI_BOT_DEVICE
*PeiBotDevice
101 ATAPI_PACKET_COMMAND Packet
;
105 // fill command packet
107 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
108 Packet
.TestUnitReady
.opcode
= ATA_CMD_TEST_UNIT_READY
;
111 // send command packet
113 Status
= PeiAtapiCommand (
117 (UINT8
) sizeof (ATAPI_PACKET_COMMAND
),
124 if (EFI_ERROR (Status
)) {
125 return EFI_DEVICE_ERROR
;
132 Sends out ATAPI Request Sense Packet Command to the specified device.
134 @param PeiServices The pointer of EFI_PEI_SERVICES.
135 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
136 @param SenseCounts Length of sense buffer.
137 @param SenseKeyBuffer Pointer to sense buffer.
139 @retval EFI_SUCCESS Command executed successfully.
140 @retval EFI_DEVICE_ERROR Some device errors happen.
145 IN EFI_PEI_SERVICES
**PeiServices
,
146 IN PEI_BOT_DEVICE
*PeiBotDevice
,
147 OUT UINTN
*SenseCounts
,
148 IN UINT8
*SenseKeyBuffer
152 ATAPI_PACKET_COMMAND Packet
;
155 ATAPI_REQUEST_SENSE_DATA
*Sense
;
160 // fill command packet for Request Sense Packet Command
162 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
163 Packet
.RequestSence
.opcode
= ATA_CMD_REQUEST_SENSE
;
164 Packet
.RequestSence
.allocation_length
= (UINT8
) sizeof (ATAPI_REQUEST_SENSE_DATA
);
166 Ptr
= SenseKeyBuffer
;
171 // request sense data from device continuously
172 // until no sense data exists in the device.
175 Sense
= (ATAPI_REQUEST_SENSE_DATA
*) Ptr
;
178 // send out Request Sense Packet Command and get one Sense
181 Status
= PeiAtapiCommand (
185 (UINT8
) sizeof (ATAPI_PACKET_COMMAND
),
187 sizeof (ATAPI_REQUEST_SENSE_DATA
),
193 // failed to get Sense data
195 if (EFI_ERROR (Status
)) {
196 if (*SenseCounts
== 0) {
197 return EFI_DEVICE_ERROR
;
203 if (Sense
->sense_key
!= ATA_SK_NO_SENSE
) {
205 Ptr
+= sizeof (ATAPI_REQUEST_SENSE_DATA
);
207 // Ptr is byte based pointer
211 if (*SenseCounts
== MAXSENSEKEY
) {
217 // when no sense key, skip out the loop
227 Sends out ATAPI Read Capacity Packet Command to the specified device.
228 This command will return the information regarding the capacity of the
231 @param PeiServices The pointer of EFI_PEI_SERVICES.
232 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
234 @retval EFI_SUCCESS Command executed successfully.
235 @retval EFI_DEVICE_ERROR Some device errors happen.
240 IN EFI_PEI_SERVICES
**PeiServices
,
241 IN PEI_BOT_DEVICE
*PeiBotDevice
245 ATAPI_PACKET_COMMAND Packet
;
246 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
;
271 PeiBotDevice
->Media
.LastBlock
= (Data
.LastLba3
<< 24) | (Data
.LastLba2
<< 16) | (Data
.LastLba1
<< 8) | Data
.LastLba0
;
273 PeiBotDevice
->Media
.MediaPresent
= TRUE
;
279 Sends out ATAPI Read Format Capacity Data Command to the specified device.
280 This command will return the information regarding the capacity of the
283 @param PeiServices The pointer of EFI_PEI_SERVICES.
284 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
286 @retval EFI_SUCCESS Command executed successfully.
287 @retval EFI_DEVICE_ERROR Some device errors happen.
291 PeiUsbReadFormattedCapacity (
292 IN EFI_PEI_SERVICES
**PeiServices
,
293 IN PEI_BOT_DEVICE
*PeiBotDevice
297 ATAPI_PACKET_COMMAND Packet
;
298 ATAPI_READ_FORMAT_CAPACITY_DATA FormatData
;
300 ZeroMem (&FormatData
, sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA
));
301 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
303 Packet
.ReadFormatCapacity
.opcode
= ATA_CMD_READ_FORMAT_CAPACITY
;
304 Packet
.ReadFormatCapacity
.allocation_length_lo
= 12;
307 // send command packet
309 Status
= PeiAtapiCommand (
313 (UINT8
) sizeof (ATAPI_PACKET_COMMAND
),
314 (VOID
*) &FormatData
,
315 sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA
),
320 if (EFI_ERROR (Status
)) {
321 return EFI_DEVICE_ERROR
;
324 if (FormatData
.DesCode
== 3) {
326 // Media is not present
328 PeiBotDevice
->Media
.MediaPresent
= FALSE
;
329 PeiBotDevice
->Media
.LastBlock
= 0;
333 PeiBotDevice
->Media
.LastBlock
= (FormatData
.LastLba3
<< 24) | (FormatData
.LastLba2
<< 16) | (FormatData
.LastLba1
<< 8) | FormatData
.LastLba0
;
335 PeiBotDevice
->Media
.LastBlock
--;
337 PeiBotDevice
->Media
.MediaPresent
= TRUE
;
344 Execute Read(10) ATAPI command on a specific SCSI target.
346 Executes the ATAPI Read(10) command on the ATAPI target specified by PeiBotDevice.
348 @param PeiServices The pointer of EFI_PEI_SERVICES.
349 @param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
350 @param Buffer The pointer to data buffer.
351 @param Lba The start logic block address of reading.
352 @param NumberOfBlocks The block number of reading.
354 @retval EFI_SUCCESS Command executed successfully.
355 @retval EFI_DEVICE_ERROR Some device errors happen.
360 IN EFI_PEI_SERVICES
**PeiServices
,
361 IN PEI_BOT_DEVICE
*PeiBotDevice
,
364 IN UINTN NumberOfBlocks
367 ATAPI_PACKET_COMMAND Packet
;
368 ATAPI_READ10_CMD
*Read10Packet
;
370 UINT16 BlocksRemaining
;
380 // prepare command packet for the Inquiry Packet Command.
382 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
383 Read10Packet
= &Packet
.Read10
;
384 Lba32
= (UINT32
) Lba
;
387 BlockSize
= (UINT32
) PeiBotDevice
->Media
.BlockSize
;
389 MaxBlock
= (UINT16
) (65535 / BlockSize
);
390 BlocksRemaining
= (UINT16
) NumberOfBlocks
;
392 Status
= EFI_SUCCESS
;
393 while (BlocksRemaining
> 0) {
395 if (BlocksRemaining
<= MaxBlock
) {
397 SectorCount
= BlocksRemaining
;
401 SectorCount
= MaxBlock
;
404 // fill the Packet data structure
406 Read10Packet
->opcode
= ATA_CMD_READ_10
;
409 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
410 // Lba0 is MSB, Lba3 is LSB
412 Read10Packet
->Lba3
= (UINT8
) (Lba32
& 0xff);
413 Read10Packet
->Lba2
= (UINT8
) (Lba32
>> 8);
414 Read10Packet
->Lba1
= (UINT8
) (Lba32
>> 16);
415 Read10Packet
->Lba0
= (UINT8
) (Lba32
>> 24);
418 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
419 // TranLen0 is MSB, TranLen is LSB
421 Read10Packet
->TranLen1
= (UINT8
) (SectorCount
& 0xff);
422 Read10Packet
->TranLen0
= (UINT8
) (SectorCount
>> 8);
424 ByteCount
= SectorCount
* BlockSize
;
426 TimeOut
= (UINT16
) (SectorCount
* 2000);
429 // send command packet
431 Status
= PeiAtapiCommand (
435 (UINT8
) sizeof (ATAPI_PACKET_COMMAND
),
442 if (Status
!= EFI_SUCCESS
) {
446 Lba32
+= SectorCount
;
447 PtrBuffer
= (UINT8
*) PtrBuffer
+ SectorCount
* BlockSize
;
448 BlocksRemaining
= (UINT16
) (BlocksRemaining
- SectorCount
);
455 Check if there is media according to sense data.
457 @param SenseData Pointer to sense data.
458 @param SenseCounts Count of sense data.
460 @retval TRUE No media
461 @retval FALSE Media exists
466 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
470 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
475 SensePtr
= SenseData
;
477 for (Index
= 0; Index
< SenseCounts
; Index
++) {
479 switch (SensePtr
->sense_key
) {
481 case ATA_SK_NOT_READY
:
482 switch (SensePtr
->addnl_sense_code
) {
484 // if no media, fill IdeDev parameter with specific info.
486 case ATA_ASC_NO_MEDIA
:
506 Check if there is media error according to sense data.
508 @param SenseData Pointer to sense data.
509 @param SenseCounts Count of sense data.
511 @retval TRUE Media error
512 @retval FALSE No media error
517 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
521 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
525 SensePtr
= SenseData
;
528 for (Index
= 0; Index
< SenseCounts
; Index
++) {
530 switch (SensePtr
->sense_key
) {
534 case ATA_SK_MEDIUM_ERROR
:
535 switch (SensePtr
->addnl_sense_code
) {
536 case ATA_ASC_MEDIA_ERR1
:
540 case ATA_ASC_MEDIA_ERR2
:
544 case ATA_ASC_MEDIA_ERR3
:
548 case ATA_ASC_MEDIA_ERR4
:
559 // Medium upside-down case
561 case ATA_SK_NOT_READY
:
562 switch (SensePtr
->addnl_sense_code
) {
563 case ATA_ASC_MEDIA_UPSIDE_DOWN
:
583 Check if media is changed according to sense data.
585 @param SenseData Pointer to sense data.
586 @param SenseCounts Count of sense data.
588 @retval TRUE There is media change event.
589 @retval FALSE media is NOT changed.
594 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
598 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
604 SensePtr
= SenseData
;
606 for (Index
= 0; Index
< SenseCounts
; Index
++) {
608 // catch media change sense key and addition sense data
610 switch (SensePtr
->sense_key
) {
611 case ATA_SK_UNIT_ATTENTION
:
612 switch (SensePtr
->addnl_sense_code
) {
613 case ATA_ASC_MEDIA_CHANGE
: