changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: aux/vga: cleanup vesa code

changeset 4243: 7ccbd823958c
parent 4242: e817c2e887e7
child 4244: 69d00d22733b
author: cinap_lenrek@felloff.net
date: Sun, 01 Feb 2015 19:28:24 +0100
files: sys/src/cmd/aux/vga/vesa.c
description: aux/vga: cleanup vesa code

dbvesamode() modified the passed in size string in the process
of option parsing. this is a no-go because the string might be
constant in the read only section. provide cracksize() function
for the parsing and make a static copy.

do the vendor specific monitor detection in vbesnarf() instead
of vbecheck(). vbecheck()'s purpose is to check if vesa bios
service is avialable, not snarf graphics card state.

nvidiascale() was a no-op because it missed the vbecall() at
the end of the function. this means it was never tested so i
add the missing vbecall(), but disable nvidiascale for now
until someone tests this.

keep fancy stuff out of the Vbe structure. it is just there for
making bios calls, not keep state about the graphics card.
     1.1--- a/sys/src/cmd/aux/vga/vesa.c
     1.2+++ b/sys/src/cmd/aux/vga/vesa.c
     1.3@@ -25,9 +25,6 @@ struct Vbe
     1.4 	uchar	*mem;	/* copy of memory; 1MB */
     1.5 	uchar	*isvalid;	/* 1byte per 4kB in mem */
     1.6 	uchar	*modebuf;
     1.7-	int	dspcon;	/* connected displays bitmask */
     1.8-	int	dspact;	/* active displays bitmask */
     1.9-	void (*scale)(Vga*, Ctlr*);
    1.10 };
    1.11 
    1.12 struct Vmode
    1.13@@ -54,6 +51,10 @@ struct Vmode
    1.14 static Vbe *vbe;
    1.15 static Edid *edid;
    1.16 
    1.17+static int dspcon;	/* connected displays bitmask */
    1.18+static int dspact;	/* active displays bitmask */
    1.19+static int (*setscale)(Vbe*, char*);
    1.20+
    1.21 Vbe *mkvbe(void);
    1.22 int vbecheck(Vbe*);
    1.23 uchar *vbemodes(Vbe*);
    1.24@@ -68,7 +69,7 @@ int vbeddcedid(Vbe *vbe, Edid *e);
    1.25 uchar* vbesetup(Vbe*, Ureg*, int);
    1.26 int vbecall(Vbe*, Ureg*);
    1.27 int setdisplay(Vbe *vbe, int display);
    1.28-int getdisplay(Vbe *vbe);
    1.29+int getdisplay(Vbe*);
    1.30 void fixbios(Vbe*);
    1.31 
    1.32 int
    1.33@@ -98,37 +99,64 @@ dbvesa(Vga* vga)
    1.34 	return 1;
    1.35 }
    1.36 
    1.37+static Attr*
    1.38+newattr(Attr *tail, char *attr, char *fmt, ...)
    1.39+{
    1.40+	va_list list;
    1.41+	char *val;
    1.42+	Attr *a;
    1.43+
    1.44+	va_start(list, fmt);
    1.45+	val = vsmprint(fmt, list);
    1.46+	va_end(list);
    1.47+
    1.48+	a = alloc(sizeof(Attr));
    1.49+	a->attr = attr;
    1.50+	a->val = val;
    1.51+	a->next = tail;
    1.52+
    1.53+	return a;
    1.54+}
    1.55+
    1.56+static char*
    1.57+cracksize(char *size, char **scale, int *display)
    1.58+{
    1.59+	static char buf[256];
    1.60+	char *f[4];
    1.61+	int i, n;
    1.62+
    1.63+	*scale = nil;
    1.64+	*display = 0;
    1.65+	snprint(buf, sizeof(buf), "%s", size);
    1.66+	n = getfields(buf, f, nelem(f), 0, ",");
    1.67+	for(i=1; i<n; i++){
    1.68+		if(f[i][0] == '#')
    1.69+			*display = atoi(&f[i][1]);
    1.70+		else if(strncmp(f[i], "scale", 5) == 0)
    1.71+			*scale = f[i];
    1.72+		else
    1.73+			error("bad size option: %s for %s\n", f[i], f[0]);
    1.74+	}
    1.75+	return f[0];
    1.76+}
    1.77+
    1.78 Mode*
    1.79 dbvesamode(char *size)
    1.80 {
    1.81-	int i, width, nargs, display;
    1.82+	int i, width, display;
    1.83 	int oldmode, olddisplay;
    1.84 	uchar *p, *ep;
    1.85-	Attr *a;
    1.86 	Vmode vm;
    1.87 	Mode *m;
    1.88 	Modelist *l;
    1.89-	char *args[4], *scale;
    1.90+	char *scale;
    1.91 
    1.92 	if(vbe == nil)
    1.93 		return nil;
    1.94 
    1.95-	scale = nil;
    1.96-	display = 0;
    1.97+	size = cracksize(size, &scale, &display);
    1.98+
    1.99 	oldmode = olddisplay = 0;
   1.100-	nargs = getfields(size, args, 4, 0, ",");
   1.101-	if(nargs > 1){
   1.102-		if(args[1][0] == '#'){
   1.103-			display = atoi(&args[1][1]);
   1.104-			if(nargs > 2)
   1.105-				scale = args[2];
   1.106-		}else if(args[1][0] == 's'){
   1.107-			scale = args[1];
   1.108-			if(nargs > 2)
   1.109-				display = atoi(&args[2][1]);
   1.110-		}
   1.111-	}
   1.112-
   1.113 	if(display != 0){
   1.114 		olddisplay = getdisplay(vbe);
   1.115 		oldmode = vbegetmode(vbe);
   1.116@@ -203,47 +231,17 @@ havemode:
   1.117 	strcpy(m->chan, vm.chan);
   1.118 	m->z = vm.depth;
   1.119 
   1.120-	a = alloc(sizeof(Attr));
   1.121-	a->attr = "id";
   1.122-	a->val = alloc(32);
   1.123-	sprint(a->val, "0x%x", vm.id);
   1.124-
   1.125-	a->next = nil;
   1.126-	m->attr = a;
   1.127-
   1.128-	/* scaling mode */
   1.129-	if(scale != nil){
   1.130-		a = alloc(sizeof(Attr));
   1.131-		a->attr = "scale";
   1.132-		a->val = alloc(32);
   1.133-		strncpy(a->val, scale, 32);
   1.134-
   1.135-		a->next = m->attr;
   1.136-		m->attr = a;
   1.137-	}
   1.138-
   1.139-	/* display id */
   1.140-	if(display != 0){
   1.141-		a = alloc(sizeof(Attr));
   1.142-		a->attr = "display";
   1.143-		a->val = alloc(2);
   1.144-		a->val[0] = '0' + display;
   1.145-
   1.146-		a->next = m->attr;
   1.147-		m->attr = a;
   1.148-	}
   1.149-
   1.150 	/* account for framebuffer stride */
   1.151 	width = vm.bpl * 8 / m->z;
   1.152-	if(width > m->x){
   1.153-		a = alloc(sizeof(Attr));
   1.154-		a->attr = "virtx";
   1.155-		a->val = alloc(32);
   1.156-		sprint(a->val, "%d", width);
   1.157+	if(width > m->x)
   1.158+		m->attr = newattr(m->attr, "virtx", "%d", width);
   1.159 
   1.160-		a->next = m->attr;
   1.161-		m->attr = a;
   1.162-	}
   1.163+	if(scale != nil)
   1.164+		m->attr = newattr(m->attr, "scale", "%s", scale);
   1.165+	if(display != 0)
   1.166+		m->attr = newattr(m->attr, "display", "%d", display);
   1.167+
   1.168+	m->attr = newattr(m->attr, "id", "0x%x", vm.id);
   1.169 
   1.170 	return m;
   1.171 }
   1.172@@ -278,36 +276,44 @@ load(Vga* vga, Ctlr* ctlr)
   1.173 {
   1.174 	int mode, display;
   1.175 	int oldmode, olddisplay;
   1.176-	char *ds;
   1.177+	char *ds, *scale;
   1.178 
   1.179 	if(vbe == nil)
   1.180 		error("no vesa bios\n");
   1.181 	mode = atoi(dbattr(vga->mode->attr, "id"));
   1.182+	scale = dbattr(vga->mode->attr, "scale");
   1.183 	ds = dbattr(vga->mode->attr, "display");
   1.184 	display = ds == nil ? 0 : atoi(ds);
   1.185 	olddisplay = oldmode = 0;
   1.186 
   1.187 	/* need to reset scaling before switching displays */
   1.188-	if(vbe->scale != nil)
   1.189-		vbe->scale(nil, nil);
   1.190-
   1.191+	if(setscale != nil)
   1.192+		(*setscale)(vbe, "scalefull");
   1.193 	if(display != 0){
   1.194 		olddisplay = getdisplay(vbe);
   1.195 		oldmode = vbegetmode(vbe);
   1.196+		if(setdisplay(vbe, display) < 0){
   1.197+			fprint(2, "setdisplay: %r\n");
   1.198+			ctlr->flag |= Ferror;
   1.199+			return;
   1.200+		}
   1.201 	}
   1.202-
   1.203-	if(setdisplay(vbe, display) < 0){
   1.204+	if(vbesetmode(vbe, mode) < 0){
   1.205+		fprint(2, "vbesetmode: %r\n");
   1.206 		ctlr->flag |= Ferror;
   1.207-		fprint(2, "vbesetmode: %r\n");
   1.208-	}else if(vbesetmode(vbe, mode) < 0){
   1.209 		if(display != 0){
   1.210 			setdisplay(vbe, olddisplay);
   1.211 			vbesetmode(vbe, oldmode);
   1.212 		}
   1.213-		ctlr->flag |= Ferror;
   1.214-		fprint(2, "vbesetmode: %r\n");
   1.215-	}else if(vbe->scale != nil)
   1.216-		vbe->scale(vga, ctlr);
   1.217+		return;
   1.218+	}
   1.219+	if(setscale != nil){
   1.220+		if((*setscale)(vbe, scale) < 0){
   1.221+			fprint(2, "setscale: %r\n");
   1.222+			ctlr->flag |= Ferror;
   1.223+			return;
   1.224+		}
   1.225+	}
   1.226 }
   1.227 
   1.228 static void
   1.229@@ -339,69 +345,47 @@ dump(Vga*, Ctlr*)
   1.230 		printedid(edid);
   1.231 }
   1.232 
   1.233-static void
   1.234-intelscale(Vga* vga, Ctlr* ctlr)
   1.235+static int
   1.236+intelscale(Vbe *vbe, char *scale)
   1.237 {
   1.238 	Ureg u;
   1.239 	int cx;
   1.240-	char *scale;
   1.241 
   1.242-	if(vbe == nil)
   1.243-		error("no vesa bios\n");
   1.244-
   1.245-	if(vga == nil)
   1.246+	if(scale == nil)
   1.247+		cx = 0;
   1.248+	else if(strcmp(scale, "scalefull") == 0)
   1.249 		cx = 4;
   1.250-	else{
   1.251-		/* NOTE: intel doesn't support "aspect" scaling mode :( */
   1.252-		scale = dbattr(vga->mode->attr, "scale");
   1.253-		if(scale == nil)
   1.254-			cx = 0;
   1.255-		else if(strcmp(scale, "scalefull") == 0)
   1.256-			cx = 4;
   1.257-		else{
   1.258-			ctlr->flag |= Ferror;
   1.259-			fprint(2, "vbescale: unsupported mode %s\n", scale);
   1.260-			return;
   1.261-		}
   1.262+	else {
   1.263+		werrstr("intelscale: not supported: %s", scale);
   1.264+		return -1;
   1.265 	}
   1.266-
   1.267 	vbesetup(vbe, &u, 0x5F61);
   1.268 	u.bx = 0;
   1.269 	u.cx = cx; /* horizontal */
   1.270 	u.dx = cx; /* vertical */
   1.271-	vbecall(vbe, &u);
   1.272+	return vbecall(vbe, &u);
   1.273 }
   1.274 
   1.275-static void
   1.276-nvidiascale(Vga* vga, Ctlr* ctlr)
   1.277+static int
   1.278+nvidiascale(Vbe *vbe, char *scale)
   1.279 {
   1.280 	Ureg u;
   1.281 	int cx;
   1.282-	char *scale;
   1.283 
   1.284-	if(vbe == nil)
   1.285-		error("no vesa bios\n");
   1.286-
   1.287-	if(vga == nil)
   1.288+	if(scale == nil)
   1.289+		cx = 1;
   1.290+	else if(strcmp(scale, "scaleaspect") == 0)
   1.291+		cx = 3;
   1.292+	else if(strcmp(scale, "scalefull") == 0)
   1.293 		cx = 0;
   1.294-	else{
   1.295-		scale = dbattr(vga->mode->attr, "scale");
   1.296-		if(scale == nil)
   1.297-			cx = 1;
   1.298-		else if(strcmp(scale, "scaleaspect") == 0)
   1.299-			cx = 3;
   1.300-		else if(strcmp(scale, "scalefull") == 0)
   1.301-			cx = 0;
   1.302-		else{
   1.303-			ctlr->flag |= Ferror;
   1.304-			fprint(2, "vbescale: unsupported mode %s\n", scale);
   1.305-			return;
   1.306-		}
   1.307+	else {
   1.308+		werrstr("nvidiascale: not supported: %s", scale);
   1.309+		return -1;
   1.310 	}
   1.311-
   1.312 	vbesetup(vbe, &u, 0x4F14);
   1.313 	u.bx = 0x102;
   1.314 	u.cx = cx;
   1.315+	return vbecall(vbe, &u);
   1.316 }
   1.317 
   1.318 Ctlr vesa = {
   1.319@@ -584,6 +568,9 @@ vbeflush(Vbe *vbe)
   1.320 int
   1.321 vbecall(Vbe *vbe, Ureg *u)
   1.322 {
   1.323+	int ax;
   1.324+
   1.325+	ax = u->ax >> 8;
   1.326 	u->trap = 0x10;
   1.327 
   1.328 	vbeflush(vbe);
   1.329@@ -595,7 +582,7 @@ vbecall(Vbe *vbe, Ureg *u)
   1.330 
   1.331 	getmem(vbe, RealModeBuf, 0);
   1.332 
   1.333-	if((u->ax&0xFFFF) != 0x004F){
   1.334+	if((u->ax&0xFFFF) != ax){
   1.335 		werrstr("VBE error %#.4lux", u->ax&0xFFFF);
   1.336 		return -1;
   1.337 	}
   1.338@@ -605,7 +592,6 @@ vbecall(Vbe *vbe, Ureg *u)
   1.339 int
   1.340 vbecheck(Vbe *vbe)
   1.341 {
   1.342-	char *oem;
   1.343 	uchar *p;
   1.344 	Ureg u;
   1.345 
   1.346@@ -621,29 +607,13 @@ vbecheck(Vbe *vbe)
   1.347 		werrstr("invalid vesa version: %.4H\n", p+4);
   1.348 		return -1;
   1.349 	}
   1.350-	oem = unfarptr(vbe, p+6);
   1.351-	if(strncmp(oem, "Intel", 5) == 0){
   1.352-		vbe->scale = intelscale;
   1.353-
   1.354-		/* detect connected display devices */
   1.355-		vbesetup(vbe, &u, 0x5F64);
   1.356-		u.bx = 0x200;
   1.357-		vbecall(vbe, &u);
   1.358-		vbe->dspcon = u.cx >> 8; /* CH = connected, CL = available? */
   1.359-
   1.360-		/* detect active display devices */
   1.361-		vbesetup(vbe, &u, 0x5F64);
   1.362-		u.bx = 0x100;
   1.363-		vbecall(vbe, &u);
   1.364-		vbe->dspact = u.cx;
   1.365-	}else if(memcmp(oem, "NVIDIA", 6) == 0)
   1.366-		vbe->scale = nvidiascale;
   1.367 	return 0;
   1.368 }
   1.369 
   1.370 int
   1.371 vbesnarf(Vbe *vbe, Vga *vga)
   1.372 {
   1.373+	char *oem;
   1.374 	uchar *p;
   1.375 	Ureg u;
   1.376 
   1.377@@ -654,6 +624,29 @@ vbesnarf(Vbe *vbe, Vga *vga)
   1.378 	if(memcmp(p, "VESA", 4) != 0 || p[5] < 2)
   1.379 		return -1;
   1.380 	vga->apz = WORD(p+18)*0x10000UL;
   1.381+
   1.382+	oem = unfarptr(vbe, p+6);
   1.383+	if(strncmp(oem, "Intel", 5) == 0){
   1.384+		setscale = intelscale;
   1.385+
   1.386+		/* detect connected display devices */
   1.387+		vbesetup(vbe, &u, 0x5F64);
   1.388+		u.bx = 0x200;
   1.389+		if(vbecall(vbe, &u) < 0)
   1.390+			u.cx = 0;
   1.391+		dspcon = u.cx >> 8; /* CH = connected, CL = available? */
   1.392+
   1.393+		/* detect active display devices */
   1.394+		vbesetup(vbe, &u, 0x5F64);
   1.395+		u.bx = 0x100;
   1.396+		if(vbecall(vbe, &u) < 0)
   1.397+			u.cx = 0;
   1.398+		dspact = u.cx;
   1.399+
   1.400+	}
   1.401+	else if(memcmp(oem, "NVIDIA", 6) == 0 && 0)	/* untested */
   1.402+		setscale = nvidiascale;
   1.403+
   1.404 	if(edid == nil){
   1.405 		edid = alloc(sizeof(Edid));
   1.406 		if(vbeddcedid(vbe, edid) < 0){
   1.407@@ -696,17 +689,20 @@ vbeprintinfo(Vbe *vbe)
   1.408 	printitem("vesa", "mem");
   1.409 	Bprint(&stdout, "%lud\n", WORD(p+18)*0x10000UL);
   1.410 
   1.411-	printitem("vesa", "dsp con");
   1.412-	for(i = 0; i < 8; i++)
   1.413-		if(vbe->dspcon & (1<<i))
   1.414-			Bprint(&stdout, "%d ", i+1);
   1.415-	Bprint(&stdout, "\n");
   1.416-
   1.417-	printitem("vesa", "dsp act");
   1.418-	for(i = 0; i < 8; i++)
   1.419-		if(vbe->dspact & (1<<i))
   1.420-			Bprint(&stdout, "%d ", i+1);
   1.421-	Bprint(&stdout, "\n");
   1.422+	if(dspcon != 0){
   1.423+		printitem("vesa", "dsp con");
   1.424+		for(i = 0; i < 8; i++)
   1.425+			if(dspcon & (1<<i))
   1.426+				Bprint(&stdout, "%d ", i+1);
   1.427+		Bprint(&stdout, "\n");
   1.428+	}
   1.429+	if(dspact != 0){
   1.430+		printitem("vesa", "dsp act");
   1.431+		for(i = 0; i < 8; i++)
   1.432+			if(dspact & (1<<i))
   1.433+				Bprint(&stdout, "%d ", i+1);
   1.434+		Bprint(&stdout, "\n");
   1.435+	}
   1.436 }
   1.437 
   1.438 uchar*
   1.439@@ -888,17 +884,17 @@ vbeddcedid(Vbe *vbe, Edid *e)
   1.440 }
   1.441 
   1.442 int
   1.443-getdisplay(Vbe *vbe)
   1.444+getdisplay(Vbe*)
   1.445 {
   1.446 	int i;
   1.447 
   1.448 	for(i = 0; i < 8; i++)
   1.449-		if(vbe->dspact & 1<<i)
   1.450+		if(dspact & 1<<i)
   1.451 			return i+1;
   1.452 
   1.453 	/* fallback to a connected one */
   1.454 	for(i = 0; i < 8; i++)
   1.455-		if(vbe->dspcon & 1<<i)
   1.456+		if(dspcon & 1<<i)
   1.457 			return i+1;
   1.458 
   1.459 	return 0;
   1.460@@ -914,20 +910,18 @@ setdisplay(Vbe *vbe, int display)
   1.461 		return 0;
   1.462 
   1.463 	cx = 1<<(display-1);
   1.464-	if(vbe->dspcon & cx){
   1.465+	if(dspcon & cx){
   1.466 		/* switch to common mode before trying */
   1.467 		vbesetmode(vbe, 3);
   1.468 
   1.469 		vbesetup(vbe, &u, 0x5F64);
   1.470 		u.bx = 0;
   1.471 		u.cx = cx;
   1.472-		vbecall(vbe, &u);
   1.473-		if(u.ax == 0x5f)
   1.474-			return 0;
   1.475-		werrstr("setdisplay: VBE error %#.4lux", u.ax);
   1.476-	}else
   1.477-		werrstr("setdisplay: %d not connected", display);
   1.478-	return -1;
   1.479+		return vbecall(vbe, &u);
   1.480+	} else {
   1.481+		werrstr("display #%d not connected", display);
   1.482+		return -1;
   1.483+	}
   1.484 }
   1.485 
   1.486 void