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

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