| plan 9 kernel history: overview | file list | diff list |
2000/0522/pc/devvga.c (diff list | history)
| pc/devvga.c on 1995/0406 | ||
| 1995/0406 | /* | |
| 2000/0326 | * VGA controller | |
| 1995/0406 | */ | |
| 1997/1101 | #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" | |
| 1995/0406 | ||
| 1997/1101 | #define Image IMAGE #include <draw.h> #include <memdraw.h> | |
| 1999/0119 | #include <cursor.h> | |
| 1997/1101 | #include "screen.h" | |
| 1995/0406 | ||
| 1997/1101 | enum { Qdir, Qvgactl, | |
| 1994/0624 | }; | |
| 1997/1101 | static Dirtab vgadir[] = { "vgactl", { Qvgactl, 0 }, 0, 0660, | |
| 1992/1119 | }; | |
| 1992/0527 | ||
| 1997/0327 | static void | |
| 1992/1119 | vgareset(void) { | |
| 1999/0714 | /* reserve the 'standard' vga registers */ if(ioalloc(0x2b0, 0x2df-0x2b0+1, 0, "vga") < 0) panic("vga ports already allocated"); if(ioalloc(0x3c0, 0x3da-0x3c0+1, 0, "vga") < 0) panic("vga ports already allocated"); | |
| 1997/0327 | conf.monitor = 1; | |
| 1992/0527 | } | |
| 1997/0327 | static Chan* | |
| 1997/1101 | vgaattach(char* spec) | |
| 1992/0527 | { | |
| 1997/0327 | if(*spec && strcmp(spec, "0")) error(Eio); return devattach('v', spec); | |
| 1992/0527 | } int | |
| 1997/1101 | vgawalk(Chan* c, char* name) | |
| 1992/0527 | { | |
| 1997/0327 | return devwalk(c, name, vgadir, nelem(vgadir), devgen); | |
| 1992/0527 | } | |
| 1997/0327 | static void | |
| 1997/1101 | vgastat(Chan* c, char* dp) | |
| 1992/0527 | { | |
| 1997/0327 | devstat(c, dp, vgadir, nelem(vgadir), devgen); | |
| 1992/0527 | } | |
| 1997/0327 | static Chan* | |
| 1997/1101 | vgaopen(Chan* c, int omode) | |
| 1992/0527 | { | |
| 1997/0327 | return devopen(c, omode, vgadir, nelem(vgadir), devgen); | |
| 1992/0527 | } | |
| 1997/0327 | static void | |
| 1996/0418 | vgaclose(Chan*) | |
| 1992/0527 | { } | |
| 1999/0714 | static void checkport(int start, int end) { /* standard vga regs are OK */ if(start >= 0x2b0 && end <= 0x2df+1) return; if(start >= 0x3c0 && end <= 0x3da+1) return; if(iounused(start, end)) return; error(Eperm); } | |
| 1997/0327 | static long | |
| 1998/0319 | vgaread(Chan* c, void* a, long n, vlong off) | |
| 1992/0527 | { | |
| 1999/1005 | int len; | |
| 1997/1101 | char *p, *s; VGAscr *scr; | |
| 1998/0319 | ulong offset = off; | |
| 2000/0330 | char chbuf[30]; | |
| 1992/0528 | ||
| 1997/1101 | switch(c->qid.path & ~CHDIR){ | |
| 1992/0527 | case Qdir: | |
| 1997/1101 | return devdirread(c, a, n, vgadir, nelem(vgadir), devgen); | |
| 1994/0624 | case Qvgactl: | |
| 1997/1101 | scr = &vgascreen[0]; p = malloc(READSTR); if(waserror()){ free(p); nexterror(); } | |
| 2000/0330 | len = 0; | |
| 1997/1101 | if(scr->dev) s = scr->dev->name; | |
| 1994/0624 | else | |
| 1997/1101 | s = "cga"; | |
| 2000/0330 | len += snprint(p+len, READSTR-len, "type %s\n", s); if(scr->gscreen) { len += snprint(p+len, READSTR-len, "size %dx%dx%d %s\n", | |
| 1997/1101 | scr->gscreen->r.max.x, scr->gscreen->r.max.y, | |
| 2000/0330 | scr->gscreen->depth, chantostr(chbuf, scr->gscreen->chan)); | |
| 1997/1101 | ||
| 2000/0330 | if(Dx(scr->gscreen->r) != Dx(physgscreenr) || Dy(scr->gscreen->r) != Dy(physgscreenr)) len += snprint(p+len, READSTR-len, "actualsize %dx%d\n", physgscreenr.max.x, physgscreenr.max.y); } | |
| 2000/0522 | len += snprint(p+len, READSTR-len, "blanktime %lud\n", blanktime); | |
| 2000/0330 | len += snprint(p+len, READSTR-len, "hwaccel %s\n", hwaccel ? "on" : "off"); len += snprint(p+len, READSTR-len, "hwblank %s\n", hwblank ? "on" : "off"); snprint(p+len, READSTR-len, "addr 0x%lux\n", scr->aperture); | |
| 1997/1101 | n = readstr(offset, a, n, p); poperror(); free(p); return n; default: error(Egreg); break; | |
| 1992/0527 | } | |
| 1997/1101 | ||
| 1992/1119 | return 0; | |
| 1992/0527 | } | |
| 1999/1009 | static char Ebusy[] = "vga already configured"; | |
| 1994/0624 | static void | |
| 1997/1101 | vgactl(char* a) | |
| 1994/0624 | { | |
| 1997/1101 | int align, i, n, size, x, y, z; | |
| 1999/1005 | char *chanstr, *field[6], *p; ulong chan; | |
| 1997/1101 | VGAscr *scr; extern VGAdev *vgadev[]; extern VGAcur *vgacur[]; | |
| 1999/1005 | Rectangle r; | |
| 1994/0624 | ||
| 2000/0308 | n = getfields(a, field, nelem(field), 1, " "); | |
| 1999/1005 | if(n < 1) | |
| 1994/0624 | error(Ebadarg); | |
| 1997/1101 | scr = &vgascreen[0]; if(strcmp(field[0], "hwgc") == 0){ | |
| 1995/0406 | if(n < 2) error(Ebadarg); | |
| 1999/1005 | ||
| 1994/0624 | if(strcmp(field[1], "off") == 0){ | |
| 1997/1101 | lock(&cursor); if(scr->cur){ if(scr->cur->disable) scr->cur->disable(scr); scr->cur = nil; | |
| 1994/0624 | } | |
| 1997/1101 | unlock(&cursor); | |
| 1994/0624 | return; } | |
| 1997/1101 | for(i = 0; vgacur[i]; i++){ if(strcmp(field[1], vgacur[i]->name)) continue; lock(&cursor); if(scr->cur && scr->cur->disable) scr->cur->disable(scr); scr->cur = vgacur[i]; if(scr->cur->enable) scr->cur->enable(scr); unlock(&cursor); return; | |
| 1994/0624 | } } else if(strcmp(field[0], "type") == 0){ | |
| 1995/0406 | if(n < 2) error(Ebadarg); | |
| 1997/1101 | for(i = 0; vgadev[i]; i++){ if(strcmp(field[1], vgadev[i]->name)) continue; if(scr->dev && scr->dev->disable) scr->dev->disable(scr); scr->dev = vgadev[i]; if(scr->dev->enable) scr->dev->enable(scr); return; | |
| 1994/0624 | } } else if(strcmp(field[0], "size") == 0){ | |
| 1999/1005 | if(n < 3) | |
| 1995/0406 | error(Ebadarg); | |
| 1999/1009 | if(drawhasclients()) error(Ebusy); | |
| 1997/1101 | x = strtoul(field[1], &p, 0); | |
| 1995/0206 | if(x == 0 || x > 2048) | |
| 1994/0624 | error(Ebadarg); | |
| 1997/1101 | if(*p) p++; | |
| 1994/0624 | ||
| 1997/1101 | y = strtoul(p, &p, 0); | |
| 1997/0613 | if(y == 0 || y > 2048) | |
| 1994/0624 | error(Ebadarg); | |
| 1997/1101 | if(*p) p++; | |
| 1994/0624 | ||
| 1999/1005 | z = strtoul(p, &p, 0); | |
| 1997/1101 | ||
| 1999/1005 | chanstr = field[2]; if((chan = strtochan(chanstr)) == 0) error("bad channel"); | |
| 1994/0624 | ||
| 1999/1005 | if(chantodepth(chan) != z) error("depth, channel do not match"); | |
| 1995/0206 | cursoroff(1); | |
| 1999/1005 | deletescreenimage(); if(screensize(x, y, z, chan)) | |
| 1997/1101 | error(Egreg); vgascreenwin(scr); | |
| 1994/0624 | cursoron(1); return; } | |
| 1999/1005 | else if(strcmp(field[0], "actualsize") == 0){ if(scr->gscreen == nil) error("set the screen size first"); if(n < 2) error(Ebadarg); x = strtoul(field[1], &p, 0); if(x == 0 || x > 2048) error(Ebadarg); if(*p) p++; y = strtoul(p, nil, 0); if(y == 0 || y > 2048) error(Ebadarg); if(x > scr->gscreen->r.max.x || y > scr->gscreen->r.max.y) error("physical screen bigger than virtual"); r = Rect(0,0,x,y); if(!eqrect(r, scr->gscreen->r)){ if(scr->cur == nil || scr->cur->doespanning == 0) error("virtual screen not supported"); } physgscreenr = r; return; } else if(strcmp(field[0], "palettedepth") == 0){ if(n < 2) error(Ebadarg); x = strtoul(field[1], &p, 0); if(x != 8 && x != 6) error(Ebadarg); scr->palettedepth = x; return; } else if(strcmp(field[0], "drawinit") == 0){ if(scr && scr->dev && scr->dev->drawinit) scr->dev->drawinit(scr); return; } | |
| 1995/0406 | else if(strcmp(field[0], "linear") == 0){ if(n < 2) error(Ebadarg); | |
| 1997/1101 | ||
| 1996/0418 | size = strtoul(field[1], 0, 0); | |
| 1995/0406 | if(n < 3) | |
| 1996/0418 | align = 0; | |
| 1995/0406 | else | |
| 1996/0418 | align = strtoul(field[2], 0, 0); | |
| 1997/1101 | if(screenaperture(size, align)) | |
| 1995/0406 | error("not enough free address space"); return; } | |
| 1999/1005 | /* else if(strcmp(field[0], "memset") == 0){ if(n < 4) error(Ebadarg); memset((void*)strtoul(field[1], 0, 0), atoi(field[2]), atoi(field[3])); return; } */ else if(strcmp(field[0], "blank") == 0){ | |
| 2000/0330 | if(n < 1) | |
| 1999/1005 | error(Ebadarg); | |
| 2000/0330 | drawblankscreen(1); | |
| 1999/1005 | return; | |
| 2000/0522 | } else if(strcmp(field[0], "blanktime") == 0){ if(n < 2) error(Ebadarg); blanktime = strtoul(field[1], 0, 0); | |
| 1999/1005 | } | |
| 1999/1006 | else if(strcmp(field[0], "hwaccel") == 0){ if(n < 2) error(Ebadarg); if(strcmp(field[1], "on") == 0) hwaccel = 1; else if(strcmp(field[1], "off") == 0) hwaccel = 0; | |
| 2000/0326 | return; } else if(strcmp(field[0], "hwblank") == 0){ if(n < 2) error(Ebadarg); if(strcmp(field[1], "on") == 0) hwblank = 1; else if(strcmp(field[1], "off") == 0) hwblank = 0; | |
| 1999/1005 | return; } | |
| 1995/0406 | ||
| 1994/0624 | error(Ebadarg); } | |
| 1997/0327 | static long | |
| 1998/0319 | vgawrite(Chan* c, void* a, long n, vlong off) | |
| 1992/0527 | { | |
| 1997/1101 | char *p; | |
| 1998/0319 | ulong offset = off; | |
| 1992/0528 | ||
| 1997/1101 | switch(c->qid.path & ~CHDIR){ | |
| 1992/0527 | case Qdir: error(Eperm); | |
| 1997/1101 | ||
| 1994/0503 | case Qvgactl: | |
| 1997/1101 | if(offset || n >= READSTR) | |
| 1994/0503 | error(Ebadarg); | |
| 1997/1101 | p = malloc(READSTR); if(waserror()){ free(p); nexterror(); } memmove(p, a, n); p[n] = 0; vgactl(p); poperror(); free(p); | |
| 1992/0603 | return n; | |
| 1997/1101 | default: error(Egreg); break; | |
| 1992/0527 | } | |
| 1997/1101 | ||
| 1992/1119 | return 0; | |
| 1995/0108 | } | |
| 1997/0327 | Dev vgadevtab = { | |
| 1997/0408 | 'v', "vga", | |
| 1997/0327 | vgareset, | |
| 1997/1101 | devinit, | |
| 1997/0327 | vgaattach, devclone, vgawalk, vgastat, vgaopen, devcreate, vgaclose, vgaread, devbread, vgawrite, devbwrite, devremove, devwstat, }; | |