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