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 #include <ioaccess.h> /* port intrinsics */
24 typedef struct _KD_PORT_INFORMATION
29 } KD_PORT_INFORMATION
, *PKD_PORT_INFORMATION
;
34 IN PKD_PORT_INFORMATION PortInformation
,
41 IN PKD_PORT_INFORMATION PortInformation
,
42 OUT PUCHAR ByteReceived
);
47 IN PKD_PORT_INFORMATION PortInformation
,
48 OUT PUCHAR ByteReceived
);
53 IN PKD_PORT_INFORMATION PortInformation
,
56 #define DEFAULT_BAUD_RATE 19200
59 const ULONG BaseArray
[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
61 const ULONG BaseArray
[2] = {0, 0x800003f8};
62 #elif defined(_M_MIPS)
63 const ULONG BaseArray
[3] = {0, 0x80006000, 0x80007000};
65 const ULONG BaseArray
[2] = {0, 0xF1012000};
67 #error Unknown architecture
70 /* MACROS *******************************************************************/
72 #define SER_RBR(x) ((PUCHAR)(x)+0)
73 #define SER_THR(x) ((PUCHAR)(x)+0)
74 #define SER_DLL(x) ((PUCHAR)(x)+0)
75 #define SER_IER(x) ((PUCHAR)(x)+1)
76 #define SR_IER_ERDA 0x01
77 #define SR_IER_ETHRE 0x02
78 #define SR_IER_ERLSI 0x04
79 #define SR_IER_EMS 0x08
80 #define SR_IER_ALL 0x0F
81 #define SER_DLM(x) ((PUCHAR)(x)+1)
82 #define SER_IIR(x) ((PUCHAR)(x)+2)
83 #define SER_FCR(x) ((PUCHAR)(x)+2)
84 #define SR_FCR_ENABLE_FIFO 0x01
85 #define SR_FCR_CLEAR_RCVR 0x02
86 #define SR_FCR_CLEAR_XMIT 0x04
87 #define SER_LCR(x) ((PUCHAR)(x)+3)
88 #define SR_LCR_CS5 0x00
89 #define SR_LCR_CS6 0x01
90 #define SR_LCR_CS7 0x02
91 #define SR_LCR_CS8 0x03
92 #define SR_LCR_ST1 0x00
93 #define SR_LCR_ST2 0x04
94 #define SR_LCR_PNO 0x00
95 #define SR_LCR_POD 0x08
96 #define SR_LCR_PEV 0x18
97 #define SR_LCR_PMK 0x28
98 #define SR_LCR_PSP 0x38
99 #define SR_LCR_BRK 0x40
100 #define SR_LCR_DLAB 0x80
101 #define SER_MCR(x) ((PUCHAR)(x)+4)
102 #define SR_MCR_DTR 0x01
103 #define SR_MCR_RTS 0x02
104 #define SR_MCR_OUT1 0x04
105 #define SR_MCR_OUT2 0x08
106 #define SR_MCR_LOOP 0x10
107 #define SER_LSR(x) ((PUCHAR)(x)+5)
108 #define SR_LSR_DR 0x01
109 #define SR_LSR_TBE 0x20
110 #define SER_MSR(x) ((PUCHAR)(x)+6)
111 #define SR_MSR_CTS 0x10
112 #define SR_MSR_DSR 0x20
113 #define SER_SCR(x) ((PUCHAR)(x)+7)
116 /* GLOBAL VARIABLES *********************************************************/
118 /* STATIC VARIABLES *********************************************************/
120 static KD_PORT_INFORMATION DefaultPort
= { 0, 0, 0 };
122 /* The com port must only be initialized once! */
123 static BOOLEAN PortInitialized
= FALSE
;
126 /* STATIC FUNCTIONS *********************************************************/
130 IN ULONG BaseAddress
)
138 /* save Modem Control Register (MCR) */
139 mcr
= READ_PORT_UCHAR(SER_MCR(BaseAddress
));
141 /* enable loop mode (set Bit 4 of the MCR) */
142 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), SR_MCR_LOOP
);
144 /* clear all modem output bits */
145 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), SR_MCR_LOOP
);
147 /* read the Modem Status Register */
148 msr
= READ_PORT_UCHAR(SER_MSR(BaseAddress
));
151 * the upper nibble of the MSR (modem output bits) must be
152 * equal to the lower nibble of the MCR (modem input bits)
154 if ((msr
& 0xF0) == 0x00)
156 /* set all modem output bits */
157 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), SR_MCR_DTR
| SR_MCR_RTS
| SR_MCR_OUT1
| SR_MCR_OUT2
| SR_MCR_LOOP
);
159 /* read the Modem Status Register */
160 msr
= READ_PORT_UCHAR(SER_MSR(BaseAddress
));
163 * the upper nibble of the MSR (modem output bits) must be
164 * equal to the lower nibble of the MCR (modem input bits)
166 if ((msr
& 0xF0) == 0xF0)
169 * setup a resonable state for the port:
170 * enable fifo and clear recieve/transmit buffers
172 WRITE_PORT_UCHAR(SER_FCR(BaseAddress
),
173 (SR_FCR_ENABLE_FIFO
| SR_FCR_CLEAR_RCVR
| SR_FCR_CLEAR_XMIT
));
174 WRITE_PORT_UCHAR(SER_FCR(BaseAddress
), 0);
175 READ_PORT_UCHAR(SER_RBR(BaseAddress
));
176 WRITE_PORT_UCHAR(SER_IER(BaseAddress
), 0);
182 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), mcr
);
188 /* FUNCTIONS ****************************************************************/
190 /* HAL.KdPortInitialize */
194 IN PKD_PORT_INFORMATION PortInformation
,
201 if (!PortInitialized
)
203 DefaultPort
.BaudRate
= PortInformation
->BaudRate
;
205 if (PortInformation
->ComPort
== 0)
207 for (i
= sizeof(BaseArray
) / sizeof(BaseArray
[0]) - 1; i
> 0; i
--)
209 if (KdpDoesComPortExist(BaseArray
[i
]))
211 DefaultPort
.BaseAddress
= BaseArray
[i
];
212 DefaultPort
.ComPort
= i
;
213 PortInformation
->BaseAddress
= DefaultPort
.BaseAddress
;
214 PortInformation
->ComPort
= DefaultPort
.ComPort
;
221 "\nKernel Debugger: No COM port found!\n\n");
222 HalDisplayString(buffer
);
227 PortInitialized
= TRUE
;
230 /* initialize port */
231 if (!KdPortInitializeEx(&DefaultPort
, Unknown1
, Unknown2
))
234 /* set global info */
235 KdComPortInUse
= (PUCHAR
)DefaultPort
.BaseAddress
;
241 /* HAL.KdPortInitializeEx */
245 IN PKD_PORT_INFORMATION PortInformation
,
259 if (PortInformation
->BaudRate
== 0)
260 PortInformation
->BaudRate
= DEFAULT_BAUD_RATE
;
262 if (PortInformation
->ComPort
== 0)
265 if (!KdpDoesComPortExist(BaseArray
[PortInformation
->ComPort
]))
268 "\nKernel Debugger: Serial port not found!\n\n");
269 HalDisplayString(buffer
);
273 ComPortBase
= BaseArray
[PortInformation
->ComPort
];
274 PortInformation
->BaseAddress
= ComPortBase
;
277 "\nSerial port COM%ld found at 0x%lx\n",
278 PortInformation
->ComPort
,
280 HalDisplayString(buffer
);
283 /* set baud rate and data format (8N1) */
285 /* turn on DTR and RTS */
286 WRITE_PORT_UCHAR(SER_MCR(ComPortBase
), SR_MCR_DTR
| SR_MCR_RTS
);
289 lcr
= READ_PORT_UCHAR(SER_LCR(ComPortBase
)) | SR_LCR_DLAB
;
290 WRITE_PORT_UCHAR(SER_LCR(ComPortBase
), lcr
);
293 divisor
= 115200 / PortInformation
->BaudRate
;
294 WRITE_PORT_UCHAR(SER_DLL(ComPortBase
), (UCHAR
)(divisor
& 0xff));
295 WRITE_PORT_UCHAR(SER_DLM(ComPortBase
), (UCHAR
)((divisor
>> 8) & 0xff));
297 /* reset DLAB and set 8N1 format */
298 WRITE_PORT_UCHAR(SER_LCR(ComPortBase
),
299 SR_LCR_CS8
| SR_LCR_ST1
| SR_LCR_PNO
);
301 /* read junk out of the RBR */
302 lcr
= READ_PORT_UCHAR(SER_RBR(ComPortBase
));
305 /* print message to blue screen */
307 "\nKernel Debugger: COM%ld (Port 0x%lx) BaudRate %ld\n\n",
308 PortInformation
->ComPort
,
310 PortInformation
->BaudRate
);
312 HalDisplayString(buffer
);
319 /* HAL.KdPortGetByte */
323 OUT PUCHAR ByteReceived
)
325 if (!PortInitialized
)
327 return KdPortGetByteEx(&DefaultPort
, ByteReceived
);
331 /* HAL.KdPortGetByteEx */
335 IN PKD_PORT_INFORMATION PortInformation
,
336 OUT PUCHAR ByteReceived
)
338 PUCHAR ComPortBase
= (PUCHAR
)PortInformation
->BaseAddress
;
340 if ((READ_PORT_UCHAR(SER_LSR(ComPortBase
)) & SR_LSR_DR
))
342 *ByteReceived
= READ_PORT_UCHAR(SER_RBR(ComPortBase
));
350 /* HAL.KdPortPollByte */
354 OUT PUCHAR ByteReceived
)
356 if (!PortInitialized
)
358 return KdPortPollByteEx(&DefaultPort
, ByteReceived
);
362 /* HAL.KdPortPollByteEx */
366 IN PKD_PORT_INFORMATION PortInformation
,
367 OUT PUCHAR ByteReceived
)
369 PUCHAR ComPortBase
= (PUCHAR
)PortInformation
->BaseAddress
;
371 while ((READ_PORT_UCHAR(SER_LSR(ComPortBase
)) & SR_LSR_DR
) == 0)
374 *ByteReceived
= READ_PORT_UCHAR(SER_RBR(ComPortBase
));
380 /* HAL.KdPortPutByte */
386 if (!PortInitialized
)
388 KdPortPutByteEx(&DefaultPort
, ByteToSend
);
391 /* HAL.KdPortPutByteEx */
395 IN PKD_PORT_INFORMATION PortInformation
,
398 PUCHAR ComPortBase
= (PUCHAR
)PortInformation
->BaseAddress
;
400 while ((READ_PORT_UCHAR(SER_LSR(ComPortBase
)) & SR_LSR_TBE
) == 0)
403 WRITE_PORT_UCHAR(SER_THR(ComPortBase
), ByteToSend
);
407 /* HAL.KdPortRestore */
425 /* HAL.KdPortDisableInterrupts */
428 KdPortDisableInterrupts(VOID
)
432 if (!PortInitialized
)
435 ch
= READ_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
));
436 ch
&= (~(SR_MCR_OUT1
| SR_MCR_OUT2
));
437 WRITE_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
), ch
);
439 ch
= READ_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
));
441 WRITE_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
), ch
);
447 /* HAL.KdPortEnableInterrupts */
450 KdPortEnableInterrupts(VOID
)
454 if (PortInitialized
== FALSE
)
457 ch
= READ_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
));
460 WRITE_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
), ch
);
462 ch
= READ_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
));
463 ch
&= (~SR_MCR_LOOP
);
464 ch
|= (SR_MCR_OUT1
| SR_MCR_OUT2
);
465 WRITE_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
), ch
);
475 KdDebuggerInitialize0(
476 IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL
)
478 return STATUS_NOT_IMPLEMENTED
;
486 KdDebuggerInitialize1(
487 IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL
)
489 return STATUS_NOT_IMPLEMENTED
;
498 IN BOOLEAN SleepTransition
)
500 /* Nothing to do on COM ports */
501 return STATUS_SUCCESS
;
510 IN BOOLEAN SleepTransition
)
512 /* Nothing to do on COM ports */
513 return STATUS_SUCCESS
;
523 IN PSTRING MessageHeader
,
524 IN PSTRING MessageData
,
525 IN OUT PKD_CONTEXT Context
)
538 OUT PSTRING MessageHeader
,
539 OUT PSTRING MessageData
,
540 OUT PULONG DataLength
,
541 IN OUT PKD_CONTEXT Context
)