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