1*17094Sbloom /* subr_prf.c 6.3 84/08/29 */ 231Sbill 3*17094Sbloom #include "param.h" 4*17094Sbloom #include "systm.h" 5*17094Sbloom #include "seg.h" 6*17094Sbloom #include "buf.h" 7*17094Sbloom #include "conf.h" 8*17094Sbloom #include "reboot.h" 9*17094Sbloom #include "vm.h" 10*17094Sbloom #include "msgbuf.h" 11*17094Sbloom #include "dir.h" 12*17094Sbloom #include "user.h" 13*17094Sbloom #include "proc.h" 14*17094Sbloom #include "tty.h" 1531Sbill 1613531Ssam #ifdef vax 1713531Ssam #include "../vax/mtpr.h" 1813531Ssam #endif 1913531Ssam 2016724Sralph #define TOCONS 0x1 2116724Sralph #define TOTTY 0x2 2216724Sralph #define TOLOG 0x4 2316724Sralph 2431Sbill /* 2531Sbill * In case console is off, 2631Sbill * panicstr contains argument to last 2731Sbill * call to panic. 2831Sbill */ 2931Sbill char *panicstr; 3031Sbill 3131Sbill /* 3231Sbill * Scaled down version of C Library printf. 332781Swnj * Used to print diagnostic information directly on console tty. 342781Swnj * Since it is not interrupt driven, all system activities are 352781Swnj * suspended. Printf should not be used for chit-chat. 362781Swnj * 372781Swnj * One additional format: %b is supported to decode error registers. 382781Swnj * Usage is: 392781Swnj * printf("reg=%b\n", regval, "<base><arg>*"); 402781Swnj * Where <base> is the output base expressed as a control character, 412781Swnj * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 422781Swnj * characters, the first of which gives the bit number to be inspected 432781Swnj * (origin 1), and the next characters (up to a control character, i.e. 442781Swnj * a character <= 32), give the name of the register. Thus 452781Swnj * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 462781Swnj * would produce output: 472781Swnj * reg=2<BITTWO,BITONE> 4831Sbill */ 4931Sbill /*VARARGS1*/ 5031Sbill printf(fmt, x1) 512781Swnj char *fmt; 522781Swnj unsigned x1; 5331Sbill { 54285Sbill 5516724Sralph prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0); 5616724Sralph logwakeup(); 57285Sbill } 58285Sbill 592377Swnj /* 602781Swnj * Uprintf prints to the current user's terminal, 612781Swnj * guarantees not to sleep (so can be called by interrupt routines) 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, 8516724Sralph * guarantees not to sleep (so can be called by interrupt routines) 8616724Sralph * and does no watermark checking - (so no verbose messages). 8716724Sralph */ 8816724Sralph /*VARARGS2*/ 8916724Sralph log(level, fmt, x1) 9016724Sralph char *fmt; 9116724Sralph unsigned x1; 9216724Sralph { 9316724Sralph register s = splhigh(); 9416724Sralph 9516724Sralph putchar('<', TOLOG, (struct tty *)0); 9616724Sralph printn(level, 10, TOLOG, (struct tty *)0); 9716724Sralph putchar('>', TOLOG, (struct tty *)0); 9816724Sralph prf(fmt, &x1, TOLOG, (struct tty *)0); 9916724Sralph splx(s); 10016724Sralph logwakeup(); 10116724Sralph } 10216724Sralph 10316724Sralph prf(fmt, adx, flags, ttyp) 1042781Swnj register char *fmt; 1052781Swnj register u_int *adx; 10616724Sralph struct tty *ttyp; 107285Sbill { 1082434Swnj register int b, c, i; 10931Sbill char *s; 1102678Swnj int any; 11131Sbill 11231Sbill loop: 1132377Swnj while ((c = *fmt++) != '%') { 11416724Sralph if (c == '\0') 11531Sbill return; 11616724Sralph putchar(c, flags, ttyp); 11731Sbill } 1182377Swnj again: 11931Sbill c = *fmt++; 1202781Swnj /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */ 1212377Swnj switch (c) { 1222377Swnj 1232377Swnj case 'l': 1242377Swnj goto again; 1252377Swnj case 'x': case 'X': 1262377Swnj b = 16; 1272377Swnj goto number; 1282377Swnj case 'd': case 'D': 1292377Swnj case 'u': /* what a joke */ 1302377Swnj b = 10; 1312377Swnj goto number; 1322377Swnj case 'o': case 'O': 1332377Swnj b = 8; 1342377Swnj number: 13516724Sralph printn((u_long)*adx, b, flags, ttyp); 1362377Swnj break; 1372377Swnj case 'c': 1382434Swnj b = *adx; 1392434Swnj for (i = 24; i >= 0; i -= 8) 1402434Swnj if (c = (b >> i) & 0x7f) 14116724Sralph putchar(c, flags, ttyp); 1422377Swnj break; 1432678Swnj case 'b': 1442678Swnj b = *adx++; 1452678Swnj s = (char *)*adx; 14616724Sralph printn((u_long)b, *s++, flags, ttyp); 1472678Swnj any = 0; 1482678Swnj if (b) { 14916724Sralph putchar('<', flags, ttyp); 1502678Swnj while (i = *s++) { 1512678Swnj if (b & (1 << (i-1))) { 1522678Swnj if (any) 15316724Sralph putchar(',', flags, ttyp); 1542678Swnj any = 1; 1552678Swnj for (; (c = *s) > 32; s++) 15616724Sralph putchar(c, flags, ttyp); 1572678Swnj } else 1582678Swnj for (; *s > 32; s++) 1592678Swnj ; 1602678Swnj } 1613878Swnj if (any) 16216724Sralph putchar('>', flags, ttyp); 1632678Swnj } 1642678Swnj break; 1652678Swnj 1662377Swnj case 's': 16731Sbill s = (char *)*adx; 168285Sbill while (c = *s++) 16916724Sralph putchar(c, flags, ttyp); 1702377Swnj break; 1713736Sroot 1723736Sroot case '%': 17316724Sralph putchar('%', flags, ttyp); 1743736Sroot break; 17531Sbill } 17631Sbill adx++; 17731Sbill goto loop; 17831Sbill } 17931Sbill 1802781Swnj /* 1812781Swnj * Printn prints a number n in base b. 1822781Swnj * We don't use recursion to avoid deep kernel stacks. 1832781Swnj */ 18416724Sralph printn(n, b, flags, ttyp) 1853101Swnj u_long n; 18616724Sralph struct tty *ttyp; 18731Sbill { 1882434Swnj char prbuf[11]; 1892377Swnj register char *cp; 19031Sbill 1912377Swnj if (b == 10 && (int)n < 0) { 19216724Sralph putchar('-', flags, ttyp); 1932377Swnj n = (unsigned)(-(int)n); 19431Sbill } 1952434Swnj cp = prbuf; 1962377Swnj do { 1972377Swnj *cp++ = "0123456789abcdef"[n%b]; 1982377Swnj n /= b; 1992377Swnj } while (n); 2002377Swnj do 20116724Sralph putchar(*--cp, flags, ttyp); 2022434Swnj while (cp > prbuf); 20331Sbill } 20431Sbill 20531Sbill /* 2061184Sbill * Panic is called on unresolvable fatal errors. 2072781Swnj * It prints "panic: mesg", and then reboots. 2082781Swnj * If we are called twice, then we avoid trying to 2092781Swnj * sync the disks as this often leads to recursive panics. 21031Sbill */ 21131Sbill panic(s) 2122781Swnj char *s; 21331Sbill { 2145416Swnj int bootopt = RB_AUTOBOOT; 2152377Swnj 2165416Swnj if (panicstr) 2175416Swnj bootopt |= RB_NOSYNC; 2189758Ssam else { 2199758Ssam panicstr = s; 2208950Sroot } 2213285Swnj printf("panic: %s\n", s); 2222781Swnj boot(RB_PANIC, bootopt); 22331Sbill } 22431Sbill 22531Sbill /* 2262941Swnj * Warn that a system table is full. 2272941Swnj */ 2282941Swnj tablefull(tab) 2292941Swnj char *tab; 2302941Swnj { 2312941Swnj 2322941Swnj printf("%s: table is full\n", tab); 2332941Swnj } 2342941Swnj 2352941Swnj /* 2362781Swnj * Hard error is the preface to plaintive error messages 2372941Swnj * about failing disk transfers. 2382781Swnj */ 2392941Swnj harderr(bp, cp) 2402678Swnj struct buf *bp; 2412941Swnj char *cp; 24231Sbill { 24331Sbill 2442941Swnj printf("%s%d%c: hard error sn%d ", cp, 2452941Swnj dkunit(bp), 'a'+(minor(bp->b_dev)&07), bp->b_blkno); 24631Sbill } 2472781Swnj 248285Sbill /* 2492377Swnj * Print a character on console or users terminal. 250285Sbill * If destination is console then the last MSGBUFS characters 251285Sbill * are saved in msgbuf for inspection later. 252285Sbill */ 2531785Sbill /*ARGSUSED*/ 25416724Sralph putchar(c, flags, ttyp) 2552377Swnj register int c; 25616724Sralph struct tty *ttyp; 257285Sbill { 258285Sbill 25916724Sralph if (flags & TOTTY) { 26016724Sralph register struct tty *tp = ttyp; 2612360Skre 26216724Sralph if (tp && (tp->t_state & TS_CARR_ON)) { 2632377Swnj register s = spl6(); 2642377Swnj if (c == '\n') 2654970Swnj (void) ttyoutput('\r', tp); 2664970Swnj (void) ttyoutput(c, tp); 2672360Skre ttstart(tp); 2682360Skre splx(s); 2692360Skre } 2702360Skre } 27116724Sralph if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 2728966Sroot #ifdef vax 2738950Sroot && mfpr(MAPEN) 2748950Sroot #endif 2758950Sroot ) { 2762172Swnj if (msgbuf.msg_magic != MSG_MAGIC) { 27712494Ssam register int i; 27812494Ssam 2792172Swnj msgbuf.msg_magic = MSG_MAGIC; 28016724Sralph msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 28112494Ssam for (i=0; i < MSG_BSIZE; i++) 28212494Ssam msgbuf.msg_bufc[i] = 0; 2832172Swnj } 2842172Swnj if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 2852172Swnj msgbuf.msg_bufx = 0; 2862172Swnj msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 287285Sbill } 28816724Sralph if ((flags & TOCONS) && c != '\0') 28916724Sralph cnputc(c); 290285Sbill } 291