I've modified load.c to only scan ethers later if not booting via pxe, and I've modified ether83815.c to know how to dig the SiS mac address out of rom, so it's no longer necessary to specify ea= to boot through an SiS interface. Notes: Sat Mar 4 08:56:35 EST 2006 rsc Now that you don't need ea= anymore, what is wrong with the probing code as it is now? I can imagine scenarios where you grab 9pxeload over the network but then use a local plan9.ini. Or where you use a local 9load but grab your plan9.ini over the network. Why disallow these? Reference: /n/sources/patch/sorry/sis-boot2 Date: Sat Mar 4 09:36:15 CET 2006 Reviewed-by: rsc --- /sys/src/boot/pc/load.c Sat Mar 4 09:35:08 2006 +++ /sys/src/boot/pc/load.c Sat Mar 4 09:35:05 2006 @@ -282,15 +282,23 @@ panic("i'm too big\n"); readlsconf(); - for(tp = types; tp->type != Tnil; tp++){ - //if(tp->type == Tether) - // continue; - if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){ + /* first pass of probing, just non-ethers if not pxe booting */ + for(tp = types; tp->type != Tnil; tp++) { + if(tp->type == Tether && !pxe) + continue; + if ((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){ print("using %s!%s!%s\n", mp->name, mp->part, mp->ini); iniread = !dotini(mp->inifs); break; } } + if (!pxe) + /* now that we've read plan9.ini, probe ethers */ + for(tp = types; tp->type != Tnil; tp++) + if(tp->type == Tether) { + probe(tp->type, Fini, Dany); + break; + } apminit(); if((p = getconf("console")) != nil) --- /sys/src/boot/pc/ether83815.c Sat Mar 4 09:35:22 2006 +++ /sys/src/boot/pc/ether83815.c Sat Mar 4 09:35:18 2006 @@ -3,6 +3,7 @@ * * Supports only internal PHY and has been tested on: * Netgear FA311TX (using Netgear DS108 10/100 hub) + * SiS 900 within SiS 630 * To do: * check Ethernet address; * test autonegotiation on 10 Mbit, and 100 Mbit full duplex; @@ -24,7 +25,7 @@ #include "etherif.h" -#define DEBUG (1) +#define DEBUG 0 #define debug if(DEBUG)print enum { @@ -77,8 +78,22 @@ Col = 1<<16, /* collision during receive */ }; -enum { /* Variants */ - Nat83815 = (0x0020<<16)|0x100B, +enum { /* PCI vendor & device IDs */ + Nat83815 = (0x0020<<16)|0x100B, + SiS = 0x1039, + SiS900 = (0x0900<<16)|SiS, + SiS7016 = (0x7016<<16)|SiS, + + SiS630bridge = 0x0008, + + /* SiS 900 PCI revision codes */ + SiSrev630s = 0x81, + SiSrev630e = 0x82, + SiSrev630ea1 = 0x83, + + SiSeenodeaddr = 8, /* short addr of SiS eeprom mac addr */ + SiS630eenodeaddr = 9, /* likewise for the 630 */ + Nseenodeaddr = 6, /* " for NS eeprom */ }; typedef struct Ctlr Ctlr; @@ -652,6 +667,7 @@ debug("%d ms\n", i); 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)); @@ -672,8 +688,83 @@ "100BASE-FXFD", }; +static int +is630(ulong id, Pcidev *p) +{ + if(id == SiS900) + switch (p->rid) { + case SiSrev630s: + case SiSrev630e: + case SiSrev630ea1: + return 1; + } + return 0; +} + +enum { + MagicReg = 0x48, + MagicRegSz = 1, + Magicrden = 0x40, /* read enable, apparently */ + Paddr= 0x70, /* address port */ + Pdata= 0x71, /* data port */ + Pcinetctlr = 2, +}; + +/* rcmos() originally from LANL's SiS 900 driver's rcmos() */ +static int +sisrdcmos(Ctlr *ctlr) +{ + int i; + unsigned reg; + ulong port; + Pcidev *p; + + debug("ns83815: SiS 630 rev. %ux reading mac address from cmos\n", ctlr->pcidev->rid); + p = pcimatch(nil, SiS, SiS630bridge); + if(p == nil) { + print("ns83815: no SiS 630 rev. %ux bridge for mac addr\n", + ctlr->pcidev->rid); + return 0; + } + port = p->mem[0].bar & ~0x01; + debug("ns83815: SiS 630 rev. %ux reading mac addr from cmos via bridge at port 0x%lux\n", ctlr->pcidev->rid, port); + + reg = pcicfgr8(p, MagicReg); + pcicfgw8(p, MagicReg, reg|Magicrden); + + for (i = 0; i < Eaddrlen; i++) { + outb(port+Paddr, SiS630eenodeaddr + i); + ctlr->sromea[i] = inb(port+Pdata); + } + + pcicfgw8(p, MagicReg, reg & ~Magicrden); + return 1; +} + +/* + * If this is a SiS 630E chipset with an embedded SiS 900 controller, + * we have to read the MAC address from the APC CMOS RAM. - sez freebsd. + * However, CMOS *is* NVRAM normally. See devrtc.c:440, memory.c:88. + */ static void -srom(Ctlr* ctlr) +sissrom(Ctlr *ctlr) +{ + union { + uchar eaddr[Eaddrlen]; + ushort alignment; + } ee; + int i, off = SiSeenodeaddr, cnt = sizeof ee.eaddr / sizeof(short); + ushort *shp = (ushort *)ee.eaddr; + + if(!is630(ctlr->id, ctlr->pcidev) || !sisrdcmos(ctlr)) { + for (i = 0; i < cnt; i++) + *shp++ = eegetw(ctlr, off++); + memmove(ctlr->sromea, ee.eaddr, sizeof ctlr->sromea); + } +} + +static void +nssrom(Ctlr* ctlr) { int i, j; @@ -683,8 +774,7 @@ /* * the MAC address is reversed, straddling word boundaries */ - memset(ctlr->sromea, 0, sizeof(ctlr->sromea)); - j = 6*16 + 15; + j = Nseenodeaddr*16 + 15; for(i=0; i<48; i++){ ctlr->sromea[i>>3] |= ((ctlr->srom[j>>4] >> (15-(j&0xF))) & 1) << (i&7); j++; @@ -692,6 +782,24 @@ } static void +srom(Ctlr* ctlr) +{ + memset(ctlr->sromea, 0, sizeof(ctlr->sromea)); + switch (ctlr->id) { + case SiS900: + case SiS7016: + sissrom(ctlr); + break; + case Nat83815: + nssrom(ctlr); + break; + default: + print("ns83815: srom: unknown id 0x%ux\n", ctlr->id); + break; + } +} + +static void scanpci83815(void) { Ctlr *ctlr; @@ -706,6 +814,7 @@ continue; case Nat83815: + case SiS900: break; } @@ -734,6 +843,7 @@ { Ctlr *ctlr; int i, x; + ulong ctladdr; uchar ea[Eaddrlen]; static int scandone; @@ -772,7 +882,8 @@ memmove(ether->ea, ctlr->sromea, Eaddrlen); for(i=0; iea[i] | (ether->ea[i+1]<<8); - csr32w(ctlr, Rrfcr, i); + ctladdr = (ctlr->id == Nat83815? i: i<<15); + csr32w(ctlr, Rrfcr, ctladdr); csr32w(ctlr, Rrfdr, x); } csr32w(ctlr, Rrfcr, Rfen|Apm|Aab|Aam);