[ros-diffs] [sir_richard] 48727: 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 Compl...

sir_richard at svn.reactos.org sir_richard at svn.reactos.org
Fri Sep 10 05:22:48 UTC 2010


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/serial/ns16550.h?rev=48727&view=auto
==============================================================================
--- 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/cportlib/cportlib.h?rev=48727&view=auto
==============================================================================
--- 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=48727&view=auto
==============================================================================
--- 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.rbuild?rev=48727&view=auto
==============================================================================
--- 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&r1=48726&r2=48727&view=diff
==============================================================================
--- 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" />




More information about the Ros-diffs mailing list