ReactOS  r75214
kdcom.c
Go to the documentation of this file.
1 /*
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)
7  */
8 
9 #include "kddll.h"
10 
11 #include <cportlib/cportlib.h>
12 #include <arc/arc.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <ndk/halfuncs.h>
16 
17 /* Serial debug connection */
18 #define DEFAULT_DEBUG_PORT 2 /* COM2 */
19 #define DEFAULT_DEBUG_COM1_IRQ 4 /* COM1 IRQ */
20 #define DEFAULT_DEBUG_COM2_IRQ 3 /* COM2 IRQ */
21 #define DEFAULT_DEBUG_BAUD_RATE 115200 /* 115200 Baud */
22 
23 #define DEFAULT_BAUD_RATE 19200
24 
25 #if defined(_M_IX86) || defined(_M_AMD64)
26 const ULONG BaseArray[] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
27 #elif defined(_M_PPC)
28 const ULONG BaseArray[] = {0, 0x800003F8};
29 #elif defined(_M_MIPS)
30 const ULONG BaseArray[] = {0, 0x80006000, 0x80007000};
31 #elif defined(_M_ARM)
32 const ULONG BaseArray[] = {0, 0xF1012000};
33 #else
34 #error Unknown architecture
35 #endif
36 
37 #define MAX_COM_PORTS (sizeof(BaseArray) / sizeof(BaseArray[0]) - 1)
38 
39 /* GLOBALS ********************************************************************/
40 
42 ULONG KdComPortIrq = 0; // Not used at the moment.
43 #ifdef KDDEBUG
44 CPPORT KdDebugComPort;
45 #endif
46 
47 /* DEBUGGING ******************************************************************/
48 
49 #ifdef KDDEBUG
50 ULONG KdpDbgPrint(const char *Format, ...)
51 {
52  va_list ap;
53  int Length;
54  char* ptr;
55  CHAR Buffer[512];
56 
57  va_start(ap, Format);
58  Length = _vsnprintf(Buffer, sizeof(Buffer), Format, ap);
59  va_end(ap);
60 
61  /* Check if we went past the buffer */
62  if (Length == -1)
63  {
64  /* Terminate it if we went over-board */
65  Buffer[sizeof(Buffer) - 1] = '\n';
66 
67  /* Put maximum */
68  Length = sizeof(Buffer);
69  }
70 
71  ptr = Buffer;
72  while (Length--)
73  {
74  if (*ptr == '\n')
75  CpPutByte(&KdDebugComPort, '\r');
76 
77  CpPutByte(&KdDebugComPort, *ptr++);
78  }
79 
80  return 0;
81 }
82 #endif
83 
84 /* FUNCTIONS ******************************************************************/
85 
87 NTAPI
89 {
90  return STATUS_SUCCESS;
91 }
92 
94 NTAPI
96 {
97  return STATUS_SUCCESS;
98 }
99 
100 NTSTATUS
101 NTAPI
102 KdSave(IN BOOLEAN SleepTransition)
103 {
104  /* Nothing to do on COM ports */
105  return STATUS_SUCCESS;
106 }
107 
108 NTSTATUS
109 NTAPI
110 KdRestore(IN BOOLEAN SleepTransition)
111 {
112  /* Nothing to do on COM ports */
113  return STATUS_SUCCESS;
114 }
115 
116 NTSTATUS
117 NTAPI
118 KdpPortInitialize(IN ULONG ComPortNumber,
119  IN ULONG ComPortBaudRate)
120 {
122 
123  KDDBGPRINT("KdpPortInitialize, Port = COM%ld\n", ComPortNumber);
124 
125  Status = CpInitialize(&KdComPort,
126  UlongToPtr(BaseArray[ComPortNumber]),
127  ComPortBaudRate);
128  if (!NT_SUCCESS(Status))
129  {
131  }
132  else
133  {
134  KdComPortInUse = KdComPort.Address;
135  return STATUS_SUCCESS;
136  }
137 }
138 
139 /******************************************************************************
140  * \name KdDebuggerInitialize0
141  * \brief Phase 0 initialization.
142  * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL.
143  * \return Status
144  */
145 NTSTATUS
146 NTAPI
148 {
149  ULONG ComPortNumber = DEFAULT_DEBUG_PORT;
150  ULONG ComPortBaudRate = DEFAULT_DEBUG_BAUD_RATE;
151 
152  PCHAR CommandLine, PortString, BaudString, IrqString;
153  ULONG Value;
154 
155  /* Check if we have a LoaderBlock */
156  if (LoaderBlock)
157  {
158  /* Get the Command Line */
159  CommandLine = LoaderBlock->LoadOptions;
160 
161  /* Upcase it */
162  _strupr(CommandLine);
163 
164  /* Get the port and baud rate */
165  PortString = strstr(CommandLine, "DEBUGPORT");
166  BaudString = strstr(CommandLine, "BAUDRATE");
167  IrqString = strstr(CommandLine, "IRQ");
168 
169  /* Check if we got the /DEBUGPORT parameter */
170  if (PortString)
171  {
172  /* Move past the actual string, to reach the port*/
173  PortString += strlen("DEBUGPORT");
174 
175  /* Now get past any spaces and skip the equal sign */
176  while (*PortString == ' ') PortString++;
177  PortString++;
178 
179  /* Do we have a serial port? */
180  if (strncmp(PortString, "COM", 3) != 0)
181  {
183  }
184 
185  /* Check for a valid Serial Port */
186  PortString += 3;
187  Value = atol(PortString);
188  if (Value >= sizeof(BaseArray) / sizeof(BaseArray[0]))
189  {
191  }
192 
193  /* Set the port to use */
194  ComPortNumber = Value;
195  }
196 
197  /* Check if we got a baud rate */
198  if (BaudString)
199  {
200  /* Move past the actual string, to reach the rate */
201  BaudString += strlen("BAUDRATE");
202 
203  /* Now get past any spaces */
204  while (*BaudString == ' ') BaudString++;
205 
206  /* And make sure we have a rate */
207  if (*BaudString)
208  {
209  /* Read and set it */
210  Value = atol(BaudString + 1);
211  if (Value) ComPortBaudRate = Value;
212  }
213  }
214 
215  /* Check Serial Port Settings [IRQ] */
216  if (IrqString)
217  {
218  /* Move past the actual string, to reach the rate */
219  IrqString += strlen("IRQ");
220 
221  /* Now get past any spaces */
222  while (*IrqString == ' ') IrqString++;
223 
224  /* And make sure we have an IRQ */
225  if (*IrqString)
226  {
227  /* Read and set it */
228  Value = atol(IrqString + 1);
229  if (Value) KdComPortIrq = Value;
230  }
231  }
232  }
233 
234 #ifdef KDDEBUG
235  /*
236  * Try to find a free COM port and use it as the KD debugging port.
237  * NOTE: Inspired by reactos/boot/freeldr/freeldr/comm/rs232.c, Rs232PortInitialize(...)
238  */
239  {
240  /*
241  * Start enumerating COM ports from the last one to the first one,
242  * and break when we find a valid port.
243  * If we reach the first element of the list, the invalid COM port,
244  * then it means that no valid port was found.
245  */
246  ULONG ComPort;
247  for (ComPort = MAX_COM_PORTS; ComPort > 0; ComPort--)
248  {
249  /* Check if the port exist; skip the KD port */
250  if ((ComPort != ComPortNumber) && CpDoesPortExist(UlongToPtr(BaseArray[ComPort])))
251  break;
252  }
253  if (ComPort != 0)
254  CpInitialize(&KdDebugComPort, UlongToPtr(BaseArray[ComPort]), DEFAULT_BAUD_RATE);
255  }
256 #endif
257 
258  KDDBGPRINT("KdDebuggerInitialize0\n");
259 
260  /* Initialize the port */
261  return KdpPortInitialize(ComPortNumber, ComPortBaudRate);
262 }
263 
264 /******************************************************************************
265  * \name KdDebuggerInitialize1
266  * \brief Phase 1 initialization.
267  * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL.
268  * \return Status
269  */
270 NTSTATUS
271 NTAPI
273 {
274  return STATUS_SUCCESS;
275 }
276 
277 
278 VOID
279 NTAPI
281 {
282  /* Send the byte */
283  CpPutByte(&KdComPort, Byte);
284 }
285 
287 NTAPI
289 {
290  USHORT Status;
291 
292  /* Poll the byte */
293  Status = CpGetByte(&KdComPort, OutByte, FALSE, FALSE);
294  switch (Status)
295  {
296  case CP_GET_SUCCESS:
297  return KDP_PACKET_RECEIVED;
298 
299  case CP_GET_NODATA:
300  return KDP_PACKET_TIMEOUT;
301 
302  case CP_GET_ERROR:
303  default:
304  return KDP_PACKET_RESEND;
305  }
306 }
307 
309 NTAPI
311 {
312  USHORT Status;
313 
314  /* Get the byte */
315  Status = CpGetByte(&KdComPort, OutByte, TRUE, FALSE);
316  switch (Status)
317  {
318  case CP_GET_SUCCESS:
319  return KDP_PACKET_RECEIVED;
320 
321  case CP_GET_NODATA:
322  return KDP_PACKET_TIMEOUT;
323 
324  case CP_GET_ERROR:
325  default:
326  return KDP_PACKET_RESEND;
327  }
328 }
329 
331 NTAPI
333 {
334  KDP_STATUS KdStatus;
335  UCHAR Byte;
336 
337  KdStatus = KdpPollByte(&Byte);
338  if ((KdStatus == KDP_PACKET_RECEIVED) && (Byte == BREAKIN_PACKET_BYTE))
339  {
340  return KDP_PACKET_RECEIVED;
341  }
342  return KDP_PACKET_TIMEOUT;
343 }
344 
345 /* EOF */
NTSTATUS NTAPI KdDebuggerInitialize0(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
Definition: kdcom.c:147
#define STATUS_SUCCESS
Definition: contextmenu.cpp:55
#define IN
Definition: typedefs.h:39
#define TRUE
Definition: types.h:120
#define CP_GET_ERROR
Definition: cportlib.h:20
#define KDDBGPRINT(...)
Definition: kddll.h:19
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
KDP_STATUS
Definition: kddll.h:25
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
unsigned char Byte
Definition: zconf.h:391
KDP_STATUS NTAPI KdpReceiveByte(OUT PUCHAR OutByte)
Definition: kdcom.c:310
NTSTATUS NTAPI KdRestore(IN BOOLEAN SleepTransition)
Definition: kdcom.c:110
USHORT NTAPI CpGetByte(IN PCPPORT Port, OUT PUCHAR Byte, IN BOOLEAN Wait, IN BOOLEAN Poll)
Definition: cport.c:256
PFNDBGPRNT KdpDbgPrint
Definition: kdvm.c:22
BOOLEAN NTAPI CpDoesPortExist(IN PUCHAR Address)
Definition: cport.c:227
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define va_end(ap)
Definition: acmsvcex.h:90
#define FALSE
Definition: types.h:117
KDP_STATUS NTAPI KdpPollBreakIn(VOID)
Definition: kdcom.c:332
NTSTATUS NTAPI KdDebuggerInitialize1(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
Definition: kdcom.c:272
static PVOID ptr
Definition: dispmode.c:41
#define DEFAULT_DEBUG_PORT
Definition: kdcom.c:18
CPPORT KdComPort
Definition: kdcom.c:41
char * va_list
Definition: acmsvcex.h:78
Definition: bufpool.h:45
NTSTATUS NTAPI KdD0Transition(VOID)
Definition: kdcom.c:88
unsigned char BOOLEAN
#define DEFAULT_DEBUG_BAUD_RATE
Definition: kdcom.c:21
#define UlongToPtr(ul)
Definition: basetsd.h:97
KDP_STATUS NTAPI KdpPollByte(OUT PUCHAR OutByte)
Definition: kdcom.c:288
PUCHAR KdComPortInUse
Definition: usage.c:17
ULONG KdComPortIrq
Definition: kdcom.c:42
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
VOID NTAPI KdpSendByte(IN UCHAR Byte)
Definition: kdcom.c:280
VOID NTAPI CpPutByte(IN PCPPORT Port, IN UCHAR Byte)
Definition: cport.c:306
_Check_return_ long __cdecl atol(_In_z_ const char *_Str)
UINTN VOID * Buffer
Definition: acefiex.h:370
#define BREAKIN_PACKET_BYTE
Definition: windbgkd.h:31
unsigned char UCHAR
Definition: xmlstorage.h:181
VOID UINTN Length
Definition: acefiex.h:718
NTSTATUS NTAPI CpInitialize(IN PCPPORT Port, IN PUCHAR Address, IN ULONG BaudRate)
Definition: cport.c:88
UINTN UINT8 Value
Definition: acefiex.h:725
PUCHAR Address
Definition: cportlib.h:29
Status
Definition: gdiplustypes.h:24
#define NT_SUCCESS(StatCode)
Definition: cmd.c:149
LONG NTSTATUS
Definition: DriverTester.h:11
_CRTIMP char *__cdecl _strupr(_Inout_z_ char *_String)
NTSTATUS NTAPI KdD3Transition(VOID)
Definition: kdcom.c:95
unsigned short USHORT
Definition: pedump.c:61
#define MAX_COM_PORTS
Definition: kdcom.c:37
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define CP_GET_SUCCESS
Definition: cportlib.h:18
#define DEFAULT_BAUD_RATE
Definition: kdcom.c:23
#define _vsnprintf
Definition: xmlstorage.h:202
signed char * PCHAR
Definition: retypes.h:7
void int int ULONGLONG int va_list * ap
Definition: winesup.h:32
#define OUT
Definition: typedefs.h:40
unsigned int ULONG
Definition: retypes.h:1
NTSTATUS NTAPI KdSave(IN BOOLEAN SleepTransition)
Definition: kdcom.c:102
#define CP_GET_NODATA
Definition: cportlib.h:19
NTSTATUS NTAPI KdpPortInitialize(IN ULONG ComPortNumber, IN ULONG ComPortBaudRate)
Definition: kdcom.c:118
IN HDEVINFO IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
Definition: devinst.c:44