summaryrefslogtreecommitdiff
path: root/EdkModulePkg
diff options
context:
space:
mode:
authorklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>2007-03-02 08:21:43 +0000
committerklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>2007-03-02 08:21:43 +0000
commitbc4e770c78d692a5a2641359f605d6e83c96da5d (patch)
tree1d7674df1d834f9da781b7b878d408c681e03f04 /EdkModulePkg
parent59e9a3659f77aee8e5f6fd25c83bc3f3adcd8c31 (diff)
downloadedk2-platforms-bc4e770c78d692a5a2641359f605d6e83c96da5d.tar.xz
In IdeBus driver block I/O read/write interface, it will always try to use UDMA mode first, if fails, then try to use PIO mode.
This may cause side effects if disk does not support UDMA mode and also let bad performance. The modification is to record supported mode and only try supported mode when do disk read/write. Also this patch combines the code for read/readex/write/writex to reduce code size. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2412 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'EdkModulePkg')
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c1213
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.h36
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.h2
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/idedata.h7
4 files changed, 197 insertions, 1061 deletions
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c
index aea126b3e6..10240bf7b3 100644
--- a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c
@@ -1075,20 +1075,23 @@ AtaBlkIoReadBlocks (
return EFI_INVALID_PARAMETER;
}
+ Status = EFI_SUCCESS;
if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
//
// For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 read block mechanism
//
- Status = AtaUdmaReadExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
- if (EFI_ERROR (Status)) {
+ if (IdeBlkIoDevice->UdmaMode.Valid) {
+ Status = AtaUdmaReadExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ } else {
Status = AtaReadSectorsExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
}
} else {
//
// For ATA-3 compatible device, use ATA-3 read block mechanism
//
- Status = AtaUdmaRead (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
- if (EFI_ERROR (Status)) {
+ if (IdeBlkIoDevice->UdmaMode.Valid) {
+ Status = AtaUdmaRead (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ } else {
Status = AtaReadSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
}
}
@@ -1196,20 +1199,23 @@ AtaBlkIoWriteBlocks (
return EFI_INVALID_PARAMETER;
}
+ Status = EFI_SUCCESS;
if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
//
// For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 write block mechanism
//
- Status = AtaUdmaWriteExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
- if (EFI_ERROR (Status)) {
+ if (IdeBlkIoDevice->UdmaMode.Valid) {
+ Status = AtaUdmaWriteExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ } else {
Status = AtaWriteSectorsExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
}
} else {
//
// For ATA-3 compatible device, use ATA-3 write block mechanism
//
- Status = AtaUdmaWrite (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
- if (EFI_ERROR (Status)) {
+ if (IdeBlkIoDevice->UdmaMode.Valid) {
+ Status = AtaUdmaWrite (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ } else {
Status = AtaWriteSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
}
}
@@ -2107,339 +2113,7 @@ AtaUdmaReadExt (
IN UINTN NumberOfBlocks
)
{
- IDE_DMA_PRD *PrdAddr;
- IDE_DMA_PRD *UsedPrdAddr;
- IDE_DMA_PRD *TempPrdAddr;
- UINT8 RegisterValue;
- UINT8 Device;
- UINT64 IoPortForBmic;
- UINT64 IoPortForBmis;
- UINT64 IoPortForBmid;
- EFI_STATUS Status;
- UINTN PrdTableNum;
- UINTN ByteCount;
- UINTN ByteAvailable;
- UINT8 *PrdBuffer;
- UINTN RemainBlockNum;
- UINT8 DeviceControl;
- UINT32 Count;
- UINTN PageCount;
- VOID *Map;
- VOID *MemPage;
- EFI_PHYSICAL_ADDRESS DeviceAddress;
-
- //
- // Channel and device differential. Select device.
- //
- Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);
-
- //
- // Enable interrupt to support UDMA and Select device
- //
- DeviceControl = 0;
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
-
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
-
- if (IdePrimary == IdeDev->Channel) {
- IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET;
- IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;
- IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET;
- } else {
- if (IdeSecondary == IdeDev->Channel) {
- IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET;
- IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;
- IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET;
- } else {
- return EFI_UNSUPPORTED;
- }
- }
-
- RemainBlockNum = NumberOfBlocks;
- while (RemainBlockNum > 0) {
-
- if (RemainBlockNum >= MAX_DMA_EXT_COMMAND_SECTORS) {
- //
- // SectorCount is used to record the number of sectors to be read
- // Max 65536 sectors can be transfered at a time.
- //
- NumberOfBlocks = MAX_DMA_EXT_COMMAND_SECTORS;
- RemainBlockNum -= MAX_DMA_EXT_COMMAND_SECTORS;
- } else {
- NumberOfBlocks = (UINT16) RemainBlockNum;
- RemainBlockNum = 0;
- }
-
- //
- // Calculate the number of PRD table to make sure the memory region
- // not cross 64K boundary
- //
- ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;
- PrdTableNum = ((ByteCount >> 16) + 1) + 1;
-
- //
- // Build PRD table
- //
- PageCount = EFI_SIZE_TO_PAGES (2 * PrdTableNum * sizeof (IDE_DMA_PRD));
- Status = IdeDev->PciIo->AllocateBuffer (
- IdeDev->PciIo,
- AllocateAnyPages,
- EfiBootServicesData,
- PageCount,
- &MemPage,
- 0
- );
- if (EFI_ERROR (Status)) {
- return EFI_OUT_OF_RESOURCES;
- }
- ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount));
-
- PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage);
-
- //
- // To make sure PRD is allocated in one 64K page
- //
- if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) {
- UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000);
- } else {
- if ((UINTN) PrdAddr & 0x03) {
- UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC);
- } else {
- UsedPrdAddr = PrdAddr;
- }
- }
-
- //
- // Build the PRD table
- //
- Status = IdeDev->PciIo->Map (
- IdeDev->PciIo,
- EfiPciIoOperationBusMasterWrite,
- DataBuffer,
- &ByteCount,
- &DeviceAddress,
- &Map
- );
- if (EFI_ERROR (Status)) {
- IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);
- return EFI_OUT_OF_RESOURCES;
- }
- PrdBuffer = (VOID *) ((UINTN) DeviceAddress);
- TempPrdAddr = UsedPrdAddr;
- while (TRUE) {
-
- ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF);
-
- if (ByteCount <= ByteAvailable) {
- TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);
- TempPrdAddr->ByteCount = (UINT16) ByteCount;
- TempPrdAddr->EndOfTable = 0x8000;
- break;
- }
-
- TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);
- TempPrdAddr->ByteCount = (UINT16) ByteAvailable;
-
- ByteCount -= ByteAvailable;
- PrdBuffer += ByteAvailable;
- TempPrdAddr++;
- }
-
- //
- // Set the base address to BMID register
- //
- IdeDev->PciIo->Io.Write (
- IdeDev->PciIo,
- EfiPciIoWidthUint32,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmid,
- 1,
- &UsedPrdAddr
- );
-
- //
- // Set BMIC register to identify the operation direction
- //
- IdeDev->PciIo->Io.Read (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- RegisterValue |= BMIC_nREAD;
-
- IdeDev->PciIo->Io.Write (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- //
- // Read BMIS register and clear ERROR and INTR bit
- //
- IdeDev->PciIo->Io.Read (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmis,
- 1,
- &RegisterValue
- );
-
- RegisterValue |= BMIS_INTERRUPT | BMIS_ERROR;
-
- IdeDev->PciIo->Io.Write (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmis,
- 1,
- &RegisterValue
- );
-
- //
- // Issue READ DMA EXT command
- //
- Status = AtaCommandIssueExt (
- IdeDev,
- READ_DMA_EXT_CMD,
- Device,
- 0,
- (UINT16) NumberOfBlocks,
- StartLba
- );
- if (EFI_ERROR (Status)) {
- IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);
- IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Set START bit of BMIC register
- //
- IdeDev->PciIo->Io.Read (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- RegisterValue |= BMIC_START;
-
- IdeDev->PciIo->Io.Write (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- //
- // Check the INTERRUPT and ERROR bit of BMIS
- // Max transfer number of sectors for one command is 65536(32Mbyte),
- // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).
- // So set the variable Count to 2000, for about 2 second timeout time.
- //
- Count = 2000;
- while (TRUE) {
-
- IdeDev->PciIo->Io.Read (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmis,
- 1,
- &RegisterValue
- );
- if ((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) || (Count == 0)) {
- if ((RegisterValue & BMIS_ERROR) || (Count == 0)) {
- //
- // Clear START bit of BMIC register before return EFI_DEVICE_ERROR
- //
- IdeDev->PciIo->Io.Read (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- RegisterValue &= ~((UINT8)BMIC_START);
-
- IdeDev->PciIo->Io.Write (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
- IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);
- IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
- return EFI_DEVICE_ERROR;
- }
- break;
- }
-
- gBS->Stall (1000);
- Count --;
- }
-
- IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);
- IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
- //
- // Read Status Register of IDE device to clear interrupt
- //
- RegisterValue = IDEReadPortB(IdeDev->PciIo,IdeDev->IoPort->Reg.Status);
- //
- // Clear START bit of BMIC register
- //
- IdeDev->PciIo->Io.Read (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- RegisterValue &= ~((UINT8) BMIC_START);
-
- IdeDev->PciIo->Io.Write (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- if (RegisterValue & BMIS_ERROR) {
- return EFI_DEVICE_ERROR;
- }
-
- DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;
- StartLba += NumberOfBlocks;
- }
-
- //
- // Disable interrupt of Select device
- //
- IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl);
- DeviceControl |= IEN_L;
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
-
- return EFI_SUCCESS;
+ return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadExtOp);
}
/**
@@ -2472,338 +2146,7 @@ AtaUdmaRead (
IN UINTN NumberOfBlocks
)
{
- IDE_DMA_PRD *PrdAddr;
- IDE_DMA_PRD *UsedPrdAddr;
- IDE_DMA_PRD *TempPrdAddr;
- UINT8 RegisterValue;
- UINT8 Device;
- UINT64 IoPortForBmic;
- UINT64 IoPortForBmis;
- UINT64 IoPortForBmid;
- EFI_STATUS Status;
- UINTN PrdTableNum;
- UINTN ByteCount;
- UINTN ByteAvailable;
- UINT8 *PrdBuffer;
- UINTN RemainBlockNum;
- UINT8 DeviceControl;
- UINT32 Count;
- UINTN PageCount;
- VOID *Map;
- VOID *MemPage;
- EFI_PHYSICAL_ADDRESS DeviceAddress;
-
- //
- // Channel and device differential
- //
- Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);
-
- //
- // Enable interrupt to support UDMA and Select device
- //
- DeviceControl = 0;
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
-
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
-
- if (IdePrimary == IdeDev->Channel) {
- IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET;
- IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;
- IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET;
- } else {
- if (IdeSecondary == IdeDev->Channel) {
- IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET;
- IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;
- IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET;
- } else {
- return EFI_UNSUPPORTED;
- }
- }
-
- RemainBlockNum = NumberOfBlocks;
- while (RemainBlockNum > 0) {
-
- if (RemainBlockNum >= MAX_DMA_COMMAND_SECTORS) {
- //
- // SectorCount is used to record the number of sectors to be read
- // Max 256 sectors can be transfered at a time.
- //
- NumberOfBlocks = MAX_DMA_COMMAND_SECTORS;
- RemainBlockNum -= MAX_DMA_COMMAND_SECTORS;
- } else {
- NumberOfBlocks = (UINT16) RemainBlockNum;
- RemainBlockNum = 0;
- }
-
- //
- // Calculate the number of PRD table to make sure the memory region
- // not cross 64K boundary
- //
- ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;
- PrdTableNum = ((ByteCount >> 16) + 1) + 1;
-
- //
- // Build PRD table
- //
- PageCount = EFI_SIZE_TO_PAGES (2 * PrdTableNum * sizeof (IDE_DMA_PRD));
- Status = IdeDev->PciIo->AllocateBuffer (
- IdeDev->PciIo,
- AllocateAnyPages,
- EfiBootServicesData,
- PageCount,
- &MemPage,
- 0
- );
- if (EFI_ERROR (Status)) {
- return EFI_OUT_OF_RESOURCES;
- }
- ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount));
-
- PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage);
- //
- // To make sure PRD is allocated in one 64K page
- //
- if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) {
- UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000);
- } else {
- if ((UINTN) PrdAddr & 0x03) {
- UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC);
- } else {
- UsedPrdAddr = PrdAddr;
- }
- }
-
- //
- // Build the PRD table
- //
- Status = IdeDev->PciIo->Map (
- IdeDev->PciIo,
- EfiPciIoOperationBusMasterWrite,
- DataBuffer,
- &ByteCount,
- &DeviceAddress,
- &Map
- );
- if (EFI_ERROR (Status)) {
- IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);
- return EFI_OUT_OF_RESOURCES;
- }
- PrdBuffer = (UINT8 *) ((UINTN) DeviceAddress);
- TempPrdAddr = UsedPrdAddr;
- while (TRUE) {
-
- ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF);
-
- if (ByteCount <= ByteAvailable) {
- TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);
- TempPrdAddr->ByteCount = (UINT16) ByteCount;
- TempPrdAddr->EndOfTable = 0x8000;
- break;
- }
-
- TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);
- TempPrdAddr->ByteCount = (UINT16) ByteAvailable;
-
- ByteCount -= ByteAvailable;
- PrdBuffer += ByteAvailable;
- TempPrdAddr++;
- }
-
- //
- // Set the base address to BMID register
- //
- IdeDev->PciIo->Io.Write (
- IdeDev->PciIo,
- EfiPciIoWidthUint32,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmid,
- 1,
- &UsedPrdAddr
- );
-
- //
- // Set BMIC register to identify the operation direction
- //
- IdeDev->PciIo->Io.Read (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- RegisterValue |= BMIC_nREAD;
-
- IdeDev->PciIo->Io.Write (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- //
- // Read BMIS register and clear ERROR and INTR bit
- //
- IdeDev->PciIo->Io.Read (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmis,
- 1,
- &RegisterValue
- );
-
- RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);
-
- IdeDev->PciIo->Io.Write (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmis,
- 1,
- &RegisterValue
- );
-
- //
- // Issue READ DMA command
- //
- Status = AtaCommandIssue (
- IdeDev,
- READ_DMA_CMD,
- Device,
- 0,
- (UINT16) NumberOfBlocks,
- StartLba
- );
- if (EFI_ERROR (Status)) {
- IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);
- IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Set START bit of BMIC register
- //
- IdeDev->PciIo->Io.Read (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- RegisterValue |= BMIC_START;
-
- IdeDev->PciIo->Io.Write (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- //
- // Check the INTERRUPT and ERROR bit of BMIS
- // Max transfer number of sectors for one command is 65536(32Mbyte),
- // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).
- // So set the variable Count to 2000, for about 2 second timeout time.
- //
- Count = 2000;
- while (TRUE) {
-
- IdeDev->PciIo->Io.Read (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmis,
- 1,
- &RegisterValue
- );
- if ((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) || (Count == 0)) {
- if ((RegisterValue & BMIS_ERROR) || (Count == 0)) {
- //
- // Clear START bit of BMIC register before return EFI_DEVICE_ERROR
- //
- IdeDev->PciIo->Io.Read (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- RegisterValue &= ~((UINT8)BMIC_START);
-
- IdeDev->PciIo->Io.Write (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
- IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);
- IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
- return EFI_DEVICE_ERROR;
- }
- break;
- }
-
- gBS->Stall (1000);
- Count --;
- }
-
- IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);
- IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
- //
- // Read Status Register of IDE device to clear interrupt
- //
- RegisterValue = IDEReadPortB(IdeDev->PciIo,IdeDev->IoPort->Reg.Status);
- //
- // Clear START bit of BMIC register
- //
- IdeDev->PciIo->Io.Read (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- RegisterValue &= ~((UINT8) BMIC_START);
-
- IdeDev->PciIo->Io.Write (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- if (RegisterValue & BMIS_ERROR) {
- return EFI_DEVICE_ERROR;
- }
-
- DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;
- StartLba += NumberOfBlocks;
- }
-
- //
- // Disable interrupt of Select device
- //
- IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl);
- DeviceControl |= IEN_L;
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
-
- return EFI_SUCCESS;
+ return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadOp);
}
/**
@@ -2836,336 +2179,7 @@ AtaUdmaWriteExt (
IN UINTN NumberOfBlocks
)
{
- IDE_DMA_PRD *PrdAddr;
- IDE_DMA_PRD *UsedPrdAddr;
- IDE_DMA_PRD *TempPrdAddr;
- UINT8 RegisterValue;
- UINT8 Device;
- UINT64 IoPortForBmic;
- UINT64 IoPortForBmis;
- UINT64 IoPortForBmid;
- EFI_STATUS Status;
- UINTN PrdTableNum;
- UINTN ByteCount;
- UINTN ByteAvailable;
- UINT8 *PrdBuffer;
- UINTN RemainBlockNum;
- UINT8 DeviceControl;
- UINT32 Count;
- UINTN PageCount;
- VOID *Map;
- VOID *MemPage;
- EFI_PHYSICAL_ADDRESS DeviceAddress;
-
- //
- // Channel and device differential
- //
- Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);
-
- //
- // Enable interrupt to support UDMA and Select device
- //
- DeviceControl = 0;
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
-
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
-
- if (IdePrimary == IdeDev->Channel) {
- IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET;
- IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;
- IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET;
- } else {
- if (IdeSecondary == IdeDev->Channel) {
- IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET;
- IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;
- IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET;
- } else {
- return EFI_UNSUPPORTED;
- }
- }
-
- RemainBlockNum = NumberOfBlocks;
- while (RemainBlockNum > 0) {
-
- if (RemainBlockNum >= MAX_DMA_EXT_COMMAND_SECTORS) {
- //
- // SectorCount is used to record the number of sectors to be read
- // Max 65536 sectors can be transfered at a time.
- //
- NumberOfBlocks = MAX_DMA_EXT_COMMAND_SECTORS;
- RemainBlockNum -= MAX_DMA_EXT_COMMAND_SECTORS;
- } else {
- NumberOfBlocks = (UINT16) RemainBlockNum;
- RemainBlockNum = 0;
- }
-
- //
- // Calculate the number of PRD table to make sure the memory region
- // not cross 64K boundary
- //
- ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;
- PrdTableNum = ((ByteCount >> 16) + 1) + 1;
-
- //
- // Build PRD table
- //
- PageCount = EFI_SIZE_TO_PAGES (2 * PrdTableNum * sizeof (IDE_DMA_PRD));
- Status = IdeDev->PciIo->AllocateBuffer (
- IdeDev->PciIo,
- AllocateAnyPages,
- EfiBootServicesData,
- PageCount,
- &MemPage,
- 0
- );
- if (EFI_ERROR (Status)) {
- return EFI_OUT_OF_RESOURCES;
- }
- ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount));
-
- PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage);
- //
- // To make sure PRD is allocated in one 64K page
- //
- if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) {
- UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000);
- } else {
- if ((UINTN) PrdAddr & 0x03) {
- UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC);
- } else {
- UsedPrdAddr = PrdAddr;
- }
- }
-
- //
- // Build the PRD table
- //
- Status = IdeDev->PciIo->Map (
- IdeDev->PciIo,
- EfiPciIoOperationBusMasterRead,
- DataBuffer,
- &ByteCount,
- &DeviceAddress,
- &Map
- );
- if (EFI_ERROR (Status)) {
- IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);
- return EFI_OUT_OF_RESOURCES;
- }
- PrdBuffer = (UINT8 *) ((UINTN) DeviceAddress);
- TempPrdAddr = UsedPrdAddr;
- while (TRUE) {
-
- ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF);
-
- if (ByteCount <= ByteAvailable) {
- TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);
- TempPrdAddr->ByteCount = (UINT16) ByteCount;
- TempPrdAddr->EndOfTable = 0x8000;
- break;
- }
-
- TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);
- TempPrdAddr->ByteCount = (UINT16) ByteAvailable;
-
- ByteCount -= ByteAvailable;
- PrdBuffer += ByteAvailable;
- TempPrdAddr++;
- }
-
- //
- // Set the base address to BMID register
- //
- IdeDev->PciIo->Io.Write (
- IdeDev->PciIo,
- EfiPciIoWidthUint32,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmid,
- 1,
- &UsedPrdAddr
- );
-
- //
- // Set BMIC register to identify the operation direction
- //
- IdeDev->PciIo->Io.Read (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
- //
- // 0000 1000
- //
- RegisterValue &= ~((UINT8) BMIC_nREAD);
-
- IdeDev->PciIo->Io.Write (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- //
- // Read BMIS register and clear ERROR and INTR bit
- //
- IdeDev->PciIo->Io.Read (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmis,
- 1,
- &RegisterValue
- );
-
- RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);
-
- IdeDev->PciIo->Io.Write (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmis,
- 1,
- &RegisterValue
- );
-
- //
- // Issue WRITE DMA EXT command
- //
- Status = AtaCommandIssueExt (
- IdeDev,
- WRITE_DMA_EXT_CMD,
- Device,
- 0,
- (UINT16) NumberOfBlocks,
- StartLba
- );
- if (EFI_ERROR (Status)) {
- IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);
- IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
- return EFI_DEVICE_ERROR;
- }
-
- //
- // Set START bit of BMIC register
- //
- IdeDev->PciIo->Io.Read (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- RegisterValue |= BMIC_START;
-
- IdeDev->PciIo->Io.Write (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- //
- // Check the INTERRUPT and ERROR bit of BMIS
- // Max transfer number of sectors for one command is 65536(32Mbyte),
- // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).
- // So set the variable Count to 2000, for about 2 second timeout time.
- //
- Count = 2000;
- while (TRUE) {
-
- IdeDev->PciIo->Io.Read (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmis,
- 1,
- &RegisterValue
- );
- if ((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) || (Count == 0)) {
- if ((RegisterValue & BMIS_ERROR) || (Count == 0)) {
- //
- // Clear START bit of BMIC register before return EFI_DEVICE_ERROR
- //
- IdeDev->PciIo->Io.Read (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- RegisterValue &= ~((UINT8)BMIC_START);
-
- IdeDev->PciIo->Io.Write (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
- IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);
- IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
- return EFI_DEVICE_ERROR;
- }
- break;
- }
-
- gBS->Stall (1000);
- Count --;
- }
-
- IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);
- IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
- //
- // Read Status Register of IDE device to clear interrupt
- //
- RegisterValue = IDEReadPortB(IdeDev->PciIo,IdeDev->IoPort->Reg.Status);
- //
- // Clear START bit of BMIC register
- //
- IdeDev->PciIo->Io.Read (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- RegisterValue &= ~((UINT8) BMIC_START);
-
- IdeDev->PciIo->Io.Write (
- IdeDev->PciIo,
- EfiPciIoWidthUint8,
- EFI_PCI_IO_PASS_THROUGH_BAR,
- IoPortForBmic,
- 1,
- &RegisterValue
- );
-
- DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;
- StartLba += NumberOfBlocks;
- }
-
- //
- // Disable interrupt of Select device
- //
- IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl);
- DeviceControl |= IEN_L;
- IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
-
- return EFI_SUCCESS;
+ return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteExtOp);
}
/**
@@ -3202,26 +2216,92 @@ AtaUdmaWrite (
IN UINTN NumberOfBlocks
)
{
- IDE_DMA_PRD *PrdAddr;
- IDE_DMA_PRD *UsedPrdAddr;
- IDE_DMA_PRD *TempPrdAddr;
- UINT8 RegisterValue;
- UINT8 Device;
- UINT64 IoPortForBmic;
- UINT64 IoPortForBmis;
- UINT64 IoPortForBmid;
- EFI_STATUS Status;
- UINTN PrdTableNum;
- UINTN ByteCount;
- UINTN ByteAvailable;
- UINT8 *PrdBuffer;
- UINTN RemainBlockNum;
- UINT8 DeviceControl;
- UINT32 Count;
- UINTN PageCount;
- VOID *Map;
- VOID *MemPage;
- EFI_PHYSICAL_ADDRESS DeviceAddress;
+ return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteOp);
+}
+
+/**
+ Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] *DataBuffer
+ A pointer to the source buffer for the data.
+
+ @param[in] StartLba
+ The starting logical block address to write to
+ on the device media.
+
+ @param[in] NumberOfBlocks
+ The number of transfer data blocks.
+
+ @param[in] UdmaOp
+ The perform operations could be AtaUdmaReadOp, AtaUdmaReadExOp,
+ AtaUdmaWriteOp, AtaUdmaWriteExOp
+
+ @return The device status of UDMA operation. If the operation is
+ successful, return EFI_SUCCESS.
+
+**/
+EFI_STATUS
+DoAtaUdma (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks,
+ IN ATA_UDMA_OPERATION UdmaOp
+ )
+{
+ IDE_DMA_PRD *PrdAddr;
+ IDE_DMA_PRD *UsedPrdAddr;
+ IDE_DMA_PRD *TempPrdAddr;
+ UINT8 RegisterValue;
+ UINT8 Device;
+ UINT64 IoPortForBmic;
+ UINT64 IoPortForBmis;
+ UINT64 IoPortForBmid;
+ EFI_STATUS Status;
+ UINTN PrdTableNum;
+ UINTN ByteCount;
+ UINTN ByteAvailable;
+ UINT8 *PrdBuffer;
+ UINTN RemainBlockNum;
+ UINT8 DeviceControl;
+ UINT32 Count;
+ UINTN PageCount;
+ VOID *Map;
+ VOID *MemPage;
+ EFI_PHYSICAL_ADDRESS DeviceAddress;
+ UINTN MaxDmaCommandSectors;
+ EFI_PCI_IO_PROTOCOL_OPERATION PciIoProtocolOp;
+ UINT8 AtaCommand;
+
+ switch (UdmaOp) {
+ case AtaUdmaReadOp:
+ MaxDmaCommandSectors = MAX_DMA_COMMAND_SECTORS;
+ PciIoProtocolOp = EfiPciIoOperationBusMasterWrite;
+ AtaCommand = READ_DMA_CMD;
+ break;
+ case AtaUdmaReadExtOp:
+ MaxDmaCommandSectors = MAX_DMA_EXT_COMMAND_SECTORS;
+ PciIoProtocolOp = EfiPciIoOperationBusMasterWrite;
+ AtaCommand = READ_DMA_EXT_CMD;
+ break;
+ case AtaUdmaWriteOp:
+ MaxDmaCommandSectors = MAX_DMA_COMMAND_SECTORS;
+ PciIoProtocolOp = EfiPciIoOperationBusMasterRead;
+ AtaCommand = WRITE_DMA_CMD;
+ break;
+ case AtaUdmaWriteExtOp:
+ MaxDmaCommandSectors = MAX_DMA_EXT_COMMAND_SECTORS;
+ PciIoProtocolOp = EfiPciIoOperationBusMasterRead;
+ AtaCommand = WRITE_DMA_EXT_CMD;
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ break;
+ }
//
// Channel and device differential
@@ -3229,7 +2309,7 @@ AtaUdmaWrite (
Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);
//
- // Enable interrupt to support UDMA
+ // Enable interrupt to support UDMA and Select device
//
DeviceControl = 0;
IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
@@ -3253,13 +2333,13 @@ AtaUdmaWrite (
RemainBlockNum = NumberOfBlocks;
while (RemainBlockNum > 0) {
- if (RemainBlockNum >= MAX_DMA_COMMAND_SECTORS) {
+ if (RemainBlockNum >= MaxDmaCommandSectors) {
//
// SectorCount is used to record the number of sectors to be read
- // Max 256 sectors can be transfered at a time.
+ // Max 65536 sectors can be transfered at a time.
//
- NumberOfBlocks = MAX_DMA_COMMAND_SECTORS;
- RemainBlockNum -= MAX_DMA_COMMAND_SECTORS;
+ NumberOfBlocks = MaxDmaCommandSectors;
+ RemainBlockNum -= MaxDmaCommandSectors;
} else {
NumberOfBlocks = (UINT16) RemainBlockNum;
RemainBlockNum = 0;
@@ -3277,20 +2357,19 @@ AtaUdmaWrite (
//
PageCount = EFI_SIZE_TO_PAGES (2 * PrdTableNum * sizeof (IDE_DMA_PRD));
Status = IdeDev->PciIo->AllocateBuffer (
- IdeDev->PciIo,
- AllocateAnyPages,
- EfiBootServicesData,
- PageCount,
- &MemPage,
- 0
- );
+ IdeDev->PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ PageCount,
+ &MemPage,
+ 0
+ );
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount));
-
+
PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage);
-
//
// To make sure PRD is allocated in one 64K page
//
@@ -3308,18 +2387,18 @@ AtaUdmaWrite (
// Build the PRD table
//
Status = IdeDev->PciIo->Map (
- IdeDev->PciIo,
- EfiPciIoOperationBusMasterRead,
- DataBuffer,
- &ByteCount,
+ IdeDev->PciIo,
+ PciIoProtocolOp,
+ DataBuffer,
+ &ByteCount,
&DeviceAddress,
&Map
);
if (EFI_ERROR (Status)) {
IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);
return EFI_OUT_OF_RESOURCES;
- }
- PrdBuffer = (UINT8 *) ((UINTN) DeviceAddress);
+ }
+ PrdBuffer = (VOID *) ((UINTN) DeviceAddress);
TempPrdAddr = UsedPrdAddr;
while (TRUE) {
@@ -3363,10 +2442,12 @@ AtaUdmaWrite (
1,
&RegisterValue
);
- //
- // 0000 1000
- //
- RegisterValue &= ~((UINT8) BMIC_nREAD);
+
+ if (UdmaOp == AtaUdmaReadExtOp || UdmaOp == AtaUdmaReadOp) {
+ RegisterValue |= BMIC_nREAD;
+ } else {
+ RegisterValue &= ~((UINT8) BMIC_nREAD);
+ }
IdeDev->PciIo->Io.Write (
IdeDev->PciIo,
@@ -3400,17 +2481,26 @@ AtaUdmaWrite (
&RegisterValue
);
- //
- // Issue WRITE DMA command
- //
- Status = AtaCommandIssue (
- IdeDev,
- WRITE_DMA_CMD,
- Device,
- 0,
- (UINT16) NumberOfBlocks,
- StartLba
- );
+ if (UdmaOp == AtaUdmaWriteExtOp || UdmaOp == AtaUdmaReadExtOp) {
+ Status = AtaCommandIssueExt (
+ IdeDev,
+ AtaCommand,
+ Device,
+ 0,
+ (UINT16) NumberOfBlocks,
+ StartLba
+ );
+ } else {
+ Status = AtaCommandIssue (
+ IdeDev,
+ AtaCommand,
+ Device,
+ 0,
+ (UINT16) NumberOfBlocks,
+ StartLba
+ );
+ }
+
if (EFI_ERROR (Status)) {
IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);
IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
@@ -3494,7 +2584,6 @@ AtaUdmaWrite (
IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);
IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);
-
//
// Read Status Register of IDE device to clear interrupt
//
@@ -3522,6 +2611,10 @@ AtaUdmaWrite (
&RegisterValue
);
+ if (RegisterValue & BMIS_ERROR) {
+ return EFI_DEVICE_ERROR;
+ }
+
DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;
StartLba += NumberOfBlocks;
}
@@ -3534,4 +2627,4 @@ AtaUdmaWrite (
IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
return EFI_SUCCESS;
-}
+} \ No newline at end of file
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.h b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.h
index b83a82a9fb..f382279ab5 100644
--- a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.h
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.h
@@ -1098,6 +1098,42 @@ AtaUdmaWriteExt (
;
/**
+ Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).
+
+ @param[in] *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ @param[in] *DataBuffer
+ A pointer to the source buffer for the data.
+
+ @param[in] StartLba
+ The starting logical block address to write to
+ on the device media.
+
+ @param[in] NumberOfBlocks
+ The number of transfer data blocks.
+
+ @param[in] UdmaOp
+ The perform operations could be AtaUdmaReadOp, AtaUdmaReadExOp,
+ AtaUdmaWriteOp, AtaUdmaWriteExOp
+
+ @return The device status of UDMA operation. If the operation is
+ successful, return EFI_SUCCESS.
+
+**/
+EFI_STATUS
+DoAtaUdma (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks,
+ IN ATA_UDMA_OPERATION UdmaOp
+ )
+;
+
+
+/**
TODO: Add function description
@param IdeDev TODO: add argument description
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.h b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.h
index 52c1f266b1..78c79d7665 100644
--- a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.h
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.h
@@ -65,7 +65,7 @@ typedef struct {
INQUIRY_DATA *pInquiryData;
EFI_IDENTIFY_DATA *pIdData;
ATA_PIO_MODE PioMode;
- ATA_UDMA_MODE UDma_Mode;
+ EFI_ATA_MODE UdmaMode;
CHAR8 ModelName[41];
REQUEST_SENSE_DATA *SenseData;
UINT8 SenseDataNumber;
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idedata.h b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idedata.h
index ec088dcfa6..0c3831119a 100644
--- a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idedata.h
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idedata.h
@@ -86,6 +86,13 @@ typedef enum {
SenseOtherSense
} SENSE_RESULT;
+typedef enum {
+ AtaUdmaReadOp,
+ AtaUdmaReadExtOp,
+ AtaUdmaWriteOp,
+ AtaUdmaWriteExtOp
+} ATA_UDMA_OPERATION;
+
//
// IDE Registers
//