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