2 * AcessOS Microkernel Version
5 * TODO: Move the Debug_putchar methods out to the arch/ tree
10 #define DEBUG_MAX_LINE_LEN 256
12 #define LOCK_DEBUG_OUTPUT 1
14 #define TRACE_TO_KTERM 0
17 extern void Threads_Dump(void);
18 extern void KernelPanic_SetMode(void);
19 extern void KernelPanic_PutChar(char Ch);
22 static void Debug_Putchar(char ch);
23 static void Debug_Puts(int bUseKTerm, const char *Str);
24 void Debug_DbgOnlyFmt(const char *format, va_list args);
25 void Debug_FmtS(int bUseKTerm, const char *format, ...);
26 void Debug_Fmt(int bUseKTerm, const char *format, va_list args);
27 void Debug_SetKTerminal(const char *File);
31 int giDebug_KTerm = -1;
32 int gbDebug_IsKPanic = 0;
33 volatile int gbInPutChar = 0;
35 tShortSpinlock glDebug_Lock;
39 static void Debug_Putchar(char ch)
41 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);
54 static void Debug_Puts(int UseKTerm, const char *Str)
58 Debug_PutStringDebug(Str);
60 if( gbDebug_IsKPanic )
62 for( len = 0; Str[len]; len ++ )
63 KernelPanic_PutChar( Str[len] );
66 for( len = 0; Str[len]; len ++ );
68 // Output to the kernel terminal
69 if( UseKTerm && !gbDebug_IsKPanic && giDebug_KTerm != -1)
71 if(gbInPutChar) return ;
73 VFS_Write(giDebug_KTerm, len, Str);
78 void Debug_DbgOnlyFmt(const char *format, va_list args)
80 Debug_Fmt(0, format, args);
83 void Debug_Fmt(int bUseKTerm, const char *format, va_list args)
85 char buf[DEBUG_MAX_LINE_LEN];
87 buf[DEBUG_MAX_LINE_LEN-1] = 0;
88 len = vsnprintf(buf, DEBUG_MAX_LINE_LEN-1, format, args);
89 //if( len < DEBUG_MAX_LINE )
91 Debug_Puts(bUseKTerm, buf);
95 void Debug_FmtS(int bUseKTerm, const char *format, ...)
98 va_start(args, format);
99 Debug_Fmt(bUseKTerm, format, args);
103 void Debug_KernelPanic(void)
105 #if LOCK_DEBUG_OUTPUT
106 SHORTREL(&glDebug_Lock);
108 gbDebug_IsKPanic = 1;
109 KernelPanic_SetMode();
113 * \fn void LogF(const char *Msg, ...)
114 * \brief Raw debug log (no new line, no prefix)
116 void LogF(const char *Fmt, ...)
120 #if LOCK_DEBUG_OUTPUT
121 SHORTLOCK(&glDebug_Lock);
126 Debug_Fmt(1, Fmt, args);
130 #if LOCK_DEBUG_OUTPUT
131 SHORTREL(&glDebug_Lock);
135 * \fn void Debug(const char *Msg, ...)
136 * \brief Print only to the debug channel (not KTerm)
138 void Debug(const char *Fmt, ...)
142 #if LOCK_DEBUG_OUTPUT
143 SHORTLOCK(&glDebug_Lock);
146 Debug_Puts(0, "Debug: ");
148 Debug_DbgOnlyFmt(Fmt, args);
150 Debug_PutCharDebug('\r');
151 Debug_PutCharDebug('\n');
152 #if LOCK_DEBUG_OUTPUT
153 SHORTREL(&glDebug_Lock);
157 * \fn void Log(const char *Msg, ...)
159 void Log(const char *Fmt, ...)
163 #if LOCK_DEBUG_OUTPUT
164 SHORTLOCK(&glDebug_Lock);
167 Debug_Puts(1, "Log: ");
169 Debug_Fmt(1, Fmt, args);
171 Debug_Puts(1, "\r\n");
173 #if LOCK_DEBUG_OUTPUT
174 SHORTREL(&glDebug_Lock);
177 void Warning(const char *Fmt, ...)
181 #if LOCK_DEBUG_OUTPUT
182 SHORTLOCK(&glDebug_Lock);
185 Debug_Puts(1, "Warning: ");
187 Debug_Fmt(1, Fmt, args);
192 #if LOCK_DEBUG_OUTPUT
193 SHORTREL(&glDebug_Lock);
196 void Panic(const char *Fmt, ...)
200 #if LOCK_DEBUG_OUTPUT
201 SHORTLOCK(&glDebug_Lock);
203 // And never SHORTREL
207 Debug_Puts(1, "Panic: ");
209 Debug_Fmt(1, Fmt, args);
216 // __asm__ __volatile__ ("xchg %bx, %bx");
217 // __asm__ __volatile__ ("cli;\n\thlt");
218 // for(;;) __asm__ __volatile__ ("hlt");
222 void Debug_SetKTerminal(const char *File)
225 if(giDebug_KTerm != -1) {
230 tmp = VFS_Open(File, VFS_OPENFLAG_WRITE);
231 Log_Log("Debug", "Opened '%s' as 0x%x", File, tmp);
233 Log_Log("Debug", "Returning to %p", __builtin_return_address(0));
236 void Debug_Enter(const char *FuncName, const char *ArgTypes, ...)
241 tTID tid = Threads_GetTID();
243 #if LOCK_DEBUG_OUTPUT
244 SHORTLOCK(&glDebug_Lock);
249 va_start(args, ArgTypes);
251 Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
252 while(i--) Debug_Puts(TRACE_TO_KTERM, " ");
254 Debug_Puts(TRACE_TO_KTERM, FuncName);
255 Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
256 Debug_Puts(TRACE_TO_KTERM, ": (");
260 pos = strpos(ArgTypes, ' ');
261 if(pos == -1 || pos > 1) {
263 Debug_Puts(TRACE_TO_KTERM, ArgTypes+1);
265 Debug_FmtS(TRACE_TO_KTERM, "%.*s", pos-1, ArgTypes+1);
267 Debug_Puts(TRACE_TO_KTERM, "=");
271 case 'p': Debug_FmtS(TRACE_TO_KTERM, "%p", va_arg(args, void*)); break;
272 case 'P': Debug_FmtS(TRACE_TO_KTERM, "%P", va_arg(args, tPAddr)); break;
273 case 's': Debug_FmtS(TRACE_TO_KTERM, "'%s'", va_arg(args, char*)); break;
274 case 'i': Debug_FmtS(TRACE_TO_KTERM, "%i", va_arg(args, int)); break;
275 case 'u': Debug_FmtS(TRACE_TO_KTERM, "%u", va_arg(args, Uint)); break;
276 case 'x': Debug_FmtS(TRACE_TO_KTERM, "0x%x", va_arg(args, Uint)); break;
277 case 'b': Debug_FmtS(TRACE_TO_KTERM, "0b%b", va_arg(args, Uint)); break;
278 case 'X': Debug_FmtS(TRACE_TO_KTERM, "0x%llx", va_arg(args, Uint64)); break; // Extended (64-Bit)
279 case 'B': Debug_FmtS(TRACE_TO_KTERM, "0b%llb", va_arg(args, Uint64)); break; // Extended (64-Bit)
282 Debug_Puts(TRACE_TO_KTERM, ", ");
286 ArgTypes = &ArgTypes[pos+1];
290 Debug_Puts(TRACE_TO_KTERM, ")\r\n");
292 #if LOCK_DEBUG_OUTPUT
293 SHORTREL(&glDebug_Lock);
297 void Debug_Log(const char *FuncName, const char *Fmt, ...)
300 int i = gDebug_Level;
301 tTID tid = Threads_GetTID();
303 #if LOCK_DEBUG_OUTPUT
304 SHORTLOCK(&glDebug_Lock);
307 Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
308 while(i--) Debug_Puts(TRACE_TO_KTERM, " ");
310 Debug_Puts(TRACE_TO_KTERM, FuncName);
311 Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
312 Debug_Puts(TRACE_TO_KTERM, ": ");
315 Debug_Fmt(TRACE_TO_KTERM, Fmt, args);
318 Debug_Puts(TRACE_TO_KTERM, "\r\n");
320 #if LOCK_DEBUG_OUTPUT
321 SHORTREL(&glDebug_Lock);
325 void Debug_Leave(const char *FuncName, char RetType, ...)
329 tTID tid = Threads_GetTID();
331 #if LOCK_DEBUG_OUTPUT
332 SHORTLOCK(&glDebug_Lock);
337 va_start(args, RetType);
343 Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
345 while(i--) Debug_Puts(TRACE_TO_KTERM, " ");
347 Debug_Puts(TRACE_TO_KTERM, FuncName);
348 Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
349 Debug_Puts(TRACE_TO_KTERM, ": RETURN");
353 Debug_Puts(TRACE_TO_KTERM, "\r\n");
354 #if LOCK_DEBUG_OUTPUT
355 SHORTREL(&glDebug_Lock);
362 case 'n': Debug_Puts(TRACE_TO_KTERM, " NULL"); break;
363 case 'p': Debug_Fmt(TRACE_TO_KTERM, " %p", args); break;
364 case 'P': Debug_Fmt(TRACE_TO_KTERM, " %P", args); break; // PAddr
365 case 's': Debug_Fmt(TRACE_TO_KTERM, " '%s'", args); break;
366 case 'i': Debug_Fmt(TRACE_TO_KTERM, " %i", args); break;
367 case 'u': Debug_Fmt(TRACE_TO_KTERM, " %u", args); break;
368 case 'x': Debug_Fmt(TRACE_TO_KTERM, " 0x%x", args); break;
370 case 'X': Debug_Fmt(TRACE_TO_KTERM, " 0x%llx", args); break;
372 Debug_Puts(TRACE_TO_KTERM, "\r\n");
376 #if LOCK_DEBUG_OUTPUT
377 SHORTREL(&glDebug_Lock);
381 void Debug_HexDump(const char *Header, const void *Data, Uint Length)
383 const Uint8 *cdat = Data;
385 LogF("%014lli ", now());
386 Debug_Puts(1, Header);
387 LogF(" (Hexdump of %p)\r\n", Data);
389 #define CH(n) ((' '<=cdat[(n)]&&cdat[(n)]<0x7F) ? cdat[(n)] : '.')
393 LogF("%014lli Log: %04x:"
394 " %02x %02x %02x %02x %02x %02x %02x %02x"
395 " %02x %02x %02x %02x %02x %02x %02x %02x"
396 " %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c\r\n",
399 cdat[ 0], cdat[ 1], cdat[ 2], cdat[ 3], cdat[ 4], cdat[ 5], cdat[ 6], cdat[ 7],
400 cdat[ 8], cdat[ 9], cdat[10], cdat[11], cdat[12], cdat[13], cdat[14], cdat[15],
401 CH(0), CH(1), CH(2), CH(3), CH(4), CH(5), CH(6), CH(7),
402 CH(8), CH(9), CH(10), CH(11), CH(12), CH(13), CH(14), CH(15)
411 LogF("%014lli Log: %04x: ", now(), pos);
412 for(i = 0; i < Length; i ++)
414 LogF("%02x ", cdat[i]);
416 for( ; i < 16; i ++) LogF(" ");
418 for(i = 0; i < Length; i ++)
420 if( i == 8 ) LogF(" ");