1 /* subr_prf.c 6.5 84/12/27 */ 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=3<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 * and does no watermark checking - (so no verbose messages). 63 */ 64 /*VARARGS1*/ 65 uprintf(fmt, x1) 66 char *fmt; 67 unsigned x1; 68 { 69 70 prf(fmt, &x1, TOTTY, u.u_ttyp); 71 } 72 73 /*VARARGS2*/ 74 tprintf(ttyp, fmt, x1) 75 struct tty *ttyp; 76 char *fmt; 77 unsigned x1; 78 { 79 80 prf(fmt, &x1, TOTTY, ttyp); 81 } 82 83 /* 84 * Log writes to the log buffer, 85 * and guarantees not to sleep (so can be called by interrupt routines). 86 */ 87 /*VARARGS2*/ 88 log(level, fmt, x1) 89 char *fmt; 90 unsigned x1; 91 { 92 register s = splhigh(); 93 94 putchar('<', TOLOG, (struct tty *)0); 95 printn(level, 10, TOLOG, (struct tty *)0); 96 putchar('>', TOLOG, (struct tty *)0); 97 prf(fmt, &x1, TOLOG, (struct tty *)0); 98 splx(s); 99 logwakeup(); 100 } 101 102 prf(fmt, adx, flags, ttyp) 103 register char *fmt; 104 register u_int *adx; 105 struct tty *ttyp; 106 { 107 register int b, c, i; 108 char *s; 109 int any; 110 111 loop: 112 while ((c = *fmt++) != '%') { 113 if (c == '\0') 114 return; 115 putchar(c, flags, ttyp); 116 } 117 again: 118 c = *fmt++; 119 /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */ 120 switch (c) { 121 122 case 'l': 123 goto again; 124 case 'x': case 'X': 125 b = 16; 126 goto number; 127 case 'd': case 'D': 128 case 'u': /* what a joke */ 129 b = 10; 130 goto number; 131 case 'o': case 'O': 132 b = 8; 133 number: 134 printn((u_long)*adx, b, flags, ttyp); 135 break; 136 case 'c': 137 b = *adx; 138 for (i = 24; i >= 0; i -= 8) 139 if (c = (b >> i) & 0x7f) 140 putchar(c, flags, ttyp); 141 break; 142 case 'b': 143 b = *adx++; 144 s = (char *)*adx; 145 printn((u_long)b, *s++, flags, ttyp); 146 any = 0; 147 if (b) { 148 while (i = *s++) { 149 if (b & (1 << (i-1))) { 150 putchar(any? ',' : '<', flags, ttyp); 151 any = 1; 152 for (; (c = *s) > 32; s++) 153 putchar(c, flags, ttyp); 154 } else 155 for (; *s > 32; s++) 156 ; 157 } 158 if (any) 159 putchar('>', flags, ttyp); 160 } 161 break; 162 163 case 's': 164 s = (char *)*adx; 165 while (c = *s++) 166 putchar(c, flags, ttyp); 167 break; 168 169 case '%': 170 putchar('%', flags, ttyp); 171 break; 172 } 173 adx++; 174 goto loop; 175 } 176 177 /* 178 * Printn prints a number n in base b. 179 * We don't use recursion to avoid deep kernel stacks. 180 */ 181 printn(n, b, flags, ttyp) 182 u_long n; 183 struct tty *ttyp; 184 { 185 char prbuf[11]; 186 register char *cp; 187 188 if (b == 10 && (int)n < 0) { 189 putchar('-', flags, ttyp); 190 n = (unsigned)(-(int)n); 191 } 192 cp = prbuf; 193 do { 194 *cp++ = "0123456789abcdef"[n%b]; 195 n /= b; 196 } while (n); 197 do 198 putchar(*--cp, flags, ttyp); 199 while (cp > prbuf); 200 } 201 202 /* 203 * Panic is called on unresolvable fatal errors. 204 * It prints "panic: mesg", and then reboots. 205 * If we are called twice, then we avoid trying to 206 * sync the disks as this often leads to recursive panics. 207 */ 208 panic(s) 209 char *s; 210 { 211 int bootopt = RB_AUTOBOOT; 212 213 if (panicstr) 214 bootopt |= RB_NOSYNC; 215 else { 216 panicstr = s; 217 } 218 printf("panic: %s\n", s); 219 boot(RB_PANIC, bootopt); 220 } 221 222 /* 223 * Warn that a system table is full. 224 */ 225 tablefull(tab) 226 char *tab; 227 { 228 229 printf("%s: table is full\n", tab); 230 } 231 232 /* 233 * Hard error is the preface to plaintive error messages 234 * about failing disk transfers. 235 */ 236 harderr(bp, cp) 237 struct buf *bp; 238 char *cp; 239 { 240 241 printf("%s%d%c: hard error sn%d ", cp, 242 dkunit(bp), 'a'+(minor(bp->b_dev)&07), bp->b_blkno); 243 } 244 245 /* 246 * Print a character on console or users terminal. 247 * If destination is console then the last MSGBUFS characters 248 * are saved in msgbuf for inspection later. 249 */ 250 /*ARGSUSED*/ 251 putchar(c, flags, tp) 252 register int c; 253 struct tty *tp; 254 { 255 extern struct tty cons; 256 257 if (flags & TOTTY) { 258 if (tp == (struct tty *)NULL && (flags & TOCONS) == 0) 259 tp = &cons; 260 if (tp && (tp->t_state & TS_CARR_ON)) { 261 register s = spl6(); 262 if (c == '\n') 263 (void) ttyoutput('\r', tp); 264 (void) ttyoutput(c, tp); 265 ttstart(tp); 266 splx(s); 267 } 268 } 269 if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 270 #ifdef vax 271 && mfpr(MAPEN) 272 #endif 273 ) { 274 if (msgbuf.msg_magic != MSG_MAGIC) { 275 register int i; 276 277 msgbuf.msg_magic = MSG_MAGIC; 278 msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 279 for (i=0; i < MSG_BSIZE; i++) 280 msgbuf.msg_bufc[i] = 0; 281 } 282 if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 283 msgbuf.msg_bufx = 0; 284 msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 285 } 286 if ((flags & TOCONS) && c != '\0') 287 cnputc(c); 288 } 289