xref: /csrg-svn/sys/kern/subr_prf.c (revision 41972)
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