shithub: riscv

Download patch

ref: 2a1b43ad98f0c7e75a1ccc9c2468540cddd0b859
parent: 0e4fc14f7e3de742e45b489d497f052199f390dd
author: cinap_lenrek <[email protected]>
date: Tue Jan 1 20:19:51 EST 2013

vga: make kernel vga drivers more stupid

previously, we had to maintain 3 sets of pci vid/did's:

1) in /lib/vgadb for detection
2) in the userspace driver in aux/vga
3) in the kernel mode driver

this change makes the kernel mode driver more dumb in
the cases where possible. we let userspace do the pci
enumeration and if needed, it can set the pci address
of the vga card. kernel mode drivers can assume to get
the right pci device passed in scr->pci for enable()
and linear() functions and just do very basic sanity
checking before mapping framebuffer and mmio regions.

vgalinearpciid() was removed as userspace is responsible
to pick pci device.

theres a new vgactl message "pcidev" where userspace
can set the bus address. we initialize scr->pci in
vgareset() to the first pci graphics card found. this
should cover cases when an old aux/vga binary is used
that doesnt use the new pcidev message.

userspace drivers will now use the pci device that got
a match from /lib/vgadb and skip ther own enumeration.
this way, vga cards can be made to work by simply adding
an entry in vgadb with no need to modify userspace or
kernelspace drivers. this is not always possible if
the driver derives information from the specific card
model.

--- a/sys/src/9/pc/devvga.c
+++ b/sys/src/9/pc/devvga.c
@@ -47,6 +47,7 @@
 	CMtype,
 	CMunblank,
 	CMsoftscreen,
+	CMpcidev,
 };
 
 static Cmdtab vgactlmsg[] = {
@@ -65,16 +66,31 @@
 	CMtype,		"type",		2,
 	CMunblank,	"unblank",	1,
 	CMsoftscreen,	"softscreen",	2,
+	CMpcidev,	"pcidev",	2,
 };
 
 static void
 vgareset(void)
 {
+	Pcidev *pci;
+	VGAscr *scr;
+
 	/* reserve the 'standard' vga registers */
 	if(ioalloc(0x2b0, 0x2df-0x2b0+1, 0, "vga") < 0)
-		panic("vga ports already allocated"); 
+		panic("vga ports already allocated");
 	if(ioalloc(0x3c0, 0x3da-0x3c0+1, 0, "vga") < 0)
-		panic("vga ports already allocated"); 
+		panic("vga ports already allocated");
+
+	/* find graphics card pci device */
+	scr = &vgascreen[0];
+	scr->pci = pci = nil;
+	while((pci = pcimatch(pci, 0, 0)) != nil){
+		if(pci->ccrb == Pcibcdisp){
+			scr->pci = pci;
+			break;
+		}
+	}
+
 	conf.monitor = 1;
 }
 
@@ -275,6 +291,16 @@
 			return;
 		}
 		break;
+
+	case CMpcidev:
+		if(cb->nf == 2){
+			Pcidev *p;
+
+			if((p = pcimatchtbdf(strtoul(cb->f[1], 0, 16))) != nil)
+				scr->pci = p;
+		} else
+			error(Ebadarg);
+		return;
 
 	case CMtype:
 		for(i = 0; vgadev[i]; i++){
--- a/sys/src/9/pc/screen.c
+++ b/sys/src/9/pc/screen.c
@@ -443,26 +443,6 @@
 }
 
 void
-vgalinearpciid(VGAscr *scr, int vid, int did)
-{
-	Pcidev *p;
-
-	p = nil;
-	while((p = pcimatch(p, vid, 0)) != nil){
-		if(p->ccrb != 3)	/* video card */
-			continue;
-		if(did != 0 && p->did != did)
-			continue;
-		break;
-	}
-	if(p == nil)
-		error("pci video card not found");
-
-	scr->pci = p;
-	vgalinearpci(scr);
-}
-
-void
 vgalinearpci(VGAscr *scr)
 {
 	ulong paddr;
--- a/sys/src/9/pc/screen.h
+++ b/sys/src/9/pc/screen.h
@@ -167,7 +167,6 @@
 /* vga.c */
 extern void	vgascreenwin(VGAscr*);
 extern void	vgaimageinit(ulong);
-extern void	vgalinearpciid(VGAscr*, int, int);
 extern void	vgalinearpci(VGAscr*);
 extern void	vgalinearaddr(VGAscr*, ulong, int);
 
--- a/sys/src/9/pc/vga3dfx.c
+++ b/sys/src/9/pc/vga3dfx.c
@@ -36,22 +36,12 @@
 
 	if(scr->mmio)
 		return;
-	if(p = pcimatch(nil, 0x121A, 0)){
-		switch(p->did){
-		case 0x0003:		/* Banshee */
-		case 0x0005:		/* Avenger (a.k.a. Voodoo3) */
-			break;
-		default:
-			return;
-		}
-	}
-	else
+	p = scr->pci;
+	if(p == nil || p->vid != 0x121A)
 		return;
-	
 	scr->mmio = vmap(p->mem[0].bar&~0x0F, p->mem[0].size);
 	if(scr->mmio == nil)
 		return;
-	scr->pci = p;
 	
 	addvgaseg("3dfxmmio", p->mem[0].bar&~0x0F, p->mem[0].size);
 	vgalinearpci(scr);
--- a/sys/src/9/pc/vgaclgd542x.c
+++ b/sys/src/9/pc/vgaclgd542x.c
@@ -44,7 +44,7 @@
 static void
 clgd542xlinear(VGAscr* scr, int, int)
 {
-	vgalinearpciid(scr, 0x1013, 0);
+	vgalinearpci(scr);
 }
 
 static void
--- a/sys/src/9/pc/vgaclgd546x.c
+++ b/sys/src/9/pc/vgaclgd546x.c
@@ -39,18 +39,9 @@
 
 	if(scr->mmio)
 		return;
-	if((p = pcimatch(nil, 0x1013, 0)) == nil)
+	p = scr->pci;
+	if(p == nil)
 		return;
-	switch(p->did){
-	case 0xD0:
-	case 0xD4:
-	case 0xD6:
-		break;
-	default:
-		return;
-	}
-
-	scr->pci = p;
 	scr->mmio = vmap(p->mem[1].bar&~0x0F, p->mem[1].size);
 	if(scr->mmio == 0)
 		return;
--- a/sys/src/9/pc/vgacyber938x.c
+++ b/sys/src/9/pc/vgacyber938x.c
@@ -46,8 +46,11 @@
 	if(scr->vaddr)
 		return;
 	
-	vgalinearpciid(scr, 0x1023, 0);
 	p = scr->pci;
+	if(p == nil)
+		return;
+
+	vgalinearpci(scr);
 
 	/*
 	 * Heuristic to detect the MMIO space.  We're flying blind
--- a/sys/src/9/pc/vgageode.c
+++ b/sys/src/9/pc/vgageode.c
@@ -29,12 +29,12 @@
 {
 	Pcidev *p;
 	
-	if(scr->mmio) return;
-	p = pcimatch(0, 0x1022, 0x2081);
+	if(scr->mmio)
+		return;
+	p = scr->pci;
 	if(!p) return;
 	scr->mmio = vmap(p->mem[2].bar&~0x0F, p->mem[2].size);
 	if(!scr->mmio) return;
-	scr->pci = p;
 	addvgaseg("geodegp", p->mem[1].bar&~0x0F, p->mem[1].size);
 	addvgaseg("geodemmio", p->mem[2].bar&~0x0F, p->mem[2].size);
 	addvgaseg("geodevid", p->mem[3].bar&~0x0F, p->mem[3].size);
--- a/sys/src/9/pc/vgahiqvideo.c
+++ b/sys/src/9/pc/vgahiqvideo.c
@@ -50,37 +50,33 @@
 	 */
 	if(scr->mmio)
 		return;
-	if(p = pcimatch(nil, 0x102C, 0)){
-		switch(p->did){
-		case 0x00C0:		/* 69000 HiQVideo */
+	p = scr->pci;
+	if(p == nil || p->vid != 0x102C)
+		return;
+	switch(p->did){
+	case 0x00C0:		/* 69000 HiQVideo */
+		vmsize = 2*1024*1024;
+		break;
+	case 0x00E0:		/* 65550 HiQV32 */
+	case 0x00E4:		/* 65554 HiQV32 */
+	case 0x00E5:		/* 65555 HiQV32 */
+		switch((hiqvideoxi(Xrx, 0x43)>>1) & 0x03){
+		default:
+		case 0:
+			vmsize = 1*1024*1024;
+			break;
+		case 1:
 			vmsize = 2*1024*1024;
 			break;
-		case 0x00E0:		/* 65550 HiQV32 */
-		case 0x00E4:		/* 65554 HiQV32 */
-		case 0x00E5:		/* 65555 HiQV32 */
-			switch((hiqvideoxi(Xrx, 0x43)>>1) & 0x03){
-			default:
-			case 0:
-				vmsize = 1*1024*1024;
-				break;
-			case 1:
-				vmsize = 2*1024*1024;
-				break;
-			}
-			break;
-		default:
-			return;
 		}
-	}
-	else
+		break;
+	default:
 		return;
-
-	scr->pci = p;
+	}
 	vgalinearpci(scr);
 	
-	if(scr->paddr) {
+	if(scr->paddr)
 		addvgaseg("hiqvideoscreen", scr->paddr, scr->apsize);
-	}
 
 	/*
 	 * Find a place for the cursor data in display memory.
--- a/sys/src/9/pc/vgai81x.c
+++ b/sys/src/9/pc/vgai81x.c
@@ -50,29 +50,6 @@
 	*dpms = mode;
 }
 
-static Pcidev *
-i81xpcimatch(void)
-{
-	Pcidev *p;
-
-	p = nil;
-	while((p = pcimatch(p, 0x8086, 0)) != nil){
-		switch(p->did){
-		default:
-			continue;
-		case 0x7121:
-		case 0x7123:
-		case 0x7125:
-		case 0x1102:
-		case 0x1112:
-		case 0x1132:
-		case 0x3577:	/* IBM R31 uses intel 830M chipset */
-			return p;
-		}
-	}
-	return nil;
-}
-
 static void
 i81xenable(VGAscr* scr)
 {
@@ -83,7 +60,7 @@
 	
 	if(scr->mmio)
 		return;
-	p = i81xpcimatch();
+	p = scr->pci;
 	if(p == nil)
 		return;
 	scr->mmio = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size);
--- a/sys/src/9/pc/vgamach64xx.c
+++ b/sys/src/9/pc/vgamach64xx.c
@@ -146,34 +146,27 @@
 static int hwscroll(VGAscr*, Rectangle, Rectangle);
 static void initengine(VGAscr*);
 
-static Pcidev*
-mach64xxpci(void)
+static void
+mach64xxenable(VGAscr* scr)
 {
 	Pcidev *p;
 	int i;
 
-	if((p = pcimatch(nil, 0x1002, 0)) == nil)
-		return nil;
+	if(scr->io)
+		return;
+	p = scr->pci;
+	if(p == nil || p->vid != 0x1002)
+		return;
 
+	mach64type = nil;
 	for (i = 0; i != nelem(mach64s); i++)
 		if (mach64s[i].m64_id == p->did) {
+			scr->id = p->did;
 			mach64type = &mach64s[i];
-			return p;
+			break;			
 		}
-	return nil;
-}
 
-static void
-mach64xxenable(VGAscr* scr)
-{
-	Pcidev *p;
-
-	if(scr->io)
-		return;
-	if(p = mach64xxpci()){
-		scr->id = p->did;
-		scr->pci = p;
-
+	if(mach64type != nil){
 		/*
 		 * The CT doesn't always have the I/O base address
 		 * in the PCI base registers. There is a way to find
--- a/sys/src/9/pc/vgamga2164w.c
+++ b/sys/src/9/pc/vgamga2164w.c
@@ -28,20 +28,6 @@
 	MGA2164AGP	= 0x051F
 };
 
-static Pcidev*
-mgapcimatch(void)
-{
-	Pcidev *p;
-
-	p = pcimatch(nil, MATROX, MGA2164AGP);
-	if(p == nil) {
-		p = pcimatch(nil, MATROX, MGA2164);
-		if(p == nil)
-			p = pcimatch(nil, MATROX, MGA2064);
-	}
-	return p;
-}
-
 static void
 mga2164wenable(VGAscr* scr)
 {
@@ -50,8 +36,8 @@
 	if(scr->mmio)
 		return;
 
-	p = mgapcimatch();
-	if(p == nil)
+	p = scr->pci;
+	if(p == nil || p->vid != MATROX)
 		return;
 
 	if(p->did == MGA2064){
--- a/sys/src/9/pc/vgamga4xx.c
+++ b/sys/src/9/pc/vgamga4xx.c
@@ -77,20 +77,6 @@
 	FILL_OPERAND	= 0x800c7804,
 };
 
-static Pcidev *
-mgapcimatch(void)
-{
-	Pcidev *p;
-	
-	p = pcimatch(nil, MATROX, MGA4xx);
-	if(p == nil)
-		p = pcimatch(nil, MATROX, MGA550);
-	if(p == nil)
-		p = pcimatch(nil, MATROX, MGA200);
-	return p;
-}
-
-
 static void
 mgawrite8(VGAscr *scr, int index, uchar val)
 {
@@ -129,7 +115,7 @@
 	if(scr->mmio)
 		return;
 
-	pci = mgapcimatch();
+	pci = scr->pci;
 	if(pci == nil)
 		return;
 
--- a/sys/src/9/pc/vganeomagic.c
+++ b/sys/src/9/pc/vganeomagic.c
@@ -39,52 +39,50 @@
 	 */
 	if(scr->mmio)
 		return;
-	if(p = pcimatch(nil, 0x10C8, 0)){
-		switch(p->did){
-		case 0x0003:		/* MagicGraph 128ZV */
-			curoff = 0x100;
-			vmsize = 1152*1024;
-			ioaddr = (p->mem[0].bar & ~0x0F) + 0x200000;
-			iosize = 0x200000;
-			break;
-		case 0x0083:		/* MagicGraph 128ZV+ */
-			curoff = 0x100;
-			vmsize = 1152*1024;
-			ioaddr = p->mem[1].bar & ~0x0F;
-			iosize = p->mem[1].size;
-			break;
-		case 0x0004:		/* MagicGraph 128XD */
-			curoff = 0x100;
-			vmsize = 2048*1024;
-			ioaddr = p->mem[1].bar & ~0x0F;
-			iosize = p->mem[1].size;
-			break;
-		case 0x0005:		/* MagicMedia 256AV */
-			curoff = 0x1000;
-			vmsize = 2560*1024;
-			ioaddr = p->mem[1].bar & ~0x0F;
-			iosize = p->mem[1].size;
-			break;
-		case 0x0006:		/* MagicMedia 256ZX */
-			curoff = 0x1000;
-			vmsize = 4096*1024;
-			ioaddr = p->mem[1].bar & ~0x0F;
-			iosize = p->mem[1].size;
-			break;
-		case 0x0016:		/* MagicMedia 256XL+ */
-			curoff = 0x1000;
-			/* Vaio VESA BIOS says 6080, but then hwgc doesn't work */
-			vmsize = 4096*1024;
-			ioaddr = p->mem[1].bar & ~0x0F;
-			iosize = p->mem[1].size;
-			break;
-		default:
-			return;
-		}
-	}
-	else
+	p = scr->pci;
+	if(p == nil || p->vid != 0x10C8)
 		return;
-	scr->pci = p;
+	switch(p->did){
+	case 0x0003:		/* MagicGraph 128ZV */
+		curoff = 0x100;
+		vmsize = 1152*1024;
+		ioaddr = (p->mem[0].bar & ~0x0F) + 0x200000;
+		iosize = 0x200000;
+		break;
+	case 0x0083:		/* MagicGraph 128ZV+ */
+		curoff = 0x100;
+		vmsize = 1152*1024;
+		ioaddr = p->mem[1].bar & ~0x0F;
+		iosize = p->mem[1].size;
+		break;
+	case 0x0004:		/* MagicGraph 128XD */
+		curoff = 0x100;
+		vmsize = 2048*1024;
+		ioaddr = p->mem[1].bar & ~0x0F;
+		iosize = p->mem[1].size;
+		break;
+	case 0x0005:		/* MagicMedia 256AV */
+		curoff = 0x1000;
+		vmsize = 2560*1024;
+		ioaddr = p->mem[1].bar & ~0x0F;
+		iosize = p->mem[1].size;
+		break;
+	case 0x0006:		/* MagicMedia 256ZX */
+		curoff = 0x1000;
+		vmsize = 4096*1024;
+		ioaddr = p->mem[1].bar & ~0x0F;
+		iosize = p->mem[1].size;
+		break;
+	case 0x0016:		/* MagicMedia 256XL+ */
+		curoff = 0x1000;
+		/* Vaio VESA BIOS says 6080, but then hwgc doesn't work */
+		vmsize = 4096*1024;
+		ioaddr = p->mem[1].bar & ~0x0F;
+		iosize = p->mem[1].size;
+		break;
+	default:
+		return;
+	}
 
 	scr->mmio = vmap(ioaddr, iosize);
 	if(scr->mmio == nil)
--- a/sys/src/9/pc/vganvidia.c
+++ b/sys/src/9/pc/vganvidia.c
@@ -77,19 +77,6 @@
 	int	dmamax;
 } nv;
 
-static Pcidev*
-nvidiapci(void)
-{
-	Pcidev *p;
-
-	p = nil;
-	while((p = pcimatch(p, 0x10DE, 0)) != nil){
-		if(p->did >= 0x20 && p->ccrb == 3)	/* video card */
-			return p;
-	}
-	return nil;
-}
-
 static void
 nvidiaenable(VGAscr* scr)
 {
@@ -99,11 +86,10 @@
 
 	if(scr->mmio)
 		return;
-	p = nvidiapci();
+	p = scr->pci;
 	if(p == nil)
 		return;
 	scr->id = p->did;
-	scr->pci = p;
 
 	scr->mmio = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
 	if(scr->mmio == nil)
--- a/sys/src/9/pc/vgaradeon.c
+++ b/sys/src/9/pc/vgaradeon.c
@@ -25,19 +25,6 @@
 	Meg	= Kilo * Kilo,
 };
 
-static Pcidev*
-radeonpci(void)
-{
-	static Pcidev *p = nil;
-	struct pciids *ids;
-
-	while ((p = pcimatch(p, ATI_PCIVID, 0)) != nil)
-		for (ids = radeon_pciids; ids->did; ids++)
-			if (ids->did == p->did)
-				return p;
-	return nil;
-}
-
 /* mmio access */
 
 static void
@@ -96,11 +83,10 @@
 
 	if (scr->mmio)
 		return;
-	p = radeonpci();
+	p = scr->pci;
 	if (p == nil)
 		return;
 	scr->id = p->did;
-	scr->pci = p;
 
 	scr->mmio = vmap(p->mem[2].bar & ~0x0f, p->mem[2].size);
 	if(scr->mmio == 0)
--- a/sys/src/9/pc/vgas3.c
+++ b/sys/src/9/pc/vgas3.c
@@ -95,12 +95,13 @@
 	ulong mmiobase, mmiosize;
 	Pcidev *p;
 	
-	vgalinearpciid(scr, PCIS3, 0);
 	p = scr->pci;
-	if(scr->paddr == 0 || p == nil)
+	if(p == nil)
 		return;
-		
-	addvgaseg("s3screen", scr->paddr, scr->apsize);
+	vgalinearpci(scr);
+
+	if(scr->paddr)
+		addvgaseg("s3screen", scr->paddr, scr->apsize);
 	
 	id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);
 	switch(id){			/* find mmio */
--- a/sys/src/9/pc/vgat2r4.c
+++ b/sys/src/9/pc/vgat2r4.c
@@ -64,17 +64,9 @@
 
 	if(scr->mmio)
 		return;
-	if(p = pcimatch(nil, 0x105D, 0)){
-		switch(p->did){
-		case 0x5348:
-			break;
-		default:
-			return;
-		}
-	}
-	else
+	p = scr->pci;
+	if(p == nil)
 		return;
-	scr->pci = p;
 	
 	mmio = vmap(p->mem[4].bar & ~0x0F, p->mem[4].size);
 	if(mmio == nil)
--- a/sys/src/9/pc/vgavmware.c
+++ b/sys/src/9/pc/vgavmware.c
@@ -137,34 +137,25 @@
 static void
 vmwarelinear(VGAscr* scr, int, int)
 {
-	char err[64];
 	Pcidev *p;
 
-	err[0] = 0;
-	p = nil;
-	while((p = pcimatch(p, PCIVMWARE, 0)) != nil){
-		if(p->ccrb != Pcibcdisp)
-			continue;
-		switch(p->did){
-		default:
-			snprint(err, sizeof err, "unknown vmware pci did %.4ux",
-				p->did);
-			continue;
-		case VMWARE1:
-			vm->ver = 1;
-			vm->ra = 0x4560;
-			vm->rd = 0x4560 + 4;
-			break;
-		case VMWARE2:
-			vm->ver = 2;
-			vm->ra = p->mem[0].bar & ~3;
-			vm->rd = vm->ra + 1;
-			break;
-		}
-		break;			/* found a card, p is set */
+	p = scr->pci;
+	if(p == nil || p->vid != PCIVMWARE)
+		return;
+	switch(p->did){
+	default:
+		return;
+	case VMWARE1:
+		vm->ver = 1;
+		vm->ra = 0x4560;
+		vm->rd = 0x4560 + 4;
+		break;
+	case VMWARE2:
+		vm->ver = 2;
+		vm->ra = p->mem[0].bar & ~3;
+		vm->rd = vm->ra + 1;
+		break;
 	}
-	if(p == nil)
-		error(err[0]? err: "no vmware vga card found");
 	// vm->fb = vmrd(vm, Rfbstart);
 	vm->fb = p->mem[1].bar & ~0xF;
 	vm->fb += vmrd(vm, Rfboffset);
--- a/sys/src/cmd/aux/vga/3dfx.c
+++ b/sys/src/cmd/aux/vga/3dfx.c
@@ -51,8 +51,10 @@
 
 	if(vga->private == nil){
 		tdfx = alloc(sizeof(Tdfx));
-		tdfx->pci = pcimatch(0, 0x121A, 0);
+		tdfx->pci = vga->pci;
 		if(tdfx->pci == nil)
+			tdfx->pci = pcimatch(0, 0x121A, 0);
+		if(tdfx->pci == nil || tdfx->pci->vid != 0x121A)
 			error("%s: not found\n", ctlr->name);
 		switch(tdfx->pci->did){
 		default:
--- a/sys/src/cmd/aux/vga/clgd546x.c
+++ b/sys/src/cmd/aux/vga/clgd546x.c
@@ -73,7 +73,7 @@
 static void
 snarf(Vga* vga, Ctlr* ctlr)
 {
-	int f, i;
+	int i;
 	uchar *mmio;
 	Pcidev *p;
 	Laguna *laguna;
@@ -93,7 +93,10 @@
 
 	if(vga->private == nil){
 		vga->private = alloc(sizeof(Laguna));
-		if((p = pcimatch(0, 0x1013, 0)) == nil)
+		p = vga->pci;
+		if(p == nil)
+			p = pcimatch(0, 0x1013, 0);
+		if(p == nil || p->vid != 0x1013)
 			error("%s: not found\n", ctlr->name);
 		switch(p->did){
 		case 0xD0:			/* CL-GD5462 */
@@ -104,14 +107,12 @@
 			vga->f[1] = 230000000;
 			break;
 		default:
-			error("%s: not found\n", ctlr->name);
+			error("%s: DID %4.4uX unsupported\n",
+				ctlr->name, p->did);
 		}
 
-		if((f = open("#v/vgactl", OWRITE)) < 0)
-			error("%s: can't open vgactl\n", ctlr->name);
-		if(write(f, "type clgd546x", 13) != 13)
-			error("%s: can't set type\n", ctlr->name);
-		close(f);
+		vgactlpci(p);
+		vgactlw("type", "clgd546x");
 	
 		mmio = segattach(0, "clgd546xmmio", 0, p->mem[1].size);
 		if(mmio == (void*)-1)
--- a/sys/src/cmd/aux/vga/geode.c
+++ b/sys/src/cmd/aux/vga/geode.c
@@ -66,8 +66,12 @@
 
 	if(!vga->private) {
 		geode = alloc(sizeof(Geode));
-		geode->pci = pcimatch(0, 0x1022, 0x2081);
-		if(!geode->pci) error("%s: not found\n", ctlr->name);
+		geode->pci = vga->pci;
+		if(geode->pci == nil){
+			geode->pci = pcimatch(0, 0x1022, 0x2081);
+			if(!geode->pci) error("%s: not found\n", ctlr->name);
+		}
+		vgactlpci(geode->pci);
 		vgactlw("type", "geode");
 		geode->mmio = segattach(0, "geodemmio", 0, geode->pci->mem[2].size);
 		if(geode->mmio == (ulong*)-1) error("%s: can't attach mmio segment\n", ctlr->name);
--- a/sys/src/cmd/aux/vga/hiqvideo.c
+++ b/sys/src/cmd/aux/vga/hiqvideo.c
@@ -52,7 +52,10 @@
 	if(vga->private == nil){
 		vga->private = alloc(sizeof(HiQVideo));
 		hqv = vga->private;
-		if((p = pcimatch(nil, 0x102C, 0)) == nil)
+		p = vga->pci;
+		if(p == nil)
+			p = pcimatch(nil, 0x102C, 0);
+		if(p == nil || p->vid != 0x102C)
 			error("%s: not found\n", ctlr->name);
 		switch(p->did){
 		case 0x00C0:		/* 69000 HiQVideo */
--- a/sys/src/cmd/aux/vga/i81x.c
+++ b/sys/src/cmd/aux/vga/i81x.c
@@ -25,7 +25,7 @@
 static void
 snarf(Vga* vga, Ctlr* ctlr)
 {
-	int f, i;
+	int i;
 	uchar *mmio;
 	ulong *rp;
 	Pcidev *p;
@@ -33,31 +33,30 @@
 
 	if(vga->private == nil){
 		vga->private = alloc(sizeof(I81x));
-		p = nil;
-		while((p = pcimatch(p, 0x8086, 0)) != nil) {
-			switch(p->did) {
-			default:
-				continue;
-			case 0x7121:	/* Vanilla 82810 */
-			case 0x7123:	/* 810-DC100, DELL OptiPlex GX100 */
-			case 0x7125:	/* 82810E */
-			case 0x1102:	/* 82815 FSB limited to 100MHz */
-			case 0x1112:	/* 82815 no AGP */
-			case 0x1132:	/* 82815 fully featured Solano */
-			case 0x3577:	/* IBM R31 uses intel 830M chipset */
-				vga->f[1] = 230000000;		/* MAX speed of internal DAC (Hz)*/
+		p = vga->pci;
+		if(p == nil){
+			while((p = pcimatch(p, 0x8086, 0)) != nil) {
+				switch(p->did) {
+				default:
+					continue;
+				case 0x7121:	/* Vanilla 82810 */
+				case 0x7123:	/* 810-DC100, DELL OptiPlex GX100 */
+				case 0x7125:	/* 82810E */
+				case 0x1102:	/* 82815 FSB limited to 100MHz */
+				case 0x1112:	/* 82815 no AGP */
+				case 0x1132:	/* 82815 fully featured Solano */
+				case 0x3577:	/* IBM R31 uses intel 830M chipset */
+					break;
+				}
 				break;
 			}
-			break;
+			if(p == nil)
+				error("%s: Intel 81x graphics function not found\n", ctlr->name);
 		}
-		if(p == nil)
-			error("%s: Intel 81x graphics function not found\n", ctlr->name);
+		vga->f[1] = 230000000;		/* MAX speed of internal DAC (Hz)*/
 
-		if((f = open("#v/vgactl", OWRITE)) < 0)
-			error("%s: can't open vgactl\n", ctlr->name);
-		if(write(f, "type i81x", 9) != 9)
-			error("%s: can't set type\n", ctlr->name);
-		close(f);
+		vgactlpci(p);
+		vgactlw("type", "i81x");
 
 		mmio = segattach(0, "i81xmmio", 0, p->mem[1].size);
 		if(mmio == (void*)-1)
--- a/sys/src/cmd/aux/vga/io.c
+++ b/sys/src/cmd/aux/vga/io.c
@@ -214,6 +214,24 @@
 }
 
 void
+vgactlpci(Pcidev *p)
+{
+	char buf[64];
+	int len;
+
+	if(p == nil)
+		return;
+	if(ctlfd == -1)
+		ctlfd = devopen("#v/vgactl", ORDWR);
+	len = snprint(buf, sizeof(buf), "pcidev %lux", (ulong)p->tbdf);
+	seek(ctlfd, 0, 0);
+	/* ignore error for old kernel */
+	write(ctlfd, buf, len);
+
+	ctlclean = 0;
+}
+
+void
 setpalette(int p, int r, int g, int b)
 {
 	vgao(PaddrW, p);
--- a/sys/src/cmd/aux/vga/mga2164w.c
+++ b/sys/src/cmd/aux/vga/mga2164w.c
@@ -118,7 +118,6 @@
 static void
 mapmga(Vga* vga, Ctlr* ctlr)
 {
-	int f;
 	uchar *m;
 	Mga *mga;
 
@@ -126,11 +125,8 @@
 		error("%s: tvp3026io: no *mga\n", ctlr->name);
 	mga = vga->private;
 
-	f = open("#v/vgactl", OWRITE);
-	if(f < 0)
-		error("%s: can't open vgactl\n", ctlr->name);
-	if(write(f, "type mga2164w", 13) != 13)
-		error("%s: can't set mga type\n", ctlr->name);
+	vgactlpci(vga->pci);
+	vgactlw("type", "mga2164w");
 	
 	m = segattach(0, "mga2164wmmio", 0, 16*1024);
 	if(m == (void*)-1)
--- a/sys/src/cmd/aux/vga/mga4xx.c
+++ b/sys/src/cmd/aux/vga/mga4xx.c
@@ -448,27 +448,18 @@
 static void
 setpalettedepth(int depth)
 {
-	int	fd;
-	char *cmd = strdup("palettedepth X");
+	char buf[12];
 
 	if ((depth != 8) && (depth != 6) && (depth != 16))
 		error("mga: invalid palette depth %d\n", depth);
 
-	fd = open("#v/vgactl", OWRITE);
-	if(fd < 0)
-		error("mga: can't open vgactl\n");
-
-	cmd[13] = '0' + depth;
-	if(write(fd, cmd, 14) != 14)
-		error("mga: can't set palette depth to %d\n", depth);
-
-	close(fd);
+	snprint(buf, sizeof(buf), "%d", depth);
+	vgactlw("palettedepth", buf);
 }
 
 static void
 mapmga4xx(Vga* vga, Ctlr* ctlr)
 {
-	int 	f;
 	uchar* 	m;
 	Mga *	mga;
 
@@ -476,12 +467,8 @@
 		error("%s: g4xxio: no *mga4xx\n", ctlr->name);
 	mga = vga->private;
 
-	f = open("#v/vgactl", OWRITE);
-	if(f < 0)
-		error("%s: can't open vgactl\n", ctlr->name);
-
-	if(write(f, "type mga4xx", 11) != 11)
-		error("%s: can't set mga type\n", ctlr->name);
+	vgactlpci(vga->pci);
+	vgactlw("type", "mga4xx");
 	
 	m = segattach(0, "mga4xxmmio", 0, 16*Kilo);
 	if(m == (void*)-1)
@@ -500,8 +487,6 @@
 	}
 	mga->mmfb = m;
 	trace("%s: frame buffer at %#p\n", ctlr->name, mga->mmfb);
-
-	close(f);
 }
 
 static void
--- a/sys/src/cmd/aux/vga/nvidia.c
+++ b/sys/src/cmd/aux/vga/nvidia.c
@@ -136,14 +136,17 @@
 		vga->private = alloc(sizeof(Nvidia));
 		nv = vga->private;
 
-		p = nil;
-		while((p = pcimatch(p, 0x10DE, 0)) != nil){
-			if(p->ccrb == 3)
-				break;
+		p = vga->pci;
+		if(p == nil){
+			while((p = pcimatch(p, 0x10DE, 0)) != nil){
+				if(p->ccrb == 3)
+					break;
+			}
+			if(p == nil)
+				error("%s: not found\n", ctlr->name);
 		}
-		if(p == nil)
-			error("%s: not found\n", ctlr->name);
 
+		vgactlpci(p);
 		vgactlw("type", ctlr->name);
 
 		mmio = segattach(0, "nvidiammio", 0, p->mem[0].size);
--- a/sys/src/cmd/aux/vga/pci.h
+++ b/sys/src/cmd/aux/vga/pci.h
@@ -103,3 +103,5 @@
 	Pcidev*	list;
 	int rawfd;
 };
+
+extern void vgactlpci(Pcidev *);
--- a/sys/src/cmd/aux/vga/radeon.c
+++ b/sys/src/cmd/aux/vga/radeon.c
@@ -232,10 +232,14 @@
 		vga->private = alloc(sizeof(Radeon));
 		radeon = vga->private;
 
+		isr300 = 0;
 		p = radeonpci(&isr300);
 		if (p == nil)
+			p = vga->pci;
+		if (p == nil)
 			error("%s: not found\n", ctlr->name);
 
+		vgactlpci(p);
 		vgactlw("type", ctlr->name);
 
 		mmio = (uintptr)segattach(0, "radeonmmio", (void *)0,
--- a/sys/src/cmd/aux/vga/t2r4.c
+++ b/sys/src/cmd/aux/vga/t2r4.c
@@ -91,7 +91,7 @@
 snarf(Vga* vga, Ctlr* ctlr)
 {
 	ulong *mmio;
-	int f, i, x;
+	int i, x;
 	Pcidev *p;
 	T2r4 *t2r4;
 	ulong *rp;
@@ -98,20 +98,20 @@
 
 	if(vga->private == nil){
 		vga->private = alloc(sizeof(T2r4));
-		if((p = pcimatch(0, 0x105D, 0)) == nil)
-			error("%s: not found\n", ctlr->name);
-		switch(p->did){
-		case 0x5348:			/*  */
-			break;
-		default:
-			error("%s: not found\n", ctlr->name);
+		p = vga->pci;
+		if(p == nil){
+			if((p = pcimatch(0, 0x105D, 0)) == nil)
+				error("%s: not found\n", ctlr->name);
+			switch(p->did){
+			case 0x5348:			/*  */
+				break;
+			default:
+				error("%s: not found\n", ctlr->name);
+			}
 		}
 
-		if((f = open("#v/vgactl", OWRITE)) < 0)
-			error("%s: can't open vgactl\n", ctlr->name);
-		if(write(f, "type t2r4", 9) != 9)
-			error("%s: can't set type\n", ctlr->name);
-		close(f);
+		vgactlpci(p);
+		vgactlw("type", "t2r4");
 	
 		mmio = segattach(0, "t2r4mmio", 0, p->mem[4].size);
 		if(mmio == (void*)-1)
--- a/sys/src/cmd/aux/vga/vmware.c
+++ b/sys/src/cmd/aux/vga/vmware.c
@@ -125,7 +125,6 @@
 	p = vga->pci;
 	if(p == nil)
 		error("%s: vga->pci not set\n", ctlr->name);
-
 	vm = alloc(sizeof(Vmware));
 	switch(p->did){
 	case VMWARE1:	/* VMware video chipset #1 */
@@ -141,8 +140,9 @@
 		break;
 
 	default:
-		error("%s: unrecognized chipset %.4ux\n", ctlr->name, p->did);
+		error("%s: unrecognized DID %.4ux\n", ctlr->name, p->did);
 	}
+	vgactlpci(p);
 
 	for(i=0; i<Nreg; i++)
 		vm->r[i] = vmrd(vm, i);