/** @file\r
Header file for AHCI mode of ATA host controller.\r
\r
- Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials \r
are licensed and made available under the terms and conditions of the BSD License \r
which accompanies this distribution. The full text of the license may be found at \r
/**\r
This function is used to send out ATA commands conforms to the PIO Data In Protocol.\r
\r
- @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
- @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
- @param Buffer A pointer to the source buffer for the data.\r
- @param ByteCount The length of the data.\r
- @param Read Flag used to determine the data transfer direction.\r
- Read equals 1, means data transferred from device to host;\r
- Read equals 0, means data transferred from host to device. \r
- @param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
- @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
- @param Timeout The time to complete the command.\r
+ @param[in] PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data\r
+ structure.\r
+ @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
+ @param[in, out] Buffer A pointer to the source buffer for the data.\r
+ @param[in] ByteCount The length of the data.\r
+ @param[in] Read Flag used to determine the data transfer direction.\r
+ Read equals 1, means data transferred from device\r
+ to host;Read equals 0, means data transferred\r
+ from host to device.\r
+ @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
+ @param[in] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
+ @param[in] Timeout The time to complete the command.\r
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
+ used by non-blocking mode.\r
\r
@retval EFI_SUCCESS send out the ATA command and device send required data successfully.\r
@retval EFI_DEVICE_ERROR command sent failed.\r
IN BOOLEAN Read,\r
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
- IN UINT64 Timeout\r
+ IN UINT64 Timeout,\r
+ IN ATA_NONBLOCK_TASK *Task\r
)\r
{\r
UINTN WordCount;\r
//\r
DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);\r
\r
+ //\r
+ // Not support the Non-blocking now,just do the blocking process.\r
+ //\r
return Status;\r
}\r
\r
/**\r
Send ATA command into device with NON_DATA protocol\r
\r
- @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
- @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
- @param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
- @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
- @param Timeout The time to complete the command.\r
+ @param[in] PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE\r
+ data structure.\r
+ @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
+ @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data\r
+ structure.\r
+ @param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
+ @param[in] Timeout The time to complete the command.\r
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
+ used by non-blocking mode.\r
\r
@retval EFI_SUCCESS Reading succeed\r
@retval EFI_ABORTED Command failed\r
IN EFI_IDE_REGISTERS *IdeRegisters,\r
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
- IN UINT64 Timeout\r
+ IN UINT64 Timeout,\r
+ IN ATA_NONBLOCK_TASK *Task\r
)\r
{\r
EFI_STATUS Status;\r
// Dump All Ide registers to ATA_STATUS_BLOCK\r
//\r
DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);\r
+ \r
+ //\r
+ // Not support the Non-blocking now,just do the blocking process.\r
+ //\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Wait for memory to be set.\r
+ \r
+ @param[in] PciIo The PCI IO protocol instance.\r
+ @param[in] PortNum The IDE Port number.\r
+\r
+ @retval EFI_DEVICE_ERROR The memory is not set.\r
+ @retval EFI_TIMEOUT The memory setting is time out.\r
+ @retval EFI_SUCCESS The memory is correct set.\r
+\r
+**/\r
+EFI_STATUS\r
+AtaUdmStatusWait (\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN UINT16 PortNum\r
+ ) \r
+{\r
+ UINT8 RegisterValue;\r
+ EFI_STATUS Status;\r
+ UINT64 Timeout;\r
+\r
+ Timeout = 2000;\r
+\r
+ while (TRUE) {\r
+ RegisterValue = IdeReadPortB (PciIo, PortNum);\r
+\r
+ if (((RegisterValue & BMIS_ERROR) != 0) || (Timeout == 0)) {\r
+ DEBUG ((EFI_D_ERROR, "ATA UDMA operation fails\n"));\r
+ Status = EFI_DEVICE_ERROR;\r
+ break;\r
+ }\r
+\r
+ if ((RegisterValue & BMIS_INTERRUPT) != 0) {\r
+ Status = EFI_SUCCESS;\r
+ DEBUG ((DEBUG_INFO, "Task->RetryTimes = %x\n", Timeout)); \r
+ break;\r
+ }\r
+ //\r
+ // Stall for 1 milliseconds.\r
+ //\r
+ MicroSecondDelay (1000);\r
+ Timeout--;\r
+ }\r
\r
return Status;\r
}\r
\r
+/**\r
+ Check if the memory to be set.\r
+ \r
+ @param[in] PciIo The PCI IO protocol instance.\r
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
+ used by non-blocking mode.\r
+ @param[in] PortForBit The bit to be checked.\r
+\r
+ @retval EFI_DEVICE_ERROR The memory setting met a issue.\r
+ @retval EFI_NOT_READY The memory is not set.\r
+ @retval EFI_TIMEOUT The memory setting is time out.\r
+ @retval EFI_SUCCESS The memory is correct set.\r
+\r
+**/\r
+EFI_STATUS\r
+AtaUdmStatusCheck (\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN ATA_NONBLOCK_TASK *Task,\r
+ IN UINT16 PortForBit\r
+ )\r
+{\r
+ UINT8 RegisterValue;\r
+\r
+ Task->RetryTimes--;\r
+ RegisterValue = IdeReadPortB(PciIo, PortForBit);\r
+\r
+ if ((RegisterValue & BMIS_ERROR) != 0) {\r
+ DEBUG ((EFI_D_ERROR, "ATA UDMA operation fails\n"));\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ if ((RegisterValue & BMIS_INTERRUPT) != 0) {\r
+ DEBUG ((DEBUG_INFO, "Task->RetryTimes = %x\n", Task->RetryTimes));\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (Task->RetryTimes == 0) {\r
+ return EFI_TIMEOUT;\r
+ } else {\r
+ //\r
+ // The memory is not set.\r
+ //\r
+ return EFI_NOT_READY;\r
+ }\r
+}\r
\r
/**\r
Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).\r
\r
- @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
- @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
- @param Read Flag used to determine the data transfer direction.\r
- Read equals 1, means data transferred from device to host;\r
- Read equals 0, means data transferred from host to device.\r
- @param DataBuffer A pointer to the source buffer for the data.\r
- @param DataLength The length of the data.\r
- @param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
- @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
- @param Timeout The time to complete the command.\r
+ @param[in] Instance A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data\r
+ structure.\r
+ @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
+ @param[in] Read Flag used to determine the data transfer\r
+ direction. Read equals 1, means data transferred\r
+ from device to host;Read equals 0, means data\r
+ transferred from host to device.\r
+ @param[in] DataBuffer A pointer to the source buffer for the data.\r
+ @param[in] DataLength The length of the data.\r
+ @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
+ @param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
+ @param[in] Timeout The time to complete the command.\r
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
+ used by non-blocking mode.\r
\r
@retval EFI_SUCCESS the operation is successful.\r
@retval EFI_OUT_OF_RESOURCES Build PRD table failed\r
EFI_STATUS\r
EFIAPI\r
AtaUdmaInOut (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN EFI_IDE_REGISTERS *IdeRegisters,\r
- IN BOOLEAN Read,\r
- IN VOID *DataBuffer,\r
- IN UINT64 DataLength,\r
- IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
- IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
- IN UINT64 Timeout\r
+ IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,\r
+ IN EFI_IDE_REGISTERS *IdeRegisters,\r
+ IN BOOLEAN Read,\r
+ IN VOID *DataBuffer,\r
+ IN UINT64 DataLength,\r
+ IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
+ IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
+ IN UINT64 Timeout,\r
+ IN ATA_NONBLOCK_TASK *Task\r
)\r
{\r
EFI_STATUS Status;\r
UINT16 IoPortForBmis;\r
UINT16 IoPortForBmid;\r
\r
- UINT8 RegisterValue;\r
-\r
- EFI_ATA_DMA_PRD *PrdBaseAddr;\r
- UINTN PrdTableNum;\r
UINTN PrdTableSize;\r
EFI_PHYSICAL_ADDRESS PrdTableMapAddr;\r
VOID *PrdTableMap;\r
+ EFI_ATA_DMA_PRD *PrdBaseAddr;\r
+ UINTN PrdTableNum;\r
\r
+ UINT8 RegisterValue;\r
UINTN PageCount;\r
UINTN ByteCount;\r
UINTN ByteRemaining;\r
-\r
UINT8 DeviceControl;\r
\r
VOID *BufferMap;\r
\r
UINT8 DeviceHead;\r
UINT8 AtaCommand;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_TPL OldTpl;\r
\r
- Status = EFI_SUCCESS;\r
- PrdBaseAddr = NULL;\r
+\r
+ Status = EFI_SUCCESS;\r
+ PrdBaseAddr = NULL;\r
+ PrdTableMap = NULL;\r
+ BufferMap = NULL;\r
+ PageCount = 0;\r
+ PciIo = Instance->PciIo;\r
\r
if ((PciIo == NULL) || (IdeRegisters == NULL) || (DataBuffer == NULL) || (AtaCommandBlock == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ //\r
+ // Before starting the Blocking BlockIO operation, push to finish all non-blocking\r
+ // BlockIO tasks.\r
+ // Delay 1ms to simulate the blocking time out checking.\r
+ //\r
+ while ((Task == NULL) && (!IsListEmpty (&Instance->NonBlockingTaskList))) {\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ AsyncNonBlockingTransferRoutine (NULL, Instance);\r
+ gBS->RestoreTPL (OldTpl);\r
+ //\r
+ // Stall for 1 milliseconds.\r
+ //\r
+ MicroSecondDelay (1000);\r
+ } \r
+\r
//\r
// The data buffer should be even alignment\r
//\r
}\r
\r
//\r
- // Calculate the number of PRD entry.\r
- // Every entry in PRD table can specify a 64K memory region.\r
+ // Set relevant IO Port address.\r
//\r
- PrdTableNum = (UINTN)(RShiftU64(DataLength, 16) + 1);\r
+ IoPortForBmic = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIC_OFFSET);\r
+ IoPortForBmis = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIS_OFFSET);\r
+ IoPortForBmid = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMID_OFFSET);\r
\r
//\r
- // Make sure that the memory region of PRD table is not cross 64K boundary\r
- //\r
- PrdTableSize = PrdTableNum * sizeof (EFI_ATA_DMA_PRD);\r
- if (PrdTableSize > 0x10000) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
+ // For Blocking mode, start the command. \r
+ // For non-blocking mode, when the command is not started, start it, otherwise\r
+ // go to check the status.\r
+ // \r
+ if (((Task != NULL) && (!Task->IsStart)) || (Task == NULL)) {\r
+ //\r
+ // Calculate the number of PRD entry.\r
+ // Every entry in PRD table can specify a 64K memory region.\r
+ //\r
+ PrdTableNum = (UINTN)(RShiftU64(DataLength, 16) + 1);\r
\r
- //\r
- // Allocate buffer for PRD table initialization.\r
- //\r
- PageCount = EFI_SIZE_TO_PAGES (PrdTableSize);\r
- Status = PciIo->AllocateBuffer (\r
- PciIo,\r
- AllocateAnyPages,\r
- EfiBootServicesData,\r
- PageCount,\r
- (VOID **)&PrdBaseAddr,\r
- 0\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
+ //\r
+ // Make sure that the memory region of PRD table is not cross 64K boundary\r
+ //\r
+ PrdTableSize = PrdTableNum * sizeof (EFI_ATA_DMA_PRD);\r
+ if (PrdTableSize > 0x10000) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
- ByteCount = EFI_PAGES_TO_SIZE (PageCount);\r
- Status = PciIo->Map (\r
- PciIo,\r
- EfiPciIoOperationBusMasterCommonBuffer,\r
- PrdBaseAddr,\r
- &ByteCount,\r
- &PrdTableMapAddr,\r
- &PrdTableMap\r
- );\r
- if (EFI_ERROR (Status) || (ByteCount != EFI_PAGES_TO_SIZE (PageCount))) {\r
- //\r
- // If the data length actually mapped is not equal to the requested amount,\r
- // it means the DMA operation may be broken into several discontinuous smaller chunks.\r
- // Can't handle this case.\r
- //\r
- PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
+ //\r
+ // Allocate buffer for PRD table initialization.\r
+ //\r
+ PageCount = EFI_SIZE_TO_PAGES (PrdTableSize);\r
+ Status = PciIo->AllocateBuffer (\r
+ PciIo,\r
+ AllocateAnyPages,\r
+ EfiBootServicesData,\r
+ PageCount,\r
+ (VOID **)&PrdBaseAddr,\r
+ 0\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
\r
- ZeroMem ((VOID *) ((UINTN) PrdBaseAddr), ByteCount);\r
+ ByteCount = EFI_PAGES_TO_SIZE (PageCount);\r
+ Status = PciIo->Map (\r
+ PciIo,\r
+ EfiPciIoOperationBusMasterCommonBuffer,\r
+ PrdBaseAddr,\r
+ &ByteCount,\r
+ &PrdTableMapAddr,\r
+ &PrdTableMap\r
+ );\r
+ if (EFI_ERROR (Status) || (ByteCount != EFI_PAGES_TO_SIZE (PageCount))) {\r
+ //\r
+ // If the data length actually mapped is not equal to the requested amount,\r
+ // it means the DMA operation may be broken into several discontinuous smaller chunks.\r
+ // Can't handle this case.\r
+ //\r
+ PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
\r
- //\r
- // Map the host address of DataBuffer to DMA master address.\r
- //\r
- if (Read) {\r
- PciIoOperation = EfiPciIoOperationBusMasterWrite;\r
- } else {\r
- PciIoOperation = EfiPciIoOperationBusMasterRead;\r
- }\r
+ ZeroMem ((VOID *) ((UINTN) PrdBaseAddr), ByteCount);\r
\r
- ByteCount = (UINTN)DataLength;\r
- Status = PciIo->Map (\r
- PciIo,\r
- PciIoOperation,\r
- DataBuffer,\r
- &ByteCount,\r
- &BufferMapAddress,\r
- &BufferMap\r
- );\r
- if (EFI_ERROR (Status) || (ByteCount != DataLength)) {\r
- PciIo->Unmap (PciIo, PrdTableMap);\r
- PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
+ //\r
+ // Map the host address of DataBuffer to DMA master address.\r
+ //\r
+ if (Read) {\r
+ PciIoOperation = EfiPciIoOperationBusMasterWrite;\r
+ } else {\r
+ PciIoOperation = EfiPciIoOperationBusMasterRead;\r
+ }\r
\r
- //\r
- // According to Ata spec, it requires the buffer address and size to be even.\r
- //\r
- ASSERT ((BufferMapAddress & 0x1) == 0);\r
- ASSERT ((ByteCount & 0x1) == 0);\r
+ ByteCount = (UINTN)DataLength;\r
+ Status = PciIo->Map (\r
+ PciIo,\r
+ PciIoOperation,\r
+ DataBuffer,\r
+ &ByteCount,\r
+ &BufferMapAddress,\r
+ &BufferMap\r
+ );\r
+ if (EFI_ERROR (Status) || (ByteCount != DataLength)) {\r
+ PciIo->Unmap (PciIo, PrdTableMap);\r
+ PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // According to Ata spec, it requires the buffer address and size to be even.\r
+ //\r
+ ASSERT ((BufferMapAddress & 0x1) == 0);\r
+ ASSERT ((ByteCount & 0x1) == 0);\r
+\r
+ //\r
+ // Fill the PRD table with appropriate bus master address of data buffer and data length.\r
+ //\r
+ ByteRemaining = ByteCount;\r
+ while (ByteRemaining != 0) {\r
+ if (ByteRemaining <= 0x10000) {\r
+ PrdBaseAddr->RegionBaseAddr = (UINT32) ((UINTN) BufferMapAddress);\r
+ PrdBaseAddr->ByteCount = (UINT16) ByteRemaining;\r
+ PrdBaseAddr->EndOfTable = 0x8000;\r
+ break;\r
+ }\r
\r
- //\r
- // Fill the PRD table with appropriate bus master address of data buffer and data length.\r
- //\r
- ByteRemaining = ByteCount;\r
- while (ByteRemaining != 0) {\r
- if (ByteRemaining <= 0x10000) {\r
PrdBaseAddr->RegionBaseAddr = (UINT32) ((UINTN) BufferMapAddress);\r
- PrdBaseAddr->ByteCount = (UINT16) ByteRemaining;\r
- PrdBaseAddr->EndOfTable = 0x8000;\r
- break;\r
- }\r
+ PrdBaseAddr->ByteCount = (UINT16) 0x0;\r
\r
- PrdBaseAddr->RegionBaseAddr = (UINT32) ((UINTN) BufferMapAddress);\r
- PrdBaseAddr->ByteCount = (UINT16) 0x0;\r
+ ByteRemaining -= 0x10000;\r
+ BufferMapAddress += 0x10000;\r
+ PrdBaseAddr++;\r
+ }\r
\r
- ByteRemaining -= 0x10000;\r
- BufferMapAddress += 0x10000;\r
- PrdBaseAddr++;\r
- }\r
+ //\r
+ // Start to enable the DMA operation\r
+ //\r
+ DeviceHead = AtaCommandBlock->AtaDeviceHead;\r
+ AtaCommand = AtaCommandBlock->AtaCommand;\r
\r
- //\r
- // Start to enable the DMA operation\r
- //\r
- DeviceHead = AtaCommandBlock->AtaDeviceHead;\r
- AtaCommand = AtaCommandBlock->AtaCommand;\r
+ IdeWritePortB (PciIo, IdeRegisters->Head, (UINT8)(0xe0 | DeviceHead));\r
\r
- IdeWritePortB (PciIo, IdeRegisters->Head, (UINT8)(0xe0 | DeviceHead));\r
+ //\r
+ // Enable interrupt to support UDMA\r
+ //\r
+ DeviceControl = 0;\r
+ IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);\r
\r
- //\r
- // Enable interrupt to support UDMA\r
- //\r
- DeviceControl = 0;\r
- IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);\r
+ //\r
+ // Read BMIS register and clear ERROR and INTR bit\r
+ //\r
+ RegisterValue = IdeReadPortB(PciIo, IoPortForBmis);\r
+ RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
+ IdeWritePortB(PciIo, IoPortForBmis, RegisterValue);\r
\r
- IoPortForBmic = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIC_OFFSET);\r
- IoPortForBmis = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIS_OFFSET);\r
- IoPortForBmid = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMID_OFFSET);\r
+ //\r
+ // Set the base address to BMID register\r
+ //\r
+ IdeWritePortDW (PciIo, IoPortForBmid, (UINT32)PrdTableMapAddr);\r
\r
- //\r
- // Read BMIS register and clear ERROR and INTR bit\r
- //\r
- RegisterValue = IdeReadPortB(PciIo, IoPortForBmis);\r
- RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
- IdeWritePortB(PciIo, IoPortForBmis, RegisterValue);\r
+ //\r
+ // Set BMIC register to identify the operation direction\r
+ //\r
+ RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);\r
+ if (Read) {\r
+ RegisterValue |= BMIC_NREAD;\r
+ } else {\r
+ RegisterValue &= ~((UINT8) BMIC_NREAD);\r
+ }\r
+ IdeWritePortB (PciIo, IoPortForBmic, RegisterValue);\r
\r
- //\r
- // Set the base address to BMID register\r
- //\r
- IdeWritePortDW(PciIo, IoPortForBmid, (UINT32)PrdTableMapAddr);\r
+ //\r
+ // Issue ATA command\r
+ //\r
+ Status = AtaIssueCommand (PciIo, IdeRegisters, AtaCommandBlock, Timeout);\r
\r
- //\r
- // Set BMIC register to identify the operation direction\r
- //\r
- RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);\r
- if (Read) {\r
- RegisterValue |= BMIC_NREAD;\r
- } else {\r
- RegisterValue &= ~((UINT8) BMIC_NREAD);\r
- }\r
- IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
\r
- //\r
- // Issue ATA command\r
- //\r
- Status = AtaIssueCommand (PciIo, IdeRegisters, AtaCommandBlock, Timeout);\r
+ //\r
+ // Set START bit of BMIC register\r
+ //\r
+ RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);\r
+ RegisterValue |= BMIC_START;\r
+ IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);\r
\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto Exit;\r
+ if (Task != NULL) {\r
+ //\r
+ // Max transfer number of sectors for one command is 65536(32Mbyte),\r
+ // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).\r
+ // So set the variable Count to 2000, for about 2 second Timeout time.\r
+ //\r
+ Task->RetryTimes = 2000;\r
+ Task->Map = BufferMap;\r
+ Task->TableMap = PrdTableMap;\r
+ Task->MapBaseAddress = PrdBaseAddr;\r
+ Task->PageCount = PageCount;\r
+ Task->IsStart = TRUE;\r
+ }\r
}\r
\r
- //\r
- // Set START bit of BMIC register\r
- //\r
- RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);\r
- RegisterValue |= BMIC_START;\r
- IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);\r
-\r
//\r
// Check the INTERRUPT and ERROR bit of BMIS\r
// Max transfer number of sectors for one command is 65536(32Mbyte),\r
// it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).\r
// So set the variable Count to 2000, for about 2 second Timeout time.\r
//\r
- Timeout = 2000;\r
- while (TRUE) {\r
- RegisterValue = IdeReadPortB(PciIo, IoPortForBmis);\r
-\r
- if (((RegisterValue & BMIS_ERROR) != 0) || (Timeout == 0)) {\r
- DEBUG ((EFI_D_ERROR, "ATA UDMA operation fails\n"));\r
- Status = EFI_DEVICE_ERROR;\r
- break;\r
- }\r
-\r
- if ((RegisterValue & BMIS_INTERRUPT) != 0) {\r
- Status = EFI_SUCCESS;\r
- break;\r
- }\r
- //\r
- // Stall for 1 milliseconds.\r
- //\r
- MicroSecondDelay (1000);\r
- Timeout--;\r
+ if (Task != NULL) {\r
+ Status = AtaUdmStatusCheck (PciIo, Task, IoPortForBmis);\r
+ } else {\r
+ Status = AtaUdmStatusWait (PciIo, IoPortForBmis);\r
}\r
\r
//\r
- // Read BMIS register and clear ERROR and INTR bit\r
+ // For blocking mode, clear registers and free buffers.\r
+ // For non blocking mode, when the related registers have been set or time\r
+ // out, or a error has been happened, it needs to clear the register and free\r
+ // buffer.\r
//\r
- RegisterValue = IdeReadPortB(PciIo, IoPortForBmis);\r
- RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
- IdeWritePortB(PciIo, IoPortForBmis, RegisterValue);\r
+ if ((Task == NULL) || Status != EFI_NOT_READY) {\r
+ //\r
+ // Read BMIS register and clear ERROR and INTR bit\r
+ //\r
+ RegisterValue = IdeReadPortB (PciIo, IoPortForBmis);\r
+ RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
+ IdeWritePortB (PciIo, IoPortForBmis, RegisterValue);\r
\r
- //\r
- // Read Status Register of IDE device to clear interrupt\r
- //\r
- RegisterValue = IdeReadPortB(PciIo, IdeRegisters->CmdOrStatus);\r
+ //\r
+ // Read Status Register of IDE device to clear interrupt\r
+ //\r
+ RegisterValue = IdeReadPortB(PciIo, IdeRegisters->CmdOrStatus);\r
\r
- //\r
- // Clear START bit of BMIC register\r
- //\r
- RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);\r
- RegisterValue &= ~((UINT8) BMIC_START);\r
- IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);\r
+ //\r
+ // Clear START bit of BMIC register\r
+ //\r
+ RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);\r
+ RegisterValue &= ~((UINT8) BMIC_START);\r
+ IdeWritePortB (PciIo, IoPortForBmic, RegisterValue);\r
\r
- //\r
- // Disable interrupt of Select device\r
- //\r
- DeviceControl = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);\r
- DeviceControl |= ATA_CTLREG_IEN_L;\r
- IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);\r
- //\r
- // Stall for 10 milliseconds.\r
- //\r
- MicroSecondDelay (10000);\r
+ //\r
+ // Disable interrupt of Select device\r
+ //\r
+ DeviceControl = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);\r
+ DeviceControl |= ATA_CTLREG_IEN_L;\r
+ IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);\r
+ //\r
+ // Stall for 10 milliseconds.\r
+ //\r
+ MicroSecondDelay (10000);\r
+\r
+ }\r
\r
Exit:\r
//\r
// Free all allocated resource\r
//\r
- PciIo->Unmap (PciIo, PrdTableMap);\r
- PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
- PciIo->Unmap (PciIo, BufferMap);\r
-\r
- //\r
- // Dump All Ide registers to ATA_STATUS_BLOCK\r
- //\r
- DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);\r
+ if ((Task == NULL) || Status != EFI_NOT_READY) {\r
+ if (Task != NULL) {\r
+ PciIo->Unmap (PciIo, Task->TableMap);\r
+ PciIo->FreeBuffer (PciIo, Task->PageCount, Task->MapBaseAddress);\r
+ PciIo->Unmap (PciIo, Task->Map);\r
+ } else {\r
+ PciIo->Unmap (PciIo, PrdTableMap);\r
+ PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
+ PciIo->Unmap (PciIo, BufferMap);\r
+ }\r
\r
+ //\r
+ // Dump All Ide registers to ATA_STATUS_BLOCK\r
+ //\r
+ DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);\r
+ }\r
+ \r
return Status;\r
}\r
\r
&Instance->IdeRegisters[Channel],\r
&AtaCommandBlock,\r
AtaStatusBlock,\r
- ATA_ATAPI_TIMEOUT\r
+ ATA_ATAPI_TIMEOUT,\r
+ NULL\r
);\r
\r
return Status;\r
&Instance->IdeRegisters[Channel],\r
&AtaCommandBlock,\r
AtaStatusBlock,\r
- ATA_ATAPI_TIMEOUT\r
+ ATA_ATAPI_TIMEOUT, \r
+ NULL\r
);\r
\r
//\r
&Instance->IdeRegisters[Channel],\r
&AtaCommandBlock,\r
AtaStatusBlock,\r
- ATA_ATAPI_TIMEOUT\r
+ ATA_ATAPI_TIMEOUT, \r
+ NULL\r
);\r
\r
return Status;\r
&Instance->IdeRegisters[Channel],\r
&AtaCommandBlock,\r
AtaStatusBlock,\r
- ATA_ATAPI_TIMEOUT\r
+ ATA_ATAPI_TIMEOUT,\r
+ NULL\r
);\r
\r
if (EFI_ERROR (Status)) {\r
&Instance->IdeRegisters[Channel],\r
&AtaCommandBlock,\r
AtaStatusBlock,\r
- ATA_ATAPI_TIMEOUT\r
+ ATA_ATAPI_TIMEOUT,\r
+ NULL\r
);\r
\r
if (!EFI_ERROR (Status)) {\r
&Instance->IdeRegisters[Channel],\r
&AtaCommandBlock,\r
AtaStatusBlock,\r
- ATA_ATAPI_TIMEOUT\r
+ ATA_ATAPI_TIMEOUT,\r
+ NULL\r
);\r
if (!EFI_ERROR (Status)) {\r
Status = IdeAtaSmartReturnStatusCheck (\r
return ;\r
}\r
\r
+\r
/**\r
Sends out an ATA Identify Command to the specified device.\r
\r
@retval EFI_SUCCESS Identify ATA device successfully.\r
@retval EFI_DEVICE_ERROR ATA Identify Device Command failed or device is not ATA device.\r
@retval EFI_OUT_OF_RESOURCES Allocate memory failed.\r
+\r
**/\r
EFI_STATUS\r
EFIAPI\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_ATA_COMMAND_BLOCK AtaCommandBlock; \r
+ EFI_ATA_COMMAND_BLOCK AtaCommandBlock;\r
\r
ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
- \r
+\r
AtaCommandBlock.AtaCommand = ATA_CMD_IDENTIFY_DRIVE;\r
AtaCommandBlock.AtaDeviceHead = (UINT8)(Device << 0x4);\r
\r
TRUE,\r
&AtaCommandBlock,\r
AtaStatusBlock,\r
- ATA_ATAPI_TIMEOUT\r
+ ATA_ATAPI_TIMEOUT,\r
+ NULL\r
);\r
\r
return Status;\r
TRUE,\r
&AtaCommandBlock,\r
AtaStatusBlock,\r
- ATA_ATAPI_TIMEOUT\r
+ ATA_ATAPI_TIMEOUT,\r
+ NULL\r
);\r
\r
return Status;\r
IdeInit = Instance->IdeControllerInit;\r
PciIo = Instance->PciIo;\r
\r
- for (IdeDevice = 0; IdeDevice < EfiIdeMaxDevice; IdeDevice++) { \r
+ for (IdeDevice = 0; IdeDevice < EfiIdeMaxDevice; IdeDevice++) {\r
//\r
// Send ATA Device Execut Diagnostic command.\r
// This command should work no matter DRDY is ready or not\r
if (EFI_ERROR (Status)) {\r
DeviceType = EfiIdeHarddisk;\r
Status = AtaIdentify (Instance, IdeChannel, IdeDevice, &Buffer, NULL);\r
- } \r
+ }\r
}\r
\r
if (EFI_ERROR (Status)) {\r
// No device is found at this port\r
//\r
continue;\r
- } \r
- \r
+ }\r
+\r
DEBUG ((EFI_D_INFO, "[%a] channel [%a] [%a] device\n", \r
(IdeChannel == 1) ? "secondary" : "primary ", (IdeDevice == 1) ? "slave " : "master",\r
DeviceType == EfiIdeCdrom ? "cdrom " : "harddisk"));\r
-\r
//\r
// If the device is a hard disk, then try to enable S.M.A.R.T feature\r
//\r
continue;\r
}\r
}\r
- \r
+\r
//\r
// Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't\r
// be set together. Only one DMA mode can be set to a device. If setting\r
TransferMode.ModeCategory = EFI_ATA_MODE_UDMA;\r
TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode);\r
Status = SetDeviceTransferMode (Instance, IdeChannel, IdeDevice, &TransferMode, NULL);\r
- \r
+\r
if (EFI_ERROR (Status)) {\r
DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));\r
continue;\r
TransferMode.ModeCategory = EFI_ATA_MODE_MDMA;\r
TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode;\r
Status = SetDeviceTransferMode (Instance, IdeChannel, IdeDevice, &TransferMode, NULL);\r
- \r
+\r
if (EFI_ERROR (Status)) {\r
DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));\r
continue;\r
}\r
}\r
- \r
+\r
//\r
// Set Parameters for the device:\r
// 1) Init\r
DriveParameters.Sector = (UINT8) ((ATA5_IDENTIFY_DATA *)(&Buffer.AtaData))->sectors_per_track;\r
DriveParameters.Heads = (UINT8) (((ATA5_IDENTIFY_DATA *)(&Buffer.AtaData))->heads - 1);\r
DriveParameters.MultipleSector = (UINT8) ((ATA5_IDENTIFY_DATA *)(&Buffer.AtaData))->multi_sector_cmd_max_sct_cnt;\r
- \r
+\r
Status = SetDriveParameters (Instance, IdeChannel, IdeDevice, &DriveParameters, NULL);\r
}\r
- \r
+\r
//\r
// Set IDE controller Timing Blocks in the PCI Configuration Space\r
//\r