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