123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include "pci.h"
- #include "vga.h"
- Biobuf stdout;
- static int iflag, lflag, pflag, rflag;
- static char *dbname = "/lib/vgadb";
- static char monitordb[128];
- static void
- dump(Vga* vga)
- {
- Ctlr *ctlr;
- Attr *attr;
-
- if(vga->mode)
- dbdumpmode(vga->mode);
- for(attr = vga->attr; attr; attr = attr->next)
- Bprint(&stdout, "vga->attr: %s=%s\n", attr->attr, attr->val);
- for(ctlr = vga->link; ctlr; ctlr = ctlr->link){
- if(ctlr->dump == 0)
- continue;
- trace("%s->dump\n", ctlr->name);
- if(ctlr->flag && ctlr->flag != Fsnarf){
- printitem(ctlr->name, "flag");
- printflag(ctlr->flag);
- Bprint(&stdout, "\n");
- }
- (*ctlr->dump)(vga, ctlr);
- ctlr->flag |= Fdump;
- }
- Bprint(&stdout, "\n");
- }
- void
- resyncinit(Vga* vga, Ctlr* ctlr, ulong on, ulong off)
- {
- Ctlr *link;
- trace("%s->resyncinit on 0x%8.8luX off 0x%8.8luX\n",
- ctlr->name, on, off);
- for(link = vga->link; link; link = link->link){
- link->flag |= on;
- link->flag &= ~off;
- if(link == ctlr)
- continue;
- if(link->init == 0 || (link->flag & Finit) == 0)
- continue;
- link->flag &= ~Finit;
- trace("%s->init 0x%8.8luX\n", link->name, link->flag);
- (*link->init)(vga, link);
- }
- }
- void
- sequencer(Vga* vga, int on)
- {
- static uchar seq01;
- static int state = 1;
- char *s;
- if(on)
- s = "on";
- else
- s = "off";
- trace("sequencer->enter %s\n", s);
- if(on){
- if(vga)
- seq01 = vga->sequencer[0x01];
- if(state == 0){
- seq01 |= 0x01;
- vgaxo(Seqx, 0x01, seq01);
- vgaxo(Seqx, 0x00, 0x03);
- }
- }
- else{
- vgaxo(Seqx, 0x00, 0x01);
- seq01 = vgaxi(Seqx, 0x01);
- vgaxo(Seqx, 0x01, seq01|0x20);
- }
- state = on;
- trace("sequencer->leave %s\n", s);
- }
- static void
- linear(Vga* vga)
- {
- char buf[256];
- char *p;
- /*
- * Set up for linear addressing: try to allocate the
- * kernel memory map then read the base-address back.
- * vga->linear is a compatibility hack.
- */
- if(vga->linear == 0){
- vga->ctlr->flag &= ~Ulinear;
- return;
- }
- if(vga->ctlr->flag & Ulinear){
- /*
- * If there's already an aperture don't bother trying
- * to set up a new one.
- */
- vgactlr("addr", buf);
- if(atoi(buf)==0 && (buf[0]!='p' || buf[1]!=' ' || atoi(buf+2)==0)){
- sprint(buf, "0x%lux 0x%lux", vga->apz ? vga->apz : vga->vmz, vga->vma);
- vgactlw("linear", buf);
- vgactlr("addr", buf);
- }
- trace("linear->addr %s\n", buf);
- /*
- * old: addr 0x12345678
- * new: addr p 0x12345678 v 0x82345678 size 0x123
- */
- if(buf[0]=='p' && buf[1]==' '){
- vga->vmb = strtoul(buf+2, 0, 0);
- p = strstr(buf, "size");
- if(p)
- vga->apz = strtoul(p+4, 0, 0);
- }else
- vga->vmb = strtoul(buf, 0, 0);
- }
- else
- vgactlw("linear", "0");
- }
- char*
- chanstr[32+1] = {
- [1] "k1",
- [2] "k2",
- [4] "k4",
- [8] "m8",
- [16] "r5g6b5",
- [24] "r8g8b8",
- [32] "x8r8g8b8",
- };
- static void
- usage(void)
- {
- fprint(2, "usage: aux/vga [ -BcdilpvV ] [ -b bios-id ] [ -m monitor ] [ -x db ] [ mode [ virtualsize ] ]\n");
- exits("usage");
- }
- void
- main(int argc, char** argv)
- {
- char *bios, buf[256], sizeb[256], *p, *vsize, *psize;
- char *type, *vtype;
- int fd, virtual, len;
- Ctlr *ctlr;
- Vga *vga;
- fmtinstall('H', encodefmt);
- Binit(&stdout, 1, OWRITE);
- bios = getenv("vgactlr");
- if((type = getenv("monitor")) == 0)
- type = "vga";
- psize = vsize = "640x480x8";
- ARGBEGIN{
- default:
- usage();
- break;
- case 'b':
- bios = EARGF(usage());
- break;
- case 'B':
- dumpbios(0x10000);
- exits(0);
- case 'c':
- cflag = 1;
- break;
- case 'd':
- dflag = 1;
- break;
- case 'i':
- iflag = 1;
- break;
- case 'l':
- lflag = 1;
- break;
- case 'm':
- type = EARGF(usage());
- break;
- case 'p':
- pflag = 1;
- break;
- case 'r':
- /*
- * rflag > 1 means "leave me alone, I know what I'm doing."
- */
- rflag++;
- break;
- case 'v':
- vflag = 1;
- break;
- case 'V':
- vflag = 1;
- Vflag = 1;
- break;
- case 'x':
- dbname = EARGF(usage());
- break;
- }ARGEND
- virtual = 0;
- switch(argc){
- default:
- usage();
- break;
- case 1:
- vsize = psize = argv[0];
- break;
- case 2:
- psize = argv[0];
- vsize = argv[1];
- virtual = 1;
- break;
- case 0:
- break;
- }
- if(lflag && strcmp(vsize, "text") == 0){
- vesatextmode();
- vgactlw("textmode", "");
- exits(0);
- }
- vga = alloc(sizeof(Vga));
- if(bios){
- if((vga->offset = strtol(bios, &p, 0)) == 0 || *p++ != '=')
- error("main: bad BIOS string format - %s\n", bios);
- len = strlen(p);
- vga->bios = alloc(len+1);
- strncpy(vga->bios, p, len);
- trace("main->BIOS %s\n", bios);
- }
- /*
- * Try to identify the VGA card and grab
- * registers. Print them out if requested.
- */
- if(strcmp(type, "vesa") == 0
- || dbctlr(dbname, vga) == 0 || vga->ctlr == 0)
- if(dbvesa(vga) == 0 || vga->ctlr == 0){
- Bprint(&stdout, "%s: controller not in %s, not vesa\n", argv0, dbname);
- dumpbios(256);
- type = "vga";
- vsize = psize = "640x480x1";
- virtual = 0;
- vga->ctlr = &generic;
- vga->link = &generic;
- }
- trace("main->snarf\n");
- for(ctlr = vga->link; ctlr; ctlr = ctlr->link){
- if(ctlr->snarf == 0)
- continue;
- trace("%s->snarf\n", ctlr->name);
- (*ctlr->snarf)(vga, ctlr);
- }
- if(pflag)
- dump(vga);
- for(ctlr = vga->link; ctlr; ctlr = ctlr->link)
- if(ctlr->flag & Ferror)
- error("%r");
- if(iflag || lflag){
- if(getenv(type))
- snprint(monitordb, sizeof monitordb, "/env/%s", type);
- else
- strecpy(monitordb, monitordb+sizeof monitordb, dbname);
- if(vga->vesa){
- strcpy(monitordb, "vesa bios");
- vga->mode = dbvesamode(psize);
- }else
- vga->mode = dbmode(monitordb, type, psize);
- if(vga->mode == 0)
- error("main: %s@%s not in %s\n", type, psize, monitordb);
- if(virtual){
- if((p = strchr(vsize, 'x')) == nil)
- error("bad virtual size %s\n", vsize);
- vga->virtx = atoi(vsize);
- vga->virty = atoi(p+1);
- if(vga->virtx < vga->mode->x || vga->virty < vga->mode->y)
- error("virtual size smaller than physical size\n");
- vga->panning = 1;
- }
- else{
- vga->virtx = vga->mode->x;
- vga->virty = vga->mode->y;
- vga->panning = 0;
- }
- trace("vmf %d vmdf %d vf1 %lud vbw %lud\n",
- vga->mode->frequency, vga->mode->deffrequency,
- vga->f[1], vga->mode->videobw);
- if(vga->mode->frequency == 0 && vga->mode->videobw != 0 && vga->f[1] != 0){
- /*
- * boost clock as much as possible subject
- * to video and memory bandwidth constraints
- */
- ulong bytes, freq, membw;
- double rr;
- freq = vga->mode->videobw;
- if(freq > vga->f[1])
- freq = vga->f[1];
- rr = (double)freq/(vga->mode->ht*vga->mode->vt);
- if(rr > 85.0) /* >85Hz is ridiculous */
- rr = 85.0;
- bytes = (vga->mode->x*vga->mode->y*vga->mode->z)/8;
- membw = rr*bytes;
- if(vga->membw != 0 && membw > vga->membw){
- membw = vga->membw;
- rr = (double)membw/bytes;
- }
- freq = rr*(vga->mode->ht*vga->mode->vt);
- vga->mode->frequency = freq;
- trace("using frequency %lud rr %.2f membw %lud\n",
- freq, rr, membw);
- }
- else if(vga->mode->frequency == 0)
- vga->mode->frequency = vga->mode->deffrequency;
- for(ctlr = vga->link; ctlr; ctlr = ctlr->link){
- if(ctlr->options == 0)
- continue;
- trace("%s->options\n", ctlr->name);
- (*ctlr->options)(vga, ctlr);
- }
- /*
- * skip init for vesa - vesa will do the registers for us
- */
- if(!vga->vesa)
- for(ctlr = vga->link; ctlr; ctlr = ctlr->link){
- if(ctlr->init == 0)
- continue;
- trace("%s->init\n", ctlr->name);
- (*ctlr->init)(vga, ctlr);
- }
- if(strcmp(vga->mode->chan, "") == 0){
- if(vga->mode->z < nelem(chanstr) && chanstr[vga->mode->z])
- strcpy(vga->mode->chan, chanstr[vga->mode->z]);
- else
- error("%s: unknown channel type to use for depth %d", vga->ctlr->name, vga->mode->z);
- }
- if(iflag || pflag)
- dump(vga);
- if(lflag){
- trace("main->load\n");
- if(vga->vmz && (vga->virtx*vga->virty*vga->mode->z)/8 > vga->vmz)
- error("%s: not enough video memory - %lud\n",
- vga->ctlr->name, vga->vmz);
- if(vga->ctlr->type)
- vtype = vga->ctlr->type;
- else if(p = strchr(vga->ctlr->name, '-')){
- strncpy(buf, vga->ctlr->name, p - vga->ctlr->name);
- buf[p - vga->ctlr->name] = 0;
- vtype = buf;
- }
- else
- vtype = vga->ctlr->name;
- vgactlw("type", vtype);
- /*
- * VESA must be set up before linear.
- * Set type to vesa for linear.
- */
- if(vga->vesa){
- vesa.load(vga, vga->vesa);
- if(vga->vesa->flag&Ferror)
- error("vesa load error\n");
- vgactlw("type", vesa.name);
- }
- /*
- * The new draw device needs linear mode set
- * before size.
- */
- linear(vga);
- /*
- * Linear is over so switch to other driver for
- * acceleration.
- */
- if(vga->vesa)
- vgactlw("type", vtype);
- sprint(buf, "%ludx%ludx%d %s",
- vga->virtx, vga->virty,
- vga->mode->z, vga->mode->chan);
- if(rflag){
- vgactlr("size", sizeb);
- if(rflag < 2 && strcmp(buf, sizeb) != 0)
- error("bad refresh: %s != %s\n",
- buf, sizeb);
- }
- else
- vgactlw("size", buf);
- /*
- * No fiddling with registers if VESA set
- * things up already. Sorry.
- */
- if(!vga->vesa){
- /*
- * Turn off the display during the load.
- */
- sequencer(vga, 0);
-
- for(ctlr = vga->link; ctlr; ctlr = ctlr->link){
- if(ctlr->load == 0 || ctlr == &vesa)
- continue;
- trace("%s->load\n", ctlr->name);
- (*ctlr->load)(vga, ctlr);
- }
-
- sequencer(vga, 1);
- }
- vgactlw("drawinit", "");
- if(vga->hwgc == 0 || cflag)
- vgactlw("hwgc", "soft");
- else
- vgactlw("hwgc", vga->hwgc->name);
- /* might as well initialize the cursor */
- if((fd = open("/dev/cursor", OWRITE)) >= 0){
- write(fd, buf, 0);
- close(fd);
- }
- if(vga->virtx != vga->mode->x || vga->virty != vga->mode->y){
- sprint(buf, "%dx%d", vga->mode->x, vga->mode->y);
- vgactlw("actualsize", buf);
- if(vga->panning)
- vgactlw("panning", "on");
- }
- if(pflag)
- dump(vga);
- }
- }
- trace("main->exits\n");
- exits(0);
- }
|