1*8966Sroot /* subr_prf.c 4.24 82/10/31 */ 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" 132360Skre #include "../h/tty.h" 1431Sbill 1531Sbill /* 1631Sbill * In case console is off, 1731Sbill * panicstr contains argument to last 1831Sbill * call to panic. 1931Sbill */ 2031Sbill char *panicstr; 2131Sbill 2231Sbill /* 2331Sbill * Scaled down version of C Library printf. 242781Swnj * Used to print diagnostic information directly on console tty. 252781Swnj * Since it is not interrupt driven, all system activities are 262781Swnj * suspended. Printf should not be used for chit-chat. 272781Swnj * 282781Swnj * One additional format: %b is supported to decode error registers. 292781Swnj * Usage is: 302781Swnj * printf("reg=%b\n", regval, "<base><arg>*"); 312781Swnj * Where <base> is the output base expressed as a control character, 322781Swnj * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 332781Swnj * characters, the first of which gives the bit number to be inspected 342781Swnj * (origin 1), and the next characters (up to a control character, i.e. 352781Swnj * a character <= 32), give the name of the register. Thus 362781Swnj * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 372781Swnj * would produce output: 382781Swnj * reg=2<BITTWO,BITONE> 3931Sbill */ 4031Sbill /*VARARGS1*/ 4131Sbill printf(fmt, x1) 422781Swnj char *fmt; 432781Swnj unsigned x1; 4431Sbill { 45285Sbill 46285Sbill prf(fmt, &x1, 0); 47285Sbill } 48285Sbill 492377Swnj /* 502781Swnj * Uprintf prints to the current user's terminal, 512781Swnj * guarantees not to sleep (so can be called by interrupt routines) 522781Swnj * and does no watermark checking - (so no verbose messages). 532377Swnj */ 542377Swnj /*VARARGS1*/ 552377Swnj uprintf(fmt, x1) 562781Swnj char *fmt; 572377Swnj unsigned x1; 58285Sbill { 59285Sbill 602377Swnj prf(fmt, &x1, 2); 61285Sbill } 62285Sbill 632377Swnj prf(fmt, adx, touser) 642781Swnj register char *fmt; 652781Swnj register u_int *adx; 66285Sbill { 672434Swnj register int b, c, i; 6831Sbill char *s; 692678Swnj int any; 7031Sbill 7131Sbill loop: 722377Swnj while ((c = *fmt++) != '%') { 7331Sbill if(c == '\0') 7431Sbill return; 752377Swnj putchar(c, touser); 7631Sbill } 772377Swnj again: 7831Sbill c = *fmt++; 792781Swnj /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */ 802377Swnj switch (c) { 812377Swnj 822377Swnj case 'l': 832377Swnj goto again; 842377Swnj case 'x': case 'X': 852377Swnj b = 16; 862377Swnj goto number; 872377Swnj case 'd': case 'D': 882377Swnj case 'u': /* what a joke */ 892377Swnj b = 10; 902377Swnj goto number; 912377Swnj case 'o': case 'O': 922377Swnj b = 8; 932377Swnj number: 943101Swnj printn((u_long)*adx, b, touser); 952377Swnj break; 962377Swnj case 'c': 972434Swnj b = *adx; 982434Swnj for (i = 24; i >= 0; i -= 8) 992434Swnj if (c = (b >> i) & 0x7f) 1002434Swnj putchar(c, touser); 1012377Swnj break; 1022678Swnj case 'b': 1032678Swnj b = *adx++; 1042678Swnj s = (char *)*adx; 1053101Swnj printn((u_long)b, *s++, touser); 1062678Swnj any = 0; 1072678Swnj if (b) { 1082678Swnj putchar('<', touser); 1092678Swnj while (i = *s++) { 1102678Swnj if (b & (1 << (i-1))) { 1112678Swnj if (any) 1122678Swnj putchar(',', touser); 1132678Swnj any = 1; 1142678Swnj for (; (c = *s) > 32; s++) 1152678Swnj putchar(c, touser); 1162678Swnj } else 1172678Swnj for (; *s > 32; s++) 1182678Swnj ; 1192678Swnj } 1203878Swnj if (any) 1213878Swnj putchar('>', touser); 1222678Swnj } 1232678Swnj break; 1242678Swnj 1252377Swnj case 's': 12631Sbill s = (char *)*adx; 127285Sbill while (c = *s++) 1282377Swnj putchar(c, touser); 1292377Swnj break; 1303736Sroot 1313736Sroot case '%': 1323736Sroot putchar('%', touser); 1333736Sroot break; 13431Sbill } 13531Sbill adx++; 13631Sbill goto loop; 13731Sbill } 13831Sbill 1392781Swnj /* 1402781Swnj * Printn prints a number n in base b. 1412781Swnj * We don't use recursion to avoid deep kernel stacks. 1422781Swnj */ 1432377Swnj printn(n, b, touser) 1443101Swnj u_long n; 14531Sbill { 1462434Swnj char prbuf[11]; 1472377Swnj register char *cp; 14831Sbill 1492377Swnj if (b == 10 && (int)n < 0) { 1502377Swnj putchar('-', touser); 1512377Swnj n = (unsigned)(-(int)n); 15231Sbill } 1532434Swnj cp = prbuf; 1542377Swnj do { 1552377Swnj *cp++ = "0123456789abcdef"[n%b]; 1562377Swnj n /= b; 1572377Swnj } while (n); 1582377Swnj do 1592377Swnj putchar(*--cp, touser); 1602434Swnj while (cp > prbuf); 16131Sbill } 16231Sbill 16331Sbill /* 1641184Sbill * Panic is called on unresolvable fatal errors. 1652781Swnj * It prints "panic: mesg", and then reboots. 1662781Swnj * If we are called twice, then we avoid trying to 1672781Swnj * sync the disks as this often leads to recursive panics. 16831Sbill */ 16931Sbill panic(s) 1702781Swnj char *s; 17131Sbill { 172*8966Sroot #ifdef sun 1738950Sroot register int *a5; 1748950Sroot #endif 1755416Swnj int bootopt = RB_AUTOBOOT; 1762377Swnj 1775416Swnj if (panicstr) 1785416Swnj bootopt |= RB_NOSYNC; 179*8966Sroot #ifdef sun 1808950Sroot else { 1818950Sroot asm("movl a6, a5"); 1828950Sroot traceback(a5, a5); 1838950Sroot } 1848950Sroot #endif 18531Sbill panicstr = s; 1863285Swnj printf("panic: %s\n", s); 1872781Swnj boot(RB_PANIC, bootopt); 18831Sbill } 18931Sbill 19031Sbill /* 1912941Swnj * Warn that a system table is full. 1922941Swnj */ 1932941Swnj tablefull(tab) 1942941Swnj char *tab; 1952941Swnj { 1962941Swnj 1972941Swnj printf("%s: table is full\n", tab); 1982941Swnj } 1992941Swnj 2002941Swnj /* 2012781Swnj * Hard error is the preface to plaintive error messages 2022941Swnj * about failing disk transfers. 2032781Swnj */ 2042941Swnj harderr(bp, cp) 2052678Swnj struct buf *bp; 2062941Swnj char *cp; 20731Sbill { 20831Sbill 2092941Swnj printf("%s%d%c: hard error sn%d ", cp, 2102941Swnj dkunit(bp), 'a'+(minor(bp->b_dev)&07), bp->b_blkno); 21131Sbill } 2122781Swnj 213285Sbill /* 2142377Swnj * Print a character on console or users terminal. 215285Sbill * If destination is console then the last MSGBUFS characters 216285Sbill * are saved in msgbuf for inspection later. 217285Sbill */ 2181785Sbill /*ARGSUSED*/ 2192377Swnj putchar(c, touser) 2202377Swnj register int c; 221285Sbill { 222285Sbill 2232377Swnj if (touser) { 2242377Swnj register struct tty *tp = u.u_ttyp; 2252360Skre 2265404Swnj if (tp && (tp->t_state&TS_CARR_ON)) { 2272377Swnj register s = spl6(); 2282377Swnj if (c == '\n') 2294970Swnj (void) ttyoutput('\r', tp); 2304970Swnj (void) ttyoutput(c, tp); 2312360Skre ttstart(tp); 2322360Skre splx(s); 2332360Skre } 2342360Skre return; 2352360Skre } 236*8966Sroot #ifdef vax 2378447Sroot #include "../vax/mtpr.h" /* XXX */ 2388950Sroot #endif 2398950Sroot if (c != '\0' && c != '\r' && c != 0177 240*8966Sroot #ifdef vax 2418950Sroot && mfpr(MAPEN) 2428950Sroot #endif 2438950Sroot ) { 2442172Swnj if (msgbuf.msg_magic != MSG_MAGIC) { 2452172Swnj msgbuf.msg_bufx = 0; 2462172Swnj msgbuf.msg_magic = MSG_MAGIC; 2472172Swnj } 2482172Swnj if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 2492172Swnj msgbuf.msg_bufx = 0; 2502172Swnj msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 251285Sbill } 252285Sbill if (c == 0) 253285Sbill return; 254285Sbill cnputc(c); 255285Sbill } 256