diff --git a/CMakeLists.txt b/CMakeLists.txt index 3fd4e4f..99901c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,5 +62,6 @@ add_compiler_flags(-D__RELFILE__="&__FILE__[__FILE__[0] == '.' ? sizeof \\\"${_P set_disk_image_size(128) # Build subprojects +add_subdirectory(sdk/xtklib) add_subdirectory(bootdata) add_subdirectory(xtldr) diff --git a/README.md b/README.md index 51c1edb..13e1e53 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ design, it requires a modern EFI enabled hardware. It is not possible currently | drivers | XT native drivers source code | | sdk/cmake | Host toolchain configuration and build-related functions | | sdk/xtdk | XT Software Development Kit headers | -| sdk/xtlib | XT Base library source code | +| sdk/xtklib | XT Base kernel-mode library source code | | services | integral subsystems services source code | | subsystems | environment subsystems source code | | xtoskrnl | XTOS kernel source code | diff --git a/sdk/xtdk/hltypes.h b/sdk/xtdk/hltypes.h new file mode 100644 index 0000000..a72cebb --- /dev/null +++ b/sdk/xtdk/hltypes.h @@ -0,0 +1,100 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: sdk/xtdk/hltypes.h + * DESCRIPTION: XT hardware abstraction layer structures definitions + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTDK_HLTYPES_H +#define __XTDK_HLTYPES_H + +#include "xttypes.h" + + +/* Default serial port settings */ +#define COMPORT_CLOCK_RATE 0x1C200 +#define COMPORT_WAIT_TIMEOUT 204800 + +/* Serial port divisors */ +#define COMPORT_DIV_DLL 0x00 /* Divisor Latch Least */ +#define COMPORT_DIV_DLM 0x01 /* Divisor Latch Most */ + +/* Serial port control flags */ +#define COMPORT_FLAG_DBR 0x01 /* Default Baud Rate */ +#define COMPORT_FLAG_MC 0x02 /* Modem Control */ + +/* Serial port Fifo Control Register (FCR) access masks */ +#define COMPORT_FCR_DISABLE 0x00 /* Disable */ +#define COMPORT_FCR_ENABLE 0x01 /* Enable */ +#define COMPORT_FCR_RCVR_RESET 0x02 /* Receiver Reset */ +#define COMPORT_FCR_TXMT_RESET 0x04 /* Transmitter Reset */ + +/* Serial port Line Control Register (LCR) access masks */ +#define COMPORT_LCR_1STOP 0x00 /* 1 Stop Bit */ +#define COMPORT_LCR_2STOP 0x04 /* 2 Stop Bits */ +#define COMPORT_LCR_5DATA 0x00 /* 5 Data Bits */ +#define COMPORT_LCR_6DATA 0x01 /* 6 Data Bits */ +#define COMPORT_LCR_7DATA 0x02 /* 7 Data Bits */ +#define COMPORT_LCR_8DATA 0x03 /* 8 Data Bits */ +#define COMPORT_LCR_PARN 0x00 /* None Parity */ +#define COMPORT_LCR_PARO 0x08 /* Odd Parity */ +#define COMPORT_LCR_PARE 0x18 /* Even Parity */ +#define COMPORT_LCR_PARM 0x28 /* Mark Parity */ +#define COMPORT_LCR_PARS 0x38 /* Space Parity */ +#define COMPORT_LCR_BREAK 0x40 /* Break */ +#define COMPORT_LCR_DLAB 0x80 /* Divisor Latch Access Bit */ + +/* Serial port Line Status Register (LSR) access masks */ +#define COMPORT_LSR_DIS 0x00 /* Disable */ +#define COMPORT_LSR_DR 0x01 /* Data Ready */ +#define COMPORT_LSR_OE 0x02 /* Overrun Error */ +#define COMPORT_LSR_PE 0x04 /* Parity Error */ +#define COMPORT_LSR_FE 0x08 /* Framing Error */ +#define COMPORT_LSR_BI 0x10 /* Break Interrupt */ +#define COMPORT_LSR_THRE 0x20 /* Transmit Holding Register Empty */ +#define COMPORT_LSR_TEMPTY 0x40 /* Transmitter Empty */ +#define COMPORT_LSR_FIFOE 0x80 /* FIFO Error */ + +/* Serial port Modem Control Register (MCR) access masks */ +#define COMPORT_MCR_DTR 0x01 /* Data Terminal Ready */ +#define COMPORT_MCR_RTS 0x02 /* Ready To Send */ +#define COMPORT_MCR_OUT1 0x04 /* Generic Output 1 */ +#define COMPORT_MCR_OUT2 0x08 /* Generic Output 2 */ +#define COMPORT_MCR_NOM 0x0F /* Normal Operation Mode */ +#define COMPORT_MCR_LOOP 0x10 /* Loopback Testing Mode */ + +/* Serial port Modem Status Register (MSR) access masks */ +#define COMPORT_MSR_DCTS 0x01 /* Delta Clear To Send */ +#define COMPORT_MSR_DDSR 0x02 /* Delta Data Set Ready */ +#define COMPORT_MSR_DTRRTS 0x03 /* DTR and RTS */ +#define COMPORT_MSR_TERI 0x04 /* Trailing Edge Ring Indicator */ +#define COMPORT_MSR_DDCD 0x08 /* Delta Data Carrier Detect */ +#define COMPORT_MSR_CTS 0x10 /* Clear To Send */ +#define COMPORT_MSR_DSR 0x20 /* Data Set Ready */ +#define COMPORT_MSR_RI 0x40 /* Ring Indicator */ +#define COMPORT_MSR_DCD 0x80 /* Data Carrier Detect */ +#define COMPORT_MSR_DSRCTSCD 0xB0 /* DSR, CTS and CD */ +#define COMPORT_MSR_TST 0xAE /* Test Pattern */ + +/* Serial port offsets of the various registers */ +#define COMPORT_REG_RBR 0x00 /* Receive Buffer Register */ +#define COMPORT_REG_THR 0x00 /* Transmit Holding Register */ +#define COMPORT_REG_IER 0x01 /* Interrupt Enable Register */ +#define COMPORT_REG_IIR 0x02 /* Interrupt Identity Register */ +#define COMPORT_REG_FCR 0x02 /* FIFO Control Register */ +#define COMPORT_REG_LCR 0x03 /* Line Control Register */ +#define COMPORT_REG_MCR 0x04 /* Modem Control Register */ +#define COMPORT_REG_LSR 0x05 /* Line Status Register */ +#define COMPORT_REG_MSR 0x06 /* Modem Status Register */ +#define COMPROT_REG_SR 0x07 /* Scratch Register */ + +/* Serial (COM) port initial state */ +typedef struct _CPPORT +{ + PUCHAR Address; + ULONG Baud; + USHORT Flags; +} CPPORT, *PCPPORT; + +#endif /* __XTDK_HLTYPES_H */ diff --git a/sdk/xtdk/xtkmapi.h b/sdk/xtdk/xtkmapi.h index fec6a50..dc5e8ae 100644 --- a/sdk/xtdk/xtkmapi.h +++ b/sdk/xtdk/xtkmapi.h @@ -21,3 +21,6 @@ /* Architecture-independent XT API */ #include "xtcommon.h" #include "xtuefi.h" + +/* Low level data types headers */ +#include "hltypes.h" diff --git a/sdk/xtdk/xtstruct.h b/sdk/xtdk/xtstruct.h index 8628fd3..14172cc 100644 --- a/sdk/xtdk/xtstruct.h +++ b/sdk/xtdk/xtstruct.h @@ -11,6 +11,7 @@ /* Structures forward references */ +typedef struct _CPPORT CPPORT, *PCPPORT; typedef struct _EFI_1394_DEVICE_PATH EFI_1394_DEVICE_PATH, *PEFI_1394_DEVICE_PATH; typedef struct _EFI_ACPI_ADR_DEVICE_PATH EFI_ACPI_ADR_DEVICE_PATH, *PEFI_ACPI_ADR_DEVICE_PATH; typedef struct _EFI_ACPI_HID_DEVICE_PATH EFI_ACPI_HID_DEVICE_PATH, *PEFI_ACPI_HID_DEVICE_PATH; diff --git a/sdk/xtklib/CMakeLists.txt b/sdk/xtklib/CMakeLists.txt new file mode 100644 index 0000000..b488d91 --- /dev/null +++ b/sdk/xtklib/CMakeLists.txt @@ -0,0 +1,15 @@ +# XT kernel-mode library +PROJECT(XTKLIB) + +# Specify include directories +include_directories( + ${EXECTOS_SOURCE_DIR}/sdk/xtdk + ${XTKLIB_SOURCE_DIR}/includes) + +# Specify list of source code files +list(APPEND XTKLIB_SOURCE + ${XTKLIB_SOURCE_DIR}/hl/cport.c + ${XTKLIB_SOURCE_DIR}/hl/${ARCH}/cpufunc.c) + +# Add library +add_library(xtklib ${XTKLIB_SOURCE}) diff --git a/sdk/xtklib/hl/amd64/cpufunc.c b/sdk/xtklib/hl/amd64/cpufunc.c new file mode 100644 index 0000000..0381ecd --- /dev/null +++ b/sdk/xtklib/hl/amd64/cpufunc.c @@ -0,0 +1,56 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: sdk/xtklib/hl/cpufunc.c + * DESCRIPTION: Routines to provide access to special AMD64 CPU instructions + * DEVELOPERS: Rafal Kupiec + */ + +#include "xtkmapi.h" + + +/** + * Reads the data from the specified I/O port. + * + * @param Port + * Specifies the port number in the range of 0-0xFFFF. + * + * @return The value read from the port. + * + * @since XT 1.0 + */ +UCHAR +XTAPI +HlIoPortInByte(IN USHORT Port) +{ + UCHAR Value; + asm volatile("inb %1, %0" + : "=a"(Value) + : "Nd"(Port)); + return Value; +} + +/** + * Writes the data to the specified I/O port. + * + * @param Port + * Specifies the port number in the range of 0-0xFFFF. + * + * @param Value + * Supplies the value to write. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +VOID +XTAPI +HlIoPortOutByte(IN USHORT Port, + IN UCHAR Value) +{ + asm volatile("outb %0, %1" + : + : + "a"(Value), + "Nd"(Port)); +} diff --git a/sdk/xtklib/hl/cport.c b/sdk/xtklib/hl/cport.c new file mode 100644 index 0000000..e7fd982 --- /dev/null +++ b/sdk/xtklib/hl/cport.c @@ -0,0 +1,298 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: sdk/xtklib/hl/cport.c + * DESCRIPTION: Serial (COM) port support + * DEVELOPERS: Rafal Kupiec + */ + +#include "xtkmapi.h" +#include "xtklib.h" + + +/* I/O port addresses for COM1 - COM8 (valid only for ia32 and amd64) */ +ULONG ComPortAddress[] = {0x000, 0x3F8, 0x2F8, 0x3E8, 0x2E8, 0x5F8, 0x4F8, 0x5E8, 0x4E8}; + + +/** + * This routine gets a byte from serial port. + * + * @param Port + * Address of port object describing a port settings. + * + * @param Byte + * Address of variable where to store the result. + * + * @param Wait + * Specifies whether to wait for a data or not. + * + * @param Poll + * Indicates whether to only poll, not reading the data. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTSTATUS +HlComPortGetByte(IN PCPPORT Port, + OUT PUCHAR Byte, + IN BOOLEAN Wait, + IN BOOLEAN Poll) +{ + UCHAR Lsr; + ULONG Retry; + + /* Make sure the port has been initialized */ + if(Port->Address == 0) + { + return STATUS_DEVICE_NOT_READY; + } + + /* Retry getting data if allowed to wait */ + Retry = Wait ? COMPORT_WAIT_TIMEOUT : 1; + while(Retry--) + { + /* Get LSR for data ready */ + Lsr = HlComPortReadLsr(Port, COMPORT_LSR_DR); + if((Lsr & COMPORT_LSR_DR) == COMPORT_LSR_DR) + { + /* Check for errors */ + if(Lsr & (COMPORT_LSR_FE | COMPORT_LSR_OE | COMPORT_LSR_PE)) + { + /* Framing, parity or overrun error occurred */ + *Byte = 0; + return STATUS_IO_DEVICE_ERROR; + } + + /* Check if only polling */ + if(Poll) + { + /* Only polling, return success */ + return STATUS_SUCCESS; + } + + /* Read the byte from serial port */ + *Byte = HlIoPortInByte(PtrToUshort(Port->Address + (ULONG)COMPORT_REG_RBR)); + + /* Check if in modem control mode */ + if(Port->Flags & COMPORT_FLAG_MC) + { + /* Handle Carrier Detected (CD) */ + if((HlIoPortInByte(PtrToShort(Port->Address + (ULONG)COMPORT_REG_MSR)) & COMPORT_MSR_DCD) == 0) + { + /* Skip byte if no CD present */ + continue; + } + } + return STATUS_SUCCESS; + } + } + + /* Reset LSR and return that no data found */ + HlComPortReadLsr(Port, 0); + return STATUS_NOT_FOUND; +} + +/** + * Reads LSR from specified serial port. + * + * @param Port + * Address of COM port. + * + * @param Byte + * Value expected from the port. + * + * @return Byte read from COM port. + * + * @since XT 1.0 + */ +UCHAR +HlComPortReadLsr(IN PCPPORT Port, + IN UCHAR Byte) +{ + UCHAR Lsr, Msr; + STATIC UCHAR RingFlag; + + /* Read the Line Status Register (LSR) */ + Lsr = HlIoPortInByte(PtrToUshort(Port->Address + (ULONG)COMPORT_REG_LSR)); + + /* Check if expected byte is present */ + if((Lsr & Byte) == 0) + { + /* Check Modem Status Register (MSR) for ring indicator */ + Msr = HlIoPortInByte(PtrToUshort(Port->Address + (ULONG)COMPORT_REG_MSR)); + RingFlag |= (Msr & COMPORT_MSR_RI) ? 1 : 2; + if(RingFlag == 3) + { + /* Ring indicator toggled, use modem control */ + Port->Flags |= COMPORT_FLAG_MC; + } + } + + /* Return byte read */ + return Lsr; +} + +/** + * This routine writes a byte to the serial port. + * + * @param Port + * Address of port object describing a port settings. + * + * @param Byte + * Data to be written. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTSTATUS +HlComPortPutByte(IN PCPPORT Port, + IN UCHAR Byte) +{ + UCHAR Lsr, Msr; + + /* Make sure the port has been initialized */ + if(Port->Address == 0) + { + return STATUS_DEVICE_NOT_READY; + } + + /* Check if port is in modem control */ + while(Port->Flags & COMPORT_FLAG_MC) + { + /* Get the Modem Status Register (MSR) */ + Msr = HlIoPortInByte(PtrToUshort(Port->Address + (ULONG)COMPORT_REG_MSR)) & COMPORT_MSR_DSRCTSCD; + if(Msr != COMPORT_MSR_DSRCTSCD) + { + /* Take character, if CD is not set */ + Lsr = HlComPortReadLsr(Port, 0); + if((Msr & COMPORT_MSR_DCD) == 0 && (Lsr & COMPORT_LSR_DR) == COMPORT_LSR_DR) + { + /* Eat the character */ + HlIoPortInByte(PtrToUshort(Port->Address + (ULONG)COMPORT_REG_RBR)); + } + } + else + { + /* CD, CTS and DSR are set, we can continue */ + break; + } + } + + /* Wait for busy port */ + while((HlComPortReadLsr(Port, COMPORT_LSR_THRE) & COMPORT_LSR_THRE) == 0); + + /* Send byte to the port */ + HlIoPortOutByte(PtrToUshort(Port->Address + (ULONG)COMPORT_REG_THR), Byte); + + return STATUS_SUCCESS; +} + +/** + * This routine initializes the COM port. + * + * @param Port + * Address of port object describing a port settings. + * + * @param PortNumber + * Supplies a port number. + * + * @param BaudRate + * Supplies an optional port baud rate. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTSTATUS +HlInitializeComPort(IN OUT PCPPORT Port, + IN ULONG PortNumber, + IN ULONG BaudRate) +{ + PUCHAR Address; + UCHAR Byte = 0; + ULONG Mode; + + /* Check if serial port is set */ + if(PortNumber == 0) + { + /* Use COM1 by default */ + PortNumber = 1; + } + + /* We support up to COM8 */ + if(PortNumber > ARRAY_SIZE(ComPortAddress)) + { + /* Fail if wrong/unsupported port used */ + return STATUS_INVALID_PARAMETER; + } + + /* Check if baud rate is set */ + if(BaudRate == 0) + { + /* Use default baud (clock) rate if not set */ + BaudRate = COMPORT_CLOCK_RATE; + Port->Flags = COMPORT_FLAG_DBR; + } + + /* Store COM pointer */ + Address = UlongToPtr(ComPortAddress[PortNumber]); + + /* Check whether this port is not already initialized */ + if((Port->Address == Address) && (Port->Baud == BaudRate)) + { + return STATUS_SUCCESS; + } + + /* Test if chosen COM port exists */ + do + { + /* Check whether the 16450/16550 scratch register exists */ + HlIoPortOutByte(PtrToUshort(Address + (ULONG)COMPROT_REG_SR), Byte); + if(HlIoPortInByte(PtrToUshort(Address + (ULONG)COMPROT_REG_SR)) != Byte) + { + return STATUS_NOT_FOUND; + } + } while(++Byte != 0); + + /* Disable interrupts */ + HlIoPortOutByte(PtrToUshort(Address + (ULONG)COMPORT_REG_LCR), COMPORT_LSR_DIS); + HlIoPortOutByte(PtrToUshort(Address + (ULONG)COMPORT_REG_IER), COMPORT_LSR_DIS); + + /* Enable Divisor Latch Access Bit (DLAB) */ + HlIoPortOutByte(PtrToUshort(Address + (ULONG)COMPORT_REG_LCR), COMPORT_LCR_DLAB); + + /* Set baud rate */ + Mode = COMPORT_CLOCK_RATE / BaudRate; + HlIoPortOutByte(PtrToUshort(Address + (ULONG)COMPORT_DIV_DLL), (UCHAR)(Mode & 0xFF)); + HlIoPortOutByte(PtrToUshort(Address + (ULONG)COMPORT_DIV_DLM), (UCHAR)((Mode >> 8) & 0xFF)); + + /* Set 8 data bits, 1 stop bits, no parity (8n1) */ + HlIoPortOutByte(PtrToUshort(Address + (ULONG)COMPORT_REG_LCR), + COMPORT_LCR_8DATA | COMPORT_LCR_1STOP | COMPORT_LCR_PARN); + + /* Enable DTR, RTS and OUT2 */ + HlIoPortOutByte(PtrToUshort(Address + (ULONG)COMPORT_REG_MCR), + COMPORT_MCR_DTR | COMPORT_MCR_RTS | COMPORT_MCR_OUT2); + + /* Enable FIFO */ + HlIoPortOutByte(PtrToUshort(Address + (ULONG)COMPORT_REG_FCR), + COMPORT_FCR_ENABLE | COMPORT_FCR_RCVR_RESET | COMPORT_FCR_TXMT_RESET); + + /* Enable loopback mode and test serial port */ + HlIoPortOutByte(PtrToUshort(Address + (ULONG)COMPORT_REG_MCR), COMPORT_MCR_LOOP); + HlIoPortOutByte(PtrToUshort(Address + (ULONG)COMPORT_REG_RBR), COMPORT_MSR_TST); + if(HlIoPortInByte(PtrToUshort(Address + (ULONG)COMPORT_REG_RBR)) != COMPORT_MSR_TST) + { + return STATUS_IO_DEVICE_ERROR; + } + + /* Disable loopback mode and use port normally */ + HlIoPortOutByte(PtrToUshort(Address + (ULONG)COMPORT_REG_MCR), COMPORT_MCR_NOM); + Port->Address = Address; + Port->Baud = BaudRate; + + /* Return success */ + return STATUS_SUCCESS; +} diff --git a/sdk/xtklib/hl/i686/cpufunc.c b/sdk/xtklib/hl/i686/cpufunc.c new file mode 100644 index 0000000..ea8e6d2 --- /dev/null +++ b/sdk/xtklib/hl/i686/cpufunc.c @@ -0,0 +1,56 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: sdk/xtklib/hl/cpufunc.c + * DESCRIPTION: Routines to provide access to special i686 CPU instructions + * DEVELOPERS: Rafal Kupiec + */ + +#include "xtkmapi.h" + + +/** + * Reads the data from the specified I/O port. + * + * @param Port + * Specifies the port number in the range of 0-0xFFFF. + * + * @return The value read from the port. + * + * @since XT 1.0 + */ +UCHAR +XTAPI +HlIoPortInByte(IN USHORT Port) +{ + UCHAR Value; + asm volatile("inb %1, %0" + : "=a"(Value) + : "Nd"(Port)); + return Value; +} + +/** + * Writes the data to the specified I/O port. + * + * @param Port + * Specifies the port number in the range of 0-0xFFFF. + * + * @param Value + * Supplies the value to write. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +VOID +XTAPI +HlIoPortOutByte(IN USHORT Port, + IN UCHAR Value) +{ + asm volatile("outb %0, %1" + : + : + "a"(Value), + "Nd"(Port)); +} diff --git a/sdk/xtklib/includes/libhl.h b/sdk/xtklib/includes/libhl.h new file mode 100644 index 0000000..80f1dc6 --- /dev/null +++ b/sdk/xtklib/includes/libhl.h @@ -0,0 +1,49 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: sdk/xtklib/includes/libhl.h + * DESCRIPTION: Hardware Abstraction Layer library + * DEVELOPERS: Rafal Kupiec + */ + +#ifndef __XTKLIB_LIBHL_H +#define __XTKLIB_LIBHL_H + +#include "xtdefs.h" +#include "xttypes.h" +#include "xtstruct.h" + + +/* I/O port addresses for COM ports */ +extern ULONG ComPortAddress[]; + +/* HAL library routines forward references */ +XTSTATUS +HlComPortGetByte(IN PCPPORT Port, + OUT PUCHAR Byte, + IN BOOLEAN Wait, + IN BOOLEAN Poll); + +UCHAR +HlComPortReadLsr(IN PCPPORT Port, + IN UCHAR Byte); + +XTSTATUS +HlComPortPutByte(IN PCPPORT Port, + IN UCHAR Byte); + +XTSTATUS +HlInitializeComPort(IN OUT PCPPORT Port, + IN ULONG PortNumber, + IN ULONG BaudRate); + +UCHAR +XTAPI +HlIoPortInByte(IN USHORT Port); + +VOID +XTAPI +HlIoPortOutByte(IN USHORT Port, + IN UCHAR Data); + +#endif /* __XTKLIB_LIBHL_H */ diff --git a/sdk/xtklib/includes/xtklib.h b/sdk/xtklib/includes/xtklib.h new file mode 100644 index 0000000..b94e27e --- /dev/null +++ b/sdk/xtklib/includes/xtklib.h @@ -0,0 +1,9 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: sdk/xtklib/includes/xtklib.h + * DESCRIPTION: XT kernel-mode library + * DEVELOPERS: Rafal Kupiec + */ + +#include "libhl.h"