1 /* 2 * Copyright (c) 1992 OMRON Corporation. 3 * Copyright (c) 1992, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * OMRON Corporation. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)subr_prf.c 8.1 (Berkeley) 06/10/93 12 */ 13 14 #include <sys/param.h> 15 #include <luna68k/stand/romvec.h> 16 17 #define TOCONS 0x1 18 #define TOTTY 0x2 19 #define TOLOG 0x4 20 21 /* 22 * In case console is off, 23 * panicstr contains argument to last 24 * call to panic. 25 */ 26 char *panicstr; 27 28 extern cnputc(); /* standard console putc */ 29 int (*v_putc)() = cnputc; /* routine to putc on virtual console */ 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=3<BITTWO,BITONE> 48 * 49 * Another additional format: %r is used to pass an additional format string 50 * and argument list recursively. Usage is typically: 51 * 52 * fn(otherstuff, fmt [, arg1, ... ] ) 53 * char *fmt; 54 * u_int arg1, ...; 55 * 56 * printf("prefix: %r, other stuff\n", fmt, &arg1); 57 */ 58 #if defined(tahoe) 59 int consintr; 60 #endif 61 62 /*VARARGS1*/ 63 printf(fmt, x1) 64 char *fmt; 65 unsigned x1; 66 { 67 #if defined(tahoe) 68 register int savintr; 69 70 savintr = consintr, consintr = 0; /* disable interrupts */ 71 #endif 72 prf(fmt, &x1, TOCONS , (struct tty *)NULL); 73 74 75 #if defined(tahoe) 76 consintr = savintr; /* reenable interrupts */ 77 #endif 78 } 79 80 prf(fmt, adx, flags, ttyp) 81 register char *fmt; 82 register u_int *adx; 83 struct tty *ttyp; 84 { 85 register int b, c, i; 86 char *s; 87 int any; 88 89 loop: 90 while ((c = *fmt++) != '%') { 91 if (c == '\0') 92 return; 93 putchar(c, flags, ttyp); 94 } 95 again: 96 c = *fmt++; 97 /* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */ 98 switch (c) { 99 100 case 'l': 101 goto again; 102 case 'x': case 'X': 103 b = 16; 104 goto number; 105 case 'd': case 'D': 106 b = -10; 107 goto number; 108 case 'u': 109 b = 10; 110 goto number; 111 case 'o': case 'O': 112 b = 8; 113 number: 114 printn((u_long)*adx, b, flags, ttyp); 115 break; 116 case 'c': 117 b = *adx; 118 #if BYTE_ORDER == LITTLE_ENDIAN 119 for (i = 24; i >= 0; i -= 8) 120 if (c = (b >> i) & 0x7f) 121 putchar(c, flags, ttyp); 122 #endif 123 #if BYTE_ORDER == BIG_ENDIAN 124 if (c = (b & 0x7f)) 125 putchar(c, flags, ttyp); 126 #endif 127 break; 128 case 'b': 129 b = *adx++; 130 s = (char *)*adx; 131 printn((u_long)b, *s++, flags, ttyp); 132 any = 0; 133 if (b) { 134 while (i = *s++) { 135 if (b & (1 << (i-1))) { 136 putchar(any ? ',' : '<', flags, ttyp); 137 any = 1; 138 for (; (c = *s) > 32; s++) 139 putchar(c, flags, ttyp); 140 } else 141 for (; *s > 32; s++) 142 ; 143 } 144 if (any) 145 putchar('>', flags, ttyp); 146 } 147 break; 148 149 case 's': 150 s = (char *)*adx; 151 while (c = *s++) 152 putchar(c, flags, ttyp); 153 break; 154 155 case 'r': 156 s = (char *)*adx++; 157 prf(s, (u_int *)*adx, flags, ttyp); 158 break; 159 160 case '%': 161 putchar('%', flags, ttyp); 162 break; 163 164 default: 165 break; 166 } 167 adx++; 168 goto loop; 169 } 170 171 /* 172 * Printn prints a number n in base b. 173 * We don't use recursion to avoid deep kernel stacks. 174 */ 175 printn(n, b, flags, ttyp) 176 u_long n; 177 struct tty *ttyp; 178 { 179 char prbuf[11]; 180 register char *cp; 181 182 if (b == -10) { 183 if ((int)n < 0) { 184 putchar('-', flags, ttyp); 185 n = (unsigned)(-(int)n); 186 } 187 b = -b; 188 } 189 cp = prbuf; 190 do { 191 *cp++ = "0123456789abcdef"[n%b]; 192 n /= b; 193 } while (n); 194 do 195 putchar(*--cp, flags, ttyp); 196 while (cp > prbuf); 197 } 198 199 /* 200 * Panic is called on unresolvable fatal errors. 201 * It prints "panic: mesg", and then reboots. 202 * If we are called twice, then we avoid trying to 203 * sync the disks as this often leads to recursive panics. 204 */ 205 panic(s) 206 char *s; 207 { 208 if (!panicstr) { 209 panicstr = s; 210 } 211 printf("panic: %s\n", s); 212 213 ROM_abort(); 214 } 215 216 /* 217 * Print a character on console or users terminal. 218 * If destination is console then the last MSGBUFS characters 219 * are saved in msgbuf for inspection later. 220 */ 221 /*ARGSUSED*/ 222 putchar(c, flags, ttyp) 223 register int c; 224 struct tty *ttyp; 225 { 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 (*v_putc)(c); 253 } 254