1*13531Ssam /* subr_prf.c 4.28 83/07/01 */ 231Sbill 331Sbill #include "../h/param.h" 431Sbill #include "../h/systm.h" 531Sbill #include "../h/seg.h" 631Sbill #include "../h/buf.h" 731Sbill #include "../h/conf.h" 81184Sbill #include "../h/reboot.h" 92172Swnj #include "../h/vm.h" 102172Swnj #include "../h/msgbuf.h" 112360Skre #include "../h/dir.h" 122360Skre #include "../h/user.h" 139758Ssam #include "../h/proc.h" 142360Skre #include "../h/tty.h" 1531Sbill 16*13531Ssam #ifdef vax 17*13531Ssam #include "../vax/mtpr.h" 18*13531Ssam #endif 19*13531Ssam 2031Sbill /* 2131Sbill * In case console is off, 2231Sbill * panicstr contains argument to last 2331Sbill * call to panic. 2431Sbill */ 2531Sbill char *panicstr; 2631Sbill 2731Sbill /* 2831Sbill * Scaled down version of C Library printf. 292781Swnj * Used to print diagnostic information directly on console tty. 302781Swnj * Since it is not interrupt driven, all system activities are 312781Swnj * suspended. Printf should not be used for chit-chat. 322781Swnj * 332781Swnj * One additional format: %b is supported to decode error registers. 342781Swnj * Usage is: 352781Swnj * printf("reg=%b\n", regval, "<base><arg>*"); 362781Swnj * Where <base> is the output base expressed as a control character, 372781Swnj * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 382781Swnj * characters, the first of which gives the bit number to be inspected 392781Swnj * (origin 1), and the next characters (up to a control character, i.e. 402781Swnj * a character <= 32), give the name of the register. Thus 412781Swnj * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 422781Swnj * would produce output: 432781Swnj * reg=2<BITTWO,BITONE> 4431Sbill */ 4531Sbill /*VARARGS1*/ 4631Sbill printf(fmt, x1) 472781Swnj char *fmt; 482781Swnj unsigned x1; 4931Sbill { 50285Sbill 51285Sbill prf(fmt, &x1, 0); 52285Sbill } 53285Sbill 542377Swnj /* 552781Swnj * Uprintf prints to the current user's terminal, 562781Swnj * guarantees not to sleep (so can be called by interrupt routines) 572781Swnj * and does no watermark checking - (so no verbose messages). 582377Swnj */ 592377Swnj /*VARARGS1*/ 602377Swnj uprintf(fmt, x1) 612781Swnj char *fmt; 622377Swnj unsigned x1; 63285Sbill { 64285Sbill 652377Swnj prf(fmt, &x1, 2); 66285Sbill } 67285Sbill 682377Swnj prf(fmt, adx, touser) 692781Swnj register char *fmt; 702781Swnj register u_int *adx; 71285Sbill { 722434Swnj register int b, c, i; 7331Sbill char *s; 742678Swnj int any; 7531Sbill 7631Sbill loop: 772377Swnj while ((c = *fmt++) != '%') { 7831Sbill if(c == '\0') 7931Sbill return; 802377Swnj putchar(c, touser); 8131Sbill } 822377Swnj again: 8331Sbill c = *fmt++; 842781Swnj /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */ 852377Swnj switch (c) { 862377Swnj 872377Swnj case 'l': 882377Swnj goto again; 892377Swnj case 'x': case 'X': 902377Swnj b = 16; 912377Swnj goto number; 922377Swnj case 'd': case 'D': 932377Swnj case 'u': /* what a joke */ 942377Swnj b = 10; 952377Swnj goto number; 962377Swnj case 'o': case 'O': 972377Swnj b = 8; 982377Swnj number: 993101Swnj printn((u_long)*adx, b, touser); 1002377Swnj break; 1012377Swnj case 'c': 1022434Swnj b = *adx; 1032434Swnj for (i = 24; i >= 0; i -= 8) 1042434Swnj if (c = (b >> i) & 0x7f) 1052434Swnj putchar(c, touser); 1062377Swnj break; 1072678Swnj case 'b': 1082678Swnj b = *adx++; 1092678Swnj s = (char *)*adx; 1103101Swnj printn((u_long)b, *s++, touser); 1112678Swnj any = 0; 1122678Swnj if (b) { 1132678Swnj putchar('<', touser); 1142678Swnj while (i = *s++) { 1152678Swnj if (b & (1 << (i-1))) { 1162678Swnj if (any) 1172678Swnj putchar(',', touser); 1182678Swnj any = 1; 1192678Swnj for (; (c = *s) > 32; s++) 1202678Swnj putchar(c, touser); 1212678Swnj } else 1222678Swnj for (; *s > 32; s++) 1232678Swnj ; 1242678Swnj } 1253878Swnj if (any) 1263878Swnj putchar('>', touser); 1272678Swnj } 1282678Swnj break; 1292678Swnj 1302377Swnj case 's': 13131Sbill s = (char *)*adx; 132285Sbill while (c = *s++) 1332377Swnj putchar(c, touser); 1342377Swnj break; 1353736Sroot 1363736Sroot case '%': 1373736Sroot putchar('%', touser); 1383736Sroot break; 13931Sbill } 14031Sbill adx++; 14131Sbill goto loop; 14231Sbill } 14331Sbill 1442781Swnj /* 1452781Swnj * Printn prints a number n in base b. 1462781Swnj * We don't use recursion to avoid deep kernel stacks. 1472781Swnj */ 1482377Swnj printn(n, b, touser) 1493101Swnj u_long n; 15031Sbill { 1512434Swnj char prbuf[11]; 1522377Swnj register char *cp; 15331Sbill 1542377Swnj if (b == 10 && (int)n < 0) { 1552377Swnj putchar('-', touser); 1562377Swnj n = (unsigned)(-(int)n); 15731Sbill } 1582434Swnj cp = prbuf; 1592377Swnj do { 1602377Swnj *cp++ = "0123456789abcdef"[n%b]; 1612377Swnj n /= b; 1622377Swnj } while (n); 1632377Swnj do 1642377Swnj putchar(*--cp, touser); 1652434Swnj while (cp > prbuf); 16631Sbill } 16731Sbill 16831Sbill /* 1691184Sbill * Panic is called on unresolvable fatal errors. 1702781Swnj * It prints "panic: mesg", and then reboots. 1712781Swnj * If we are called twice, then we avoid trying to 1722781Swnj * sync the disks as this often leads to recursive panics. 17331Sbill */ 17431Sbill panic(s) 1752781Swnj char *s; 17631Sbill { 1775416Swnj int bootopt = RB_AUTOBOOT; 1782377Swnj 1795416Swnj if (panicstr) 1805416Swnj bootopt |= RB_NOSYNC; 1819758Ssam else { 1829758Ssam panicstr = s; 1838950Sroot } 1843285Swnj printf("panic: %s\n", s); 1852781Swnj boot(RB_PANIC, bootopt); 18631Sbill } 18731Sbill 18831Sbill /* 1892941Swnj * Warn that a system table is full. 1902941Swnj */ 1912941Swnj tablefull(tab) 1922941Swnj char *tab; 1932941Swnj { 1942941Swnj 1952941Swnj printf("%s: table is full\n", tab); 1962941Swnj } 1972941Swnj 1982941Swnj /* 1992781Swnj * Hard error is the preface to plaintive error messages 2002941Swnj * about failing disk transfers. 2012781Swnj */ 2022941Swnj harderr(bp, cp) 2032678Swnj struct buf *bp; 2042941Swnj char *cp; 20531Sbill { 20631Sbill 2072941Swnj printf("%s%d%c: hard error sn%d ", cp, 2082941Swnj dkunit(bp), 'a'+(minor(bp->b_dev)&07), bp->b_blkno); 20931Sbill } 2102781Swnj 211285Sbill /* 2122377Swnj * Print a character on console or users terminal. 213285Sbill * If destination is console then the last MSGBUFS characters 214285Sbill * are saved in msgbuf for inspection later. 215285Sbill */ 2161785Sbill /*ARGSUSED*/ 2172377Swnj putchar(c, touser) 2182377Swnj register int c; 219285Sbill { 220285Sbill 2212377Swnj if (touser) { 2222377Swnj register struct tty *tp = u.u_ttyp; 2232360Skre 2245404Swnj if (tp && (tp->t_state&TS_CARR_ON)) { 2252377Swnj register s = spl6(); 2262377Swnj if (c == '\n') 2274970Swnj (void) ttyoutput('\r', tp); 2284970Swnj (void) ttyoutput(c, tp); 2292360Skre ttstart(tp); 2302360Skre splx(s); 2312360Skre } 2322360Skre return; 2332360Skre } 2348950Sroot if (c != '\0' && c != '\r' && c != 0177 2358966Sroot #ifdef vax 2368950Sroot && mfpr(MAPEN) 2378950Sroot #endif 2388950Sroot ) { 2392172Swnj if (msgbuf.msg_magic != MSG_MAGIC) { 24012494Ssam register int i; 24112494Ssam 2422172Swnj msgbuf.msg_bufx = 0; 2432172Swnj msgbuf.msg_magic = MSG_MAGIC; 24412494Ssam for (i=0; i < MSG_BSIZE; i++) 24512494Ssam msgbuf.msg_bufc[i] = 0; 2462172Swnj } 2472172Swnj if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 2482172Swnj msgbuf.msg_bufx = 0; 2492172Swnj msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 250285Sbill } 251285Sbill if (c == 0) 252285Sbill return; 253285Sbill cnputc(c); 254285Sbill } 255