/** @file
Pei USB ATATPI command implementations.
Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
of the BSD License which accompanies this distribution. The
full text of the license may be found at
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "UsbBotPeim.h"
#include "BotPeim.h"
/**
Sends out ATAPI Inquiry Packet Command to the specified device. This command will
return INQUIRY data of the device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
@retval EFI_SUCCESS Inquiry command completes successfully.
@retval EFI_DEVICE_ERROR Inquiry command failed.
**/
)
{
//
// fill command packet
//
//
// Send scsi INQUIRY command packet.
// According to SCSI Primary Commands-2 spec, host only needs to
// retrieve the first 36 bytes for standard INQUIRY data.
//
&Packet,
(UINT8) sizeof (ATAPI_PACKET_COMMAND),
&Idata,
36,
2000
);
return EFI_DEVICE_ERROR;
}
} else {
}
return EFI_SUCCESS;
}
/**
Sends out ATAPI Test Unit Ready Packet Command to the specified device
to find out whether device is accessible.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
@retval EFI_SUCCESS TestUnit command executed successfully.
@retval EFI_DEVICE_ERROR Device cannot be executed TestUnit command successfully.
**/
)
{
//
// fill command packet
//
//
// send command packet
//
&Packet,
(UINT8) sizeof (ATAPI_PACKET_COMMAND),
NULL,
0,
2000
);
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
/**
Sends out ATAPI Request Sense Packet Command to the specified device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
@param SenseCounts Length of sense buffer.
@param SenseKeyBuffer Pointer to sense buffer.
@retval EFI_SUCCESS Command executed successfully.
@retval EFI_DEVICE_ERROR Some device errors happen.
**/
)
{
*SenseCounts = 0;
//
// fill command packet for Request Sense Packet Command
//
//
// request sense data from device continuously
// until no sense data exists in the device.
//
while (SenseReq) {
//
// send out Request Sense Packet Command and get one Sense
// data form device.
//
&Packet,
(UINT8) sizeof (ATAPI_PACKET_COMMAND),
sizeof (ATAPI_REQUEST_SENSE_DATA),
2000
);
//
// failed to get Sense data
//
if (*SenseCounts == 0) {
return EFI_DEVICE_ERROR;
} else {
return EFI_SUCCESS;
}
}
Ptr += sizeof (ATAPI_REQUEST_SENSE_DATA);
//
// Ptr is byte based pointer
//
(*SenseCounts)++;
if (*SenseCounts == MAXSENSEKEY) {
break;
}
} else {
//
// when no sense key, skip out the loop
//
}
}
return EFI_SUCCESS;
}
/**
Sends out ATAPI Read Capacity Packet Command to the specified device.
This command will return the information regarding the capacity of the
media in the device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
@retval EFI_SUCCESS Command executed successfully.
@retval EFI_DEVICE_ERROR Some device errors happen.
**/
)
{
//
// send command packet
//
&Packet,
(UINT8) sizeof (ATAPI_PACKET_COMMAND),
sizeof (ATAPI_READ_CAPACITY_DATA),
2000
);
return EFI_DEVICE_ERROR;
}
PeiBotDevice->Media.LastBlock = (Data.LastLba3 << 24) | (Data.LastLba2 << 16) | (Data.LastLba1 << 8) | Data.LastLba0;
return EFI_SUCCESS;
}
/**
Sends out ATAPI Read Format Capacity Data Command to the specified device.
This command will return the information regarding the capacity of the
media in the device.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
@retval EFI_SUCCESS Command executed successfully.
@retval EFI_DEVICE_ERROR Some device errors happen.
**/
)
{
//
// send command packet
//
&Packet,
(UINT8) sizeof (ATAPI_PACKET_COMMAND),
(VOID *) &FormatData,
sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA),
2000
);
return EFI_DEVICE_ERROR;
}
//
// Media is not present
//
} else {
PeiBotDevice->Media.LastBlock = (FormatData.LastLba3 << 24) | (FormatData.LastLba2 << 16) | (FormatData.LastLba1 << 8) | FormatData.LastLba0;
}
return EFI_SUCCESS;
}
/**
Execute Read(10) ATAPI command on a specific SCSI target.
Executes the ATAPI Read(10) command on the ATAPI target specified by PeiBotDevice.
@param PeiServices The pointer of EFI_PEI_SERVICES.
@param PeiBotDevice The pointer to PEI_BOT_DEVICE instance.
@param Buffer The pointer to data buffer.
@param Lba The start logic block address of reading.
@param NumberOfBlocks The block number of reading.
@retval EFI_SUCCESS Command executed successfully.
@retval EFI_DEVICE_ERROR Some device errors happen.
**/
)
{
//
// prepare command packet for the Inquiry Packet Command.
//
while (BlocksRemaining > 0) {
if (BlocksRemaining <= MaxBlock) {
} else {
}
//
// fill the Packet data structure
//
//
// Lba0 ~ Lba3 specify the start logical block address of the data transfer.
// Lba0 is MSB, Lba3 is LSB
//
//
// TranLen0 ~ TranLen1 specify the transfer length in block unit.
// TranLen0 is MSB, TranLen is LSB
//
//
// send command packet
//
&Packet,
(UINT8) sizeof (ATAPI_PACKET_COMMAND),
);
if (Status != EFI_SUCCESS) {
return Status;
}
Lba32 += SectorCount;
}
return Status;
}
/**
Check if there is media according to sense data.
@param SenseData Pointer to sense data.
@param SenseCounts Count of sense data.
@retval TRUE No media
@retval FALSE Media exists
**/
)
{
case ATA_SK_NOT_READY:
switch (SensePtr->addnl_sense_code) {
//
// if no media, fill IdeDev parameter with specific info.
//
case ATA_ASC_NO_MEDIA:
break;
default:
break;
}
break;
default:
break;
}
SensePtr++;
}
return NoMedia;
}
/**
Check if there is media error according to sense data.
@param SenseData Pointer to sense data.
@param SenseCounts Count of sense data.
@retval TRUE Media error
@retval FALSE No media error
**/
)
{
//
// Medium error case
//
case ATA_SK_MEDIUM_ERROR:
switch (SensePtr->addnl_sense_code) {
case ATA_ASC_MEDIA_ERR1:
//
// fall through
//
case ATA_ASC_MEDIA_ERR2:
//
// fall through
//
case ATA_ASC_MEDIA_ERR3:
//
// fall through
//
case ATA_ASC_MEDIA_ERR4:
break;
default:
break;
}
break;
//
// Medium upside-down case
//
case ATA_SK_NOT_READY:
switch (SensePtr->addnl_sense_code) {
break;
default:
break;
}
break;
default:
break;
}
SensePtr++;
}
return Error;
}
/**
Check if media is changed according to sense data.
@param SenseData Pointer to sense data.
@param SenseCounts Count of sense data.
@retval TRUE There is media change event.
@retval FALSE media is NOT changed.
**/
)
{
MediaChange = FALSE;
//
// catch media change sense key and addition sense data
//
case ATA_SK_UNIT_ATTENTION:
switch (SensePtr->addnl_sense_code) {
case ATA_ASC_MEDIA_CHANGE:
MediaChange = TRUE;
break;
default:
break;
}
break;
default:
break;
}
SensePtr++;
}
return MediaChange;
}