#include "../h/local.h"
#ifdef SCCS_ID
static char SCCS_ID [] = "@(#)prf.c 3.2 01:50:16 - 81/12/10 ";
#endif SCCS_ID
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/seg.h"
#include "../h/buf.h"
#include "../h/conf.h"
#ifdef UCB_FSNAM
#include "../h/mount.h"
#include "../h/filsys.h"
#endif UCB_FSNAM
/*
* In case console is off,
* panicstr contains argument to last
* call to panic.
*/
char *panicstr;
/*
* Scaled down version of C Library printf.
* Only %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 pretty much
* suspended.
* Printf should not be used for chit-chat.
*/
/* VARARGS 1 */
printf(fmt, x1)
register char *fmt;
unsigned x1;
{
register c;
register unsigned int *adx;
char *s;
adx = &x1;
loop:
while((c = *fmt++) != '%') {
if(c == '\0')
return;
putchar(c);
}
c = *fmt++;
if(c == 'd' || c == 'u' || c == 'o' || c == 'x')
printn((long)*adx, c=='o'? 8: (c=='x'? 16:10));
else if(c == 's') {
s = (char *)*adx;
while(c = *s++)
putchar(c);
#ifdef UCB_DEVERR
} else if (c == 'D' || c == 'O') {
printn(*(long *)adx, c=='D'?10:8);
#else UCB_DEVERR
} else if (c == 'D') {
printn(*(long *)adx, 10);
#endif UCB_DEVERR
adx += (sizeof(long) / sizeof(int)) - 1;
}
#ifdef UCB_DEVERR
/*
* Additional format: %b for decoding error registers.
* Usage is:
* printf("reg=%b\n", regval, "*");
* Where 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 <=16), give the name of the register. Thus
* printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE");
* would produce output:
* reg=3
*/
else if (c == 'b') {
unsigned b;
int i, any;
b = *adx++;
s = (char *)*adx;
printn((long)b, *s++);
any = 0;
if (b) {
putchar('<');
while (i = *s++) {
if (b & (1 << (i-1))) {
if (any)
putchar(',');
any = 1;
for (; (c = *s) > 16; s++)
putchar(c);
} else
for (; *s > 16; s++)
;
}
putchar('>');
}
}
#endif UCB_DEVERR
adx++;
goto loop;
}
/*
* Print an unsigned integer in base b.
*/
printn(n, b)
long n;
{
register long a;
if (n<0) { /* shouldn't happen */
putchar('-');
n = -n;
}
if(a = n/b)
printn(a, b);
putchar("0123456789ABCDEF"[(int)(n%b)]);
}
/*
* Panic is called on unresolvable
* fatal errors.
* It syncs, prints "panic: mesg" and
* then loops.
*/
panic(s)
char *s;
{
#ifdef CGL_AUTOB
int i, j;
#endif CGL_AUTOB
panicstr = s;
#ifdef CGL_AUTOB
printf("\007\007\007\007\n\nSYSTEM FAULT\n\n");
printf("panic: %s\n", s);
spl0();
printf("syncing disks...");
for (i=j=0; i<15; i++)
while(--j); /* wait for sync to finish */
printf("done\n");
autoboot(1);
#else UCB_AUTOB
update();
printf("panic: %s\n", s);
for(;;)
idle();
#endif UCB_AUTOB
}
#ifdef CGL_AUTOB
#define HPCS1 ((physadr)0176700) /* csr of boot disk */
#define LOC2 ((physadr)02)
#define JMPI 0137 /* jmp (pc)+ */
autoboot(flag)
{
int reboot(), reboot1();
if (CSW->r[0] == SNGLU) /* magic csr setting for manual intervention */
for(;;)
idle();
spl7();
while ((HPCS1->r[0] & 0200) == 0); /* wait for xfer to finish */
LOC2->r[0] = JMPI;
if (flag)
LOC2->r[1] = (int)reboot; /* dump memory first */
else
LOC2->r[1] = (int)reboot1; /* no memory dump */
reset(); /* (in l.s) */
/* NOTREACHED */
}
#endif UCB_AUTOB
/*
* prdev prints a warning message of the
* form "mesg on dev x/y".
* x and y are the major and minor parts of
* the device argument.
*/
prdev(str, dev)
char *str;
dev_t dev;
{
#ifdef UCB_FSNAM
register struct mount *mp;
register struct filsys *fp;
for (mp = &mount[0]; mp < mountNMOUNT; mp++)
if (mp->m_bufp!=NULL && mp->m_dev==dev) {
#ifdef UCB_MOUNT
fp = mp->m_caddr;
#else UCB_MOUNT
fp = mp->m_bufp->b_un.b_filsys;
#endif UCB_MOUNT
printf("%s on %s (%u/%u)\n", str, fp->s_fsmnt,
major(dev), minor(dev));
return;
}
#endif UCB_FSNAM
printf("%s on dev %u/%u\n", str, major(dev), minor(dev));
}
/*
* deverr prints a diagnostic from
* a device driver.
* It prints the device, block number,
* and an octal word (usually some error
* status register) passed as argument.
*/
deverror(bp, o1, o2)
register struct buf *bp;
{
prdev("err", bp->b_dev);
#ifdef DEC
printf("bn=%D er=%o,%o\n", bp->b_blkno, o1, o2);
#else
printf("bn=%D er=%x ad=%x\n", bp->b_blkno, o1, o2);
#endif
}