Author: sir_richard
Date: Fri Sep 10 05:22:48 2010
New Revision: 48727
URL:
http://svn.reactos.org/svn/reactos?rev=48727&view=rev
Log:
Patch by Anton Yarotsky:
[CPORTLIB]: Implement Windows' Cp (ComPort) library. See Notes in C file. Not yet
used. Based on MS Whitepaper: Building Hardware and Firmware to Complement Microsoft
Windows Headless Operation.
Added:
trunk/reactos/include/reactos/drivers/serial/
trunk/reactos/include/reactos/drivers/serial/ns16550.h (with props)
trunk/reactos/include/reactos/libs/cportlib/
trunk/reactos/include/reactos/libs/cportlib/cportlib.h (with props)
trunk/reactos/lib/cportlib/
trunk/reactos/lib/cportlib/cport.c (with props)
trunk/reactos/lib/cportlib/cportlib.rbuild (with props)
Modified:
trunk/reactos/lib/lib.rbuild
Added: trunk/reactos/include/reactos/drivers/serial/ns16550.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/drivers/se…
==============================================================================
--- trunk/reactos/include/reactos/drivers/serial/ns16550.h (added)
+++ trunk/reactos/include/reactos/drivers/serial/ns16550.h [iso-8859-1] Fri Sep 10
05:22:48 2010
@@ -1,0 +1,108 @@
+/*
+ * PROJECT: ReactOS ComPort Library
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
+ * FILE: include/reactos/drivers/serial/ns16550.h
+ * PURPOSE: Header for National Semiconductor 16550 UART
+ * PROGRAMMERS: ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#pragma once
+
+/* Note: These definitions are the internal definitions used by Microsoft serial
+ driver (see src/kernel/serial.h in Windows sources). Linux uses its own, as
+ do most other OS.
+*/
+
+#if !defined(SERIAL_REGISTER_STRIDE)
+#define SERIAL_REGISTER_STRIDE 1
+#endif
+
+#define RECEIVE_BUFFER_REGISTER ((ULONG)((0x00)*SERIAL_REGISTER_STRIDE))
+#define TRANSMIT_HOLDING_REGISTER ((ULONG)((0x00)*SERIAL_REGISTER_STRIDE))
+#define INTERRUPT_ENABLE_REGISTER ((ULONG)((0x01)*SERIAL_REGISTER_STRIDE))
+#define INTERRUPT_IDENT_REGISTER ((ULONG)((0x02)*SERIAL_REGISTER_STRIDE))
+#define FIFO_CONTROL_REGISTER ((ULONG)((0x02)*SERIAL_REGISTER_STRIDE))
+#define LINE_CONTROL_REGISTER ((ULONG)((0x03)*SERIAL_REGISTER_STRIDE))
+#define MODEM_CONTROL_REGISTER ((ULONG)((0x04)*SERIAL_REGISTER_STRIDE))
+#define LINE_STATUS_REGISTER ((ULONG)((0x05)*SERIAL_REGISTER_STRIDE))
+#define MODEM_STATUS_REGISTER ((ULONG)((0x06)*SERIAL_REGISTER_STRIDE))
+#define DIVISOR_LATCH_LSB ((ULONG)((0x00)*SERIAL_REGISTER_STRIDE))
+#define DIVISOR_LATCH_MSB ((ULONG)((0x01)*SERIAL_REGISTER_STRIDE))
+#define SERIAL_REGISTER_SPAN ((ULONG)(7*SERIAL_REGISTER_STRIDE))
+#define SERIAL_STATUS_LENGTH ((ULONG)(1*SERIAL_REGISTER_STRIDE))
+
+#define SERIAL_DATA_LENGTH_5 0x00
+#define SERIAL_DATA_LENGTH_6 0x01
+#define SERIAL_DATA_LENGTH_7 0x02
+#define SERIAL_DATA_LENGTH_8 0x03
+
+#define SERIAL_IER_RDA 0x01
+#define SERIAL_IER_THR 0x02
+#define SERIAL_IER_RLS 0x04
+#define SERIAL_IER_MS 0x08
+
+#define SERIAL_IIR_RLS 0x06
+#define SERIAL_IIR_RDA 0x04
+#define SERIAL_IIR_CTI 0x0c
+#define SERIAL_IIR_THR 0x02
+#define SERIAL_IIR_MS 0x00
+#define SERIAL_IIR_FIFOS_ENABLED 0xc0
+#define SERIAL_IIR_NO_INTERRUPT_PENDING 0x01
+#define SERIAL_IIR_MUST_BE_ZERO 0x30
+
+#define SERIAL_FCR_ENABLE ((UCHAR)0x01)
+#define SERIAL_FCR_RCVR_RESET ((UCHAR)0x02)
+#define SERIAL_FCR_TXMT_RESET ((UCHAR)0x04)
+
+#define SERIAL_1_BYTE_HIGH_WATER ((UCHAR)0x00)
+#define SERIAL_4_BYTE_HIGH_WATER ((UCHAR)0x40)
+#define SERIAL_8_BYTE_HIGH_WATER ((UCHAR)0x80)
+#define SERIAL_14_BYTE_HIGH_WATER ((UCHAR)0xc0)
+
+#define SERIAL_LCR_DLAB 0x80
+#define SERIAL_LCR_BREAK 0x40
+
+#define SERIAL_5_DATA ((UCHAR)0x00)
+#define SERIAL_6_DATA ((UCHAR)0x01)
+#define SERIAL_7_DATA ((UCHAR)0x02)
+#define SERIAL_8_DATA ((UCHAR)0x03)
+#define SERIAL_DATA_MASK ((UCHAR)0x03)
+
+#define SERIAL_1_STOP ((UCHAR)0x00)
+#define SERIAL_1_5_STOP ((UCHAR)0x04) // Only valid for 5 data bits
+#define SERIAL_2_STOP ((UCHAR)0x04) // Not valid for 5 data bits
+#define SERIAL_STOP_MASK ((UCHAR)0x04)
+
+#define SERIAL_NONE_PARITY ((UCHAR)0x00)
+#define SERIAL_ODD_PARITY ((UCHAR)0x08)
+#define SERIAL_EVEN_PARITY ((UCHAR)0x18)
+#define SERIAL_MARK_PARITY ((UCHAR)0x28)
+#define SERIAL_SPACE_PARITY ((UCHAR)0x38)
+#define SERIAL_PARITY_MASK ((UCHAR)0x38)
+
+#define SERIAL_MCR_DTR 0x01
+#define SERIAL_MCR_RTS 0x02
+#define SERIAL_MCR_OUT1 0x04
+#define SERIAL_MCR_OUT2 0x08
+#define SERIAL_MCR_LOOP 0x10
+#define SERIAL_MCR_TL16C550CAFE 0x20
+
+#define SERIAL_LSR_DR 0x01
+#define SERIAL_LSR_OE 0x02
+#define SERIAL_LSR_PE 0x04
+#define SERIAL_LSR_FE 0x08
+#define SERIAL_LSR_BI 0x10
+#define SERIAL_LSR_THRE 0x20
+#define SERIAL_LSR_TEMT 0x40
+#define SERIAL_LSR_FIFOERR 0x80
+
+#define SERIAL_MSR_DCTS 0x01
+#define SERIAL_MSR_DDSR 0x02
+#define SERIAL_MSR_TERI 0x04
+#define SERIAL_MSR_DDCD 0x08
+#define SERIAL_MSR_CTS 0x10
+#define SERIAL_MSR_DSR 0x20
+#define SERIAL_MSR_RI 0x40
+#define SERIAL_MSR_DCD 0x80
Propchange: trunk/reactos/include/reactos/drivers/serial/ns16550.h
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/include/reactos/libs/cportlib/cportlib.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/libs/cport…
==============================================================================
--- trunk/reactos/include/reactos/libs/cportlib/cportlib.h (added)
+++ trunk/reactos/include/reactos/libs/cportlib/cportlib.h [iso-8859-1] Fri Sep 10
05:22:48 2010
@@ -1,0 +1,74 @@
+/*
+ * PROJECT: ReactOS ComPort Library
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
+ * FILE: include/reactos/lib/cportlib/cportlib.h
+ * PURPOSE: Header for the ComPort Library
+ * PROGRAMMERS: ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <ntdef.h>
+
+#define CP_GET_SUCCESS 0
+#define CP_GET_NODATA 1
+#define CP_GET_ERROR 2
+
+#define CPPORT_FLAG_MODEM_CONTROL 0x02
+typedef struct _CPPORT
+{
+ PUCHAR Address;
+ ULONG Baud;
+ USHORT Flags;
+} CPPORT, *PCPPORT;
+
+VOID
+NTAPI
+CpInitialize(
+ IN PCPPORT Port,
+ IN PUCHAR Address,
+ IN ULONG Rate
+ );
+
+VOID
+NTAPI
+CpEnableFifo(
+ IN PUCHAR Address,
+ IN BOOLEAN Enable
+ );
+
+BOOLEAN
+NTAPI
+CpDoesPortExist(
+ IN PUCHAR Address
+ );
+
+UCHAR
+NTAPI
+CpReadLsr(
+ IN PCPPORT Port,
+ IN UCHAR ExpectedValue
+ );
+
+VOID
+NTAPI
+CpSetBaud(
+ IN PCPPORT Port,
+ IN ULONG Rate
+ );
+
+USHORT
+NTAPI
+CpGetByte(
+ IN PCPPORT Port,
+ IN PUCHAR Byte,
+ IN BOOLEAN Wait,
+ IN BOOLEAN Poll
+ );
+
+VOID
+NTAPI
+CpPutByte(
+ IN PCPPORT Port,
+ IN UCHAR Byte
+ );
Propchange: trunk/reactos/include/reactos/libs/cportlib/cportlib.h
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/lib/cportlib/cport.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cportlib/cport.c?rev=4…
==============================================================================
--- trunk/reactos/lib/cportlib/cport.c (added)
+++ trunk/reactos/lib/cportlib/cport.c [iso-8859-1] Fri Sep 10 05:22:48 2010
@@ -1,0 +1,227 @@
+/*
+ * PROJECT: ReactOS ComPort Library
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
+ * FILE: lib/reactos/cportlib/cport.c
+ * PURPOSE: Provides a serial port library for KDCOM, INIT, and FREELDR
+ * PROGRAMMERS: ReactOS Portable Systems Group
+ */
+
+/* NOTE: This library follows the precise serial port intialization steps documented
+ * by Microsoft in some of their Server hardware guidance. Because they've clearly
+ * documented their serial algorithms, we use the same ones to stay
"compliant".
+ * Do not change this code to "improve" it. It's done this way on purpose,
at least on x86.
+ * -- sir_richard
+ */
+
+/* NOTE: This code is used by Headless Support (Ntoskrnl.exe and Osloader.exe) and
+ Kdcom.dll in Windows. It may be that WinDBG depends on some of these quirks.
+*/
+
+/* NOTE: The original code supports Modem Control. We currently do not */
+
+/* FIXMEs:
+ - Make this serial-port specific (NS16550 vs other serial port types)
+ - Get x64 KDCOM, KDBG, FREELDR, and other current code to use this
+*/
+
+/* INCLUDES *******************************************************************/
+
+#include <cportlib/cportlib.h>
+#include <drivers/serial/ns16550.h>
+#include <intrin.h>
+#include <ioaccess.h>
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+UCHAR RingIndicator;
+
+/* FUNCTIONS ******************************************************************/
+
+VOID
+NTAPI
+CpInitialize(IN PCPPORT Port,
+ IN PUCHAR Address,
+ IN ULONG Rate)
+{
+ /* Reset port data */
+ Port->Address = Address;
+ Port->Baud = 0;
+
+ /* Set the baud rate */
+ CpSetBaud(Port, Rate);
+
+ /* Enable on DTR and RTS */
+ WRITE_PORT_UCHAR(Address + MODEM_CONTROL_REGISTER,
+ SERIAL_MCR_DTR | SERIAL_MCR_RTS);
+
+ /* Disable interrupts */
+ WRITE_PORT_UCHAR(Address + INTERRUPT_ENABLE_REGISTER, 0);
+}
+
+VOID
+NTAPI
+CpEnableFifo(IN PUCHAR Address,
+ IN BOOLEAN Enable)
+{
+ /* Set FIFO */
+ WRITE_PORT_UCHAR(Address + FIFO_CONTROL_REGISTER, Enable ? SERIAL_FCR_ENABLE : 0);
+}
+
+BOOLEAN
+NTAPI
+CpDoesPortExist(IN PUCHAR Address)
+{
+ UCHAR Old;
+ /*
+ * See "Building Hardware and Firmware to Complement Microsoft Windows
Headless Operation"
+ * Out-of-Band Management Port Device Requirements:
+ * The device must act as a 16550 or 16450 UART.
+ * Windows Server 2003 will test this device using the following process.
+ * 1. Save off the current modem status register.
+ * 2. Place the UART into diagnostic mode (The UART is placed into loopback
mode
+ * by writing SERIAL_MCR_LOOP to the modem control register).
+ * 3. The modem status register is read and the high bits are checked. This
means
+ * SERIAL_MSR_CTS, SERIAL_MSR_DSR, SERIAL_MSR_RI and SERIAL_MSR_DCD should
+ * all be clear.
+ * 4. Place the UART in diagnostic mode and turn on OUTPUT (Loopback Mode and
+ * OUTPUT are both turned on by writing (SERIAL_MCR_LOOP |
SERIAL_MCR_OUT1)
+ * to the modem control register).
+ * 5. The modem status register is read and the ring indicator is checked.
+ * This means SERIAL_MSR_RI should be set.
+ * 6. Restore original modem status register.
+ */
+ Old = READ_PORT_UCHAR(Address + MODEM_CONTROL_REGISTER);
+ WRITE_PORT_UCHAR(Address + MODEM_CONTROL_REGISTER, SERIAL_MCR_LOOP);
+ WRITE_PORT_UCHAR(Address + MODEM_CONTROL_REGISTER, SERIAL_MCR_LOOP);
+ if (!(READ_PORT_UCHAR(Address + MODEM_STATUS_REGISTER) &
+ (SERIAL_MSR_CTS | SERIAL_MSR_DSR | SERIAL_MSR_RI | SERIAL_MSR_DCD)))
+ {
+ WRITE_PORT_UCHAR(Address + MODEM_CONTROL_REGISTER,
+ (SERIAL_MCR_OUT1 | SERIAL_MCR_LOOP));
+ if (READ_PORT_UCHAR(Address + MODEM_STATUS_REGISTER) & SERIAL_MSR_RI)
+ {
+ WRITE_PORT_UCHAR(Address + MODEM_CONTROL_REGISTER, Old);
+ return TRUE;
+ }
+ }
+ WRITE_PORT_UCHAR(Address + MODEM_CONTROL_REGISTER, Old);
+ return FALSE;
+}
+
+UCHAR
+NTAPI
+CpReadLsr(IN PCPPORT Port,
+ IN UCHAR ExpectedValue)
+{
+ UCHAR Lsr, Msr;
+
+ /* Read the LSR and check if the expected value is present */
+ Lsr = READ_PORT_UCHAR(Port->Address + LINE_STATUS_REGISTER);
+ if (!(Lsr & ExpectedValue))
+ {
+ /* Check the MSR for ring indicator toggle */
+ Msr = READ_PORT_UCHAR(Port->Address + MODEM_STATUS_REGISTER);
+
+ /* If the indicator reaches 3, we've seen this on/off twice */
+ RingIndicator |= (Msr & SERIAL_MSR_RI) ? 1 : 2;
+ if (RingIndicator == 3) Port->Flags |= CPPORT_FLAG_MODEM_CONTROL;
+ }
+
+ return Lsr;
+}
+
+VOID
+NTAPI
+CpSetBaud(IN PCPPORT Port,
+ IN ULONG Rate)
+{
+ UCHAR Lcr;
+ USHORT Mode;
+
+ /* Add DLAB */
+ Lcr = READ_PORT_UCHAR(Port->Address + LINE_CONTROL_REGISTER);
+ WRITE_PORT_UCHAR(Port->Address + LINE_CONTROL_REGISTER, Lcr | SERIAL_LCR_DLAB);
+
+ /* Set baud rate */
+ Mode = 115200 / Rate;
+ WRITE_PORT_UCHAR(Port->Address + DIVISOR_LATCH_MSB, (UCHAR)((Mode >> 8)
& 0xff));
+ WRITE_PORT_UCHAR(Port->Address + DIVISOR_LATCH_LSB, (UCHAR)(Mode & 0xff));
+
+ /* Reset DLAB and set 8 data bits, 1 stop bit, no parity, no break */
+ WRITE_PORT_UCHAR(Port->Address + LINE_CONTROL_REGISTER,
+ SERIAL_8_DATA | SERIAL_1_STOP |
SERIAL_NONE_PARITY);
+
+ /* Save baud rate in port */
+ Port->Baud = Rate;
+}
+
+USHORT
+NTAPI
+CpGetByte(IN PCPPORT Port,
+ IN PUCHAR Byte,
+ IN BOOLEAN Wait,
+ IN BOOLEAN Poll)
+{
+ UCHAR Lsr;
+ ULONG i;
+
+ /* Handle early read-before-init */
+ if (!Port->Address) return CP_GET_NODATA;
+
+ /* If "wait" mode enabled, spin many times, otherwise attempt just once
*/
+ i = Wait ? 204800 : 1;
+ while (i--)
+ {
+ /* Read LSR for data ready */
+ Lsr = CpReadLsr(Port, SERIAL_LSR_DR);
+ if ((Lsr & SERIAL_LSR_DR) == SERIAL_LSR_DR)
+ {
+ /* If an error happened, clear the byte and fail */
+ if (Lsr & (SERIAL_LSR_FE | SERIAL_LSR_PE))
+ {
+ *Byte = 0;
+ return CP_GET_ERROR;
+ }
+
+ /* If only polling was requested by caller, return now */
+ if (Poll) return CP_GET_SUCCESS;
+
+ /* Otherwise read the byte and return it */
+ *Byte = READ_PORT_UCHAR(Port->Address + RECEIVE_BUFFER_REGISTER);
+
+ /* Handle CD if port is in modem control mode */
+ if (Port->Flags & CPPORT_FLAG_MODEM_CONTROL)
+ {
+ /* Not implemented yet */
+ DPRINT1("CP: CPPORT_FLAG_MODEM_CONTROL
unexpected\n");
+ }
+
+ /* Byte was read */
+ return CP_GET_SUCCESS;
+ }
+ }
+
+ /* Reset LSR, no data was found */
+ CpReadLsr(Port, 0);
+ return CP_GET_NODATA;
+}
+
+VOID
+NTAPI
+CpPutByte(IN PCPPORT Port,
+ IN UCHAR Byte)
+{
+ /* Check if port is in modem control to handle CD */
+ while (Port->Flags & CPPORT_FLAG_MODEM_CONTROL)
+ {
+ /* Not implemented yet */
+ DPRINT1("CP: CPPORT_FLAG_MODEM_CONTROL unexpected\n");
+ }
+
+ /* Wait for LSR to say we can go ahead */
+ while (!(CpReadLsr(Port, SERIAL_LSR_THRE) & SERIAL_LSR_THRE));
+
+ /* Send the byte */
+ WRITE_PORT_UCHAR(Port->Address + RECEIVE_BUFFER_REGISTER, Byte);
+}
Propchange: trunk/reactos/lib/cportlib/cport.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/lib/cportlib/cportlib.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cportlib/cportlib.rbui…
==============================================================================
--- trunk/reactos/lib/cportlib/cportlib.rbuild (added)
+++ trunk/reactos/lib/cportlib/cportlib.rbuild [iso-8859-1] Fri Sep 10 05:22:48 2010
@@ -1,0 +1,8 @@
+<?xml version="1.0"?>
+<!DOCTYPE module SYSTEM "../../tools/rbuild/project.dtd">
+<group>
+ <module name="cportlib" type="staticlibrary">
+ <include base="cportlib">.</include>
+ <file>cport.c</file>
+ </module>
+</group>
Propchange: trunk/reactos/lib/cportlib/cportlib.rbuild
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/reactos/lib/lib.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/lib.rbuild?rev=48727&a…
==============================================================================
--- trunk/reactos/lib/lib.rbuild [iso-8859-1] (original)
+++ trunk/reactos/lib/lib.rbuild [iso-8859-1] Fri Sep 10 05:22:48 2010
@@ -12,6 +12,9 @@
</directory>
<directory name="cmlib">
<xi:include href="cmlib/cmlib.rbuild" />
+ </directory>
+ <directory name="cportlib">
+ <xi:include href="cportlib/cportlib.rbuild" />
</directory>
<directory name="debugsup">
<xi:include href="debugsup/debugsup.rbuild" />