From f5752cb24c2a53281c9459a629f1c15c3f40d1c6 Mon Sep 17 00:00:00 2001 From: klu2 Date: Mon, 5 May 2008 07:21:29 +0000 Subject: [PATCH] Add DuetTimerLib and DuetSerialIo library instance. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@5162 6f19259b-4bc3-4df7-8a09-765794883524 --- DuetPkg/DuetPkg.dsc | 3 +- .../DuetSerialIoLib/DuetSerialIoLib.inf | 36 +++ .../Library/DuetSerialIoLib/SerialPortLib.c | 160 +++++++++++ DuetPkg/Library/DuetTimerLib/DuetTimerLib.inf | 68 +++++ DuetPkg/Library/DuetTimerLib/x86TimerLib.c | 252 ++++++++++++++++++ 5 files changed, 517 insertions(+), 2 deletions(-) create mode 100644 DuetPkg/Library/DuetSerialIoLib/DuetSerialIoLib.inf create mode 100644 DuetPkg/Library/DuetSerialIoLib/SerialPortLib.c create mode 100644 DuetPkg/Library/DuetTimerLib/DuetTimerLib.inf create mode 100644 DuetPkg/Library/DuetTimerLib/x86TimerLib.c diff --git a/DuetPkg/DuetPkg.dsc b/DuetPkg/DuetPkg.dsc index 6b7916fc2d..76ca7a50da 100644 --- a/DuetPkg/DuetPkg.dsc +++ b/DuetPkg/DuetPkg.dsc @@ -48,7 +48,7 @@ OemHookStatusCodeLib|IntelFrameworkModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf - TimerLib|MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf + TimerLib|DuetPkg/Library/DuetTimerLib/DuetTimerLib.inf [LibraryClasses.common.DXE_DRIVER] MemoryAllocationLib|MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.inf @@ -79,7 +79,6 @@ ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf SerialPortLib|DuetPkg/Library/DuetSerialIoLib/DuetSerialIoLib.inf IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf - #TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf DebugLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf [LibraryClasses.common.UEFI_DRIVER] diff --git a/DuetPkg/Library/DuetSerialIoLib/DuetSerialIoLib.inf b/DuetPkg/Library/DuetSerialIoLib/DuetSerialIoLib.inf new file mode 100644 index 0000000000..07a7ee9fa2 --- /dev/null +++ b/DuetPkg/Library/DuetSerialIoLib/DuetSerialIoLib.inf @@ -0,0 +1,36 @@ +#/**@file +# This library instance produce SerialIo library class for DUET platform. +# +# Copyright (c) 2006 - 2007, 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. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DuetSerialPortLib + FILE_GUID = 1B25AF84-1EA8-4b52-894E-BFA6880B97FF + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = SerialPortLib + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x0002000A + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + SerialPortLib + IoLib + +[Sources.common] + SerialPortLib.c + + diff --git a/DuetPkg/Library/DuetSerialIoLib/SerialPortLib.c b/DuetPkg/Library/DuetSerialIoLib/SerialPortLib.c new file mode 100644 index 0000000000..518172ae50 --- /dev/null +++ b/DuetPkg/Library/DuetSerialIoLib/SerialPortLib.c @@ -0,0 +1,160 @@ +/** @file + Serial I/O Port library functions with no library constructor/destructor + + Copyright (c) 2006, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + 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 + +//--------------------------------------------- +// UART Register Offsets +//--------------------------------------------- +#define BAUD_LOW_OFFSET 0x00 +#define BAUD_HIGH_OFFSET 0x01 +#define IER_OFFSET 0x01 +#define LCR_SHADOW_OFFSET 0x01 +#define FCR_SHADOW_OFFSET 0x02 +#define IR_CONTROL_OFFSET 0x02 +#define FCR_OFFSET 0x02 +#define EIR_OFFSET 0x02 +#define BSR_OFFSET 0x03 +#define LCR_OFFSET 0x03 +#define MCR_OFFSET 0x04 +#define LSR_OFFSET 0x05 +#define MSR_OFFSET 0x06 + +//--------------------------------------------- +// UART Register Bit Defines +//--------------------------------------------- +#define LSR_TXRDY 0x20 +#define LSR_RXDA 0x01 +#define DLAB 0x01 + +UINT16 gComBase = 0x3f8; +UINTN gBps = 115200; +UINT8 gData = 8; +UINT8 gStop = 1; +UINT8 gParity = 0; +UINT8 gBreakSet = 0; +/* + + Programmed hardware of Serial port. + + @return Always return EFI_UNSUPPORTED. + +**/ +RETURN_STATUS +EFIAPI +SerialPortInitialize ( + VOID + ) +{ + UINTN Divisor; + UINT8 OutputData; + UINT8 Data; + + // + // Map 5..8 to 0..3 + // + Data = (UINT8) (gData - (UINT8)5); + + // + // Calculate divisor for baud generator + // + Divisor = 115200 / gBps; + + // + // Set communications format + // + OutputData = (UINT8)((DLAB << 7) | ((gBreakSet << 6) | ((gParity << 3) | ((gStop << 2) | Data)))); + IoWrite8 (gComBase + LCR_OFFSET, OutputData); + + // + // Configure baud rate + // + IoWrite8 (gComBase + BAUD_HIGH_OFFSET, (UINT8)(Divisor >> 8)); + IoWrite8 (gComBase + BAUD_LOW_OFFSET, (UINT8)(Divisor & 0xff)); + + // + // Switch back to bank 0 + // + OutputData = (UINT8)((~DLAB<<7)|((gBreakSet<<6)|((gParity<<3)|((gStop<<2)| Data)))); + IoWrite8 (gComBase + LCR_OFFSET, OutputData); + + return RETURN_SUCCESS; +} + +/** + Write data to serial device. + + @param Buffer Point of data buffer which need to be writed. + @param NumberOfBytes Number of output bytes which are cached in Buffer. + + @retval 0 Write data failed. + @retval !0 Actual number of bytes writed to serial device. + +**/ +UINTN +EFIAPI +SerialPortWrite ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + UINTN Result; + UINT8 Data; + + if (NULL == Buffer) { + return 0; + } + + Result = NumberOfBytes; + + while (NumberOfBytes--) { + // + // Wait for the serail port to be ready. + // + do { + Data = IoRead8 (gComBase + LSR_OFFSET); + } while ((Data & LSR_TXRDY) == 0); + + IoWrite8 (gComBase, *Buffer++); + } + + return Result; + +} + + +/** + Read data from serial device and save the datas in buffer. + + @param Buffer Point of data buffer which need to be writed. + @param NumberOfBytes Number of output bytes which are cached in Buffer. + + @retval 0 Read data failed. + @retval !0 Aactual number of bytes read from serial device. + +**/ +UINTN +EFIAPI +SerialPortRead ( + OUT UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + return 0; +} + diff --git a/DuetPkg/Library/DuetTimerLib/DuetTimerLib.inf b/DuetPkg/Library/DuetTimerLib/DuetTimerLib.inf new file mode 100644 index 0000000000..f03c6bd10a --- /dev/null +++ b/DuetPkg/Library/DuetTimerLib/DuetTimerLib.inf @@ -0,0 +1,68 @@ +#/** @file +# Timer Library implementation for Boot Timer moudles that require timer services. +# +# Timer Library that uses CPU resources to provide calibrated +# delays on IA-32 and x64, and uses ITC on IPF. Note: Because CpuLocalApci +# and ITC could be programmed by OS, it cannot be used by SMM drivers +# and runtime drivers, ACPI timer is recommended for SMM drivers and RUNTIME +# drivers. +# Copyright (c) 2007, 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. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DuetTimerLib + FILE_GUID = 5F9A01F5-726E-4f59-809D-887F4766734E + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00020000 + + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.Ia32] + x86TimerLib.c + +[Sources.X64] + x86TimerLib.c + + +[Packages] + MdePkg/MdePkg.dec + + +[LibraryClasses] + BaseLib + +[LibraryClasses.IA32] + PcdLib + IoLib + +[LibraryClasses.X64] + PcdLib + IoLib + +[LibraryClasses.IPF] + DebugLib + PalCallLib + + +[Pcd.IA32] + gEfiMdePkgTokenSpaceGuid.PcdFSBClock + +[Pcd.X64] + gEfiMdePkgTokenSpaceGuid.PcdFSBClock + diff --git a/DuetPkg/Library/DuetTimerLib/x86TimerLib.c b/DuetPkg/Library/DuetTimerLib/x86TimerLib.c new file mode 100644 index 0000000000..263ce9a2ec --- /dev/null +++ b/DuetPkg/Library/DuetTimerLib/x86TimerLib.c @@ -0,0 +1,252 @@ +/** @file + Timer Library functions built upon local APIC on IA32/x64. + + Copyright (c) 2006 - 2007, 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 + + +// +// The following array is used in calculating the frequency of local APIC +// timer. Refer to IA-32 developers' manual for more details. +// +GLOBAL_REMOVE_IF_UNREFERENCED +CONST UINT8 mTimerLibLocalApicDivisor[] = { + 0x02, 0x04, 0x08, 0x10, + 0x02, 0x04, 0x08, 0x10, + 0x20, 0x40, 0x80, 0x01, + 0x20, 0x40, 0x80, 0x01 +}; + +/** + Internal function to retrieve the base address of local APIC. + + Internal function to retrieve the base address of local APIC. + + @return The base address of local APIC + +**/ +STATIC +UINTN +InternalX86GetApicBase ( + VOID + ) +{ + return (UINTN)AsmMsrBitFieldRead64 (27, 12, 35) << 12; +} + +/** + Internal function to return the frequency of the local APIC timer. + + Internal function to return the frequency of the local APIC timer. + + @param ApicBase The base address of memory mapped registers of local APIC. + + @return The frequency of the timer in Hz. + +**/ +STATIC +UINT32 +InternalX86GetTimerFrequency ( + IN UINTN ApicBase + ) +{ + return + PcdGet32(PcdFSBClock) / + mTimerLibLocalApicDivisor[MmioBitFieldRead32 (ApicBase + 0x3e0, 0, 3)]; +} + +/** + Internal function to read the current tick counter of local APIC. + + Internal function to read the current tick counter of local APIC. + + @param ApicBase The base address of memory mapped registers of local APIC. + + @return The tick counter read. + +**/ +STATIC +INT32 +InternalX86GetTimerTick ( + IN UINTN ApicBase + ) +{ + return MmioRead32 (ApicBase + 0x390); +} + +/** + Stalls the CPU for at least the given number of ticks. + + Stalls the CPU for at least the given number of ticks. It's invoked by + MicroSecondDelay() and NanoSecondDelay(). + + @param ApicBase The base address of memory mapped registers of local APIC. + @param Delay A period of time to delay in ticks. + +**/ +STATIC +VOID +InternalX86Delay ( + IN UINTN ApicBase, + IN UINT32 Delay + ) +{ + INT32 Ticks; + + // + // The target timer count is calculated here + // + Ticks = InternalX86GetTimerTick (ApicBase) - Delay; + + // + // Wait until time out + // Delay > 2^31 could not be handled by this function + // Timer wrap-arounds are handled correctly by this function + // + while (InternalX86GetTimerTick (ApicBase) - Ticks >= 0); +} + +/** + Stalls the CPU for at least the given number of microseconds. + + Stalls the CPU for the number of microseconds specified by MicroSeconds. + + @param MicroSeconds The minimum number of microseconds to delay. + + @return MicroSeconds + +**/ +UINTN +EFIAPI +MicroSecondDelay ( + IN UINTN MicroSeconds + ) +{ + UINTN ApicBase; + + ApicBase = InternalX86GetApicBase (); + InternalX86Delay ( + ApicBase, + (UINT32)DivU64x32 ( + MultU64x64 ( + InternalX86GetTimerFrequency (ApicBase), + MicroSeconds + ), + 1000000u + ) + ); + return MicroSeconds; +} + +/** + Stalls the CPU for at least the given number of nanoseconds. + + Stalls the CPU for the number of nanoseconds specified by NanoSeconds. + + @param NanoSeconds The minimum number of nanoseconds to delay. + + @return NanoSeconds + +**/ +UINTN +EFIAPI +NanoSecondDelay ( + IN UINTN NanoSeconds + ) +{ + UINTN ApicBase; + + ApicBase = InternalX86GetApicBase (); + InternalX86Delay ( + ApicBase, + (UINT32)DivU64x32 ( + MultU64x64 ( + InternalX86GetTimerFrequency (ApicBase), + NanoSeconds + ), + 1000000000u + ) + ); + return NanoSeconds; +} + +/** + Retrieves the current value of a 64-bit free running performance counter. + + Retrieves the current value of a 64-bit free running performance counter. The + counter can either count up by 1 or count down by 1. If the physical + performance counter counts by a larger increment, then the counter values + must be translated. The properties of the counter can be retrieved from + GetPerformanceCounterProperties(). + + @return The current value of the free running performance counter. + +**/ +UINT64 +EFIAPI +GetPerformanceCounter ( + VOID + ) +{ + return (UINT64)(UINT32)InternalX86GetTimerTick (InternalX86GetApicBase ()); +} + +/** + Retrieves the 64-bit frequency in Hz and the range of performance counter + values. + + If StartValue is not NULL, then the value that the performance counter starts + with immediately after is it rolls over is returned in StartValue. If + EndValue is not NULL, then the value that the performance counter end with + immediately before it rolls over is returned in EndValue. The 64-bit + frequency of the performance counter in Hz is always returned. If StartValue + is less than EndValue, then the performance counter counts up. If StartValue + is greater than EndValue, then the performance counter counts down. For + example, a 64-bit free running counter that counts up would have a StartValue + of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter + that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0. + + @param StartValue The value the performance counter starts with when it + rolls over. + @param EndValue The value that the performance counter ends with before + it rolls over. + + @return The frequency in Hz. + +**/ +UINT64 +EFIAPI +GetPerformanceCounterProperties ( + OUT UINT64 *StartValue, OPTIONAL + OUT UINT64 *EndValue OPTIONAL + ) +{ + UINTN ApicBase; + + ApicBase = InternalX86GetApicBase (); + + if (StartValue != NULL) { + *StartValue = MmioRead32 (ApicBase + 0x380); + } + + if (EndValue != NULL) { + *EndValue = 0; + } + + return (UINT64) InternalX86GetTimerFrequency (ApicBase);; +}