[KDCOM]
[reactos.git] / reactos / drivers / base / kdcom / i386 / kdbg.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/base/kdcom/kdbg.c
5 * PURPOSE: Serial i/o functions for the kernel debugger.
6 * PROGRAMMER: Alex Ionescu
7 * Hervé Poussineau
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #define NOEXTAPI
13 #include <ntifs.h>
14 #include <halfuncs.h>
15 #include <stdio.h>
16 #include "arc/arc.h"
17 #include "windbgkd.h"
18 #include <kddll.h>
19 #include <ioaccess.h> /* port intrinsics */
20 #include <cportlib/cportlib.h>
21
22 #define NDEBUG
23 #include <debug.h>
24
25
26 typedef struct _KD_PORT_INFORMATION
27 {
28 ULONG ComPort;
29 ULONG BaudRate;
30 ULONG BaseAddress;
31 } KD_PORT_INFORMATION, *PKD_PORT_INFORMATION;
32
33 BOOLEAN
34 NTAPI
35 KdPortInitializeEx(
36 IN PKD_PORT_INFORMATION PortInformation,
37 IN ULONG Unknown1,
38 IN ULONG Unknown2);
39
40 BOOLEAN
41 NTAPI
42 KdPortGetByteEx(
43 IN PKD_PORT_INFORMATION PortInformation,
44 OUT PUCHAR ByteReceived);
45
46 BOOLEAN
47 NTAPI
48 KdPortPollByteEx(
49 IN PKD_PORT_INFORMATION PortInformation,
50 OUT PUCHAR ByteReceived);
51
52 VOID
53 NTAPI
54 KdPortPutByteEx(
55 IN PKD_PORT_INFORMATION PortInformation,
56 IN UCHAR ByteToSend);
57
58 #define DEFAULT_BAUD_RATE 19200
59
60 #if defined(_M_IX86) || defined(_M_AMD64)
61 const ULONG BaseArray[] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
62 #elif defined(_M_PPC)
63 const ULONG BaseArray[] = {0, 0x800003F8};
64 #elif defined(_M_MIPS)
65 const ULONG BaseArray[] = {0, 0x80006000, 0x80007000};
66 #elif defined(_M_ARM)
67 const ULONG BaseArray[] = {0, 0xF1012000};
68 #else
69 #error Unknown architecture
70 #endif
71
72 /* MACROS *******************************************************************/
73
74 #define SER_RBR(x) ((PUCHAR)(x)+0)
75 #define SER_THR(x) ((PUCHAR)(x)+0)
76 #define SER_DLL(x) ((PUCHAR)(x)+0)
77 #define SER_IER(x) ((PUCHAR)(x)+1)
78 #define SR_IER_ERDA 0x01
79 #define SR_IER_ETHRE 0x02
80 #define SR_IER_ERLSI 0x04
81 #define SR_IER_EMS 0x08
82 #define SR_IER_ALL 0x0F
83 #define SER_DLM(x) ((PUCHAR)(x)+1)
84 #define SER_IIR(x) ((PUCHAR)(x)+2)
85 #define SER_FCR(x) ((PUCHAR)(x)+2)
86 #define SR_FCR_ENABLE_FIFO 0x01
87 #define SR_FCR_CLEAR_RCVR 0x02
88 #define SR_FCR_CLEAR_XMIT 0x04
89 #define SER_LCR(x) ((PUCHAR)(x)+3)
90 #define SR_LCR_CS5 0x00
91 #define SR_LCR_CS6 0x01
92 #define SR_LCR_CS7 0x02
93 #define SR_LCR_CS8 0x03
94 #define SR_LCR_ST1 0x00
95 #define SR_LCR_ST2 0x04
96 #define SR_LCR_PNO 0x00
97 #define SR_LCR_POD 0x08
98 #define SR_LCR_PEV 0x18
99 #define SR_LCR_PMK 0x28
100 #define SR_LCR_PSP 0x38
101 #define SR_LCR_BRK 0x40
102 #define SR_LCR_DLAB 0x80
103 #define SER_MCR(x) ((PUCHAR)(x)+4)
104 #define SR_MCR_DTR 0x01
105 #define SR_MCR_RTS 0x02
106 #define SR_MCR_OUT1 0x04
107 #define SR_MCR_OUT2 0x08
108 #define SR_MCR_LOOP 0x10
109 #define SER_LSR(x) ((PUCHAR)(x)+5)
110 #define SR_LSR_DR 0x01
111 #define SR_LSR_TBE 0x20
112 #define SER_MSR(x) ((PUCHAR)(x)+6)
113 #define SR_MSR_CTS 0x10
114 #define SR_MSR_DSR 0x20
115 #define SER_SCR(x) ((PUCHAR)(x)+7)
116
117
118 /* GLOBAL VARIABLES *********************************************************/
119
120 /* STATIC VARIABLES *********************************************************/
121
122 static KD_PORT_INFORMATION DefaultPort = { 0, 0, 0 };
123
124 /* The com port must only be initialized once! */
125 static BOOLEAN PortInitialized = FALSE;
126
127
128 /* FUNCTIONS ****************************************************************/
129
130 /* HAL.KdPortInitialize */
131 BOOLEAN
132 NTAPI
133 KdPortInitialize(
134 IN PKD_PORT_INFORMATION PortInformation,
135 IN ULONG Unknown1,
136 IN ULONG Unknown2)
137 {
138 SIZE_T i;
139 CHAR buffer[80];
140
141 if (!PortInitialized)
142 {
143 DefaultPort.BaudRate = PortInformation->BaudRate;
144
145 if (PortInformation->ComPort == 0)
146 {
147 /*
148 * Start enumerating COM ports from the last one to the first one,
149 * and break when we find a valid port.
150 * If we reach the first element of the list, the invalid COM port,
151 * then it means that no valid port was found.
152 */
153 for (i = sizeof(BaseArray) / sizeof(BaseArray[0]) - 1; i > 0; i--)
154 {
155 if (CpDoesPortExist(UlongToPtr(BaseArray[i])))
156 {
157 PortInformation->BaseAddress = DefaultPort.BaseAddress = BaseArray[i];
158 PortInformation->ComPort = DefaultPort.ComPort = i;
159 break;
160 }
161 }
162 if (i == 0)
163 {
164 sprintf(buffer,
165 "\nKernel Debugger: No COM port found!\n\n");
166 HalDisplayString(buffer);
167 return FALSE;
168 }
169 }
170
171 PortInitialized = TRUE;
172 }
173
174 /* initialize port */
175 if (!KdPortInitializeEx(&DefaultPort, Unknown1, Unknown2))
176 return FALSE;
177
178 /* set global info */
179 KdComPortInUse = (PUCHAR)DefaultPort.BaseAddress;
180
181 return TRUE;
182 }
183
184
185 /* HAL.KdPortInitializeEx ; ReactOS-specific */
186 BOOLEAN
187 NTAPI
188 KdPortInitializeEx(
189 IN PKD_PORT_INFORMATION PortInformation,
190 IN ULONG Unknown1,
191 IN ULONG Unknown2)
192 {
193 ULONG ComPortBase;
194 CHAR buffer[80];
195 ULONG divisor;
196 UCHAR lcr;
197
198 #ifdef _ARM_
199 UNIMPLEMENTED;
200 return FALSE;
201 #endif
202
203 if (PortInformation->BaudRate == 0)
204 PortInformation->BaudRate = DEFAULT_BAUD_RATE;
205
206 if (PortInformation->ComPort != 0)
207 {
208 if (!CpDoesPortExist(UlongToPtr(BaseArray[PortInformation->ComPort])))
209 {
210 sprintf(buffer,
211 "\nKernel Debugger: Serial port not found!\n\n");
212 HalDisplayString(buffer);
213 return FALSE;
214 }
215
216 ComPortBase = BaseArray[PortInformation->ComPort];
217 PortInformation->BaseAddress = ComPortBase;
218 }
219 else
220 {
221 ComPortBase = PortInformation->BaseAddress;
222 }
223
224 if (ComPortBase == 0)
225 return FALSE;
226
227 #ifndef NDEBUG
228 sprintf(buffer,
229 "\nSerial port COM%ld found at 0x%lx\n",
230 PortInformation->ComPort,
231 ComPortBase);
232 HalDisplayString(buffer);
233 #endif /* NDEBUG */
234
235 /* set baud rate and data format (8N1) */
236
237 /* turn on DTR and RTS */
238 WRITE_PORT_UCHAR(SER_MCR(ComPortBase), SR_MCR_DTR | SR_MCR_RTS);
239
240 /* set DLAB */
241 lcr = READ_PORT_UCHAR(SER_LCR(ComPortBase)) | SR_LCR_DLAB;
242 WRITE_PORT_UCHAR(SER_LCR(ComPortBase), lcr);
243
244 /* set baud rate */
245 divisor = 115200 / PortInformation->BaudRate;
246 WRITE_PORT_UCHAR(SER_DLL(ComPortBase), (UCHAR)(divisor & 0xff));
247 WRITE_PORT_UCHAR(SER_DLM(ComPortBase), (UCHAR)((divisor >> 8) & 0xff));
248
249 /* reset DLAB and set 8N1 format */
250 WRITE_PORT_UCHAR(SER_LCR(ComPortBase),
251 SR_LCR_CS8 | SR_LCR_ST1 | SR_LCR_PNO);
252
253 /* read junk out of the RBR */
254 lcr = READ_PORT_UCHAR(SER_RBR(ComPortBase));
255
256 #ifndef NDEBUG
257 /* print message to blue screen */
258 sprintf(buffer,
259 "\nKernel Debugger: COM%ld (Port 0x%lx) BaudRate %ld\n\n",
260 PortInformation->ComPort,
261 ComPortBase,
262 PortInformation->BaudRate);
263
264 HalDisplayString(buffer);
265 #endif /* NDEBUG */
266
267 return TRUE;
268 }
269
270
271 /* HAL.KdPortGetByte */
272 BOOLEAN
273 NTAPI
274 KdPortGetByte(
275 OUT PUCHAR ByteReceived)
276 {
277 if (!PortInitialized)
278 return FALSE;
279 return KdPortGetByteEx(&DefaultPort, ByteReceived);
280 }
281
282
283 /* HAL.KdPortGetByteEx ; ReactOS-specific */
284 BOOLEAN
285 NTAPI
286 KdPortGetByteEx(
287 IN PKD_PORT_INFORMATION PortInformation,
288 OUT PUCHAR ByteReceived)
289 {
290 PUCHAR ComPortBase = (PUCHAR)PortInformation->BaseAddress;
291
292 if ((READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_DR))
293 {
294 *ByteReceived = READ_PORT_UCHAR(SER_RBR(ComPortBase));
295 return TRUE;
296 }
297
298 return FALSE;
299 }
300
301
302 /* HAL.KdPortPollByte */
303 BOOLEAN
304 NTAPI
305 KdPortPollByte(
306 OUT PUCHAR ByteReceived)
307 {
308 if (!PortInitialized)
309 return FALSE;
310 return KdPortPollByteEx(&DefaultPort, ByteReceived);
311 }
312
313
314 /* HAL.KdPortPollByteEx ; ReactOS-specific */
315 BOOLEAN
316 NTAPI
317 KdPortPollByteEx(
318 IN PKD_PORT_INFORMATION PortInformation,
319 OUT PUCHAR ByteReceived)
320 {
321 PUCHAR ComPortBase = (PUCHAR)PortInformation->BaseAddress;
322
323 while ((READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_DR) == 0)
324 ;
325
326 *ByteReceived = READ_PORT_UCHAR(SER_RBR(ComPortBase));
327
328 return TRUE;
329 }
330
331
332 /* HAL.KdPortPutByte */
333 VOID
334 NTAPI
335 KdPortPutByte(
336 IN UCHAR ByteToSend)
337 {
338 if (!PortInitialized)
339 return;
340 KdPortPutByteEx(&DefaultPort, ByteToSend);
341 }
342
343 /* HAL.KdPortPutByteEx ; ReactOS-specific */
344 VOID
345 NTAPI
346 KdPortPutByteEx(
347 IN PKD_PORT_INFORMATION PortInformation,
348 IN UCHAR ByteToSend)
349 {
350 PUCHAR ComPortBase = (PUCHAR)PortInformation->BaseAddress;
351
352 while ((READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_TBE) == 0)
353 ;
354
355 WRITE_PORT_UCHAR(SER_THR(ComPortBase), ByteToSend);
356 }
357
358
359 /* HAL.KdPortRestore */
360 VOID
361 NTAPI
362 KdPortRestore(VOID)
363 {
364 UNIMPLEMENTED;
365 }
366
367
368 /* HAL.KdPortSave */
369 VOID
370 NTAPI
371 KdPortSave(VOID)
372 {
373 UNIMPLEMENTED;
374 }
375
376
377 /* HAL.KdPortDisableInterrupts */
378 BOOLEAN
379 NTAPI
380 KdPortDisableInterrupts(VOID)
381 {
382 UCHAR ch;
383
384 if (!PortInitialized)
385 return FALSE;
386
387 ch = READ_PORT_UCHAR(SER_MCR(DefaultPort.BaseAddress));
388 ch &= (~(SR_MCR_OUT1 | SR_MCR_OUT2));
389 WRITE_PORT_UCHAR(SER_MCR(DefaultPort.BaseAddress), ch);
390
391 ch = READ_PORT_UCHAR(SER_IER(DefaultPort.BaseAddress));
392 ch &= (~SR_IER_ALL);
393 WRITE_PORT_UCHAR(SER_IER(DefaultPort.BaseAddress), ch);
394
395 return TRUE;
396 }
397
398
399 /* HAL.KdPortEnableInterrupts */
400 BOOLEAN
401 NTAPI
402 KdPortEnableInterrupts(VOID)
403 {
404 UCHAR ch;
405
406 if (PortInitialized == FALSE)
407 return FALSE;
408
409 ch = READ_PORT_UCHAR(SER_IER(DefaultPort.BaseAddress));
410 ch &= (~SR_IER_ALL);
411 ch |= SR_IER_ERDA;
412 WRITE_PORT_UCHAR(SER_IER(DefaultPort.BaseAddress), ch);
413
414 ch = READ_PORT_UCHAR(SER_MCR(DefaultPort.BaseAddress));
415 ch &= (~SR_MCR_LOOP);
416 ch |= (SR_MCR_OUT1 | SR_MCR_OUT2);
417 WRITE_PORT_UCHAR(SER_MCR(DefaultPort.BaseAddress), ch);
418
419 return TRUE;
420 }
421
422 /*
423 * @unimplemented
424 */
425 NTSTATUS
426 NTAPI
427 KdDebuggerInitialize0(
428 IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
429 {
430 return STATUS_NOT_IMPLEMENTED;
431 }
432
433 /*
434 * @unimplemented
435 */
436 NTSTATUS
437 NTAPI
438 KdDebuggerInitialize1(
439 IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
440 {
441 return STATUS_NOT_IMPLEMENTED;
442 }
443
444 /*
445 * @implemented
446 */
447 NTSTATUS
448 NTAPI
449 KdSave(
450 IN BOOLEAN SleepTransition)
451 {
452 /* Nothing to do on COM ports */
453 return STATUS_SUCCESS;
454 }
455
456 /*
457 * @implemented
458 */
459 NTSTATUS
460 NTAPI
461 KdRestore(
462 IN BOOLEAN SleepTransition)
463 {
464 /* Nothing to do on COM ports */
465 return STATUS_SUCCESS;
466 }
467
468 /*
469 * @unimplemented
470 */
471 VOID
472 NTAPI
473 KdSendPacket(
474 IN ULONG PacketType,
475 IN PSTRING MessageHeader,
476 IN PSTRING MessageData,
477 IN OUT PKD_CONTEXT Context)
478 {
479 UNIMPLEMENTED;
480 return;
481 }
482
483 /*
484 * @unimplemented
485 */
486 KDSTATUS
487 NTAPI
488 KdReceivePacket(
489 IN ULONG PacketType,
490 OUT PSTRING MessageHeader,
491 OUT PSTRING MessageData,
492 OUT PULONG DataLength,
493 IN OUT PKD_CONTEXT Context)
494 {
495 UNIMPLEMENTED;
496 return 0;
497 }
498
499 /* EOF */