1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 #include "pci.h"
6 #include "vga.h"
7
8 int curprintindex;
9
10 static int iobfd = -1;
11 static int iowfd = -1;
12 static int iolfd = -1;
13 static int biosfd = -1;
14 static ulong biosoffset = 0;
15
16 enum {
17 Nctlchar = 256,
18 Nattr = 16,
19 };
20
21 static int ctlfd = -1;
22 static char ctlbuf[Nctlchar];
23 static int ctlclean;
24
25 static struct {
26 char* attr;
27 char* val;
28 } attr[Nattr];
29
30 static int
devopen(char * device,int mode)31 devopen(char* device, int mode)
32 {
33 int fd;
34
35 if((fd = open(device, mode)) < 0)
36 error("devopen(%s, %d): %r\n", device, mode);
37 return fd;
38 }
39
40 uchar
inportb(long port)41 inportb(long port)
42 {
43 uchar data;
44
45 if(iobfd == -1)
46 iobfd = devopen("#P/iob", ORDWR);
47
48 if(pread(iobfd, &data, sizeof(data), port) != sizeof(data))
49 error("inportb(0x%4.4lx): %r\n", port);
50 return data;
51 }
52
53 void
outportb(long port,uchar data)54 outportb(long port, uchar data)
55 {
56 if(iobfd == -1)
57 iobfd = devopen("#P/iob", ORDWR);
58
59 if(pwrite(iobfd, &data, sizeof(data), port) != sizeof(data))
60 error("outportb(0x%4.4lx, 0x%2.2uX): %r\n", port, data);
61 }
62
63 ushort
inportw(long port)64 inportw(long port)
65 {
66 ushort data;
67
68 if(iowfd == -1)
69 iowfd = devopen("#P/iow", ORDWR);
70
71 if(pread(iowfd, &data, sizeof(data), port) != sizeof(data))
72 error("inportw(0x%4.4lx): %r\n", port);
73 return data;
74 }
75
76 void
outportw(long port,ushort data)77 outportw(long port, ushort data)
78 {
79 if(iowfd == -1)
80 iowfd = devopen("#P/iow", ORDWR);
81
82 if(pwrite(iowfd, &data, sizeof(data), port) != sizeof(data))
83 error("outportw(0x%4.4lx, 0x%2.2uX): %r\n", port, data);
84 }
85
86 ulong
inportl(long port)87 inportl(long port)
88 {
89 ulong data;
90
91 if(iolfd == -1)
92 iolfd = devopen("#P/iol", ORDWR);
93
94 if(pread(iolfd, &data, sizeof(data), port) != sizeof(data))
95 error("inportl(0x%4.4lx): %r\n", port);
96 return data;
97 }
98
99 void
outportl(long port,ulong data)100 outportl(long port, ulong data)
101 {
102 if(iolfd == -1)
103 iolfd = devopen("#P/iol", ORDWR);
104
105 if(pwrite(iolfd, &data, sizeof(data), port) != sizeof(data))
106 error("outportl(0x%4.4lx, 0x%2.2luX): %r\n", port, data);
107 }
108
109 static void
vgactlinit(void)110 vgactlinit(void)
111 {
112 int nattr;
113 char *nl, *p, *vp;
114
115 if(ctlclean)
116 return;
117
118 if(ctlfd == -1){
119 ctlfd = devopen("#v/vgactl", ORDWR);
120 memset(attr, 0, sizeof(attr));
121 }
122
123 seek(ctlfd, 0, 0);
124 nattr = read(ctlfd, ctlbuf, Nctlchar-1);
125 if(nattr < 0)
126 error("vgactlr: read: %r\n");
127 ctlbuf[nattr] = 0;
128
129 nattr = 0;
130 vp = ctlbuf;
131 for(nl = strchr(ctlbuf, '\n'); nl; nl = strchr(nl, '\n')){
132
133 *nl = '\0';
134 if(p = strchr(vp, ' ')){
135 *p++ = '\0';
136 attr[nattr].attr = vp;
137 if(*p == '\0')
138 error("vgactlr: bad format: <%s>\n", vp);
139 attr[nattr].val = p;
140 }
141 else
142 error("vgactlr: bad format: <%s>\n", vp);
143
144 if(++nattr >= Nattr-2)
145 error("vgactlr: too many attributes: %d\n", nattr);
146 attr[nattr].attr = 0;
147
148 vp = ++nl;
149 }
150
151 ctlclean = 1;
152 }
153
154 char*
vgactlr(char * a,char * v)155 vgactlr(char* a, char* v)
156 {
157 int i;
158
159 trace("vgactlr: look for %s\n", a);
160 vgactlinit();
161 for(i = 0; attr[i].attr; i++){
162 if(strcmp(attr[i].attr, a) == 0){
163 strcpy(v, attr[i].val);
164 trace("vgactlr: value %s\n", v);
165 return v;
166 }
167 }
168 trace("vgactlr: %s not found\n", a);
169
170 return 0;
171 }
172
173 void
vgactlw(char * attr,char * val)174 vgactlw(char* attr, char* val)
175 {
176 int len;
177 char buf[128];
178
179 if(ctlfd == -1)
180 ctlfd = devopen("#v/vgactl", ORDWR);
181
182 seek(ctlfd, 0, 0);
183 len = sprint(buf, "%s %s", attr, val);
184 trace("+vgactlw %s\n", buf);
185 if(write(ctlfd, buf, len) != len)
186 error("vgactlw: <%s>: %r\n", buf);
187 trace("-vgactlw %s\n", buf);
188
189 ctlclean = 0;
190 }
191
192 void
setpalette(int p,int r,int g,int b)193 setpalette(int p, int r, int g, int b)
194 {
195 vgao(PaddrW, p);
196 vgao(Pdata, r);
197 vgao(Pdata, g);
198 vgao(Pdata, b);
199 }
200
201 static long
doreadbios(char * buf,long len,long offset)202 doreadbios(char* buf, long len, long offset)
203 {
204 char file[64];
205
206 if(biosfd == -1){
207 biosfd = open("#v/vgabios", OREAD);
208 biosoffset = 0;
209 }
210 if(biosfd == -1){
211 snprint(file, sizeof file, "#p/%d/mem", getpid());
212 biosfd = devopen(file, OREAD);
213 biosoffset = 0x80000000;
214 }
215 if(biosfd == -1)
216 return -1;
217 seek(biosfd, biosoffset+offset, 0);
218 return read(biosfd, buf, len);
219 }
220
221 char*
readbios(long len,long offset)222 readbios(long len, long offset)
223 {
224 static char bios[0x10000];
225 static long biosoffset;
226 static long bioslen;
227 int n;
228
229 if(biosoffset <= offset && offset+len <= biosoffset+bioslen)
230 return bios+(offset - biosoffset);
231
232 if(len > sizeof(bios))
233 error("enormous bios len %ld at %lux\n", len, offset);
234
235 n = doreadbios(bios, sizeof(bios), offset);
236 if(n < len)
237 error("short bios read %ld at %lux got %d\n", len,offset, n);
238
239 biosoffset = offset;
240 bioslen = n;
241 return bios;
242 }
243
244 void
dumpbios(long size)245 dumpbios(long size)
246 {
247 uchar *buf;
248 long offset;
249 int i, n;
250 char c;
251
252 buf = alloc(size);
253 offset = 0xC0000;
254 if(doreadbios((char*)buf, size, offset) != size)
255 error("short bios read in dumpbios\n");
256
257 if(buf[0] != 0x55 || buf[1] != 0xAA){
258 offset = 0xE0000;
259 if(doreadbios((char*)buf, size, offset) != size)
260 error("short bios read in dumpbios\n");
261 if(buf[0] != 0x55 || buf[1] != 0xAA){
262 free(buf);
263 return;
264 }
265 }
266
267 for(i = 0; i < size; i += 16){
268 Bprint(&stdout, "0x%luX", offset+i);
269 for(n = 0; n < 16; n++)
270 Bprint(&stdout, " %2.2uX", buf[i+n]);
271 Bprint(&stdout, " ");
272 for(n = 0; n < 16; n++){
273 c = buf[i+n];
274 if(c < 0x20 || c >= 0x7F)
275 c = '.';
276 Bprint(&stdout, "%c", c);
277 }
278 Bprint(&stdout, "\n");
279 }
280 free(buf);
281 }
282
283 void*
alloc(ulong nbytes)284 alloc(ulong nbytes)
285 {
286 void *v;
287
288 if((v = malloc(nbytes)) == 0)
289 error("alloc: %lud bytes - %r\n", nbytes);
290
291 return memset(v, 0, nbytes);
292 }
293
294 void
printitem(char * ctlr,char * item)295 printitem(char* ctlr, char* item)
296 {
297 int n;
298
299 if(curprintindex){
300 curprintindex = 0;
301 Bprint(&stdout, "\n");
302 }
303
304 n = 0;
305 if(ctlr && *ctlr)
306 n = Bprint(&stdout, "%s ", ctlr);
307 Bprint(&stdout, "%-*s", 20-n, item);
308 }
309
310 void
printreg(ulong data)311 printreg(ulong data)
312 {
313 int width;
314
315 width = 3;
316 if((curprintindex % 16) == 0 && curprintindex){
317 Bprint(&stdout, "\n");
318 curprintindex = 0;
319 width = 23;
320 }
321 if(curprintindex == 8)
322 Bprint(&stdout, " -");
323 Bprint(&stdout, "%*.2luX", width, data);
324 curprintindex++;
325 }
326
327 static char *flagname[32] = {
328 [0x00] "Fsnarf",
329 [0x01] "Foptions",
330 [0x02] "Finit",
331 [0x03] "Fload",
332 [0x04] "Fdump",
333
334 [0x08] "Hpclk2x8",
335 [0x09] "Upclk2x8",
336 [0x0A] "Henhanced",
337 [0x0B] "Uenhanced",
338 [0x0C] "Hpvram",
339 [0x0D] "Upvram",
340 [0x0E] "Hextsid",
341 [0x0F] "Uextsid",
342 [0x10] "Hclk2",
343 [0x11] "Uclk2",
344 [0x12] "Hlinear",
345 [0x13] "Ulinear",
346 [0x14] "Hclkdiv",
347 [0x15] "Uclkdiv",
348 [0x16] "Hsid32",
349 };
350
351 void
printflag(ulong flag)352 printflag(ulong flag)
353 {
354 int i;
355 char first;
356
357 first = ' ';
358 for(i = 31; i >= 0; i--){
359 if((flag & (1<<i)) == 0)
360 continue;
361 if(flagname[i])
362 Bprint(&stdout, "%c%s", first, flagname[i]);
363 else
364 Bprint(&stdout, "%c0x%x", first, 1<<i);
365 first = '|';
366 }
367 }
368