The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/pc/etherdp83820.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * National Semiconductor DP83820
    3  * 10/100/1000 Mb/s Ethernet Network Interface Controller
    4  * (Gig-NIC).
    5  * Driver assumes little-endian and 32-bit host throughout.
    6  */
    7 #include "u.h"
    8 #include "../port/lib.h"
    9 #include "mem.h"
   10 #include "dat.h"
   11 #include "fns.h"
   12 #include "io.h"
   13 #include "../port/error.h"
   14 #include "../port/netif.h"
   15 
   16 #include "etherif.h"
   17 #include "ethermii.h"
   18 
   19 enum {                                  /* Registers */
   20         Cr              = 0x00,         /* Command */
   21         Cfg             = 0x04,         /* Configuration and Media Status */
   22         Mear            = 0x08,         /* MII/EEPROM Access */
   23         Ptscr           = 0x0C,         /* PCI Test Control */
   24         Isr             = 0x10,         /* Interrupt Status */
   25         Imr             = 0x14,         /* Interrupt Mask */
   26         Ier             = 0x18,         /* Interrupt Enable */
   27         Ihr             = 0x1C,         /* Interrupt Holdoff */
   28         Txdp            = 0x20,         /* Transmit Descriptor Pointer */
   29         Txdphi          = 0x24,         /* Transmit Descriptor Pointer Hi */
   30         Txcfg           = 0x28,         /* Transmit Configuration */
   31         Gpior           = 0x2C,         /* General Purpose I/O Control */
   32         Rxdp            = 0x30,         /* Receive Descriptor Pointer */
   33         Rxdphi          = 0x34,         /* Receive Descriptor Pointer Hi */
   34         Rxcfg           = 0x38,         /* Receive Configuration */
   35         Pqcr            = 0x3C,         /* Priority Queueing Control */
   36         Wcsr            = 0x40,         /* Wake on LAN Control/Status */
   37         Pcr             = 0x44,         /* Pause Control/Status */
   38         Rfcr            = 0x48,         /* Receive Filter/Match Control */
   39         Rfdr            = 0x4C,         /* Receive Filter/Match Data */
   40         Brar            = 0x50,         /* Boot ROM Address */
   41         Brdr            = 0x54,         /* Boot ROM Data */
   42         Srr             = 0x58,         /* Silicon Revision */
   43         Mibc            = 0x5C,         /* MIB Control */
   44         Mibd            = 0x60,         /* MIB Data */
   45         Txdp1           = 0xA0,         /* Txdp Priority 1 */
   46         Txdp2           = 0xA4,         /* Txdp Priority 2 */
   47         Txdp3           = 0xA8,         /* Txdp Priority 3 */
   48         Rxdp1           = 0xB0,         /* Rxdp Priority 1 */
   49         Rxdp2           = 0xB4,         /* Rxdp Priority 2 */
   50         Rxdp3           = 0xB8,         /* Rxdp Priority 3 */
   51         Vrcr            = 0xBC,         /* VLAN/IP Receive Control */
   52         Vtcr            = 0xC0,         /* VLAN/IP Transmit Control */
   53         Vdr             = 0xC4,         /* VLAN Data */
   54         Ccsr            = 0xCC,         /* Clockrun Control/Status */
   55         Tbicr           = 0xE0,         /* TBI Control */
   56         Tbisr           = 0xE4,         /* TBI Status */
   57         Tanar           = 0xE8,         /* TBI ANAR */
   58         Tanlpar         = 0xEC,         /* TBI ANLPAR */
   59         Taner           = 0xF0,         /* TBI ANER */
   60         Tesr            = 0xF4,         /* TBI ESR */
   61 };
   62 
   63 enum {                                  /* Cr */
   64         Txe             = 0x00000001,   /* Transmit Enable */
   65         Txd             = 0x00000002,   /* Transmit Disable */
   66         Rxe             = 0x00000004,   /* Receiver Enable */
   67         Rxd             = 0x00000008,   /* Receiver Disable */
   68         Txr             = 0x00000010,   /* Transmitter Reset */
   69         Rxr             = 0x00000020,   /* Receiver Reset */
   70         Swien           = 0x00000080,   /* Software Interrupt Enable */
   71         Rst             = 0x00000100,   /* Reset */
   72         TxpriSHFT       = 9,            /* Tx Priority Queue Select */
   73         TxpriMASK       = 0x00001E00,
   74         RxpriSHFT       = 13,           /* Rx Priority Queue Select */
   75         RxpriMASK       = 0x0001E000,
   76 };
   77 
   78 enum {                                  /* Configuration and Media Status */
   79         Bem             = 0x00000001,   /* Big Endian Mode */
   80         Ext125          = 0x00000002,   /* External 125MHz reference Select */
   81         Bromdis         = 0x00000004,   /* Disable Boot ROM interface */
   82         Pesel           = 0x00000008,   /* Parity Error Detection Action */
   83         Exd             = 0x00000010,   /* Excessive Deferral Abort */
   84         Pow             = 0x00000020,   /* Program Out of Window Timer */
   85         Sb              = 0x00000040,   /* Single Back-off */
   86         Reqalg          = 0x00000080,   /* PCI Bus Request Algorithm */
   87         Extstsen        = 0x00000100,   /* Extended Status Enable */
   88         Phydis          = 0x00000200,   /* Disable PHY */
   89         Phyrst          = 0x00000400,   /* Reset PHY */
   90         M64addren       = 0x00000800,   /* Master 64-bit Addressing Enable */
   91         Data64en        = 0x00001000,   /* 64-bit Data Enable */
   92         Pci64det        = 0x00002000,   /* PCI 64-bit Bus Detected */
   93         T64addren       = 0x00004000,   /* Target 64-bit Addressing Enable */
   94         Mwidis          = 0x00008000,   /* MWI Disable */
   95         Mrmdis          = 0x00010000,   /* MRM Disable */
   96         Tmrtest         = 0x00020000,   /* Timer Test Mode */
   97         Spdstsien       = 0x00040000,   /* PHY Spdsts Interrupt Enable */
   98         Lnkstsien       = 0x00080000,   /* PHY Lnksts Interrupt Enable */
   99         Dupstsien       = 0x00100000,   /* PHY Dupsts Interrupt Enable */
  100         Mode1000        = 0x00400000,   /* 1000Mb/s Mode Control */
  101         Tbien           = 0x01000000,   /* Ten-Bit Interface Enable */
  102         Dupsts          = 0x10000000,   /* Full Duplex Status */
  103         Spdsts100       = 0x20000000,   /* SPEED100 Input Pin Status */
  104         Spdsts1000      = 0x40000000,   /* SPEED1000 Input Pin Status */
  105         Lnksts          = 0x80000000,   /* Link Status */
  106 };
  107 
  108 enum {                                  /* MII/EEPROM Access */
  109         Eedi            = 0x00000001,   /* EEPROM Data In */
  110         Eedo            = 0x00000002,   /* EEPROM Data Out */
  111         Eeclk           = 0x00000004,   /* EEPROM Serial Clock */
  112         Eesel           = 0x00000008,   /* EEPROM Chip Select */
  113         Mdio            = 0x00000010,   /* MII Management Data */
  114         Mddir           = 0x00000020,   /* MII Management Direction */
  115         Mdc             = 0x00000040,   /* MII Management Clock */
  116 };
  117 
  118 enum {                                  /* Interrupts */
  119         Rxok            = 0x00000001,   /* Rx OK */
  120         Rxdesc          = 0x00000002,   /* Rx Descriptor */
  121         Rxerr           = 0x00000004,   /* Rx Packet Error */
  122         Rxearly         = 0x00000008,   /* Rx Early Threshold */
  123         Rxidle          = 0x00000010,   /* Rx Idle */
  124         Rxorn           = 0x00000020,   /* Rx Overrun */
  125         Txok            = 0x00000040,   /* Tx Packet OK */
  126         Txdesc          = 0x00000080,   /* Tx Descriptor */
  127         Txerr           = 0x00000100,   /* Tx Packet Error */
  128         Txidle          = 0x00000200,   /* Tx Idle */
  129         Txurn           = 0x00000400,   /* Tx Underrun */
  130         Mib             = 0x00000800,   /* MIB Service */
  131         Swi             = 0x00001000,   /* Software Interrupt */
  132         Pme             = 0x00002000,   /* Power Management Event */
  133         Phy             = 0x00004000,   /* PHY Interrupt */
  134         Hibint          = 0x00008000,   /* High Bits Interrupt Set */
  135         Rxsovr          = 0x00010000,   /* Rx Status FIFO Overrun */
  136         Rtabt           = 0x00020000,   /* Received Target Abort */
  137         Rmabt           = 0x00040000,   /* Received Master Abort */
  138         Sserr           = 0x00080000,   /* Signalled System Error */
  139         Dperr           = 0x00100000,   /* Detected Parity Error */
  140         Rxrcmp          = 0x00200000,   /* Receive Reset Complete */
  141         Txrcmp          = 0x00400000,   /* Transmit Reset Complete */
  142         Rxdesc0         = 0x00800000,   /* Rx Descriptor for Priority Queue 0 */
  143         Rxdesc1         = 0x01000000,   /* Rx Descriptor for Priority Queue 1 */
  144         Rxdesc2         = 0x02000000,   /* Rx Descriptor for Priority Queue 2 */
  145         Rxdesc3         = 0x04000000,   /* Rx Descriptor for Priority Queue 3 */
  146         Txdesc0         = 0x08000000,   /* Tx Descriptor for Priority Queue 0 */
  147         Txdesc1         = 0x10000000,   /* Tx Descriptor for Priority Queue 1 */
  148         Txdesc2         = 0x20000000,   /* Tx Descriptor for Priority Queue 2 */
  149         Txdesc3         = 0x40000000,   /* Tx Descriptor for Priority Queue 3 */
  150 };
  151 
  152 enum {                                  /* Interrupt Enable */
  153         Ien             = 0x00000001,   /* Interrupt Enable */
  154 };
  155 
  156 enum {                                  /* Interrupt Holdoff */
  157         IhSHFT          = 0,            /* Interrupt Holdoff */
  158         IhMASK          = 0x000000FF,
  159         Ihctl           = 0x00000100,   /* Interrupt Holdoff Control */
  160 };
  161 
  162 enum {                                  /* Transmit Configuration */
  163         TxdrthSHFT      = 0,            /* Tx Drain Threshold */
  164         TxdrthMASK      = 0x000000FF,
  165         FlthSHFT        = 16,           /* Tx Fill Threshold */
  166         FlthMASK        = 0x0000FF00,
  167         Brstdis         = 0x00080000,   /* 1000Mb/s Burst Disable */
  168         MxdmaSHFT       = 20,           /* Max Size per Tx DMA Burst */
  169         MxdmaMASK       = 0x00700000,
  170         Ecretryen       = 0x00800000,   /* Excessive Collision Retry Enable */
  171         Atp             = 0x10000000,   /* Automatic Transmit Padding */
  172         Mlb             = 0x20000000,   /* MAC Loopback */
  173         Hbi             = 0x40000000,   /* Heartbeat Ignore */
  174         Csi             = 0x80000000,   /* Carrier Sense Ignore */
  175 };
  176 
  177 enum {                                  /* Receive Configuration */
  178         RxdrthSHFT      = 1,            /* Rx Drain Threshold */
  179         RxdrthMASK      = 0x0000003E,
  180         Airl            = 0x04000000,   /* Accept In-Range Length Errored */
  181         Alp             = 0x08000000,   /* Accept Long Packets */
  182         Rxfd            = 0x10000000,   /* Receive Full Duplex */
  183         Stripcrc        = 0x20000000,   /* Strip CRC */
  184         Arp             = 0x40000000,   /* Accept Runt Packets */
  185         Aep             = 0x80000000,   /* Accept Errored Packets */
  186 };
  187 
  188 enum {                                  /* Priority Queueing Control */
  189         Txpqen          = 0x00000001,   /* Transmit Priority Queuing Enable */
  190         Txfairen        = 0x00000002,   /* Transmit Fairness Enable */
  191         RxpqenSHFT      = 2,            /* Receive Priority Queue Enable */
  192         RxpqenMASK      = 0x0000000C,
  193 };
  194 
  195 enum {                                  /* Pause Control/Status */
  196         PscntSHFT       = 0,            /* Pause Counter Value */
  197         PscntMASK       = 0x0000FFFF,
  198         Pstx            = 0x00020000,   /* Transmit Pause Frame */
  199         PsffloSHFT      = 18,           /* Rx Data FIFO Lo Threshold */
  200         PsffloMASK      = 0x000C0000,
  201         PsffhiSHFT      = 20,           /* Rx Data FIFO Hi Threshold */
  202         PsffhiMASK      = 0x00300000,
  203         PsstloSHFT      = 22,           /* Rx Stat FIFO Hi Threshold */
  204         PsstloMASK      = 0x00C00000,
  205         PssthiSHFT      = 24,           /* Rx Stat FIFO Hi Threshold */
  206         PssthiMASK      = 0x03000000,
  207         Psrcvd          = 0x08000000,   /* Pause Frame Received */
  208         Psact           = 0x10000000,   /* Pause Active */
  209         Psda            = 0x20000000,   /* Pause on Destination Address */
  210         Psmcast         = 0x40000000,   /* Pause on Multicast */
  211         Psen            = 0x80000000,   /* Pause Enable */
  212 };
  213 
  214 enum {                                  /* Receive Filter/Match Control */
  215         RfaddrSHFT      = 0,            /* Extended Register Address */
  216         RfaddrMASK      = 0x000003FF,
  217         Ulm             = 0x00080000,   /* U/L bit mask */
  218         Uhen            = 0x00100000,   /* Unicast Hash Enable */
  219         Mhen            = 0x00200000,   /* Multicast Hash Enable */
  220         Aarp            = 0x00400000,   /* Accept ARP Packets */
  221         ApatSHFT        = 23,           /* Accept on Pattern Match */
  222         ApatMASK        = 0x07800000,
  223         Apm             = 0x08000000,   /* Accept on Perfect Match */
  224         Aau             = 0x10000000,   /* Accept All Unicast */
  225         Aam             = 0x20000000,   /* Accept All Multicast */
  226         Aab             = 0x40000000,   /* Accept All Broadcast */
  227         Rfen            = 0x80000000,   /* Rx Filter Enable */
  228 };
  229 
  230 enum {                                  /* Receive Filter/Match Data */
  231         RfdataSHFT      = 0,            /* Receive Filter Data */
  232         RfdataMASK      = 0x0000FFFF,
  233         BmaskSHFT       = 16,           /* Byte Mask */
  234         BmaskMASK       = 0x00030000,
  235 };
  236 
  237 enum {                                  /* MIB Control */
  238         Wrn             = 0x00000001,   /* Warning Test Indicator */
  239         Frz             = 0x00000002,   /* Freeze All Counters */
  240         Aclr            = 0x00000004,   /* Clear All Counters */
  241         Mibs            = 0x00000008,   /* MIB Counter Strobe */
  242 };
  243 
  244 enum {                                  /* MIB Data */
  245         Nmibd           = 11,           /* Number of MIB Data Registers */
  246 };
  247 
  248 enum {                                  /* VLAN/IP Receive Control */
  249         Vtden           = 0x00000001,   /* VLAN Tag Detection Enable */
  250         Vtren           = 0x00000002,   /* VLAN Tag Removal Enable */
  251         Dvtf            = 0x00000004,   /* Discard VLAN Tagged Frames */
  252         Dutf            = 0x00000008,   /* Discard Untagged Frames */
  253         Ipen            = 0x00000010,   /* IP Checksum Enable */
  254         Ripe            = 0x00000020,   /* Reject IP Checksum Errors */
  255         Rtcpe           = 0x00000040,   /* Reject TCP Checksum Errors */
  256         Rudpe           = 0x00000080,   /* Reject UDP Checksum Errors */
  257 };
  258 
  259 enum {                                  /* VLAN/IP Transmit Control */
  260         Vgti            = 0x00000001,   /* VLAN Global Tag Insertion */
  261         Vppti           = 0x00000002,   /* VLAN Per-Packet Tag Insertion */
  262         Gchk            = 0x00000004,   /* Global Checksum Generation */
  263         Ppchk           = 0x00000008,   /* Per-Packet Checksum Generation */
  264 };
  265 
  266 enum {                                  /* VLAN Data */
  267         VtypeSHFT       = 0,            /* VLAN Type Field */
  268         VtypeMASK       = 0x0000FFFF,
  269         VtciSHFT        = 16,           /* VLAN Tag Control Information */
  270         VtciMASK        = 0xFFFF0000,
  271 };
  272 
  273 enum {                                  /* Clockrun Control/Status */
  274         Clkrunen        = 0x00000001,   /* CLKRUN Enable */
  275         Pmeen           = 0x00000100,   /* PME Enable */
  276         Pmests          = 0x00008000,   /* PME Status */
  277 };
  278 
  279 typedef struct {
  280         u32int  link;                   /* Link to the next descriptor */
  281         u32int  bufptr;                 /* pointer to data Buffer */
  282         int     cmdsts;                 /* Command/Status */
  283         int     extsts;                 /* optional Extended Status */
  284 
  285         Block*  bp;                     /* Block containing bufptr */
  286         u32int  unused;                 /* pad to 64-bit */
  287 } Desc;
  288 
  289 enum {                                  /* Common cmdsts bits */
  290         SizeMASK        = 0x0000FFFF,   /* Descriptor Byte Count */
  291         SizeSHFT        = 0,
  292         Ok              = 0x08000000,   /* Packet OK */
  293         Crc             = 0x10000000,   /* Suppress/Include CRC */
  294         Intr            = 0x20000000,   /* Interrupt on ownership transfer */
  295         More            = 0x40000000,   /* not last descriptor in a packet */
  296         Own             = 0x80000000,   /* Descriptor Ownership */
  297 };
  298 
  299 enum {                                  /* Transmit cmdsts bits */
  300         CcntMASK        = 0x000F0000,   /* Collision Count */
  301         CcntSHFT        = 16,
  302         Ec              = 0x00100000,   /* Excessive Collisions */
  303         Owc             = 0x00200000,   /* Out of Window Collision */
  304         Ed              = 0x00400000,   /* Excessive Deferral */
  305         Td              = 0x00800000,   /* Transmit Deferred */
  306         Crs             = 0x01000000,   /* Carrier Sense Lost */
  307         Tfu             = 0x02000000,   /* Transmit FIFO Underrun */
  308         Txa             = 0x04000000,   /* Transmit Abort */
  309 };
  310 
  311 enum {                                  /* Receive cmdsts bits */
  312         Irl             = 0x00010000,   /* In-Range Length Error */
  313         Lbp             = 0x00020000,   /* Loopback Packet */
  314         Fae             = 0x00040000,   /* Frame Alignment Error */
  315         Crce            = 0x00080000,   /* CRC Error */
  316         Ise             = 0x00100000,   /* Invalid Symbol Error */
  317         Runt            = 0x00200000,   /* Runt Packet Received */
  318         Long            = 0x00400000,   /* Too Long Packet Received */
  319         DestMASK        = 0x01800000,   /* Destination Class */
  320         DestSHFT        = 23,
  321         Rxo             = 0x02000000,   /* Receive Overrun */
  322         Rxa             = 0x04000000,   /* Receive Aborted */
  323 };
  324 
  325 enum {                                  /* extsts bits */
  326         EvtciMASK       = 0x0000FFFF,   /* VLAN Tag Control Information */
  327         EvtciSHFT       = 0,
  328         Vpkt            = 0x00010000,   /* VLAN Packet */
  329         Ippkt           = 0x00020000,   /* IP Packet */
  330         Iperr           = 0x00040000,   /* IP Checksum Error */
  331         Tcppkt          = 0x00080000,   /* TCP Packet */
  332         Tcperr          = 0x00100000,   /* TCP Checksum Error */
  333         Udppkt          = 0x00200000,   /* UDP Packet */
  334         Udperr          = 0x00400000,   /* UDP Checksum Error */
  335 };
  336 
  337 enum {
  338         Nrd             = 256,
  339         Nrb             = 4*Nrd,
  340         Rbsz            = ROUNDUP(sizeof(Etherpkt)+8, 8),
  341         Ntd             = 128,
  342 };
  343 
  344 typedef struct Ctlr Ctlr;
  345 typedef struct Ctlr {
  346         int     port;
  347         Pcidev* pcidev;
  348         Ctlr*   next;
  349         int     active;
  350         int     id;
  351 
  352         int     eepromsz;               /* address size in bits */
  353         ushort* eeprom;
  354 
  355         int*    nic;
  356         int     cfg;
  357         int     imr;
  358 
  359         QLock   alock;                  /* attach */
  360         Lock    ilock;                  /* init */
  361         void*   alloc;                  /* base of per-Ctlr allocated data */
  362 
  363         Mii*    mii;
  364 
  365         Lock    rdlock;                 /* receive */
  366         Desc*   rd;
  367         int     nrd;
  368         int     nrb;
  369         int     rdx;
  370         int     rxcfg;
  371 
  372         Lock    tlock;                  /* transmit */
  373         Desc*   td;
  374         int     ntd;
  375         int     tdh;
  376         int     tdt;
  377         int     ntq;
  378         int     txcfg;
  379 
  380         int     rxidle;
  381 
  382         uint    mibd[Nmibd];
  383 
  384         int     ec;
  385         int     owc;
  386         int     ed;
  387         int     crs;
  388         int     tfu;
  389         int     txa;
  390 } Ctlr;
  391 
  392 #define csr32r(c, r)    (*((c)->nic+((r)/4)))
  393 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
  394 
  395 static Ctlr* dp83820ctlrhead;
  396 static Ctlr* dp83820ctlrtail;
  397 
  398 static Lock dp83820rblock;              /* free receive Blocks */
  399 static Block* dp83820rbpool;
  400 
  401 static char* dp83820mibs[Nmibd] = {
  402         "RXErroredPkts",
  403         "RXFCSErrors",
  404         "RXMsdPktErrors",
  405         "RXFAErrors",
  406         "RXSymbolErrors",
  407         "RXFrameToLong",
  408         "RXIRLErrors",
  409         "RXBadOpcodes",
  410         "RXPauseFrames",
  411         "TXPauseFrames",
  412         "TXSQEErrors",
  413 };
  414 
  415 static int
  416 mdior(Ctlr* ctlr, int n)
  417 {
  418         int data, i, mear, r;
  419 
  420         mear = csr32r(ctlr, Mear);
  421         r = ~(Mdc|Mddir) & mear;
  422         data = 0;
  423         for(i = n-1; i >= 0; i--){
  424                 if(csr32r(ctlr, Mear) & Mdio)
  425                         data |= (1<<i);
  426                 csr32w(ctlr, Mear, Mdc|r);
  427                 csr32w(ctlr, Mear, r);
  428         }
  429         csr32w(ctlr, Mear, mear);
  430 
  431         return data;
  432 }
  433 
  434 static void
  435 mdiow(Ctlr* ctlr, int bits, int n)
  436 {
  437         int i, mear, r;
  438 
  439         mear = csr32r(ctlr, Mear);
  440         r = Mddir|(~Mdc & mear);
  441         for(i = n-1; i >= 0; i--){
  442                 if(bits & (1<<i))
  443                         r |= Mdio;
  444                 else
  445                         r &= ~Mdio;
  446                 csr32w(ctlr, Mear, r);
  447                 csr32w(ctlr, Mear, Mdc|r);
  448         }
  449         csr32w(ctlr, Mear, mear);
  450 }
  451 
  452 static int
  453 dp83820miimir(Mii* mii, int pa, int ra)
  454 {
  455         int data;
  456         Ctlr *ctlr;
  457 
  458         ctlr = mii->ctlr;
  459 
  460         /*
  461          * MII Management Interface Read.
  462          *
  463          * Preamble;
  464          * ST+OP+PA+RA;
  465          * LT + 16 data bits.
  466          */
  467         mdiow(ctlr, 0xFFFFFFFF, 32);
  468         mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
  469         data = mdior(ctlr, 18);
  470 
  471         if(data & 0x10000)
  472                 return -1;
  473 
  474         return data & 0xFFFF;
  475 }
  476 
  477 static int
  478 dp83820miimiw(Mii* mii, int pa, int ra, int data)
  479 {
  480         Ctlr *ctlr;
  481 
  482         ctlr = mii->ctlr;
  483 
  484         /*
  485          * MII Management Interface Write.
  486          *
  487          * Preamble;
  488          * ST+OP+PA+RA+LT + 16 data bits;
  489          * Z.
  490          */
  491         mdiow(ctlr, 0xFFFFFFFF, 32);
  492         data &= 0xFFFF;
  493         data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
  494         mdiow(ctlr, data, 32);
  495 
  496         return 0;
  497 }
  498 
  499 static Block *
  500 dp83820rballoc(Desc* desc)
  501 {
  502         Block *bp;
  503 
  504         if(desc->bp == nil){
  505                 ilock(&dp83820rblock);
  506                 if((bp = dp83820rbpool) == nil){
  507                         iunlock(&dp83820rblock);
  508                         desc->bp = nil;
  509                         desc->cmdsts = Own;
  510                         return nil;
  511                 }
  512                 dp83820rbpool = bp->next;
  513                 bp->next = nil;
  514                 _xinc(&bp->ref);        /* prevent bp from being freed */
  515                 iunlock(&dp83820rblock);
  516         
  517                 desc->bufptr = PCIWADDR(bp->rp);
  518                 desc->bp = bp;
  519         }
  520         else{
  521                 bp = desc->bp;
  522                 bp->rp = bp->lim - Rbsz;
  523                 bp->wp = bp->rp;
  524         }
  525 
  526         coherence();
  527         desc->cmdsts = Intr|Rbsz;
  528 
  529         return bp;
  530 }
  531 
  532 static void
  533 dp83820rbfree(Block *bp)
  534 {
  535         bp->rp = bp->lim - Rbsz;
  536         bp->wp = bp->rp;
  537 
  538         ilock(&dp83820rblock);
  539         bp->next = dp83820rbpool;
  540         dp83820rbpool = bp;
  541         iunlock(&dp83820rblock);
  542 }
  543 
  544 static void
  545 dp83820halt(Ctlr* ctlr)
  546 {
  547         int i, timeo;
  548 
  549         ilock(&ctlr->ilock);
  550         csr32w(ctlr, Imr, 0);
  551         csr32w(ctlr, Ier, 0);
  552         csr32w(ctlr, Cr, Rxd|Txd);
  553         for(timeo = 0; timeo < 1000; timeo++){
  554                 if(!(csr32r(ctlr, Cr) & (Rxe|Txe)))
  555                         break;
  556                 microdelay(1);
  557         }
  558         csr32w(ctlr, Mibc, Frz);
  559         iunlock(&ctlr->ilock);
  560 
  561         if(ctlr->rd != nil){
  562                 for(i = 0; i < ctlr->nrd; i++){
  563                         if(ctlr->rd[i].bp == nil)
  564                                 continue;
  565                         freeb(ctlr->rd[i].bp);
  566                         ctlr->rd[i].bp = nil;
  567                 }
  568         }
  569         if(ctlr->td != nil){
  570                 for(i = 0; i < ctlr->ntd; i++){
  571                         if(ctlr->td[i].bp == nil)
  572                                 continue;
  573                         freeb(ctlr->td[i].bp);
  574                         ctlr->td[i].bp = nil;
  575                 }
  576         }
  577 }
  578 
  579 static void
  580 dp83820cfg(Ctlr* ctlr)
  581 {
  582         int cfg;
  583 
  584         /*
  585          * Don't know how to deal with a TBI yet.
  586          */
  587         if(ctlr->mii == nil)
  588                 return;
  589 
  590         /*
  591          * The polarity of these bits is at the mercy
  592          * of the board designer.
  593          * The correct answer for all speed and duplex questions
  594          * should be to query the phy.
  595          */
  596         cfg = csr32r(ctlr, Cfg);
  597         if(!(cfg & Dupsts)){
  598                 ctlr->rxcfg |= Rxfd;
  599                 ctlr->txcfg |= Csi|Hbi;
  600                 iprint("83820: full duplex, ");
  601         }
  602         else{
  603                 ctlr->rxcfg &= ~Rxfd;
  604                 ctlr->txcfg &= ~(Csi|Hbi);
  605                 iprint("83820: half duplex, ");
  606         }
  607         csr32w(ctlr, Rxcfg, ctlr->rxcfg);
  608         csr32w(ctlr, Txcfg, ctlr->txcfg);
  609 
  610         switch(cfg & (Spdsts1000|Spdsts100)){
  611         case Spdsts1000:                /* 100Mbps */
  612         default:                        /* 10Mbps */
  613                 ctlr->cfg &= ~Mode1000;
  614                 if((cfg & (Spdsts1000|Spdsts100)) == Spdsts1000)
  615                         iprint("100Mb/s\n");
  616                 else
  617                         iprint("10Mb/s\n");
  618                 break;
  619         case Spdsts100:                 /* 1Gbps */
  620                 ctlr->cfg |= Mode1000;
  621                 iprint("1Gb/s\n");
  622                 break;
  623         }
  624         csr32w(ctlr, Cfg, ctlr->cfg);
  625 }
  626 
  627 static void
  628 dp83820init(Ether* edev)
  629 {
  630         int i;
  631         Ctlr *ctlr;
  632         Desc *desc;
  633         uchar *alloc;
  634 
  635         ctlr = edev->ctlr;
  636 
  637         dp83820halt(ctlr);
  638 
  639         /*
  640          * Receiver
  641          */
  642         alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 8);
  643         ctlr->rd = (Desc*)alloc;
  644         alloc += ctlr->nrd*sizeof(Desc);
  645         memset(ctlr->rd, 0, ctlr->nrd*sizeof(Desc));
  646         ctlr->rdx = 0;
  647         for(i = 0; i < ctlr->nrd; i++){
  648                 desc = &ctlr->rd[i];
  649                 desc->link = PCIWADDR(&ctlr->rd[NEXT(i, ctlr->nrd)]);
  650                 if(dp83820rballoc(desc) == nil)
  651                         continue;
  652         }
  653         csr32w(ctlr, Rxdphi, 0);
  654         csr32w(ctlr, Rxdp, PCIWADDR(ctlr->rd));
  655 
  656         for(i = 0; i < Eaddrlen; i += 2){
  657                 csr32w(ctlr, Rfcr, i);
  658                 csr32w(ctlr, Rfdr, (edev->ea[i+1]<<8)|edev->ea[i]);
  659         }
  660         csr32w(ctlr, Rfcr, Rfen|Aab|Aam|Apm);
  661 
  662         ctlr->rxcfg = Stripcrc|(((2*(ETHERMINTU+4))/8)<<RxdrthSHFT);
  663         ctlr->imr |= Rxorn|Rxidle|Rxearly|Rxdesc|Rxok;
  664 
  665         /*
  666          * Transmitter.
  667          */
  668         ctlr->td = (Desc*)alloc;
  669         memset(ctlr->td, 0, ctlr->ntd*sizeof(Desc));
  670         ctlr->tdh = ctlr->tdt = ctlr->ntq = 0;
  671         for(i = 0; i < ctlr->ntd; i++){
  672                 desc = &ctlr->td[i];
  673                 desc->link = PCIWADDR(&ctlr->td[NEXT(i, ctlr->ntd)]);
  674         }
  675         csr32w(ctlr, Txdphi, 0);
  676         csr32w(ctlr, Txdp, PCIWADDR(ctlr->td));
  677 
  678         ctlr->txcfg = Atp|(((2*(ETHERMINTU+4))/32)<<FlthSHFT)|((4096/32)<<TxdrthSHFT);
  679         ctlr->imr |= Txurn|Txidle|Txdesc|Txok;
  680 
  681         ilock(&ctlr->ilock);
  682 
  683         dp83820cfg(ctlr);
  684 
  685         csr32w(ctlr, Mibc, Aclr);
  686         ctlr->imr |= Mib;
  687 
  688         csr32w(ctlr, Imr, ctlr->imr);
  689 
  690         /* try coalescing adjacent interrupts; use hold-off interval of 100µs */
  691         csr32w(ctlr, Ihr, Ihctl|(1<<IhSHFT));
  692 
  693         csr32w(ctlr, Ier, Ien);
  694         csr32w(ctlr, Cr, Rxe|Txe);
  695 
  696         iunlock(&ctlr->ilock);
  697 }
  698 
  699 static void
  700 dp83820attach(Ether* edev)
  701 {
  702         Block *bp;
  703         Ctlr *ctlr;
  704 
  705         ctlr = edev->ctlr;
  706         qlock(&ctlr->alock);
  707         if(ctlr->alloc != nil){
  708                 qunlock(&ctlr->alock);
  709                 return;
  710         }
  711 
  712         if(waserror()){
  713                 if(ctlr->mii != nil){
  714                         free(ctlr->mii);
  715                         ctlr->mii = nil;
  716                 }
  717                 if(ctlr->alloc != nil){
  718                         free(ctlr->alloc);
  719                         ctlr->alloc = nil;
  720                 }
  721                 qunlock(&ctlr->alock);
  722                 nexterror();
  723         }
  724 
  725         if(!(ctlr->cfg & Tbien)){
  726                 if((ctlr->mii = malloc(sizeof(Mii))) == nil)
  727                         error(Enomem);
  728                 ctlr->mii->ctlr = ctlr;
  729                 ctlr->mii->mir = dp83820miimir;
  730                 ctlr->mii->miw = dp83820miimiw;
  731                 if(mii(ctlr->mii, ~0) == 0)
  732                         error("no PHY");
  733                 ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien;
  734                 ctlr->imr |= Phy;
  735         }
  736 
  737         ctlr->nrd = Nrd;
  738         ctlr->nrb = Nrb;
  739         ctlr->ntd = Ntd;
  740         ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0);
  741         if(ctlr->alloc == nil)
  742                 error(Enomem);
  743 
  744         for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){
  745                 if((bp = allocb(Rbsz)) == nil)
  746                         break;
  747                 bp->free = dp83820rbfree;
  748                 dp83820rbfree(bp);
  749         }
  750 
  751         dp83820init(edev);
  752 
  753         qunlock(&ctlr->alock);
  754         poperror();
  755 }
  756 
  757 static void
  758 dp83820transmit(Ether* edev)
  759 {
  760         Block *bp;
  761         Ctlr *ctlr;
  762         Desc *desc;
  763         int cmdsts, r, x;
  764 
  765         ctlr = edev->ctlr;
  766 
  767         ilock(&ctlr->tlock);
  768 
  769         bp = nil;
  770         for(x = ctlr->tdh; ctlr->ntq; x = NEXT(x, ctlr->ntd)){
  771                 desc = &ctlr->td[x];
  772                 if((cmdsts = desc->cmdsts) & Own)
  773                         break;
  774                 if(!(cmdsts & Ok)){
  775                         if(cmdsts & Ec)
  776                                 ctlr->ec++;
  777                         if(cmdsts & Owc)
  778                                 ctlr->owc++;
  779                         if(cmdsts & Ed)
  780                                 ctlr->ed++;
  781                         if(cmdsts & Crs)
  782                                 ctlr->crs++;
  783                         if(cmdsts & Tfu)
  784                                 ctlr->tfu++;
  785                         if(cmdsts & Txa)
  786                                 ctlr->txa++;
  787                         edev->oerrs++;
  788                 }
  789                 desc->bp->next = bp;
  790                 bp = desc->bp;
  791                 desc->bp = nil;
  792 
  793                 ctlr->ntq--;
  794         }
  795         ctlr->tdh = x;
  796         if(bp != nil)
  797                 freeblist(bp);
  798 
  799         x = ctlr->tdt;
  800         while(ctlr->ntq < (ctlr->ntd-1)){
  801                 if((bp = qget(edev->oq)) == nil)
  802                         break;
  803 
  804                 desc = &ctlr->td[x];
  805                 desc->bufptr = PCIWADDR(bp->rp);
  806                 desc->bp = bp;
  807                 ctlr->ntq++;
  808                 coherence();
  809                 desc->cmdsts = Own|Intr|BLEN(bp);
  810 
  811                 x = NEXT(x, ctlr->ntd);
  812         }
  813         if(x != ctlr->tdt){
  814                 ctlr->tdt = x;
  815                 r = csr32r(ctlr, Cr);
  816                 csr32w(ctlr, Cr, Txe|r);
  817         }
  818 
  819         iunlock(&ctlr->tlock);
  820 }
  821 
  822 static void
  823 dp83820interrupt(Ureg*, void* arg)
  824 {
  825         Block *bp;
  826         Ctlr *ctlr;
  827         Desc *desc;
  828         Ether *edev;
  829         int cmdsts, i, isr, r, x;
  830 
  831         edev = arg;
  832         ctlr = edev->ctlr;
  833 
  834         for(isr = csr32r(ctlr, Isr); isr & ctlr->imr; isr = csr32r(ctlr, Isr)){
  835                 if(isr & (Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok)){
  836                         x = ctlr->rdx;
  837                         desc = &ctlr->rd[x];
  838                         while((cmdsts = desc->cmdsts) & Own){
  839                                 if((cmdsts & Ok) && desc->bp != nil){
  840                                         bp = desc->bp;
  841                                         desc->bp = nil;
  842                                         bp->wp += cmdsts & SizeMASK;
  843                                         etheriq(edev, bp, 1);
  844                                 }
  845                                 else if(0 && !(cmdsts & Ok)){
  846                                         iprint("dp83820: rx %8.8uX:", cmdsts);
  847                                         bp = desc->bp;
  848                                         for(i = 0; i < 20; i++)
  849                                                 iprint(" %2.2uX", bp->rp[i]);
  850                                         iprint("\n");
  851                                 }
  852                                 dp83820rballoc(desc);
  853 
  854                                 x = NEXT(x, ctlr->nrd);
  855                                 desc = &ctlr->rd[x];
  856                         }
  857                         ctlr->rdx = x;
  858 
  859                         if(isr & Rxidle){
  860                                 r = csr32r(ctlr, Cr);
  861                                 csr32w(ctlr, Cr, Rxe|r);
  862                                 ctlr->rxidle++;
  863                         }
  864 
  865                         isr &= ~(Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok);
  866                 }
  867 
  868                 if(isr & Txurn){
  869                         x = (ctlr->txcfg & TxdrthMASK)>>TxdrthSHFT;
  870                         r = (ctlr->txcfg & FlthMASK)>>FlthSHFT;
  871                         if(x < ((TxdrthMASK)>>TxdrthSHFT)
  872                         && x < (2048/32 - r)){
  873                                 ctlr->txcfg &= ~TxdrthMASK;
  874                                 x++;
  875                                 ctlr->txcfg |= x<<TxdrthSHFT;
  876                                 csr32w(ctlr, Txcfg, ctlr->txcfg);
  877                         }
  878                 }
  879 
  880                 if(isr & (Txurn|Txidle|Txdesc|Txok)){
  881                         dp83820transmit(edev);
  882                         isr &= ~(Txurn|Txidle|Txdesc|Txok);
  883                 }
  884 
  885                 if(isr & Mib){
  886                         for(i = 0; i < Nmibd; i++){
  887                                 r = csr32r(ctlr, Mibd+(i*sizeof(int)));
  888                                 ctlr->mibd[i] += r & 0xFFFF;
  889                         }
  890                         isr &= ~Mib;
  891                 }
  892 
  893                 if((isr & Phy) && ctlr->mii != nil){
  894                         ctlr->mii->mir(ctlr->mii, 1, Bmsr);
  895                         print("phy: cfg %8.8uX bmsr %4.4uX\n",
  896                                 csr32r(ctlr, Cfg),
  897                                 ctlr->mii->mir(ctlr->mii, 1, Bmsr));
  898                         dp83820cfg(ctlr);
  899                         isr &= ~Phy;
  900                 }
  901                 if(isr)
  902                         iprint("dp83820: isr %8.8uX\n", isr);
  903         }
  904 }
  905 
  906 static long
  907 dp83820ifstat(Ether* edev, void* a, long n, ulong offset)
  908 {
  909         char *p;
  910         Ctlr *ctlr;
  911         int i, l, r;
  912 
  913         ctlr = edev->ctlr;
  914 
  915         edev->crcs = ctlr->mibd[Mibd+(1*sizeof(int))];
  916         edev->frames = ctlr->mibd[Mibd+(3*sizeof(int))];
  917         edev->buffs = ctlr->mibd[Mibd+(5*sizeof(int))];
  918         edev->overflows = ctlr->mibd[Mibd+(2*sizeof(int))];
  919 
  920         if(n == 0)
  921                 return 0;
  922 
  923         p = malloc(READSTR);
  924         l = 0;
  925         for(i = 0; i < Nmibd; i++){
  926                 r = csr32r(ctlr, Mibd+(i*sizeof(int)));
  927                 ctlr->mibd[i] += r & 0xFFFF;
  928                 if(ctlr->mibd[i] != 0 && dp83820mibs[i] != nil)
  929                         l += snprint(p+l, READSTR-l, "%s: %ud %ud\n",
  930                                 dp83820mibs[i], ctlr->mibd[i], r);
  931         }
  932         l += snprint(p+l, READSTR-l, "rxidle %d\n", ctlr->rxidle);
  933         l += snprint(p+l, READSTR-l, "ec %d\n", ctlr->ec);
  934         l += snprint(p+l, READSTR-l, "owc %d\n", ctlr->owc);
  935         l += snprint(p+l, READSTR-l, "ed %d\n", ctlr->ed);
  936         l += snprint(p+l, READSTR-l, "crs %d\n", ctlr->crs);
  937         l += snprint(p+l, READSTR-l, "tfu %d\n", ctlr->tfu);
  938         l += snprint(p+l, READSTR-l, "txa %d\n", ctlr->txa);
  939 
  940         l += snprint(p+l, READSTR, "rom:");
  941         for(i = 0; i < 0x10; i++){
  942                 if(i && ((i & 0x07) == 0))
  943                         l += snprint(p+l, READSTR-l, "\n    ");
  944                 l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->eeprom[i]);
  945         }
  946         l += snprint(p+l, READSTR-l, "\n");
  947 
  948         if(ctlr->mii != nil && ctlr->mii->curphy != nil){
  949                 l += snprint(p+l, READSTR, "phy:");
  950                 for(i = 0; i < NMiiPhyr; i++){
  951                         if(i && ((i & 0x07) == 0))
  952                                 l += snprint(p+l, READSTR-l, "\n    ");
  953                         r = miimir(ctlr->mii, i);
  954                         l += snprint(p+l, READSTR-l, " %4.4uX", r);
  955                 }
  956                 snprint(p+l, READSTR-l, "\n");
  957         }
  958 
  959         n = readstr(offset, a, n, p);
  960         free(p);
  961 
  962         return n;
  963 }
  964 
  965 static void
  966 dp83820promiscuous(void* arg, int on)
  967 {
  968         USED(arg, on);
  969 }
  970 
  971 /* multicast already on, don't need to do anything */
  972 static void
  973 dp83820multicast(void*, uchar*, int)
  974 {
  975 }
  976 
  977 static int
  978 dp83820detach(Ctlr* ctlr)
  979 {
  980         /*
  981          * Soft reset the controller.
  982          */
  983         csr32w(ctlr, Cr, Rst);
  984         delay(1);
  985         while(csr32r(ctlr, Cr) & Rst)
  986                 delay(1);
  987         return 0;
  988 }
  989 
  990 static void
  991 dp83820shutdown(Ether* ether)
  992 {
  993 print("dp83820shutdown\n");
  994         dp83820detach(ether->ctlr);
  995 }
  996 
  997 static int
  998 atc93c46r(Ctlr* ctlr, int address)
  999 {
 1000         int data, i, mear, r, size;
 1001 
 1002         /*
 1003          * Analog Technology, Inc. ATC93C46
 1004          * or equivalent serial EEPROM.
 1005          */
 1006         mear = csr32r(ctlr, Mear);
 1007         mear &= ~(Eesel|Eeclk|Eedo|Eedi);
 1008         r = Eesel|mear;
 1009 
 1010 reread:
 1011         csr32w(ctlr, Mear, r);
 1012         data = 0x06;
 1013         for(i = 3-1; i >= 0; i--){
 1014                 if(data & (1<<i))
 1015                         r |= Eedi;
 1016                 else
 1017                         r &= ~Eedi;
 1018                 csr32w(ctlr, Mear, r);
 1019                 csr32w(ctlr, Mear, Eeclk|r);
 1020                 microdelay(1);
 1021                 csr32w(ctlr, Mear, r);
 1022                 microdelay(1);
 1023         }
 1024 
 1025         /*
 1026          * First time through must work out the EEPROM size.
 1027          */
 1028         if((size = ctlr->eepromsz) == 0)
 1029                 size = 8;
 1030 
 1031         for(size = size-1; size >= 0; size--){
 1032                 if(address & (1<<size))
 1033                         r |= Eedi;
 1034                 else
 1035                         r &= ~Eedi;
 1036                 csr32w(ctlr, Mear, r);
 1037                 microdelay(1);
 1038                 csr32w(ctlr, Mear, Eeclk|r);
 1039                 microdelay(1);
 1040                 csr32w(ctlr, Mear, r);
 1041                 microdelay(1);
 1042                 if(!(csr32r(ctlr, Mear) & Eedo))
 1043                         break;
 1044         }
 1045         r &= ~Eedi;
 1046 
 1047         data = 0;
 1048         for(i = 16-1; i >= 0; i--){
 1049                 csr32w(ctlr, Mear, Eeclk|r);
 1050                 microdelay(1);
 1051                 if(csr32r(ctlr, Mear) & Eedo)
 1052                         data |= (1<<i);
 1053                 csr32w(ctlr, Mear, r);
 1054                 microdelay(1);
 1055         }
 1056 
 1057         csr32w(ctlr, Mear, mear);
 1058 
 1059         if(ctlr->eepromsz == 0){
 1060                 ctlr->eepromsz = 8-size;
 1061                 ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
 1062                 goto reread;
 1063         }
 1064 
 1065         return data;
 1066 }
 1067 
 1068 static int
 1069 dp83820reset(Ctlr* ctlr)
 1070 {
 1071         int i, r;
 1072         unsigned char sum;
 1073 
 1074         /*
 1075          * Soft reset the controller;
 1076          * read the EEPROM to get the initial settings
 1077          * of the Cfg and Gpior bits which should be cleared by
 1078          * the reset.
 1079          */
 1080         dp83820detach(ctlr);
 1081 
 1082         atc93c46r(ctlr, 0);
 1083         if(ctlr->eeprom == nil) {
 1084                 print("dp83820reset: no eeprom\n");
 1085                 return -1;
 1086         }
 1087         sum = 0;
 1088         for(i = 0; i < 0x0E; i++){
 1089                 r = atc93c46r(ctlr, i);
 1090                 ctlr->eeprom[i] = r;
 1091                 sum += r;
 1092                 sum += r>>8;
 1093         }
 1094 
 1095         if(sum != 0){
 1096                 print("dp83820reset: bad EEPROM checksum\n");
 1097                 return -1;
 1098         }
 1099 
 1100 #ifdef notdef
 1101         csr32w(ctlr, Gpior, ctlr->eeprom[4]);
 1102 
 1103         cfg = Extstsen|Exd;
 1104         r = csr32r(ctlr, Cfg);
 1105         if(ctlr->eeprom[5] & 0x0001)
 1106                 cfg |= Ext125;
 1107         if(ctlr->eeprom[5] & 0x0002)
 1108                 cfg |= M64addren;
 1109         if((ctlr->eeprom[5] & 0x0004) && (r & Pci64det))
 1110                 cfg |= Data64en;
 1111         if(ctlr->eeprom[5] & 0x0008)
 1112                 cfg |= T64addren;
 1113         if(!(pcicfgr16(ctlr->pcidev, PciPCR) & 0x10))
 1114                 cfg |= Mwidis;
 1115         if(ctlr->eeprom[5] & 0x0020)
 1116                 cfg |= Mrmdis;
 1117         if(ctlr->eeprom[5] & 0x0080)
 1118                 cfg |= Mode1000;
 1119         if(ctlr->eeprom[5] & 0x0200)
 1120                 cfg |= Tbien|Mode1000;
 1121         /*
 1122          * What about RO bits we might have destroyed with Rst?
 1123          * What about Exd, Tmrtest, Extstsen, Pintctl?
 1124          * Why does it think it has detected a 64-bit bus when
 1125          * it hasn't?
 1126          */
 1127 #else
 1128         // r = csr32r(ctlr, Cfg);
 1129         // r &= ~(Mode1000|T64addren|Data64en|M64addren);
 1130         // csr32w(ctlr, Cfg, r);
 1131         // csr32w(ctlr, Cfg, 0x2000);
 1132 #endif                                          /* notdef */
 1133         ctlr->cfg = csr32r(ctlr, Cfg);
 1134 print("cfg %8.8uX pcicfg %8.8uX\n", ctlr->cfg, pcicfgr32(ctlr->pcidev, PciPCR));
 1135         ctlr->cfg &= ~(T64addren|Data64en|M64addren);
 1136         csr32w(ctlr, Cfg, ctlr->cfg);
 1137         csr32w(ctlr, Mibc, Aclr|Frz);
 1138 
 1139         return 0;
 1140 }
 1141 
 1142 static void
 1143 dp83820pci(void)
 1144 {
 1145         void *mem;
 1146         Pcidev *p;
 1147         Ctlr *ctlr;
 1148 
 1149         p = nil;
 1150         while(p = pcimatch(p, 0, 0)){
 1151                 if(p->ccrb != Pcibcnet || p->ccru != Pciscether)
 1152                         continue;
 1153 
 1154                 switch((p->did<<16)|p->vid){
 1155                 default:
 1156                         continue;
 1157                 case (0x0022<<16)|0x100B:       /* DP83820 (Gig-NIC) */
 1158                         break;
 1159                 }
 1160 
 1161                 mem = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size);
 1162                 if(mem == 0){
 1163                         print("DP83820: can't map %8.8luX\n", p->mem[1].bar);
 1164                         continue;
 1165                 }
 1166 
 1167                 ctlr = malloc(sizeof(Ctlr));
 1168                 ctlr->port = p->mem[1].bar & ~0x0F;
 1169                 ctlr->pcidev = p;
 1170                 ctlr->id = (p->did<<16)|p->vid;
 1171 
 1172                 ctlr->nic = mem;
 1173                 if(dp83820reset(ctlr)){
 1174                         free(ctlr);
 1175                         continue;
 1176                 }
 1177                 pcisetbme(p);
 1178 
 1179                 if(dp83820ctlrhead != nil)
 1180                         dp83820ctlrtail->next = ctlr;
 1181                 else
 1182                         dp83820ctlrhead = ctlr;
 1183                 dp83820ctlrtail = ctlr;
 1184         }
 1185 }
 1186 
 1187 static int
 1188 dp83820pnp(Ether* edev)
 1189 {
 1190         int i;
 1191         Ctlr *ctlr;
 1192         uchar ea[Eaddrlen];
 1193 
 1194         if(dp83820ctlrhead == nil)
 1195                 dp83820pci();
 1196 
 1197         /*
 1198          * Any adapter matches if no edev->port is supplied,
 1199          * otherwise the ports must match.
 1200          */
 1201         for(ctlr = dp83820ctlrhead; ctlr != nil; ctlr = ctlr->next){
 1202                 if(ctlr->active)
 1203                         continue;
 1204                 if(edev->port == 0 || edev->port == ctlr->port){
 1205                         ctlr->active = 1;
 1206                         break;
 1207                 }
 1208         }
 1209         if(ctlr == nil)
 1210                 return -1;
 1211 
 1212         edev->ctlr = ctlr;
 1213         edev->port = ctlr->port;
 1214         edev->irq = ctlr->pcidev->intl;
 1215         edev->tbdf = ctlr->pcidev->tbdf;
 1216         edev->mbps = 1000;
 1217 
 1218         /*
 1219          * Check if the adapter's station address is to be overridden.
 1220          * If not, read it from the EEPROM and set in ether->ea prior to
 1221          * loading the station address in the hardware.
 1222          */
 1223         memset(ea, 0, Eaddrlen);
 1224         if(memcmp(ea, edev->ea, Eaddrlen) == 0)
 1225                 for(i = 0; i < Eaddrlen/2; i++){
 1226                         edev->ea[2*i] = ctlr->eeprom[0x0C-i];
 1227                         edev->ea[2*i+1] = ctlr->eeprom[0x0C-i]>>8;
 1228                 }
 1229 
 1230         edev->attach = dp83820attach;
 1231         edev->transmit = dp83820transmit;
 1232         edev->interrupt = dp83820interrupt;
 1233         edev->ifstat = dp83820ifstat;
 1234 
 1235         edev->arg = edev;
 1236         edev->promiscuous = dp83820promiscuous;
 1237         edev->multicast = dp83820multicast;
 1238         edev->shutdown = dp83820shutdown;
 1239 
 1240         return 0;
 1241 }
 1242 
 1243 void
 1244 etherdp83820link(void)
 1245 {
 1246         addethercard("DP83820", dp83820pnp);
 1247 }

Cache object: 7dca016d93c318ef1f6751e7a90424e7


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.