2 * AcessOS Microkernel Version
8 #define DEBUG_MAX_LINE_LEN 256
9 #define LOCK_DEBUG_OUTPUT 1 // Avoid interleaving of output lines?
10 #define TRACE_TO_KTERM 0 // Send ENTER/DEBUG/LEAVE to debug?
13 extern void Threads_Dump(void);
14 extern void KernelPanic_SetMode(void);
15 extern void KernelPanic_PutChar(char Ch);
16 extern void IPStack_SendDebugText(const char *Text);
19 static void Debug_Putchar(char ch);
20 static void Debug_Puts(int bUseKTerm, const char *Str);
21 void Debug_DbgOnlyFmt(const char *format, va_list args);
22 void Debug_FmtS(int bUseKTerm, const char *format, ...);
23 void Debug_Fmt(int bUseKTerm, const char *format, va_list args);
24 void Debug_SetKTerminal(const char *File);
28 int giDebug_KTerm = -1;
29 int gbDebug_IsKPanic = 0;
30 volatile int gbInPutChar = 0;
32 tShortSpinlock glDebug_Lock;
34 // - Disabled because it breaks shit
35 int gbSendNetworkDebug = 0;
38 static void Debug_Putchar(char ch)
40 Debug_PutCharDebug(ch);
42 if( !gbDebug_IsKPanic )
44 if(gbInPutChar) return ;
46 if(giDebug_KTerm != -1)
47 VFS_Write(giDebug_KTerm, 1, &ch);
51 KernelPanic_PutChar(ch);
53 if( gbSendNetworkDebug )
55 char str[2] = {ch, 0};
56 IPStack_SendDebugText(str);
60 static void Debug_Puts(int UseKTerm, const char *Str)
64 Debug_PutStringDebug(Str);
66 if( gbDebug_IsKPanic )
68 for( len = 0; Str[len]; len ++ )
69 KernelPanic_PutChar( Str[len] );
72 for( len = 0; Str[len]; len ++ );
74 if( gbSendNetworkDebug )
75 IPStack_SendDebugText(Str);
77 // Output to the kernel terminal
78 if( UseKTerm && !gbDebug_IsKPanic && giDebug_KTerm != -1)
80 if(gbInPutChar) return ;
82 VFS_Write(giDebug_KTerm, len, Str);
87 void Debug_DbgOnlyFmt(const char *format, va_list args)
89 Debug_Fmt(0, format, args);
92 void Debug_Fmt(int bUseKTerm, const char *format, va_list args)
94 char buf[DEBUG_MAX_LINE_LEN];
96 buf[DEBUG_MAX_LINE_LEN-1] = 0;
97 /*len = */vsnprintf(buf, DEBUG_MAX_LINE_LEN-1, format, args);
98 //if( len < DEBUG_MAX_LINE )
100 Debug_Puts(bUseKTerm, buf);
104 void Debug_FmtS(int bUseKTerm, const char *format, ...)
107 va_start(args, format);
108 Debug_Fmt(bUseKTerm, format, args);
112 void Debug_KernelPanic(void)
114 #if LOCK_DEBUG_OUTPUT
115 SHORTREL(&glDebug_Lock);
117 gbDebug_IsKPanic = 1;
118 KernelPanic_SetMode();
122 * \fn void LogF(const char *Msg, ...)
123 * \brief Raw debug log (no new line, no prefix)
125 void LogF(const char *Fmt, ...)
129 #if LOCK_DEBUG_OUTPUT
130 SHORTLOCK(&glDebug_Lock);
135 Debug_Fmt(1, Fmt, args);
139 #if LOCK_DEBUG_OUTPUT
140 SHORTREL(&glDebug_Lock);
144 * \fn void Debug(const char *Msg, ...)
145 * \brief Print only to the debug channel (not KTerm)
147 void Debug(const char *Fmt, ...)
151 #if LOCK_DEBUG_OUTPUT
152 SHORTLOCK(&glDebug_Lock);
155 Debug_Puts(0, "Debug: ");
157 Debug_DbgOnlyFmt(Fmt, args);
159 Debug_PutCharDebug('\r');
160 Debug_PutCharDebug('\n');
161 #if LOCK_DEBUG_OUTPUT
162 SHORTREL(&glDebug_Lock);
167 void LogFV(const char *Fmt, va_list args)
169 #if LOCK_DEBUG_OUTPUT
170 SHORTLOCK(&glDebug_Lock);
173 Debug_Fmt(1, Fmt, args);
175 #if LOCK_DEBUG_OUTPUT
176 SHORTREL(&glDebug_Lock);
180 void LogV(const char *Fmt, va_list args)
182 #if LOCK_DEBUG_OUTPUT
183 SHORTLOCK(&glDebug_Lock);
186 Debug_Puts(1, "Log: ");
187 Debug_Fmt(1, Fmt, args);
188 Debug_Puts(1, "\r\n");
190 #if LOCK_DEBUG_OUTPUT
191 SHORTREL(&glDebug_Lock);
196 * \fn void Log(const char *Msg, ...)
198 void Log(const char *Fmt, ...)
206 void Warning(const char *Fmt, ...)
210 #if LOCK_DEBUG_OUTPUT
211 SHORTLOCK(&glDebug_Lock);
214 Debug_Puts(1, "Warning: ");
216 Debug_Fmt(1, Fmt, args);
221 #if LOCK_DEBUG_OUTPUT
222 SHORTREL(&glDebug_Lock);
225 void Panic(const char *Fmt, ...)
229 #if LOCK_DEBUG_OUTPUT
230 SHORTLOCK(&glDebug_Lock);
232 // And never SHORTREL
236 Debug_Puts(1, "Panic: ");
238 Debug_Fmt(1, Fmt, args);
249 void Debug_SetKTerminal(const char *File)
252 if(giDebug_KTerm != -1) {
257 tmp = VFS_Open(File, VFS_OPENFLAG_WRITE);
258 // Log_Log("Debug", "Opened '%s' as 0x%x", File, tmp);
260 // Log_Log("Debug", "Returning to %p", __builtin_return_address(0));
263 void Debug_Enter(const char *FuncName, const char *ArgTypes, ...)
268 tTID tid = Threads_GetTID();
270 #if LOCK_DEBUG_OUTPUT
271 SHORTLOCK(&glDebug_Lock);
276 va_start(args, ArgTypes);
278 Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
279 while(i--) Debug_Puts(TRACE_TO_KTERM, " ");
281 Debug_Puts(TRACE_TO_KTERM, FuncName);
282 Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
283 Debug_Puts(TRACE_TO_KTERM, ": (");
287 pos = strpos(ArgTypes, ' ');
288 if(pos == -1 || pos > 1) {
290 Debug_Puts(TRACE_TO_KTERM, ArgTypes+1);
292 Debug_FmtS(TRACE_TO_KTERM, "%.*s", pos-1, ArgTypes+1);
294 Debug_Puts(TRACE_TO_KTERM, "=");
298 case 'p': Debug_FmtS(TRACE_TO_KTERM, "%p", va_arg(args, void*)); break;
299 case 'P': Debug_FmtS(TRACE_TO_KTERM, "%P", va_arg(args, tPAddr)); break;
300 case 's': Debug_FmtS(TRACE_TO_KTERM, "'%s'", va_arg(args, char*)); break;
301 case 'i': Debug_FmtS(TRACE_TO_KTERM, "%i", va_arg(args, int)); break;
302 case 'u': Debug_FmtS(TRACE_TO_KTERM, "%u", va_arg(args, Uint)); break;
303 case 'x': Debug_FmtS(TRACE_TO_KTERM, "0x%x", va_arg(args, Uint)); break;
304 case 'b': Debug_FmtS(TRACE_TO_KTERM, "0b%b", va_arg(args, Uint)); break;
305 case 'X': Debug_FmtS(TRACE_TO_KTERM, "0x%llx", va_arg(args, Uint64)); break; // Extended (64-Bit)
306 case 'B': Debug_FmtS(TRACE_TO_KTERM, "0b%llb", va_arg(args, Uint64)); break; // Extended (64-Bit)
309 Debug_Puts(TRACE_TO_KTERM, ", ");
313 ArgTypes = &ArgTypes[pos+1];
317 Debug_Puts(TRACE_TO_KTERM, ")\r\n");
319 #if LOCK_DEBUG_OUTPUT
320 SHORTREL(&glDebug_Lock);
324 void Debug_Log(const char *FuncName, const char *Fmt, ...)
327 int i = gDebug_Level;
328 tTID tid = Threads_GetTID();
330 #if LOCK_DEBUG_OUTPUT
331 SHORTLOCK(&glDebug_Lock);
334 Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
335 while(i--) Debug_Puts(TRACE_TO_KTERM, " ");
337 Debug_Puts(TRACE_TO_KTERM, FuncName);
338 Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
339 Debug_Puts(TRACE_TO_KTERM, ": ");
342 Debug_Fmt(TRACE_TO_KTERM, Fmt, args);
345 Debug_Puts(TRACE_TO_KTERM, "\r\n");
347 #if LOCK_DEBUG_OUTPUT
348 SHORTREL(&glDebug_Lock);
352 void Debug_Leave(const char *FuncName, char RetType, ...)
356 tTID tid = Threads_GetTID();
358 #if LOCK_DEBUG_OUTPUT
359 SHORTLOCK(&glDebug_Lock);
364 va_start(args, RetType);
370 Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
372 while(i--) Debug_Puts(TRACE_TO_KTERM, " ");
374 Debug_Puts(TRACE_TO_KTERM, FuncName);
375 Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
376 Debug_Puts(TRACE_TO_KTERM, ": RETURN");
380 Debug_Puts(TRACE_TO_KTERM, "\r\n");
381 #if LOCK_DEBUG_OUTPUT
382 SHORTREL(&glDebug_Lock);
389 case 'n': Debug_Puts(TRACE_TO_KTERM, " NULL"); break;
390 case 'p': Debug_Fmt(TRACE_TO_KTERM, " %p", args); break;
391 case 'P': Debug_Fmt(TRACE_TO_KTERM, " %P", args); break; // PAddr
392 case 's': Debug_Fmt(TRACE_TO_KTERM, " '%s'", args); break;
393 case 'i': Debug_Fmt(TRACE_TO_KTERM, " %i", args); break;
394 case 'u': Debug_Fmt(TRACE_TO_KTERM, " %u", args); break;
395 case 'x': Debug_Fmt(TRACE_TO_KTERM, " 0x%x", args); break;
397 case 'X': Debug_Fmt(TRACE_TO_KTERM, " 0x%llx", args); break;
399 Debug_Puts(TRACE_TO_KTERM, "\r\n");
403 #if LOCK_DEBUG_OUTPUT
404 SHORTREL(&glDebug_Lock);
408 void Debug_HexDump(const char *Header, const void *Data, size_t Length)
410 const Uint8 *cdat = Data;
412 LogF("%014lli ", now());
413 Debug_Puts(1, Header);
414 LogF(" (Hexdump of %p)\r\n", Data);
416 #define CH(n) ((' '<=cdat[(n)]&&cdat[(n)]<0x7F) ? cdat[(n)] : '.')
420 LogF("%014lli Log: %04x:"
421 " %02x %02x %02x %02x %02x %02x %02x %02x"
422 " %02x %02x %02x %02x %02x %02x %02x %02x"
423 " %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c\r\n",
426 cdat[ 0], cdat[ 1], cdat[ 2], cdat[ 3], cdat[ 4], cdat[ 5], cdat[ 6], cdat[ 7],
427 cdat[ 8], cdat[ 9], cdat[10], cdat[11], cdat[12], cdat[13], cdat[14], cdat[15],
428 CH(0), CH(1), CH(2), CH(3), CH(4), CH(5), CH(6), CH(7),
429 CH(8), CH(9), CH(10), CH(11), CH(12), CH(13), CH(14), CH(15)
438 LogF("%014lli Log: %04x: ", now(), pos);
439 for(i = 0; i < Length; i ++)
441 LogF("%02x ", cdat[i]);
443 for( ; i < 16; i ++) LogF(" ");
445 for(i = 0; i < Length; i ++)
447 if( i == 8 ) LogF(" ");