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