[SHELL32_APITEST] Strengthen ShellHook testcase for fullscreen (#4051)
[reactos.git] / drivers / base / kdcom / kdcom.c
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
52 CPPORT KdComPort;
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
97 NTSTATUS
98 NTAPI
99 KdD0Transition(VOID)
100 {
101 return STATUS_SUCCESS;
102 }
103
104 NTSTATUS
105 NTAPI
106 KdD3Transition(VOID)
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 {
132 NTSTATUS Status;
133
134 KDDBGPRINT("KdpPortInitialize, Port = COM%ld\n", ComPortNumber);
135
136 Status = CpInitialize(&KdComPort,
137 UlongToPtr(BaseArray[ComPortNumber]),
138 ComPortBaudRate);
139 if (!NT_SUCCESS(Status))
140 {
141 return STATUS_INVALID_PARAMETER;
142 }
143 else
144 {
145 KdComPortInUse = KdComPort.Address;
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
158 KdDebuggerInitialize0(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
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 {
193 return STATUS_INVALID_PARAMETER;
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 {
201 return STATUS_INVALID_PARAMETER;
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
283 KdDebuggerInitialize1(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
284 {
285 return STATUS_SUCCESS;
286 }
287
288
289 VOID
290 NTAPI
291 KdpSendByte(IN UCHAR Byte)
292 {
293 /* Send the byte */
294 CpPutByte(&KdComPort, Byte);
295 }
296
297 KDP_STATUS
298 NTAPI
299 KdpPollByte(OUT PUCHAR OutByte)
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
319 KDP_STATUS
320 NTAPI
321 KdpReceiveByte(OUT PUCHAR OutByte)
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
341 KDP_STATUS
342 NTAPI
343 KdpPollBreakIn(VOID)
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 */