2.9BSD/usr/net/sys/sys/prf.c
/*
* SCCS id @(#)prf.c 2.1 (Berkeley) 8/5/83
*/
#include "param.h"
#include <sys/systm.h>
#include <sys/filsys.h>
#include <sys/mount.h>
#include <sys/seg.h>
#include <sys/buf.h>
#include <sys/conf.h>
#include <sys/inline.h>
#ifdef UCB_AUTOBOOT
#include <sys/reboot.h>
#endif
/*
* In case console is off,
* panicstr contains argument to last
* call to panic.
*/
char *panicstr;
/*
* Scaled down version of C Library printf.
* Only %c %s %u %d (==%u) %o %x %D %O are recognized.
* Used to print diagnostic information directly on console tty.
* Since it is not interrupt driven, all system activities are
* suspended. Printf should not be used for chit-chat.
*
*/
#ifdef UCB_DEVERR
/*
* One additional format: %b is supported to decode error registers.
* Usage is:
* printf("reg=%b\n", regval, "<base><arg>*");
* Where <base> is the output base expressed as a control character,
* e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of
* characters, the first of which gives the bit number to be inspected
* (origin 1), and the next characters (up to a control character, i.e.
* a character <= 32), give the name of the register. Thus
* printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
* would produce output:
* reg=3<BITTWO,BITONE>
*/
#endif UCB_DEVERR
/*VARARGS1*/
printf(fmt, x1)
register char *fmt;
unsigned x1;
{
prf(fmt, &x1, 0);
}
#ifdef UCB_UPRINTF
/*
* Uprintf prints to the current user's terminal,
* guarantees not to sleep (so could be called by interrupt routines;
* but prints on the tty of the current process)
* and does no watermark checking - (so no verbose messages).
* NOTE: with current kernel mapping scheme, the user structure is
* not guaranteed to be accessible at interrupt level (see seg.h);
* a savemap/restormap would be needed here or in putchar if uprintf
* was to be used at interrupt time.
*/
/*VARARGS1*/
uprintf(fmt, x1)
char *fmt;
unsigned x1;
{
prf(fmt, &x1, 2);
}
#else
/*VARARGS1*/
uprintf(fmt, x1)
char *fmt;
unsigned x1;
{
prf(fmt, &x1, 0);
}
#endif UCB_PRINTF
prf(fmt, adx, touser)
register char *fmt;
register unsigned int *adx;
{
register c;
char *s;
#ifdef UCB_DEVERR
int i, any;
unsigned b;
#endif
loop:
while((c = *fmt++) != '%') {
if(c == '\0')
return;
putchar(c, touser);
}
c = *fmt++;
if(c == 'd' || c == 'u' || c == 'o' || c == 'x')
printn((long)*adx, c=='o'? 8: (c=='x'? 16:10), touser);
else if(c == 'c')
putchar(*adx, touser);
else if(c == 's') {
s = (char *)*adx;
while(c = *s++)
putchar(c, touser);
} else if (c == 'D' || c == 'O' || c == 'X') {
printn(*(long *)adx, c=='D'?10:c=='O'?8:16, touser);
adx += (sizeof(long) / sizeof(int)) - 1;
}
#ifdef UCB_DEVERR
else if (c == 'b') {
b = *adx++;
s = (char *) *adx;
printn((long) b, *s++, touser);
any = 0;
if (b) {
putchar('<', touser);
while (i = *s++) {
if (b & (1 << (i - 1))) {
if (any)
putchar(',', touser);
any = 1;
for (; (c = *s) > 32; s++)
putchar(c, touser);
} else
for (; *s > 32; s++)
;
}
putchar('>', touser);
}
}
#endif
adx++;
goto loop;
}
/*
* Print an unsigned integer in base b, avoiding recursion.
*/
printn(n, b, touser)
long n;
{
long a;
char prbuf[12];
register char *cp;
if (b == 10 && n < 0) {
putchar('-', touser);
n = -n;
}
cp = prbuf;
do {
*cp++ = "0123456789ABCDEF"[(int)(n%b)];
} while (n = n/b); /* Avoid n /= b, since that requires alrem */
do
putchar(*--cp, touser);
while (cp > prbuf);
}
/*
* Panic is called on fatal errors.
* It prints "panic: mesg", syncs, and then reboots if possible.
* If we are called twice, then we avoid trying to
* sync the disks as this often leads to recursive panics.
*/
panic(s)
register char *s;
{
#ifdef UCB_AUTOBOOT
int bootopt = (panicstr == NULL) ? RB_DUMP : (RB_DUMP | RB_NOSYNC);
if (panicstr == NULL)
panicstr = s;
printf("panic: %s\n", s);
(void) _spl0();
boot(rootdev,bootopt);
/*NOTREACHED*/
#else
printf("panic: %s\n", s);
if (panicstr == NULL) {
panicstr = s;
if (bfreelist.b_forw)
update();
}
for(;;)
idle();
#endif
}
/*
* Warn that a system table is full.
*/
tablefull(tab)
char *tab;
{
printf("%s: table is full\n", tab);
}
/*
* Hard error is the preface to plaintive error messages
* about failing disk tranfers.
*/
harderr(bp, cp)
struct buf *bp;
char *cp;
{
printf("%s%d%c: hard error bn %D ", cp,
dkunit(bp), 'a' + (minor(bp->b_dev) & 07), bp->b_blkno);
}
/*
* Fserr prints the name of a file system
* with an error diagnostic, in the form
* filsys: error message
*/
fserr(fp, cp)
struct filsys *fp;
char *cp;
{
printf("%s: %s\n", fp->s_fsmnt, cp);
}
#ifndef UCB_DEVERR
/*
* deverr prints a diagnostic from
* a device driver.
* It prints the device, block number,
* and 2 octal words (usually some error
* status registers) passed as argument.
*/
deverror(bp, o1, o2)
register struct buf *bp;
{
register struct mount *mp;
register struct filsys *fp;
for(mp = mount; mp < mountNMOUNT; mp++)
if(mp->m_inodp != NULL)
if(bp->b_dev == mp->m_dev) {
fp = &mp->m_filsys;
fserr(fp, "err");
}
printf("err on dev %u/%u\n", major(bp->b_dev), minor(bp->b_dev));
printf("bn=%D er=%o,%o\n", bp->b_blkno, o1, o2);
}
#endif UCB_DEVERR