xref: /plan9/sys/src/cmd/aux/vga/io.c (revision 8cf6001e50e647a07ccf484b8e2f9940411befb9)
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