diff options
| author | Konstantin Kirik (snegovick) <snegovick@uprojects.org> | 2025-12-28 12:27:31 +0300 |
|---|---|---|
| committer | Konstantin Kirik (snegovick) <snegovick@uprojects.org> | 2025-12-28 12:27:31 +0300 |
| commit | 78ee7d5717807e6ac779293d0d3c78341de6130a (patch) | |
| tree | a43e3b0f61318ac45e6d907c7cc5bad2c6d7f497 /os/pc/ethervt6102.c | |
| parent | bdaf46cf45bbb59261da245d548a179d95a42768 (diff) | |
Move existing boards into subdits split per arch
Diffstat (limited to 'os/pc/ethervt6102.c')
| -rw-r--r-- | os/pc/ethervt6102.c | 1025 |
1 files changed, 0 insertions, 1025 deletions
diff --git a/os/pc/ethervt6102.c b/os/pc/ethervt6102.c deleted file mode 100644 index 20d43a4e..00000000 --- a/os/pc/ethervt6102.c +++ /dev/null @@ -1,1025 +0,0 @@ -/* - * VIA VT6102 Fast Ethernet Controller (Rhine II). - * To do: - * cache-line size alignments - done - * reduce tx interrupts - * use 2 descriptors on tx for alignment - done - * reorganise initialisation/shutdown/reset - * adjust Tx FIFO threshold on underflow - untested - * why does the link status never cause an interrupt? - * use the lproc as a periodic timer for stalls, etc. - */ -#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" -#include "ethermii.h" - -enum { - Par0 = 0x00, /* Ethernet Address */ - Rcr = 0x06, /* Receive Configuration */ - Tcr = 0x07, /* Transmit Configuration */ - Cr = 0x08, /* Control */ - Isr = 0x0C, /* Interrupt Status */ - Imr = 0x0E, /* Interrupt Mask */ - Rxdaddr = 0x18, /* Current Rx Descriptor Address */ - Txdaddr = 0x1C, /* Current Tx Descriptor Address */ - Phyadr = 0x6C, /* Phy Address */ - Miisr = 0x6D, /* MII Status */ - Bcr0 = 0x6E, /* Bus Control */ - Bcr1 = 0x6F, - Miicr = 0x70, /* MII Control */ - Miiadr = 0x71, /* MII Address */ - Miidata = 0x72, /* MII Data */ - Eecsr = 0x74, /* EEPROM Control and Status */ -}; - -enum { /* Rcr */ - Sep = 0x01, /* Accept Error Packets */ - Ar = 0x02, /* Accept Small Packets */ - Am = 0x04, /* Accept Multicast */ - Ab = 0x08, /* Accept Broadcast */ - Prom = 0x10, /* Accept Physical Address Packets */ - RrftMASK = 0xE0, /* Receive FIFO Threshold */ - RrftSHIFT = 5, - Rrft64 = 0<<RrftSHIFT, - Rrft32 = 1<<RrftSHIFT, - Rrft128 = 2<<RrftSHIFT, - Rrft256 = 3<<RrftSHIFT, - Rrft512 = 4<<RrftSHIFT, - Rrft768 = 5<<RrftSHIFT, - Rrft1024 = 6<<RrftSHIFT, - RrftSAF = 7<<RrftSHIFT, -}; - -enum { /* Tcr */ - Lb0 = 0x02, /* Loopback Mode */ - Lb1 = 0x04, - Ofset = 0x08, /* Back-off Priority Selection */ - RtsfMASK = 0xE0, /* Transmit FIFO Threshold */ - RtsfSHIFT = 5, - Rtsf128 = 0<<RtsfSHIFT, - Rtsf256 = 1<<RtsfSHIFT, - Rtsf512 = 2<<RtsfSHIFT, - Rtsf1024 = 3<<RtsfSHIFT, - RtsfSAF = 7<<RtsfSHIFT, -}; - -enum { /* Cr */ - Init = 0x0001, /* INIT Process Begin */ - Strt = 0x0002, /* Start NIC */ - Stop = 0x0004, /* Stop NIC */ - Rxon = 0x0008, /* Turn on Receive Process */ - Txon = 0x0010, /* Turn on Transmit Process */ - Tdmd = 0x0020, /* Transmit Poll Demand */ - Rdmd = 0x0040, /* Receive Poll Demand */ - Eren = 0x0100, /* Early Receive Enable */ - Fdx = 0x0400, /* Set MAC to Full Duplex Mode */ - Dpoll = 0x0800, /* Disable Td/Rd Auto Polling */ - Tdmd1 = 0x2000, /* Transmit Poll Demand 1 */ - Rdmd1 = 0x4000, /* Receive Poll Demand 1 */ - Sfrst = 0x8000, /* Software Reset */ -}; - -enum { /* Isr/Imr */ - Prx = 0x0001, /* Received Packet Successfully */ - Ptx = 0x0002, /* Transmitted Packet Successfully */ - Rxe = 0x0004, /* Receive Error */ - Txe = 0x0008, /* Transmit Error */ - Tu = 0x0010, /* Transmit Buffer Underflow */ - Ru = 0x0020, /* Receive Buffer Link Error */ - Be = 0x0040, /* PCI Bus Error */ - Cnt = 0x0080, /* Counter Overflow */ - Eri = 0x0100, /* Early Receive Interrupt */ - Udfi = 0x0200, /* Tx FIFO Underflow */ - Ovfi = 0x0400, /* Receive FIFO Overflow */ - Pktrace = 0x0800, /* Hmmm... */ - Norbf = 0x1000, /* No Receive Buffers */ - Abti = 0x2000, /* Transmission Abort */ - Srci = 0x4000, /* Port State Change */ - Geni = 0x8000, /* General Purpose Interrupt */ -}; - -enum { /* Phyadr */ - PhyadMASK = 0x1F, /* PHY Address */ - PhyadSHIFT = 0, - Mfdc = 0x20, /* Accelerate MDC Speed */ - Mpo0 = 0x40, /* MII Polling Timer Interval */ - Mpo1 = 0x80, -}; - -enum { /* Bcr0 */ - DmaMASK = 0x07, /* DMA Length */ - DmaSHIFT = 0, - Dma32 = 0<<DmaSHIFT, - Dma64 = 1<<DmaSHIFT, - Dma128 = 2<<DmaSHIFT, - Dma256 = 3<<DmaSHIFT, - Dma512 = 4<<DmaSHIFT, - Dma1024 = 5<<DmaSHIFT, - DmaSAF = 7<<DmaSHIFT, - CrftMASK = 0x38, /* Rx FIFO Threshold */ - CrftSHIFT = 3, - Crft64 = 1<<CrftSHIFT, - Crft128 = 2<<CrftSHIFT, - Crft256 = 3<<CrftSHIFT, - Crft512 = 4<<CrftSHIFT, - Crft1024 = 5<<CrftSHIFT, - CrftSAF = 7<<CrftSHIFT, - Extled = 0x40, /* Extra LED Support Control */ - Med2 = 0x80, /* Medium Select Control */ -}; - -enum { /* Bcr1 */ - PotMASK = 0x07, /* Polling Timer Interval */ - PotSHIFT = 0, - CtftMASK = 0x38, /* Tx FIFO Threshold */ - CtftSHIFT = 3, - Ctft64 = 1<<CtftSHIFT, - Ctft128 = 2<<CtftSHIFT, - Ctft256 = 3<<CtftSHIFT, - Ctft512 = 4<<CtftSHIFT, - Ctft1024 = 5<<CtftSHIFT, - CtftSAF = 7<<CtftSHIFT, -}; - -enum { /* Miicr */ - Mdc = 0x01, /* Clock */ - Mdi = 0x02, /* Data In */ - Mdo = 0x04, /* Data Out */ - Mout = 0x08, /* Output Enable */ - Mdpm = 0x10, /* Direct Program Mode Enable */ - Wcmd = 0x20, /* Write Enable */ - Rcmd = 0x40, /* Read Enable */ - Mauto = 0x80, /* Auto Polling Enable */ -}; - -enum { /* Miiadr */ - MadMASK = 0x1F, /* MII Port Address */ - MadSHIFT = 0, - Mdone = 0x20, /* Accelerate MDC Speed */ - Msrcen = 0x40, /* MII Polling Timer Interval */ - Midle = 0x80, -}; - -enum { /* Eecsr */ - Edo = 0x01, /* Data Out */ - Edi = 0x02, /* Data In */ - Eck = 0x04, /* Clock */ - Ecs = 0x08, /* Chip Select */ - Dpm = 0x10, /* Direct Program Mode Enable */ - Autold = 0x20, /* Dynamic Reload */ - Embp = 0x40, /* Embedded Program Enable */ - Eepr = 0x80, /* Programmed */ -}; - -/* - * Ring descriptor. The space allocated for each - * of these will be rounded up to a cache-line boundary. - * The first 4 elements are known to the hardware. - */ -typedef struct Ds Ds; -typedef struct Ds { - uint status; - uint control; - uint addr; - uint branch; - - Block* bp; - void* bounce; - Ds* next; - Ds* prev; -} Ds; - -enum { /* Rx Ds status */ - Rerr = 0x00000001, /* Receiver Error */ - Crc = 0x00000002, /* CRC Error */ - Fae = 0x00000004, /* Frame Alignment Error */ - Fov = 0x00000008, /* FIFO Overflow */ - Long = 0x00000010, /* A Long Packet */ - Runt = 0x00000020, /* A Runt Packet */ - Rxserr = 0x00000040, /* System Error */ - Buff = 0x00000080, /* Buffer Underflow Error */ - Rxedp = 0x00000100, /* End of Packet Buffer */ - Rxstp = 0x00000200, /* Packet Start */ - Chn = 0x00000400, /* Chain Buffer */ - Phy = 0x00000800, /* Physical Address Packet */ - Bar = 0x00001000, /* Broadcast Packet */ - Mar = 0x00002000, /* Multicast Packet */ - Rxok = 0x00008000, /* Packet Received Successfully */ - LengthMASK = 0x07FF0000, /* Received Packet Length */ - LengthSHIFT = 16, - - Own = 0x80000000, /* Descriptor Owned by NIC */ -}; - -enum { /* Tx Ds status */ - NcrMASK = 0x0000000F, /* Collision Retry Count */ - NcrSHIFT = 0, - Cols = 0x00000010, /* Experienced Collisions */ - Cdh = 0x00000080, /* CD Heartbeat */ - Abt = 0x00000100, /* Aborted after Excessive Collisions */ - Owc = 0x00000200, /* Out of Window Collision Seen */ - Crs = 0x00000400, /* Carrier Sense Lost */ - Udf = 0x00000800, /* FIFO Underflow */ - Tbuff = 0x00001000, /* Invalid Td */ - Txserr = 0x00002000, /* System Error */ - Terr = 0x00008000, /* Excessive Collisions */ -}; - -enum { /* Tx Ds control */ - TbsMASK = 0x000007FF, /* Tx Buffer Size */ - TbsSHIFT = 0, - Chain = 0x00008000, /* Chain Buffer */ - Crcdisable = 0x00010000, /* Disable CRC generation */ - Stp = 0x00200000, /* Start of Packet */ - Edp = 0x00400000, /* End of Packet */ - Ic = 0x00800000, /* Assert Interrupt Immediately */ -}; - -enum { - Nrd = 64, - Ntd = 64, - Rdbsz = ROUNDUP(ETHERMAXTU+4, 4), - - Nrxstats = 8, - Ntxstats = 9, - - Txcopy = 128, -}; - -typedef struct Ctlr Ctlr; -typedef struct Ctlr { - int port; - Pcidev* pcidev; - Ctlr* next; - int active; - int id; - uchar par[Eaddrlen]; - - QLock alock; /* attach */ - void* alloc; /* receive/transmit descriptors */ - int cls; /* alignment */ - int nrd; - int ntd; - - Ds* rd; - Ds* rdh; - - Lock tlock; - Ds* td; - Ds* tdh; - Ds* tdt; - int tdused; - - Lock clock; /* */ - int cr; - int imr; - int tft; /* Tx threshold */ - - Mii* mii; - Rendez lrendez; - int lwakeup; - - uint rxstats[Nrxstats]; /* statistics */ - uint txstats[Ntxstats]; - uint intr; - uint lintr; - uint lsleep; - uint rintr; - uint tintr; - uint taligned; - uint tsplit; - uint tcopied; - uint txdw; -} Ctlr; - -static Ctlr* vt6102ctlrhead; -static Ctlr* vt6102ctlrtail; - -#define csr8r(c, r) (inb((c)->port+(r))) -#define csr16r(c, r) (ins((c)->port+(r))) -#define csr32r(c, r) (inl((c)->port+(r))) -#define csr8w(c, r, b) (outb((c)->port+(r), (int)(b))) -#define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w))) -#define csr32w(c, r, w) (outl((c)->port+(r), (ulong)(w))) - -static char* rxstats[Nrxstats] = { - "Receiver Error", - "CRC Error", - "Frame Alignment Error", - "FIFO Overflow", - "Long Packet", - "Runt Packet", - "System Error", - "Buffer Underflow Error", -}; -static char* txstats[Ntxstats] = { - "Aborted after Excessive Collisions", - "Out of Window Collision Seen", - "Carrier Sense Lost", - "FIFO Underflow", - "Invalid Td", - "System Error", - nil, - "Excessive Collisions", -}; - -static long -vt6102ifstat(Ether* edev, void* a, long n, ulong offset) -{ - char *p; - Ctlr *ctlr; - int i, l, r; - - ctlr = edev->ctlr; - - p = malloc(2*READSTR); - l = 0; - for(i = 0; i < Nrxstats; i++){ - l += snprint(p+l, 2*READSTR-l, "%s: %ud\n", - rxstats[i], ctlr->rxstats[i]); - } - for(i = 0; i < Ntxstats; i++){ - if(txstats[i] == nil) - continue; - l += snprint(p+l, 2*READSTR-l, "%s: %ud\n", - txstats[i], ctlr->txstats[i]); - } - l += snprint(p+l, 2*READSTR-l, "cls: %ud\n", ctlr->cls); - l += snprint(p+l, 2*READSTR-l, "intr: %ud\n", ctlr->intr); - l += snprint(p+l, 2*READSTR-l, "lintr: %ud\n", ctlr->lintr); - l += snprint(p+l, 2*READSTR-l, "lsleep: %ud\n", ctlr->lsleep); - l += snprint(p+l, 2*READSTR-l, "rintr: %ud\n", ctlr->rintr); - l += snprint(p+l, 2*READSTR-l, "tintr: %ud\n", ctlr->tintr); - l += snprint(p+l, 2*READSTR-l, "taligned: %ud\n", ctlr->taligned); - l += snprint(p+l, 2*READSTR-l, "tsplit: %ud\n", ctlr->tsplit); - l += snprint(p+l, 2*READSTR-l, "tcopied: %ud\n", ctlr->tcopied); - l += snprint(p+l, 2*READSTR-l, "txdw: %ud\n", ctlr->txdw); - l += snprint(p+l, 2*READSTR-l, "tft: %ud\n", ctlr->tft); - - if(ctlr->mii != nil && ctlr->mii->curphy != nil){ - l += snprint(p+l, 2*READSTR, "phy: "); - for(i = 0; i < NMiiPhyr; i++){ - if(i && ((i & 0x07) == 0)) - l += snprint(p+l, 2*READSTR-l, "\n "); - r = miimir(ctlr->mii, i); - l += snprint(p+l, 2*READSTR-l, " %4.4uX", r); - } - snprint(p+l, 2*READSTR-l, "\n"); - } - snprint(p+l, 2*READSTR-l, "\n"); - - n = readstr(offset, a, n, p); - free(p); - - return n; -} - -static void -vt6102promiscuous(void* arg, int on) -{ - int rcr; - Ctlr *ctlr; - Ether *edev; - - edev = arg; - ctlr = edev->ctlr; - rcr = csr8r(ctlr, Rcr); - if(on) - rcr |= Prom; - else - rcr &= ~Prom; - csr8w(ctlr, Rcr, rcr); -} - -static void -vt6102multicast(void* arg, uchar* addr, int on) -{ - /* - * For now Am is set in Rcr. - * Will need to interlock with promiscuous - * when this gets filled in. - */ - USED(arg, addr, on); -} - -static int -vt6102wakeup(void* v) -{ - return *((int*)v) != 0; -} - -static void -vt6102imr(Ctlr* ctlr, int imr) -{ - ilock(&ctlr->clock); - ctlr->imr |= imr; - csr16w(ctlr, Imr, ctlr->imr); - iunlock(&ctlr->clock); -} - -static void -vt6102lproc(void* arg) -{ - Ctlr *ctlr; - Ether *edev; - MiiPhy *phy; - - edev = arg; - ctlr = edev->ctlr; - for(;;){ - if(ctlr->mii == nil || ctlr->mii->curphy == nil) - break; - if(miistatus(ctlr->mii) < 0) - goto enable; - - phy = ctlr->mii->curphy; - ilock(&ctlr->clock); - if(phy->fd) - ctlr->cr |= Fdx; - else - ctlr->cr &= ~Fdx; - csr16w(ctlr, Cr, ctlr->cr); - iunlock(&ctlr->clock); -enable: - ctlr->lwakeup = 0; - vt6102imr(ctlr, Srci); - - ctlr->lsleep++; - sleep(&ctlr->lrendez, vt6102wakeup, &ctlr->lwakeup); - - } - pexit("vt6102lproc: done", 1); -} - -static void -vt6102attach(Ether* edev) -{ - int i; - Ctlr *ctlr; - Ds *ds, *prev; - uchar *alloc, *bounce; - char name[KNAMELEN]; - - ctlr = edev->ctlr; - qlock(&ctlr->alock); - if(ctlr->alloc != nil){ - qunlock(&ctlr->alock); - return; - } - - /* - * Descriptor and bounce-buffer space. - * Must all be aligned on a 4-byte boundary, - * but try to align on cache-lines. - */ - ctlr->nrd = Nrd; - ctlr->ntd = Ntd; - alloc = malloc((ctlr->nrd+ctlr->ntd)*ctlr->cls + ctlr->ntd*Txcopy + ctlr->cls-1); - if(alloc == nil){ - qunlock(&ctlr->alock); - return; - } - ctlr->alloc = alloc; - alloc = (uchar*)ROUNDUP((ulong)alloc, ctlr->cls); - - ctlr->rd = (Ds*)alloc; - - if(waserror()){ - ds = ctlr->rd; - for(i = 0; i < ctlr->nrd; i++){ - if(ds->bp != nil){ - freeb(ds->bp); - ds->bp = nil; - } - if((ds = ds->next) == nil) - break; - } - free(ctlr->alloc); - ctlr->alloc = nil; - qunlock(&ctlr->alock); - nexterror(); - } - - prev = ctlr->rd + ctlr->nrd-1; - for(i = 0; i < ctlr->nrd; i++){ - ds = (Ds*)alloc; - alloc += ctlr->cls; - - ds->control = Rdbsz; - ds->branch = PCIWADDR(alloc); - - ds->bp = iallocb(Rdbsz+3); - if(ds->bp == nil) - error("vt6102: can't allocate receive ring\n"); - ds->bp->rp = (uchar*)ROUNDUP((ulong)ds->bp->rp, 4); - ds->addr = PCIWADDR(ds->bp->rp); - - ds->next = (Ds*)alloc; - ds->prev = prev; - prev = ds; - - ds->status = Own; - } - prev->branch = 0; - prev->next = ctlr->rd; - prev->status = 0; - ctlr->rdh = ctlr->rd; - - ctlr->td = (Ds*)alloc; - prev = ctlr->td + ctlr->ntd-1; - bounce = alloc + ctlr->ntd*ctlr->cls; - for(i = 0; i < ctlr->ntd; i++){ - ds = (Ds*)alloc; - alloc += ctlr->cls; - - ds->bounce = bounce; - bounce += Txcopy; - ds->next = (Ds*)alloc; - ds->prev = prev; - prev = ds; - } - prev->next = ctlr->td; - ctlr->tdh = ctlr->tdt = ctlr->td; - ctlr->tdused = 0; - - ctlr->cr = Dpoll|Rdmd|Txon|Rxon|Strt; - /*Srci|Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx*/ - ctlr->imr = Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx; - - ilock(&ctlr->clock); - csr32w(ctlr, Rxdaddr, PCIWADDR(ctlr->rd)); - csr32w(ctlr, Txdaddr, PCIWADDR(ctlr->td)); - csr16w(ctlr, Isr, ~0); - csr16w(ctlr, Imr, ctlr->imr); - csr16w(ctlr, Cr, ctlr->cr); - iunlock(&ctlr->clock); - - snprint(name, KNAMELEN, "#l%dlproc", edev->ctlrno); - kproc(name, vt6102lproc, edev, 0); - - qunlock(&ctlr->alock); - poperror(); -} - -static void -vt6102transmit(Ether* edev) -{ - Block *bp; - Ctlr *ctlr; - Ds *ds, *next; - int control, i, o, prefix, size, tdused, timeo; - - ctlr = edev->ctlr; - - ilock(&ctlr->tlock); - - /* - * Free any completed packets - */ - ds = ctlr->tdh; - for(tdused = ctlr->tdused; tdused > 0; tdused--){ - /* - * For some errors the chip will turn the Tx engine - * off. Wait for that to happen. - * Could reset and re-init the chip here if it doesn't - * play fair. - * To do: adjust Tx FIFO threshold on underflow. - */ - if(ds->status & (Abt|Tbuff|Udf)){ - for(timeo = 0; timeo < 1000; timeo++){ - if(!(csr16r(ctlr, Cr) & Txon)) - break; - microdelay(1); - } - ds->status = Own; - csr32w(ctlr, Txdaddr, PCIWADDR(ds)); - } - - if(ds->status & Own) - break; - ds->addr = 0; - ds->branch = 0; - - if(ds->bp != nil){ - freeb(ds->bp); - ds->bp = nil; - } - for(i = 0; i < Ntxstats-1; i++){ - if(ds->status & (1<<i)) - ctlr->txstats[i]++; - } - ctlr->txstats[i] += (ds->status & NcrMASK)>>NcrSHIFT; - - ds = ds->next; - } - ctlr->tdh = ds; - - /* - * Try to fill the ring back up. - */ - ds = ctlr->tdt; - while(tdused < ctlr->ntd-2){ - if((bp = qget(edev->oq)) == nil) - break; - tdused++; - - size = BLEN(bp); - prefix = 0; - - if(o = (((int)bp->rp) & 0x03)){ - prefix = Txcopy-o; - if(prefix > size) - prefix = size; - memmove(ds->bounce, bp->rp, prefix); - ds->addr = PCIWADDR(ds->bounce); - bp->rp += prefix; - size -= prefix; - } - - next = ds->next; - ds->branch = PCIWADDR(ds->next); - - if(size){ - if(prefix){ - next->bp = bp; - next->addr = PCIWADDR(bp->rp); - next->branch = PCIWADDR(next->next); - next->control = Edp|Chain|((size<<TbsSHIFT) & TbsMASK); - - control = Stp|Chain|((prefix<<TbsSHIFT) & TbsMASK); - - next = next->next; - tdused++; - ctlr->tsplit++; - } - else{ - ds->bp = bp; - ds->addr = PCIWADDR(bp->rp); - control = Edp|Stp|((size<<TbsSHIFT) & TbsMASK); - ctlr->taligned++; - } - } - else{ - freeb(bp); - control = Edp|Stp|((prefix<<TbsSHIFT) & TbsMASK); - ctlr->tcopied++; - } - - ds->control = control; - if(tdused >= ctlr->ntd-2){ - ds->control |= Ic; - ctlr->txdw++; - } - coherence(); - ds->status = Own; - - ds = next; - } - ctlr->tdt = ds; - ctlr->tdused = tdused; - if(ctlr->tdused) - csr16w(ctlr, Cr, Tdmd|ctlr->cr); - - iunlock(&ctlr->tlock); -} - -static void -vt6102receive(Ether* edev) -{ - Ds *ds; - Block *bp; - Ctlr *ctlr; - int i, len; - - ctlr = edev->ctlr; - - ds = ctlr->rdh; - while(!(ds->status & Own) && ds->status != 0){ - if(ds->status & Rerr){ - for(i = 0; i < Nrxstats; i++){ - if(ds->status & (1<<i)) - ctlr->rxstats[i]++; - } - } - else if(bp = iallocb(Rdbsz+3)){ - len = ((ds->status & LengthMASK)>>LengthSHIFT)-4; - ds->bp->wp = ds->bp->rp+len; - etheriq(edev, ds->bp, 1); - bp->rp = (uchar*)ROUNDUP((ulong)bp->rp, 4); - ds->addr = PCIWADDR(bp->rp); - ds->bp = bp; - } - ds->control = Rdbsz; - ds->branch = 0; - ds->status = 0; - - ds->prev->branch = PCIWADDR(ds); - coherence(); - ds->prev->status = Own; - - ds = ds->next; - } - ctlr->rdh = ds; - - csr16w(ctlr, Cr, ctlr->cr); -} - -static void -vt6102interrupt(Ureg*, void* arg) -{ - Ctlr *ctlr; - Ether *edev; - int imr, isr, r, timeo; - - edev = arg; - ctlr = edev->ctlr; - - ilock(&ctlr->clock); - csr16w(ctlr, Imr, 0); - imr = ctlr->imr; - ctlr->intr++; - for(;;){ - if((isr = csr16r(ctlr, Isr)) != 0) - csr16w(ctlr, Isr, isr); - if((isr & ctlr->imr) == 0) - break; - - if(isr & Srci){ - imr &= ~Srci; - ctlr->lwakeup = isr & Srci; - wakeup(&ctlr->lrendez); - isr &= ~Srci; - ctlr->lintr++; - } - if(isr & (Norbf|Pktrace|Ovfi|Ru|Rxe|Prx)){ - vt6102receive(edev); - isr &= ~(Norbf|Pktrace|Ovfi|Ru|Rxe|Prx); - ctlr->rintr++; - } - if(isr & (Abti|Udfi|Tu|Txe|Ptx)){ - if(isr & (Abti|Udfi|Tu)){ - for(timeo = 0; timeo < 1000; timeo++){ - if(!(csr16r(ctlr, Cr) & Txon)) - break; - microdelay(1); - } - - if((isr & Udfi) && ctlr->tft < CtftSAF){ - ctlr->tft += 1<<CtftSHIFT; - r = csr8r(ctlr, Bcr1) & ~CtftMASK; - csr8w(ctlr, Bcr1, r|ctlr->tft); - } - } - vt6102transmit(edev); - isr &= ~(Abti|Udfi|Tu|Txe|Ptx); - ctlr->tintr++; - } - if(isr) - panic("vt6102: isr %4.4uX\n", isr); - } - ctlr->imr = imr; - csr16w(ctlr, Imr, ctlr->imr); - iunlock(&ctlr->clock); -} - -static int -vt6102miimicmd(Mii* mii, int pa, int ra, int cmd, int data) -{ - Ctlr *ctlr; - int r, timeo; - - ctlr = mii->ctlr; - - csr8w(ctlr, Miicr, 0); - r = csr8r(ctlr, Phyadr); - csr8w(ctlr, Phyadr, (r & ~PhyadMASK)|pa); - csr8w(ctlr, Phyadr, pa); - csr8w(ctlr, Miiadr, ra); - if(cmd == Wcmd) - csr16w(ctlr, Miidata, data); - csr8w(ctlr, Miicr, cmd); - - for(timeo = 0; timeo < 10000; timeo++){ - if(!(csr8r(ctlr, Miicr) & cmd)) - break; - microdelay(1); - } - if(timeo >= 10000) - return -1; - - if(cmd == Wcmd) - return 0; - return csr16r(ctlr, Miidata); -} - -static int -vt6102miimir(Mii* mii, int pa, int ra) -{ - return vt6102miimicmd(mii, pa, ra, Rcmd, 0); -} - -static int -vt6102miimiw(Mii* mii, int pa, int ra, int data) -{ - return vt6102miimicmd(mii, pa, ra, Wcmd, data); -} - -static int -vt6102detach(Ctlr* ctlr) -{ - int timeo; - - /* - * Soft reset the controller. - */ - csr16w(ctlr, Cr, Sfrst); - for(timeo = 0; timeo < 10000; timeo++){ - if(!(csr16r(ctlr, Cr) & Sfrst)) - break; - microdelay(1); - } - if(timeo >= 1000) - return -1; - - return 0; -} - -static int -vt6102reset(Ctlr* ctlr) -{ - MiiPhy *phy; - int i, r, timeo; - - if(vt6102detach(ctlr) < 0) - return -1; - - /* - * Load the MAC address into the PAR[01] - * registers. - */ - r = csr8r(ctlr, Eecsr); - csr8w(ctlr, Eecsr, Autold|r); - for(timeo = 0; timeo < 100; timeo++){ - if(!(csr8r(ctlr, Cr) & Autold)) - break; - microdelay(1); - } - if(timeo >= 100) - return -1; - - for(i = 0; i < Eaddrlen; i++) - ctlr->par[i] = csr8r(ctlr, Par0+i); - - /* - * 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|ctlr->tft); - - 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); - - /* - * Link management. - */ - if((ctlr->mii = malloc(sizeof(Mii))) == nil) - return -1; - ctlr->mii->mir = vt6102miimir; - ctlr->mii->miw = vt6102miimiw; - ctlr->mii->ctlr = ctlr; - - if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){ - free(ctlr->mii); - ctlr->mii = nil; - return -1; - } - // print("oui %X phyno %d\n", phy->oui, phy->phyno); - USED(phy); - - //miiane(ctlr->mii, ~0, ~0, ~0); - - return 0; -} - -static void -vt6102pci(void) -{ - Pcidev *p; - Ctlr *ctlr; - int cls, port; - - p = nil; - while(p = pcimatch(p, 0, 0)){ - if(p->ccrb != Pcibcnet || p->ccru != Pciscether) - continue; - - switch((p->did<<16)|p->vid){ - default: - continue; - case (0x3065<<16)|0x1106: /* Rhine II */ - case (0x3106<<16)|0x1106: /* Rhine III */ - break; - } - - port = p->mem[0].bar & ~0x01; - if(ioalloc(port, p->mem[0].size, 0, "vt6102") < 0){ - print("vt6102: port 0x%uX in use\n", port); - continue; - } - ctlr = malloc(sizeof(Ctlr)); - ctlr->port = port; - ctlr->pcidev = p; - ctlr->id = (p->did<<16)|p->vid; - if((cls = pcicfgr8(p, PciCLS)) == 0 || cls == 0xFF) - cls = 0x10; - ctlr->cls = cls*4; - if(ctlr->cls < sizeof(Ds)){ - print("vt6102: cls %d < sizeof(Ds)\n", ctlr->cls); - iofree(port); - free(ctlr); - continue; - } - ctlr->tft = Ctft64; - - if(vt6102reset(ctlr)){ - iofree(port); - free(ctlr); - continue; - } - pcisetbme(p); - - if(vt6102ctlrhead != nil) - vt6102ctlrtail->next = ctlr; - else - vt6102ctlrhead = ctlr; - vt6102ctlrtail = ctlr; - } -} - -static int -vt6102pnp(Ether* edev) -{ - Ctlr *ctlr; - - if(vt6102ctlrhead == nil) - vt6102pci(); - - /* - * Any adapter matches if no edev->port is supplied, - * otherwise the ports must match. - */ - for(ctlr = vt6102ctlrhead; ctlr != nil; ctlr = ctlr->next){ - if(ctlr->active) - continue; - if(edev->port == 0 || edev->port == ctlr->port){ - ctlr->active = 1; - break; - } - } - if(ctlr == nil) - return -1; - - edev->ctlr = ctlr; - edev->port = ctlr->port; - edev->irq = ctlr->pcidev->intl; - edev->tbdf = ctlr->pcidev->tbdf; - edev->mbps = 100; - memmove(edev->ea, ctlr->par, Eaddrlen); - - /* - * Linkage to the generic ethernet driver. - */ - edev->attach = vt6102attach; - edev->transmit = vt6102transmit; - edev->interrupt = vt6102interrupt; - edev->ifstat = vt6102ifstat; - edev->ctl = nil; - - edev->arg = edev; - edev->promiscuous = vt6102promiscuous; - edev->multicast = vt6102multicast; - - return 0; -} - -void -ethervt6102link(void) -{ - addethercard("vt6102", vt6102pnp); - addethercard("rhine", vt6102pnp); -} |
