From 630d580d530d3154ad90eee3f3688ab00b335275 Mon Sep 17 00:00:00 2001 From: jchen20 Date: Wed, 24 Jun 2009 02:21:05 +0000 Subject: Code scrub for IdeBusDxe driver git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8636 6f19259b-4bc3-4df7-8a09-765794883524 --- IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ata.c | 3234 ++++++++++---------- IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Atapi.c | 1382 ++++----- .../Bus/Pci/IdeBusDxe/ComponentName.c | 2 + .../Bus/Pci/IdeBusDxe/ComponentName.h | 11 +- .../Bus/Pci/IdeBusDxe/DriverConfiguration.c | 188 +- .../Bus/Pci/IdeBusDxe/DriverDiagnostics.c | 87 +- IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.c | 931 ++---- IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.h | 1200 +++----- IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c | 413 +-- IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.h | 364 ++- 10 files changed, 3449 insertions(+), 4363 deletions(-) (limited to 'IntelFrameworkModulePkg') diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ata.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ata.c index 87d466f9d0..98d9323ea7 100644 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ata.c +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ata.c @@ -1,4 +1,6 @@ /** @file + This file contains all helper functions on the ATA command + Copyright (c) 2006 - 2008, Intel Corporation.
All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -22,7 +24,234 @@ **/ #include "IdeBus.h" +/** + This function is called by ATAIdentify() to identity whether this disk + supports ATA/ATAPI6 48bit addressing, ie support >120G capacity + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + + @retval EFI_SUCCESS The disk specified by IdeDev is a Atapi6 supported one and + 48-bit addressing must be used + @retval EFI_UNSUPPORTED The disk dosn't not support Atapi6 or it supports but the + capacity is below 120G, 48bit addressing is not needed + @retval EFI_DEVICE_ERROR The identify data in IdeDev is incorrect + @retval EFI_INVALID_PARAMETER The identify data in IdeDev is NULL. + + @note This function must be called after DEVICE_IDENTITY command has been + successfully returned + +**/ +EFI_STATUS +AtaAtapi6Identify ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + UINT8 Index; + EFI_LBA TmpLba; + EFI_LBA Capacity; + EFI_IDENTIFY_DATA *Atapi6IdentifyStruct; + + if (IdeDev->IdData == NULL) { + return EFI_INVALID_PARAMETER; + } + + Atapi6IdentifyStruct = IdeDev->IdData; + + if ((Atapi6IdentifyStruct->AtapiData.cmd_set_support_83 & (BIT15 | BIT14)) != 0x4000) { + // + // Per ATA-6 spec, word83: bit15 is zero and bit14 is one + // + return EFI_DEVICE_ERROR; + } + + if ((Atapi6IdentifyStruct->AtapiData.cmd_set_support_83 & BIT10) == 0) { + // + // The device dosn't support 48 bit addressing + // + return EFI_UNSUPPORTED; + } + + // + // 48 bit address feature set is supported, get maximum capacity + // + Capacity = Atapi6IdentifyStruct->AtapiData.max_user_lba_for_48bit_addr[0]; + for (Index = 1; Index < 4; Index++) { + // + // Lower byte goes first: word[100] is the lowest word, word[103] is highest + // + TmpLba = Atapi6IdentifyStruct->AtapiData.max_user_lba_for_48bit_addr[Index]; + Capacity |= LShiftU64 (TmpLba, 16 * Index); + } + + if (Capacity > MAX_28BIT_ADDRESSING_CAPACITY) { + // + // Capacity exceeds 120GB. 48-bit addressing is really needed + // + IdeDev->Type = Ide48bitAddressingHardDisk; + + // + // Fill block media information:Media->LogicalPartition , + // Media->WriteCaching will be filledin the DiscoverIdeDevcie() function. + // + IdeDev->BlkIo.Media->IoAlign = 4; + IdeDev->BlkIo.Media->MediaId = 1; + IdeDev->BlkIo.Media->RemovableMedia = FALSE; + IdeDev->BlkIo.Media->MediaPresent = TRUE; + IdeDev->BlkIo.Media->ReadOnly = FALSE; + IdeDev->BlkIo.Media->BlockSize = 0x200; + IdeDev->BlkIo.Media->LastBlock = Capacity - 1; + + return EFI_SUCCESS; + } + + return EFI_UNSUPPORTED; +} +/** + Enable SMART of the disk if supported + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to record + all the information of the IDE device. +**/ +VOID +AtaSMARTSupport ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + EFI_STATUS Status; + BOOLEAN SMARTSupported; + UINT8 Device; + EFI_IDENTIFY_DATA *TmpAtaIdentifyPointer; + UINT8 DeviceSelect; + UINT8 LBAMid; + UINT8 LBAHigh; + + // + // Detect if the device supports S.M.A.R.T. + // + if ((IdeDev->IdData->AtaData.command_set_supported_83 & 0xc000) != 0x4000) { + // + // Data in word 82 is not valid (bit15 shall be zero and bit14 shall be to one) + // + return ; + } else { + if ((IdeDev->IdData->AtaData.command_set_supported_82 & 0x0001) != 0x0001) { + // + // S.M.A.R.T is not supported by the device + // + SMARTSupported = FALSE; + } else { + SMARTSupported = TRUE; + } + } + + if (!SMARTSupported) { + // + // Report nonsupport status code + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED) + ); + } else { + // + // Enable this feature + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_ENABLE) + ); + + Device = (UINT8) ((IdeDev->Device << 4) | 0xe0); + Status = AtaNonDataCommandIn ( + IdeDev, + ATA_CMD_SMART, + Device, + ATA_SMART_ENABLE_OPERATION, + 0, + 0, + ATA_CONSTANT_4F, + ATA_CONSTANT_C2 + ); + // + // Detect if this feature is enabled + // + TmpAtaIdentifyPointer = (EFI_IDENTIFY_DATA *) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA)); + if (TmpAtaIdentifyPointer == NULL) { + return; + } + + DeviceSelect = (UINT8) ((IdeDev->Device) << 4); + Status = AtaPioDataIn ( + IdeDev, + (VOID *) TmpAtaIdentifyPointer, + sizeof (EFI_IDENTIFY_DATA), + ATA_CMD_IDENTIFY_DRIVE, + DeviceSelect, + 0, + 0, + 0, + 0 + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (TmpAtaIdentifyPointer); + return ; + } + + // + // Check if the feature is enabled + // + if ((TmpAtaIdentifyPointer->AtaData.command_set_feature_enb_85 & 0x0001) == 0x0001) { + // + // Read status data + // + AtaNonDataCommandIn ( + IdeDev, + ATA_CMD_SMART, + Device, + ATA_SMART_RETURN_STATUS, + 0, + 0, + ATA_CONSTANT_4F, + ATA_CONSTANT_C2 + ); + LBAMid = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb); + LBAHigh = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb); + + if ((LBAMid == 0x4f) && (LBAHigh == 0xc2)) { + // + // The threshold exceeded condition is not detected by the device + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD) + ); + } else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) { + // + // The threshold exceeded condition is detected by the device + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD) + ); + } + + } else { + // + // Report disabled status code + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLED) + ); + } + + gBS->FreePool (TmpAtaIdentifyPointer); + } + + return ; +} /** Sends out an ATA Identify Command to the specified device. @@ -34,17 +263,12 @@ information it needs to fill the IDE_BLK_IO_DEV data structure, including device type, media block size, media capacity, and etc. - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure,used - to record all the information of the IDE device. - - @retval EFI_SUCCESS Identify ATA device successfully. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to record + all the information of the IDE device. - @retval EFI_DEVICE_ERROR ATA Identify Device Command failed or - device is not ATA device. - - @note - parameter IdeDev will be updated in this function. + @retval EFI_SUCCESS Identify ATA device successfully. + @retval EFI_DEVICE_ERROR ATA Identify Device Command failed or device is not ATA device. + @note parameter IdeDev will be updated in this function. **/ EFI_STATUS @@ -178,153 +402,71 @@ ATAIdentify ( return EFI_DEVICE_ERROR; } - /** - This function is called by ATAIdentify() to identity whether this disk - supports ATA/ATAPI6 48bit addressing, ie support >120G capacity - - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @retval EFI_SUCCESS The disk specified by IdeDev is a Atapi6 supported one - and 48-bit addressing must be used - - @retval EFI_UNSUPPORTED The disk dosn't not support Atapi6 or it supports but - the capacity is below 120G, 48bit addressing is not needed + This function is a helper function used to change the char order in a string. It + is designed specially for the PrintAtaModuleName() function. After the IDE device + is detected, the IDE driver gets the device module name by sending ATA command + called ATA Identify Command or ATAPI Identify Command to the specified IDE device. + The module name returned is a string of ASCII characters: the first character is bit8--bit15 + of the first word, the second character is BIT0--bit7 of the first word and so on. Thus + the string can not be print directly before it is preprocessed by this func to change + the order of characters in each word in the string. + + @param Destination Indicates the destination string. + @param Source Indicates the source string. + @param Size the length of the string +**/ +VOID +SwapStringChars ( + IN CHAR8 *Destination, + IN CHAR8 *Source, + IN UINT32 Size + ) +{ + UINT32 Index; + CHAR8 Temp; - @retval EFI_DEVICE_ERROR The identify data in IdeDev is incorrect - - @retval EFI_INVALID_PARAMETER The identify data in IdeDev is NULL. + for (Index = 0; Index < Size; Index += 2) { - @note - This function must be called after DEVICE_IDENTITY command has been - successfully returned + Temp = Source[Index + 1]; + Destination[Index + 1] = Source[Index]; + Destination[Index] = Temp; + } +} +/** + This function is called by ATAIdentify() or ATAPIIdentify() to print device's module name. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. **/ -EFI_STATUS -AtaAtapi6Identify ( +VOID +PrintAtaModuleName ( IN IDE_BLK_IO_DEV *IdeDev ) { - UINT8 Index; - EFI_LBA TmpLba; - EFI_LBA Capacity; - EFI_IDENTIFY_DATA *Atapi6IdentifyStruct; - if (IdeDev->IdData == NULL) { - return EFI_INVALID_PARAMETER; + return ; } - Atapi6IdentifyStruct = IdeDev->IdData; + SwapStringChars (IdeDev->ModelName, IdeDev->IdData->AtaData.ModelName, 40); + IdeDev->ModelName[40] = 0x00; +} - if ((Atapi6IdentifyStruct->AtapiData.cmd_set_support_83 & (BIT15 | BIT14)) != 0x4000) { - // - // Per ATA-6 spec, word83: bit15 is zero and bit14 is one - // - return EFI_DEVICE_ERROR; - } - - if ((Atapi6IdentifyStruct->AtapiData.cmd_set_support_83 & BIT10) == 0) { - // - // The device dosn't support 48 bit addressing - // - return EFI_UNSUPPORTED; - } - - // - // 48 bit address feature set is supported, get maximum capacity - // - Capacity = Atapi6IdentifyStruct->AtapiData.max_user_lba_for_48bit_addr[0]; - for (Index = 1; Index < 4; Index++) { - // - // Lower byte goes first: word[100] is the lowest word, word[103] is highest - // - TmpLba = Atapi6IdentifyStruct->AtapiData.max_user_lba_for_48bit_addr[Index]; - Capacity |= LShiftU64 (TmpLba, 16 * Index); - } - - if (Capacity > MAX_28BIT_ADDRESSING_CAPACITY) { - // - // Capacity exceeds 120GB. 48-bit addressing is really needed - // - IdeDev->Type = Ide48bitAddressingHardDisk; - - // - // Fill block media information:Media->LogicalPartition , - // Media->WriteCaching will be filledin the DiscoverIdeDevcie() function. - // - IdeDev->BlkIo.Media->IoAlign = 4; - IdeDev->BlkIo.Media->MediaId = 1; - IdeDev->BlkIo.Media->RemovableMedia = FALSE; - IdeDev->BlkIo.Media->MediaPresent = TRUE; - IdeDev->BlkIo.Media->ReadOnly = FALSE; - IdeDev->BlkIo.Media->BlockSize = 0x200; - IdeDev->BlkIo.Media->LastBlock = Capacity - 1; - - return EFI_SUCCESS; - } - - return EFI_UNSUPPORTED; -} - -/** - This function is called by ATAIdentify() or ATAPIIdentify() - to print device's module name. - - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - -**/ -VOID -PrintAtaModuleName ( - IN IDE_BLK_IO_DEV *IdeDev - ) -{ - if (IdeDev->IdData == NULL) { - return ; - } - - SwapStringChars (IdeDev->ModelName, IdeDev->IdData->AtaData.ModelName, 40); - IdeDev->ModelName[40] = 0x00; -} - -/** - This function is used to send out ATA commands conforms to the - PIO Data In Protocol. - - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @param[in] *Buffer - buffer contained data transferred from device to host. - - @param[in] ByteCount - data size in byte unit of the buffer. - - @param[in] AtaCommand - value of the Command Register - - @param[in] Head - value of the Head/Device Register - - @param[in] SectorCount - value of the Sector Count Register - - @param[in] SectorNumber - value of the Sector Number Register - - @param[in] CylinderLsb - value of the low byte of the Cylinder Register - - @param[in] CylinderMsb - value of the high byte of the Cylinder Register - - @retval EFI_SUCCESS send out the ATA command and device send required - data successfully. +/** + This function is used to send out ATA commands conforms to the PIO Data In Protocol. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @param Buffer buffer contained data transferred from device to host. + @param ByteCount data size in byte unit of the buffer. + @param AtaCommand value of the Command Register + @param Head value of the Head/Device Register + @param SectorCount value of the Sector Count Register + @param SectorNumber value of the Sector Number Register + @param CylinderLsb value of the low byte of the Cylinder Register + @param CylinderMsb value of the high byte of the Cylinder Register + + @retval EFI_SUCCESS send out the ATA command and device send required data successfully. @retval EFI_DEVICE_ERROR command sent failed. **/ @@ -461,10 +603,8 @@ AtaPioDataIn ( This function is used to send out ATA commands conforms to the PIO Data Out Protocol. - @param *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. @param *Buffer buffer contained data transferred from host to device. @param ByteCount data size in byte unit of the buffer. @param AtaCommand value of the Command Register @@ -474,9 +614,8 @@ AtaPioDataIn ( @param CylinderLsb value of the low byte of the Cylinder Register @param CylinderMsb value of the high byte of the Cylinder Register - @retval EFI_SUCCESS send out the ATA command and device received required - data successfully. - + @retval EFI_SUCCESS send out the ATA command and device received required + data successfully. @retval EFI_DEVICE_ERROR command sent failed. **/ @@ -613,9 +752,8 @@ AtaPioDataOut ( some debug information and if there is ERR bit set in the Status Register, the Error Register's value is also be parsed and print out. - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to + record all the information of the IDE device. @retval EFI_SUCCESS No err information in the Status Register. @retval EFI_DEVICE_ERROR Any err information in the Status Register. @@ -633,26 +771,26 @@ CheckErrorStatus ( DEBUG_CODE_BEGIN (); - if ((StatusRegister & ATA_STSREG_DWF) != 0) { - DEBUG ( - (EFI_D_BLKIO, - "CheckErrorStatus()-- %02x : Error : Write Fault\n", - StatusRegister) - ); - } + if ((StatusRegister & ATA_STSREG_DWF) != 0) { + DEBUG ( + (EFI_D_BLKIO, + "CheckErrorStatus()-- %02x : Error : Write Fault\n", + StatusRegister) + ); + } - if ((StatusRegister & ATA_STSREG_CORR) != 0) { - DEBUG ( - (EFI_D_BLKIO, - "CheckErrorStatus()-- %02x : Error : Corrected Data\n", - StatusRegister) - ); - } + if ((StatusRegister & ATA_STSREG_CORR) != 0) { + DEBUG ( + (EFI_D_BLKIO, + "CheckErrorStatus()-- %02x : Error : Corrected Data\n", + StatusRegister) + ); + } - if ((StatusRegister & ATA_STSREG_ERR) != 0) { - ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + if ((StatusRegister & ATA_STSREG_ERR) != 0) { + ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); - if ((ErrorRegister & ATA_ERRREG_BBK) != 0) { + if ((ErrorRegister & ATA_ERRREG_BBK) != 0) { DEBUG ( (EFI_D_BLKIO, "CheckErrorStatus()-- %02x : Error : Bad Block Detected\n", @@ -712,25 +850,16 @@ CheckErrorStatus ( } /** - This function is called by the AtaBlkIoReadBlocks() to perform - reading from media in block unit. - - @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] Lba - The starting logical block address to read from - on the device media. - - @param[in] NumberOfBlocks - The number of transfer data blocks. - - @return return status is fully dependent on the return status - of AtaPioDataIn() function. + This function is called by the AtaBlkIoReadBlocks() to perform reading from + media in block unit. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @param DataBuffer A pointer to the destination buffer for the data. + @param Lba The starting logical block address to read from on the device media. + @param NumberOfBlocks The number of transfer data blocks. + + @return status is fully dependent on the return status of AtaPioDataIn() function. **/ EFI_STATUS @@ -830,25 +959,16 @@ AtaReadSectors ( } /** - This function is called by the AtaBlkIoWriteBlocks() to perform - writing onto media in block unit. - - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure,used - to record all the information of the IDE device. - - @param[in] *BufferData - A pointer to the source buffer for the data. - - @param[in] Lba - The starting logical block address to write onto - the device media. - - @param[in] NumberOfBlocks - The number of transfer data blocks. - - @return return status is fully dependent on the return status - of AtaPioDataOut() function. + This function is called by the AtaBlkIoWriteBlocks() to perform writing onto + media in block unit. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to record + all the information of the IDE device. + @param BufferData A pointer to the source buffer for the data. + @param Lba The starting logical block address to write onto the device media. + @param NumberOfBlocks The number of transfer data blocks. + + @return status is fully dependent on the return status of AtaPioDataIn() function. **/ EFI_STATUS @@ -933,12 +1053,10 @@ AtaWriteSectors ( return Status; } - /** - This function is used to implement the Soft Reset on the specified - device. But, the ATA Soft Reset mechanism is so strong a reset method - that it will force resetting on both devices connected to the - same cable. + This function is used to implement the Soft Reset on the specified device. But, + the ATA Soft Reset mechanism is so strong a reset method that it will force + resetting on both devices connected to the same cable. It is called by IdeBlkIoReset(), a interface function of Block I/O protocol. @@ -946,17 +1064,13 @@ AtaWriteSectors ( This function can also be used by the ATAPI device to perform reset when ATAPI Reset command is failed. - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. @retval EFI_SUCCESS Soft reset completes successfully. @retval EFI_DEVICE_ERROR Any step during the reset process is failed. - @note - The registers initial values after ATA soft reset are different - to the ATA device and ATAPI device. - + @note The registers initial values after ATA soft reset are different + to the ATA device and ATAPI device. **/ EFI_STATUS AtaSoftReset ( @@ -1005,1015 +1119,1082 @@ AtaSoftReset ( return EFI_SUCCESS; } - /** - This function is the ATA implementation for ReadBlocks in the - Block I/O Protocol interface. - - @param[in] *IdeBlkIoDevice - Indicates the calling context. - - @param[in] MediaId - The media id that the read request is for. + This function is used to send out ATA commands conforms to the PIO Data In + Protocol, supporting ATA/ATAPI-6 standard - @param[in] LBA - The starting logical block address to read from - on the device. - - @param[in] BufferSize - The size of the Buffer in bytes. This must be a - multiple of the intrinsic block size of the device. - - @param[out] *Buffer - A pointer to the destination buffer for the data. - The caller is responsible for either having implicit - or explicit ownership of the memory that data is read into. - - @retval EFI_SUCCESS Read Blocks successfully. - @retval EFI_DEVICE_ERROR Read Blocks failed. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. + Comparing with ATA-3 data in protocol, we have two differents here: + 1. Do NOT wait for DRQ clear before sending command into IDE device.(the + wait will frequently fail... cause writing function return error) - @retval EFI_BAD_BUFFER_SIZE - The BufferSize parameter is not a multiple of the - intrinsic block size of the device. + 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly + slow down writing performance by 100 times!) - @retval EFI_INVALID_PARAMETER - The read request contains LBAs that are not valid, - or the data buffer is not valid. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param Buffer buffer contained data transferred from device to host. + @param ByteCount data size in byte unit of the buffer. + @param AtaCommand value of the Command Register + @param StartLba the start LBA of this transaction + @param SectorCount the count of sectors to be transfered - @note - If Read Block error because of device error, this function will call - AtaSoftReset() function to reset device. + @retval EFI_SUCCESS send out the ATA command and device send required data successfully. + @retval EFI_DEVICE_ERROR command sent failed. **/ EFI_STATUS -AtaBlkIoReadBlocks ( - IN IDE_BLK_IO_DEV *IdeBlkIoDevice, - IN UINT32 MediaId, - IN EFI_LBA LBA, - IN UINTN BufferSize, - OUT VOID *Buffer +AtaPioDataInExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN OUT VOID *Buffer, + IN UINT32 ByteCount, + IN UINT8 AtaCommand, + IN EFI_LBA StartLba, + IN UINT16 SectorCount ) { - EFI_BLOCK_IO_MEDIA *Media; - UINTN BlockSize; - UINTN NumberOfBlocks; - EFI_STATUS Status; + UINT8 DevSel; + UINT8 SectorCount8; + UINT8 LbaLow; + UINT8 LbaMid; + UINT8 LbaHigh; + UINTN WordCount; + UINTN Increment; + UINT16 *Buffer16; + EFI_STATUS Status; - if (Buffer == NULL) { - return EFI_INVALID_PARAMETER; + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; } - if (BufferSize == 0) { - return EFI_SUCCESS; + // + // Select device, set bit6 as 1 to indicate LBA mode is used + // + DevSel = (UINT8) (IdeDev->Device << 4); + DevSel |= 0x40; + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + DevSel + ); + + // + // Wait for DRDY singnal asserting. ATAPI device needn't wait + // + if ( (IdeDev->Type == IdeHardDisk) || + (IdeDev->Type == Ide48bitAddressingHardDisk)) { + + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } } - Status = EFI_SUCCESS; + // + // Fill feature register if needed + // + if (AtaCommand == ATA_CMD_SET_FEATURES) { + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03); + } // - // Get the intrinsic block size + // Fill the sector count register, which is a two-byte FIFO. Need write twice. // - Media = IdeBlkIoDevice->BlkIo.Media; - BlockSize = Media->BlockSize; + SectorCount8 = (UINT8) (SectorCount >> 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); - NumberOfBlocks = BufferSize / BlockSize; + SectorCount8 = (UINT8) SectorCount; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); - if (MediaId != Media->MediaId) { - return EFI_MEDIA_CHANGED; - } + // + // Fill the start LBA registers, which are also two-byte FIFO + // + LbaLow = (UINT8) RShiftU64 (StartLba, 24); + LbaMid = (UINT8) RShiftU64 (StartLba, 32); + LbaHigh = (UINT8) RShiftU64 (StartLba, 40); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - if (BufferSize % BlockSize != 0) { - return EFI_BAD_BUFFER_SIZE; - } + LbaLow = (UINT8) StartLba; + LbaMid = (UINT8) RShiftU64 (StartLba, 8); + LbaHigh = (UINT8) RShiftU64 (StartLba, 16); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - if (!(Media->MediaPresent)) { - return EFI_NO_MEDIA; - } + // + // Send command via Command Register, invoking the processing of this command + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); - if (LBA > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } + Buffer16 = (UINT16 *) Buffer; - if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } + // + // According to PIO data in protocol, host can perform a series of reads to + // the data register after each time device set DRQ ready; + // - if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { - return EFI_INVALID_PARAMETER; - } + // + // 256 words + // + Increment = 256; - Status = EFI_SUCCESS; - if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { + // + // used to record bytes of currently transfered data + // + WordCount = 0; + + while (WordCount < ByteCount / 2) { // - // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 read block mechanism + // Poll DRQ bit set, data transfer can be performed only when DRQ is ready. // - if (IdeBlkIoDevice->UdmaMode.Valid) { - Status = AtaUdmaReadExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); - } else { - Status = AtaReadSectorsExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); + Status = DRQReady2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; } - } else { + + Status = CheckErrorStatus (IdeDev); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + // - // For ATA-3 compatible device, use ATA-3 read block mechanism + // Get the byte count for one series of read // - if (IdeBlkIoDevice->UdmaMode.Valid) { - Status = AtaUdmaRead (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); - } else { - Status = AtaReadSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); + if ((WordCount + Increment) > ByteCount / 2) { + Increment = ByteCount / 2 - WordCount; } - } - if (EFI_ERROR (Status)) { - AtaSoftReset (IdeBlkIoDevice); - return EFI_DEVICE_ERROR; - } + IDEReadPortWMultiple ( + IdeDev->PciIo, + IdeDev->IoPort->Data, + Increment, + Buffer16 + ); - return EFI_SUCCESS; + WordCount += Increment; + Buffer16 += Increment; -} + } + return CheckErrorStatus (IdeDev); +} /** - This function is the ATA implementation for WriteBlocks in the - Block I/O Protocol interface. - - @param[in] *IdeBlkIoDevice - Indicates the calling context. - - @param[in] MediaId - The media id that the write request is for. - - @param[in] LBA - The starting logical block address to write onto - the device. - - @param[in] BufferSize - The size of the Buffer in bytes. This must be a - multiple of the intrinsic block size of the device. - - @param[out] *Buffer - A pointer to the source buffer for the data. - The caller is responsible for either having implicit - or explicit ownership of the memory that data is - written from. - - @retval EFI_SUCCESS Write Blocks successfully. - @retval EFI_DEVICE_ERROR Write Blocks failed. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. - - @retval EFI_BAD_BUFFER_SIZE - The BufferSize parameter is not a multiple of the - intrinsic block size of the device. + Send ATA Ext command into device with NON_DATA protocol - @retval EFI_INVALID_PARAMETER - The write request contains LBAs that are not valid, - or the data buffer is not valid. + @param IdeDev Standard IDE device private data structure + @param AtaCommand The ATA command to be sent + @param Device The value in Device register + @param Feature The value in Feature register + @param SectorCount The value in SectorCount register + @param LbaAddress The LBA address in 48-bit mode - @note - If Write Block error because of device error, this function will call - AtaSoftReset() function to reset device. + @retval EFI_SUCCESS Reading succeed + @retval EFI_DEVICE_ERROR Error executing commands on this device. **/ EFI_STATUS -AtaBlkIoWriteBlocks ( - IN IDE_BLK_IO_DEV *IdeBlkIoDevice, - IN UINT32 MediaId, - IN EFI_LBA LBA, - IN UINTN BufferSize, - OUT VOID *Buffer +AtaCommandIssueExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT8 AtaCommand, + IN UINT8 Device, + IN UINT16 Feature, + IN UINT16 SectorCount, + IN EFI_LBA LbaAddress ) { + EFI_STATUS Status; + UINT8 SectorCount8; + UINT8 Feature8; + UINT8 LbaLow; + UINT8 LbaMid; + UINT8 LbaHigh; - EFI_BLOCK_IO_MEDIA *Media; - UINTN BlockSize; - UINTN NumberOfBlocks; - EFI_STATUS Status; - - if (Buffer == NULL) { - return EFI_INVALID_PARAMETER; + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; } - if (BufferSize == 0) { - return EFI_SUCCESS; + // + // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility) + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | 0xe0) + ); + + // + // ATA commands for ATA device must be issued when DRDY is set + // + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; } - Status = EFI_SUCCESS; + // + // Pass parameter into device register block + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); // - // Get the intrinsic block size + // Fill the feature register, which is a two-byte FIFO. Need write twice. // - Media = IdeBlkIoDevice->BlkIo.Media; - BlockSize = Media->BlockSize; - NumberOfBlocks = BufferSize / BlockSize; + Feature8 = (UINT8) (Feature >> 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); - if (MediaId != Media->MediaId) { - return EFI_MEDIA_CHANGED; - } + Feature8 = (UINT8) Feature; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); - if (BufferSize % BlockSize != 0) { - return EFI_BAD_BUFFER_SIZE; - } + // + // Fill the sector count register, which is a two-byte FIFO. Need write twice. + // + SectorCount8 = (UINT8) (SectorCount >> 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); - if (LBA > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } + SectorCount8 = (UINT8) SectorCount; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); - if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) { - return EFI_INVALID_PARAMETER; - } + // + // Fill the start LBA registers, which are also two-byte FIFO + // + LbaLow = (UINT8) RShiftU64 (LbaAddress, 24); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + LbaLow = (UINT8) LbaAddress; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); - if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { - return EFI_INVALID_PARAMETER; - } + LbaMid = (UINT8) RShiftU64 (LbaAddress, 32); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + LbaMid = (UINT8) RShiftU64 (LbaAddress, 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); - Status = EFI_SUCCESS; - if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { - // - // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 write block mechanism - // - 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 - // - if (IdeBlkIoDevice->UdmaMode.Valid) { - Status = AtaUdmaWrite (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); - } else { - Status = AtaWriteSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); - } - } + LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - if (EFI_ERROR (Status)) { - AtaSoftReset (IdeBlkIoDevice); - return EFI_DEVICE_ERROR; - } + // + // Work around for Segate 160G disk writing + // + gBS->Stall (1800); + + // + // Send command via Command Register + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); + + // + // Stall at least 400ns + // + gBS->Stall (100); 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. + Send ATA Ext command into device with NON_DATA protocol - @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. + @param IdeDev Standard IDE device private data structure + @param AtaCommand The ATA command to be sent + @param Device The value in Device register + @param Feature The value in Feature register + @param SectorCount The value in SectorCount register + @param LbaAddress The LBA address in 48-bit mode - @return return status is fully dependent on the return status - of AtaPioDataInExt() function. + @retval EFI_SUCCESS Reading succeed + @retval EFI_DEVICE_ERROR Error executing commands on this device. **/ EFI_STATUS -AtaReadSectorsExt ( +AtaCommandIssue ( IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA StartLba, - IN UINTN NumberOfBlocks + IN UINT8 AtaCommand, + IN UINT8 Device, + IN UINT16 Feature, + IN UINT16 SectorCount, + IN EFI_LBA LbaAddress ) { EFI_STATUS Status; - UINTN BlocksRemaining; - EFI_LBA Lba64; - UINT8 AtaCommand; - UINT16 SectorCount; - UINT32 ByteCount; - VOID *Buffer; + UINT8 SectorCount8; + UINT8 Feature8; + UINT8 Lba0; + UINT8 Lba1; + UINT8 Lba2; + UINT8 Lba3; + + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } // - // Using ATA "Read Sectors Ext" command(opcode=0x24) with PIO DATA IN protocol + // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility) // - AtaCommand = ATA_CMD_READ_SECTORS_EXT; - Buffer = DataBuffer; - BlocksRemaining = NumberOfBlocks; - Lba64 = StartLba; - Status = EFI_SUCCESS; + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | 0xe0) + ); - while (BlocksRemaining > 0) { + // + // ATA commands for ATA device must be issued when DRDY is set + // + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } - if (BlocksRemaining >= 0x10000) { - // - // SectorCount is used to record the number of sectors to be read - // Max 65536 sectors can be transfered at a time. - // - SectorCount = 0xffff; - } else { - SectorCount = (UINT16) BlocksRemaining; - } + Lba0 = (UINT8) LbaAddress; + Lba1 = (UINT8) RShiftU64 (LbaAddress, 8); + Lba2 = (UINT8) RShiftU64 (LbaAddress, 16); + Lba3 = (UINT8) RShiftU64 (LbaAddress, 24); + Device = (UINT8) (Device | Lba3); - // - // ByteCount is the number of bytes that will be read - // - ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize); + // + // Pass parameter into device register block + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); - // - // call AtaPioDataInExt() to send Read Sector Command and receive data read - // - Status = AtaPioDataInExt ( - IdeDev, - Buffer, - ByteCount, - AtaCommand, - Lba64, - SectorCount - ); - if (EFI_ERROR (Status)) { - return Status; - } + // + // Fill the feature register, which is a two-byte FIFO. Need write twice. + // + Feature8 = (UINT8) Feature; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); - Lba64 += SectorCount; - Buffer = ((UINT8 *) Buffer + ByteCount); - BlocksRemaining -= SectorCount; - } + // + // Fill the sector count register, which is a two-byte FIFO. Need write twice. + // + SectorCount8 = (UINT8) SectorCount; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); - return Status; -} + // + // Fill the start LBA registers, which are also two-byte FIFO + // -/** - This function is called by the AtaBlkIoWriteBlocks() to perform - writing onto media in block unit. The function has been enhanced to - support >120GB access and transfer at most 65536 blocks per command + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, Lba0); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, Lba1); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, Lba2); - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure,used - to record all the information of the IDE device. + // + // Send command via Command Register + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); - @param[in] *DataBuffer - A pointer to the source buffer for the data. + // + // Stall at least 400ns + // + gBS->Stall (100); - @param[in] StartLba - The starting logical block address to write onto - the device media. + return EFI_SUCCESS; +} +/** + Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt). - @param[in] NumberOfBlocks - The number of transfer data blocks. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param DataBuffer A pointer to the source buffer for the data. + @param StartLba The starting logical block address to write to + on the device media. + @param NumberOfBlocks The number of transfer data blocks. + @param UdmaOp The perform operations could be AtaUdmaReadOp, AtaUdmaReadExOp, + AtaUdmaWriteOp, AtaUdmaWriteExOp - @return status is fully dependent on the return status - of AtaPioDataOutExt() function. + @retval EFI_SUCCESS the operation is successful. + @retval EFI_OUT_OF_RESOURCES Build PRD table failed + @retval EFI_UNSUPPORTED Unknown channel or operations command + @retval EFI_DEVICE_ERROR Ata command execute failed **/ EFI_STATUS -AtaWriteSectorsExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA StartLba, - IN UINTN NumberOfBlocks +DoAtaUdma ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks, + IN ATA_UDMA_OPERATION UdmaOp ) { - EFI_STATUS Status; - EFI_LBA Lba64; - UINTN BlocksRemaining; - UINT8 AtaCommand; - UINT16 SectorCount; - UINT32 ByteCount; - VOID *Buffer; + 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 = ATAPI_MAX_DMA_CMD_SECTORS; + PciIoProtocolOp = EfiPciIoOperationBusMasterWrite; + AtaCommand = ATA_CMD_READ_DMA; + break; + case AtaUdmaReadExtOp: + MaxDmaCommandSectors = ATAPI_MAX_DMA_EXT_CMD_SECTORS; + PciIoProtocolOp = EfiPciIoOperationBusMasterWrite; + AtaCommand = ATA_CMD_READ_DMA_EXT; + break; + case AtaUdmaWriteOp: + MaxDmaCommandSectors = ATAPI_MAX_DMA_CMD_SECTORS; + PciIoProtocolOp = EfiPciIoOperationBusMasterRead; + AtaCommand = ATA_CMD_WRITE_DMA; + break; + case AtaUdmaWriteExtOp: + MaxDmaCommandSectors = ATAPI_MAX_DMA_EXT_CMD_SECTORS; + PciIoProtocolOp = EfiPciIoOperationBusMasterRead; + AtaCommand = ATA_CMD_WRITE_DMA_EXT; + break; + default: + return EFI_UNSUPPORTED; + break; + } // - // Using ATA "Write Sectors Ext" cmd(opcode=0x24) with PIO DATA OUT protocol + // Select device // - AtaCommand = ATA_CMD_WRITE_SECTORS_EXT; - Lba64 = StartLba; - Buffer = DataBuffer; - BlocksRemaining = NumberOfBlocks; + Device = (UINT8) ((IdeDev->Device << 4) | 0xe0); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); - Status = EFI_SUCCESS; + // + // Enable interrupt to support UDMA + // + DeviceControl = 0; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); - while (BlocksRemaining > 0) { + 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; + } + } - if (BlocksRemaining >= 0x10000) { + // + // 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 + ); + + Status = EFI_SUCCESS; + + RemainBlockNum = NumberOfBlocks; + while (RemainBlockNum > 0) { + + if (RemainBlockNum >= MaxDmaCommandSectors) { // - // SectorCount is used to record the number of sectors to be written. + // SectorCount is used to record the number of sectors to be read // Max 65536 sectors can be transfered at a time. // - SectorCount = 0xffff; + NumberOfBlocks = MaxDmaCommandSectors; + RemainBlockNum -= MaxDmaCommandSectors; } else { - SectorCount = (UINT16) BlocksRemaining; + NumberOfBlocks = (UINT16) RemainBlockNum; + RemainBlockNum = 0; } // - // ByteCount is the number of bytes that will be written + // Calculate the number of PRD table to make sure the memory region + // not cross 64K boundary // - ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize); + ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize; + PrdTableNum = ((ByteCount >> 16) + 1) + 1; // - // Call AtaPioDataOutExt() to send "Write Sectors Ext" Command + // Build PRD table // - Status = AtaPioDataOutExt ( - IdeDev, - Buffer, - ByteCount, - AtaCommand, - Lba64, - SectorCount - ); + 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 Status; + return EFI_OUT_OF_RESOURCES; } + ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount)); - Lba64 += SectorCount; - Buffer = ((UINT8 *) Buffer + ByteCount); - BlocksRemaining -= SectorCount; - } - - return Status; -} + 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; + } + } -/** - This function is used to send out ATA commands conforms to the - PIO Data In Protocol, supporting ATA/ATAPI-6 standard - - Comparing with ATA-3 data in protocol, we have two differents here:
- 1. Do NOT wait for DRQ clear before sending command into IDE device.(the - wait will frequently fail... cause writing function return error) + // + // Build the PRD table + // + Status = IdeDev->PciIo->Map ( + 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) { - 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly - slow down writing performance by 100 times!) + ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF); - @param[in] *IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. + if (ByteCount <= ByteAvailable) { + TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer); + TempPrdAddr->ByteCount = (UINT16) ByteCount; + TempPrdAddr->EndOfTable = 0x8000; + break; + } - @param[in, out] *Buffer buffer contained data transferred from device to host. - @param[in] ByteCount data size in byte unit of the buffer. - @param[in] AtaCommand value of the Command Register - @param[in] StartLba the start LBA of this transaction - @param[in] SectorCount the count of sectors to be transfered + TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer); + TempPrdAddr->ByteCount = (UINT16) ByteAvailable; - @retval EFI_SUCCESS send out the ATA command and device send required - data successfully. + ByteCount -= ByteAvailable; + PrdBuffer += ByteAvailable; + TempPrdAddr++; + } - @retval EFI_DEVICE_ERROR command sent failed. + // + // Set the base address to BMID register + // + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint32, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmid, + 1, + &UsedPrdAddr + ); -**/ -EFI_STATUS -AtaPioDataInExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN OUT VOID *Buffer, - IN UINT32 ByteCount, - IN UINT8 AtaCommand, - IN EFI_LBA StartLba, - IN UINT16 SectorCount - ) -{ - UINT8 DevSel; - UINT8 SectorCount8; - UINT8 LbaLow; - UINT8 LbaMid; - UINT8 LbaHigh; - UINTN WordCount; - UINTN Increment; - UINT16 *Buffer16; - EFI_STATUS Status; + // + // Set BMIC register to identify the operation direction + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); - Status = WaitForBSYClear (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } + if (UdmaOp == AtaUdmaReadExtOp || UdmaOp == AtaUdmaReadOp) { + RegisterValue |= BMIC_NREAD; + } else { + RegisterValue &= ~((UINT8) BMIC_NREAD); + } - // - // Select device, set bit6 as 1 to indicate LBA mode is used - // - DevSel = (UINT8) (IdeDev->Device << 4); - DevSel |= 0x40; - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - DevSel - ); + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); - // - // Wait for DRDY singnal asserting. ATAPI device needn't wait - // - if ( (IdeDev->Type == IdeHardDisk) || - (IdeDev->Type == Ide48bitAddressingHardDisk)) { + if (UdmaOp == AtaUdmaWriteExtOp || UdmaOp == AtaUdmaReadExtOp) { + Status = AtaCommandIssueExt ( + IdeDev, + AtaCommand, + Device, + 0, + (UINT16) NumberOfBlocks, + StartLba + ); + } else { + Status = AtaCommandIssue ( + IdeDev, + AtaCommand, + Device, + 0, + (UINT16) NumberOfBlocks, + StartLba + ); + } - Status = DRDYReady (IdeDev, ATATIMEOUT); if (EFI_ERROR (Status)) { + IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage); + IdeDev->PciIo->Unmap (IdeDev->PciIo, Map); return EFI_DEVICE_ERROR; } - } - - // - // Fill feature register if needed - // - if (AtaCommand == ATA_CMD_SET_FEATURES) { - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03); - } - - // - // Fill the sector count register, which is a two-byte FIFO. Need write twice. - // - SectorCount8 = (UINT8) (SectorCount >> 8); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); - - SectorCount8 = (UINT8) SectorCount; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); - - // - // Fill the start LBA registers, which are also two-byte FIFO - // - LbaLow = (UINT8) RShiftU64 (StartLba, 24); - LbaMid = (UINT8) RShiftU64 (StartLba, 32); - LbaHigh = (UINT8) RShiftU64 (StartLba, 40); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - - LbaLow = (UINT8) StartLba; - LbaMid = (UINT8) RShiftU64 (StartLba, 8); - LbaHigh = (UINT8) RShiftU64 (StartLba, 16); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - // - // Send command via Command Register, invoking the processing of this command - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); - - Buffer16 = (UINT16 *) Buffer; - - // - // According to PIO data in protocol, host can perform a series of reads to - // the data register after each time device set DRQ ready; - // + // + // Set START bit of BMIC register + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); - // - // 256 words - // - Increment = 256; + RegisterValue |= BMIC_START; - // - // used to record bytes of currently transfered data - // - WordCount = 0; + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); - while (WordCount < ByteCount / 2) { // - // Poll DRQ bit set, data transfer can be performed only when DRQ is ready. + // 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. // - Status = DRQReady2 (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } + Status = EFI_SUCCESS; + Count = 2000; + while (TRUE) { - Status = CheckErrorStatus (IdeDev); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + if (((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) != 0) || (Count == 0)) { + if (((RegisterValue & BMIS_ERROR) != 0) || (Count == 0)) { + Status = EFI_DEVICE_ERROR; + break; + } + break; + } + + gBS->Stall (1000); + Count --; } + IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage); + IdeDev->PciIo->Unmap (IdeDev->PciIo, Map); // - // Get the byte count for one series of read + // Read BMIS register and clear ERROR and INTR bit // - if ((WordCount + Increment) > ByteCount / 2) { - Increment = ByteCount / 2 - WordCount; - } + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); - IDEReadPortWMultiple ( - IdeDev->PciIo, - IdeDev->IoPort->Data, - Increment, - Buffer16 - ); + RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR); - WordCount += Increment; - Buffer16 += Increment; + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + // + // 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); - return CheckErrorStatus (IdeDev); -} + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); -/** - This function is used to send out ATA commands conforms to the - PIO Data Out Protocol, supporting ATA/ATAPI-6 standard + if ((RegisterValue & BMIS_ERROR) != 0) { + return EFI_DEVICE_ERROR; + } - Comparing with ATA-3 data out protocol, we have two differents here:
- 1. Do NOT wait for DRQ clear before sending command into IDE device.(the - wait will frequently fail... cause writing function return error) + if (EFI_ERROR (Status)) { + break; + } + DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize; + StartLba += NumberOfBlocks; + } - 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly - slow down writing performance by 100 times!) + // + // Disable interrupt of Select device + // + IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl); + DeviceControl |= ATA_CTLREG_IEN_L; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. + return Status; +} - @param[in] *Buffer buffer contained data transferred from host to device. - @param[in] ByteCount data size in byte unit of the buffer. - @param[in] AtaCommand value of the Command Register - @param[in] StartLba the start LBA of this transaction - @param[in] SectorCount the count of sectors to be transfered - @retval EFI_SUCCESS send out the ATA command and device receive required - data successfully. +/** + 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 - @retval EFI_DEVICE_ERROR command sent failed. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @param DataBuffer A pointer to the destination buffer for the data. + @param StartLba The starting logical block address to read from on the device media. + @param NumberOfBlocks The number of transfer data blocks. + @return status depends on the function DoAtaUdma() returns. **/ EFI_STATUS -AtaPioDataOutExt ( +AtaUdmaReadExt ( IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *Buffer, - IN UINT32 ByteCount, - IN UINT8 AtaCommand, + IN VOID *DataBuffer, IN EFI_LBA StartLba, - IN UINT16 SectorCount + IN UINTN NumberOfBlocks ) { - UINT8 DevSel; - UINT8 SectorCount8; - UINT8 LbaLow; - UINT8 LbaMid; - UINT8 LbaHigh; - UINTN WordCount; - UINTN Increment; - UINT16 *Buffer16; - EFI_STATUS Status; - - Status = WaitForBSYClear (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Select device. Set bit6 as 1 to indicate LBA mode is used - // - DevSel = (UINT8) (IdeDev->Device << 4); - DevSel |= 0x40; - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - DevSel - ); - - // - // Wait for DRDY singnal asserting. - // - Status = DRDYReady (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Fill feature register if needed - // - if (AtaCommand == ATA_CMD_SET_FEATURES) { - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03); - } + 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 - // - // Fill the sector count register, which is a two-byte FIFO. Need write twice. - // - SectorCount8 = (UINT8) (SectorCount >> 8); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @param DataBuffer A pointer to the destination buffer for the data. + @param StartLba The starting logical block address to read from + on the device media. + @param NumberOfBlocks The number of transfer data blocks. + + @return status depends on the function DoAtaUdma() returns. +**/ +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); +} - SectorCount8 = (UINT8) SectorCount; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); +/** + 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 - // - // Fill the start LBA registers, which are also two-byte FIFO - // - LbaLow = (UINT8) RShiftU64 (StartLba, 24); - LbaMid = (UINT8) RShiftU64 (StartLba, 32); - LbaHigh = (UINT8) RShiftU64 (StartLba, 40); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @param DataBuffer A pointer to the destination buffer for the data. + @param StartLba The starting logical block address to read from on the device media. + @param NumberOfBlocks The number of transfer data blocks. - LbaLow = (UINT8) StartLba; - LbaMid = (UINT8) RShiftU64 (StartLba, 8); - LbaHigh = (UINT8) RShiftU64 (StartLba, 16); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + @return status is fully dependent on the return status of AtaPioDataInExt() function. +**/ +EFI_STATUS +AtaReadSectorsExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +{ + EFI_STATUS Status; + UINTN BlocksRemaining; + EFI_LBA Lba64; + UINT8 AtaCommand; + UINT16 SectorCount; + UINT32 ByteCount; + VOID *Buffer; // - // Send command via Command Register, invoking the processing of this command + // Using ATA "Read Sectors Ext" command(opcode=0x24) with PIO DATA IN protocol // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); - - Buffer16 = (UINT16 *) Buffer; + AtaCommand = ATA_CMD_READ_SECTORS_EXT; + Buffer = DataBuffer; + BlocksRemaining = NumberOfBlocks; + Lba64 = StartLba; + Status = EFI_SUCCESS; - // - // According to PIO Data Out protocol, host can perform a series of writes to - // the data register after each time device set DRQ ready; - // - Increment = 256; + while (BlocksRemaining > 0) { - // - // used to record bytes of currently transfered data - // - WordCount = 0; + if (BlocksRemaining >= 0x10000) { + // + // SectorCount is used to record the number of sectors to be read + // Max 65536 sectors can be transfered at a time. + // + SectorCount = 0xffff; + } else { + SectorCount = (UINT16) BlocksRemaining; + } - while (WordCount < ByteCount / 2) { // - // Poll DRQ bit set, data transfer can be performed only when DRQ is ready. + // ByteCount is the number of bytes that will be read // - Status = DRQReady2 (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - Status = CheckErrorStatus (IdeDev); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } + ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize); // - // Write data into device by one series of writing to data register + // call AtaPioDataInExt() to send Read Sector Command and receive data read // - if ((WordCount + Increment) > ByteCount / 2) { - Increment = ByteCount / 2 - WordCount; + Status = AtaPioDataInExt ( + IdeDev, + Buffer, + ByteCount, + AtaCommand, + Lba64, + SectorCount + ); + if (EFI_ERROR (Status)) { + return Status; } - IDEWritePortWMultiple ( - IdeDev->PciIo, - IdeDev->IoPort->Data, - Increment, - Buffer16 - ); - - WordCount += Increment; - Buffer16 += Increment; - + Lba64 += SectorCount; + Buffer = ((UINT8 *) Buffer + ByteCount); + BlocksRemaining -= SectorCount; } - // - // while - // - return CheckErrorStatus (IdeDev); + return Status; } +/** + This function is the ATA implementation for ReadBlocks in the + Block I/O Protocol interface. + @param IdeBlkIoDevice Indicates the calling context. + @param MediaId The media id that the read request is for. + @param LBA The starting logical block address to read from on the device. + @param BufferSize The size of the Buffer in bytes. This must be a multiple + of the intrinsic block size of the device. -/** - Enable SMART of the disk if supported + @param Buffer A pointer to the destination buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the memory that data is read into. + + @retval EFI_SUCCESS Read Blocks successfully. + @retval EFI_DEVICE_ERROR Read Blocks failed. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, + or the data buffer is not valid. - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure,used - to record all the information of the IDE device. + @note If Read Block error because of device error, this function will call + AtaSoftReset() function to reset device. **/ -VOID -AtaSMARTSupport ( - IN IDE_BLK_IO_DEV *IdeDev +EFI_STATUS +AtaBlkIoReadBlocks ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer ) { - EFI_STATUS Status; - BOOLEAN SMARTSupported; - UINT8 Device; - EFI_IDENTIFY_DATA *TmpAtaIdentifyPointer; - UINT8 DeviceSelect; - UINT8 LBAMid; - UINT8 LBAHigh; + EFI_BLOCK_IO_MEDIA *Media; + UINTN BlockSize; + UINTN NumberOfBlocks; + EFI_STATUS Status; + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + Status = EFI_SUCCESS; // - // Detect if the device supports S.M.A.R.T. + // Get the intrinsic block size // - if ((IdeDev->IdData->AtaData.command_set_supported_83 & 0xc000) != 0x4000) { - // - // Data in word 82 is not valid (bit15 shall be zero and bit14 shall be to one) - // - return ; - } else { - if ((IdeDev->IdData->AtaData.command_set_supported_82 & 0x0001) != 0x0001) { - // - // S.M.A.R.T is not supported by the device - // - SMARTSupported = FALSE; - } else { - SMARTSupported = TRUE; - } + Media = IdeBlkIoDevice->BlkIo.Media; + BlockSize = Media->BlockSize; + + NumberOfBlocks = BufferSize / BlockSize; + + if (MediaId != Media->MediaId) { + return EFI_MEDIA_CHANGED; } - if (!SMARTSupported) { - // - // Report nonsupport status code - // - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED) - ); - } else { - // - // Enable this feature - // - REPORT_STATUS_CODE ( - EFI_PROGRESS_CODE, - (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_ENABLE) - ); + if (BufferSize % BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } - Device = (UINT8) ((IdeDev->Device << 4) | 0xe0); - Status = AtaNonDataCommandIn ( - IdeDev, - ATA_CMD_SMART, - Device, - ATA_SMART_ENABLE_OPERATION, - 0, - 0, - ATA_CONSTANT_4F, - ATA_CONSTANT_C2 - ); + if (!(Media->MediaPresent)) { + return EFI_NO_MEDIA; + } + + if (LBA > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { // - // Detect if this feature is enabled + // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 read block mechanism // - TmpAtaIdentifyPointer = (EFI_IDENTIFY_DATA *) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA)); - if (TmpAtaIdentifyPointer == NULL) { - return; - } - - DeviceSelect = (UINT8) ((IdeDev->Device) << 4); - Status = AtaPioDataIn ( - IdeDev, - (VOID *) TmpAtaIdentifyPointer, - sizeof (EFI_IDENTIFY_DATA), - ATA_CMD_IDENTIFY_DRIVE, - DeviceSelect, - 0, - 0, - 0, - 0 - ); - if (EFI_ERROR (Status)) { - gBS->FreePool (TmpAtaIdentifyPointer); - return ; + if (IdeBlkIoDevice->UdmaMode.Valid) { + Status = AtaUdmaReadExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); + } else { + Status = AtaReadSectorsExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); } - + } else { // - // Check if the feature is enabled + // For ATA-3 compatible device, use ATA-3 read block mechanism // - if ((TmpAtaIdentifyPointer->AtaData.command_set_feature_enb_85 & 0x0001) == 0x0001) { - // - // Read status data - // - AtaNonDataCommandIn ( - IdeDev, - ATA_CMD_SMART, - Device, - ATA_SMART_RETURN_STATUS, - 0, - 0, - ATA_CONSTANT_4F, - ATA_CONSTANT_C2 - ); - LBAMid = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb); - LBAHigh = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb); - - if ((LBAMid == 0x4f) && (LBAHigh == 0xc2)) { - // - // The threshold exceeded condition is not detected by the device - // - REPORT_STATUS_CODE ( - EFI_PROGRESS_CODE, - (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD) - ); - - } else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) { - // - // The threshold exceeded condition is detected by the device - // - REPORT_STATUS_CODE ( - EFI_PROGRESS_CODE, - (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD) - ); - } - + if (IdeBlkIoDevice->UdmaMode.Valid) { + Status = AtaUdmaRead (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); } else { - // - // Report disabled status code - // - REPORT_STATUS_CODE ( - EFI_ERROR_CODE | EFI_ERROR_MINOR, - (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLED) - ); + Status = AtaReadSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); } + } - gBS->FreePool (TmpAtaIdentifyPointer); + if (EFI_ERROR (Status)) { + AtaSoftReset (IdeBlkIoDevice); + return EFI_DEVICE_ERROR; } - return ; -} + return EFI_SUCCESS; +} /** - Enable Long Physical Sector Feature for ATA device. + This function is used to send out ATA commands conforms to the + PIO Data Out Protocol, supporting ATA/ATAPI-6 standard - @param IdeDev The IDE device data + Comparing with ATA-3 data out protocol, we have two differents here:
+ 1. Do NOT wait for DRQ clear before sending command into IDE device.(the + wait will frequently fail... cause writing function return error) + + 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly + slow down writing performance by 100 times!) + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param Buffer buffer contained data transferred from host to device. + @param ByteCount data size in byte unit of the buffer. + @param AtaCommand value of the Command Register + @param StartLba the start LBA of this transaction + @param SectorCount the count of sectors to be transfered + + @retval EFI_SUCCESS send out the ATA command and device receive required + data successfully. + @retval EFI_DEVICE_ERROR command sent failed. - @retval EFI_SUCCESS The ATA device supports Long Physical Sector feature - and corresponding fields in BlockIo structure is updated. - @retval EFI_UNSUPPORTED The device is not ATA device or Long Physical Sector - feature is not supported. **/ EFI_STATUS -AtaEnableLongPhysicalSector ( - IN IDE_BLK_IO_DEV *IdeDev +AtaPioDataOutExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *Buffer, + IN UINT32 ByteCount, + IN UINT8 AtaCommand, + IN EFI_LBA StartLba, + IN UINT16 SectorCount ) { - EFI_ATA_IDENTIFY_DATA *AtaIdentifyData; - UINT16 PhyLogicSectorSupport; + UINT8 DevSel; + UINT8 SectorCount8; + UINT8 LbaLow; + UINT8 LbaMid; + UINT8 LbaHigh; + UINTN WordCount; + UINTN Increment; + UINT16 *Buffer16; + EFI_STATUS Status; + + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } - ASSERT (IdeDev->IdData != NULL); // - // Only valid for ATA device + // Select device. Set bit6 as 1 to indicate LBA mode is used // - AtaIdentifyData = (EFI_ATA_IDENTIFY_DATA *) &IdeDev->IdData->AtaData; - if ((AtaIdentifyData->config & 0x8000) != 0) { - return EFI_UNSUPPORTED; - } - PhyLogicSectorSupport = AtaIdentifyData->phy_logic_sector_support; + DevSel = (UINT8) (IdeDev->Device << 4); + DevSel |= 0x40; + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + DevSel + ); + // - // Check whether Long Physical Sector Feature is supported - // - if ((PhyLogicSectorSupport & 0xc000) == 0x4000) { - IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock = 1; - IdeDev->BlkIo.Media->LowestAlignedLba = 0; - // - // Check whether one physical block contains multiple physical blocks - // - if ((PhyLogicSectorSupport & 0x2000) != 0) { - IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock = - (UINT32) (1 << (PhyLogicSectorSupport & 0x000f)); - // - // Check lowest alignment of logical blocks within physical block - // - if ((AtaIdentifyData->alignment_logic_in_phy_blocks & 0xc000) == 0x4000) { - IdeDev->BlkIo.Media->LowestAlignedLba = - (EFI_LBA) (AtaIdentifyData->alignment_logic_in_phy_blocks & 0x3fff); - } - } - // - // Check logical block size - // - IdeDev->BlkIo.Media->BlockSize = 0x200; - if ((PhyLogicSectorSupport & 0x1000) != 0) { - IdeDev->BlkIo.Media->BlockSize = (UINT32) ( - ((AtaIdentifyData->logic_sector_size_hi << 16) | - AtaIdentifyData->logic_sector_size_lo) * sizeof (UINT16) - ); - } - return EFI_SUCCESS; - } else { - return EFI_UNSUPPORTED; - } -} - - -/** - Send ATA Ext command into device with NON_DATA protocol - - @param IdeDev Standard IDE device private data structure - @param AtaCommand The ATA command to be sent - @param Device The value in Device register - @param Feature The value in Feature register - @param SectorCount The value in SectorCount register - @param LbaAddress The LBA address in 48-bit mode - - @retval EFI_SUCCESS Reading succeed - @retval EFI_DEVICE_ERROR Error executing commands on this device. - -**/ -EFI_STATUS -AtaCommandIssueExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINT8 AtaCommand, - IN UINT8 Device, - IN UINT16 Feature, - IN UINT16 SectorCount, - IN EFI_LBA LbaAddress - ) -{ - EFI_STATUS Status; - UINT8 SectorCount8; - UINT8 Feature8; - UINT8 LbaLow; - UINT8 LbaMid; - UINT8 LbaHigh; - - Status = WaitForBSYClear (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility) - // - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - (UINT8) ((IdeDev->Device << 4) | 0xe0) - ); - - // - // ATA commands for ATA device must be issued when DRDY is set + // Wait for DRDY singnal asserting. // Status = DRDYReady (IdeDev, ATATIMEOUT); if (EFI_ERROR (Status)) { @@ -2021,18 +2202,11 @@ AtaCommandIssueExt ( } // - // Pass parameter into device register block - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); - - // - // Fill the feature register, which is a two-byte FIFO. Need write twice. + // Fill feature register if needed // - Feature8 = (UINT8) (Feature >> 8); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); - - Feature8 = (UINT8) Feature; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); + if (AtaCommand == ATA_CMD_SET_FEATURES) { + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03); + } // // Fill the sector count register, which is a two-byte FIFO. Need write twice. @@ -2046,685 +2220,579 @@ AtaCommandIssueExt ( // // Fill the start LBA registers, which are also two-byte FIFO // - LbaLow = (UINT8) RShiftU64 (LbaAddress, 24); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); - LbaLow = (UINT8) LbaAddress; + LbaLow = (UINT8) RShiftU64 (StartLba, 24); + LbaMid = (UINT8) RShiftU64 (StartLba, 32); + LbaHigh = (UINT8) RShiftU64 (StartLba, 40); IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); - - LbaMid = (UINT8) RShiftU64 (LbaAddress, 32); IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); - LbaMid = (UINT8) RShiftU64 (LbaAddress, 8); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); - - LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16); IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - // - // Work around for Segate 160G disk writing - // - gBS->Stall (1800); + LbaLow = (UINT8) StartLba; + LbaMid = (UINT8) RShiftU64 (StartLba, 8); + LbaHigh = (UINT8) RShiftU64 (StartLba, 16); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); // - // Send command via Command Register + // Send command via Command Register, invoking the processing of this command // IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); - // - // Stall at least 400ns - // - gBS->Stall (100); - - return EFI_SUCCESS; -} - -/** - Send ATA Ext command into device with NON_DATA protocol - - @param IdeDev Standard IDE device private data structure - @param AtaCommand The ATA command to be sent - @param Device The value in Device register - @param Feature The value in Feature register - @param SectorCount The value in SectorCount register - @param LbaAddress The LBA address in 48-bit mode - - @retval EFI_SUCCESS Reading succeed - @retval EFI_DEVICE_ERROR Error executing commands on this device. - -**/ -EFI_STATUS -AtaCommandIssue ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINT8 AtaCommand, - IN UINT8 Device, - IN UINT16 Feature, - IN UINT16 SectorCount, - IN EFI_LBA LbaAddress - ) -{ - EFI_STATUS Status; - UINT8 SectorCount8; - UINT8 Feature8; - UINT8 Lba0; - UINT8 Lba1; - UINT8 Lba2; - UINT8 Lba3; - - Status = WaitForBSYClear (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility) - // - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - (UINT8) ((IdeDev->Device << 4) | 0xe0) - ); - - // - // ATA commands for ATA device must be issued when DRDY is set - // - Status = DRDYReady (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - Lba0 = (UINT8) LbaAddress; - Lba1 = (UINT8) RShiftU64 (LbaAddress, 8); - Lba2 = (UINT8) RShiftU64 (LbaAddress, 16); - Lba3 = (UINT8) RShiftU64 (LbaAddress, 24); - Device = (UINT8) (Device | Lba3); + Buffer16 = (UINT16 *) Buffer; // - // Pass parameter into device register block + // According to PIO Data Out protocol, host can perform a series of writes to + // the data register after each time device set DRQ ready; // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); + Increment = 256; // - // Fill the feature register, which is a two-byte FIFO. Need write twice. + // used to record bytes of currently transfered data // - Feature8 = (UINT8) Feature; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); + WordCount = 0; - // - // Fill the sector count register, which is a two-byte FIFO. Need write twice. - // - SectorCount8 = (UINT8) SectorCount; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + while (WordCount < ByteCount / 2) { + // + // Poll DRQ bit set, data transfer can be performed only when DRQ is ready. + // + Status = DRQReady2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } - // - // Fill the start LBA registers, which are also two-byte FIFO - // + Status = CheckErrorStatus (IdeDev); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, Lba0); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, Lba1); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, Lba2); + // + // Write data into device by one series of writing to data register + // + if ((WordCount + Increment) > ByteCount / 2) { + Increment = ByteCount / 2 - WordCount; + } - // - // Send command via Command Register - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); + IDEWritePortWMultiple ( + IdeDev->PciIo, + IdeDev->IoPort->Data, + Increment, + Buffer16 + ); - // - // Stall at least 400ns - // - gBS->Stall (100); + WordCount += Increment; + Buffer16 += Increment; - return EFI_SUCCESS; + } + return CheckErrorStatus (IdeDev); } - /** - This function is called by the AtaBlkIoReadBlocks() to perform - reading from media in block unit. The function has been enhanced to + 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 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. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param DataBuffer A pointer to the source buffer for the data. + @param StartLba The starting logical block address to write to + on the device media. + @param 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 + @return status depends on the function DoAtaUdma() returns. **/ EFI_STATUS -AtaUdmaReadExt ( +AtaUdmaWriteExt ( IN IDE_BLK_IO_DEV *IdeDev, IN VOID *DataBuffer, IN EFI_LBA StartLba, IN UINTN NumberOfBlocks ) { - return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadExtOp); + return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteExtOp); } /** - 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 + This function is called by the AtaBlkIoWriteBlocks() to perform + writing to media in block unit. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param DataBuffer A pointer to the source buffer for the data. + @param StartLba The starting logical block address to write to + on the device media. + @param NumberOfBlocks The number of transfer data blocks. + + @return status depends on the function DoAtaUdma() returns. **/ EFI_STATUS -AtaUdmaRead ( +AtaUdmaWrite ( IN IDE_BLK_IO_DEV *IdeDev, IN VOID *DataBuffer, IN EFI_LBA StartLba, IN UINTN NumberOfBlocks ) { - return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadOp); + return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteOp); } - /** This function is called by the AtaBlkIoWriteBlocks() to perform - writing to media in block unit. The function has been enhanced to + writing onto 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. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used + to record all the information of the IDE device. + @param DataBuffer A pointer to the source buffer for the data. + @param StartLba The starting logical block address to write onto the device + media. + @param 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 + @return status is fully dependent on the return status of AtaPioDataOutExt() function. **/ EFI_STATUS -AtaUdmaWriteExt ( +AtaWriteSectorsExt ( IN IDE_BLK_IO_DEV *IdeDev, IN VOID *DataBuffer, IN EFI_LBA StartLba, IN UINTN NumberOfBlocks ) { - return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteExtOp); -} + EFI_STATUS Status; + EFI_LBA Lba64; + UINTN BlocksRemaining; + UINT8 AtaCommand; + UINT16 SectorCount; + UINT32 ByteCount; + VOID *Buffer; -/** - 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 + // + // Using ATA "Write Sectors Ext" cmd(opcode=0x24) with PIO DATA OUT protocol + // + AtaCommand = ATA_CMD_WRITE_SECTORS_EXT; + Lba64 = StartLba; + Buffer = DataBuffer; + BlocksRemaining = NumberOfBlocks; + + Status = EFI_SUCCESS; - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. + while (BlocksRemaining > 0) { - @param[in] *DataBuffer - A pointer to the source buffer for the data. + if (BlocksRemaining >= 0x10000) { + // + // SectorCount is used to record the number of sectors to be written. + // Max 65536 sectors can be transfered at a time. + // + SectorCount = 0xffff; + } else { + SectorCount = (UINT16) BlocksRemaining; + } - @param[in] StartLba - The starting logical block address to write to - on the device media. + // + // ByteCount is the number of bytes that will be written + // + ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize); - @param[in] NumberOfBlocks - The number of transfer data blocks. + // + // Call AtaPioDataOutExt() to send "Write Sectors Ext" Command + // + Status = AtaPioDataOutExt ( + IdeDev, + Buffer, + ByteCount, + AtaCommand, + Lba64, + SectorCount + ); + if (EFI_ERROR (Status)) { + return Status; + } - @return The device status of UDMA operation. If the operation is - successful, return EFI_SUCCESS. + Lba64 += SectorCount; + Buffer = ((UINT8 *) Buffer + ByteCount); + BlocksRemaining -= SectorCount; + } - 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); + return Status; } - /** - 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. + This function is the ATA implementation for WriteBlocks in the + Block I/O Protocol interface. - @param[in] NumberOfBlocks - The number of transfer data blocks. + @param IdeBlkIoDevice Indicates the calling context. + @param MediaId The media id that the write request is for. + @param LBA The starting logical block address to write onto the device. + @param BufferSize The size of the Buffer in bytes. This must be a multiple + of the intrinsic block size of the device. + @param Buffer A pointer to the source buffer for the data.The caller + is responsible for either having implicit or explicit + ownership of the memory that data is written from. - @param[in] UdmaOp - The perform operations could be AtaUdmaReadOp, AtaUdmaReadExOp, - AtaUdmaWriteOp, AtaUdmaWriteExOp + @retval EFI_SUCCESS Write Blocks successfully. + @retval EFI_DEVICE_ERROR Write Blocks failed. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. - @return The device status of UDMA operation. If the operation is - successful, return EFI_SUCCESS. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, + or the data buffer is not valid. + @note If Write Block error because of device error, this function will call + AtaSoftReset() function to reset device. **/ EFI_STATUS -DoAtaUdma ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA StartLba, - IN UINTN NumberOfBlocks, - IN ATA_UDMA_OPERATION UdmaOp +AtaBlkIoWriteBlocks ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer ) { - 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 = ATAPI_MAX_DMA_CMD_SECTORS; - PciIoProtocolOp = EfiPciIoOperationBusMasterWrite; - AtaCommand = ATA_CMD_READ_DMA; - break; - case AtaUdmaReadExtOp: - MaxDmaCommandSectors = ATAPI_MAX_DMA_EXT_CMD_SECTORS; - PciIoProtocolOp = EfiPciIoOperationBusMasterWrite; - AtaCommand = ATA_CMD_READ_DMA_EXT; - break; - case AtaUdmaWriteOp: - MaxDmaCommandSectors = ATAPI_MAX_DMA_CMD_SECTORS; - PciIoProtocolOp = EfiPciIoOperationBusMasterRead; - AtaCommand = ATA_CMD_WRITE_DMA; - break; - case AtaUdmaWriteExtOp: - MaxDmaCommandSectors = ATAPI_MAX_DMA_EXT_CMD_SECTORS; - PciIoProtocolOp = EfiPciIoOperationBusMasterRead; - AtaCommand = ATA_CMD_WRITE_DMA_EXT; - break; - default: - return EFI_UNSUPPORTED; - break; + EFI_BLOCK_IO_MEDIA *Media; + UINTN BlockSize; + UINTN NumberOfBlocks; + EFI_STATUS Status; + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; } - // - // Select device - // - Device = (UINT8) ((IdeDev->Device << 4) | 0xe0); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + Status = EFI_SUCCESS; // - // Enable interrupt to support UDMA + // Get the intrinsic block size // - DeviceControl = 0; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); + Media = IdeBlkIoDevice->BlkIo.Media; + BlockSize = Media->BlockSize; + NumberOfBlocks = BufferSize / BlockSize; - 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; - } + if (MediaId != Media->MediaId) { + return EFI_MEDIA_CHANGED; } - // - // 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 - ); + if (BufferSize % BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } - Status = EFI_SUCCESS; - - RemainBlockNum = NumberOfBlocks; - while (RemainBlockNum > 0) { + if (LBA > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } - 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 = MaxDmaCommandSectors; - RemainBlockNum -= MaxDmaCommandSectors; - } else { - NumberOfBlocks = (UINT16) RemainBlockNum; - RemainBlockNum = 0; - } + if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } - // - // 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; + if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { + return EFI_INVALID_PARAMETER; + } + Status = EFI_SUCCESS; + if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { // - // Build PRD table + // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 write block mechanism // - 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); + if (IdeBlkIoDevice->UdmaMode.Valid) { + Status = AtaUdmaWriteExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); } else { - if ((UINTN) PrdAddr & 0x03) { - UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC); - } else { - UsedPrdAddr = PrdAddr; - } + Status = AtaWriteSectorsExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); } - + } else { // - // Build the PRD table + // For ATA-3 compatible device, use ATA-3 write block mechanism // - Status = IdeDev->PciIo->Map ( - IdeDev->PciIo, - PciIoProtocolOp, - DataBuffer, - &ByteCount, - &DeviceAddress, - &Map - ); - if (EFI_ERROR (Status)) { - IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage); - return EFI_OUT_OF_RESOURCES; + if (IdeBlkIoDevice->UdmaMode.Valid) { + Status = AtaUdmaWrite (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); + } else { + Status = AtaWriteSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); } - PrdBuffer = (VOID *) ((UINTN) DeviceAddress); - TempPrdAddr = UsedPrdAddr; - while (TRUE) { + } - ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF); + if (EFI_ERROR (Status)) { + AtaSoftReset (IdeBlkIoDevice); + return EFI_DEVICE_ERROR; + } - if (ByteCount <= ByteAvailable) { - TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer); - TempPrdAddr->ByteCount = (UINT16) ByteCount; - TempPrdAddr->EndOfTable = 0x8000; - break; - } + return EFI_SUCCESS; +} +/** + Enable Long Physical Sector Feature for ATA device. - TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer); - TempPrdAddr->ByteCount = (UINT16) ByteAvailable; + @param IdeDev The IDE device data - ByteCount -= ByteAvailable; - PrdBuffer += ByteAvailable; - TempPrdAddr++; - } + @retval EFI_SUCCESS The ATA device supports Long Physical Sector feature + and corresponding fields in BlockIo structure is updated. + @retval EFI_UNSUPPORTED The device is not ATA device or Long Physical Sector + feature is not supported. +**/ +EFI_STATUS +AtaEnableLongPhysicalSector ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + EFI_ATA_IDENTIFY_DATA *AtaIdentifyData; + UINT16 PhyLogicSectorSupport; + ASSERT (IdeDev->IdData != NULL); + // + // Only valid for ATA device + // + AtaIdentifyData = (EFI_ATA_IDENTIFY_DATA *) &IdeDev->IdData->AtaData; + if ((AtaIdentifyData->config & 0x8000) != 0) { + return EFI_UNSUPPORTED; + } + PhyLogicSectorSupport = AtaIdentifyData->phy_logic_sector_support; + // + // Check whether Long Physical Sector Feature is supported + // + if ((PhyLogicSectorSupport & 0xc000) == 0x4000) { + IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock = 1; + IdeDev->BlkIo.Media->LowestAlignedLba = 0; // - // Set the base address to BMID register + // Check whether one physical block contains multiple physical blocks // - IdeDev->PciIo->Io.Write ( - IdeDev->PciIo, - EfiPciIoWidthUint32, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmid, - 1, - &UsedPrdAddr - ); - + if ((PhyLogicSectorSupport & 0x2000) != 0) { + IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock = + (UINT32) (1 << (PhyLogicSectorSupport & 0x000f)); + // + // Check lowest alignment of logical blocks within physical block + // + if ((AtaIdentifyData->alignment_logic_in_phy_blocks & 0xc000) == 0x4000) { + IdeDev->BlkIo.Media->LowestAlignedLba = + (EFI_LBA) (AtaIdentifyData->alignment_logic_in_phy_blocks & 0x3fff); + } + } // - // Set BMIC register to identify the operation direction + // Check logical block size // - IdeDev->PciIo->Io.Read ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmic, - 1, - &RegisterValue - ); - - if (UdmaOp == AtaUdmaReadExtOp || UdmaOp == AtaUdmaReadOp) { - RegisterValue |= BMIC_NREAD; - } else { - RegisterValue &= ~((UINT8) BMIC_NREAD); + IdeDev->BlkIo.Media->BlockSize = 0x200; + if ((PhyLogicSectorSupport & 0x1000) != 0) { + IdeDev->BlkIo.Media->BlockSize = (UINT32) ( + ((AtaIdentifyData->logic_sector_size_hi << 16) | + AtaIdentifyData->logic_sector_size_lo) * sizeof (UINT16) + ); } + return EFI_SUCCESS; + } else { + return EFI_UNSUPPORTED; + } +} +/** + Send ATA command into device with NON_DATA protocol - IdeDev->PciIo->Io.Write ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmic, - 1, - &RegisterValue - ); + @param IdeDev Standard IDE device private data structure + @param AtaCommand The ATA command to be sent + @param Device The value in Device register + @param Feature The value in Feature register + @param SectorCount The value in SectorCount register + @param LbaLow The value in LBA_LOW register + @param LbaMiddle The value in LBA_MIDDLE register + @param LbaHigh The value in LBA_HIGH register - if (UdmaOp == AtaUdmaWriteExtOp || UdmaOp == AtaUdmaReadExtOp) { - Status = AtaCommandIssueExt ( - IdeDev, - AtaCommand, - Device, - 0, - (UINT16) NumberOfBlocks, - StartLba - ); - } else { - Status = AtaCommandIssue ( - IdeDev, - AtaCommand, - Device, - 0, - (UINT16) NumberOfBlocks, - StartLba - ); - } + @retval EFI_SUCCESS Reading succeed + @retval EFI_ABORTED Command failed + @retval EFI_DEVICE_ERROR Device status error. - if (EFI_ERROR (Status)) { - IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage); - IdeDev->PciIo->Unmap (IdeDev->PciIo, Map); - return EFI_DEVICE_ERROR; - } +**/ +EFI_STATUS +AtaNonDataCommandIn ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT8 AtaCommand, + IN UINT8 Device, + IN UINT8 Feature, + IN UINT8 SectorCount, + IN UINT8 LbaLow, + IN UINT8 LbaMiddle, + IN UINT8 LbaHigh + ) +{ + EFI_STATUS Status; + UINT8 StatusRegister; - // - // Set START bit of BMIC register - // - IdeDev->PciIo->Io.Read ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmic, - 1, - &RegisterValue - ); + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } - RegisterValue |= BMIC_START; + // + // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility) + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | 0xe0) + ); - IdeDev->PciIo->Io.Write ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmic, - 1, - &RegisterValue - ); + // + // ATA commands for ATA device must be issued when DRDY is set + // + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } - // - // 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. - // - Status = EFI_SUCCESS; - Count = 2000; - while (TRUE) { + // + // Pass parameter into device register block + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMiddle); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - IdeDev->PciIo->Io.Read ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmis, - 1, - &RegisterValue - ); - if (((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) != 0) || (Count == 0)) { - if (((RegisterValue & BMIS_ERROR) != 0) || (Count == 0)) { - Status = EFI_DEVICE_ERROR; - break; - } - break; - } + // + // Send command via Command Register + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); - gBS->Stall (1000); - Count --; - } + // + // Wait for command completion + // For ATAPI_SMART_CMD, we may need more timeout to let device + // adjust internal states. + // + if (AtaCommand == ATA_CMD_SMART) { + Status = WaitForBSYClear (IdeDev, ATASMARTTIMEOUT); + } else { + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + } + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } - IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage); - IdeDev->PciIo->Unmap (IdeDev->PciIo, Map); + StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) { // - // Read BMIS register and clear ERROR and INTR bit + // Failed to execute command, abort operation // - IdeDev->PciIo->Io.Read ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmis, - 1, - &RegisterValue - ); + return EFI_ABORTED; + } - RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR); + return EFI_SUCCESS; +} - IdeDev->PciIo->Io.Write ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmis, - 1, - &RegisterValue - ); - // - // 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 - ); +/** + Send ATA Ext command into device with NON_DATA protocol - RegisterValue &= ~((UINT8) BMIC_START); + @param IdeDev Standard IDE device private data structure + @param AtaCommand The ATA command to be sent + @param Device The value in Device register + @param Feature The value in Feature register + @param SectorCount The value in SectorCount register + @param LbaAddress The LBA address in 48-bit mode - IdeDev->PciIo->Io.Write ( - IdeDev->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - IoPortForBmic, - 1, - &RegisterValue - ); + @retval EFI_SUCCESS Reading succeed + @retval EFI_ABORTED Command failed + @retval EFI_DEVICE_ERROR Device status error. - if ((RegisterValue & BMIS_ERROR) != 0) { - return EFI_DEVICE_ERROR; - } +**/ +EFI_STATUS +AtaNonDataCommandInExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT8 AtaCommand, + IN UINT8 Device, + IN UINT16 Feature, + IN UINT16 SectorCount, + IN EFI_LBA LbaAddress + ) +{ + EFI_STATUS Status; + UINT8 StatusRegister; + UINT8 SectorCount8; + UINT8 Feature8; + UINT8 LbaLow; + UINT8 LbaMid; + UINT8 LbaHigh; - if (EFI_ERROR (Status)) { - break; - } - DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize; - StartLba += NumberOfBlocks; + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; } // - // Disable interrupt of Select device + // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility) // - IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl); - DeviceControl |= ATA_CTLREG_IEN_L; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | 0xe0) + ); - return Status; + // + // ATA commands for ATA device must be issued when DRDY is set + // + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Pass parameter into device register block + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); + + // + // Fill the feature register, which is a two-byte FIFO. Need write twice. + // + Feature8 = (UINT8) (Feature >> 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); + + Feature8 = (UINT8) Feature; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); + + // + // Fill the sector count register, which is a two-byte FIFO. Need write twice. + // + SectorCount8 = (UINT8) (SectorCount >> 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + SectorCount8 = (UINT8) SectorCount; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + // + // Fill the start LBA registers, which are also two-byte FIFO + // + LbaLow = (UINT8) RShiftU64 (LbaAddress, 24); + LbaMid = (UINT8) RShiftU64 (LbaAddress, 32); + LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + + LbaLow = (UINT8) LbaAddress; + LbaMid = (UINT8) RShiftU64 (LbaAddress, 8); + LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + + // + // Send command via Command Register + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); + + // + // Wait for command completion + // + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) { + // + // Failed to execute command, abort operation + // + return EFI_ABORTED; + } + + return EFI_SUCCESS; } + + diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Atapi.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Atapi.c index b53f20ee82..74b48d1443 100644 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Atapi.c +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Atapi.c @@ -1,4 +1,6 @@ /** @file + This file contains all helper functions on the ATAPI command + Copyright (c) 2006 - 2008, Intel Corporation All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -17,28 +19,18 @@ in the LS-120 drive or ZIP drive. The media status is returned in the Error Status. - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @retval EFI_SUCCESS - The media status is achieved successfully and the media - can be read/written. - - @retval EFI_DEVICE_ERROR - Get Media Status Command is failed. - - @retval EFI_NO_MEDIA - There is no media in the drive. - - @retval EFI_WRITE_PROTECTED - The media is writing protected. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. - @note - This function must be called after the LS120EnableMediaStatus() - with second parameter set to TRUE - (means enable media status notification) is called. + @retval EFI_SUCCESS The media status is achieved successfully and the media + can be read/written. + @retval EFI_DEVICE_ERROR Get Media Status Command is failed. + @retval EFI_NO_MEDIA There is no media in the drive. + @retval EFI_WRITE_PROTECTED The media is writing protected. + @note This function must be called after the LS120EnableMediaStatus() + with second parameter set to TRUE + (means enable media status notification) is called. **/ EFI_STATUS LS120GetMediaStatus ( @@ -100,25 +92,17 @@ LS120GetMediaStatus ( return EFI_SUCCESS; } } - /** This function is used to send Enable Media Status Notification Command or Disable Media Status Notification 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] Enable - a flag that indicates whether enable or disable media - status notification. - - @retval EFI_SUCCESS - If command completes successfully. - - @retval EFI_DEVICE_ERROR - If command failed. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param Enable a flag that indicates whether enable or disable media + status notification. + @retval EFI_SUCCESS If command completes successfully. + @retval EFI_DEVICE_ERROR If command failed. **/ EFI_STATUS LS120EnableMediaStatus ( @@ -179,283 +163,184 @@ LS120EnableMediaStatus ( return EFI_SUCCESS; } - /** - This function is called by DiscoverIdeDevice() during its device - identification. - - Its main purpose is to get enough information for the device media - to fill in the Media data structure of the Block I/O Protocol interface. - - There are 5 steps to reach such objective: - - 1. Sends out the ATAPI Identify Command to the specified device. - Only ATAPI device responses to this command. If the command succeeds, - it returns the Identify data structure which filled with information - about the device. Since the ATAPI device contains removable media, - the only meaningful information is the device module name. - - 2. Sends out ATAPI Inquiry Packet Command to the specified device. - This command will return inquiry data of the device, which contains - the device type information. + This function reads the pending data in the device. - 3. Allocate sense data space for future use. We don't detect the media - presence here to improvement boot performance, especially when CD - media is present. The media detection will be performed just before - each BLK_IO read/write + @param IdeDev Indicates the calling context. - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. + @retval EFI_SUCCESS Successfully read. + @retval EFI_NOT_READY The BSY is set avoiding reading. - @retval EFI_SUCCESS - Identify ATAPI device successfully. - - @retval EFI_DEVICE_ERROR - ATAPI Identify Device Command failed or device type - is not supported by this IDE driver. +**/ +EFI_STATUS +AtapiReadPendingData ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + UINT8 AltRegister; + UINT16 TempWordBuffer; - @note - Parameter "IdeDev" will be updated in this function. + AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); + if ((AltRegister & ATA_STSREG_BSY) == ATA_STSREG_BSY) { + return EFI_NOT_READY; + } + if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) { + TempWordBuffer = IDEReadPortB (IdeDev->PciIo,IdeDev->IoPort->Alt.AltStatus); + while ((TempWordBuffer & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) { + IDEReadPortWMultiple ( + IdeDev->PciIo, + IdeDev->IoPort->Data, + 1, + &TempWordBuffer + ); + TempWordBuffer = IDEReadPortB (IdeDev->PciIo,IdeDev->IoPort->Alt.AltStatus); + } + } + return EFI_SUCCESS; +} - TODO: EFI_OUT_OF_RESOURCES - add return value to function comment - TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +/** + This function is called by either AtapiPacketCommandIn() or AtapiPacketCommandOut(). + It is used to transfer data between host and device. The data direction is specified + by the fourth parameter. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @param Buffer buffer contained data transferred between host and device. + @param ByteCount data size in byte unit of the buffer. + @param Read flag used to determine the data transfer direction. + Read equals 1, means data transferred from device to host; + Read equals 0, means data transferred from host to device. + @param TimeOut timeout value for wait DRQ ready before each data stream's transfer. + + @retval EFI_SUCCESS data is transferred successfully. + @retval EFI_DEVICE_ERROR the device failed to transfer data. **/ EFI_STATUS -ATAPIIdentify ( - IN IDE_BLK_IO_DEV *IdeDev +PioReadWriteData ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT16 *Buffer, + IN UINT32 ByteCount, + IN BOOLEAN Read, + IN UINTN TimeOut ) { - EFI_IDENTIFY_DATA *AtapiIdentifyPointer; - UINT8 DeviceSelect; - EFI_STATUS Status; - // - // device select bit + // required transfer data in word unit. // - DeviceSelect = (UINT8) ((IdeDev->Device) << 4); + UINT32 RequiredWordCount; - AtapiIdentifyPointer = AllocatePool (sizeof (EFI_IDENTIFY_DATA)); - if (AtapiIdentifyPointer == NULL) { - return EFI_OUT_OF_RESOURCES; - } // - // Send ATAPI Identify Command to get IDENTIFY data. + // actual transfer data in word unit. // - Status = AtaPioDataIn ( - IdeDev, - (VOID *) AtapiIdentifyPointer, - sizeof (EFI_IDENTIFY_DATA), - ATA_CMD_IDENTIFY_DEVICE, - DeviceSelect, - 0, - 0, - 0, - 0 - ); - - if (EFI_ERROR (Status)) { - gBS->FreePool (AtapiIdentifyPointer); - return EFI_DEVICE_ERROR; - } - - IdeDev->IdData = AtapiIdentifyPointer; - PrintAtaModuleName (IdeDev); + UINT32 ActualWordCount; + UINT32 WordCount; + EFI_STATUS Status; + UINT16 *PtrBuffer; // - // Send ATAPI Inquiry Packet Command to get INQUIRY data. + // No data transfer is premitted. // - Status = AtapiInquiry (IdeDev); - if (EFI_ERROR (Status)) { - gBS->FreePool (IdeDev->IdData); - // - // Make sure the pIdData will not be freed again. - // - IdeDev->IdData = NULL; - return EFI_DEVICE_ERROR; + if (ByteCount == 0) { + return EFI_SUCCESS; } // - // Get media removable info from INQUIRY data. - // - IdeDev->BlkIo.Media->RemovableMedia = (UINT8) ((IdeDev->InquiryData->RMB & 0x80) == 0x80); - - // - // Identify device type via INQUIRY data. - // - switch (IdeDev->InquiryData->peripheral_type & 0x1f) { - + // for performance, we assert the ByteCount is an even number + // which is actually a resonable assumption + ASSERT((ByteCount%2) == 0); + + PtrBuffer = Buffer; + RequiredWordCount = ByteCount / 2; // - // Magnetic Disk + // ActuralWordCount means the word count of data really transferred. // - case 0x00: + ActualWordCount = 0; + while (ActualWordCount < RequiredWordCount) { + // - // device is LS120 or ZIP drive. + // before each data transfer stream, the host should poll DRQ bit ready, + // to see whether indicates device is ready to transfer data. // - IdeDev->Type = IdeMagnetic; - - IdeDev->BlkIo.Media->MediaId = 0; + Status = DRQReady2 (IdeDev, TimeOut); + if (EFI_ERROR (Status)) { + return CheckErrorStatus (IdeDev); + } + // - // Give initial value + // read Status Register will clear interrupt // - IdeDev->BlkIo.Media->MediaPresent = FALSE; - - IdeDev->BlkIo.Media->LastBlock = 0; - IdeDev->BlkIo.Media->BlockSize = 0x200; - break; - - // - // CD-ROM - // - case 0x05: + IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); - IdeDev->Type = IdeCdRom; - IdeDev->BlkIo.Media->MediaId = 0; // - // Give initial value + // get current data transfer size from Cylinder Registers. // - IdeDev->BlkIo.Media->MediaPresent = FALSE; + WordCount = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb) << 8; + WordCount = WordCount | IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb); + WordCount = WordCount & 0xffff; + WordCount /= 2; - IdeDev->BlkIo.Media->LastBlock = 0; - IdeDev->BlkIo.Media->BlockSize = 0x800; - IdeDev->BlkIo.Media->ReadOnly = TRUE; - break; + WordCount = MIN (WordCount, (RequiredWordCount - ActualWordCount)); - // - // Tape - // - case 0x01: + if (Read) { + IDEReadPortWMultiple ( + IdeDev->PciIo, + IdeDev->IoPort->Data, + WordCount, + PtrBuffer + ); + } else { + IDEWritePortWMultiple ( + IdeDev->PciIo, + IdeDev->IoPort->Data, + WordCount, + PtrBuffer + ); + } - // - // WORM - // - case 0x04: + PtrBuffer += WordCount; + ActualWordCount += WordCount; + } - // - // Optical - // - case 0x07: - - default: - IdeDev->Type = IdeUnknown; - gBS->FreePool (IdeDev->IdData); - gBS->FreePool (IdeDev->InquiryData); + if (Read) { // - // Make sure the pIdData and pInquiryData will not be freed again. + // In the case where the drive wants to send more data than we need to read, + // the DRQ bit will be set and cause delays from DRQClear2(). + // We need to read data from the drive until it clears DRQ so we can move on. // - IdeDev->IdData = NULL; - IdeDev->InquiryData = NULL; - return EFI_DEVICE_ERROR; + AtapiReadPendingData (IdeDev); } // - // original sense data numbers + // After data transfer is completed, normally, DRQ bit should clear. // - IdeDev->SenseDataNumber = 20; - - IdeDev->SenseData = AllocatePool (IdeDev->SenseDataNumber * sizeof (ATAPI_REQUEST_SENSE_DATA)); - if (IdeDev->SenseData == NULL) { - gBS->FreePool (IdeDev->IdData); - gBS->FreePool (IdeDev->InquiryData); - // - // Make sure the pIdData and pInquiryData will not be freed again. - // - IdeDev->IdData = NULL; - IdeDev->InquiryData = NULL; - return EFI_OUT_OF_RESOURCES; + Status = DRQClear2 (IdeDev, ATAPITIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; } - return EFI_SUCCESS; + // + // read status register to check whether error happens. + // + return CheckErrorStatus (IdeDev); } /** - Sends out ATAPI Inquiry Packet Command to the specified device. - This command will return INQUIRY data of the device. - - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @retval EFI_SUCCESS - Inquiry command completes successfully. - - @retval EFI_DEVICE_ERROR - Inquiry command failed. - - @note - Parameter "IdeDev" will be updated in this function. - -**/ -EFI_STATUS -AtapiInquiry ( - IN IDE_BLK_IO_DEV *IdeDev - ) -{ - ATAPI_PACKET_COMMAND Packet; - EFI_STATUS Status; - ATAPI_INQUIRY_DATA *InquiryData; - - // - // prepare command packet for the ATAPI Inquiry Packet Command. - // - ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); - Packet.Inquiry.opcode = ATA_CMD_INQUIRY; - Packet.Inquiry.page_code = 0; - Packet.Inquiry.allocation_length = sizeof (ATAPI_INQUIRY_DATA); - - InquiryData = AllocatePool (sizeof (ATAPI_INQUIRY_DATA)); - if (InquiryData == NULL) { - return EFI_DEVICE_ERROR; - } - - // - // Send command packet and get requested Inquiry data. - // - Status = AtapiPacketCommandIn ( - IdeDev, - &Packet, - (UINT16 *) InquiryData, - sizeof (ATAPI_INQUIRY_DATA), - ATAPITIMEOUT - ); - if (EFI_ERROR (Status)) { - gBS->FreePool (InquiryData); - return EFI_DEVICE_ERROR; - } - - IdeDev->InquiryData = InquiryData; - - return EFI_SUCCESS; -} - -/** - This function is used to send out ATAPI commands conforms to the - Packet Command with PIO Data In Protocol. - - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @param[in] *Packet - pointer pointing to ATAPI_PACKET_COMMAND data structure - which contains the contents of the command. - - @param[in] *Buffer - buffer contained data transferred from device to host. - - @param[in] ByteCount - data size in byte unit of the buffer. - - @param[in] TimeOut - this parameter is used to specify the timeout - value for the PioReadWriteData() function. - - @retval EFI_SUCCESS - send out the ATAPI packet command successfully - and device sends data successfully. - - @retval EFI_DEVICE_ERROR - the device failed to send data. + This function is used to send out ATAPI commands conforms to the Packet Command + with PIO Data In Protocol. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param Packet pointer pointing to ATAPI_PACKET_COMMAND data structure + which contains the contents of the command. + @param Buffer buffer contained data transferred from device to host. + @param ByteCount data size in byte unit of the buffer. + @param TimeOut this parameter is used to specify the timeout value for the + PioReadWriteData() function. + + @retval EFI_SUCCESS send out the ATAPI packet command successfully + and device sends data successfully. + @retval EFI_DEVICE_ERROR the device failed to send data. **/ EFI_STATUS @@ -542,35 +427,21 @@ AtapiPacketCommandIn ( // return PioReadWriteData (IdeDev, Buffer, ByteCount, 1, TimeOut); } - /** - This function is used to send out ATAPI commands conforms to the - Packet Command with PIO Data Out Protocol. - - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @param[in] *Packet - pointer pointing to ATAPI_PACKET_COMMAND data structure - which contains the contents of the command. - - @param[in] *Buffer - buffer contained data transferred from host to device. - - @param[in] ByteCount - data size in byte unit of the buffer. - - @param[in] TimeOut - this parameter is used to specify the timeout - value for the PioReadWriteData() function. - - @retval EFI_SUCCESS - send out the ATAPI packet command successfully - and device received data successfully. - - @retval EFI_DEVICE_ERROR - the device failed to send data. + This function is used to send out ATAPI commands conforms to the Packet Command + with PIO Data Out Protocol. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param Packet pointer pointing to ATAPI_PACKET_COMMAND data structure + which contains the contents of the command. + @param Buffer buffer contained data transferred from host to device. + @param ByteCount data size in byte unit of the buffer. + @param TimeOut this parameter is used to specify the timeout value + for the PioReadWriteData() function. + @retval EFI_SUCCESS send out the ATAPI packet command successfully + and device received data successfully. + @retval EFI_DEVICE_ERROR the device failed to send data. **/ EFI_STATUS @@ -655,213 +526,249 @@ AtapiPacketCommandOut ( // return PioReadWriteData (IdeDev, Buffer, ByteCount, 0, TimeOut); } - /** - This function is called by either AtapiPacketCommandIn() or - AtapiPacketCommandOut(). It is used to transfer data between - host and device. The data direction is specified by the fourth - parameter. + Sends out ATAPI Inquiry Packet Command to the specified device. This command will + return INQUIRY data of the device. - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. - @param[in] *Buffer - buffer contained data transferred between host and device. + @retval EFI_SUCCESS Inquiry command completes successfully. + @retval EFI_DEVICE_ERROR Inquiry command failed. - @param[in] ByteCount - data size in byte unit of the buffer. + @note Parameter "IdeDev" will be updated in this function. - @param[in] Read - flag used to determine the data transfer direction. - Read equals 1, means data transferred from device to host; - Read equals 0, means data transferred from host to device. +**/ +EFI_STATUS +AtapiInquiry ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + ATAPI_PACKET_COMMAND Packet; + EFI_STATUS Status; + ATAPI_INQUIRY_DATA *InquiryData; + + // + // prepare command packet for the ATAPI Inquiry Packet Command. + // + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.Inquiry.opcode = ATA_CMD_INQUIRY; + Packet.Inquiry.page_code = 0; + Packet.Inquiry.allocation_length = sizeof (ATAPI_INQUIRY_DATA); + + InquiryData = AllocatePool (sizeof (ATAPI_INQUIRY_DATA)); + if (InquiryData == NULL) { + return EFI_DEVICE_ERROR; + } + + // + // Send command packet and get requested Inquiry data. + // + Status = AtapiPacketCommandIn ( + IdeDev, + &Packet, + (UINT16 *) InquiryData, + sizeof (ATAPI_INQUIRY_DATA), + ATAPITIMEOUT + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (InquiryData); + return EFI_DEVICE_ERROR; + } + + IdeDev->InquiryData = InquiryData; - @param[in] TimeOut - timeout value for wait DRQ ready before each data - stream's transfer. + return EFI_SUCCESS; +} +/** + This function is called by DiscoverIdeDevice() during its device + identification. + Its main purpose is to get enough information for the device media + to fill in the Media data structure of the Block I/O Protocol interface. - @retval EFI_SUCCESS - data is transferred successfully. + There are 5 steps to reach such objective: + 1. Sends out the ATAPI Identify Command to the specified device. + Only ATAPI device responses to this command. If the command succeeds, + it returns the Identify data structure which filled with information + about the device. Since the ATAPI device contains removable media, + the only meaningful information is the device module name. + 2. Sends out ATAPI Inquiry Packet Command to the specified device. + This command will return inquiry data of the device, which contains + the device type information. + 3. Allocate sense data space for future use. We don't detect the media + presence here to improvement boot performance, especially when CD + media is present. The media detection will be performed just before + each BLK_IO read/write - @retval EFI_DEVICE_ERROR - the device failed to transfer data. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @retval EFI_SUCCESS Identify ATAPI device successfully. + @retval EFI_DEVICE_ERROR ATAPI Identify Device Command failed or device type + is not supported by this IDE driver. + @retval EFI_OUT_OF_RESOURCES Allocate memory for sense data failed + + @note Parameter "IdeDev" will be updated in this function. **/ EFI_STATUS -PioReadWriteData ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINT16 *Buffer, - IN UINT32 ByteCount, - IN BOOLEAN Read, - IN UINTN TimeOut +ATAPIIdentify ( + IN IDE_BLK_IO_DEV *IdeDev ) { + EFI_IDENTIFY_DATA *AtapiIdentifyPointer; + UINT8 DeviceSelect; + EFI_STATUS Status; + // - // required transfer data in word unit. + // device select bit // - UINT32 RequiredWordCount; + DeviceSelect = (UINT8) ((IdeDev->Device) << 4); + AtapiIdentifyPointer = AllocatePool (sizeof (EFI_IDENTIFY_DATA)); + if (AtapiIdentifyPointer == NULL) { + return EFI_OUT_OF_RESOURCES; + } // - // actual transfer data in word unit. + // Send ATAPI Identify Command to get IDENTIFY data. // - UINT32 ActualWordCount; - UINT32 WordCount; - EFI_STATUS Status; - UINT16 *PtrBuffer; + Status = AtaPioDataIn ( + IdeDev, + (VOID *) AtapiIdentifyPointer, + sizeof (EFI_IDENTIFY_DATA), + ATA_CMD_IDENTIFY_DEVICE, + DeviceSelect, + 0, + 0, + 0, + 0 + ); + + if (EFI_ERROR (Status)) { + gBS->FreePool (AtapiIdentifyPointer); + return EFI_DEVICE_ERROR; + } + + IdeDev->IdData = AtapiIdentifyPointer; + PrintAtaModuleName (IdeDev); // - // No data transfer is premitted. + // Send ATAPI Inquiry Packet Command to get INQUIRY data. // - if (ByteCount == 0) { - return EFI_SUCCESS; + Status = AtapiInquiry (IdeDev); + if (EFI_ERROR (Status)) { + gBS->FreePool (IdeDev->IdData); + // + // Make sure the pIdData will not be freed again. + // + IdeDev->IdData = NULL; + return EFI_DEVICE_ERROR; } // - // for performance, we assert the ByteCount is an even number - // which is actually a resonable assumption - ASSERT((ByteCount%2) == 0); - - PtrBuffer = Buffer; - RequiredWordCount = ByteCount / 2; + // Get media removable info from INQUIRY data. // - // ActuralWordCount means the word count of data really transferred. + IdeDev->BlkIo.Media->RemovableMedia = (UINT8) ((IdeDev->InquiryData->RMB & 0x80) == 0x80); + // - ActualWordCount = 0; + // Identify device type via INQUIRY data. + // + switch (IdeDev->InquiryData->peripheral_type & 0x1f) { + + // + // Magnetic Disk + // + case 0x00: - while (ActualWordCount < RequiredWordCount) { - - // - // before each data transfer stream, the host should poll DRQ bit ready, - // to see whether indicates device is ready to transfer data. - // - Status = DRQReady2 (IdeDev, TimeOut); - if (EFI_ERROR (Status)) { - return CheckErrorStatus (IdeDev); - } - // - // read Status Register will clear interrupt + // device is LS120 or ZIP drive. // - IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + IdeDev->Type = IdeMagnetic; + IdeDev->BlkIo.Media->MediaId = 0; // - // get current data transfer size from Cylinder Registers. + // Give initial value // - WordCount = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb) << 8; - WordCount = WordCount | IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb); - WordCount = WordCount & 0xffff; - WordCount /= 2; + IdeDev->BlkIo.Media->MediaPresent = FALSE; - WordCount = MIN (WordCount, (RequiredWordCount - ActualWordCount)); + IdeDev->BlkIo.Media->LastBlock = 0; + IdeDev->BlkIo.Media->BlockSize = 0x200; + break; - if (Read) { - IDEReadPortWMultiple ( - IdeDev->PciIo, - IdeDev->IoPort->Data, - WordCount, - PtrBuffer - ); - } else { - IDEWritePortWMultiple ( - IdeDev->PciIo, - IdeDev->IoPort->Data, - WordCount, - PtrBuffer - ); - } + // + // CD-ROM + // + case 0x05: - PtrBuffer += WordCount; - ActualWordCount += WordCount; - } - - if (Read) { + IdeDev->Type = IdeCdRom; + IdeDev->BlkIo.Media->MediaId = 0; // - // In the case where the drive wants to send more data than we need to read, - // the DRQ bit will be set and cause delays from DRQClear2(). - // We need to read data from the drive until it clears DRQ so we can move on. + // Give initial value // - AtapiReadPendingData (IdeDev); - } + IdeDev->BlkIo.Media->MediaPresent = FALSE; + + IdeDev->BlkIo.Media->LastBlock = 0; + IdeDev->BlkIo.Media->BlockSize = 0x800; + IdeDev->BlkIo.Media->ReadOnly = TRUE; + break; // - // After data transfer is completed, normally, DRQ bit should clear. + // Tape // - Status = DRQClear2 (IdeDev, ATAPITIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } + case 0x01: // - // read status register to check whether error happens. + // WORM // - return CheckErrorStatus (IdeDev); -} - -/** - Sends out ATAPI Test Unit Ready Packet Command to the specified device - to find out whether device is accessible. - - @param[in] *IdeDev Pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param[out] *SResult Sense result for this packet command. - - @retval EFI_SUCCESS Device is accessible. - @retval EFI_DEVICE_ERROR Device is not accessible. - -**/ -EFI_STATUS -AtapiTestUnitReady ( - IN IDE_BLK_IO_DEV *IdeDev, - OUT SENSE_RESULT *SResult - ) -{ - ATAPI_PACKET_COMMAND Packet; - EFI_STATUS Status; - UINTN SenseCount; - + case 0x04: + // - // fill command packet + // Optical // - ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); - Packet.TestUnitReady.opcode = ATA_CMD_TEST_UNIT_READY; + case 0x07: + + default: + IdeDev->Type = IdeUnknown; + gBS->FreePool (IdeDev->IdData); + gBS->FreePool (IdeDev->InquiryData); + // + // Make sure the pIdData and pInquiryData will not be freed again. + // + IdeDev->IdData = NULL; + IdeDev->InquiryData = NULL; + return EFI_DEVICE_ERROR; + } // - // send command packet + // original sense data numbers // - Status = AtapiPacketCommandIn (IdeDev, &Packet, NULL, 0, ATAPITIMEOUT); - if (EFI_ERROR (Status)) { - return Status; - } + IdeDev->SenseDataNumber = 20; - Status = AtapiRequestSense (IdeDev, &SenseCount); - if (EFI_ERROR (Status)) { - return Status; + IdeDev->SenseData = AllocatePool (IdeDev->SenseDataNumber * sizeof (ATAPI_REQUEST_SENSE_DATA)); + if (IdeDev->SenseData == NULL) { + gBS->FreePool (IdeDev->IdData); + gBS->FreePool (IdeDev->InquiryData); + // + // Make sure the pIdData and pInquiryData will not be freed again. + // + IdeDev->IdData = NULL; + IdeDev->InquiryData = NULL; + return EFI_OUT_OF_RESOURCES; } - ParseSenseData (IdeDev, SenseCount, SResult); return EFI_SUCCESS; } - /** - Sends out ATAPI Request Sense Packet Command to the specified device. - This command will return all the current Sense data in the device. - This function will pack all the Sense data in one single buffer. - - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @param[out] **SenseCounts - allocated in this function, and freed by the calling function. - This buffer is used to accommodate all the sense data returned - by the device. - - @retval EFI_SUCCESS - Request Sense command completes successfully. - - @retval EFI_DEVICE_ERROR - Request Sense command failed. - + Sends out ATAPI Request Sense Packet Command to the specified device. This command + will return all the current Sense data in the device. This function will pack + all the Sense data in one single buffer. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param SenseCounts allocated in this function, and freed by the calling function. + This buffer is used to accommodate all the sense data returned + by the device. + + @retval EFI_SUCCESS Request Sense command completes successfully. + @retval EFI_DEVICE_ERROR Request Sense command failed. **/ EFI_STATUS AtapiRequestSense ( @@ -918,30 +825,148 @@ AtapiRequestSense ( } } - (*SenseCounts)++; - // - // We limit MAX sense data count to 20 in order to avoid dead loop. Some - // incompatible ATAPI devices don't retrive NO_SENSE when there is no media. - // In this case, dead loop occurs if we don't have a gatekeeper. 20 is - // supposed to be large enough for any ATAPI device. - // - if ((Sense->sense_key != ATA_SK_NO_SENSE) && ((*SenseCounts) < 20)) { - // - // Ptr is word-based pointer - // - Ptr += (sizeof (ATAPI_REQUEST_SENSE_DATA) + 1) >> 1; + (*SenseCounts)++; + // + // We limit MAX sense data count to 20 in order to avoid dead loop. Some + // incompatible ATAPI devices don't retrive NO_SENSE when there is no media. + // In this case, dead loop occurs if we don't have a gatekeeper. 20 is + // supposed to be large enough for any ATAPI device. + // + if ((Sense->sense_key != ATA_SK_NO_SENSE) && ((*SenseCounts) < 20)) { + // + // Ptr is word-based pointer + // + Ptr += (sizeof (ATAPI_REQUEST_SENSE_DATA) + 1) >> 1; + + } else { + // + // when no sense key, skip out the loop + // + FetchSenseData = FALSE; + } + } + + return EFI_SUCCESS; +} +/** + This function is used to parse sense data. Only the first sense data is honoured + + @param IdeDev Indicates the calling context. + @param SenseCount Count of sense data. + @param Result The parsed result. + + @retval EFI_SUCCESS Successfully parsed. + @retval EFI_INVALID_PARAMETER Count of sense data is zero. + +**/ +EFI_STATUS +ParseSenseData ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN SenseCount, + OUT SENSE_RESULT *Result + ) +{ + ATAPI_REQUEST_SENSE_DATA *SenseData; + + if (SenseCount == 0) { + return EFI_INVALID_PARAMETER; + } + + // + // Only use the first sense data + // + SenseData = IdeDev->SenseData; + *Result = SenseOtherSense; + + switch (SenseData->sense_key) { + case ATA_SK_NO_SENSE: + *Result = SenseNoSenseKey; + break; + case ATA_SK_NOT_READY: + switch (SenseData->addnl_sense_code) { + case ATA_ASC_NO_MEDIA: + *Result = SenseNoMedia; + break; + case ATA_ASC_MEDIA_UPSIDE_DOWN: + *Result = SenseMediaError; + break; + case ATA_ASC_NOT_READY: + if (SenseData->addnl_sense_code_qualifier == ATA_ASCQ_IN_PROGRESS) { + *Result = SenseDeviceNotReadyNeedRetry; + } else { + *Result = SenseDeviceNotReadyNoRetry; + } + break; + } + break; + case ATA_SK_UNIT_ATTENTION: + if (SenseData->addnl_sense_code == ATA_ASC_MEDIA_CHANGE) { + *Result = SenseMediaChange; + } + break; + case ATA_SK_MEDIUM_ERROR: + switch (SenseData->addnl_sense_code) { + case ATA_ASC_MEDIA_ERR1: + case ATA_ASC_MEDIA_ERR2: + case ATA_ASC_MEDIA_ERR3: + case ATA_ASC_MEDIA_ERR4: + *Result = SenseMediaError; + break; + } + break; + default: + break; + } + + return EFI_SUCCESS; +} + +/** + Sends out ATAPI Test Unit Ready Packet Command to the specified device + to find out whether device is accessible. + + @param IdeDev Pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param SResult Sense result for this packet command. + + @retval EFI_SUCCESS Device is accessible. + @retval EFI_DEVICE_ERROR Device is not accessible. + +**/ +EFI_STATUS +AtapiTestUnitReady ( + IN IDE_BLK_IO_DEV *IdeDev, + OUT SENSE_RESULT *SResult + ) +{ + ATAPI_PACKET_COMMAND Packet; + EFI_STATUS Status; + UINTN SenseCount; + + // + // fill command packet + // + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.TestUnitReady.opcode = ATA_CMD_TEST_UNIT_READY; + + // + // send command packet + // + Status = AtapiPacketCommandIn (IdeDev, &Packet, NULL, 0, ATAPITIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } - } else { - // - // when no sense key, skip out the loop - // - FetchSenseData = FALSE; - } + Status = AtapiRequestSense (IdeDev, &SenseCount); + if (EFI_ERROR (Status)) { + return Status; } + ParseSenseData (IdeDev, SenseCount, SResult); return EFI_SUCCESS; } + /** Sends out ATAPI Read Capacity Packet Command to the specified device. This command will return the information regarding the capacity of the @@ -953,16 +978,17 @@ AtapiRequestSense ( if the Read Capacity Command failed, the Sense data must be requested and be analyzed to determine if the Read Capacity Command should retry. - @param[in] *IdeDev Pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - @param[out] SResult Sense result for this packet command + @param IdeDev Pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param SResult Sense result for this packet command @retval EFI_SUCCESS Read Capacity Command finally completes successfully. @retval EFI_DEVICE_ERROR Read Capacity Command failed because of device error. + @retval EFI_NOT_READY Operation succeeds but returned capacity is 0 @note Parameter "IdeDev" will be updated in this function. - TODO: EFI_NOT_READY - add return value to function comment + **/ EFI_STATUS AtapiReadCapacity ( @@ -1082,30 +1108,70 @@ AtapiReadCapacity ( return EFI_DEVICE_ERROR; } } +/** + This function is used to test the current media write-protected or not residing + in the LS-120 drive or ZIP drive. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param WriteProtected if True, current media is write protected. + if FALSE, current media is writable + + @retval EFI_SUCCESS The media write-protected status is achieved successfully + @retval EFI_DEVICE_ERROR Get Media Status Command is failed. +**/ +EFI_STATUS +IsLS120orZipWriteProtected ( + IN IDE_BLK_IO_DEV *IdeDev, + OUT BOOLEAN *WriteProtected + ) +{ + EFI_STATUS Status; + + *WriteProtected = FALSE; + + Status = LS120EnableMediaStatus (IdeDev, TRUE); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // the Get Media Status Command is only valid + // if a Set Features/Enable Media Status Command has been priviously issued. + // + if (LS120GetMediaStatus (IdeDev) == EFI_WRITE_PROTECTED) { + + *WriteProtected = TRUE; + } else { + + *WriteProtected = FALSE; + } + + // + // After Get Media Status Command completes, + // Set Features/Disable Media Command should be sent. + // + Status = LS120EnableMediaStatus (IdeDev, FALSE); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} /** - Used before read/write blocks from/to ATAPI device media. - Since ATAPI device media is removable, it is necessary to detect - whether media is present and get current present media's - information, and if media has been changed, Block I/O Protocol - need to be reinstalled. - - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @param[out] *MediaChange - return value that indicates if the media of the device has been - changed. - - @retval EFI_SUCCESS - media found successfully. - - @retval EFI_DEVICE_ERROR - any error encounters during media detection. - - @retval EFI_NO_MEDIA - media not found. + Used before read/write blocks from/to ATAPI device media. Since ATAPI device + media is removable, it is necessary to detect whether media is present and + get current present media's information, and if media has been changed, Block + I/O Protocol need to be reinstalled. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param MediaChange return value that indicates if the media of the device has been + changed. + + @retval EFI_SUCCESS media found successfully. + @retval EFI_DEVICE_ERROR any error encounters during media detection. + @retval EFI_NO_MEDIA media not found. @note parameter IdeDev may be updated in this function. @@ -1350,22 +1416,14 @@ AtapiDetectMedia ( 65536. This is the main difference between READ(10) and READ(12) Command. The maximum number of blocks in READ(12) is 2 power 32. - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @param[in] *Buffer - A pointer to the destination buffer for the data. - - @param[in] Lba - The starting logical block address to read from - on the device media. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param Buffer A pointer to the destination buffer for the data. + @param Lba The starting logical block address to read from on the + device media. + @param NumberOfBlocks The number of transfer data blocks. - @param[in] NumberOfBlocks - The number of transfer data blocks. - - @return status is fully dependent on the return status - of AtapiPacketCommandIn() function. + @return status is fully dependent on the return status of AtapiPacketCommandIn() function. **/ EFI_STATUS @@ -1475,22 +1533,14 @@ AtapiReadSectors ( unit. The maximum number of blocks that can be transferred once is 65536. - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @param[in] *Buffer - A pointer to the source buffer for the data. - - @param[in] Lba - The starting logical block address to write onto - the device media. - - @param[in] NumberOfBlocks - The number of transfer data blocks. - - @return status is fully dependent on the return status - of AtapiPacketCommandOut() function. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param Buffer A pointer to the source buffer for the data. + @param Lba The starting logical block address to write onto + the device media. + @param NumberOfBlocks The number of transfer data blocks. + + @return status is fully dependent on the return status of AtapiPacketCommandOut() function. **/ EFI_STATUS @@ -1586,7 +1636,6 @@ AtapiWriteSectors ( return Status; } - /** This function is used to implement the Soft Reset on the specified ATAPI device. Different from the AtaSoftReset(), here reset is a ATA @@ -1599,15 +1648,11 @@ AtapiWriteSectors ( This function is called by IdeBlkIoReset(), a interface function of Block I/O protocol. - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. - @retval EFI_SUCCESS - Soft reset completes successfully. - - @retval EFI_DEVICE_ERROR - Any step during the reset process is failed. + @retval EFI_SUCCESS Soft reset completes successfully. + @retval EFI_DEVICE_ERROR Any step during the reset process is failed. **/ EFI_STATUS @@ -1651,45 +1696,23 @@ AtapiSoftReset ( This function is the ATAPI implementation for ReadBlocks in the Block I/O Protocol interface. - @param[in] *IdeBlkIoDevice - Indicates the calling context. - - @param[in] MediaId - The media id that the read request is for. - - @param[in] LBA - The starting logical block address to read from - on the device. - - @param[in] BufferSize - The size of the Buffer in bytes. This must be a - multiple of the intrinsic block size of the device. - - @param[out] *Buffer - A pointer to the destination buffer for the data. - The caller is responsible for either having implicit - or explicit ownership of the memory that data is read into. - - @retval EFI_SUCCESS - Read Blocks successfully. - - @retval EFI_DEVICE_ERROR - Read Blocks failed. - - @retval EFI_NO_MEDIA - There is no media in the device. + @param IdeBlkIoDevice Indicates the calling context. + @param MediaId The media id that the read request is for. + @param LBA The starting logical block address to read from on the device. + @param BufferSize The size of the Buffer in bytes. This must be a multiple + of the intrinsic block size of the device. + @param Buffer A pointer to the destination buffer for the data. The caller + is responsible for either having implicit or explicit + ownership of the memory that data is read into. - @retval EFI_MEDIA_CHANGED - The MediaId is not for the current media. - - @retval EFI_BAD_BUFFER_SIZE - The BufferSize parameter is not a multiple of the - intrinsic block size of the device. - - @retval EFI_INVALID_PARAMETER - The read request contains LBAs that are not valid, - or the data buffer is not valid. - + @retval EFI_SUCCESS Read Blocks successfully. + @retval EFI_DEVICE_ERROR Read Blocks failed. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, + or the data buffer is not valid. **/ EFI_STATUS AtapiBlkIoReadBlocks ( @@ -1799,53 +1822,29 @@ AtapiBlkIoReadBlocks ( return EFI_SUCCESS; } - /** This function is the ATAPI implementation for WriteBlocks in the Block I/O Protocol interface. - @param[in] *IdeBlkIoDevice - Indicates the calling context. - - @param[in] MediaId - The media id that the write request is for. - - @param[in] LBA - The starting logical block address to write onto - the device. - - @param[in] BufferSize - The size of the Buffer in bytes. This must be a - multiple of the intrinsic block size of the device. - - @param[out] *Buffer - A pointer to the source buffer for the data. - The caller is responsible for either having implicit - or explicit ownership of the memory that data is - written from. - - @retval EFI_SUCCESS - Write Blocks successfully. - - @retval EFI_DEVICE_ERROR - Write Blocks failed. - - @retval EFI_NO_MEDIA - There is no media in the device. - - @retval EFI_MEDIA_CHANGE - The MediaId is not for the current media. - - @retval EFI_BAD_BUFFER_SIZE - The BufferSize parameter is not a multiple of the - intrinsic block size of the device. - - @retval EFI_INVALID_PARAMETER - The write request contains LBAs that are not valid, - or the data buffer is not valid. - - TODO: EFI_MEDIA_CHANGED - add return value to function comment - TODO: EFI_WRITE_PROTECTED - add return value to function comment + @param IdeBlkIoDevice Indicates the calling context. + @param MediaId The media id that the write request is for. + @param LBA The starting logical block address to write onto the device. + @param BufferSize The size of the Buffer in bytes. This must be a multiple + of the intrinsic block size of the device. + @param Buffer A pointer to the source buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the memory that data is written from. + + @retval EFI_SUCCESS Write Blocks successfully. + @retval EFI_DEVICE_ERROR Write Blocks failed. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, + or the data buffer is not valid. + + @retval EFI_WRITE_PROTECTED The write protected is enabled or the media does not support write **/ EFI_STATUS AtapiBlkIoWriteBlocks ( @@ -1949,162 +1948,5 @@ AtapiBlkIoWriteBlocks ( } -/** - This function is used to parse sense data. Only the first - sense data is honoured. - - @param[in] IdeDev Indicates the calling context. - @param[in] SenseCount Count of sense data. - @param[out] Result The parsed result. - - @retval EFI_SUCCESS Successfully parsed. - @retval EFI_INVALID_PARAMETER Count of sense data is zero. - -**/ -EFI_STATUS -ParseSenseData ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINTN SenseCount, - OUT SENSE_RESULT *Result - ) -{ - ATAPI_REQUEST_SENSE_DATA *SenseData; - - if (SenseCount == 0) { - return EFI_INVALID_PARAMETER; - } - - // - // Only use the first sense data - // - SenseData = IdeDev->SenseData; - *Result = SenseOtherSense; - - switch (SenseData->sense_key) { - case ATA_SK_NO_SENSE: - *Result = SenseNoSenseKey; - break; - case ATA_SK_NOT_READY: - switch (SenseData->addnl_sense_code) { - case ATA_ASC_NO_MEDIA: - *Result = SenseNoMedia; - break; - case ATA_ASC_MEDIA_UPSIDE_DOWN: - *Result = SenseMediaError; - break; - case ATA_ASC_NOT_READY: - if (SenseData->addnl_sense_code_qualifier == ATA_ASCQ_IN_PROGRESS) { - *Result = SenseDeviceNotReadyNeedRetry; - } else { - *Result = SenseDeviceNotReadyNoRetry; - } - break; - } - break; - case ATA_SK_UNIT_ATTENTION: - if (SenseData->addnl_sense_code == ATA_ASC_MEDIA_CHANGE) { - *Result = SenseMediaChange; - } - break; - case ATA_SK_MEDIUM_ERROR: - switch (SenseData->addnl_sense_code) { - case ATA_ASC_MEDIA_ERR1: - case ATA_ASC_MEDIA_ERR2: - case ATA_ASC_MEDIA_ERR3: - case ATA_ASC_MEDIA_ERR4: - *Result = SenseMediaError; - break; - } - break; - default: - break; - } - - return EFI_SUCCESS; -} - -/** - This function reads the pending data in the device. - - @param[in] IdeDev Indicates the calling context. - - @retval EFI_SUCCESS Successfully read. - @retval EFI_NOT_READY The BSY is set avoiding reading. - -**/ -EFI_STATUS -AtapiReadPendingData ( - IN IDE_BLK_IO_DEV *IdeDev - ) -{ - UINT8 AltRegister; - UINT16 TempWordBuffer; - - AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); - if ((AltRegister & ATA_STSREG_BSY) == ATA_STSREG_BSY) { - return EFI_NOT_READY; - } - if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) { - TempWordBuffer = IDEReadPortB (IdeDev->PciIo,IdeDev->IoPort->Alt.AltStatus); - while ((TempWordBuffer & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) { - IDEReadPortWMultiple ( - IdeDev->PciIo, - IdeDev->IoPort->Data, - 1, - &TempWordBuffer - ); - TempWordBuffer = IDEReadPortB (IdeDev->PciIo,IdeDev->IoPort->Alt.AltStatus); - } - } - return EFI_SUCCESS; -} - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param WriteProtected TODO: add argument description - - @retval EFI_DEVICE_ERROR TODO: Add description for return value - @retval EFI_DEVICE_ERROR TODO: Add description for return value - @retval EFI_SUCCESS TODO: Add description for return value. - -**/ -EFI_STATUS -IsLS120orZipWriteProtected ( - IN IDE_BLK_IO_DEV *IdeDev, - OUT BOOLEAN *WriteProtected - ) -{ - EFI_STATUS Status; - - *WriteProtected = FALSE; - - Status = LS120EnableMediaStatus (IdeDev, TRUE); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // the Get Media Status Command is only valid - // if a Set Features/Enable Media Status Command has been priviously issued. - // - if (LS120GetMediaStatus (IdeDev) == EFI_WRITE_PROTECTED) { - - *WriteProtected = TRUE; - } else { - - *WriteProtected = FALSE; - } - // - // After Get Media Status Command completes, - // Set Features/Disable Media Command should be sent. - // - Status = LS120EnableMediaStatus (IdeDev, FALSE); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - return EFI_SUCCESS; -} diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.c index 9a4f92fb0a..b021f35544 100644 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.c +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.c @@ -1,4 +1,6 @@ /** @file + UEFI Component Name(2) protocol implementation for ConPlatform driver. + Copyright (c) 2006 - 2008, Intel Corporation All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.h b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.h index b75fd3f8d4..6d6d001e5f 100644 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.h +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ComponentName.h @@ -1,4 +1,7 @@ /** @file + + UEFI Component Name(2) protocol implementation header file for IDE Bus driver. + Copyright (c) 2006, Intel Corporation All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -13,7 +16,7 @@ #ifndef _IDE_BUS_COMPONENT_NAME_H_ #define _IDE_BUS_COMPONENT_NAME_H_ -#define ADD_NAME(x) AddName ((x)); +#define ADD_IDE_ATAPI_NAME(x) AddName ((x)); extern EFI_COMPONENT_NAME_PROTOCOL gIDEBusComponentName; extern EFI_COMPONENT_NAME2_PROTOCOL gIDEBusComponentName2; @@ -150,11 +153,9 @@ IDEBusComponentNameGetControllerName ( /** - TODO: Add function description + Add the component name for the IDE/ATAPI device - @param IdeBlkIoDevicePtr TODO: add argument description - - TODO: add return values. + @param IdeBlkIoDevicePtr A pointer to the IDE_BLK_IO_DEV instance. **/ VOID diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverConfiguration.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverConfiguration.c index 97e51b2b0b..8beb95608e 100644 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverConfiguration.c +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverConfiguration.c @@ -1,4 +1,7 @@ /** @file + Implementation of UEFI Driver Configuration Protocol for IDE bus driver which + provides ability to set IDE bus controller specific options. + Copyright (c) 2006 - 2008, Intel Corporation All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -31,11 +34,11 @@ EFI_DRIVER_CONFIGURATION_PROTOCOL gIDEBusDriverConfiguration = { }; /** - TODO: Add function description + Interprete keyboard input. - @retval EFI_ABORTED TODO: Add description for return value. - @retval EFI_SUCCESS TODO: Add description for return value. - @retval EFI_NOT_FOUND TODO: Add description for return value. + @retval EFI_ABORTED Get an 'ESC' key inputed. + @retval EFI_SUCCESS Get an 'Y' or 'y' inputed. + @retval EFI_NOT_FOUND Get an 'N' or 'n' inputed.. **/ EFI_STATUS @@ -80,46 +83,35 @@ GetResponse ( Allows the user to set controller specific options for a controller that a driver is currently managing. - @param This A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL - instance. - @param ControllerHandle The handle of the controller to set options on. - @param ChildHandle The handle of the child controller to set options on. - This is an optional parameter that may be NULL. - It will be NULL for device drivers, and for a bus drivers - that wish to set options for the bus controller. - It will not be NULL for a bus driver that wishes to set - options for one of its child controllers. - @param Language A pointer to a three character ISO 639-2 language - identifier. This is the language of the user interface - that should be presented to the user, and it must match - one of the languages specified in SupportedLanguages. - The number of languages supported by a driver is up to - the driver writer. - @param ActionRequired A pointer to the action that the calling agent is - required to perform when this function returns. - See "Related Definitions" for a list of the actions that - the calling agent is required to perform prior to - accessing ControllerHandle again. - - @retval EFI_SUCCESS The driver specified by This successfully set the - configuration options for the controller specified - by ControllerHandle.. + @param This A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL instance. + @param ControllerHandle The handle of the controller to set options on. + @param ChildHandle The handle of the child controller to set options on. + This is an optional parameter that may be NULL. + It will be NULL for device drivers, and for a bus drivers + that wish to set options for the bus controller. + It will not be NULL for a bus driver that wishes to set + options for one of its child controllers. + @param Language A pointer to a three character ISO 639-2 language identifier. + This is the language of the user interface that should be presented + to the user, and it must match one of the languages specified in + SupportedLanguages. The number of languages supported by a driver is up to + the driver writer. + @param ActionRequired A pointer to the action that the calling agent is required + to perform when this function returns. + + + @retval EFI_SUCCESS The driver specified by This successfully set the configuration + options for the controller specified by ControllerHandle.. @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. - @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a - valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. @retval EFI_INVALID_PARAMETER ActionRequired is NULL. - @retval EFI_UNSUPPORTED The driver specified by This does not support - setting configuration options for the controller - specified by ControllerHandle and ChildHandle. - @retval EFI_UNSUPPORTED The driver specified by This does not support the - language specified by Language. - @retval EFI_DEVICE_ERROR A device error occurred while attempt to set the - configuration options for the controller specified - by ControllerHandle and ChildHandle. - @retval EFI_OUT_RESOURCES There are not enough resources available to set the - configuration options for the controller specified - by ControllerHandle and ChildHandle. - + @retval EFI_UNSUPPORTED The driver specified by This does not support setting configuration options for + the controller specified by ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the language specified by Language. + @retval EFI_DEVICE_ERROR A device error occurred while attempt to set the configuration options for the + controller specified by ControllerHandle and ChildHandle. + @retval EFI_OUT_RESOURCES There are not enough resources available to set the configuration options for the + controller specified by ControllerHandle and ChildHandle **/ EFI_STATUS EFIAPI @@ -189,35 +181,25 @@ IDEBusDriverConfigurationSetOptions ( /** Tests to see if a controller's current configuration options are valid. - @param This A pointer to the EFI_DRIVER_CONFIGURATION_PROTOCOL - instance. - @param ControllerHandle The handle of the controller to test if it's current - configuration options are valid. - @param ChildHandle The handle of the child controller to test if it's - current - configuration options are valid. This is an optional - parameter that may be NULL. It will be NULL for device - drivers. It will also be NULL for a bus drivers that - wish to test the configuration options for the bus - controller. It will not be NULL for a bus driver that - wishes to test configuration options for one of - its child controllers. - - @retval EFI_SUCCESS The controller specified by ControllerHandle and - ChildHandle that is being managed by the driver - specified by This has a valid set of configuration - options. + @param This A pointer to the EFI_DRIVER_CONFIGURATION_PROTOCOL instance. + @param ControllerHandle The handle of the controller to test if it's current configuration options + are valid. + @param ChildHandle The handle of the child controller to test if it's current configuration + options are valid. This is an optional parameter that may be NULL. It will + be NULL for device drivers. It will also be NULL for a bus drivers that + wish to test the configuration options for the bus controller. It will + not be NULL for a bus driver that wishes to test configuration options for + one of its child controllers. + @retval EFI_SUCCESS The controller specified by ControllerHandle and ChildHandle that is being + managed by the driver specified by This has a valid set of configuration + options. @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. - @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid - EFI_HANDLE. - @retval EFI_UNSUPPORTED The driver specified by This is not currently - managing the controller specified by - ControllerHandle and ChildHandle. - @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and - ChildHandle that is being managed by the driver - specified by This has an invalid set of - configuration options. - + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_UNSUPPORTED The driver specified by This is not currently managing the controller + specified by ControllerHandle and ChildHandle. + @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and ChildHandle that is being + managed by the driver specified by This has an invalid set of configuration + options. **/ EFI_STATUS EFIAPI @@ -249,51 +231,37 @@ IDEBusDriverConfigurationOptionsValid ( return EFI_SUCCESS; } - /** Forces a driver to set the default configuration options for a controller. - @param This A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL - instance. - @param ControllerHandle The handle of the controller to force default - configuration options on. - @param ChildHandle The handle of the child controller to force default - configuration options on This is an optional parameter - that may be NULL. It will be NULL for device drivers. - It will also be NULL for a bus drivers that wish to - force default configuration options for the bus - controller. It will not be NULL for a bus driver that - wishes to force default configuration options for one - of its child controllers. - @param DefaultType The type of default configuration options to force on - the controller specified by ControllerHandle and - ChildHandle. See Table 9-1 for legal values. - A DefaultType of 0x00000000 must be supported - by this protocol. - @param ActionRequired A pointer to the action that the calling agent - is required to perform when this function returns. - - @retval EFI_SUCCESS The driver specified by This successfully forced - the default configuration options on the - controller specified by ControllerHandle and - ChildHandle. + @param This A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL instance. + @param ControllerHandle The handle of the controller to force default configuration options on. + @param ChildHandle The handle of the child controller to force default configuration + options on This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL for a bus + drivers that wish to force default configuration options for the bus + controller. It will not be NULL for a bus driver that wishes to force + default configuration options for one of its child controllers. + @param DefaultType The type of default configuration options to force on the controller + specified by ControllerHandle and ChildHandle. + @param ActionRequired A pointer to the action that the calling agent is required to perform + when this function returns. + + @retval EFI_SUCCESS The driver specified by This successfully forced the + default configuration options on the controller specified by + ControllerHandle and ChildHandle. @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. - @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a - valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. @retval EFI_INVALID_PARAMETER ActionRequired is NULL. - @retval EFI_UNSUPPORTED The driver specified by This does not support - forcing the default configuration options on - the controller specified by ControllerHandle - and ChildHandle. - @retval EFI_UNSUPPORTED The driver specified by This does not support - the configuration type specified by DefaultType. - @retval EFI_DEVICE_ERROR A device error occurred while attempt to force - the default configuration options on the controller - specified by ControllerHandle and ChildHandle. - @retval EFI_OUT_RESOURCES There are not enough resources available to force - the default configuration options on the controller - specified by ControllerHandle and ChildHandle. - + @retval EFI_UNSUPPORTED The driver specified by This does not support forcing the default + configuration options on the controller specified by ControllerHandle + and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the configuration type + specified by DefaultType. + @retval EFI_DEVICE_ERROR A device error occurred while attempt to force the default configuration + options on the controller specified by ControllerHandle and ChildHandle. + @retval EFI_OUT_RESOURCES There are not enough resources available to force the default configuration + options on the controller specified by ControllerHandle and ChildHandle. **/ EFI_STATUS EFIAPI diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverDiagnostics.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverDiagnostics.c index 85d2bf3ad8..5e1383c0c2 100644 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverDiagnostics.c +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/DriverDiagnostics.c @@ -1,4 +1,7 @@ /** @file + Implementation of UEFI driver Dialnostics protocol which to perform diagnostic on the IDE + Bus controller. + Copyright (c) 2006 - 2008, Intel Corporation All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -34,59 +37,49 @@ GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gIDEBusDriverDiag /** Runs diagnostics on a controller. - @param This A pointer to the EFI_DRIVER_DIAGNOSTICS_PROTOCOL - instance. + @param This A pointer to the EFI_DRIVER_DIAGNOSTICS_PROTOCOLinstance. @param ControllerHandle The handle of the controller to run diagnostics on. - @param ChildHandle The handle of the child controller to run diagnostics on - This is an optional parameter that may be NULL. It will - be NULL for device drivers. It will also be NULL for a - bus drivers that wish to run diagnostics on the bus - controller. It will not be NULL for a bus driver that - wishes to run diagnostics on one of its child - controllers. - @param DiagnosticType Indicates type of diagnostics to perform on the - controller specified by ControllerHandle and ChildHandle. - See "Related Definitions" for the list of supported - types. - @param Language A pointer to a three character ISO 639-2 language - identifier. This is the language in which the optional - error message should be returned in Buffer, and it must - match one of the languages specified in - SupportedLanguages. The number of languages supported by - a driver is up to the driver writer. - @param ErrorType A GUID that defines the format of the data returned in - Buffer. - @param BufferSize The size, in bytes, of the data returned in Buffer. - @param Buffer A buffer that contains a Null-terminated Unicode string - plus some additional data whose format is defined by - ErrorType. Buffer is allocated by this function with - AllocatePool(), and it is the caller's responsibility - to free it with a call to FreePool(). - - @retval EFI_SUCCESS The controller specified by ControllerHandle and - ChildHandle passed the diagnostic. + @param ChildHandle The handle of the child controller to run diagnostics on + This is an optional parameter that may be NULL. It will + be NULL for device drivers. It will also be NULL for a + bus drivers that wish to run diagnostics on the bus controller. + It will not be NULL for a bus driver that wishes to run + diagnostics on one of its child controllers. + @param DiagnosticType Indicates type of diagnostics to perform on the controller + specified by ControllerHandle and ChildHandle. + @param Language A pointer to a three character ISO 639-2 language identifier. + This is the language in which the optional error message should + be returned in Buffer, and it must match one of the languages + specified in SupportedLanguages. The number of languages supported by + a driver is up to the driver writer. + @param ErrorType A GUID that defines the format of the data returned in Buffer. + @param BufferSize The size, in bytes, of the data returned in Buffer. + @param Buffer A buffer that contains a Null-terminated Unicode string + plus some additional data whose format is defined by ErrorType. + Buffer is allocated by this function with AllocatePool(), and + it is the caller's responsibility to free it with a call to FreePool(). + + @retval EFI_SUCCESS The controller specified by ControllerHandle and ChildHandle passed + the diagnostic. @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. - @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid - EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. @retval EFI_INVALID_PARAMETER Language is NULL. @retval EFI_INVALID_PARAMETER ErrorType is NULL. @retval EFI_INVALID_PARAMETER BufferType is NULL. @retval EFI_INVALID_PARAMETER Buffer is NULL. - @retval EFI_UNSUPPORTED The driver specified by This does not support - running diagnostics for the controller specified - by ControllerHandle and ChildHandle. - @retval EFI_UNSUPPORTED The driver specified by This does not support the - type of diagnostic specified by DiagnosticType. - @retval EFI_UNSUPPORTED The driver specified by This does not support the - language specified by Language. - @retval EFI_OUT_OF_RESOURCES There are not enough resources available to complete - the diagnostics. - @retval EFI_OUT_OF_RESOURCES There are not enough resources available to return - the status information in ErrorType, BufferSize, - and Buffer. - @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and - ChildHandle did not pass the diagnostic. - + @retval EFI_UNSUPPORTED The driver specified by This does not support running + diagnostics for the controller specified by ControllerHandle + and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + type of diagnostic specified by DiagnosticType. + @retval EFI_UNSUPPORTED The driver specified by This does not support the language + specified by Language. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to complete the + diagnostics. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to return the + status information in ErrorType, BufferSize,and Buffer. + @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and ChildHandle + did not pass the diagnostic. **/ EFI_STATUS EFIAPI diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.c index 96f1ce3bd8..fa4d636acb 100644 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.c +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.c @@ -1,4 +1,6 @@ /** @file + The file ontaining the helper functions implement of the Ide Bus driver + Copyright (c) 2006 - 2008, Intel Corporation All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -19,13 +21,12 @@ BOOLEAN MasterDeviceExist = FALSE; UINT8 MasterDeviceType = INVALID_DEVICE_TYPE; /** - TODO: Add function description - - @param PciIo TODO: add argument description - @param Port TODO: add argument description + read a one-byte data from a IDE port - TODO: add return values. + @param PciIo The PCI IO protocol instance + @param Port the IDE Port number + return the one-byte data read from IDE port **/ UINT8 IDEReadPortB ( @@ -49,7 +50,6 @@ IDEReadPortB ( ); return Data; } - /** Reads multiple words of data from the IDE data port. Call the IO abstraction once to do the complete read, @@ -109,14 +109,11 @@ IDEReadPortWMultiple ( } /** - TODO: Add function description - - @param PciIo TODO: add argument description - @param Port TODO: add argument description - @param Data TODO: add argument description - - TODO: add return values. + write a 1-byte data to a specific IDE port + @param PciIo PCI IO protocol instance + @param Port The IDE port to be writen + @param Data The data to write to the port **/ VOID IDEWritePortB ( @@ -140,14 +137,11 @@ IDEWritePortB ( } /** - TODO: Add function description - - @param PciIo TODO: add argument description - @param Port TODO: add argument description - @param Data TODO: add argument description - - TODO: add return values. + write a 1-word data to a specific IDE port + @param PciIo PCI IO protocol instance + @param Port The IDE port to be writen + @param Data The data to write to the port **/ VOID IDEWritePortW ( @@ -227,10 +221,6 @@ IDEWritePortWMultiple ( gBS->FreePool (WorkingBuffer); } - -// -// GetIdeRegistersBaseAddr -// /** Get IDE IO port registers' base addresses by mode. In 'Compatibility' mode, use fixed addresses. In Native-PCI mode, get base addresses from BARs in @@ -287,9 +277,6 @@ GetIdeRegistersBaseAddr ( IN EFI_PCI_IO_PROTOCOL *PciIo, OUT IDE_REGISTERS_BASE_ADDR *IdeRegsBaseAddr ) -// TODO: EFI_UNSUPPORTED - add return value to function comment -// TODO: EFI_UNSUPPORTED - add return value to function comment -// TODO: EFI_SUCCESS - add return value to function comment { EFI_STATUS Status; PCI_TYPE00 PciData; @@ -366,7 +353,6 @@ EFI_STATUS ReassignIdeResources ( IN IDE_BLK_IO_DEV *IdeDev ) -// TODO: EFI_SUCCESS - add return value to function comment { EFI_STATUS Status; IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel]; @@ -407,135 +393,6 @@ ReassignIdeResources ( return EFI_SUCCESS; } -// -// DiscoverIdeDevice -// -/** - Detect if there is disk connected to this port - - @param IdeDev The BLK_IO private data which specifies the IDE device. - -**/ -EFI_STATUS -DiscoverIdeDevice ( - IN IDE_BLK_IO_DEV *IdeDev - ) -// TODO: EFI_NOT_FOUND - add return value to function comment -// TODO: EFI_NOT_FOUND - add return value to function comment -// TODO: EFI_SUCCESS - add return value to function comment -{ - EFI_STATUS Status; - EFI_STATUS LongPhyStatus; - - // - // If a channel has not been checked, check it now. Then set it to "checked" state - // After this step, all devices in this channel have been checked. - // - if (!ChannelDeviceDetected) { - Status = DetectIDEController (IdeDev); - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } - } - - Status = EFI_NOT_FOUND; - - // - // Device exists. test if it is an ATA device. - // Prefer the result from DetectIDEController, - // if failed, try another device type to handle - // devices that not follow the spec. - // - if ((IdeDev->Device == IdeMaster) && (MasterDeviceExist)) { - if (MasterDeviceType == ATA_DEVICE_TYPE) { - Status = ATAIdentify (IdeDev); - if (EFI_ERROR (Status)) { - Status = ATAPIIdentify (IdeDev); - if (!EFI_ERROR (Status)) { - MasterDeviceType = ATAPI_DEVICE_TYPE; - } - } - } else { - Status = ATAPIIdentify (IdeDev); - if (EFI_ERROR (Status)) { - Status = ATAIdentify (IdeDev); - if (!EFI_ERROR (Status)) { - MasterDeviceType = ATA_DEVICE_TYPE; - } - } - } - } - if ((IdeDev->Device == IdeSlave) && (SlaveDeviceExist)) { - if (SlaveDeviceType == ATA_DEVICE_TYPE) { - Status = ATAIdentify (IdeDev); - if (EFI_ERROR (Status)) { - Status = ATAPIIdentify (IdeDev); - if (!EFI_ERROR (Status)) { - SlaveDeviceType = ATAPI_DEVICE_TYPE; - } - } - } else { - Status = ATAPIIdentify (IdeDev); - if (EFI_ERROR (Status)) { - Status = ATAIdentify (IdeDev); - if (!EFI_ERROR (Status)) { - SlaveDeviceType = ATA_DEVICE_TYPE; - } - } - } - } - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } - // - // Init Block I/O interface - // - LongPhyStatus = AtaEnableLongPhysicalSector (IdeDev); - if (!EFI_ERROR (LongPhyStatus)) { - IdeDev->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2; - } else { - IdeDev->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION; - } - IdeDev->BlkIo.Reset = IDEBlkIoReset; - IdeDev->BlkIo.ReadBlocks = IDEBlkIoReadBlocks; - IdeDev->BlkIo.WriteBlocks = IDEBlkIoWriteBlocks; - IdeDev->BlkIo.FlushBlocks = IDEBlkIoFlushBlocks; - - IdeDev->BlkMedia.LogicalPartition = FALSE; - IdeDev->BlkMedia.WriteCaching = FALSE; - - // - // Init Disk Info interface - // - gBS->CopyMem (&IdeDev->DiskInfo.Interface, &gEfiDiskInfoIdeInterfaceGuid, sizeof (EFI_GUID)); - IdeDev->DiskInfo.Inquiry = IDEDiskInfoInquiry; - IdeDev->DiskInfo.Identify = IDEDiskInfoIdentify; - IdeDev->DiskInfo.SenseData = IDEDiskInfoSenseData; - IdeDev->DiskInfo.WhichIde = IDEDiskInfoWhichIde; - - return EFI_SUCCESS; -} - -/** - This interface is used to initialize all state data related to the detection of one - channel. - - @retval EFI_SUCCESS Completed Successfully. - -**/ -EFI_STATUS -InitializeIDEChannelData ( - VOID - ) -{ - ChannelDeviceDetected = FALSE; - MasterDeviceExist = FALSE; - MasterDeviceType = 0xff; - SlaveDeviceExist = FALSE; - SlaveDeviceType = 0xff; - return EFI_SUCCESS; -} - /** This function is called by DiscoverIdeDevice(). It is used for detect whether the IDE device exists in the specified Channel as the specified @@ -552,20 +409,12 @@ InitializeIDEChannelData ( register, it is a must to select the current device to accept the command by set the device number in the Head/Device Register. - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. + @param IdeDev pointer to IDE_BLK_IO_DEV data structure, used to record all the + information of the IDE device. - @retval TRUE - successfully detects device. + @retval EFI_SUCCESS successfully detects device. - @retval FALSE - any failure during detection process will return this - value. - - @note - TODO: EFI_SUCCESS - add return value to function comment - TODO: EFI_NOT_FOUND - add return value to function comment + @retval other any failure during detection process will return this value. **/ EFI_STATUS @@ -732,24 +581,140 @@ DetectIDEController ( ChannelDeviceDetected = TRUE; return EFI_SUCCESS; } +/** + Detect if there is disk attached to this port + + @param IdeDev The BLK_IO private data which specifies the IDE device. + +**/ +EFI_STATUS +DiscoverIdeDevice ( + IN IDE_BLK_IO_DEV *IdeDev + ) +{ + EFI_STATUS Status; + EFI_STATUS LongPhyStatus; + + // + // If a channel has not been checked, check it now. Then set it to "checked" state + // After this step, all devices in this channel have been checked. + // + if (!ChannelDeviceDetected) { + Status = DetectIDEController (IdeDev); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + } + + Status = EFI_NOT_FOUND; + + // + // Device exists. test if it is an ATA device. + // Prefer the result from DetectIDEController, + // if failed, try another device type to handle + // devices that not follow the spec. + // + if ((IdeDev->Device == IdeMaster) && (MasterDeviceExist)) { + if (MasterDeviceType == ATA_DEVICE_TYPE) { + Status = ATAIdentify (IdeDev); + if (EFI_ERROR (Status)) { + Status = ATAPIIdentify (IdeDev); + if (!EFI_ERROR (Status)) { + MasterDeviceType = ATAPI_DEVICE_TYPE; + } + } + } else { + Status = ATAPIIdentify (IdeDev); + if (EFI_ERROR (Status)) { + Status = ATAIdentify (IdeDev); + if (!EFI_ERROR (Status)) { + MasterDeviceType = ATA_DEVICE_TYPE; + } + } + } + } + if ((IdeDev->Device == IdeSlave) && (SlaveDeviceExist)) { + if (SlaveDeviceType == ATA_DEVICE_TYPE) { + Status = ATAIdentify (IdeDev); + if (EFI_ERROR (Status)) { + Status = ATAPIIdentify (IdeDev); + if (!EFI_ERROR (Status)) { + SlaveDeviceType = ATAPI_DEVICE_TYPE; + } + } + } else { + Status = ATAPIIdentify (IdeDev); + if (EFI_ERROR (Status)) { + Status = ATAIdentify (IdeDev); + if (!EFI_ERROR (Status)) { + SlaveDeviceType = ATA_DEVICE_TYPE; + } + } + } + } + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + // + // Init Block I/O interface + // + LongPhyStatus = AtaEnableLongPhysicalSector (IdeDev); + if (!EFI_ERROR (LongPhyStatus)) { + IdeDev->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2; + } else { + IdeDev->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION; + } + IdeDev->BlkIo.Reset = IDEBlkIoReset; + IdeDev->BlkIo.ReadBlocks = IDEBlkIoReadBlocks; + IdeDev->BlkIo.WriteBlocks = IDEBlkIoWriteBlocks; + IdeDev->BlkIo.FlushBlocks = IDEBlkIoFlushBlocks; + + IdeDev->BlkMedia.LogicalPartition = FALSE; + IdeDev->BlkMedia.WriteCaching = FALSE; + // + // Init Disk Info interface + // + gBS->CopyMem (&IdeDev->DiskInfo.Interface, &gEfiDiskInfoIdeInterfaceGuid, sizeof (EFI_GUID)); + IdeDev->DiskInfo.Inquiry = IDEDiskInfoInquiry; + IdeDev->DiskInfo.Identify = IDEDiskInfoIdentify; + IdeDev->DiskInfo.SenseData = IDEDiskInfoSenseData; + IdeDev->DiskInfo.WhichIde = IDEDiskInfoWhichIde; + + return EFI_SUCCESS; +} + +/** + This interface is used to initialize all state data related to the detection of one + channel. + + @retval EFI_SUCCESS Completed Successfully. + +**/ +EFI_STATUS +InitializeIDEChannelData ( + VOID + ) +{ + ChannelDeviceDetected = FALSE; + MasterDeviceExist = FALSE; + MasterDeviceType = 0xff; + SlaveDeviceExist = FALSE; + SlaveDeviceType = 0xff; + return EFI_SUCCESS; +} /** This function is used to poll for the DRQ bit clear in the Status Register. DRQ is cleared when the device is finished transferring data. So this function is called after data transfer is finished. - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ clear. - @param[in] TimeoutInMilliSeconds - used to designate the timeout for the DRQ clear. + @retval EFI_SUCCESS DRQ bit clear within the time out. - @retval EFI_SUCCESS - DRQ bit clear within the time out. - - @retval EFI_TIMEOUT - DRQ bit not clear within the time out. + @retval EFI_TIMEOUT DRQ bit not clear within the time out. @note Read Status Register will clear interrupt status. @@ -760,11 +725,6 @@ DRQClear ( IN IDE_BLK_IO_DEV *IdeDev, IN UINTN TimeoutInMilliSeconds ) -// TODO: function comment is missing 'Routine Description:' -// TODO: function comment is missing 'Arguments:' -// TODO: IdeDev - add argument and description to function comment -// TODO: TimeoutInMilliSeconds - add argument and description to function comment -// TODO: EFI_ABORTED - add return value to function comment { UINT32 Delay; UINT8 StatusRegister; @@ -805,28 +765,21 @@ DRQClear ( return EFI_SUCCESS; } - /** This function is used to poll for the DRQ bit clear in the Alternate Status Register. DRQ is cleared when the device is finished transferring data. So this function is called after data transfer is finished. - @param[in] *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. - @param[in] TimeoutInMilliSeconds - used to designate the timeout for the DRQ clear. + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ clear. - @retval EFI_SUCCESS - DRQ bit clear within the time out. + @retval EFI_SUCCESS DRQ bit clear within the time out. - @retval EFI_TIMEOUT - DRQ bit not clear within the time out. - - @note - Read Alternate Status Register will not clear interrupt status. + @retval EFI_TIMEOUT DRQ bit not clear within the time out. + @note Read Alternate Status Register will not clear interrupt status. **/ EFI_STATUS @@ -834,11 +787,6 @@ DRQClear2 ( IN IDE_BLK_IO_DEV *IdeDev, IN UINTN TimeoutInMilliSeconds ) -// TODO: function comment is missing 'Routine Description:' -// TODO: function comment is missing 'Arguments:' -// TODO: IdeDev - add argument and description to function comment -// TODO: TimeoutInMilliSeconds - add argument and description to function comment -// TODO: EFI_ABORTED - add return value to function comment { UINT32 Delay; UINT8 AltRegister; @@ -887,24 +835,15 @@ DRQClear2 ( is called after the command is sent to the device and before required data is transferred. - @param[in] IDE_BLK_IO_DEV IN *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure,used - to record all the information of the IDE device. - - @param[in] UINTN IN TimeoutInMilliSeconds - used to designate the timeout for the DRQ ready. - - @retval EFI_SUCCESS - DRQ bit set within the time out. - - @retval EFI_TIMEOUT - DRQ bit not set within the time out. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to + record all the information of the IDE device. + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. - @retval EFI_ABORTED - DRQ bit not set caused by the command abort. + @retval EFI_SUCCESS DRQ bit set within the time out. + @retval EFI_TIMEOUT DRQ bit not set within the time out. + @retval EFI_ABORTED DRQ bit not set caused by the command abort. - @note - Read Status Register will clear interrupt status. + @note Read Status Register will clear interrupt status. **/ EFI_STATUS @@ -912,10 +851,6 @@ DRQReady ( IN IDE_BLK_IO_DEV *IdeDev, IN UINTN TimeoutInMilliSeconds ) -// TODO: function comment is missing 'Routine Description:' -// TODO: function comment is missing 'Arguments:' -// TODO: IdeDev - add argument and description to function comment -// TODO: TimeoutInMilliSeconds - add argument and description to function comment { UINT32 Delay; UINT8 StatusRegister; @@ -957,31 +892,20 @@ DRQReady ( return EFI_SUCCESS; } - /** - This function is used to poll for the DRQ bit set in the - Alternate Status Register. DRQ is set when the device is ready to - transfer data. So this function is called after the command - is sent to the device and before required data is transferred. - - @param[in] IDE_BLK_IO_DEV IN *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @param[in] UINTN IN TimeoutInMilliSeconds - used to designate the timeout for the DRQ ready. - - @retval EFI_SUCCESS - DRQ bit set within the time out. + This function is used to poll for the DRQ bit set in the Alternate Status Register. + DRQ is set when the device is ready to transfer data. So this function is called after + the command is sent to the device and before required data is transferred. - @retval EFI_TIMEOUT - DRQ bit not set within the time out. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to + record all the information of the IDE device. - @retval EFI_ABORTED - DRQ bit not set caused by the command abort. + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. - @note - Read Alternate Status Register will not clear interrupt status. + @retval EFI_SUCCESS DRQ bit set within the time out. + @retval EFI_TIMEOUT DRQ bit not set within the time out. + @retval EFI_ABORTED DRQ bit not set caused by the command abort. + @note Read Alternate Status Register will not clear interrupt status. **/ EFI_STATUS @@ -989,10 +913,6 @@ DRQReady2 ( IN IDE_BLK_IO_DEV *IdeDev, IN UINTN TimeoutInMilliSeconds ) -// TODO: function comment is missing 'Routine Description:' -// TODO: function comment is missing 'Arguments:' -// TODO: IdeDev - add argument and description to function comment -// TODO: TimeoutInMilliSeconds - add argument and description to function comment { UINT32 Delay; UINT8 AltRegister; @@ -1036,36 +956,23 @@ DRQReady2 ( } /** - This function is used to poll for the BSY bit clear in the - Status Register. BSY is clear when the device is not busy. - Every command must be sent after device is not busy. - - @param[in] IDE_BLK_IO_DEV IN *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. + This function is used to poll for the BSY bit clear in the Status Register. BSY + is clear when the device is not busy. Every command must be sent after device is not busy. - @param[in] UINTN IN TimeoutInMilliSeconds - used to designate the timeout for the DRQ ready. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. - @retval EFI_SUCCESS - BSY bit clear within the time out. - - @retval EFI_TIMEOUT - BSY bit not clear within the time out. - - @note - Read Status Register will clear interrupt status. + @retval EFI_SUCCESS BSY bit clear within the time out. + @retval EFI_TIMEOUT BSY bit not clear within the time out. + @note Read Status Register will clear interrupt status. **/ EFI_STATUS WaitForBSYClear ( IN IDE_BLK_IO_DEV *IdeDev, IN UINTN TimeoutInMilliSeconds ) -// TODO: function comment is missing 'Routine Description:' -// TODO: function comment is missing 'Arguments:' -// TODO: IdeDev - add argument and description to function comment -// TODO: TimeoutInMilliSeconds - add argument and description to function comment { UINT32 Delay; UINT8 StatusRegister; @@ -1093,29 +1000,18 @@ WaitForBSYClear ( return EFI_SUCCESS; } -// -// WaitForBSYClear2 -// /** - This function is used to poll for the BSY bit clear in the - Alternate Status Register. BSY is clear when the device is not busy. - Every command must be sent after device is not busy. - - @param[in] IDE_BLK_IO_DEV IN *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. + This function is used to poll for the BSY bit clear in the Alternate Status Register. + BSY is clear when the device is not busy. Every command must be sent after device is + not busy. - @param[in] UINTN IN TimeoutInMilliSeconds - used to designate the timeout for the DRQ ready. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @paramTimeoutInMilliSeconds used to designate the timeout for the DRQ ready. - @retval EFI_SUCCESS - BSY bit clear within the time out. - - @retval EFI_TIMEOUT - BSY bit not clear within the time out. - - @note - Read Alternate Status Register will not clear interrupt status. + @retval EFI_SUCCESS BSY bit clear within the time out. + @retval EFI_TIMEOUT BSY bit not clear within the time out. + @note Read Alternate Status Register will not clear interrupt status. **/ EFI_STATUS @@ -1123,10 +1019,6 @@ WaitForBSYClear2 ( IN IDE_BLK_IO_DEV *IdeDev, IN UINTN TimeoutInMilliSeconds ) -// TODO: function comment is missing 'Routine Description:' -// TODO: function comment is missing 'Arguments:' -// TODO: IdeDev - add argument and description to function comment -// TODO: TimeoutInMilliSeconds - add argument and description to function comment { UINT32 Delay; UINT8 AltRegister; @@ -1150,43 +1042,25 @@ WaitForBSYClear2 ( return EFI_SUCCESS; } - -// -// DRDYReady -// /** - This function is used to poll for the DRDY bit set in the - Status Register. DRDY bit is set when the device is ready - to accept command. Most ATA commands must be sent after - DRDY set except the ATAPI Packet Command. - - @param[in] IDE_BLK_IO_DEV IN *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. - - @param[in] UINTN IN DelayInMilliSeconds - used to designate the timeout for the DRQ ready. - - @retval EFI_SUCCESS - DRDY bit set within the time out. + This function is used to poll for the DRDY bit set in the Status Register. DRDY + bit is set when the device is ready to accept command. Most ATA commands must be + sent after DRDY set except the ATAPI Packet Command. - @retval EFI_TIMEOUT - DRDY bit not set within the time out. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param DelayInMilliSeconds used to designate the timeout for the DRQ ready. - @note - Read Status Register will clear interrupt status. + @retval EFI_SUCCESS DRDY bit set within the time out. + @retval EFI_TIMEOUT DRDY bit not set within the time out. + @note Read Status Register will clear interrupt status. **/ EFI_STATUS DRDYReady ( IN IDE_BLK_IO_DEV *IdeDev, IN UINTN DelayInMilliSeconds ) -// TODO: function comment is missing 'Routine Description:' -// TODO: function comment is missing 'Arguments:' -// TODO: IdeDev - add argument and description to function comment -// TODO: DelayInMilliSeconds - add argument and description to function comment -// TODO: EFI_ABORTED - add return value to function comment { UINT32 Delay; UINT8 StatusRegister; @@ -1221,31 +1095,19 @@ DRDYReady ( return EFI_SUCCESS; } - -// -// DRDYReady2 -// /** - This function is used to poll for the DRDY bit set in the - Alternate Status Register. DRDY bit is set when the device is ready - to accept command. Most ATA commands must be sent after - DRDY set except the ATAPI Packet Command. - - @param[in] IDE_BLK_IO_DEV IN *IdeDev - pointer pointing to IDE_BLK_IO_DEV data structure, used - to record all the information of the IDE device. + This function is used to poll for the DRDY bit set in the Alternate Status Register. + DRDY bit is set when the device is ready to accept command. Most ATA commands must + be sent after DRDY set except the ATAPI Packet Command. - @param[in] UINTN IN DelayInMilliSeconds - used to designate the timeout for the DRQ ready. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param DelayInMilliSeconds used to designate the timeout for the DRQ ready. - @retval EFI_SUCCESS - DRDY bit set within the time out. + @retval EFI_SUCCESS DRDY bit set within the time out. + @retval EFI_TIMEOUT DRDY bit not set within the time out. - @retval EFI_TIMEOUT - DRDY bit not set within the time out. - - @note - Read Alternate Status Register will clear interrupt status. + @note Read Alternate Status Register will clear interrupt status. **/ EFI_STATUS @@ -1253,11 +1115,6 @@ DRDYReady2 ( IN IDE_BLK_IO_DEV *IdeDev, IN UINTN DelayInMilliSeconds ) -// TODO: function comment is missing 'Routine Description:' -// TODO: function comment is missing 'Arguments:' -// TODO: IdeDev - add argument and description to function comment -// TODO: DelayInMilliSeconds - add argument and description to function comment -// TODO: EFI_ABORTED - add return value to function comment { UINT32 Delay; UINT8 AltRegister; @@ -1292,57 +1149,10 @@ DRDYReady2 ( return EFI_SUCCESS; } - -// -// SwapStringChars -// -/** - This function is a helper function used to change the char order in a - string. It is designed specially for the PrintAtaModuleName() function. - After the IDE device is detected, the IDE driver gets the device module - name by sending ATA command called ATA Identify Command or ATAPI - Identify Command to the specified IDE device. The module name returned - is a string of ASCII characters: the first character is bit8--bit15 - of the first word, the second character is BIT0--bit7 of the first word - and so on. Thus the string can not be print directly before it is - preprocessed by this func to change the order of characters in - each word in the string. - - @param[in] CHAR8 IN *Destination - Indicates the destination string. - - @param[in] CHAR8 IN *Source - Indicates the source string. - - @param[in] UINT8 IN Size - the length of the string - -**/ -VOID -SwapStringChars ( - IN CHAR8 *Destination, - IN CHAR8 *Source, - IN UINT32 Size - ) -{ - UINT32 Index; - CHAR8 Temp; - - for (Index = 0; Index < Size; Index += 2) { - - Temp = Source[Index + 1]; - Destination[Index + 1] = Source[Index]; - Destination[Index] = Temp; - } -} - -// -// ReleaseIdeResources -// /** Release resources of an IDE device before stopping it. - @param[in] *IdeBlkIoDevice Standard IDE device private data structure + @param IdeBlkIoDevice Standard IDE device private data structure **/ VOID @@ -1401,16 +1211,11 @@ ReleaseIdeResources ( return ; } - -// -// SetDeviceTransferMode -// /** Set the calculated Best transfer mode to a detected device - @param[in] *IdeDev Standard IDE device private data structure - @param[in] *TransferMode The device transfer mode to be set - + @param IdeDev Standard IDE device private data structure + @param TransferMode The device transfer mode to be set @return Set transfer mode Command execute status. **/ @@ -1419,7 +1224,6 @@ SetDeviceTransferMode ( IN IDE_BLK_IO_DEV *IdeDev, IN ATA_TRANSFER_MODE *TransferMode ) -// TODO: function comment is missing 'Routine Description:' { EFI_STATUS Status; UINT8 DeviceSelect; @@ -1445,229 +1249,11 @@ SetDeviceTransferMode ( return Status; } - -/** - Send ATA command into device with NON_DATA protocol - - @param IdeDev Standard IDE device private data structure - @param AtaCommand The ATA command to be sent - @param Device The value in Device register - @param Feature The value in Feature register - @param SectorCount The value in SectorCount register - @param LbaLow The value in LBA_LOW register - @param LbaMiddle The value in LBA_MIDDLE register - @param LbaHigh The value in LBA_HIGH register - - @retval EFI_SUCCESS Reading succeed - @retval EFI_ABORTED Command failed - @retval EFI_DEVICE_ERROR Device status error. - -**/ -EFI_STATUS -AtaNonDataCommandIn ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINT8 AtaCommand, - IN UINT8 Device, - IN UINT8 Feature, - IN UINT8 SectorCount, - IN UINT8 LbaLow, - IN UINT8 LbaMiddle, - IN UINT8 LbaHigh - ) -{ - EFI_STATUS Status; - UINT8 StatusRegister; - - Status = WaitForBSYClear (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility) - // - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - (UINT8) ((IdeDev->Device << 4) | 0xe0) - ); - - // - // ATA commands for ATA device must be issued when DRDY is set - // - Status = DRDYReady (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Pass parameter into device register block - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMiddle); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - - // - // Send command via Command Register - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); - - // - // Wait for command completion - // For ATAPI_SMART_CMD, we may need more timeout to let device - // adjust internal states. - // - if (AtaCommand == ATA_CMD_SMART) { - Status = WaitForBSYClear (IdeDev, ATASMARTTIMEOUT); - } else { - Status = WaitForBSYClear (IdeDev, ATATIMEOUT); - } - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); - if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) { - // - // Failed to execute command, abort operation - // - return EFI_ABORTED; - } - - return EFI_SUCCESS; -} - -/** - Send ATA Ext command into device with NON_DATA protocol - - @param IdeDev Standard IDE device private data structure - @param AtaCommand The ATA command to be sent - @param Device The value in Device register - @param Feature The value in Feature register - @param SectorCount The value in SectorCount register - @param LbaAddress The LBA address in 48-bit mode - - @retval EFI_SUCCESS Reading succeed - @retval EFI_ABORTED Command failed - @retval EFI_DEVICE_ERROR Device status error. - -**/ -EFI_STATUS -AtaNonDataCommandInExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINT8 AtaCommand, - IN UINT8 Device, - IN UINT16 Feature, - IN UINT16 SectorCount, - IN EFI_LBA LbaAddress - ) -{ - EFI_STATUS Status; - UINT8 StatusRegister; - UINT8 SectorCount8; - UINT8 Feature8; - UINT8 LbaLow; - UINT8 LbaMid; - UINT8 LbaHigh; - - Status = WaitForBSYClear (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility) - // - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - (UINT8) ((IdeDev->Device << 4) | 0xe0) - ); - - // - // ATA commands for ATA device must be issued when DRDY is set - // - Status = DRDYReady (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - // - // Pass parameter into device register block - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); - - // - // Fill the feature register, which is a two-byte FIFO. Need write twice. - // - Feature8 = (UINT8) (Feature >> 8); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); - - Feature8 = (UINT8) Feature; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); - - // - // Fill the sector count register, which is a two-byte FIFO. Need write twice. - // - SectorCount8 = (UINT8) (SectorCount >> 8); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); - - SectorCount8 = (UINT8) SectorCount; - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); - - // - // Fill the start LBA registers, which are also two-byte FIFO - // - LbaLow = (UINT8) RShiftU64 (LbaAddress, 24); - LbaMid = (UINT8) RShiftU64 (LbaAddress, 32); - LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - - LbaLow = (UINT8) LbaAddress; - LbaMid = (UINT8) RShiftU64 (LbaAddress, 8); - LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); - - // - // Send command via Command Register - // - IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); - - // - // Wait for command completion - // - Status = WaitForBSYClear (IdeDev, ATATIMEOUT); - if (EFI_ERROR (Status)) { - return EFI_DEVICE_ERROR; - } - - StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); - if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) { - // - // Failed to execute command, abort operation - // - return EFI_ABORTED; - } - - return EFI_SUCCESS; -} - -// -// SetDriveParameters -// /** Set drive parameters for devices not support PACKETS command - @param[in] IdeDev Standard IDE device private data structure - @param[in] DriveParameters The device parameters to be set into the disk - + @param IdeDev Standard IDE device private data structure + @param DriveParameters The device parameters to be set into the disk @return SetParameters Command execute status. **/ @@ -1714,12 +1300,11 @@ SetDriveParameters ( } /** - TODO: Add function description - - @param IdeDev TODO: add argument description + Enable Interrupt on IDE controller - @retval EFI_SUCCESS TODO: Add description for return value. + @param IdeDev Standard IDE device private data structure + @retval EFI_SUCCESS Enable Interrupt successfully **/ EFI_STATUS EnableInterrupt ( @@ -1736,99 +1321,3 @@ EnableInterrupt ( return EFI_SUCCESS; } - -/** - Clear pending IDE interrupt before OS loader/kernel take control of the IDE device. - - @param[in] Event Pointer to this event - @param[in] Context Event hanlder private data - -**/ -VOID -EFIAPI -ClearInterrupt ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - EFI_STATUS Status; - UINT64 IoPortForBmis; - UINT8 RegisterValue; - IDE_BLK_IO_DEV *IdeDev; - - // - // Get our context - // - IdeDev = (IDE_BLK_IO_DEV *) Context; - - // - // Obtain IDE IO port registers' base addresses - // - Status = ReassignIdeResources (IdeDev); - if (EFI_ERROR (Status)) { - return; - } - - // - // Check whether interrupt is pending - // - - // - // Reset IDE device to force it de-assert interrupt pin - // Note: this will reset all devices on this IDE channel - // - AtaSoftReset (IdeDev); - if (EFI_ERROR (Status)) { - return; - } - - // - // Get base address of IDE Bus Master Status Regsiter - // - if (IdePrimary == IdeDev->Channel) { - IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET; - } else { - if (IdeSecondary == IdeDev->Channel) { - IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET; - } else { - return; - } - } - // - // 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 - ); - - // - // Select the other device on this channel to ensure this device to release the interrupt pin - // - if (IdeDev->Device == 0) { - RegisterValue = (1 << 4) | 0xe0; - } else { - RegisterValue = (0 << 4) | 0xe0; - } - IDEWritePortB ( - IdeDev->PciIo, - IdeDev->IoPort->Head, - RegisterValue - ); - -} diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.h b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.h index 89bc191ab9..b919457bb5 100644 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.h +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.h @@ -1,6 +1,6 @@ /** @file Header file for IDE Bus Driver, containing the helper functions' - entire prototype. + prototype. Copyright (c) 2006 - 2007 Intel Corporation.
All rights reserved. This program and the accompanying materials @@ -25,49 +25,12 @@ // Helper functions Prototype // /** - TODO: Add function description + read a one-byte data from a IDE port - @param This TODO: add argument description - @param Controller TODO: add argument description - @param Handle TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -DeRegisterIdeDevice ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_HANDLE Handle - ); - -/** - TODO: Add function description - - @param Controller TODO: add argument description - @param PciIo TODO: add argument description - @param ParentDevicePath TODO: add argument description - @param RemainingDevicePath TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -EnableIdeDevice ( - IN EFI_HANDLE Controller, - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -/** - TODO: Add function description - - @param PciIo TODO: add argument description - @param Port TODO: add argument description - - TODO: add return values. + @param PciIo The PCI IO protocol instance + @param Port the IDE Port number + return the one-byte data read from IDE port **/ UINT8 IDEReadPortB ( @@ -76,14 +39,14 @@ IDEReadPortB ( ); /** - TODO: Add function description - - @param PciIo TODO: add argument description - @param Port TODO: add argument description - @param Count TODO: add argument description - @param Buffer TODO: add argument description + Reads multiple words of data from the IDE data port. + Call the IO abstraction once to do the complete read, + not one word at a time - TODO: add return values. + @param PciIo Pointer to the EFI_PCI_IO instance + @param Port IO port to read + @param Count No. of UINT16's to read + @param Buffer Pointer to the data buffer for read **/ VOID @@ -95,14 +58,11 @@ IDEReadPortWMultiple ( ); /** - TODO: Add function description - - @param PciIo TODO: add argument description - @param Port TODO: add argument description - @param Data TODO: add argument description - - TODO: add return values. + write a 1-byte data to a specific IDE port + @param PciIo PCI IO protocol instance + @param Port The IDE port to be writen + @param Data The data to write to the port **/ VOID IDEWritePortB ( @@ -112,14 +72,11 @@ IDEWritePortB ( ); /** - TODO: Add function description - - @param PciIo TODO: add argument description - @param Port TODO: add argument description - @param Data TODO: add argument description - - TODO: add return values. + write a 1-word data to a specific IDE port + @param PciIo PCI IO protocol instance + @param Port The IDE port to be writen + @param Data The data to write to the port **/ VOID IDEWritePortW ( @@ -129,14 +86,14 @@ IDEWritePortW ( ); /** - TODO: Add function description - - @param PciIo TODO: add argument description - @param Port TODO: add argument description - @param Count TODO: add argument description - @param Buffer TODO: add argument description + Write multiple words of data to the IDE data port. + Call the IO abstraction once to do the complete read, + not one word at a time - TODO: add return values. + @param PciIo Pointer to the EFI_PCI_IO instance + @param Port IO port to read + @param Count No. of UINT16's to read + @param Buffer Pointer to the data buffer for read **/ VOID @@ -148,12 +105,54 @@ IDEWritePortWMultiple ( ); /** - TODO: Add function description + Get IDE IO port registers' base addresses by mode. In 'Compatibility' mode, + use fixed addresses. In Native-PCI mode, get base addresses from BARs in + the PCI IDE controller's Configuration Space. - @param PciIo TODO: add argument description - @param IdeRegsBaseAddr TODO: add argument description + The steps to get IDE IO port registers' base addresses for each channel + as follows: - TODO: add return values. + 1. Examine the Programming Interface byte of the Class Code fields in PCI IDE + controller's Configuration Space to determine the operating mode. + + 2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below. +
+  ___________________________________________
+  |           | Command Block | Control Block |
+  |  Channel  |   Registers   |   Registers   |
+  |___________|_______________|_______________|
+  |  Primary  |  1F0h - 1F7h  |  3F6h - 3F7h  |
+  |___________|_______________|_______________|
+  | Secondary |  170h - 177h  |  376h - 377h  |
+  |___________|_______________|_______________|
+
+  Table 1. Compatibility resource mappings
+  
+ + b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs + in IDE controller's PCI Configuration Space, shown in the Table 2 below. +
+  ___________________________________________________
+  |           |   Command Block   |   Control Block   |
+  |  Channel  |     Registers     |     Registers     |
+  |___________|___________________|___________________|
+  |  Primary  | BAR at offset 0x10| BAR at offset 0x14|
+  |___________|___________________|___________________|
+  | Secondary | BAR at offset 0x18| BAR at offset 0x1C|
+  |___________|___________________|___________________|
+
+  Table 2. BARs for Register Mapping
+  
+ @note Refer to Intel ICH4 datasheet, Control Block Offset: 03F4h for + primary, 0374h for secondary. So 2 bytes extra offset should be + added to the base addresses read from BARs. + + For more details, please refer to PCI IDE Controller Specification and Intel + ICH4 Datasheet. + + @param PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance + @param IdeRegsBaseAddr Pointer to IDE_REGISTERS_BASE_ADDR to + receive IDE IO port registers' base addresses **/ EFI_STATUS @@ -163,11 +162,12 @@ GetIdeRegistersBaseAddr ( ); /** - TODO: Add function description + This function is used to requery IDE resources. The IDE controller will + probably switch between native and legacy modes during the EFI->CSM->OS + transfer. We do this everytime before an BlkIo operation to ensure its + succeess. - @param IdeDev TODO: add argument description - - TODO: add return values. + @param IdeDev The BLK_IO private data which specifies the IDE device **/ EFI_STATUS @@ -176,11 +176,9 @@ ReassignIdeResources ( ); /** - TODO: Add function description - - @param IdeDev TODO: add argument description + Detect if there is disk attached to this port - TODO: add return values. + @param IdeDev The BLK_IO private data which specifies the IDE device. **/ EFI_STATUS @@ -201,25 +199,20 @@ InitializeIDEChannelData ( ); /** - TODO: Add function description + This function is used to poll for the DRQ bit clear in the Status + Register. DRQ is cleared when the device is finished transferring data. + So this function is called after data transfer is finished. - @param IdeDev TODO: add argument description + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ clear. - TODO: add return values. + @retval EFI_SUCCESS DRQ bit clear within the time out. -**/ -EFI_STATUS -DetectIDEController ( - IN IDE_BLK_IO_DEV *IdeDev - ); + @retval EFI_TIMEOUT DRQ bit not clear within the time out. -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param TimeoutInMilliSeconds TODO: add argument description - - TODO: add return values. + @note + Read Status Register will clear interrupt status. **/ EFI_STATUS @@ -229,12 +222,21 @@ DRQClear ( ); /** - TODO: Add function description + This function is used to poll for the DRQ bit clear in the Alternate + Status Register. DRQ is cleared when the device is finished + transferring data. So this function is called after data transfer + is finished. - @param IdeDev TODO: add argument description - @param TimeoutInMilliSeconds TODO: add argument description + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. - TODO: add return values. + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ clear. + + @retval EFI_SUCCESS DRQ bit clear within the time out. + + @retval EFI_TIMEOUT DRQ bit not clear within the time out. + @note + Read Alternate Status Register will not clear interrupt status. **/ EFI_STATUS @@ -244,12 +246,21 @@ DRQClear2 ( ); /** - TODO: Add function description + This function is used to poll for the DRQ bit set in the + Status Register. + DRQ is set when the device is ready to transfer data. So this function + is called after the command is sent to the device and before required + data is transferred. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to + record all the information of the IDE device. + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. - @param IdeDev TODO: add argument description - @param TimeoutInMilliSeconds TODO: add argument description + @retval EFI_SUCCESS DRQ bit set within the time out. + @retval EFI_TIMEOUT DRQ bit not set within the time out. + @retval EFI_ABORTED DRQ bit not set caused by the command abort. - TODO: add return values. + @note Read Status Register will clear interrupt status. **/ EFI_STATUS @@ -259,12 +270,19 @@ DRQReady ( ); /** - TODO: Add function description + This function is used to poll for the DRQ bit set in the Alternate Status Register. + DRQ is set when the device is ready to transfer data. So this function is called after + the command is sent to the device and before required data is transferred. - @param IdeDev TODO: add argument description - @param TimeoutInMilliSeconds TODO: add argument description + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to + record all the information of the IDE device. - TODO: add return values. + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. + + @retval EFI_SUCCESS DRQ bit set within the time out. + @retval EFI_TIMEOUT DRQ bit not set within the time out. + @retval EFI_ABORTED DRQ bit not set caused by the command abort. + @note Read Alternate Status Register will not clear interrupt status. **/ EFI_STATUS @@ -274,13 +292,17 @@ DRQReady2 ( ); /** - TODO: Add function description + This function is used to poll for the BSY bit clear in the Status Register. BSY + is clear when the device is not busy. Every command must be sent after device is not busy. - @param IdeDev TODO: add argument description - @param TimeoutInMilliSeconds TODO: add argument description + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready. - TODO: add return values. + @retval EFI_SUCCESS BSY bit clear within the time out. + @retval EFI_TIMEOUT BSY bit not clear within the time out. + @note Read Status Register will clear interrupt status. **/ EFI_STATUS WaitForBSYClear ( @@ -289,12 +311,17 @@ WaitForBSYClear ( ); /** - TODO: Add function description + This function is used to poll for the BSY bit clear in the Alternate Status Register. + BSY is clear when the device is not busy. Every command must be sent after device is + not busy. - @param IdeDev TODO: add argument description - @param TimeoutInMilliSeconds TODO: add argument description + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @paramTimeoutInMilliSeconds used to designate the timeout for the DRQ ready. - TODO: add return values. + @retval EFI_SUCCESS BSY bit clear within the time out. + @retval EFI_TIMEOUT BSY bit not clear within the time out. + @note Read Alternate Status Register will not clear interrupt status. **/ EFI_STATUS @@ -304,13 +331,18 @@ WaitForBSYClear2 ( ); /** - TODO: Add function description + This function is used to poll for the DRDY bit set in the Status Register. DRDY + bit is set when the device is ready to accept command. Most ATA commands must be + sent after DRDY set except the ATAPI Packet Command. - @param IdeDev TODO: add argument description - @param DelayInMilliSeconds TODO: add argument description + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param DelayInMilliSeconds used to designate the timeout for the DRQ ready. - TODO: add return values. + @retval EFI_SUCCESS DRDY bit set within the time out. + @retval EFI_TIMEOUT DRDY bit not set within the time out. + @note Read Status Register will clear interrupt status. **/ EFI_STATUS DRDYReady ( @@ -319,12 +351,18 @@ DRDYReady ( ); /** - TODO: Add function description + This function is used to poll for the DRDY bit set in the Alternate Status Register. + DRDY bit is set when the device is ready to accept command. Most ATA commands must + be sent after DRDY set except the ATAPI Packet Command. + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param DelayInMilliSeconds used to designate the timeout for the DRQ ready. - @param IdeDev TODO: add argument description - @param DelayInMilliSeconds TODO: add argument description + @retval EFI_SUCCESS DRDY bit set within the time out. + @retval EFI_TIMEOUT DRDY bit not set within the time out. - TODO: add return values. + @note Read Alternate Status Register will clear interrupt status. **/ EFI_STATUS @@ -333,32 +371,26 @@ DRDYReady2 ( IN UINTN DelayInMilliSeconds ); -/** - TODO: Add function description - - @param Destination TODO: add argument description - @param Source TODO: add argument description - @param Size TODO: add argument description - - TODO: add return values. - -**/ -VOID -SwapStringChars ( - IN CHAR8 *Destination, - IN CHAR8 *Source, - IN UINT32 Size - ); - // // ATA device functions' prototype // /** - TODO: Add function description + Sends out an ATA Identify Command to the specified device. + + This function is called by DiscoverIdeDevice() during its device + identification. It sends out the ATA Identify Command to the + specified device. Only ATA device responses to this command. If + the command succeeds, it returns the Identify data structure which + contains information about the device. This function extracts the + information it needs to fill the IDE_BLK_IO_DEV data structure, + including device type, media block size, media capacity, and etc. - @param IdeDev TODO: add argument description + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to record + all the information of the IDE device. - TODO: add return values. + @retval EFI_SUCCESS Identify ATA device successfully. + @retval EFI_DEVICE_ERROR ATA Identify Device Command failed or device is not ATA device. + @note parameter IdeDev will be updated in this function. **/ EFI_STATUS @@ -367,32 +399,31 @@ ATAIdentify ( ); /** - TODO: Add function description - - @param IdeDev TODO: add argument description - - TODO: add return values. + This function is called by ATAIdentify() or ATAPIIdentify() to print device's module name. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. **/ VOID PrintAtaModuleName ( IN IDE_BLK_IO_DEV *IdeDev ); - /** - TODO: Add function description + This function is used to send out ATA commands conforms to the PIO Data In Protocol. - @param IdeDev TODO: add argument description - @param Buffer TODO: add argument description - @param ByteCount TODO: add argument description - @param AtaCommand TODO: add argument description - @param Head TODO: add argument description - @param SectorCount TODO: add argument description - @param SectorNumber TODO: add argument description - @param CylinderLsb TODO: add argument description - @param CylinderMsb TODO: add argument description - - TODO: add return values. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @param Buffer buffer contained data transferred from device to host. + @param ByteCount data size in byte unit of the buffer. + @param AtaCommand value of the Command Register + @param Head value of the Head/Device Register + @param SectorCount value of the Sector Count Register + @param SectorNumber value of the Sector Number Register + @param CylinderLsb value of the low byte of the Cylinder Register + @param CylinderMsb value of the high byte of the Cylinder Register + + @retval EFI_SUCCESS send out the ATA command and device send required data successfully. + @retval EFI_DEVICE_ERROR command sent failed. **/ EFI_STATUS @@ -409,19 +440,23 @@ AtaPioDataIn ( ); /** - TODO: Add function description + This function is used to send out ATA commands conforms to the + PIO Data Out Protocol. - @param IdeDev TODO: add argument description - @param Buffer TODO: add argument description - @param ByteCount TODO: add argument description - @param AtaCommand TODO: add argument description - @param Head TODO: add argument description - @param SectorCount TODO: add argument description - @param SectorNumber TODO: add argument description - @param CylinderLsb TODO: add argument description - @param CylinderMsb TODO: add argument description + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + @param *Buffer buffer contained data transferred from host to device. + @param ByteCount data size in byte unit of the buffer. + @param AtaCommand value of the Command Register + @param Head value of the Head/Device Register + @param SectorCount value of the Sector Count Register + @param SectorNumber value of the Sector Number Register + @param CylinderLsb value of the low byte of the Cylinder Register + @param CylinderMsb value of the high byte of the Cylinder Register - TODO: add return values. + @retval EFI_SUCCESS send out the ATA command and device received required + data successfully. + @retval EFI_DEVICE_ERROR command sent failed. **/ EFI_STATUS @@ -438,11 +473,15 @@ AtaPioDataOut ( ); /** - TODO: Add function description + This function is used to analyze the Status Register and print out + some debug information and if there is ERR bit set in the Status + Register, the Error Register's value is also be parsed and print out. - @param IdeDev TODO: add argument description + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to + record all the information of the IDE device. - TODO: add return values. + @retval EFI_SUCCESS No err information in the Status Register. + @retval EFI_DEVICE_ERROR Any err information in the Status Register. **/ EFI_STATUS @@ -451,50 +490,23 @@ CheckErrorStatus ( ); /** - TODO: Add function description + This function is used to implement the Soft Reset on the specified device. But, + the ATA Soft Reset mechanism is so strong a reset method that it will force + resetting on both devices connected to the same cable. - @param IdeDev TODO: add argument description - @param DataBuffer TODO: add argument description - @param Lba TODO: add argument description - @param NumberOfBlocks TODO: add argument description + It is called by IdeBlkIoReset(), a interface function of Block + I/O protocol. - TODO: add return values. + This function can also be used by the ATAPI device to perform reset when + ATAPI Reset command is failed. -**/ -EFI_STATUS -AtaReadSectors ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA Lba, - IN UINTN NumberOfBlocks - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param BufferData TODO: add argument description - @param Lba TODO: add argument description - @param NumberOfBlocks TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtaWriteSectors ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *BufferData, - IN EFI_LBA Lba, - IN UINTN NumberOfBlocks - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - - TODO: add return values. + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record + all the information of the IDE device. + @retval EFI_SUCCESS Soft reset completes successfully. + @retval EFI_DEVICE_ERROR Any step during the reset process is failed. + @note The registers initial values after ATA soft reset are different + to the ATA device and ATAPI device. **/ EFI_STATUS AtaSoftReset ( @@ -502,15 +514,30 @@ AtaSoftReset ( ); /** - TODO: Add function description + This function is the ATA implementation for ReadBlocks in the + Block I/O Protocol interface. + + @param IdeBlkIoDevice Indicates the calling context. + @param MediaId The media id that the read request is for. + @param LBA The starting logical block address to read from on the device. + @param BufferSize The size of the Buffer in bytes. This must be a multiple + of the intrinsic block size of the device. - @param IdeBlkIoDevice TODO: add argument description - @param MediaId TODO: add argument description - @param Lba TODO: add argument description - @param BufferSize TODO: add argument description - @param Buffer TODO: add argument description + @param Buffer A pointer to the destination buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the memory that data is read into. - TODO: add return values. + @retval EFI_SUCCESS Read Blocks successfully. + @retval EFI_DEVICE_ERROR Read Blocks failed. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, + or the data buffer is not valid. + + @note If Read Block error because of device error, this function will call + AtaSoftReset() function to reset device. **/ EFI_STATUS @@ -523,16 +550,30 @@ AtaBlkIoReadBlocks ( ); /** - TODO: Add function description + This function is the ATA implementation for WriteBlocks in the + Block I/O Protocol interface. + + @param IdeBlkIoDevice Indicates the calling context. + @param MediaId The media id that the write request is for. + @param LBA The starting logical block address to write onto the device. + @param BufferSize The size of the Buffer in bytes. This must be a multiple + of the intrinsic block size of the device. + @param Buffer A pointer to the source buffer for the data.The caller + is responsible for either having implicit or explicit + ownership of the memory that data is written from. - @param IdeBlkIoDevice TODO: add argument description - @param MediaId TODO: add argument description - @param Lba TODO: add argument description - @param BufferSize TODO: add argument description - @param Buffer TODO: add argument description + @retval EFI_SUCCESS Write Blocks successfully. + @retval EFI_DEVICE_ERROR Write Blocks failed. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. - TODO: add return values. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, + or the data buffer is not valid. + @note If Write Block error because of device error, this function will call + AtaSoftReset() function to reset device. **/ EFI_STATUS AtaBlkIoWriteBlocks ( @@ -543,16 +584,35 @@ AtaBlkIoWriteBlocks ( OUT VOID *Buffer ); -// -// ATAPI device functions' prototype -// /** - TODO: Add function description - - @param IdeDev TODO: add argument description + This function is called by DiscoverIdeDevice() during its device + identification. + Its main purpose is to get enough information for the device media + to fill in the Media data structure of the Block I/O Protocol interface. + + There are 5 steps to reach such objective: + 1. Sends out the ATAPI Identify Command to the specified device. + Only ATAPI device responses to this command. If the command succeeds, + it returns the Identify data structure which filled with information + about the device. Since the ATAPI device contains removable media, + the only meaningful information is the device module name. + 2. Sends out ATAPI Inquiry Packet Command to the specified device. + This command will return inquiry data of the device, which contains + the device type information. + 3. Allocate sense data space for future use. We don't detect the media + presence here to improvement boot performance, especially when CD + media is present. The media detection will be performed just before + each BLK_IO read/write + + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. - TODO: add return values. + @retval EFI_SUCCESS Identify ATAPI device successfully. + @retval EFI_DEVICE_ERROR ATAPI Identify Device Command failed or device type + is not supported by this IDE driver. + @retval EFI_OUT_OF_RESOURCES Allocate memory for sense data failed + @note Parameter "IdeDev" will be updated in this function. **/ EFI_STATUS ATAPIIdentify ( @@ -560,185 +620,22 @@ ATAPIIdentify ( ); /** - TODO: Add function description + This function is used to implement the Soft Reset on the specified + ATAPI device. Different from the AtaSoftReset(), here reset is a ATA + Soft Reset Command special for ATAPI device, and it only take effects + on the specified ATAPI device, not on the whole IDE bus. + Since the ATAPI soft reset is needed when device is in exceptional + condition (such as BSY bit is always set ), I think the Soft Reset + command should be sent without waiting for the BSY clear and DRDY + set. + This function is called by IdeBlkIoReset(), + a interface function of Block I/O protocol. - @param IdeDev TODO: add argument description + @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. - TODO: add return values. - -**/ -EFI_STATUS -AtapiInquiry ( - IN IDE_BLK_IO_DEV *IdeDev - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param Packet TODO: add argument description - @param Buffer TODO: add argument description - @param ByteCount TODO: add argument description - @param TimeOut TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtapiPacketCommandIn ( - IN IDE_BLK_IO_DEV *IdeDev, - IN ATAPI_PACKET_COMMAND *Packet, - IN UINT16 *Buffer, - IN UINT32 ByteCount, - IN UINTN TimeOut - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param Packet TODO: add argument description - @param Buffer TODO: add argument description - @param ByteCount TODO: add argument description - @param TimeOut TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtapiPacketCommandOut ( - IN IDE_BLK_IO_DEV *IdeDev, - IN ATAPI_PACKET_COMMAND *Packet, - IN UINT16 *Buffer, - IN UINT32 ByteCount, - IN UINTN TimeOut - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param Buffer TODO: add argument description - @param ByteCount TODO: add argument description - @param Read TODO: add argument description - @param TimeOut TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -PioReadWriteData ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINT16 *Buffer, - IN UINT32 ByteCount, - IN BOOLEAN Read, - IN UINTN TimeOut - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param SResult TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtapiTestUnitReady ( - IN IDE_BLK_IO_DEV *IdeDev, - OUT SENSE_RESULT *SResult - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param SenseCounts TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtapiRequestSense ( - IN IDE_BLK_IO_DEV *IdeDev, - OUT UINTN *SenseCounts - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param SResult TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtapiReadCapacity ( - IN IDE_BLK_IO_DEV *IdeDev, - OUT SENSE_RESULT *SResult - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param MediaChange TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtapiDetectMedia ( - IN IDE_BLK_IO_DEV *IdeDev, - OUT BOOLEAN *MediaChange - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param Buffer TODO: add argument description - @param Lba TODO: add argument description - @param NumberOfBlocks TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtapiReadSectors ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *Buffer, - IN EFI_LBA Lba, - IN UINTN NumberOfBlocks - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param Buffer TODO: add argument description - @param Lba TODO: add argument description - @param NumberOfBlocks TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtapiWriteSectors ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *Buffer, - IN EFI_LBA Lba, - IN UINTN NumberOfBlocks - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - - TODO: add return values. + @retval EFI_SUCCESS Soft reset completes successfully. + @retval EFI_DEVICE_ERROR Any step during the reset process is failed. **/ EFI_STATUS @@ -747,16 +644,26 @@ AtapiSoftReset ( ); /** - TODO: Add function description - - @param IdeBlkIoDevice TODO: add argument description - @param MediaId TODO: add argument description - @param Lba TODO: add argument description - @param BufferSize TODO: add argument description - @param Buffer TODO: add argument description - - TODO: add return values. + This function is the ATAPI implementation for ReadBlocks in the + Block I/O Protocol interface. + @param IdeBlkIoDevice Indicates the calling context. + @param MediaId The media id that the read request is for. + @param LBA The starting logical block address to read from on the device. + @param BufferSize The size of the Buffer in bytes. This must be a multiple + of the intrinsic block size of the device. + @param Buffer A pointer to the destination buffer for the data. The caller + is responsible for either having implicit or explicit + ownership of the memory that data is read into. + + @retval EFI_SUCCESS Read Blocks successfully. + @retval EFI_DEVICE_ERROR Read Blocks failed. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, + or the data buffer is not valid. **/ EFI_STATUS AtapiBlkIoReadBlocks ( @@ -768,16 +675,28 @@ AtapiBlkIoReadBlocks ( ); /** - TODO: Add function description + This function is the ATAPI implementation for WriteBlocks in the + Block I/O Protocol interface. - @param IdeBlkIoDevice TODO: add argument description - @param MediaId TODO: add argument description - @param Lba TODO: add argument description - @param BufferSize TODO: add argument description - @param Buffer TODO: add argument description + @param IdeBlkIoDevice Indicates the calling context. + @param MediaId The media id that the write request is for. + @param LBA The starting logical block address to write onto the device. + @param BufferSize The size of the Buffer in bytes. This must be a multiple + of the intrinsic block size of the device. + @param Buffer A pointer to the source buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the memory that data is written from. - TODO: add return values. + @retval EFI_SUCCESS Write Blocks successfully. + @retval EFI_DEVICE_ERROR Write Blocks failed. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGE The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, + or the data buffer is not valid. + @retval EFI_WRITE_PROTECTED The write protected is enabled or the media does not support write **/ EFI_STATUS AtapiBlkIoWriteBlocks ( @@ -789,56 +708,9 @@ AtapiBlkIoWriteBlocks ( ); /** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param SenseCount TODO: add argument description - @param Result TODO: add argument description + Release resources of an IDE device before stopping it. - TODO: add return values. - -**/ -EFI_STATUS -ParseSenseData ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINTN SenseCount, - OUT SENSE_RESULT *Result - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtapiReadPendingData ( - IN IDE_BLK_IO_DEV *IdeDev - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param WriteProtected TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -IsLS120orZipWriteProtected ( - IN IDE_BLK_IO_DEV *IdeDev, - OUT BOOLEAN *WriteProtected - ); - -/** - TODO: Add function description - - @param IdeBlkIoDevice TODO: add argument description - - TODO: add return values. + @param IdeBlkIoDevice Standard IDE device private data structure **/ VOID @@ -847,49 +719,32 @@ ReleaseIdeResources ( ); /** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param TransferMode TODO: add argument description - - TODO: add return values. + Set the calculated Best transfer mode to a detected device + @param IdeDev Standard IDE device private data structure + @param TransferMode The device transfer mode to be set + @return Set transfer mode Command execute status. **/ EFI_STATUS SetDeviceTransferMode ( IN IDE_BLK_IO_DEV *IdeDev, IN ATA_TRANSFER_MODE *TransferMode ); - /** - TODO: Add function description + Send ATA command into device with NON_DATA protocol - @param IdeDev TODO: add argument description - @param NativeMaxAddress TODO: add argument description + @param IdeDev Standard IDE device private data structure + @param AtaCommand The ATA command to be sent + @param Device The value in Device register + @param Feature The value in Feature register + @param SectorCount The value in SectorCount register + @param LbaLow The value in LBA_LOW register + @param LbaMiddle The value in LBA_MIDDLE register + @param LbaHigh The value in LBA_HIGH register - TODO: add return values. - -**/ -EFI_STATUS -ReadNativeMaxAddress ( - IN IDE_BLK_IO_DEV *IdeDev, - OUT EFI_LBA *NativeMaxAddress - ); - - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param AtaCommand TODO: add argument description - @param Device TODO: add argument description - @param Feature TODO: add argument description - @param SectorCount TODO: add argument description - @param LbaLow TODO: add argument description - @param LbaMiddle TODO: add argument description - @param LbaHigh TODO: add argument description - - TODO: add return values. + @retval EFI_SUCCESS Reading succeed + @retval EFI_ABORTED Command failed + @retval EFI_DEVICE_ERROR Device status error. **/ EFI_STATUS @@ -905,16 +760,18 @@ AtaNonDataCommandIn ( ); /** - TODO: Add function description + Send ATA Ext command into device with NON_DATA protocol - @param IdeDev TODO: add argument description - @param AtaCommand TODO: add argument description - @param Device TODO: add argument description - @param Feature TODO: add argument description - @param SectorCount TODO: add argument description - @param LbaAddress TODO: add argument description + @param IdeDev Standard IDE device private data structure + @param AtaCommand The ATA command to be sent + @param Device The value in Device register + @param Feature The value in Feature register + @param SectorCount The value in SectorCount register + @param LbaAddress The LBA address in 48-bit mode - TODO: add return values. + @retval EFI_SUCCESS Reading succeed + @retval EFI_ABORTED Command failed + @retval EFI_DEVICE_ERROR Device status error. **/ EFI_STATUS @@ -926,230 +783,6 @@ AtaNonDataCommandInExt ( IN UINT16 SectorCount, IN EFI_LBA LbaAddress ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param DataBuffer TODO: add argument description - @param StartLba TODO: add argument description - @param NumberOfBlocks TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtaReadSectorsExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA StartLba, - IN UINTN NumberOfBlocks - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param DataBuffer TODO: add argument description - @param StartLba TODO: add argument description - @param NumberOfBlocks TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtaWriteSectorsExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA StartLba, - IN UINTN NumberOfBlocks - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param DataBuffer TODO: add argument description - @param StartLba TODO: add argument description - @param NumberOfBlocks TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtaUdmaReadExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA StartLba, - IN UINTN NumberOfBlocks - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param DataBuffer TODO: add argument description - @param StartLba TODO: add argument description - @param NumberOfBlocks TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtaUdmaRead ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA StartLba, - IN UINTN NumberOfBlocks - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param DataBuffer TODO: add argument description - @param StartLba TODO: add argument description - @param NumberOfBlocks TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtaUdmaWriteExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA StartLba, - IN UINTN NumberOfBlocks - ); - -/** - 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 - @param DataBuffer TODO: add argument description - @param StartLba TODO: add argument description - @param NumberOfBlocks TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtaUdmaWrite ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *DataBuffer, - IN EFI_LBA StartLba, - IN UINTN NumberOfBlocks - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param AtaCommand TODO: add argument description - @param Device TODO: add argument description - @param Feature TODO: add argument description - @param SectorCount TODO: add argument description - @param LbaAddress TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtaCommandIssueExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINT8 AtaCommand, - IN UINT8 Device, - IN UINT16 Feature, - IN UINT16 SectorCount, - IN EFI_LBA LbaAddress - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param AtaCommand TODO: add argument description - @param Device TODO: add argument description - @param Feature TODO: add argument description - @param SectorCount TODO: add argument description - @param LbaAddress TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtaCommandIssue ( - IN IDE_BLK_IO_DEV *IdeDev, - IN UINT8 AtaCommand, - IN UINT8 Device, - IN UINT16 Feature, - IN UINT16 SectorCount, - IN EFI_LBA LbaAddress - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtaAtapi6Identify ( - IN IDE_BLK_IO_DEV *IdeDev - ); - - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - - TODO: add return values. - -**/ -VOID -AtaSMARTSupport ( - IN IDE_BLK_IO_DEV *IdeDev - ); - - /** Enable Long Physical Sector Feature for ATA device. @@ -1166,58 +799,11 @@ AtaEnableLongPhysicalSector ( ); /** - TODO: Add function description + Set drive parameters for devices not support PACKETS command - @param IdeDev TODO: add argument description - @param Buffer TODO: add argument description - @param ByteCount TODO: add argument description - @param AtaCommand TODO: add argument description - @param StartLba TODO: add argument description - @param SectorCount TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtaPioDataInExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN OUT VOID *Buffer, - IN UINT32 ByteCount, - IN UINT8 AtaCommand, - IN EFI_LBA StartLba, - IN UINT16 SectorCount - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param Buffer TODO: add argument description - @param ByteCount TODO: add argument description - @param AtaCommand TODO: add argument description - @param StartLba TODO: add argument description - @param SectorCount TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -AtaPioDataOutExt ( - IN IDE_BLK_IO_DEV *IdeDev, - IN VOID *Buffer, - IN UINT32 ByteCount, - IN UINT8 AtaCommand, - IN EFI_LBA StartLba, - IN UINT16 SectorCount - ); - -/** - TODO: Add function description - - @param IdeDev TODO: add argument description - @param DriveParameters TODO: add argument description - - TODO: add return values. + @param IdeDev Standard IDE device private data structure + @param DriveParameters The device parameters to be set into the disk + @return SetParameters Command execute status. **/ EFI_STATUS @@ -1227,30 +813,14 @@ SetDriveParameters ( ); /** - TODO: Add function description - - @param IdeDev TODO: add argument description + Enable Interrupt on IDE controller - TODO: add return values. + @param IdeDev Standard IDE device private data structure + @retval EFI_SUCCESS Enable Interrupt successfully **/ EFI_STATUS EnableInterrupt ( IN IDE_BLK_IO_DEV *IdeDev ); - -/** - Clear pending IDE interrupt before OS loader/kernel take control of the IDE device. - - @param[in] Event Pointer to this event. - @param[in] Context Event hanlder private data. - -**/ -VOID -EFIAPI -ClearInterrupt ( - IN EFI_EVENT Event, - IN VOID *Context - ); - #endif diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c index 9c7d6e2063..b3434d754e 100644 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c @@ -1,4 +1,8 @@ /** @file + This file implement UEFI driver for IDE Bus which includes device identification, + Child device(Disk, CDROM, etc) enumeration and child handler installation, and + driver stop. + Copyright (c) 2006 - 2008, Intel Corporation All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -30,21 +34,106 @@ EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding = { NULL, NULL }; +/** + Deregister an IDE device and free resources -// -// *********************************************************************************** -// IDEBusDriverBindingSupported -// *********************************************************************************** -// + @param This Protocol instance pointer. + @param Controller Ide device handle + @param Handle Handle of device to deregister driver on + + @retval EFI_SUCCESS Deregiter a specific IDE device successfully + + +**/ +EFI_STATUS +DeRegisterIdeDevice ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_HANDLE Handle + ) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + IDE_BLK_IO_DEV *IdeBlkIoDevice; + EFI_PCI_IO_PROTOCOL *PciIo; + UINTN Index; + + Status = gBS->OpenProtocol ( + Handle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo); + + // + // Report Status code: Device disabled + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_DISABLE), + IdeBlkIoDevice->DevicePath + ); + + // + // Close the child handle + // + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + Handle, + &gEfiDevicePathProtocolGuid, + IdeBlkIoDevice->DevicePath, + &gEfiBlockIoProtocolGuid, + &IdeBlkIoDevice->BlkIo, + &gEfiDiskInfoProtocolGuid, + &IdeBlkIoDevice->DiskInfo, + NULL + ); + + if (EFI_ERROR (Status)) { + gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + return Status; + } + + // + // Release allocated resources + // + Index = IdeBlkIoDevice->Channel * 2 + IdeBlkIoDevice->Device; + if (Index < MAX_IDE_DEVICE) { + IdeBlkIoDevice->IdeBusDriverPrivateData->HaveScannedDevice[Index] = FALSE; + } + ReleaseIdeResources (IdeBlkIoDevice); + + return EFI_SUCCESS; +} /** - Register Driver Binding protocol for this driver. + Supported function of Driver Binding protocol for this driver. - @param[in] This -- A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle -- The handle of the controller to test. - @param[in] RemainingDevicePath -- A pointer to the remaining portion of a device path. + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param ControllerHandle The handle of the controller to test. + @param RemainingDevicePath A pointer to the remaining portion of a device path. @retval EFI_SUCCESS Driver loaded. - @retval other Driver not loaded. + @retval other Driver not loaded. **/ EFI_STATUS @@ -54,8 +143,6 @@ IDEBusDriverBindingSupported ( IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) -// TODO: Controller - add argument and description to function comment -// TODO: EFI_UNSUPPORTED - add return value to function comment { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; @@ -134,22 +221,18 @@ IDEBusDriverBindingSupported ( return Status; } -// -// *********************************************************************************** -// IDEBusDriverBindingStart -// *********************************************************************************** -// + /** - Start this driver on Controller by detecting all disks and installing - BlockIo protocol on them. + Start function of Driver binding protocol which start this driver on Controller + by detecting all disks and installing BlockIo protocol on them. - @param This Protocol instance pointer. - @param Controller Handle of device to bind driver to. - @param RemainingDevicePath Not used, always produce all possible children. + @param This Protocol instance pointer. + @param Controller Handle of device to bind driver to. + @param RemainingDevicePath produce all possible children. - @retval EFI_SUCCESS This driver is added to ControllerHandle. + @retval EFI_SUCCESS This driver is added to ControllerHandle. @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle. - @retval other This driver does not support this device. + @retval other This driver does not support this device. **/ EFI_STATUS @@ -698,7 +781,7 @@ IDEBusDriverBindingStart ( // Add Component Name for the IDE/ATAPI device that was discovered. // IdeBlkIoDevicePtr->ControllerNameTable = NULL; - ADD_NAME (IdeBlkIoDevicePtr); + ADD_IDE_ATAPI_NAME (IdeBlkIoDevicePtr); Status = gBS->InstallMultipleProtocolInterfaces ( &IdeBlkIoDevicePtr->Handle, @@ -821,14 +904,9 @@ ErrorExit: return Status; } - -// -// *********************************************************************************** -// IDEBusDriverBindingStop -// *********************************************************************************** -// /** - Stop this driver on Controller Handle. + Stop function of Driver Binding Protocol which is to stop the driver on Controller Handle and all + child handle attached to the controller handle if there are. @param This Protocol instance pointer. @param Controller Handle of device to stop driver on @@ -847,8 +925,6 @@ IDEBusDriverBindingStop ( IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) -// TODO: Controller - add argument and description to function comment -// TODO: EFI_DEVICE_ERROR - add return value to function comment { EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; @@ -949,115 +1025,15 @@ IDEBusDriverBindingStop ( return EFI_SUCCESS; } -// -// *********************************************************************************** -// DeRegisterIdeDevice -// *********************************************************************************** -// -/** - Deregister an IDE device and free resources - - @param This Protocol instance pointer. - @param Controller Ide device handle - @param Handle Handle of device to deregister driver on - - @return EFI_STATUS - -**/ -EFI_STATUS -DeRegisterIdeDevice ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_HANDLE Handle - ) -// TODO: EFI_SUCCESS - add return value to function comment -{ - EFI_STATUS Status; - EFI_BLOCK_IO_PROTOCOL *BlkIo; - IDE_BLK_IO_DEV *IdeBlkIoDevice; - EFI_PCI_IO_PROTOCOL *PciIo; - UINTN Index; - - Status = gBS->OpenProtocol ( - Handle, - &gEfiBlockIoProtocolGuid, - (VOID **) &BlkIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo); - - // - // Report Status code: Device disabled - // - REPORT_STATUS_CODE_WITH_DEVICE_PATH ( - EFI_PROGRESS_CODE, - (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_DISABLE), - IdeBlkIoDevice->DevicePath - ); - - // - // Close the child handle - // - Status = gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Handle - ); - - Status = gBS->UninstallMultipleProtocolInterfaces ( - Handle, - &gEfiDevicePathProtocolGuid, - IdeBlkIoDevice->DevicePath, - &gEfiBlockIoProtocolGuid, - &IdeBlkIoDevice->BlkIo, - &gEfiDiskInfoProtocolGuid, - &IdeBlkIoDevice->DiskInfo, - NULL - ); - - if (EFI_ERROR (Status)) { - gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - return Status; - } - - // - // Release allocated resources - // - Index = IdeBlkIoDevice->Channel * 2 + IdeBlkIoDevice->Device; - if (Index < MAX_IDE_DEVICE) { - IdeBlkIoDevice->IdeBusDriverPrivateData->HaveScannedDevice[Index] = FALSE; - } - ReleaseIdeResources (IdeBlkIoDevice); - - return EFI_SUCCESS; -} - -// -// *********************************************************************************** -// IDEBlkIoReset -// *********************************************************************************** -// /** - GC_TODO: Add function description + issue ATA or ATAPI command to reset a block IO device. + @param This Block IO protocol instance pointer. + @param ExtendedVerification If FALSE,for ATAPI device, driver will only invoke ATAPI reset method + If TRUE, for ATAPI device, driver need invoke ATA reset method after + invoke ATAPI reset method - @param This GC_TODO: add argument description. - @param ExtendedVerification GC_TODO: add argument description. - - @retval EFI_DEVICE_ERROR GC_TODO: Add description for return value. + @retval EFI_DEVICE_ERROR When the device is neighther ATA device or ATAPI device. + @retval EFI_SUCCESS The device reset successfully **/ EFI_STATUS @@ -1107,15 +1083,16 @@ Done: } /** - Read data from block io device + Read data from a block IO device - @param This Protocol instance pointer. - @param MediaId The media ID of the device - @param LBA Starting LBA address to read data + @param This Block IO protocol instance pointer. + @param MediaId The media ID of the device + @param LBA Starting LBA address to read data @param BufferSize The size of data to be read - @param Buffer Caller supplied buffer to save data + @param Buffer Caller supplied buffer to save data - @return read data status + @retval EFI_DEVICE_ERROR unknown device type + @retval other read data status. **/ EFI_STATUS @@ -1127,7 +1104,6 @@ IDEBlkIoReadBlocks ( IN UINTN BufferSize, OUT VOID *Buffer ) -// TODO: EFI_DEVICE_ERROR - add return value to function comment { IDE_BLK_IO_DEV *IdeBlkIoDevice; EFI_STATUS Status; @@ -1182,13 +1158,14 @@ Done: /** Write data to block io device - @param This Protocol instance pointer. - @param MediaId The media ID of the device - @param LBA Starting LBA address to write data + @param This Protocol instance pointer. + @param MediaId The media ID of the device + @param LBA Starting LBA address to write data @param BufferSize The size of data to be written - @param Buffer Caller supplied buffer to save data + @param Buffer Caller supplied buffer to save data - @return write data status + @retval EFI_DEVICE_ERROR unknown device type + @retval other write data status **/ EFI_STATUS @@ -1200,7 +1177,6 @@ IDEBlkIoWriteBlocks ( IN UINTN BufferSize, IN VOID *Buffer ) -// TODO: EFI_DEVICE_ERROR - add return value to function comment { IDE_BLK_IO_DEV *IdeBlkIoDevice; EFI_STATUS Status; @@ -1250,19 +1226,13 @@ Done: gBS->RestoreTPL (OldTpl); return Status; } - -// -// *********************************************************************************** -// IDEBlkIoFlushBlocks -// *********************************************************************************** -// /** - TODO: Add function description + Flushes all modified data to a physical block devices - @param This TODO: add argument description - - @retval EFI_SUCCESS GC_TODO: Add description for return value. + @param This Indicates a pointer to the calling context which to sepcify a + sepcific block device + @retval EFI_SUCCESS Always return success. **/ EFI_STATUS EFIAPI @@ -1362,14 +1332,14 @@ IDEDiskInfoIdentify ( Return the results of the Request Sense command to a drive in SenseData. Data format of Sense data is defined by the Interface GUID. - @param This Protocol instance pointer. - @param SenseData Results of Request Sense command to device - @param SenseDataSize Size of SenseData in bytes. + @param This Protocol instance pointer. + @param SenseData Results of Request Sense command to device + @param SenseDataSize Size of SenseData in bytes. @param SenseDataNumber Type of SenseData - @retval EFI_SUCCESS InquiryData valid - @retval EFI_NOT_FOUND Device does not support this data class - @retval EFI_DEVICE_ERROR Error reading InquiryData from device + @retval EFI_SUCCESS InquiryData valid + @retval EFI_NOT_FOUND Device does not support this data class + @retval EFI_DEVICE_ERROR Error reading InquiryData from device @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough **/ @@ -1389,11 +1359,11 @@ IDEDiskInfoSenseData ( Return the results of the Request Sense command to a drive in SenseData. Data format of Sense data is defined by the Interface GUID. - @param This Protocol instance pointer. + @param This Protocol instance pointer. @param IdeChannel Primary or Secondary - @param IdeDevice Master or Slave + @param IdeDevice Master or Slave - @retval EFI_SUCCESS IdeChannel and IdeDevice are valid + @retval EFI_SUCCESS IdeChannel and IdeDevice are valid @retval EFI_UNSUPPORTED This is not an IDE device **/ @@ -1414,6 +1384,103 @@ IDEDiskInfoWhichIde ( return EFI_SUCCESS; } +/** + The is an event(generally the event is exitBootService event) call back function. + Clear pending IDE interrupt before OS loader/kernel take control of the IDE device. + + @param Event Pointer to this event + @param Context Event hanlder private data + +**/ +VOID +EFIAPI +ClearInterrupt ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + UINT64 IoPortForBmis; + UINT8 RegisterValue; + IDE_BLK_IO_DEV *IdeDev; + + // + // Get our context + // + IdeDev = (IDE_BLK_IO_DEV *) Context; + + // + // Obtain IDE IO port registers' base addresses + // + Status = ReassignIdeResources (IdeDev); + if (EFI_ERROR (Status)) { + return; + } + + // + // Check whether interrupt is pending + // + + // + // Reset IDE device to force it de-assert interrupt pin + // Note: this will reset all devices on this IDE channel + // + AtaSoftReset (IdeDev); + if (EFI_ERROR (Status)) { + return; + } + + // + // Get base address of IDE Bus Master Status Regsiter + // + if (IdePrimary == IdeDev->Channel) { + IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET; + } else { + if (IdeSecondary == IdeDev->Channel) { + IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET; + } else { + return; + } + } + // + // 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 + ); + + // + // Select the other device on this channel to ensure this device to release the interrupt pin + // + if (IdeDev->Device == 0) { + RegisterValue = (1 << 4) | 0xe0; + } else { + RegisterValue = (0 << 4) | 0xe0; + } + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + RegisterValue + ); + +} + /** The user Entry Point for module IdeBus. The user code starts with this function. diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.h b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.h index 092b219503..55f4b72f16 100644 --- a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.h +++ b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.h @@ -119,34 +119,16 @@ typedef struct { #include "Ide.h" -// -// Prototypes -// Driver model protocol interface -// -/** - TODO: Add function description - - @param ImageHandle TODO: add argument description - @param SystemTable TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -EFIAPI -IDEBusControllerDriverEntryPoint ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ); /** - TODO: Add function description + Supported function of Driver Binding protocol for this driver. - @param This TODO: add argument description - @param Controller TODO: add argument description - @param RemainingDevicePath TODO: add argument description + @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param ControllerHandle The handle of the controller to test. + @param RemainingDevicePath A pointer to the remaining portion of a device path. - TODO: add return values. + @retval EFI_SUCCESS Driver loaded. + @retval other Driver not loaded. **/ EFI_STATUS @@ -158,13 +140,16 @@ IDEBusDriverBindingSupported ( ); /** - TODO: Add function description + Start function of Driver binding protocol which start this driver on Controller + by detecting all disks and installing BlockIo protocol on them. - @param This TODO: add argument description - @param Controller TODO: add argument description - @param RemainingDevicePath TODO: add argument description + @param This Protocol instance pointer. + @param Controller Handle of device to bind driver to. + @param RemainingDevicePath produce all possible children. - TODO: add return values. + @retval EFI_SUCCESS This driver is added to ControllerHandle. + @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle. + @retval other This driver does not support this device. **/ EFI_STATUS @@ -176,14 +161,16 @@ IDEBusDriverBindingStart ( ); /** - TODO: Add function description + Stop function of Driver Binding Protocol which is to stop the driver on Controller Handle and all + child handle attached to the controller handle if there are. - @param This TODO: add argument description - @param Controller TODO: add argument description - @param NumberOfChildren TODO: add argument description - @param ChildHandleBuffer TODO: add argument description + @param This Protocol instance pointer. + @param Controller Handle of device to stop driver on + @param NumberOfChildren Not used + @param ChildHandleBuffer Not used - TODO: add return values. + @retval EFI_SUCCESS This driver is removed DeviceHandle + @retval other This driver was not removed from this device **/ EFI_STATUS @@ -199,16 +186,38 @@ IDEBusDriverBindingStop ( // EFI Driver Configuration Functions // /** - TODO: Add function description - - @param This TODO: add argument description - @param ControllerHandle TODO: add argument description - @param ChildHandle TODO: add argument description - @param Language TODO: add argument description - @param ActionRequired TODO: add argument description - - TODO: add return values. - + Allows the user to set controller specific options for a controller that a + driver is currently managing. + + @param This A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL instance. + @param ControllerHandle The handle of the controller to set options on. + @param ChildHandle The handle of the child controller to set options on. + This is an optional parameter that may be NULL. + It will be NULL for device drivers, and for a bus drivers + that wish to set options for the bus controller. + It will not be NULL for a bus driver that wishes to set + options for one of its child controllers. + @param Language A pointer to a three character ISO 639-2 language identifier. + This is the language of the user interface that should be presented + to the user, and it must match one of the languages specified in + SupportedLanguages. The number of languages supported by a driver is up to + the driver writer. + @param ActionRequired A pointer to the action that the calling agent is required + to perform when this function returns. + + + @retval EFI_SUCCESS The driver specified by This successfully set the configuration + options for the controller specified by ControllerHandle.. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ActionRequired is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support setting configuration options for + the controller specified by ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the language specified by Language. + @retval EFI_DEVICE_ERROR A device error occurred while attempt to set the configuration options for the + controller specified by ControllerHandle and ChildHandle. + @retval EFI_OUT_RESOURCES There are not enough resources available to set the configuration options for the + controller specified by ControllerHandle and ChildHandle **/ EFI_STATUS EFIAPI @@ -221,14 +230,27 @@ IDEBusDriverConfigurationSetOptions ( ); /** - TODO: Add function description - - @param This TODO: add argument description - @param ControllerHandle TODO: add argument description - @param ChildHandle TODO: add argument description - - TODO: add return values. - + Tests to see if a controller's current configuration options are valid. + + @param This A pointer to the EFI_DRIVER_CONFIGURATION_PROTOCOL instance. + @param ControllerHandle The handle of the controller to test if it's current configuration options + are valid. + @param ChildHandle The handle of the child controller to test if it's current configuration + options are valid. This is an optional parameter that may be NULL. It will + be NULL for device drivers. It will also be NULL for a bus drivers that + wish to test the configuration options for the bus controller. It will + not be NULL for a bus driver that wishes to test configuration options for + one of its child controllers. + @retval EFI_SUCCESS The controller specified by ControllerHandle and ChildHandle that is being + managed by the driver specified by This has a valid set of configuration + options. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_UNSUPPORTED The driver specified by This is not currently managing the controller + specified by ControllerHandle and ChildHandle. + @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and ChildHandle that is being + managed by the driver specified by This has an invalid set of configuration + options. **/ EFI_STATUS EFIAPI @@ -239,16 +261,36 @@ IDEBusDriverConfigurationOptionsValid ( ); /** - TODO: Add function description - - @param This TODO: add argument description - @param ControllerHandle TODO: add argument description - @param ChildHandle TODO: add argument description - @param DefaultType TODO: add argument description - @param ActionRequired TODO: add argument description - - TODO: add return values. - + Forces a driver to set the default configuration options for a controller. + + @param This A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL instance. + @param ControllerHandle The handle of the controller to force default configuration options on. + @param ChildHandle The handle of the child controller to force default configuration + options on This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL for a bus + drivers that wish to force default configuration options for the bus + controller. It will not be NULL for a bus driver that wishes to force + default configuration options for one of its child controllers. + @param DefaultType The type of default configuration options to force on the controller + specified by ControllerHandle and ChildHandle. + @param ActionRequired A pointer to the action that the calling agent is required to perform + when this function returns. + + @retval EFI_SUCCESS The driver specified by This successfully forced the + default configuration options on the controller specified by + ControllerHandle and ChildHandle. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ActionRequired is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support forcing the default + configuration options on the controller specified by ControllerHandle + and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the configuration type + specified by DefaultType. + @retval EFI_DEVICE_ERROR A device error occurred while attempt to force the default configuration + options on the controller specified by ControllerHandle and ChildHandle. + @retval EFI_OUT_RESOURCES There are not enough resources available to force the default configuration + options on the controller specified by ControllerHandle and ChildHandle. **/ EFI_STATUS EFIAPI @@ -264,19 +306,51 @@ IDEBusDriverConfigurationForceDefaults ( // EFI Driver Diagnostics Functions // /** - TODO: Add function description - - @param This TODO: add argument description - @param ControllerHandle TODO: add argument description - @param ChildHandle TODO: add argument description - @param DiagnosticType TODO: add argument description - @param Language TODO: add argument description - @param ErrorType TODO: add argument description - @param BufferSize TODO: add argument description - @param Buffer TODO: add argument description - - TODO: add return values. - + Runs diagnostics on a controller. + + @param This A pointer to the EFI_DRIVER_DIAGNOSTICS_PROTOCOLinstance. + @param ControllerHandle The handle of the controller to run diagnostics on. + @param ChildHandle The handle of the child controller to run diagnostics on + This is an optional parameter that may be NULL. It will + be NULL for device drivers. It will also be NULL for a + bus drivers that wish to run diagnostics on the bus controller. + It will not be NULL for a bus driver that wishes to run + diagnostics on one of its child controllers. + @param DiagnosticType Indicates type of diagnostics to perform on the controller + specified by ControllerHandle and ChildHandle. + @param Language A pointer to a three character ISO 639-2 language identifier. + This is the language in which the optional error message should + be returned in Buffer, and it must match one of the languages + specified in SupportedLanguages. The number of languages supported by + a driver is up to the driver writer. + @param ErrorType A GUID that defines the format of the data returned in Buffer. + @param BufferSize The size, in bytes, of the data returned in Buffer. + @param Buffer A buffer that contains a Null-terminated Unicode string + plus some additional data whose format is defined by ErrorType. + Buffer is allocated by this function with AllocatePool(), and + it is the caller's responsibility to free it with a call to FreePool(). + + @retval EFI_SUCCESS The controller specified by ControllerHandle and ChildHandle passed + the diagnostic. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER ErrorType is NULL. + @retval EFI_INVALID_PARAMETER BufferType is NULL. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support running + diagnostics for the controller specified by ControllerHandle + and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + type of diagnostic specified by DiagnosticType. + @retval EFI_UNSUPPORTED The driver specified by This does not support the language + specified by Language. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to complete the + diagnostics. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to return the + status information in ErrorType, BufferSize,and Buffer. + @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and ChildHandle + did not pass the diagnostic. **/ EFI_STATUS EFIAPI @@ -291,16 +365,15 @@ IDEBusDriverDiagnosticsRunDiagnostics ( OUT CHAR16 **Buffer ); -// -// Block I/O Protocol Interface -// /** - TODO: Add function description - - @param This TODO: add argument description - @param ExtendedVerification TODO: add argument description + issue ATA or ATAPI command to reset a block IO device. + @param This Block IO protocol instance pointer. + @param ExtendedVerification If FALSE,for ATAPI device, driver will only invoke ATAPI reset method + If TRUE, for ATAPI device, driver need invoke ATA reset method after + invoke ATAPI reset method - TODO: add return values. + @retval EFI_DEVICE_ERROR When the device is neighther ATA device or ATAPI device. + @retval EFI_SUCCESS The device reset successfully **/ EFI_STATUS @@ -311,15 +384,16 @@ IDEBlkIoReset ( ); /** - TODO: Add function description + Read data from a block IO device - @param This TODO: add argument description - @param MediaId TODO: add argument description - @param Lba TODO: add argument description - @param BufferSize TODO: add argument description - @param Buffer TODO: add argument description + @param This Block IO protocol instance pointer. + @param MediaId The media ID of the device + @param LBA Starting LBA address to read data + @param BufferSize The size of data to be read + @param Buffer Caller supplied buffer to save data - TODO: add return values. + @retval EFI_DEVICE_ERROR unknown device type + @retval EFI_SUCCESS read the data successfully. **/ EFI_STATUS @@ -333,15 +407,16 @@ IDEBlkIoReadBlocks ( ); /** - TODO: Add function description + Write data to block io device - @param This TODO: add argument description - @param MediaId TODO: add argument description - @param Lba TODO: add argument description - @param BufferSize TODO: add argument description - @param Buffer TODO: add argument description + @param This Protocol instance pointer. + @param MediaId The media ID of the device + @param LBA Starting LBA address to write data + @param BufferSize The size of data to be written + @param Buffer Caller supplied buffer to save data - TODO: add return values. + @retval EFI_DEVICE_ERROR unknown device type + @retval other write data status **/ EFI_STATUS @@ -355,42 +430,30 @@ IDEBlkIoWriteBlocks ( ); /** - TODO: Add function description + Flushes all modified data to a physical block devices - @param This TODO: add argument description - - TODO: add return values. + @param This Indicates a pointer to the calling context which to sepcify a + sepcific block device + @retval EFI_SUCCESS Always return success. **/ EFI_STATUS EFIAPI IDEBlkIoFlushBlocks ( IN EFI_BLOCK_IO_PROTOCOL *This ); - -/** - TODO: Add function description - - @param PciIo TODO: add argument description - @param Enable TODO: add argument description - - TODO: add return values. - -**/ -EFI_STATUS -IDERegisterDecodeEnableorDisable ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN BOOLEAN Enable - ); - /** - TODO: Add function description + Return the results of the Inquiry command to a drive in InquiryData. + Data format of Inquiry data is defined by the Interface GUID. - @param This TODO: add argument description - @param InquiryData TODO: add argument description - @param IntquiryDataSize TODO: add argument description + @param This Protocol instance pointer. + @param InquiryData Results of Inquiry command to device + @param InquiryDataSize Size of InquiryData in bytes. - TODO: add return values. + @retval EFI_SUCCESS InquiryData valid + @retval EFI_NOT_FOUND Device does not support this data class + @retval EFI_DEVICE_ERROR Error reading InquiryData from device + @retval EFI_BUFFER_TOO_SMALL IntquiryDataSize not big enough **/ EFI_STATUS @@ -402,13 +465,17 @@ IDEDiskInfoInquiry ( ); /** - TODO: Add function description + Return the results of the Identify command to a drive in IdentifyData. + Data format of Identify data is defined by the Interface GUID. - @param This TODO: add argument description - @param IdentifyData TODO: add argument description - @param IdentifyDataSize TODO: add argument description + @param This Protocol instance pointer. + @param IdentifyData Results of Identify command to device + @param IdentifyDataSize Size of IdentifyData in bytes. - TODO: add return values. + @retval EFI_SUCCESS IdentifyData valid + @retval EFI_NOT_FOUND Device does not support this data class + @retval EFI_DEVICE_ERROR Error reading IdentifyData from device + @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough **/ EFI_STATUS @@ -420,14 +487,18 @@ IDEDiskInfoIdentify ( ); /** - TODO: Add function description + Return the results of the Request Sense command to a drive in SenseData. + Data format of Sense data is defined by the Interface GUID. - @param This TODO: add argument description - @param SenseData TODO: add argument description - @param SenseDataSize TODO: add argument description - @param SenseDataNumber TODO: add argument description + @param This Protocol instance pointer. + @param SenseData Results of Request Sense command to device + @param SenseDataSize Size of SenseData in bytes. + @param SenseDataNumber Type of SenseData - TODO: add return values. + @retval EFI_SUCCESS InquiryData valid + @retval EFI_NOT_FOUND Device does not support this data class + @retval EFI_DEVICE_ERROR Error reading InquiryData from device + @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough **/ EFI_STATUS @@ -440,13 +511,15 @@ IDEDiskInfoSenseData ( ); /** - TODO: Add function description + Return the results of the Request Sense command to a drive in SenseData. + Data format of Sense data is defined by the Interface GUID. - @param This TODO: add argument description - @param IdeChannel TODO: add argument description - @param IdeDevice TODO: add argument description + @param This Protocol instance pointer. + @param IdeChannel Primary or Secondary + @param IdeDevice Master or Slave - TODO: add return values. + @retval EFI_SUCCESS IdeChannel and IdeDevice are valid + @retval EFI_UNSUPPORTED This is not an IDE device **/ EFI_STATUS @@ -456,5 +529,18 @@ IDEDiskInfoWhichIde ( OUT UINT32 *IdeChannel, OUT UINT32 *IdeDevice ); +/** + The is an event(generally the event is exitBootService event) call back function. + Clear pending IDE interrupt before OS loader/kernel take control of the IDE device. + + @param Event Pointer to this event + @param Context Event hanlder private data +**/ +VOID +EFIAPI +ClearInterrupt ( + IN EFI_EVENT Event, + IN VOID *Context + ); #endif -- cgit v1.2.3