1*25870Ssam /* prf.c 1.1 86/01/12 */ 2*25870Ssam /* prf.c 4.3 81/05/05 */ 3*25870Ssam 4*25870Ssam #include "../machine/mtpr.h" 5*25870Ssam 6*25870Ssam #include "param.h" 7*25870Ssam #include "../tahoe/cp.h" 8*25870Ssam #ifdef NOIO 9*25870Ssam #define CINADR 0xf0000 /* Dummy keyboard (memory mapped) */ 10*25870Ssam #define COUTADR 0xf1000 /* Dummy screen -,,- */ 11*25870Ssam #endif 12*25870Ssam 13*25870Ssam /* 14*25870Ssam * Scaled down version of C Library printf. 15*25870Ssam * Used to print diagnostic information directly on console tty. 16*25870Ssam * Since it is not interrupt driven, all system activities are 17*25870Ssam * suspended. Printf should not be used for chit-chat. 18*25870Ssam * 19*25870Ssam * One additional format: %b is supported to decode error registers. 20*25870Ssam * Usage is: 21*25870Ssam * printf("reg=%b\n", regval, "<base><arg>*"); 22*25870Ssam * Where <base> is the output base expressed as a control character, 23*25870Ssam * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 24*25870Ssam * characters, the first of which gives the bit number to be inspected 25*25870Ssam * (origin 1), and the next characters (up to a control character, i.e. 26*25870Ssam * a character <= 32), give the name of the register. Thus 27*25870Ssam * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 28*25870Ssam * would produce output: 29*25870Ssam * reg=2<BITTWO,BITONE> 30*25870Ssam */ 31*25870Ssam /*VARARGS1*/ 32*25870Ssam printf(fmt, x1) 33*25870Ssam char *fmt; 34*25870Ssam unsigned x1; 35*25870Ssam { 36*25870Ssam 37*25870Ssam prf(fmt, &x1); 38*25870Ssam } 39*25870Ssam 40*25870Ssam prf(fmt, adx) 41*25870Ssam register char *fmt; 42*25870Ssam register u_int *adx; 43*25870Ssam { 44*25870Ssam register int b, c, i; 45*25870Ssam char *s; 46*25870Ssam int any; 47*25870Ssam 48*25870Ssam loop: 49*25870Ssam while ((c = *fmt++) != '%') { 50*25870Ssam if(c == '\0') 51*25870Ssam return; 52*25870Ssam putchar(c); 53*25870Ssam } 54*25870Ssam again: 55*25870Ssam c = *fmt++; 56*25870Ssam /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */ 57*25870Ssam switch (c) { 58*25870Ssam 59*25870Ssam case 'l': 60*25870Ssam goto again; 61*25870Ssam case 'x': case 'X': 62*25870Ssam b = 16; 63*25870Ssam goto number; 64*25870Ssam case 'd': case 'D': 65*25870Ssam case 'u': /* what a joke */ 66*25870Ssam b = 10; 67*25870Ssam goto number; 68*25870Ssam case 'o': case 'O': 69*25870Ssam b = 8; 70*25870Ssam number: 71*25870Ssam printn((u_long)*adx, b); 72*25870Ssam break; 73*25870Ssam case 'c': 74*25870Ssam b = *adx; 75*25870Ssam for (i = 24; i >= 0; i -= 8) 76*25870Ssam if (c = (b >> i) & 0x7f) 77*25870Ssam putchar(c); 78*25870Ssam break; 79*25870Ssam case 'b': 80*25870Ssam b = *adx++; 81*25870Ssam s = (char *)*adx; 82*25870Ssam printn((u_long)b, *s++); 83*25870Ssam any = 0; 84*25870Ssam if (b) { 85*25870Ssam putchar('<'); 86*25870Ssam while (i = *s++) { 87*25870Ssam if (b & (1 << (i-1))) { 88*25870Ssam if (any) 89*25870Ssam putchar(','); 90*25870Ssam any = 1; 91*25870Ssam for (; (c = *s) > 32; s++) 92*25870Ssam putchar(c); 93*25870Ssam } else 94*25870Ssam for (; *s > 32; s++) 95*25870Ssam ; 96*25870Ssam } 97*25870Ssam putchar('>'); 98*25870Ssam } 99*25870Ssam break; 100*25870Ssam 101*25870Ssam case 's': 102*25870Ssam s = (char *)*adx; 103*25870Ssam while (c = *s++) 104*25870Ssam putchar(c); 105*25870Ssam break; 106*25870Ssam } 107*25870Ssam adx++; 108*25870Ssam goto loop; 109*25870Ssam } 110*25870Ssam 111*25870Ssam /* 112*25870Ssam * Printn prints a number n in base b. 113*25870Ssam * We don't use recursion to avoid deep kernel stacks. 114*25870Ssam */ 115*25870Ssam printn(n, b) 116*25870Ssam u_long n; 117*25870Ssam { 118*25870Ssam char prbuf[11]; 119*25870Ssam register char *cp; 120*25870Ssam 121*25870Ssam if (b == 10 && (int)n < 0) { 122*25870Ssam putchar('-'); 123*25870Ssam n = (unsigned)(-(int)n); 124*25870Ssam } 125*25870Ssam cp = prbuf; 126*25870Ssam do { 127*25870Ssam *cp++ = "0123456789abcdef"[n%b]; 128*25870Ssam n /= b; 129*25870Ssam } while (n); 130*25870Ssam do 131*25870Ssam putchar(*--cp); 132*25870Ssam while (cp > prbuf); 133*25870Ssam } 134*25870Ssam 135*25870Ssam /* 136*25870Ssam * Print a character on console. 137*25870Ssam * Attempts to save and restore device 138*25870Ssam * status. 139*25870Ssam * 140*25870Ssam * Whether or not printing is inhibited, 141*25870Ssam * the last MSGBUFS characters 142*25870Ssam * are saved in msgbuf for inspection later. 143*25870Ssam */ 144*25870Ssam #ifdef NOIO 145*25870Ssam char *coutadr=(char *)COUTADR; 146*25870Ssam putchar(c) 147*25870Ssam register c; 148*25870Ssam { 149*25870Ssam *coutadr++ = c; 150*25870Ssam } 151*25870Ssam 152*25870Ssam char *cinadr=(char *)CINADR; 153*25870Ssam getchar() 154*25870Ssam { 155*25870Ssam return( *cinadr++ ); 156*25870Ssam } 157*25870Ssam 158*25870Ssam #else 159*25870Ssam struct cpdcb_o cpout; 160*25870Ssam struct cpdcb_i cpin; 161*25870Ssam 162*25870Ssam /* console requires even parity */ 163*25870Ssam #define EVENP 164*25870Ssam putchar(c) 165*25870Ssam char c; 166*25870Ssam { 167*25870Ssam int time; 168*25870Ssam #ifdef EVENP 169*25870Ssam register mask, par; 170*25870Ssam 171*25870Ssam for(par=0, mask=1; mask!=0200; mask<<=1, par<<=1) 172*25870Ssam par ^= c&mask; 173*25870Ssam c |= par; 174*25870Ssam #endif EVENP 175*25870Ssam cpout.cp_hdr.cp_unit = CPCONS; /* Resets done bit */ 176*25870Ssam cpout.cp_hdr.cp_comm = CPWRITE; 177*25870Ssam cpout.cp_hdr.cp_count = 1; 178*25870Ssam cpout.cp_buf[0] = c; 179*25870Ssam mtpr(CPMDCB, &cpout); 180*25870Ssam #ifdef SIMIO 181*25870Ssam simout(&cpout); 182*25870Ssam #endif 183*25870Ssam time = 100000; /* Delay loop */ 184*25870Ssam while (time--) { 185*25870Ssam uncache (&cpout.cp_hdr.cp_unit) ; 186*25870Ssam if (cpout.cp_hdr.cp_unit & CPDONE) break; 187*25870Ssam } 188*25870Ssam if (c == '\n') putchar ('\r'); 189*25870Ssam } 190*25870Ssam 191*25870Ssam #ifdef SIMIO 192*25870Ssam simout(addr) 193*25870Ssam { 194*25870Ssam asm(".byte 0x4"); 195*25870Ssam } 196*25870Ssam simin(addr) 197*25870Ssam { 198*25870Ssam asm(".byte 0x3"); 199*25870Ssam } 200*25870Ssam #endif 201*25870Ssam 202*25870Ssam getchar() 203*25870Ssam { 204*25870Ssam char c; 205*25870Ssam 206*25870Ssam cpin.cp_hdr.cp_unit = CPCONS; /* Resets done bit */ 207*25870Ssam cpin.cp_hdr.cp_comm = CPREAD; 208*25870Ssam cpin.cp_hdr.cp_count = 1; 209*25870Ssam mtpr(CPMDCB, &cpin); 210*25870Ssam #ifdef SIMIO 211*25870Ssam simin(&cpin); 212*25870Ssam #endif 213*25870Ssam while ((cpin.cp_hdr.cp_unit & CPDONE) == 0) 214*25870Ssam uncache (&cpin.cp_hdr.cp_unit); 215*25870Ssam uncache (&cpin.cpi_buf[0]); 216*25870Ssam c = cpin.cpi_buf[0] & 0x7f; 217*25870Ssam if (c == '\r') c = '\n'; 218*25870Ssam putchar(c); 219*25870Ssam return(c); 220*25870Ssam } 221*25870Ssam #endif 222*25870Ssam 223*25870Ssam 224*25870Ssam gets(buf) 225*25870Ssam char *buf; 226*25870Ssam { 227*25870Ssam register char *lp; 228*25870Ssam register c; 229*25870Ssam 230*25870Ssam lp = buf; 231*25870Ssam for (;;) { 232*25870Ssam c = getchar() & 0177; 233*25870Ssam store: 234*25870Ssam switch(c) { 235*25870Ssam case '\n': 236*25870Ssam case '\r': 237*25870Ssam c = '\n'; 238*25870Ssam *lp++ = '\0'; 239*25870Ssam return; 240*25870Ssam case '\b': 241*25870Ssam case '#': 242*25870Ssam lp--; 243*25870Ssam if (lp < buf) 244*25870Ssam lp = buf; 245*25870Ssam continue; 246*25870Ssam case '@': 247*25870Ssam case 'u'&037: 248*25870Ssam lp = buf; 249*25870Ssam putchar('\n'); 250*25870Ssam continue; 251*25870Ssam default: 252*25870Ssam *lp++ = c; 253*25870Ssam } 254*25870Ssam } 255*25870Ssam } 256