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 *****************************************************************/
22 typedef struct _KD_PORT_INFORMATION
27 } KD_PORT_INFORMATION
, *PKD_PORT_INFORMATION
;
32 IN PKD_PORT_INFORMATION PortInformation
,
39 IN PKD_PORT_INFORMATION PortInformation
,
40 OUT PUCHAR ByteReceived
);
45 IN PKD_PORT_INFORMATION PortInformation
,
46 OUT PUCHAR ByteReceived
);
51 IN PKD_PORT_INFORMATION PortInformation
,
54 #define DEFAULT_BAUD_RATE 19200
57 const ULONG BaseArray
[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
59 const ULONG BaseArray
[2] = {0, 0x800003f8};
60 #elif defined(_M_MIPS)
61 const ULONG BaseArray
[3] = {0, 0x80006000, 0x80007000};
63 const ULONG BaseArray
[2] = {0, 0xF1012000};
65 #error Unknown architecture
68 /* MACROS *******************************************************************/
70 #define SER_RBR(x) ((PUCHAR)(x)+0)
71 #define SER_THR(x) ((PUCHAR)(x)+0)
72 #define SER_DLL(x) ((PUCHAR)(x)+0)
73 #define SER_IER(x) ((PUCHAR)(x)+1)
74 #define SR_IER_ERDA 0x01
75 #define SR_IER_ETHRE 0x02
76 #define SR_IER_ERLSI 0x04
77 #define SR_IER_EMS 0x08
78 #define SR_IER_ALL 0x0F
79 #define SER_DLM(x) ((PUCHAR)(x)+1)
80 #define SER_IIR(x) ((PUCHAR)(x)+2)
81 #define SER_FCR(x) ((PUCHAR)(x)+2)
82 #define SR_FCR_ENABLE_FIFO 0x01
83 #define SR_FCR_CLEAR_RCVR 0x02
84 #define SR_FCR_CLEAR_XMIT 0x04
85 #define SER_LCR(x) ((PUCHAR)(x)+3)
86 #define SR_LCR_CS5 0x00
87 #define SR_LCR_CS6 0x01
88 #define SR_LCR_CS7 0x02
89 #define SR_LCR_CS8 0x03
90 #define SR_LCR_ST1 0x00
91 #define SR_LCR_ST2 0x04
92 #define SR_LCR_PNO 0x00
93 #define SR_LCR_POD 0x08
94 #define SR_LCR_PEV 0x18
95 #define SR_LCR_PMK 0x28
96 #define SR_LCR_PSP 0x38
97 #define SR_LCR_BRK 0x40
98 #define SR_LCR_DLAB 0x80
99 #define SER_MCR(x) ((PUCHAR)(x)+4)
100 #define SR_MCR_DTR 0x01
101 #define SR_MCR_RTS 0x02
102 #define SR_MCR_OUT1 0x04
103 #define SR_MCR_OUT2 0x08
104 #define SR_MCR_LOOP 0x10
105 #define SER_LSR(x) ((PUCHAR)(x)+5)
106 #define SR_LSR_DR 0x01
107 #define SR_LSR_TBE 0x20
108 #define SER_MSR(x) ((PUCHAR)(x)+6)
109 #define SR_MSR_CTS 0x10
110 #define SR_MSR_DSR 0x20
111 #define SER_SCR(x) ((PUCHAR)(x)+7)
114 /* GLOBAL VARIABLES *********************************************************/
116 /* STATIC VARIABLES *********************************************************/
118 static KD_PORT_INFORMATION DefaultPort
= { 0, 0, 0 };
120 /* The com port must only be initialized once! */
121 static BOOLEAN PortInitialized
= FALSE
;
124 /* STATIC FUNCTIONS *********************************************************/
128 IN ULONG BaseAddress
)
136 /* save Modem Control Register (MCR) */
137 mcr
= READ_PORT_UCHAR(SER_MCR(BaseAddress
));
139 /* enable loop mode (set Bit 4 of the MCR) */
140 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), SR_MCR_LOOP
);
142 /* clear all modem output bits */
143 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), SR_MCR_LOOP
);
145 /* read the Modem Status Register */
146 msr
= READ_PORT_UCHAR(SER_MSR(BaseAddress
));
149 * the upper nibble of the MSR (modem output bits) must be
150 * equal to the lower nibble of the MCR (modem input bits)
152 if ((msr
& 0xF0) == 0x00)
154 /* set all modem output bits */
155 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), SR_MCR_DTR
| SR_MCR_RTS
| SR_MCR_OUT1
| SR_MCR_OUT2
| SR_MCR_LOOP
);
157 /* read the Modem Status Register */
158 msr
= READ_PORT_UCHAR(SER_MSR(BaseAddress
));
161 * the upper nibble of the MSR (modem output bits) must be
162 * equal to the lower nibble of the MCR (modem input bits)
164 if ((msr
& 0xF0) == 0xF0)
167 * setup a resonable state for the port:
168 * enable fifo and clear recieve/transmit buffers
170 WRITE_PORT_UCHAR(SER_FCR(BaseAddress
),
171 (SR_FCR_ENABLE_FIFO
| SR_FCR_CLEAR_RCVR
| SR_FCR_CLEAR_XMIT
));
172 WRITE_PORT_UCHAR(SER_FCR(BaseAddress
), 0);
173 READ_PORT_UCHAR(SER_RBR(BaseAddress
));
174 WRITE_PORT_UCHAR(SER_IER(BaseAddress
), 0);
180 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), mcr
);
186 /* FUNCTIONS ****************************************************************/
188 /* HAL.KdPortInitialize */
192 IN PKD_PORT_INFORMATION PortInformation
,
199 if (!PortInitialized
)
201 DefaultPort
.BaudRate
= PortInformation
->BaudRate
;
203 if (PortInformation
->ComPort
== 0)
205 for (i
= sizeof(BaseArray
) / sizeof(BaseArray
[0]) - 1; i
> 0; i
--)
207 if (KdpDoesComPortExist(BaseArray
[i
]))
209 DefaultPort
.BaseAddress
= BaseArray
[i
];
210 DefaultPort
.ComPort
= i
;
211 PortInformation
->BaseAddress
= DefaultPort
.BaseAddress
;
212 PortInformation
->ComPort
= DefaultPort
.ComPort
;
219 "\nKernel Debugger: No COM port found!\n\n");
220 HalDisplayString(buffer
);
225 PortInitialized
= TRUE
;
228 /* initialize port */
229 if (!KdPortInitializeEx(&DefaultPort
, Unknown1
, Unknown2
))
232 /* set global info */
233 *KdComPortInUse
= (PUCHAR
)DefaultPort
.BaseAddress
;
239 /* HAL.KdPortInitializeEx */
243 IN PKD_PORT_INFORMATION PortInformation
,
252 if (PortInformation
->BaudRate
== 0)
253 PortInformation
->BaudRate
= DEFAULT_BAUD_RATE
;
255 if (PortInformation
->ComPort
== 0)
258 if (!KdpDoesComPortExist(BaseArray
[PortInformation
->ComPort
]))
261 "\nKernel Debugger: Serial port not found!\n\n");
262 HalDisplayString(buffer
);
266 ComPortBase
= BaseArray
[PortInformation
->ComPort
];
267 PortInformation
->BaseAddress
= ComPortBase
;
270 "\nSerial port COM%ld found at 0x%lx\n",
271 PortInformation
->ComPort
,
273 HalDisplayString(buffer
);
276 /* set baud rate and data format (8N1) */
278 /* turn on DTR and RTS */
279 WRITE_PORT_UCHAR(SER_MCR(ComPortBase
), SR_MCR_DTR
| SR_MCR_RTS
);
282 lcr
= READ_PORT_UCHAR(SER_LCR(ComPortBase
)) | SR_LCR_DLAB
;
283 WRITE_PORT_UCHAR(SER_LCR(ComPortBase
), lcr
);
286 divisor
= 115200 / PortInformation
->BaudRate
;
287 WRITE_PORT_UCHAR(SER_DLL(ComPortBase
), (UCHAR
)(divisor
& 0xff));
288 WRITE_PORT_UCHAR(SER_DLM(ComPortBase
), (UCHAR
)((divisor
>> 8) & 0xff));
290 /* reset DLAB and set 8N1 format */
291 WRITE_PORT_UCHAR(SER_LCR(ComPortBase
),
292 SR_LCR_CS8
| SR_LCR_ST1
| SR_LCR_PNO
);
294 /* read junk out of the RBR */
295 lcr
= READ_PORT_UCHAR(SER_RBR(ComPortBase
));
298 /* print message to blue screen */
300 "\nKernel Debugger: COM%ld (Port 0x%lx) BaudRate %ld\n\n",
301 PortInformation
->ComPort
,
303 PortInformation
->BaudRate
);
305 HalDisplayString(buffer
);
312 /* HAL.KdPortGetByte */
316 OUT PUCHAR ByteReceived
)
318 if (!PortInitialized
)
320 return KdPortGetByteEx(&DefaultPort
, ByteReceived
);
324 /* HAL.KdPortGetByteEx */
328 IN PKD_PORT_INFORMATION PortInformation
,
329 OUT PUCHAR ByteReceived
)
331 PUCHAR ComPortBase
= (PUCHAR
)PortInformation
->BaseAddress
;
333 if ((READ_PORT_UCHAR(SER_LSR(ComPortBase
)) & SR_LSR_DR
))
335 *ByteReceived
= READ_PORT_UCHAR(SER_RBR(ComPortBase
));
343 /* HAL.KdPortPollByte */
347 OUT PUCHAR ByteReceived
)
349 if (!PortInitialized
)
351 return KdPortPollByteEx(&DefaultPort
, ByteReceived
);
355 /* HAL.KdPortPollByteEx */
359 IN PKD_PORT_INFORMATION PortInformation
,
360 OUT PUCHAR ByteReceived
)
362 PUCHAR ComPortBase
= (PUCHAR
)PortInformation
->BaseAddress
;
364 while ((READ_PORT_UCHAR(SER_LSR(ComPortBase
)) & SR_LSR_DR
) == 0)
367 *ByteReceived
= READ_PORT_UCHAR(SER_RBR(ComPortBase
));
373 /* HAL.KdPortPutByte */
379 if (!PortInitialized
)
381 KdPortPutByteEx(&DefaultPort
, ByteToSend
);
384 /* HAL.KdPortPutByteEx */
388 IN PKD_PORT_INFORMATION PortInformation
,
391 PUCHAR ComPortBase
= (PUCHAR
)PortInformation
->BaseAddress
;
393 while ((READ_PORT_UCHAR(SER_LSR(ComPortBase
)) & SR_LSR_TBE
) == 0)
396 WRITE_PORT_UCHAR(SER_THR(ComPortBase
), ByteToSend
);
400 /* HAL.KdPortRestore */
418 /* HAL.KdPortDisableInterrupts */
421 KdPortDisableInterrupts(VOID
)
425 if (!PortInitialized
)
428 ch
= READ_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
));
429 ch
&= (~(SR_MCR_OUT1
| SR_MCR_OUT2
));
430 WRITE_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
), ch
);
432 ch
= READ_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
));
434 WRITE_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
), ch
);
440 /* HAL.KdPortEnableInterrupts */
443 KdPortEnableInterrupts(VOID
)
447 if (PortInitialized
== FALSE
)
450 ch
= READ_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
));
453 WRITE_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
), ch
);
455 ch
= READ_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
));
456 ch
&= (~SR_MCR_LOOP
);
457 ch
|= (SR_MCR_OUT1
| SR_MCR_OUT2
);
458 WRITE_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
), ch
);
468 KdDebuggerInitialize0(
469 IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL
)
472 return STATUS_NOT_IMPLEMENTED
;
480 KdDebuggerInitialize1(
481 IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL
)
484 return STATUS_NOT_IMPLEMENTED
;
493 IN BOOLEAN SleepTransition
)
495 /* Nothing to do on COM ports */
496 return STATUS_SUCCESS
;
505 IN BOOLEAN SleepTransition
)
507 /* Nothing to do on COM ports */
508 return STATUS_SUCCESS
;
518 IN PSTRING MessageHeader
,
519 IN PSTRING MessageData
,
520 IN OUT PKD_CONTEXT Context
)
533 OUT PSTRING MessageHeader
,
534 OUT PSTRING MessageData
,
535 OUT PULONG DataLength
,
536 IN OUT PKD_CONTEXT Context
)