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*40808Smarc * @(#)subr_prf.c 7.16 (Berkeley) 04/05/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 */ 42*40808Smarc 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 46*40808Smarc #ifdef KADB 47*40808Smarc extern cngetc(); /* standard console getc */ 48*40808Smarc extern cnpoll(); 49*40808Smarc int (*v_getc)() = cngetc; /* "" getc from virtual console */ 50*40808Smarc int (*v_poll)() = cnpoll; /* kdb hook to enable input polling */ 51*40808Smarc #endif 52*40808Smarc 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); 9516724Sralph logwakeup(); 9629946Skarels #if defined(tahoe) 9729946Skarels consintr = savintr; /* reenable interrupts */ 9829946Skarels #endif 99285Sbill } 100285Sbill 1012377Swnj /* 10239560Smarc * Uprintf prints to the controlling terminal for the current process. 10325389Skarels * It may block if the tty queue is overfull. 10430695Skarels * No message is printed if the queue does not clear 10530695Skarels * in a reasonable time. 1062377Swnj */ 1072377Swnj /*VARARGS1*/ 1082377Swnj uprintf(fmt, x1) 1092781Swnj char *fmt; 1102377Swnj unsigned x1; 111285Sbill { 11239560Smarc register struct tty *tp = u.u_procp->p_session->s_ttyp; 113285Sbill 11439560Smarc if (tp != NULL && tp->t_session == u.u_procp->p_session) 11530695Skarels prf(fmt, &x1, TOTTY, tp); 116285Sbill } 117285Sbill 11818364Skarels /* 11918364Skarels * tprintf prints on the specified terminal (console if none) 12018364Skarels * and logs the message. It is designed for error messages from 12125389Skarels * single-open devices, and may be called from interrupt level 12225389Skarels * (does not sleep). 12318364Skarels */ 12416724Sralph /*VARARGS2*/ 12539560Smarc tprintf(vp, fmt, x1) 12639560Smarc register caddr_t vp; 12716724Sralph char *fmt; 12816724Sralph unsigned x1; 12916724Sralph { 13025389Skarels int flags = TOTTY | TOLOG; 13116724Sralph 13239560Smarc #ifdef notyet 13325389Skarels logpri(LOG_INFO); 13439560Smarc 13539560Smarc if (vp == NULL || 13639560Smarc VOP_IOCTL(vp, TIOCCHECKOUTQ, &val, FWRITE, NOCRED) != 0 || 13739560Smarc val == 0) 13825389Skarels flags = TOLOG; 13939560Smarc prf(fmt, &x1, flags, vp); 14025389Skarels logwakeup(); 14139560Smarc #else 14239560Smarc printf("tprintf called\n"); 14339560Smarc #endif 14416724Sralph } 14516724Sralph 14616724Sralph /* 14716724Sralph * Log writes to the log buffer, 14817594Skarels * and guarantees not to sleep (so can be called by interrupt routines). 14918364Skarels * If there is no process reading the log yet, it writes to the console also. 15016724Sralph */ 15116724Sralph /*VARARGS2*/ 15216724Sralph log(level, fmt, x1) 15316724Sralph char *fmt; 15416724Sralph unsigned x1; 15516724Sralph { 15616724Sralph register s = splhigh(); 15718364Skarels extern int log_open; 15816724Sralph 15925389Skarels logpri(level); 16039560Smarc prf(fmt, &x1, TOLOG, (caddr_t)0); 16116724Sralph splx(s); 16218364Skarels if (!log_open) 16339560Smarc prf(fmt, &x1, TOCONS, (caddr_t)0); 16416724Sralph logwakeup(); 16516724Sralph } 16616724Sralph 16725389Skarels logpri(level) 16825389Skarels int level; 16925389Skarels { 17025389Skarels 17125389Skarels putchar('<', TOLOG, (struct tty *)0); 17226356Skarels printn((u_long)level, 10, TOLOG, (struct tty *)0); 17325389Skarels putchar('>', TOLOG, (struct tty *)0); 17425389Skarels } 17525389Skarels 17633479Skarels /*VARARGS1*/ 17733479Skarels addlog(fmt, x1) 17833479Skarels char *fmt; 17933479Skarels unsigned x1; 18033479Skarels { 18133479Skarels register s = splhigh(); 18233479Skarels 18339560Smarc prf(fmt, &x1, TOLOG, (caddr_t)0); 18433479Skarels splx(s); 18533479Skarels if (!log_open) 18639560Smarc prf(fmt, &x1, TOCONS, (caddr_t)0); 18733479Skarels logwakeup(); 18833479Skarels } 18933479Skarels 19039560Smarc prf(fmt, adx, flags, where) 1912781Swnj register char *fmt; 1922781Swnj register u_int *adx; 19339560Smarc caddr_t where; 194285Sbill { 1952434Swnj register int b, c, i; 19631Sbill char *s; 1972678Swnj int any; 19831Sbill 19931Sbill loop: 2002377Swnj while ((c = *fmt++) != '%') { 20116724Sralph if (c == '\0') 20231Sbill return; 20339560Smarc putchar(c, flags, where); 20431Sbill } 2052377Swnj again: 20631Sbill c = *fmt++; 20729946Skarels /* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */ 2082377Swnj switch (c) { 2092377Swnj 2102377Swnj case 'l': 2112377Swnj goto again; 2122377Swnj case 'x': case 'X': 2132377Swnj b = 16; 2142377Swnj goto number; 2152377Swnj case 'd': case 'D': 21629946Skarels b = -10; 21729946Skarels goto number; 21829946Skarels case 'u': 2192377Swnj b = 10; 2202377Swnj goto number; 2212377Swnj case 'o': case 'O': 2222377Swnj b = 8; 2232377Swnj number: 22439560Smarc printn((u_long)*adx, b, flags, where); 2252377Swnj break; 2262377Swnj case 'c': 2272434Swnj b = *adx; 22833479Skarels #if BYTE_ORDER == LITTLE_ENDIAN 2292434Swnj for (i = 24; i >= 0; i -= 8) 2302434Swnj if (c = (b >> i) & 0x7f) 23139560Smarc putchar(c, flags, where); 23229946Skarels #endif 23333479Skarels #if BYTE_ORDER == BIG_ENDIAN 23429946Skarels if (c = (b & 0x7f)) 23539560Smarc putchar(c, flags, where); 23629946Skarels #endif 2372377Swnj break; 2382678Swnj case 'b': 2392678Swnj b = *adx++; 2402678Swnj s = (char *)*adx; 24139560Smarc printn((u_long)b, *s++, flags, where); 2422678Swnj any = 0; 2432678Swnj if (b) { 2442678Swnj while (i = *s++) { 2452678Swnj if (b & (1 << (i-1))) { 24639560Smarc putchar(any ? ',' : '<', flags, where); 2472678Swnj any = 1; 2482678Swnj for (; (c = *s) > 32; s++) 24939560Smarc putchar(c, flags, where); 2502678Swnj } else 2512678Swnj for (; *s > 32; s++) 2522678Swnj ; 2532678Swnj } 2543878Swnj if (any) 25539560Smarc putchar('>', flags, where); 2562678Swnj } 2572678Swnj break; 2582678Swnj 2592377Swnj case 's': 26031Sbill s = (char *)*adx; 261285Sbill while (c = *s++) 26239560Smarc putchar(c, flags, where); 2632377Swnj break; 2643736Sroot 26533479Skarels case 'r': 26633479Skarels s = (char *)*adx++; 26739560Smarc prf(s, (u_int *)*adx, flags, where); 26833479Skarels break; 26933479Skarels 2703736Sroot case '%': 27139560Smarc putchar('%', flags, where); 2723736Sroot break; 27331Sbill } 27431Sbill adx++; 27531Sbill goto loop; 27631Sbill } 27731Sbill 2782781Swnj /* 2792781Swnj * Printn prints a number n in base b. 2802781Swnj * We don't use recursion to avoid deep kernel stacks. 2812781Swnj */ 28239560Smarc printn(n, b, flags, where) 2833101Swnj u_long n; 28439560Smarc caddr_t where; 28531Sbill { 2862434Swnj char prbuf[11]; 2872377Swnj register char *cp; 28831Sbill 28929946Skarels if (b == -10) { 29029946Skarels if ((int)n < 0) { 29139560Smarc putchar('-', flags, where); 29229946Skarels n = (unsigned)(-(int)n); 29329946Skarels } 29429946Skarels b = -b; 29531Sbill } 2962434Swnj cp = prbuf; 2972377Swnj do { 2982377Swnj *cp++ = "0123456789abcdef"[n%b]; 2992377Swnj n /= b; 3002377Swnj } while (n); 3012377Swnj do 30239560Smarc putchar(*--cp, flags, where); 3032434Swnj while (cp > prbuf); 30431Sbill } 30531Sbill 30631Sbill /* 3071184Sbill * Panic is called on unresolvable fatal errors. 3082781Swnj * It prints "panic: mesg", and then reboots. 3092781Swnj * If we are called twice, then we avoid trying to 3102781Swnj * sync the disks as this often leads to recursive panics. 31131Sbill */ 31231Sbill panic(s) 3132781Swnj char *s; 31431Sbill { 31530566Skarels int bootopt = RB_AUTOBOOT | RB_DUMP; 3162377Swnj 3175416Swnj if (panicstr) 3185416Swnj bootopt |= RB_NOSYNC; 3199758Ssam else { 3209758Ssam panicstr = s; 3218950Sroot } 3223285Swnj printf("panic: %s\n", s); 32335282Skarels #ifdef KADB 32430625Skarels if (boothowto & RB_KDB) { 32534420Skarels int x = splnet(); /* below kdb pri */ 32630625Skarels 32730625Skarels setsoftkdb(); 32834420Skarels splx(x); 32930625Skarels } 33030625Skarels #endif 33130566Skarels boot(bootopt); 33231Sbill } 33331Sbill 33431Sbill /* 3352941Swnj * Warn that a system table is full. 3362941Swnj */ 3372941Swnj tablefull(tab) 3382941Swnj char *tab; 3392941Swnj { 3402941Swnj 34124839Seric log(LOG_ERR, "%s: table is full\n", tab); 3422941Swnj } 3432941Swnj 3442941Swnj /* 3452377Swnj * Print a character on console or users terminal. 346285Sbill * If destination is console then the last MSGBUFS characters 347285Sbill * are saved in msgbuf for inspection later. 348285Sbill */ 3491785Sbill /*ARGSUSED*/ 35039560Smarc putchar(c, flags, where) 3512377Swnj register int c; 35239560Smarc caddr_t where; 353285Sbill { 35433479Skarels extern int msgbufmapped; 355285Sbill 35630549Skarels if (panicstr) 35730549Skarels constty = 0; 35839560Smarc if ((flags & TOCONS) && where == 0 && constty) { 35939560Smarc where = (caddr_t)constty; 36030549Skarels flags |= TOTTY; 36130549Skarels } 36239560Smarc if ((flags & TOTTY) && where && tputchar(c, (struct tty *)where) < 0 && 36339560Smarc (flags & TOCONS) && (struct tty *)where == constty) 36439560Smarc constty = 0; 36533479Skarels if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 && 36633479Skarels msgbufmapped) { 3672172Swnj if (msgbuf.msg_magic != MSG_MAGIC) { 36812494Ssam register int i; 36912494Ssam 3702172Swnj msgbuf.msg_magic = MSG_MAGIC; 37116724Sralph msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 37212494Ssam for (i=0; i < MSG_BSIZE; i++) 37312494Ssam msgbuf.msg_bufc[i] = 0; 3742172Swnj } 37526427Sbloom msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 3762172Swnj if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 3772172Swnj msgbuf.msg_bufx = 0; 378285Sbill } 37930549Skarels if ((flags & TOCONS) && constty == 0 && c != '\0') 38030549Skarels (*v_putc)(c); 381285Sbill } 382