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@reactos.org)
11 #include <cportlib/cportlib.h>
15 #include <ndk/halfuncs.h>
17 /* Serial debug connection */
18 #if defined(SARCH_PC98)
19 #define DEFAULT_DEBUG_PORT 2 /* COM2 */
20 #define DEFAULT_DEBUG_COM1_IRQ 4
21 #define DEFAULT_DEBUG_COM2_IRQ 5
22 #define DEFAULT_DEBUG_BAUD_RATE 9600
23 #define DEFAULT_BAUD_RATE 9600
25 #define DEFAULT_DEBUG_PORT 2 /* COM2 */
26 #define DEFAULT_DEBUG_COM1_IRQ 4
27 #define DEFAULT_DEBUG_COM2_IRQ 3
28 #define DEFAULT_DEBUG_BAUD_RATE 115200
29 #define DEFAULT_BAUD_RATE 19200
32 #if defined(_M_IX86) || defined(_M_AMD64)
33 #if defined(SARCH_PC98)
34 const ULONG BaseArray
[] = {0, 0x30, 0x238};
36 const ULONG BaseArray
[] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
39 const ULONG BaseArray
[] = {0, 0x800003F8};
40 #elif defined(_M_MIPS)
41 const ULONG BaseArray
[] = {0, 0x80006000, 0x80007000};
43 const ULONG BaseArray
[] = {0, 0xF1012000};
45 #error Unknown architecture
48 #define MAX_COM_PORTS (sizeof(BaseArray) / sizeof(BaseArray[0]) - 1)
50 /* GLOBALS ********************************************************************/
53 ULONG KdComPortIrq
= 0; // Not used at the moment.
55 CPPORT KdDebugComPort
;
58 /* DEBUGGING ******************************************************************/
61 ULONG
KdpDbgPrint(const char *Format
, ...)
69 Length
= _vsnprintf(Buffer
, sizeof(Buffer
), Format
, ap
);
72 /* Check if we went past the buffer */
75 /* Terminate it if we went over-board */
76 Buffer
[sizeof(Buffer
) - 1] = '\n';
79 Length
= sizeof(Buffer
);
86 CpPutByte(&KdDebugComPort
, '\r');
88 CpPutByte(&KdDebugComPort
, *ptr
++);
95 /* FUNCTIONS ******************************************************************/
101 return STATUS_SUCCESS
;
108 return STATUS_SUCCESS
;
113 KdSave(IN BOOLEAN SleepTransition
)
115 /* Nothing to do on COM ports */
116 return STATUS_SUCCESS
;
121 KdRestore(IN BOOLEAN SleepTransition
)
123 /* Nothing to do on COM ports */
124 return STATUS_SUCCESS
;
129 KdpPortInitialize(IN ULONG ComPortNumber
,
130 IN ULONG ComPortBaudRate
)
134 KDDBGPRINT("KdpPortInitialize, Port = COM%ld\n", ComPortNumber
);
136 Status
= CpInitialize(&KdComPort
,
137 UlongToPtr(BaseArray
[ComPortNumber
]),
139 if (!NT_SUCCESS(Status
))
141 return STATUS_INVALID_PARAMETER
;
145 KdComPortInUse
= KdComPort
.Address
;
146 return STATUS_SUCCESS
;
150 /******************************************************************************
151 * \name KdDebuggerInitialize0
152 * \brief Phase 0 initialization.
153 * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL.
158 KdDebuggerInitialize0(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL
)
160 ULONG ComPortNumber
= DEFAULT_DEBUG_PORT
;
161 ULONG ComPortBaudRate
= DEFAULT_DEBUG_BAUD_RATE
;
163 PCHAR CommandLine
, PortString
, BaudString
, IrqString
;
166 /* Check if we have a LoaderBlock */
169 /* Get the Command Line */
170 CommandLine
= LoaderBlock
->LoadOptions
;
173 _strupr(CommandLine
);
175 /* Get the port and baud rate */
176 PortString
= strstr(CommandLine
, "DEBUGPORT");
177 BaudString
= strstr(CommandLine
, "BAUDRATE");
178 IrqString
= strstr(CommandLine
, "IRQ");
180 /* Check if we got the /DEBUGPORT parameter */
183 /* Move past the actual string, to reach the port*/
184 PortString
+= strlen("DEBUGPORT");
186 /* Now get past any spaces and skip the equal sign */
187 while (*PortString
== ' ') PortString
++;
190 /* Do we have a serial port? */
191 if (strncmp(PortString
, "COM", 3) != 0)
193 return STATUS_INVALID_PARAMETER
;
196 /* Check for a valid Serial Port */
198 Value
= atol(PortString
);
199 if (Value
>= sizeof(BaseArray
) / sizeof(BaseArray
[0]))
201 return STATUS_INVALID_PARAMETER
;
204 /* Set the port to use */
205 ComPortNumber
= Value
;
208 /* Check if we got a baud rate */
211 /* Move past the actual string, to reach the rate */
212 BaudString
+= strlen("BAUDRATE");
214 /* Now get past any spaces */
215 while (*BaudString
== ' ') BaudString
++;
217 /* And make sure we have a rate */
220 /* Read and set it */
221 Value
= atol(BaudString
+ 1);
222 if (Value
) ComPortBaudRate
= Value
;
226 /* Check Serial Port Settings [IRQ] */
229 /* Move past the actual string, to reach the rate */
230 IrqString
+= strlen("IRQ");
232 /* Now get past any spaces */
233 while (*IrqString
== ' ') IrqString
++;
235 /* And make sure we have an IRQ */
238 /* Read and set it */
239 Value
= atol(IrqString
+ 1);
240 if (Value
) KdComPortIrq
= Value
;
247 * Try to find a free COM port and use it as the KD debugging port.
248 * NOTE: Inspired by reactos/boot/freeldr/freeldr/comm/rs232.c, Rs232PortInitialize(...)
252 * Start enumerating COM ports from the last one to the first one,
253 * and break when we find a valid port.
254 * If we reach the first element of the list, the invalid COM port,
255 * then it means that no valid port was found.
258 for (ComPort
= MAX_COM_PORTS
; ComPort
> 0; ComPort
--)
260 /* Check if the port exist; skip the KD port */
261 if ((ComPort
!= ComPortNumber
) && CpDoesPortExist(UlongToPtr(BaseArray
[ComPort
])))
265 CpInitialize(&KdDebugComPort
, UlongToPtr(BaseArray
[ComPort
]), DEFAULT_BAUD_RATE
);
269 KDDBGPRINT("KdDebuggerInitialize0\n");
271 /* Initialize the port */
272 return KdpPortInitialize(ComPortNumber
, ComPortBaudRate
);
275 /******************************************************************************
276 * \name KdDebuggerInitialize1
277 * \brief Phase 1 initialization.
278 * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL.
283 KdDebuggerInitialize1(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL
)
285 return STATUS_SUCCESS
;
291 KdpSendByte(IN UCHAR Byte
)
294 CpPutByte(&KdComPort
, Byte
);
299 KdpPollByte(OUT PUCHAR OutByte
)
304 Status
= CpGetByte(&KdComPort
, OutByte
, FALSE
, FALSE
);
308 return KDP_PACKET_RECEIVED
;
311 return KDP_PACKET_TIMEOUT
;
315 return KDP_PACKET_RESEND
;
321 KdpReceiveByte(OUT PUCHAR OutByte
)
326 Status
= CpGetByte(&KdComPort
, OutByte
, TRUE
, FALSE
);
330 return KDP_PACKET_RECEIVED
;
333 return KDP_PACKET_TIMEOUT
;
337 return KDP_PACKET_RESEND
;
348 KdStatus
= KdpPollByte(&Byte
);
349 if ((KdStatus
== KDP_PACKET_RECEIVED
) && (Byte
== BREAKIN_PACKET_BYTE
))
351 return KDP_PACKET_RECEIVED
;
353 return KDP_PACKET_TIMEOUT
;