Random fixes, disabled debug in vterm, random crash disappeared, also doing fixes...
[tpg/acess2.git] / Kernel / debug.c
1 /*
2  * AcessOS Microkernel Version
3  * debug.c
4  */
5 #include <acess.h>
6 #include <stdarg.h>
7
8 #define DEBUG_TO_E9     1
9 #define DEBUG_TO_SERIAL 1
10 #define SERIAL_PORT     0x3F8
11 #define GDB_SERIAL_PORT 0x2F8
12
13 // === IMPORTS ===
14 extern void Threads_Dump();
15
16 // === GLOBALS ===
17  int    gDebug_Level = 0;
18  int    giDebug_KTerm = -1;
19  int    gbDebug_SerialSetup = 0;
20  int    gbGDB_SerialSetup = 0;
21
22 // === CODE ===
23 int putDebugChar(char ch)
24 {
25         if(!gbGDB_SerialSetup) {
26                 outb(GDB_SERIAL_PORT + 1, 0x00);    // Disable all interrupts
27                 outb(GDB_SERIAL_PORT + 3, 0x80);    // Enable DLAB (set baud rate divisor)
28                 outb(GDB_SERIAL_PORT + 0, 0x03);    // Set divisor to 3 (lo byte) 38400 baud
29                 outb(GDB_SERIAL_PORT + 1, 0x00);    //                  (hi byte)
30                 outb(GDB_SERIAL_PORT + 3, 0x03);    // 8 bits, no parity, one stop bit
31                 outb(GDB_SERIAL_PORT + 2, 0xC7);    // Enable FIFO with 14-byte threshold and clear it
32                 outb(GDB_SERIAL_PORT + 4, 0x0B);    // IRQs enabled, RTS/DSR set
33                 gbDebug_SerialSetup = 1;
34         }
35         while( (inb(GDB_SERIAL_PORT + 5) & 0x20) == 0 );
36         outb(GDB_SERIAL_PORT, ch);
37         return 0;
38 }
39 int getDebugChar()
40 {
41         if(!gbGDB_SerialSetup) {
42                 outb(GDB_SERIAL_PORT + 1, 0x00);    // Disable all interrupts
43                 outb(GDB_SERIAL_PORT + 3, 0x80);    // Enable DLAB (set baud rate divisor)
44                 outb(GDB_SERIAL_PORT + 0, 0x03);    // Set divisor to 3 (lo byte) 38400 baud
45                 outb(GDB_SERIAL_PORT + 1, 0x00);    //                  (hi byte)
46                 outb(GDB_SERIAL_PORT + 3, 0x03);    // 8 bits, no parity, one stop bit
47                 outb(GDB_SERIAL_PORT + 2, 0xC7);    // Enable FIFO with 14-byte threshold and clear it
48                 outb(GDB_SERIAL_PORT + 4, 0x0B);    // IRQs enabled, RTS/DSR set
49                 gbDebug_SerialSetup = 1;
50         }
51         while( (inb(GDB_SERIAL_PORT + 5) & 1) == 0)     ;
52         return inb(GDB_SERIAL_PORT);
53 }
54
55 volatile int    gbInPutChar = 0;
56
57 static void Debug_Putchar(char ch)
58 {
59         #if DEBUG_TO_E9
60         __asm__ __volatile__ ( "outb %%al, $0xe9" :: "a"(((Uint8)ch)) );
61         #endif
62         
63         #if DEBUG_TO_SERIAL
64         if(!gbDebug_SerialSetup) {
65                 outb(SERIAL_PORT + 1, 0x00);    // Disable all interrupts
66                 outb(SERIAL_PORT + 3, 0x80);    // Enable DLAB (set baud rate divisor)
67                 outb(SERIAL_PORT + 0, 0x03);    // Set divisor to 3 (lo byte) 38400 baud
68                 outb(SERIAL_PORT + 1, 0x00);    //                  (hi byte)
69                 outb(SERIAL_PORT + 3, 0x03);    // 8 bits, no parity, one stop bit
70                 outb(SERIAL_PORT + 2, 0xC7);    // Enable FIFO with 14-byte threshold and clear it
71                 outb(SERIAL_PORT + 4, 0x0B);    // IRQs enabled, RTS/DSR set
72                 gbDebug_SerialSetup = 1;
73         }
74         while( (inb(SERIAL_PORT + 5) & 0x20) == 0 );
75         outb(SERIAL_PORT, ch);
76         #endif
77         
78         if(gbInPutChar) return ;
79         gbInPutChar = 1;
80         if(giDebug_KTerm != -1)
81                 VFS_Write(giDebug_KTerm, 1, &ch);
82         gbInPutChar = 0;
83 }
84
85 static void Debug_Puts(char *Str)
86 {
87         while(*Str)     Debug_Putchar(*Str++);
88 }
89
90 void Debug_Fmt(const char *format, va_list *args)
91 {
92         char    c, pad = ' ';
93          int    minSize = 0, len;
94         char    tmpBuf[34];     // For Integers
95         char    *p = NULL;
96          int    isLongLong = 0;
97         Uint64  arg;
98          int    bPadLeft = 0;
99
100         while((c = *format++) != 0)
101         {
102                 // Non control character
103                 if( c != '%' ) {
104                         Debug_Putchar(c);
105                         continue;
106                 }
107
108                 c = *format++;
109
110                 // Literal %
111                 if(c == '%') {
112                         Debug_Putchar('%');
113                         continue;
114                 }
115
116                 // Pointer
117                 if(c == 'p') {
118                         Uint    ptr = va_arg(*args, Uint);
119                         Debug_Putchar('*');     Debug_Putchar('0');     Debug_Putchar('x');
120                         p = tmpBuf;
121                         itoa(p, ptr, 16, BITS/4, '0');
122                         goto printString;
123                 }
124
125                 // Get Argument
126                 arg = va_arg(*args, Uint);
127
128                 // - Padding Side Flag
129                 if(c == '+') {
130                         bPadLeft = 1;
131                         c = *format++;
132                 }
133
134                 // Padding
135                 if(c == '0') {
136                         pad = '0';
137                         c = *format++;
138                 } else
139                         pad = ' ';
140
141                 // Minimum length
142                 minSize = 1;
143                 if('1' <= c && c <= '9')
144                 {
145                         minSize = 0;
146                         while('0' <= c && c <= '9')
147                         {
148                                 minSize *= 10;
149                                 minSize += c - '0';
150                                 c = *format++;
151                         }
152                 }
153
154                 // Long (default)
155                 isLongLong = 0;
156                 if(c == 'l') {
157                         c = *format++;
158                         if(c == 'l') {
159                                 #if BITS == 32
160                                 arg |= va_arg(*args, Uint);
161                                 #endif
162                                 c = *format++;
163                                 isLongLong = 1;
164                         }
165                 }
166
167                 p = tmpBuf;
168                 switch (c) {
169                 case 'd':
170                 case 'i':
171                         if( (isLongLong && arg >> 63) || (!isLongLong && arg >> 31) ) {
172                                 Debug_Putchar('-');
173                                 arg = -arg;
174                         }
175                         itoa(p, arg, 10, minSize, pad);
176                         goto printString;
177                 case 'u':
178                         itoa(p, arg, 10, minSize, pad);
179                         goto printString;
180                 case 'x':
181                         itoa(p, arg, 16, minSize, pad);
182                         goto printString;
183                 case 'o':
184                         itoa(p, arg, 8, minSize, pad);
185                         goto printString;
186                 case 'b':
187                         itoa(p, arg, 2, minSize, pad);
188                         goto printString;
189
190                 printString:
191                         if(!p)          p = "(null)";
192                         while(*p)       Debug_Putchar(*p++);
193                         break;
194
195                 case 'B':       //Boolean
196                         if(arg) Debug_Puts("True");
197                         else    Debug_Puts("False");
198                         break;
199
200                 case 's':
201                         p = (char*)(Uint)arg;
202                         if(!p)          p = "(null)";
203                         len = strlen(p);
204                         if( !bPadLeft ) while(len++ < minSize)  Debug_Putchar(pad);
205                         while(*p)       Debug_Putchar(*p++);
206                         if( bPadLeft )  while(len++ < minSize)  Debug_Putchar(pad);
207                         break;
208
209                 // Single Character / Array
210                 case 'c':
211                         if(minSize == 1) {
212                                 Debug_Putchar(arg);
213                                 break;
214                         }
215                         p = (char*)(Uint)arg;
216                         if(!p)  goto printString;
217                         while(minSize--)        Debug_Putchar(*p++);
218                         break;
219
220                 default:
221                         Debug_Putchar(arg);
222                         break;
223                 }
224     }
225 }
226
227 /**
228  * \fn void LogF(char *Msg, ...)
229  */
230 void LogF(char *Fmt, ...)
231 {
232         va_list args;
233
234         va_start(args, Fmt);
235
236         Debug_Fmt(Fmt, &args);
237
238         va_end(args);
239 }
240 /**
241  * \fn void Log(char *Msg, ...)
242  */
243 void Log(char *Fmt, ...)
244 {
245         va_list args;
246
247         Debug_Puts("Log: ");
248         va_start(args, Fmt);
249         Debug_Fmt(Fmt, &args);
250         va_end(args);
251         Debug_Putchar('\n');
252 }
253 void Warning(char *Fmt, ...)
254 {
255         va_list args;
256         Debug_Puts("Warning: ");
257         va_start(args, Fmt);
258         Debug_Fmt(Fmt, &args);
259         va_end(args);
260         Debug_Putchar('\n');
261 }
262 void Panic(char *Fmt, ...)
263 {
264         va_list args;
265         Debug_Puts("Panic: ");
266         va_start(args, Fmt);
267         Debug_Fmt(Fmt, &args);
268         va_end(args);
269         Debug_Putchar('\n');
270
271         Threads_Dump();
272
273         __asm__ __volatile__ ("xchg %bx, %bx");
274         __asm__ __volatile__ ("cli;\n\thlt");
275         for(;;) __asm__ __volatile__ ("hlt");
276 }
277
278 void Debug_SetKTerminal(char *File)
279 {
280          int    tmp;
281         if(giDebug_KTerm != -1) {
282                 tmp = giDebug_KTerm;
283                 giDebug_KTerm = -1;
284                 VFS_Close(tmp);
285         }
286         tmp = VFS_Open(File, VFS_OPENFLAG_WRITE);
287         Log_Log("Debug", "Opened '%s' as 0x%x", File, tmp);
288         giDebug_KTerm = tmp;
289         Log_Log("Debug", "Returning to %p", __builtin_return_address(0));
290 }
291
292 void Debug_Enter(char *FuncName, char *ArgTypes, ...)
293 {
294         va_list args;
295          int    i = gDebug_Level ++;
296          int    pos;
297
298         va_start(args, ArgTypes);
299
300         while(i--)      Debug_Putchar(' ');
301
302         Debug_Puts(FuncName);   Debug_Puts(": (");
303
304         while(*ArgTypes)
305         {
306                 pos = strpos(ArgTypes, ' ');
307                 if(pos != -1)   ArgTypes[pos] = '\0';
308                 if(pos == -1 || pos > 1) {
309                         Debug_Puts(ArgTypes+1);
310                         Debug_Putchar('=');
311                 }
312                 if(pos != -1)   ArgTypes[pos] = ' ';
313                 switch(*ArgTypes)
314                 {
315                 case 'p':       Debug_Fmt("%p", &args); break;
316                 case 's':       Debug_Fmt("'%s'", &args);       break;
317                 case 'i':       Debug_Fmt("%i", &args); break;
318                 case 'u':       Debug_Fmt("%u", &args); break;
319                 case 'x':       Debug_Fmt("0x%x", &args);       break;
320                 case 'b':       Debug_Fmt("0b%b", &args);       break;
321                 // Extended (64-Bit)
322                 case 'X':       Debug_Fmt("0x%llx", &args);     break;
323                 case 'B':       Debug_Fmt("0b%llb", &args);     break;
324                 }
325                 if(pos != -1) {
326                         Debug_Putchar(',');     Debug_Putchar(' ');
327                 }
328
329                 if(pos == -1)   break;
330                 ArgTypes = &ArgTypes[pos+1];
331         }
332
333         va_end(args);
334         Debug_Putchar(')');     Debug_Putchar('\n');
335 }
336
337 void Debug_Log(char *FuncName, char *Fmt, ...)
338 {
339         va_list args;
340          int    i = gDebug_Level;
341
342         va_start(args, Fmt);
343
344         while(i--)      Debug_Putchar(' ');
345
346         Debug_Puts(FuncName);   Debug_Puts(": ");
347         Debug_Fmt(Fmt, &args);
348
349         va_end(args);
350         Debug_Putchar('\n');
351 }
352
353 void Debug_Leave(char *FuncName, char RetType, ...)
354 {
355         va_list args;
356          int    i = --gDebug_Level;
357
358         va_start(args, RetType);
359
360         if( i == -1 ) {
361                 gDebug_Level = 0;
362                 i = 0;
363         }
364         // Indenting
365         while(i--)      Debug_Putchar(' ');
366
367         Debug_Puts(FuncName);   Debug_Puts(": RETURN");
368
369         // No Return
370         if(RetType == '-') {
371                 Debug_Putchar('\n');
372                 return;
373         }
374
375         Debug_Putchar(' ');
376         switch(RetType)
377         {
378         case 'n':       Debug_Puts("NULL");     break;
379         case 'p':       Debug_Fmt("%p", &args); break;
380         case 's':       Debug_Fmt("'%s'", &args);       break;
381         case 'i':       Debug_Fmt("%i", &args); break;
382         case 'u':       Debug_Fmt("%u", &args); break;
383         case 'x':       Debug_Fmt("0x%x", &args);       break;
384         // Extended (64-Bit)
385         case 'X':       Debug_Fmt("0x%llx", &args);     break;
386         }
387         Debug_Putchar('\n');
388
389         va_end(args);
390 }
391
392 void Debug_HexDump(char *Header, void *Data, Uint Length)
393 {
394         Uint8   *cdat = Data;
395         Uint    pos = 0;
396         Debug_Puts(Header);
397         LogF(" (Hexdump of %p)\n", Data);
398
399         while(Length >= 16)
400         {
401                 #define CH(n)   ((' '<=cdat[(n)]&&cdat[(n)]<=0x7F) ? cdat[(n)] : '.')
402                 Log("%04x: %02x %02x %02x %02x %02x %02x %02x %02x"
403                         " %02x %02x %02x %02x %02x %02x %02x %02x"
404                         "  %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c",
405                         pos,
406                         cdat[0], cdat[1], cdat[2], cdat[3], cdat[4], cdat[5], cdat[6], cdat[7],
407                         cdat[8], cdat[9], cdat[10], cdat[11], cdat[12], cdat[13], cdat[14], cdat[15],
408                         CH(0),  CH(1),  CH(2),  CH(3),  CH(4),  CH(5),  CH(6),  CH(7),
409                         CH(8),  CH(9),  CH(10), CH(11), CH(12), CH(13), CH(14), CH(15)
410                         );
411                 Length -= 16;
412                 cdat += 16;
413                 pos += 16;
414         }
415
416         LogF("Log: %04x: ", pos);
417         while(Length)
418         {
419                 Uint    byte = *cdat;
420                 LogF("%02x ", byte);
421                 Length--;
422                 cdat ++;
423         }
424         Debug_Putchar('\n');
425 }
426
427 // --- EXPORTS ---
428 EXPORT(Log);
429 EXPORT(Warning);
430 EXPORT(Debug_Enter);
431 EXPORT(Debug_Log);
432 EXPORT(Debug_Leave);

UCC git Repository :: git.ucc.asn.au