10 static int iflag, lflag, pflag, rflag;
12 static char *dbname = "/lib/vgadb";
13 static char monitordb[128];
23 dbdumpmode(vga->mode);
25 for(attr = vga->attr; attr; attr = attr->next)
26 Bprint(&stdout, "vga->attr: %s=%s\n", attr->attr, attr->val);
28 for(ctlr = vga->link; ctlr; ctlr = ctlr->link){
32 trace("%s->dump\n", ctlr->name);
33 if(ctlr->flag && ctlr->flag != Fsnarf){
34 printitem(ctlr->name, "flag");
35 printflag(ctlr->flag);
36 Bprint(&stdout, "\n");
38 (*ctlr->dump)(vga, ctlr);
42 for(i=0; i < nelem(vga->edid); i++){
44 printedid(vga->edid[i]);
47 Bprint(&stdout, "\n");
51 resyncinit(Vga* vga, Ctlr* ctlr, ulong on, ulong off)
55 trace("%s->resyncinit on 0x%8.8luX off 0x%8.8luX\n",
58 for(link = vga->link; link; link = link->link){
64 if(link->init == 0 || (link->flag & Finit) == 0)
67 trace("%s->init 0x%8.8luX\n", link->name, link->flag);
68 (*link->init)(vga, link);
73 sequencer(Vga* vga, int on)
83 trace("sequencer->enter %s\n", s);
86 seq01 = vga->sequencer[0x01];
89 vgaxo(Seqx, 0x01, seq01);
90 vgaxo(Seqx, 0x00, 0x03);
94 vgaxo(Seqx, 0x00, 0x01);
95 seq01 = vgaxi(Seqx, 0x01);
96 vgaxo(Seqx, 0x01, seq01|0x20);
99 trace("sequencer->leave %s\n", s);
109 * Set up for linear addressing: try to allocate the
110 * kernel memory map then read the base-address back.
111 * vga->linear is a compatibility hack.
113 if(vga->linear == 0){
114 vga->ctlr->flag &= ~Ulinear;
117 if(vga->ctlr->flag & Ulinear){
119 * If there's already an aperture don't bother trying
120 * to set up a new one.
122 vgactlr("addr", buf);
123 if(atoi(buf)==0 && (buf[0]!='p' || buf[1]!=' ' || atoi(buf+2)==0)){
124 sprint(buf, "0x%lux 0x%lux", vga->apz ? vga->apz : vga->vmz, vga->vma);
125 vgactlw("linear", buf);
126 vgactlr("addr", buf);
128 trace("linear->addr %s\n", buf);
130 * old: addr 0x12345678
131 * new: addr p 0x12345678 v 0x82345678 size 0x123
133 if(buf[0]=='p' && buf[1]==' '){
134 vga->vmb = strtoul(buf+2, 0, 0);
135 p = strstr(buf, "size");
137 vga->apz = strtoul(p+4, 0, 0);
139 vga->vmb = strtoul(buf, 0, 0);
142 vgactlw("linear", "0");
146 dbedidmode(Vga *vga, char *type, char *size)
155 snprint(buf, sizeof(buf), "%s", size);
156 if((p = strchr(buf, 'x')) != nil){
160 if((p = strchr(p, 'x')) != nil){
166 for(i=0; i<nelem(vga->edid); i++){
167 if(vga->edid[i] == nil)
169 for(l = vga->edid[i]->modelist; l != nil; l = l->next)
170 if(strcmp(l->name, type) == 0)
173 for(i=0; i<nelem(vga->edid); i++){
174 if(vga->edid[i] == nil)
176 for(l = vga->edid[i]->modelist; l != nil; l = l->next)
177 if((x == 0 || l->x == x) && (y == 0 || l->y == y))
183 m = alloc(sizeof(Mode));
188 snprint(m->type, sizeof(m->type), "%s", type);
189 snprint(m->size, sizeof(m->size), "%dx%dx%d", x, y, z);
207 fprint(2, "usage: aux/vga [ -BcdilpvV ] [ -b bios-id ] [ -m monitor ] [ -x db ] [ mode [ virtualsize ] ]\n");
212 main(int argc, char** argv)
214 char *bios, buf[256], sizeb[256], *p, *vsize, *psize;
220 fmtinstall('H', encodefmt);
221 Binit(&stdout, 1, OWRITE);
223 bios = getenv("vgactlr");
224 if((type = getenv("monitor")) == 0)
226 psize = vsize = "640x480x8";
233 bios = EARGF(usage());
251 type = EARGF(usage());
258 * rflag > 1 means "leave me alone, I know what I'm doing."
270 dbname = EARGF(usage());
280 vsize = psize = argv[0];
291 if(lflag && strcmp(vsize, "text") == 0){
293 vgactlw("textmode", "");
297 vga = alloc(sizeof(Vga));
299 if((vga->offset = strtol(bios, &p, 0)) == 0 || *p++ != '=')
300 error("main: bad BIOS string format - %s\n", bios);
302 vga->bios = alloc(len+1);
303 strncpy(vga->bios, p, len);
304 trace("main->BIOS %s\n", bios);
308 * Try to identify the VGA card and grab
309 * registers. Print them out if requested.
310 * If monitor=vesa or our vga controller can't be found
311 * in vgadb, try vesa modes; failing that, try vga.
313 if(strcmp(type, "vesa") == 0 || dbctlr(dbname, vga) == 0 ||
315 if(dbvesa(vga) == 0 || vga->ctlr == 0){
316 Bprint(&stdout, "%s: controller not in %s, not vesa\n",
320 vsize = psize = "640x480x1";
322 vga->ctlr = &generic;
323 vga->link = &generic;
326 trace("main->snarf\n");
327 for(ctlr = vga->link; ctlr; ctlr = ctlr->link){
330 trace("%s->snarf\n", ctlr->name);
331 (*ctlr->snarf)(vga, ctlr);
337 for(ctlr = vga->link; ctlr; ctlr = ctlr->link)
338 if(ctlr->flag & Ferror)
343 snprint(monitordb, sizeof monitordb, "/env/%s", type);
345 strecpy(monitordb, monitordb+sizeof monitordb, dbname);
348 strcpy(monitordb, "vesa bios");
349 vga->mode = dbvesamode(vga, psize);
351 vga->mode = dbmode(monitordb, type, psize);
353 vga->mode = dbedidmode(vga, type, psize);
356 error("main: %s@%s not in %s\n", type, psize, monitordb);
359 * because vga programs shb/ehb (Crt02, Crt03) the same as
360 * shs/ehs (Crt04, Crt05), only shb/ehb is specified in vgadb
361 * meaning the horizontal sync pulse start and end position.
363 if(vga->mode->shs == 0)
364 vga->mode->shs = vga->mode->shb;
365 if(vga->mode->ehs == 0)
366 vga->mode->ehs = vga->mode->ehb;
369 if((p = strchr(vsize, 'x')) == nil)
370 error("bad virtual size %s\n", vsize);
371 vga->virtx = atoi(vsize);
372 vga->virty = atoi(p+1);
373 if(vga->virtx < vga->mode->x || vga->virty < vga->mode->y)
374 error("virtual size smaller than physical size\n");
378 vga->virtx = vga->mode->x;
379 vga->virty = vga->mode->y;
383 trace("vmf %d vmdf %d vf1 %lud vbw %lud\n",
384 vga->mode->frequency, vga->mode->deffrequency,
385 vga->f[1], vga->mode->videobw);
386 if(vga->mode->frequency == 0 && vga->mode->videobw != 0 && vga->f[1] != 0){
388 * boost clock as much as possible subject
389 * to video and memory bandwidth constraints
391 ulong bytes, freq, membw;
394 freq = vga->mode->videobw;
398 rr = (double)freq/(vga->mode->ht*vga->mode->vt);
399 if(rr > 85.0) /* >85Hz is ridiculous */
402 bytes = (vga->mode->x*vga->mode->y*vga->mode->z)/8;
404 if(vga->membw != 0 && membw > vga->membw){
406 rr = (double)membw/bytes;
409 freq = rr*(vga->mode->ht*vga->mode->vt);
410 vga->mode->frequency = freq;
412 trace("using frequency %lud rr %.2f membw %lud\n",
415 else if(vga->mode->frequency == 0)
416 vga->mode->frequency = vga->mode->deffrequency;
418 for(ctlr = vga->link; ctlr; ctlr = ctlr->link){
419 if(ctlr->options == 0)
421 trace("%s->options\n", ctlr->name);
422 (*ctlr->options)(vga, ctlr);
426 * skip init for vesa - vesa will do the registers for us
429 for(ctlr = vga->link; ctlr; ctlr = ctlr->link){
432 trace("%s->init\n", ctlr->name);
433 (*ctlr->init)(vga, ctlr);
436 if(strcmp(vga->mode->chan, "") == 0){
437 if(vga->mode->z < nelem(chanstr) && chanstr[vga->mode->z])
438 strcpy(vga->mode->chan, chanstr[vga->mode->z]);
440 error("%s: unknown channel type to use for depth %d\n", vga->ctlr->name, vga->mode->z);
447 trace("main->load\n");
448 if(vga->vmz && (vga->virtx*vga->virty*vga->mode->z)/8 > vga->vmz)
449 error("%s: not enough video memory - %lud\n",
450 vga->ctlr->name, vga->vmz);
453 vtype = vga->ctlr->type;
454 else if(p = strchr(vga->ctlr->name, '-')){
455 strncpy(buf, vga->ctlr->name, p - vga->ctlr->name);
456 buf[p - vga->ctlr->name] = 0;
460 vtype = vga->ctlr->name;
463 * VESA must be set up before linear.
464 * Set type to vesa for linear.
467 vesa.load(vga, vga->vesa);
468 if(vga->vesa->flag&Ferror)
469 error("vesa load error\n");
470 vgactlw("type", vesa.name);
472 vgactlw("type", vtype);
475 * The new draw device needs linear mode set
481 * Linear is over so switch to other driver for
484 if(vga->vesa && strcmp(vesa.name, vtype))
485 vgactlw("type", vtype);
487 sprint(buf, "%ludx%ludx%d %s",
488 vga->virtx, vga->virty,
489 vga->mode->z, vga->mode->chan);
491 vgactlr("size", sizeb);
492 if(rflag < 2 && strcmp(buf, sizeb) != 0)
493 error("bad refresh: %s != %s\n",
497 vgactlw("size", buf);
500 * No fiddling with registers if VESA set
501 * things up already. Sorry.
505 * Turn off the display during the load.
509 for(ctlr = vga->link; ctlr; ctlr = ctlr->link){
510 if(ctlr->load == 0 || ctlr == &vesa)
512 trace("%s->load\n", ctlr->name);
513 (*ctlr->load)(vga, ctlr);
519 vgactlw("drawinit", "");
521 if(vga->hwgc == 0 || cflag)
522 vgactlw("hwgc", "soft");
524 vgactlw("hwgc", vga->hwgc->name);
526 if(vga->virtx != vga->mode->x || vga->virty != vga->mode->y){
527 sprint(buf, "%dx%d", vga->mode->x, vga->mode->y);
528 vgactlw("actualsize", buf);
530 vgactlw("panning", "on");
538 trace("main->exits\n");