Add leftover from sync, fixes build.
[reactos.git] / 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 <debug.h>
14
15 /* GLOBALS *******************************************************************/
16
17 #define KdpBufferSize (1024 * 512)
18 BOOLEAN KdpLoggingEnabled = FALSE;
19 PCHAR KdpDebugBuffer = NULL;
20 volatile ULONG KdpCurrentPosition = 0;
21 volatile ULONG KdpFreeBytes = 0;
22 KSPIN_LOCK KdpDebugLogSpinLock;
23 KEVENT KdpLoggerThreadEvent;
24 HANDLE KdpLogFileHandle;
25
26 KSPIN_LOCK KdpSerialSpinLock;
27 KD_PORT_INFORMATION SerialPortInfo = { DEFAULT_DEBUG_PORT, DEFAULT_DEBUG_BAUD_RATE, 0 };
28
29 /* Current Port in use. FIXME: Do we support more then one? */
30 ULONG KdpPort;
31
32 /* DEBUG LOG FUNCTIONS *******************************************************/
33
34 VOID
35 NTAPI
36 KdpLoggerThread(PVOID Context)
37 {
38 ULONG beg, end, num;
39 IO_STATUS_BLOCK Iosb;
40
41 KdpLoggingEnabled = TRUE;
42
43 while (TRUE)
44 {
45 KeWaitForSingleObject(&KdpLoggerThreadEvent, 0, KernelMode, FALSE, NULL);
46
47 /* Bug */
48 end = KdpCurrentPosition;
49 num = KdpFreeBytes;
50 beg = (end + num) % KdpBufferSize;
51 num = KdpBufferSize - num;
52
53 /* Nothing to do? */
54 if (num == 0)
55 continue;
56
57 if (end > beg)
58 {
59 NtWriteFile(KdpLogFileHandle, NULL, NULL, NULL, &Iosb,
60 KdpDebugBuffer + beg, num, NULL, NULL);
61 }
62 else
63 {
64 NtWriteFile(KdpLogFileHandle, NULL, NULL, NULL, &Iosb,
65 KdpDebugBuffer + beg, KdpBufferSize - beg, NULL, NULL);
66
67 NtWriteFile(KdpLogFileHandle, NULL, NULL, NULL, &Iosb,
68 KdpDebugBuffer, end, NULL, NULL);
69 }
70
71 (VOID)InterlockedExchangeAddUL(&KdpFreeBytes, num);
72 }
73 }
74
75 VOID
76 NTAPI
77 KdpPrintToLogFile(PCH String,
78 ULONG StringLength)
79 {
80 ULONG beg, end, num;
81 KIRQL OldIrql;
82
83 if (KdpDebugBuffer == NULL) return;
84
85 /* Acquire the printing spinlock without waiting at raised IRQL */
86 while (TRUE)
87 {
88 /* Wait when the spinlock becomes available */
89 while (!KeTestSpinLock(&KdpDebugLogSpinLock));
90
91 /* Spinlock was free, raise IRQL */
92 KeRaiseIrql(HIGH_LEVEL, &OldIrql);
93
94 /* Try to get the spinlock */
95 if (KeTryToAcquireSpinLockAtDpcLevel(&KdpDebugLogSpinLock))
96 break;
97
98 /* Someone else got the spinlock, lower IRQL back */
99 KeLowerIrql(OldIrql);
100 }
101
102 beg = KdpCurrentPosition;
103 num = KdpFreeBytes;
104 if (StringLength < num)
105 num = StringLength;
106
107 if (num != 0)
108 {
109 end = (beg + num) % KdpBufferSize;
110 KdpCurrentPosition = end;
111 KdpFreeBytes -= num;
112
113 if (end > beg)
114 {
115 RtlCopyMemory(KdpDebugBuffer + beg, String, num);
116 }
117 else
118 {
119 RtlCopyMemory(KdpDebugBuffer + beg, String, KdpBufferSize - beg);
120 RtlCopyMemory(KdpDebugBuffer, String + KdpBufferSize - beg, end);
121 }
122 }
123
124 /* Release spinlock */
125 KiReleaseSpinLock(&KdpDebugLogSpinLock);
126
127 /* Lower IRQL */
128 KeLowerIrql(OldIrql);
129
130 /* Signal the logger thread */
131 if (OldIrql <= DISPATCH_LEVEL && KdpLoggingEnabled)
132 KeSetEvent(&KdpLoggerThreadEvent, 0, FALSE);
133 }
134
135 VOID
136 NTAPI
137 KdpInitDebugLog(PKD_DISPATCH_TABLE DispatchTable,
138 ULONG BootPhase)
139 {
140 NTSTATUS Status;
141 UNICODE_STRING FileName;
142 OBJECT_ATTRIBUTES ObjectAttributes;
143 IO_STATUS_BLOCK Iosb;
144 HANDLE ThreadHandle;
145 KPRIORITY Priority;
146
147 if (!KdpDebugMode.File) return;
148
149 if (BootPhase == 0)
150 {
151 KdComPortInUse = NULL;
152
153 /* Write out the functions that we support for now */
154 DispatchTable->KdpInitRoutine = KdpInitDebugLog;
155 DispatchTable->KdpPrintRoutine = KdpPrintToLogFile;
156
157 /* Register as a Provider */
158 InsertTailList(&KdProviders, &DispatchTable->KdProvidersList);
159
160 }
161 else if (BootPhase == 1)
162 {
163 /* Allocate a buffer for debug log */
164 KdpDebugBuffer = ExAllocatePool(NonPagedPool, KdpBufferSize);
165 KdpFreeBytes = KdpBufferSize;
166
167 /* Initialize spinlock */
168 KeInitializeSpinLock(&KdpDebugLogSpinLock);
169
170 /* Display separator + ReactOS version at start of the debug log */
171 DPRINT1("---------------------------------------------------------------\n");
172 DPRINT1("ReactOS "KERNEL_VERSION_STR" (Build "KERNEL_VERSION_BUILD_STR")\n");
173 }
174 else if (BootPhase == 2)
175 {
176 HalDisplayString("\n File log debugging enabled\n\n");
177 }
178 else if (BootPhase == 3)
179 {
180 /* Setup the log name */
181 RtlInitUnicodeString(&FileName, L"\\SystemRoot\\debug.log");
182 InitializeObjectAttributes(&ObjectAttributes,
183 &FileName,
184 0,
185 NULL,
186 NULL);
187
188 /* Create the log file */
189 Status = NtCreateFile(&KdpLogFileHandle,
190 FILE_APPEND_DATA | SYNCHRONIZE,
191 &ObjectAttributes,
192 &Iosb,
193 NULL,
194 FILE_ATTRIBUTE_NORMAL,
195 FILE_SHARE_READ,
196 FILE_SUPERSEDE,
197 FILE_WRITE_THROUGH | FILE_SYNCHRONOUS_IO_NONALERT,
198 NULL,
199 0);
200
201 if (!NT_SUCCESS(Status)) return;
202
203 KeInitializeEvent(&KdpLoggerThreadEvent, SynchronizationEvent, TRUE);
204
205 /* Create the logger thread */
206 Status = PsCreateSystemThread(&ThreadHandle,
207 THREAD_ALL_ACCESS,
208 NULL,
209 NULL,
210 NULL,
211 KdpLoggerThread,
212 NULL);
213
214 if (!NT_SUCCESS(Status)) return;
215
216 Priority = 7;
217 NtSetInformationThread(ThreadHandle,
218 ThreadPriority,
219 &Priority,
220 sizeof(Priority));
221 }
222 }
223
224 /* SERIAL FUNCTIONS **********************************************************/
225
226 VOID
227 NTAPI
228 KdpSerialDebugPrint(LPSTR Message,
229 ULONG Length)
230 {
231 KIRQL OldIrql;
232 PCHAR pch = (PCHAR) Message;
233
234 /* Acquire the printing spinlock without waiting at raised IRQL */
235 while (TRUE)
236 {
237 /* Wait when the spinlock becomes available */
238 while (!KeTestSpinLock(&KdpSerialSpinLock));
239
240 /* Spinlock was free, raise IRQL */
241 KeRaiseIrql(HIGH_LEVEL, &OldIrql);
242
243 /* Try to get the spinlock */
244 if (KeTryToAcquireSpinLockAtDpcLevel(&KdpSerialSpinLock))
245 break;
246
247 /* Someone else got the spinlock, lower IRQL back */
248 KeLowerIrql(OldIrql);
249 }
250
251 /* Output the message */
252 while (*pch != 0)
253 {
254 if (*pch == '\n')
255 {
256 KdPortPutByteEx(&SerialPortInfo, '\r');
257 }
258 KdPortPutByteEx(&SerialPortInfo, *pch);
259 pch++;
260 }
261
262 /* Release spinlock */
263 KiReleaseSpinLock(&KdpSerialSpinLock);
264
265 /* Lower IRQL */
266 KeLowerIrql(OldIrql);
267 }
268
269 VOID
270 NTAPI
271 KdpSerialInit(PKD_DISPATCH_TABLE DispatchTable,
272 ULONG BootPhase)
273 {
274 if (!KdpDebugMode.Serial) return;
275
276 if (BootPhase == 0)
277 {
278 /* Write out the functions that we support for now */
279 DispatchTable->KdpInitRoutine = KdpSerialInit;
280 DispatchTable->KdpPrintRoutine = KdpSerialDebugPrint;
281
282 /* Initialize the Port */
283 if (!KdPortInitializeEx(&SerialPortInfo, 0, 0))
284 {
285 KdpDebugMode.Serial = FALSE;
286 return;
287 }
288 KdComPortInUse = (PUCHAR)(ULONG_PTR)SerialPortInfo.BaseAddress;
289
290 /* Initialize spinlock */
291 KeInitializeSpinLock(&KdpSerialSpinLock);
292
293 /* Register as a Provider */
294 InsertTailList(&KdProviders, &DispatchTable->KdProvidersList);
295
296 /* Display separator + ReactOS version at start of the debug log */
297 DPRINT1("-----------------------------------------------------\n");
298 DPRINT1("ReactOS "KERNEL_VERSION_STR" (Build "KERNEL_VERSION_BUILD_STR")\n");
299 DPRINT1("Command Line: %s\n", KeLoaderBlock->LoadOptions);
300 DPRINT1("ARC Paths: %s %s %s %s\n", KeLoaderBlock->ArcBootDeviceName,
301 KeLoaderBlock->NtHalPathName,
302 KeLoaderBlock->ArcHalDeviceName,
303 KeLoaderBlock->NtBootPathName);
304 }
305 else if (BootPhase == 2)
306 {
307 HalDisplayString("\n Serial debugging enabled\n\n");
308 }
309 }
310
311 /* SCREEN FUNCTIONS **********************************************************/
312
313 VOID
314 NTAPI
315 KdpScreenPrint(LPSTR Message,
316 ULONG Length)
317 {
318 /* Call HAL */
319 HalDisplayString(Message);
320 }
321
322 VOID
323 NTAPI
324 KdpScreenInit(PKD_DISPATCH_TABLE DispatchTable,
325 ULONG BootPhase)
326 {
327 if (!KdpDebugMode.Screen) return;
328
329 if (BootPhase == 0)
330 {
331 /* Write out the functions that we support for now */
332 DispatchTable->KdpInitRoutine = KdpScreenInit;
333 DispatchTable->KdpPrintRoutine = KdpScreenPrint;
334
335 /* Register as a Provider */
336 InsertTailList(&KdProviders, &DispatchTable->KdProvidersList);
337 }
338 else if (BootPhase == 2)
339 {
340 HalDisplayString("\n Screen debugging enabled\n\n");
341 }
342 }
343
344 /* GENERAL FUNCTIONS *********************************************************/
345
346 ULONG
347 NTAPI
348 KdpPrintString(LPSTR String,
349 ULONG Length)
350 {
351 PLIST_ENTRY CurrentEntry;
352 PKD_DISPATCH_TABLE CurrentTable;
353
354 if (!KdpDebugMode.Value) return 0;
355
356 /* Call the registered handlers */
357 CurrentEntry = KdProviders.Flink;
358 while (CurrentEntry != &KdProviders)
359 {
360 /* Get the current table */
361 CurrentTable = CONTAINING_RECORD(CurrentEntry,
362 KD_DISPATCH_TABLE,
363 KdProvidersList);
364
365 /* Call it */
366 CurrentTable->KdpPrintRoutine(String, Length);
367
368 /* Next Table */
369 CurrentEntry = CurrentEntry->Flink;
370 }
371
372 /* Call the Wrapper Routine */
373 if (WrapperTable.KdpPrintRoutine)
374 WrapperTable.KdpPrintRoutine(String, Length);
375
376 /* Return the Length */
377 return Length;
378 }
379
380 /* EOF */