1 /* subr_prf.c 6.4 84/12/21 */ 2 3 #include "param.h" 4 #include "systm.h" 5 #include "seg.h" 6 #include "buf.h" 7 #include "conf.h" 8 #include "reboot.h" 9 #include "vm.h" 10 #include "msgbuf.h" 11 #include "dir.h" 12 #include "user.h" 13 #include "proc.h" 14 #include "ioctl.h" 15 #include "tty.h" 16 17 #ifdef vax 18 #include "../vax/mtpr.h" 19 #endif 20 21 #define TOCONS 0x1 22 #define TOTTY 0x2 23 #define TOLOG 0x4 24 25 /* 26 * In case console is off, 27 * panicstr contains argument to last 28 * call to panic. 29 */ 30 char *panicstr; 31 32 /* 33 * Scaled down version of C Library printf. 34 * Used to print diagnostic information directly on console tty. 35 * Since it is not interrupt driven, all system activities are 36 * suspended. Printf should not be used for chit-chat. 37 * 38 * One additional format: %b is supported to decode error registers. 39 * Usage is: 40 * printf("reg=%b\n", regval, "<base><arg>*"); 41 * Where <base> is the output base expressed as a control character, 42 * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 43 * characters, the first of which gives the bit number to be inspected 44 * (origin 1), and the next characters (up to a control character, i.e. 45 * a character <= 32), give the name of the register. Thus 46 * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 47 * would produce output: 48 * reg=2<BITTWO,BITONE> 49 */ 50 /*VARARGS1*/ 51 printf(fmt, x1) 52 char *fmt; 53 unsigned x1; 54 { 55 56 prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0); 57 logwakeup(); 58 } 59 60 /* 61 * Uprintf prints to the current user's terminal, 62 * guarantees not to sleep (so can be called by interrupt routines) 63 * and does no watermark checking - (so no verbose messages). 64 */ 65 /*VARARGS1*/ 66 uprintf(fmt, x1) 67 char *fmt; 68 unsigned x1; 69 { 70 71 prf(fmt, &x1, TOTTY, u.u_ttyp); 72 } 73 74 /*VARARGS2*/ 75 tprintf(ttyp, fmt, x1) 76 struct tty *ttyp; 77 char *fmt; 78 unsigned x1; 79 { 80 81 prf(fmt, &x1, TOTTY, ttyp); 82 } 83 84 /* 85 * Log writes to the log buffer, 86 * guarantees not to sleep (so can be called by interrupt routines) 87 * and does no watermark checking - (so no verbose messages). 88 */ 89 /*VARARGS2*/ 90 log(level, fmt, x1) 91 char *fmt; 92 unsigned x1; 93 { 94 register s = splhigh(); 95 96 putchar('<', TOLOG, (struct tty *)0); 97 printn(level, 10, TOLOG, (struct tty *)0); 98 putchar('>', TOLOG, (struct tty *)0); 99 prf(fmt, &x1, TOLOG, (struct tty *)0); 100 splx(s); 101 logwakeup(); 102 } 103 104 prf(fmt, adx, flags, ttyp) 105 register char *fmt; 106 register u_int *adx; 107 struct tty *ttyp; 108 { 109 register int b, c, i; 110 char *s; 111 int any; 112 113 loop: 114 while ((c = *fmt++) != '%') { 115 if (c == '\0') 116 return; 117 putchar(c, flags, ttyp); 118 } 119 again: 120 c = *fmt++; 121 /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */ 122 switch (c) { 123 124 case 'l': 125 goto again; 126 case 'x': case 'X': 127 b = 16; 128 goto number; 129 case 'd': case 'D': 130 case 'u': /* what a joke */ 131 b = 10; 132 goto number; 133 case 'o': case 'O': 134 b = 8; 135 number: 136 printn((u_long)*adx, b, flags, ttyp); 137 break; 138 case 'c': 139 b = *adx; 140 for (i = 24; i >= 0; i -= 8) 141 if (c = (b >> i) & 0x7f) 142 putchar(c, flags, ttyp); 143 break; 144 case 'b': 145 b = *adx++; 146 s = (char *)*adx; 147 printn((u_long)b, *s++, flags, ttyp); 148 any = 0; 149 if (b) { 150 putchar('<', flags, ttyp); 151 while (i = *s++) { 152 if (b & (1 << (i-1))) { 153 if (any) 154 putchar(',', flags, ttyp); 155 any = 1; 156 for (; (c = *s) > 32; s++) 157 putchar(c, flags, ttyp); 158 } else 159 for (; *s > 32; s++) 160 ; 161 } 162 if (any) 163 putchar('>', flags, ttyp); 164 } 165 break; 166 167 case 's': 168 s = (char *)*adx; 169 while (c = *s++) 170 putchar(c, flags, ttyp); 171 break; 172 173 case '%': 174 putchar('%', flags, ttyp); 175 break; 176 } 177 adx++; 178 goto loop; 179 } 180 181 /* 182 * Printn prints a number n in base b. 183 * We don't use recursion to avoid deep kernel stacks. 184 */ 185 printn(n, b, flags, ttyp) 186 u_long n; 187 struct tty *ttyp; 188 { 189 char prbuf[11]; 190 register char *cp; 191 192 if (b == 10 && (int)n < 0) { 193 putchar('-', flags, ttyp); 194 n = (unsigned)(-(int)n); 195 } 196 cp = prbuf; 197 do { 198 *cp++ = "0123456789abcdef"[n%b]; 199 n /= b; 200 } while (n); 201 do 202 putchar(*--cp, flags, ttyp); 203 while (cp > prbuf); 204 } 205 206 /* 207 * Panic is called on unresolvable fatal errors. 208 * It prints "panic: mesg", and then reboots. 209 * If we are called twice, then we avoid trying to 210 * sync the disks as this often leads to recursive panics. 211 */ 212 panic(s) 213 char *s; 214 { 215 int bootopt = RB_AUTOBOOT; 216 217 if (panicstr) 218 bootopt |= RB_NOSYNC; 219 else { 220 panicstr = s; 221 } 222 printf("panic: %s\n", s); 223 boot(RB_PANIC, bootopt); 224 } 225 226 /* 227 * Warn that a system table is full. 228 */ 229 tablefull(tab) 230 char *tab; 231 { 232 233 printf("%s: table is full\n", tab); 234 } 235 236 /* 237 * Hard error is the preface to plaintive error messages 238 * about failing disk transfers. 239 */ 240 harderr(bp, cp) 241 struct buf *bp; 242 char *cp; 243 { 244 245 printf("%s%d%c: hard error sn%d ", cp, 246 dkunit(bp), 'a'+(minor(bp->b_dev)&07), bp->b_blkno); 247 } 248 249 /* 250 * Print a character on console or users terminal. 251 * If destination is console then the last MSGBUFS characters 252 * are saved in msgbuf for inspection later. 253 */ 254 /*ARGSUSED*/ 255 putchar(c, flags, ttyp) 256 register int c; 257 struct tty *ttyp; 258 { 259 260 if (flags & TOTTY) { 261 register struct tty *tp = ttyp; 262 263 if (tp && (tp->t_state & TS_CARR_ON)) { 264 register s = spl6(); 265 if (c == '\n') 266 (void) ttyoutput('\r', tp); 267 (void) ttyoutput(c, tp); 268 ttstart(tp); 269 splx(s); 270 } 271 } 272 if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 273 #ifdef vax 274 && mfpr(MAPEN) 275 #endif 276 ) { 277 if (msgbuf.msg_magic != MSG_MAGIC) { 278 register int i; 279 280 msgbuf.msg_magic = MSG_MAGIC; 281 msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 282 for (i=0; i < MSG_BSIZE; i++) 283 msgbuf.msg_bufc[i] = 0; 284 } 285 if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 286 msgbuf.msg_bufx = 0; 287 msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 288 } 289 if ((flags & TOCONS) && c != '\0') 290 cnputc(c); 291 } 292