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
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};
66 #error Unknown architecture
69 /* MACROS *******************************************************************/
71 #define SER_RBR(x) ((PUCHAR)(x)+0)
72 #define SER_THR(x) ((PUCHAR)(x)+0)
73 #define SER_DLL(x) ((PUCHAR)(x)+0)
74 #define SER_IER(x) ((PUCHAR)(x)+1)
75 #define SR_IER_ERDA 0x01
76 #define SR_IER_ETHRE 0x02
77 #define SR_IER_ERLSI 0x04
78 #define SR_IER_EMS 0x08
79 #define SR_IER_ALL 0x0F
80 #define SER_DLM(x) ((PUCHAR)(x)+1)
81 #define SER_IIR(x) ((PUCHAR)(x)+2)
82 #define SER_FCR(x) ((PUCHAR)(x)+2)
83 #define SR_FCR_ENABLE_FIFO 0x01
84 #define SR_FCR_CLEAR_RCVR 0x02
85 #define SR_FCR_CLEAR_XMIT 0x04
86 #define SER_LCR(x) ((PUCHAR)(x)+3)
87 #define SR_LCR_CS5 0x00
88 #define SR_LCR_CS6 0x01
89 #define SR_LCR_CS7 0x02
90 #define SR_LCR_CS8 0x03
91 #define SR_LCR_ST1 0x00
92 #define SR_LCR_ST2 0x04
93 #define SR_LCR_PNO 0x00
94 #define SR_LCR_POD 0x08
95 #define SR_LCR_PEV 0x18
96 #define SR_LCR_PMK 0x28
97 #define SR_LCR_PSP 0x38
98 #define SR_LCR_BRK 0x40
99 #define SR_LCR_DLAB 0x80
100 #define SER_MCR(x) ((PUCHAR)(x)+4)
101 #define SR_MCR_DTR 0x01
102 #define SR_MCR_RTS 0x02
103 #define SR_MCR_OUT1 0x04
104 #define SR_MCR_OUT2 0x08
105 #define SR_MCR_LOOP 0x10
106 #define SER_LSR(x) ((PUCHAR)(x)+5)
107 #define SR_LSR_DR 0x01
108 #define SR_LSR_TBE 0x20
109 #define SER_MSR(x) ((PUCHAR)(x)+6)
110 #define SR_MSR_CTS 0x10
111 #define SR_MSR_DSR 0x20
112 #define SER_SCR(x) ((PUCHAR)(x)+7)
115 /* GLOBAL VARIABLES *********************************************************/
117 /* STATIC VARIABLES *********************************************************/
119 static KD_PORT_INFORMATION DefaultPort
= { 0, 0, 0 };
121 /* The com port must only be initialized once! */
122 static BOOLEAN PortInitialized
= FALSE
;
125 /* STATIC FUNCTIONS *********************************************************/
129 IN ULONG BaseAddress
)
137 /* save Modem Control Register (MCR) */
138 mcr
= READ_PORT_UCHAR(SER_MCR(BaseAddress
));
140 /* enable loop mode (set Bit 4 of the MCR) */
141 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), SR_MCR_LOOP
);
143 /* clear all modem output bits */
144 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), SR_MCR_LOOP
);
146 /* read the Modem Status Register */
147 msr
= READ_PORT_UCHAR(SER_MSR(BaseAddress
));
150 * the upper nibble of the MSR (modem output bits) must be
151 * equal to the lower nibble of the MCR (modem input bits)
153 if ((msr
& 0xF0) == 0x00)
155 /* set all modem output bits */
156 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), SR_MCR_DTR
| SR_MCR_RTS
| SR_MCR_OUT1
| SR_MCR_OUT2
| SR_MCR_LOOP
);
158 /* read the Modem Status Register */
159 msr
= READ_PORT_UCHAR(SER_MSR(BaseAddress
));
162 * the upper nibble of the MSR (modem output bits) must be
163 * equal to the lower nibble of the MCR (modem input bits)
165 if ((msr
& 0xF0) == 0xF0)
168 * setup a resonable state for the port:
169 * enable fifo and clear recieve/transmit buffers
171 WRITE_PORT_UCHAR(SER_FCR(BaseAddress
),
172 (SR_FCR_ENABLE_FIFO
| SR_FCR_CLEAR_RCVR
| SR_FCR_CLEAR_XMIT
));
173 WRITE_PORT_UCHAR(SER_FCR(BaseAddress
), 0);
174 READ_PORT_UCHAR(SER_RBR(BaseAddress
));
175 WRITE_PORT_UCHAR(SER_IER(BaseAddress
), 0);
181 WRITE_PORT_UCHAR(SER_MCR(BaseAddress
), mcr
);
187 /* FUNCTIONS ****************************************************************/
189 /* HAL.KdPortInitialize */
193 IN PKD_PORT_INFORMATION PortInformation
,
200 if (!PortInitialized
)
202 DefaultPort
.BaudRate
= PortInformation
->BaudRate
;
204 if (PortInformation
->ComPort
== 0)
206 for (i
= sizeof(BaseArray
) / sizeof(BaseArray
[0]) - 1; i
> 0; i
--)
208 if (KdpDoesComPortExist(BaseArray
[i
]))
210 DefaultPort
.BaseAddress
= BaseArray
[i
];
211 DefaultPort
.ComPort
= i
;
212 PortInformation
->BaseAddress
= DefaultPort
.BaseAddress
;
213 PortInformation
->ComPort
= DefaultPort
.ComPort
;
220 "\nKernel Debugger: No COM port found!\n\n");
221 HalDisplayString(buffer
);
226 PortInitialized
= TRUE
;
229 /* initialize port */
230 if (!KdPortInitializeEx(&DefaultPort
, Unknown1
, Unknown2
))
233 /* set global info */
234 KdComPortInUse
= (PUCHAR
)DefaultPort
.BaseAddress
;
240 /* HAL.KdPortInitializeEx */
244 IN PKD_PORT_INFORMATION PortInformation
,
258 if (PortInformation
->BaudRate
== 0)
259 PortInformation
->BaudRate
= DEFAULT_BAUD_RATE
;
261 if (PortInformation
->ComPort
== 0)
264 if (!KdpDoesComPortExist(BaseArray
[PortInformation
->ComPort
]))
267 "\nKernel Debugger: Serial port not found!\n\n");
268 HalDisplayString(buffer
);
272 ComPortBase
= BaseArray
[PortInformation
->ComPort
];
273 PortInformation
->BaseAddress
= ComPortBase
;
276 "\nSerial port COM%ld found at 0x%lx\n",
277 PortInformation
->ComPort
,
279 HalDisplayString(buffer
);
282 /* set baud rate and data format (8N1) */
284 /* turn on DTR and RTS */
285 WRITE_PORT_UCHAR(SER_MCR(ComPortBase
), SR_MCR_DTR
| SR_MCR_RTS
);
288 lcr
= READ_PORT_UCHAR(SER_LCR(ComPortBase
)) | SR_LCR_DLAB
;
289 WRITE_PORT_UCHAR(SER_LCR(ComPortBase
), lcr
);
292 divisor
= 115200 / PortInformation
->BaudRate
;
293 WRITE_PORT_UCHAR(SER_DLL(ComPortBase
), (UCHAR
)(divisor
& 0xff));
294 WRITE_PORT_UCHAR(SER_DLM(ComPortBase
), (UCHAR
)((divisor
>> 8) & 0xff));
296 /* reset DLAB and set 8N1 format */
297 WRITE_PORT_UCHAR(SER_LCR(ComPortBase
),
298 SR_LCR_CS8
| SR_LCR_ST1
| SR_LCR_PNO
);
300 /* read junk out of the RBR */
301 lcr
= READ_PORT_UCHAR(SER_RBR(ComPortBase
));
304 /* print message to blue screen */
306 "\nKernel Debugger: COM%ld (Port 0x%lx) BaudRate %ld\n\n",
307 PortInformation
->ComPort
,
309 PortInformation
->BaudRate
);
311 HalDisplayString(buffer
);
318 /* HAL.KdPortGetByte */
322 OUT PUCHAR ByteReceived
)
324 if (!PortInitialized
)
326 return KdPortGetByteEx(&DefaultPort
, ByteReceived
);
330 /* HAL.KdPortGetByteEx */
334 IN PKD_PORT_INFORMATION PortInformation
,
335 OUT PUCHAR ByteReceived
)
337 PUCHAR ComPortBase
= (PUCHAR
)PortInformation
->BaseAddress
;
339 if ((READ_PORT_UCHAR(SER_LSR(ComPortBase
)) & SR_LSR_DR
))
341 *ByteReceived
= READ_PORT_UCHAR(SER_RBR(ComPortBase
));
349 /* HAL.KdPortPollByte */
353 OUT PUCHAR ByteReceived
)
355 if (!PortInitialized
)
357 return KdPortPollByteEx(&DefaultPort
, ByteReceived
);
361 /* HAL.KdPortPollByteEx */
365 IN PKD_PORT_INFORMATION PortInformation
,
366 OUT PUCHAR ByteReceived
)
368 PUCHAR ComPortBase
= (PUCHAR
)PortInformation
->BaseAddress
;
370 while ((READ_PORT_UCHAR(SER_LSR(ComPortBase
)) & SR_LSR_DR
) == 0)
373 *ByteReceived
= READ_PORT_UCHAR(SER_RBR(ComPortBase
));
379 /* HAL.KdPortPutByte */
385 if (!PortInitialized
)
387 KdPortPutByteEx(&DefaultPort
, ByteToSend
);
390 /* HAL.KdPortPutByteEx */
394 IN PKD_PORT_INFORMATION PortInformation
,
397 PUCHAR ComPortBase
= (PUCHAR
)PortInformation
->BaseAddress
;
399 while ((READ_PORT_UCHAR(SER_LSR(ComPortBase
)) & SR_LSR_TBE
) == 0)
402 WRITE_PORT_UCHAR(SER_THR(ComPortBase
), ByteToSend
);
406 /* HAL.KdPortRestore */
424 /* HAL.KdPortDisableInterrupts */
427 KdPortDisableInterrupts(VOID
)
431 if (!PortInitialized
)
434 ch
= READ_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
));
435 ch
&= (~(SR_MCR_OUT1
| SR_MCR_OUT2
));
436 WRITE_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
), ch
);
438 ch
= READ_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
));
440 WRITE_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
), ch
);
446 /* HAL.KdPortEnableInterrupts */
449 KdPortEnableInterrupts(VOID
)
453 if (PortInitialized
== FALSE
)
456 ch
= READ_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
));
459 WRITE_PORT_UCHAR(SER_IER(DefaultPort
.BaseAddress
), ch
);
461 ch
= READ_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
));
462 ch
&= (~SR_MCR_LOOP
);
463 ch
|= (SR_MCR_OUT1
| SR_MCR_OUT2
);
464 WRITE_PORT_UCHAR(SER_MCR(DefaultPort
.BaseAddress
), ch
);
474 KdDebuggerInitialize0(
475 IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL
)
477 return STATUS_NOT_IMPLEMENTED
;
485 KdDebuggerInitialize1(
486 IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL
)
488 return STATUS_NOT_IMPLEMENTED
;
497 IN BOOLEAN SleepTransition
)
499 /* Nothing to do on COM ports */
500 return STATUS_SUCCESS
;
509 IN BOOLEAN SleepTransition
)
511 /* Nothing to do on COM ports */
512 return STATUS_SUCCESS
;
522 IN PSTRING MessageHeader
,
523 IN PSTRING MessageData
,
524 IN OUT PKD_CONTEXT Context
)
537 OUT PSTRING MessageHeader
,
538 OUT PSTRING MessageData
,
539 OUT PULONG DataLength
,
540 IN OUT PKD_CONTEXT Context
)