FreeBSD/Linux Kernel Cross Reference
sys/alphapc/devvga.c
1 /*
2 * VGA controller
3 */
4 #include "u.h"
5 #include "../port/lib.h"
6 #include "mem.h"
7 #include "dat.h"
8 #include "fns.h"
9 #include "io.h"
10 #include "../port/error.h"
11
12 #define Image IMAGE
13 #include <draw.h>
14 #include <memdraw.h>
15 #include <cursor.h>
16 #include "screen.h"
17
18 extern uchar *vgabios;
19
20 enum {
21 Qdir,
22 Qvgactl,
23 Qvgabios,
24 };
25
26 static Dirtab vgadir[] = {
27 ".", { Qdir, 0, QTDIR }, 0, 0550,
28 "vgactl", { Qvgactl, 0 }, 0, 0660,
29 "vgabios", { Qvgabios, 0 }, 0x10000, 0440,
30 };
31
32 static void
33 vgareset(void)
34 {
35 /* reserve the 'standard' vga registers */
36 if(ioalloc(0x2b0, 0x2df-0x2b0+1, 0, "vga") < 0)
37 panic("vga ports already allocated");
38 if(ioalloc(0x3c0, 0x3da-0x3c0+1, 0, "vga") < 0)
39 panic("vga ports already allocated");
40 conf.monitor = 1;
41 }
42
43 static Chan*
44 vgaattach(char* spec)
45 {
46 if(*spec && strcmp(spec, ""))
47 error(Eio);
48 return devattach('v', spec);
49 }
50
51 Walkqid*
52 vgawalk(Chan* c, Chan *nc, char** name, int nname)
53 {
54 return devwalk(c, nc, name, nname, vgadir, nelem(vgadir), devgen);
55 }
56
57 static int
58 vgastat(Chan* c, uchar* dp, int n)
59 {
60 return devstat(c, dp, n, vgadir, nelem(vgadir), devgen);
61 }
62
63 static Chan*
64 vgaopen(Chan* c, int omode)
65 {
66 return devopen(c, omode, vgadir, nelem(vgadir), devgen);
67 }
68
69 static void
70 vgaclose(Chan*)
71 {
72 }
73
74 static void
75 checkport(int start, int end)
76 {
77 /* standard vga regs are OK */
78 if(start >= 0x2b0 && end <= 0x2df+1)
79 return;
80 if(start >= 0x3c0 && end <= 0x3da+1)
81 return;
82
83 if(iounused(start, end))
84 return;
85 error(Eperm);
86 }
87
88 static long
89 vgaread(Chan* c, void* a, long n, vlong off)
90 {
91 int len;
92 char *p, *s;
93 VGAscr *scr;
94 ulong offset = off;
95 char chbuf[30];
96
97 switch((ulong)c->qid.path){
98
99 case Qdir:
100 return devdirread(c, a, n, vgadir, nelem(vgadir), devgen);
101
102 case Qvgactl:
103 scr = &vgascreen[0];
104
105 p = malloc(READSTR);
106 if(waserror()){
107 free(p);
108 nexterror();
109 }
110
111 len = 0;
112
113 if(scr->dev)
114 s = scr->dev->name;
115 else
116 s = "cga";
117 len += snprint(p+len, READSTR-len, "type %s\n", s);
118
119 if(scr->gscreen) {
120 len += snprint(p+len, READSTR-len, "size %dx%dx%d %s\n",
121 scr->gscreen->r.max.x, scr->gscreen->r.max.y,
122 scr->gscreen->depth, chantostr(chbuf, scr->gscreen->chan));
123
124 if(Dx(scr->gscreen->r) != Dx(physgscreenr)
125 || Dy(scr->gscreen->r) != Dy(physgscreenr))
126 len += snprint(p+len, READSTR-len, "actualsize %dx%d\n",
127 physgscreenr.max.x, physgscreenr.max.y);
128 }
129
130 len += snprint(p+len, READSTR-len, "blanktime %lud\n", blanktime);
131 len += snprint(p+len, READSTR-len, "hwaccel %s\n", hwaccel ? "on" : "off");
132 len += snprint(p+len, READSTR-len, "hwblank %s\n", hwblank ? "on" : "off");
133 snprint(p+len, READSTR-len, "addr 0x%lux\n", scr->paddr);
134 n = readstr(offset, a, n, p);
135 poperror();
136 free(p);
137
138 return n;
139
140 case Qvgabios:
141 if(vgabios == nil)
142 error(Egreg);
143 if(offset&0x80000000)
144 offset &= ~0x800E0000;
145 if(offset+n > 0x10000)
146 n = 0x10000-offset;
147 if(n < 0)
148 return 0;
149 memmove(a, vgabios+offset, n);
150 return n;
151
152 default:
153 error(Egreg);
154 break;
155 }
156
157 return 0;
158 }
159
160 static char Ebusy[] = "vga already configured";
161
162 static void
163 vgactl(char* a)
164 {
165 int align, i, n, size, x, y, z;
166 char *chanstr, *field[6], *p;
167 ulong chan;
168 VGAscr *scr;
169 extern VGAdev *vgadev[];
170 extern VGAcur *vgacur[];
171 Rectangle r;
172
173 n = tokenize(a, field, nelem(field));
174 if(n < 1)
175 error(Ebadarg);
176
177 scr = &vgascreen[0];
178 if(strcmp(field[0], "hwgc") == 0){
179 if(n < 2)
180 error(Ebadarg);
181
182 if(strcmp(field[1], "off") == 0){
183 lock(&cursor);
184 if(scr->cur){
185 if(scr->cur->disable)
186 scr->cur->disable(scr);
187 scr->cur = nil;
188 }
189 unlock(&cursor);
190 return;
191 }
192
193 for(i = 0; vgacur[i]; i++){
194 if(strcmp(field[1], vgacur[i]->name))
195 continue;
196 lock(&cursor);
197 if(scr->cur && scr->cur->disable)
198 scr->cur->disable(scr);
199 scr->cur = vgacur[i];
200 if(scr->cur->enable)
201 scr->cur->enable(scr);
202 unlock(&cursor);
203 return;
204 }
205 }
206 else if(strcmp(field[0], "type") == 0){
207 if(n < 2)
208 error(Ebadarg);
209
210 for(i = 0; vgadev[i]; i++){
211 if(strcmp(field[1], vgadev[i]->name))
212 continue;
213 if(scr->dev && scr->dev->disable)
214 scr->dev->disable(scr);
215 scr->dev = vgadev[i];
216 if(scr->dev->enable)
217 scr->dev->enable(scr);
218 return;
219 }
220 }
221 else if(strcmp(field[0], "size") == 0){
222 if(n < 3)
223 error(Ebadarg);
224 if(drawhasclients())
225 error(Ebusy);
226
227 x = strtoul(field[1], &p, 0);
228 if(x == 0 || x > 2048)
229 error(Ebadarg);
230 if(*p)
231 p++;
232
233 y = strtoul(p, &p, 0);
234 if(y == 0 || y > 2048)
235 error(Ebadarg);
236 if(*p)
237 p++;
238
239 z = strtoul(p, &p, 0);
240
241 chanstr = field[2];
242 if((chan = strtochan(chanstr)) == 0)
243 error("bad channel");
244
245 if(chantodepth(chan) != z)
246 error("depth, channel do not match");
247
248 cursoroff(1);
249 deletescreenimage();
250 if(screensize(x, y, z, chan))
251 error(Egreg);
252 vgascreenwin(scr);
253 cursoron(1);
254 return;
255 }
256 else if(strcmp(field[0], "actualsize") == 0){
257 if(scr->gscreen == nil)
258 error("set the screen size first");
259
260 if(n < 2)
261 error(Ebadarg);
262 x = strtoul(field[1], &p, 0);
263 if(x == 0 || x > 2048)
264 error(Ebadarg);
265 if(*p)
266 p++;
267
268 y = strtoul(p, nil, 0);
269 if(y == 0 || y > 2048)
270 error(Ebadarg);
271
272 if(x > scr->gscreen->r.max.x || y > scr->gscreen->r.max.y)
273 error("physical screen bigger than virtual");
274
275 r = Rect(0,0,x,y);
276 if(!eqrect(r, scr->gscreen->r)){
277 if(scr->cur == nil || scr->cur->doespanning == 0)
278 error("virtual screen not supported");
279 }
280
281 physgscreenr = r;
282 return;
283 }
284 else if(strcmp(field[0], "palettedepth") == 0){
285 if(n < 2)
286 error(Ebadarg);
287
288 x = strtoul(field[1], &p, 0);
289 if(x != 8 && x != 6)
290 error(Ebadarg);
291
292 scr->palettedepth = x;
293 return;
294 }
295 else if(strcmp(field[0], "drawinit") == 0){
296 if(scr && scr->dev && scr->dev->drawinit)
297 scr->dev->drawinit(scr);
298 return;
299 }
300 else if(strcmp(field[0], "linear") == 0){
301 if(n < 2)
302 error(Ebadarg);
303
304 size = strtoul(field[1], 0, 0);
305 if(n < 3)
306 align = 0;
307 else
308 align = strtoul(field[2], 0, 0);
309 if(screenaperture(size, align))
310 error("not enough free address space");
311 return;
312 }
313 /* else if(strcmp(field[0], "memset") == 0){
314 if(n < 4)
315 error(Ebadarg);
316 memset((void*)strtoul(field[1], 0, 0), atoi(field[2]), atoi(field[3]));
317 return;
318 }
319 */
320 else if(strcmp(field[0], "blank") == 0){
321 if(n < 1)
322 error(Ebadarg);
323 drawblankscreen(1);
324 return;
325 }
326 else if(strcmp(field[0], "blanktime") == 0){
327 if(n < 2)
328 error(Ebadarg);
329 blanktime = strtoul(field[1], 0, 0);
330 return;
331 }
332 else if(strcmp(field[0], "hwaccel") == 0){
333 if(n < 2)
334 error(Ebadarg);
335 if(strcmp(field[1], "on") == 0)
336 hwaccel = 1;
337 else if(strcmp(field[1], "off") == 0)
338 hwaccel = 0;
339 return;
340 }
341 else if(strcmp(field[0], "hwblank") == 0){
342 if(n < 2)
343 error(Ebadarg);
344 if(strcmp(field[1], "on") == 0)
345 hwblank = 1;
346 else if(strcmp(field[1], "off") == 0)
347 hwblank = 0;
348 return;
349 }
350
351 error(Ebadarg);
352 }
353
354 static long
355 vgawrite(Chan* c, void* a, long n, vlong off)
356 {
357 char *p;
358 ulong offset = off;
359
360 switch((ulong)c->qid.path){
361
362 case Qdir:
363 error(Eperm);
364
365 case Qvgactl:
366 if(offset || n >= READSTR)
367 error(Ebadarg);
368 p = malloc(READSTR);
369 if(waserror()){
370 free(p);
371 nexterror();
372 }
373 memmove(p, a, n);
374 p[n] = 0;
375 vgactl(p);
376 poperror();
377 free(p);
378 return n;
379
380 default:
381 error(Egreg);
382 break;
383 }
384
385 return 0;
386 }
387
388 Dev vgadevtab = {
389 'v',
390 "vga",
391
392 vgareset,
393 devinit,
394 devshutdown,
395 vgaattach,
396 vgawalk,
397 vgastat,
398 vgaopen,
399 devcreate,
400 vgaclose,
401 vgaread,
402 devbread,
403 vgawrite,
404 devbwrite,
405 devremove,
406 devwstat,
407 };
Cache object: 656b79e5b202dfe2739095d51c2e2934
|