Here are the relevant changes from /sys/src/fs/pc/ether83815.c to /sys/src/9/pc/ether83815.c. Some of the changes include more device IDs supported and better handling of ethernet addresses. Federico Reference: /n/sources/patch/applied/ether83815-changes Date: Sat Feb 18 05:02:59 CET 2006 --- /sys/src/9/pc/ether83815.c Sat Feb 18 04:58:40 2006 +++ /sys/src/9/pc/ether83815.c Sat Feb 18 04:58:32 2006 @@ -79,9 +79,22 @@ Col = 1<<16, /* collision during receive */ }; -enum { /* Variants */ +enum { /* PCI vendor & device IDs */ Nat83815 = (0x0020<<16)|0x100B, - Sis900 = (0x0630<<16)|0x1039, /* untested */ + 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; @@ -511,11 +524,19 @@ } else if(bp = iallocb(Rbsz)){ len = (cmdsts&Size)-4; - des->bp->wp = des->bp->rp+len; - etheriq(ether, des->bp, 1); + if(len <= 0){ + debug("ns83815: packet len %d <=0\n", len); + freeb(des->bp); + }else{ + des->bp->wp = des->bp->rp+len; + etheriq(ether, des->bp, 1); + } des->bp = bp; des->addr = PADDR(bp->rp); coherence(); + }else{ + debug("ns83815: interrupt: iallocb for input buffer failed\n"); + des->bp->next = 0; } des->cmdsts = Rbsz; @@ -810,8 +831,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 */ +}; + +/* 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)) { + print("ns83815: reading SiS mac address from eeprom\n"); + 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; @@ -821,8 +917,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++; @@ -830,21 +925,47 @@ } 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; Pcidev *p; + ulong id; p = nil; while(p = pcimatch(p, 0, 0)){ if(p->ccrb != 0x02 || p->ccru != 0) continue; - switch((p->did<<16)|p->vid){ + id = (p->did<<16)|p->vid; + switch(id){ default: continue; case Nat83815: - case Sis900: + print("ns83815: FA31[12] found\n"); + break; + case SiS900: + print("ns83815: SiS900"); + if (is630(id, p)) + print(" (within SiS630)"); + print(" found\n"); break; } @@ -855,7 +976,7 @@ ctlr = malloc(sizeof(Ctlr)); ctlr->port = p->mem[0].bar & ~0x01; ctlr->pcidev = p; - ctlr->id = (p->did<<16)|p->vid; + ctlr->id = id; if(ioalloc(ctlr->port, p->mem[0].size, 0, "ns83815") < 0){ print("ns83815: port 0x%uX in use\n", ctlr->port); @@ -885,6 +1006,7 @@ { Ctlr *ctlr; int i, x; + ulong ctladdr; uchar ea[Eaddrlen]; static int scandone; @@ -923,7 +1045,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);