2 * COPYRIGHT: GPL, see COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/base/kddll/kdcom.c
5 * PURPOSE: COM port functions for the kernel debugger.
6 * PROGRAMMER: Timo Kreuzer (timo.kreuzer@ewactos.org)
12 /* Define wait timeout value. */
13 #define REPEAT_COUNT (1000 * 1000)
15 /* serial debug connection */
16 #define DEFAULT_DEBUG_PORT 2 /* COM2 */
17 #define DEFAULT_DEBUG_COM1_IRQ 4 /* COM1 IRQ */
18 #define DEFAULT_DEBUG_COM2_IRQ 3 /* COM2 IRQ */
19 #define DEFAULT_DEBUG_BAUD_RATE 115200 /* 115200 Baud */
21 #define DEFAULT_BAUD_RATE 19200
24 #if defined(_M_IX86) || defined(_M_AMD64)
25 const ULONG BaseArray
[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
27 const ULONG BaseArray
[2] = {0, 0x800003f8};
28 #elif defined(_M_MIPS)
29 const ULONG BaseArray
[3] = {0, 0x80006000, 0x80007000};
31 const ULONG BaseArray
[2] = {0, 0xF1012000};
33 #error Unknown architecture
36 /* GLOBALS ********************************************************************/
39 ULONG ComPortNumber
= DEFAULT_DEBUG_PORT
;
40 ULONG ComPortBaudRate
= DEFAULT_DEBUG_BAUD_RATE
;
50 KDDBGPRINT("KdpPortInitialize\n");
52 /* Enable loop mode (set Bit 4 of the MCR) */
53 WRITE_PORT_UCHAR(ComPortBase
+ COM_MCR
, MCR_LOOP
);
55 /* Clear all modem output bits */
56 WRITE_PORT_UCHAR(ComPortBase
+ COM_MCR
, MCR_LOOP
);
58 /* The upper nibble of the MSR (modem output bits) must be
59 * equal to the lower nibble of the MCR (modem input bits) */
60 if ((READ_PORT_UCHAR(ComPortBase
+ COM_MSR
) & 0xF0) != 0x00)
62 return STATUS_INVALID_PARAMETER
;
65 /* Set all modem output bits */
66 WRITE_PORT_UCHAR(ComPortBase
+ COM_MCR
, MCR_ALL
);
68 /* The upper nibble of the MSR (modem output bits) must be
69 * equal to the lower nibble of the MCR (modem input bits) */
70 if ((READ_PORT_UCHAR(ComPortBase
+ COM_MSR
) & 0xF0) != 0xF0)
72 return STATUS_INVALID_PARAMETER
;
76 WRITE_PORT_UCHAR(ComPortBase
+ COM_FCR
,
77 FCR_ENABLE_FIFO
| FCR_CLEAR_RCVR
| FCR_CLEAR_XMIT
);
79 /* Disable interrupts */
80 WRITE_PORT_UCHAR(ComPortBase
+ COM_LCR
, 0);
81 WRITE_PORT_UCHAR(ComPortBase
+ COM_IEN
, 0);
83 /* Enable on DTR and RTS */
84 WRITE_PORT_UCHAR(ComPortBase
+ COM_MCR
, MCR_DTR
| MCR_RTS
);
87 WRITE_PORT_UCHAR(ComPortBase
+ COM_LCR
, LCR_DLAB
);
90 Mode
= 115200 / ComPortBaudRate
;
91 WRITE_PORT_UCHAR(ComPortBase
+ COM_DLL
, (UCHAR
)(Mode
& 0xff));
92 WRITE_PORT_UCHAR(ComPortBase
+ COM_DLM
, (UCHAR
)((Mode
>> 8) & 0xff));
94 /* Reset DLAB and set 8 data bits, 1 stop bit, no parity, no break */
95 WRITE_PORT_UCHAR(ComPortBase
+ COM_LCR
, LCR_CS8
| LCR_ST1
| LCR_PNO
);
97 /* Check for 16450/16550 scratch register */
98 WRITE_PORT_UCHAR(ComPortBase
+ COM_SCR
, 0xff);
99 if (READ_PORT_UCHAR(ComPortBase
+ COM_SCR
) != 0xff)
101 return STATUS_INVALID_PARAMETER
;
103 WRITE_PORT_UCHAR(ComPortBase
+ COM_SCR
, 0x00);
104 if (READ_PORT_UCHAR(ComPortBase
+ COM_SCR
) != 0x00)
106 return STATUS_INVALID_PARAMETER
;
109 return STATUS_SUCCESS
;
112 /******************************************************************************
113 * \name KdDebuggerInitialize0
114 * \brief Phase 0 initialization.
115 * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL.
120 KdDebuggerInitialize0(
121 IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL
)
123 PCHAR CommandLine
, PortString
, BaudString
, IrqString
;
126 /* Check if e have a LoaderBlock */
129 /* Get the Command Line */
130 CommandLine
= LoaderBlock
->LoadOptions
;
133 _strupr(CommandLine
);
135 /* Get the port and baud rate */
136 PortString
= strstr(CommandLine
, "DEBUGPORT");
137 BaudString
= strstr(CommandLine
, "BAUDRATE");
138 IrqString
= strstr(CommandLine
, "IRQ");
140 /* Check if we got the /DEBUGPORT parameter */
143 /* Move past the actual string, to reach the port*/
144 PortString
+= strlen("DEBUGPORT");
146 /* Now get past any spaces and skip the equal sign */
147 while (*PortString
== ' ') PortString
++;
150 /* Do we have a serial port? */
151 if (strncmp(PortString
, "COM", 3) != 0)
153 return STATUS_INVALID_PARAMETER
;
156 /* Gheck for a valid Serial Port */
158 Value
= atol(PortString
);
161 return STATUS_INVALID_PARAMETER
;
164 /* Set the port to use */
165 ComPortNumber
= Value
;
168 /* Check if we got a baud rate */
171 /* Move past the actual string, to reach the rate */
172 BaudString
+= strlen("BAUDRATE");
174 /* Now get past any spaces */
175 while (*BaudString
== ' ') BaudString
++;
177 /* And make sure we have a rate */
180 /* Read and set it */
181 Value
= atol(BaudString
+ 1);
182 if (Value
) ComPortBaudRate
= Value
;
186 /* Check Serial Port Settings [IRQ] */
189 /* Move past the actual string, to reach the rate */
190 IrqString
+= strlen("IRQ");
192 /* Now get past any spaces */
193 while (*IrqString
== ' ') IrqString
++;
195 /* And make sure we have an IRQ */
198 /* Read and set it */
199 Value
= atol(IrqString
+ 1);
200 if (Value
) ComPortIrq
= Value
;
205 /* Get base address */
206 ComPortBase
= UlongToPtr(BaseArray
[ComPortNumber
]);
207 KdComPortInUse
= ComPortBase
;
209 /* Initialize the port */
210 return KdpPortInitialize();
215 KdpSendByte(IN BYTE Byte
)
217 /* Wait for the port to be ready */
218 while ((READ_PORT_UCHAR(ComPortBase
+ COM_LSR
) & LSR_TBE
) == 0);
220 /* This is needed due to subtle timing issues */
221 READ_PORT_UCHAR(ComPortBase
+ COM_MSR
);
222 while ((READ_PORT_UCHAR(ComPortBase
+ COM_LSR
) & LSR_TBE
) == 0);
223 READ_PORT_UCHAR(ComPortBase
+ COM_MSR
);
226 WRITE_PORT_UCHAR(ComPortBase
+ COM_DAT
, Byte
);
231 KdpPollByte(OUT PBYTE OutByte
)
233 READ_PORT_UCHAR(ComPortBase
+ COM_MSR
); // Timing
235 /* Check if data is available */
236 if ((READ_PORT_UCHAR(ComPortBase
+ COM_LSR
) & LSR_DR
))
238 /* Yes, return the byte */
239 *OutByte
= READ_PORT_UCHAR(ComPortBase
+ COM_DAT
);
240 return KDP_PACKET_RECEIVED
;
244 return KDP_PACKET_TIMEOUT
;
249 KdpReceiveByte(OUT PBYTE OutByte
)
251 ULONG Repeats
= REPEAT_COUNT
;
255 /* Check if data is available */
256 if (KdpPollByte(OutByte
) == KDP_PACKET_RECEIVED
)
258 /* We successfully got a byte */
259 return KDP_PACKET_RECEIVED
;
264 return KDP_PACKET_TIMEOUT
;
272 if (KdpPollByte(&Byte
) == KDP_PACKET_RECEIVED
)
274 if (Byte
== BREAKIN_PACKET_BYTE
)
276 return KDP_PACKET_RECEIVED
;
279 return KDP_PACKET_TIMEOUT
;
285 IN BOOLEAN SleepTransition
)
287 /* Nothing to do on COM ports */
288 return STATUS_SUCCESS
;
294 IN BOOLEAN SleepTransition
)
296 /* Nothing to do on COM ports */
297 return STATUS_SUCCESS
;