xref: /plan9/sys/src/cmd/aux/vga/main.c (revision 8cf6001e50e647a07ccf484b8e2f9940411befb9)
1219b2ee8SDavid du Colombier #include <u.h>
2219b2ee8SDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
4219b2ee8SDavid du Colombier 
59a747e4fSDavid du Colombier #include "pci.h"
6219b2ee8SDavid du Colombier #include "vga.h"
7219b2ee8SDavid du Colombier 
87dd7cddfSDavid du Colombier Biobuf stdout;
97dd7cddfSDavid du Colombier 
109a747e4fSDavid du Colombier static int iflag, lflag, pflag, rflag;
11219b2ee8SDavid du Colombier 
12219b2ee8SDavid du Colombier static char *dbname = "/lib/vgadb";
13219b2ee8SDavid du Colombier static char monitordb[128];
14219b2ee8SDavid du Colombier 
15219b2ee8SDavid du Colombier static void
dump(Vga * vga)16219b2ee8SDavid du Colombier dump(Vga* vga)
17219b2ee8SDavid du Colombier {
18219b2ee8SDavid du Colombier 	Ctlr *ctlr;
199a747e4fSDavid du Colombier 	Attr *attr;
20219b2ee8SDavid du Colombier 
21219b2ee8SDavid du Colombier 	if(vga->mode)
22219b2ee8SDavid du Colombier 		dbdumpmode(vga->mode);
23219b2ee8SDavid du Colombier 
249a747e4fSDavid du Colombier 	for(attr = vga->attr; attr; attr = attr->next)
259a747e4fSDavid du Colombier 		Bprint(&stdout, "vga->attr: %s=%s\n", attr->attr, attr->val);
269a747e4fSDavid du Colombier 
27219b2ee8SDavid du Colombier 	for(ctlr = vga->link; ctlr; ctlr = ctlr->link){
28219b2ee8SDavid du Colombier 		if(ctlr->dump == 0)
29219b2ee8SDavid du Colombier 			continue;
30219b2ee8SDavid du Colombier 
317dd7cddfSDavid du Colombier 		trace("%s->dump\n", ctlr->name);
32219b2ee8SDavid du Colombier 		if(ctlr->flag && ctlr->flag != Fsnarf){
33219b2ee8SDavid du Colombier 			printitem(ctlr->name, "flag");
347dd7cddfSDavid du Colombier 			printflag(ctlr->flag);
357dd7cddfSDavid du Colombier 			Bprint(&stdout, "\n");
36219b2ee8SDavid du Colombier 		}
37219b2ee8SDavid du Colombier 		(*ctlr->dump)(vga, ctlr);
38219b2ee8SDavid du Colombier 		ctlr->flag |= Fdump;
39219b2ee8SDavid du Colombier 	}
407dd7cddfSDavid du Colombier 	Bprint(&stdout, "\n");
41219b2ee8SDavid du Colombier }
42219b2ee8SDavid du Colombier 
43219b2ee8SDavid du Colombier void
resyncinit(Vga * vga,Ctlr * ctlr,ulong on,ulong off)44219b2ee8SDavid du Colombier resyncinit(Vga* vga, Ctlr* ctlr, ulong on, ulong off)
45219b2ee8SDavid du Colombier {
46219b2ee8SDavid du Colombier 	Ctlr *link;
47219b2ee8SDavid du Colombier 
487dd7cddfSDavid du Colombier 	trace("%s->resyncinit on 0x%8.8luX off 0x%8.8luX\n",
497dd7cddfSDavid du Colombier 		ctlr->name, on, off);
50219b2ee8SDavid du Colombier 
51219b2ee8SDavid du Colombier 	for(link = vga->link; link; link = link->link){
52219b2ee8SDavid du Colombier 		link->flag |= on;
53219b2ee8SDavid du Colombier 		link->flag &= ~off;
54219b2ee8SDavid du Colombier 		if(link == ctlr)
55219b2ee8SDavid du Colombier 			continue;
56219b2ee8SDavid du Colombier 
57219b2ee8SDavid du Colombier 		if(link->init == 0 || (link->flag & Finit) == 0)
58219b2ee8SDavid du Colombier 			continue;
59219b2ee8SDavid du Colombier 		link->flag &= ~Finit;
607dd7cddfSDavid du Colombier 		trace("%s->init 0x%8.8luX\n", link->name, link->flag);
61219b2ee8SDavid du Colombier 		(*link->init)(vga, link);
62219b2ee8SDavid du Colombier 	}
63219b2ee8SDavid du Colombier }
64219b2ee8SDavid du Colombier 
65219b2ee8SDavid du Colombier void
sequencer(Vga * vga,int on)66219b2ee8SDavid du Colombier sequencer(Vga* vga, int on)
67219b2ee8SDavid du Colombier {
68219b2ee8SDavid du Colombier 	static uchar seq01;
697dd7cddfSDavid du Colombier 	static int state = 1;
707dd7cddfSDavid du Colombier 	char *s;
71219b2ee8SDavid du Colombier 
727dd7cddfSDavid du Colombier 	if(on)
737dd7cddfSDavid du Colombier 		s = "on";
747dd7cddfSDavid du Colombier 	else
757dd7cddfSDavid du Colombier 		s = "off";
767dd7cddfSDavid du Colombier 	trace("sequencer->enter %s\n", s);
77219b2ee8SDavid du Colombier 	if(on){
78219b2ee8SDavid du Colombier 		if(vga)
79219b2ee8SDavid du Colombier 			seq01 = vga->sequencer[0x01];
807dd7cddfSDavid du Colombier 		if(state == 0){
81219b2ee8SDavid du Colombier 			seq01 |= 0x01;
82219b2ee8SDavid du Colombier 			vgaxo(Seqx, 0x01, seq01);
83219b2ee8SDavid du Colombier 			vgaxo(Seqx, 0x00, 0x03);
84219b2ee8SDavid du Colombier 		}
857dd7cddfSDavid du Colombier 	}
86219b2ee8SDavid du Colombier 	else{
87219b2ee8SDavid du Colombier 		vgaxo(Seqx, 0x00, 0x01);
88219b2ee8SDavid du Colombier 		seq01 = vgaxi(Seqx, 0x01);
89219b2ee8SDavid du Colombier 		vgaxo(Seqx, 0x01, seq01|0x20);
90219b2ee8SDavid du Colombier 	}
917dd7cddfSDavid du Colombier 	state = on;
927dd7cddfSDavid du Colombier 	trace("sequencer->leave %s\n", s);
93219b2ee8SDavid du Colombier }
94219b2ee8SDavid du Colombier 
957dd7cddfSDavid du Colombier static void
linear(Vga * vga)967dd7cddfSDavid du Colombier linear(Vga* vga)
97219b2ee8SDavid du Colombier {
987dd7cddfSDavid du Colombier 	char buf[256];
99b0dcc5a8SDavid du Colombier 	char *p;
1007dd7cddfSDavid du Colombier 
1017dd7cddfSDavid du Colombier 	/*
1027dd7cddfSDavid du Colombier 	 * Set up for linear addressing: try to allocate the
1037dd7cddfSDavid du Colombier 	 * kernel memory map then read the base-address back.
1047dd7cddfSDavid du Colombier 	 * vga->linear is a compatibility hack.
1057dd7cddfSDavid du Colombier 	 */
1067dd7cddfSDavid du Colombier 	if(vga->linear == 0){
1077dd7cddfSDavid du Colombier 		vga->ctlr->flag &= ~Ulinear;
1087dd7cddfSDavid du Colombier 		return;
1097dd7cddfSDavid du Colombier 	}
1107dd7cddfSDavid du Colombier 	if(vga->ctlr->flag & Ulinear){
111b0dcc5a8SDavid du Colombier 		/*
112b0dcc5a8SDavid du Colombier 		 * If there's already an aperture don't bother trying
113b0dcc5a8SDavid du Colombier 		 * to set up a new one.
114b0dcc5a8SDavid du Colombier 		 */
115b0dcc5a8SDavid du Colombier 		vgactlr("addr", buf);
116b0dcc5a8SDavid du Colombier 		if(atoi(buf)==0 && (buf[0]!='p' || buf[1]!=' ' || atoi(buf+2)==0)){
1177dd7cddfSDavid du Colombier 			sprint(buf, "0x%lux 0x%lux", vga->apz ? vga->apz : vga->vmz, vga->vma);
1187dd7cddfSDavid du Colombier 			vgactlw("linear", buf);
1197dd7cddfSDavid du Colombier 			vgactlr("addr", buf);
120b0dcc5a8SDavid du Colombier 		}
1217dd7cddfSDavid du Colombier 		trace("linear->addr %s\n", buf);
122b0dcc5a8SDavid du Colombier 		/*
123b0dcc5a8SDavid du Colombier 		 * old: addr 0x12345678
124b0dcc5a8SDavid du Colombier 		 * new: addr p 0x12345678 v 0x82345678 size 0x123
125b0dcc5a8SDavid du Colombier 		 */
126b0dcc5a8SDavid du Colombier 		if(buf[0]=='p' && buf[1]==' '){
127b0dcc5a8SDavid du Colombier 			vga->vmb = strtoul(buf+2, 0, 0);
128b0dcc5a8SDavid du Colombier 			p = strstr(buf, "size");
129b0dcc5a8SDavid du Colombier 			if(p)
130b0dcc5a8SDavid du Colombier 				vga->apz = strtoul(p+4, 0, 0);
131b0dcc5a8SDavid du Colombier 		}else
1327dd7cddfSDavid du Colombier 			vga->vmb = strtoul(buf, 0, 0);
1337dd7cddfSDavid du Colombier 	}
1347dd7cddfSDavid du Colombier 	else
1357dd7cddfSDavid du Colombier 		vgactlw("linear", "0");
1367dd7cddfSDavid du Colombier }
1377dd7cddfSDavid du Colombier 
1387dd7cddfSDavid du Colombier char*
1397dd7cddfSDavid du Colombier chanstr[32+1] = {
1407dd7cddfSDavid du Colombier [1]	"k1",
1417dd7cddfSDavid du Colombier [2]	"k2",
1427dd7cddfSDavid du Colombier [4]	"k4",
1437dd7cddfSDavid du Colombier [8]	"m8",
1447dd7cddfSDavid du Colombier [16]	"r5g6b5",
1457dd7cddfSDavid du Colombier [24]	"r8g8b8",
1467dd7cddfSDavid du Colombier [32]	"x8r8g8b8",
1477dd7cddfSDavid du Colombier };
1487dd7cddfSDavid du Colombier 
1490aa8dc3cSDavid du Colombier static void
usage(void)1500aa8dc3cSDavid du Colombier usage(void)
1510aa8dc3cSDavid du Colombier {
1520aa8dc3cSDavid du Colombier 	fprint(2, "usage: aux/vga [ -BcdilpvV ] [ -b bios-id ] [ -m monitor ] [ -x db ] [ mode [ virtualsize ] ]\n");
1530aa8dc3cSDavid du Colombier 	exits("usage");
1540aa8dc3cSDavid du Colombier }
1550aa8dc3cSDavid du Colombier 
1567dd7cddfSDavid du Colombier void
main(int argc,char ** argv)1577dd7cddfSDavid du Colombier main(int argc, char** argv)
1587dd7cddfSDavid du Colombier {
159b0dcc5a8SDavid du Colombier 	char *bios, buf[256], sizeb[256], *p, *vsize, *psize;
160b0dcc5a8SDavid du Colombier 	char *type, *vtype;
161e1c8dbc8SDavid du Colombier 	int fd, virtual, len;
162219b2ee8SDavid du Colombier 	Ctlr *ctlr;
163219b2ee8SDavid du Colombier 	Vga *vga;
164219b2ee8SDavid du Colombier 
165ee55fa65SDavid du Colombier 	fmtinstall('H', encodefmt);
1667dd7cddfSDavid du Colombier 	Binit(&stdout, 1, OWRITE);
1677dd7cddfSDavid du Colombier 
1687dd7cddfSDavid du Colombier 	bios = getenv("vgactlr");
169219b2ee8SDavid du Colombier 	if((type = getenv("monitor")) == 0)
170219b2ee8SDavid du Colombier 		type = "vga";
1717dd7cddfSDavid du Colombier 	psize = vsize = "640x480x8";
172219b2ee8SDavid du Colombier 
173219b2ee8SDavid du Colombier 	ARGBEGIN{
1740aa8dc3cSDavid du Colombier 	default:
1750aa8dc3cSDavid du Colombier 		usage();
1767dd7cddfSDavid du Colombier 		break;
1770aa8dc3cSDavid du Colombier 	case 'b':
1780aa8dc3cSDavid du Colombier 		bios = EARGF(usage());
1790aa8dc3cSDavid du Colombier 		break;
1807dd7cddfSDavid du Colombier 	case 'B':
1817dd7cddfSDavid du Colombier 		dumpbios(0x10000);
1827dd7cddfSDavid du Colombier 		exits(0);
183219b2ee8SDavid du Colombier 	case 'c':
184219b2ee8SDavid du Colombier 		cflag = 1;
185219b2ee8SDavid du Colombier 		break;
186219b2ee8SDavid du Colombier 	case 'd':
187219b2ee8SDavid du Colombier 		dflag = 1;
188219b2ee8SDavid du Colombier 		break;
189219b2ee8SDavid du Colombier 	case 'i':
190219b2ee8SDavid du Colombier 		iflag = 1;
191219b2ee8SDavid du Colombier 		break;
192219b2ee8SDavid du Colombier 	case 'l':
193219b2ee8SDavid du Colombier 		lflag = 1;
194219b2ee8SDavid du Colombier 		break;
195219b2ee8SDavid du Colombier 	case 'm':
1960aa8dc3cSDavid du Colombier 		type = EARGF(usage());
197219b2ee8SDavid du Colombier 		break;
198219b2ee8SDavid du Colombier 	case 'p':
199219b2ee8SDavid du Colombier 		pflag = 1;
200219b2ee8SDavid du Colombier 		break;
2019a747e4fSDavid du Colombier 	case 'r':
2029a747e4fSDavid du Colombier 		/*
2039a747e4fSDavid du Colombier 		 * rflag > 1 means "leave me alone, I know what I'm doing."
2049a747e4fSDavid du Colombier 		 */
2059a747e4fSDavid du Colombier 		rflag++;
2069a747e4fSDavid du Colombier 		break;
207219b2ee8SDavid du Colombier 	case 'v':
208219b2ee8SDavid du Colombier 		vflag = 1;
209219b2ee8SDavid du Colombier 		break;
2107dd7cddfSDavid du Colombier 	case 'V':
2117dd7cddfSDavid du Colombier 		vflag = 1;
2127dd7cddfSDavid du Colombier 		Vflag = 1;
2137dd7cddfSDavid du Colombier 		break;
2147dd7cddfSDavid du Colombier 	case 'x':
2150aa8dc3cSDavid du Colombier 		dbname = EARGF(usage());
2167dd7cddfSDavid du Colombier 		break;
217219b2ee8SDavid du Colombier 	}ARGEND
218219b2ee8SDavid du Colombier 
2197dd7cddfSDavid du Colombier 	virtual = 0;
2207dd7cddfSDavid du Colombier 	switch(argc){
2210aa8dc3cSDavid du Colombier 	default:
2220aa8dc3cSDavid du Colombier 		usage();
2230aa8dc3cSDavid du Colombier 		break;
2247dd7cddfSDavid du Colombier 	case 1:
2257dd7cddfSDavid du Colombier 		vsize = psize = argv[0];
2267dd7cddfSDavid du Colombier 		break;
2277dd7cddfSDavid du Colombier 	case 2:
2287dd7cddfSDavid du Colombier 		psize = argv[0];
2297dd7cddfSDavid du Colombier 		vsize = argv[1];
2307dd7cddfSDavid du Colombier 		virtual = 1;
2317dd7cddfSDavid du Colombier 		break;
2327dd7cddfSDavid du Colombier 	case 0:
2337dd7cddfSDavid du Colombier 		break;
2347dd7cddfSDavid du Colombier 	}
2357dd7cddfSDavid du Colombier 
236b0dcc5a8SDavid du Colombier 	if(lflag && strcmp(vsize, "text") == 0){
237b0dcc5a8SDavid du Colombier 		vesatextmode();
238b0dcc5a8SDavid du Colombier 		vgactlw("textmode", "");
239b0dcc5a8SDavid du Colombier 		exits(0);
240b0dcc5a8SDavid du Colombier 	}
241b0dcc5a8SDavid du Colombier 
242219b2ee8SDavid du Colombier 	vga = alloc(sizeof(Vga));
2437dd7cddfSDavid du Colombier 	if(bios){
2447dd7cddfSDavid du Colombier 		if((vga->offset = strtol(bios, &p, 0)) == 0 || *p++ != '=')
2457dd7cddfSDavid du Colombier 			error("main: bad BIOS string format - %s\n", bios);
2467dd7cddfSDavid du Colombier 		len = strlen(p);
2477dd7cddfSDavid du Colombier 		vga->bios = alloc(len+1);
2487dd7cddfSDavid du Colombier 		strncpy(vga->bios, p, len);
2497dd7cddfSDavid du Colombier 		trace("main->BIOS %s\n", bios);
2507dd7cddfSDavid du Colombier 	}
251219b2ee8SDavid du Colombier 
252219b2ee8SDavid du Colombier 	/*
253219b2ee8SDavid du Colombier 	 * Try to identify the VGA card and grab
254219b2ee8SDavid du Colombier 	 * registers.  Print them out if requested.
255556cddebSDavid du Colombier 	 * If monitor=vesa or our vga controller can't be found
256556cddebSDavid du Colombier 	 * in vgadb, try vesa modes; failing that, try vga.
257219b2ee8SDavid du Colombier 	 */
258556cddebSDavid du Colombier 	if(strcmp(type, "vesa") == 0 || dbctlr(dbname, vga) == 0 ||
259556cddebSDavid du Colombier 	    vga->ctlr == 0)
260b0dcc5a8SDavid du Colombier 		if(dbvesa(vga) == 0 || vga->ctlr == 0){
261556cddebSDavid du Colombier 			Bprint(&stdout, "%s: controller not in %s, not vesa\n",
262556cddebSDavid du Colombier 				argv0, dbname);
2637dd7cddfSDavid du Colombier 			dumpbios(256);
264219b2ee8SDavid du Colombier 			type = "vga";
2657dd7cddfSDavid du Colombier 			vsize = psize = "640x480x1";
2667dd7cddfSDavid du Colombier 			virtual = 0;
267219b2ee8SDavid du Colombier 			vga->ctlr = &generic;
268219b2ee8SDavid du Colombier 			vga->link = &generic;
269219b2ee8SDavid du Colombier 		}
270219b2ee8SDavid du Colombier 
2717dd7cddfSDavid du Colombier 	trace("main->snarf\n");
272219b2ee8SDavid du Colombier 	for(ctlr = vga->link; ctlr; ctlr = ctlr->link){
273219b2ee8SDavid du Colombier 		if(ctlr->snarf == 0)
274219b2ee8SDavid du Colombier 			continue;
2757dd7cddfSDavid du Colombier 		trace("%s->snarf\n", ctlr->name);
276219b2ee8SDavid du Colombier 		(*ctlr->snarf)(vga, ctlr);
277219b2ee8SDavid du Colombier 	}
278219b2ee8SDavid du Colombier 
279219b2ee8SDavid du Colombier 	if(pflag)
280219b2ee8SDavid du Colombier 		dump(vga);
281219b2ee8SDavid du Colombier 
28214414594SDavid du Colombier 	for(ctlr = vga->link; ctlr; ctlr = ctlr->link)
28314414594SDavid du Colombier 		if(ctlr->flag & Ferror)
284*8cf6001eSDavid du Colombier 			error("%r\n");
28514414594SDavid du Colombier 
286219b2ee8SDavid du Colombier 	if(iflag || lflag){
287219b2ee8SDavid du Colombier 		if(getenv(type))
2884d44ba9bSDavid du Colombier 			snprint(monitordb, sizeof monitordb, "/env/%s", type);
289219b2ee8SDavid du Colombier 		else
2904d44ba9bSDavid du Colombier 			strecpy(monitordb, monitordb+sizeof monitordb, dbname);
291219b2ee8SDavid du Colombier 
292b0dcc5a8SDavid du Colombier 		if(vga->vesa){
293b0dcc5a8SDavid du Colombier 			strcpy(monitordb, "vesa bios");
294b0dcc5a8SDavid du Colombier 			vga->mode = dbvesamode(psize);
295b0dcc5a8SDavid du Colombier 		}else
296b0dcc5a8SDavid du Colombier 			vga->mode = dbmode(monitordb, type, psize);
297b0dcc5a8SDavid du Colombier 		if(vga->mode == 0)
2987dd7cddfSDavid du Colombier 			error("main: %s@%s not in %s\n", type, psize, monitordb);
299b0dcc5a8SDavid du Colombier 
3007dd7cddfSDavid du Colombier 		if(virtual){
3017dd7cddfSDavid du Colombier 			if((p = strchr(vsize, 'x')) == nil)
3027dd7cddfSDavid du Colombier 				error("bad virtual size %s\n", vsize);
3037dd7cddfSDavid du Colombier 			vga->virtx = atoi(vsize);
3047dd7cddfSDavid du Colombier 			vga->virty = atoi(p+1);
3057dd7cddfSDavid du Colombier 			if(vga->virtx < vga->mode->x || vga->virty < vga->mode->y)
3067dd7cddfSDavid du Colombier 				error("virtual size smaller than physical size\n");
3079a747e4fSDavid du Colombier 			vga->panning = 1;
3089a747e4fSDavid du Colombier 		}
3099a747e4fSDavid du Colombier 		else{
3107dd7cddfSDavid du Colombier 			vga->virtx = vga->mode->x;
3117dd7cddfSDavid du Colombier 			vga->virty = vga->mode->y;
3129a747e4fSDavid du Colombier 			vga->panning = 0;
3137dd7cddfSDavid du Colombier 		}
3147dd7cddfSDavid du Colombier 
3159a747e4fSDavid du Colombier 		trace("vmf %d vmdf %d vf1 %lud vbw %lud\n",
3169a747e4fSDavid du Colombier 			vga->mode->frequency, vga->mode->deffrequency,
3179a747e4fSDavid du Colombier 			vga->f[1], vga->mode->videobw);
3187dd7cddfSDavid du Colombier 		if(vga->mode->frequency == 0 && vga->mode->videobw != 0 && vga->f[1] != 0){
3199a747e4fSDavid du Colombier 			/*
3209a747e4fSDavid du Colombier 			 * boost clock as much as possible subject
3219a747e4fSDavid du Colombier 			 * to video and memory bandwidth constraints
3229a747e4fSDavid du Colombier 			 */
3239a747e4fSDavid du Colombier 			ulong bytes, freq, membw;
3247dd7cddfSDavid du Colombier 			double rr;
3257dd7cddfSDavid du Colombier 
3267dd7cddfSDavid du Colombier 			freq = vga->mode->videobw;
3277dd7cddfSDavid du Colombier 			if(freq > vga->f[1])
3287dd7cddfSDavid du Colombier 				freq = vga->f[1];
3297dd7cddfSDavid du Colombier 
3307dd7cddfSDavid du Colombier 			rr = (double)freq/(vga->mode->ht*vga->mode->vt);
3317dd7cddfSDavid du Colombier 			if(rr > 85.0)		/* >85Hz is ridiculous */
3327dd7cddfSDavid du Colombier 				rr = 85.0;
3337dd7cddfSDavid du Colombier 
3349a747e4fSDavid du Colombier 			bytes = (vga->mode->x*vga->mode->y*vga->mode->z)/8;
3359a747e4fSDavid du Colombier 			membw = rr*bytes;
3367dd7cddfSDavid du Colombier 			if(vga->membw != 0 && membw > vga->membw){
3377dd7cddfSDavid du Colombier 				membw = vga->membw;
3389a747e4fSDavid du Colombier 				rr = (double)membw/bytes;
3397dd7cddfSDavid du Colombier 			}
3407dd7cddfSDavid du Colombier 
3417dd7cddfSDavid du Colombier 			freq = rr*(vga->mode->ht*vga->mode->vt);
3427dd7cddfSDavid du Colombier 			vga->mode->frequency = freq;
3437dd7cddfSDavid du Colombier 
3449a747e4fSDavid du Colombier 			trace("using frequency %lud rr %.2f membw %lud\n",
3459a747e4fSDavid du Colombier 				freq, rr, membw);
3469a747e4fSDavid du Colombier 		}
3479a747e4fSDavid du Colombier 		else if(vga->mode->frequency == 0)
3487dd7cddfSDavid du Colombier 			vga->mode->frequency = vga->mode->deffrequency;
349219b2ee8SDavid du Colombier 
350219b2ee8SDavid du Colombier 		for(ctlr = vga->link; ctlr; ctlr = ctlr->link){
351219b2ee8SDavid du Colombier 			if(ctlr->options == 0)
352219b2ee8SDavid du Colombier 				continue;
3537dd7cddfSDavid du Colombier 			trace("%s->options\n", ctlr->name);
354219b2ee8SDavid du Colombier 			(*ctlr->options)(vga, ctlr);
355219b2ee8SDavid du Colombier 		}
356219b2ee8SDavid du Colombier 
357b0dcc5a8SDavid du Colombier 		/*
358b0dcc5a8SDavid du Colombier 		 * skip init for vesa - vesa will do the registers for us
359b0dcc5a8SDavid du Colombier 		 */
360b0dcc5a8SDavid du Colombier 		if(!vga->vesa)
361219b2ee8SDavid du Colombier 		for(ctlr = vga->link; ctlr; ctlr = ctlr->link){
362219b2ee8SDavid du Colombier 			if(ctlr->init == 0)
363219b2ee8SDavid du Colombier 				continue;
3647dd7cddfSDavid du Colombier 			trace("%s->init\n", ctlr->name);
365219b2ee8SDavid du Colombier 			(*ctlr->init)(vga, ctlr);
366219b2ee8SDavid du Colombier 		}
367219b2ee8SDavid du Colombier 
3687dd7cddfSDavid du Colombier 		if(strcmp(vga->mode->chan, "") == 0){
3697dd7cddfSDavid du Colombier 			if(vga->mode->z < nelem(chanstr) && chanstr[vga->mode->z])
3707dd7cddfSDavid du Colombier 				strcpy(vga->mode->chan, chanstr[vga->mode->z]);
3717dd7cddfSDavid du Colombier 			else
372*8cf6001eSDavid du Colombier 				error("%s: unknown channel type to use for depth %d\n", vga->ctlr->name, vga->mode->z);
3737dd7cddfSDavid du Colombier 		}
3747dd7cddfSDavid du Colombier 
375219b2ee8SDavid du Colombier 		if(iflag || pflag)
376219b2ee8SDavid du Colombier 			dump(vga);
377219b2ee8SDavid du Colombier 
378219b2ee8SDavid du Colombier 		if(lflag){
3797dd7cddfSDavid du Colombier 			trace("main->load\n");
3807dd7cddfSDavid du Colombier 			if(vga->vmz && (vga->virtx*vga->virty*vga->mode->z)/8 > vga->vmz)
381219b2ee8SDavid du Colombier 				error("%s: not enough video memory - %lud\n",
3827dd7cddfSDavid du Colombier 					vga->ctlr->name, vga->vmz);
3837dd7cddfSDavid du Colombier 
3847dd7cddfSDavid du Colombier 			if(vga->ctlr->type)
385b0dcc5a8SDavid du Colombier 				vtype = vga->ctlr->type;
3867dd7cddfSDavid du Colombier 			else if(p = strchr(vga->ctlr->name, '-')){
3877dd7cddfSDavid du Colombier 				strncpy(buf, vga->ctlr->name, p - vga->ctlr->name);
3887dd7cddfSDavid du Colombier 				buf[p - vga->ctlr->name] = 0;
389b0dcc5a8SDavid du Colombier 				vtype = buf;
3907dd7cddfSDavid du Colombier 			}
3917dd7cddfSDavid du Colombier 			else
392b0dcc5a8SDavid du Colombier 				vtype = vga->ctlr->name;
393b0dcc5a8SDavid du Colombier 			vgactlw("type", vtype);
394b0dcc5a8SDavid du Colombier 
395b0dcc5a8SDavid du Colombier 			/*
396b0dcc5a8SDavid du Colombier 			 * VESA must be set up before linear.
397b0dcc5a8SDavid du Colombier 			 * Set type to vesa for linear.
398b0dcc5a8SDavid du Colombier 			 */
399b0dcc5a8SDavid du Colombier 			if(vga->vesa){
400b0dcc5a8SDavid du Colombier 				vesa.load(vga, vga->vesa);
401ffa04b9dSDavid du Colombier 				if(vga->vesa->flag&Ferror)
402ffa04b9dSDavid du Colombier 					error("vesa load error\n");
403ffa04b9dSDavid du Colombier 				vgactlw("type", vesa.name);
404b0dcc5a8SDavid du Colombier 			}
4057dd7cddfSDavid du Colombier 
4067dd7cddfSDavid du Colombier 			/*
4077dd7cddfSDavid du Colombier 			 * The new draw device needs linear mode set
4087dd7cddfSDavid du Colombier 			 * before size.
4097dd7cddfSDavid du Colombier 			 */
4107dd7cddfSDavid du Colombier 			linear(vga);
4117dd7cddfSDavid du Colombier 
412b0dcc5a8SDavid du Colombier 			/*
413b0dcc5a8SDavid du Colombier 			 * Linear is over so switch to other driver for
414b0dcc5a8SDavid du Colombier 			 * acceleration.
415b0dcc5a8SDavid du Colombier 			 */
416b0dcc5a8SDavid du Colombier 			if(vga->vesa)
417b0dcc5a8SDavid du Colombier 				vgactlw("type", vtype);
418b0dcc5a8SDavid du Colombier 
4199a747e4fSDavid du Colombier 			sprint(buf, "%ludx%ludx%d %s",
4209a747e4fSDavid du Colombier 				vga->virtx, vga->virty,
4219a747e4fSDavid du Colombier 				vga->mode->z, vga->mode->chan);
4229a747e4fSDavid du Colombier 			if(rflag){
4239a747e4fSDavid du Colombier 				vgactlr("size", sizeb);
4249a747e4fSDavid du Colombier 				if(rflag < 2 && strcmp(buf, sizeb) != 0)
4259a747e4fSDavid du Colombier 					error("bad refresh: %s != %s\n",
4269a747e4fSDavid du Colombier 						buf, sizeb);
4279a747e4fSDavid du Colombier 			}
4287dd7cddfSDavid du Colombier 			else
4297dd7cddfSDavid du Colombier 				vgactlw("size", buf);
430219b2ee8SDavid du Colombier 
431219b2ee8SDavid du Colombier 			/*
432b0dcc5a8SDavid du Colombier 			 * No fiddling with registers if VESA set
433b0dcc5a8SDavid du Colombier 			 * things up already.  Sorry.
434b0dcc5a8SDavid du Colombier 			 */
435b0dcc5a8SDavid du Colombier 			if(!vga->vesa){
436b0dcc5a8SDavid du Colombier 				/*
437219b2ee8SDavid du Colombier 				 * Turn off the display during the load.
438219b2ee8SDavid du Colombier 				 */
439219b2ee8SDavid du Colombier 				sequencer(vga, 0);
440219b2ee8SDavid du Colombier 
441219b2ee8SDavid du Colombier 				for(ctlr = vga->link; ctlr; ctlr = ctlr->link){
442b0dcc5a8SDavid du Colombier 					if(ctlr->load == 0 || ctlr == &vesa)
443219b2ee8SDavid du Colombier 						continue;
4447dd7cddfSDavid du Colombier 					trace("%s->load\n", ctlr->name);
445219b2ee8SDavid du Colombier 					(*ctlr->load)(vga, ctlr);
446219b2ee8SDavid du Colombier 				}
4477dd7cddfSDavid du Colombier 
448219b2ee8SDavid du Colombier 				sequencer(vga, 1);
449b0dcc5a8SDavid du Colombier 			}
450219b2ee8SDavid du Colombier 
4517dd7cddfSDavid du Colombier 			vgactlw("drawinit", "");
4527dd7cddfSDavid du Colombier 
453219b2ee8SDavid du Colombier 			if(vga->hwgc == 0 || cflag)
454e862f8a5SDavid du Colombier 				vgactlw("hwgc", "soft");
455219b2ee8SDavid du Colombier 			else
456219b2ee8SDavid du Colombier 				vgactlw("hwgc", vga->hwgc->name);
457219b2ee8SDavid du Colombier 
458e1c8dbc8SDavid du Colombier 			/* might as well initialize the cursor */
459e1c8dbc8SDavid du Colombier 			if((fd = open("/dev/cursor", OWRITE)) >= 0){
460e1c8dbc8SDavid du Colombier 				write(fd, buf, 0);
461e1c8dbc8SDavid du Colombier 				close(fd);
462e1c8dbc8SDavid du Colombier 			}
463e1c8dbc8SDavid du Colombier 
4649a747e4fSDavid du Colombier 			if(vga->virtx != vga->mode->x || vga->virty != vga->mode->y){
4657dd7cddfSDavid du Colombier 				sprint(buf, "%dx%d", vga->mode->x, vga->mode->y);
4667dd7cddfSDavid du Colombier 				vgactlw("actualsize", buf);
4679a747e4fSDavid du Colombier 				if(vga->panning)
4689a747e4fSDavid du Colombier 					vgactlw("panning", "on");
4697dd7cddfSDavid du Colombier 			}
4707dd7cddfSDavid du Colombier 
471219b2ee8SDavid du Colombier 			if(pflag)
472219b2ee8SDavid du Colombier 				dump(vga);
473219b2ee8SDavid du Colombier 		}
474219b2ee8SDavid du Colombier 	}
475219b2ee8SDavid du Colombier 
4767dd7cddfSDavid du Colombier 	trace("main->exits\n");
477219b2ee8SDavid du Colombier 	exits(0);
478219b2ee8SDavid du Colombier }
479