xref: /plan9/sys/src/cmd/aux/vga/io.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier #include <u.h>
2*219b2ee8SDavid du Colombier #include <libc.h>
3*219b2ee8SDavid du Colombier #include <stdarg.h>
4*219b2ee8SDavid du Colombier 
5*219b2ee8SDavid du Colombier #include "vga.h"
6*219b2ee8SDavid du Colombier 
7*219b2ee8SDavid du Colombier static int iobfd = -1;
8*219b2ee8SDavid du Colombier static int iowfd = -1;
9*219b2ee8SDavid du Colombier static int iolfd = -1;
10*219b2ee8SDavid du Colombier static int biosfd = -1;
11*219b2ee8SDavid du Colombier 
12*219b2ee8SDavid du Colombier enum {
13*219b2ee8SDavid du Colombier 	Nctlchar	= 256,
14*219b2ee8SDavid du Colombier 	Nattr		= 16,
15*219b2ee8SDavid du Colombier };
16*219b2ee8SDavid du Colombier 
17*219b2ee8SDavid du Colombier static int ctlfd = -1;
18*219b2ee8SDavid du Colombier static char ctlbuf[Nctlchar];
19*219b2ee8SDavid du Colombier 
20*219b2ee8SDavid du Colombier static struct {
21*219b2ee8SDavid du Colombier 	char*	attr;
22*219b2ee8SDavid du Colombier 	char*	val;
23*219b2ee8SDavid du Colombier } attr[Nattr];
24*219b2ee8SDavid du Colombier 
25*219b2ee8SDavid du Colombier static int
26*219b2ee8SDavid du Colombier devopen(char *device, int mode)
27*219b2ee8SDavid du Colombier {
28*219b2ee8SDavid du Colombier 	int fd;
29*219b2ee8SDavid du Colombier 
30*219b2ee8SDavid du Colombier 	if((fd = open(device, mode)) < 0)
31*219b2ee8SDavid du Colombier 		error("devopen(%s, %d): %r\n", device, mode);
32*219b2ee8SDavid du Colombier 	return fd;
33*219b2ee8SDavid du Colombier }
34*219b2ee8SDavid du Colombier 
35*219b2ee8SDavid du Colombier uchar
36*219b2ee8SDavid du Colombier inportb(long port)
37*219b2ee8SDavid du Colombier {
38*219b2ee8SDavid du Colombier 	uchar data;
39*219b2ee8SDavid du Colombier 
40*219b2ee8SDavid du Colombier 	if(iobfd == -1)
41*219b2ee8SDavid du Colombier 		iobfd = devopen("#v/vgaiob", ORDWR);
42*219b2ee8SDavid du Colombier 
43*219b2ee8SDavid du Colombier 	seek(iobfd, port, 0);
44*219b2ee8SDavid du Colombier 	if(read(iobfd, &data, sizeof(data)) != sizeof(data))
45*219b2ee8SDavid du Colombier 		error("inportb(0x%4.4x): %r\n", port);
46*219b2ee8SDavid du Colombier 	return data;
47*219b2ee8SDavid du Colombier }
48*219b2ee8SDavid du Colombier 
49*219b2ee8SDavid du Colombier void
50*219b2ee8SDavid du Colombier outportb(long port, uchar data)
51*219b2ee8SDavid du Colombier {
52*219b2ee8SDavid du Colombier 	if(iobfd == -1)
53*219b2ee8SDavid du Colombier 		iobfd = devopen("#v/vgaiob", ORDWR);
54*219b2ee8SDavid du Colombier 
55*219b2ee8SDavid du Colombier 	seek(iobfd, port, 0);
56*219b2ee8SDavid du Colombier 	if(write(iobfd, &data, sizeof(data)) != sizeof(data))
57*219b2ee8SDavid du Colombier 		error("outportb(0x%4.4x, 0x%2.2X): %r\n", port, data);
58*219b2ee8SDavid du Colombier }
59*219b2ee8SDavid du Colombier 
60*219b2ee8SDavid du Colombier ushort
61*219b2ee8SDavid du Colombier inportw(long port)
62*219b2ee8SDavid du Colombier {
63*219b2ee8SDavid du Colombier 	ushort data;
64*219b2ee8SDavid du Colombier 
65*219b2ee8SDavid du Colombier 	if(iowfd == -1)
66*219b2ee8SDavid du Colombier 		iowfd = devopen("#v/vgaiow", ORDWR);
67*219b2ee8SDavid du Colombier 
68*219b2ee8SDavid du Colombier 	seek(iowfd, port, 0);
69*219b2ee8SDavid du Colombier 	if(read(iowfd, &data, sizeof(data)) != sizeof(data))
70*219b2ee8SDavid du Colombier 		error("inportw(0x%4.4x): %r\n", port);
71*219b2ee8SDavid du Colombier 	return data;
72*219b2ee8SDavid du Colombier }
73*219b2ee8SDavid du Colombier 
74*219b2ee8SDavid du Colombier void
75*219b2ee8SDavid du Colombier outportw(long port, ushort data)
76*219b2ee8SDavid du Colombier {
77*219b2ee8SDavid du Colombier 	if(iowfd == -1)
78*219b2ee8SDavid du Colombier 		iowfd = devopen("#v/vgaiow", ORDWR);
79*219b2ee8SDavid du Colombier 
80*219b2ee8SDavid du Colombier 	seek(iowfd, port, 0);
81*219b2ee8SDavid du Colombier 	if(write(iowfd, &data, sizeof(data)) != sizeof(data))
82*219b2ee8SDavid du Colombier 		error("outportw(0x%4.4x, 0x%2.2X): %r\n", port, data);
83*219b2ee8SDavid du Colombier }
84*219b2ee8SDavid du Colombier 
85*219b2ee8SDavid du Colombier ulong
86*219b2ee8SDavid du Colombier inportl(long port)
87*219b2ee8SDavid du Colombier {
88*219b2ee8SDavid du Colombier 	ulong data;
89*219b2ee8SDavid du Colombier 
90*219b2ee8SDavid du Colombier 	if(iolfd == -1)
91*219b2ee8SDavid du Colombier 		iolfd = devopen("#v/vgaiol", ORDWR);
92*219b2ee8SDavid du Colombier 
93*219b2ee8SDavid du Colombier 	seek(iolfd, port, 0);
94*219b2ee8SDavid du Colombier 	if(read(iolfd, &data, sizeof(data)) != sizeof(data))
95*219b2ee8SDavid du Colombier 		error("inportl(0x%4.4x): %r\n", port);
96*219b2ee8SDavid du Colombier 	return data;
97*219b2ee8SDavid du Colombier }
98*219b2ee8SDavid du Colombier 
99*219b2ee8SDavid du Colombier void
100*219b2ee8SDavid du Colombier outportl(long port, ulong data)
101*219b2ee8SDavid du Colombier {
102*219b2ee8SDavid du Colombier 	if(iolfd == -1)
103*219b2ee8SDavid du Colombier 		iolfd = devopen("#v/vgaiol", ORDWR);
104*219b2ee8SDavid du Colombier 
105*219b2ee8SDavid du Colombier 	seek(iolfd, port, 0);
106*219b2ee8SDavid du Colombier 	if(write(iolfd, &data, sizeof(data)) != sizeof(data))
107*219b2ee8SDavid du Colombier 		error("outportl(0x%4.4x, 0x%2.2X): %r\n", port, data);
108*219b2ee8SDavid du Colombier }
109*219b2ee8SDavid du Colombier 
110*219b2ee8SDavid du Colombier static void
111*219b2ee8SDavid du Colombier vgactlinit(void)
112*219b2ee8SDavid du Colombier {
113*219b2ee8SDavid du Colombier 	int nattr;
114*219b2ee8SDavid du Colombier 	char *nl, *p, *vp;
115*219b2ee8SDavid du Colombier 
116*219b2ee8SDavid du Colombier 	if(ctlfd == -1){
117*219b2ee8SDavid du Colombier 		ctlfd = devopen("#v/vgactl", ORDWR);
118*219b2ee8SDavid du Colombier 		memset(attr, 0, sizeof(attr));
119*219b2ee8SDavid du Colombier 	}
120*219b2ee8SDavid du Colombier 
121*219b2ee8SDavid du Colombier 	if(attr[0].attr)
122*219b2ee8SDavid du Colombier 		return;
123*219b2ee8SDavid du Colombier 
124*219b2ee8SDavid du Colombier 	seek(ctlfd, 0, 0);
125*219b2ee8SDavid du Colombier 	if(read(ctlfd, ctlbuf, Nctlchar) < 0)
126*219b2ee8SDavid du Colombier 		error("vgactlr: read: %r\n");
127*219b2ee8SDavid du Colombier 	ctlbuf[Nctlchar-1] = 0;
128*219b2ee8SDavid du Colombier 
129*219b2ee8SDavid du Colombier 	nattr = 0;
130*219b2ee8SDavid du Colombier 	vp = ctlbuf;
131*219b2ee8SDavid du Colombier 	for(nl = strchr(ctlbuf, '\n'); nl; nl = strchr(nl, '\n')){
132*219b2ee8SDavid du Colombier 
133*219b2ee8SDavid du Colombier 		*nl = '\0';
134*219b2ee8SDavid du Colombier 		if(p = strtok(vp, ":")){
135*219b2ee8SDavid du Colombier 			attr[nattr].attr = p;
136*219b2ee8SDavid du Colombier 			if((p = strtok(0, " \t")) == 0)
137*219b2ee8SDavid du Colombier 				error("vgactlr: bad format: <%s>\n", vp);
138*219b2ee8SDavid du Colombier 			attr[nattr].val = p;
139*219b2ee8SDavid du Colombier 		}
140*219b2ee8SDavid du Colombier 		else
141*219b2ee8SDavid du Colombier 			error("vgactlr: bad format: <%s>\n", vp);
142*219b2ee8SDavid du Colombier 
143*219b2ee8SDavid du Colombier 		if(++nattr >= Nattr-2)
144*219b2ee8SDavid du Colombier 			error("vgactlr: too many attributes: %d\n", nattr);
145*219b2ee8SDavid du Colombier 		attr[nattr].attr = 0;
146*219b2ee8SDavid du Colombier 
147*219b2ee8SDavid du Colombier 		vp = ++nl;
148*219b2ee8SDavid du Colombier 	}
149*219b2ee8SDavid du Colombier }
150*219b2ee8SDavid du Colombier 
151*219b2ee8SDavid du Colombier char*
152*219b2ee8SDavid du Colombier vgactlr(char *a, char *v)
153*219b2ee8SDavid du Colombier {
154*219b2ee8SDavid du Colombier 	int i;
155*219b2ee8SDavid du Colombier 
156*219b2ee8SDavid du Colombier 	vgactlinit();
157*219b2ee8SDavid du Colombier 
158*219b2ee8SDavid du Colombier 	for(i = 0; attr[i].attr; i++){
159*219b2ee8SDavid du Colombier 		if(strcmp(attr[i].attr, a) == 0){
160*219b2ee8SDavid du Colombier 			strcpy(v, attr[i].val);
161*219b2ee8SDavid du Colombier 			return v;
162*219b2ee8SDavid du Colombier 		}
163*219b2ee8SDavid du Colombier 	}
164*219b2ee8SDavid du Colombier 
165*219b2ee8SDavid du Colombier 	return 0;
166*219b2ee8SDavid du Colombier }
167*219b2ee8SDavid du Colombier 
168*219b2ee8SDavid du Colombier void
169*219b2ee8SDavid du Colombier vgactlw(char *attr, char *val)
170*219b2ee8SDavid du Colombier {
171*219b2ee8SDavid du Colombier 	int len;
172*219b2ee8SDavid du Colombier 	char buf[128];
173*219b2ee8SDavid du Colombier 
174*219b2ee8SDavid du Colombier 	if(ctlfd == -1)
175*219b2ee8SDavid du Colombier 		ctlfd = devopen("#v/vgactl", ORDWR);
176*219b2ee8SDavid du Colombier 
177*219b2ee8SDavid du Colombier 	seek(ctlfd, 0, 0);
178*219b2ee8SDavid du Colombier 	len = sprint(buf, "%s %s", attr, val);
179*219b2ee8SDavid du Colombier 	verbose("+vgactlw %s\n", buf);
180*219b2ee8SDavid du Colombier 	if(write(ctlfd, buf, len) != len)
181*219b2ee8SDavid du Colombier 		error("vgactlw: <%s>: %r\n",  buf);
182*219b2ee8SDavid du Colombier 	verbose("-vgactlw %s\n", buf);
183*219b2ee8SDavid du Colombier }
184*219b2ee8SDavid du Colombier 
185*219b2ee8SDavid du Colombier long
186*219b2ee8SDavid du Colombier readbios(char *buf, long len, long offset)
187*219b2ee8SDavid du Colombier {
188*219b2ee8SDavid du Colombier 	if(biosfd == -1)
189*219b2ee8SDavid du Colombier 		biosfd = devopen("#p/1/mem", OREAD);
190*219b2ee8SDavid du Colombier 
191*219b2ee8SDavid du Colombier 	seek(biosfd, 0x80000000|offset, 0);
192*219b2ee8SDavid du Colombier 	if(read(biosfd, buf, len) != len)
193*219b2ee8SDavid du Colombier 		error("readbios read: %r\n");
194*219b2ee8SDavid du Colombier 	return len;
195*219b2ee8SDavid du Colombier }
196*219b2ee8SDavid du Colombier 
197*219b2ee8SDavid du Colombier void
198*219b2ee8SDavid du Colombier dumpbios(void)
199*219b2ee8SDavid du Colombier {
200*219b2ee8SDavid du Colombier 	uchar buf[256];
201*219b2ee8SDavid du Colombier 	long offset;
202*219b2ee8SDavid du Colombier 	int i, n;
203*219b2ee8SDavid du Colombier 	char c;
204*219b2ee8SDavid du Colombier 
205*219b2ee8SDavid du Colombier 	offset = 0xC0000;
206*219b2ee8SDavid du Colombier 	readbios((char*)buf, sizeof(buf), offset);
207*219b2ee8SDavid du Colombier 	if(buf[0] != 0x55 || buf[1] != 0xAA){
208*219b2ee8SDavid du Colombier 		offset = 0xE0000;
209*219b2ee8SDavid du Colombier 		readbios((char*)buf, sizeof(buf), offset);
210*219b2ee8SDavid du Colombier 		if(buf[0] != 0x55 || buf[1] != 0xAA)
211*219b2ee8SDavid du Colombier 			return;
212*219b2ee8SDavid du Colombier 	}
213*219b2ee8SDavid du Colombier 
214*219b2ee8SDavid du Colombier 	for(i = 0; i < sizeof(buf); i += 16){
215*219b2ee8SDavid du Colombier 		print("0x%X", offset+i);
216*219b2ee8SDavid du Colombier 		for(n = 0; n < 16; n++)
217*219b2ee8SDavid du Colombier 			print(" %2.2uX", buf[i+n]);
218*219b2ee8SDavid du Colombier 		print("  ");
219*219b2ee8SDavid du Colombier 		for(n = 0; n < 16; n++){
220*219b2ee8SDavid du Colombier 			c = buf[i+n];
221*219b2ee8SDavid du Colombier 			if(c < 0x20 || c >= 0x7F)
222*219b2ee8SDavid du Colombier 				c = '.';
223*219b2ee8SDavid du Colombier 			print("%c", c);
224*219b2ee8SDavid du Colombier 		}
225*219b2ee8SDavid du Colombier 		print("\n");
226*219b2ee8SDavid du Colombier 	}
227*219b2ee8SDavid du Colombier }
228*219b2ee8SDavid du Colombier 
229*219b2ee8SDavid du Colombier int vflag;
230*219b2ee8SDavid du Colombier 
231*219b2ee8SDavid du Colombier void
232*219b2ee8SDavid du Colombier error(char *format, ...)
233*219b2ee8SDavid du Colombier {
234*219b2ee8SDavid du Colombier 	char buf[512];
235*219b2ee8SDavid du Colombier 	int n;
236*219b2ee8SDavid du Colombier 
237*219b2ee8SDavid du Colombier 	sequencer(0, 1);
238*219b2ee8SDavid du Colombier 	n = sprint(buf, "%s: ", argv0);
239*219b2ee8SDavid du Colombier 	doprint(buf+n, buf+sizeof(buf)-n, format, (&format+1));
240*219b2ee8SDavid du Colombier 	fprint(2, buf);
241*219b2ee8SDavid du Colombier 	if(vflag)
242*219b2ee8SDavid du Colombier 		print(buf+n);
243*219b2ee8SDavid du Colombier 	exits("error");
244*219b2ee8SDavid du Colombier }
245*219b2ee8SDavid du Colombier 
246*219b2ee8SDavid du Colombier void*
247*219b2ee8SDavid du Colombier alloc(ulong nbytes)
248*219b2ee8SDavid du Colombier {
249*219b2ee8SDavid du Colombier 	void *v;
250*219b2ee8SDavid du Colombier 
251*219b2ee8SDavid du Colombier 	if((v = malloc(nbytes)) == 0)
252*219b2ee8SDavid du Colombier 		error("can't malloc %d bytes - %r\n", nbytes);
253*219b2ee8SDavid du Colombier 
254*219b2ee8SDavid du Colombier 	return memset(v, 0, nbytes);
255*219b2ee8SDavid du Colombier }
256*219b2ee8SDavid du Colombier 
257*219b2ee8SDavid du Colombier static int curindex;
258*219b2ee8SDavid du Colombier 
259*219b2ee8SDavid du Colombier void
260*219b2ee8SDavid du Colombier printitem(char *ctlr, char *item)
261*219b2ee8SDavid du Colombier {
262*219b2ee8SDavid du Colombier 	int n;
263*219b2ee8SDavid du Colombier 
264*219b2ee8SDavid du Colombier 	if(curindex){
265*219b2ee8SDavid du Colombier 		curindex = 0;
266*219b2ee8SDavid du Colombier 		print("\n");
267*219b2ee8SDavid du Colombier 	}
268*219b2ee8SDavid du Colombier 
269*219b2ee8SDavid du Colombier 	n = 0;
270*219b2ee8SDavid du Colombier 	if(ctlr && *ctlr)
271*219b2ee8SDavid du Colombier 		n = print("%s ", ctlr);
272*219b2ee8SDavid du Colombier 	print("%-*s", 20-n, item);
273*219b2ee8SDavid du Colombier }
274*219b2ee8SDavid du Colombier 
275*219b2ee8SDavid du Colombier void
276*219b2ee8SDavid du Colombier printreg(ulong data)
277*219b2ee8SDavid du Colombier {
278*219b2ee8SDavid du Colombier 	int width;
279*219b2ee8SDavid du Colombier 
280*219b2ee8SDavid du Colombier 	width = 3;
281*219b2ee8SDavid du Colombier 	if((curindex % 16) == 0 && curindex){
282*219b2ee8SDavid du Colombier 		print("\n");
283*219b2ee8SDavid du Colombier 		curindex = 0;
284*219b2ee8SDavid du Colombier 		width = 23;
285*219b2ee8SDavid du Colombier 	}
286*219b2ee8SDavid du Colombier 	if(curindex == 8)
287*219b2ee8SDavid du Colombier 		print(" -");
288*219b2ee8SDavid du Colombier 	print("%*.2X", width, data);
289*219b2ee8SDavid du Colombier 	curindex++;
290*219b2ee8SDavid du Colombier }
291*219b2ee8SDavid du Colombier 
292*219b2ee8SDavid du Colombier void
293*219b2ee8SDavid du Colombier verbose(char *format, ...)
294*219b2ee8SDavid du Colombier {
295*219b2ee8SDavid du Colombier 	char buf[512];
296*219b2ee8SDavid du Colombier 
297*219b2ee8SDavid du Colombier 	if(vflag){
298*219b2ee8SDavid du Colombier 		if(curindex){
299*219b2ee8SDavid du Colombier 			curindex = 0;
300*219b2ee8SDavid du Colombier 			print("\n");
301*219b2ee8SDavid du Colombier 		}
302*219b2ee8SDavid du Colombier 		doprint(buf, buf+sizeof(buf), format, (&format+1));
303*219b2ee8SDavid du Colombier 		print(buf);
304*219b2ee8SDavid du Colombier 	}
305*219b2ee8SDavid du Colombier }
306