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/etherdp83820.c | |
| parent | bdaf46cf45bbb59261da245d548a179d95a42768 (diff) | |
Move existing boards into subdits split per arch
Diffstat (limited to 'os/pc/etherdp83820.c')
| -rw-r--r-- | os/pc/etherdp83820.c | 1246 |
1 files changed, 0 insertions, 1246 deletions
diff --git a/os/pc/etherdp83820.c b/os/pc/etherdp83820.c deleted file mode 100644 index aeda3713..00000000 --- a/os/pc/etherdp83820.c +++ /dev/null @@ -1,1246 +0,0 @@ -/* - * National Semiconductor DP83820 - * 10/100/1000 Mb/s Ethernet Network Interface Controller - * (Gig-NIC). - * Driver assumes little-endian and 32-bit host throughout. - */ -#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 { /* Registers */ - Cr = 0x00, /* Command */ - Cfg = 0x04, /* Configuration and Media Status */ - Mear = 0x08, /* MII/EEPROM Access */ - Ptscr = 0x0C, /* PCI Test Control */ - Isr = 0x10, /* Interrupt Status */ - Imr = 0x14, /* Interrupt Mask */ - Ier = 0x18, /* Interrupt Enable */ - Ihr = 0x1C, /* Interrupt Holdoff */ - Txdp = 0x20, /* Transmit Descriptor Pointer */ - Txdphi = 0x24, /* Transmit Descriptor Pointer Hi */ - Txcfg = 0x28, /* Transmit Configuration */ - Gpior = 0x2C, /* General Purpose I/O Control */ - Rxdp = 0x30, /* Receive Descriptor Pointer */ - Rxdphi = 0x34, /* Receive Descriptor Pointer Hi */ - Rxcfg = 0x38, /* Receive Configuration */ - Pqcr = 0x3C, /* Priority Queueing Control */ - Wcsr = 0x40, /* Wake on LAN Control/Status */ - Pcr = 0x44, /* Pause Control/Status */ - Rfcr = 0x48, /* Receive Filter/Match Control */ - Rfdr = 0x4C, /* Receive Filter/Match Data */ - Brar = 0x50, /* Boot ROM Address */ - Brdr = 0x54, /* Boot ROM Data */ - Srr = 0x58, /* Silicon Revision */ - Mibc = 0x5C, /* MIB Control */ - Mibd = 0x60, /* MIB Data */ - Txdp1 = 0xA0, /* Txdp Priority 1 */ - Txdp2 = 0xA4, /* Txdp Priority 2 */ - Txdp3 = 0xA8, /* Txdp Priority 3 */ - Rxdp1 = 0xB0, /* Rxdp Priority 1 */ - Rxdp2 = 0xB4, /* Rxdp Priority 2 */ - Rxdp3 = 0xB8, /* Rxdp Priority 3 */ - Vrcr = 0xBC, /* VLAN/IP Receive Control */ - Vtcr = 0xC0, /* VLAN/IP Transmit Control */ - Vdr = 0xC4, /* VLAN Data */ - Ccsr = 0xCC, /* Clockrun Control/Status */ - Tbicr = 0xE0, /* TBI Control */ - Tbisr = 0xE4, /* TBI Status */ - Tanar = 0xE8, /* TBI ANAR */ - Tanlpar = 0xEC, /* TBI ANLPAR */ - Taner = 0xF0, /* TBI ANER */ - Tesr = 0xF4, /* TBI ESR */ -}; - -enum { /* Cr */ - Txe = 0x00000001, /* Transmit Enable */ - Txd = 0x00000002, /* Transmit Disable */ - Rxe = 0x00000004, /* Receiver Enable */ - Rxd = 0x00000008, /* Receiver Disable */ - Txr = 0x00000010, /* Transmitter Reset */ - Rxr = 0x00000020, /* Receiver Reset */ - Swien = 0x00000080, /* Software Interrupt Enable */ - Rst = 0x00000100, /* Reset */ - TxpriSHFT = 9, /* Tx Priority Queue Select */ - TxpriMASK = 0x00001E00, - RxpriSHFT = 13, /* Rx Priority Queue Select */ - RxpriMASK = 0x0001E000, -}; - -enum { /* Configuration and Media Status */ - Bem = 0x00000001, /* Big Endian Mode */ - Ext125 = 0x00000002, /* External 125MHz reference Select */ - Bromdis = 0x00000004, /* Disable Boot ROM interface */ - Pesel = 0x00000008, /* Parity Error Detection Action */ - Exd = 0x00000010, /* Excessive Deferral Abort */ - Pow = 0x00000020, /* Program Out of Window Timer */ - Sb = 0x00000040, /* Single Back-off */ - Reqalg = 0x00000080, /* PCI Bus Request Algorithm */ - Extstsen = 0x00000100, /* Extended Status Enable */ - Phydis = 0x00000200, /* Disable PHY */ - Phyrst = 0x00000400, /* Reset PHY */ - M64addren = 0x00000800, /* Master 64-bit Addressing Enable */ - Data64en = 0x00001000, /* 64-bit Data Enable */ - Pci64det = 0x00002000, /* PCI 64-bit Bus Detected */ - T64addren = 0x00004000, /* Target 64-bit Addressing Enable */ - Mwidis = 0x00008000, /* MWI Disable */ - Mrmdis = 0x00010000, /* MRM Disable */ - Tmrtest = 0x00020000, /* Timer Test Mode */ - Spdstsien = 0x00040000, /* PHY Spdsts Interrupt Enable */ - Lnkstsien = 0x00080000, /* PHY Lnksts Interrupt Enable */ - Dupstsien = 0x00100000, /* PHY Dupsts Interrupt Enable */ - Mode1000 = 0x00400000, /* 1000Mb/s Mode Control */ - Tbien = 0x01000000, /* Ten-Bit Interface Enable */ - Dupsts = 0x10000000, /* Full Duplex Status */ - Spdsts100 = 0x20000000, /* SPEED100 Input Pin Status */ - Spdsts1000 = 0x40000000, /* SPEED1000 Input Pin Status */ - Lnksts = 0x80000000, /* Link Status */ -}; - -enum { /* MII/EEPROM Access */ - Eedi = 0x00000001, /* EEPROM Data In */ - Eedo = 0x00000002, /* EEPROM Data Out */ - Eeclk = 0x00000004, /* EEPROM Serial Clock */ - Eesel = 0x00000008, /* EEPROM Chip Select */ - Mdio = 0x00000010, /* MII Management Data */ - Mddir = 0x00000020, /* MII Management Direction */ - Mdc = 0x00000040, /* MII Management Clock */ -}; - -enum { /* Interrupts */ - Rxok = 0x00000001, /* Rx OK */ - Rxdesc = 0x00000002, /* Rx Descriptor */ - Rxerr = 0x00000004, /* Rx Packet Error */ - Rxearly = 0x00000008, /* Rx Early Threshold */ - Rxidle = 0x00000010, /* Rx Idle */ - Rxorn = 0x00000020, /* Rx Overrun */ - Txok = 0x00000040, /* Tx Packet OK */ - Txdesc = 0x00000080, /* Tx Descriptor */ - Txerr = 0x00000100, /* Tx Packet Error */ - Txidle = 0x00000200, /* Tx Idle */ - Txurn = 0x00000400, /* Tx Underrun */ - Mib = 0x00000800, /* MIB Service */ - Swi = 0x00001000, /* Software Interrupt */ - Pme = 0x00002000, /* Power Management Event */ - Phy = 0x00004000, /* PHY Interrupt */ - Hibint = 0x00008000, /* High Bits Interrupt Set */ - Rxsovr = 0x00010000, /* Rx Status FIFO Overrun */ - Rtabt = 0x00020000, /* Received Target Abort */ - Rmabt = 0x00040000, /* Received Master Abort */ - Sserr = 0x00080000, /* Signalled System Error */ - Dperr = 0x00100000, /* Detected Parity Error */ - Rxrcmp = 0x00200000, /* Receive Reset Complete */ - Txrcmp = 0x00400000, /* Transmit Reset Complete */ - Rxdesc0 = 0x00800000, /* Rx Descriptor for Priority Queue 0 */ - Rxdesc1 = 0x01000000, /* Rx Descriptor for Priority Queue 1 */ - Rxdesc2 = 0x02000000, /* Rx Descriptor for Priority Queue 2 */ - Rxdesc3 = 0x04000000, /* Rx Descriptor for Priority Queue 3 */ - Txdesc0 = 0x08000000, /* Tx Descriptor for Priority Queue 0 */ - Txdesc1 = 0x10000000, /* Tx Descriptor for Priority Queue 1 */ - Txdesc2 = 0x20000000, /* Tx Descriptor for Priority Queue 2 */ - Txdesc3 = 0x40000000, /* Tx Descriptor for Priority Queue 3 */ -}; - -enum { /* Interrupt Enable */ - Ien = 0x00000001, /* Interrupt Enable */ -}; - -enum { /* Interrupt Holdoff */ - IhSHFT = 0, /* Interrupt Holdoff */ - IhMASK = 0x000000FF, - Ihctl = 0x00000100, /* Interrupt Holdoff Control */ -}; - -enum { /* Transmit Configuration */ - TxdrthSHFT = 0, /* Tx Drain Threshold */ - TxdrthMASK = 0x000000FF, - FlthSHFT = 16, /* Tx Fill Threshold */ - FlthMASK = 0x0000FF00, - Brstdis = 0x00080000, /* 1000Mb/s Burst Disable */ - MxdmaSHFT = 20, /* Max Size per Tx DMA Burst */ - MxdmaMASK = 0x00700000, - Ecretryen = 0x00800000, /* Excessive Collision Retry Enable */ - Atp = 0x10000000, /* Automatic Transmit Padding */ - Mlb = 0x20000000, /* MAC Loopback */ - Hbi = 0x40000000, /* Heartbeat Ignore */ - Csi = 0x80000000, /* Carrier Sense Ignore */ -}; - -enum { /* Receive Configuration */ - RxdrthSHFT = 1, /* Rx Drain Threshold */ - RxdrthMASK = 0x0000003E, - Airl = 0x04000000, /* Accept In-Range Length Errored */ - Alp = 0x08000000, /* Accept Long Packets */ - Rxfd = 0x10000000, /* Receive Full Duplex */ - Stripcrc = 0x20000000, /* Strip CRC */ - Arp = 0x40000000, /* Accept Runt Packets */ - Aep = 0x80000000, /* Accept Errored Packets */ -}; - -enum { /* Priority Queueing Control */ - Txpqen = 0x00000001, /* Transmit Priority Queuing Enable */ - Txfairen = 0x00000002, /* Transmit Fairness Enable */ - RxpqenSHFT = 2, /* Receive Priority Queue Enable */ - RxpqenMASK = 0x0000000C, -}; - -enum { /* Pause Control/Status */ - PscntSHFT = 0, /* Pause Counter Value */ - PscntMASK = 0x0000FFFF, - Pstx = 0x00020000, /* Transmit Pause Frame */ - PsffloSHFT = 18, /* Rx Data FIFO Lo Threshold */ - PsffloMASK = 0x000C0000, - PsffhiSHFT = 20, /* Rx Data FIFO Hi Threshold */ - PsffhiMASK = 0x00300000, - PsstloSHFT = 22, /* Rx Stat FIFO Hi Threshold */ - PsstloMASK = 0x00C00000, - PssthiSHFT = 24, /* Rx Stat FIFO Hi Threshold */ - PssthiMASK = 0x03000000, - Psrcvd = 0x08000000, /* Pause Frame Received */ - Psact = 0x10000000, /* Pause Active */ - Psda = 0x20000000, /* Pause on Destination Address */ - Psmcast = 0x40000000, /* Pause on Multicast */ - Psen = 0x80000000, /* Pause Enable */ -}; - -enum { /* Receive Filter/Match Control */ - RfaddrSHFT = 0, /* Extended Register Address */ - RfaddrMASK = 0x000003FF, - Ulm = 0x00080000, /* U/L bit mask */ - Uhen = 0x00100000, /* Unicast Hash Enable */ - Mhen = 0x00200000, /* Multicast Hash Enable */ - Aarp = 0x00400000, /* Accept ARP Packets */ - ApatSHFT = 23, /* Accept on Pattern Match */ - ApatMASK = 0x07800000, - Apm = 0x08000000, /* Accept on Perfect Match */ - Aau = 0x10000000, /* Accept All Unicast */ - Aam = 0x20000000, /* Accept All Multicast */ - Aab = 0x40000000, /* Accept All Broadcast */ - Rfen = 0x80000000, /* Rx Filter Enable */ -}; - -enum { /* Receive Filter/Match Data */ - RfdataSHFT = 0, /* Receive Filter Data */ - RfdataMASK = 0x0000FFFF, - BmaskSHFT = 16, /* Byte Mask */ - BmaskMASK = 0x00030000, -}; - -enum { /* MIB Control */ - Wrn = 0x00000001, /* Warning Test Indicator */ - Frz = 0x00000002, /* Freeze All Counters */ - Aclr = 0x00000004, /* Clear All Counters */ - Mibs = 0x00000008, /* MIB Counter Strobe */ -}; - -enum { /* MIB Data */ - Nmibd = 11, /* Number of MIB Data Registers */ -}; - -enum { /* VLAN/IP Receive Control */ - Vtden = 0x00000001, /* VLAN Tag Detection Enable */ - Vtren = 0x00000002, /* VLAN Tag Removal Enable */ - Dvtf = 0x00000004, /* Discard VLAN Tagged Frames */ - Dutf = 0x00000008, /* Discard Untagged Frames */ - Ipen = 0x00000010, /* IP Checksum Enable */ - Ripe = 0x00000020, /* Reject IP Checksum Errors */ - Rtcpe = 0x00000040, /* Reject TCP Checksum Errors */ - Rudpe = 0x00000080, /* Reject UDP Checksum Errors */ -}; - -enum { /* VLAN/IP Transmit Control */ - Vgti = 0x00000001, /* VLAN Global Tag Insertion */ - Vppti = 0x00000002, /* VLAN Per-Packet Tag Insertion */ - Gchk = 0x00000004, /* Global Checksum Generation */ - Ppchk = 0x00000008, /* Per-Packet Checksum Generation */ -}; - -enum { /* VLAN Data */ - VtypeSHFT = 0, /* VLAN Type Field */ - VtypeMASK = 0x0000FFFF, - VtciSHFT = 16, /* VLAN Tag Control Information */ - VtciMASK = 0xFFFF0000, -}; - -enum { /* Clockrun Control/Status */ - Clkrunen = 0x00000001, /* CLKRUN Enable */ - Pmeen = 0x00000100, /* PME Enable */ - Pmests = 0x00008000, /* PME Status */ -}; - -typedef struct { - u32int link; /* Link to the next descriptor */ - u32int bufptr; /* pointer to data Buffer */ - int cmdsts; /* Command/Status */ - int extsts; /* optional Extended Status */ - - Block* bp; /* Block containing bufptr */ - u32int unused; /* pad to 64-bit */ -} Desc; - -enum { /* Common cmdsts bits */ - SizeMASK = 0x0000FFFF, /* Descriptor Byte Count */ - SizeSHFT = 0, - Ok = 0x08000000, /* Packet OK */ - Crc = 0x10000000, /* Suppress/Include CRC */ - Intr = 0x20000000, /* Interrupt on ownership transfer */ - More = 0x40000000, /* not last descriptor in a packet */ - Own = 0x80000000, /* Descriptor Ownership */ -}; - -enum { /* Transmit cmdsts bits */ - CcntMASK = 0x000F0000, /* Collision Count */ - CcntSHFT = 16, - Ec = 0x00100000, /* Excessive Collisions */ - Owc = 0x00200000, /* Out of Window Collision */ - Ed = 0x00400000, /* Excessive Deferral */ - Td = 0x00800000, /* Transmit Deferred */ - Crs = 0x01000000, /* Carrier Sense Lost */ - Tfu = 0x02000000, /* Transmit FIFO Underrun */ - Txa = 0x04000000, /* Transmit Abort */ -}; - -enum { /* Receive cmdsts bits */ - Irl = 0x00010000, /* In-Range Length Error */ - Lbp = 0x00020000, /* Loopback Packet */ - Fae = 0x00040000, /* Frame Alignment Error */ - Crce = 0x00080000, /* CRC Error */ - Ise = 0x00100000, /* Invalid Symbol Error */ - Runt = 0x00200000, /* Runt Packet Received */ - Long = 0x00400000, /* Too Long Packet Received */ - DestMASK = 0x01800000, /* Destination Class */ - DestSHFT = 23, - Rxo = 0x02000000, /* Receive Overrun */ - Rxa = 0x04000000, /* Receive Aborted */ -}; - -enum { /* extsts bits */ - EvtciMASK = 0x0000FFFF, /* VLAN Tag Control Information */ - EvtciSHFT = 0, - Vpkt = 0x00010000, /* VLAN Packet */ - Ippkt = 0x00020000, /* IP Packet */ - Iperr = 0x00040000, /* IP Checksum Error */ - Tcppkt = 0x00080000, /* TCP Packet */ - Tcperr = 0x00100000, /* TCP Checksum Error */ - Udppkt = 0x00200000, /* UDP Packet */ - Udperr = 0x00400000, /* UDP Checksum Error */ -}; - -enum { - Nrd = 256, - Nrb = 4*Nrd, - Rbsz = ROUNDUP(sizeof(Etherpkt)+8, 8), - Ntd = 128, -}; - -typedef struct Ctlr Ctlr; -typedef struct Ctlr { - int port; - Pcidev* pcidev; - Ctlr* next; - int active; - int id; - - int eepromsz; /* address size in bits */ - ushort* eeprom; - - int* nic; - int cfg; - int imr; - - QLock alock; /* attach */ - Lock ilock; /* init */ - void* alloc; /* base of per-Ctlr allocated data */ - - Mii* mii; - - Lock rdlock; /* receive */ - Desc* rd; - int nrd; - int nrb; - int rdx; - int rxcfg; - - Lock tlock; /* transmit */ - Desc* td; - int ntd; - int tdh; - int tdt; - int ntq; - int txcfg; - - int rxidle; - - uint mibd[Nmibd]; - - int ec; - int owc; - int ed; - int crs; - int tfu; - int txa; -} Ctlr; - -#define csr32r(c, r) (*((c)->nic+((r)/4))) -#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v)) - -static Ctlr* dp83820ctlrhead; -static Ctlr* dp83820ctlrtail; - -static Lock dp83820rblock; /* free receive Blocks */ -static Block* dp83820rbpool; - -static char* dp83820mibs[Nmibd] = { - "RXErroredPkts", - "RXFCSErrors", - "RXMsdPktErrors", - "RXFAErrors", - "RXSymbolErrors", - "RXFrameToLong", - "RXIRLErrors", - "RXBadOpcodes", - "RXPauseFrames", - "TXPauseFrames", - "TXSQEErrors", -}; - -static int -mdior(Ctlr* ctlr, int n) -{ - int data, i, mear, r; - - mear = csr32r(ctlr, Mear); - r = ~(Mdc|Mddir) & mear; - data = 0; - for(i = n-1; i >= 0; i--){ - if(csr32r(ctlr, Mear) & Mdio) - data |= (1<<i); - csr32w(ctlr, Mear, Mdc|r); - csr32w(ctlr, Mear, r); - } - csr32w(ctlr, Mear, mear); - - return data; -} - -static void -mdiow(Ctlr* ctlr, int bits, int n) -{ - int i, mear, r; - - mear = csr32r(ctlr, Mear); - r = Mddir|(~Mdc & mear); - for(i = n-1; i >= 0; i--){ - if(bits & (1<<i)) - r |= Mdio; - else - r &= ~Mdio; - csr32w(ctlr, Mear, r); - csr32w(ctlr, Mear, Mdc|r); - } - csr32w(ctlr, Mear, mear); -} - -static int -dp83820miimir(Mii* mii, int pa, int ra) -{ - int data; - Ctlr *ctlr; - - ctlr = mii->ctlr; - - /* - * MII Management Interface Read. - * - * Preamble; - * ST+OP+PA+RA; - * LT + 16 data bits. - */ - mdiow(ctlr, 0xFFFFFFFF, 32); - mdiow(ctlr, 0x1800|(pa<<5)|ra, 14); - data = mdior(ctlr, 18); - - if(data & 0x10000) - return -1; - - return data & 0xFFFF; -} - -static int -dp83820miimiw(Mii* mii, int pa, int ra, int data) -{ - Ctlr *ctlr; - - ctlr = mii->ctlr; - - /* - * MII Management Interface Write. - * - * Preamble; - * ST+OP+PA+RA+LT + 16 data bits; - * Z. - */ - mdiow(ctlr, 0xFFFFFFFF, 32); - data &= 0xFFFF; - data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16); - mdiow(ctlr, data, 32); - - return 0; -} - -static Block * -dp83820rballoc(Desc* desc) -{ - Block *bp; - - if(desc->bp == nil){ - ilock(&dp83820rblock); - if((bp = dp83820rbpool) == nil){ - iunlock(&dp83820rblock); - desc->bp = nil; - desc->cmdsts = Own; - return nil; - } - dp83820rbpool = bp->next; - bp->next = nil; - iunlock(&dp83820rblock); - - desc->bufptr = PCIWADDR(bp->rp); - desc->bp = bp; - } - else{ - bp = desc->bp; - bp->rp = bp->lim - Rbsz; - bp->wp = bp->rp; - } - - coherence(); - desc->cmdsts = Intr|Rbsz; - - return bp; -} - -static void -dp83820rbfree(Block *bp) -{ - bp->rp = bp->lim - Rbsz; - bp->wp = bp->rp; - - ilock(&dp83820rblock); - bp->next = dp83820rbpool; - dp83820rbpool = bp; - iunlock(&dp83820rblock); -} - -static void -dp83820halt(Ctlr* ctlr) -{ - int i, timeo; - - ilock(&ctlr->ilock); - csr32w(ctlr, Imr, 0); - csr32w(ctlr, Ier, 0); - csr32w(ctlr, Cr, Rxd|Txd); - for(timeo = 0; timeo < 1000; timeo++){ - if(!(csr32r(ctlr, Cr) & (Rxe|Txe))) - break; - microdelay(1); - } - csr32w(ctlr, Mibc, Frz); - iunlock(&ctlr->ilock); - - if(ctlr->rd != nil){ - for(i = 0; i < ctlr->nrd; i++){ - if(ctlr->rd[i].bp == nil) - continue; - freeb(ctlr->rd[i].bp); - ctlr->rd[i].bp = nil; - } - } - if(ctlr->td != nil){ - for(i = 0; i < ctlr->ntd; i++){ - if(ctlr->td[i].bp == nil) - continue; - freeb(ctlr->td[i].bp); - ctlr->td[i].bp = nil; - } - } -} - -static void -dp83820cfg(Ctlr* ctlr) -{ - int cfg; - - /* - * Don't know how to deal with a TBI yet. - */ - if(ctlr->mii == nil) - return; - - /* - * The polarity of these bits is at the mercy - * of the board designer. - * The correct answer for all speed and duplex questions - * should be to query the phy. - */ - cfg = csr32r(ctlr, Cfg); - if(!(cfg & Dupsts)){ - ctlr->rxcfg |= Rxfd; - ctlr->txcfg |= Csi|Hbi; - iprint("83820: full duplex, "); - } - else{ - ctlr->rxcfg &= ~Rxfd; - ctlr->txcfg &= ~(Csi|Hbi); - iprint("83820: half duplex, "); - } - csr32w(ctlr, Rxcfg, ctlr->rxcfg); - csr32w(ctlr, Txcfg, ctlr->txcfg); - - switch(cfg & (Spdsts1000|Spdsts100)){ - case Spdsts1000: /* 100Mbps */ - default: /* 10Mbps */ - ctlr->cfg &= ~Mode1000; - if((cfg & (Spdsts1000|Spdsts100)) == Spdsts1000) - iprint("100Mb/s\n"); - else - iprint("10Mb/s\n"); - break; - case Spdsts100: /* 1Gbps */ - ctlr->cfg |= Mode1000; - iprint("1Gb/s\n"); - break; - } - csr32w(ctlr, Cfg, ctlr->cfg); -} - -static void -dp83820init(Ether* edev) -{ - int i; - Ctlr *ctlr; - Desc *desc; - uchar *alloc; - - ctlr = edev->ctlr; - - dp83820halt(ctlr); - - /* - * Receiver - */ - alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 8); - ctlr->rd = (Desc*)alloc; - alloc += ctlr->nrd*sizeof(Desc); - memset(ctlr->rd, 0, ctlr->nrd*sizeof(Desc)); - ctlr->rdx = 0; - for(i = 0; i < ctlr->nrd; i++){ - desc = &ctlr->rd[i]; - desc->link = PCIWADDR(&ctlr->rd[NEXT(i, ctlr->nrd)]); - if(dp83820rballoc(desc) == nil) - continue; - } - csr32w(ctlr, Rxdphi, 0); - csr32w(ctlr, Rxdp, PCIWADDR(ctlr->rd)); - - for(i = 0; i < Eaddrlen; i += 2){ - csr32w(ctlr, Rfcr, i); - csr32w(ctlr, Rfdr, (edev->ea[i+1]<<8)|edev->ea[i]); - } - csr32w(ctlr, Rfcr, Rfen|Aab|Aam|Apm); - - ctlr->rxcfg = Stripcrc|(((2*(ETHERMINTU+4))/8)<<RxdrthSHFT); - ctlr->imr |= Rxorn|Rxidle|Rxearly|Rxdesc|Rxok; - - /* - * Transmitter. - */ - ctlr->td = (Desc*)alloc; - memset(ctlr->td, 0, ctlr->ntd*sizeof(Desc)); - ctlr->tdh = ctlr->tdt = ctlr->ntq = 0; - for(i = 0; i < ctlr->ntd; i++){ - desc = &ctlr->td[i]; - desc->link = PCIWADDR(&ctlr->td[NEXT(i, ctlr->ntd)]); - } - csr32w(ctlr, Txdphi, 0); - csr32w(ctlr, Txdp, PCIWADDR(ctlr->td)); - - ctlr->txcfg = Atp|(((2*(ETHERMINTU+4))/32)<<FlthSHFT)|((4096/32)<<TxdrthSHFT); - ctlr->imr |= Txurn|Txidle|Txdesc|Txok; - - ilock(&ctlr->ilock); - - dp83820cfg(ctlr); - - csr32w(ctlr, Mibc, Aclr); - ctlr->imr |= Mib; - - csr32w(ctlr, Imr, ctlr->imr); - - /* try coalescing adjacent interrupts; use hold-off interval of 100µs */ - csr32w(ctlr, Ihr, Ihctl|(1<<IhSHFT)); - - csr32w(ctlr, Ier, Ien); - csr32w(ctlr, Cr, Rxe|Txe); - - iunlock(&ctlr->ilock); -} - -static void -dp83820attach(Ether* edev) -{ - Block *bp; - Ctlr *ctlr; - - ctlr = edev->ctlr; - qlock(&ctlr->alock); - if(ctlr->alloc != nil){ - qunlock(&ctlr->alock); - return; - } - - if(waserror()){ - if(ctlr->mii != nil){ - free(ctlr->mii); - ctlr->mii = nil; - } - if(ctlr->alloc != nil){ - free(ctlr->alloc); - ctlr->alloc = nil; - } - qunlock(&ctlr->alock); - nexterror(); - } - - if(!(ctlr->cfg & Tbien)){ - if((ctlr->mii = malloc(sizeof(Mii))) == nil) - error(Enomem); - ctlr->mii->ctlr = ctlr; - ctlr->mii->mir = dp83820miimir; - ctlr->mii->miw = dp83820miimiw; - if(mii(ctlr->mii, ~0) == 0) - error("no PHY"); - ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien; - ctlr->imr |= Phy; - } - - ctlr->nrd = Nrd; - ctlr->nrb = Nrb; - ctlr->ntd = Ntd; - ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0); - if(ctlr->alloc == nil) - error(Enomem); - - for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){ - if((bp = allocb(Rbsz)) == nil) - break; - bp->free = dp83820rbfree; - dp83820rbfree(bp); - } - - dp83820init(edev); - - qunlock(&ctlr->alock); - poperror(); -} - -static void -dp83820transmit(Ether* edev) -{ - Block *bp; - Ctlr *ctlr; - Desc *desc; - int cmdsts, r, x; - - ctlr = edev->ctlr; - - ilock(&ctlr->tlock); - - bp = nil; - for(x = ctlr->tdh; ctlr->ntq; x = NEXT(x, ctlr->ntd)){ - desc = &ctlr->td[x]; - if((cmdsts = desc->cmdsts) & Own) - break; - if(!(cmdsts & Ok)){ - if(cmdsts & Ec) - ctlr->ec++; - if(cmdsts & Owc) - ctlr->owc++; - if(cmdsts & Ed) - ctlr->ed++; - if(cmdsts & Crs) - ctlr->crs++; - if(cmdsts & Tfu) - ctlr->tfu++; - if(cmdsts & Txa) - ctlr->txa++; - edev->oerrs++; - } - desc->bp->next = bp; - bp = desc->bp; - desc->bp = nil; - - ctlr->ntq--; - } - ctlr->tdh = x; - if(bp != nil) - freeblist(bp); - - x = ctlr->tdt; - while(ctlr->ntq < (ctlr->ntd-1)){ - if((bp = qget(edev->oq)) == nil) - break; - - desc = &ctlr->td[x]; - desc->bufptr = PCIWADDR(bp->rp); - desc->bp = bp; - ctlr->ntq++; - coherence(); - desc->cmdsts = Own|Intr|BLEN(bp); - - x = NEXT(x, ctlr->ntd); - } - if(x != ctlr->tdt){ - ctlr->tdt = x; - r = csr32r(ctlr, Cr); - csr32w(ctlr, Cr, Txe|r); - } - - iunlock(&ctlr->tlock); -} - -static void -dp83820interrupt(Ureg*, void* arg) -{ - Block *bp; - Ctlr *ctlr; - Desc *desc; - Ether *edev; - int cmdsts, i, isr, r, x; - - edev = arg; - ctlr = edev->ctlr; - - for(isr = csr32r(ctlr, Isr); isr & ctlr->imr; isr = csr32r(ctlr, Isr)){ - if(isr & (Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok)){ - x = ctlr->rdx; - desc = &ctlr->rd[x]; - while((cmdsts = desc->cmdsts) & Own){ - if((cmdsts & Ok) && desc->bp != nil){ - bp = desc->bp; - desc->bp = nil; - bp->wp += cmdsts & SizeMASK; - etheriq(edev, bp, 1); - } - //else if(!(cmdsts & Ok)){ - // iprint("dp83820: rx %8.8uX:", cmdsts); - // bp = desc->bp; - // for(i = 0; i < 20; i++) - // iprint(" %2.2uX", bp->rp[i]); - // iprint("\n"); - //} - dp83820rballoc(desc); - - x = NEXT(x, ctlr->nrd); - desc = &ctlr->rd[x]; - } - ctlr->rdx = x; - - if(isr & Rxidle){ - r = csr32r(ctlr, Cr); - csr32w(ctlr, Cr, Rxe|r); - ctlr->rxidle++; - } - - isr &= ~(Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok); - } - - if(isr & Txurn){ - x = (ctlr->txcfg & TxdrthMASK)>>TxdrthSHFT; - r = (ctlr->txcfg & FlthMASK)>>FlthSHFT; - if(x < ((TxdrthMASK)>>TxdrthSHFT) - && x < (2048/32 - r)){ - ctlr->txcfg &= ~TxdrthMASK; - x++; - ctlr->txcfg |= x<<TxdrthSHFT; - csr32w(ctlr, Txcfg, ctlr->txcfg); - } - } - - if(isr & (Txurn|Txidle|Txdesc|Txok)){ - dp83820transmit(edev); - isr &= ~(Txurn|Txidle|Txdesc|Txok); - } - - if(isr & Mib){ - for(i = 0; i < Nmibd; i++){ - r = csr32r(ctlr, Mibd+(i*sizeof(int))); - ctlr->mibd[i] += r & 0xFFFF; - } - isr &= ~Mib; - } - - if((isr & Phy) && ctlr->mii != nil){ - ctlr->mii->mir(ctlr->mii, 1, Bmsr); - print("phy: cfg %8.8uX bmsr %4.4uX\n", - csr32r(ctlr, Cfg), - ctlr->mii->mir(ctlr->mii, 1, Bmsr)); - dp83820cfg(ctlr); - isr &= ~Phy; - } - if(isr) - iprint("dp83820: isr %8.8uX\n", isr); - } -} - -static long -dp83820ifstat(Ether* edev, void* a, long n, ulong offset) -{ - char *p; - Ctlr *ctlr; - int i, l, r; - - ctlr = edev->ctlr; - - edev->crcs = ctlr->mibd[Mibd+(1*sizeof(int))]; - edev->frames = ctlr->mibd[Mibd+(3*sizeof(int))]; - edev->buffs = ctlr->mibd[Mibd+(5*sizeof(int))]; - edev->overflows = ctlr->mibd[Mibd+(2*sizeof(int))]; - - if(n == 0) - return 0; - - p = malloc(READSTR); - l = 0; - for(i = 0; i < Nmibd; i++){ - r = csr32r(ctlr, Mibd+(i*sizeof(int))); - ctlr->mibd[i] += r & 0xFFFF; - if(ctlr->mibd[i] != 0 && dp83820mibs[i] != nil) - l += snprint(p+l, READSTR-l, "%s: %ud %ud\n", - dp83820mibs[i], ctlr->mibd[i], r); - } - l += snprint(p+l, READSTR-l, "rxidle %d\n", ctlr->rxidle); - l += snprint(p+l, READSTR-l, "ec %d\n", ctlr->ec); - l += snprint(p+l, READSTR-l, "owc %d\n", ctlr->owc); - l += snprint(p+l, READSTR-l, "ed %d\n", ctlr->ed); - l += snprint(p+l, READSTR-l, "crs %d\n", ctlr->crs); - l += snprint(p+l, READSTR-l, "tfu %d\n", ctlr->tfu); - l += snprint(p+l, READSTR-l, "txa %d\n", ctlr->txa); - - l += snprint(p+l, READSTR, "rom:"); - for(i = 0; i < 0x10; i++){ - if(i && ((i & 0x07) == 0)) - l += snprint(p+l, READSTR-l, "\n "); - l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->eeprom[i]); - } - l += snprint(p+l, READSTR-l, "\n"); - - if(ctlr->mii != nil && ctlr->mii->curphy != nil){ - l += snprint(p+l, READSTR, "phy:"); - for(i = 0; i < NMiiPhyr; i++){ - if(i && ((i & 0x07) == 0)) - l += snprint(p+l, READSTR-l, "\n "); - r = miimir(ctlr->mii, i); - l += snprint(p+l, READSTR-l, " %4.4uX", r); - } - snprint(p+l, READSTR-l, "\n"); - } - - n = readstr(offset, a, n, p); - free(p); - - return n; -} - -static void -dp83820promiscuous(void* arg, int on) -{ - USED(arg, on); -} - -/* multicast already on, don't need to do anything */ -static void -dp83820multicast(void*, uchar*, int) -{ -} - -static int -dp83820detach(Ctlr* ctlr) -{ - /* - * Soft reset the controller. - */ - csr32w(ctlr, Cr, Rst); - delay(1); - while(csr32r(ctlr, Cr) & Rst) - delay(1); - return 0; -} - -static void -dp83820shutdown(Ether* ether) -{ -print("dp83820shutdown\n"); - dp83820detach(ether->ctlr); -} - -static int -atc93c46r(Ctlr* ctlr, int address) -{ - int data, i, mear, r, size; - - /* - * Analog Technology, Inc. ATC93C46 - * or equivalent serial EEPROM. - */ - mear = csr32r(ctlr, Mear); - mear &= ~(Eesel|Eeclk|Eedo|Eedi); - r = Eesel|mear; - -reread: - csr32w(ctlr, Mear, r); - data = 0x06; - for(i = 3-1; i >= 0; i--){ - if(data & (1<<i)) - r |= Eedi; - else - r &= ~Eedi; - csr32w(ctlr, Mear, r); - csr32w(ctlr, Mear, Eeclk|r); - microdelay(1); - csr32w(ctlr, Mear, r); - microdelay(1); - } - - /* - * First time through must work out the EEPROM size. - */ - if((size = ctlr->eepromsz) == 0) - size = 8; - - for(size = size-1; size >= 0; size--){ - if(address & (1<<size)) - r |= Eedi; - else - r &= ~Eedi; - csr32w(ctlr, Mear, r); - microdelay(1); - csr32w(ctlr, Mear, Eeclk|r); - microdelay(1); - csr32w(ctlr, Mear, r); - microdelay(1); - if(!(csr32r(ctlr, Mear) & Eedo)) - break; - } - r &= ~Eedi; - - data = 0; - for(i = 16-1; i >= 0; i--){ - csr32w(ctlr, Mear, Eeclk|r); - microdelay(1); - if(csr32r(ctlr, Mear) & Eedo) - data |= (1<<i); - csr32w(ctlr, Mear, r); - microdelay(1); - } - - csr32w(ctlr, Mear, mear); - - if(ctlr->eepromsz == 0){ - ctlr->eepromsz = 8-size; - ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort)); - goto reread; - } - - return data; -} - -static int -dp83820reset(Ctlr* ctlr) -{ - int i, r; - unsigned char sum; - - /* - * Soft reset the controller; - * read the EEPROM to get the initial settings - * of the Cfg and Gpior bits which should be cleared by - * the reset. - */ - dp83820detach(ctlr); - - atc93c46r(ctlr, 0); - if(ctlr->eeprom == nil) { - print("dp83820reset: no eeprom\n"); - return -1; - } - sum = 0; - for(i = 0; i < 0x0E; i++){ - r = atc93c46r(ctlr, i); - ctlr->eeprom[i] = r; - sum += r; - sum += r>>8; - } - - if(sum != 0){ - print("dp83820reset: bad EEPROM checksum\n"); - return -1; - } - -#ifdef notdef - csr32w(ctlr, Gpior, ctlr->eeprom[4]); - - cfg = Extstsen|Exd; - r = csr32r(ctlr, Cfg); - if(ctlr->eeprom[5] & 0x0001) - cfg |= Ext125; - if(ctlr->eeprom[5] & 0x0002) - cfg |= M64addren; - if((ctlr->eeprom[5] & 0x0004) && (r & Pci64det)) - cfg |= Data64en; - if(ctlr->eeprom[5] & 0x0008) - cfg |= T64addren; - if(!(pcicfgr16(ctlr->pcidev, PciPCR) & 0x10)) - cfg |= Mwidis; - if(ctlr->eeprom[5] & 0x0020) - cfg |= Mrmdis; - if(ctlr->eeprom[5] & 0x0080) - cfg |= Mode1000; - if(ctlr->eeprom[5] & 0x0200) - cfg |= Tbien|Mode1000; - /* - * What about RO bits we might have destroyed with Rst? - * What about Exd, Tmrtest, Extstsen, Pintctl? - * Why does it think it has detected a 64-bit bus when - * it hasn't? - */ -#else - //r = csr32r(ctlr, Cfg); - //r &= ~(Mode1000|T64addren|Data64en|M64addren); - //csr32w(ctlr, Cfg, r); - //csr32w(ctlr, Cfg, 0x2000); -#endif /* notdef */ - ctlr->cfg = csr32r(ctlr, Cfg); -print("cfg %8.8uX pcicfg %8.8uX\n", ctlr->cfg, pcicfgr32(ctlr->pcidev, PciPCR)); - ctlr->cfg &= ~(T64addren|Data64en|M64addren); - csr32w(ctlr, Cfg, ctlr->cfg); - csr32w(ctlr, Mibc, Aclr|Frz); - - return 0; -} - -static void -dp83820pci(void) -{ - void *mem; - Pcidev *p; - Ctlr *ctlr; - - 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 (0x0022<<16)|0x100B: /* DP83820 (Gig-NIC) */ - break; - } - - mem = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size); - if(mem == 0){ - print("DP83820: can't map %8.8luX\n", p->mem[1].bar); - continue; - } - - ctlr = malloc(sizeof(Ctlr)); - ctlr->port = p->mem[1].bar & ~0x0F; - ctlr->pcidev = p; - ctlr->id = (p->did<<16)|p->vid; - - ctlr->nic = mem; - if(dp83820reset(ctlr)){ - free(ctlr); - continue; - } - pcisetbme(p); - - if(dp83820ctlrhead != nil) - dp83820ctlrtail->next = ctlr; - else - dp83820ctlrhead = ctlr; - dp83820ctlrtail = ctlr; - } -} - -static int -dp83820pnp(Ether* edev) -{ - int i; - Ctlr *ctlr; - uchar ea[Eaddrlen]; - - if(dp83820ctlrhead == nil) - dp83820pci(); - - /* - * Any adapter matches if no edev->port is supplied, - * otherwise the ports must match. - */ - for(ctlr = dp83820ctlrhead; 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 = 1000; - - /* - * 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, edev->ea, Eaddrlen) == 0) - for(i = 0; i < Eaddrlen/2; i++){ - edev->ea[2*i] = ctlr->eeprom[0x0C-i]; - edev->ea[2*i+1] = ctlr->eeprom[0x0C-i]>>8; - } - - edev->attach = dp83820attach; - edev->transmit = dp83820transmit; - edev->interrupt = dp83820interrupt; - edev->ifstat = dp83820ifstat; - - edev->arg = edev; - edev->promiscuous = dp83820promiscuous; - edev->multicast = dp83820multicast; - edev->shutdown = dp83820shutdown; - - return 0; -} - -void -etherdp83820link(void) -{ - addethercard("DP83820", dp83820pnp); -} |
