1*18364Skarels /* subr_prf.c 6.6 85/03/18 */ 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" 16*18364Skarels #include "syslog.h" 1731Sbill 1813531Ssam #ifdef vax 1913531Ssam #include "../vax/mtpr.h" 2013531Ssam #endif 2113531Ssam 2216724Sralph #define TOCONS 0x1 2316724Sralph #define TOTTY 0x2 2416724Sralph #define TOLOG 0x4 2516724Sralph 2631Sbill /* 2731Sbill * In case console is off, 2831Sbill * panicstr contains argument to last 2931Sbill * call to panic. 3031Sbill */ 3131Sbill char *panicstr; 3231Sbill 3331Sbill /* 3431Sbill * Scaled down version of C Library printf. 352781Swnj * Used to print diagnostic information directly on console tty. 362781Swnj * Since it is not interrupt driven, all system activities are 372781Swnj * suspended. Printf should not be used for chit-chat. 382781Swnj * 392781Swnj * One additional format: %b is supported to decode error registers. 402781Swnj * Usage is: 412781Swnj * printf("reg=%b\n", regval, "<base><arg>*"); 422781Swnj * Where <base> is the output base expressed as a control character, 432781Swnj * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 442781Swnj * characters, the first of which gives the bit number to be inspected 452781Swnj * (origin 1), and the next characters (up to a control character, i.e. 462781Swnj * a character <= 32), give the name of the register. Thus 472781Swnj * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 482781Swnj * would produce output: 4917594Skarels * reg=3<BITTWO,BITONE> 5031Sbill */ 5131Sbill /*VARARGS1*/ 5231Sbill printf(fmt, x1) 532781Swnj char *fmt; 542781Swnj unsigned x1; 5531Sbill { 56285Sbill 5716724Sralph prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0); 5816724Sralph logwakeup(); 59285Sbill } 60285Sbill 612377Swnj /* 6217594Skarels * Uprintf prints to the current user's terminal 632781Swnj * and does no watermark checking - (so no verbose messages). 642377Swnj */ 652377Swnj /*VARARGS1*/ 662377Swnj uprintf(fmt, x1) 672781Swnj char *fmt; 682377Swnj unsigned x1; 69285Sbill { 70285Sbill 7116724Sralph prf(fmt, &x1, TOTTY, u.u_ttyp); 72285Sbill } 73285Sbill 74*18364Skarels /* 75*18364Skarels * tprintf prints on the specified terminal (console if none) 76*18364Skarels * and logs the message. It is designed for error messages from 77*18364Skarels * single-open devices, and may be called from interrupt level. 78*18364Skarels */ 7916724Sralph /*VARARGS2*/ 8016724Sralph tprintf(ttyp, fmt, x1) 8116724Sralph struct tty *ttyp; 8216724Sralph char *fmt; 8316724Sralph unsigned x1; 8416724Sralph { 8516724Sralph 86*18364Skarels prf(fmt, &x1, TOTTY | TOLOG, ttyp); 8716724Sralph } 8816724Sralph 8916724Sralph /* 9016724Sralph * Log writes to the log buffer, 9117594Skarels * and guarantees not to sleep (so can be called by interrupt routines). 92*18364Skarels * If there is no process reading the log yet, it writes to the console also. 9316724Sralph */ 9416724Sralph /*VARARGS2*/ 9516724Sralph log(level, fmt, x1) 9616724Sralph char *fmt; 9716724Sralph unsigned x1; 9816724Sralph { 9916724Sralph register s = splhigh(); 100*18364Skarels extern int log_open; 10116724Sralph 10216724Sralph putchar('<', TOLOG, (struct tty *)0); 10316724Sralph printn(level, 10, TOLOG, (struct tty *)0); 10416724Sralph putchar('>', TOLOG, (struct tty *)0); 10516724Sralph prf(fmt, &x1, TOLOG, (struct tty *)0); 10616724Sralph splx(s); 107*18364Skarels if (!log_open) 108*18364Skarels prf(fmt, &x1, TOCONS, (struct tty *)0); 10916724Sralph logwakeup(); 11016724Sralph } 11116724Sralph 11216724Sralph prf(fmt, adx, flags, ttyp) 1132781Swnj register char *fmt; 1142781Swnj register u_int *adx; 11516724Sralph struct tty *ttyp; 116285Sbill { 1172434Swnj register int b, c, i; 11831Sbill char *s; 1192678Swnj int any; 12031Sbill 12131Sbill loop: 1222377Swnj while ((c = *fmt++) != '%') { 12316724Sralph if (c == '\0') 12431Sbill return; 12516724Sralph putchar(c, flags, ttyp); 12631Sbill } 1272377Swnj again: 12831Sbill c = *fmt++; 1292781Swnj /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */ 1302377Swnj switch (c) { 1312377Swnj 1322377Swnj case 'l': 1332377Swnj goto again; 1342377Swnj case 'x': case 'X': 1352377Swnj b = 16; 1362377Swnj goto number; 1372377Swnj case 'd': case 'D': 1382377Swnj case 'u': /* what a joke */ 1392377Swnj b = 10; 1402377Swnj goto number; 1412377Swnj case 'o': case 'O': 1422377Swnj b = 8; 1432377Swnj number: 14416724Sralph printn((u_long)*adx, b, flags, ttyp); 1452377Swnj break; 1462377Swnj case 'c': 1472434Swnj b = *adx; 1482434Swnj for (i = 24; i >= 0; i -= 8) 1492434Swnj if (c = (b >> i) & 0x7f) 15016724Sralph putchar(c, flags, ttyp); 1512377Swnj break; 1522678Swnj case 'b': 1532678Swnj b = *adx++; 1542678Swnj s = (char *)*adx; 15516724Sralph printn((u_long)b, *s++, flags, ttyp); 1562678Swnj any = 0; 1572678Swnj if (b) { 1582678Swnj while (i = *s++) { 1592678Swnj if (b & (1 << (i-1))) { 16017594Skarels putchar(any? ',' : '<', flags, ttyp); 1612678Swnj any = 1; 1622678Swnj for (; (c = *s) > 32; s++) 16316724Sralph putchar(c, flags, ttyp); 1642678Swnj } else 1652678Swnj for (; *s > 32; s++) 1662678Swnj ; 1672678Swnj } 1683878Swnj if (any) 16916724Sralph putchar('>', flags, ttyp); 1702678Swnj } 1712678Swnj break; 1722678Swnj 1732377Swnj case 's': 17431Sbill s = (char *)*adx; 175285Sbill while (c = *s++) 17616724Sralph putchar(c, flags, ttyp); 1772377Swnj break; 1783736Sroot 1793736Sroot case '%': 18016724Sralph putchar('%', flags, ttyp); 1813736Sroot break; 18231Sbill } 18331Sbill adx++; 18431Sbill goto loop; 18531Sbill } 18631Sbill 1872781Swnj /* 1882781Swnj * Printn prints a number n in base b. 1892781Swnj * We don't use recursion to avoid deep kernel stacks. 1902781Swnj */ 19116724Sralph printn(n, b, flags, ttyp) 1923101Swnj u_long n; 19316724Sralph struct tty *ttyp; 19431Sbill { 1952434Swnj char prbuf[11]; 1962377Swnj register char *cp; 19731Sbill 1982377Swnj if (b == 10 && (int)n < 0) { 19916724Sralph putchar('-', flags, ttyp); 2002377Swnj n = (unsigned)(-(int)n); 20131Sbill } 2022434Swnj cp = prbuf; 2032377Swnj do { 2042377Swnj *cp++ = "0123456789abcdef"[n%b]; 2052377Swnj n /= b; 2062377Swnj } while (n); 2072377Swnj do 20816724Sralph putchar(*--cp, flags, ttyp); 2092434Swnj while (cp > prbuf); 21031Sbill } 21131Sbill 21231Sbill /* 2131184Sbill * Panic is called on unresolvable fatal errors. 2142781Swnj * It prints "panic: mesg", and then reboots. 2152781Swnj * If we are called twice, then we avoid trying to 2162781Swnj * sync the disks as this often leads to recursive panics. 21731Sbill */ 21831Sbill panic(s) 2192781Swnj char *s; 22031Sbill { 2215416Swnj int bootopt = RB_AUTOBOOT; 2222377Swnj 2235416Swnj if (panicstr) 2245416Swnj bootopt |= RB_NOSYNC; 2259758Ssam else { 2269758Ssam panicstr = s; 2278950Sroot } 2283285Swnj printf("panic: %s\n", s); 2292781Swnj boot(RB_PANIC, bootopt); 23031Sbill } 23131Sbill 23231Sbill /* 2332941Swnj * Warn that a system table is full. 2342941Swnj */ 2352941Swnj tablefull(tab) 2362941Swnj char *tab; 2372941Swnj { 2382941Swnj 239*18364Skarels log(KERN_FAIL, "%s: table is full\n", tab); 2402941Swnj } 2412941Swnj 2422941Swnj /* 2432781Swnj * Hard error is the preface to plaintive error messages 2442941Swnj * about failing disk transfers. 2452781Swnj */ 2462941Swnj harderr(bp, cp) 2472678Swnj struct buf *bp; 2482941Swnj char *cp; 24931Sbill { 25031Sbill 2512941Swnj printf("%s%d%c: hard error sn%d ", cp, 2522941Swnj dkunit(bp), 'a'+(minor(bp->b_dev)&07), bp->b_blkno); 25331Sbill } 2542781Swnj 255285Sbill /* 2562377Swnj * Print a character on console or users terminal. 257285Sbill * If destination is console then the last MSGBUFS characters 258285Sbill * are saved in msgbuf for inspection later. 259285Sbill */ 2601785Sbill /*ARGSUSED*/ 26117594Skarels putchar(c, flags, tp) 2622377Swnj register int c; 26317594Skarels struct tty *tp; 264285Sbill { 26517594Skarels extern struct tty cons; 266285Sbill 26716724Sralph if (flags & TOTTY) { 26817594Skarels if (tp == (struct tty *)NULL && (flags & TOCONS) == 0) 26917594Skarels tp = &cons; 27016724Sralph if (tp && (tp->t_state & TS_CARR_ON)) { 2712377Swnj register s = spl6(); 2722377Swnj if (c == '\n') 2734970Swnj (void) ttyoutput('\r', tp); 2744970Swnj (void) ttyoutput(c, tp); 2752360Skre ttstart(tp); 2762360Skre splx(s); 2772360Skre } 2782360Skre } 27916724Sralph if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 2808966Sroot #ifdef vax 2818950Sroot && mfpr(MAPEN) 2828950Sroot #endif 2838950Sroot ) { 2842172Swnj if (msgbuf.msg_magic != MSG_MAGIC) { 28512494Ssam register int i; 28612494Ssam 2872172Swnj msgbuf.msg_magic = MSG_MAGIC; 28816724Sralph msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 28912494Ssam for (i=0; i < MSG_BSIZE; i++) 29012494Ssam msgbuf.msg_bufc[i] = 0; 2912172Swnj } 2922172Swnj if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 2932172Swnj msgbuf.msg_bufx = 0; 2942172Swnj msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 295285Sbill } 29616724Sralph if ((flags & TOCONS) && c != '\0') 29716724Sralph cnputc(c); 298285Sbill } 299