1*9758Ssam /* subr_prf.c 4.25 82/12/17 */ 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" 13*9758Ssam #include "../h/proc.h" 142360Skre #include "../h/tty.h" 1531Sbill 1631Sbill /* 1731Sbill * In case console is off, 1831Sbill * panicstr contains argument to last 1931Sbill * call to panic. 2031Sbill */ 2131Sbill char *panicstr; 2231Sbill 2331Sbill /* 2431Sbill * Scaled down version of C Library printf. 252781Swnj * Used to print diagnostic information directly on console tty. 262781Swnj * Since it is not interrupt driven, all system activities are 272781Swnj * suspended. Printf should not be used for chit-chat. 282781Swnj * 292781Swnj * One additional format: %b is supported to decode error registers. 302781Swnj * Usage is: 312781Swnj * printf("reg=%b\n", regval, "<base><arg>*"); 322781Swnj * Where <base> is the output base expressed as a control character, 332781Swnj * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 342781Swnj * characters, the first of which gives the bit number to be inspected 352781Swnj * (origin 1), and the next characters (up to a control character, i.e. 362781Swnj * a character <= 32), give the name of the register. Thus 372781Swnj * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 382781Swnj * would produce output: 392781Swnj * reg=2<BITTWO,BITONE> 4031Sbill */ 4131Sbill /*VARARGS1*/ 4231Sbill printf(fmt, x1) 432781Swnj char *fmt; 442781Swnj unsigned x1; 4531Sbill { 46285Sbill 47285Sbill prf(fmt, &x1, 0); 48285Sbill } 49285Sbill 502377Swnj /* 512781Swnj * Uprintf prints to the current user's terminal, 522781Swnj * guarantees not to sleep (so can be called by interrupt routines) 532781Swnj * and does no watermark checking - (so no verbose messages). 542377Swnj */ 552377Swnj /*VARARGS1*/ 562377Swnj uprintf(fmt, x1) 572781Swnj char *fmt; 582377Swnj unsigned x1; 59285Sbill { 60285Sbill 612377Swnj prf(fmt, &x1, 2); 62285Sbill } 63285Sbill 642377Swnj prf(fmt, adx, touser) 652781Swnj register char *fmt; 662781Swnj register u_int *adx; 67285Sbill { 682434Swnj register int b, c, i; 6931Sbill char *s; 702678Swnj int any; 7131Sbill 7231Sbill loop: 732377Swnj while ((c = *fmt++) != '%') { 7431Sbill if(c == '\0') 7531Sbill return; 762377Swnj putchar(c, touser); 7731Sbill } 782377Swnj again: 7931Sbill c = *fmt++; 802781Swnj /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */ 812377Swnj switch (c) { 822377Swnj 832377Swnj case 'l': 842377Swnj goto again; 852377Swnj case 'x': case 'X': 862377Swnj b = 16; 872377Swnj goto number; 882377Swnj case 'd': case 'D': 892377Swnj case 'u': /* what a joke */ 902377Swnj b = 10; 912377Swnj goto number; 922377Swnj case 'o': case 'O': 932377Swnj b = 8; 942377Swnj number: 953101Swnj printn((u_long)*adx, b, touser); 962377Swnj break; 972377Swnj case 'c': 982434Swnj b = *adx; 992434Swnj for (i = 24; i >= 0; i -= 8) 1002434Swnj if (c = (b >> i) & 0x7f) 1012434Swnj putchar(c, touser); 1022377Swnj break; 1032678Swnj case 'b': 1042678Swnj b = *adx++; 1052678Swnj s = (char *)*adx; 1063101Swnj printn((u_long)b, *s++, touser); 1072678Swnj any = 0; 1082678Swnj if (b) { 1092678Swnj putchar('<', touser); 1102678Swnj while (i = *s++) { 1112678Swnj if (b & (1 << (i-1))) { 1122678Swnj if (any) 1132678Swnj putchar(',', touser); 1142678Swnj any = 1; 1152678Swnj for (; (c = *s) > 32; s++) 1162678Swnj putchar(c, touser); 1172678Swnj } else 1182678Swnj for (; *s > 32; s++) 1192678Swnj ; 1202678Swnj } 1213878Swnj if (any) 1223878Swnj putchar('>', touser); 1232678Swnj } 1242678Swnj break; 1252678Swnj 1262377Swnj case 's': 12731Sbill s = (char *)*adx; 128285Sbill while (c = *s++) 1292377Swnj putchar(c, touser); 1302377Swnj break; 1313736Sroot 1323736Sroot case '%': 1333736Sroot putchar('%', touser); 1343736Sroot break; 13531Sbill } 13631Sbill adx++; 13731Sbill goto loop; 13831Sbill } 13931Sbill 1402781Swnj /* 1412781Swnj * Printn prints a number n in base b. 1422781Swnj * We don't use recursion to avoid deep kernel stacks. 1432781Swnj */ 1442377Swnj printn(n, b, touser) 1453101Swnj u_long n; 14631Sbill { 1472434Swnj char prbuf[11]; 1482377Swnj register char *cp; 14931Sbill 1502377Swnj if (b == 10 && (int)n < 0) { 1512377Swnj putchar('-', touser); 1522377Swnj n = (unsigned)(-(int)n); 15331Sbill } 1542434Swnj cp = prbuf; 1552377Swnj do { 1562377Swnj *cp++ = "0123456789abcdef"[n%b]; 1572377Swnj n /= b; 1582377Swnj } while (n); 1592377Swnj do 1602377Swnj putchar(*--cp, touser); 1612434Swnj while (cp > prbuf); 16231Sbill } 16331Sbill 16431Sbill /* 1651184Sbill * Panic is called on unresolvable fatal errors. 1662781Swnj * It prints "panic: mesg", and then reboots. 1672781Swnj * If we are called twice, then we avoid trying to 1682781Swnj * sync the disks as this often leads to recursive panics. 16931Sbill */ 17031Sbill panic(s) 1712781Swnj char *s; 17231Sbill { 1738966Sroot #ifdef sun 1748950Sroot register int *a5; 1758950Sroot #endif 1765416Swnj int bootopt = RB_AUTOBOOT; 1772377Swnj 1785416Swnj if (panicstr) 1795416Swnj bootopt |= RB_NOSYNC; 180*9758Ssam else { 181*9758Ssam panicstr = s; 1828966Sroot #ifdef sun 1838950Sroot asm("movl a6, a5"); 1848950Sroot traceback(a5, a5); 185*9758Ssam resume(pcbb(u.u_procp)); /* for adb traceback */ 186*9758Ssam #endif 1878950Sroot } 1883285Swnj printf("panic: %s\n", s); 1892781Swnj boot(RB_PANIC, bootopt); 19031Sbill } 19131Sbill 19231Sbill /* 1932941Swnj * Warn that a system table is full. 1942941Swnj */ 1952941Swnj tablefull(tab) 1962941Swnj char *tab; 1972941Swnj { 1982941Swnj 1992941Swnj printf("%s: table is full\n", tab); 2002941Swnj } 2012941Swnj 2022941Swnj /* 2032781Swnj * Hard error is the preface to plaintive error messages 2042941Swnj * about failing disk transfers. 2052781Swnj */ 2062941Swnj harderr(bp, cp) 2072678Swnj struct buf *bp; 2082941Swnj char *cp; 20931Sbill { 21031Sbill 2112941Swnj printf("%s%d%c: hard error sn%d ", cp, 2122941Swnj dkunit(bp), 'a'+(minor(bp->b_dev)&07), bp->b_blkno); 21331Sbill } 2142781Swnj 215285Sbill /* 2162377Swnj * Print a character on console or users terminal. 217285Sbill * If destination is console then the last MSGBUFS characters 218285Sbill * are saved in msgbuf for inspection later. 219285Sbill */ 2201785Sbill /*ARGSUSED*/ 2212377Swnj putchar(c, touser) 2222377Swnj register int c; 223285Sbill { 224285Sbill 2252377Swnj if (touser) { 2262377Swnj register struct tty *tp = u.u_ttyp; 2272360Skre 2285404Swnj if (tp && (tp->t_state&TS_CARR_ON)) { 2292377Swnj register s = spl6(); 2302377Swnj if (c == '\n') 2314970Swnj (void) ttyoutput('\r', tp); 2324970Swnj (void) ttyoutput(c, tp); 2332360Skre ttstart(tp); 2342360Skre splx(s); 2352360Skre } 2362360Skre return; 2372360Skre } 2388966Sroot #ifdef vax 2398447Sroot #include "../vax/mtpr.h" /* XXX */ 2408950Sroot #endif 2418950Sroot if (c != '\0' && c != '\r' && c != 0177 2428966Sroot #ifdef vax 2438950Sroot && mfpr(MAPEN) 2448950Sroot #endif 2458950Sroot ) { 2462172Swnj if (msgbuf.msg_magic != MSG_MAGIC) { 2472172Swnj msgbuf.msg_bufx = 0; 2482172Swnj msgbuf.msg_magic = MSG_MAGIC; 2492172Swnj } 2502172Swnj if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 2512172Swnj msgbuf.msg_bufx = 0; 2522172Swnj msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 253285Sbill } 254285Sbill if (c == 0) 255285Sbill return; 256285Sbill cnputc(c); 257285Sbill } 258