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