17dd7cddfSDavid du Colombier /*
27dd7cddfSDavid du Colombier * VGA controller
37dd7cddfSDavid du Colombier */
4bd389b36SDavid du Colombier #include "u.h"
5bd389b36SDavid du Colombier #include "../port/lib.h"
6bd389b36SDavid du Colombier #include "mem.h"
7bd389b36SDavid du Colombier #include "dat.h"
8bd389b36SDavid du Colombier #include "fns.h"
94de34a7eSDavid du Colombier #include "io.h"
10bd389b36SDavid du Colombier #include "../port/error.h"
11bd389b36SDavid du Colombier
127dd7cddfSDavid du Colombier #define Image IMAGE
137dd7cddfSDavid du Colombier #include <draw.h>
147dd7cddfSDavid du Colombier #include <memdraw.h>
157dd7cddfSDavid du Colombier #include <cursor.h>
16bd389b36SDavid du Colombier #include "screen.h"
17bd389b36SDavid du Colombier
18219b2ee8SDavid du Colombier enum {
197dd7cddfSDavid du Colombier Qdir,
204de34a7eSDavid du Colombier Qvgabios,
217dd7cddfSDavid du Colombier Qvgactl,
229a747e4fSDavid du Colombier Qvgaovl,
239a747e4fSDavid du Colombier Qvgaovlctl,
24bd389b36SDavid du Colombier };
25bd389b36SDavid du Colombier
267dd7cddfSDavid du Colombier static Dirtab vgadir[] = {
279a747e4fSDavid du Colombier ".", { Qdir, 0, QTDIR }, 0, 0550,
284de34a7eSDavid du Colombier "vgabios", { Qvgabios, 0 }, 0x100000, 0440,
297dd7cddfSDavid du Colombier "vgactl", { Qvgactl, 0 }, 0, 0660,
309a747e4fSDavid du Colombier "vgaovl", { Qvgaovl, 0 }, 0, 0660,
319a747e4fSDavid du Colombier "vgaovlctl", { Qvgaovlctl, 0 }, 0, 0660,
329a747e4fSDavid du Colombier };
339a747e4fSDavid du Colombier
349a747e4fSDavid du Colombier enum {
359a747e4fSDavid du Colombier CMactualsize,
369a747e4fSDavid du Colombier CMblank,
379a747e4fSDavid du Colombier CMblanktime,
389a747e4fSDavid du Colombier CMdrawinit,
399a747e4fSDavid du Colombier CMhwaccel,
409a747e4fSDavid du Colombier CMhwblank,
419a747e4fSDavid du Colombier CMhwgc,
429a747e4fSDavid du Colombier CMlinear,
439a747e4fSDavid du Colombier CMpalettedepth,
449a747e4fSDavid du Colombier CMpanning,
459a747e4fSDavid du Colombier CMsize,
464de34a7eSDavid du Colombier CMtextmode,
479a747e4fSDavid du Colombier CMtype,
4839734e7eSDavid du Colombier CMunblank,
499a747e4fSDavid du Colombier };
509a747e4fSDavid du Colombier
519a747e4fSDavid du Colombier static Cmdtab vgactlmsg[] = {
529a747e4fSDavid du Colombier CMactualsize, "actualsize", 2,
539a747e4fSDavid du Colombier CMblank, "blank", 1,
549a747e4fSDavid du Colombier CMblanktime, "blanktime", 2,
559a747e4fSDavid du Colombier CMdrawinit, "drawinit", 1,
569a747e4fSDavid du Colombier CMhwaccel, "hwaccel", 2,
579a747e4fSDavid du Colombier CMhwblank, "hwblank", 2,
589a747e4fSDavid du Colombier CMhwgc, "hwgc", 2,
599a747e4fSDavid du Colombier CMlinear, "linear", 0,
609a747e4fSDavid du Colombier CMpalettedepth, "palettedepth", 2,
619a747e4fSDavid du Colombier CMpanning, "panning", 2,
629a747e4fSDavid du Colombier CMsize, "size", 3,
634de34a7eSDavid du Colombier CMtextmode, "textmode", 1,
649a747e4fSDavid du Colombier CMtype, "type", 2,
6539734e7eSDavid du Colombier CMunblank, "unblank", 1,
667dd7cddfSDavid du Colombier };
677dd7cddfSDavid du Colombier
687dd7cddfSDavid du Colombier static void
vgareset(void)69bd389b36SDavid du Colombier vgareset(void)
70bd389b36SDavid du Colombier {
717dd7cddfSDavid du Colombier /* reserve the 'standard' vga registers */
727dd7cddfSDavid du Colombier if(ioalloc(0x2b0, 0x2df-0x2b0+1, 0, "vga") < 0)
737dd7cddfSDavid du Colombier panic("vga ports already allocated");
747dd7cddfSDavid du Colombier if(ioalloc(0x3c0, 0x3da-0x3c0+1, 0, "vga") < 0)
757dd7cddfSDavid du Colombier panic("vga ports already allocated");
767dd7cddfSDavid du Colombier conf.monitor = 1;
77bd389b36SDavid du Colombier }
78bd389b36SDavid du Colombier
797dd7cddfSDavid du Colombier static Chan*
vgaattach(char * spec)807dd7cddfSDavid du Colombier vgaattach(char* spec)
81bd389b36SDavid du Colombier {
827dd7cddfSDavid du Colombier if(*spec && strcmp(spec, "0"))
837dd7cddfSDavid du Colombier error(Eio);
847dd7cddfSDavid du Colombier return devattach('v', spec);
85bd389b36SDavid du Colombier }
86bd389b36SDavid du Colombier
879a747e4fSDavid du Colombier Walkqid*
vgawalk(Chan * c,Chan * nc,char ** name,int nname)889a747e4fSDavid du Colombier vgawalk(Chan* c, Chan *nc, char** name, int nname)
89bd389b36SDavid du Colombier {
909a747e4fSDavid du Colombier return devwalk(c, nc, name, nname, vgadir, nelem(vgadir), devgen);
91bd389b36SDavid du Colombier }
92bd389b36SDavid du Colombier
939a747e4fSDavid du Colombier static int
vgastat(Chan * c,uchar * dp,int n)949a747e4fSDavid du Colombier vgastat(Chan* c, uchar* dp, int n)
95219b2ee8SDavid du Colombier {
969a747e4fSDavid du Colombier return devstat(c, dp, n, vgadir, nelem(vgadir), devgen);
977dd7cddfSDavid du Colombier }
98219b2ee8SDavid du Colombier
997dd7cddfSDavid du Colombier static Chan*
vgaopen(Chan * c,int omode)1007dd7cddfSDavid du Colombier vgaopen(Chan* c, int omode)
1017dd7cddfSDavid du Colombier {
1029a747e4fSDavid du Colombier VGAscr *scr;
1039a747e4fSDavid du Colombier static char *openctl = "openctl\n";
1049a747e4fSDavid du Colombier
1059a747e4fSDavid du Colombier scr = &vgascreen[0];
1069a747e4fSDavid du Colombier if ((ulong)c->qid.path == Qvgaovlctl) {
107b7b24591SDavid du Colombier if (scr->dev && scr->dev->ovlctl)
1089a747e4fSDavid du Colombier scr->dev->ovlctl(scr, c, openctl, strlen(openctl));
1099a747e4fSDavid du Colombier else
1109a747e4fSDavid du Colombier error(Enonexist);
1119a747e4fSDavid du Colombier }
1127dd7cddfSDavid du Colombier return devopen(c, omode, vgadir, nelem(vgadir), devgen);
1137dd7cddfSDavid du Colombier }
1147dd7cddfSDavid du Colombier
1157dd7cddfSDavid du Colombier static void
vgaclose(Chan * c)1169a747e4fSDavid du Colombier vgaclose(Chan* c)
1177dd7cddfSDavid du Colombier {
1189a747e4fSDavid du Colombier VGAscr *scr;
1199a747e4fSDavid du Colombier static char *closectl = "closectl\n";
1209a747e4fSDavid du Colombier
1219a747e4fSDavid du Colombier scr = &vgascreen[0];
1229a747e4fSDavid du Colombier if((ulong)c->qid.path == Qvgaovlctl)
123b7b24591SDavid du Colombier if(scr->dev && scr->dev->ovlctl){
1249a747e4fSDavid du Colombier if(waserror()){
1259a747e4fSDavid du Colombier print("ovlctl error: %s\n", up->errstr);
1269a747e4fSDavid du Colombier return;
1279a747e4fSDavid du Colombier }
1289a747e4fSDavid du Colombier scr->dev->ovlctl(scr, c, closectl, strlen(closectl));
1299a747e4fSDavid du Colombier poperror();
1309a747e4fSDavid du Colombier }
1317dd7cddfSDavid du Colombier }
1327dd7cddfSDavid du Colombier
1337dd7cddfSDavid du Colombier static void
checkport(int start,int end)1347dd7cddfSDavid du Colombier checkport(int start, int end)
1357dd7cddfSDavid du Colombier {
1367dd7cddfSDavid du Colombier /* standard vga regs are OK */
1377dd7cddfSDavid du Colombier if(start >= 0x2b0 && end <= 0x2df+1)
1387dd7cddfSDavid du Colombier return;
1397dd7cddfSDavid du Colombier if(start >= 0x3c0 && end <= 0x3da+1)
1407dd7cddfSDavid du Colombier return;
1417dd7cddfSDavid du Colombier
1427dd7cddfSDavid du Colombier if(iounused(start, end))
1437dd7cddfSDavid du Colombier return;
1447dd7cddfSDavid du Colombier error(Eperm);
1457dd7cddfSDavid du Colombier }
1467dd7cddfSDavid du Colombier
1477dd7cddfSDavid du Colombier static long
vgaread(Chan * c,void * a,long n,vlong off)1487dd7cddfSDavid du Colombier vgaread(Chan* c, void* a, long n, vlong off)
1497dd7cddfSDavid du Colombier {
1507dd7cddfSDavid du Colombier int len;
1517dd7cddfSDavid du Colombier char *p, *s;
1527dd7cddfSDavid du Colombier VGAscr *scr;
1537dd7cddfSDavid du Colombier ulong offset = off;
1547dd7cddfSDavid du Colombier char chbuf[30];
1557dd7cddfSDavid du Colombier
1569a747e4fSDavid du Colombier switch((ulong)c->qid.path){
1577dd7cddfSDavid du Colombier
1587dd7cddfSDavid du Colombier case Qdir:
1597dd7cddfSDavid du Colombier return devdirread(c, a, n, vgadir, nelem(vgadir), devgen);
1607dd7cddfSDavid du Colombier
1614de34a7eSDavid du Colombier case Qvgabios:
1624de34a7eSDavid du Colombier if(offset >= 0x100000)
1634de34a7eSDavid du Colombier return 0;
1644de34a7eSDavid du Colombier if(offset+n >= 0x100000)
1654de34a7eSDavid du Colombier n = 0x100000 - offset;
1664de34a7eSDavid du Colombier memmove(a, (uchar*)kaddr(0)+offset, n);
1674de34a7eSDavid du Colombier return n;
1684de34a7eSDavid du Colombier
1697dd7cddfSDavid du Colombier case Qvgactl:
1707dd7cddfSDavid du Colombier scr = &vgascreen[0];
1717dd7cddfSDavid du Colombier
1727dd7cddfSDavid du Colombier p = malloc(READSTR);
173*aa72973aSDavid du Colombier if(p == nil)
174*aa72973aSDavid du Colombier error(Enomem);
1757dd7cddfSDavid du Colombier if(waserror()){
1767dd7cddfSDavid du Colombier free(p);
1777dd7cddfSDavid du Colombier nexterror();
1787dd7cddfSDavid du Colombier }
1797dd7cddfSDavid du Colombier
1807dd7cddfSDavid du Colombier len = 0;
1817dd7cddfSDavid du Colombier
1827dd7cddfSDavid du Colombier if(scr->dev)
1837dd7cddfSDavid du Colombier s = scr->dev->name;
1847dd7cddfSDavid du Colombier else
1857dd7cddfSDavid du Colombier s = "cga";
1867dd7cddfSDavid du Colombier len += snprint(p+len, READSTR-len, "type %s\n", s);
1877dd7cddfSDavid du Colombier
1887dd7cddfSDavid du Colombier if(scr->gscreen) {
1897dd7cddfSDavid du Colombier len += snprint(p+len, READSTR-len, "size %dx%dx%d %s\n",
1907dd7cddfSDavid du Colombier scr->gscreen->r.max.x, scr->gscreen->r.max.y,
1917dd7cddfSDavid du Colombier scr->gscreen->depth, chantostr(chbuf, scr->gscreen->chan));
1927dd7cddfSDavid du Colombier
1937dd7cddfSDavid du Colombier if(Dx(scr->gscreen->r) != Dx(physgscreenr)
1947dd7cddfSDavid du Colombier || Dy(scr->gscreen->r) != Dy(physgscreenr))
1957dd7cddfSDavid du Colombier len += snprint(p+len, READSTR-len, "actualsize %dx%d\n",
1967dd7cddfSDavid du Colombier physgscreenr.max.x, physgscreenr.max.y);
1977dd7cddfSDavid du Colombier }
1987dd7cddfSDavid du Colombier
1996a9fc400SDavid du Colombier len += snprint(p+len, READSTR-len, "blank time %lud idle %d state %s\n",
2006a9fc400SDavid du Colombier blanktime, drawidletime(), scr->isblank ? "off" : "on");
2017dd7cddfSDavid du Colombier len += snprint(p+len, READSTR-len, "hwaccel %s\n", hwaccel ? "on" : "off");
2027dd7cddfSDavid du Colombier len += snprint(p+len, READSTR-len, "hwblank %s\n", hwblank ? "on" : "off");
2039a747e4fSDavid du Colombier len += snprint(p+len, READSTR-len, "panning %s\n", panning ? "on" : "off");
2044de34a7eSDavid du Colombier len += snprint(p+len, READSTR-len, "addr p 0x%lux v 0x%p size 0x%ux\n", scr->paddr, scr->vaddr, scr->apsize);
2054de34a7eSDavid du Colombier USED(len);
2064de34a7eSDavid du Colombier
2077dd7cddfSDavid du Colombier n = readstr(offset, a, n, p);
2087dd7cddfSDavid du Colombier poperror();
2097dd7cddfSDavid du Colombier free(p);
2107dd7cddfSDavid du Colombier
2117dd7cddfSDavid du Colombier return n;
2127dd7cddfSDavid du Colombier
2139a747e4fSDavid du Colombier case Qvgaovl:
2149a747e4fSDavid du Colombier case Qvgaovlctl:
2159a747e4fSDavid du Colombier error(Ebadusefd);
2169a747e4fSDavid du Colombier break;
2179a747e4fSDavid du Colombier
2187dd7cddfSDavid du Colombier default:
2197dd7cddfSDavid du Colombier error(Egreg);
2207dd7cddfSDavid du Colombier break;
2217dd7cddfSDavid du Colombier }
2227dd7cddfSDavid du Colombier
2237dd7cddfSDavid du Colombier return 0;
2247dd7cddfSDavid du Colombier }
2257dd7cddfSDavid du Colombier
2267dd7cddfSDavid du Colombier static char Ebusy[] = "vga already configured";
2277dd7cddfSDavid du Colombier
2287dd7cddfSDavid du Colombier static void
vgactl(Cmdbuf * cb)2299a747e4fSDavid du Colombier vgactl(Cmdbuf *cb)
2307dd7cddfSDavid du Colombier {
2319a747e4fSDavid du Colombier int align, i, size, x, y, z;
2329a747e4fSDavid du Colombier char *chanstr, *p;
2337dd7cddfSDavid du Colombier ulong chan;
2349a747e4fSDavid du Colombier Cmdtab *ct;
2357dd7cddfSDavid du Colombier VGAscr *scr;
2367dd7cddfSDavid du Colombier extern VGAdev *vgadev[];
2377dd7cddfSDavid du Colombier extern VGAcur *vgacur[];
238219b2ee8SDavid du Colombier
2397dd7cddfSDavid du Colombier scr = &vgascreen[0];
2409a747e4fSDavid du Colombier ct = lookupcmd(cb, vgactlmsg, nelem(vgactlmsg));
2419a747e4fSDavid du Colombier switch(ct->index){
2429a747e4fSDavid du Colombier case CMhwgc:
2439a747e4fSDavid du Colombier if(strcmp(cb->f[1], "off") == 0){
2447dd7cddfSDavid du Colombier lock(&cursor);
2457dd7cddfSDavid du Colombier if(scr->cur){
2467dd7cddfSDavid du Colombier if(scr->cur->disable)
2477dd7cddfSDavid du Colombier scr->cur->disable(scr);
2487dd7cddfSDavid du Colombier scr->cur = nil;
249219b2ee8SDavid du Colombier }
2507dd7cddfSDavid du Colombier unlock(&cursor);
251219b2ee8SDavid du Colombier return;
252219b2ee8SDavid du Colombier }
2534de34a7eSDavid du Colombier if(strcmp(cb->f[1], "soft") == 0){
2544de34a7eSDavid du Colombier lock(&cursor);
2554de34a7eSDavid du Colombier swcursorinit();
2564de34a7eSDavid du Colombier if(scr->cur && scr->cur->disable)
2574de34a7eSDavid du Colombier scr->cur->disable(scr);
2584de34a7eSDavid du Colombier scr->cur = &swcursor;
2594de34a7eSDavid du Colombier if(scr->cur->enable)
2604de34a7eSDavid du Colombier scr->cur->enable(scr);
2614de34a7eSDavid du Colombier unlock(&cursor);
2624de34a7eSDavid du Colombier return;
2634de34a7eSDavid du Colombier }
2647dd7cddfSDavid du Colombier for(i = 0; vgacur[i]; i++){
2659a747e4fSDavid du Colombier if(strcmp(cb->f[1], vgacur[i]->name))
2667dd7cddfSDavid du Colombier continue;
2677dd7cddfSDavid du Colombier lock(&cursor);
2687dd7cddfSDavid du Colombier if(scr->cur && scr->cur->disable)
2697dd7cddfSDavid du Colombier scr->cur->disable(scr);
2707dd7cddfSDavid du Colombier scr->cur = vgacur[i];
2717dd7cddfSDavid du Colombier if(scr->cur->enable)
2727dd7cddfSDavid du Colombier scr->cur->enable(scr);
2737dd7cddfSDavid du Colombier unlock(&cursor);
274219b2ee8SDavid du Colombier return;
275219b2ee8SDavid du Colombier }
2769a747e4fSDavid du Colombier break;
2777dd7cddfSDavid du Colombier
2789a747e4fSDavid du Colombier case CMtype:
2797dd7cddfSDavid du Colombier for(i = 0; vgadev[i]; i++){
2809a747e4fSDavid du Colombier if(strcmp(cb->f[1], vgadev[i]->name))
2817dd7cddfSDavid du Colombier continue;
2827dd7cddfSDavid du Colombier if(scr->dev && scr->dev->disable)
2837dd7cddfSDavid du Colombier scr->dev->disable(scr);
2847dd7cddfSDavid du Colombier scr->dev = vgadev[i];
2857dd7cddfSDavid du Colombier if(scr->dev->enable)
2867dd7cddfSDavid du Colombier scr->dev->enable(scr);
287219b2ee8SDavid du Colombier return;
288219b2ee8SDavid du Colombier }
2899a747e4fSDavid du Colombier break;
2909a747e4fSDavid du Colombier
2914de34a7eSDavid du Colombier case CMtextmode:
2924de34a7eSDavid du Colombier screeninit();
2934de34a7eSDavid du Colombier return;
2944de34a7eSDavid du Colombier
2959a747e4fSDavid du Colombier case CMsize:
2969a747e4fSDavid du Colombier x = strtoul(cb->f[1], &p, 0);
297868c5196SDavid du Colombier if(x == 0 || x > 10240)
298219b2ee8SDavid du Colombier error(Ebadarg);
2997dd7cddfSDavid du Colombier if(*p)
3007dd7cddfSDavid du Colombier p++;
301219b2ee8SDavid du Colombier
3027dd7cddfSDavid du Colombier y = strtoul(p, &p, 0);
303868c5196SDavid du Colombier if(y == 0 || y > 10240)
304219b2ee8SDavid du Colombier error(Ebadarg);
3057dd7cddfSDavid du Colombier if(*p)
3067dd7cddfSDavid du Colombier p++;
307219b2ee8SDavid du Colombier
3087dd7cddfSDavid du Colombier z = strtoul(p, &p, 0);
3097dd7cddfSDavid du Colombier
3109a747e4fSDavid du Colombier chanstr = cb->f[2];
3117dd7cddfSDavid du Colombier if((chan = strtochan(chanstr)) == 0)
3127dd7cddfSDavid du Colombier error("bad channel");
3137dd7cddfSDavid du Colombier
3147dd7cddfSDavid du Colombier if(chantodepth(chan) != z)
3157dd7cddfSDavid du Colombier error("depth, channel do not match");
316219b2ee8SDavid du Colombier
317219b2ee8SDavid du Colombier cursoroff(1);
3187dd7cddfSDavid du Colombier deletescreenimage();
3197dd7cddfSDavid du Colombier if(screensize(x, y, z, chan))
3207dd7cddfSDavid du Colombier error(Egreg);
3217dd7cddfSDavid du Colombier vgascreenwin(scr);
3224de34a7eSDavid du Colombier resetscreenimage();
323219b2ee8SDavid du Colombier cursoron(1);
324219b2ee8SDavid du Colombier return;
3259a747e4fSDavid du Colombier
3269a747e4fSDavid du Colombier case CMactualsize:
3277dd7cddfSDavid du Colombier if(scr->gscreen == nil)
3287dd7cddfSDavid du Colombier error("set the screen size first");
3297dd7cddfSDavid du Colombier
3309a747e4fSDavid du Colombier x = strtoul(cb->f[1], &p, 0);
3317dd7cddfSDavid du Colombier if(x == 0 || x > 2048)
3327dd7cddfSDavid du Colombier error(Ebadarg);
3337dd7cddfSDavid du Colombier if(*p)
3347dd7cddfSDavid du Colombier p++;
3357dd7cddfSDavid du Colombier
3367dd7cddfSDavid du Colombier y = strtoul(p, nil, 0);
3377dd7cddfSDavid du Colombier if(y == 0 || y > 2048)
3387dd7cddfSDavid du Colombier error(Ebadarg);
3397dd7cddfSDavid du Colombier
3407dd7cddfSDavid du Colombier if(x > scr->gscreen->r.max.x || y > scr->gscreen->r.max.y)
3417dd7cddfSDavid du Colombier error("physical screen bigger than virtual");
3427dd7cddfSDavid du Colombier
3439a747e4fSDavid du Colombier physgscreenr = Rect(0,0,x,y);
3449a747e4fSDavid du Colombier scr->gscreen->clipr = physgscreenr;
3457dd7cddfSDavid du Colombier return;
3467dd7cddfSDavid du Colombier
3479a747e4fSDavid du Colombier case CMpalettedepth:
3489a747e4fSDavid du Colombier x = strtoul(cb->f[1], &p, 0);
3497dd7cddfSDavid du Colombier if(x != 8 && x != 6)
3507dd7cddfSDavid du Colombier error(Ebadarg);
3517dd7cddfSDavid du Colombier
3527dd7cddfSDavid du Colombier scr->palettedepth = x;
3537dd7cddfSDavid du Colombier return;
3549a747e4fSDavid du Colombier
3559a747e4fSDavid du Colombier case CMdrawinit:
356cb8c047aSDavid du Colombier if(scr->gscreen == nil)
357cb8c047aSDavid du Colombier error("drawinit: no gscreen");
358cb8c047aSDavid du Colombier if(scr->dev && scr->dev->drawinit)
3597dd7cddfSDavid du Colombier scr->dev->drawinit(scr);
3607dd7cddfSDavid du Colombier return;
3617dd7cddfSDavid du Colombier
3629a747e4fSDavid du Colombier case CMlinear:
3639a747e4fSDavid du Colombier if(cb->nf!=2 && cb->nf!=3)
3649a747e4fSDavid du Colombier error(Ebadarg);
3659a747e4fSDavid du Colombier size = strtoul(cb->f[1], 0, 0);
3669a747e4fSDavid du Colombier if(cb->nf == 2)
3677dd7cddfSDavid du Colombier align = 0;
3687dd7cddfSDavid du Colombier else
3699a747e4fSDavid du Colombier align = strtoul(cb->f[2], 0, 0);
3704de34a7eSDavid du Colombier if(screenaperture(size, align) < 0)
3717dd7cddfSDavid du Colombier error("not enough free address space");
3727dd7cddfSDavid du Colombier return;
3739a747e4fSDavid du Colombier /*
3749a747e4fSDavid du Colombier case CMmemset:
3759a747e4fSDavid du Colombier memset((void*)strtoul(cb->f[1], 0, 0), atoi(cb->f[2]), atoi(cb->f[3]));
3767dd7cddfSDavid du Colombier return;
3777dd7cddfSDavid du Colombier */
3789a747e4fSDavid du Colombier
3799a747e4fSDavid du Colombier case CMblank:
3807dd7cddfSDavid du Colombier drawblankscreen(1);
3817dd7cddfSDavid du Colombier return;
3829a747e4fSDavid du Colombier
38339734e7eSDavid du Colombier case CMunblank:
38439734e7eSDavid du Colombier drawblankscreen(0);
38539734e7eSDavid du Colombier return;
38639734e7eSDavid du Colombier
3879a747e4fSDavid du Colombier case CMblanktime:
3889a747e4fSDavid du Colombier blanktime = strtoul(cb->f[1], 0, 0);
3897dd7cddfSDavid du Colombier return;
3909a747e4fSDavid du Colombier
3919a747e4fSDavid du Colombier case CMpanning:
3929a747e4fSDavid du Colombier if(strcmp(cb->f[1], "on") == 0){
3939a747e4fSDavid du Colombier if(scr == nil || scr->cur == nil)
3949a747e4fSDavid du Colombier error("set screen first");
3959a747e4fSDavid du Colombier if(!scr->cur->doespanning)
3969a747e4fSDavid du Colombier error("panning not supported");
3979a747e4fSDavid du Colombier scr->gscreen->clipr = scr->gscreen->r;
3989a747e4fSDavid du Colombier panning = 1;
3997dd7cddfSDavid du Colombier }
4009a747e4fSDavid du Colombier else if(strcmp(cb->f[1], "off") == 0){
4019a747e4fSDavid du Colombier scr->gscreen->clipr = physgscreenr;
4029a747e4fSDavid du Colombier panning = 0;
4039a747e4fSDavid du Colombier }else
4049a747e4fSDavid du Colombier break;
4059a747e4fSDavid du Colombier return;
4069a747e4fSDavid du Colombier
4079a747e4fSDavid du Colombier case CMhwaccel:
4089a747e4fSDavid du Colombier if(strcmp(cb->f[1], "on") == 0)
4097dd7cddfSDavid du Colombier hwaccel = 1;
4109a747e4fSDavid du Colombier else if(strcmp(cb->f[1], "off") == 0)
4117dd7cddfSDavid du Colombier hwaccel = 0;
4127dd7cddfSDavid du Colombier else
4139a747e4fSDavid du Colombier break;
4147dd7cddfSDavid du Colombier return;
4159a747e4fSDavid du Colombier
4169a747e4fSDavid du Colombier case CMhwblank:
4179a747e4fSDavid du Colombier if(strcmp(cb->f[1], "on") == 0)
4187dd7cddfSDavid du Colombier hwblank = 1;
4199a747e4fSDavid du Colombier else if(strcmp(cb->f[1], "off") == 0)
4207dd7cddfSDavid du Colombier hwblank = 0;
4217dd7cddfSDavid du Colombier else
4229a747e4fSDavid du Colombier break;
4237dd7cddfSDavid du Colombier return;
4247dd7cddfSDavid du Colombier }
425219b2ee8SDavid du Colombier
4269a747e4fSDavid du Colombier cmderror(cb, "bad VGA control message");
427219b2ee8SDavid du Colombier }
428219b2ee8SDavid du Colombier
4299a747e4fSDavid du Colombier char Enooverlay[] = "No overlay support";
4309a747e4fSDavid du Colombier
4317dd7cddfSDavid du Colombier static long
vgawrite(Chan * c,void * a,long n,vlong off)4327dd7cddfSDavid du Colombier vgawrite(Chan* c, void* a, long n, vlong off)
433bd389b36SDavid du Colombier {
4347dd7cddfSDavid du Colombier ulong offset = off;
4359a747e4fSDavid du Colombier Cmdbuf *cb;
4369a747e4fSDavid du Colombier VGAscr *scr;
437bd389b36SDavid du Colombier
4389a747e4fSDavid du Colombier switch((ulong)c->qid.path){
4397dd7cddfSDavid du Colombier
440bd389b36SDavid du Colombier case Qdir:
441bd389b36SDavid du Colombier error(Eperm);
4427dd7cddfSDavid du Colombier
443219b2ee8SDavid du Colombier case Qvgactl:
4447dd7cddfSDavid du Colombier if(offset || n >= READSTR)
445bd389b36SDavid du Colombier error(Ebadarg);
4469a747e4fSDavid du Colombier cb = parsecmd(a, n);
4477dd7cddfSDavid du Colombier if(waserror()){
4489a747e4fSDavid du Colombier free(cb);
4497dd7cddfSDavid du Colombier nexterror();
4507dd7cddfSDavid du Colombier }
4519a747e4fSDavid du Colombier vgactl(cb);
4527dd7cddfSDavid du Colombier poperror();
4539a747e4fSDavid du Colombier free(cb);
4549a747e4fSDavid du Colombier return n;
4559a747e4fSDavid du Colombier
4569a747e4fSDavid du Colombier case Qvgaovl:
4579a747e4fSDavid du Colombier scr = &vgascreen[0];
458b7b24591SDavid du Colombier if (scr->dev == nil || scr->dev->ovlwrite == nil) {
4599a747e4fSDavid du Colombier error(Enooverlay);
4609a747e4fSDavid du Colombier break;
4619a747e4fSDavid du Colombier }
4629a747e4fSDavid du Colombier return scr->dev->ovlwrite(scr, a, n, off);
4639a747e4fSDavid du Colombier
4649a747e4fSDavid du Colombier case Qvgaovlctl:
4659a747e4fSDavid du Colombier scr = &vgascreen[0];
466b7b24591SDavid du Colombier if (scr->dev == nil || scr->dev->ovlctl == nil) {
4679a747e4fSDavid du Colombier error(Enooverlay);
4689a747e4fSDavid du Colombier break;
4699a747e4fSDavid du Colombier }
4709a747e4fSDavid du Colombier scr->dev->ovlctl(scr, c, a, n);
471bd389b36SDavid du Colombier return n;
472219b2ee8SDavid du Colombier
473219b2ee8SDavid du Colombier default:
4747dd7cddfSDavid du Colombier error(Egreg);
475219b2ee8SDavid du Colombier break;
476219b2ee8SDavid du Colombier }
477219b2ee8SDavid du Colombier
478219b2ee8SDavid du Colombier return 0;
479219b2ee8SDavid du Colombier }
480219b2ee8SDavid du Colombier
4817dd7cddfSDavid du Colombier Dev vgadevtab = {
4827dd7cddfSDavid du Colombier 'v',
4837dd7cddfSDavid du Colombier "vga",
484bd389b36SDavid du Colombier
4857dd7cddfSDavid du Colombier vgareset,
4867dd7cddfSDavid du Colombier devinit,
4879a747e4fSDavid du Colombier devshutdown,
4887dd7cddfSDavid du Colombier vgaattach,
4897dd7cddfSDavid du Colombier vgawalk,
4907dd7cddfSDavid du Colombier vgastat,
4917dd7cddfSDavid du Colombier vgaopen,
4927dd7cddfSDavid du Colombier devcreate,
4937dd7cddfSDavid du Colombier vgaclose,
4947dd7cddfSDavid du Colombier vgaread,
4957dd7cddfSDavid du Colombier devbread,
4967dd7cddfSDavid du Colombier vgawrite,
4977dd7cddfSDavid du Colombier devbwrite,
4987dd7cddfSDavid du Colombier devremove,
4997dd7cddfSDavid du Colombier devwstat,
500bd389b36SDavid du Colombier };
501