minor optimization
[unix-history] / usr / src / sys / kern / subr_prf.c
CommitLineData
da7c5cc6 1/*
e018935f 2 * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
71e86b6c 6 * @(#)subr_prf.c 7.15 (Berkeley) %G%
da7c5cc6 7 */
8cbb423c 8
94368568
JB
9#include "param.h"
10#include "systm.h"
11#include "seg.h"
12#include "buf.h"
13#include "conf.h"
14#include "reboot.h"
15#include "vm.h"
16#include "msgbuf.h"
94368568
JB
17#include "user.h"
18#include "proc.h"
3358b36b 19#include "ioctl.h"
71e86b6c
MT
20#include "vnode.h"
21#include "file.h"
94368568 22#include "tty.h"
bd10af3f 23#include "syslog.h"
96d38f03 24
40ed2c45 25#include "machine/mtpr.h"
f7f8b75f 26#ifdef KADB
40ed2c45 27#include "machine/kdbparam.h"
3eb8e016
MK
28#endif
29
34ef3482
RC
30#define TOCONS 0x1
31#define TOTTY 0x2
32#define TOLOG 0x4
33
8cbb423c
BJ
34/*
35 * In case console is off,
36 * panicstr contains argument to last
37 * call to panic.
38 */
8cbb423c
BJ
39char *panicstr;
40
ed2d0915
MK
41extern cnputc(); /* standard console putc */
42extern struct tty cons; /* standard console tty */
43struct tty *constty; /* pointer to console "window" tty */
44int (*v_putc)() = cnputc; /* routine to putc on virtual console */
45
1d4b2ce4
MK
46extern cnputc(); /* standard console putc */
47extern struct tty cons; /* standard console tty */
48struct tty *constty; /* pointer to console "window" tty */
49int (*v_console)() = cnputc; /* routine to putc on virtual console */
50
8cbb423c
BJ
51/*
52 * Scaled down version of C Library printf.
b725a0ca
BJ
53 * Used to print diagnostic information directly on console tty.
54 * Since it is not interrupt driven, all system activities are
55 * suspended. Printf should not be used for chit-chat.
56 *
57 * One additional format: %b is supported to decode error registers.
58 * Usage is:
59 * printf("reg=%b\n", regval, "<base><arg>*");
60 * Where <base> is the output base expressed as a control character,
61 * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of
62 * characters, the first of which gives the bit number to be inspected
63 * (origin 1), and the next characters (up to a control character, i.e.
64 * a character <= 32), give the name of the register. Thus
65 * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
66 * would produce output:
8d907ccf 67 * reg=3<BITTWO,BITONE>
6a79e262
MK
68 *
69 * Another additional format: %r is used to pass an additional format string
70 * and argument list recursively. Usage is typically:
71 *
72 * fn(otherstuff, fmt [, arg1, ... ] )
73 * char *fmt;
74 * u_int arg1, ...;
75 *
76 * printf("prefix: %r, other stuff\n", fmt, &arg1);
8cbb423c 77 */
fb1db32c
MK
78#if defined(tahoe)
79int consintr;
80#endif
81
8cbb423c
BJ
82/*VARARGS1*/
83printf(fmt, x1)
b725a0ca
BJ
84 char *fmt;
85 unsigned x1;
96d38f03 86{
fb1db32c
MK
87#if defined(tahoe)
88 register int savintr;
96d38f03 89
fb1db32c
MK
90 savintr = consintr, consintr = 0; /* disable interrupts */
91#endif
71e86b6c 92 prf(fmt, &x1, TOCONS | TOLOG, (caddr_t)0);
34ef3482 93 logwakeup();
fb1db32c
MK
94#if defined(tahoe)
95 consintr = savintr; /* reenable interrupts */
96#endif
96d38f03
BJ
97}
98
843267b1 99/*
71e86b6c 100 * Uprintf prints to the controlling terminal for the current process.
6f71a9f6 101 * It may block if the tty queue is overfull.
ca9b16e5
MK
102 * No message is printed if the queue does not clear
103 * in a reasonable time.
843267b1
BJ
104 */
105/*VARARGS1*/
106uprintf(fmt, x1)
b725a0ca 107 char *fmt;
843267b1 108 unsigned x1;
96d38f03 109{
71e86b6c 110 register struct tty *tp = u.u_procp->p_session->s_ttyp;
96d38f03 111
71e86b6c 112 if (tp != NULL && tp->t_session == u.u_procp->p_session)
ca9b16e5 113 prf(fmt, &x1, TOTTY, tp);
34ef3482
RC
114}
115
bd10af3f
MK
116/*
117 * tprintf prints on the specified terminal (console if none)
118 * and logs the message. It is designed for error messages from
6f71a9f6
MK
119 * single-open devices, and may be called from interrupt level
120 * (does not sleep).
bd10af3f 121 */
34ef3482 122/*VARARGS2*/
71e86b6c
MT
123tprintf(vp, fmt, x1)
124 register caddr_t vp;
34ef3482
RC
125 char *fmt;
126 unsigned x1;
127{
6f71a9f6 128 int flags = TOTTY | TOLOG;
34ef3482 129
71e86b6c 130#ifdef notyet
6f71a9f6 131 logpri(LOG_INFO);
71e86b6c
MT
132
133 if (vp == NULL ||
134 VOP_IOCTL(vp, TIOCCHECKOUTQ, &val, FWRITE, NOCRED) != 0 ||
135 val == 0)
6f71a9f6 136 flags = TOLOG;
71e86b6c 137 prf(fmt, &x1, flags, vp);
6f71a9f6 138 logwakeup();
71e86b6c
MT
139#else
140 printf("tprintf called\n");
141#endif
34ef3482
RC
142}
143
144/*
145 * Log writes to the log buffer,
8d907ccf 146 * and guarantees not to sleep (so can be called by interrupt routines).
bd10af3f 147 * If there is no process reading the log yet, it writes to the console also.
34ef3482
RC
148 */
149/*VARARGS2*/
150log(level, fmt, x1)
151 char *fmt;
152 unsigned x1;
153{
154 register s = splhigh();
bd10af3f 155 extern int log_open;
34ef3482 156
6f71a9f6 157 logpri(level);
71e86b6c 158 prf(fmt, &x1, TOLOG, (caddr_t)0);
34ef3482 159 splx(s);
bd10af3f 160 if (!log_open)
71e86b6c 161 prf(fmt, &x1, TOCONS, (caddr_t)0);
34ef3482 162 logwakeup();
96d38f03
BJ
163}
164
6f71a9f6
MK
165logpri(level)
166 int level;
167{
168
169 putchar('<', TOLOG, (struct tty *)0);
8011f5df 170 printn((u_long)level, 10, TOLOG, (struct tty *)0);
6f71a9f6
MK
171 putchar('>', TOLOG, (struct tty *)0);
172}
173
c55a3dd0
MK
174/*VARARGS1*/
175addlog(fmt, x1)
176 char *fmt;
177 unsigned x1;
178{
179 register s = splhigh();
180
71e86b6c 181 prf(fmt, &x1, TOLOG, (caddr_t)0);
c55a3dd0
MK
182 splx(s);
183 if (!log_open)
71e86b6c 184 prf(fmt, &x1, TOCONS, (caddr_t)0);
c55a3dd0
MK
185 logwakeup();
186}
187
71e86b6c 188prf(fmt, adx, flags, where)
b725a0ca
BJ
189 register char *fmt;
190 register u_int *adx;
71e86b6c 191 caddr_t where;
8cbb423c 192{
d5726689 193 register int b, c, i;
8cbb423c 194 char *s;
3c79e4ff 195 int any;
8cbb423c 196
8cbb423c 197loop:
843267b1 198 while ((c = *fmt++) != '%') {
34ef3482 199 if (c == '\0')
8cbb423c 200 return;
71e86b6c 201 putchar(c, flags, where);
8cbb423c 202 }
843267b1 203again:
8cbb423c 204 c = *fmt++;
fb1db32c 205 /* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */
843267b1
BJ
206 switch (c) {
207
208 case 'l':
209 goto again;
210 case 'x': case 'X':
211 b = 16;
212 goto number;
213 case 'd': case 'D':
fb1db32c
MK
214 b = -10;
215 goto number;
216 case 'u':
843267b1
BJ
217 b = 10;
218 goto number;
219 case 'o': case 'O':
220 b = 8;
221number:
71e86b6c 222 printn((u_long)*adx, b, flags, where);
843267b1
BJ
223 break;
224 case 'c':
d5726689 225 b = *adx;
c55a3dd0 226#if BYTE_ORDER == LITTLE_ENDIAN
d5726689
BJ
227 for (i = 24; i >= 0; i -= 8)
228 if (c = (b >> i) & 0x7f)
71e86b6c 229 putchar(c, flags, where);
fb1db32c 230#endif
c55a3dd0 231#if BYTE_ORDER == BIG_ENDIAN
fb1db32c 232 if (c = (b & 0x7f))
71e86b6c 233 putchar(c, flags, where);
fb1db32c 234#endif
843267b1 235 break;
3c79e4ff
BJ
236 case 'b':
237 b = *adx++;
238 s = (char *)*adx;
71e86b6c 239 printn((u_long)b, *s++, flags, where);
3c79e4ff
BJ
240 any = 0;
241 if (b) {
3c79e4ff
BJ
242 while (i = *s++) {
243 if (b & (1 << (i-1))) {
71e86b6c 244 putchar(any ? ',' : '<', flags, where);
3c79e4ff
BJ
245 any = 1;
246 for (; (c = *s) > 32; s++)
71e86b6c 247 putchar(c, flags, where);
3c79e4ff
BJ
248 } else
249 for (; *s > 32; s++)
250 ;
251 }
1ce587f2 252 if (any)
71e86b6c 253 putchar('>', flags, where);
3c79e4ff
BJ
254 }
255 break;
256
843267b1 257 case 's':
8cbb423c 258 s = (char *)*adx;
96d38f03 259 while (c = *s++)
71e86b6c 260 putchar(c, flags, where);
843267b1 261 break;
2bb8d359 262
c55a3dd0
MK
263 case 'r':
264 s = (char *)*adx++;
71e86b6c 265 prf(s, (u_int *)*adx, flags, where);
c55a3dd0
MK
266 break;
267
2bb8d359 268 case '%':
71e86b6c 269 putchar('%', flags, where);
2bb8d359 270 break;
8cbb423c
BJ
271 }
272 adx++;
273 goto loop;
274}
275
b725a0ca
BJ
276/*
277 * Printn prints a number n in base b.
278 * We don't use recursion to avoid deep kernel stacks.
279 */
71e86b6c 280printn(n, b, flags, where)
a0eab615 281 u_long n;
71e86b6c 282 caddr_t where;
8cbb423c 283{
d5726689 284 char prbuf[11];
843267b1 285 register char *cp;
8cbb423c 286
fb1db32c
MK
287 if (b == -10) {
288 if ((int)n < 0) {
71e86b6c 289 putchar('-', flags, where);
fb1db32c
MK
290 n = (unsigned)(-(int)n);
291 }
292 b = -b;
8cbb423c 293 }
d5726689 294 cp = prbuf;
843267b1
BJ
295 do {
296 *cp++ = "0123456789abcdef"[n%b];
297 n /= b;
298 } while (n);
299 do
71e86b6c 300 putchar(*--cp, flags, where);
d5726689 301 while (cp > prbuf);
8cbb423c
BJ
302}
303
304/*
0dc06be8 305 * Panic is called on unresolvable fatal errors.
b725a0ca
BJ
306 * It prints "panic: mesg", and then reboots.
307 * If we are called twice, then we avoid trying to
308 * sync the disks as this often leads to recursive panics.
8cbb423c
BJ
309 */
310panic(s)
b725a0ca 311 char *s;
8cbb423c 312{
295184b1 313 int bootopt = RB_AUTOBOOT | RB_DUMP;
843267b1 314
68503f9a
BJ
315 if (panicstr)
316 bootopt |= RB_NOSYNC;
cddce008 317 else {
961945a8 318 panicstr = s;
961945a8 319 }
a9c526c1 320 printf("panic: %s\n", s);
f7f8b75f 321#ifdef KADB
3eb8e016 322 if (boothowto & RB_KDB) {
e018935f 323 int x = splnet(); /* below kdb pri */
3eb8e016
MK
324
325 setsoftkdb();
e018935f 326 splx(x);
3eb8e016
MK
327 }
328#endif
295184b1 329 boot(bootopt);
8cbb423c
BJ
330}
331
fdd11a14
BJ
332/*
333 * Warn that a system table is full.
334 */
335tablefull(tab)
336 char *tab;
337{
338
283ffc90 339 log(LOG_ERR, "%s: table is full\n", tab);
fdd11a14
BJ
340}
341
96d38f03 342/*
843267b1 343 * Print a character on console or users terminal.
96d38f03
BJ
344 * If destination is console then the last MSGBUFS characters
345 * are saved in msgbuf for inspection later.
346 */
49c84d3f 347/*ARGSUSED*/
71e86b6c 348putchar(c, flags, where)
843267b1 349 register int c;
71e86b6c 350 caddr_t where;
96d38f03 351{
c55a3dd0 352 extern int msgbufmapped;
96d38f03 353
ed2d0915
MK
354 if (panicstr)
355 constty = 0;
71e86b6c
MT
356 if ((flags & TOCONS) && where == 0 && constty) {
357 where = (caddr_t)constty;
ed2d0915
MK
358 flags |= TOTTY;
359 }
1d4b2ce4
MK
360 if ((flags & TOCONS) && panicstr == 0 && tp == 0 && constty) {
361 tp = constty;
362 flags |= TOTTY;
363 }
71e86b6c
MT
364 if ((flags & TOTTY) && where && tputchar(c, (struct tty *)where) < 0 &&
365 (flags & TOCONS) && (struct tty *)where == constty)
366 constty = 0;
c55a3dd0
MK
367 if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 &&
368 msgbufmapped) {
90f8d91f 369 if (msgbuf.msg_magic != MSG_MAGIC) {
76db4195
SL
370 register int i;
371
90f8d91f 372 msgbuf.msg_magic = MSG_MAGIC;
34ef3482 373 msgbuf.msg_bufx = msgbuf.msg_bufr = 0;
76db4195
SL
374 for (i=0; i < MSG_BSIZE; i++)
375 msgbuf.msg_bufc[i] = 0;
90f8d91f 376 }
7e401e0e 377 msgbuf.msg_bufc[msgbuf.msg_bufx++] = c;
90f8d91f
BJ
378 if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE)
379 msgbuf.msg_bufx = 0;
96d38f03 380 }
1d4b2ce4 381 (*v_console)(c);
96d38f03 382}