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