123381Smckusick /* 223381Smckusick * Copyright (c) 1982 Regents of the University of California. 323381Smckusick * All rights reserved. The Berkeley software License Agreement 423381Smckusick * specifies the terms and conditions for redistribution. 523381Smckusick * 6*24759Skarels * @(#)subr_prf.c 6.8 (Berkeley) 09/16/85 723381Smckusick */ 831Sbill 917094Sbloom #include "param.h" 1017094Sbloom #include "systm.h" 1117094Sbloom #include "seg.h" 1217094Sbloom #include "buf.h" 1317094Sbloom #include "conf.h" 1417094Sbloom #include "reboot.h" 1517094Sbloom #include "vm.h" 1617094Sbloom #include "msgbuf.h" 1717094Sbloom #include "dir.h" 1817094Sbloom #include "user.h" 1917094Sbloom #include "proc.h" 2017577Sbloom #include "ioctl.h" 2117094Sbloom #include "tty.h" 2218364Skarels #include "syslog.h" 2331Sbill 2413531Ssam #ifdef vax 2513531Ssam #include "../vax/mtpr.h" 2613531Ssam #endif 2713531Ssam 2816724Sralph #define TOCONS 0x1 2916724Sralph #define TOTTY 0x2 3016724Sralph #define TOLOG 0x4 3116724Sralph 3231Sbill /* 3331Sbill * In case console is off, 3431Sbill * panicstr contains argument to last 3531Sbill * call to panic. 3631Sbill */ 3731Sbill char *panicstr; 3831Sbill 3931Sbill /* 4031Sbill * Scaled down version of C Library printf. 412781Swnj * Used to print diagnostic information directly on console tty. 422781Swnj * Since it is not interrupt driven, all system activities are 432781Swnj * suspended. Printf should not be used for chit-chat. 442781Swnj * 452781Swnj * One additional format: %b is supported to decode error registers. 462781Swnj * Usage is: 472781Swnj * printf("reg=%b\n", regval, "<base><arg>*"); 482781Swnj * Where <base> is the output base expressed as a control character, 492781Swnj * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 502781Swnj * characters, the first of which gives the bit number to be inspected 512781Swnj * (origin 1), and the next characters (up to a control character, i.e. 522781Swnj * a character <= 32), give the name of the register. Thus 532781Swnj * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 542781Swnj * would produce output: 5517594Skarels * reg=3<BITTWO,BITONE> 5631Sbill */ 5731Sbill /*VARARGS1*/ 5831Sbill printf(fmt, x1) 592781Swnj char *fmt; 602781Swnj unsigned x1; 6131Sbill { 62285Sbill 6316724Sralph prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0); 6416724Sralph logwakeup(); 65285Sbill } 66285Sbill 672377Swnj /* 6817594Skarels * Uprintf prints to the current user's terminal 692781Swnj * and does no watermark checking - (so no verbose messages). 702377Swnj */ 712377Swnj /*VARARGS1*/ 722377Swnj uprintf(fmt, x1) 732781Swnj char *fmt; 742377Swnj unsigned x1; 75285Sbill { 76285Sbill 7716724Sralph prf(fmt, &x1, TOTTY, u.u_ttyp); 78285Sbill } 79285Sbill 8018364Skarels /* 8118364Skarels * tprintf prints on the specified terminal (console if none) 8218364Skarels * and logs the message. It is designed for error messages from 8318364Skarels * single-open devices, and may be called from interrupt level. 8418364Skarels */ 8516724Sralph /*VARARGS2*/ 8616724Sralph tprintf(ttyp, fmt, x1) 8716724Sralph struct tty *ttyp; 8816724Sralph char *fmt; 8916724Sralph unsigned x1; 9016724Sralph { 9116724Sralph 9218364Skarels prf(fmt, &x1, TOTTY | TOLOG, ttyp); 9316724Sralph } 9416724Sralph 9516724Sralph /* 9616724Sralph * Log writes to the log buffer, 9717594Skarels * and guarantees not to sleep (so can be called by interrupt routines). 9818364Skarels * If there is no process reading the log yet, it writes to the console also. 9916724Sralph */ 10016724Sralph /*VARARGS2*/ 10116724Sralph log(level, fmt, x1) 10216724Sralph char *fmt; 10316724Sralph unsigned x1; 10416724Sralph { 10516724Sralph register s = splhigh(); 10618364Skarels extern int log_open; 10716724Sralph 10816724Sralph putchar('<', TOLOG, (struct tty *)0); 10916724Sralph printn(level, 10, TOLOG, (struct tty *)0); 11016724Sralph putchar('>', TOLOG, (struct tty *)0); 11116724Sralph prf(fmt, &x1, TOLOG, (struct tty *)0); 11216724Sralph splx(s); 11318364Skarels if (!log_open) 11418364Skarels prf(fmt, &x1, TOCONS, (struct tty *)0); 11516724Sralph logwakeup(); 11616724Sralph } 11716724Sralph 11816724Sralph prf(fmt, adx, flags, ttyp) 1192781Swnj register char *fmt; 1202781Swnj register u_int *adx; 12116724Sralph struct tty *ttyp; 122285Sbill { 1232434Swnj register int b, c, i; 12431Sbill char *s; 1252678Swnj int any; 12631Sbill 12731Sbill loop: 1282377Swnj while ((c = *fmt++) != '%') { 12916724Sralph if (c == '\0') 13031Sbill return; 13116724Sralph putchar(c, flags, ttyp); 13231Sbill } 1332377Swnj again: 13431Sbill c = *fmt++; 1352781Swnj /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */ 1362377Swnj switch (c) { 1372377Swnj 1382377Swnj case 'l': 1392377Swnj goto again; 1402377Swnj case 'x': case 'X': 1412377Swnj b = 16; 1422377Swnj goto number; 1432377Swnj case 'd': case 'D': 1442377Swnj case 'u': /* what a joke */ 1452377Swnj b = 10; 1462377Swnj goto number; 1472377Swnj case 'o': case 'O': 1482377Swnj b = 8; 1492377Swnj number: 15016724Sralph printn((u_long)*adx, b, flags, ttyp); 1512377Swnj break; 1522377Swnj case 'c': 1532434Swnj b = *adx; 1542434Swnj for (i = 24; i >= 0; i -= 8) 1552434Swnj if (c = (b >> i) & 0x7f) 15616724Sralph putchar(c, flags, ttyp); 1572377Swnj break; 1582678Swnj case 'b': 1592678Swnj b = *adx++; 1602678Swnj s = (char *)*adx; 16116724Sralph printn((u_long)b, *s++, flags, ttyp); 1622678Swnj any = 0; 1632678Swnj if (b) { 1642678Swnj while (i = *s++) { 1652678Swnj if (b & (1 << (i-1))) { 16617594Skarels putchar(any? ',' : '<', flags, ttyp); 1672678Swnj any = 1; 1682678Swnj for (; (c = *s) > 32; s++) 16916724Sralph putchar(c, flags, ttyp); 1702678Swnj } else 1712678Swnj for (; *s > 32; s++) 1722678Swnj ; 1732678Swnj } 1743878Swnj if (any) 17516724Sralph putchar('>', flags, ttyp); 1762678Swnj } 1772678Swnj break; 1782678Swnj 1792377Swnj case 's': 18031Sbill s = (char *)*adx; 181285Sbill while (c = *s++) 18216724Sralph putchar(c, flags, ttyp); 1832377Swnj break; 1843736Sroot 1853736Sroot case '%': 18616724Sralph putchar('%', flags, ttyp); 1873736Sroot break; 18831Sbill } 18931Sbill adx++; 19031Sbill goto loop; 19131Sbill } 19231Sbill 1932781Swnj /* 1942781Swnj * Printn prints a number n in base b. 1952781Swnj * We don't use recursion to avoid deep kernel stacks. 1962781Swnj */ 19716724Sralph printn(n, b, flags, ttyp) 1983101Swnj u_long n; 19916724Sralph struct tty *ttyp; 20031Sbill { 2012434Swnj char prbuf[11]; 2022377Swnj register char *cp; 20331Sbill 2042377Swnj if (b == 10 && (int)n < 0) { 20516724Sralph putchar('-', flags, ttyp); 2062377Swnj n = (unsigned)(-(int)n); 20731Sbill } 2082434Swnj cp = prbuf; 2092377Swnj do { 2102377Swnj *cp++ = "0123456789abcdef"[n%b]; 2112377Swnj n /= b; 2122377Swnj } while (n); 2132377Swnj do 21416724Sralph putchar(*--cp, flags, ttyp); 2152434Swnj while (cp > prbuf); 21631Sbill } 21731Sbill 21831Sbill /* 2191184Sbill * Panic is called on unresolvable fatal errors. 2202781Swnj * It prints "panic: mesg", and then reboots. 2212781Swnj * If we are called twice, then we avoid trying to 2222781Swnj * sync the disks as this often leads to recursive panics. 22331Sbill */ 22431Sbill panic(s) 2252781Swnj char *s; 22631Sbill { 2275416Swnj int bootopt = RB_AUTOBOOT; 2282377Swnj 2295416Swnj if (panicstr) 2305416Swnj bootopt |= RB_NOSYNC; 2319758Ssam else { 2329758Ssam panicstr = s; 2338950Sroot } 2343285Swnj printf("panic: %s\n", s); 2352781Swnj boot(RB_PANIC, bootopt); 23631Sbill } 23731Sbill 23831Sbill /* 2392941Swnj * Warn that a system table is full. 2402941Swnj */ 2412941Swnj tablefull(tab) 2422941Swnj char *tab; 2432941Swnj { 2442941Swnj 24518364Skarels log(KERN_FAIL, "%s: table is full\n", tab); 2462941Swnj } 2472941Swnj 2482941Swnj /* 2492781Swnj * Hard error is the preface to plaintive error messages 2502941Swnj * about failing disk transfers. 2512781Swnj */ 2522941Swnj harderr(bp, cp) 2532678Swnj struct buf *bp; 2542941Swnj char *cp; 25531Sbill { 25631Sbill 2572941Swnj printf("%s%d%c: hard error sn%d ", cp, 258*24759Skarels minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev)&07), bp->b_blkno); 25931Sbill } 2602781Swnj 261285Sbill /* 2622377Swnj * Print a character on console or users terminal. 263285Sbill * If destination is console then the last MSGBUFS characters 264285Sbill * are saved in msgbuf for inspection later. 265285Sbill */ 2661785Sbill /*ARGSUSED*/ 26717594Skarels putchar(c, flags, tp) 2682377Swnj register int c; 26917594Skarels struct tty *tp; 270285Sbill { 27117594Skarels extern struct tty cons; 272285Sbill 27316724Sralph if (flags & TOTTY) { 27417594Skarels if (tp == (struct tty *)NULL && (flags & TOCONS) == 0) 27517594Skarels tp = &cons; 27616724Sralph if (tp && (tp->t_state & TS_CARR_ON)) { 2772377Swnj register s = spl6(); 2782377Swnj if (c == '\n') 2794970Swnj (void) ttyoutput('\r', tp); 2804970Swnj (void) ttyoutput(c, tp); 2812360Skre ttstart(tp); 2822360Skre splx(s); 2832360Skre } 2842360Skre } 28516724Sralph if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 2868966Sroot #ifdef vax 2878950Sroot && mfpr(MAPEN) 2888950Sroot #endif 2898950Sroot ) { 2902172Swnj if (msgbuf.msg_magic != MSG_MAGIC) { 29112494Ssam register int i; 29212494Ssam 2932172Swnj msgbuf.msg_magic = MSG_MAGIC; 29416724Sralph msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 29512494Ssam for (i=0; i < MSG_BSIZE; i++) 29612494Ssam msgbuf.msg_bufc[i] = 0; 2972172Swnj } 2982172Swnj if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 2992172Swnj msgbuf.msg_bufx = 0; 3002172Swnj msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 301285Sbill } 30216724Sralph if ((flags & TOCONS) && c != '\0') 30316724Sralph cnputc(c); 304285Sbill } 305