ReactOS 0.4.16-dev-2473-gb34a1f1
ns16550.c File Reference
#include <intrin.h>
#include <ioaccess.h>
#include <ntstatus.h>
#include <cportlib/cportlib.h>
#include <drivers/serial/ns16550.h>
Include dependency graph for ns16550.c:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define TIMEOUT_COUNT   (1024 * 200)
 

Functions

static BOOLEAN ComPortTest1 (_In_ PUCHAR Address)
 
static BOOLEAN ComPortTest2 (_In_ PUCHAR Address)
 
BOOLEAN NTAPI Uart16550DoesPortExist (_In_ PUCHAR Address)
 
VOID NTAPI Uart16550EnableFifo (_In_ PUCHAR Address, _In_ BOOLEAN Enable)
 
VOID NTAPI Uart16550SetBaud (_Inout_ PCPPORT Port, _In_ ULONG BaudRate)
 
NTSTATUS NTAPI Uart16550Initialize (_Inout_ PCPPORT Port, _In_ PUCHAR Address, _In_ ULONG BaudRate)
 
static UCHAR NTAPI Cp16550ReadLsr (_Inout_ PCPPORT Port, _In_ UCHAR ExpectedValue)
 
USHORT NTAPI Uart16550GetByte (_Inout_ PCPPORT Port, _Out_ PUCHAR Byte, _In_ BOOLEAN Wait, _In_ BOOLEAN Poll)
 
VOID NTAPI Uart16550PutByte (_Inout_ PCPPORT Port, _In_ UCHAR Byte)
 

Variables

UCHAR RingIndicator
 

Macro Definition Documentation

◆ TIMEOUT_COUNT

#define TIMEOUT_COUNT   (1024 * 200)

Definition at line 32 of file ns16550.c.

Function Documentation

◆ ComPortTest1()

static BOOLEAN ComPortTest1 ( _In_ PUCHAR  Address)
static

Definition at line 39 of file ns16550.c.

41{
42 /*
43 * See "Building Hardware and Firmware to Complement Microsoft Windows Headless Operation"
44 * Out-of-Band Management Port Device Requirements:
45 * The device must act as a 16550 or 16450 UART.
46 * Windows Server 2003 will test this device using the following process:
47 * 1. Save off the current modem status register.
48 * 2. Place the UART into diagnostic mode (The UART is placed into loopback mode
49 * by writing SERIAL_MCR_LOOP to the modem control register).
50 * 3. The modem status register is read and the high bits are checked. This means
51 * SERIAL_MSR_CTS, SERIAL_MSR_DSR, SERIAL_MSR_RI and SERIAL_MSR_DCD should
52 * all be clear.
53 * 4. Place the UART in diagnostic mode and turn on OUTPUT (Loopback Mode and
54 * OUTPUT are both turned on by writing (SERIAL_MCR_LOOP | SERIAL_MCR_OUT1)
55 * to the modem control register).
56 * 5. The modem status register is read and the ring indicator is checked.
57 * This means SERIAL_MSR_RI should be set.
58 * 6. Restore original modem status register.
59 *
60 * REMARK: Strangely enough, the Virtual PC 2007 virtual machine
61 * doesn't pass this test.
62 */
63
64 BOOLEAN RetVal = FALSE;
65 UCHAR Mcr, Msr;
66
67 /* Save the Modem Control Register */
69
70 /* Enable loop (diagnostic) mode (set Bit 4 of the MCR) */
72
73 /* Clear all modem output bits */
75
76 /* Read the Modem Status Register */
78
79 /*
80 * The upper nibble of the MSR (modem output bits) must be
81 * equal to the lower nibble of the MCR (modem input bits).
82 */
84 {
85 /* Set all modem output bits */
87 SERIAL_MCR_OUT1 | SERIAL_MCR_LOOP); // Windows
88/* ReactOS
89 WRITE_PORT_UCHAR(Address + MODEM_CONTROL_REGISTER,
90 SERIAL_MCR_DTR | SERIAL_MCR_RTS | SERIAL_MCR_OUT1 | SERIAL_MCR_OUT2 | SERIAL_MCR_LOOP);
91*/
92
93 /* Read the Modem Status Register */
95
96 /*
97 * The upper nibble of the MSR (modem output bits) must be
98 * equal to the lower nibble of the MCR (modem input bits).
99 */
100 if (Msr & SERIAL_MSR_RI) // Windows
101 // if (Msr & (SERIAL_MSR_CTS | SERIAL_MSR_DSR | SERIAL_MSR_RI | SERIAL_MSR_DCD) == 0xF0) // ReactOS
102 {
103 RetVal = TRUE;
104 }
105 }
106
107 /* Restore the MCR */
109
110 return RetVal;
111}
unsigned char BOOLEAN
Definition: actypes.h:127
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define SERIAL_MCR_OUT1
Definition: ns16550.h:123
#define SERIAL_MSR_CTS
Definition: ns16550.h:147
#define SERIAL_MCR_LOOP
Definition: ns16550.h:125
#define SERIAL_MSR_DSR
Definition: ns16550.h:148
#define SERIAL_MSR_DCD
Definition: ns16550.h:150
#define MODEM_CONTROL_REGISTER
Definition: ns16550.h:37
#define SERIAL_MSR_RI
Definition: ns16550.h:149
#define MODEM_STATUS_REGISTER
Definition: ns16550.h:39
#define READ_PORT_UCHAR(p)
Definition: pc98vid.h:22
#define WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21
static WCHAR Address[46]
Definition: ping.c:68
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by Uart16550DoesPortExist().

◆ ComPortTest2()

static BOOLEAN ComPortTest2 ( _In_ PUCHAR  Address)
static

Definition at line 114 of file ns16550.c.

116{
117 /*
118 * This test checks whether the 16450/16550 scratch register is available.
119 * If not, the serial port is considered as unexisting.
120 */
121
122 UCHAR Byte = 0;
123
124 do
125 {
127
129 return FALSE;
130
131 } while (++Byte != 0);
132
133 return TRUE;
134}
unsigned char Byte
Definition: zlib.h:37
#define SCRATCH_REGISTER
Definition: ns16550.h:40

Referenced by Uart16550DoesPortExist().

◆ Cp16550ReadLsr()

static UCHAR NTAPI Cp16550ReadLsr ( _Inout_ PCPPORT  Port,
_In_ UCHAR  ExpectedValue 
)
static

Definition at line 226 of file ns16550.c.

229{
230 UCHAR Lsr, Msr;
231
232 /* Read the LSR and check if the expected value is present */
234 if (!(Lsr & ExpectedValue))
235 {
236 /* Check the MSR for ring indicator toggle */
238
239 /* If the indicator reaches 3, we've seen this on/off twice */
240 RingIndicator |= (Msr & SERIAL_MSR_RI) ? 1 : 2;
241 if (RingIndicator == 3)
243 }
244
245 return Lsr;
246}
#define CPPORT_FLAG_MODEM_CONTROL
Definition: cportlib.h:24
CPPORT Port[4]
Definition: headless.c:38
UCHAR RingIndicator
Definition: ns16550.c:34
#define LINE_STATUS_REGISTER
Definition: ns16550.h:38
PUCHAR Address
Definition: cportlib.h:28
USHORT Flags
Definition: cportlib.h:30

Referenced by CpReadLsr(), Uart16550GetByte(), and Uart16550PutByte().

◆ Uart16550DoesPortExist()

BOOLEAN NTAPI Uart16550DoesPortExist ( _In_ PUCHAR  Address)

Definition at line 138 of file ns16550.c.

140{
142}
static BOOLEAN ComPortTest1(_In_ PUCHAR Address)
Definition: ns16550.c:39
static BOOLEAN ComPortTest2(_In_ PUCHAR Address)
Definition: ns16550.c:114

Referenced by CpDoesPortExist(), and Uart16550Initialize().

◆ Uart16550EnableFifo()

VOID NTAPI Uart16550EnableFifo ( _In_ PUCHAR  Address,
_In_ BOOLEAN  Enable 
)

Definition at line 146 of file ns16550.c.

149{
150 /* Set FIFO and clear the receive/transmit buffers */
154}
#define SERIAL_FCR_ENABLE
Definition: ns16550.h:82
#define SERIAL_FCR_DISABLE
Definition: ns16550.h:81
#define FIFO_CONTROL_REGISTER
Definition: ns16550.h:35
#define SERIAL_FCR_RCVR_RESET
Definition: ns16550.h:83
#define SERIAL_FCR_TXMT_RESET
Definition: ns16550.h:84
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:142

Referenced by CpEnableFifo(), and Uart16550Initialize().

◆ Uart16550GetByte()

USHORT NTAPI Uart16550GetByte ( _Inout_ PCPPORT  Port,
_Out_ PUCHAR  Byte,
_In_ BOOLEAN  Wait,
_In_ BOOLEAN  Poll 
)

Definition at line 250 of file ns16550.c.

255{
256 UCHAR Lsr;
257 ULONG LimitCount = Wait ? TIMEOUT_COUNT : 1;
258
259 /* Handle early read-before-init */
260 if (!Port->Address)
261 return CP_GET_NODATA;
262
263 /* If "wait" mode enabled, spin many times, otherwise attempt just once */
264 while (LimitCount--)
265 {
266 /* Read LSR for data ready */
268 if ((Lsr & SERIAL_LSR_DR) == SERIAL_LSR_DR)
269 {
270 /* If an error happened, clear the byte and fail */
272 {
273 *Byte = 0;
274 return CP_GET_ERROR;
275 }
276
277 /* If only polling was requested by caller, return now */
278 if (Poll)
279 return CP_GET_SUCCESS;
280
281 /* Otherwise read the byte and return it */
283
284 /* Handle CD if port is in modem control mode */
286 {
287 /* Not implemented yet */
288 // DPRINT1("CP: CPPORT_FLAG_MODEM_CONTROL unexpected\n");
289 }
290
291 /* Byte was read */
292 return CP_GET_SUCCESS;
293 }
294 }
295
296 /* Reset LSR, no data was found */
298 return CP_GET_NODATA;
299}
#define CP_GET_SUCCESS
Definition: cportlib.h:17
#define CP_GET_NODATA
Definition: cportlib.h:18
#define CP_GET_ERROR
Definition: cportlib.h:19
#define TIMEOUT_COUNT
Definition: ns16550.c:32
static UCHAR NTAPI Cp16550ReadLsr(_Inout_ PCPPORT Port, _In_ UCHAR ExpectedValue)
Definition: ns16550.c:226
#define SERIAL_LSR_PE
Definition: ns16550.h:133
#define SERIAL_LSR_OE
Definition: ns16550.h:132
#define RECEIVE_BUFFER_REGISTER
Definition: ns16550.h:31
#define SERIAL_LSR_DR
Definition: ns16550.h:131
#define SERIAL_LSR_FE
Definition: ns16550.h:134
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170

Referenced by CpGetByte().

◆ Uart16550Initialize()

NTSTATUS NTAPI Uart16550Initialize ( _Inout_ PCPPORT  Port,
_In_ PUCHAR  Address,
_In_ ULONG  BaudRate 
)

Definition at line 182 of file ns16550.c.

186{
187 /* Validity checks */
188 if (Port == NULL || Address == NULL || BaudRate == 0)
190
192 return STATUS_NOT_FOUND;
193
194 /* Initialize port data */
196 Port->BaudRate = 0;
197 Port->Flags = 0;
198
199 /* Disable the interrupts */
202
203 /* Turn on DTR, RTS and OUT2 */
206
207 /* Set the baud rate */
208 Uart16550SetBaud(Port, BaudRate);
209
210 /* Set 8 data bits, 1 stop bit, no parity, no break */
213
214 /* Turn on FIFO */
215 // TODO: Check whether FIFO exists and turn it on in that case.
216 Uart16550EnableFifo(Address, TRUE); // for 16550
217
218 /* Read junk out of the RBR */
220
221 return STATUS_SUCCESS;
222}
#define VOID
Definition: acefi.h:82
#define NULL
Definition: types.h:112
VOID NTAPI Uart16550SetBaud(_Inout_ PCPPORT Port, _In_ ULONG BaudRate)
Definition: ns16550.c:158
VOID NTAPI Uart16550EnableFifo(_In_ PUCHAR Address, _In_ BOOLEAN Enable)
Definition: ns16550.c:146
BOOLEAN NTAPI Uart16550DoesPortExist(_In_ PUCHAR Address)
Definition: ns16550.c:138
#define SERIAL_MCR_RTS
Definition: ns16550.h:122
#define INTERRUPT_ENABLE_REGISTER
Definition: ns16550.h:33
#define SERIAL_MCR_OUT2
Definition: ns16550.h:124
#define SERIAL_8_DATA
Definition: ns16550.h:103
#define SERIAL_NONE_PARITY
Definition: ns16550.h:111
#define SERIAL_MCR_DTR
Definition: ns16550.h:121
#define LINE_CONTROL_REGISTER
Definition: ns16550.h:36
#define SERIAL_1_STOP
Definition: ns16550.h:106
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
ULONG BaudRate
Definition: cportlib.h:29
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135

Referenced by CpInitialize().

◆ Uart16550PutByte()

VOID NTAPI Uart16550PutByte ( _Inout_ PCPPORT  Port,
_In_ UCHAR  Byte 
)

Definition at line 303 of file ns16550.c.

306{
307 /* Check if port is in modem control to handle CD */
308 // while (Port->Flags & CPPORT_FLAG_MODEM_CONTROL) // Commented for the moment.
309 if (Port->Flags & CPPORT_FLAG_MODEM_CONTROL) // To be removed when this becomes implemented.
310 {
311 /* Not implemented yet */
312 // DPRINT1("CP: CPPORT_FLAG_MODEM_CONTROL unexpected\n");
313 }
314
315 /* Wait for LSR to say we can go ahead */
317 NOTHING;
318
319 /* Send the byte */
321}
#define NOTHING
Definition: input_list.c:10
#define TRANSMIT_HOLDING_REGISTER
Definition: ns16550.h:32
#define SERIAL_LSR_THRE
Definition: ns16550.h:136

Referenced by CpPutByte().

◆ Uart16550SetBaud()

VOID NTAPI Uart16550SetBaud ( _Inout_ PCPPORT  Port,
_In_ ULONG  BaudRate 
)

Definition at line 158 of file ns16550.c.

161{
162 UCHAR Lcr;
163 ULONG Mode = CLOCK_RATE / BaudRate;
164
165 /* Set the DLAB on */
168
169 /* Set the baud rate */
172
173 /* Reset DLAB */
175
176 /* Save baud rate in port */
177 Port->BaudRate = BaudRate;
178}
_In_ ULONG Mode
Definition: hubbusif.h:303
#define DIVISOR_LATCH_MSB
Definition: ns16550.h:43
#define CLOCK_RATE
Definition: ns16550.h:21
#define DIVISOR_LATCH_LSB
Definition: ns16550.h:42
#define SERIAL_LCR_DLAB
Definition: ns16550.h:94

Referenced by CpSetBaud(), and Uart16550Initialize().

Variable Documentation

◆ RingIndicator

UCHAR RingIndicator

Definition at line 34 of file ns16550.c.

Referenced by Cp16550ReadLsr(), and CpReadLsr().