123381Smckusick /* 234420Skarels * Copyright (c) 1982, 1986, 1988 Regents of the University of California. 323381Smckusick * All rights reserved. The Berkeley software License Agreement 423381Smckusick * specifies the terms and conditions for redistribution. 523381Smckusick * 6*41972Smckusick * @(#)subr_prf.c 7.17 (Berkeley) 05/15/90 723381Smckusick */ 831Sbill 917094Sbloom #include "param.h" 1017094Sbloom #include "systm.h" 1117094Sbloom #include "seg.h" 1217094Sbloom #include "buf.h" 1317094Sbloom #include "conf.h" 1417094Sbloom #include "reboot.h" 1517094Sbloom #include "vm.h" 1617094Sbloom #include "msgbuf.h" 1717094Sbloom #include "user.h" 1817094Sbloom #include "proc.h" 1917577Sbloom #include "ioctl.h" 2039560Smarc #include "vnode.h" 2139560Smarc #include "file.h" 2217094Sbloom #include "tty.h" 2318364Skarels #include "syslog.h" 2431Sbill 2537496Smckusick #include "machine/mtpr.h" 2635282Skarels #ifdef KADB 2737496Smckusick #include "machine/kdbparam.h" 2830625Skarels #endif 2930625Skarels 3016724Sralph #define TOCONS 0x1 3116724Sralph #define TOTTY 0x2 3216724Sralph #define TOLOG 0x4 3316724Sralph 3431Sbill /* 3531Sbill * In case console is off, 3631Sbill * panicstr contains argument to last 3731Sbill * call to panic. 3831Sbill */ 3931Sbill char *panicstr; 4031Sbill 4130549Skarels extern cnputc(); /* standard console putc */ 4240808Smarc int (*v_putc)() = cnputc; /* routine to putc on virtual console */ 4330549Skarels extern struct tty cons; /* standard console tty */ 4430549Skarels struct tty *constty; /* pointer to console "window" tty */ 4530549Skarels 4640808Smarc #ifdef KADB 4740808Smarc extern cngetc(); /* standard console getc */ 4840808Smarc extern cnpoll(); 4940808Smarc int (*v_getc)() = cngetc; /* "" getc from virtual console */ 5040808Smarc int (*v_poll)() = cnpoll; /* kdb hook to enable input polling */ 5140808Smarc #endif 5240808Smarc 5331Sbill /* 5431Sbill * Scaled down version of C Library printf. 552781Swnj * Used to print diagnostic information directly on console tty. 562781Swnj * Since it is not interrupt driven, all system activities are 572781Swnj * suspended. Printf should not be used for chit-chat. 582781Swnj * 592781Swnj * One additional format: %b is supported to decode error registers. 602781Swnj * Usage is: 612781Swnj * printf("reg=%b\n", regval, "<base><arg>*"); 622781Swnj * Where <base> is the output base expressed as a control character, 632781Swnj * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 642781Swnj * characters, the first of which gives the bit number to be inspected 652781Swnj * (origin 1), and the next characters (up to a control character, i.e. 662781Swnj * a character <= 32), give the name of the register. Thus 672781Swnj * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 682781Swnj * would produce output: 6917594Skarels * reg=3<BITTWO,BITONE> 7034478Skarels * 7134478Skarels * Another additional format: %r is used to pass an additional format string 7234478Skarels * and argument list recursively. Usage is typically: 7334478Skarels * 7434478Skarels * fn(otherstuff, fmt [, arg1, ... ] ) 7534478Skarels * char *fmt; 7634478Skarels * u_int arg1, ...; 7734478Skarels * 7834478Skarels * printf("prefix: %r, other stuff\n", fmt, &arg1); 7931Sbill */ 8029946Skarels #if defined(tahoe) 8129946Skarels int consintr; 8229946Skarels #endif 8329946Skarels 8431Sbill /*VARARGS1*/ 8531Sbill printf(fmt, x1) 862781Swnj char *fmt; 872781Swnj unsigned x1; 8831Sbill { 8929946Skarels #if defined(tahoe) 9029946Skarels register int savintr; 91285Sbill 9229946Skarels savintr = consintr, consintr = 0; /* disable interrupts */ 9329946Skarels #endif 9439560Smarc prf(fmt, &x1, TOCONS | TOLOG, (caddr_t)0); 95*41972Smckusick if (!panicstr) 96*41972Smckusick logwakeup(); 9729946Skarels #if defined(tahoe) 9829946Skarels consintr = savintr; /* reenable interrupts */ 9929946Skarels #endif 100285Sbill } 101285Sbill 1022377Swnj /* 10339560Smarc * Uprintf prints to the controlling terminal for the current process. 10425389Skarels * It may block if the tty queue is overfull. 10530695Skarels * No message is printed if the queue does not clear 10630695Skarels * in a reasonable time. 1072377Swnj */ 1082377Swnj /*VARARGS1*/ 1092377Swnj uprintf(fmt, x1) 1102781Swnj char *fmt; 1112377Swnj unsigned x1; 112285Sbill { 11339560Smarc register struct tty *tp = u.u_procp->p_session->s_ttyp; 114285Sbill 11539560Smarc if (tp != NULL && tp->t_session == u.u_procp->p_session) 116*41972Smckusick prf(fmt, &x1, TOTTY, (caddr_t)tp); 117285Sbill } 118285Sbill 11918364Skarels /* 12018364Skarels * tprintf prints on the specified terminal (console if none) 12118364Skarels * and logs the message. It is designed for error messages from 12225389Skarels * single-open devices, and may be called from interrupt level 12325389Skarels * (does not sleep). 12418364Skarels */ 12516724Sralph /*VARARGS2*/ 12639560Smarc tprintf(vp, fmt, x1) 12739560Smarc register caddr_t vp; 12816724Sralph char *fmt; 12916724Sralph unsigned x1; 13016724Sralph { 131*41972Smckusick #ifdef notyet 13225389Skarels int flags = TOTTY | TOLOG; 13316724Sralph 13425389Skarels logpri(LOG_INFO); 13539560Smarc 13639560Smarc if (vp == NULL || 13739560Smarc VOP_IOCTL(vp, TIOCCHECKOUTQ, &val, FWRITE, NOCRED) != 0 || 13839560Smarc val == 0) 13925389Skarels flags = TOLOG; 14039560Smarc prf(fmt, &x1, flags, vp); 14125389Skarels logwakeup(); 14239560Smarc #else 14339560Smarc printf("tprintf called\n"); 14439560Smarc #endif 14516724Sralph } 14616724Sralph 14716724Sralph /* 14816724Sralph * Log writes to the log buffer, 14917594Skarels * and guarantees not to sleep (so can be called by interrupt routines). 15018364Skarels * If there is no process reading the log yet, it writes to the console also. 15116724Sralph */ 15216724Sralph /*VARARGS2*/ 15316724Sralph log(level, fmt, x1) 15416724Sralph char *fmt; 15516724Sralph unsigned x1; 15616724Sralph { 15716724Sralph register s = splhigh(); 15818364Skarels extern int log_open; 15916724Sralph 16025389Skarels logpri(level); 16139560Smarc prf(fmt, &x1, TOLOG, (caddr_t)0); 16216724Sralph splx(s); 16318364Skarels if (!log_open) 16439560Smarc prf(fmt, &x1, TOCONS, (caddr_t)0); 16516724Sralph logwakeup(); 16616724Sralph } 16716724Sralph 16825389Skarels logpri(level) 16925389Skarels int level; 17025389Skarels { 17125389Skarels 172*41972Smckusick putchar('<', TOLOG, (caddr_t)0); 173*41972Smckusick printn((u_long)level, 10, TOLOG, (caddr_t)0); 174*41972Smckusick putchar('>', TOLOG, (caddr_t)0); 17525389Skarels } 17625389Skarels 17733479Skarels /*VARARGS1*/ 17833479Skarels addlog(fmt, x1) 17933479Skarels char *fmt; 18033479Skarels unsigned x1; 18133479Skarels { 18233479Skarels register s = splhigh(); 18333479Skarels 18439560Smarc prf(fmt, &x1, TOLOG, (caddr_t)0); 18533479Skarels splx(s); 18633479Skarels if (!log_open) 18739560Smarc prf(fmt, &x1, TOCONS, (caddr_t)0); 18833479Skarels logwakeup(); 18933479Skarels } 19033479Skarels 19139560Smarc prf(fmt, adx, flags, where) 1922781Swnj register char *fmt; 1932781Swnj register u_int *adx; 19439560Smarc caddr_t where; 195285Sbill { 1962434Swnj register int b, c, i; 19731Sbill char *s; 1982678Swnj int any; 19931Sbill 20031Sbill loop: 2012377Swnj while ((c = *fmt++) != '%') { 20216724Sralph if (c == '\0') 20331Sbill return; 20439560Smarc putchar(c, flags, where); 20531Sbill } 2062377Swnj again: 20731Sbill c = *fmt++; 20829946Skarels /* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */ 2092377Swnj switch (c) { 2102377Swnj 2112377Swnj case 'l': 2122377Swnj goto again; 2132377Swnj case 'x': case 'X': 2142377Swnj b = 16; 2152377Swnj goto number; 2162377Swnj case 'd': case 'D': 21729946Skarels b = -10; 21829946Skarels goto number; 21929946Skarels case 'u': 2202377Swnj b = 10; 2212377Swnj goto number; 2222377Swnj case 'o': case 'O': 2232377Swnj b = 8; 2242377Swnj number: 22539560Smarc printn((u_long)*adx, b, flags, where); 2262377Swnj break; 2272377Swnj case 'c': 2282434Swnj b = *adx; 22933479Skarels #if BYTE_ORDER == LITTLE_ENDIAN 2302434Swnj for (i = 24; i >= 0; i -= 8) 2312434Swnj if (c = (b >> i) & 0x7f) 23239560Smarc putchar(c, flags, where); 23329946Skarels #endif 23433479Skarels #if BYTE_ORDER == BIG_ENDIAN 23529946Skarels if (c = (b & 0x7f)) 23639560Smarc putchar(c, flags, where); 23729946Skarels #endif 2382377Swnj break; 2392678Swnj case 'b': 2402678Swnj b = *adx++; 2412678Swnj s = (char *)*adx; 24239560Smarc printn((u_long)b, *s++, flags, where); 2432678Swnj any = 0; 2442678Swnj if (b) { 2452678Swnj while (i = *s++) { 2462678Swnj if (b & (1 << (i-1))) { 24739560Smarc putchar(any ? ',' : '<', flags, where); 2482678Swnj any = 1; 2492678Swnj for (; (c = *s) > 32; s++) 25039560Smarc putchar(c, flags, where); 2512678Swnj } else 2522678Swnj for (; *s > 32; s++) 2532678Swnj ; 2542678Swnj } 2553878Swnj if (any) 25639560Smarc putchar('>', flags, where); 2572678Swnj } 2582678Swnj break; 2592678Swnj 2602377Swnj case 's': 26131Sbill s = (char *)*adx; 262285Sbill while (c = *s++) 26339560Smarc putchar(c, flags, where); 2642377Swnj break; 2653736Sroot 26633479Skarels case 'r': 26733479Skarels s = (char *)*adx++; 26839560Smarc prf(s, (u_int *)*adx, flags, where); 26933479Skarels break; 27033479Skarels 2713736Sroot case '%': 27239560Smarc putchar('%', flags, where); 2733736Sroot break; 27431Sbill } 27531Sbill adx++; 27631Sbill goto loop; 27731Sbill } 27831Sbill 2792781Swnj /* 2802781Swnj * Printn prints a number n in base b. 2812781Swnj * We don't use recursion to avoid deep kernel stacks. 2822781Swnj */ 28339560Smarc printn(n, b, flags, where) 2843101Swnj u_long n; 28539560Smarc caddr_t where; 28631Sbill { 2872434Swnj char prbuf[11]; 2882377Swnj register char *cp; 28931Sbill 29029946Skarels if (b == -10) { 29129946Skarels if ((int)n < 0) { 29239560Smarc putchar('-', flags, where); 29329946Skarels n = (unsigned)(-(int)n); 29429946Skarels } 29529946Skarels b = -b; 29631Sbill } 2972434Swnj cp = prbuf; 2982377Swnj do { 2992377Swnj *cp++ = "0123456789abcdef"[n%b]; 3002377Swnj n /= b; 3012377Swnj } while (n); 3022377Swnj do 30339560Smarc putchar(*--cp, flags, where); 3042434Swnj while (cp > prbuf); 30531Sbill } 30631Sbill 30731Sbill /* 3081184Sbill * Panic is called on unresolvable fatal errors. 3092781Swnj * It prints "panic: mesg", and then reboots. 3102781Swnj * If we are called twice, then we avoid trying to 3112781Swnj * sync the disks as this often leads to recursive panics. 31231Sbill */ 31331Sbill panic(s) 3142781Swnj char *s; 31531Sbill { 31630566Skarels int bootopt = RB_AUTOBOOT | RB_DUMP; 3172377Swnj 3185416Swnj if (panicstr) 3195416Swnj bootopt |= RB_NOSYNC; 3209758Ssam else { 3219758Ssam panicstr = s; 3228950Sroot } 3233285Swnj printf("panic: %s\n", s); 32435282Skarels #ifdef KADB 32530625Skarels if (boothowto & RB_KDB) { 32634420Skarels int x = splnet(); /* below kdb pri */ 32730625Skarels 32830625Skarels setsoftkdb(); 32934420Skarels splx(x); 33030625Skarels } 33130625Skarels #endif 33230566Skarels boot(bootopt); 33331Sbill } 33431Sbill 33531Sbill /* 3362941Swnj * Warn that a system table is full. 3372941Swnj */ 3382941Swnj tablefull(tab) 3392941Swnj char *tab; 3402941Swnj { 3412941Swnj 34224839Seric log(LOG_ERR, "%s: table is full\n", tab); 3432941Swnj } 3442941Swnj 3452941Swnj /* 3462377Swnj * Print a character on console or users terminal. 347285Sbill * If destination is console then the last MSGBUFS characters 348285Sbill * are saved in msgbuf for inspection later. 349285Sbill */ 3501785Sbill /*ARGSUSED*/ 35139560Smarc putchar(c, flags, where) 3522377Swnj register int c; 35339560Smarc caddr_t where; 354285Sbill { 35533479Skarels extern int msgbufmapped; 356285Sbill 35730549Skarels if (panicstr) 35830549Skarels constty = 0; 35939560Smarc if ((flags & TOCONS) && where == 0 && constty) { 36039560Smarc where = (caddr_t)constty; 36130549Skarels flags |= TOTTY; 36230549Skarels } 36339560Smarc if ((flags & TOTTY) && where && tputchar(c, (struct tty *)where) < 0 && 36439560Smarc (flags & TOCONS) && (struct tty *)where == constty) 36539560Smarc constty = 0; 36633479Skarels if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 && 36733479Skarels msgbufmapped) { 3682172Swnj if (msgbuf.msg_magic != MSG_MAGIC) { 36912494Ssam register int i; 37012494Ssam 3712172Swnj msgbuf.msg_magic = MSG_MAGIC; 37216724Sralph msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 37312494Ssam for (i=0; i < MSG_BSIZE; i++) 37412494Ssam msgbuf.msg_bufc[i] = 0; 3752172Swnj } 37626427Sbloom msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 3772172Swnj if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 3782172Swnj msgbuf.msg_bufx = 0; 379285Sbill } 38030549Skarels if ((flags & TOCONS) && constty == 0 && c != '\0') 38130549Skarels (*v_putc)(c); 382285Sbill } 383