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

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