From 8a8c2d742b51525f66c2210e3c8a251de10022ff Mon Sep 17 00:00:00 2001 From: "Charles.Forsyth" Date: Wed, 11 Jun 2008 14:21:44 +0000 Subject: 20080611-1520 --- os/boot/pc/etherrhine.c | 533 +++++++++++++++++++++++------------------------- 1 file changed, 257 insertions(+), 276 deletions(-) (limited to 'os/boot/pc/etherrhine.c') diff --git a/os/boot/pc/etherrhine.c b/os/boot/pc/etherrhine.c index b4d37bf5..2a582c72 100644 --- a/os/boot/pc/etherrhine.c +++ b/os/boot/pc/etherrhine.c @@ -1,4 +1,4 @@ - /* +/* Via Rhine driver, written for VT6102. Uses the ethermii to control PHY. @@ -7,7 +7,7 @@ (almost) copy-free by using (possibly) two descriptors (if it allows arbitrary tx lengths, which it should..): first for alignment and second for rest of the frame. Rx-part should be worth doing. -*/ + */ #include "u.h" #include "lib.h" #include "mem.h" @@ -18,267 +18,228 @@ typedef struct QLock { int r; } QLock; #define qlock(i) while(0) #define qunlock(i) while(0) -#define coherence() #define iprint print #include "etherif.h" #include "ethermii.h" -typedef struct Desc Desc; -typedef struct Ctlr Ctlr; - enum { Ntxd = 4, Nrxd = 4, Nwait = 50, - Ntxstats = 9, - Nrxstats = 8, BIGSTR = 8192, }; +typedef struct Desc Desc; +typedef struct Ctlr Ctlr; + struct Desc { - ulong stat; - ulong size; - ulong addr; - ulong next; - char *buf; - ulong pad[3]; + ulong stat; + ulong size; + ulong addr; + ulong next; + char *buf; + ulong pad[3]; }; struct Ctlr { - Pcidev *pci; - int attached; - int txused; - int txhead; - int txtail; - int rxtail; - ulong port; + Pcidev *pci; + int attached; + int txused; + int txhead; + int txtail; + int rxtail; + ulong port; - Mii mii; + Mii mii; - ulong txstats[Ntxstats]; - ulong rxstats[Nrxstats]; + Desc *txd; /* wants to be aligned on 16-byte boundary */ + Desc *rxd; - Desc *txd; /* wants to be aligned on 16-byte boundary */ - Desc *rxd; - - QLock attachlck; - Lock tlock; + QLock attachlck; + Lock tlock; }; #define ior8(c, r) (inb((c)->port+(r))) +#define iow8(c, r, b) (outb((c)->port+(r), (int)(b))) #define ior16(c, r) (ins((c)->port+(r))) #define ior32(c, r) (inl((c)->port+(r))) -#define iow8(c, r, b) (outb((c)->port+(r), (int)(b))) #define iow16(c, r, w) (outs((c)->port+(r), (ushort)(w))) #define iow32(c, r, l) (outl((c)->port+(r), (ulong)(l))) +/* names used everywhere else */ +#define csr8r ior8 +#define csr8w iow8 +#define csr16r ior16 +#define csr16w iow16 +#define csr32r ior32 +#define csr32w iow32 + enum Regs { - Eaddr = 0x0, - Rcr = 0x6, - Tcr = 0x7, - Cr = 0x8, - Isr = 0xc, - Imr = 0xe, - McastAddr = 0x10, - RxdAddr = 0x18, - TxdAddr = 0x1C, - Bcr = 0x6e, - RhineMiiPhy = 0x6C, - RhineMiiSr = 0x6D, - RhineMiiCr = 0x70, - RhineMiiAddr = 0x71, - RhineMiiData = 0x72, - Eecsr = 0x74, - ConfigB = 0x79, - ConfigD = 0x7B, - MiscCr = 0x80, - HwSticky = 0x83, - MiscIsr = 0x84, - MiscImr = 0x86, - WolCrSet = 0xA0, - WolCfgSet = 0xA1, - WolCgSet = 0xA3, - WolCrClr = 0xA4, - PwrCfgClr = 0xA5, - WolCgClr = 0xA7, + Eaddr = 0x0, + Rcr = 0x6, + Tcr = 0x7, + Cr = 0x8, + Isr = 0xc, + Imr = 0xe, + McastAddr = 0x10, + RxdAddr = 0x18, + TxdAddr = 0x1C, + Bcr0 = 0x6E, /* Bus Control */ + Bcr1 = 0x6F, + RhineMiiPhy = 0x6C, + RhineMiiSr = 0x6D, + RhineMiiCr = 0x70, + RhineMiiAddr = 0x71, + RhineMiiData = 0x72, + Eecsr = 0x74, + ConfigB = 0x79, + ConfigD = 0x7B, + MiscCr = 0x80, + HwSticky = 0x83, + MiscIsr = 0x84, + MiscImr = 0x86, + WolCrSet = 0xA0, + WolCfgSet = 0xA1, + WolCgSet = 0xA3, + WolCrClr = 0xA4, + PwrCfgClr = 0xA5, + WolCgClr = 0xA7, }; -enum Rcrbits { - RxErrX = 1<<0, - RxSmall = 1<<1, - RxMcast = 1<<2, - RxBcast = 1<<3, - RxProm = 1<<4, - RxFifo64 = 0<<5, RxFifo32 = 1<<5, RxFifo128 = 2<<5, RxFifo256 = 3<<5, - RxFifo512 = 4<<5, RxFifo768 = 5<<5, RxFifo1024 = 6<<5, - RxFifoStoreForward = 7<<5, +enum { /* Rcr */ + Sep = 0x01, /* Accept Error Packets */ + Ar = 0x02, /* Accept Small Packets */ + Am = 0x04, /* Accept Multicast */ + Ab = 0x08, /* Accept Broadcast */ + RxBcast = Ab, + Prom = 0x10, /* Accept Physical Address Packets */ + RxProm = Prom, + RrftMASK = 0xE0, /* Receive FIFO Threshold */ + RrftSHIFT = 5, + Rrft64 = 0<ctlr; qlock(&ctlr->attachlck); if (ctlr->attached == 0) { @@ -321,14 +282,15 @@ attach(Ether *edev) s = splhi(); iow32(ctlr, TxdAddr, PCIWADDR(&txd[0])); iow32(ctlr, RxdAddr, PCIWADDR(&rxd[0])); - iow16(ctlr, Cr, (phy->fd ? FullDuplex : 0) | NoAutoPoll | TxOn | RxOn | Start | Rdmd); + iow16(ctlr, Cr, (phy->fd? FullDuplex: 0) | NoAutoPoll | TxOn | + RxOn | Start | Rdmd); iow16(ctlr, Isr, 0xFFFF); iow16(ctlr, Imr, 0xFFFF); iow8(ctlr, MiscIsr, 0xFF); iow8(ctlr, MiscImr, ~(3<<5)); splx(s); + ctlr->attached = 1; } - ctlr->attached++; qunlock(&ctlr->attachlck); } @@ -341,23 +303,21 @@ txstart(Ether *edev) RingBuf *tb; ctlr = edev->ctlr; - txd = ctlr->txd; i = ctlr->txhead; - txused = ctlr->txused; n = 0; - while (txused < Ntxd) { + for (txused = ctlr->txused; txused < Ntxd; txused++) { tb = &edev->tb[edev->ti]; if(tb->owner != Interface) break; td = &txd[i]; memmove(td->buf, tb->pkt, tb->len); - td->size = tb->len | TxChainStart | TxChainEnd | TxInt; /* could reduce number of ints here */ + /* could reduce number of intrs here */ + td->size = tb->len | TxChainStart | TxChainEnd | TxInt; coherence(); td->stat = OwnNic; i = (i + 1) % Ntxd; - txused++; n++; tb->owner = Host; @@ -374,6 +334,7 @@ static void transmit(Ether *edev) { Ctlr *ctlr; + ctlr = edev->ctlr; ilock(&ctlr->tlock); txstart(edev); @@ -385,27 +346,18 @@ txcomplete(Ether *edev) { Ctlr *ctlr; Desc *txd, *td; - int i, txused, j; + int i, txused; ulong stat; ctlr = edev->ctlr; txd = ctlr->txd; - txused = ctlr->txused; i = ctlr->txtail; - while (txused > 0) { + for (txused = ctlr->txused; txused > 0; txused--) { td = &txd[i]; stat = td->stat; - if (stat & OwnNic) break; - - ctlr->txstats[Ntxstats-1] += stat & 0xF; - for (j = 0; j < Ntxstats-1; ++j) - if (stat & (1<<(j+8))) - ctlr->txstats[j]++; - i = (i + 1) % Ntxd; - txused--; } ctlr->txused = txused; ctlr->txtail = i; @@ -423,14 +375,15 @@ interrupt(Ureg *, void *arg) ushort isr, misr; ulong stat; Desc *rxd, *rd; - int i, n, j, size; + int i, n, size; edev = (Ether*)arg; ctlr = edev->ctlr; iow16(ctlr, Imr, 0); isr = ior16(ctlr, Isr); iow16(ctlr, Isr, 0xFFFF); - misr = ior16(ctlr, MiscIsr) & ~(3<<5); /* don't care about used defined ints */ + /* don't care about used defined intrs */ + misr = ior16(ctlr, MiscIsr) & ~(3<<5); if (isr & RxOk) { rxd = ctlr->rxd; @@ -440,14 +393,9 @@ interrupt(Ureg *, void *arg) while ((rxd[i].stat & OwnNic) == 0) { rd = &rxd[i]; stat = rd->stat; - for (j = 0; j < Nrxstats; ++j) - if (stat & (1<rxstats[j]++; - if (stat & 0xFF) iprint("rx: %lux\n", stat & 0xFF); - - size = ((rd->stat>>16) & 2047) - 4; + size = ((rd->stat>>16) & (2048-1)) - 4; rb = &edev->rb[edev->ri]; if(rb->owner == Interface){ @@ -473,24 +421,11 @@ interrupt(Ureg *, void *arg) isr &= ~TxOk; } if (isr | misr) - iprint("etherrhine: unhandled irq(s). isr:%x misr:%x\n", isr, misr); - + iprint("etherrhine: unhandled irq(s). isr:%x misr:%x\n", + isr, misr); iow16(ctlr, Imr, 0xFFFF); } -static void -promiscuous(void *arg, int enable) -{ - Ether *edev; - Ctlr *ctlr; - - edev = arg; - ctlr = edev->ctlr; - ilock(&ctlr->tlock); - iow8(ctlr, Rcr, ior8(ctlr, Rcr) | (enable ? RxProm : RxBcast)); - iunlock(&ctlr->tlock); -} - static int miiread(Mii *mii, int phy, int reg) { @@ -498,7 +433,7 @@ miiread(Mii *mii, int phy, int reg) int n; ctlr = mii->ctlr; - + n = Nwait; while (n-- && ior8(ctlr, RhineMiiCr) & (Rcmd | Wcmd)) microdelay(1); @@ -516,9 +451,7 @@ miiread(Mii *mii, int phy, int reg) if (n == Nwait) iprint("etherrhine: miiread: timeout\n"); - n = ior16(ctlr, RhineMiiData); - - return n; + return ior16(ctlr, RhineMiiData); } static int @@ -553,17 +486,50 @@ miiwrite(Mii *mii, int phy, int reg, int data) static void reset(Ctlr* ctlr) { - int i; - - iow16(ctlr, Cr, ior16(ctlr, Cr) | Stop); - iow16(ctlr, Cr, ior16(ctlr, Cr) | Reset); + int r, timeo; + + /* + * Soft reset the controller. + */ + csr16w(ctlr, Cr, Stop); + csr16w(ctlr, Cr, Stop|Reset); + for(timeo = 0; timeo < 10000; timeo++){ + if(!(csr16r(ctlr, Cr) & Reset)) + break; + microdelay(1); + } + if(timeo >= 1000) + return; - for (i = 0; i < Nwait; ++i) { - if ((ior16(ctlr, Cr) & Reset) == 0) - return; - delay(5); + /* + * Load the MAC address into the PAR[01] + * registers. + */ + r = csr8r(ctlr, Eecsr); + csr8w(ctlr, Eecsr, EeAutoLoad|r); + for(timeo = 0; timeo < 100; timeo++){ + if(!(csr8r(ctlr, Cr) & EeAutoLoad)) + break; + microdelay(1); } - iprint("etherrhine: reset timeout\n"); + if(timeo >= 100) + return; + + /* + * Configure DMA and Rx/Tx thresholds. + * If the Rx/Tx threshold bits in Bcr[01] are 0 then + * the thresholds are determined by Rcr/Tcr. + */ + r = csr8r(ctlr, Bcr0) & ~(CrftMASK|DmaMASK); + csr8w(ctlr, Bcr0, r|Crft64|Dma64); + r = csr8r(ctlr, Bcr1) & ~CtftMASK; + csr8w(ctlr, Bcr1, r|Ctft64); + + r = csr8r(ctlr, Rcr) & ~(RrftMASK|Prom|Ar|Sep); + csr8w(ctlr, Rcr, r|Ab|Am); + + r = csr8r(ctlr, Tcr) & ~(RtsfMASK|Ofset|Lb1|Lb0); + csr8w(ctlr, Tcr, r); } static void @@ -579,11 +545,9 @@ init(Ether *edev) int i; ctlr = edev->ctlr; - ilock(&ctlr->tlock); pcisetbme(ctlr->pci); - reset(ctlr); iow8(ctlr, Eecsr, ior8(ctlr, Eecsr) | EeAutoLoad); @@ -592,7 +556,7 @@ init(Ether *edev) break; delay(5); } - if (i == Nwait) + if (i >= Nwait) iprint("etherrhine: eeprom autoload timeout\n"); for (i = 0; i < Eaddrlen; ++i) @@ -603,6 +567,7 @@ init(Ether *edev) ctlr->mii.ctlr = ctlr; if(mii(&ctlr->mii, ~0) == 0 || ctlr->mii.curphy == nil){ + iunlock(&ctlr->tlock); iprint("etherrhine: init mii failure\n"); return; } @@ -610,7 +575,6 @@ init(Ether *edev) if (ctlr->mii.phy[i]) if (ctlr->mii.phy[i]->oui != 0xFFFFF) ctlr->mii.curphy = ctlr->mii.phy[i]; - miistatus(&ctlr->mii); iow16(ctlr, Imr, 0); @@ -626,12 +590,22 @@ rhinematch(ulong) int nfound = 0; Pcidev *p = nil; - while (p = pcimatch(p, 0x1106, 0)) - if (p->did == 0x3065) + while(p = pcimatch(p, 0x1106, 0)){ + if(p->ccrb != Pcibcnet || p->ccru != Pciscether) + continue; + switch((p->did<<16)|p->vid){ + default: + continue; + case (0x3053<<16)|0x1106: /* Rhine III vt6105m (Soekris) */ + case (0x3065<<16)|0x1106: /* Rhine II */ + case (0x3106<<16)|0x1106: /* Rhine III */ if (++nfound > nrhines) { nrhines++; - break; + return p; } + break; + } + } return p; } @@ -642,6 +616,8 @@ rhinepnp(Ether *edev) Ctlr *ctlr; ulong port; + if (edev->attach) + return 0; p = rhinematch(edev->port); if (p == nil) return -1; @@ -655,7 +631,7 @@ rhinepnp(Ether *edev) memset(ctlr, 0, sizeof(Ctlr)); ctlr->txd = xspanalloc(sizeof(Desc) * Ntxd, 16, 0); ctlr->rxd = xspanalloc(sizeof(Desc) * Nrxd, 16, 0); - + ctlr->pci = p; ctlr->port = port; @@ -666,7 +642,6 @@ rhinepnp(Ether *edev) init(edev); - edev->attach = attach; edev->transmit = transmit; edev->interrupt = interrupt; @@ -674,3 +649,9 @@ rhinepnp(Ether *edev) return 0; } + +int +vt6102pnp(Ether *edev) +{ + return rhinepnp(edev); +} -- cgit v1.2.3