1c2c66affSColin Finck /*
2c2c66affSColin Finck * COPYRIGHT: GPL, see COPYING in the top level directory
3c2c66affSColin Finck * PROJECT: ReactOS kernel
4c2c66affSColin Finck * FILE: drivers/base/kdgdb/kdcom.c
5c2c66affSColin Finck * PURPOSE: COM port functions for the kernel debugger.
6c2c66affSColin Finck */
7c2c66affSColin Finck
8c2c66affSColin Finck #include "kdgdb.h"
9c2c66affSColin Finck
10c2c66affSColin Finck #include <cportlib/cportlib.h>
11c2c66affSColin Finck #include <arc/arc.h>
12c2c66affSColin Finck #include <stdlib.h>
13c2c66affSColin Finck #include <ndk/halfuncs.h>
14c2c66affSColin Finck
15c2c66affSColin Finck /* Serial debug connection */
16*4501bbacSDmitry Borisov #if defined(SARCH_PC98)
17c2c66affSColin Finck #define DEFAULT_DEBUG_PORT 2 /* COM2 */
18*4501bbacSDmitry Borisov #define DEFAULT_DEBUG_COM1_IRQ 4
19*4501bbacSDmitry Borisov #define DEFAULT_DEBUG_COM2_IRQ 5
20*4501bbacSDmitry Borisov #define DEFAULT_DEBUG_BAUD_RATE 9600
21*4501bbacSDmitry Borisov #define DEFAULT_BAUD_RATE 9600
22*4501bbacSDmitry Borisov #else
23*4501bbacSDmitry Borisov #define DEFAULT_DEBUG_PORT 2 /* COM2 */
24*4501bbacSDmitry Borisov #define DEFAULT_DEBUG_COM1_IRQ 4
25*4501bbacSDmitry Borisov #define DEFAULT_DEBUG_COM2_IRQ 3
26*4501bbacSDmitry Borisov #define DEFAULT_DEBUG_BAUD_RATE 115200
27c2c66affSColin Finck #define DEFAULT_BAUD_RATE 19200
28*4501bbacSDmitry Borisov #endif
29c2c66affSColin Finck
30c2c66affSColin Finck #if defined(_M_IX86) || defined(_M_AMD64)
31222e7923SDmitry Borisov #if defined(SARCH_PC98)
32222e7923SDmitry Borisov const ULONG BaseArray[] = {0, 0x30, 0x238};
33222e7923SDmitry Borisov #else
34c2c66affSColin Finck const ULONG BaseArray[] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
35222e7923SDmitry Borisov #endif
36c2c66affSColin Finck #elif defined(_M_PPC)
37c2c66affSColin Finck const ULONG BaseArray[] = {0, 0x800003F8};
38c2c66affSColin Finck #elif defined(_M_MIPS)
39c2c66affSColin Finck const ULONG BaseArray[] = {0, 0x80006000, 0x80007000};
40c2c66affSColin Finck #elif defined(_M_ARM)
41c2c66affSColin Finck const ULONG BaseArray[] = {0, 0xF1012000};
42c2c66affSColin Finck #else
43c2c66affSColin Finck #error Unknown architecture
44c2c66affSColin Finck #endif
45c2c66affSColin Finck
46c2c66affSColin Finck #define MAX_COM_PORTS (sizeof(BaseArray) / sizeof(BaseArray[0]) - 1)
47c2c66affSColin Finck
48c2c66affSColin Finck /* GLOBALS ********************************************************************/
49c2c66affSColin Finck
50c2c66affSColin Finck CPPORT KdComPort;
51c2c66affSColin Finck ULONG KdComPortIrq = 0; // Not used at the moment.
52c2c66affSColin Finck #ifdef KDDEBUG
53c2c66affSColin Finck CPPORT KdDebugComPort;
54c2c66affSColin Finck #endif
55c2c66affSColin Finck
56c2c66affSColin Finck /* DEBUGGING ******************************************************************/
57c2c66affSColin Finck
58c2c66affSColin Finck #ifdef KDDEBUG
KdpDbgPrint(const char * Format,...)59c2c66affSColin Finck ULONG KdpDbgPrint(const char *Format, ...)
60c2c66affSColin Finck {
61c2c66affSColin Finck va_list ap;
62c2c66affSColin Finck int Length;
63c2c66affSColin Finck char* ptr;
64c2c66affSColin Finck CHAR Buffer[512];
65c2c66affSColin Finck
66c2c66affSColin Finck va_start(ap, Format);
67c2c66affSColin Finck Length = _vsnprintf(Buffer, sizeof(Buffer), Format, ap);
68c2c66affSColin Finck va_end(ap);
69c2c66affSColin Finck
70c2c66affSColin Finck /* Check if we went past the buffer */
71c2c66affSColin Finck if (Length == -1)
72c2c66affSColin Finck {
73c2c66affSColin Finck /* Terminate it if we went over-board */
74c2c66affSColin Finck Buffer[sizeof(Buffer) - 1] = '\n';
75c2c66affSColin Finck
76c2c66affSColin Finck /* Put maximum */
77c2c66affSColin Finck Length = sizeof(Buffer);
78c2c66affSColin Finck }
79c2c66affSColin Finck
80c2c66affSColin Finck ptr = Buffer;
81c2c66affSColin Finck while (Length--)
82c2c66affSColin Finck {
83c2c66affSColin Finck if (*ptr == '\n')
84c2c66affSColin Finck CpPutByte(&KdDebugComPort, '\r');
85c2c66affSColin Finck
86c2c66affSColin Finck CpPutByte(&KdDebugComPort, *ptr++);
87c2c66affSColin Finck }
88c2c66affSColin Finck
89c2c66affSColin Finck return 0;
90c2c66affSColin Finck }
91c2c66affSColin Finck #endif
92c2c66affSColin Finck
93c2c66affSColin Finck /* FUNCTIONS ******************************************************************/
94c2c66affSColin Finck
95c2c66affSColin Finck NTSTATUS
96c2c66affSColin Finck NTAPI
KdD0Transition(VOID)97c2c66affSColin Finck KdD0Transition(VOID)
98c2c66affSColin Finck {
99c2c66affSColin Finck return STATUS_SUCCESS;
100c2c66affSColin Finck }
101c2c66affSColin Finck
102c2c66affSColin Finck NTSTATUS
103c2c66affSColin Finck NTAPI
KdD3Transition(VOID)104c2c66affSColin Finck KdD3Transition(VOID)
105c2c66affSColin Finck {
106c2c66affSColin Finck return STATUS_SUCCESS;
107c2c66affSColin Finck }
108c2c66affSColin Finck
109c2c66affSColin Finck NTSTATUS
110c2c66affSColin Finck NTAPI
KdSave(IN BOOLEAN SleepTransition)111c2c66affSColin Finck KdSave(IN BOOLEAN SleepTransition)
112c2c66affSColin Finck {
113c2c66affSColin Finck /* Nothing to do on COM ports */
114c2c66affSColin Finck return STATUS_SUCCESS;
115c2c66affSColin Finck }
116c2c66affSColin Finck
117c2c66affSColin Finck NTSTATUS
118c2c66affSColin Finck NTAPI
KdRestore(IN BOOLEAN SleepTransition)119c2c66affSColin Finck KdRestore(IN BOOLEAN SleepTransition)
120c2c66affSColin Finck {
121c2c66affSColin Finck /* Nothing to do on COM ports */
122c2c66affSColin Finck return STATUS_SUCCESS;
123c2c66affSColin Finck }
124c2c66affSColin Finck
125c2c66affSColin Finck NTSTATUS
126c2c66affSColin Finck NTAPI
KdpPortInitialize(IN ULONG ComPortNumber,IN ULONG ComPortBaudRate)127c2c66affSColin Finck KdpPortInitialize(IN ULONG ComPortNumber,
128c2c66affSColin Finck IN ULONG ComPortBaudRate)
129c2c66affSColin Finck {
130c2c66affSColin Finck NTSTATUS Status;
131c2c66affSColin Finck
132c2c66affSColin Finck Status = CpInitialize(&KdComPort,
133c2c66affSColin Finck UlongToPtr(BaseArray[ComPortNumber]),
134c2c66affSColin Finck ComPortBaudRate);
135c2c66affSColin Finck if (!NT_SUCCESS(Status))
136c2c66affSColin Finck {
137c2c66affSColin Finck return STATUS_INVALID_PARAMETER;
138c2c66affSColin Finck }
139de369ce2SJérôme Gardou
140c2c66affSColin Finck KdComPortInUse = KdComPort.Address;
141c2c66affSColin Finck return STATUS_SUCCESS;
142c2c66affSColin Finck }
143c2c66affSColin Finck
144c2c66affSColin Finck /******************************************************************************
145c2c66affSColin Finck * \name KdDebuggerInitialize0
146c2c66affSColin Finck * \brief Phase 0 initialization.
147c2c66affSColin Finck * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL.
148c2c66affSColin Finck * \return Status
149c2c66affSColin Finck */
150c2c66affSColin Finck NTSTATUS
151c2c66affSColin Finck NTAPI
KdDebuggerInitialize0(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)152c2c66affSColin Finck KdDebuggerInitialize0(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
153c2c66affSColin Finck {
154c2c66affSColin Finck ULONG ComPortNumber = DEFAULT_DEBUG_PORT;
155c2c66affSColin Finck ULONG ComPortBaudRate = DEFAULT_DEBUG_BAUD_RATE;
156c2c66affSColin Finck
157c2c66affSColin Finck PCHAR CommandLine, PortString, BaudString, IrqString;
158c2c66affSColin Finck ULONG Value;
159c2c66affSColin Finck
160c2c66affSColin Finck /* Check if we have a LoaderBlock */
161c2c66affSColin Finck if (LoaderBlock)
162c2c66affSColin Finck {
163c2c66affSColin Finck /* Get the Command Line */
164c2c66affSColin Finck CommandLine = LoaderBlock->LoadOptions;
165c2c66affSColin Finck
166c2c66affSColin Finck /* Upcase it */
167c2c66affSColin Finck _strupr(CommandLine);
168c2c66affSColin Finck
169c2c66affSColin Finck /* Get the port and baud rate */
170c2c66affSColin Finck PortString = strstr(CommandLine, "DEBUGPORT");
171c2c66affSColin Finck BaudString = strstr(CommandLine, "BAUDRATE");
172c2c66affSColin Finck IrqString = strstr(CommandLine, "IRQ");
173c2c66affSColin Finck
174c2c66affSColin Finck /* Check if we got the /DEBUGPORT parameter */
175c2c66affSColin Finck if (PortString)
176c2c66affSColin Finck {
177c2c66affSColin Finck /* Move past the actual string, to reach the port*/
178c2c66affSColin Finck PortString += strlen("DEBUGPORT");
179c2c66affSColin Finck
180c2c66affSColin Finck /* Now get past any spaces and skip the equal sign */
181c2c66affSColin Finck while (*PortString == ' ') PortString++;
182c2c66affSColin Finck PortString++;
183c2c66affSColin Finck
184c2c66affSColin Finck /* Do we have a serial port? */
185c2c66affSColin Finck if (strncmp(PortString, "COM", 3) != 0)
186c2c66affSColin Finck {
187c2c66affSColin Finck return STATUS_INVALID_PARAMETER;
188c2c66affSColin Finck }
189c2c66affSColin Finck
190c2c66affSColin Finck /* Check for a valid Serial Port */
191c2c66affSColin Finck PortString += 3;
192c2c66affSColin Finck Value = atol(PortString);
193c2c66affSColin Finck if (Value >= sizeof(BaseArray) / sizeof(BaseArray[0]))
194c2c66affSColin Finck {
195c2c66affSColin Finck return STATUS_INVALID_PARAMETER;
196c2c66affSColin Finck }
197c2c66affSColin Finck
198c2c66affSColin Finck /* Set the port to use */
199c2c66affSColin Finck ComPortNumber = Value;
200c2c66affSColin Finck }
201c2c66affSColin Finck
202c2c66affSColin Finck /* Check if we got a baud rate */
203c2c66affSColin Finck if (BaudString)
204c2c66affSColin Finck {
205c2c66affSColin Finck /* Move past the actual string, to reach the rate */
206c2c66affSColin Finck BaudString += strlen("BAUDRATE");
207c2c66affSColin Finck
208c2c66affSColin Finck /* Now get past any spaces */
209c2c66affSColin Finck while (*BaudString == ' ') BaudString++;
210c2c66affSColin Finck
211c2c66affSColin Finck /* And make sure we have a rate */
212c2c66affSColin Finck if (*BaudString)
213c2c66affSColin Finck {
214c2c66affSColin Finck /* Read and set it */
215c2c66affSColin Finck Value = atol(BaudString + 1);
216c2c66affSColin Finck if (Value) ComPortBaudRate = Value;
217c2c66affSColin Finck }
218c2c66affSColin Finck }
219c2c66affSColin Finck
220c2c66affSColin Finck /* Check Serial Port Settings [IRQ] */
221c2c66affSColin Finck if (IrqString)
222c2c66affSColin Finck {
223c2c66affSColin Finck /* Move past the actual string, to reach the rate */
224c2c66affSColin Finck IrqString += strlen("IRQ");
225c2c66affSColin Finck
226c2c66affSColin Finck /* Now get past any spaces */
227c2c66affSColin Finck while (*IrqString == ' ') IrqString++;
228c2c66affSColin Finck
229c2c66affSColin Finck /* And make sure we have an IRQ */
230c2c66affSColin Finck if (*IrqString)
231c2c66affSColin Finck {
232c2c66affSColin Finck /* Read and set it */
233c2c66affSColin Finck Value = atol(IrqString + 1);
234c2c66affSColin Finck if (Value) KdComPortIrq = Value;
235c2c66affSColin Finck }
236c2c66affSColin Finck }
237c2c66affSColin Finck }
238c2c66affSColin Finck
239c2c66affSColin Finck #ifdef KDDEBUG
240c2c66affSColin Finck /*
241c2c66affSColin Finck * Try to find a free COM port and use it as the KD debugging port.
242c2c66affSColin Finck * NOTE: Inspired by reactos/boot/freeldr/freeldr/comm/rs232.c, Rs232PortInitialize(...)
243c2c66affSColin Finck */
244c2c66affSColin Finck {
245c2c66affSColin Finck /*
246c2c66affSColin Finck * Start enumerating COM ports from the last one to the first one,
247c2c66affSColin Finck * and break when we find a valid port.
248c2c66affSColin Finck * If we reach the first element of the list, the invalid COM port,
249c2c66affSColin Finck * then it means that no valid port was found.
250c2c66affSColin Finck */
251c2c66affSColin Finck ULONG ComPort;
252c2c66affSColin Finck for (ComPort = MAX_COM_PORTS; ComPort > 0; ComPort--)
253c2c66affSColin Finck {
254c2c66affSColin Finck /* Check if the port exist; skip the KD port */
255c2c66affSColin Finck if ((ComPort != ComPortNumber) && CpDoesPortExist(UlongToPtr(BaseArray[ComPort])))
256c2c66affSColin Finck break;
257c2c66affSColin Finck }
258c2c66affSColin Finck if (ComPort != 0)
259c2c66affSColin Finck CpInitialize(&KdDebugComPort, UlongToPtr(BaseArray[ComPort]), DEFAULT_BAUD_RATE);
260c2c66affSColin Finck }
261c2c66affSColin Finck #endif
262c2c66affSColin Finck
263c2c66affSColin Finck /* Initialize the port */
264c2c66affSColin Finck return KdpPortInitialize(ComPortNumber, ComPortBaudRate);
265c2c66affSColin Finck }
266c2c66affSColin Finck
267c2c66affSColin Finck /******************************************************************************
268c2c66affSColin Finck * \name KdDebuggerInitialize1
269c2c66affSColin Finck * \brief Phase 1 initialization.
270c2c66affSColin Finck * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL.
271c2c66affSColin Finck * \return Status
272c2c66affSColin Finck */
273c2c66affSColin Finck NTSTATUS
274c2c66affSColin Finck NTAPI
KdDebuggerInitialize1(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)275c2c66affSColin Finck KdDebuggerInitialize1(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
276c2c66affSColin Finck {
277c2c66affSColin Finck return STATUS_SUCCESS;
278c2c66affSColin Finck }
279c2c66affSColin Finck
280c2c66affSColin Finck
281c2c66affSColin Finck VOID
282c2c66affSColin Finck NTAPI
KdpSendByte(_In_ UCHAR Byte)283c2c66affSColin Finck KdpSendByte(_In_ UCHAR Byte)
284c2c66affSColin Finck {
285c2c66affSColin Finck /* Send the byte */
286c2c66affSColin Finck CpPutByte(&KdComPort, Byte);
287c2c66affSColin Finck }
288c2c66affSColin Finck
289c2c66affSColin Finck KDSTATUS
290c2c66affSColin Finck NTAPI
KdpPollByte(OUT PUCHAR OutByte)291c2c66affSColin Finck KdpPollByte(OUT PUCHAR OutByte)
292c2c66affSColin Finck {
293c2c66affSColin Finck /* Poll the byte */
294c2c66affSColin Finck if (CpGetByte(&KdComPort, OutByte, FALSE, FALSE) == CP_GET_SUCCESS)
295c2c66affSColin Finck {
296c2c66affSColin Finck return KdPacketReceived;
297c2c66affSColin Finck }
298c2c66affSColin Finck else
299c2c66affSColin Finck {
300c2c66affSColin Finck return KdPacketTimedOut;
301c2c66affSColin Finck }
302c2c66affSColin Finck }
303c2c66affSColin Finck
304c2c66affSColin Finck KDSTATUS
305c2c66affSColin Finck NTAPI
KdpReceiveByte(_Out_ PUCHAR OutByte)306c2c66affSColin Finck KdpReceiveByte(_Out_ PUCHAR OutByte)
307c2c66affSColin Finck {
308de369ce2SJérôme Gardou USHORT CpStatus;
309de369ce2SJérôme Gardou
310de369ce2SJérôme Gardou do
311de369ce2SJérôme Gardou {
312de369ce2SJérôme Gardou CpStatus = CpGetByte(&KdComPort, OutByte, TRUE, FALSE);
313de369ce2SJérôme Gardou } while (CpStatus == CP_GET_NODATA);
314de369ce2SJérôme Gardou
315c2c66affSColin Finck /* Get the byte */
316c2c66affSColin Finck if (CpStatus == CP_GET_SUCCESS)
317c2c66affSColin Finck {
318c2c66affSColin Finck return KdPacketReceived;
319c2c66affSColin Finck }
320c2c66affSColin Finck
321c2c66affSColin Finck return KdPacketTimedOut;
322c2c66affSColin Finck }
323c2c66affSColin Finck
324c2c66affSColin Finck KDSTATUS
325c2c66affSColin Finck NTAPI
KdpPollBreakIn(VOID)326c2c66affSColin Finck KdpPollBreakIn(VOID)
327c2c66affSColin Finck {
328c2c66affSColin Finck KDSTATUS KdStatus;
329c2c66affSColin Finck UCHAR Byte;
330c2c66affSColin Finck
331c2c66affSColin Finck KdStatus = KdpPollByte(&Byte);
332c2c66affSColin Finck if (KdStatus == KdPacketReceived)
333c2c66affSColin Finck {
334c2c66affSColin Finck if (Byte == 0x03)
335c2c66affSColin Finck {
336c2c66affSColin Finck KDDBGPRINT("BreakIn Polled.\n");
337c2c66affSColin Finck return KdPacketReceived;
338c2c66affSColin Finck }
339c2c66affSColin Finck else if (Byte == '$')
340c2c66affSColin Finck {
341c2c66affSColin Finck /* GDB tried to send a new packet. N-ack it. */
342c2c66affSColin Finck KdpSendByte('-');
343c2c66affSColin Finck }
344c2c66affSColin Finck }
345c2c66affSColin Finck return KdPacketTimedOut;
346c2c66affSColin Finck }
347c2c66affSColin Finck
348c2c66affSColin Finck /* EOF */
349