ba0b552234a929a0584eb20f57700d291658decb
[reactos.git] / reactos / hal / halx86 / kdbg.c
1 /* $Id: kdbg.c,v 1.3 2002/01/23 23:39:24 chorns 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), 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.KdPortGetByte */
267 BOOLEAN
268 STDCALL
269 KdPortGetByte (
270 PUCHAR ByteRecieved
271 )
272 {
273 if (PortInitialized == FALSE)
274 return FALSE;
275
276 if ((READ_PORT_UCHAR (SER_LSR(PortBase)) & SR_LSR_DR))
277 {
278 *ByteRecieved = READ_PORT_UCHAR (SER_RBR(PortBase));
279 return TRUE;
280 }
281
282 return FALSE;
283 }
284
285
286 /* HAL.KdPortPollByte */
287 BOOLEAN
288 STDCALL
289 KdPortPollByte (
290 PUCHAR ByteRecieved
291 )
292 {
293 if (PortInitialized == FALSE)
294 return FALSE;
295
296 while ((READ_PORT_UCHAR (SER_LSR(PortBase)) & SR_LSR_DR) == 0)
297 ;
298
299 *ByteRecieved = READ_PORT_UCHAR (SER_RBR(PortBase));
300
301 return TRUE;
302 }
303
304
305 /* HAL.KdPortPutByte */
306 VOID
307 STDCALL
308 KdPortPutByte (
309 UCHAR ByteToSend
310 )
311 {
312 if (PortInitialized == FALSE)
313 return;
314
315 while ((READ_PORT_UCHAR (SER_LSR(PortBase)) & SR_LSR_TBE) == 0)
316 ;
317
318 WRITE_PORT_UCHAR (SER_THR(PortBase), ByteToSend);
319 }
320
321
322 /* HAL.KdPortRestore */
323 VOID
324 STDCALL
325 KdPortRestore (
326 VOID
327 )
328 {
329 }
330
331
332 /* HAL.KdPortSave */
333 VOID
334 STDCALL
335 KdPortSave (
336 VOID
337 )
338 {
339 }
340
341
342 /* HAL.KdPortDisableInterrupts */
343 BOOLEAN
344 STDCALL
345 KdPortDisableInterrupts()
346 {
347 UCHAR ch;
348
349 if (PortInitialized == FALSE)
350 return FALSE;
351
352 ch = READ_PORT_UCHAR (SER_MCR (PortBase));
353 ch &= (~(SR_MCR_OUT1 | SR_MCR_OUT2));
354 WRITE_PORT_UCHAR (SER_MCR (PortBase), ch);
355
356 ch = READ_PORT_UCHAR (SER_IER (PortBase));
357 ch &= (~SR_IER_ALL);
358 WRITE_PORT_UCHAR (SER_IER (PortBase), ch);
359
360 return TRUE;
361 }
362
363
364 /* HAL.KdPortEnableInterrupts */
365 BOOLEAN
366 STDCALL
367 KdPortEnableInterrupts()
368 {
369 UCHAR ch;
370
371 if (PortInitialized == FALSE)
372 return FALSE;
373
374 ch = READ_PORT_UCHAR (SER_IER (PortBase));
375 ch &= (~SR_IER_ALL);
376 ch |= SR_IER_ERDA;
377 WRITE_PORT_UCHAR (SER_IER (PortBase), ch);
378
379 ch = READ_PORT_UCHAR (SER_MCR (PortBase));
380 ch &= (~SR_MCR_LOOP);
381 ch |= (SR_MCR_OUT1 | SR_MCR_OUT2);
382 WRITE_PORT_UCHAR (SER_MCR (PortBase), ch);
383
384 return TRUE;
385 }
386
387 /* EOF */