atapi.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,385 行 · 第 1/5 页
C
2,385 行
EFI_STATUS
AtapiPacketCommandIn (
IN IDE_BLK_IO_DEV *IdeDev,
IN ATAPI_PACKET_COMMAND *Packet,
IN UINT16 *Buffer,
IN UINT32 ByteCount,
IN UINTN TimeOut
)
/*++
Name:
AtapiPacketCommandIn
Purpose:
This function is used to send out ATAPI commands conforms to the
Packet Command with PIO Data In Protocol.
Parameters:
IDE_BLK_IO_DEV IN *IdeDev
pointer pointing to IDE_BLK_IO_DEV data structure, used
to record all the information of the IDE device.
ATAPI_PACKET_COMMAND IN *Packet
pointer pointing to ATAPI_PACKET_COMMAND data structure
which contains the contents of the command.
UINT16 IN *Buffer
buffer contained data transferred from device to host.
UINT32 IN ByteCount
data size in byte unit of the buffer.
UINTN IN TimeOut
this parameter is used to specify the timeout
value for the PioReadWriteData() function.
Returns:
EFI_SUCCESS
send out the ATAPI packet command successfully
and device sends data successfully.
EFI_DEVICE_ERROR
the device failed to send data.
Notes:
--*/
// TODO: function comment is missing 'Routine Description:'
// TODO: function comment is missing 'Arguments:'
// TODO: IdeDev - add argument and description to function comment
// TODO: Packet - add argument and description to function comment
// TODO: Buffer - add argument and description to function comment
// TODO: ByteCount - add argument and description to function comment
// TODO: TimeOut - add argument and description to function comment
{
UINT16 *CommandIndex;
EFI_STATUS Status;
UINT32 Count;
//
// Set all the command parameters by fill related registers.
// Before write to all the following registers, BSY and DRQ must be 0.
//
Status = DRQClear2 (IdeDev, ATAPITIMEOUT);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Select device via Device/Head Register.
//
IDEWritePortB (
IdeDev->PciIo,
IdeDev->IoPort->Head,
(UINT8) ((IdeDev->Device << 4) | DEFAULT_CMD) // DEFAULT_CMD: 0xa0 (1010,0000)
);
//
// No OVL; No DMA
//
IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x00);
//
// set the transfersize to MAX_ATAPI_BYTE_COUNT to let the device
// determine how many data should be transferred.
//
IDEWritePortB (
IdeDev->PciIo,
IdeDev->IoPort->CylinderLsb,
(UINT8) (MAX_ATAPI_BYTE_COUNT & 0x00ff)
);
IDEWritePortB (
IdeDev->PciIo,
IdeDev->IoPort->CylinderMsb,
(UINT8) (MAX_ATAPI_BYTE_COUNT >> 8)
);
//
// DEFAULT_CTL:0x0a (0000,1010)
// Disable interrupt
//
IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DEFAULT_CTL);
//
// Send Packet command to inform device
// that the following data bytes are command packet.
//
IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, PACKET_CMD);
Status = DRQReady (IdeDev, ATAPITIMEOUT);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Send out command packet
//
CommandIndex = Packet->Data16;
for (Count = 0; Count < 6; Count++, CommandIndex++) {
IDEWritePortW (IdeDev->PciIo, IdeDev->IoPort->Data, *CommandIndex);
gBS->Stall (10);
}
//
// call PioReadWriteData() function to get
// requested transfer data form device.
//
return PioReadWriteData (IdeDev, Buffer, ByteCount, 1, TimeOut);
}
EFI_STATUS
AtapiPacketCommandOut (
IN IDE_BLK_IO_DEV *IdeDev,
IN ATAPI_PACKET_COMMAND *Packet,
IN UINT16 *Buffer,
IN UINT32 ByteCount,
IN UINTN TimeOut
)
/*++
Name:
AtapiPacketCommandOut
Purpose:
This function is used to send out ATAPI commands conforms to the
Packet Command with PIO Data Out Protocol.
Parameters:
IDE_BLK_IO_DEV IN *IdeDev
pointer pointing to IDE_BLK_IO_DEV data structure, used
to record all the information of the IDE device.
ATAPI_PACKET_COMMAND IN *Packet
pointer pointing to ATAPI_PACKET_COMMAND data structure
which contains the contents of the command.
VOID IN *Buffer
buffer contained data transferred from host to device.
UINT32 IN ByteCount
data size in byte unit of the buffer.
UINTN IN TimeOut
this parameter is used to specify the timeout
value for the PioReadWriteData() function.
Returns:
EFI_SUCCESS
send out the ATAPI packet command successfully
and device received data successfully.
EFI_DEVICE_ERROR
the device failed to send data.
Notes:
--*/
// TODO: function comment is missing 'Routine Description:'
// TODO: function comment is missing 'Arguments:'
// TODO: IdeDev - add argument and description to function comment
// TODO: Packet - add argument and description to function comment
// TODO: Buffer - add argument and description to function comment
// TODO: ByteCount - add argument and description to function comment
// TODO: TimeOut - add argument and description to function comment
{
UINT16 *CommandIndex;
EFI_STATUS Status;
UINT32 Count;
//
// set all the command parameters
// Before write to all the following registers, BSY and DRQ must be 0.
//
Status = DRQClear2 (IdeDev, ATAPITIMEOUT);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Select device via Device/Head Register.
//
IDEWritePortB (
IdeDev->PciIo,
IdeDev->IoPort->Head,
(UINT8) ((IdeDev->Device << 4) | DEFAULT_CMD) // DEFAULT_CMD: 0xa0 (1010,0000)
);
//
// No OVL; No DMA
//
IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x00);
//
// set the transfersize to MAX_ATAPI_BYTE_COUNT to
// let the device determine how many data should be transferred.
//
IDEWritePortB (
IdeDev->PciIo,
IdeDev->IoPort->CylinderLsb,
(UINT8) (MAX_ATAPI_BYTE_COUNT & 0x00ff)
);
IDEWritePortB (
IdeDev->PciIo,
IdeDev->IoPort->CylinderMsb,
(UINT8) (MAX_ATAPI_BYTE_COUNT >> 8)
);
//
// DEFAULT_CTL:0x0a (0000,1010)
// Disable interrupt
//
IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DEFAULT_CTL);
//
// Send Packet command to inform device
// that the following data bytes are command packet.
//
IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, PACKET_CMD);
Status = DRQReady2 (IdeDev, ATAPITIMEOUT);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Send out command packet
//
CommandIndex = Packet->Data16;
for (Count = 0; Count < 6; Count++, CommandIndex++) {
IDEWritePortW (IdeDev->PciIo, IdeDev->IoPort->Data, *CommandIndex);
gBS->Stall (10);
}
//
// call PioReadWriteData() function to send requested transfer data to device.
//
return PioReadWriteData (IdeDev, Buffer, ByteCount, 0, TimeOut);
}
EFI_STATUS
PioReadWriteData (
IN IDE_BLK_IO_DEV *IdeDev,
IN UINT16 *Buffer,
IN UINT32 ByteCount,
IN BOOLEAN Read,
IN UINTN TimeOut
)
/*++
Name:
PioReadWriteData
Purpose:
This function is called by either AtapiPacketCommandIn() or
AtapiPacketCommandOut(). It is used to transfer data between
host and device. The data direction is specified by the fourth
parameter.
Parameters:
IDE_BLK_IO_DEV IN *IdeDev
pointer pointing to IDE_BLK_IO_DEV data structure, used
to record all the information of the IDE device.
VOID IN *Buffer
buffer contained data transferred between host and device.
UINT32 IN ByteCount
data size in byte unit of the buffer.
BOOLEAN IN Read
flag used to determine the data transfer direction.
Read equals 1, means data transferred from device to host;
Read equals 0, means data transferred from host to device.
UINTN IN TimeOut
timeout value for wait DRQ ready before each data
stream's transfer.
Returns:
EFI_SUCCESS
data is transferred successfully.
EFI_DEVICE_ERROR
the device failed to transfer data.
Notes:
--*/
// TODO: function comment is missing 'Routine Description:'
// TODO: function comment is missing 'Arguments:'
// TODO: IdeDev - add argument and description to function comment
// TODO: Buffer - add argument and description to function comment
// TODO: ByteCount - add argument and description to function comment
// TODO: Read - add argument and description to function comment
// TODO: TimeOut - add argument and description to function comment
{
//
// required transfer data in word unit.
//
UINT32 RequiredWordCount;
//
// actual transfer data in word unit.
//
UINT32 ActualWordCount;
UINT32 WordCount;
EFI_STATUS Status;
UINT16 *PtrBuffer;
//
// containing status byte read from Status Register.
//
UINT8 StatusRegister;
//
// No data transfer is premitted.
//
if (ByteCount == 0) {
return EFI_SUCCESS;
}
//
// for performance, we assert the ByteCount is an even number
// which is actually a resonable assumption
ASSERT((ByteCount%2) == 0);
PtrBuffer = Buffer;
RequiredWordCount = ByteCount / 2;
//
// ActuralWordCount means the word count of data really transferred.
//
ActualWordCount = 0;
while (ActualWordCount < RequiredWordCount) {
//
// before each data transfer stream, the host should poll DRQ bit ready,
// to see whether indicates device is ready to transfer data.
//
Status = DRQReady2 (IdeDev, TimeOut);
if (EFI_ERROR (Status)) {
return CheckErrorStatus (IdeDev);
}
//
// read Status Register will clear interrupt
//
StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
//
// get current data transfer size from Cylinder Registers.
//
WordCount =
(
(IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb) << 8) |
IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb)
) & 0xffff;
WordCount /= 2;
WordCount = EFI_MIN (WordCount, (RequiredWordCount - ActualWordCount));
if (Read) {
IDEReadPortWMultiple (
IdeDev->PciIo,
IdeDev->IoPort->Data,
WordCount,
PtrBuffer
);
} else {
IDEWritePortWMultiple (
IdeDev->PciIo,
IdeDev->IoPort->Data,
WordCount,
PtrBuffer
);
}
PtrBuffer += WordCount;
ActualWordCount += WordCount;
}
if (Read) {
// In the case where the drive wants to send more data than we need to read,
// the DRQ bit will be set and cause delays from DRQClear2().
// We need to read data from the drive until it clears DRQ so we can move on.
AtapiReadPendingData (IdeDev);
}
//
// After data transfer is completed, normally, DRQ bit should clear.
//
Status = DRQClear2 (IdeDev, ATAPITIMEOUT);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
//
// read status register to check whether error happens.
//
return CheckErrorStatus (IdeDev);
}
EFI_STATUS
AtapiTestUnitReady (
IN IDE_BLK_IO_DEV *IdeDev,
OUT UINTN *SenseCount
)
/*++
Name:
AtapiTestUnitReady
Purpose:
Sends out ATAPI Test Unit Ready Packet Command to the specified device
to find out whether device is accessible. Sense count is requested
after this packet command.
Parameters:
IDE_BLK_IO_DEV IN *IdeDev
pointer pointing to IDE_BLK_IO_DEV data structure, used
to record all the information of the IDE device.
SenseCount OUT *SenseCount
sense count for this packet command.
Returns:
EFI_SUCCESS
command is issued and sense data is requested successfully.
EFI_DEVICE_ERROR
exceptional error without sense data (*SenseCount == 0)
Notes:
--*/
{
ATAPI_PACKET_COMMAND Packet;
EFI_STATUS Status;
*SenseCount = 0;
//
// fill command packet
//
EfiZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
Packet.TestUnitReady.opcode = TEST_UNIT_READY;
//
// send command packet
//
Status = AtapiPacketCommandIn (IdeDev, &Packet, NULL, 0, ATAPITIMEOUT);
if (EFI_ERROR (Status)) {
return Status;
}
Status = AtapiRequestSense (IdeDev, SenseCount);
if (EFI_ERROR (Status)) {
*SenseCount = 0;
return Status;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?