Sync with trunk r63174.
[reactos.git] / drivers / base / kdcom / kdcom.c
1 /*
2 * COPYRIGHT: GPL, see COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/base/kddll/kdcom.c
5 * PURPOSE: COM port functions for the kernel debugger.
6 * PROGRAMMER: Timo Kreuzer (timo.kreuzer@ewactos.org)
7 */
8
9 #include "kddll.h"
10
11 #include <cportlib/cportlib.h>
12 #include <arc/arc.h>
13 #include <stdlib.h>
14 #include <ndk/halfuncs.h>
15
16 #define NDEBUG
17 #include <debug.h>
18
19 /* Serial debug connection */
20 #define DEFAULT_DEBUG_PORT 2 /* COM2 */
21 #define DEFAULT_DEBUG_COM1_IRQ 4 /* COM1 IRQ */
22 #define DEFAULT_DEBUG_COM2_IRQ 3 /* COM2 IRQ */
23 #define DEFAULT_DEBUG_BAUD_RATE 115200 /* 115200 Baud */
24
25 #define DEFAULT_BAUD_RATE 19200
26
27 #if defined(_M_IX86) || defined(_M_AMD64)
28 const ULONG BaseArray[] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
29 #elif defined(_M_PPC)
30 const ULONG BaseArray[] = {0, 0x800003F8};
31 #elif defined(_M_MIPS)
32 const ULONG BaseArray[] = {0, 0x80006000, 0x80007000};
33 #elif defined(_M_ARM)
34 const ULONG BaseArray[] = {0, 0xF1012000};
35 #else
36 #error Unknown architecture
37 #endif
38
39 /* GLOBALS ********************************************************************/
40
41 CPPORT KdDebugComPort;
42 ULONG KdDebugComPortIrq = 0; // Not used at the moment.
43
44
45 /* FUNCTIONS ******************************************************************/
46
47 NTSTATUS
48 NTAPI
49 KdD0Transition(VOID)
50 {
51 return STATUS_SUCCESS;
52 }
53
54 NTSTATUS
55 NTAPI
56 KdD3Transition(VOID)
57 {
58 return STATUS_SUCCESS;
59 }
60
61 NTSTATUS
62 NTAPI
63 KdSave(IN BOOLEAN SleepTransition)
64 {
65 /* Nothing to do on COM ports */
66 return STATUS_SUCCESS;
67 }
68
69 NTSTATUS
70 NTAPI
71 KdRestore(IN BOOLEAN SleepTransition)
72 {
73 /* Nothing to do on COM ports */
74 return STATUS_SUCCESS;
75 }
76
77 NTSTATUS
78 NTAPI
79 KdpPortInitialize(IN ULONG ComPortNumber,
80 IN ULONG ComPortBaudRate)
81 {
82 NTSTATUS Status;
83
84 KDDBGPRINT("KdpPortInitialize, Port = COM%ld\n", ComPortNumber);
85
86 Status = CpInitialize(&KdDebugComPort,
87 UlongToPtr(BaseArray[ComPortNumber]),
88 ComPortBaudRate);
89 if (!NT_SUCCESS(Status))
90 {
91 return STATUS_INVALID_PARAMETER;
92 }
93 else
94 {
95 KdComPortInUse = KdDebugComPort.Address;
96 return STATUS_SUCCESS;
97 }
98 }
99
100 /******************************************************************************
101 * \name KdDebuggerInitialize0
102 * \brief Phase 0 initialization.
103 * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL.
104 * \return Status
105 */
106 NTSTATUS
107 NTAPI
108 KdDebuggerInitialize0(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
109 {
110 ULONG ComPortNumber = DEFAULT_DEBUG_PORT;
111 ULONG ComPortBaudRate = DEFAULT_DEBUG_BAUD_RATE;
112
113 PCHAR CommandLine, PortString, BaudString, IrqString;
114 ULONG Value;
115
116 /* Check if e have a LoaderBlock */
117 if (LoaderBlock)
118 {
119 /* HACK */
120 KdpDbgPrint = LoaderBlock->u.I386.CommonDataArea;
121 KDDBGPRINT("KdDebuggerInitialize0\n");
122
123 /* Get the Command Line */
124 CommandLine = LoaderBlock->LoadOptions;
125
126 /* Upcase it */
127 _strupr(CommandLine);
128
129 /* Get the port and baud rate */
130 PortString = strstr(CommandLine, "DEBUGPORT");
131 BaudString = strstr(CommandLine, "BAUDRATE");
132 IrqString = strstr(CommandLine, "IRQ");
133
134 /* Check if we got the /DEBUGPORT parameter */
135 if (PortString)
136 {
137 /* Move past the actual string, to reach the port*/
138 PortString += strlen("DEBUGPORT");
139
140 /* Now get past any spaces and skip the equal sign */
141 while (*PortString == ' ') PortString++;
142 PortString++;
143
144 /* Do we have a serial port? */
145 if (strncmp(PortString, "COM", 3) != 0)
146 {
147 return STATUS_INVALID_PARAMETER;
148 }
149
150 /* Check for a valid Serial Port */
151 PortString += 3;
152 Value = atol(PortString);
153 if (Value >= sizeof(BaseArray) / sizeof(BaseArray[0]))
154 {
155 return STATUS_INVALID_PARAMETER;
156 }
157
158 /* Set the port to use */
159 ComPortNumber = Value;
160 }
161
162 /* Check if we got a baud rate */
163 if (BaudString)
164 {
165 /* Move past the actual string, to reach the rate */
166 BaudString += strlen("BAUDRATE");
167
168 /* Now get past any spaces */
169 while (*BaudString == ' ') BaudString++;
170
171 /* And make sure we have a rate */
172 if (*BaudString)
173 {
174 /* Read and set it */
175 Value = atol(BaudString + 1);
176 if (Value) ComPortBaudRate = Value;
177 }
178 }
179
180 /* Check Serial Port Settings [IRQ] */
181 if (IrqString)
182 {
183 /* Move past the actual string, to reach the rate */
184 IrqString += strlen("IRQ");
185
186 /* Now get past any spaces */
187 while (*IrqString == ' ') IrqString++;
188
189 /* And make sure we have an IRQ */
190 if (*IrqString)
191 {
192 /* Read and set it */
193 Value = atol(IrqString + 1);
194 if (Value) KdDebugComPortIrq = Value;
195 }
196 }
197 }
198
199 /* Initialize the port */
200 return KdpPortInitialize(ComPortNumber, ComPortBaudRate);
201 }
202
203 /******************************************************************************
204 * \name KdDebuggerInitialize1
205 * \brief Phase 1 initialization.
206 * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL.
207 * \return Status
208 */
209 NTSTATUS
210 NTAPI
211 KdDebuggerInitialize1(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
212 {
213 return STATUS_SUCCESS;
214 }
215
216
217 VOID
218 NTAPI
219 KdpSendByte(IN UCHAR Byte)
220 {
221 /* Send the byte */
222 CpPutByte(&KdDebugComPort, Byte);
223 }
224
225 KDP_STATUS
226 NTAPI
227 KdpPollByte(OUT PUCHAR OutByte)
228 {
229 /* Poll the byte */
230 if (CpGetByte(&KdDebugComPort, OutByte, FALSE, FALSE) == CP_GET_SUCCESS)
231 {
232 return KDP_PACKET_RECEIVED;
233 }
234 else
235 {
236 return KDP_PACKET_TIMEOUT;
237 }
238 }
239
240 KDP_STATUS
241 NTAPI
242 KdpReceiveByte(OUT PUCHAR OutByte)
243 {
244 /* Get the byte */
245 if (CpGetByte(&KdDebugComPort, OutByte, TRUE, FALSE) == CP_GET_SUCCESS)
246 {
247 return KDP_PACKET_RECEIVED;
248 }
249 else
250 {
251 return KDP_PACKET_TIMEOUT;
252 }
253 }
254
255 KDP_STATUS
256 NTAPI
257 KdpPollBreakIn(VOID)
258 {
259 KDP_STATUS KdStatus;
260 UCHAR Byte;
261
262 KdStatus = KdpPollByte(&Byte);
263 if ((KdStatus == KDP_PACKET_RECEIVED) && (Byte == BREAKIN_PACKET_BYTE))
264 {
265 return KDP_PACKET_RECEIVED;
266 }
267 return KDP_PACKET_TIMEOUT;
268 }
269
270 /* EOF */