/* Copyright 1990,1991,1992 Eric R. Smith. All rights reserved. */ /* MiNT debugging output routines */ /* also, ksprintf is put here, for lack of any better place to put it */ #include "mint.h" #include static void VDEBUGOUT P_((const char *, va_list)); /* * ksprintf implements a very crude sprintf() function that provides only * what MiNT needs... * * NOTE: this sprintf probably doesn't conform to any standard at * all. It's only use in life is that it won't overflow fixed * size buffers (i.e. it won't try to write more than SPRINTF_MAX * characters into a string) */ static int PUTC(char *p, int c, int *cnt, int width) { int put = 1; if (*cnt <= 0) return 0; *p++ = c; *cnt -= 1; while (*cnt > 0 && --width > 0) { *p++ = ' '; *cnt -= 1; put++; } return put; } static int PUTS(char *p, const char *s, int *cnt, int width) { int put = 0; if (s == 0) s = "(null)"; while (*cnt > 0 && *s) { *p++ = *s++; put++; *cnt -= 1; width--; } while (width-- > 0 && *cnt > 0) { *p++ = ' '; put++; *cnt -= 1; } return put; } static int PUTL(char *p, unsigned long u, int base, int *cnt, int width, int fill_char) { int put = 0; static char obuf[32]; char *t; t = obuf; do { *t++ = "0123456789abcdef"[u % base]; u /= base; width--; } while (u > 0); while (width-- > 0 && *cnt > 0) { *p++ = fill_char; put++; *cnt -= 1; } while (*cnt > 0 && t != obuf) { *p++ = *--t; put++; *cnt -= 1; } return put; } int vksprintf(char *buf, const char *fmt, va_list args) { char *p = buf, c, fill_char; char *s_arg; int i_arg; long l_arg; int cnt; int width, long_flag; cnt = SPRINTF_MAX - 1; while( (c = *fmt++) != 0 ) { if (c != '%') { p += PUTC(p, c, &cnt, 1); continue; } c = *fmt++; width = 0; long_flag = 0; fill_char = ' '; if (c == '0') fill_char = '0'; while (c && isdigit(c)) { width = 10*width + (c-'0'); c = *fmt++; } if (c == 'l' || c == 'L') { long_flag = 1; c = *fmt++; } if (!c) break; switch (c) { case '%': p += PUTC(p, c, &cnt, width); break; case 'c': i_arg = va_arg(args, int); p += PUTC(p, i_arg, &cnt, width); break; case 's': s_arg = va_arg(args, char *); p += PUTS(p, s_arg, &cnt, width); break; case 'd': if (long_flag) { l_arg = va_arg(args, long); } else { l_arg = va_arg(args, int); } if (l_arg < 0) { p += PUTC(p, '-', &cnt, 1); width--; l_arg = -l_arg; } p += PUTL(p, l_arg, 10, &cnt, width, fill_char); break; case 'o': if (long_flag) { l_arg = va_arg(args, long); } else { l_arg = va_arg(args, unsigned int); } p += PUTL(p, l_arg, 8, &cnt, width, fill_char); break; case 'x': if (long_flag) { l_arg = va_arg(args, long); } else { l_arg = va_arg(args, unsigned int); } p += PUTL(p, l_arg, 16, &cnt, width, fill_char); break; case 'u': if (long_flag) { l_arg = va_arg(args, long); } else { l_arg = va_arg(args, unsigned int); } p += PUTL(p, l_arg, 10, &cnt, width, fill_char); break; } } *p = 0; return (p - buf); } int ksprintf(char *buf, const char *fmt, ...) { va_list args; int foo; va_start(args, fmt); foo = vksprintf(buf, fmt, args); va_end(args); return foo; } int debug_level = 0; /* how much debugging info should we print? */ int out_device = 2; /* BIOS device to write errors to */ /* * out_next[i] is the out_device value to use when the current * device is i and the user hits F3. * Cycle is CON -> PRN -> AUX -> MIDI -> 6 -> 7 -> 8 -> 9 -> CON * (Note: BIOS devices 6-8 exist on Mega STe and TT, 9 on TT.) * * out_device and this table are exported to bios.c and used here in HALT(). */ /* 0 1 2 3 4 5 6 7 8 9 */ char out_next[] = { 1, 3, 0, 6, 0, 0, 7, 8, 9, 2 }; void debug_ws(s) const char *s; { long r; while (*s) { (void)Bconout(out_device, *s); if (*s == '\n' && out_device != 0 && Bconstat(out_device)) { r = Bconin(out_device) & 0x00ff0000; if (r == 0x3b0000) debug_level++; else if (r == 0x3c0000) --debug_level; else if (r == 0x400000) DUMPPROC(); else if (r == 0x620000) { do { r = Bconin(out_device) & 0x00ff0000; } while (r != 0x610000); } } s++; } } static void VDEBUGOUT(s, args) const char *s; va_list args; { char buf[SPRINTF_MAX]; ksprintf(buf, "pid %d (%s): ", curproc->pid, curproc->name); debug_ws(buf); vksprintf(buf, s, args); debug_ws(buf); debug_ws("\r\n"); } void TRACE(const char *s, ...) { va_list args; if (debug_level > 1) { va_start(args, s); VDEBUGOUT(s, args); va_end(args); } } void DEBUG(const char *s, ...) { va_list args; if (debug_level) { va_start(args, s); VDEBUGOUT(s, args); va_end(args); } } void ALERT(const char *s, ...) { va_list args; va_start(args, s); VDEBUGOUT(s, args); va_end(args); } EXITING void FATAL(const char *s, ...) { va_list args; va_start(args, s); VDEBUGOUT(s, args); va_end(args); HALT(); } EXITING void HALT() { long r; extern long tosssp; /* in main.c */ restr_intr(); /* restore interrupts to normal */ debug_ws("Fatal MiNT error: adjust debug level and hit a key...\r\n"); sys_q[READY_Q] = 0; /* prevent context switches */ for(;;) { r = Bconin(2) & 0x00ff0000; if (r == 0x3b0000) debug_level++; else if (r == 0x3c0000) --debug_level; else if (r == 0x3d0000) /* F3: cycle to next device */ out_device = out_next[out_device]; else if (r == 0x3e0000) out_device = 2; /* F4: reset to console */ else if (r == 0x3f0000) DUMPMEM(core); /* F5: dump memory */ else if (r == 0x400000) DUMPPROC(); else break; } for(;;) { debug_ws("System halted. Press 'x' to exit, or else reboot\r\n"); r = Bconin(2); if ( (r & 0x0ff) == 'x' ) { close_filesys(); (void)Super((void *)tosssp); /* gratuitous (void *) for Lattice */ zeroexit(); } } } /* some key definitions */ #define CTRLALT 0xc #define DEL 0x53 /* scan code of delete key */ #define UNDO 0x61 /* scan code of undo key */ void do_func_key(scan) int scan; { extern struct tty con_tty; switch (scan) { case DEL: reboot(); break; case UNDO: killgroup(con_tty.pgrp, SIGQUIT); break; case 0x3b: /* F1 */ debug_level++; break; case 0x3c: /* F2 */ if (debug_level > 0) --debug_level; break; case 0x3d: /* F3 */ out_device = out_next[out_device]; break; case 0x3e: /* F4 */ out_device = 2; break; case 0x3f: /* F5 */ DUMPMEM(core); break; case 0x40: /* F6 */ DUMPPROC(); break; } }