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){
95 if(scr->cur && scr->cur->disable)
96 scr->cur->disable(scr);
100 vgaattach(char* spec)
102 if(*spec && strcmp(spec, "0"))
104 return devattach('v', spec);
108 vgawalk(Chan* c, Chan *nc, char** name, int nname)
110 return devwalk(c, nc, name, nname, vgadir, nelem(vgadir), devgen);
114 vgastat(Chan* c, uchar* dp, int n)
116 return devstat(c, dp, n, vgadir, nelem(vgadir), devgen);
120 vgaopen(Chan* c, int omode)
123 static char *openctl = "openctl\n";
126 if ((ulong)c->qid.path == Qvgaovlctl) {
127 if (scr->dev && scr->dev->ovlctl)
128 scr->dev->ovlctl(scr, c, openctl, strlen(openctl));
132 return devopen(c, omode, vgadir, nelem(vgadir), devgen);
139 static char *closectl = "closectl\n";
142 if((ulong)c->qid.path == Qvgaovlctl)
143 if(scr->dev && scr->dev->ovlctl){
145 print("ovlctl error: %s\n", up->errstr);
148 scr->dev->ovlctl(scr, c, closectl, strlen(closectl));
154 vgaread(Chan* c, void* a, long n, vlong off)
161 switch((ulong)c->qid.path){
164 return devdirread(c, a, n, vgadir, nelem(vgadir), devgen);
169 s = smalloc(READSTR);
174 p = s, e = s+READSTR;
175 p = seprint(p, e, "type %s\n",
176 scr->dev != nil ? scr->dev->name : "cga");
177 if(scr->gscreen != nil) {
178 p = seprint(p, e, "size %dx%dx%d %s\n",
179 scr->gscreen->r.max.x, scr->gscreen->r.max.y,
180 scr->gscreen->depth, chantostr(chbuf, scr->gscreen->chan));
181 if(Dx(scr->gscreen->r) != Dx(physgscreenr)
182 || Dy(scr->gscreen->r) != Dy(physgscreenr))
183 p = seprint(p, e, "actualsize %dx%d\n",
184 physgscreenr.max.x, physgscreenr.max.y);
186 p = seprint(p, e, "hwgc %s\n",
187 scr->cur != nil ? scr->cur->name : "off");
188 p = seprint(p, e, "hwaccel %s\n", hwaccel ? "on" : "off");
189 p = seprint(p, e, "hwblank %s\n", hwblank ? "on" : "off");
190 p = seprint(p, e, "panning %s\n", panning ? "on" : "off");
191 p = seprint(p, e, "addr p %#p v %#p size %#ux\n",
192 scr->paddr, scr->vaddr, scr->apsize);
193 p = seprint(p, e, "softscreen %s\n", scr->softscreen ? "on" : "off");
195 n = readstr(offset, a, n, s);
214 static char Ebusy[] = "vga already configured";
215 static char Enoscreen[] = "set the screen size first";
220 int align, i, size, x, y, z;
226 extern VGAdev *vgadev[];
227 extern VGAcur *vgacur[];
230 ct = lookupcmd(cb, vgactlmsg, nelem(vgactlmsg));
233 if(scr->gscreen == nil)
235 if(strcmp(cb->f[1], "off") == 0){
239 if(scr->cur->disable)
240 scr->cur->disable(scr);
246 for(i = 0; vgacur[i]; i++){
247 if(strcmp(cb->f[1], vgacur[i]->name))
251 if(scr->cur && scr->cur->disable)
252 scr->cur->disable(scr);
253 scr->cur = vgacur[i];
255 scr->cur->enable(scr);
266 if((p = pcimatchtbdf(strtoul(cb->f[1], 0, 16))) != nil)
273 for(i = 0; vgadev[i]; i++){
274 if(strcmp(cb->f[1], vgadev[i]->name))
284 if(scr->dev->disable)
285 scr->dev->disable(scr);
287 scr->dev = vgadev[i];
289 scr->dev->enable(scr);
300 x = strtoul(cb->f[1], &p, 0);
303 y = strtoul(p, &p, 0);
306 z = strtoul(p, &p, 0);
307 if(badrect(Rect(0,0,x,y)))
310 if((chan = strtochan(chanstr)) == 0)
311 error("bad channel");
312 if(chantodepth(chan) != z)
313 error("depth, channel do not match");
315 if(screensize(x, y, z, chan))
321 if(scr->gscreen == nil)
323 x = strtoul(cb->f[1], &p, 0);
326 y = strtoul(p, nil, 0);
330 if(!rectinrect(r, scr->gscreen->r))
331 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;
358 if(screensize(x, y, z, chan))
363 if(scr->gscreen == nil)
365 if(scr->dev && scr->dev->drawinit)
366 scr->dev->drawinit(scr);
367 hwblank = scr->blank != nil;
368 hwaccel = scr->fill != nil || scr->scroll != nil;
370 scr->gscreen->clipr = panning ? scr->gscreen->r : physgscreenr;
376 if(cb->nf!=2 && cb->nf!=3)
378 size = strtoul(cb->f[1], 0, 0);
382 align = strtoul(cb->f[2], 0, 0);
383 if(screenaperture(size, align) < 0)
384 error("not enough free address space");
388 if(strcmp(cb->f[1], "on") == 0){
390 error("set cursor first");
391 if(!scr->cur->doespanning)
392 error("panning not supported");
395 else if(strcmp(cb->f[1], "off") == 0){
399 if(scr->gscreen == nil)
405 if(strcmp(cb->f[1], "on") == 0)
407 else if(strcmp(cb->f[1], "off") == 0)
414 if(strcmp(cb->f[1], "on") == 0)
416 else if(strcmp(cb->f[1], "off") == 0)
423 cmderror(cb, "bad VGA control message");
426 char Enooverlay[] = "No overlay support";
429 vgawrite(Chan* c, void* a, long n, vlong off)
435 switch((ulong)c->qid.path){
441 if(offset || n >= READSTR)
455 if (scr->dev == nil || scr->dev->ovlwrite == nil) {
459 return scr->dev->ovlwrite(scr, a, n, off);
463 if (scr->dev == nil || scr->dev->ovlctl == nil) {
467 scr->dev->ovlctl(scr, c, a, n);