5 #include "../port/lib.h"
10 #include "../port/error.h"
26 static Dirtab vgadir[] = {
27 ".", { Qdir, 0, QTDIR }, 0, 0550,
28 "vgabios", { Qvgabios, 0 }, 0x100000, 0440,
29 "vgactl", { Qvgactl, 0 }, 0, 0660,
30 "vgaovl", { Qvgaovl, 0 }, 0, 0660,
31 "vgaovlctl", { Qvgaovlctl, 0 }, 0, 0660,
51 static Cmdtab vgactlmsg[] = {
52 CMactualsize, "actualsize", 2,
54 CMblanktime, "blanktime", 2,
55 CMdrawinit, "drawinit", 1,
56 CMhwaccel, "hwaccel", 2,
57 CMhwblank, "hwblank", 2,
59 CMlinear, "linear", 0,
60 CMpalettedepth, "palettedepth", 2,
61 CMpanning, "panning", 2,
63 CMtextmode, "textmode", 1,
65 CMunblank, "unblank", 1,
71 /* reserve the 'standard' vga registers */
72 if(ioalloc(0x2b0, 0x2df-0x2b0+1, 0, "vga") < 0)
73 panic("vga ports already allocated");
74 if(ioalloc(0x3c0, 0x3da-0x3c0+1, 0, "vga") < 0)
75 panic("vga ports already allocated");
82 if(*spec && strcmp(spec, "0"))
84 return devattach('v', spec);
88 vgawalk(Chan* c, Chan *nc, char** name, int nname)
90 return devwalk(c, nc, name, nname, vgadir, nelem(vgadir), devgen);
94 vgastat(Chan* c, uchar* dp, int n)
96 return devstat(c, dp, n, vgadir, nelem(vgadir), devgen);
100 vgaopen(Chan* c, int omode)
103 static char *openctl = "openctl\n";
106 if ((ulong)c->qid.path == Qvgaovlctl) {
107 if (scr->dev && scr->dev->ovlctl)
108 scr->dev->ovlctl(scr, c, openctl, strlen(openctl));
112 return devopen(c, omode, vgadir, nelem(vgadir), devgen);
119 static char *closectl = "closectl\n";
122 if((ulong)c->qid.path == Qvgaovlctl)
123 if(scr->dev && scr->dev->ovlctl){
125 print("ovlctl error: %s\n", up->errstr);
128 scr->dev->ovlctl(scr, c, closectl, strlen(closectl));
134 checkport(int start, int end)
136 /* standard vga regs are OK */
137 if(start >= 0x2b0 && end <= 0x2df+1)
139 if(start >= 0x3c0 && end <= 0x3da+1)
142 if(iounused(start, end))
148 vgaread(Chan* c, void* a, long n, vlong off)
156 switch((ulong)c->qid.path){
159 return devdirread(c, a, n, vgadir, nelem(vgadir), devgen);
162 if(offset >= 0x100000)
164 if(offset+n >= 0x100000)
165 n = 0x100000 - offset;
166 memmove(a, (uchar*)kaddr(0)+offset, n);
184 len += snprint(p+len, READSTR-len, "type %s\n", s);
187 len += snprint(p+len, READSTR-len, "size %dx%dx%d %s\n",
188 scr->gscreen->r.max.x, scr->gscreen->r.max.y,
189 scr->gscreen->depth, chantostr(chbuf, scr->gscreen->chan));
191 if(Dx(scr->gscreen->r) != Dx(physgscreenr)
192 || Dy(scr->gscreen->r) != Dy(physgscreenr))
193 len += snprint(p+len, READSTR-len, "actualsize %dx%d\n",
194 physgscreenr.max.x, physgscreenr.max.y);
197 len += snprint(p+len, READSTR-len, "blank time %lud idle %d state %s\n",
198 blanktime, drawidletime(), scr->isblank ? "off" : "on");
199 len += snprint(p+len, READSTR-len, "hwaccel %s\n", hwaccel ? "on" : "off");
200 len += snprint(p+len, READSTR-len, "hwblank %s\n", hwblank ? "on" : "off");
201 len += snprint(p+len, READSTR-len, "panning %s\n", panning ? "on" : "off");
202 len += snprint(p+len, READSTR-len, "addr p 0x%lux v 0x%p size 0x%ux\n", scr->paddr, scr->vaddr, scr->apsize);
205 n = readstr(offset, a, n, p);
224 static char Ebusy[] = "vga already configured";
229 int align, i, size, x, y, z;
234 extern VGAdev *vgadev[];
235 extern VGAcur *vgacur[];
238 ct = lookupcmd(cb, vgactlmsg, nelem(vgactlmsg));
241 if(strcmp(cb->f[1], "off") == 0){
244 if(scr->cur->disable)
245 scr->cur->disable(scr);
251 if(strcmp(cb->f[1], "soft") == 0){
254 if(scr->cur && scr->cur->disable)
255 scr->cur->disable(scr);
256 scr->cur = &swcursor;
258 scr->cur->enable(scr);
262 for(i = 0; vgacur[i]; i++){
263 if(strcmp(cb->f[1], vgacur[i]->name))
266 if(scr->cur && scr->cur->disable)
267 scr->cur->disable(scr);
268 scr->cur = vgacur[i];
270 scr->cur->enable(scr);
277 for(i = 0; vgadev[i]; i++){
278 if(strcmp(cb->f[1], vgadev[i]->name))
281 if(scr->dev->disable)
282 scr->dev->disable(scr);
287 scr->dev = vgadev[i];
289 scr->dev->enable(scr);
299 x = strtoul(cb->f[1], &p, 0);
300 if(x == 0 || x > 10240)
305 y = strtoul(p, &p, 0);
306 if(y == 0 || y > 10240)
311 z = strtoul(p, &p, 0);
314 if((chan = strtochan(chanstr)) == 0)
315 error("bad channel");
317 if(chantodepth(chan) != z)
318 error("depth, channel do not match");
322 if(screensize(x, y, z, chan))
327 if(scr->gscreen == nil)
328 error("set the screen size first");
330 x = strtoul(cb->f[1], &p, 0);
331 if(x == 0 || x > 2048)
336 y = strtoul(p, nil, 0);
337 if(y == 0 || y > 2048)
340 if(x > scr->gscreen->r.max.x || y > scr->gscreen->r.max.y)
341 error("physical screen bigger than virtual");
343 physgscreenr = Rect(0,0,x,y);
344 scr->gscreen->clipr = physgscreenr;
348 x = strtoul(cb->f[1], &p, 0);
352 scr->palettedepth = x;
356 if(scr->gscreen == nil)
357 error("drawinit: no gscreen");
358 if(scr->dev && scr->dev->drawinit)
359 scr->dev->drawinit(scr);
360 hwblank = scr->blank != nil;
361 hwaccel = scr->scroll || scr->fill;
368 if(cb->nf!=2 && cb->nf!=3)
370 size = strtoul(cb->f[1], 0, 0);
374 align = strtoul(cb->f[2], 0, 0);
375 if(screenaperture(size, align) < 0)
376 error("not enough free address space");
388 blanktime = strtoul(cb->f[1], 0, 0);
392 if(strcmp(cb->f[1], "on") == 0){
393 if(scr == nil || scr->cur == nil)
394 error("set screen first");
395 if(!scr->cur->doespanning)
396 error("panning not supported");
397 scr->gscreen->clipr = scr->gscreen->r;
400 else if(strcmp(cb->f[1], "off") == 0){
401 scr->gscreen->clipr = physgscreenr;
408 if(strcmp(cb->f[1], "on") == 0)
410 else if(strcmp(cb->f[1], "off") == 0)
417 if(strcmp(cb->f[1], "on") == 0)
419 else if(strcmp(cb->f[1], "off") == 0)
426 cmderror(cb, "bad VGA control message");
429 char Enooverlay[] = "No overlay support";
432 vgawrite(Chan* c, void* a, long n, vlong off)
438 switch((ulong)c->qid.path){
444 if(offset || n >= READSTR)
458 if (scr->dev == nil || scr->dev->ovlwrite == nil) {
462 return scr->dev->ovlwrite(scr, a, n, off);
466 if (scr->dev == nil || scr->dev->ovlctl == nil) {
470 scr->dev->ovlctl(scr, c, a, n);