61e5d42d04dcb5828359bcc470109bad992a2580
[reactos.git] / reactos / hal / halx86 / kdbg.c
1 /* $Id: kdbg.c,v 1.7 2003/12/28 22:38:09 fireball Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/hal/x86/kdbg.c
6 * PURPOSE: Serial i/o functions for the kernel debugger.
7 * PROGRAMMER: Emanuele Aliberti
8 * Eric Kohl
9 * UPDATE HISTORY:
10 * Created 05/09/99
11 */
12
13 /* INCLUDES *****************************************************************/
14
15 #include <ddk/ntddk.h>
16
17 #define NDEBUG
18 #include <internal/debug.h>
19
20
21 #define DEFAULT_BAUD_RATE 19200
22
23
24 /* MACROS *******************************************************************/
25
26 #define SER_RBR(x) ((x)+0)
27 #define SER_THR(x) ((x)+0)
28 #define SER_DLL(x) ((x)+0)
29 #define SER_IER(x) ((x)+1)
30 #define SR_IER_ERDA 0x01
31 #define SR_IER_ETHRE 0x02
32 #define SR_IER_ERLSI 0x04
33 #define SR_IER_EMS 0x08
34 #define SR_IER_ALL 0x0F
35 #define SER_DLM(x) ((x)+1)
36 #define SER_IIR(x) ((x)+2)
37 #define SER_LCR(x) ((x)+3)
38 #define SR_LCR_CS5 0x00
39 #define SR_LCR_CS6 0x01
40 #define SR_LCR_CS7 0x02
41 #define SR_LCR_CS8 0x03
42 #define SR_LCR_ST1 0x00
43 #define SR_LCR_ST2 0x04
44 #define SR_LCR_PNO 0x00
45 #define SR_LCR_POD 0x08
46 #define SR_LCR_PEV 0x18
47 #define SR_LCR_PMK 0x28
48 #define SR_LCR_PSP 0x38
49 #define SR_LCR_BRK 0x40
50 #define SR_LCR_DLAB 0x80
51 #define SER_MCR(x) ((x)+4)
52 #define SR_MCR_DTR 0x01
53 #define SR_MCR_RTS 0x02
54 #define SR_MCR_OUT1 0x04
55 #define SR_MCR_OUT2 0x08
56 #define SR_MCR_LOOP 0x10
57 #define SER_LSR(x) ((x)+5)
58 #define SR_LSR_DR 0x01
59 #define SR_LSR_TBE 0x20
60 #define SER_MSR(x) ((x)+6)
61 #define SR_MSR_CTS 0x10
62 #define SR_MSR_DSR 0x20
63 #define SER_SCR(x) ((x)+7)
64
65
66 /* GLOBAL VARIABLES *********************************************************/
67
68 ULONG EXPORTED KdComPortInUse = 0;
69
70
71 /* STATIC VARIABLES *********************************************************/
72
73 static ULONG ComPort = 0;
74 static ULONG BaudRate = 0;
75 static PUCHAR PortBase = (PUCHAR)0;
76
77 /* The com port must only be initialized once! */
78 static BOOLEAN PortInitialized = FALSE;
79
80
81 /* STATIC FUNCTIONS *********************************************************/
82
83 static BOOLEAN
84 KdpDoesComPortExist (PUCHAR BaseAddress)
85 {
86 BOOLEAN found;
87 BYTE mcr;
88 BYTE msr;
89
90 found = FALSE;
91
92 /* save Modem Control Register (MCR) */
93 mcr = READ_PORT_UCHAR (SER_MCR(BaseAddress));
94
95 /* enable loop mode (set Bit 4 of the MCR) */
96 WRITE_PORT_UCHAR (SER_MCR(BaseAddress), 0x10);
97
98 /* clear all modem output bits */
99 WRITE_PORT_UCHAR (SER_MCR(BaseAddress), 0x10);
100
101 /* read the Modem Status Register */
102 msr = READ_PORT_UCHAR (SER_MSR(BaseAddress));
103
104 /*
105 * the upper nibble of the MSR (modem output bits) must be
106 * equal to the lower nibble of the MCR (modem input bits)
107 */
108 if ((msr & 0xF0) == 0x00)
109 {
110 /* set all modem output bits */
111 WRITE_PORT_UCHAR (SER_MCR(BaseAddress), 0x1F);
112
113 /* read the Modem Status Register */
114 msr = READ_PORT_UCHAR (SER_MSR(BaseAddress));
115
116 /*
117 * the upper nibble of the MSR (modem output bits) must be
118 * equal to the lower nibble of the MCR (modem input bits)
119 */
120 if ((msr & 0xF0) == 0xF0)
121 found = TRUE;
122 }
123
124 /* restore MCR */
125 WRITE_PORT_UCHAR (SER_MCR(BaseAddress), mcr);
126
127 return (found);
128 }
129
130
131 /* FUNCTIONS ****************************************************************/
132
133 /* HAL.KdPortInitialize */
134 BOOLEAN
135 STDCALL
136 KdPortInitialize (
137 PKD_PORT_INFORMATION PortInformation,
138 DWORD Unknown1,
139 DWORD Unknown2
140 )
141 {
142 ULONG BaseArray[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
143 char buffer[80];
144 ULONG divisor;
145 BYTE lcr;
146
147 if (PortInitialized == FALSE)
148 {
149 if (PortInformation->BaudRate != 0)
150 {
151 BaudRate = PortInformation->BaudRate;
152 }
153 else
154 {
155 BaudRate = DEFAULT_BAUD_RATE;
156 }
157
158 if (PortInformation->ComPort == 0)
159 {
160 if (KdpDoesComPortExist ((PUCHAR)BaseArray[2]))
161 {
162 PortBase = (PUCHAR)BaseArray[2];
163 ComPort = 2;
164 PortInformation->BaseAddress = (ULONG)PortBase;
165 PortInformation->ComPort = ComPort;
166 #ifndef NDEBUG
167 sprintf (buffer,
168 "\nSerial port COM%ld found at 0x%lx\n",
169 ComPort,
170 (ULONG)PortBase);
171 HalDisplayString (buffer);
172 #endif /* NDEBUG */
173 }
174 else if (KdpDoesComPortExist ((PUCHAR)BaseArray[1]))
175 {
176 PortBase = (PUCHAR)BaseArray[1];
177 ComPort = 1;
178 PortInformation->BaseAddress = (ULONG)PortBase;
179 PortInformation->ComPort = ComPort;
180 #ifndef NDEBUG
181 sprintf (buffer,
182 "\nSerial port COM%ld found at 0x%lx\n",
183 ComPort,
184 (ULONG)PortBase);
185 HalDisplayString (buffer);
186 #endif /* NDEBUG */
187 }
188 else
189 {
190 sprintf (buffer,
191 "\nKernel Debugger: No COM port found!!!\n\n");
192 HalDisplayString (buffer);
193 return FALSE;
194 }
195 }
196 else
197 {
198 if (KdpDoesComPortExist ((PUCHAR)BaseArray[PortInformation->ComPort]))
199 {
200 PortBase = (PUCHAR)BaseArray[PortInformation->ComPort];
201 ComPort = PortInformation->ComPort;
202 PortInformation->BaseAddress = (ULONG)PortBase;
203 #ifndef NDEBUG
204 sprintf (buffer,
205 "\nSerial port COM%ld found at 0x%lx\n",
206 ComPort,
207 (ULONG)PortBase);
208 HalDisplayString (buffer);
209 #endif /* NDEBUG */
210 }
211 else
212 {
213 sprintf (buffer,
214 "\nKernel Debugger: No serial port found!!!\n\n");
215 HalDisplayString (buffer);
216 return FALSE;
217 }
218 }
219
220 PortInitialized = TRUE;
221 }
222
223 /*
224 * set baud rate and data format (8N1)
225 */
226
227 /* turn on DTR and RTS */
228 WRITE_PORT_UCHAR (SER_MCR(PortBase), SR_MCR_DTR | SR_MCR_RTS);
229
230 /* set DLAB */
231 lcr = READ_PORT_UCHAR (SER_LCR(PortBase)) | SR_LCR_DLAB;
232 WRITE_PORT_UCHAR (SER_LCR(PortBase), lcr);
233
234 /* set baud rate */
235 divisor = 115200 / BaudRate;
236 WRITE_PORT_UCHAR (SER_DLL(PortBase), (UCHAR)(divisor & 0xff));
237 WRITE_PORT_UCHAR (SER_DLM(PortBase), (UCHAR)((divisor >> 8) & 0xff));
238
239 /* reset DLAB and set 8N1 format */
240 WRITE_PORT_UCHAR (SER_LCR(PortBase),
241 SR_LCR_CS8 | SR_LCR_ST1 | SR_LCR_PNO);
242
243 /* read junk out of the RBR */
244 lcr = READ_PORT_UCHAR (SER_RBR(PortBase));
245
246 /*
247 * set global info
248 */
249 KdComPortInUse = (ULONG)PortBase;
250
251 /*
252 * print message to blue screen
253 */
254 sprintf (buffer,
255 "\nKernel Debugger: COM%ld (Port 0x%lx) BaudRate %ld\n\n",
256 ComPort,
257 (ULONG)PortBase,
258 BaudRate);
259
260 HalDisplayString (buffer);
261
262 return TRUE;
263 }
264
265
266 /* HAL.KdPortInitializeEx */
267 BOOLEAN
268 STDCALL
269 KdPortInitializeEx (
270 PKD_PORT_INFORMATION PortInformation,
271 DWORD Unknown1,
272 DWORD Unknown2
273 )
274 {
275 ULONG BaseArray[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
276 PUCHAR ComPortBase;
277 char buffer[80];
278 ULONG divisor;
279 BYTE lcr;
280
281 if (PortInformation->BaudRate == 0)
282 {
283 PortInformation->BaudRate = DEFAULT_BAUD_RATE;
284 }
285
286 if (PortInformation->ComPort == 0)
287 {
288 return FALSE;
289 }
290 else
291 {
292 if (KdpDoesComPortExist ((PUCHAR)BaseArray[PortInformation->ComPort]))
293 {
294 ComPortBase = (PUCHAR)BaseArray[PortInformation->ComPort];
295 PortInformation->BaseAddress = (ULONG)ComPortBase;
296 #ifndef NDEBUG
297 sprintf (buffer,
298 "\nSerial port COM%ld found at 0x%lx\n",
299 PortInformation->ComPort,
300 (ULONG)ComPortBase];
301 HalDisplayString (buffer);
302 #endif /* NDEBUG */
303 }
304 else
305 {
306 sprintf (buffer,
307 "\nKernel Debugger: Serial port not found!!!\n\n");
308 HalDisplayString (buffer);
309 return FALSE;
310 }
311 }
312
313 /*
314 * set baud rate and data format (8N1)
315 */
316
317 /* turn on DTR and RTS */
318 WRITE_PORT_UCHAR (SER_MCR(ComPortBase), SR_MCR_DTR | SR_MCR_RTS);
319
320 /* set DLAB */
321 lcr = READ_PORT_UCHAR (SER_LCR(ComPortBase)) | SR_LCR_DLAB;
322 WRITE_PORT_UCHAR (SER_LCR(ComPortBase), lcr);
323
324 /* set baud rate */
325 divisor = 115200 / PortInformation->BaudRate;
326 WRITE_PORT_UCHAR (SER_DLL(ComPortBase), (UCHAR)(divisor & 0xff));
327 WRITE_PORT_UCHAR (SER_DLM(ComPortBase), (UCHAR)((divisor >> 8) & 0xff));
328
329 /* reset DLAB and set 8N1 format */
330 WRITE_PORT_UCHAR (SER_LCR(ComPortBase),
331 SR_LCR_CS8 | SR_LCR_ST1 | SR_LCR_PNO);
332
333 /* read junk out of the RBR */
334 lcr = READ_PORT_UCHAR (SER_RBR(ComPortBase));
335
336 #ifndef NDEBUG
337
338 /*
339 * print message to blue screen
340 */
341 sprintf (buffer,
342 "\nKernel Debugger: COM%ld (Port 0x%lx) BaudRate %ld\n\n",
343 PortInformation->ComPort,
344 (ULONG)ComPortBase,
345 PortInformation->BaudRate);
346
347 HalDisplayString (buffer);
348
349 #endif /* NDEBUG */
350
351 return TRUE;
352 }
353
354
355 /* HAL.KdPortGetByte */
356 BOOLEAN
357 STDCALL
358 KdPortGetByte (
359 PUCHAR ByteRecieved
360 )
361 {
362 if (PortInitialized == FALSE)
363 return FALSE;
364
365 if ((READ_PORT_UCHAR (SER_LSR(PortBase)) & SR_LSR_DR))
366 {
367 *ByteRecieved = READ_PORT_UCHAR (SER_RBR(PortBase));
368 return TRUE;
369 }
370
371 return FALSE;
372 }
373
374
375 /* HAL.KdPortGetByteEx */
376 BOOLEAN
377 STDCALL
378 KdPortGetByteEx (
379 PKD_PORT_INFORMATION PortInformation,
380 PUCHAR ByteRecieved
381 )
382 {
383 PUCHAR ComPortBase = (PUCHAR)PortInformation->BaseAddress;
384
385 if ((READ_PORT_UCHAR (SER_LSR(ComPortBase)) & SR_LSR_DR))
386 {
387 *ByteRecieved = READ_PORT_UCHAR (SER_RBR(ComPortBase));
388 return TRUE;
389 }
390
391 return FALSE;
392 }
393
394
395 /* HAL.KdPortPollByte */
396 BOOLEAN
397 STDCALL
398 KdPortPollByte (
399 PUCHAR ByteRecieved
400 )
401 {
402 if (PortInitialized == FALSE)
403 return FALSE;
404
405 while ((READ_PORT_UCHAR (SER_LSR(PortBase)) & SR_LSR_DR) == 0)
406 ;
407
408 *ByteRecieved = READ_PORT_UCHAR (SER_RBR(PortBase));
409
410 return TRUE;
411 }
412
413
414 /* HAL.KdPortPollByteEx */
415 BOOLEAN
416 STDCALL
417 KdPortPollByteEx (
418 PKD_PORT_INFORMATION PortInformation,
419 PUCHAR ByteRecieved
420 )
421 {
422 PUCHAR ComPortBase = (PUCHAR)PortInformation->BaseAddress;
423
424 while ((READ_PORT_UCHAR (SER_LSR(ComPortBase)) & SR_LSR_DR) == 0)
425 ;
426
427 *ByteRecieved = READ_PORT_UCHAR (SER_RBR(ComPortBase));
428
429 return TRUE;
430 }
431
432
433
434
435 /* HAL.KdPortPutByte */
436 VOID
437 STDCALL
438 KdPortPutByte (
439 UCHAR ByteToSend
440 )
441 {
442 if (PortInitialized == FALSE)
443 return;
444
445 while ((READ_PORT_UCHAR (SER_LSR(PortBase)) & SR_LSR_TBE) == 0)
446 ;
447
448 WRITE_PORT_UCHAR (SER_THR(PortBase), ByteToSend);
449 }
450
451 /* HAL.KdPortPutByteEx */
452 VOID
453 STDCALL
454 KdPortPutByteEx (
455 PKD_PORT_INFORMATION PortInformation,
456 UCHAR ByteToSend
457 )
458 {
459 PUCHAR ComPortBase = (PUCHAR)PortInformation->BaseAddress;
460
461 while ((READ_PORT_UCHAR (SER_LSR(ComPortBase)) & SR_LSR_TBE) == 0)
462 ;
463
464 WRITE_PORT_UCHAR (SER_THR(ComPortBase), ByteToSend);
465 }
466
467
468 /* HAL.KdPortRestore */
469 VOID
470 STDCALL
471 KdPortRestore (
472 VOID
473 )
474 {
475 }
476
477
478 /* HAL.KdPortSave */
479 VOID
480 STDCALL
481 KdPortSave (
482 VOID
483 )
484 {
485 }
486
487
488 /* HAL.KdPortDisableInterrupts */
489 BOOLEAN
490 STDCALL
491 KdPortDisableInterrupts()
492 {
493 UCHAR ch;
494
495 if (PortInitialized == FALSE)
496 return FALSE;
497
498 ch = READ_PORT_UCHAR (SER_MCR (PortBase));
499 ch &= (~(SR_MCR_OUT1 | SR_MCR_OUT2));
500 WRITE_PORT_UCHAR (SER_MCR (PortBase), ch);
501
502 ch = READ_PORT_UCHAR (SER_IER (PortBase));
503 ch &= (~SR_IER_ALL);
504 WRITE_PORT_UCHAR (SER_IER (PortBase), ch);
505
506 return TRUE;
507 }
508
509
510 /* HAL.KdPortEnableInterrupts */
511 BOOLEAN
512 STDCALL
513 KdPortEnableInterrupts()
514 {
515 UCHAR ch;
516
517 if (PortInitialized == FALSE)
518 return FALSE;
519
520 ch = READ_PORT_UCHAR (SER_IER (PortBase));
521 ch &= (~SR_IER_ALL);
522 ch |= SR_IER_ERDA;
523 WRITE_PORT_UCHAR (SER_IER (PortBase), ch);
524
525 ch = READ_PORT_UCHAR (SER_MCR (PortBase));
526 ch &= (~SR_MCR_LOOP);
527 ch |= (SR_MCR_OUT1 | SR_MCR_OUT2);
528 WRITE_PORT_UCHAR (SER_MCR (PortBase), ch);
529
530 return TRUE;
531 }
532
533 /* EOF */