5 #include "../port/lib.h"
10 #include "../port/error.h"
25 static Dirtab vgadir[] = {
26 ".", { Qdir, 0, QTDIR }, 0, 0550,
27 "vgactl", { Qvgactl, 0 }, 0, 0660,
28 "vgaovl", { Qvgaovl, 0 }, 0, 0660,
29 "vgaovlctl", { Qvgaovlctl, 0 }, 0, 0660,
48 static Cmdtab vgactlmsg[] = {
49 CMactualsize, "actualsize", 2,
50 CMdrawinit, "drawinit", 1,
51 CMhwaccel, "hwaccel", 2,
52 CMhwblank, "hwblank", 2,
54 CMlinear, "linear", 0,
55 CMpalettedepth, "palettedepth", 2,
56 CMpanning, "panning", 2,
58 CMtextmode, "textmode", 1,
60 CMsoftscreen, "softscreen", 2,
61 CMpcidev, "pcidev", 2,
70 /* reserve the 'standard' vga registers */
71 if(ioalloc(0x2b0, 0x2df-0x2b0+1, 0, "vga") < 0)
72 panic("vga ports already allocated");
73 if(ioalloc(0x3c0, 0x3da-0x3c0+1, 0, "vga") < 0)
74 panic("vga ports already allocated");
76 /* find graphics card pci device */
79 while((pci = pcimatch(pci, 0, 0)) != nil){
80 if(pci->ccrb == Pcibcdisp){
92 if(*spec && strcmp(spec, "0"))
94 return devattach('v', spec);
98 vgawalk(Chan* c, Chan *nc, char** name, int nname)
100 return devwalk(c, nc, name, nname, vgadir, nelem(vgadir), devgen);
104 vgastat(Chan* c, uchar* dp, int n)
106 return devstat(c, dp, n, vgadir, nelem(vgadir), devgen);
110 vgaopen(Chan* c, int omode)
113 static char *openctl = "openctl\n";
116 if ((ulong)c->qid.path == Qvgaovlctl) {
117 if (scr->dev && scr->dev->ovlctl)
118 scr->dev->ovlctl(scr, c, openctl, strlen(openctl));
122 return devopen(c, omode, vgadir, nelem(vgadir), devgen);
129 static char *closectl = "closectl\n";
132 if((ulong)c->qid.path == Qvgaovlctl)
133 if(scr->dev && scr->dev->ovlctl){
135 print("ovlctl error: %s\n", up->errstr);
138 scr->dev->ovlctl(scr, c, closectl, strlen(closectl));
144 vgaread(Chan* c, void* a, long n, vlong off)
151 switch((ulong)c->qid.path){
154 return devdirread(c, a, n, vgadir, nelem(vgadir), devgen);
159 s = smalloc(READSTR);
164 p = s, e = s+READSTR;
165 p = seprint(p, e, "type %s\n",
166 scr->dev != nil ? scr->dev->name : "cga");
167 if(scr->gscreen != nil) {
168 p = seprint(p, e, "size %dx%dx%d %s\n",
169 scr->gscreen->r.max.x, scr->gscreen->r.max.y,
170 scr->gscreen->depth, chantostr(chbuf, scr->gscreen->chan));
171 if(Dx(scr->gscreen->r) != Dx(physgscreenr)
172 || Dy(scr->gscreen->r) != Dy(physgscreenr))
173 p = seprint(p, e, "actualsize %dx%d\n",
174 physgscreenr.max.x, physgscreenr.max.y);
176 p = seprint(p, e, "hwgc %s\n",
177 scr->cur != nil ? scr->cur->name : "off");
178 p = seprint(p, e, "hwaccel %s\n", hwaccel ? "on" : "off");
179 p = seprint(p, e, "hwblank %s\n", hwblank ? "on" : "off");
180 p = seprint(p, e, "panning %s\n", panning ? "on" : "off");
181 p = seprint(p, e, "addr p %#p v %#p size %#ux\n",
182 scr->paddr, scr->vaddr, scr->apsize);
183 p = seprint(p, e, "softscreen %s\n", scr->softscreen ? "on" : "off");
185 n = readstr(offset, a, n, s);
204 static char Ebusy[] = "vga already configured";
205 static char Enoscreen[] = "set the screen size first";
210 int align, i, size, x, y, z;
216 extern VGAdev *vgadev[];
217 extern VGAcur *vgacur[];
220 ct = lookupcmd(cb, vgactlmsg, nelem(vgactlmsg));
223 if(scr->gscreen == nil)
225 if(strcmp(cb->f[1], "off") == 0){
228 if(scr->cur->disable)
229 scr->cur->disable(scr);
235 if(strcmp(cb->f[1], "soft") == 0){
238 if(scr->cur && scr->cur->disable)
239 scr->cur->disable(scr);
240 scr->cur = &swcursor;
242 scr->cur->enable(scr);
246 for(i = 0; vgacur[i]; i++){
247 if(strcmp(cb->f[1], vgacur[i]->name))
250 if(scr->cur && scr->cur->disable)
251 scr->cur->disable(scr);
252 scr->cur = vgacur[i];
254 scr->cur->enable(scr);
264 if((p = pcimatchtbdf(strtoul(cb->f[1], 0, 16))) != nil)
271 for(i = 0; vgadev[i]; i++){
272 if(strcmp(cb->f[1], vgadev[i]->name))
282 if(scr->dev->disable)
283 scr->dev->disable(scr);
285 scr->dev = vgadev[i];
287 scr->dev->enable(scr);
298 x = strtoul(cb->f[1], &p, 0);
301 y = strtoul(p, &p, 0);
304 z = strtoul(p, &p, 0);
305 if(badrect(Rect(0,0,x,y)))
308 if((chan = strtochan(chanstr)) == 0)
309 error("bad channel");
310 if(chantodepth(chan) != z)
311 error("depth, channel do not match");
314 if(screensize(x, y, z, chan))
320 if(scr->gscreen == nil)
322 x = strtoul(cb->f[1], &p, 0);
325 y = strtoul(p, nil, 0);
329 if(!rectinrect(r, scr->gscreen->r))
330 error("physical screen bigger than virtual");
337 x = strtoul(cb->f[1], &p, 0);
340 scr->palettedepth = x;
344 if(strcmp(cb->f[1], "on") == 0)
346 else if(strcmp(cb->f[1], "off") == 0)
350 if(scr->gscreen == nil)
353 x = scr->gscreen->r.max.x;
354 y = scr->gscreen->r.max.y;
355 z = scr->gscreen->depth;
356 chan = scr->gscreen->chan;
359 if(screensize(x, y, z, chan))
364 if(scr->gscreen == nil)
366 if(scr->dev && scr->dev->drawinit)
367 scr->dev->drawinit(scr);
368 hwblank = scr->blank != nil;
369 hwaccel = scr->fill != nil || scr->scroll != nil;
371 scr->gscreen->clipr = panning ? scr->gscreen->r : physgscreenr;
378 if(cb->nf!=2 && cb->nf!=3)
380 size = strtoul(cb->f[1], 0, 0);
384 align = strtoul(cb->f[2], 0, 0);
385 if(screenaperture(size, align) < 0)
386 error("not enough free address space");
390 if(strcmp(cb->f[1], "on") == 0){
392 error("set cursor first");
393 if(!scr->cur->doespanning)
394 error("panning not supported");
397 else if(strcmp(cb->f[1], "off") == 0){
401 if(scr->gscreen == nil)
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);