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