:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / hal / halx86 / kdbg.c
1 /* $Id$
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), divisor & 0xff);
237         WRITE_PORT_UCHAR (SER_DLM(PortBase), (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), divisor & 0xff);
327         WRITE_PORT_UCHAR (SER_DLM(ComPortBase), (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 */