Browse Source

Plan 9 from Bell Labs 2005-05-11

David du Colombier 19 years ago
parent
commit
89823ed35d

+ 9 - 7
dist/replica/_plan9.db

@@ -824,7 +824,7 @@ alpha/mkfile - 664 sys sys 948141303 46
 amd64 - 20000000775 sys sys 1114458599 0
 amd64/bin - 20000000775 sys sys 1114458475 0
 amd64/include - 20000000775 sys sys 1114458660 0
-amd64/include/u.h - 644 sys sys 1114458660 1658
+amd64/include/u.h - 664 sys sys 1114458660 1658
 amd64/include/ureg.h - 644 sys sys 1114458660 454
 amd64/lib - 20000000775 sys sys 1114458490 0
 amd64/mkfile - 644 sys sys 1114458599 46
@@ -5860,7 +5860,7 @@ sys/src/9/pc/ether8139.c - 664 sys sys 1086987324 18362
 sys/src/9/pc/ether8169.c - 664 sys sys 1110882037 22704
 sys/src/9/pc/ether82543gc.c - 664 sys sys 1055689887 32296
 sys/src/9/pc/ether82557.c - 664 sys sys 1115566440 30076
-sys/src/9/pc/ether83815.c - 664 sys sys 1115476450 23479
+sys/src/9/pc/ether83815.c - 664 sys sys 1115744557 23481
 sys/src/9/pc/ether8390.c - 664 sys sys 1112382834 17701
 sys/src/9/pc/ether8390.h - 664 sys sys 1015014517 1511
 sys/src/9/pc/etherdp83820.c - 664 sys sys 1083469193 29134
@@ -7610,13 +7610,13 @@ sys/src/cmd/aux/vga/io.c - 664 sys sys 1014925009 6222
 sys/src/cmd/aux/vga/mach32.c - 664 sys sys 1014925009 6004
 sys/src/cmd/aux/vga/mach64.c - 664 sys sys 1014925009 8279
 sys/src/cmd/aux/vga/mach64xx.c - 664 sys sys 1097900455 30266
-sys/src/cmd/aux/vga/main.c - 664 sys sys 1114703149 9471
+sys/src/cmd/aux/vga/main.c - 664 sys sys 1115734902 9535
 sys/src/cmd/aux/vga/mga2164w.c - 664 sys sys 1014925010 13196
 sys/src/cmd/aux/vga/mga4xx.c - 664 sys sys 1014925010 35895
-sys/src/cmd/aux/vga/mkfile - 664 sys sys 1114453579 915
+sys/src/cmd/aux/vga/mkfile - 664 sys sys 1115734903 927
 sys/src/cmd/aux/vga/neomagic.c - 664 sys sys 1104430499 8975
 sys/src/cmd/aux/vga/notes.txt - 664 sys sys 1028334647 14376
-sys/src/cmd/aux/vga/nvidia.c - 664 sys sys 1109511456 23718
+sys/src/cmd/aux/vga/nvidia.c - 664 sys sys 1115734903 31499
 sys/src/cmd/aux/vga/palette.c - 664 sys sys 1014925010 2201
 sys/src/cmd/aux/vga/pci.c - 664 sys sys 1014925011 8659
 sys/src/cmd/aux/vga/pci.h - 664 sys sys 1014925011 3290
@@ -7638,9 +7638,10 @@ sys/src/cmd/aux/vga/tvp3025.c - 664 sys sys 1014925013 1960
 sys/src/cmd/aux/vga/tvp3025clock.c - 664 sys sys 1014925013 1511
 sys/src/cmd/aux/vga/tvp3026.c - 664 sys sys 1014925013 3580
 sys/src/cmd/aux/vga/tvp3026clock.c - 664 sys sys 1014925013 1960
-sys/src/cmd/aux/vga/vesa.c - 664 sys sys 1114703149 9421
+sys/src/cmd/aux/vga/vesa.c - 664 sys sys 1115734903 21639
+sys/src/cmd/aux/vga/vesadb.c - 664 sys sys 1115734902 10446
 sys/src/cmd/aux/vga/vga.c - 664 sys sys 1014925013 9305
-sys/src/cmd/aux/vga/vga.h - 664 sys sys 1114453579 10336
+sys/src/cmd/aux/vga/vga.h - 664 sys sys 1115734902 10470
 sys/src/cmd/aux/vga/virge.c - 664 sys sys 1090439328 18587
 sys/src/cmd/aux/vga/vision864.c - 664 sys sys 1014925014 2325
 sys/src/cmd/aux/vga/vision964.c - 664 sys sys 1014925014 3426
@@ -12963,3 +12964,4 @@ usr/glenda/lib/profile - 664 glenda glenda 1105128663 890
 usr/glenda/readme.acme - 664 glenda glenda 1019860628 4753
 usr/glenda/readme.rio - 664 glenda glenda 1019860628 6370
 usr/glenda/tmp - 20000000775 glenda glenda 1018802620 0
+386/bin/aux/vga - 775 sys sys 1115781003 333311

+ 9 - 8
dist/replica/plan9.db

@@ -147,7 +147,7 @@
 386/bin/aux/tr2post - 775 sys sys 1104121987 176578
 386/bin/aux/trampoline - 775 sys sys 1104121988 83293
 386/bin/aux/typepasswd - 775 sys sys 1104121988 69503
-386/bin/aux/vga - 775 sys sys 1114744259 314451
+386/bin/aux/vga - 775 sys sys 1115781003 333311
 386/bin/aux/vmmousepoll - 775 sys sys 1032480572 41434
 386/bin/aux/vmware - 775 sys sys 1049428256 453
 386/bin/aux/vmwarefs - 775 sys sys 1095563640 99117
@@ -824,7 +824,7 @@ alpha/mkfile - 664 sys sys 948141303 46
 amd64 - 20000000775 sys sys 1114458599 0
 amd64/bin - 20000000775 sys sys 1114458475 0
 amd64/include - 20000000775 sys sys 1114458660 0
-amd64/include/u.h - 644 sys sys 1114458660 1658
+amd64/include/u.h - 664 sys sys 1114458660 1658
 amd64/include/ureg.h - 644 sys sys 1114458660 454
 amd64/lib - 20000000775 sys sys 1114458490 0
 amd64/mkfile - 644 sys sys 1114458599 46
@@ -5860,7 +5860,7 @@ sys/src/9/pc/ether8139.c - 664 sys sys 1086987324 18362
 sys/src/9/pc/ether8169.c - 664 sys sys 1110882037 22704
 sys/src/9/pc/ether82543gc.c - 664 sys sys 1055689887 32296
 sys/src/9/pc/ether82557.c - 664 sys sys 1115566440 30076
-sys/src/9/pc/ether83815.c - 664 sys sys 1115476450 23479
+sys/src/9/pc/ether83815.c - 664 sys sys 1115744557 23481
 sys/src/9/pc/ether8390.c - 664 sys sys 1112382834 17701
 sys/src/9/pc/ether8390.h - 664 sys sys 1015014517 1511
 sys/src/9/pc/etherdp83820.c - 664 sys sys 1083469193 29134
@@ -7610,13 +7610,13 @@ sys/src/cmd/aux/vga/io.c - 664 sys sys 1014925009 6222
 sys/src/cmd/aux/vga/mach32.c - 664 sys sys 1014925009 6004
 sys/src/cmd/aux/vga/mach64.c - 664 sys sys 1014925009 8279
 sys/src/cmd/aux/vga/mach64xx.c - 664 sys sys 1097900455 30266
-sys/src/cmd/aux/vga/main.c - 664 sys sys 1114703149 9471
+sys/src/cmd/aux/vga/main.c - 664 sys sys 1115734902 9535
 sys/src/cmd/aux/vga/mga2164w.c - 664 sys sys 1014925010 13196
 sys/src/cmd/aux/vga/mga4xx.c - 664 sys sys 1014925010 35895
-sys/src/cmd/aux/vga/mkfile - 664 sys sys 1114453579 915
+sys/src/cmd/aux/vga/mkfile - 664 sys sys 1115734903 927
 sys/src/cmd/aux/vga/neomagic.c - 664 sys sys 1104430499 8975
 sys/src/cmd/aux/vga/notes.txt - 664 sys sys 1028334647 14376
-sys/src/cmd/aux/vga/nvidia.c - 664 sys sys 1109511456 23718
+sys/src/cmd/aux/vga/nvidia.c - 664 sys sys 1115734903 31499
 sys/src/cmd/aux/vga/palette.c - 664 sys sys 1014925010 2201
 sys/src/cmd/aux/vga/pci.c - 664 sys sys 1014925011 8659
 sys/src/cmd/aux/vga/pci.h - 664 sys sys 1014925011 3290
@@ -7638,9 +7638,10 @@ sys/src/cmd/aux/vga/tvp3025.c - 664 sys sys 1014925013 1960
 sys/src/cmd/aux/vga/tvp3025clock.c - 664 sys sys 1014925013 1511
 sys/src/cmd/aux/vga/tvp3026.c - 664 sys sys 1014925013 3580
 sys/src/cmd/aux/vga/tvp3026clock.c - 664 sys sys 1014925013 1960
-sys/src/cmd/aux/vga/vesa.c - 664 sys sys 1114703149 9421
+sys/src/cmd/aux/vga/vesa.c - 664 sys sys 1115734903 21639
+sys/src/cmd/aux/vga/vesadb.c - 664 sys sys 1115734902 10446
 sys/src/cmd/aux/vga/vga.c - 664 sys sys 1014925013 9305
-sys/src/cmd/aux/vga/vga.h - 664 sys sys 1114453579 10336
+sys/src/cmd/aux/vga/vga.h - 664 sys sys 1115734902 10470
 sys/src/cmd/aux/vga/virge.c - 664 sys sys 1090439328 18587
 sys/src/cmd/aux/vga/vision864.c - 664 sys sys 1014925014 2325
 sys/src/cmd/aux/vga/vision964.c - 664 sys sys 1014925014 3426

+ 9 - 0
dist/replica/plan9.log

@@ -14890,3 +14890,12 @@
 1115568160 1 c sys/src/boot/pc/ether82557.c - 664 sys sys 1115566440 18947
 1115694191 0 c sys/src/9/pc/etherigbe.c - 664 sys sys 1115694068 43995
 1115694191 1 c sys/src/boot/pc/etherigbe.c - 664 sys sys 1115693946 40304
+1115715666 0 m amd64/include/u.h - 664 sys sys 1114458660 1658
+1115735470 0 c sys/src/cmd/aux/vga/main.c - 664 sys sys 1115734902 9535
+1115735470 1 c sys/src/cmd/aux/vga/mkfile - 664 sys sys 1115734903 927
+1115735470 2 c sys/src/cmd/aux/vga/nvidia.c - 664 sys sys 1115734903 31499
+1115735470 3 c sys/src/cmd/aux/vga/vesa.c - 664 sys sys 1115734903 21639
+1115735470 4 a sys/src/cmd/aux/vga/vesadb.c - 664 sys sys 1115734902 10446
+1115735470 5 c sys/src/cmd/aux/vga/vga.h - 664 sys sys 1115734902 10470
+1115746273 0 c sys/src/9/pc/ether83815.c - 664 sys sys 1115744557 23481
+1115782284 0 c 386/bin/aux/vga - 775 sys sys 1115781003 333311

+ 88 - 87
sys/src/9/pc/ether83815.c

@@ -44,13 +44,13 @@ typedef struct Des {
 } Des;
 
 enum {	/* cmdsts */
-	Own		= 1<<31,	/* set by data producer to hand to consumer */
+	Own	= 1<<31,	/* set by data producer to hand to consumer */
 	More	= 1<<30,	/* more of packet in next descriptor */
-	Intr		= 1<<29,	/* interrupt when device is done with it */
+	Intr	= 1<<29,	/* interrupt when device is done with it */
 	Supcrc	= 1<<28,	/* suppress crc on transmit */
 	Inccrc	= 1<<28,	/* crc included on receive (always) */
-	Ok		= 1<<27,	/* packet ok */
-	Size		= 0xFFF,	/* packet size in bytes */
+	Ok	= 1<<27,	/* packet ok */
+	Size	= 0xFFF,	/* packet size in bytes */
 
 	/* transmit */
 	Txa	= 1<<26,	/* transmission aborted */
@@ -70,17 +70,17 @@ enum {	/* cmdsts */
 	  Duni=	1<<23,		/* unicast */
 	  Dmulti=	2<<23,		/* multicast */
 	  Dbroad=	3<<23,		/* broadcast */
-	Long = 1<<22,	/* too long packet received */
-	Runt =  1<<21,	/* packet less than 64 bytes */
-	Ise =	1<<20,	/* invalid symbol */
-	Crce =	1<<19,	/* invalid crc */
-	Fae =	1<<18,	/* frame alignment error */
-	Lbp =	1<<17,	/* loopback packet */
-	Col =	1<<16,	/* collision during receive */
+	Long = 1<<22,		/* too long packet received */
+	Runt =  1<<21,		/* packet less than 64 bytes */
+	Ise =	1<<20,		/* invalid symbol */
+	Crce =	1<<19,		/* invalid crc */
+	Fae =	1<<18,		/* frame alignment error */
+	Lbp =	1<<17,		/* loopback packet */
+	Col =	1<<16,		/* collision during receive */
 };
 
-enum {					/* Variants */
-	Nat83815		= (0x0020<<16)|0x100B,
+enum {				/* Variants */
+	Nat83815	= (0x0020<<16)|0x100B,
 };
 
 typedef struct Ctlr Ctlr;
@@ -92,7 +92,7 @@ typedef struct Ctlr {
 	int	id;			/* (pcidev->did<<16)|pcidev->vid */
 
 	ushort	srom[0xB+1];
-	uchar	sromea[Eaddrlen];			/* MAC address */
+	uchar	sromea[Eaddrlen];	/* MAC address */
 
 	uchar	fd;			/* option or auto negotiation */
 
@@ -133,7 +133,7 @@ typedef struct Ctlr {
 	ulong	ec;
 	ulong	txurn;
 
-	ulong	dperr;		/* system errors */
+	ulong	dperr;			/* system errors */
 	ulong	rmabt;
 	ulong	rtabt;
 	ulong	sserr;
@@ -145,7 +145,7 @@ static Ctlr* ctlrtail;
 
 enum {
 	/* registers (could memory map) */
-	Rcr=		0x00,	/* command register */
+	Rcr=	0x00,		/* command register */
 	  Rst=		1<<8,
 	  Rxr=		1<<5,	/* receiver reset */
 	  Txr=		1<<4,	/* transmitter reset */
@@ -153,8 +153,8 @@ enum {
 	  Rxe=		1<<2,	/* receiver enable */
 	  Txd=		1<<1,	/* transmitter disable */
 	  Txe=		1<<0,	/* transmitter enable */
-	Rcfg=	0x04,	/* configuration */
-	  Lnksts=		1<<31,	/* link good */
+	Rcfg=	0x04,		/* configuration */
+	  Lnksts=	1<<31,	/* link good */
 	  Speed100=	1<<30,	/* 100 Mb/s link */
 	  Fdup=		1<<29,	/* full duplex */
 	  Pol=		1<<28,	/* polarity reversal (10baseT) */
@@ -164,115 +164,115 @@ enum {
 	  Paneg_ena=	1<<13,	/* auto negotiation enable */
 	  Paneg_all=	7<<13,	/* auto negotiation enable 10/100 half & full */
 	  Ext_phy=	1<<12,	/* enable MII for external PHY */
-	  Phy_rst=		1<<10,	/* reset internal PHY */
-	  Phy_dis=		1<<9,	/* disable internal PHY (eg, low power) */
+	  Phy_rst=	1<<10,	/* reset internal PHY */
+	  Phy_dis=	1<<9,	/* disable internal PHY (eg, low power) */
 	  Req_alg=	1<<7,	/* PCI bus request: set means less aggressive */
-	  Sb=			1<<6,	/* single slot back-off not random */
+	  Sb=		1<<6,	/* single slot back-off not random */
 	  Pow=		1<<5,	/* out of window timer selection */
 	  Exd=		1<<4,	/* disable excessive deferral timer */
-	  Pesel=		1<<3,	/* parity error algorithm selection */
+	  Pesel=	1<<3,	/* parity error algorithm selection */
 	  Brom_dis=	1<<2,	/* disable boot rom interface */
 	  Bem=		1<<0,	/* big-endian mode */
-	Rmear=	0x08,	/* eeprom access */
+	Rmear=	0x08,		/* eeprom access */
 	  Mdc=		1<<6,	/* MII mangement check */
-	  Mddir=		1<<5,	/* MII management direction */
+	  Mddir=	1<<5,	/* MII management direction */
 	  Mdio=		1<<4,	/* MII mangement data */
-	  Eesel=		1<<3,	/* EEPROM chip select */
-	  Eeclk=		1<<2,	/* EEPROM clock */
+	  Eesel=	1<<3,	/* EEPROM chip select */
+	  Eeclk=	1<<2,	/* EEPROM clock */
 	  Eedo=		1<<1,	/* EEPROM data out (from chip) */
 	  Eedi=		1<<0,	/* EEPROM data in (to chip) */
-	Rptscr=	0x0C,	/* pci test control */
-	Risr=		0x10,	/* interrupt status */
+	Rptscr=	0x0C,		/* pci test control */
+	Risr=	0x10,		/* interrupt status */
 	  Txrcmp=	1<<25,	/* transmit reset complete */
 	  Rxrcmp=	1<<24,	/* receiver reset complete */
-	  Dperr=		1<<23,	/* detected parity error */
-	  Sserr=		1<<22,	/* signalled system error */
-	  Rmabt=		1<<21,	/* received master abort */
-	  Rtabt=		1<<20,	/* received target abort */
-	  Rxsovr=		1<<16,	/* RX status FIFO overrun */
-	  Hiberr=		1<<15,	/* high bits error set (OR of 25-16) */
+	  Dperr=	1<<23,	/* detected parity error */
+	  Sserr=	1<<22,	/* signalled system error */
+	  Rmabt=	1<<21,	/* received master abort */
+	  Rtabt=	1<<20,	/* received target abort */
+	  Rxsovr=	1<<16,	/* RX status FIFO overrun */
+	  Hiberr=	1<<15,	/* high bits error set (OR of 25-16) */
 	  Phy=		1<<14,	/* PHY interrupt */
 	  Pme=		1<<13,	/* power management event (wake online) */
 	  Swi=		1<<12,	/* software interrupt */
 	  Mib=		1<<11,	/* MIB service */
-	  Txurn=		1<<10,	/* TX underrun */
-	  Txidle=		1<<9,	/* TX idle */
-	  Txerr=		1<<8,	/* TX packet error */
-	  Txdesc=		1<<7,	/* TX descriptor (with Intr bit done) */
+	  Txurn=	1<<10,	/* TX underrun */
+	  Txidle=	1<<9,	/* TX idle */
+	  Txerr=	1<<8,	/* TX packet error */
+	  Txdesc=	1<<7,	/* TX descriptor (with Intr bit done) */
 	  Txok=		1<<6,	/* TX ok */
-	  Rxorn=		1<<5,	/* RX overrun */
-	  Rxidle=		1<<4,	/* RX idle */
-	  Rxearly=		1<<3,	/* RX early threshold */
-	  Rxerr=		1<<2,	/* RX packet error */
-	  Rxdesc=		1<<1,	/* RX descriptor (with Intr bit done) */
+	  Rxorn=	1<<5,	/* RX overrun */
+	  Rxidle=	1<<4,	/* RX idle */
+	  Rxearly=	1<<3,	/* RX early threshold */
+	  Rxerr=	1<<2,	/* RX packet error */
+	  Rxdesc=	1<<1,	/* RX descriptor (with Intr bit done) */
 	  Rxok=		1<<0,	/* RX ok */
-	Rimr=	0x14,	/* interrupt mask */
-	Rier=	0x18,	/* interrupt enable */
-	  Ie=			1<<0,	/* interrupt enable */
-	Rtxdp=	0x20,	/* transmit descriptor pointer */
-	Rtxcfg=	0x24,	/* transmit configuration */
+	Rimr=	0x14,		/* interrupt mask */
+	Rier=	0x18,		/* interrupt enable */
+	  Ie=		1<<0,	/* interrupt enable */
+	Rtxdp=	0x20,		/* transmit descriptor pointer */
+	Rtxcfg=	0x24,		/* transmit configuration */
 	  Csi=		1<<31,	/* carrier sense ignore (needed for full duplex) */
 	  Hbi=		1<<30,	/* heartbeat ignore (needed for full duplex) */
 	  Atp=		1<<28,	/* automatic padding of runt packets */
-	  Mxdma=		7<<20,	/* maximum dma transfer field */
+	  Mxdma=	7<<20,	/* maximum dma transfer field */
 	  Mxdma32=	4<<20,	/* 4x32-bit words (32 bytes) */
 	  Mxdma64=	5<<20,	/* 8x32-bit words (64 bytes) */
-	  Flth=		0x3F<<8,	/* Tx fill threshold, units of 32 bytes (must be > Mxdma) */
-	  Drth=		0x3F<<0,	/* Tx drain threshold (units of 32 bytes) */
-	  Flth128=		4<<8,	/* fill at 128 bytes */
+	  Flth=		0x3F<<8,/* Tx fill threshold, units of 32 bytes (must be > Mxdma) */
+	  Drth=		0x3F<<0,/* Tx drain threshold (units of 32 bytes) */
+	  Flth128=	4<<8,	/* fill at 128 bytes */
 	  Drth512=	16<<0,	/* drain at 512 bytes */
-	Rrxdp=	0x30,	/* receive descriptor pointer */
-	Rrxcfg=	0x34,	/* receive configuration */
+	Rrxdp=	0x30,		/* receive descriptor pointer */
+	Rrxcfg=	0x34,		/* receive configuration */
 	  Atx=		1<<28,	/* accept transmit packets (needed for full duplex) */
-	  Rdrth=		0x1F<<1,	/* Rx drain threshold (units of 32 bytes) */
+	  Rdrth=	0x1F<<1,/* Rx drain threshold (units of 32 bytes) */
 	  Rdrth64=	2<<1,	/* drain at 64 bytes */
-	Rccsr=	0x3C,	/* CLKRUN control/status */
-	  Pmests=		1<<15,	/* PME status */
-	Rwcsr=	0x40,	/* wake on lan control/status */
-	Rpcr=	0x44,	/* pause control/status */
-	Rrfcr=	0x48,	/* receive filter/match control */
+	Rccsr=	0x3C,		/* CLKRUN control/status */
+	  Pmests=	1<<15,	/* PME status */
+	Rwcsr=	0x40,		/* wake on lan control/status */
+	Rpcr=	0x44,		/* pause control/status */
+	Rrfcr=	0x48,		/* receive filter/match control */
 	  Rfen=		1<<31,	/* receive filter enable */
 	  Aab=		1<<30,	/* accept all broadcast */
 	  Aam=		1<<29,	/* accept all multicast */
 	  Aau=		1<<28,	/* accept all unicast */
 	  Apm=		1<<27,	/* accept on perfect match */
-	  Apat=		0xF<<23,	/* accept on pattern match */
+	  Apat=		0xF<<23,/* accept on pattern match */
 	  Aarp=		1<<22,	/* accept ARP */
 	  Mhen=		1<<21,	/* multicast hash enable */
 	  Uhen=		1<<20,	/* unicast hash enable */
 	  Ulm=		1<<19,	/* U/L bit mask */
-						/* bits 0-9 are rfaddr */
-	Rrfdr=	0x4C,	/* receive filter/match data */
-	Rbrar=	0x50,	/* boot rom address */
-	Rbrdr=	0x54,	/* boot rom data */
-	Rsrr=	0x58,	/* silicon revision */
-	Rmibc=	0x5C,	/* MIB control */
-					/* 60-78 MIB data */
+				/* bits 0-9 are rfaddr */
+	Rrfdr=	0x4C,		/* receive filter/match data */
+	Rbrar=	0x50,		/* boot rom address */
+	Rbrdr=	0x54,		/* boot rom data */
+	Rsrr=	0x58,		/* silicon revision */
+	Rmibc=	0x5C,		/* MIB control */
+				/* 60-78 MIB data */
 
 	/* PHY registers */
-	Rbmcr=	0x80,	/* basic mode configuration */
-	  Reset=		1<<15,
-	  Sel100=		1<<13,	/* select 100Mb/sec if no auto neg */
-	  Anena=		1<<12,	/* auto negotiation enable */
+	Rbmcr=	0x80,		/* basic mode configuration */
+	  Reset=	1<<15,
+	  Sel100=	1<<13,	/* select 100Mb/sec if no auto neg */
+	  Anena=	1<<12,	/* auto negotiation enable */
 	  Anrestart=	1<<9,	/* restart auto negotiation */
-	  Selfdx=		1<<8,	/* select full duplex if no auto neg */
-	Rbmsr=	0x84,	/* basic mode status */
+	  Selfdx=	1<<8,	/* select full duplex if no auto neg */
+	Rbmsr=	0x84,		/* basic mode status */
 	  Ancomp=	1<<5,	/* autonegotiation complete */
 	Rphyidr1= 0x88,
 	Rphyidr2= 0x8C,
-	Ranar=	0x90,	/* autonegotiation advertisement */
-	Ranlpar=	0x94,	/* autonegotiation link partner ability */
-	Raner=	0x98,	/* autonegotiation expansion */
-	Rannptr=	0x9C,	/* autonegotiation next page TX */
-	Rphysts=	0xC0,	/* PHY status */
-	Rmicr=	0xC4,	/* MII control */
-	  Inten=		1<<1,	/* PHY interrupt enable */
-	Rmisr=	0xC8,	/* MII status */
-	Rfcscr=	0xD0,	/* false carrier sense counter */
-	Rrecr=	0xD4,	/* receive error counter */
-	Rpcsr=	0xD8,	/* 100Mb config/status */
-	Rphycr=	0xE4,	/* PHY control */
-	Rtbscr=	0xE8,	/* 10BaseT status/control */
+	Ranar=	0x90,		/* autonegotiation advertisement */
+	Ranlpar= 0x94,		/* autonegotiation link partner ability */
+	Raner=	0x98,		/* autonegotiation expansion */
+	Rannptr= 0x9C,		/* autonegotiation next page TX */
+	Rphysts= 0xC0,		/* PHY status */
+	Rmicr=	0xC4,		/* MII control */
+	  Inten=	1<<1,	/* PHY interrupt enable */
+	Rmisr=	0xC8,		/* MII status */
+	Rfcscr=	0xD0,		/* false carrier sense counter */
+	Rrecr=	0xD4,		/* receive error counter */
+	Rpcsr=	0xD8,		/* 100Mb config/status */
+	Rphycr=	0xE4,		/* PHY control */
+	Rtbscr=	0xE8,		/* 10BaseT status/control */
 };
 
 /*
@@ -771,6 +771,7 @@ softreset(Ctlr* ctlr, int resetphys)
 		w &= 0xFFFF;
 		debug("bmsr: %4.4ux\n", w);
 	}
+	USED(w);
 	debug("anar: %4.4ux\n", csr16r(ctlr, Ranar));
 	debug("anlpar: %4.4ux\n", csr16r(ctlr, Ranlpar));
 	debug("aner: %4.4ux\n", csr16r(ctlr, Raner));

+ 3 - 1
sys/src/cmd/aux/vga/main.c

@@ -401,8 +401,10 @@ main(int argc, char** argv)
 			 * Set type to vesa for linear.
 			 */
 			if(vga->vesa){
-				vgactlw("type", vesa.name);
 				vesa.load(vga, vga->vesa);
+				if(vga->vesa->flag&Ferror)
+					error("vesa load error\n");
+				vgactlw("type", vesa.name);
 			}
 
 			/*

+ 1 - 0
sys/src/cmd/aux/vga/mkfile

@@ -52,6 +52,7 @@ OFILES=\
 	tvp3026.$O\
 	tvp3026clock.$O\
 	vesa.$O\
+	vesadb.$O\
 	vga.$O\
 	virge.$O\
 	vision864.$O\

+ 376 - 103
sys/src/cmd/aux/vga/nvidia.c

@@ -49,12 +49,13 @@
 
 typedef struct Nvidia	Nvidia;
 struct Nvidia {
-	ulong	mmio;
 	Pcidev*	pci;
+	int	did;	/* not always == pci->did */
 
 	int	arch;
 	int	crystalfreq;
 
+	ulong*	mmio;
 	ulong*	pfb;			/* mmio pointers */
 	ulong*	pramdac;
 	ulong*	pextdev;
@@ -77,6 +78,8 @@ struct Nvidia {
 	ushort	interlace;
 	ushort	extra;
 	ushort	crtcowner;
+	ushort	timingH;
+	ushort	timingV;
 
 	ulong	vpll;
 	ulong	vpllB;
@@ -90,6 +93,8 @@ struct Nvidia {
 	ulong	head2;
 	ulong	cursorconfig;
 	ulong	dither;
+	ulong	crtcsync;
+	ulong	displayV;
 
 	int	islcd;
 	int	fpwidth;
@@ -99,6 +104,27 @@ struct Nvidia {
 	int	crtcnumber;
 };
 
+static void
+getpcixdid(Nvidia* nv)
+{
+	ulong	pcicmd, pciid;
+	ushort	vid, did;
+
+	pcicmd = pcicfgr32(nv->pci, PciPCR);
+	pcicfgw32(nv->pci, PciPCR, pcicmd | 0x02);
+	pciid = nv->mmio[0x1800/4];
+	pcicfgw32(nv->pci, PciPCR, pcicmd);
+
+	vid = pciid >> 16;
+	did = (pciid & 0xFFFF);
+	if (did == 0x10DE)
+		did = vid;
+	else if (vid == 0xDE10)
+		did = ((pciid << 8) & 0xFF00) | ((pciid >> 8) & 0x00FF);
+
+	nv->did = did;
+}
+
 static void
 snarf(Vga* vga, Ctlr* ctlr)
 {
@@ -118,12 +144,52 @@ snarf(Vga* vga, Ctlr* ctlr)
 		}
 		if(p == nil)
 			error("%s: not found\n", ctlr->name);
-		nv->arch = ((p->did&0x0F00) >> 8) * 10;
-		if(nv->arch == 0)
-			nv->arch = 4;
-		if((p->did < 0x20) || (nv->arch > 30))
-			error("%s: DID %4.4uX unsupported\n", ctlr->name, p->did);
 
+		nv->did = p->did;
+		if ((nv->did & 0xfff0) == 0x00f0)
+			getpcixdid(nv);
+
+		switch (nv->did & 0x0ff0) {
+		case 0x0020:
+		case 0x00A0:
+			nv->arch = 4;
+			break;
+		case 0x0100:   /* GeForce 256 */
+		case 0x0110:   /* GeForce2 MX */
+		case 0x0150:   /* GeForce2 */
+		case 0x0170:   /* GeForce4 MX */
+		case 0x0180:   /* GeForce4 MX (8x AGP) */
+		case 0x01A0:   /* nForce */
+		case 0x01F0:   /* nForce2 */
+			nv->arch = 10;
+			break;
+		case 0x0200:   /* GeForce3 */
+		case 0x0250:   /* GeForce4 Ti */
+		case 0x0280:   /* GeForce4 Ti (8x AGP) */
+			nv->arch = 20;
+			break;
+		case 0x0300:   /* GeForceFX 5800 */
+		case 0x0310:   /* GeForceFX 5600 */
+		case 0x0320:   /* GeForceFX 5200 */
+		case 0x0330:   /* GeForceFX 5900 */
+		case 0x0340:   /* GeForceFX 5700 */
+			nv->arch = 30;
+			break;
+		case 0x0040:
+		case 0x00C0:
+		case 0x0120:
+		case 0x0130:
+		case 0x0140:
+		case 0x0160:
+		case 0x01D0:
+		case 0x0090:
+		case 0x0210:
+			nv->arch = 40;
+			break;
+		default:
+			error("%s: DID %4.4uX unsupported\n", ctlr->name, nv->did);
+			break;
+		}
 		vgactlw("type", ctlr->name);
 
 		if((m = segattach(0, "nvidiammio", 0, p->mem[0].size)) == -1)
@@ -131,7 +197,7 @@ snarf(Vga* vga, Ctlr* ctlr)
 				ctlr->name, p->mem[0].size);
 
 		nv->pci = p;
-		nv->mmio = m;
+		nv->mmio = (ulong*)m;
 
 		mmio = (ulong*)m;
 		nv->pfb = mmio+0x00100000/4;
@@ -143,10 +209,10 @@ snarf(Vga* vga, Ctlr* ctlr)
 		nv->pramin = mmio+0x00710000/4;
 		nv->pgraph = mmio+0x00400000/4;
 		nv->fifo = mmio+0x00800000/4;
-		nv->pcrtc= mmio+0x00600000/4;
+		nv->pcrtc= mmio+0x00600000/4;		
 	}
 	nv = vga->private;
-	implementation = nv->pci->did & 0x0ff0;
+	implementation = nv->did & 0x0ff0;
 
 	/*
 	 * Unlock
@@ -165,16 +231,22 @@ snarf(Vga* vga, Ctlr* ctlr)
 		if(nv->pextdev[0x00000000] & (1 << 22))
 			nv->crystalfreq = 27000000;
 
-	nv->twoheads = (implementation >= 0x0110) &&
-				    (implementation != 0x0150) &&
-				    (implementation != 0x01A0) &&
-				    (implementation != 0x0200);
+	nv->twoheads = (nv->arch >= 10) &&
+			(implementation != 0x0100) &&
+			(implementation != 0x0150) &&
+			(implementation != 0x01A0) &&
+			(implementation != 0x0200);
 
 	nv->twostagepll = (implementation == 0x0310) ||
-					(implementation == 0x0340);
+				(implementation == 0x0340) ||
+				(nv->arch >= 40);
+
+	if (nv->twoheads && (implementation != 0x0110))
+		if(nv->pextdev[0x00000000] & (1 << 22))
+			nv->crystalfreq = 27000000;
 
 	/* laptop chips */
-	switch (nv->pci->did & 0xffff) {
+	switch (nv->did & 0xffff) {
 	case 0x0112:
 	case 0x0174:
 	case 0x0175:
@@ -185,7 +257,8 @@ snarf(Vga* vga, Ctlr* ctlr)
 	case 0x017D:
 	case 0x0186:
 	case 0x0187:
-	case 0x0189:
+	case 0x0189:	/* 0x0189 not in nwaples's driver */
+	case 0x018D:
 	case 0x0286:
 	case 0x028C:
 	case 0x0316:
@@ -207,6 +280,13 @@ snarf(Vga* vga, Ctlr* ctlr)
 	case 0x0349:
 	case 0x034B:
 	case 0x034C:
+	case 0x0160:
+	case 0x0166:
+	case 0x00C8:
+	case 0x00CC:
+	case 0x0144:
+	case 0x0146:
+	case 0x0148:
 		nv->islcd = 1;
 		break;
 	default:
@@ -224,11 +304,28 @@ snarf(Vga* vga, Ctlr* ctlr)
 			else
 				vga->vmz = 1024*1024*32;
 		}
+	} else if (implementation == 0x01a0) {
+		p = nil;
+		tmp = MKBUS(BusPCI, 0, 0, 1);
+		while((p = pcimatch(p, 0x10DE, 0)) != nil){
+			if(p->tbdf == tmp)
+				break;
+		}
+		tmp = pcicfgr32(p, 0x7C);
+		vga->vmz = (((tmp >> 6) & 31) + 1) * 1024 * 1024;
+	} else if (implementation == 0x01f0) {
+		p = nil;
+		tmp = MKBUS(BusPCI, 0, 0, 1);
+		while((p = pcimatch(p, 0x10DE, 0)) != nil){
+			if(p->tbdf == tmp)
+				break;
+		}
+		tmp = pcicfgr32(p, 0x84);
+		vga->vmz = (((tmp >> 4) & 127) + 1) * 1024 * 1024;
 	} else {
-		tmp = (nv->pfb[0x0000020C/4] >> 20) & 0xFF;
+		tmp = (nv->pfb[0x0000020C/4] >> 20) & 0xFFF;
 		if (tmp == 0)
 			tmp = 16;
-
 		vga->vmz = 1024*1024*tmp;
 	}
 
@@ -254,6 +351,10 @@ snarf(Vga* vga, Ctlr* ctlr)
 	nv->scale = nv->pramdac[0x00000848/4];
 	nv->config = nv->pfb[0x00000200/4];
 
+	if (nv->pixel & 0x80){
+		nv->islcd = 1;
+	}
+
 	if (nv->arch >= 10) {
 		if (nv->twoheads) {
 			nv->head = nv->pcrtc[0x0860/4];
@@ -264,17 +365,17 @@ snarf(Vga* vga, Ctlr* ctlr)
 		nv->cursorconfig = nv->pcrtc[0x0810/4];
 		if (implementation == 0x0110)
 			nv->dither = nv->pramdac[0x0528/4];
-		else if (implementation >= 0x0170)
+		else if (nv->twoheads)
 			nv->dither = nv->pramdac[0x083C/4];
 	}
 
 	/*
 	 * DFP.
 	 */
-	if (nv->pixel & 0x80){
-		nv->islcd = 1;
+	if (nv->islcd) {
        		nv->fpwidth = nv->pramdac[0x0820/4] + 1;
        		nv->fpheight = nv->pramdac[0x0800/4] + 1;
+		nv->crtcsync = nv->pramdac[0x0828/4];
 	}
 
 	nv->crtcnumber = 0;
@@ -521,9 +622,17 @@ init(Vga* vga, Ctlr* ctlr)
 		nv->head |= 0x00001000;
 		nv->head2 |= ~0x00001000;
 		nv->crtcowner = 0;
+		if((nv->did & 0x0ff0) == 0x0110)
+			nv->dither &= ~0x00010000;
+		else
+			nv->dither &= ~1;
 	}
 	nv->cursorconfig = 0x00000100 | 0x02000000;
 
+	nv->timingH = 0;
+	nv->timingV = 0;
+	nv->displayV = vga->crt[0x12] + 1;
+
 	ctlr->flag |= Finit;
 }
 
@@ -559,68 +668,140 @@ load(Vga* vga, Ctlr* ctlr)
 		}
 	}
 
-	nv->pramin[0x0000] = 0x80000010;
-	nv->pramin[0x0001] = 0x80011201;  
-	nv->pramin[0x0002] = 0x80000011;
-	nv->pramin[0x0003] = 0x80011202; 
-	nv->pramin[0x0004] = 0x80000012;
-	nv->pramin[0x0005] = 0x80011203;
-	nv->pramin[0x0006] = 0x80000013;
-	nv->pramin[0x0007] = 0x80011204;
-	nv->pramin[0x0008] = 0x80000014;
-	nv->pramin[0x0009] = 0x80011205;
-	nv->pramin[0x000A] = 0x80000015;
-	nv->pramin[0x000B] = 0x80011206;
-	nv->pramin[0x000C] = 0x80000016;
-	nv->pramin[0x000D] = 0x80011207;
-	nv->pramin[0x000E] = 0x80000017;
-	nv->pramin[0x000F] = 0x80011208;
-	nv->pramin[0x0800] = 0x00003000;
-	nv->pramin[0x0801] = vga->vmz - 1;
-	nv->pramin[0x0802] = 0x00000002;
-	nv->pramin[0x0803] = 0x00000002;
-	if (nv->arch >= 10)
-		nv->pramin[0x0804] = 0x01008062;
-	else
-		nv->pramin[0x0804] = 0x01008042;
-	nv->pramin[0x0805] = 0x00000000;
-	nv->pramin[0x0806] = 0x12001200;
-	nv->pramin[0x0807] = 0x00000000;
-	nv->pramin[0x0808] = 0x01008043;
-	nv->pramin[0x0809] = 0x00000000;
-	nv->pramin[0x080A] = 0x00000000;
-	nv->pramin[0x080B] = 0x00000000;
-	nv->pramin[0x080C] = 0x01008044;
-	nv->pramin[0x080D] = 0x00000002;
-	nv->pramin[0x080E] = 0x00000000;
-	nv->pramin[0x080F] = 0x00000000;
-	nv->pramin[0x0810] = 0x01008019;
-	nv->pramin[0x0811] = 0x00000000;
-	nv->pramin[0x0812] = 0x00000000;
-	nv->pramin[0x0813] = 0x00000000;
-	nv->pramin[0x0814] = 0x0100A05C;
-	nv->pramin[0x0815] = 0x00000000;
-	nv->pramin[0x0816] = 0x00000000;
-	nv->pramin[0x0817] = 0x00000000;
-	nv->pramin[0x0818] = 0x0100805F;
-	nv->pramin[0x0819] = 0x00000000;
-	nv->pramin[0x081A] = 0x12001200;
-	nv->pramin[0x081B] = 0x00000000;
-	nv->pramin[0x081C] = 0x0100804A;
-	nv->pramin[0x081D] = 0x00000002;
-	nv->pramin[0x081E] = 0x00000000;
-	nv->pramin[0x081F] = 0x00000000;
-	nv->pramin[0x0820] = 0x01018077;
-	nv->pramin[0x0821] = 0x00000000;
-	nv->pramin[0x0822] = 0x01201200;
-	nv->pramin[0x0823] = 0x00000000;
-	nv->pramin[0x0824] = 0x00003002;
-	nv->pramin[0x0825] = 0x00007FFF;
-	nv->pramin[0x0826] = (vga->vmz - 128 * 1024) | 0x00000002;
-	nv->pramin[0x0827] = 0x00000002;
-
+	if (nv->arch >= 40) {
+		nv->pramin[0x0000] = 0x80000010;
+		nv->pramin[0x0001] = 0x00101202;
+		nv->pramin[0x0002] = 0x80000011;
+		nv->pramin[0x0003] = 0x00101204;
+		nv->pramin[0x0004] = 0x80000012;
+		nv->pramin[0x0005] = 0x00101206;
+		nv->pramin[0x0006] = 0x80000013;
+		nv->pramin[0x0007] = 0x00101208;
+		nv->pramin[0x0008] = 0x80000014;
+		nv->pramin[0x0009] = 0x0010120A;
+		nv->pramin[0x000A] = 0x80000015;
+		nv->pramin[0x000B] = 0x0010120C;
+		nv->pramin[0x000C] = 0x80000016;
+		nv->pramin[0x000D] = 0x0010120E;
+		nv->pramin[0x000E] = 0x80000017;
+		nv->pramin[0x000F] = 0x00101210;
+		nv->pramin[0x0800] = 0x00003000;
+		nv->pramin[0x0801] = vga->vmz - 1;
+		nv->pramin[0x0802] = 0x00000002;
+		nv->pramin[0x0808] = 0x02080062;
+		nv->pramin[0x0809] = 0x00000000;
+		nv->pramin[0x080A] = 0x00001200;
+		nv->pramin[0x080B] = 0x00001200;
+		nv->pramin[0x080C] = 0x00000000;
+		nv->pramin[0x080D] = 0x00000000;
+		nv->pramin[0x0810] = 0x02080043;
+		nv->pramin[0x0811] = 0x00000000;
+		nv->pramin[0x0812] = 0x00000000;
+		nv->pramin[0x0813] = 0x00000000;
+		nv->pramin[0x0814] = 0x00000000;
+		nv->pramin[0x0815] = 0x00000000;
+		nv->pramin[0x0818] = 0x02080044;
+		nv->pramin[0x0819] = 0x02000000;
+		nv->pramin[0x081A] = 0x00000000;
+		nv->pramin[0x081B] = 0x00000000;
+		nv->pramin[0x081C] = 0x00000000;
+		nv->pramin[0x081D] = 0x00000000;
+		nv->pramin[0x0820] = 0x02080019;
+		nv->pramin[0x0821] = 0x00000000;
+		nv->pramin[0x0822] = 0x00000000;
+		nv->pramin[0x0823] = 0x00000000;
+		nv->pramin[0x0824] = 0x00000000;
+		nv->pramin[0x0825] = 0x00000000;
+		nv->pramin[0x0828] = 0x020A005C;
+		nv->pramin[0x0829] = 0x00000000;
+		nv->pramin[0x082A] = 0x00000000;
+		nv->pramin[0x082B] = 0x00000000;
+		nv->pramin[0x082C] = 0x00000000;
+		nv->pramin[0x082D] = 0x00000000;
+		nv->pramin[0x0830] = 0x0208009F;
+		nv->pramin[0x0831] = 0x00000000;
+		nv->pramin[0x0832] = 0x00001200;
+		nv->pramin[0x0833] = 0x00001200;
+		nv->pramin[0x0834] = 0x00000000;
+		nv->pramin[0x0835] = 0x00000000;
+		nv->pramin[0x0838] = 0x0208004A;
+		nv->pramin[0x0839] = 0x02000000;
+		nv->pramin[0x083A] = 0x00000000;
+		nv->pramin[0x083B] = 0x00000000;
+		nv->pramin[0x083C] = 0x00000000;
+		nv->pramin[0x083D] = 0x00000000;
+		nv->pramin[0x0840] = 0x02080077;
+		nv->pramin[0x0841] = 0x00000000;
+		nv->pramin[0x0842] = 0x00001200;
+		nv->pramin[0x0843] = 0x00001200;
+		nv->pramin[0x0844] = 0x00000000;
+		nv->pramin[0x0845] = 0x00000000;
+		nv->pramin[0x084C] = 0x00003002;
+		nv->pramin[0x084D] = 0x00007FFF;
+		nv->pramin[0x084E] = (vga->vmz - 128 * 1024) | 0x00000002;
+	} else {
+		nv->pramin[0x0000] = 0x80000010;
+		nv->pramin[0x0001] = 0x80011201;  
+		nv->pramin[0x0002] = 0x80000011;
+		nv->pramin[0x0003] = 0x80011202; 
+		nv->pramin[0x0004] = 0x80000012;
+		nv->pramin[0x0005] = 0x80011203;
+		nv->pramin[0x0006] = 0x80000013;
+		nv->pramin[0x0007] = 0x80011204;
+		nv->pramin[0x0008] = 0x80000014;
+		nv->pramin[0x0009] = 0x80011205;
+		nv->pramin[0x000A] = 0x80000015;
+		nv->pramin[0x000B] = 0x80011206;
+		nv->pramin[0x000C] = 0x80000016;
+		nv->pramin[0x000D] = 0x80011207;
+		nv->pramin[0x000E] = 0x80000017;
+		nv->pramin[0x000F] = 0x80011208;
+		nv->pramin[0x0800] = 0x00003000;
+		nv->pramin[0x0801] = vga->vmz - 1;
+		nv->pramin[0x0802] = 0x00000002;
+		nv->pramin[0x0803] = 0x00000002;
+		if (nv->arch >= 10)
+			nv->pramin[0x0804] = 0x01008062;
+		else
+			nv->pramin[0x0804] = 0x01008042;
+		nv->pramin[0x0805] = 0x00000000;
+		nv->pramin[0x0806] = 0x12001200;
+		nv->pramin[0x0807] = 0x00000000;
+		nv->pramin[0x0808] = 0x01008043;
+		nv->pramin[0x0809] = 0x00000000;
+		nv->pramin[0x080A] = 0x00000000;
+		nv->pramin[0x080B] = 0x00000000;
+		nv->pramin[0x080C] = 0x01008044;
+		nv->pramin[0x080D] = 0x00000002;
+		nv->pramin[0x080E] = 0x00000000;
+		nv->pramin[0x080F] = 0x00000000;
+		nv->pramin[0x0810] = 0x01008019;
+		nv->pramin[0x0811] = 0x00000000;
+		nv->pramin[0x0812] = 0x00000000;
+		nv->pramin[0x0813] = 0x00000000;
+		nv->pramin[0x0814] = 0x0100A05C;
+		nv->pramin[0x0815] = 0x00000000;
+		nv->pramin[0x0816] = 0x00000000;
+		nv->pramin[0x0817] = 0x00000000;
+		nv->pramin[0x0818] = 0x0100805F;
+		nv->pramin[0x0819] = 0x00000000;
+		nv->pramin[0x081A] = 0x12001200;
+		nv->pramin[0x081B] = 0x00000000;
+		nv->pramin[0x081C] = 0x0100804A;
+		nv->pramin[0x081D] = 0x00000002;
+		nv->pramin[0x081E] = 0x00000000;
+		nv->pramin[0x081F] = 0x00000000;
+		nv->pramin[0x0820] = 0x01018077;
+		nv->pramin[0x0821] = 0x00000000;
+		nv->pramin[0x0822] = 0x01201200;
+		nv->pramin[0x0823] = 0x00000000;
+		nv->pramin[0x0824] = 0x00003002;
+		nv->pramin[0x0825] = 0x00007FFF;
+		nv->pramin[0x0826] = (vga->vmz - 128 * 1024) | 0x00000002;
+		nv->pramin[0x0827] = 0x00000002;
+	}
 	if (nv->arch < 10) {
-		if((nv->pci->did & 0x0fff) == 0x0020) {
+		if((nv->did & 0x0fff) == 0x0020) {
 			nv->pramin[0x0824] |= 0x00020000;
 			nv->pramin[0x0826] += nv->pci->mem[1].bar;
 		}
@@ -629,6 +810,7 @@ load(Vga* vga, Ctlr* ctlr)
 		nv->pgraph[0x0084/4] = 0x72111101;
 		nv->pgraph[0x0088/4] = 0x11D5F071;
 		nv->pgraph[0x008C/4] = 0x0004FF31;
+		nv->pgraph[0x008C/4] = 0x4004FF31;
 
 		nv->pgraph[0x0140/4] = 0x00000000;
 		nv->pgraph[0x0100/4] = 0xFFFFFFFF;
@@ -637,6 +819,7 @@ load(Vga* vga, Ctlr* ctlr)
 		nv->pgraph[0x0720/4] = 0x00000001;
 
 		nv->pgraph[0x0810/4] = 0x00000000;
+		nv->pgraph[0x0608/4] = 0xFFFFFFFF;
 	} else {
 		nv->pgraph[0x0080/4] = 0xFFFFFFFF;
 		nv->pgraph[0x0080/4] = 0x00000000;
@@ -646,6 +829,8 @@ load(Vga* vga, Ctlr* ctlr)
 		nv->pgraph[0x0144/4] = 0x10010100;
 		nv->pgraph[0x0714/4] = 0xFFFFFFFF;
 		nv->pgraph[0x0720/4] = 0x00000001;
+		nv->pgraph[0x0710/4] &= 0x0007ff00;
+		nv->pgraph[0x0710/4] |= 0x00020100;
 
 		if (nv->arch == 10) {
 			nv->pgraph[0x0084/4] = 0x00118700;
@@ -661,8 +846,54 @@ load(Vga* vga, Ctlr* ctlr)
 			nv->pgraph[0x688/4] = vga->vmz - 1;
 
 			nv->pgraph[0x0810/4] = 0x00000000;
+			nv->pgraph[0x0608/4] = 0xFFFFFFFF;
 		} else {
-			if(nv->arch >= 30) {
+			if (nv->arch >= 40) {
+				nv->pgraph[0x0084/4] = 0x401287c0;
+				nv->pgraph[0x008C/4] = 0x60de8051;
+				nv->pgraph[0x0090/4] = 0x00008000;
+				nv->pgraph[0x0610/4] = 0x00be3c5f;
+
+				if ((nv->did & 0xfff0) == 0x0040) {
+					nv->pgraph[0x09b0/4] = 0x83280fff;
+					nv->pgraph[0x09b4/4] = 0x000000a0;
+				} else {
+					nv->pgraph[0x0820/4] = 0x83280eff;
+					nv->pgraph[0x0824/4] = 0x000000a0;
+				}
+
+				switch(nv->did & 0xfff0) {
+				case 0x0040:
+					nv->pgraph[0x09b8/4] = 0x0078e366;
+					nv->pgraph[0x09bc/4] = 0x0000014c;
+					nv->pfb[0x033C/4] &= 0xffff7fff;
+					break;
+				case 0x00C0:
+					nv->pgraph[0x0828/4] = 0x007596ff;
+					nv->pgraph[0x082C/4] = 0x00000108;
+					break;
+				case 0x0160:
+					nv->pmc[0x1700/4] = nv->pfb[0x020C/4];
+					nv->pmc[0x1704/4] = 0;
+					nv->pmc[0x1708/4] = 0;
+					nv->pmc[0x170C/4] = nv->pfb[0x020C/4];
+					nv->pgraph[0x0860/4] = 0;
+					nv->pgraph[0x0864/4] = 0;
+					nv->pramdac[0x0608/4] |= 0x00100000;
+					break;
+				case 0x0140:
+					nv->pgraph[0x0828/4] = 0x0072cb77;
+					nv->pgraph[0x082C/4] = 0x00000108;
+					break;
+				default:
+					break;
+				};
+
+				nv->pgraph[0x0b38/4] = 0x2ffff800;
+				nv->pgraph[0x0b3c/4] = 0x00006000;
+				nv->pgraph[0x032C/4] = 0x01000000; 
+				nv->pgraph[0x0220/4] = 0x00001200;
+			} else if (nv->arch == 30) {
 				nv->pgraph[0x0084/4] = 0x40108700;
 				nv->pgraph[0x0890/4] = 0x00140000;
 				nv->pgraph[0x008C/4] = 0xf00e0431;
@@ -676,7 +907,7 @@ load(Vga* vga, Ctlr* ctlr)
 				nv->pgraph[0x0090/4] = 0x00000000;
 				nv->pgraph[0x009C/4] = 0x00000040;
 
-				if((nv->pci->did & 0x0ff0) >= 0x0250) {
+				if((nv->did & 0x0ff0) >= 0x0250) {
 					nv->pgraph[0x0890/4] = 0x00080000;
 					nv->pgraph[0x0610/4] = 0x304B1FB6; 
 					nv->pgraph[0x0B80/4] = 0x18B82880; 
@@ -699,19 +930,44 @@ load(Vga* vga, Ctlr* ctlr)
 			for(i = 0; i < 32; i++)
 				nv->pgraph[(0x0900/4) + i] = nv->pfb[(0x0240/4) + i];
 
-			nv->pgraph[0x09A4/4] = nv->pfb[0x0200/4];
-			nv->pgraph[0x09A8/4] = nv->pfb[0x0204/4];
-			nv->pgraph[0x0750/4] = 0x00EA0000;
-			nv->pgraph[0x0754/4] = nv->pfb[0x0200/4];
-			nv->pgraph[0x0750/4] = 0x00EA0004;
-			nv->pgraph[0x0754/4] = nv->pfb[0x0204/4];
-
-			nv->pgraph[0x0820/4] = 0;
-			nv->pgraph[0x0824/4] = 0;
-			nv->pgraph[0x0864/4] = vga->vmz - 1;
-			nv->pgraph[0x0868/4] = vga->vmz - 1;
+			if(nv->arch >= 40) {
+				if((nv->did & 0xfff0) == 0x0040) {
+					nv->pgraph[0x09A4/4] = nv->pfb[0x0200/4];
+					nv->pgraph[0x09A8/4] = nv->pfb[0x0204/4];
+					nv->pgraph[0x69A4/4] = nv->pfb[0x0200/4];
+					nv->pgraph[0x69A8/4] = nv->pfb[0x0204/4];
+
+					nv->pgraph[0x0820/4] = 0;
+					nv->pgraph[0x0824/4] = 0;
+					nv->pgraph[0x0864/4] = vga->vmz - 1;
+					nv->pgraph[0x0868/4] = vga->vmz - 1;
+				} else {
+					nv->pgraph[0x09F0/4] = nv->pfb[0x0200/4];
+					nv->pgraph[0x09F4/4] = nv->pfb[0x0204/4];
+					nv->pgraph[0x69F0/4] = nv->pfb[0x0200/4];
+					nv->pgraph[0x69F4/4] = nv->pfb[0x0204/4];
+
+					nv->pgraph[0x0840/4] = 0;
+					nv->pgraph[0x0844/4] = 0;
+					nv->pgraph[0x08a0/4] = vga->vmz - 1;
+					nv->pgraph[0x08a4/4] = vga->vmz - 1;
+				}
+			} else {
+				nv->pgraph[0x09A4/4] = nv->pfb[0x0200/4];
+				nv->pgraph[0x09A8/4] = nv->pfb[0x0204/4];
+				nv->pgraph[0x0750/4] = 0x00EA0000;
+				nv->pgraph[0x0754/4] = nv->pfb[0x0200/4];
+				nv->pgraph[0x0750/4] = 0x00EA0004;
+				nv->pgraph[0x0754/4] = nv->pfb[0x0204/4];
+
+				nv->pgraph[0x0820/4] = 0;
+				nv->pgraph[0x0824/4] = 0;
+				nv->pgraph[0x0864/4] = vga->vmz - 1;
+				nv->pgraph[0x0868/4] = vga->vmz - 1;
+			}
 
 			nv->pgraph[0x0B20/4] = 0x00000000;
+			nv->pgraph[0x0B04/4] = 0xFFFFFFFF;
 		}
 	}
 
@@ -724,10 +980,16 @@ load(Vga* vga, Ctlr* ctlr)
 	nv->pfifo[0x0141] = 0x00000001;
 	nv->pfifo[0x0480] = 0x00000000;
 	nv->pfifo[0x0494] = 0x00000000;
-	nv->pfifo[0x0481] = 0x00000100;
+	if (nv->arch >= 40)
+		nv->pfifo[0x0481] = 0x00010000;
+	else
+		nv->pfifo[0x0481] = 0x00000100;
 	nv->pfifo[0x0490] = 0x00000000;
 	nv->pfifo[0x0491] = 0x00000000;
-	nv->pfifo[0x048B] = 0x00001209;
+	if (nv->arch >= 40)
+		nv->pfifo[0x048B] = 0x00001213;
+	else
+		nv->pfifo[0x048B] = 0x00001209;
 	nv->pfifo[0x0400] = 0x00000000;
 	nv->pfifo[0x0414] = 0x00000000;
 	nv->pfifo[0x0084] = 0x03000100;
@@ -763,14 +1025,16 @@ load(Vga* vga, Ctlr* ctlr)
 		nv->pmc[0x1588/4] = 0;
 
 		nv->pcrtc[0x0810/4] = nv->cursorconfig;
+		nv->pcrtc[0x0830/4] = nv->displayV - 3;
+		nv->pcrtc[0x0834/4] = nv->displayV - 1;
 
 		if (nv->islcd) {
-			if((nv->pci->did & 0x0ff0) == 0x0110)
+			if((nv->did & 0x0ff0) == 0x0110)
 				nv->pramdac[0x0528/4] = nv->dither;
-			else if((nv->pci->did & 0x0ff0) >= 0x0170)
+			else if (nv->twoheads)
 				nv->pramdac[0x083C/4] = nv->dither;
-			vgaxo(Crtx, 0x53, 0);
-			vgaxo(Crtx, 0x54, 0);
+			vgaxo(Crtx, 0x53, nv->timingH);
+			vgaxo(Crtx, 0x54, nv->timingV);
 			vgaxo(Crtx, 0x21, 0xFA);
 		}
 		vgaxo(Crtx, 0x41, nv->extra);
@@ -786,9 +1050,10 @@ load(Vga* vga, Ctlr* ctlr)
 	vgaxo(Crtx, 0x2F, nv->cursor2);
 	vgaxo(Crtx, 0x39, nv->interlace);
 
-	if (nv->islcd)
+	if (nv->islcd) {
 		nv->pramdac[0x00000848/4] = nv->scale;	
-	else {
+		nv->pramdac[0x00000828/4] = nv->crtcsync;	
+	} else {
 		nv->pramdac[0x0000050C/4] = nv->pllsel;
 		nv->pramdac[0x00000508/4] = nv->vpll;
 		if (nv->twoheads)
@@ -829,6 +1094,8 @@ dump(Vga* vga, Ctlr* ctlr)
 	Bprint(&stdout, " %d Hz\n", nv->crystalfreq);
 	printitem(ctlr->name, "arch");
 	Bprint(&stdout, " %d\n", nv->arch);
+	printitem(ctlr->name, "did");
+	Bprint(&stdout, " %.4ux\n", nv->did);
 	printitem(ctlr->name, "repaint0");
 	Bprint(&stdout, " %ux\n", nv->repaint0);
 	printitem(ctlr->name, "repaint1");
@@ -851,6 +1118,10 @@ dump(Vga* vga, Ctlr* ctlr)
 	Bprint(&stdout, " %ux\n", nv->extra);
 	printitem(ctlr->name, "crtcowner");
 	Bprint(&stdout, " %ux\n", nv->crtcowner);
+	printitem(ctlr->name, "timingH");
+	Bprint(&stdout, " %ux\n", nv->timingH);
+	printitem(ctlr->name, "timingV");
+	Bprint(&stdout, " %ux\n", nv->timingV);
 	printitem(ctlr->name, "vpll");
 	Bprint(&stdout, " %lux\n", nv->vpll);
 	printitem(ctlr->name, "vpllB");
@@ -875,6 +1146,8 @@ dump(Vga* vga, Ctlr* ctlr)
 	Bprint(&stdout, " %lux\n", nv->cursorconfig);
 	printitem(ctlr->name, "dither");
 	Bprint(&stdout, " %lux\n", nv->dither);
+	printitem(ctlr->name, "crtcsync");
+	Bprint(&stdout, " %lux\n", nv->crtcsync);
 	printitem(ctlr->name, "islcd");
 	Bprint(&stdout, " %d\n", nv->islcd);
 	printitem(ctlr->name, "twoheads");

+ 502 - 8
sys/src/cmd/aux/vga/vesa.c

@@ -9,6 +9,8 @@ typedef struct Ureg Ureg;
 
 typedef struct Vbe Vbe;
 typedef struct Vmode Vmode;
+typedef struct Modelist Modelist;
+typedef struct Edid Edid;
 
 enum
 {
@@ -43,6 +45,43 @@ struct Vmode
 	ulong	paddr;
 };
 
+struct Edid {
+	char		mfr[4];		/* manufacturer */
+	char		serialstr[16];	/* serial number as string (in extended data) */
+	char		name[16];		/* monitor name as string (in extended data) */
+	ushort	product;		/* product code, 0 = unused */
+	ulong	serial;		/* serial number, 0 = unused */
+	uchar	version;		/* major version number */
+	uchar	revision;		/* minor version number */
+	uchar	mfrweek;		/* week of manufacture, 0 = unused */
+	int		mfryear;		/* year of manufacture, 0 = unused */
+	uchar 	dxcm;		/* horizontal image size in cm. */
+	uchar	dycm;		/* vertical image size in cm. */
+	int		gamma;		/* gamma*100 */
+	int		rrmin;		/* minimum vertical refresh rate */
+	int		rrmax;		/* maximum vertical refresh rate */
+	int		hrmin;		/* minimum horizontal refresh rate */
+	int		hrmax;		/* maximum horizontal refresh rate */
+	ulong	pclkmax;		/* maximum pixel clock */
+	int		flags;
+
+	Modelist	*modelist;		/* list of supported modes */
+};
+
+struct Modelist
+{
+	Mode;
+	Modelist *next;
+};
+
+enum {
+	Fdigital = 1<<0,		/* is a digital display */
+	Fdpmsstandby = 1<<1,	/* supports DPMS standby mode */
+	Fdpmssuspend = 1<<2,	/* supports DPMS suspend mode */
+	Fdpmsactiveoff = 1<<3,	/* supports DPMS active off mode */
+	Fmonochrome = 1<<4,	/* is a monochrome display */
+	Fgtf = 1<<5,			/* supports VESA GTF: see /lib/vesa/gtf10.pdf */
+};
 
 #define WORD(p) ((p)[0] | ((p)[1]<<8))
 #define LONG(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24))
@@ -50,6 +89,7 @@ struct Vmode
 #define PLONG(p, v) (p)[0] = (v); (p)[1] = (v)>>8; (p)[2] = (v)>>16; (p)[3] = (v)>>24
 
 static Vbe *vbe;
+static Edid edid;
 
 Vbe *mkvbe(void);
 int vbecheck(Vbe*);
@@ -58,8 +98,11 @@ int vbemodeinfo(Vbe*, int, Vmode*);
 int vbegetmode(Vbe*);
 int vbesetmode(Vbe*, int);
 void vbeprintinfo(Vbe*);
-void vbeprintmodeinfo(Vbe*, int);
+void vbeprintmodeinfo(Vbe*, int, char*);
 int vbesnarf(Vbe*, Vga*);
+void vesaddc(void);
+int vbeddcedid(Vbe *vbe, Edid *e);
+void printedid(Edid*);
 
 int
 dbvesa(Vga* vga)
@@ -88,10 +131,11 @@ dbvesa(Vga* vga)
 Mode*
 dbvesamode(char *mode)
 {
+	int i;
 	uchar *p, *ep;
 	Vmode vm;
 	Mode *m;
-
+	
 	if(vbe == nil)
 		return nil;
 
@@ -104,6 +148,15 @@ dbvesamode(char *mode)
 		if(strcmp(vm.name, mode) == 0)
 			goto havemode;
 	}
+	if(1){
+		fprint(2, "warning: scanning for unoffered vesa modes\n");
+		for(i=0x100; i<0x200; i++){
+			if(vbemodeinfo(vbe, i, &vm) < 0)
+				continue;
+			if(strcmp(vm.name, mode) == 0)
+				goto havemode;
+		}
+	}
 	werrstr("no such vesa mode");
 	return nil;
 
@@ -158,6 +211,8 @@ load(Vga* vga, Ctlr* ctlr)
 static void
 dump(Vga*, Ctlr*)
 {
+	int i;
+	char did[0x200];
 	uchar *p, *ep;
 
 	if(!vbe){
@@ -165,12 +220,24 @@ dump(Vga*, Ctlr*)
 		return;
 	}
 
+	memset(did, 0, sizeof did);
 	vbeprintinfo(vbe);
 	p = vbemodes(vbe);
 	if(p){
-		for(ep=p+1024; (p[0]!=0xFF || p[1]!=0xFF) && p<ep; p+=2)
-			vbeprintmodeinfo(vbe, WORD(p));
+		for(ep=p+1024; (p[0]!=0xFF || p[1]!=0xFF) && p<ep; p+=2){
+			vbeprintmodeinfo(vbe, WORD(p), "");
+			did[WORD(p)] = 1;
+		}
 	}
+	for(i=0x100; i<0x1FF; i++)
+		if(!did[i])
+			vbeprintmodeinfo(vbe, i, " (unoffered)");
+				
+	
+	if(vbeddcedid(vbe, &edid) < 0)
+		fprint(2, "warning: reading edid: %r\n");
+	else
+		printedid(&edid);
 }
 
 Ctlr vesa = {
@@ -443,15 +510,17 @@ vbemodeinfo(Vbe *vbe, int id, Vmode *m)
 }
 
 void
-vbeprintmodeinfo(Vbe *vbe, int id)
+vbeprintmodeinfo(Vbe *vbe, int id, char *suffix)
 {
 	Vmode m;
 
-	if(vbemodeinfo(vbe, id, &m) < 0)
+	if(vbemodeinfo(vbe, id, &m) < 0){
+	//	Bprint(&stdout, "vesa: cannot get mode 0x%ux: %r\n", id);
 		return;
+	}
 	printitem("vesa", "mode");
-	Bprint(&stdout, "0x%ux %s %s %s\n",
-		m.id, m.name, m.chan, m.model);
+	Bprint(&stdout, "0x%ux %s %s %s%s\n",
+		m.id, m.name, m.chan, m.model, suffix);
 }
 
 int
@@ -512,3 +581,428 @@ vesatextmode(void)
 		error("vbesetmode: %r\n");
 }
 
+static Flag edidflags[] = {
+	Fdigital, "digital",
+	Fdpmsstandby, "standby",
+	Fdpmssuspend, "suspend",
+	Fdpmsactiveoff, "activeoff",
+	Fmonochrome, "monochrome",
+	Fgtf, "gtf",
+	0
+};
+
+int parseedid128(Edid *e, void *v);
+
+int
+vbeddcedid(Vbe *vbe, Edid *e)
+{
+	uchar *p;
+	Ureg u;
+	
+	p = vbesetup(vbe, &u, 0x4F15);
+	u.bx = 0x0001;
+	if(vbecall(vbe, &u) < 0)
+		return -1;
+	if(parseedid128(e, p) < 0){
+		werrstr("parseedid128: %r");
+		return -1;
+	}
+	return 0;
+}
+	
+void
+printedid(Edid *e)
+{
+	Modelist *l;
+	
+	printitem("edid", "mfr");
+	Bprint(&stdout, "%s\n", e->mfr);
+	printitem("edid", "serialstr");
+	Bprint(&stdout, "%s\n", e->serialstr);
+	printitem("edid", "name");
+	Bprint(&stdout, "%s\n", e->name);
+	printitem("edid", "product");
+	Bprint(&stdout, "%d\n", e->product);
+	printitem("edid", "serial");
+	Bprint(&stdout, "%lud\n", e->serial);
+	printitem("edid", "version");
+	Bprint(&stdout, "%d.%d\n", e->version, e->revision);
+	printitem("edid", "mfrdate");
+	Bprint(&stdout, "%d.%d\n", e->mfryear, e->mfrweek);
+	printitem("edid", "size (cm)");
+	Bprint(&stdout, "%dx%d\n", e->dxcm, e->dycm);
+	printitem("edid", "gamma");
+	Bprint(&stdout, "%.2f\n", e->gamma/100.);
+	printitem("edid", "vert (Hz)");
+	Bprint(&stdout, "%d-%d\n", e->rrmin, e->rrmax);
+	printitem("edid", "horz (Hz)");
+	Bprint(&stdout, "%d-%d\n", e->hrmin, e->hrmax);
+	printitem("edid", "pclkmax");
+	Bprint(&stdout, "%lud\n", e->pclkmax);
+	printitem("edid", "flags");
+	printflags(edidflags, e->flags);
+	
+	for(l=e->modelist; l; l=l->next){
+		printitem("edid", l->name);
+		Bprint(&stdout, "\n\t\tclock=%g\n\t\tshb=%d ehb=%d ht=%d\n\t\tvrs=%d vre=%d vt=%d\n\t\thsync=%c vsync=%c %s\n",
+			l->frequency/1.e6, l->shb, l->ehb, l->ht, l->vrs, l->vre, l->vt, l->hsync?l->hsync:'?', l->vsync?l->vsync:'?', l->interlace?"interlace=v" : "");
+	}
+}
+
+Modelist*
+addmode(Modelist *l, Mode m)
+{
+	int rr;
+	Modelist **lp;
+
+//m.z = 8; // BUG
+	rr = (m.frequency+m.ht*m.vt/2)/(m.ht*m.vt);
+	snprint(m.name, sizeof m.name, "%dx%dx%d@%dHz", m.x, m.y, m.z, rr);
+
+	if(m.shs == 0)
+		m.shs = m.shb;
+	if(m.ehs == 0)
+		m.ehs = m.ehb;
+	if(m.vbs == 0)
+		m.vbs = m.vrs;
+	if(m.vbe == 0)
+		m.vbe = m.vbs+1;
+
+	for(lp=&l; *lp; lp=&(*lp)->next){
+		if(strcmp((*lp)->name, m.name) == 0){
+			(*lp)->Mode = m;
+			return l;
+		}
+	}
+
+	*lp = alloc(sizeof(**lp));
+	(*lp)->Mode = m;
+	return l;
+}
+
+/*
+ * Parse VESA EDID information.  Based on the VESA
+ * Extended Display Identification Data standard, Version 3,
+ * November 13, 1997.  See /lib/vesa/edidv3.pdf.
+ *
+ * This only handles 128-byte EDID blocks.  Until I find
+ * a monitor that produces 256-byte blocks, I'm not going
+ * to try to decode them.
+ */
+
+/*
+ * Established timings block.  There is a bitmap
+ * that says whether each mode is supported.  Most
+ * of these have VESA definitions.  Those that don't are marked
+ * as such, and we ignore them (the lookup fails).
+ */
+static char *estabtime[] = {
+	"720x400@70Hz",	/* non-VESA: IBM, VGA */
+	"720x400@88Hz",	/* non-VESA: IBM, XGA2 */
+	"640x480@60Hz",
+	"640x480@67Hz",	/* non-VESA: Apple, Mac II */
+	"640x480@72Hz",
+	"640x480@75Hz",
+	"800x600@56Hz",
+	"800x600@60Hz",
+
+	"800x600@72Hz",
+	"800x600@75Hz",
+	"832x624@75Hz",	/* non-VESA: Apple, Mac II */
+	"1024x768i@87Hz",	/* non-VESA: IBM */
+	"1024x768@60Hz",
+	"1024x768@70Hz",
+	"1024x768@75Hz",
+	"1280x1024@75Hz",
+
+	"1152x870@75Hz",	/* non-VESA: Apple, Mac II */
+};
+
+/*
+ * Decode the EDID detailed timing block.  See pp. 20-21 of the standard.
+ */
+static int
+decodedtb(Mode *m, uchar *p)
+{
+	int ha, hb, hso, hspw, rr, va, vb, vso, vspw;
+	/* int dxmm, dymm, hbord, vbord; */
+
+	memset(m, 0, sizeof *m);
+
+	m->frequency = ((p[1]<<8) | p[0]) * 10000;
+
+	ha = ((p[4] & 0xF0)<<4) | p[2];		/* horizontal active */
+	hb = ((p[4] & 0x0F)<<8) | p[3];		/* horizontal blanking */
+	va = ((p[7] & 0xF0)<<4) | p[5];		/* vertical active */
+	vb = ((p[7] & 0x0F)<<8) | p[6];		/* vertical blanking */
+	hso = ((p[11] & 0xC0)<<2) | p[8];	/* horizontal sync offset */
+	hspw = ((p[11] & 0x30)<<4) | p[9];	/* horizontal sync pulse width */
+	vso = ((p[11] & 0x0C)<<2) | ((p[10] & 0xF0)>>4);	/* vertical sync offset */
+	vspw = ((p[11] & 0x03)<<4) | (p[10] & 0x0F);		/* vertical sync pulse width */
+
+	/* dxmm = (p[14] & 0xF0)<<4) | p[12]; 	/* horizontal image size (mm) */
+	/* dymm = (p[14] & 0x0F)<<8) | p[13];	/* vertical image size (mm) */
+	/* hbord = p[15];		/* horizontal border (pixels) */
+	/* vbord = p[16];		/* vertical border (pixels) */
+
+	m->x = ha;
+	m->y = va;
+
+	m->ht = ha+hb;
+	m->shs = ha;
+	m->shb = ha+hso;
+	m->ehb = ha+hso+hspw;
+	m->ehs = ha+hb;
+
+	m->vt = va+vb;
+	m->vbs = va;	
+	m->vrs = va+vso;
+	m->vre = va+vso+vspw;
+	m->vbe = va+vb;
+
+	if(p[17] & 0x80)	/* interlaced */
+		m->interlace = 'v';
+
+	if(p[17] & 0x60)	/* some form of stereo monitor mode; no support */
+		return -1;
+
+	/*
+	 * Sync signal description.  I have no idea how to properly handle the 
+	 * first three cases, which I think are aimed at things other than
+	 * canonical SVGA monitors.
+	 */
+	switch((p[17] & 0x18)>>3) {
+	case 0:	/* analog composite sync signal*/
+	case 1:	/* bipolar analog composite sync signal */
+		/* p[17] & 0x04 means serration: hsync during vsync */
+		/* p[17] & 0x02 means sync pulse appears on RGB not just G */
+		break;
+
+	case 2:	/* digital composite sync signal */
+		/* p[17] & 0x04 means serration: hsync during vsync */
+		/* p[17] & 0x02 means hsync positive outside vsync */
+		break;
+
+	case 3:	/* digital separate sync signal; the norm */
+		m->vsync = (p[17] & 0x04) ? '+' : '-';
+		m->hsync = (p[17] & 0x02) ? '+' : '-';
+		break;
+	}
+	/* p[17] & 0x01 is another stereo bit, only referenced if p[17] & 0x60 != 0 */
+
+	rr = (m->frequency+m->ht*m->vt/2) / (m->ht*m->vt);
+
+	snprint(m->name, sizeof m->name, "%dx%d@%dHz", m->x, m->y, rr);
+
+	return 0;
+}
+
+extern Mode *vesamodes[];
+
+int
+vesalookup(Mode *m, char *name)
+{
+	Mode **p;
+
+	for(p=vesamodes; *p; p++)
+		if(strcmp((*p)->name, name) == 0) {
+			*m = **p;
+			return 0;
+		}
+
+	return -1;
+}
+
+static int
+decodesti(Mode *m, uchar *p)
+{
+	int x, y, rr;
+	char str[20];
+
+	x = (p[0]+31)*8;
+	switch((p[1]>>6) & 3){
+	default:
+	case 0:
+		y = x;
+		break;
+	case 1:
+		y = (x*4)/3;
+		break;
+	case 2:
+		y = (x*5)/4;
+		break;
+	case 3:
+		y = (x*16)/9;
+		break;
+	}
+	rr = (p[1] & 0x1F) + 60;
+
+	sprint(str, "%dx%d@%dHz", x, y, rr);
+	return vesalookup(m, str);
+}
+
+int
+parseedid128(Edid *e, void *v)
+{
+	static uchar magic[8] = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 };
+	uchar *p, *q, sum;
+	int dpms, estab, i, m, vid;
+	Mode mode;
+
+	memset(e, 0, sizeof *e);
+
+	p = (uchar*)v;
+	if(memcmp(p, magic, 8) != 0) {
+		werrstr("bad edid header");
+		return -1;
+	}
+
+	sum = 0;
+	for(i=0; i<128; i++) 
+		sum += p[i];
+	if(sum != 0) {
+		werrstr("bad edid checksum");
+		return -1;
+	}
+	p += 8;
+
+	assert(p == (uchar*)v+8);	/* assertion offsets from pp. 12-13 of the standard */
+	/*
+	 * Manufacturer name is three 5-bit ascii letters, packed
+	 * into a big endian [sic] short in big endian order.  The high bit is unused.
+	 */
+	i = (p[0]<<8) | p[1];
+	p += 2;
+	e->mfr[0] = 'A'-1 + ((i>>10) & 0x1F);
+	e->mfr[1] = 'A'-1 + ((i>>5) & 0x1F);
+	e->mfr[2] = 'A'-1 + (i & 0x1F);
+	e->mfr[3] = '\0';
+
+	/*
+	 * Product code is a little endian short.
+	 */
+	e->product = (p[1]<<8) | p[0];
+	p += 2;
+
+	/*
+	 * Serial number is a little endian long, 0x01010101 = unused.
+	 */
+	e->serial = (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0];
+	p += 4;
+	if(e->serial == 0x01010101)
+		e->serial = 0;
+
+	e->mfrweek = *p++;
+	e->mfryear = 1990 + *p++;
+
+	assert(p == (uchar*)v+8+10);
+	/*
+	 * Structure version is next two bytes: major.minor.
+	 */
+	e->version = *p++;
+	e->revision = *p++;
+
+	assert(p == (uchar*)v+8+10+2);
+	/*
+	 * Basic display parameters / features.
+	 */
+	/*
+	 * Video input definition byte: 0x80 tells whether it is
+	 * an analog or digital screen; we ignore the other bits.
+	 * See p. 15 of the standard.
+	 */
+	vid = *p++;
+	if(vid & 0x80)
+		e->flags |= Fdigital;
+
+	e->dxcm = *p++;
+	e->dycm = *p++;
+	e->gamma = 100 + *p++;
+	dpms = *p++;
+	if(dpms & 0x80)
+		e->flags |= Fdpmsstandby;
+	if(dpms & 0x40)
+		e->flags |= Fdpmssuspend;
+	if(dpms & 0x20)
+		e->flags |= Fdpmsactiveoff;
+	if((dpms & 0x18) == 0x00)
+		e->flags |= Fmonochrome;
+	if(dpms & 0x01)
+		e->flags |= Fgtf;
+
+	assert(p == (uchar*)v+8+10+2+5);
+	/*
+	 * Color characteristics currently ignored.
+	 */
+	p += 10;
+
+	assert(p == (uchar*)v+8+10+2+5+10);
+	/*
+	 * Established timings: a bitmask of 19 preset timings.
+	 */
+	estab = (p[0]<<16) | (p[1]<<8) | p[2];
+	p += 3;
+	
+	for(i=0, m=1<<23; i<nelem(estabtime); i++, m>>=1)
+		if(estab & m)
+			if(vesalookup(&mode, estabtime[i]) == 0)
+				e->modelist = addmode(e->modelist,  mode);
+
+	assert(p == (uchar*)v+8+10+2+5+10+3);
+	/*
+	 * Standard Timing Identifications: eight 2-byte selectors
+	 * of more standard timings.
+	 */
+	for(i=0; i<8; i++, p+=2)
+		if(decodesti(&mode, p+2*i) == 0)
+			e->modelist = addmode(e->modelist, mode);
+
+	assert(p == (uchar*)v+8+10+2+5+10+3+16);
+	/*
+	 * Detailed Timings
+	 */
+fprint(2, "dt\n");
+	for(i=0; i<4; i++, p+=18) {
+fprint(2, "%.8H\n", p);
+		if(p[0] || p[1]) {	/* detailed timing block: p[0] or p[1] != 0 */
+			if(decodedtb(&mode, p) == 0)
+				e->modelist = addmode(e->modelist, mode);
+		} else if(p[2]==0) {	/* monitor descriptor block */
+			switch(p[3]) {
+			case 0xFF:	/* monitor serial number (13-byte ascii, 0A terminated) */
+				if(q = memchr(p+5, 0x0A, 13))
+					*q = '\0';
+				memset(e->serialstr, 0, sizeof(e->serialstr));
+				strncpy(e->serialstr, (char*)p+5, 13);
+				break;
+			case 0xFE:	/* ascii string (13-byte ascii, 0A terminated) */
+				break;
+			case 0xFD:	/* monitor range limits */
+				print("fd %.18H\n", p);
+				e->rrmin = p[5];
+				e->rrmax = p[6];
+				e->hrmin = p[7]*1000;
+				e->hrmax = p[8]*1000;
+				if(p[9] != 0xFF)
+					e->pclkmax = p[9]*10*1000000;
+				break;
+			case 0xFC:	/* monitor name (13-byte ascii, 0A terminated) */
+				if(q = memchr(p+5, 0x0A, 13))
+					*q = '\0';
+				memset(e->name, 0, sizeof(e->name));
+				strncpy(e->name, (char*)p+5, 13);
+				break;
+			case 0xFB:	/* extra color point data */
+				break;
+			case 0xFA:	/* extra standard timing identifications */
+				for(i=0; i<6; i++)
+					if(decodesti(&mode, p+5+2*i) == 0)
+						e->modelist = addmode(e->modelist, mode);
+				break;
+			}
+		}
+	}
+
+	assert(p == (uchar*)v+8+10+2+5+10+3+16+72);
+	return 0;
+}

+ 770 - 0
sys/src/cmd/aux/vga/vesadb.c

@@ -0,0 +1,770 @@
+// DO NOT EDIT; this file is automatically generated from vesa.txt
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "pci.h"
+#include "vga.h"
+
+// VESA Monitor Timing Standard mode definitions as per
+// VESA and Industry Standards and Guidelines for Computer
+// Display Monitor Timing, Version 1.0, Revision 0.8, 17 September 1998.
+//
+// See /lib/vesa/dmtv1r08.pdf.
+//
+// This might go back into vgadb at some point. It's here mainly
+// so that people don't change it, and so that we can run without vgadb.
+
+static Mode vesa640x480x60 = {
+	.name = "640x480@60Hz",
+	.x = 640,
+	.y = 480,
+
+	.ht = 800,
+	.shb = 648,
+	.ehb = 648+144,
+	.shs = 656,
+	.ehs = 656+96,
+
+	.vt = 525,
+	.vrs = 490,
+	.vre = 490+2,
+	.vbs = 488,
+	.vbe = 488+29,
+
+	.frequency = 25175000,
+
+	.hsync = '-',
+	.vsync = '-',
+	.interlace = '\0',
+};
+
+static Mode vesa640x480x72 = {
+	.name = "640x480@72Hz",
+	.x = 640,
+	.y = 480,
+
+	.ht = 832,
+	.shb = 648,
+	.ehb = 648+176,
+	.shs = 664,
+	.ehs = 664+40,
+
+	.vt = 520,
+	.vrs = 489,
+	.vre = 489+3,
+	.vbs = 488,
+	.vbe = 488+24,
+
+	.frequency = 31500000,
+
+	.hsync = '-',
+	.vsync = '-',
+	.interlace = '\0',
+};
+
+static Mode vesa640x480x75 = {
+	.name = "640x480@75Hz",
+	.x = 640,
+	.y = 480,
+
+	.ht = 840,
+	.shb = 640,
+	.ehb = 640+200,
+	.shs = 656,
+	.ehs = 656+64,
+
+	.vt = 500,
+	.vrs = 481,
+	.vre = 481+3,
+	.vbs = 480,
+	.vbe = 480+20,
+
+	.frequency = 31500000,
+
+	.hsync = '-',
+	.vsync = '-',
+	.interlace = '\0',
+};
+
+static Mode vesa640x480x85 = {
+	.name = "640x480@85Hz",
+	.x = 640,
+	.y = 480,
+
+	.ht = 832,
+	.shb = 640,
+	.ehb = 640+192,
+	.shs = 696,
+	.ehs = 696+56,
+
+	.vt = 509,
+	.vrs = 481,
+	.vre = 481+3,
+	.vbs = 480,
+	.vbe = 480+29,
+
+	.frequency = 36000000,
+
+	.hsync = '-',
+	.vsync = '-',
+	.interlace = '\0',
+};
+
+static Mode vesa800x600x56 = {
+	.name = "800x600@56Hz",
+	.x = 800,
+	.y = 600,
+
+	.ht = 1024,
+	.shb = 800,
+	.ehb = 800+224,
+	.shs = 824,
+	.ehs = 824+72,
+
+	.vt = 625,
+	.vrs = 601,
+	.vre = 601+2,
+	.vbs = 600,
+	.vbe = 600+25,
+
+	.frequency = 36000000,
+
+	.hsync = '+',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa800x600x60 = {
+	.name = "800x600@60Hz",
+	.x = 800,
+	.y = 600,
+
+	.ht = 1056,
+	.shb = 800,
+	.ehb = 800+256,
+	.shs = 840,
+	.ehs = 840+128,
+
+	.vt = 628,
+	.vrs = 601,
+	.vre = 601+4,
+	.vbs = 600,
+	.vbe = 600+28,
+
+	.frequency = 40000000,
+
+	.hsync = '+',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa800x600x72 = {
+	.name = "800x600@72Hz",
+	.x = 800,
+	.y = 600,
+
+	.ht = 1040,
+	.shb = 800,
+	.ehb = 800+240,
+	.shs = 856,
+	.ehs = 856+120,
+
+	.vt = 666,
+	.vrs = 637,
+	.vre = 637+6,
+	.vbs = 600,
+	.vbe = 600+66,
+
+	.frequency = 50000000,
+
+	.hsync = '+',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa800x600x75 = {
+	.name = "800x600@75Hz",
+	.x = 800,
+	.y = 600,
+
+	.ht = 1056,
+	.shb = 800,
+	.ehb = 800+256,
+	.shs = 816,
+	.ehs = 816+80,
+
+	.vt = 625,
+	.vrs = 601,
+	.vre = 601+3,
+	.vbs = 600,
+	.vbe = 600+25,
+
+	.frequency = 49500000,
+
+	.hsync = '+',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa800x600x85 = {
+	.name = "800x600@85Hz",
+	.x = 800,
+	.y = 600,
+
+	.ht = 1048,
+	.shb = 800,
+	.ehb = 800+248,
+	.shs = 832,
+	.ehs = 832+64,
+
+	.vt = 631,
+	.vrs = 601,
+	.vre = 601+3,
+	.vbs = 600,
+	.vbe = 600+31,
+
+	.frequency = 56250000,
+
+	.hsync = '+',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa1024x768x60 = {
+	.name = "1024x768@60Hz",
+	.x = 1024,
+	.y = 768,
+
+	.ht = 1344,
+	.shb = 1024,
+	.ehb = 1024+320,
+	.shs = 1048,
+	.ehs = 1048+136,
+
+	.vt = 806,
+	.vrs = 771,
+	.vre = 771+6,
+	.vbs = 768,
+	.vbe = 768+38,
+
+	.frequency = 65000000,
+
+	.hsync = '-',
+	.vsync = '-',
+	.interlace = '\0',
+};
+
+static Mode vesa1024x768x70 = {
+	.name = "1024x768@70Hz",
+	.x = 1024,
+	.y = 768,
+
+	.ht = 1328,
+	.shb = 1024,
+	.ehb = 1024+304,
+	.shs = 1048,
+	.ehs = 1048+136,
+
+	.vt = 806,
+	.vrs = 771,
+	.vre = 771+6,
+	.vbs = 768,
+	.vbe = 768+38,
+
+	.frequency = 75000000,
+
+	.hsync = '-',
+	.vsync = '-',
+	.interlace = '\0',
+};
+
+static Mode vesa1024x768x75 = {
+	.name = "1024x768@75Hz",
+	.x = 1024,
+	.y = 768,
+
+	.ht = 1312,
+	.shb = 1024,
+	.ehb = 1024+288,
+	.shs = 1040,
+	.ehs = 1040+96,
+
+	.vt = 800,
+	.vrs = 769,
+	.vre = 769+3,
+	.vbs = 768,
+	.vbe = 768+32,
+
+	.frequency = 78750000,
+
+	.hsync = '+',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa1024x768x85 = {
+	.name = "1024x768@85Hz",
+	.x = 1024,
+	.y = 768,
+
+	.ht = 1376,
+	.shb = 1024,
+	.ehb = 1024+352,
+	.shs = 1072,
+	.ehs = 1072+96,
+
+	.vt = 808,
+	.vrs = 769,
+	.vre = 769+3,
+	.vbs = 768,
+	.vbe = 768+40,
+
+	.frequency = 94500000,
+
+	.hsync = '+',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa1152x864x75 = {
+	.name = "1152x864@75Hz",
+	.x = 1152,
+	.y = 864,
+
+	.ht = 1600,
+	.shb = 1152,
+	.ehb = 1152+448,
+	.shs = 1216,
+	.ehs = 1216+128,
+
+	.vt = 900,
+	.vrs = 865,
+	.vre = 865+3,
+	.vbs = 864,
+	.vbe = 864+36,
+
+	.frequency = 108000000,
+
+	.hsync = '+',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa1280x960x60 = {
+	.name = "1280x960@60Hz",
+	.x = 1280,
+	.y = 960,
+
+	.ht = 1800,
+	.shb = 1280,
+	.ehb = 1280+520,
+	.shs = 1376,
+	.ehs = 1376+112,
+
+	.vt = 1000,
+	.vrs = 961,
+	.vre = 961+3,
+	.vbs = 960,
+	.vbe = 960+40,
+
+	.frequency = 108000000,
+
+	.hsync = '+',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa1280x960x85 = {
+	.name = "1280x960@85Hz",
+	.x = 1280,
+	.y = 960,
+
+	.ht = 1728,
+	.shb = 1280,
+	.ehb = 1280+448,
+	.shs = 1344,
+	.ehs = 1344+160,
+
+	.vt = 1011,
+	.vrs = 961,
+	.vre = 961+3,
+	.vbs = 960,
+	.vbe = 960+51,
+
+	.frequency = 148500000,
+
+	.hsync = '+',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa1280x1024x60 = {
+	.name = "1280x1024@60Hz",
+	.x = 1280,
+	.y = 1024,
+
+	.ht = 1688,
+	.shb = 1280,
+	.ehb = 1280+408,
+	.shs = 1328,
+	.ehs = 1328+112,
+
+	.vt = 1066,
+	.vrs = 1025,
+	.vre = 1025+3,
+	.vbs = 1024,
+	.vbe = 1024+42,
+
+	.frequency = 108000000,
+
+	.hsync = '+',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa1280x1024x75 = {
+	.name = "1280x1024@75Hz",
+	.x = 1280,
+	.y = 1024,
+
+	.ht = 1688,
+	.shb = 1280,
+	.ehb = 1280+408,
+	.shs = 1296,
+	.ehs = 1296+144,
+
+	.vt = 1066,
+	.vrs = 1025,
+	.vre = 1025+3,
+	.vbs = 1024,
+	.vbe = 1024+42,
+
+	.frequency = 135000000,
+
+	.hsync = '+',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa1280x1024x85 = {
+	.name = "1280x1024@85Hz",
+	.x = 1280,
+	.y = 1024,
+
+	.ht = 1728,
+	.shb = 1280,
+	.ehb = 1280+448,
+	.shs = 1344,
+	.ehs = 1344+160,
+
+	.vt = 1072,
+	.vrs = 1025,
+	.vre = 1025+3,
+	.vbs = 1024,
+	.vbe = 1024+48,
+
+	.frequency = 157500000,
+
+	.hsync = '+',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa1600x1200x60 = {
+	.name = "1600x1200@60Hz",
+	.x = 1600,
+	.y = 1200,
+
+	.ht = 2160,
+	.shb = 1600,
+	.ehb = 1600+560,
+	.shs = 1664,
+	.ehs = 1664+192,
+
+	.vt = 1250,
+	.vrs = 1201,
+	.vre = 1201+3,
+	.vbs = 1200,
+	.vbe = 1200+50,
+
+	.frequency = 162000000,
+
+	.hsync = '+',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa1600x1200x65 = {
+	.name = "1600x1200@65Hz",
+	.x = 1600,
+	.y = 1200,
+
+	.ht = 2160,
+	.shb = 1600,
+	.ehb = 1600+560,
+	.shs = 1664,
+	.ehs = 1664+192,
+
+	.vt = 1250,
+	.vrs = 1201,
+	.vre = 1201+3,
+	.vbs = 1200,
+	.vbe = 1200+50,
+
+	.frequency = 175500000,
+
+	.hsync = '+',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa1600x1200x70 = {
+	.name = "1600x1200@70Hz",
+	.x = 1600,
+	.y = 1200,
+
+	.ht = 2160,
+	.shb = 1600,
+	.ehb = 1600+560,
+	.shs = 1664,
+	.ehs = 1664+192,
+
+	.vt = 1250,
+	.vrs = 1201,
+	.vre = 1201+3,
+	.vbs = 1200,
+	.vbe = 1200+50,
+
+	.frequency = 189000000,
+
+	.hsync = '+',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa1600x1200x75 = {
+	.name = "1600x1200@75Hz",
+	.x = 1600,
+	.y = 1200,
+
+	.ht = 2160,
+	.shb = 1600,
+	.ehb = 1600+560,
+	.shs = 1664,
+	.ehs = 1664+192,
+
+	.vt = 1250,
+	.vrs = 1201,
+	.vre = 1201+3,
+	.vbs = 1200,
+	.vbe = 1200+50,
+
+	.frequency = 202500000,
+
+	.hsync = '+',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa1600x1200x85 = {
+	.name = "1600x1200@85Hz",
+	.x = 1600,
+	.y = 1200,
+
+	.ht = 2160,
+	.shb = 1600,
+	.ehb = 1600+560,
+	.shs = 1664,
+	.ehs = 1664+192,
+
+	.vt = 1250,
+	.vrs = 1201,
+	.vre = 1201+3,
+	.vbs = 1200,
+	.vbe = 1200+50,
+
+	.frequency = 229500000,
+
+	.hsync = '+',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa1792x1344x60 = {
+	.name = "1792x1344@60Hz",
+	.x = 1792,
+	.y = 1344,
+
+	.ht = 2448,
+	.shb = 1792,
+	.ehb = 1792+656,
+	.shs = 1920,
+	.ehs = 1920+200,
+
+	.vt = 1394,
+	.vrs = 1345,
+	.vre = 1345+3,
+	.vbs = 1344,
+	.vbe = 1344+50,
+
+	.frequency = 204750000,
+
+	.hsync = '-',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa1792x1344x75 = {
+	.name = "1792x1344@75Hz",
+	.x = 1792,
+	.y = 1344,
+
+	.ht = 2456,
+	.shb = 1792,
+	.ehb = 1792+664,
+	.shs = 1888,
+	.ehs = 1888+216,
+
+	.vt = 1417,
+	.vrs = 1345,
+	.vre = 1345+3,
+	.vbs = 1344,
+	.vbe = 1344+73,
+
+	.frequency = 261000000,
+
+	.hsync = '-',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa1856x1392x60 = {
+	.name = "1856x1392@60Hz",
+	.x = 1856,
+	.y = 1392,
+
+	.ht = 2528,
+	.shb = 1856,
+	.ehb = 1856+672,
+	.shs = 1952,
+	.ehs = 1952+224,
+
+	.vt = 1439,
+	.vrs = 1393,
+	.vre = 1393+3,
+	.vbs = 1392,
+	.vbe = 1392+47,
+
+	.frequency = 218250000,
+
+	.hsync = '-',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa1856x1392x75 = {
+	.name = "1856x1392@75Hz",
+	.x = 1856,
+	.y = 1392,
+
+	.ht = 2560,
+	.shb = 1856,
+	.ehb = 1856+704,
+	.shs = 1984,
+	.ehs = 1984+224,
+
+	.vt = 1500,
+	.vrs = 1393,
+	.vre = 1393+3,
+	.vbs = 1392,
+	.vbe = 1392+108,
+
+	.frequency = 288000000,
+
+	.hsync = '-',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa1920x1440x60 = {
+	.name = "1920x1440@60Hz",
+	.x = 1920,
+	.y = 1440,
+
+	.ht = 2600,
+	.shb = 1920,
+	.ehb = 1920+680,
+	.shs = 2048,
+	.ehs = 2048+208,
+
+	.vt = 1500,
+	.vrs = 1441,
+	.vre = 1441+3,
+	.vbs = 1440,
+	.vbe = 1440+60,
+
+	.frequency = 234000000,
+
+	.hsync = '-',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+static Mode vesa1920x1440x75 = {
+	.name = "1920x1440@75Hz",
+	.x = 1920,
+	.y = 1440,
+
+	.ht = 2640,
+	.shb = 1920,
+	.ehb = 1920+720,
+	.shs = 2064,
+	.ehs = 2064+224,
+
+	.vt = 1500,
+	.vrs = 1441,
+	.vre = 1441+3,
+	.vbs = 1440,
+	.vbe = 1440+60,
+
+	.frequency = 297000000,
+
+	.hsync = '-',
+	.vsync = '+',
+	.interlace = '\0',
+};
+
+Mode *vesamodes[] = {
+	&vesa640x480x60,
+	&vesa640x480x72,
+	&vesa640x480x75,
+	&vesa640x480x85,
+	&vesa800x600x56,
+	&vesa800x600x60,
+	&vesa800x600x72,
+	&vesa800x600x75,
+	&vesa800x600x85,
+	&vesa1024x768x60,
+	&vesa1024x768x70,
+	&vesa1024x768x75,
+	&vesa1024x768x85,
+	&vesa1152x864x75,
+	&vesa1280x960x60,
+	&vesa1280x960x85,
+	&vesa1280x1024x60,
+	&vesa1280x1024x75,
+	&vesa1280x1024x85,
+	&vesa1600x1200x60,
+	&vesa1600x1200x65,
+	&vesa1600x1200x70,
+	&vesa1600x1200x75,
+	&vesa1600x1200x85,
+	&vesa1792x1344x60,
+	&vesa1792x1344x75,
+	&vesa1856x1392x60,
+	&vesa1856x1392x75,
+	&vesa1920x1440x60,
+	&vesa1920x1440x75,
+	0
+};

+ 4 - 0
sys/src/cmd/aux/vga/vga.h

@@ -93,6 +93,7 @@ typedef struct Mode {
 	char	type[Namelen+1];	/* monitor type e.g. "vs1782" */
 	char	size[Namelen+1];	/* size e.g. "1376x1024x8" */
 	char	chan[Namelen+1];	/* channel descriptor, e.g. "m8" or "r8g8b8a8" */
+	char name[Namelen+1];	/* optional */
 
 	int	frequency;		/* Dot Clock (MHz) */
 	int	deffrequency;		/* Default dot clock if calculation can't be done */
@@ -111,6 +112,9 @@ typedef struct Mode {
 	int	vrs;			/* Vertical Retrace Start (Crt10) */
 	int	vre;			/* Vertical Retrace End (Crt11) */
 
+	int		vbs;		/* optional Vertical Blank Start */
+	int		vbe;		/* optional Vertical Blank End */
+	
 	ulong	videobw;
 
 	char	hsync;