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,
53 static Cmdtab vgactlmsg[] = {
54 CMactualsize, "actualsize", 2,
56 CMblanktime, "blanktime", 2,
57 CMdrawinit, "drawinit", 1,
58 CMhwaccel, "hwaccel", 2,
59 CMhwblank, "hwblank", 2,
61 CMlinear, "linear", 0,
62 CMpalettedepth, "palettedepth", 2,
63 CMpanning, "panning", 2,
65 CMtextmode, "textmode", 1,
67 CMunblank, "unblank", 1,
68 CMsoftscreen, "softscreen", 2,
69 CMpcidev, "pcidev", 2,
78 /* reserve the 'standard' vga registers */
79 if(ioalloc(0x2b0, 0x2df-0x2b0+1, 0, "vga") < 0)
80 panic("vga ports already allocated");
81 if(ioalloc(0x3c0, 0x3da-0x3c0+1, 0, "vga") < 0)
82 panic("vga ports already allocated");
84 /* find graphics card pci device */
87 while((pci = pcimatch(pci, 0, 0)) != nil){
88 if(pci->ccrb == Pcibcdisp){
100 if(*spec && strcmp(spec, "0"))
102 return devattach('v', spec);
106 vgawalk(Chan* c, Chan *nc, char** name, int nname)
108 return devwalk(c, nc, name, nname, vgadir, nelem(vgadir), devgen);
112 vgastat(Chan* c, uchar* dp, int n)
114 return devstat(c, dp, n, vgadir, nelem(vgadir), devgen);
118 vgaopen(Chan* c, int omode)
121 static char *openctl = "openctl\n";
124 if ((ulong)c->qid.path == Qvgaovlctl) {
125 if (scr->dev && scr->dev->ovlctl)
126 scr->dev->ovlctl(scr, c, openctl, strlen(openctl));
130 return devopen(c, omode, vgadir, nelem(vgadir), devgen);
137 static char *closectl = "closectl\n";
140 if((ulong)c->qid.path == Qvgaovlctl)
141 if(scr->dev && scr->dev->ovlctl){
143 print("ovlctl error: %s\n", up->errstr);
146 scr->dev->ovlctl(scr, c, closectl, strlen(closectl));
152 checkport(int start, int end)
154 /* standard vga regs are OK */
155 if(start >= 0x2b0 && end <= 0x2df+1)
157 if(start >= 0x3c0 && end <= 0x3da+1)
160 if(iounused(start, end))
166 vgaread(Chan* c, void* a, long n, vlong off)
174 switch((ulong)c->qid.path){
177 return devdirread(c, a, n, vgadir, nelem(vgadir), devgen);
180 if(offset >= 0x100000)
182 if(offset+n >= 0x100000)
183 n = 0x100000 - offset;
184 memmove(a, (uchar*)kaddr(0)+offset, n);
190 p = smalloc(READSTR);
202 len += snprint(p+len, READSTR-len, "type %s\n", s);
205 len += snprint(p+len, READSTR-len, "size %dx%dx%d %s\n",
206 scr->gscreen->r.max.x, scr->gscreen->r.max.y,
207 scr->gscreen->depth, chantostr(chbuf, scr->gscreen->chan));
209 if(Dx(scr->gscreen->r) != Dx(physgscreenr)
210 || Dy(scr->gscreen->r) != Dy(physgscreenr))
211 len += snprint(p+len, READSTR-len, "actualsize %dx%d\n",
212 physgscreenr.max.x, physgscreenr.max.y);
215 len += snprint(p+len, READSTR-len, "blank time %lud idle %d state %s\n",
216 blanktime, drawidletime(), scr->isblank ? "off" : "on");
217 len += snprint(p+len, READSTR-len, "hwaccel %s\n", hwaccel ? "on" : "off");
218 len += snprint(p+len, READSTR-len, "hwblank %s\n", hwblank ? "on" : "off");
219 len += snprint(p+len, READSTR-len, "panning %s\n", panning ? "on" : "off");
220 len += snprint(p+len, READSTR-len, "addr p 0x%lux v 0x%p size 0x%ux\n", scr->paddr, scr->vaddr, scr->apsize);
221 len += snprint(p+len, READSTR-len, "softscreen %s\n", scr->softscreen ? "on" : "off");
224 n = readstr(offset, a, n, p);
243 static char Ebusy[] = "vga already configured";
248 int align, i, size, x, y, z;
253 extern VGAdev *vgadev[];
254 extern VGAcur *vgacur[];
257 ct = lookupcmd(cb, vgactlmsg, nelem(vgactlmsg));
260 if(scr->gscreen == nil)
261 error("hwgc: no gscreen");
263 if(strcmp(cb->f[1], "off") == 0){
266 if(scr->cur->disable)
267 scr->cur->disable(scr);
273 if(strcmp(cb->f[1], "soft") == 0){
276 if(scr->cur && scr->cur->disable)
277 scr->cur->disable(scr);
278 scr->cur = &swcursor;
280 scr->cur->enable(scr);
284 for(i = 0; vgacur[i]; i++){
285 if(strcmp(cb->f[1], vgacur[i]->name))
288 if(scr->cur && scr->cur->disable)
289 scr->cur->disable(scr);
290 scr->cur = vgacur[i];
292 scr->cur->enable(scr);
302 if((p = pcimatchtbdf(strtoul(cb->f[1], 0, 16))) != nil)
309 for(i = 0; vgadev[i]; i++){
310 if(strcmp(cb->f[1], vgadev[i]->name))
313 if(scr->dev->disable)
314 scr->dev->disable(scr);
319 scr->dev = vgadev[i];
321 scr->dev->enable(scr);
331 x = strtoul(cb->f[1], &p, 0);
332 if(x == 0 || x > 10240)
337 y = strtoul(p, &p, 0);
338 if(y == 0 || y > 10240)
343 z = strtoul(p, &p, 0);
346 if((chan = strtochan(chanstr)) == 0)
347 error("bad channel");
349 if(chantodepth(chan) != z)
350 error("depth, channel do not match");
354 if(screensize(x, y, z, chan))
359 if(scr->gscreen == nil)
360 error("set the screen size first");
362 x = strtoul(cb->f[1], &p, 0);
363 if(x == 0 || x > 2048)
368 y = strtoul(p, nil, 0);
369 if(y == 0 || y > 2048)
372 if(x > scr->gscreen->r.max.x || y > scr->gscreen->r.max.y)
373 error("physical screen bigger than virtual");
375 physgscreenr = Rect(0,0,x,y);
376 scr->gscreen->clipr = physgscreenr;
380 x = strtoul(cb->f[1], &p, 0);
384 scr->palettedepth = x;
388 if(strcmp(cb->f[1], "on") == 0)
390 else if(strcmp(cb->f[1], "off") == 0)
394 if(scr->gscreen == nil)
396 x = scr->gscreen->r.max.x;
397 y = scr->gscreen->r.max.y;
398 z = scr->gscreen->depth;
399 chan = scr->gscreen->chan;
402 if(screensize(x, y, z, chan))
406 if(scr->gscreen == nil)
407 error("drawinit: no gscreen");
408 if(scr->dev && scr->dev->drawinit)
409 scr->dev->drawinit(scr);
410 hwblank = scr->blank != nil;
411 hwaccel = !scr->softscreen && (scr->scroll || scr->fill);
418 if(cb->nf!=2 && cb->nf!=3)
420 size = strtoul(cb->f[1], 0, 0);
424 align = strtoul(cb->f[2], 0, 0);
425 if(screenaperture(size, align) < 0)
426 error("not enough free address space");
438 blanktime = strtoul(cb->f[1], 0, 0);
442 if(strcmp(cb->f[1], "on") == 0){
443 if(scr == nil || scr->cur == nil)
444 error("set screen first");
445 if(!scr->cur->doespanning)
446 error("panning not supported");
447 scr->gscreen->clipr = scr->gscreen->r;
450 else if(strcmp(cb->f[1], "off") == 0){
451 scr->gscreen->clipr = physgscreenr;
458 if(strcmp(cb->f[1], "on") == 0)
460 else if(strcmp(cb->f[1], "off") == 0)
467 if(strcmp(cb->f[1], "on") == 0)
469 else if(strcmp(cb->f[1], "off") == 0)
476 cmderror(cb, "bad VGA control message");
479 char Enooverlay[] = "No overlay support";
482 vgawrite(Chan* c, void* a, long n, vlong off)
488 switch((ulong)c->qid.path){
494 if(offset || n >= READSTR)
508 if (scr->dev == nil || scr->dev->ovlwrite == nil) {
512 return scr->dev->ovlwrite(scr, a, n, off);
516 if (scr->dev == nil || scr->dev->ovlctl == nil) {
520 scr->dev->ovlctl(scr, c, a, n);