From 78ee7d5717807e6ac779293d0d3c78341de6130a Mon Sep 17 00:00:00 2001 From: "Konstantin Kirik (snegovick)" Date: Sun, 28 Dec 2025 12:27:31 +0300 Subject: Move existing boards into subdits split per arch --- os/pc/ether83815.c | 1119 ---------------------------------------------------- 1 file changed, 1119 deletions(-) delete mode 100644 os/pc/ether83815.c (limited to 'os/pc/ether83815.c') diff --git a/os/pc/ether83815.c b/os/pc/ether83815.c deleted file mode 100644 index 3d2d9d76..00000000 --- a/os/pc/ether83815.c +++ /dev/null @@ -1,1119 +0,0 @@ -/* - * National Semiconductor DP83815 - * - * Supports only internal PHY and has been tested on: - * Netgear FA311TX (using Netgear DS108 10/100 hub) - * To do: - * check Ethernet address; - * test autonegotiation on 10 Mbit, and 100 Mbit full duplex; - * external PHY via MII (should be common code for MII); - * thresholds; - * ring sizing; - * physical link changes/disconnect; - * push initialisation back to attach. - * - * C H Forsyth, forsyth@vitanuova.com, 18th June 2001. - */ - -#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" - -#define DEBUG (0) -#define debug if(DEBUG)print - -enum { - Nrde = 64, - Ntde = 64, -}; - -#define Rbsz ROUNDUP(sizeof(Etherpkt)+4, 4) - -typedef struct Des { - ulong next; - int cmdsts; - ulong addr; - Block* bp; -} Des; - -enum { /* cmdsts */ - 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 */ - 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 */ - - /* transmit */ - Txa = 1<<26, /* transmission aborted */ - Tfu = 1<<25, /* transmit fifo underrun */ - Crs = 1<<24, /* carrier sense lost */ - Td = 1<<23, /* transmission deferred */ - Ed = 1<<22, /* excessive deferral */ - Owc = 1<<21, /* out of window collision */ - Ec = 1<<20, /* excessive collisions */ - /* 19-16 collision count */ - - /* receive */ - Rxa = 1<<26, /* receive aborted (same as Rxo) */ - Rxo = 1<<25, /* receive overrun */ - Dest = 3<<23, /* destination class */ - Drej= 0<<23, /* packet was rejected */ - 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 */ -}; - -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; -typedef struct Ctlr { - int port; - Pcidev* pcidev; - Ctlr* next; - int active; - int id; /* (pcidev->did<<16)|pcidev->vid */ - - ushort srom[0xB+1]; - uchar sromea[Eaddrlen]; /* MAC address */ - - uchar fd; /* option or auto negotiation */ - - int mbps; - - Lock lock; - - Des* rdr; /* receive descriptor ring */ - int nrdr; /* size of rdr */ - int rdrx; /* index into rdr */ - - Lock tlock; - Des* tdr; /* transmit descriptor ring */ - int ntdr; /* size of tdr */ - int tdrh; /* host index into tdr */ - int tdri; /* interface index into tdr */ - int ntq; /* descriptors active */ - int ntqmax; - - ulong rxa; /* receive statistics */ - ulong rxo; - ulong rlong; - ulong runt; - ulong ise; - ulong crce; - ulong fae; - ulong lbp; - ulong col; - ulong rxsovr; - ulong rxorn; - - ulong txa; /* transmit statistics */ - ulong tfu; - ulong crs; - ulong td; - ulong ed; - ulong owc; - ulong ec; - ulong txurn; - - ulong dperr; /* system errors */ - ulong rmabt; - ulong rtabt; - ulong sserr; - ulong rxsover; -} Ctlr; - -static Ctlr* ctlrhead; -static Ctlr* ctlrtail; - -enum { - /* registers (could memory map) */ - Rcr= 0x00, /* command register */ - Rst= 1<<8, - Rxr= 1<<5, /* receiver reset */ - Txr= 1<<4, /* transmitter reset */ - Rxd= 1<<3, /* receiver disable */ - Rxe= 1<<2, /* receiver enable */ - Txd= 1<<1, /* transmitter disable */ - Txe= 1<<0, /* transmitter enable */ - 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) */ - Aneg_dn= 1<<27, /* autonegotiation done */ - Pint_acen= 1<<17, /* PHY interrupt auto clear enable */ - Pause_adv= 1<<16, /* advertise pause during auto neg */ - 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) */ - Req_alg= 1<<7, /* PCI bus request: set means less aggressive */ - 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 */ - Brom_dis= 1<<2, /* disable boot rom interface */ - Bem= 1<<0, /* big-endian mode */ - Rmear= 0x08, /* eeprom access */ - Mdc= 1<<6, /* MII mangement check */ - Mddir= 1<<5, /* MII management direction */ - Mdio= 1<<4, /* MII mangement data */ - 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 */ - 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) */ - 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) */ - 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) */ - 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 */ - 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 */ - 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 */ - Drth512= 16<<0, /* drain at 512 bytes */ - 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) */ - 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 */ - 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 */ - 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 */ - - /* 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 */ - Anrestart= 1<<9, /* restart auto negotiation */ - 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 */ -}; - -/* - * eeprom addresses - * 7 to 9 (16 bit words): mac address, shifted and reversed - */ - -#define csr32r(c, r) (inl((c)->port+(r))) -#define csr32w(c, r, l) (outl((c)->port+(r), (ulong)(l))) -#define csr16r(c, r) (ins((c)->port+(r))) -#define csr16w(c, r, l) (outs((c)->port+(r), (ulong)(l))) - -static void -dumpcregs(Ctlr *ctlr) -{ - int i; - - for(i=0; i<=0x5C; i+=4) - print("%2.2ux %8.8lux\n", i, csr32r(ctlr, i)); -} - -static void -promiscuous(void* arg, int on) -{ - Ctlr *ctlr; - ulong w; - - ctlr = ((Ether*)arg)->ctlr; - ilock(&ctlr->lock); - w = csr32r(ctlr, Rrfcr); - if(on != ((w&Aau)!=0)){ - csr32w(ctlr, Rrfcr, w & ~Rfen); - csr32w(ctlr, Rrfcr, Rfen | (w ^ Aau)); - } - iunlock(&ctlr->lock); -} - -static void -attach(Ether* ether) -{ - Ctlr *ctlr; - - ctlr = ether->ctlr; - ilock(&ctlr->lock); - if(0) - dumpcregs(ctlr); - csr32w(ctlr, Rcr, Rxe); - iunlock(&ctlr->lock); -} - -static long -ifstat(Ether* ether, void* a, long n, ulong offset) -{ - Ctlr *ctlr; - char *buf, *p; - int i, l, len; - - ctlr = ether->ctlr; - - ether->crcs = ctlr->crce; - ether->frames = ctlr->runt+ctlr->ise+ctlr->rlong+ctlr->fae; - ether->buffs = ctlr->rxorn+ctlr->tfu; - ether->overflows = ctlr->rxsovr; - - if(n == 0) - return 0; - - p = malloc(READSTR); - l = snprint(p, READSTR, "Rxa: %lud\n", ctlr->rxa); - l += snprint(p+l, READSTR-l, "Rxo: %lud\n", ctlr->rxo); - l += snprint(p+l, READSTR-l, "Rlong: %lud\n", ctlr->rlong); - l += snprint(p+l, READSTR-l, "Runt: %lud\n", ctlr->runt); - l += snprint(p+l, READSTR-l, "Ise: %lud\n", ctlr->ise); - l += snprint(p+l, READSTR-l, "Fae: %lud\n", ctlr->fae); - l += snprint(p+l, READSTR-l, "Lbp: %lud\n", ctlr->lbp); - l += snprint(p+l, READSTR-l, "Tfu: %lud\n", ctlr->tfu); - l += snprint(p+l, READSTR-l, "Txa: %lud\n", ctlr->txa); - l += snprint(p+l, READSTR-l, "CRC Error: %lud\n", ctlr->crce); - l += snprint(p+l, READSTR-l, "Collision Seen: %lud\n", ctlr->col); - l += snprint(p+l, READSTR-l, "Frame Too Long: %lud\n", ctlr->rlong); - l += snprint(p+l, READSTR-l, "Runt Frame: %lud\n", ctlr->runt); - l += snprint(p+l, READSTR-l, "Rx Underflow Error: %lud\n", ctlr->rxorn); - l += snprint(p+l, READSTR-l, "Tx Underrun: %lud\n", ctlr->txurn); - l += snprint(p+l, READSTR-l, "Excessive Collisions: %lud\n", ctlr->ec); - l += snprint(p+l, READSTR-l, "Late Collision: %lud\n", ctlr->owc); - l += snprint(p+l, READSTR-l, "Loss of Carrier: %lud\n", ctlr->crs); - l += snprint(p+l, READSTR-l, "Parity: %lud\n", ctlr->dperr); - l += snprint(p+l, READSTR-l, "Aborts: %lud\n", ctlr->rmabt+ctlr->rtabt); - l += snprint(p+l, READSTR-l, "RX Status overrun: %lud\n", ctlr->rxsover); - snprint(p+l, READSTR-l, "ntqmax: %d\n", ctlr->ntqmax); - ctlr->ntqmax = 0; - buf = a; - len = readstr(offset, buf, n, p); - if(offset > l) - offset -= l; - else - offset = 0; - buf += len; - n -= len; - - l = snprint(p, READSTR, "srom:"); - for(i = 0; i < nelem(ctlr->srom); i++){ - if(i && ((i & 0x0F) == 0)) - l += snprint(p+l, READSTR-l, "\n "); - l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->srom[i]); - } - - snprint(p+l, READSTR-l, "\n"); - len += readstr(offset, buf, n, p); - free(p); - - return len; -} - -static void -txstart(Ether* ether) -{ - Ctlr *ctlr; - Block *bp; - Des *des; - int started; - - ctlr = ether->ctlr; - started = 0; - while(ctlr->ntq < ctlr->ntdr-1){ - bp = qget(ether->oq); - if(bp == nil) - break; - des = &ctlr->tdr[ctlr->tdrh]; - des->bp = bp; - des->addr = PADDR(bp->rp); - ctlr->ntq++; - coherence(); - des->cmdsts = Own | BLEN(bp); - ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr); - started = 1; - } - if(started){ - coherence(); - csr32w(ctlr, Rcr, Txe); /* prompt */ - } - - if(ctlr->ntq > ctlr->ntqmax) - ctlr->ntqmax = ctlr->ntq; -} - -static void -transmit(Ether* ether) -{ - Ctlr *ctlr; - - ctlr = ether->ctlr; - ilock(&ctlr->tlock); - txstart(ether); - iunlock(&ctlr->tlock); -} - -static void -txrxcfg(Ctlr *ctlr, int txdrth) -{ - ulong rx, tx; - - rx = csr32r(ctlr, Rrxcfg); - tx = csr32r(ctlr, Rtxcfg); - if(ctlr->fd){ - rx |= Atx; - tx |= Csi | Hbi; - }else{ - rx &= ~Atx; - tx &= ~(Csi | Hbi); - } - tx &= ~(Mxdma|Drth|Flth); - tx |= Mxdma64 | Flth128 | txdrth; - csr32w(ctlr, Rtxcfg, tx); - rx &= ~(Mxdma|Rdrth); - rx |= Mxdma64 | Rdrth64; - csr32w(ctlr, Rrxcfg, rx); -} - -static void -interrupt(Ureg*, void* arg) -{ - int len, status, cmdsts, n; - Ctlr *ctlr; - Ether *ether; - Des *des; - Block *bp; - - ether = arg; - ctlr = ether->ctlr; - - while((status = csr32r(ctlr, Risr)) != 0){ - - status &= ~(Pme|Mib); - - if(status & Hiberr){ - if(status & Rxsovr) - ctlr->rxsover++; - if(status & Sserr) - ctlr->sserr++; - if(status & Dperr) - ctlr->dperr++; - if(status & Rmabt) - ctlr->rmabt++; - if(status & Rtabt) - ctlr->rtabt++; - status &= ~(Hiberr|Txrcmp|Rxrcmp|Rxsovr|Dperr|Sserr|Rmabt|Rtabt); - } - - /* update link state */ - if(status&Phy){ - status &= ~Phy; - csr32r(ctlr, Rcfg); - n = csr32r(ctlr, Rcfg); -// iprint("83815 phy %x %x\n", n, n&Lnksts); - ether->link = (n&Lnksts) != 0; - } - - /* - * Received packets. - */ - if(status & (Rxdesc|Rxok|Rxerr|Rxearly|Rxorn)){ - des = &ctlr->rdr[ctlr->rdrx]; - while((cmdsts = des->cmdsts) & Own){ - if((cmdsts&Ok) == 0){ - if(cmdsts & Rxa) - ctlr->rxa++; - if(cmdsts & Rxo) - ctlr->rxo++; - if(cmdsts & Long) - ctlr->rlong++; - if(cmdsts & Runt) - ctlr->runt++; - if(cmdsts & Ise) - ctlr->ise++; - if(cmdsts & Crce) - ctlr->crce++; - if(cmdsts & Fae) - ctlr->fae++; - if(cmdsts & Lbp) - ctlr->lbp++; - if(cmdsts & Col) - ctlr->col++; - } - else if(bp = iallocb(Rbsz)){ - len = (cmdsts&Size)-4; - 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; - coherence(); - - ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr); - des = &ctlr->rdr[ctlr->rdrx]; - } - status &= ~(Rxdesc|Rxok|Rxerr|Rxearly|Rxorn); - } - - /* - * Check the transmit side: - * check for Transmit Underflow and Adjust - * the threshold upwards; - * free any transmitted buffers and try to - * top-up the ring. - */ - if(status & Txurn){ - ctlr->txurn++; - ilock(&ctlr->lock); - /* change threshold */ - iunlock(&ctlr->lock); - status &= ~(Txurn); - } - - ilock(&ctlr->tlock); - while(ctlr->ntq){ - des = &ctlr->tdr[ctlr->tdri]; - cmdsts = des->cmdsts; - if(cmdsts & Own) - break; - - if((cmdsts & Ok) == 0){ - if(cmdsts & Txa) - ctlr->txa++; - if(cmdsts & Tfu) - ctlr->tfu++; - if(cmdsts & Td) - ctlr->td++; - if(cmdsts & Ed) - ctlr->ed++; - if(cmdsts & Owc) - ctlr->owc++; - if(cmdsts & Ec) - ctlr->ec++; - ether->oerrs++; - } - - freeb(des->bp); - des->bp = nil; - des->cmdsts = 0; - - ctlr->ntq--; - ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr); - } - txstart(ether); - iunlock(&ctlr->tlock); - - status &= ~(Txurn|Txidle|Txerr|Txdesc|Txok); - - /* - * Anything left not catered for? - */ - if(status) - print("#l%d: status %8.8uX\n", ether->ctlrno, status); - } -} - -static void -ctlrinit(Ether* ether) -{ - Ctlr *ctlr; - Des *des, *last; - - ctlr = ether->ctlr; - - /* - * Allocate suitable aligned descriptors - * for the transmit and receive rings; - * initialise the receive ring; - * initialise the transmit ring; - * unmask interrupts and start the transmit side. - */ - des = xspanalloc((ctlr->nrdr+ctlr->ntdr)*sizeof(Des), 32, 0); - ctlr->tdr = des; - ctlr->rdr = des+ctlr->ntdr; - - last = nil; - for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){ - des->bp = iallocb(Rbsz); - if(des->bp == nil) - error(Enomem); - des->cmdsts = Rbsz; - des->addr = PADDR(des->bp->rp); - if(last != nil) - last->next = PADDR(des); - last = des; - } - ctlr->rdr[ctlr->nrdr-1].next = PADDR(ctlr->rdr); - ctlr->rdrx = 0; - csr32w(ctlr, Rrxdp, PADDR(ctlr->rdr)); - - last = nil; - for(des = ctlr->tdr; des < &ctlr->tdr[ctlr->ntdr]; des++){ - des->cmdsts = 0; - des->bp = nil; - des->addr = ~0; - if(last != nil) - last->next = PADDR(des); - last = des; - } - ctlr->tdr[ctlr->ntdr-1].next = PADDR(ctlr->tdr); - ctlr->tdrh = 0; - ctlr->tdri = 0; - csr32w(ctlr, Rtxdp, PADDR(ctlr->tdr)); - - txrxcfg(ctlr, Drth512); - - csr32w(ctlr, Rimr, Dperr|Sserr|Rmabt|Rtabt|Rxsovr|Hiberr|Txurn|Txerr| - Txdesc|Txok|Rxorn|Rxerr|Rxdesc|Rxok); /* Phy|Pme|Mib */ - csr32w(ctlr, Rmicr, Inten); /* enable phy interrupts */ - csr32r(ctlr, Risr); /* clear status */ - csr32w(ctlr, Rier, Ie); -} - -static void -eeclk(Ctlr *ctlr, int clk) -{ - csr32w(ctlr, Rmear, Eesel | clk); - microdelay(2); -} - -static void -eeidle(Ctlr *ctlr) -{ - int i; - - eeclk(ctlr, 0); - eeclk(ctlr, Eeclk); - for(i=0; i<25; i++){ - eeclk(ctlr, 0); - eeclk(ctlr, Eeclk); - } - eeclk(ctlr, 0); - csr32w(ctlr, Rmear, 0); - microdelay(2); -} - -static int -eegetw(Ctlr *ctlr, int a) -{ - int d, i, w, v; - - eeidle(ctlr); - eeclk(ctlr, 0); - eeclk(ctlr, Eeclk); - d = 0x180 | a; - for(i=0x400; i; i>>=1){ - v = (d & i) ? Eedi : 0; - eeclk(ctlr, v); - eeclk(ctlr, Eeclk|v); - } - eeclk(ctlr, 0); - - w = 0; - for(i=0x8000; i; i >>= 1){ - eeclk(ctlr, Eeclk); - if(csr32r(ctlr, Rmear) & Eedo) - w |= i; - microdelay(2); - eeclk(ctlr, 0); - } - eeidle(ctlr); - return w; -} - -static void -resetctlr(Ctlr *ctlr) -{ - int i; - - csr32w(ctlr, Rcr, Rst); - for(i=0;; i++){ - if(i > 100) - panic("ns83815: soft reset did not complete"); - microdelay(250); - if((csr32r(ctlr, Rcr) & Rst) == 0) - break; - delay(1); - } -} - -static void -shutdown(Ether* ether) -{ - Ctlr *ctlr = ether->ctlr; - -print("ether83815 shutting down\n"); - csr32w(ctlr, Rcr, Rxd|Txd); /* disable transceiver */ - resetctlr(ctlr); -} - -static void -softreset(Ctlr* ctlr, int resetphys) -{ - int i, w; - - /* - * Soft-reset the controller - */ - resetctlr(ctlr); - csr32w(ctlr, Rccsr, Pmests); - csr32w(ctlr, Rccsr, 0); - csr32w(ctlr, Rcfg, csr32r(ctlr, Rcfg) | Pint_acen); - - if(resetphys){ - /* - * Soft-reset the PHY - */ - csr32w(ctlr, Rbmcr, Reset); - for(i=0;; i++){ - if(i > 100) - panic("ns83815: PHY soft reset time out"); - if((csr32r(ctlr, Rbmcr) & Reset) == 0) - break; - delay(1); - } - } - - /* - * Initialisation values, in sequence (see 4.4 Recommended Registers Configuration) - */ - csr16w(ctlr, 0xCC, 0x0001); /* PGSEL */ - csr16w(ctlr, 0xE4, 0x189C); /* PMCCSR */ - csr16w(ctlr, 0xFC, 0x0000); /* TSTDAT */ - csr16w(ctlr, 0xF4, 0x5040); /* DSPCFG */ - csr16w(ctlr, 0xF8, 0x008C); /* SDCFG */ - - /* - * Auto negotiate - */ - w = csr16r(ctlr, Rbmsr); /* clear latched bits */ - debug("anar: %4.4ux\n", csr16r(ctlr, Ranar)); - csr16w(ctlr, Rbmcr, Anena); - if(csr16r(ctlr, Ranar) == 0 || (csr32r(ctlr, Rcfg) & Aneg_dn) == 0){ - csr16w(ctlr, Rbmcr, Anena|Anrestart); - for(i=0;; i++){ - if(i > 3000){ - print("ns83815: auto neg timed out\n"); - break; - } - if((w = csr16r(ctlr, Rbmsr)) & Ancomp) - break; - delay(1); - } - 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)); - debug("aner: %4.4ux\n", csr16r(ctlr, Raner)); - debug("physts: %4.4ux\n", csr16r(ctlr, Rphysts)); - debug("tbscr: %4.4ux\n", csr16r(ctlr, Rtbscr)); -} - -static int -media(Ether* ether) -{ - Ctlr* ctlr; - ulong cfg; - - ctlr = ether->ctlr; - cfg = csr32r(ctlr, Rcfg); - ctlr->fd = (cfg & Fdup) != 0; - ether->link = (cfg&Lnksts) != 0; - return (cfg&(Lnksts|Speed100)) == Lnksts? 10: 100; -} - -static char* mediatable[9] = { - "10BASE-T", /* TP */ - "10BASE-2", /* BNC */ - "10BASE-5", /* AUI */ - "100BASE-TX", - "10BASE-TFD", - "100BASE-TXFD", - "100BASE-T4", - "100BASE-FX", - "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 -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; - - for(i = 0; i < nelem(ctlr->srom); i++) - ctlr->srom[i] = eegetw(ctlr, i); - - /* - * the MAC address is reversed, straddling word boundaries - */ - 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++; - } -} - -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 != Pcibcnet || p->ccru != 0) - continue; - id = (p->did<<16)|p->vid; - switch(id){ - default: - continue; - - case Nat83815: - break; - case SiS900: - break; - } - - /* - * bar[0] is the I/O port register address and - * bar[1] is the memory-mapped register address. - */ - ctlr = malloc(sizeof(Ctlr)); - ctlr->port = p->mem[0].bar & ~0x01; - ctlr->pcidev = p; - ctlr->id = id; - - if(ioalloc(ctlr->port, p->mem[0].size, 0, "ns83815") < 0){ - print("ns83815: port 0x%uX in use\n", ctlr->port); - free(ctlr); - continue; - } - - softreset(ctlr, 0); - srom(ctlr); - - if(ctlrhead != nil) - ctlrtail->next = ctlr; - else - ctlrhead = ctlr; - ctlrtail = ctlr; - } -} - -/* multicast already on, don't need to do anything */ -static void -multicast(void*, uchar*, int) -{ -} - -static int -reset(Ether* ether) -{ - Ctlr *ctlr; - int i, x; - ulong ctladdr; - uchar ea[Eaddrlen]; - static int scandone; - - if(scandone == 0){ - scanpci83815(); - scandone = 1; - } - - /* - * Any adapter matches if no ether->port is supplied, - * otherwise the ports must match. - */ - for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){ - if(ctlr->active) - continue; - if(ether->port == 0 || ether->port == ctlr->port){ - ctlr->active = 1; - break; - } - } - if(ctlr == nil) - return -1; - - ether->ctlr = ctlr; - ether->port = ctlr->port; - ether->irq = ctlr->pcidev->intl; - ether->tbdf = ctlr->pcidev->tbdf; - - /* - * Check if the adapter's station address is to be overridden. - * If not, read it from the EEPROM and set in ether->ea prior to - * loading the station address in the hardware. - */ - memset(ea, 0, Eaddrlen); - if(memcmp(ea, ether->ea, Eaddrlen) == 0) - memmove(ether->ea, ctlr->sromea, Eaddrlen); - for(i=0; iea[i] | (ether->ea[i+1]<<8); - ctladdr = (ctlr->id == Nat83815? i: i<<15); - csr32w(ctlr, Rrfcr, ctladdr); - csr32w(ctlr, Rrfdr, x); - } - csr32w(ctlr, Rrfcr, Rfen|Apm|Aab|Aam); - - ether->mbps = media(ether); - - /* - * Look for a medium override in case there's no autonegotiation - * the autonegotiation fails. - */ - - for(i = 0; i < ether->nopt; i++){ - if(cistrcmp(ether->opt[i], "FD") == 0){ - ctlr->fd = 1; - continue; - } - for(x = 0; x < nelem(mediatable); x++){ - debug("compare <%s> <%s>\n", mediatable[x], - ether->opt[i]); - if(cistrcmp(mediatable[x], ether->opt[i]) == 0){ - if(x != 4 && x >= 3) - ether->mbps = 100; - else - ether->mbps = 10; - switch(x){ - default: - ctlr->fd = 0; - break; - - case 0x04: /* 10BASE-TFD */ - case 0x05: /* 100BASE-TXFD */ - case 0x08: /* 100BASE-FXFD */ - ctlr->fd = 1; - break; - } - break; - } - } - } - - /* - * Initialise descriptor rings, ethernet address. - */ - ctlr->nrdr = Nrde; - ctlr->ntdr = Ntde; - pcisetbme(ctlr->pcidev); - ctlrinit(ether); - - /* - * Linkage to the generic ethernet driver. - */ - ether->attach = attach; - ether->transmit = transmit; - ether->interrupt = interrupt; - ether->ifstat = ifstat; - - ether->arg = ether; - ether->promiscuous = promiscuous; - ether->multicast = multicast; - ether->shutdown = shutdown; - return 0; -} - -void -ether83815link(void) -{ - addethercard("83815", reset); -} -- cgit v1.2.3