From bc4e770c78d692a5a2641359f605d6e83c96da5d Mon Sep 17 00:00:00 2001 From: klu2 Date: Fri, 2 Mar 2007 08:21:43 +0000 Subject: [PATCH 1/1] 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 --- EdkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c | 1405 ++++----------------- EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.h | 36 + EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.h | 2 +- EdkModulePkg/Bus/Pci/IdeBus/Dxe/idedata.h | 7 + 4 files changed, 293 insertions(+), 1157 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,29 +2113,198 @@ 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. + return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadExtOp); +} + +/** + This function is called by the AtaBlkIoReadBlocks() to perform + reading from media in block unit. The function has been enhanced to + support >120GB access and transfer at most 65536 blocks per command + + @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 destination buffer for the data. + @param[in] StartLba The starting logical block address to read from + on the device media. + @param[in] NumberOfBlocks The number of transfer data blocks. + + @return The device status of UDMA operation. If the operation is + successful, return EFI_SUCCESS. + + TODO: EFI_UNSUPPORTED - add return value to function comment + TODO: EFI_DEVICE_ERROR - add return value to function comment + TODO: EFI_DEVICE_ERROR - add return value to function comment + TODO: EFI_DEVICE_ERROR - add return value to function comment +**/ +EFI_STATUS +AtaUdmaRead ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +{ + return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadOp); +} + +/** + This function is called by the AtaBlkIoWriteBlocks() to perform + writing to media in block unit. The function has been enhanced to + support >120GB access and transfer at most 65536 blocks per command + + @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. + + @return The device status of UDMA operation. If the operation is + successful, return EFI_SUCCESS. + + TODO: EFI_UNSUPPORTED - add return value to function comment + TODO: EFI_DEVICE_ERROR - add return value to function comment + TODO: EFI_DEVICE_ERROR - add return value to function comment +**/ +EFI_STATUS +AtaUdmaWriteExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +{ + return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteExtOp); +} + +/** + This function is called by the AtaBlkIoWriteBlocks() to perform + writing to media in block unit. The function has been enhanced to + support >120GB access and transfer at most 65536 blocks per command + + @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. + + @return The device status of UDMA operation. If the operation is + successful, return EFI_SUCCESS. + + TODO: EFI_UNSUPPORTED - add return value to function comment + TODO: EFI_DEVICE_ERROR - add return value to function comment + TODO: EFI_DEVICE_ERROR - add return value to function comment +**/ +EFI_STATUS +AtaUdmaWrite ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +{ + 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 // Device = (UINT8) ((IdeDev->Device << 4) | 0xe0); @@ -2158,13 +2333,13 @@ AtaUdmaReadExt ( RemainBlockNum = NumberOfBlocks; while (RemainBlockNum > 0) { - if (RemainBlockNum >= MAX_DMA_EXT_COMMAND_SECTORS) { + if (RemainBlockNum >= MaxDmaCommandSectors) { // // 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; + NumberOfBlocks = MaxDmaCommandSectors; + RemainBlockNum -= MaxDmaCommandSectors; } else { NumberOfBlocks = (UINT16) RemainBlockNum; RemainBlockNum = 0; @@ -2182,20 +2357,19 @@ AtaUdmaReadExt ( // 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 // @@ -2213,17 +2387,17 @@ AtaUdmaReadExt ( // Build the PRD table // Status = IdeDev->PciIo->Map ( - IdeDev->PciIo, - EfiPciIoOperationBusMasterWrite, - 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 = (VOID *) ((UINTN) DeviceAddress); TempPrdAddr = UsedPrdAddr; while (TRUE) { @@ -2269,7 +2443,11 @@ AtaUdmaReadExt ( &RegisterValue ); - RegisterValue |= BMIC_nREAD; + if (UdmaOp == AtaUdmaReadExtOp || UdmaOp == AtaUdmaReadOp) { + RegisterValue |= BMIC_nREAD; + } else { + RegisterValue &= ~((UINT8) BMIC_nREAD); + } IdeDev->PciIo->Io.Write ( IdeDev->PciIo, @@ -2292,7 +2470,7 @@ AtaUdmaReadExt ( &RegisterValue ); - RegisterValue |= BMIS_INTERRUPT | BMIS_ERROR; + RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR); IdeDev->PciIo->Io.Write ( IdeDev->PciIo, @@ -2303,17 +2481,26 @@ AtaUdmaReadExt ( &RegisterValue ); - // - // Issue READ DMA EXT command - // - Status = AtaCommandIssueExt ( - IdeDev, - READ_DMA_EXT_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); @@ -2440,1098 +2627,4 @@ AtaUdmaReadExt ( IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); return EFI_SUCCESS; -} - -/** - This function is called by the AtaBlkIoReadBlocks() to perform - reading from media in block unit. The function has been enhanced to - support >120GB access and transfer at most 65536 blocks per command - - @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 destination buffer for the data. - @param[in] StartLba The starting logical block address to read from - on the device media. - @param[in] NumberOfBlocks The number of transfer data blocks. - - @return The device status of UDMA operation. If the operation is - successful, return EFI_SUCCESS. - - TODO: EFI_UNSUPPORTED - add return value to function comment - TODO: EFI_DEVICE_ERROR - add return value to function comment - TODO: EFI_DEVICE_ERROR - add return value to function comment - TODO: EFI_DEVICE_ERROR - add return value to function comment -**/ -EFI_STATUS -AtaUdmaRead ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA StartLba, - 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; -} - -/** - This function is called by the AtaBlkIoWriteBlocks() to perform - writing to media in block unit. The function has been enhanced to - support >120GB access and transfer at most 65536 blocks per command - - @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. - - @return The device status of UDMA operation. If the operation is - successful, return EFI_SUCCESS. - - TODO: EFI_UNSUPPORTED - add return value to function comment - TODO: EFI_DEVICE_ERROR - add return value to function comment - TODO: EFI_DEVICE_ERROR - add return value to function comment -**/ -EFI_STATUS -AtaUdmaWriteExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA StartLba, - 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; -} - -/** - This function is called by the AtaBlkIoWriteBlocks() to perform - writing to media in block unit. The function has been enhanced to - support >120GB access and transfer at most 65536 blocks per command - - @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. - - @return The device status of UDMA operation. If the operation is - successful, return EFI_SUCCESS. - - TODO: EFI_UNSUPPORTED - add return value to function comment - TODO: EFI_DEVICE_ERROR - add return value to function comment - TODO: EFI_DEVICE_ERROR - add return value to function comment -**/ -EFI_STATUS -AtaUdmaWrite ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA StartLba, - 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 - // - 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, - 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 command - // - Status = AtaCommandIssue ( - IdeDev, - WRITE_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 - ); - - 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; -} +} \ 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 @@ -1097,6 +1097,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 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 // -- 2.39.2