## diffname pc/ether79c970.c 1995/0721 ## diff -e /dev/null /n/fornaxdump/1995/0721/sys/src/brazil/pc/ether79c970.c 0a /* * AM79C970 * PCnet-PCI Single-Chip Ethernet Controller for PCI Local Bus * To do: * only issue transmit interrupt if necessary? * dynamically increase rings as necessary? * use Block's as receive buffers? */ #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "../port/error.h" #include "../port/netif.h" #include "etherif.h" enum { Lognrdre = 6, Nrdre = (1<port; outl(port+Rdp, Iena|Strt); } static void ringinit(Ctlr* ctlr) { int i, x; /* * Initialise the receive and transmit buffer rings. The ring * entries must be aligned on 16-byte boundaries. */ if(ctlr->rdr == 0) ctlr->rdr = xspanalloc(Nrdre*sizeof(Rdre), 0x10, 0); if(ctlr->rrb == 0) ctlr->rrb = xalloc(Nrdre*Rbsize); x = PADDR(ctlr->rrb); for(i = 0; i < Nrdre; i++){ ctlr->rdr[i].rbadr = x; x += Rbsize; ctlr->rdr[i].rmd1 = Own|(-Rbsize & 0xFFFF); } ctlr->rdrx = 0; if(ctlr->tdr == 0) ctlr->tdr = xspanalloc(Ntdre*sizeof(Tdre), 0x10, 0); if(ctlr->trb == 0) ctlr->trb = xalloc(Ntdre*Rbsize); x = PADDR(ctlr->trb); for(i = 0; i < Ntdre; i++){ ctlr->tdr[i].tbadr = x; x += Rbsize; } ctlr->tdrx = 0; } static void promiscuous(void* arg, int on) { Ether *ether; int port, x; Ctlr *ctlr; ether = arg; port = ether->port; ctlr = ether->ctlr; /* * Put the chip into promiscuous mode. First we must wait until * anyone transmitting is done, then we can stop the chip and put * it in promiscuous mode. Restarting is made harder by the chip * reloading the transmit and receive descriptor pointers with their * base addresses when Strt is set (unlike the older Lance chip), * so the rings must be re-initialised. */ qlock(ðer->tlock); ilock(&ctlr->raplock); outl(port+Rdp, Stop); outl(port+Rap, 15); x = inl(port+Rdp) & ~Prom; if(on) x |= Prom; outl(port+Rdp, x); outl(port+Rap, 0); ringinit(ctlr); outl(port+Rdp, Iena|Strt); iunlock(&ctlr->raplock); qunlock(ðer->tlock); } static int owntdre(void* arg) { return (((Tdre*)arg)->tmd1 & Own) == 0; } static long write(Ether* ether, void* buf, long n) { int port; Ctlr *ctlr; Tdre *tdre; Etherpkt *pkt; port = ether->port; ctlr = ether->ctlr; /* * Wait for a transmit ring descriptor (and hence a buffer) to become * free. If none become free after a reasonable period, give up. */ tdre = &ctlr->tdr[ctlr->tdrx]; tsleep(&ctlr->trendez, owntdre, tdre, 100); if(owntdre(tdre) == 0) return 0; /* * Copy the packet to the transmit buffer and fill in our * source ethernet address. There's no need to pad to ETHERMINTU * here as we set ApadXmit in CSR4. */ pkt = KADDR(tdre->tbadr); memmove(pkt->d, buf, n); memmove(pkt->s, ether->ea, sizeof(pkt->s)); /* * Give ownership of the descriptor to the chip, increment the * software ring descriptor pointer and tell the chip to poll. */ tdre->tmd2 = 0; tdre->tmd1 = Own|Stp|Enp|(-n & 0xFFFF); ctlr->tdrx = NEXT(ctlr->tdrx, Ntdre); outl(port+Rdp, Iena|Tdmd); ether->outpackets++; return n; } static void interrupt(Ureg*, void* arg) { Ether *ether; int port, csr0, status; Ctlr *ctlr; Rdre *rdre; Etherpkt *pkt; ether = arg; port = ether->port; ctlr = ether->ctlr; /* * Acknowledge all interrupts and whine about those that shouldn't * happen. */ csr0 = inl(port+Rdp); outl(port+Rdp, Babl|Cerr|Miss|Merr|Rint|Tint|Iena); if(csr0 & (Babl|Miss|Merr)) print("AMD70C970#%d: csr0 = 0x%uX\n", ether->ctlrno, csr0); /* * Receiver interrupt: run round the descriptor ring logging * errors and passing valid receive data up to the higher levels * until we encounter a descriptor still owned by the chip. */ if(csr0 & Rint){ rdre = &ctlr->rdr[ctlr->rdrx]; while(((status = rdre->rmd1) & Own) == 0){ if(status & RxErr){ if(status & RxBuff) ether->buffs++; if(status & RxCrc) ether->crcs++; if(status & RxOflo) ether->overflows++; } else{ ether->inpackets++; pkt = KADDR(rdre->rbadr); etherrloop(ether, pkt, (rdre->rmd2 & 0x0FFF)-4); } /* * Finished with this descriptor, reinitialise it, * give it back to the chip, then on to the next... */ rdre->rmd2 = 0; rdre->rmd1 = Own|(-Rbsize & 0xFFFF); ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre); rdre = &ctlr->rdr[ctlr->rdrx]; } } /* * Transmitter interrupt: wakeup anyone waiting for a free descriptor. */ if(csr0 & Tint) wakeup(&ctlr->trendez); } typedef struct Adapter Adapter; struct Adapter { Adapter* next; int port; PCIcfg* pcicfg; }; static Adapter *adapter; static PCIcfg* amd79c90(Ether* ether) { PCIcfg *pcicfg; static int devno = 0; int port; Adapter *ap; pcicfg = malloc(sizeof(PCIcfg)); for(;;){ pcicfg->vid = 0x1022; pcicfg->did = 0x2000; if((devno = pcimatch(0, devno, pcicfg)) == -1) break; port = pcicfg->baseaddr[0] & ~0x01; if(ether->port == 0 || ether->port == port) return pcicfg; ap = malloc(sizeof(Adapter)); ap->pcicfg = pcicfg; ap->port = port; ap->next = adapter; adapter = ap; pcicfg = malloc(sizeof(PCIcfg)); } free(pcicfg); return 0; } static int reset(Ether* ether) { int port, x; PCIcfg *pcicfg; Adapter *ap, **app; uchar ea[Eaddrlen]; Ctlr *ctlr; /* * Any adapter matches if no ether->port is supplied, otherwise the * ports must match. First see if we've already found an adapter that fits * the bill. If not then scan for another. */ port = 0; pcicfg = 0; for(app = &adapter, ap = *app; ap; app = &ap->next, ap = ap->next){ if(ether->port == 0 || ether->port == ap->port){ port = ap->port; pcicfg = ap->pcicfg; *app = ap->next; free(ap); break; } } if(port == 0 && (pcicfg = amd79c90(ether))){ port = pcicfg->baseaddr[0] & ~0x01; ether->irq = pcicfg->irq; } if(port == 0) return -1; if(pcicfg) free(pcicfg); /* * How can we tell what mode we're in at this point - if we're in WORD * mode then the only 32-bit access we are allowed to make is a write to * the RDP, which forces the chip to DWORD mode; if we're in DWORD mode * then we're not allowed to make any non-DWORD accesses? * Assuming we do a DWORD write to the RDP, how can we tell what we're * about to overwrite as we can't reliably access the RAP? * * Force DWORD mode by writing to RDP, doing a reset then writing to RDP * again; at least we know what state we're in now. The value of RAP after * a reset is 0, so the second DWORD write will be to CSR0. * Set the software style in BCR20 to be PCnet-PCI to ensure 32-bit access. * Set the auto pad transmit in CSR4. */ outl(port+Rdp, 0x00); inl(port+Sreset); outl(port+Rdp, Stop); outl(port+Rap, 20); outl(port+Bdp, 0x0002); outl(port+Rap, 4); x = inl(port+Rdp) & 0xFFFF; outl(port+Rdp, ApadXmt|x); outl(port+Rap, 0); /* * Check if we are going to override the adapter's station address. * If not, read it from the I/O-space and set in ether->ea prior to loading the * station address in the initialisation block. */ memset(ea, 0, Eaddrlen); if(memcmp(ea, ether->ea, Eaddrlen) == 0){ x = inl(port+Aprom); ether->ea[0] = x & 0xFF; ether->ea[1] = (x>>8) & 0xFF; ether->ea[2] = (x>>16) & 0xFF; ether->ea[3] = (x>>24) & 0xFF; x = inl(port+Aprom+4); ether->ea[4] = x & 0xFF; ether->ea[5] = (x>>8) & 0xFF; } /* * Allocate a controller structure and start to fill in the * initialisation block (must be DWORD aligned). */ ether->ctlr = malloc(sizeof(Ctlr)); ctlr = ether->ctlr; ctlr->iblock.rlen = Lognrdre<<4; ctlr->iblock.tlen = Logntdre<<4; memmove(ctlr->iblock.padr, ether->ea, sizeof(ctlr->iblock.padr)); ringinit(ctlr); ctlr->iblock.rdra = PADDR(ctlr->rdr); ctlr->iblock.tdra = PADDR(ctlr->tdr); /* * Point the chip at the initialisation block and tell it to go. * Mask the Idon interrupt and poll for completion. Strt and interrupt * enables will be set later when we're ready to attach to the network. */ x = PADDR(&ctlr->iblock); outl(port+Rap, 1); outl(port+Rdp, x & 0xFFFF); outl(port+Rap, 2); outl(port+Rdp, (x>>16) & 0xFFFF); outl(port+Rap, 3); outl(port+Rdp, Idonm); outl(port+Rap, 0); outl(port+Rdp, Init); while((inl(port+Rdp) & Idon) == 0) ; outl(port+Rdp, Idon|Stop); ether->port = port; ether->attach = attach; ether->write = write; ether->interrupt = interrupt; ether->promiscuous = promiscuous; ether->arg = ether; return 0; } void ether79c970link(void) { addethercard("AMD79C970", reset); } . ## diffname pc/ether79c970.c 1995/0817 ## diff -e /n/fornaxdump/1995/0721/sys/src/brazil/pc/ether79c970.c /n/fornaxdump/1995/0817/sys/src/brazil/pc/ether79c970.c 23c Logntdre = 5, . 21c Lognrdre = 7, . ## diffname pc/ether79c970.c 1996/0607 ## diff -e /n/fornaxdump/1995/0817/sys/src/brazil/pc/ether79c970.c /n/fornaxdump/1996/0607/sys/src/brazil/pc/ether79c970.c 460c * enables will be set later when attaching to the network. . 426c * Check if the adapter's station address is to be over-ridden. . 407,408c * again. The value of RAP after a reset is 0, so the second DWORD write * will be to CSR0. . 399,404c * How to tell what mode the chip is in at this point - if it's in WORD * mode then the only 32-bit access allowedis a write to the RDP, which * forces the chip to DWORD mode; if it's in DWORD mode then only DWORD * accesses are allowed? * Assuming a DWORD write is done to the RDP, what will be overwritten as * the RAP can't reliably be accessed? . 395,397d 388,392c if(port == 0 && (port = amd79c90(ether)) == 0) . 382c ether->irq = ap->irq; . 378d 367d 358d 355,356d 352a ap->irq = irq; . 351d 346,348c port = pcicfg.baseaddr[0] & ~0x01; irq = pcicfg.irq; if(ether->port == 0 || ether->port == port){ ether->irq = irq; return port; } . 341,343c pcicfg.vid = 0x1022; pcicfg.did = 0x2000; if((devno = pcimatch(0, devno, &pcicfg)) == -1) . 339d 336c int irq, port; . 334c PCIcfg pcicfg; . 331c static int . 327c int irq; . 241c * here as ApadXmit is set in CSR4. . 239c * Copy the packet to the transmit buffer and fill in the . 4a * bag the tsleep in write, buffer them up; * loop in interrupt routine until all done; . ## diffname pc/ether79c970.c 1996/0608 ## diff -e /n/fornaxdump/1996/0607/sys/src/brazil/pc/ether79c970.c /n/fornaxdump/1996/0608/sys/src/brazil/pc/ether79c970.c 374,375c * ports must match. First see if an adapter that fits the bill has * already been found. If not then scan for another. . 287c * until a descriptor is encountered still owned by the chip. . 188,189c * Put the chip into promiscuous mode. First must wait until * anyone transmitting is done, then stop the chip and put . ## diffname pc/ether79c970.c 1997/0327 ## diff -e /n/fornaxdump/1996/0608/sys/src/brazil/pc/ether79c970.c /n/emeliedump/1997/0327/sys/src/brazil/pc/ether79c970.c 474a ether->promiscuous = promiscuous; . 473d 471a ether->ifstat = ifstat; . 470c ether->transmit = transmit; . 466,467c csr32w(ctlr, Rdp, Idon|Stop); ctlr->init = 0; iunlock(ctlr); /* * Linkage to the generic ethernet driver. */ . 464c while(!(csr32r(ctlr, Rdp) & Idon)) . 455,462c csr32w(ctlr, Rap, 1); csr32w(ctlr, Rdp, x & 0xFFFF); csr32w(ctlr, Rap, 2); csr32w(ctlr, Rdp, (x>>16) & 0xFFFF); csr32w(ctlr, Rap, 3); csr32w(ctlr, Rdp, Idon); csr32w(ctlr, Rap, 0); csr32w(ctlr, Rdp, Init); . 438,440d 435,436c * Start to fill in the initialisation block * (must be DWORD aligned). . 423,431c if(!memcmp(ea, ether->ea, Eaddrlen)){ x = csr32r(ctlr, Aprom); ether->ea[0] = x; ether->ea[1] = x>>8; ether->ea[2] = x>>16; ether->ea[3] = x>>24; x = csr32r(ctlr, Aprom+4); ether->ea[4] = x; ether->ea[5] = x>>8; . 415c csr32w(ctlr, Rap, 0); . 411,413c csr32w(ctlr, Rap, 4); x = csr32r(ctlr, Rdp) & 0xFFFF; csr32w(ctlr, Rdp, ApadXmt|x); . 408,409c csr32w(ctlr, Rap, 20); csr32w(ctlr, Bdp, 0x0002); . 404,406c csr32w(ctlr, Rdp, 0x00); csr32r(ctlr, Sreset); csr32w(ctlr, Rdp, Stop); . 392c * mode then the only 32-bit access allowed is a write to the RDP, which . 390a * Allocate a controller structure and start to initialise it. */ ether->ctlr = malloc(sizeof(Ctlr)); ctlr = ether->ctlr; ilock(ctlr); ctlr->init = 1; ctlr->port = port; /* . 382,383c ether->tbdf = ap->tbdf; *bpp = bp->next; freeb(bp); . 378c bpp = &adapter; for(bp = *bpp; bp; bp = bp->next){ ap = (Adapter*)bp->rp; . 375c * already been found. If not, scan for another. . 368c Block *bp, **bpp; Adapter *ap; . 354,358c amd79c970adapter(&adapter, port, irq, p->tbdf); . 350a ether->tbdf = p->tbdf; . 341,348c while(p = pcimatch(p, 0x1022, 0x2000)){ port = p->bar[0] & ~0x01; irq = p->intl; . 339d 336,337c static Pcidev *p; . 332a static void amd79c970adapter(Block** bpp, int port, int irq, int tbdf) { Block *bp; Adapter *ap; bp = allocb(sizeof(Adapter)); ap = (Adapter*)bp->rp; ap->port = port; ap->irq = irq; ap->tbdf = tbdf; bp->next = *bpp; *bpp = bp; } . 325,331c typedef struct Adapter { int port; int irq; int tbdf; } Adapter; static Block* adapter; . 321,322c if(csr0 & Tint){ lock(ctlr); while(ctlr->ntq){ dre = &ctlr->tdr[ctlr->tdri]; if(dre->md1 & Own) break; if(dre->md1 & TxErr){ if(dre->md2 & Rtry) ctlr->rtry++; if(dre->md2 & Lcar) ctlr->lcar++; if(dre->md2 & Lcol) ctlr->lcol++; if(dre->md2 & Uflo) ctlr->uflo++; if(dre->md2 & TxBuff) ctlr->txbuff++; ether->oerrs++; } freeb(dre->bp); ctlr->ntq--; ctlr->tdri = NEXT(ctlr->tdri, Ntdre); } txstart(ether); unlock(ctlr); } goto intrloop; . 314c dre = &ctlr->rdr[ctlr->rdrx]; . 310,311c dre->md2 = 0; dre->md1 = Own|(-Rbsize & 0xFFFF); . 300,303c else if(bp = iallocb(Rbsize)){ len = (dre->md2 & 0x0FFF)-4; dre->bp->wp = dre->bp->rp+len; etheriq(ether, dre->bp, 1); dre->bp = bp; dre->addr = PADDR(bp->rp); . 290,298c dre = &ctlr->rdr[ctlr->rdrx]; while(!(dre->md1 & Own)){ if(dre->md1 & RxErr){ if(dre->md1 & RxBuff) ctlr->rxbuff++; if(dre->md1 & Crc) ctlr->crc++; if(dre->md1 & Oflo) ctlr->oflo++; if(dre->md1 & Fram) ctlr->fram++; . 282c print("#l%d: csr0 = 0x%uX\n", ether->ctlrno, csr0); if(!(csr0 & (Rint|Tint))) return; . 279,280c intrloop: csr0 = csr32r(ctlr, Rdp) & 0xFFFF; csr32w(ctlr, Rdp, Babl|Cerr|Miss|Merr|Rint|Tint|Iena); . 272d 268,269c Ether *ether; int csr0, len; Dre *dre; Block *bp; . 265,266d 258,259c static void transmit(Ether* ether) { Ctlr *ctlr; ctlr = ether->ctlr; ilock(ctlr); txstart(ether); iunlock(ctlr); . 249,256c /* * Give ownership of the descriptor to the chip, * increment the software ring descriptor pointer * and tell the chip to poll. * There's no need to pad to ETHERMINTU * here as ApadXmit is set in CSR4. */ dre = &ctlr->tdr[ctlr->tdrh]; dre->bp = bp; dre->addr = PADDR(bp->rp); dre->md2 = 0; dre->md1 = Own|Stp|Enp|(-BLEN(bp) & 0xFFFF); ctlr->ntq++; csr32w(ctlr, Rdp, Iena|Tdmd); ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre); } } . 240,247c while(ctlr->ntq < (Ntdre-1)){ bp = qget(ether->oq); if(bp == nil) break; . 231,238c if(ctlr->init) return; . 228d 225,226c Block *bp; Dre *dre; . 217,223d 214,215c static void txstart(Ether* ether) . 211c ilock(ctlr); ctlr->init = 0; csr32w(ctlr, Rdp, Iena|Strt); iunlock(ctlr); . 208,209d 204,205c csr32w(ctlr, Rdp, x); csr32w(ctlr, Rap, 0); . 200,201c csr32w(ctlr, Rdp, Stop); csr32w(ctlr, Rap, 15); x = csr32r(ctlr, Rdp) & ~Prom; . 197,198c while(ctlr->ntq) ; . 195c ilock(ctlr); if(ctlr->init){ iunlock(ctlr); return; } ctlr->init = 1; iunlock(ctlr); . 184d 180c int x; . 165,173c ctlr->tdr = xspanalloc(Ntdre*sizeof(Dre), 0x10, 0); memset(ctlr->tdr, 0, Ntdre*sizeof(Dre)); ctlr->tdrh = ctlr->tdri = 0; . 152,160c if(ctlr->rdr == 0){ ctlr->rdr = xspanalloc(Nrdre*sizeof(Dre), 0x10, 0); for(dre = ctlr->rdr; dre < &ctlr->rdr[Nrdre]; dre++){ dre->bp = iallocb(Rbsize); dre->addr = PADDR(dre->bp->rp); dre->md2 = 0; dre->md1 = Own|(-Rbsize & 0xFFFF); } . 149,150c * Initialise the receive and transmit buffer rings. * The ring entries must be aligned on 16-byte boundaries. * * This routine is protected by ctlr->init. . 146c Dre *dre; . 142a static long ifstat(Ether* ether, void* a, long n, ulong offset) { Ctlr *ctlr; char buf[512]; int len; ctlr = ether->ctlr; ether->crcs = ctlr->crc; ether->frames = ctlr->fram; ether->buffs = ctlr->rxbuff+ctlr->txbuff; ether->overflows = ctlr->oflo; if(n == 0) return 0; len = sprint(buf, "Rxbuff: %ld\n", ctlr->rxbuff); len += sprint(buf+len, "Crc: %ld\n", ctlr->crc); len += sprint(buf+len, "Oflo: %ld\n", ctlr->oflo); len += sprint(buf+len, "Fram: %ld\n", ctlr->fram); len += sprint(buf+len, "Rtry: %ld\n", ctlr->rtry); len += sprint(buf+len, "Lcar: %ld\n", ctlr->lcar); len += sprint(buf+len, "Lcol: %ld\n", ctlr->lcol); len += sprint(buf+len, "Uflo: %ld\n", ctlr->uflo); sprint(buf+len, "Txbuff: %ld\n", ctlr->txbuff); return readstr(offset, a, n, buf); } . 139,140c ctlr = ether->ctlr; ilock(ctlr); if(ctlr->init){ iunlock(ctlr); return; } csr32w(ctlr, Rdp, Iena|Strt); iunlock(ctlr); . 137c Ctlr *ctlr; . 133a #define csr32r(c, r) (inl((c)->port+(r))) #define csr32w(c, r, l) (outl((c)->port+(r), (ulong)(l))) . 128,131c Dre* tdr; /* transmit descriptor ring */ int tdrh; /* host index into tdr */ int tdri; /* interface index into tdr */ int ntq; /* descriptors active */ ulong rxbuff; /* receive statistics */ ulong crc; ulong oflo; ulong fram; ulong rtry; /* transmit statistics */ ulong lcar; ulong lcol; ulong uflo; ulong txbuff; . 124,126c Dre* rdr; /* receive descriptor ring */ int rdrx; . 121a typedef struct Ctlr { Lock; int port; int init; /* initialisation in progress */ . 119,120c enum { /* md2 */ Rtry = 0x04000000, /* failed after repeated retries */ Lcar = 0x08000000, /* loss of carrier */ Lcol = 0x10000000, /* late collision */ Uflo = 0x40000000, /* underflow error */ TxBuff = 0x80000000, /* buffer error */ }; . 97,115c enum { /* md1 */ Enp = 0x01000000, /* end of packet */ Stp = 0x02000000, /* start of packet */ RxBuff = 0x04000000, /* buffer error */ Def = 0x04000000, /* deferred */ Crc = 0x08000000, /* CRC error */ One = 0x08000000, /* one retry needed */ Oflo = 0x10000000, /* overflow error */ More = 0x10000000, /* more than one retry needed */ Fram = 0x20000000, /* framing error */ RxErr = 0x40000000, /* Fram|Oflo|Crc|RxBuff */ TxErr = 0x40000000, /* Uflo|Lcol|Lcar|Rtry */ . 90,95c typedef struct { /* descriptor ring entry */ ulong addr; ulong md1; /* status|bcnt */ ulong md2; /* rcc|rpc|mcnt */ Block* bp; } Dre; . 81,82c uchar rlen; /* upper 4 bits */ uchar tlen; /* upper 4 bits */ . 79c typedef struct { /* Initialisation Block */ . 75,76c enum { /* CSR15 */ Prom = 0x8000, /* promiscuous mode */ . 71,72c enum { /* CSR4 */ ApadXmt = 0x0800, /* auto pad transmit */ . 58,68c enum { /* CSR3 */ Bswp = 0x0004, /* byte swap */ Emba = 0x0008, /* enable modified back-off algorithm */ Dxmt2pd = 0x0010, /* disable transmit two part deferral */ Lappen = 0x0020, /* look-ahead packet processing enable */ . 39,55c enum { /* CSR0 */ Init = 0x0001, /* begin initialisation */ Strt = 0x0002, /* enable chip */ Stop = 0x0004, /* disable chip */ Tdmd = 0x0008, /* transmit demand */ Txon = 0x0010, /* transmitter on */ Rxon = 0x0020, /* receiver on */ Iena = 0x0040, /* interrupt enable */ Intr = 0x0080, /* interrupt flag */ Idon = 0x0100, /* initialisation done */ Tint = 0x0200, /* transmit interrupt */ Rint = 0x0400, /* receive interrupt */ Merr = 0x0800, /* memory error */ Miss = 0x1000, /* missed frame */ Cerr = 0x2000, /* collision */ Babl = 0x4000, /* transmitter timeout */ Err = 0x8000, /* Babl|Cerr|Miss|Merr */ . 31,36c enum { /* DWIO I/O resource map */ Aprom = 0x0000, /* physical address */ Rdp = 0x0010, /* register data port */ Rap = 0x0014, /* register address port */ Sreset = 0x0018, /* software reset */ Bdp = 0x001C, /* bus configuration register data port */ . 28c Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */ . 23,26c Lognrdre = 6, Nrdre = (1<rxbuff); len += snprint(p+len, READSTR-len, "Crc: %ld\n", ctlr->crc); len += snprint(p+len, READSTR-len, "Oflo: %ld\n", ctlr->oflo); len += snprint(p+len, READSTR-len, "Fram: %ld\n", ctlr->fram); len += snprint(p+len, READSTR-len, "Rtry: %ld\n", ctlr->rtry); len += snprint(p+len, READSTR-len, "Lcar: %ld\n", ctlr->lcar); len += snprint(p+len, READSTR-len, "Lcol: %ld\n", ctlr->lcol); len += snprint(p+len, READSTR-len, "Uflo: %ld\n", ctlr->uflo); snprint(p+len, READSTR-len, "Txbuff: %ld\n", ctlr->txbuff); . 161a Ctlr *ctlr; . 159,160c char *p; . ## diffname pc/ether79c970.c 1997/0723 ## diff -e /n/emeliedump/1997/0417/sys/src/brazil/pc/ether79c970.c /n/emeliedump/1997/0723/sys/src/brazil/pc/ether79c970.c 476a bpp = &bp->next; . ## diffname pc/ether79c970.c 1997/1011 ## diff -e /n/emeliedump/1997/0723/sys/src/brazil/pc/ether79c970.c /n/emeliedump/1997/1011/sys/src/brazil/pc/ether79c970.c 479c if(port == 0) . 461,463c * Any adapter matches if no port is supplied, * otherwise the ports must match. . 459a if(scandone == 0){ amd79c970pci(); scandone = 1; } . 458a static int scandone; . 436,448c p = nil; while(p = pcimatch(p, 0x1022, 0x2000)) amd79c970adapter(&adapter, p->mem[0].bar & ~0x01, p->intl, p->tbdf); . 433,434c Pcidev *p; . 430,431c static void amd79c970pci(void) . ## diffname pc/ether79c970.c 1999/0112 ## diff -e /n/emeliedump/1997/1011/sys/src/brazil/pc/ether79c970.c /n/emeliedump/1999/0112/sys/src/brazil/pc/ether79c970.c 329,330c if(csr0 & Merr) ctlr->merr++; if(csr0 & Miss) ctlr->miss++; if(csr0 & Babl) ctlr->babl++; //if(csr0 & (Babl|Miss|Merr)) // print("#l%d: csr0 = 0x%uX\n", ether->ctlrno, csr0); . 182c len += snprint(p+len, READSTR-len, "Txbuff: %ld\n", ctlr->txbuff); len += snprint(p+len, READSTR-len, "Merr: %ld\n", ctlr->merr); len += snprint(p+len, READSTR-len, "Miss: %ld\n", ctlr->miss); snprint(p+len, READSTR-len, "Babl: %ld\n", ctlr->babl); . 134a ulong merr; /* bobf is such a whiner */ ulong miss; ulong babl; . ## diffname pc/ether79c970.c 1999/0314 ## diff -e /n/emeliedump/1999/0112/sys/src/brazil/pc/ether79c970.c /n/emeliedump/1999/0314/sys/src/brazil/pc/ether79c970.c 450a pcisetbme(p); } . 449c while(p = pcimatch(p, 0x1022, 0x2000)){ . ## diffname pc/ether79c970.c 1999/0714 ## diff -e /n/emeliedump/1999/0314/sys/src/brazil/pc/ether79c970.c /n/emeliedump/1999/0714/sys/src/brazil/pc/ether79c970.c 450c port = p->mem[0].bar & ~0x01; if(ioalloc(port, p->mem[0].size, 0, "amd79c970") < 0){ print("amd79c970: port %d in use\n", port); continue; } amd79c970adapter(&adapter, port, p->intl, p->tbdf); . 446a int port; . ## diffname pc/ether79c970.c 2000/0619 ## diff -e /n/emeliedump/1999/0714/sys/src/brazil/pc/ether79c970.c /n/emeliedump/2000/0619/sys/src/9/pc/ether79c970.c 453c print("amd79c970: port 0x%uX in use\n", port); . ## diffname pc/ether79c970.c 2001/0504 ## diff -e /n/emeliedump/2000/0619/sys/src/9/pc/ether79c970.c /n/emeliedump/2001/0504/sys/src/9/pc/ether79c970.c 433c bp = iallocb(sizeof(Adapter)); if(bp == nil) return; . ## diffname pc/ether79c970.c 2001/0527 ## diff -e /n/emeliedump/2001/0504/sys/src/9/pc/ether79c970.c /n/emeliedump/2001/0527/sys/src/9/pc/ether79c970.c 458c if(amd79c970adapter(&adapter, port, p->intl, p->tbdf)){ iofree(port); continue; } . 442a return 0; . 435c return -1; . 433c bp = allocb(sizeof(Adapter)); . 427c static int . 211a if(dre->bp == nil) panic("can't allocate ethernet receive ring\n"); . ## diffname pc/ether79c970.c 2001/0712 ## diff -e /n/emeliedump/2001/0527/sys/src/9/pc/ether79c970.c /n/emeliedump/2001/0712/sys/src/9/pc/ether79c970.c 595d 513d 509,510c ether->ctlr = ctlr; ether->port = ctlr->port; ether->irq = ctlr->pcidev->intl; ether->tbdf = ctlr->pcidev->tbdf; pcisetbme(ctlr->pcidev); . 503c if(ctlr == nil) . 501d 489,498c for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){ if(ctlr->active) continue; if(ether->port == 0 || ether->port == ctlr->port){ ctlr->active = 1; . 482,483d 480c if(ctlrhead == nil) . 478d 473,475c int x; . 462,466c ctlr = malloc(sizeof(Ctlr)); ctlr->port = p->mem[0].bar & ~0x01; ctlr->pcidev = p; if(ctlrhead != nil) ctlrtail->next = ctlr; else ctlrhead = ctlr; ctlrtail = ctlr; . 453a Ctlr *ctlr; Pcidev *p; . 452d 422,448d 140a static Ctlr* ctlrhead; static Ctlr* ctlrtail; . 112a Pcidev* pcidev; Ctlr* next; int active; . 109a typedef struct Ctlr Ctlr; . ## diffname pc/ether79c970.c 2001/0822 ## diff -e /n/emeliedump/2001/0712/sys/src/9/pc/ether79c970.c /n/emeliedump/2001/0822/sys/src/9/pc/ether79c970.c 564c /* * We used to set CSR0 to Idon|Stop here, and then * in attach change it to Iena|Strt. Apparently the simulated * 79C970 in VMware never enables after a write of Idon|Stop, * so we enable the device here now. */ ctlr->iow(ctlr, Rdp, Iena|Strt); . 562c while(!(ctlr->ior(ctlr, Rdp) & Idon)) . 553,560c ctlr->iow(ctlr, Rap, 1); ctlr->iow(ctlr, Rdp, x & 0xFFFF); ctlr->iow(ctlr, Rap, 2); ctlr->iow(ctlr, Rdp, (x>>16) & 0xFFFF); ctlr->iow(ctlr, Rap, 3); ctlr->iow(ctlr, Rdp, Idon); ctlr->iow(ctlr, Rap, 0); ctlr->iow(ctlr, Rdp, Init); . 528,530c if(ctlr->ior == io16r) x = ctlr->ior(ctlr, Aprom+2); else x >>= 16; ether->ea[2] = x; ether->ea[3] = x>>8; x = ctlr->ior(ctlr, Aprom+4); . 525c x = ctlr->ior(ctlr, Aprom); . 519,521c * Check if the adapter's station address is to be overridden. * If not, read it from the I/O-space and set in ether->ea prior to * loading the station address in the initialisation block. . 516,517d 512,514c ctlr->iow(ctlr, Rap, 0); . 509,510c ctlr->iow(ctlr, Rap, 4); x = ctlr->ior(ctlr, Rdp) & 0xFFFF; ctlr->iow(ctlr, Rdp, ApadXmt|x); . 505,507c ctlr->iow(ctlr, Rap, 20); ctlr->iow(ctlr, Bdp, 0x0002); . 492,501d 490a io32r(ctlr, Sreset); io16r(ctlr, Sreset); if(io16w(ctlr, Rap, 0), io16r(ctlr, Rdp) == 4){ ctlr->ior = io16r; ctlr->iow = io16w; }else if(io32w(ctlr, Rap, 0), io32r(ctlr, Rdp) == 4){ ctlr->ior = io32r; ctlr->iow = io32w; }else{ print("#l%d: card doesn't talk right\n", ether->ctlrno); iunlock(ctlr); return -1; } ctlr->iow(ctlr, Rap, 88); x = ctlr->ior(ctlr, Rdp); ctlr->iow(ctlr, Rap, 89); x |= ctlr->ior(ctlr, Rdp)<<16; switch(x&0xFFFFFFF){ case 0x2420003: /* PCnet/PCI 79C970 */ case 0x2621003: /* PCnet/PCI II 79C970A */ break; default: print("#l%d: unknown PCnet card version %.7ux\n", ether->ctlrno, x&0xFFFFFFF); iunlock(ctlr); return -1; } . 343,344c csr0 = ctlr->ior(ctlr, Rdp) & 0xFFFF; ctlr->iow(ctlr, Rdp, Babl|Cerr|Miss|Merr|Rint|Tint|Iena); . 310c ctlr->iow(ctlr, Rdp, Iena|Tdmd); . 302c * here as ApadXmt is set in CSR4. . 276c ctlr->iow(ctlr, Rdp, Iena|Strt); . 269,270c ctlr->iow(ctlr, Rdp, x); ctlr->iow(ctlr, Rap, 0); . 265,266c ctlr->iow(ctlr, Rap, 15); x = ctlr->ior(ctlr, Rdp) & ~Prom; . 263c ctlr->iow(ctlr, Rdp, Stop); . 166a static void attach(Ether*) { } . 158,164c static void io32w(Ctlr *c, int r, int v) { outl(c->port+r, v); . 156c static int io32r(Ctlr *c, int r) { return inl(c->port+r); } . 154c if(r >= Rdp) r = (r-Rdp)/2+Rdp; outs(c->port+r, v); } . 152c io16w(Ctlr *c, int r, int v) . 148,149c /* * The Rdp, Rap, Sreset, Bdp ports are 32-bit port offset in the enumeration above. * To get to 16-bit offsets, scale down with 0x10 staying the same. */ static int io16r(Ctlr *c, int r) { if(r >= Rdp) r = (r-Rdp)/2+Rdp; return ins(c->port+r); } . 144a int (*ior)(Ctlr*, int); void (*iow)(Ctlr*, int, int); }; . 143d 111c struct Ctlr { . 2c * AMD79C970 . ## diffname pc/ether79c970.c 2001/1015 ## diff -e /n/emeliedump/2001/0822/sys/src/9/pc/ether79c970.c /n/emeliedump/2001/1015/sys/src/9/pc/ether79c970.c 503a if(ioalloc(ctlr->port, 0x20, 0, "ether79c970") < 0) return -1; . ## diffname pc/ether79c970.c 2002/0404 ## diff -e /n/emeliedump/2001/1015/sys/src/9/pc/ether79c970.c /n/emeliedump/2002/0404/sys/src/9/pc/ether79c970.c 540a ether->ctlrno, x&0xFFFFFFF); iprint("#l%d: unknown PCnet card version %.7ux\n", . 525a iprint("#l%d: card doesn't talk right\n", ether->ctlrno); . 504,506d