1*17594Skarels /* subr_prf.c 6.5 84/12/27 */ 231Sbill 317094Sbloom #include "param.h" 417094Sbloom #include "systm.h" 517094Sbloom #include "seg.h" 617094Sbloom #include "buf.h" 717094Sbloom #include "conf.h" 817094Sbloom #include "reboot.h" 917094Sbloom #include "vm.h" 1017094Sbloom #include "msgbuf.h" 1117094Sbloom #include "dir.h" 1217094Sbloom #include "user.h" 1317094Sbloom #include "proc.h" 1417577Sbloom #include "ioctl.h" 1517094Sbloom #include "tty.h" 1631Sbill 1713531Ssam #ifdef vax 1813531Ssam #include "../vax/mtpr.h" 1913531Ssam #endif 2013531Ssam 2116724Sralph #define TOCONS 0x1 2216724Sralph #define TOTTY 0x2 2316724Sralph #define TOLOG 0x4 2416724Sralph 2531Sbill /* 2631Sbill * In case console is off, 2731Sbill * panicstr contains argument to last 2831Sbill * call to panic. 2931Sbill */ 3031Sbill char *panicstr; 3131Sbill 3231Sbill /* 3331Sbill * Scaled down version of C Library printf. 342781Swnj * Used to print diagnostic information directly on console tty. 352781Swnj * Since it is not interrupt driven, all system activities are 362781Swnj * suspended. Printf should not be used for chit-chat. 372781Swnj * 382781Swnj * One additional format: %b is supported to decode error registers. 392781Swnj * Usage is: 402781Swnj * printf("reg=%b\n", regval, "<base><arg>*"); 412781Swnj * Where <base> is the output base expressed as a control character, 422781Swnj * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 432781Swnj * characters, the first of which gives the bit number to be inspected 442781Swnj * (origin 1), and the next characters (up to a control character, i.e. 452781Swnj * a character <= 32), give the name of the register. Thus 462781Swnj * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 472781Swnj * would produce output: 48*17594Skarels * reg=3<BITTWO,BITONE> 4931Sbill */ 5031Sbill /*VARARGS1*/ 5131Sbill printf(fmt, x1) 522781Swnj char *fmt; 532781Swnj unsigned x1; 5431Sbill { 55285Sbill 5616724Sralph prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0); 5716724Sralph logwakeup(); 58285Sbill } 59285Sbill 602377Swnj /* 61*17594Skarels * Uprintf prints to the current user's terminal 622781Swnj * and does no watermark checking - (so no verbose messages). 632377Swnj */ 642377Swnj /*VARARGS1*/ 652377Swnj uprintf(fmt, x1) 662781Swnj char *fmt; 672377Swnj unsigned x1; 68285Sbill { 69285Sbill 7016724Sralph prf(fmt, &x1, TOTTY, u.u_ttyp); 71285Sbill } 72285Sbill 7316724Sralph /*VARARGS2*/ 7416724Sralph tprintf(ttyp, fmt, x1) 7516724Sralph struct tty *ttyp; 7616724Sralph char *fmt; 7716724Sralph unsigned x1; 7816724Sralph { 7916724Sralph 8016724Sralph prf(fmt, &x1, TOTTY, ttyp); 8116724Sralph } 8216724Sralph 8316724Sralph /* 8416724Sralph * Log writes to the log buffer, 85*17594Skarels * and guarantees not to sleep (so can be called by interrupt routines). 8616724Sralph */ 8716724Sralph /*VARARGS2*/ 8816724Sralph log(level, fmt, x1) 8916724Sralph char *fmt; 9016724Sralph unsigned x1; 9116724Sralph { 9216724Sralph register s = splhigh(); 9316724Sralph 9416724Sralph putchar('<', TOLOG, (struct tty *)0); 9516724Sralph printn(level, 10, TOLOG, (struct tty *)0); 9616724Sralph putchar('>', TOLOG, (struct tty *)0); 9716724Sralph prf(fmt, &x1, TOLOG, (struct tty *)0); 9816724Sralph splx(s); 9916724Sralph logwakeup(); 10016724Sralph } 10116724Sralph 10216724Sralph prf(fmt, adx, flags, ttyp) 1032781Swnj register char *fmt; 1042781Swnj register u_int *adx; 10516724Sralph struct tty *ttyp; 106285Sbill { 1072434Swnj register int b, c, i; 10831Sbill char *s; 1092678Swnj int any; 11031Sbill 11131Sbill loop: 1122377Swnj while ((c = *fmt++) != '%') { 11316724Sralph if (c == '\0') 11431Sbill return; 11516724Sralph putchar(c, flags, ttyp); 11631Sbill } 1172377Swnj again: 11831Sbill c = *fmt++; 1192781Swnj /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */ 1202377Swnj switch (c) { 1212377Swnj 1222377Swnj case 'l': 1232377Swnj goto again; 1242377Swnj case 'x': case 'X': 1252377Swnj b = 16; 1262377Swnj goto number; 1272377Swnj case 'd': case 'D': 1282377Swnj case 'u': /* what a joke */ 1292377Swnj b = 10; 1302377Swnj goto number; 1312377Swnj case 'o': case 'O': 1322377Swnj b = 8; 1332377Swnj number: 13416724Sralph printn((u_long)*adx, b, flags, ttyp); 1352377Swnj break; 1362377Swnj case 'c': 1372434Swnj b = *adx; 1382434Swnj for (i = 24; i >= 0; i -= 8) 1392434Swnj if (c = (b >> i) & 0x7f) 14016724Sralph putchar(c, flags, ttyp); 1412377Swnj break; 1422678Swnj case 'b': 1432678Swnj b = *adx++; 1442678Swnj s = (char *)*adx; 14516724Sralph printn((u_long)b, *s++, flags, ttyp); 1462678Swnj any = 0; 1472678Swnj if (b) { 1482678Swnj while (i = *s++) { 1492678Swnj if (b & (1 << (i-1))) { 150*17594Skarels putchar(any? ',' : '<', flags, ttyp); 1512678Swnj any = 1; 1522678Swnj for (; (c = *s) > 32; s++) 15316724Sralph putchar(c, flags, ttyp); 1542678Swnj } else 1552678Swnj for (; *s > 32; s++) 1562678Swnj ; 1572678Swnj } 1583878Swnj if (any) 15916724Sralph putchar('>', flags, ttyp); 1602678Swnj } 1612678Swnj break; 1622678Swnj 1632377Swnj case 's': 16431Sbill s = (char *)*adx; 165285Sbill while (c = *s++) 16616724Sralph putchar(c, flags, ttyp); 1672377Swnj break; 1683736Sroot 1693736Sroot case '%': 17016724Sralph putchar('%', flags, ttyp); 1713736Sroot break; 17231Sbill } 17331Sbill adx++; 17431Sbill goto loop; 17531Sbill } 17631Sbill 1772781Swnj /* 1782781Swnj * Printn prints a number n in base b. 1792781Swnj * We don't use recursion to avoid deep kernel stacks. 1802781Swnj */ 18116724Sralph printn(n, b, flags, ttyp) 1823101Swnj u_long n; 18316724Sralph struct tty *ttyp; 18431Sbill { 1852434Swnj char prbuf[11]; 1862377Swnj register char *cp; 18731Sbill 1882377Swnj if (b == 10 && (int)n < 0) { 18916724Sralph putchar('-', flags, ttyp); 1902377Swnj n = (unsigned)(-(int)n); 19131Sbill } 1922434Swnj cp = prbuf; 1932377Swnj do { 1942377Swnj *cp++ = "0123456789abcdef"[n%b]; 1952377Swnj n /= b; 1962377Swnj } while (n); 1972377Swnj do 19816724Sralph putchar(*--cp, flags, ttyp); 1992434Swnj while (cp > prbuf); 20031Sbill } 20131Sbill 20231Sbill /* 2031184Sbill * Panic is called on unresolvable fatal errors. 2042781Swnj * It prints "panic: mesg", and then reboots. 2052781Swnj * If we are called twice, then we avoid trying to 2062781Swnj * sync the disks as this often leads to recursive panics. 20731Sbill */ 20831Sbill panic(s) 2092781Swnj char *s; 21031Sbill { 2115416Swnj int bootopt = RB_AUTOBOOT; 2122377Swnj 2135416Swnj if (panicstr) 2145416Swnj bootopt |= RB_NOSYNC; 2159758Ssam else { 2169758Ssam panicstr = s; 2178950Sroot } 2183285Swnj printf("panic: %s\n", s); 2192781Swnj boot(RB_PANIC, bootopt); 22031Sbill } 22131Sbill 22231Sbill /* 2232941Swnj * Warn that a system table is full. 2242941Swnj */ 2252941Swnj tablefull(tab) 2262941Swnj char *tab; 2272941Swnj { 2282941Swnj 2292941Swnj printf("%s: table is full\n", tab); 2302941Swnj } 2312941Swnj 2322941Swnj /* 2332781Swnj * Hard error is the preface to plaintive error messages 2342941Swnj * about failing disk transfers. 2352781Swnj */ 2362941Swnj harderr(bp, cp) 2372678Swnj struct buf *bp; 2382941Swnj char *cp; 23931Sbill { 24031Sbill 2412941Swnj printf("%s%d%c: hard error sn%d ", cp, 2422941Swnj dkunit(bp), 'a'+(minor(bp->b_dev)&07), bp->b_blkno); 24331Sbill } 2442781Swnj 245285Sbill /* 2462377Swnj * Print a character on console or users terminal. 247285Sbill * If destination is console then the last MSGBUFS characters 248285Sbill * are saved in msgbuf for inspection later. 249285Sbill */ 2501785Sbill /*ARGSUSED*/ 251*17594Skarels putchar(c, flags, tp) 2522377Swnj register int c; 253*17594Skarels struct tty *tp; 254285Sbill { 255*17594Skarels extern struct tty cons; 256285Sbill 25716724Sralph if (flags & TOTTY) { 258*17594Skarels if (tp == (struct tty *)NULL && (flags & TOCONS) == 0) 259*17594Skarels tp = &cons; 26016724Sralph if (tp && (tp->t_state & TS_CARR_ON)) { 2612377Swnj register s = spl6(); 2622377Swnj if (c == '\n') 2634970Swnj (void) ttyoutput('\r', tp); 2644970Swnj (void) ttyoutput(c, tp); 2652360Skre ttstart(tp); 2662360Skre splx(s); 2672360Skre } 2682360Skre } 26916724Sralph if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 2708966Sroot #ifdef vax 2718950Sroot && mfpr(MAPEN) 2728950Sroot #endif 2738950Sroot ) { 2742172Swnj if (msgbuf.msg_magic != MSG_MAGIC) { 27512494Ssam register int i; 27612494Ssam 2772172Swnj msgbuf.msg_magic = MSG_MAGIC; 27816724Sralph msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 27912494Ssam for (i=0; i < MSG_BSIZE; i++) 28012494Ssam msgbuf.msg_bufc[i] = 0; 2812172Swnj } 2822172Swnj if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 2832172Swnj msgbuf.msg_bufx = 0; 2842172Swnj msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 285285Sbill } 28616724Sralph if ((flags & TOCONS) && c != '\0') 28716724Sralph cnputc(c); 288285Sbill } 289