strip whitespace from end of lines
[reactos.git] / reactos / ntoskrnl / kd / kdio.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/kd/kdio.c
5 * PURPOSE: NT Kernel Debugger Input/Output Functions
6 *
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ntoskrnl.h>
13 #include <internal/debug.h>
14
15 /* GLOBALS *******************************************************************/
16
17 #define BufferSize 32*1024
18
19 HANDLE KdbLogFileHandle;
20 BOOLEAN KdpLogInitialized;
21 CHAR DebugBuffer[BufferSize];
22 ULONG CurrentPosition;
23 WORK_QUEUE_ITEM KdpDebugLogQueue;
24 BOOLEAN ItemQueued;
25 KD_PORT_INFORMATION SerialPortInfo = {DEFAULT_DEBUG_PORT, DEFAULT_DEBUG_BAUD_RATE, 0};
26
27 /* Current Port in use. FIXME: Do we support more then one? */
28 ULONG KdpPort;
29
30 /* DEBUG LOG FUNCTIONS *******************************************************/
31
32 VOID
33 STDCALL
34 KdpPrintToLogInternal(PVOID Context)
35 {
36 IO_STATUS_BLOCK Iosb;
37
38 /* Write to the Debug Log */
39 NtWriteFile(KdbLogFileHandle,
40 NULL,
41 NULL,
42 NULL,
43 &Iosb,
44 DebugBuffer,
45 CurrentPosition,
46 NULL,
47 NULL);
48
49 /* Clear the Current Position */
50 CurrentPosition = 0;
51
52 /* A new item can be queued now */
53 ItemQueued = FALSE;
54 }
55
56 VOID
57 STDCALL
58 KdpPrintToLog(PCH String)
59 {
60 ULONG StringLength = strlen(String);
61
62 /* Don't overflow */
63 if ((CurrentPosition + StringLength) > BufferSize) return;
64
65 /* Add the string to the buffer */
66 RtlMoveMemory(&DebugBuffer[CurrentPosition], String, StringLength);
67
68 /* Update the Current Position */
69 CurrentPosition += StringLength;
70
71 /* Make sure we are initialized and can queue */
72 if (!KdpLogInitialized || (ItemQueued)) return;
73
74 /* Queue the work item */
75 ExQueueWorkItem(&KdpDebugLogQueue, HyperCriticalWorkQueue);
76 ItemQueued = TRUE;
77 }
78
79 VOID
80 STDCALL
81 KdpInitDebugLog(PKD_DISPATCH_TABLE DispatchTable,
82 ULONG BootPhase)
83 {
84 if (!KdpDebugMode.File) return;
85 NTSTATUS Status;
86 OBJECT_ATTRIBUTES ObjectAttributes;
87 UNICODE_STRING FileName;
88 IO_STATUS_BLOCK Iosb;
89
90 if (BootPhase == 0)
91 {
92 /* Write out the functions that we support for now */
93 DispatchTable->KdpInitRoutine = KdpInitDebugLog;
94 DispatchTable->KdpPrintRoutine = KdpPrintToLog;
95
96 /* Register as a Provider */
97 InsertTailList(&KdProviders, &DispatchTable->KdProvidersList);
98 }
99 else if (BootPhase == 2)
100 {
101 HalDisplayString("\n File log debugging enabled\n\n");
102 }
103 else if (BootPhase == 3)
104 {
105 /* Setup the Log Name */
106 RtlInitUnicodeString(&FileName, L"\\SystemRoot\\debug.log");
107 InitializeObjectAttributes(&ObjectAttributes,
108 &FileName,
109 0,
110 NULL,
111 NULL);
112
113 /* Create the Log File */
114 Status = NtCreateFile(&KdbLogFileHandle,
115 FILE_ALL_ACCESS,
116 &ObjectAttributes,
117 &Iosb,
118 NULL,
119 FILE_ATTRIBUTE_NORMAL,
120 FILE_SHARE_READ,
121 FILE_SUPERSEDE,
122 FILE_WRITE_THROUGH | FILE_SYNCHRONOUS_IO_NONALERT,
123 NULL,
124 0);
125
126 /* Allow it to be used */
127 ExInitializeWorkItem(&KdpDebugLogQueue, &KdpPrintToLogInternal, NULL);
128 KdpLogInitialized = TRUE;
129 }
130 }
131
132 /* SERIAL FUNCTIONS **********************************************************/
133
134 VOID
135 STDCALL
136 KdpSerialDebugPrint(LPSTR Message)
137 {
138 PCHAR pch = (PCHAR) Message;
139
140 while (*pch != 0)
141 {
142 if (*pch == '\n')
143 {
144 KdPortPutByteEx(&SerialPortInfo, '\r');
145 }
146 KdPortPutByteEx(&SerialPortInfo, *pch);
147 pch++;
148 }
149 }
150
151 VOID
152 STDCALL
153 KdpSerialInit(PKD_DISPATCH_TABLE DispatchTable,
154 ULONG BootPhase)
155 {
156 if (!KdpDebugMode.Serial) return;
157
158 if (BootPhase == 0)
159 {
160 /* Write out the functions that we support for now */
161 DispatchTable->KdpInitRoutine = KdpSerialInit;
162 DispatchTable->KdpPrintRoutine = KdpSerialDebugPrint;
163
164 /* Initialize the Port */
165 KdPortInitializeEx(&SerialPortInfo, 0, 0);
166
167 /* Register as a Provider */
168 InsertTailList(&KdProviders, &DispatchTable->KdProvidersList);
169 }
170 else if (BootPhase == 2)
171 {
172 HalDisplayString("\n Serial debugging enabled\n\n");
173 }
174 }
175
176 /* SCREEN FUNCTIONS **********************************************************/
177
178 VOID
179 STDCALL
180 KdpScreenInit(PKD_DISPATCH_TABLE DispatchTable,
181 ULONG BootPhase)
182 {
183 if (!KdpDebugMode.Screen) return;
184
185 if (BootPhase == 0)
186 {
187 /* Write out the functions that we support for now */
188 DispatchTable->KdpInitRoutine = KdpScreenInit;
189 DispatchTable->KdpPrintRoutine = HalDisplayString;
190
191 /* Register as a Provider */
192 InsertTailList(&KdProviders, &DispatchTable->KdProvidersList);
193 }
194 else if (BootPhase == 2)
195 {
196 HalDisplayString("\n Screen debugging enabled\n\n");
197 }
198 }
199
200 /* GENERAL FUNCTIONS *********************************************************/
201
202 BOOLEAN
203 STDCALL
204 KdpDetectConflicts(PCM_RESOURCE_LIST DriverList)
205 {
206 ULONG ComPortBase = 0;
207 ULONG i;
208 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
209
210 /* Select the COM Port Base */
211 switch (KdpPort)
212 {
213 case 1: ComPortBase = 0x3f8; break;
214 case 2: ComPortBase = 0x2f8; break;
215 case 3: ComPortBase = 0x3e8; break;
216 case 4: ComPortBase = 0x2e8; break;
217 }
218
219 /* search for this port address in DriverList */
220 for (i = 0; i < DriverList->List[0].PartialResourceList.Count; i++)
221 {
222 ResourceDescriptor = &DriverList->List[0].PartialResourceList.PartialDescriptors[i];
223 if (ResourceDescriptor->Type == CmResourceTypePort)
224 {
225 if ((ResourceDescriptor->u.Port.Start.u.LowPart <= ComPortBase) &&
226 (ResourceDescriptor->u.Port.Start.u.LowPart +
227 ResourceDescriptor->u.Port.Length > ComPortBase))
228 {
229 /* Conflict found */
230 return TRUE;
231 }
232 }
233 }
234
235 /* No Conflicts */
236 return FALSE;
237 }
238
239 ULONG
240 STDCALL
241 KdpPrintString(PANSI_STRING String)
242 {
243 if (!KdpDebugMode.Value) return 0;
244 PCH pch = String->Buffer;
245 PLIST_ENTRY CurrentEntry;
246 PKD_DISPATCH_TABLE CurrentTable;
247
248 /* Call the registered handlers */
249 CurrentEntry = KdProviders.Flink;
250 while (CurrentEntry != &KdProviders)
251 {
252 /* Get the current table */
253 CurrentTable = CONTAINING_RECORD(CurrentEntry,
254 KD_DISPATCH_TABLE,
255 KdProvidersList);
256
257 /* Call it */
258 CurrentTable->KdpPrintRoutine(pch);
259
260 /* Next Table */
261 CurrentEntry = CurrentEntry->Flink;
262 }
263
264 /* Call the Wrapper Routine */
265 if (WrapperInitRoutine) WrapperTable.KdpPrintRoutine(pch);
266
267 /* Return the Length */
268 return((ULONG)String->Length);
269 }
270
271 /* EOF */
272