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
10 /* INCLUDES *****************************************************************/
21 #include <ioaccess.h> /* port intrinsics */
23 typedef struct _KD_PORT_INFORMATION
27 ULONG_PTR BaseAddress
;
28 } KD_PORT_INFORMATION
, *PKD_PORT_INFORMATION
;
33 IN PKD_PORT_INFORMATION PortInformation
,
40 IN PKD_PORT_INFORMATION PortInformation
,
41 OUT PUCHAR ByteReceived
);
46 IN PKD_PORT_INFORMATION PortInformation
,
47 OUT PUCHAR ByteReceived
);
52 IN PKD_PORT_INFORMATION PortInformation
,
55 #define DEFAULT_BAUD_RATE 19200
58 const ULONG BaseArray
[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
60 const ULONG BaseArray
[2] = {0, 0x800003f8};
61 #elif defined(_M_MIPS)
62 const ULONG BaseArray
[3] = {0, 0x80006000, 0x80007000};
64 const ULONG BaseArray
[2] = {0, 0xF1012000};
65 #elif defined(_M_AMD64)
66 const ULONG BaseArray
[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
68 #error Unknown architecture
71 /* MACROS *******************************************************************/
73 #define SER_RBR(x) ((PUCHAR)(x)+0)
74 #define SER_THR(x) ((PUCHAR)(x)+0)
75 #define SER_DLL(x) ((PUCHAR)(x)+0)
76 #define SER_IER(x) ((PUCHAR)(x)+1)
77 #define SR_IER_ERDA 0x01
78 #define SR_IER_ETHRE 0x02
79 #define SR_IER_ERLSI 0x04
80 #define SR_IER_EMS 0x08
81 #define SR_IER_ALL 0x0F
82 #define SER_DLM(x) ((PUCHAR)(x)+1)
83 #define SER_IIR(x) ((PUCHAR)(x)+2)
84 #define SER_FCR(x) ((PUCHAR)(x)+2)
85 #define SR_FCR_ENABLE_FIFO 0x01
86 #define SR_FCR_CLEAR_RCVR 0x02
87 #define SR_FCR_CLEAR_XMIT 0x04
88 #define SER_LCR(x) ((PUCHAR)(x)+3)
89 #define SR_LCR_CS5 0x00
90 #define SR_LCR_CS6 0x01
91 #define SR_LCR_CS7 0x02
92 #define SR_LCR_CS8 0x03
93 #define SR_LCR_ST1 0x00
94 #define SR_LCR_ST2 0x04
95 #define SR_LCR_PNO 0x00
96 #define SR_LCR_POD 0x08
97 #define SR_LCR_PEV 0x18
98 #define SR_LCR_PMK 0x28
99 #define SR_LCR_PSP 0x38
100 #define SR_LCR_BRK 0x40
101 #define SR_LCR_DLAB 0x80
102 #define SER_MCR(x) ((PUCHAR)(x)+4)
103 #define SR_MCR_DTR 0x01
104 #define SR_MCR_RTS 0x02
105 #define SR_MCR_OUT1 0x04
106 #define SR_MCR_OUT2 0x08
107 #define SR_MCR_LOOP 0x10
108 #define SER_LSR(x) ((PUCHAR)(x)+5)
109 #define SR_LSR_DR 0x01
110 #define SR_LSR_TBE 0x20
111 #define SER_MSR(x) ((PUCHAR)(x)+6)
112 #define SR_MSR_CTS 0x10
113 #define SR_MSR_DSR 0x20
114 #define SER_SCR(x) ((PUCHAR)(x)+7)
117 /* GLOBAL VARIABLES *********************************************************/
119 /* STATIC VARIABLES *********************************************************/
121 static KD_PORT_INFORMATION DefaultPort
= { 0, 0, 0 };
123 /* The com port must only be initialized once! */
124 static BOOLEAN PortInitialized
= FALSE
;
127 /* STATIC FUNCTIONS *********************************************************/
131 IN ULONG_PTR BaseAddress
)
139 /* save Modem Control Register (MCR) */
140 mcr
= READ_PORT_UCHAR(SER_MCR(BaseAddress
));
142 /* enable loop mode (set Bit 4 of the MCR) */
143 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), SR_MCR_LOOP
);
145 /* clear all modem output bits */
146 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), SR_MCR_LOOP
);
148 /* read the Modem Status Register */
149 msr
= READ_PORT_UCHAR(SER_MSR(BaseAddress
));
152 * the upper nibble of the MSR (modem output bits) must be
153 * equal to the lower nibble of the MCR (modem input bits)
155 if ((msr
& 0xF0) == 0x00)
157 /* set all modem output bits */
158 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), SR_MCR_DTR
| SR_MCR_RTS
| SR_MCR_OUT1
| SR_MCR_OUT2
| SR_MCR_LOOP
);
160 /* read the Modem Status Register */
161 msr
= READ_PORT_UCHAR(SER_MSR(BaseAddress
));
164 * the upper nibble of the MSR (modem output bits) must be
165 * equal to the lower nibble of the MCR (modem input bits)
167 if ((msr
& 0xF0) == 0xF0)
170 * setup a resonable state for the port:
171 * enable fifo and clear recieve/transmit buffers
173 WRITE_PORT_UCHAR(SER_FCR(BaseAddress
),
174 (SR_FCR_ENABLE_FIFO
| SR_FCR_CLEAR_RCVR
| SR_FCR_CLEAR_XMIT
));
175 WRITE_PORT_UCHAR(SER_FCR(BaseAddress
), 0);
176 READ_PORT_UCHAR(SER_RBR(BaseAddress
));
177 WRITE_PORT_UCHAR(SER_IER(BaseAddress
), 0);
183 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), mcr
);
189 /* FUNCTIONS ****************************************************************/
193 IN PDRIVER_OBJECT DriverObject
,
194 IN PUNICODE_STRING RegistryPath
)
196 return STATUS_SUCCESS
;
199 /* HAL.KdPortInitialize */
203 IN PKD_PORT_INFORMATION PortInformation
,
210 if (!PortInitialized
)
212 DefaultPort
.BaudRate
= PortInformation
->BaudRate
;
214 if (PortInformation
->ComPort
== 0)
216 for (i
= sizeof(BaseArray
) / sizeof(BaseArray
[0]) - 1; i
> 0; i
--)
218 if (KdpDoesComPortExist(BaseArray
[i
]))
220 DefaultPort
.BaseAddress
= BaseArray
[i
];
221 DefaultPort
.ComPort
= i
;
222 PortInformation
->BaseAddress
= DefaultPort
.BaseAddress
;
223 PortInformation
->ComPort
= DefaultPort
.ComPort
;
230 "\nKernel Debugger: No COM port found!\n\n");
231 HalDisplayString(buffer
);
236 PortInitialized
= TRUE
;
239 /* initialize port */
240 if (!KdPortInitializeEx(&DefaultPort
, Unknown1
, Unknown2
))
243 /* set global info */
244 *KdComPortInUse
= (PUCHAR
)DefaultPort
.BaseAddress
;
250 /* HAL.KdPortInitializeEx */
254 IN PKD_PORT_INFORMATION PortInformation
,
258 ULONG_PTR ComPortBase
;
268 if (PortInformation
->BaudRate
== 0)
269 PortInformation
->BaudRate
= DEFAULT_BAUD_RATE
;
271 if (PortInformation
->ComPort
== 0)
274 if (!KdpDoesComPortExist(BaseArray
[PortInformation
->ComPort
]))
277 "\nKernel Debugger: Serial port not found!\n\n");
278 HalDisplayString(buffer
);
282 ComPortBase
= BaseArray
[PortInformation
->ComPort
];
283 PortInformation
->BaseAddress
= ComPortBase
;
286 "\nSerial port COM%ld found at 0x%lx\n",
287 PortInformation
->ComPort
,
289 HalDisplayString(buffer
);
292 /* set baud rate and data format (8N1) */
294 /* turn on DTR and RTS */
295 WRITE_PORT_UCHAR(SER_MCR(ComPortBase
), SR_MCR_DTR
| SR_MCR_RTS
);
298 lcr
= READ_PORT_UCHAR(SER_LCR(ComPortBase
)) | SR_LCR_DLAB
;
299 WRITE_PORT_UCHAR(SER_LCR(ComPortBase
), lcr
);
302 divisor
= 115200 / PortInformation
->BaudRate
;
303 WRITE_PORT_UCHAR(SER_DLL(ComPortBase
), (UCHAR
)(divisor
& 0xff));
304 WRITE_PORT_UCHAR(SER_DLM(ComPortBase
), (UCHAR
)((divisor
>> 8) & 0xff));
306 /* reset DLAB and set 8N1 format */
307 WRITE_PORT_UCHAR(SER_LCR(ComPortBase
),
308 SR_LCR_CS8
| SR_LCR_ST1
| SR_LCR_PNO
);
310 /* read junk out of the RBR */
311 lcr
= READ_PORT_UCHAR(SER_RBR(ComPortBase
));
314 /* print message to blue screen */
316 "\nKernel Debugger: COM%ld (Port 0x%lx) BaudRate %ld\n\n",
317 PortInformation
->ComPort
,
319 PortInformation
->BaudRate
);
321 HalDisplayString(buffer
);
328 /* HAL.KdPortGetByte */
332 OUT PUCHAR ByteReceived
)
334 if (!PortInitialized
)
336 return KdPortGetByteEx(&DefaultPort
, ByteReceived
);
340 /* HAL.KdPortGetByteEx */
344 IN PKD_PORT_INFORMATION PortInformation
,
345 OUT PUCHAR ByteReceived
)
347 PUCHAR ComPortBase
= (PUCHAR
)PortInformation
->BaseAddress
;
349 if ((READ_PORT_UCHAR(SER_LSR(ComPortBase
)) & SR_LSR_DR
))
351 *ByteReceived
= READ_PORT_UCHAR(SER_RBR(ComPortBase
));
359 /* HAL.KdPortPollByte */
363 OUT PUCHAR ByteReceived
)
365 if (!PortInitialized
)
367 return KdPortPollByteEx(&DefaultPort
, ByteReceived
);
371 /* HAL.KdPortPollByteEx */
375 IN PKD_PORT_INFORMATION PortInformation
,
376 OUT PUCHAR ByteReceived
)
378 PUCHAR ComPortBase
= (PUCHAR
)PortInformation
->BaseAddress
;
380 while ((READ_PORT_UCHAR(SER_LSR(ComPortBase
)) & SR_LSR_DR
) == 0)
383 *ByteReceived
= READ_PORT_UCHAR(SER_RBR(ComPortBase
));
389 /* HAL.KdPortPutByte */
395 if (!PortInitialized
)
397 KdPortPutByteEx(&DefaultPort
, ByteToSend
);
400 /* HAL.KdPortPutByteEx */
404 IN PKD_PORT_INFORMATION PortInformation
,
407 PUCHAR ComPortBase
= (PUCHAR
)PortInformation
->BaseAddress
;
409 while ((READ_PORT_UCHAR(SER_LSR(ComPortBase
)) & SR_LSR_TBE
) == 0)
412 WRITE_PORT_UCHAR(SER_THR(ComPortBase
), ByteToSend
);
416 /* HAL.KdPortRestore */
434 /* HAL.KdPortDisableInterrupts */
437 KdPortDisableInterrupts(VOID
)
441 if (!PortInitialized
)
444 ch
= READ_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
));
445 ch
&= (~(SR_MCR_OUT1
| SR_MCR_OUT2
));
446 WRITE_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
), ch
);
448 ch
= READ_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
));
450 WRITE_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
), ch
);
456 /* HAL.KdPortEnableInterrupts */
459 KdPortEnableInterrupts(VOID
)
463 if (PortInitialized
== FALSE
)
466 ch
= READ_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
));
469 WRITE_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
), ch
);
471 ch
= READ_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
));
472 ch
&= (~SR_MCR_LOOP
);
473 ch
|= (SR_MCR_OUT1
| SR_MCR_OUT2
);
474 WRITE_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
), ch
);
484 KdDebuggerInitialize0(
485 IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL
)
488 return STATUS_NOT_IMPLEMENTED
;
496 KdDebuggerInitialize1(
497 IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL
)
500 return STATUS_NOT_IMPLEMENTED
;
509 IN BOOLEAN SleepTransition
)
511 /* Nothing to do on COM ports */
512 return STATUS_SUCCESS
;
521 IN BOOLEAN SleepTransition
)
523 /* Nothing to do on COM ports */
524 return STATUS_SUCCESS
;
534 IN PSTRING MessageHeader
,
535 IN PSTRING MessageData
,
536 IN OUT PKD_CONTEXT Context
)
549 OUT PSTRING MessageHeader
,
550 OUT PSTRING MessageData
,
551 OUT PULONG DataLength
,
552 IN OUT PKD_CONTEXT Context
)