Commit | Line | Data |
---|---|---|
ec3296ac | 1 | /* prf.c 1.6 90/06/22 */ |
1e1f58c3 SL |
2 | /* prf.c 4.3 81/05/05 */ |
3 | ||
c18e27ed | 4 | #include "machine/mtpr.h" |
1e1f58c3 | 5 | |
ec3296ac BJ |
6 | #include "sys/param.h" |
7 | #include "tahoe/cp.h" | |
1e1f58c3 SL |
8 | |
9 | /* | |
10 | * Scaled down version of C Library printf. | |
11 | * Used to print diagnostic information directly on console tty. | |
12 | * Since it is not interrupt driven, all system activities are | |
13 | * suspended. Printf should not be used for chit-chat. | |
14 | * | |
15 | * One additional format: %b is supported to decode error registers. | |
16 | * Usage is: | |
17 | * printf("reg=%b\n", regval, "<base><arg>*"); | |
18 | * Where <base> is the output base expressed as a control character, | |
19 | * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of | |
20 | * characters, the first of which gives the bit number to be inspected | |
21 | * (origin 1), and the next characters (up to a control character, i.e. | |
22 | * a character <= 32), give the name of the register. Thus | |
23 | * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); | |
24 | * would produce output: | |
25 | * reg=2<BITTWO,BITONE> | |
26 | */ | |
27 | /*VARARGS1*/ | |
28 | printf(fmt, x1) | |
29 | char *fmt; | |
30 | unsigned x1; | |
31 | { | |
32 | ||
33 | prf(fmt, &x1); | |
34 | } | |
35 | ||
36 | prf(fmt, adx) | |
37 | register char *fmt; | |
38 | register u_int *adx; | |
39 | { | |
40 | register int b, c, i; | |
41 | char *s; | |
42 | int any; | |
43 | ||
44 | loop: | |
45 | while ((c = *fmt++) != '%') { | |
54e5fb0b | 46 | if (c == '\0') |
1e1f58c3 SL |
47 | return; |
48 | putchar(c); | |
49 | } | |
50 | again: | |
51 | c = *fmt++; | |
52 | /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */ | |
53 | switch (c) { | |
54 | ||
55 | case 'l': | |
56 | goto again; | |
57 | case 'x': case 'X': | |
58 | b = 16; | |
59 | goto number; | |
60 | case 'd': case 'D': | |
61 | case 'u': /* what a joke */ | |
62 | b = 10; | |
63 | goto number; | |
64 | case 'o': case 'O': | |
65 | b = 8; | |
66 | number: | |
67 | printn((u_long)*adx, b); | |
68 | break; | |
69 | case 'c': | |
70 | b = *adx; | |
71 | for (i = 24; i >= 0; i -= 8) | |
72 | if (c = (b >> i) & 0x7f) | |
73 | putchar(c); | |
74 | break; | |
75 | case 'b': | |
76 | b = *adx++; | |
77 | s = (char *)*adx; | |
78 | printn((u_long)b, *s++); | |
79 | any = 0; | |
80 | if (b) { | |
1e1f58c3 SL |
81 | while (i = *s++) { |
82 | if (b & (1 << (i-1))) { | |
54e5fb0b | 83 | putchar(any? ',' : '<'); |
1e1f58c3 SL |
84 | any = 1; |
85 | for (; (c = *s) > 32; s++) | |
86 | putchar(c); | |
87 | } else | |
88 | for (; *s > 32; s++) | |
89 | ; | |
90 | } | |
54e5fb0b MK |
91 | if (any) |
92 | putchar('>'); | |
1e1f58c3 SL |
93 | } |
94 | break; | |
95 | ||
96 | case 's': | |
97 | s = (char *)*adx; | |
98 | while (c = *s++) | |
99 | putchar(c); | |
100 | break; | |
101 | } | |
102 | adx++; | |
103 | goto loop; | |
104 | } | |
105 | ||
1e1f58c3 SL |
106 | /* |
107 | * Print a character on console. | |
1e1f58c3 | 108 | */ |
1e1f58c3 SL |
109 | struct cpdcb_o cpout; |
110 | struct cpdcb_i cpin; | |
111 | ||
112 | /* console requires even parity */ | |
113 | #define EVENP | |
54e5fb0b | 114 | |
1e1f58c3 | 115 | putchar(c) |
54e5fb0b | 116 | char c; |
1e1f58c3 SL |
117 | { |
118 | int time; | |
119 | #ifdef EVENP | |
120 | register mask, par; | |
121 | ||
54e5fb0b | 122 | for (par = 0, mask = 1; mask != 0200; mask <<= 1, par <<= 1) |
1e1f58c3 SL |
123 | par ^= c&mask; |
124 | c |= par; | |
125 | #endif EVENP | |
126 | cpout.cp_hdr.cp_unit = CPCONS; /* Resets done bit */ | |
127 | cpout.cp_hdr.cp_comm = CPWRITE; | |
128 | cpout.cp_hdr.cp_count = 1; | |
129 | cpout.cp_buf[0] = c; | |
130 | mtpr(CPMDCB, &cpout); | |
1e1f58c3 SL |
131 | time = 100000; /* Delay loop */ |
132 | while (time--) { | |
54e5fb0b MK |
133 | uncache(&cpout.cp_hdr.cp_unit); |
134 | if (cpout.cp_hdr.cp_unit & CPDONE) | |
135 | break; | |
1e1f58c3 | 136 | } |
54e5fb0b MK |
137 | if (c == '\n') |
138 | putchar ('\r'); | |
1e1f58c3 | 139 | } |
1e1f58c3 SL |
140 | |
141 | getchar() | |
142 | { | |
54e5fb0b | 143 | char c; |
1e1f58c3 SL |
144 | |
145 | cpin.cp_hdr.cp_unit = CPCONS; /* Resets done bit */ | |
146 | cpin.cp_hdr.cp_comm = CPREAD; | |
147 | cpin.cp_hdr.cp_count = 1; | |
148 | mtpr(CPMDCB, &cpin); | |
1e1f58c3 | 149 | while ((cpin.cp_hdr.cp_unit & CPDONE) == 0) |
54e5fb0b MK |
150 | uncache(&cpin.cp_hdr.cp_unit); |
151 | uncache(&cpin.cpi_buf[0]); | |
1e1f58c3 | 152 | c = cpin.cpi_buf[0] & 0x7f; |
54e5fb0b MK |
153 | if (c == '\r') |
154 | c = '\n'; | |
155 | if (c != '\b' && c != '\177') | |
156 | putchar(c); | |
157 | return (c); | |
1e1f58c3 | 158 | } |
0aa02f62 KB |
159 | |
160 | trap(ps) | |
161 | int ps; | |
162 | { | |
163 | printf("Trap %o\n", ps); | |
164 | for (;;) | |
165 | ; | |
166 | } | |
167 | ||
168 | uncache (addr) | |
169 | char *addr; | |
170 | { | |
171 | /* Return *(addr-0x4000); DIRTY assumes this address is valid */ | |
172 | mtpr(PDCS, addr); | |
173 | } |