From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=missing; spf=fail (domain: intel.com, ip: , mailfrom: prince.agyeman@intel.com) Received: from mga14.intel.com (mga14.intel.com []) by groups.io with SMTP; Thu, 04 Apr 2019 08:32:27 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 04 Apr 2019 08:32:25 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.60,308,1549958400"; d="scan'208";a="220571756" Received: from paagyema-desk2.amr.corp.intel.com ([10.7.159.148]) by orsmga001.jf.intel.com with ESMTP; 04 Apr 2019 08:32:25 -0700 From: "Agyeman, Prince" To: devel@edk2.groups.io Cc: Maurice Ma , Benjamin You Subject: [PATCH v2 1/2] CorebootModulePkg: Fix non - CRLF line endings Date: Thu, 4 Apr 2019 08:32:24 -0700 Message-Id: <5740003cd80306d755ed0ed5f32c6597b3f94a8b.1554337466.git.prince.agyeman@intel.com> X-Mailer: git-send-email 2.19.1.windows.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1658 Replaced non CRLF line endings with CRLF Cc: Maurice Ma Cc: Benjamin You Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Agyeman --- CorebootModulePkg/Include/Coreboot.h | 32 +- .../BaseSerialPortLib16550.c | 2178 ++++++++--------- .../SataControllerDxe/SataController.h | 1082 ++++---- CorebootModulePkg/SecCore/Ia32/Stack.S | 138 +- 4 files changed, 1715 insertions(+), 1715 deletions(-) diff --git a/CorebootModulePkg/Include/Coreboot.h b/CorebootModulePkg/Include/Coreboot.h index 784e0b128a..b622e6f17e 100644 --- a/CorebootModulePkg/Include/Coreboot.h +++ b/CorebootModulePkg/Include/Coreboot.h @@ -80,7 +80,7 @@ struct imd_root { UINT32 max_entries; UINT32 num_entries; UINT32 flags; - UINT32 entry_align; + UINT32 entry_align; UINT32 max_offset; struct imd_entry entries[0]; }; @@ -165,21 +165,21 @@ struct cb_serial { UINT32 type; UINT32 baseaddr; UINT32 baud; - UINT32 regwidth; - - // Crystal or input frequency to the chip containing the UART. - // Provide the board specific details to allow the payload to - // initialize the chip containing the UART and make independent - // decisions as to which dividers to select and their values - // to eventually arrive at the desired console baud-rate. - UINT32 input_hertz; - - // UART PCI address: bus, device, function - // 1 << 31 - Valid bit, PCI UART in use - // Bus << 20 - // Device << 15 - // Function << 12 - UINT32 uart_pci_addr; + UINT32 regwidth; + + // Crystal or input frequency to the chip containing the UART. + // Provide the board specific details to allow the payload to + // initialize the chip containing the UART and make independent + // decisions as to which dividers to select and their values + // to eventually arrive at the desired console baud-rate. + UINT32 input_hertz; + + // UART PCI address: bus, device, function + // 1 << 31 - Valid bit, PCI UART in use + // Bus << 20 + // Device << 15 + // Function << 12 + UINT32 uart_pci_addr; }; #define CB_TAG_CONSOLE 0x00010 diff --git a/CorebootModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c b/CorebootModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c index a5e1755a44..804b948906 100644 --- a/CorebootModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c +++ b/CorebootModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c @@ -1,1095 +1,1095 @@ -/** @file - 16550 UART Serial Port library functions - - (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
- Copyright (c) 2006 - 2016, 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 - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include -#include -#include -#include -#include -#include -#include -#include - -// +/** @file + 16550 UART Serial Port library functions + + (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2006 - 2016, 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 + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +// // PCI Definitions. -// -#define PCI_BRIDGE_32_BIT_IO_SPACE 0x01 - -// -// 16550 UART register offsets and bitfields -// -#define R_UART_RXBUF 0 -#define R_UART_TXBUF 0 -#define R_UART_BAUD_LOW 0 -#define R_UART_BAUD_HIGH 1 -#define R_UART_FCR 2 -#define B_UART_FCR_FIFOE BIT0 -#define B_UART_FCR_FIFO64 BIT5 -#define R_UART_LCR 3 -#define B_UART_LCR_DLAB BIT7 -#define R_UART_MCR 4 -#define B_UART_MCR_DTRC BIT0 -#define B_UART_MCR_RTS BIT1 -#define R_UART_LSR 5 -#define B_UART_LSR_RXRDY BIT0 -#define B_UART_LSR_TXRDY BIT5 -#define B_UART_LSR_TEMT BIT6 -#define R_UART_MSR 6 -#define B_UART_MSR_CTS BIT4 -#define B_UART_MSR_DSR BIT5 -#define B_UART_MSR_RI BIT6 -#define B_UART_MSR_DCD BIT7 - -// -// 4-byte structure for each PCI node in PcdSerialPciDeviceInfo -// -typedef struct { - UINT8 Device; - UINT8 Function; - UINT16 PowerManagementStatusAndControlRegister; -} PCI_UART_DEVICE_INFO; - -/** - Read an 8-bit 16550 register. If PcdSerialUseMmio is TRUE, then the value is read from - MMIO space. If PcdSerialUseMmio is FALSE, then the value is read from I/O space. The - parameter Offset is added to the base address of the 16550 registers that is specified - by PcdSerialRegisterBase. - - @param Base The base address register of UART device. - @param Offset The offset of the 16550 register to read. - - @return The value read from the 16550 register. - -**/ -UINT8 -SerialPortReadRegister ( - UINTN Base, - UINTN Offset - ) -{ - if (PcdGetBool (PcdSerialUseMmio)) { - return MmioRead8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride)); - } else { - return IoRead8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride)); - } -} - -/** - Write an 8-bit 16550 register. If PcdSerialUseMmio is TRUE, then the value is written to - MMIO space. If PcdSerialUseMmio is FALSE, then the value is written to I/O space. The - parameter Offset is added to the base address of the 16550 registers that is specified - by PcdSerialRegisterBase. - - @param Base The base address register of UART device. - @param Offset The offset of the 16550 register to write. - @param Value The value to write to the 16550 register specified by Offset. - - @return The value written to the 16550 register. - -**/ -UINT8 -SerialPortWriteRegister ( - UINTN Base, - UINTN Offset, - UINT8 Value - ) -{ - if (PcdGetBool (PcdSerialUseMmio)) { - return MmioWrite8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride), Value); - } else { - return IoWrite8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride), Value); - } -} - -/** - Update the value of an 16-bit PCI configuration register in a PCI device. If the - PCI Configuration register specified by PciAddress is already programmed with a - non-zero value, then return the current value. Otherwise update the PCI configuration - register specified by PciAddress with the value specified by Value and return the - value programmed into the PCI configuration register. All values must be masked - using the bitmask specified by Mask. - - @param PciAddress PCI Library address of the PCI Configuration register to update. - @param Value The value to program into the PCI Configuration Register. - @param Mask Bitmask of the bits to check and update in the PCI configuration register. - -**/ -UINT16 -SerialPortLibUpdatePciRegister16 ( - UINTN PciAddress, - UINT16 Value, - UINT16 Mask - ) -{ - UINT16 CurrentValue; - - CurrentValue = PciRead16 (PciAddress) & Mask; - if (CurrentValue != 0) { - return CurrentValue; - } - return PciWrite16 (PciAddress, Value & Mask); -} - -/** - Update the value of an 32-bit PCI configuration register in a PCI device. If the - PCI Configuration register specified by PciAddress is already programmed with a - non-zero value, then return the current value. Otherwise update the PCI configuration - register specified by PciAddress with the value specified by Value and return the - value programmed into the PCI configuration register. All values must be masked - using the bitmask specified by Mask. - - @param PciAddress PCI Library address of the PCI Configuration register to update. - @param Value The value to program into the PCI Configuration Register. - @param Mask Bitmask of the bits to check and update in the PCI configuration register. - - @return The Secondary bus number that is actually programed into the PCI to PCI Bridge device. - -**/ -UINT32 -SerialPortLibUpdatePciRegister32 ( - UINTN PciAddress, - UINT32 Value, - UINT32 Mask - ) -{ - UINT32 CurrentValue; - - CurrentValue = PciRead32 (PciAddress) & Mask; - if (CurrentValue != 0) { - return CurrentValue; - } - return PciWrite32 (PciAddress, Value & Mask); -} - -/** - Retrieve the I/O or MMIO base address register for the PCI UART device. - - This function assumes Root Bus Numer is Zero, and enables I/O and MMIO in PCI UART - Device if they are not already enabled. - - @return The base address register of the UART device. - -**/ -UINTN -GetSerialRegisterBase ( - VOID - ) -{ - UINTN PciLibAddress; - UINTN BusNumber; - UINTN SubordinateBusNumber; - UINT32 ParentIoBase; - UINT32 ParentIoLimit; - UINT16 ParentMemoryBase; - UINT16 ParentMemoryLimit; - UINT32 IoBase; - UINT32 IoLimit; - UINT16 MemoryBase; - UINT16 MemoryLimit; - UINTN SerialRegisterBase; - UINTN BarIndex; - UINT32 RegisterBaseMask; - PCI_UART_DEVICE_INFO *DeviceInfo; - - // - // Get PCI Device Info - // - DeviceInfo = (PCI_UART_DEVICE_INFO *) PcdGetPtr (PcdSerialPciDeviceInfo); - - // - // If PCI Device Info is empty, then assume fixed address UART and return PcdSerialRegisterBase - // - if (DeviceInfo->Device == 0xff) { - return (UINTN)PcdGet64 (PcdSerialRegisterBase); - } - - // - // Assume PCI Bus 0 I/O window is 0-64KB and MMIO windows is 0-4GB - // - ParentMemoryBase = 0 >> 16; - ParentMemoryLimit = 0xfff00000 >> 16; - ParentIoBase = 0 >> 12; - ParentIoLimit = 0xf000 >> 12; - - // - // Enable I/O and MMIO in PCI Bridge - // Assume Root Bus Numer is Zero. - // - for (BusNumber = 0; (DeviceInfo + 1)->Device != 0xff; DeviceInfo++) { - // - // Compute PCI Lib Address to PCI to PCI Bridge - // - PciLibAddress = PCI_LIB_ADDRESS (BusNumber, DeviceInfo->Device, DeviceInfo->Function, 0); - - // - // Retrieve and verify the bus numbers in the PCI to PCI Bridge - // - BusNumber = PciRead8 (PciLibAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET); - SubordinateBusNumber = PciRead8 (PciLibAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET); - if (BusNumber == 0 || BusNumber > SubordinateBusNumber) { - return 0; - } - - // - // Retrieve and verify the I/O or MMIO decode window in the PCI to PCI Bridge - // - if (PcdGetBool (PcdSerialUseMmio)) { - MemoryLimit = PciRead16 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit)) & 0xfff0; - MemoryBase = PciRead16 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase)) & 0xfff0; - - // - // If PCI Bridge MMIO window is disabled, then return 0 - // - if (MemoryLimit < MemoryBase) { - return 0; - } - - // - // If PCI Bridge MMIO window is not in the address range decoded by the parent PCI Bridge, then return 0 - // - if (MemoryBase < ParentMemoryBase || MemoryBase > ParentMemoryLimit || MemoryLimit > ParentMemoryLimit) { - return 0; - } - ParentMemoryBase = MemoryBase; - ParentMemoryLimit = MemoryLimit; - } else { - IoLimit = PciRead8 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimit)); - if ((IoLimit & PCI_BRIDGE_32_BIT_IO_SPACE ) == 0) { - IoLimit = IoLimit >> 4; - } else { - IoLimit = (PciRead16 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimitUpper16)) << 4) | (IoLimit >> 4); - } - IoBase = PciRead8 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase)); - if ((IoBase & PCI_BRIDGE_32_BIT_IO_SPACE ) == 0) { - IoBase = IoBase >> 4; - } else { - IoBase = (PciRead16 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBaseUpper16)) << 4) | (IoBase >> 4); - } - - // - // If PCI Bridge I/O window is disabled, then return 0 - // - if (IoLimit < IoBase) { - return 0; - } - - // - // If PCI Bridge I/O window is not in the address range decoded by the parent PCI Bridge, then return 0 - // - if (IoBase < ParentIoBase || IoBase > ParentIoLimit || IoLimit > ParentIoLimit) { - return 0; - } - ParentIoBase = IoBase; - ParentIoLimit = IoLimit; - } - } - - // - // Compute PCI Lib Address to PCI UART - // - PciLibAddress = PCI_LIB_ADDRESS (BusNumber, DeviceInfo->Device, DeviceInfo->Function, 0); - - // - // Find the first IO or MMIO BAR - // - RegisterBaseMask = 0xFFFFFFF0; - for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex ++) { - SerialRegisterBase = PciRead32 (PciLibAddress + PCI_BASE_ADDRESSREG_OFFSET + BarIndex * 4); - if (PcdGetBool (PcdSerialUseMmio) && ((SerialRegisterBase & BIT0) == 0)) { - // - // MMIO BAR is found - // - RegisterBaseMask = 0xFFFFFFF0; - break; - } - - if ((!PcdGetBool (PcdSerialUseMmio)) && ((SerialRegisterBase & BIT0) != 0)) { - // - // IO BAR is found - // - RegisterBaseMask = 0xFFFFFFF8; - break; - } - } - - // - // MMIO or IO BAR is not found. - // - if (BarIndex == PCI_MAX_BAR) { - return 0; - } - - // - // Program UART BAR - // - SerialRegisterBase = SerialPortLibUpdatePciRegister32 ( - PciLibAddress + PCI_BASE_ADDRESSREG_OFFSET + BarIndex * 4, - (UINT32)PcdGet64 (PcdSerialRegisterBase), - RegisterBaseMask - ); - - // - // Verify that the UART BAR is in the address range decoded by the parent PCI Bridge - // - if (PcdGetBool (PcdSerialUseMmio)) { - if (((SerialRegisterBase >> 16) & 0xfff0) < ParentMemoryBase || ((SerialRegisterBase >> 16) & 0xfff0) > ParentMemoryLimit) { - return 0; - } - } else { - if ((SerialRegisterBase >> 12) < ParentIoBase || (SerialRegisterBase >> 12) > ParentIoLimit) { - return 0; - } - } - - // - // Enable I/O and MMIO in PCI UART Device if they are not already enabled - // - PciOr16 ( - PciLibAddress + PCI_COMMAND_OFFSET, - PcdGetBool (PcdSerialUseMmio) ? EFI_PCI_COMMAND_MEMORY_SPACE : EFI_PCI_COMMAND_IO_SPACE - ); - - // - // Force D0 state if a Power Management and Status Register is specified - // - if (DeviceInfo->PowerManagementStatusAndControlRegister != 0x00) { - if ((PciRead16 (PciLibAddress + DeviceInfo->PowerManagementStatusAndControlRegister) & (BIT0 | BIT1)) != 0x00) { - PciAnd16 (PciLibAddress + DeviceInfo->PowerManagementStatusAndControlRegister, (UINT16)~(BIT0 | BIT1)); - // - // If PCI UART was not in D0, then make sure FIFOs are enabled, but do not reset FIFOs - // - SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, (UINT8)(PcdGet8 (PcdSerialFifoControl) & (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64))); - } - } - - // - // Get PCI Device Info - // - DeviceInfo = (PCI_UART_DEVICE_INFO *) PcdGetPtr (PcdSerialPciDeviceInfo); - - // - // Enable I/O or MMIO in PCI Bridge - // Assume Root Bus Numer is Zero. - // - for (BusNumber = 0; (DeviceInfo + 1)->Device != 0xff; DeviceInfo++) { - // - // Compute PCI Lib Address to PCI to PCI Bridge - // - PciLibAddress = PCI_LIB_ADDRESS (BusNumber, DeviceInfo->Device, DeviceInfo->Function, 0); - - // - // Enable the I/O or MMIO decode windows in the PCI to PCI Bridge - // - PciOr16 ( - PciLibAddress + PCI_COMMAND_OFFSET, - PcdGetBool (PcdSerialUseMmio) ? EFI_PCI_COMMAND_MEMORY_SPACE : EFI_PCI_COMMAND_IO_SPACE - ); - - // - // Force D0 state if a Power Management and Status Register is specified - // - if (DeviceInfo->PowerManagementStatusAndControlRegister != 0x00) { - if ((PciRead16 (PciLibAddress + DeviceInfo->PowerManagementStatusAndControlRegister) & (BIT0 | BIT1)) != 0x00) { - PciAnd16 (PciLibAddress + DeviceInfo->PowerManagementStatusAndControlRegister, (UINT16)~(BIT0 | BIT1)); - } - } - - BusNumber = PciRead8 (PciLibAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET); - } - - return SerialRegisterBase; -} - -/** - Return whether the hardware flow control signal allows writing. - - @param SerialRegisterBase The base address register of UART device. - - @retval TRUE The serial port is writable. - @retval FALSE The serial port is not writable. -**/ -BOOLEAN -SerialPortWritable ( - UINTN SerialRegisterBase - ) -{ - if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { - if (PcdGetBool (PcdSerialDetectCable)) { - // - // Wait for both DSR and CTS to be set - // DSR is set if a cable is connected. - // CTS is set if it is ok to transmit data - // - // DSR CTS Description Action - // === === ======================================== ======== - // 0 0 No cable connected. Wait - // 0 1 No cable connected. Wait - // 1 0 Cable connected, but not clear to send. Wait - // 1 1 Cable connected, and clear to send. Transmit - // - return (BOOLEAN) ((SerialPortReadRegister (SerialRegisterBase, R_UART_MSR) & (B_UART_MSR_DSR | B_UART_MSR_CTS)) == (B_UART_MSR_DSR | B_UART_MSR_CTS)); - } else { - // - // Wait for both DSR and CTS to be set OR for DSR to be clear. - // DSR is set if a cable is connected. - // CTS is set if it is ok to transmit data - // - // DSR CTS Description Action - // === === ======================================== ======== - // 0 0 No cable connected. Transmit - // 0 1 No cable connected. Transmit - // 1 0 Cable connected, but not clear to send. Wait +// +#define PCI_BRIDGE_32_BIT_IO_SPACE 0x01 + +// +// 16550 UART register offsets and bitfields +// +#define R_UART_RXBUF 0 +#define R_UART_TXBUF 0 +#define R_UART_BAUD_LOW 0 +#define R_UART_BAUD_HIGH 1 +#define R_UART_FCR 2 +#define B_UART_FCR_FIFOE BIT0 +#define B_UART_FCR_FIFO64 BIT5 +#define R_UART_LCR 3 +#define B_UART_LCR_DLAB BIT7 +#define R_UART_MCR 4 +#define B_UART_MCR_DTRC BIT0 +#define B_UART_MCR_RTS BIT1 +#define R_UART_LSR 5 +#define B_UART_LSR_RXRDY BIT0 +#define B_UART_LSR_TXRDY BIT5 +#define B_UART_LSR_TEMT BIT6 +#define R_UART_MSR 6 +#define B_UART_MSR_CTS BIT4 +#define B_UART_MSR_DSR BIT5 +#define B_UART_MSR_RI BIT6 +#define B_UART_MSR_DCD BIT7 + +// +// 4-byte structure for each PCI node in PcdSerialPciDeviceInfo +// +typedef struct { + UINT8 Device; + UINT8 Function; + UINT16 PowerManagementStatusAndControlRegister; +} PCI_UART_DEVICE_INFO; + +/** + Read an 8-bit 16550 register. If PcdSerialUseMmio is TRUE, then the value is read from + MMIO space. If PcdSerialUseMmio is FALSE, then the value is read from I/O space. The + parameter Offset is added to the base address of the 16550 registers that is specified + by PcdSerialRegisterBase. + + @param Base The base address register of UART device. + @param Offset The offset of the 16550 register to read. + + @return The value read from the 16550 register. + +**/ +UINT8 +SerialPortReadRegister ( + UINTN Base, + UINTN Offset + ) +{ + if (PcdGetBool (PcdSerialUseMmio)) { + return MmioRead8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride)); + } else { + return IoRead8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride)); + } +} + +/** + Write an 8-bit 16550 register. If PcdSerialUseMmio is TRUE, then the value is written to + MMIO space. If PcdSerialUseMmio is FALSE, then the value is written to I/O space. The + parameter Offset is added to the base address of the 16550 registers that is specified + by PcdSerialRegisterBase. + + @param Base The base address register of UART device. + @param Offset The offset of the 16550 register to write. + @param Value The value to write to the 16550 register specified by Offset. + + @return The value written to the 16550 register. + +**/ +UINT8 +SerialPortWriteRegister ( + UINTN Base, + UINTN Offset, + UINT8 Value + ) +{ + if (PcdGetBool (PcdSerialUseMmio)) { + return MmioWrite8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride), Value); + } else { + return IoWrite8 (Base + Offset * PcdGet32 (PcdSerialRegisterStride), Value); + } +} + +/** + Update the value of an 16-bit PCI configuration register in a PCI device. If the + PCI Configuration register specified by PciAddress is already programmed with a + non-zero value, then return the current value. Otherwise update the PCI configuration + register specified by PciAddress with the value specified by Value and return the + value programmed into the PCI configuration register. All values must be masked + using the bitmask specified by Mask. + + @param PciAddress PCI Library address of the PCI Configuration register to update. + @param Value The value to program into the PCI Configuration Register. + @param Mask Bitmask of the bits to check and update in the PCI configuration register. + +**/ +UINT16 +SerialPortLibUpdatePciRegister16 ( + UINTN PciAddress, + UINT16 Value, + UINT16 Mask + ) +{ + UINT16 CurrentValue; + + CurrentValue = PciRead16 (PciAddress) & Mask; + if (CurrentValue != 0) { + return CurrentValue; + } + return PciWrite16 (PciAddress, Value & Mask); +} + +/** + Update the value of an 32-bit PCI configuration register in a PCI device. If the + PCI Configuration register specified by PciAddress is already programmed with a + non-zero value, then return the current value. Otherwise update the PCI configuration + register specified by PciAddress with the value specified by Value and return the + value programmed into the PCI configuration register. All values must be masked + using the bitmask specified by Mask. + + @param PciAddress PCI Library address of the PCI Configuration register to update. + @param Value The value to program into the PCI Configuration Register. + @param Mask Bitmask of the bits to check and update in the PCI configuration register. + + @return The Secondary bus number that is actually programed into the PCI to PCI Bridge device. + +**/ +UINT32 +SerialPortLibUpdatePciRegister32 ( + UINTN PciAddress, + UINT32 Value, + UINT32 Mask + ) +{ + UINT32 CurrentValue; + + CurrentValue = PciRead32 (PciAddress) & Mask; + if (CurrentValue != 0) { + return CurrentValue; + } + return PciWrite32 (PciAddress, Value & Mask); +} + +/** + Retrieve the I/O or MMIO base address register for the PCI UART device. + + This function assumes Root Bus Numer is Zero, and enables I/O and MMIO in PCI UART + Device if they are not already enabled. + + @return The base address register of the UART device. + +**/ +UINTN +GetSerialRegisterBase ( + VOID + ) +{ + UINTN PciLibAddress; + UINTN BusNumber; + UINTN SubordinateBusNumber; + UINT32 ParentIoBase; + UINT32 ParentIoLimit; + UINT16 ParentMemoryBase; + UINT16 ParentMemoryLimit; + UINT32 IoBase; + UINT32 IoLimit; + UINT16 MemoryBase; + UINT16 MemoryLimit; + UINTN SerialRegisterBase; + UINTN BarIndex; + UINT32 RegisterBaseMask; + PCI_UART_DEVICE_INFO *DeviceInfo; + + // + // Get PCI Device Info + // + DeviceInfo = (PCI_UART_DEVICE_INFO *) PcdGetPtr (PcdSerialPciDeviceInfo); + + // + // If PCI Device Info is empty, then assume fixed address UART and return PcdSerialRegisterBase + // + if (DeviceInfo->Device == 0xff) { + return (UINTN)PcdGet64 (PcdSerialRegisterBase); + } + + // + // Assume PCI Bus 0 I/O window is 0-64KB and MMIO windows is 0-4GB + // + ParentMemoryBase = 0 >> 16; + ParentMemoryLimit = 0xfff00000 >> 16; + ParentIoBase = 0 >> 12; + ParentIoLimit = 0xf000 >> 12; + + // + // Enable I/O and MMIO in PCI Bridge + // Assume Root Bus Numer is Zero. + // + for (BusNumber = 0; (DeviceInfo + 1)->Device != 0xff; DeviceInfo++) { + // + // Compute PCI Lib Address to PCI to PCI Bridge + // + PciLibAddress = PCI_LIB_ADDRESS (BusNumber, DeviceInfo->Device, DeviceInfo->Function, 0); + + // + // Retrieve and verify the bus numbers in the PCI to PCI Bridge + // + BusNumber = PciRead8 (PciLibAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET); + SubordinateBusNumber = PciRead8 (PciLibAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET); + if (BusNumber == 0 || BusNumber > SubordinateBusNumber) { + return 0; + } + + // + // Retrieve and verify the I/O or MMIO decode window in the PCI to PCI Bridge + // + if (PcdGetBool (PcdSerialUseMmio)) { + MemoryLimit = PciRead16 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit)) & 0xfff0; + MemoryBase = PciRead16 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase)) & 0xfff0; + + // + // If PCI Bridge MMIO window is disabled, then return 0 + // + if (MemoryLimit < MemoryBase) { + return 0; + } + + // + // If PCI Bridge MMIO window is not in the address range decoded by the parent PCI Bridge, then return 0 + // + if (MemoryBase < ParentMemoryBase || MemoryBase > ParentMemoryLimit || MemoryLimit > ParentMemoryLimit) { + return 0; + } + ParentMemoryBase = MemoryBase; + ParentMemoryLimit = MemoryLimit; + } else { + IoLimit = PciRead8 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimit)); + if ((IoLimit & PCI_BRIDGE_32_BIT_IO_SPACE ) == 0) { + IoLimit = IoLimit >> 4; + } else { + IoLimit = (PciRead16 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimitUpper16)) << 4) | (IoLimit >> 4); + } + IoBase = PciRead8 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase)); + if ((IoBase & PCI_BRIDGE_32_BIT_IO_SPACE ) == 0) { + IoBase = IoBase >> 4; + } else { + IoBase = (PciRead16 (PciLibAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBaseUpper16)) << 4) | (IoBase >> 4); + } + + // + // If PCI Bridge I/O window is disabled, then return 0 + // + if (IoLimit < IoBase) { + return 0; + } + + // + // If PCI Bridge I/O window is not in the address range decoded by the parent PCI Bridge, then return 0 + // + if (IoBase < ParentIoBase || IoBase > ParentIoLimit || IoLimit > ParentIoLimit) { + return 0; + } + ParentIoBase = IoBase; + ParentIoLimit = IoLimit; + } + } + + // + // Compute PCI Lib Address to PCI UART + // + PciLibAddress = PCI_LIB_ADDRESS (BusNumber, DeviceInfo->Device, DeviceInfo->Function, 0); + + // + // Find the first IO or MMIO BAR + // + RegisterBaseMask = 0xFFFFFFF0; + for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex ++) { + SerialRegisterBase = PciRead32 (PciLibAddress + PCI_BASE_ADDRESSREG_OFFSET + BarIndex * 4); + if (PcdGetBool (PcdSerialUseMmio) && ((SerialRegisterBase & BIT0) == 0)) { + // + // MMIO BAR is found + // + RegisterBaseMask = 0xFFFFFFF0; + break; + } + + if ((!PcdGetBool (PcdSerialUseMmio)) && ((SerialRegisterBase & BIT0) != 0)) { + // + // IO BAR is found + // + RegisterBaseMask = 0xFFFFFFF8; + break; + } + } + + // + // MMIO or IO BAR is not found. + // + if (BarIndex == PCI_MAX_BAR) { + return 0; + } + + // + // Program UART BAR + // + SerialRegisterBase = SerialPortLibUpdatePciRegister32 ( + PciLibAddress + PCI_BASE_ADDRESSREG_OFFSET + BarIndex * 4, + (UINT32)PcdGet64 (PcdSerialRegisterBase), + RegisterBaseMask + ); + + // + // Verify that the UART BAR is in the address range decoded by the parent PCI Bridge + // + if (PcdGetBool (PcdSerialUseMmio)) { + if (((SerialRegisterBase >> 16) & 0xfff0) < ParentMemoryBase || ((SerialRegisterBase >> 16) & 0xfff0) > ParentMemoryLimit) { + return 0; + } + } else { + if ((SerialRegisterBase >> 12) < ParentIoBase || (SerialRegisterBase >> 12) > ParentIoLimit) { + return 0; + } + } + + // + // Enable I/O and MMIO in PCI UART Device if they are not already enabled + // + PciOr16 ( + PciLibAddress + PCI_COMMAND_OFFSET, + PcdGetBool (PcdSerialUseMmio) ? EFI_PCI_COMMAND_MEMORY_SPACE : EFI_PCI_COMMAND_IO_SPACE + ); + + // + // Force D0 state if a Power Management and Status Register is specified + // + if (DeviceInfo->PowerManagementStatusAndControlRegister != 0x00) { + if ((PciRead16 (PciLibAddress + DeviceInfo->PowerManagementStatusAndControlRegister) & (BIT0 | BIT1)) != 0x00) { + PciAnd16 (PciLibAddress + DeviceInfo->PowerManagementStatusAndControlRegister, (UINT16)~(BIT0 | BIT1)); + // + // If PCI UART was not in D0, then make sure FIFOs are enabled, but do not reset FIFOs + // + SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, (UINT8)(PcdGet8 (PcdSerialFifoControl) & (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64))); + } + } + + // + // Get PCI Device Info + // + DeviceInfo = (PCI_UART_DEVICE_INFO *) PcdGetPtr (PcdSerialPciDeviceInfo); + + // + // Enable I/O or MMIO in PCI Bridge + // Assume Root Bus Numer is Zero. + // + for (BusNumber = 0; (DeviceInfo + 1)->Device != 0xff; DeviceInfo++) { + // + // Compute PCI Lib Address to PCI to PCI Bridge + // + PciLibAddress = PCI_LIB_ADDRESS (BusNumber, DeviceInfo->Device, DeviceInfo->Function, 0); + + // + // Enable the I/O or MMIO decode windows in the PCI to PCI Bridge + // + PciOr16 ( + PciLibAddress + PCI_COMMAND_OFFSET, + PcdGetBool (PcdSerialUseMmio) ? EFI_PCI_COMMAND_MEMORY_SPACE : EFI_PCI_COMMAND_IO_SPACE + ); + + // + // Force D0 state if a Power Management and Status Register is specified + // + if (DeviceInfo->PowerManagementStatusAndControlRegister != 0x00) { + if ((PciRead16 (PciLibAddress + DeviceInfo->PowerManagementStatusAndControlRegister) & (BIT0 | BIT1)) != 0x00) { + PciAnd16 (PciLibAddress + DeviceInfo->PowerManagementStatusAndControlRegister, (UINT16)~(BIT0 | BIT1)); + } + } + + BusNumber = PciRead8 (PciLibAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET); + } + + return SerialRegisterBase; +} + +/** + Return whether the hardware flow control signal allows writing. + + @param SerialRegisterBase The base address register of UART device. + + @retval TRUE The serial port is writable. + @retval FALSE The serial port is not writable. +**/ +BOOLEAN +SerialPortWritable ( + UINTN SerialRegisterBase + ) +{ + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { + if (PcdGetBool (PcdSerialDetectCable)) { + // + // Wait for both DSR and CTS to be set + // DSR is set if a cable is connected. + // CTS is set if it is ok to transmit data + // + // DSR CTS Description Action + // === === ======================================== ======== + // 0 0 No cable connected. Wait + // 0 1 No cable connected. Wait + // 1 0 Cable connected, but not clear to send. Wait // 1 1 Cable connected, and clear to send. Transmit - // - return (BOOLEAN) ((SerialPortReadRegister (SerialRegisterBase, R_UART_MSR) & (B_UART_MSR_DSR | B_UART_MSR_CTS)) != (B_UART_MSR_DSR)); - } - } - - return TRUE; -} - -/** - Initialize the serial device hardware. - - If no initialization is required, then return RETURN_SUCCESS. - If the serial device was successfully initialized, then return RETURN_SUCCESS. - If the serial device could not be initialized, then return RETURN_DEVICE_ERROR. - - @retval RETURN_SUCCESS The serial device was initialized. - @retval RETURN_DEVICE_ERROR The serial device could not be initialized. - -**/ -RETURN_STATUS -EFIAPI -SerialPortInitialize ( - VOID - ) -{ - RETURN_STATUS Status; - UINTN SerialRegisterBase; - UINT32 Divisor; - UINT32 CurrentDivisor; - BOOLEAN Initialized; - - // - // Perform platform specific initialization required to enable use of the 16550 device - // at the location specified by PcdSerialUseMmio and PcdSerialRegisterBase. - // - Status = PlatformHookSerialPortInitialize (); - if (RETURN_ERROR (Status)) { - return Status; - } - - // - // Calculate divisor for baud generator - // Ref_Clk_Rate / Baud_Rate / 16 - // - Divisor = PcdGet32 (PcdSerialClockRate) / (PcdGet32 (PcdSerialBaudRate) * 16); - if ((PcdGet32 (PcdSerialClockRate) % (PcdGet32 (PcdSerialBaudRate) * 16)) >= PcdGet32 (PcdSerialBaudRate) * 8) { - Divisor++; - } - - // - // Get the base address of the serial port in either I/O or MMIO space - // - SerialRegisterBase = GetSerialRegisterBase (); - if (SerialRegisterBase ==0) { - return RETURN_DEVICE_ERROR; - } - - // - // See if the serial port is already initialized - // - Initialized = TRUE; - if ((SerialPortReadRegister (SerialRegisterBase, R_UART_LCR) & 0x3F) != (PcdGet8 (PcdSerialLineControl) & 0x3F)) { - Initialized = FALSE; - } - SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_LCR) | B_UART_LCR_DLAB)); - CurrentDivisor = SerialPortReadRegister (SerialRegisterBase, R_UART_BAUD_HIGH) << 8; - CurrentDivisor |= (UINT32) SerialPortReadRegister (SerialRegisterBase, R_UART_BAUD_LOW); - SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_LCR) & ~B_UART_LCR_DLAB)); - if (CurrentDivisor != Divisor) { - Initialized = FALSE; - } - if (Initialized) { - return RETURN_SUCCESS; - } - - // - // Wait for the serial port to be ready. - // Verify that both the transmit FIFO and the shift register are empty. - // - while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) != (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)); - - // - // Configure baud rate - // - SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, B_UART_LCR_DLAB); - SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_HIGH, (UINT8) (Divisor >> 8)); - SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_LOW, (UINT8) (Divisor & 0xff)); - - // - // Clear DLAB and configure Data Bits, Parity, and Stop Bits. - // Strip reserved bits from PcdSerialLineControl - // - SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(PcdGet8 (PcdSerialLineControl) & 0x3F)); - - // - // Enable and reset FIFOs - // Strip reserved bits from PcdSerialFifoControl - // - SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, 0x00); - SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, (UINT8)(PcdGet8 (PcdSerialFifoControl) & (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64))); - - // - // Set RTS and DTR in Modem Control Register(MCR) - // - SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, - EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY); - - return RETURN_SUCCESS; -} - -/** - Write data from buffer to serial device. - - Writes NumberOfBytes data bytes from Buffer to the serial device. - The number of bytes actually written to the serial device is returned. - If the return value is less than NumberOfBytes, then the write operation failed. - - If Buffer is NULL, then ASSERT(). - - If NumberOfBytes is zero, then return 0. - - @param Buffer Pointer to the data buffer to be written. - @param NumberOfBytes Number of bytes to written to the serial device. - - @retval 0 NumberOfBytes is 0. - @retval >0 The number of bytes written to the serial device. - If this value is less than NumberOfBytes, then the write operation failed. - -**/ -UINTN -EFIAPI -SerialPortWrite ( - IN UINT8 *Buffer, - IN UINTN NumberOfBytes - ) -{ - UINTN SerialRegisterBase; - UINTN Result; - UINTN Index; - UINTN FifoSize; - - if (Buffer == NULL) { - return 0; - } - - SerialRegisterBase = GetSerialRegisterBase (); - if (SerialRegisterBase ==0) { - return 0; - } - - if (NumberOfBytes == 0) { - // - // Flush the hardware - // - - // - // Wait for both the transmit FIFO and shift register empty. - // - while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) != (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)); - - // - // Wait for the hardware flow control signal - // - while (!SerialPortWritable (SerialRegisterBase)); - return 0; - } - - // - // Compute the maximum size of the Tx FIFO - // - FifoSize = 1; - if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFOE) != 0) { - if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFO64) == 0) { - FifoSize = 16; - } else { - FifoSize = PcdGet32 (PcdSerialExtendedTxFifoSize); - } - } - - Result = NumberOfBytes; - while (NumberOfBytes != 0) { - // - // Wait for the serial port to be ready, to make sure both the transmit FIFO - // and shift register empty. - // - while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & B_UART_LSR_TEMT) == 0); - - // - // Fill then entire Tx FIFO - // - for (Index = 0; Index < FifoSize && NumberOfBytes != 0; Index++, NumberOfBytes--, Buffer++) { - // - // Wait for the hardware flow control signal - // - while (!SerialPortWritable (SerialRegisterBase)); - - // - // Write byte to the transmit buffer. - // - SerialPortWriteRegister (SerialRegisterBase, R_UART_TXBUF, *Buffer); - } - } - return Result; -} - -/** - Reads data from a serial device into a buffer. - - @param Buffer Pointer to the data buffer to store the data read from the serial device. - @param NumberOfBytes Number of bytes to read from the serial device. - - @retval 0 NumberOfBytes is 0. - @retval >0 The number of bytes read from the serial device. - If this value is less than NumberOfBytes, then the read operation failed. - -**/ -UINTN -EFIAPI -SerialPortRead ( - OUT UINT8 *Buffer, - IN UINTN NumberOfBytes - ) -{ - UINTN SerialRegisterBase; - UINTN Result; - UINT8 Mcr; - - if (NULL == Buffer) { - return 0; - } - - SerialRegisterBase = GetSerialRegisterBase (); - if (SerialRegisterBase ==0) { - return 0; - } - - Mcr = (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_MCR) & ~B_UART_MCR_RTS); - - for (Result = 0; NumberOfBytes-- != 0; Result++, Buffer++) { - // - // Wait for the serial port to have some data. - // - while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & B_UART_LSR_RXRDY) == 0) { - if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { - // - // Set RTS to let the peer send some data - // - SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, (UINT8)(Mcr | B_UART_MCR_RTS)); - } - } - if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { - // - // Clear RTS to prevent peer from sending data - // - SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, Mcr); - } - - // - // Read byte from the receive buffer. - // - *Buffer = SerialPortReadRegister (SerialRegisterBase, R_UART_RXBUF); - } - - return Result; -} - - -/** - Polls a serial device to see if there is any data waiting to be read. - + // + return (BOOLEAN) ((SerialPortReadRegister (SerialRegisterBase, R_UART_MSR) & (B_UART_MSR_DSR | B_UART_MSR_CTS)) == (B_UART_MSR_DSR | B_UART_MSR_CTS)); + } else { + // + // Wait for both DSR and CTS to be set OR for DSR to be clear. + // DSR is set if a cable is connected. + // CTS is set if it is ok to transmit data + // + // DSR CTS Description Action + // === === ======================================== ======== + // 0 0 No cable connected. Transmit + // 0 1 No cable connected. Transmit + // 1 0 Cable connected, but not clear to send. Wait + // 1 1 Cable connected, and clear to send. Transmit + // + return (BOOLEAN) ((SerialPortReadRegister (SerialRegisterBase, R_UART_MSR) & (B_UART_MSR_DSR | B_UART_MSR_CTS)) != (B_UART_MSR_DSR)); + } + } + + return TRUE; +} + +/** + Initialize the serial device hardware. + + If no initialization is required, then return RETURN_SUCCESS. + If the serial device was successfully initialized, then return RETURN_SUCCESS. + If the serial device could not be initialized, then return RETURN_DEVICE_ERROR. + + @retval RETURN_SUCCESS The serial device was initialized. + @retval RETURN_DEVICE_ERROR The serial device could not be initialized. + +**/ +RETURN_STATUS +EFIAPI +SerialPortInitialize ( + VOID + ) +{ + RETURN_STATUS Status; + UINTN SerialRegisterBase; + UINT32 Divisor; + UINT32 CurrentDivisor; + BOOLEAN Initialized; + + // + // Perform platform specific initialization required to enable use of the 16550 device + // at the location specified by PcdSerialUseMmio and PcdSerialRegisterBase. + // + Status = PlatformHookSerialPortInitialize (); + if (RETURN_ERROR (Status)) { + return Status; + } + + // + // Calculate divisor for baud generator + // Ref_Clk_Rate / Baud_Rate / 16 + // + Divisor = PcdGet32 (PcdSerialClockRate) / (PcdGet32 (PcdSerialBaudRate) * 16); + if ((PcdGet32 (PcdSerialClockRate) % (PcdGet32 (PcdSerialBaudRate) * 16)) >= PcdGet32 (PcdSerialBaudRate) * 8) { + Divisor++; + } + + // + // Get the base address of the serial port in either I/O or MMIO space + // + SerialRegisterBase = GetSerialRegisterBase (); + if (SerialRegisterBase ==0) { + return RETURN_DEVICE_ERROR; + } + + // + // See if the serial port is already initialized + // + Initialized = TRUE; + if ((SerialPortReadRegister (SerialRegisterBase, R_UART_LCR) & 0x3F) != (PcdGet8 (PcdSerialLineControl) & 0x3F)) { + Initialized = FALSE; + } + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_LCR) | B_UART_LCR_DLAB)); + CurrentDivisor = SerialPortReadRegister (SerialRegisterBase, R_UART_BAUD_HIGH) << 8; + CurrentDivisor |= (UINT32) SerialPortReadRegister (SerialRegisterBase, R_UART_BAUD_LOW); + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_LCR) & ~B_UART_LCR_DLAB)); + if (CurrentDivisor != Divisor) { + Initialized = FALSE; + } + if (Initialized) { + return RETURN_SUCCESS; + } + + // + // Wait for the serial port to be ready. + // Verify that both the transmit FIFO and the shift register are empty. + // + while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) != (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)); + + // + // Configure baud rate + // + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, B_UART_LCR_DLAB); + SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_HIGH, (UINT8) (Divisor >> 8)); + SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_LOW, (UINT8) (Divisor & 0xff)); + + // + // Clear DLAB and configure Data Bits, Parity, and Stop Bits. + // Strip reserved bits from PcdSerialLineControl + // + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8)(PcdGet8 (PcdSerialLineControl) & 0x3F)); + + // + // Enable and reset FIFOs + // Strip reserved bits from PcdSerialFifoControl + // + SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, 0x00); + SerialPortWriteRegister (SerialRegisterBase, R_UART_FCR, (UINT8)(PcdGet8 (PcdSerialFifoControl) & (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64))); + + // + // Set RTS and DTR in Modem Control Register(MCR) + // + SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, + EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY); + + return RETURN_SUCCESS; +} + +/** + Write data from buffer to serial device. + + Writes NumberOfBytes data bytes from Buffer to the serial device. + The number of bytes actually written to the serial device is returned. + If the return value is less than NumberOfBytes, then the write operation failed. + + If Buffer is NULL, then ASSERT(). + + If NumberOfBytes is zero, then return 0. + + @param Buffer Pointer to the data buffer to be written. + @param NumberOfBytes Number of bytes to written to the serial device. + + @retval 0 NumberOfBytes is 0. + @retval >0 The number of bytes written to the serial device. + If this value is less than NumberOfBytes, then the write operation failed. + +**/ +UINTN +EFIAPI +SerialPortWrite ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes + ) +{ + UINTN SerialRegisterBase; + UINTN Result; + UINTN Index; + UINTN FifoSize; + + if (Buffer == NULL) { + return 0; + } + + SerialRegisterBase = GetSerialRegisterBase (); + if (SerialRegisterBase ==0) { + return 0; + } + + if (NumberOfBytes == 0) { + // + // Flush the hardware + // + + // + // Wait for both the transmit FIFO and shift register empty. + // + while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) != (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)); + + // + // Wait for the hardware flow control signal + // + while (!SerialPortWritable (SerialRegisterBase)); + return 0; + } + + // + // Compute the maximum size of the Tx FIFO + // + FifoSize = 1; + if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFOE) != 0) { + if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFO64) == 0) { + FifoSize = 16; + } else { + FifoSize = PcdGet32 (PcdSerialExtendedTxFifoSize); + } + } + + Result = NumberOfBytes; + while (NumberOfBytes != 0) { + // + // Wait for the serial port to be ready, to make sure both the transmit FIFO + // and shift register empty. + // + while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & B_UART_LSR_TEMT) == 0); + + // + // Fill then entire Tx FIFO + // + for (Index = 0; Index < FifoSize && NumberOfBytes != 0; Index++, NumberOfBytes--, Buffer++) { + // + // Wait for the hardware flow control signal + // + while (!SerialPortWritable (SerialRegisterBase)); + + // + // Write byte to the transmit buffer. + // + SerialPortWriteRegister (SerialRegisterBase, R_UART_TXBUF, *Buffer); + } + } + return Result; +} + +/** + Reads data from a serial device into a buffer. + + @param Buffer Pointer to the data buffer to store the data read from the serial device. + @param NumberOfBytes Number of bytes to read from the serial device. + + @retval 0 NumberOfBytes is 0. + @retval >0 The number of bytes read from the serial device. + If this value is less than NumberOfBytes, then the read operation failed. + +**/ +UINTN +EFIAPI +SerialPortRead ( + OUT UINT8 *Buffer, + IN UINTN NumberOfBytes + ) +{ + UINTN SerialRegisterBase; + UINTN Result; + UINT8 Mcr; + + if (NULL == Buffer) { + return 0; + } + + SerialRegisterBase = GetSerialRegisterBase (); + if (SerialRegisterBase ==0) { + return 0; + } + + Mcr = (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_MCR) & ~B_UART_MCR_RTS); + + for (Result = 0; NumberOfBytes-- != 0; Result++, Buffer++) { + // + // Wait for the serial port to have some data. + // + while ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & B_UART_LSR_RXRDY) == 0) { + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { + // + // Set RTS to let the peer send some data + // + SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, (UINT8)(Mcr | B_UART_MCR_RTS)); + } + } + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { + // + // Clear RTS to prevent peer from sending data + // + SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, Mcr); + } + + // + // Read byte from the receive buffer. + // + *Buffer = SerialPortReadRegister (SerialRegisterBase, R_UART_RXBUF); + } + + return Result; +} + + +/** + Polls a serial device to see if there is any data waiting to be read. + Polls a serial device to see if there is any data waiting to be read. - If there is data waiting to be read from the serial device, then TRUE is returned. - If there is no data waiting to be read from the serial device, then FALSE is returned. - - @retval TRUE Data is waiting to be read from the serial device. - @retval FALSE There is no data waiting to be read from the serial device. - -**/ -BOOLEAN -EFIAPI -SerialPortPoll ( - VOID - ) -{ - UINTN SerialRegisterBase; - - SerialRegisterBase = GetSerialRegisterBase (); - if (SerialRegisterBase ==0) { - return FALSE; - } - - // - // Read the serial port status - // - if ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & B_UART_LSR_RXRDY) != 0) { - if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { - // - // Clear RTS to prevent peer from sending data - // - SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_MCR) & ~B_UART_MCR_RTS)); - } - return TRUE; - } - - if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { - // - // Set RTS to let the peer send some data - // - SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_MCR) | B_UART_MCR_RTS)); - } - - return FALSE; -} - -/** - Sets the control bits on a serial device. - - @param Control Sets the bits of Control that are settable. - - @retval RETURN_SUCCESS The new control bits were set on the serial device. - @retval RETURN_UNSUPPORTED The serial device does not support this operation. - @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. - -**/ -RETURN_STATUS -EFIAPI -SerialPortSetControl ( - IN UINT32 Control - ) -{ - UINTN SerialRegisterBase; - UINT8 Mcr; - - // - // First determine the parameter is invalid. - // - if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY | - EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0) { - return RETURN_UNSUPPORTED; - } - - SerialRegisterBase = GetSerialRegisterBase (); - if (SerialRegisterBase ==0) { - return RETURN_UNSUPPORTED; - } - - // - // Read the Modem Control Register. - // - Mcr = SerialPortReadRegister (SerialRegisterBase, R_UART_MCR); - Mcr &= (~(B_UART_MCR_DTRC | B_UART_MCR_RTS)); - - if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) { - Mcr |= B_UART_MCR_DTRC; - } - - if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) { - Mcr |= B_UART_MCR_RTS; - } - - // - // Write the Modem Control Register. - // - SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, Mcr); - - return RETURN_SUCCESS; -} - -/** - Retrieve the status of the control bits on a serial device. - - @param Control A pointer to return the current control signals from the serial device. - - @retval RETURN_SUCCESS The control bits were read from the serial device. - @retval RETURN_UNSUPPORTED The serial device does not support this operation. - @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. - -**/ -RETURN_STATUS -EFIAPI -SerialPortGetControl ( - OUT UINT32 *Control - ) -{ - UINTN SerialRegisterBase; - UINT8 Msr; - UINT8 Mcr; - UINT8 Lsr; - - SerialRegisterBase = GetSerialRegisterBase (); - if (SerialRegisterBase ==0) { - return RETURN_UNSUPPORTED; - } - - *Control = 0; - - // - // Read the Modem Status Register. - // - Msr = SerialPortReadRegister (SerialRegisterBase, R_UART_MSR); - - if ((Msr & B_UART_MSR_CTS) == B_UART_MSR_CTS) { - *Control |= EFI_SERIAL_CLEAR_TO_SEND; - } - - if ((Msr & B_UART_MSR_DSR) == B_UART_MSR_DSR) { - *Control |= EFI_SERIAL_DATA_SET_READY; - } - - if ((Msr & B_UART_MSR_RI) == B_UART_MSR_RI) { - *Control |= EFI_SERIAL_RING_INDICATE; - } - - if ((Msr & B_UART_MSR_DCD) == B_UART_MSR_DCD) { - *Control |= EFI_SERIAL_CARRIER_DETECT; - } - - // - // Read the Modem Control Register. - // - Mcr = SerialPortReadRegister (SerialRegisterBase, R_UART_MCR); - - if ((Mcr & B_UART_MCR_DTRC) == B_UART_MCR_DTRC) { - *Control |= EFI_SERIAL_DATA_TERMINAL_READY; - } - - if ((Mcr & B_UART_MCR_RTS) == B_UART_MCR_RTS) { - *Control |= EFI_SERIAL_REQUEST_TO_SEND; - } - - if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { - *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; - } - - // - // Read the Line Status Register. - // - Lsr = SerialPortReadRegister (SerialRegisterBase, R_UART_LSR); - - if ((Lsr & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) == (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) { - *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY; - } - - if ((Lsr & B_UART_LSR_RXRDY) == 0) { - *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY; - } - - return RETURN_SUCCESS; -} - -/** + If there is data waiting to be read from the serial device, then TRUE is returned. + If there is no data waiting to be read from the serial device, then FALSE is returned. + + @retval TRUE Data is waiting to be read from the serial device. + @retval FALSE There is no data waiting to be read from the serial device. + +**/ +BOOLEAN +EFIAPI +SerialPortPoll ( + VOID + ) +{ + UINTN SerialRegisterBase; + + SerialRegisterBase = GetSerialRegisterBase (); + if (SerialRegisterBase ==0) { + return FALSE; + } + + // + // Read the serial port status + // + if ((SerialPortReadRegister (SerialRegisterBase, R_UART_LSR) & B_UART_LSR_RXRDY) != 0) { + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { + // + // Clear RTS to prevent peer from sending data + // + SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_MCR) & ~B_UART_MCR_RTS)); + } + return TRUE; + } + + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { + // + // Set RTS to let the peer send some data + // + SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, (UINT8)(SerialPortReadRegister (SerialRegisterBase, R_UART_MCR) | B_UART_MCR_RTS)); + } + + return FALSE; +} + +/** + Sets the control bits on a serial device. + + @param Control Sets the bits of Control that are settable. + + @retval RETURN_SUCCESS The new control bits were set on the serial device. + @retval RETURN_UNSUPPORTED The serial device does not support this operation. + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetControl ( + IN UINT32 Control + ) +{ + UINTN SerialRegisterBase; + UINT8 Mcr; + + // + // First determine the parameter is invalid. + // + if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY | + EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0) { + return RETURN_UNSUPPORTED; + } + + SerialRegisterBase = GetSerialRegisterBase (); + if (SerialRegisterBase ==0) { + return RETURN_UNSUPPORTED; + } + + // + // Read the Modem Control Register. + // + Mcr = SerialPortReadRegister (SerialRegisterBase, R_UART_MCR); + Mcr &= (~(B_UART_MCR_DTRC | B_UART_MCR_RTS)); + + if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) { + Mcr |= B_UART_MCR_DTRC; + } + + if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) { + Mcr |= B_UART_MCR_RTS; + } + + // + // Write the Modem Control Register. + // + SerialPortWriteRegister (SerialRegisterBase, R_UART_MCR, Mcr); + + return RETURN_SUCCESS; +} + +/** + Retrieve the status of the control bits on a serial device. + + @param Control A pointer to return the current control signals from the serial device. + + @retval RETURN_SUCCESS The control bits were read from the serial device. + @retval RETURN_UNSUPPORTED The serial device does not support this operation. + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortGetControl ( + OUT UINT32 *Control + ) +{ + UINTN SerialRegisterBase; + UINT8 Msr; + UINT8 Mcr; + UINT8 Lsr; + + SerialRegisterBase = GetSerialRegisterBase (); + if (SerialRegisterBase ==0) { + return RETURN_UNSUPPORTED; + } + + *Control = 0; + + // + // Read the Modem Status Register. + // + Msr = SerialPortReadRegister (SerialRegisterBase, R_UART_MSR); + + if ((Msr & B_UART_MSR_CTS) == B_UART_MSR_CTS) { + *Control |= EFI_SERIAL_CLEAR_TO_SEND; + } + + if ((Msr & B_UART_MSR_DSR) == B_UART_MSR_DSR) { + *Control |= EFI_SERIAL_DATA_SET_READY; + } + + if ((Msr & B_UART_MSR_RI) == B_UART_MSR_RI) { + *Control |= EFI_SERIAL_RING_INDICATE; + } + + if ((Msr & B_UART_MSR_DCD) == B_UART_MSR_DCD) { + *Control |= EFI_SERIAL_CARRIER_DETECT; + } + + // + // Read the Modem Control Register. + // + Mcr = SerialPortReadRegister (SerialRegisterBase, R_UART_MCR); + + if ((Mcr & B_UART_MCR_DTRC) == B_UART_MCR_DTRC) { + *Control |= EFI_SERIAL_DATA_TERMINAL_READY; + } + + if ((Mcr & B_UART_MCR_RTS) == B_UART_MCR_RTS) { + *Control |= EFI_SERIAL_REQUEST_TO_SEND; + } + + if (PcdGetBool (PcdSerialUseHardwareFlowControl)) { + *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; + } + + // + // Read the Line Status Register. + // + Lsr = SerialPortReadRegister (SerialRegisterBase, R_UART_LSR); + + if ((Lsr & (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) == (B_UART_LSR_TEMT | B_UART_LSR_TXRDY)) { + *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY; + } + + if ((Lsr & B_UART_LSR_RXRDY) == 0) { + *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY; + } + + return RETURN_SUCCESS; +} + +/** Sets the baud rate, receive FIFO depth, transmit/receive time out, parity, - data bits, and stop bits on a serial device. - - @param BaudRate The requested baud rate. A BaudRate value of 0 will use the - device's default interface speed. - On output, the value actually set. + data bits, and stop bits on a serial device. + + @param BaudRate The requested baud rate. A BaudRate value of 0 will use the + device's default interface speed. + On output, the value actually set. @param ReceiveFifoDepth The requested depth of the FIFO on the receive side of the - serial interface. A ReceiveFifoDepth value of 0 will use - the device's default FIFO depth. - On output, the value actually set. - @param Timeout The requested time out for a single character in microseconds. - This timeout applies to both the transmit and receive side of the - interface. A Timeout value of 0 will use the device's default time - out value. - On output, the value actually set. - @param Parity The type of parity to use on this serial device. A Parity value of - DefaultParity will use the device's default parity value. - On output, the value actually set. - @param DataBits The number of data bits to use on the serial device. A DataBits + serial interface. A ReceiveFifoDepth value of 0 will use + the device's default FIFO depth. + On output, the value actually set. + @param Timeout The requested time out for a single character in microseconds. + This timeout applies to both the transmit and receive side of the + interface. A Timeout value of 0 will use the device's default time + out value. + On output, the value actually set. + @param Parity The type of parity to use on this serial device. A Parity value of + DefaultParity will use the device's default parity value. + On output, the value actually set. + @param DataBits The number of data bits to use on the serial device. A DataBits value of 0 will use the device's default data bit setting. - On output, the value actually set. - @param StopBits The number of stop bits to use on this serial device. A StopBits - value of DefaultStopBits will use the device's default number of - stop bits. - On output, the value actually set. - - @retval RETURN_SUCCESS The new attributes were set on the serial device. - @retval RETURN_UNSUPPORTED The serial device does not support this operation. - @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value. - @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. - -**/ -RETURN_STATUS -EFIAPI -SerialPortSetAttributes ( - IN OUT UINT64 *BaudRate, - IN OUT UINT32 *ReceiveFifoDepth, - IN OUT UINT32 *Timeout, - IN OUT EFI_PARITY_TYPE *Parity, - IN OUT UINT8 *DataBits, - IN OUT EFI_STOP_BITS_TYPE *StopBits - ) -{ - UINTN SerialRegisterBase; - UINT32 SerialBaudRate; - UINTN Divisor; - UINT8 Lcr; - UINT8 LcrData; - UINT8 LcrParity; - UINT8 LcrStop; - - SerialRegisterBase = GetSerialRegisterBase (); - if (SerialRegisterBase ==0) { - return RETURN_UNSUPPORTED; - } - - // - // Check for default settings and fill in actual values. - // - if (*BaudRate == 0) { - *BaudRate = PcdGet32 (PcdSerialBaudRate); - } - SerialBaudRate = (UINT32) *BaudRate; - - if (*DataBits == 0) { - LcrData = (UINT8) (PcdGet8 (PcdSerialLineControl) & 0x3); - *DataBits = LcrData + 5; - } else { - if ((*DataBits < 5) || (*DataBits > 8)) { - return RETURN_INVALID_PARAMETER; - } - // - // Map 5..8 to 0..3 - // - LcrData = (UINT8) (*DataBits - (UINT8) 5); - } - - if (*Parity == DefaultParity) { - LcrParity = (UINT8) ((PcdGet8 (PcdSerialLineControl) >> 3) & 0x7); - switch (LcrParity) { - case 0: - *Parity = NoParity; - break; - - case 3: - *Parity = EvenParity; - break; - - case 1: - *Parity = OddParity; - break; - - case 7: - *Parity = SpaceParity; - break; - - case 5: - *Parity = MarkParity; - break; - - default: - break; - } - } else { - switch (*Parity) { - case NoParity: - LcrParity = 0; - break; - - case EvenParity: - LcrParity = 3; - break; - - case OddParity: - LcrParity = 1; - break; - - case SpaceParity: - LcrParity = 7; - break; - - case MarkParity: - LcrParity = 5; - break; - - default: - return RETURN_INVALID_PARAMETER; - } - } - - if (*StopBits == DefaultStopBits) { - LcrStop = (UINT8) ((PcdGet8 (PcdSerialLineControl) >> 2) & 0x1); - switch (LcrStop) { - case 0: - *StopBits = OneStopBit; - break; - - case 1: - if (*DataBits == 5) { - *StopBits = OneFiveStopBits; - } else { - *StopBits = TwoStopBits; - } - break; - - default: - break; - } - } else { - switch (*StopBits) { - case OneStopBit: - LcrStop = 0; - break; - - case OneFiveStopBits: - case TwoStopBits: - LcrStop = 1; - break; - - default: - return RETURN_INVALID_PARAMETER; - } - } - - // - // Calculate divisor for baud generator - // Ref_Clk_Rate / Baud_Rate / 16 - // - Divisor = PcdGet32 (PcdSerialClockRate) / (SerialBaudRate * 16); - if ((PcdGet32 (PcdSerialClockRate) % (SerialBaudRate * 16)) >= SerialBaudRate * 8) { - Divisor++; - } - - // - // Configure baud rate - // - SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, B_UART_LCR_DLAB); - SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_HIGH, (UINT8) (Divisor >> 8)); - SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_LOW, (UINT8) (Divisor & 0xff)); - - // - // Clear DLAB and configure Data Bits, Parity, and Stop Bits. - // Strip reserved bits from line control value - // - Lcr = (UINT8) ((LcrParity << 3) | (LcrStop << 2) | LcrData); - SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8) (Lcr & 0x3F)); - - return RETURN_SUCCESS; -} - + On output, the value actually set. + @param StopBits The number of stop bits to use on this serial device. A StopBits + value of DefaultStopBits will use the device's default number of + stop bits. + On output, the value actually set. + + @retval RETURN_SUCCESS The new attributes were set on the serial device. + @retval RETURN_UNSUPPORTED The serial device does not support this operation. + @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value. + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetAttributes ( + IN OUT UINT64 *BaudRate, + IN OUT UINT32 *ReceiveFifoDepth, + IN OUT UINT32 *Timeout, + IN OUT EFI_PARITY_TYPE *Parity, + IN OUT UINT8 *DataBits, + IN OUT EFI_STOP_BITS_TYPE *StopBits + ) +{ + UINTN SerialRegisterBase; + UINT32 SerialBaudRate; + UINTN Divisor; + UINT8 Lcr; + UINT8 LcrData; + UINT8 LcrParity; + UINT8 LcrStop; + + SerialRegisterBase = GetSerialRegisterBase (); + if (SerialRegisterBase ==0) { + return RETURN_UNSUPPORTED; + } + + // + // Check for default settings and fill in actual values. + // + if (*BaudRate == 0) { + *BaudRate = PcdGet32 (PcdSerialBaudRate); + } + SerialBaudRate = (UINT32) *BaudRate; + + if (*DataBits == 0) { + LcrData = (UINT8) (PcdGet8 (PcdSerialLineControl) & 0x3); + *DataBits = LcrData + 5; + } else { + if ((*DataBits < 5) || (*DataBits > 8)) { + return RETURN_INVALID_PARAMETER; + } + // + // Map 5..8 to 0..3 + // + LcrData = (UINT8) (*DataBits - (UINT8) 5); + } + + if (*Parity == DefaultParity) { + LcrParity = (UINT8) ((PcdGet8 (PcdSerialLineControl) >> 3) & 0x7); + switch (LcrParity) { + case 0: + *Parity = NoParity; + break; + + case 3: + *Parity = EvenParity; + break; + + case 1: + *Parity = OddParity; + break; + + case 7: + *Parity = SpaceParity; + break; + + case 5: + *Parity = MarkParity; + break; + + default: + break; + } + } else { + switch (*Parity) { + case NoParity: + LcrParity = 0; + break; + + case EvenParity: + LcrParity = 3; + break; + + case OddParity: + LcrParity = 1; + break; + + case SpaceParity: + LcrParity = 7; + break; + + case MarkParity: + LcrParity = 5; + break; + + default: + return RETURN_INVALID_PARAMETER; + } + } + + if (*StopBits == DefaultStopBits) { + LcrStop = (UINT8) ((PcdGet8 (PcdSerialLineControl) >> 2) & 0x1); + switch (LcrStop) { + case 0: + *StopBits = OneStopBit; + break; + + case 1: + if (*DataBits == 5) { + *StopBits = OneFiveStopBits; + } else { + *StopBits = TwoStopBits; + } + break; + + default: + break; + } + } else { + switch (*StopBits) { + case OneStopBit: + LcrStop = 0; + break; + + case OneFiveStopBits: + case TwoStopBits: + LcrStop = 1; + break; + + default: + return RETURN_INVALID_PARAMETER; + } + } + + // + // Calculate divisor for baud generator + // Ref_Clk_Rate / Baud_Rate / 16 + // + Divisor = PcdGet32 (PcdSerialClockRate) / (SerialBaudRate * 16); + if ((PcdGet32 (PcdSerialClockRate) % (SerialBaudRate * 16)) >= SerialBaudRate * 8) { + Divisor++; + } + + // + // Configure baud rate + // + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, B_UART_LCR_DLAB); + SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_HIGH, (UINT8) (Divisor >> 8)); + SerialPortWriteRegister (SerialRegisterBase, R_UART_BAUD_LOW, (UINT8) (Divisor & 0xff)); + + // + // Clear DLAB and configure Data Bits, Parity, and Stop Bits. + // Strip reserved bits from line control value + // + Lcr = (UINT8) ((LcrParity << 3) | (LcrStop << 2) | LcrData); + SerialPortWriteRegister (SerialRegisterBase, R_UART_LCR, (UINT8) (Lcr & 0x3F)); + + return RETURN_SUCCESS; +} + diff --git a/CorebootModulePkg/SataControllerDxe/SataController.h b/CorebootModulePkg/SataControllerDxe/SataController.h index 1ef4555615..d13ab889d9 100644 --- a/CorebootModulePkg/SataControllerDxe/SataController.h +++ b/CorebootModulePkg/SataControllerDxe/SataController.h @@ -1,542 +1,542 @@ -/** @file - Header file for Sata Controller driver. - - Copyright (c) 2011, 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 - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#ifndef _SATA_CONTROLLER_H_ -#define _SATA_CONTROLLER_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// -// Global Variables definitions -// -extern EFI_DRIVER_BINDING_PROTOCOL gSataControllerDriverBinding; -extern EFI_COMPONENT_NAME_PROTOCOL gSataControllerComponentName; -extern EFI_COMPONENT_NAME2_PROTOCOL gSataControllerComponentName2; - -#define AHCI_BAR_INDEX 0x05 -#define R_AHCI_CAP 0x0 -#define B_AHCI_CAP_NPS (BIT4 | BIT3 | BIT2 | BIT1 | BIT0) // Number of Ports -#define B_AHCI_CAP_SPM BIT17 // Supports Port Multiplier - -/// -/// AHCI each channel can have up to 1 device -/// -#define AHCI_MAX_DEVICES 0x01 - -/// -/// AHCI each channel can have 15 devices in the presence of a multiplier -/// -#define AHCI_MULTI_MAX_DEVICES 0x0F - -/// -/// IDE supports 2 channel max -/// -#define IDE_MAX_CHANNEL 0x02 - -/// -/// IDE supports 2 devices max -/// -#define IDE_MAX_DEVICES 0x02 - -#define SATA_ENUMER_ALL FALSE - -// -// Sata Controller driver private data structure -// - -#define SATA_CONTROLLER_SIGNATURE SIGNATURE_32('S','A','T','A') - -typedef struct _EFI_SATA_CONTROLLER_PRIVATE_DATA { - // - // Standard signature used to identify Sata Controller private data - // - UINT32 Signature; - - // - // Protocol instance of IDE_CONTROLLER_INIT produced by this driver - // - EFI_IDE_CONTROLLER_INIT_PROTOCOL IdeInit; - - // - // Copy of protocol pointers used by this driver - // - EFI_PCI_IO_PROTOCOL *PciIo; - - // - // The number of devices that are supported by this channel - // - UINT8 DeviceCount; - - // +/** @file + Header file for Sata Controller driver. + + Copyright (c) 2011, 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 + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SATA_CONTROLLER_H_ +#define _SATA_CONTROLLER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Global Variables definitions +// +extern EFI_DRIVER_BINDING_PROTOCOL gSataControllerDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gSataControllerComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gSataControllerComponentName2; + +#define AHCI_BAR_INDEX 0x05 +#define R_AHCI_CAP 0x0 +#define B_AHCI_CAP_NPS (BIT4 | BIT3 | BIT2 | BIT1 | BIT0) // Number of Ports +#define B_AHCI_CAP_SPM BIT17 // Supports Port Multiplier + +/// +/// AHCI each channel can have up to 1 device +/// +#define AHCI_MAX_DEVICES 0x01 + +/// +/// AHCI each channel can have 15 devices in the presence of a multiplier +/// +#define AHCI_MULTI_MAX_DEVICES 0x0F + +/// +/// IDE supports 2 channel max +/// +#define IDE_MAX_CHANNEL 0x02 + +/// +/// IDE supports 2 devices max +/// +#define IDE_MAX_DEVICES 0x02 + +#define SATA_ENUMER_ALL FALSE + +// +// Sata Controller driver private data structure +// + +#define SATA_CONTROLLER_SIGNATURE SIGNATURE_32('S','A','T','A') + +typedef struct _EFI_SATA_CONTROLLER_PRIVATE_DATA { + // + // Standard signature used to identify Sata Controller private data + // + UINT32 Signature; + + // + // Protocol instance of IDE_CONTROLLER_INIT produced by this driver + // + EFI_IDE_CONTROLLER_INIT_PROTOCOL IdeInit; + + // + // Copy of protocol pointers used by this driver + // + EFI_PCI_IO_PROTOCOL *PciIo; + + // + // The number of devices that are supported by this channel + // + UINT8 DeviceCount; + + // // The highest disqualified mode for each attached device, - // From ATA/ATAPI spec, if a mode is not supported, - // the modes higher than it is also not supported - // - EFI_ATA_COLLECTIVE_MODE *DisqualifiedModes; - - // - // A copy of EFI_IDENTIFY_DATA data for each attached SATA device and its flag - // - EFI_IDENTIFY_DATA *IdentifyData; - BOOLEAN *IdentifyValid; -} EFI_SATA_CONTROLLER_PRIVATE_DATA; - -#define SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS(a) CR(a, EFI_SATA_CONTROLLER_PRIVATE_DATA, IdeInit, SATA_CONTROLLER_SIGNATURE) - -// -// Driver binding functions declaration -// -/** - Supported function of Driver Binding protocol for this driver. - Test to see if this driver supports ControllerHandle. - - @param This Protocol instance pointer. - @param Controller Handle of device to test. - @param RemainingDevicePath A pointer to the device path. Should be ignored by - device driver. - - @retval EFI_SUCCESS This driver supports this device. - @retval EFI_ALREADY_STARTED This driver is already running on this device. - @retval other This driver does not support this device. - -**/ -EFI_STATUS -EFIAPI -SataControllerSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -; - -/** - This routine is called right after the .Supported() called and - Start this driver on ControllerHandle. - - @param This Protocol instance pointer. - @param Controller Handle of device to bind driver to. - @param RemainingDevicePath A pointer to the device path. Should be ignored by - device driver. - - @retval EFI_SUCCESS This driver is added to this device. - @retval EFI_ALREADY_STARTED This driver is already running on this device. - @retval other Some error occurs when binding this driver to this device. - -**/ -EFI_STATUS -EFIAPI -SataControllerStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -; - -/** - Stop this driver on ControllerHandle. - - @param This Protocol instance pointer. - @param Controller Handle of device to stop driver on. - @param NumberOfChildren Not used. - @param ChildHandleBuffer Not used. - - @retval EFI_SUCCESS This driver is removed from this device. - @retval other Some error occurs when removing this driver from this device. - -**/ -EFI_STATUS -EFIAPI -SataControllerStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ) -; - -// -// IDE controller init functions declaration -// -/** - Returns the information about the specified IDE channel. - - This function can be used to obtain information about a particular IDE channel. - The driver entity uses this information during the enumeration process. - - If Enabled is set to FALSE, the driver entity will not scan the channel. Note - that it will not prevent an operating system driver from scanning the channel. - - For most of today's controllers, MaxDevices will either be 1 or 2. For SATA - controllers, this value will always be 1. SATA configurations can contain SATA - port multipliers. SATA port multipliers behave like SATA bridges and can support - up to 16 devices on the other side. If a SATA port out of the IDE controller - is connected to a port multiplier, MaxDevices will be set to the number of SATA - devices that the port multiplier supports. Because today's port multipliers - support up to fifteen SATA devices, this number can be as large as fifteen. The IDE - bus driver is required to scan for the presence of port multipliers behind an SATA - controller and enumerate up to MaxDevices number of devices behind the port - multiplier. - - In this context, the devices behind a port multiplier constitute a channel. - - @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. - @param[in] Channel Zero-based channel number. - @param[out] Enabled TRUE if this channel is enabled. Disabled channels - are not scanned to see if any devices are present. - @param[out] MaxDevices The maximum number of IDE devices that the bus driver - can expect on this channel. For the ATA/ATAPI - specification, version 6, this number will either be - one or two. For Serial ATA (SATA) configurations with a - port multiplier, this number can be as large as fifteen. - - @retval EFI_SUCCESS Information was returned without any errors. - @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). - -**/ -EFI_STATUS -EFIAPI -IdeInitGetChannelInfo ( - IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, - IN UINT8 Channel, - OUT BOOLEAN *Enabled, - OUT UINT8 *MaxDevices - ) -; - -/** - The notifications from the driver entity that it is about to enter a certain - phase of the IDE channel enumeration process. - - This function can be used to notify the IDE controller driver to perform - specific actions, including any chipset-specific initialization, so that the - chipset is ready to enter the next phase. Seven notification points are defined - at this time. - - More synchronization points may be added as required in the future. - - @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. - @param[in] Phase The phase during enumeration. - @param[in] Channel Zero-based channel number. - - @retval EFI_SUCCESS The notification was accepted without any errors. - @retval EFI_UNSUPPORTED Phase is not supported. - @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). - @retval EFI_NOT_READY This phase cannot be entered at this time; for - example, an attempt was made to enter a Phase - without having entered one or more previous - Phase. - -**/ -EFI_STATUS -EFIAPI -IdeInitNotifyPhase ( - IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, - IN EFI_IDE_CONTROLLER_ENUM_PHASE Phase, - IN UINT8 Channel - ) -; - -/** - Submits the device information to the IDE controller driver. - - This function is used by the driver entity to pass detailed information about - a particular device to the IDE controller driver. The driver entity obtains - this information by issuing an ATA or ATAPI IDENTIFY_DEVICE command. IdentifyData - is the pointer to the response data buffer. The IdentifyData buffer is owned - by the driver entity, and the IDE controller driver must make a local copy - of the entire buffer or parts of the buffer as needed. The original IdentifyData - buffer pointer may not be valid when - - - EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() or - - EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() is called at a later point. - - The IDE controller driver may consult various fields of EFI_IDENTIFY_DATA to - compute the optimum mode for the device. These fields are not limited to the - timing information. For example, an implementation of the IDE controller driver - may examine the vendor and type/mode field to match known bad drives. - - The driver entity may submit drive information in any order, as long as it - submits information for all the devices belonging to the enumeration group - before EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() is called for any device - in that enumeration group. If a device is absent, EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() - should be called with IdentifyData set to NULL. The IDE controller driver may - not have any other mechanism to know whether a device is present or not. Therefore, - setting IdentifyData to NULL does not constitute an error condition. - EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() can be called only once for a - given (Channel, Device) pair. - - @param[in] This A pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. - @param[in] Channel Zero-based channel number. - @param[in] Device Zero-based device number on the Channel. - @param[in] IdentifyData The device's response to the ATA IDENTIFY_DEVICE command. - - @retval EFI_SUCCESS The information was accepted without any errors. - @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). - @retval EFI_INVALID_PARAMETER Device is invalid. - -**/ -EFI_STATUS -EFIAPI -IdeInitSubmitData ( - IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, - IN UINT8 Channel, - IN UINT8 Device, - IN EFI_IDENTIFY_DATA *IdentifyData - ) -; - -/** - Disqualifies specific modes for an IDE device. - - This function allows the driver entity or other drivers (such as platform - drivers) to reject certain timing modes and request the IDE controller driver - to recalculate modes. This function allows the driver entity and the IDE - controller driver to negotiate the timings on a per-device basis. This function - is useful in the case of drives that lie about their capabilities. An example - is when the IDE device fails to accept the timing modes that are calculated - by the IDE controller driver based on the response to the Identify Drive command. - - If the driver entity does not want to limit the ATA timing modes and leave that - decision to the IDE controller driver, it can either not call this function for - the given device or call this function and set the Valid flag to FALSE for all - modes that are listed in EFI_ATA_COLLECTIVE_MODE. - - The driver entity may disqualify modes for a device in any order and any number - of times. - - This function can be called multiple times to invalidate multiple modes of the - same type (e.g., Programmed Input/Output [PIO] modes 3 and 4). See the ATA/ATAPI - specification for more information on PIO modes. - - For Serial ATA (SATA) controllers, this member function can be used to disqualify - a higher transfer rate mode on a given channel. For example, a platform driver - may inform the IDE controller driver to not use second-generation (Gen2) speeds - for a certain SATA drive. - - @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. - @param[in] Channel The zero-based channel number. - @param[in] Device The zero-based device number on the Channel. - @param[in] BadModes The modes that the device does not support and that - should be disqualified. - - @retval EFI_SUCCESS The modes were accepted without any errors. - @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). - @retval EFI_INVALID_PARAMETER Device is invalid. - @retval EFI_INVALID_PARAMETER IdentifyData is NULL. - -**/ -EFI_STATUS -EFIAPI -IdeInitDisqualifyMode ( - IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, - IN UINT8 Channel, - IN UINT8 Device, - IN EFI_ATA_COLLECTIVE_MODE *BadModes - ) -; - -/** - Returns the information about the optimum modes for the specified IDE device. - - This function is used by the driver entity to obtain the optimum ATA modes for - a specific device. The IDE controller driver takes into account the following - while calculating the mode: - - The IdentifyData inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() - - The BadModes inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() - - The driver entity is required to call EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() - for all the devices that belong to an enumeration group before calling - EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() for any device in the same group. - - The IDE controller driver will use controller- and possibly platform-specific - algorithms to arrive at SupportedModes. The IDE controller may base its - decision on user preferences and other considerations as well. This function - may be called multiple times because the driver entity may renegotiate the mode - with the IDE controller driver using EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode(). - - The driver entity may collect timing information for various devices in any - order. The driver entity is responsible for making sure that all the dependencies - are satisfied. For example, the SupportedModes information for device A that - was previously returned may become stale after a call to - EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() for device B. - - The buffer SupportedModes is allocated by the callee because the caller does - not necessarily know the size of the buffer. The type EFI_ATA_COLLECTIVE_MODE - is defined in a way that allows for future extensibility and can be of variable - length. This memory pool should be deallocated by the caller when it is no - longer necessary. - - The IDE controller driver for a Serial ATA (SATA) controller can use this - member function to force a lower speed (first-generation [Gen1] speeds on a - second-generation [Gen2]-capable hardware). The IDE controller driver can - also allow the driver entity to stay with the speed that has been negotiated - by the physical layer. - - @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. - @param[in] Channel A zero-based channel number. - @param[in] Device A zero-based device number on the Channel. - @param[out] SupportedModes The optimum modes for the device. - - @retval EFI_SUCCESS SupportedModes was returned. - @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). - @retval EFI_INVALID_PARAMETER Device is invalid. - @retval EFI_INVALID_PARAMETER SupportedModes is NULL. - @retval EFI_NOT_READY Modes cannot be calculated due to a lack of - data. This error may happen if - EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() - and EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyData() - were not called for at least one drive in the - same enumeration group. - -**/ -EFI_STATUS -EFIAPI -IdeInitCalculateMode ( - IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, - IN UINT8 Channel, - IN UINT8 Device, - OUT EFI_ATA_COLLECTIVE_MODE **SupportedModes - ) -; - -/** - Commands the IDE controller driver to program the IDE controller hardware - so that the specified device can operate at the specified mode. - - This function is used by the driver entity to instruct the IDE controller - driver to program the IDE controller hardware to the specified modes. This - function can be called only once for a particular device. For a Serial ATA - (SATA) Advanced Host Controller Interface (AHCI) controller, no controller- - specific programming may be required. - - @param[in] This Pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. - @param[in] Channel Zero-based channel number. - @param[in] Device Zero-based device number on the Channel. - @param[in] Modes The modes to set. - - @retval EFI_SUCCESS The command was accepted without any errors. - @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). - @retval EFI_INVALID_PARAMETER Device is invalid. - @retval EFI_NOT_READY Modes cannot be set at this time due to lack of data. - @retval EFI_DEVICE_ERROR Modes cannot be set due to hardware failure. - The driver entity should not use this device. - -**/ -EFI_STATUS -EFIAPI -IdeInitSetTiming ( - IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, - IN UINT8 Channel, - IN UINT8 Device, - IN EFI_ATA_COLLECTIVE_MODE *Modes - ) -; - -// -// Forward reference declaration -// -/** - Retrieves a Unicode string that is the user readable name of the UEFI Driver. - - @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. - @param Language A pointer to a three character ISO 639-2 language identifier. - This is the language of the driver name that that the caller - is requesting, 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 DriverName A pointer to the Unicode string to return. This Unicode string - is the name of the driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by This - and the language specified by Language was returned - in DriverName. - @retval EFI_INVALID_PARAMETER Language is NULL. - @retval EFI_INVALID_PARAMETER DriverName is NULL. - @retval EFI_UNSUPPORTED The driver specified by This does not support the - language specified by Language. -**/ -EFI_STATUS -EFIAPI -SataControllerComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ) -; - -/** - Retrieves a Unicode string that is the user readable name of the controller - that is being managed by an UEFI Driver. - - @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. - @param ControllerHandle The handle of a controller that the driver specified by - This is managing. This handle specifies the controller - whose name is to be returned. - @param OPTIONAL ChildHandle The handle of the child controller to retrieve the name - of. 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 retrieve the name of the - bus controller. It will not be NULL for a bus driver - that wishes to retrieve the name of a child controller. - @param Language A pointer to a three character ISO 639-2 language - identifier. This is the language of the controller name - that that the caller is requesting, 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 ControllerName A pointer to the Unicode string to return. This Unicode - string is the name of the controller specified by - ControllerHandle and ChildHandle in the language - specified by Language from the point of view of the - driver specified by This. - - @retval EFI_SUCCESS The Unicode string for the user readable name in the - language specified by Language for the driver - specified by This was returned in DriverName. - @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 ControllerName is NULL. - @retval EFI_UNSUPPORTED The driver specified by This is not currently - managing the controller specified by - ControllerHandle and ChildHandle. - @retval EFI_UNSUPPORTED The driver specified by This does not support the - language specified by Language. -**/ -EFI_STATUS -EFIAPI -SataControllerComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ) -; - -#endif + // From ATA/ATAPI spec, if a mode is not supported, + // the modes higher than it is also not supported + // + EFI_ATA_COLLECTIVE_MODE *DisqualifiedModes; + + // + // A copy of EFI_IDENTIFY_DATA data for each attached SATA device and its flag + // + EFI_IDENTIFY_DATA *IdentifyData; + BOOLEAN *IdentifyValid; +} EFI_SATA_CONTROLLER_PRIVATE_DATA; + +#define SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS(a) CR(a, EFI_SATA_CONTROLLER_PRIVATE_DATA, IdeInit, SATA_CONTROLLER_SIGNATURE) + +// +// Driver binding functions declaration +// +/** + Supported function of Driver Binding protocol for this driver. + Test to see if this driver supports ControllerHandle. + + @param This Protocol instance pointer. + @param Controller Handle of device to test. + @param RemainingDevicePath A pointer to the device path. Should be ignored by + device driver. + + @retval EFI_SUCCESS This driver supports this device. + @retval EFI_ALREADY_STARTED This driver is already running on this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +SataControllerSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + +/** + This routine is called right after the .Supported() called and + Start this driver on ControllerHandle. + + @param This Protocol instance pointer. + @param Controller Handle of device to bind driver to. + @param RemainingDevicePath A pointer to the device path. Should be ignored by + device driver. + + @retval EFI_SUCCESS This driver is added to this device. + @retval EFI_ALREADY_STARTED This driver is already running on this device. + @retval other Some error occurs when binding this driver to this device. + +**/ +EFI_STATUS +EFIAPI +SataControllerStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + +/** + Stop this driver on ControllerHandle. + + @param This Protocol instance pointer. + @param Controller Handle of device to stop driver on. + @param NumberOfChildren Not used. + @param ChildHandleBuffer Not used. + + @retval EFI_SUCCESS This driver is removed from this device. + @retval other Some error occurs when removing this driver from this device. + +**/ +EFI_STATUS +EFIAPI +SataControllerStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +; + +// +// IDE controller init functions declaration +// +/** + Returns the information about the specified IDE channel. + + This function can be used to obtain information about a particular IDE channel. + The driver entity uses this information during the enumeration process. + + If Enabled is set to FALSE, the driver entity will not scan the channel. Note + that it will not prevent an operating system driver from scanning the channel. + + For most of today's controllers, MaxDevices will either be 1 or 2. For SATA + controllers, this value will always be 1. SATA configurations can contain SATA + port multipliers. SATA port multipliers behave like SATA bridges and can support + up to 16 devices on the other side. If a SATA port out of the IDE controller + is connected to a port multiplier, MaxDevices will be set to the number of SATA + devices that the port multiplier supports. Because today's port multipliers + support up to fifteen SATA devices, this number can be as large as fifteen. The IDE + bus driver is required to scan for the presence of port multipliers behind an SATA + controller and enumerate up to MaxDevices number of devices behind the port + multiplier. + + In this context, the devices behind a port multiplier constitute a channel. + + @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. + @param[in] Channel Zero-based channel number. + @param[out] Enabled TRUE if this channel is enabled. Disabled channels + are not scanned to see if any devices are present. + @param[out] MaxDevices The maximum number of IDE devices that the bus driver + can expect on this channel. For the ATA/ATAPI + specification, version 6, this number will either be + one or two. For Serial ATA (SATA) configurations with a + port multiplier, this number can be as large as fifteen. + + @retval EFI_SUCCESS Information was returned without any errors. + @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). + +**/ +EFI_STATUS +EFIAPI +IdeInitGetChannelInfo ( + IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, + IN UINT8 Channel, + OUT BOOLEAN *Enabled, + OUT UINT8 *MaxDevices + ) +; + +/** + The notifications from the driver entity that it is about to enter a certain + phase of the IDE channel enumeration process. + + This function can be used to notify the IDE controller driver to perform + specific actions, including any chipset-specific initialization, so that the + chipset is ready to enter the next phase. Seven notification points are defined + at this time. + + More synchronization points may be added as required in the future. + + @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. + @param[in] Phase The phase during enumeration. + @param[in] Channel Zero-based channel number. + + @retval EFI_SUCCESS The notification was accepted without any errors. + @retval EFI_UNSUPPORTED Phase is not supported. + @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). + @retval EFI_NOT_READY This phase cannot be entered at this time; for + example, an attempt was made to enter a Phase + without having entered one or more previous + Phase. + +**/ +EFI_STATUS +EFIAPI +IdeInitNotifyPhase ( + IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, + IN EFI_IDE_CONTROLLER_ENUM_PHASE Phase, + IN UINT8 Channel + ) +; + +/** + Submits the device information to the IDE controller driver. + + This function is used by the driver entity to pass detailed information about + a particular device to the IDE controller driver. The driver entity obtains + this information by issuing an ATA or ATAPI IDENTIFY_DEVICE command. IdentifyData + is the pointer to the response data buffer. The IdentifyData buffer is owned + by the driver entity, and the IDE controller driver must make a local copy + of the entire buffer or parts of the buffer as needed. The original IdentifyData + buffer pointer may not be valid when + + - EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() or + - EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() is called at a later point. + + The IDE controller driver may consult various fields of EFI_IDENTIFY_DATA to + compute the optimum mode for the device. These fields are not limited to the + timing information. For example, an implementation of the IDE controller driver + may examine the vendor and type/mode field to match known bad drives. + + The driver entity may submit drive information in any order, as long as it + submits information for all the devices belonging to the enumeration group + before EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() is called for any device + in that enumeration group. If a device is absent, EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() + should be called with IdentifyData set to NULL. The IDE controller driver may + not have any other mechanism to know whether a device is present or not. Therefore, + setting IdentifyData to NULL does not constitute an error condition. + EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() can be called only once for a + given (Channel, Device) pair. + + @param[in] This A pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. + @param[in] Channel Zero-based channel number. + @param[in] Device Zero-based device number on the Channel. + @param[in] IdentifyData The device's response to the ATA IDENTIFY_DEVICE command. + + @retval EFI_SUCCESS The information was accepted without any errors. + @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). + @retval EFI_INVALID_PARAMETER Device is invalid. + +**/ +EFI_STATUS +EFIAPI +IdeInitSubmitData ( + IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, + IN UINT8 Channel, + IN UINT8 Device, + IN EFI_IDENTIFY_DATA *IdentifyData + ) +; + +/** + Disqualifies specific modes for an IDE device. + + This function allows the driver entity or other drivers (such as platform + drivers) to reject certain timing modes and request the IDE controller driver + to recalculate modes. This function allows the driver entity and the IDE + controller driver to negotiate the timings on a per-device basis. This function + is useful in the case of drives that lie about their capabilities. An example + is when the IDE device fails to accept the timing modes that are calculated + by the IDE controller driver based on the response to the Identify Drive command. + + If the driver entity does not want to limit the ATA timing modes and leave that + decision to the IDE controller driver, it can either not call this function for + the given device or call this function and set the Valid flag to FALSE for all + modes that are listed in EFI_ATA_COLLECTIVE_MODE. + + The driver entity may disqualify modes for a device in any order and any number + of times. + + This function can be called multiple times to invalidate multiple modes of the + same type (e.g., Programmed Input/Output [PIO] modes 3 and 4). See the ATA/ATAPI + specification for more information on PIO modes. + + For Serial ATA (SATA) controllers, this member function can be used to disqualify + a higher transfer rate mode on a given channel. For example, a platform driver + may inform the IDE controller driver to not use second-generation (Gen2) speeds + for a certain SATA drive. + + @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. + @param[in] Channel The zero-based channel number. + @param[in] Device The zero-based device number on the Channel. + @param[in] BadModes The modes that the device does not support and that + should be disqualified. + + @retval EFI_SUCCESS The modes were accepted without any errors. + @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). + @retval EFI_INVALID_PARAMETER Device is invalid. + @retval EFI_INVALID_PARAMETER IdentifyData is NULL. + +**/ +EFI_STATUS +EFIAPI +IdeInitDisqualifyMode ( + IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, + IN UINT8 Channel, + IN UINT8 Device, + IN EFI_ATA_COLLECTIVE_MODE *BadModes + ) +; + +/** + Returns the information about the optimum modes for the specified IDE device. + + This function is used by the driver entity to obtain the optimum ATA modes for + a specific device. The IDE controller driver takes into account the following + while calculating the mode: + - The IdentifyData inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() + - The BadModes inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() + + The driver entity is required to call EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() + for all the devices that belong to an enumeration group before calling + EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() for any device in the same group. + + The IDE controller driver will use controller- and possibly platform-specific + algorithms to arrive at SupportedModes. The IDE controller may base its + decision on user preferences and other considerations as well. This function + may be called multiple times because the driver entity may renegotiate the mode + with the IDE controller driver using EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode(). + + The driver entity may collect timing information for various devices in any + order. The driver entity is responsible for making sure that all the dependencies + are satisfied. For example, the SupportedModes information for device A that + was previously returned may become stale after a call to + EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() for device B. + + The buffer SupportedModes is allocated by the callee because the caller does + not necessarily know the size of the buffer. The type EFI_ATA_COLLECTIVE_MODE + is defined in a way that allows for future extensibility and can be of variable + length. This memory pool should be deallocated by the caller when it is no + longer necessary. + + The IDE controller driver for a Serial ATA (SATA) controller can use this + member function to force a lower speed (first-generation [Gen1] speeds on a + second-generation [Gen2]-capable hardware). The IDE controller driver can + also allow the driver entity to stay with the speed that has been negotiated + by the physical layer. + + @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. + @param[in] Channel A zero-based channel number. + @param[in] Device A zero-based device number on the Channel. + @param[out] SupportedModes The optimum modes for the device. + + @retval EFI_SUCCESS SupportedModes was returned. + @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). + @retval EFI_INVALID_PARAMETER Device is invalid. + @retval EFI_INVALID_PARAMETER SupportedModes is NULL. + @retval EFI_NOT_READY Modes cannot be calculated due to a lack of + data. This error may happen if + EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() + and EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyData() + were not called for at least one drive in the + same enumeration group. + +**/ +EFI_STATUS +EFIAPI +IdeInitCalculateMode ( + IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, + IN UINT8 Channel, + IN UINT8 Device, + OUT EFI_ATA_COLLECTIVE_MODE **SupportedModes + ) +; + +/** + Commands the IDE controller driver to program the IDE controller hardware + so that the specified device can operate at the specified mode. + + This function is used by the driver entity to instruct the IDE controller + driver to program the IDE controller hardware to the specified modes. This + function can be called only once for a particular device. For a Serial ATA + (SATA) Advanced Host Controller Interface (AHCI) controller, no controller- + specific programming may be required. + + @param[in] This Pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. + @param[in] Channel Zero-based channel number. + @param[in] Device Zero-based device number on the Channel. + @param[in] Modes The modes to set. + + @retval EFI_SUCCESS The command was accepted without any errors. + @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). + @retval EFI_INVALID_PARAMETER Device is invalid. + @retval EFI_NOT_READY Modes cannot be set at this time due to lack of data. + @retval EFI_DEVICE_ERROR Modes cannot be set due to hardware failure. + The driver entity should not use this device. + +**/ +EFI_STATUS +EFIAPI +IdeInitSetTiming ( + IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, + IN UINT8 Channel, + IN UINT8 Device, + IN EFI_ATA_COLLECTIVE_MODE *Modes + ) +; + +// +// Forward reference declaration +// +/** + Retrieves a Unicode string that is the user readable name of the UEFI Driver. + + @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param Language A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, 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 DriverName A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER DriverName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. +**/ +EFI_STATUS +EFIAPI +SataControllerComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +; + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an UEFI Driver. + + @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param ControllerHandle The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + @param OPTIONAL ChildHandle The handle of the child controller to retrieve the name + of. 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 retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + @param Language A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, 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 ControllerName A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + @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 ControllerName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. +**/ +EFI_STATUS +EFIAPI +SataControllerComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +; + +#endif diff --git a/CorebootModulePkg/SecCore/Ia32/Stack.S b/CorebootModulePkg/SecCore/Ia32/Stack.S index 6a8e0e4b15..1900a8c54a 100644 --- a/CorebootModulePkg/SecCore/Ia32/Stack.S +++ b/CorebootModulePkg/SecCore/Ia32/Stack.S @@ -1,78 +1,78 @@ -#------------------------------------------------------------------------------ -# -# Copyright (c) 2013, 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 -# which accompanies this distribution. The full text of the license may be found at -# http://opensource.org/licenses/bsd-license.php. -# -# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -# -# Abstract: -# +#------------------------------------------------------------------------------ +# +# Copyright (c) 2013, 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 +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Abstract: +# # Switch the stack from temporary memory to permanent memory. -# -#------------------------------------------------------------------------------ - - -#------------------------------------------------------------------------------ -# VOID -# EFIAPI -# SecSwitchStack ( -# UINT32 TemporaryMemoryBase, -# UINT32 PermenentMemoryBase -# )# -#------------------------------------------------------------------------------ -ASM_GLOBAL ASM_PFX (SecSwitchStack) -ASM_PFX(SecSwitchStack): - # - # Save standard registers so they can be used to change stack - # - pushl %eax - pushl %ebx - pushl %ecx - pushl %edx - - # - # !!CAUTION!! this function address's is pushed into stack after +# +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# SecSwitchStack ( +# UINT32 TemporaryMemoryBase, +# UINT32 PermenentMemoryBase +# )# +#------------------------------------------------------------------------------ +ASM_GLOBAL ASM_PFX (SecSwitchStack) +ASM_PFX(SecSwitchStack): + # + # Save standard registers so they can be used to change stack + # + pushl %eax + pushl %ebx + pushl %ecx + pushl %edx + + # + # !!CAUTION!! this function address's is pushed into stack after # migration of whole temporary memory, so need save it to permanent - # memory at first! - # - movl 20(%esp), %ebx # Save the first parameter - movl 24(%esp), %ecx # Save the second parameter - - # + # memory at first! + # + movl 20(%esp), %ebx # Save the first parameter + movl 24(%esp), %ecx # Save the second parameter + + # # Save this function's return address into permanent memory at first. # Then, Fixup the esp point to permanent memory - # - movl %esp, %eax - subl %ebx, %eax - addl %ecx, %eax + # + movl %esp, %eax + subl %ebx, %eax + addl %ecx, %eax movl 0(%esp), %edx # copy pushed register's value to permanent memory - movl %edx, 0(%eax) - movl 4(%esp), %edx - movl %edx, 4(%eax) - movl 8(%esp), %edx - movl %edx, 8(%eax) - movl 12(%esp), %edx - movl %edx, 12(%eax) + movl %edx, 0(%eax) + movl 4(%esp), %edx + movl %edx, 4(%eax) + movl 8(%esp), %edx + movl %edx, 8(%eax) + movl 12(%esp), %edx + movl %edx, 12(%eax) movl 16(%esp), %edx # Update this function's return address into permanent memory - movl %edx, 16(%eax) + movl %edx, 16(%eax) movl %eax, %esp # From now, esp is pointed to permanent memory - - # + + # # Fixup the ebp point to permanent memory - # - movl %ebp, %eax - subl %ebx, %eax - addl %ecx, %eax + # + movl %ebp, %eax + subl %ebx, %eax + addl %ecx, %eax movl %eax, %ebp # From now, ebp is pointed to permanent memory - - popl %edx - popl %ecx - popl %ebx - popl %eax - ret - - + + popl %edx + popl %ecx + popl %ebx + popl %eax + ret + + -- 2.19.1.windows.1