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/ether82543gc.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  * Intel RS-82543GC Gigabit Ethernet Controller
    3  * as found on the Intel PRO/1000[FT] Server Adapter.
    4  * The older non-[FT] cards use the 82542 (LSI L2A1157) chip; no attempt
    5  * is made to handle the older chip although it should be possible.
    6  * The datasheet is not very clear about running on a big-endian system
    7  * and this driver assumes little-endian throughout.
    8  * To do:
    9  *      GMII/MII
   10  *      receive tuning
   11  *      transmit tuning
   12  */
   13 #include "u.h"
   14 #include "../port/lib.h"
   15 #include "mem.h"
   16 #include "dat.h"
   17 #include "fns.h"
   18 #include "io.h"
   19 #include "../port/error.h"
   20 #include "../port/netif.h"
   21 
   22 #include "etherif.h"
   23 
   24 enum {
   25         Ctrl            = 0x00000000,   /* Device Control */
   26         Status          = 0x00000008,   /* Device Status */
   27         Eecd            = 0x00000010,   /* EEPROM/Flash Control/Data */
   28         Ctrlext         = 0x00000018,   /* Extended Device Control */
   29         Mdic            = 0x00000020,   /* MDI Control */
   30         Fcal            = 0x00000028,   /* Flow Control Address Low */
   31         Fcah            = 0x0000002C,   /* Flow Control Address High */
   32         Fct             = 0x00000030,   /* Flow Control Type */
   33         Icr             = 0x000000C0,   /* Interrupt Cause Read */
   34         Ics             = 0x000000C8,   /* Interrupt Cause Set */
   35         Ims             = 0x000000D0,   /* Interrupt Mask Set/Read */
   36         Imc             = 0x000000D8,   /* Interrupt mask Clear */
   37         Rctl            = 0x00000100,   /* Receive Control */
   38         Fcttv           = 0x00000170,   /* Flow Control Transmit Timer Value */
   39         Txcw            = 0x00000178,   /* Transmit configuration word reg. */
   40         Rxcw            = 0x00000180,   /* Receive configuration word reg. */
   41         Tctl            = 0x00000400,   /* Transmit Control */
   42         Tipg            = 0x00000410,   /* Transmit IPG */
   43         Tbt             = 0x00000448,   /* Transmit Burst Timer */
   44         Ait             = 0x00000458,   /* Adaptive IFS Throttle */
   45         Fcrtl           = 0x00002160,   /* Flow Control RX Threshold Low */
   46         Fcrth           = 0x00002168,   /* Flow Control Rx Threshold High */
   47         Rdfh            = 0x00002410,   /* Receive data fifo head */
   48         Rdft            = 0x00002418,   /* Receive data fifo tail */
   49         Rdfhs           = 0x00002420,   /* Receive data fifo head saved */
   50         Rdfts           = 0x00002428,   /* Receive data fifo tail saved */
   51         Rdfpc           = 0x00002430,   /* Receive data fifo packet count */
   52         Rdbal           = 0x00002800,   /* Rdesc Base Address Low */
   53         Rdbah           = 0x00002804,   /* Rdesc Base Address High */
   54         Rdlen           = 0x00002808,   /* Receive Descriptor Length */
   55         Rdh             = 0x00002810,   /* Receive Descriptor Head */
   56         Rdt             = 0x00002818,   /* Receive Descriptor Tail */
   57         Rdtr            = 0x00002820,   /* Receive Descriptor Timer Ring */
   58         Rxdctl          = 0x00002828,   /* Receive Descriptor Control */
   59         Txdmac          = 0x00003000,   /* Transfer DMA Control */
   60         Ett             = 0x00003008,   /* Early Transmit Control */
   61         Tdfh            = 0x00003410,   /* Transmit data fifo head */
   62         Tdft            = 0x00003418,   /* Transmit data fifo tail */
   63         Tdfhs           = 0x00003420,   /* Transmit data Fifo Head saved */
   64         Tdfts           = 0x00003428,   /* Transmit data fifo tail saved */
   65         Tdfpc           = 0x00003430,   /* Trasnmit data Fifo packet count */
   66         Tdbal           = 0x00003800,   /* Tdesc Base Address Low */
   67         Tdbah           = 0x00003804,   /* Tdesc Base Address High */
   68         Tdlen           = 0x00003808,   /* Transmit Descriptor Length */
   69         Tdh             = 0x00003810,   /* Transmit Descriptor Head */
   70         Tdt             = 0x00003818,   /* Transmit Descriptor Tail */
   71         Tidv            = 0x00003820,   /* Transmit Interrupt Delay Value */
   72         Txdctl          = 0x00003828,   /* Transmit Descriptor Control */
   73 
   74         Statistics      = 0x00004000,   /* Start of Statistics Area */
   75         Gorcl           = 0x88/4,       /* Good Octets Received Count */
   76         Gotcl           = 0x90/4,       /* Good Octets Transmitted Count */
   77         Torl            = 0xC0/4,       /* Total Octets Received */
   78         Totl            = 0xC8/4,       /* Total Octets Transmitted */
   79         Nstatistics     = 64,
   80 
   81         Rxcsum          = 0x00005000,   /* Receive Checksum Control */
   82         Mta             = 0x00005200,   /* Multicast Table Array */
   83         Ral             = 0x00005400,   /* Receive Address Low */
   84         Rah             = 0x00005404,   /* Receive Address High */
   85 };
   86 
   87 enum {                                  /* Ctrl */
   88         Bem             = 0x00000002,   /* Big Endian Mode */
   89         Prior           = 0x00000004,   /* Priority on the PCI bus */
   90         Lrst            = 0x00000008,   /* Link Reset */
   91         Asde            = 0x00000020,   /* Auto-Speed Detection Enable */
   92         Slu             = 0x00000040,   /* Set Link Up */
   93         Ilos            = 0x00000080,   /* Invert Loss of Signal (LOS) */
   94         Frcspd          = 0x00000800,   /* Force Speed */
   95         Frcdplx         = 0x00001000,   /* Force Duplex */
   96         Swdpinslo       = 0x003C0000,   /* Software Defined Pins - lo nibble */
   97         Swdpin0         = 0x00040000,
   98         Swdpin1         = 0x00080000,
   99         Swdpin2         = 0x00100000,
  100         Swdpin3         = 0x00200000,
  101         Swdpiolo        = 0x03C00000,   /* Software Defined I/O Pins */
  102         Swdpio0         = 0x00400000,
  103         Swdpio1         = 0x00800000,
  104         Swdpio2         = 0x01000000,
  105         Swdpio3         = 0x02000000,
  106         Devrst          = 0x04000000,   /* Device Reset */
  107         Rfce            = 0x08000000,   /* Receive Flow Control Enable */
  108         Tfce            = 0x10000000,   /* Transmit Flow Control Enable */
  109         Vme             = 0x40000000,   /* VLAN Mode Enable */
  110 };
  111 
  112 enum {                                  /* Status */
  113         Lu              = 0x00000002,   /* Link Up */
  114         Tckok           = 0x00000004,   /* Transmit clock is running */
  115         Rbcok           = 0x00000008,   /* Receive clock is running */
  116         Txoff           = 0x00000010,   /* Transmission Paused */
  117         Tbimode         = 0x00000020,   /* TBI Mode Indication */
  118         SpeedMASK       = 0x000000C0,
  119         Speed10         = 0x00000000,   /* 10Mb/s */
  120         Speed100        = 0x00000040,   /* 100Mb/s */
  121         Speed1000       = 0x00000080,   /* 1000Mb/s */
  122         Mtxckok         = 0x00000400,   /* MTX clock is running */
  123         Pci66           = 0x00000800,   /* PCI Bus speed indication */
  124         Bus64           = 0x00001000,   /* PCI Bus width indication */
  125 };
  126 
  127 enum {                                  /* Ctrl and Status */
  128         Fd              = 0x00000001,   /* Full-Duplex */
  129         AsdvMASK        = 0x00000300,
  130         Asdv10          = 0x00000000,   /* 10Mb/s */
  131         Asdv100         = 0x00000100,   /* 100Mb/s */
  132         Asdv1000        = 0x00000200,   /* 1000Mb/s */
  133 };
  134 
  135 enum {                                  /* Eecd */
  136         Sk              = 0x00000001,   /* Clock input to the EEPROM */
  137         Cs              = 0x00000002,   /* Chip Select */
  138         Di              = 0x00000004,   /* Data Input to the EEPROM */
  139         Do              = 0x00000008,   /* Data Output from the EEPROM */
  140 };
  141 
  142 enum {                                  /* Ctrlext */
  143         Gpien           = 0x0000000F,   /* General Purpose Interrupt Enables */
  144         Swdpinshi       = 0x000000F0,   /* Software Defined Pins - hi nibble */
  145         Swdpiohi        = 0x00000F00,   /* Software Defined Pins - I or O */
  146         Asdchk          = 0x00001000,   /* ASD Check */
  147         Eerst           = 0x00002000,   /* EEPROM Reset */
  148         Ips             = 0x00004000,   /* Invert Power State */
  149         Spdbyps         = 0x00008000,   /* Speed Select Bypass */
  150 };
  151 
  152 enum {                                  /* EEPROM content offsets */
  153         Ea              = 0x00,         /* Ethernet Address */
  154         Cf              = 0x03,         /* Compatibility Field */
  155         Pba             = 0x08,         /* Printed Board Assembly number */
  156         Icw1            = 0x0A,         /* Initialization Control Word 1 */
  157         Sid             = 0x0B,         /* Subsystem ID */
  158         Svid            = 0x0C,         /* Subsystem Vendor ID */
  159         Did             = 0x0D,         /* Device ID */
  160         Vid             = 0x0E,         /* Vendor ID */
  161         Icw2            = 0x0F,         /* Initialization Control Word 2 */
  162 };
  163 
  164 enum {                                  /* Mdic */
  165         MDIdMASK        = 0x0000FFFF,   /* Data */
  166         MDIdSHIFT       = 0,
  167         MDIrMASK        = 0x001F0000,   /* PHY Register Address */
  168         MDIrSHIFT       = 16,
  169         MDIpMASK        = 0x03E00000,   /* PHY Address */
  170         MDIpSHIFT       = 21,
  171         MDIwop          = 0x04000000,   /* Write Operation */
  172         MDIrop          = 0x08000000,   /* Read Operation */
  173         MDIready        = 0x10000000,   /* End of Transaction */
  174         MDIie           = 0x20000000,   /* Interrupt Enable */
  175         MDIe            = 0x40000000,   /* Error */
  176 };
  177 
  178 enum {                                  /* Icr, Ics, Ims, Imc */
  179         Txdw            = 0x00000001,   /* Transmit Descriptor Written Back */
  180         Txqe            = 0x00000002,   /* Transmit Queue Empty */
  181         Lsc             = 0x00000004,   /* Link Status Change */
  182         Rxseq           = 0x00000008,   /* Receive Sequence Error */
  183         Rxdmt0          = 0x00000010,   /* Rdesc Minimum Threshold Reached */
  184         Rxo             = 0x00000040,   /* Receiver Overrun */
  185         Rxt0            = 0x00000080,   /* Receiver Timer Interrupt */
  186         Mdac            = 0x00000200,   /* MDIO Access Completed */
  187         Rxcfg           = 0x00000400,   /* Receiving /C/ ordered sets */
  188         Gpi0            = 0x00000800,   /* General Purpose Interrupts */
  189         Gpi1            = 0x00001000,
  190         Gpi2            = 0x00002000,
  191         Gpi3            = 0x00004000,
  192 };
  193 
  194 enum {                                  /* Txcw */
  195         Ane             = 0x80000000,   /* Autonegotiate enable */
  196         Np              = 0x00008000,   /* Next Page */
  197         As              = 0x00000100,   /* Asymmetric Flow control desired */
  198         Ps              = 0x00000080,   /* Pause supported */
  199         Hd              = 0x00000040,   /* Half duplex supported */
  200         TxcwFd          = 0x00000020,   /* Full Duplex supported */
  201 };
  202 
  203 enum {                                  /* Rxcw */
  204         Rxword          = 0x0000FFFF,   /* Data from auto-negotiation process */
  205         Rxnocarrier     = 0x04000000,   /* Carrier Sense indication */
  206         Rxinvalid       = 0x08000000,   /* Invalid Symbol during configuration */
  207         Rxchange        = 0x10000000,   /* Change to the Rxword indication */
  208         Rxconfig        = 0x20000000,   /* /C/ order set reception indication */
  209         Rxsync          = 0x40000000,   /* Lost bit synchronization indication */
  210         Anc             = 0x80000000,   /* Auto Negotiation Complete */
  211 };
  212 
  213 enum {                                  /* Rctl */
  214         Rrst            = 0x00000001,   /* Receiver Software Reset */
  215         Ren             = 0x00000002,   /* Receiver Enable */
  216         Sbp             = 0x00000004,   /* Store Bad Packets */
  217         Upe             = 0x00000008,   /* Unicast Promiscuous Enable */
  218         Mpe             = 0x00000010,   /* Multicast Promiscuous Enable */
  219         Lpe             = 0x00000020,   /* Long Packet Reception Enable */
  220         LbmMASK         = 0x000000C0,   /* Loopback Mode */
  221         LbmOFF          = 0x00000000,   /* No Loopback */
  222         LbmTBI          = 0x00000040,   /* TBI Loopback */
  223         LbmMII          = 0x00000080,   /* GMII/MII Loopback */
  224         LbmXCVR         = 0x000000C0,   /* Transceiver Loopback */
  225         RdtmsMASK       = 0x00000300,   /* Rdesc Minimum Threshold Size */
  226         RdtmsHALF       = 0x00000000,   /* Threshold is 1/2 Rdlen */
  227         RdtmsQUARTER    = 0x00000100,   /* Threshold is 1/4 Rdlen */
  228         RdtmsEIGHTH     = 0x00000200,   /* Threshold is 1/8 Rdlen */
  229         MoMASK          = 0x00003000,   /* Multicast Offset */
  230         Bam             = 0x00008000,   /* Broadcast Accept Mode */
  231         BsizeMASK       = 0x00030000,   /* Receive Buffer Size */
  232         Bsize2048       = 0x00000000,   /* Bsex = 0 */
  233         Bsize1024       = 0x00010000,   /* Bsex = 0 */
  234         Bsize512        = 0x00020000,   /* Bsex = 0 */
  235         Bsize256        = 0x00030000,   /* Bsex = 0 */
  236         Bsize16384      = 0x00010000,   /* Bsex = 1 */
  237         Vfe             = 0x00040000,   /* VLAN Filter Enable */
  238         Cfien           = 0x00080000,   /* Canonical Form Indicator Enable */
  239         Cfi             = 0x00100000,   /* Canonical Form Indicator value */
  240         Dpf             = 0x00400000,   /* Discard Pause Frames */
  241         Pmcf            = 0x00800000,   /* Pass MAC Control Frames */
  242         Bsex            = 0x02000000,   /* Buffer Size Extension */
  243         Secrc           = 0x04000000,   /* Strip CRC from incoming packet */
  244 };
  245 
  246 enum {                                  /* Tctl */
  247         Trst            = 0x00000001,   /* Transmitter Software Reset */
  248         Ten             = 0x00000002,   /* Transmit Enable */
  249         Psp             = 0x00000008,   /* Pad Short Packets */
  250         CtMASK          = 0x00000FF0,   /* Collision Threshold */
  251         CtSHIFT         = 4,
  252         ColdMASK        = 0x003FF000,   /* Collision Distance */
  253         ColdSHIFT       = 12,
  254         Swxoff          = 0x00400000,   /* Sofware XOFF Transmission */
  255         Pbe             = 0x00800000,   /* Packet Burst Enable */
  256         Rtlc            = 0x01000000,   /* Re-transmit on Late Collision */
  257         Nrtu            = 0x02000000,   /* No Re-transmit on Underrrun */
  258 };
  259 
  260 enum {                                  /* [RT]xdctl */
  261         PthreshMASK     = 0x0000003F,   /* Prefetch Threshold */
  262         PthreshSHIFT    = 0,
  263         HthreshMASK     = 0x00003F00,   /* Host Threshold */
  264         HthreshSHIFT    = 8,
  265         WthreshMASK     = 0x003F0000,   /* Writeback Threshold */
  266         WthreshSHIFT    = 16,
  267         Gran            = 0x00000000,   /* Granularity */
  268         RxGran          = 0x01000000,   /* Granularity */
  269 };
  270 
  271 enum {                                  /* Rxcsum */
  272         PcssMASK        = 0x000000FF,   /* Packet Checksum Start */
  273         PcssSHIFT       = 0,
  274         Ipofl           = 0x00000100,   /* IP Checksum Off-load Enable */
  275         Tuofl           = 0x00000200,   /* TCP/UDP Checksum Off-load Enable */
  276 };
  277 
  278 enum {                                  /* Receive Delay Timer Ring */
  279         Fpd             = 0x80000000,   /* Flush partial Descriptor Block */
  280 };
  281 
  282 typedef struct Rdesc {                  /* Receive Descriptor */
  283         uint    addr[2];
  284         ushort  length;
  285         ushort  checksum;
  286         uchar   status;
  287         uchar   errors;
  288         ushort  special;
  289 } Rdesc;
  290 
  291 enum {                                  /* Rdesc status */
  292         Rdd             = 0x01,         /* Descriptor Done */
  293         Reop            = 0x02,         /* End of Packet */
  294         Ixsm            = 0x04,         /* Ignore Checksum Indication */
  295         Vp              = 0x08,         /* Packet is 802.1Q (matched VET) */
  296         Tcpcs           = 0x20,         /* TCP Checksum Calculated on Packet */
  297         Ipcs            = 0x40,         /* IP Checksum Calculated on Packet */
  298         Pif             = 0x80,         /* Passed in-exact filter */
  299 };
  300 
  301 enum {                                  /* Rdesc errors */
  302         Ce              = 0x01,         /* CRC Error or Alignment Error */
  303         Se              = 0x02,         /* Symbol Error */
  304         Seq             = 0x04,         /* Sequence Error */
  305         Cxe             = 0x10,         /* Carrier Extension Error */
  306         Tcpe            = 0x20,         /* TCP/UDP Checksum Error */
  307         Ipe             = 0x40,         /* IP Checksum Error */
  308         Rxe             = 0x80,         /* RX Data Error */
  309 };
  310 
  311 typedef struct Tdesc {                  /* Legacy+Normal Transmit Descriptor */
  312         uint    addr[2];
  313         uint    control;                /* varies with descriptor type */
  314         uint    status;                 /* varies with descriptor type */
  315 } Tdesc;
  316 
  317 enum {                                  /* Tdesc control */
  318         CsoMASK         = 0x00000F00,   /* Checksum Offset */
  319         CsoSHIFT        = 16,
  320         Teop            = 0x01000000,   /* End of Packet */
  321         Ifcs            = 0x02000000,   /* Insert FCS */
  322         Ic              = 0x04000000,   /* Insert Checksum (Dext == 0) */
  323         Tse             = 0x04000000,   /* TCP Segmentaion Enable (Dext == 1) */
  324         Rs              = 0x08000000,   /* Report Status */
  325         Rps             = 0x10000000,   /* Report Status Sent */
  326         Dext            = 0x20000000,   /* Extension (!legacy) */
  327         Vle             = 0x40000000,   /* VLAN Packet Enable */
  328         Ide             = 0x80000000,   /* Interrupt Delay Enable */
  329 };
  330 
  331 enum {                                  /* Tdesc status */
  332         Tdd             = 0x00000001,   /* Descriptor Done */
  333         Ec              = 0x00000002,   /* Excess Collisions */
  334         Lc              = 0x00000004,   /* Late Collision */
  335         Tu              = 0x00000008,   /* Transmit Underrun */
  336         CssMASK         = 0x0000FF00,   /* Checksum Start Field */
  337         CssSHIFT        = 8,
  338 };
  339 
  340 enum {
  341         Nrdesc          = 256,          /* multiple of 8 */
  342         Ntdesc          = 256,          /* multiple of 8 */
  343         Nblocks         = 4098,         /* total number of blocks to use */
  344 
  345         SBLOCKSIZE      = 2048,
  346         JBLOCKSIZE      = 16384,
  347 
  348         NORMAL          = 1,
  349         JUMBO           = 2,
  350 };
  351 
  352 typedef struct Ctlr Ctlr;
  353 typedef struct Ctlr {
  354         int     port;
  355         Pcidev* pcidev;
  356         Ctlr*   next;
  357         int     active;
  358         int     started;
  359         int     id;
  360         ushort  eeprom[0x40];
  361 
  362         int*    nic;
  363         int     im;                     /* interrupt mask */
  364 
  365         Lock    slock;
  366         uint    statistics[Nstatistics];
  367 
  368         Lock    rdlock;
  369         Rdesc*  rdba;                   /* receive descriptor base address */
  370         Block*  rb[Nrdesc];             /* receive buffers */
  371         int     rdh;                    /* receive descriptor head */
  372         int     rdt;                    /* receive descriptor tail */
  373         Block** freehead;               /* points to long or short head */
  374 
  375         Lock    tdlock;
  376         Tdesc*  tdba;                   /* transmit descriptor base address */
  377         Block*  tb[Ntdesc];             /* transmit buffers */
  378         int     tdh;                    /* transmit descriptor head */
  379         int     tdt;                    /* transmit descriptor tail */
  380         int     txstalled;              /* count of times unable to send */
  381 
  382         int     txcw;
  383         int     fcrtl;
  384         int     fcrth;
  385 
  386         ulong   multimask[128];         /* bit mask for multicast addresses */
  387 } Ctlr;
  388 
  389 static Ctlr* gc82543ctlrhead;
  390 static Ctlr* gc82543ctlrtail;
  391 
  392 static Lock freelistlock;
  393 static Block* freeShortHead;
  394 static Block* freeJumboHead;
  395 
  396 #define csr32r(c, r)    (*((c)->nic+((r)/4)))
  397 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
  398 
  399 static void gc82543watchdog(void* arg);
  400 
  401 static void
  402 gc82543attach(Ether* edev)
  403 {
  404         int ctl;
  405         Ctlr *ctlr;
  406         char name[KNAMELEN];
  407 
  408         /*
  409          * To do here:
  410          *      one-time stuff;
  411          *              adjust queue length depending on speed;
  412          *              flow control.
  413          *      more needed here...
  414          */
  415         ctlr = edev->ctlr;
  416         lock(&ctlr->slock);
  417         if(ctlr->started == 0){
  418                 ctlr->started = 1;
  419                 snprint(name, KNAMELEN, "#l%d82543", edev->ctlrno);
  420                 kproc(name, gc82543watchdog, edev);
  421         }
  422         unlock(&ctlr->slock);
  423 
  424         ctl = csr32r(ctlr, Rctl)|Ren;
  425         csr32w(ctlr, Rctl, ctl);
  426         ctl = csr32r(ctlr, Tctl)|Ten;
  427         csr32w(ctlr, Tctl, ctl);
  428 
  429         csr32w(ctlr, Ims, ctlr->im);
  430 }
  431 
  432 static char* statistics[Nstatistics] = {
  433         "CRC Error",
  434         "Alignment Error",
  435         "Symbol Error",
  436         "RX Error",
  437         "Missed Packets",
  438         "Single Collision",
  439         "Excessive Collisions",
  440         "Multiple Collision",
  441         "Late Collisions",
  442         nil,
  443         "Collision",
  444         "Transmit Underrun",
  445         "Defer",
  446         "Transmit - No CRS",
  447         "Sequence Error",
  448         "Carrier Extension Error",
  449         "Receive Error Length",
  450         nil,
  451         "XON Received",
  452         "XON Transmitted",
  453         "XOFF Received",
  454         "XOFF Transmitted",
  455         "FC Received Unsupported",
  456         "Packets Received (64 Bytes)",
  457         "Packets Received (65-127 Bytes)",
  458         "Packets Received (128-255 Bytes)",
  459         "Packets Received (256-511 Bytes)",
  460         "Packets Received (512-1023 Bytes)",
  461         "Packets Received (1024-1522 Bytes)",
  462         "Good Packets Received",
  463         "Broadcast Packets Received",
  464         "Multicast Packets Received",
  465         "Good Packets Transmitted",
  466         nil,
  467         "Good Octets Received",
  468         nil,
  469         "Good Octets Transmitted",
  470         nil,
  471         nil,
  472         nil,
  473         "Receive No Buffers",
  474         "Receive Undersize",
  475         "Receive Fragment",
  476         "Receive Oversize",
  477         "Receive Jabber",
  478         nil,
  479         nil,
  480         nil,
  481         "Total Octets Received",
  482         nil,
  483         "Total Octets Transmitted",
  484         nil,
  485         "Total Packets Received",
  486         "Total Packets Transmitted",
  487         "Packets Transmitted (64 Bytes)",
  488         "Packets Transmitted (65-127 Bytes)",
  489         "Packets Transmitted (128-255 Bytes)",
  490         "Packets Transmitted (256-511 Bytes)",
  491         "Packets Transmitted (512-1023 Bytes)",
  492         "Packets Transmitted (1024-1522 Bytes)",
  493         "Multicast Packets Transmitted",
  494         "Broadcast Packets Transmitted",
  495         "TCP Segmentation Context Transmitted",
  496         "TCP Segmentation Context Fail",
  497 };
  498 
  499 static long
  500 gc82543ifstat(Ether* edev, void* a, long n, ulong offset)
  501 {
  502         Ctlr *ctlr;
  503         char *p, *s;
  504         int i, l, r;
  505         uvlong tuvl, ruvl;
  506 
  507         ctlr = edev->ctlr;
  508         lock(&ctlr->slock);
  509         p = malloc(READSTR);
  510         l = 0;
  511         for(i = 0; i < Nstatistics; i++){
  512                 r = csr32r(ctlr, Statistics+i*4);
  513                 if((s = statistics[i]) == nil)
  514                         continue;
  515                 switch(i){
  516                 case Gorcl:
  517                 case Gotcl:
  518                 case Torl:
  519                 case Totl:
  520                         ruvl = r;
  521                         ruvl += ((uvlong)csr32r(ctlr, Statistics+(i+1)*4))<<32;
  522                         tuvl = ruvl;
  523                         tuvl += ctlr->statistics[i];
  524                         tuvl += ((uvlong)ctlr->statistics[i+1])<<32;
  525                         if(tuvl == 0)
  526                                 continue;
  527                         ctlr->statistics[i] = tuvl;
  528                         ctlr->statistics[i+1] = tuvl>>32;
  529                         l += snprint(p+l, READSTR-l, "%s: %llud %llud\n",
  530                                 s, tuvl, ruvl);
  531                         i++;
  532                         break;
  533 
  534                 default:
  535                         ctlr->statistics[i] += r;
  536                         if(ctlr->statistics[i] == 0)
  537                                 continue;
  538                         l += snprint(p+l, READSTR-l, "%s: %ud %ud\n",
  539                                 s, ctlr->statistics[i], r);
  540                         break;
  541                 }
  542         }
  543 
  544         l += snprint(p+l, READSTR-l, "eeprom:");
  545         for(i = 0; i < 0x40; i++){
  546                 if(i && ((i & 0x07) == 0))
  547                         l += snprint(p+l, READSTR-l, "\n       ");
  548                 l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->eeprom[i]);
  549         }
  550 
  551         snprint(p+l, READSTR-l, "\ntxstalled %d\n", ctlr->txstalled);
  552         n = readstr(offset, a, n, p);
  553         free(p);
  554         unlock(&ctlr->slock);
  555 
  556         return n;
  557 }
  558 
  559 static void
  560 gc82543promiscuous(void* arg, int on)
  561 {
  562         int rctl;
  563         Ctlr *ctlr;
  564         Ether *edev;
  565 
  566         edev = arg;
  567         ctlr = edev->ctlr;
  568 
  569         rctl = csr32r(ctlr, Rctl);
  570         rctl &= ~MoMASK;                /* make sure we're using bits 47:36 */
  571         if(on)
  572                 rctl |= Upe|Mpe;
  573         else
  574                 rctl &= ~(Upe|Mpe);
  575         csr32w(ctlr, Rctl, rctl);
  576 }
  577 
  578 static void
  579 gc82543multicast(void* arg, uchar* addr, int on)
  580 {
  581         int bit, x;
  582         Ctlr *ctlr;
  583         Ether *edev;
  584 
  585         edev = arg;
  586         ctlr = edev->ctlr;
  587         x = addr[5]>>1;
  588         bit = ((addr[5] & 1)<<4)|(addr[4]>>4);
  589         if(on)
  590                 ctlr->multimask[x] |= 1<<bit;
  591         else
  592                 ctlr->multimask[x] &= ~(1<<bit);
  593         
  594         csr32w(ctlr, Mta+x*4, ctlr->multimask[x]);
  595 }
  596 
  597 static long
  598 gc82543ctl(Ether* edev, void* buf, long n)
  599 {
  600         Cmdbuf *cb;
  601         Ctlr *ctlr;
  602         int ctrl, i, r;
  603 
  604         ctlr = edev->ctlr;
  605         if(ctlr == nil)
  606                 error(Enonexist);
  607 
  608         lock(&ctlr->slock);
  609         r = 0;
  610         cb = parsecmd(buf, n);
  611         if(cb->nf < 2)
  612                 r = -1;
  613         else if(cistrcmp(cb->f[0], "auto") == 0){
  614                 ctrl = csr32r(ctlr, Ctrl);
  615                 if(cistrcmp(cb->f[1], "off") == 0){
  616                         csr32w(ctlr, Txcw, ctlr->txcw & ~Ane);
  617                         ctrl |= (Slu|Fd);
  618                         if(ctlr->txcw & As)
  619                                 ctrl |= Rfce;
  620                         if(ctlr->txcw & Ps)
  621                                 ctrl |= Tfce;
  622                         csr32w(ctlr, Ctrl, ctrl);
  623                 }
  624                 else if(cistrcmp(cb->f[1], "on") == 0){
  625                         csr32w(ctlr, Txcw, ctlr->txcw);
  626                         ctrl &= ~(Slu|Fd);
  627                         csr32w(ctlr, Ctrl, ctrl);
  628                 }
  629                 else
  630                         r = -1;
  631         }
  632         else if(cistrcmp(cb->f[0], "clear") == 0){
  633                 if(cistrcmp(cb->f[1], "stats") == 0){
  634                         for(i = 0; i < Nstatistics; i++)
  635                                 ctlr->statistics[i] = 0;
  636                 }
  637                 else
  638                         r = -1;
  639         }
  640         else
  641                 r = -1;
  642         unlock(&ctlr->slock);
  643 
  644         free(cb);
  645         return (r == 0) ? n : r;
  646 }
  647 
  648 static void
  649 gc82543txinit(Ctlr* ctlr)
  650 {
  651         int i;
  652         int tdsize;
  653         Block *bp, **bpp;
  654 
  655         tdsize = ROUND(Ntdesc*sizeof(Tdesc), 4096);
  656 
  657         if(ctlr->tdba == nil)
  658                 ctlr->tdba = xspanalloc(tdsize, 32, 0);
  659 
  660         for(i = 0; i < Ntdesc; i++){
  661                 bpp = &ctlr->tb[i];
  662                 bp = *bpp;
  663                 if(bp != nil){
  664                         *bpp = nil;
  665                         freeb(bp);
  666                 }
  667                 memset(&ctlr->tdba[i], 0, sizeof(Tdesc));
  668         }
  669 
  670         csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba));
  671         csr32w(ctlr, Tdbah, 0);
  672         csr32w(ctlr, Tdlen, Ntdesc*sizeof(Tdesc));
  673 
  674         /*
  675          * set the ring head and tail pointers.
  676          */
  677         ctlr->tdh = 0;
  678         csr32w(ctlr, Tdh, ctlr->tdh);
  679         ctlr->tdt = 0;
  680         csr32w(ctlr, Tdt, ctlr->tdt);
  681 
  682         csr32w(ctlr, Tipg, (6<<20)|(8<<10)|6);
  683         csr32w(ctlr, Tidv, 128);
  684         csr32w(ctlr, Ait, 0);
  685         csr32w(ctlr, Txdmac, 0);
  686         csr32w(ctlr, Txdctl, Gran|(4<<WthreshSHIFT)|(1<<HthreshSHIFT)|16);
  687         csr32w(ctlr, Tctl, (0x0F<<CtSHIFT)|Psp|(6<<ColdSHIFT));
  688 
  689         ctlr->im |= Txdw;
  690 }
  691 
  692 static void
  693 gc82543transmit(Ether* edev)
  694 {
  695         Block *bp, **bpp;
  696         Ctlr *ctlr;
  697         Tdesc *tdesc;
  698         int tdh, tdt, s;
  699 
  700         ctlr = edev->ctlr;
  701 
  702         ilock(&ctlr->tdlock);
  703         tdh = ctlr->tdh;
  704         for(;;){
  705                 /*
  706                  * Free any completed packets
  707                  */
  708                 tdesc = &ctlr->tdba[tdh];
  709                 if(!(tdesc->status & Tdd))
  710                         break;
  711                 memset(tdesc, 0, sizeof(Tdesc));
  712                 bpp = &ctlr->tb[tdh];
  713                 bp = *bpp;
  714                 if(bp != nil){
  715                         *bpp = nil;
  716                         freeb(bp);
  717                 }
  718                 tdh = NEXT(tdh, Ntdesc);
  719         }
  720         ctlr->tdh = tdh;
  721         s = csr32r(ctlr, Status);
  722 
  723         /*
  724          * Try to fill the ring back up
  725          * but only if link is up and transmission isn't paused.
  726          */
  727         if((s & (Txoff|Lu)) == Lu){
  728                 tdt = ctlr->tdt;
  729                 while(NEXT(tdt, Ntdesc) != tdh){
  730                         if((bp = qget(edev->oq)) == nil)
  731                                 break;
  732 
  733                         tdesc = &ctlr->tdba[tdt];
  734                         tdesc->addr[0] = PCIWADDR(bp->rp);
  735                         tdesc->control = Ide|Rs|Ifcs|Teop|BLEN(bp);
  736                         ctlr->tb[tdt] = bp;
  737                         tdt = NEXT(tdt, Ntdesc);
  738                 }
  739 
  740                 if(tdt != ctlr->tdt){
  741                         ctlr->tdt = tdt;
  742                         csr32w(ctlr, Tdt, tdt);
  743                 }
  744         }
  745         else
  746                 ctlr->txstalled++;
  747 
  748         iunlock(&ctlr->tdlock);
  749 }
  750 
  751 static Block *
  752 gc82543allocb(Ctlr* ctlr)
  753 {
  754         Block *bp;
  755 
  756         ilock(&freelistlock);
  757         if((bp = *(ctlr->freehead)) != nil){
  758                 *(ctlr->freehead) = bp->next;
  759                 bp->next = nil;
  760                 _xinc(&bp->ref);        /* prevent bp from being freed */
  761         }
  762         iunlock(&freelistlock);
  763         return bp;
  764 }
  765 
  766 static void
  767 gc82543replenish(Ctlr* ctlr)
  768 {
  769         int rdt;
  770         Block *bp;
  771         Rdesc *rdesc;
  772 
  773         ilock(&ctlr->rdlock);
  774         rdt = ctlr->rdt;
  775         while(NEXT(rdt, Nrdesc) != ctlr->rdh){
  776                 rdesc = &ctlr->rdba[rdt];
  777                 if(ctlr->rb[rdt] == nil){
  778                         bp = gc82543allocb(ctlr);
  779                         if(bp == nil){
  780                                 iprint("no available buffers\n");
  781                                 break;
  782                         }
  783                         ctlr->rb[rdt] = bp;
  784                         rdesc->addr[0] = PCIWADDR(bp->rp);
  785                         rdesc->addr[1] = 0;
  786                 }
  787                 coherence();
  788                 rdesc->status = 0;
  789                 rdt = NEXT(rdt, Nrdesc);
  790         }
  791         ctlr->rdt = rdt;
  792         csr32w(ctlr, Rdt, rdt);
  793         iunlock(&ctlr->rdlock);
  794 }
  795 
  796 static void
  797 gc82543rxinit(Ctlr* ctlr)
  798 {
  799         int rdsize, i;
  800 
  801         csr32w(ctlr, Rctl, Dpf|Bsize2048|Bam|RdtmsHALF);
  802 
  803         /*
  804          * Allocate the descriptor ring and load its
  805          * address and length into the NIC.
  806          */
  807         rdsize = ROUND(Nrdesc*sizeof(Rdesc), 4096);
  808         if(ctlr->rdba == nil)
  809                 ctlr->rdba = xspanalloc(rdsize, 32, 0);
  810         memset(ctlr->rdba, 0, rdsize);
  811 
  812         ctlr->rdh = 0;
  813         ctlr->rdt = 0;
  814 
  815         csr32w(ctlr, Rdtr, Fpd|64);
  816         csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba));
  817         csr32w(ctlr, Rdbah, 0);
  818         csr32w(ctlr, Rdlen, Nrdesc*sizeof(Rdesc));
  819         csr32w(ctlr, Rdh, 0);
  820         csr32w(ctlr, Rdt, 0);
  821         for(i = 0; i < Nrdesc; i++){
  822                 if(ctlr->rb[i] != nil){
  823                         freeb(ctlr->rb[i]);
  824                         ctlr->rb[i] = nil;
  825                 }
  826         }
  827         gc82543replenish(ctlr);
  828 
  829         csr32w(ctlr, Rxdctl, RxGran|(8<<WthreshSHIFT)|(4<<HthreshSHIFT)|1);
  830         ctlr->im |= Rxt0|Rxo|Rxdmt0|Rxseq;
  831 }
  832 
  833 static void
  834 gc82543recv(Ether* edev, int icr)
  835 {
  836         Block *bp;
  837         Ctlr *ctlr;
  838         Rdesc *rdesc;
  839         int rdh;
  840 
  841         ctlr = edev->ctlr;
  842 
  843         rdh = ctlr->rdh;
  844         for(;;){
  845                 rdesc = &ctlr->rdba[rdh];
  846 
  847                 if(!(rdesc->status & Rdd))
  848                         break;
  849 
  850                 if((rdesc->status & Reop) && rdesc->errors == 0){
  851                         bp = ctlr->rb[rdh];
  852                         ctlr->rb[rdh] = nil;
  853                         bp->wp += rdesc->length;
  854                         bp->next = nil;
  855                         etheriq(edev, bp, 1);
  856                 }
  857 
  858                 if(ctlr->rb[rdh] != nil){
  859                         /* either non eop packet, or error */
  860                         freeb(ctlr->rb[rdh]);
  861                         ctlr->rb[rdh] = nil;
  862                 }
  863                 memset(rdesc, 0, sizeof(Rdesc));
  864                 coherence();
  865                 rdh = NEXT(rdh, Nrdesc);
  866         }
  867         ctlr->rdh = rdh;
  868 
  869         if(icr & Rxdmt0)
  870                 gc82543replenish(ctlr);
  871 }
  872 
  873 static void
  874 freegc82543short(Block *bp)
  875 {
  876         ilock(&freelistlock);
  877         /* reset read/write pointer to proper positions */
  878         bp->rp = bp->lim - ROUND(SBLOCKSIZE, BLOCKALIGN);
  879         bp->wp = bp->rp;
  880         bp->next = freeShortHead;
  881         freeShortHead = bp;
  882         iunlock(&freelistlock);
  883 }
  884 
  885 static void
  886 freegc82532jumbo(Block *bp)
  887 {
  888         ilock(&freelistlock);
  889         /* reset read/write pointer to proper positions */
  890         bp->rp = bp->lim - ROUND(JBLOCKSIZE, BLOCKALIGN);
  891         bp->wp = bp->rp;
  892         bp->next = freeJumboHead;
  893         freeJumboHead = bp;
  894         iunlock(&freelistlock);
  895 }
  896 
  897 static void
  898 linkintr(Ctlr* ctlr)
  899 {
  900         int ctrl;
  901 
  902         ctrl = csr32r(ctlr, Ctrl);
  903 
  904         if((ctrl & Swdpin1) ||
  905           ((csr32r(ctlr, Rxcw) & Rxconfig) && !(csr32r(ctlr, Txcw) & Ane))){
  906                 csr32w(ctlr, Txcw, ctlr->txcw);
  907                 ctrl &= ~(Slu|Fd|Frcdplx);
  908                 csr32w(ctlr, Ctrl, ctrl);
  909         }
  910 }
  911 
  912 static void
  913 gc82543interrupt(Ureg*, void* arg)
  914 {
  915         Ctlr *ctlr;
  916         Ether *edev;
  917         int icr;
  918 
  919         edev = arg;
  920         ctlr = edev->ctlr;
  921 
  922         while((icr = csr32r(ctlr, Icr) & ctlr->im) != 0){
  923                 /*
  924                  * Link status changed.
  925                  */
  926                 if(icr & (Lsc|Rxseq))
  927                         linkintr(ctlr);
  928 
  929                 /*
  930                  * Process recv buffers.
  931                  */
  932                 gc82543recv(edev, icr);
  933 
  934                 /*
  935                  * Refill transmit ring and free packets.
  936                  */
  937                 gc82543transmit(edev);
  938         }
  939 }
  940 
  941 static int
  942 gc82543init(Ether* edev)
  943 {
  944         int csr, i;
  945         Block *bp;
  946         Ctlr *ctlr;
  947 
  948         ctlr = edev->ctlr;
  949 
  950         /*
  951          * Allocate private buffer pool to use for receiving packets.
  952          */
  953         ilock(&freelistlock);
  954         if (ctlr->freehead == nil){
  955                 for(i = 0; i < Nblocks; i++){
  956                         bp = iallocb(SBLOCKSIZE);
  957                         if(bp != nil){
  958                                 bp->next = freeShortHead;
  959                                 bp->free = freegc82543short;
  960                                 freeShortHead = bp;
  961                         }
  962                         else{
  963                                 print("82543gc: no memory\n");
  964                                 break;
  965                         }
  966                 }
  967                 ctlr->freehead = &freeShortHead;
  968         }
  969         iunlock(&freelistlock);
  970 
  971         /*
  972          * Set up the receive addresses.
  973          * There are 16 addresses. The first should be the MAC address.
  974          * The others are cleared and not marked valid (MS bit of Rah).
  975          */
  976         csr = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
  977         csr32w(ctlr, Ral, csr);
  978         csr = 0x80000000|(edev->ea[5]<<8)|edev->ea[4];
  979         csr32w(ctlr, Rah, csr);
  980         for(i = 1; i < 16; i++){
  981                 csr32w(ctlr, Ral+i*8, 0);
  982                 csr32w(ctlr, Rah+i*8, 0);
  983         }
  984 
  985         /*
  986          * Clear the Multicast Table Array.
  987          * It's a 4096 bit vector accessed as 128 32-bit registers.
  988          */
  989         for(i = 0; i < 128; i++)
  990                 csr32w(ctlr, Mta+i*4, 0);
  991 
  992         gc82543txinit(ctlr);
  993         gc82543rxinit(ctlr);
  994 
  995         return 0;
  996 }
  997 
  998 static int
  999 at93c46io(Ctlr* ctlr, char* op, int data)
 1000 {
 1001         char *lp, *p;
 1002         int i, loop, eecd, r;
 1003 
 1004         eecd = csr32r(ctlr, Eecd);
 1005 
 1006         r = 0;
 1007         loop = -1;
 1008         lp = nil;
 1009         for(p = op; *p != '\0'; p++){
 1010                 switch(*p){
 1011                 default:
 1012                         return -1;
 1013                 case ' ':
 1014                         continue;
 1015                 case ':':                       /* start of loop */
 1016                         if(lp != nil){
 1017                                 if(p != (lp+1) || loop != 7)
 1018                                         return -1;
 1019                                 lp = p;
 1020                                 loop = 15;
 1021                                 continue;
 1022                         }
 1023                         lp = p;
 1024                         loop = 7;
 1025                         continue;
 1026                 case ';':                       /* end of loop */
 1027                         if(lp == nil)
 1028                                 return -1;
 1029                         loop--;
 1030                         if(loop >= 0)
 1031                                 p = lp;
 1032                         else
 1033                                 lp = nil;
 1034                         continue;
 1035                 case 'C':                       /* assert clock */
 1036                         eecd |= Sk;
 1037                         break;
 1038                 case 'c':                       /* deassert clock */
 1039                         eecd &= ~Sk;
 1040                         break;
 1041                 case 'D':                       /* next bit in 'data' byte */
 1042                         if(loop < 0)
 1043                                 return -1;
 1044                         if(data & (1<<loop))
 1045                                 eecd |= Di;
 1046                         else
 1047                                 eecd &= ~Di;
 1048                         break;
 1049                 case 'O':                       /* collect data output */
 1050                         i = (csr32r(ctlr, Eecd) & Do) != 0;
 1051                         if(loop >= 0)
 1052                                 r |= (i<<loop);
 1053                         else
 1054                                 r = i;
 1055                         continue;
 1056                 case 'I':                       /* assert data input */
 1057                         eecd |= Di;
 1058                         break;
 1059                 case 'i':                       /* deassert data input */
 1060                         eecd &= ~Di;
 1061                         break;
 1062                 case 'S':                       /* enable chip select */
 1063                         eecd |= Cs;
 1064                         break;
 1065                 case 's':                       /* disable chip select */
 1066                         eecd &= ~Cs;
 1067                         break;
 1068                 }
 1069                 csr32w(ctlr, Eecd, eecd);
 1070                 microdelay(1);
 1071         }
 1072         if(loop >= 0)
 1073                 return -1;
 1074         return r;
 1075 }
 1076 
 1077 static int
 1078 at93c46r(Ctlr* ctlr)
 1079 {
 1080         ushort sum;
 1081         int addr, data;
 1082 
 1083         sum = 0;
 1084         for(addr = 0; addr < 0x40; addr++){
 1085                 /*
 1086                  * Read a word at address 'addr' from the Atmel AT93C46
 1087                  * 3-Wire Serial EEPROM or compatible. The EEPROM access is
 1088                  * controlled by 4 bits in Eecd. See the AT93C46 datasheet
 1089                  * for protocol details.
 1090                  */
 1091                 if(at93c46io(ctlr, "S ICc :DCc;", (0x02<<6)|addr) != 0)
 1092                         break;
 1093                 data = at93c46io(ctlr, "::COc;", 0);
 1094                 at93c46io(ctlr, "sic", 0);
 1095                 ctlr->eeprom[addr] = data;
 1096                 sum += data;
 1097         }
 1098 
 1099         return sum;
 1100 }
 1101 
 1102 static void
 1103 gc82543detach(Ctlr* ctlr)
 1104 {
 1105         /*
 1106          * Perform a device reset to get the chip back to the
 1107          * power-on state, followed by an EEPROM reset to read
 1108          * the defaults for some internal registers.
 1109          */
 1110         csr32w(ctlr, Imc, ~0);
 1111         csr32w(ctlr, Rctl, 0);
 1112         csr32w(ctlr, Tctl, 0);
 1113 
 1114         delay(10);
 1115 
 1116         csr32w(ctlr, Ctrl, Devrst);
 1117         while(csr32r(ctlr, Ctrl) & Devrst)
 1118                 ;
 1119 
 1120         csr32w(ctlr, Ctrlext, Eerst);
 1121         while(csr32r(ctlr, Ctrlext) & Eerst)
 1122                 ;
 1123 
 1124         csr32w(ctlr, Imc, ~0);
 1125         while(csr32r(ctlr, Icr))
 1126                 ;
 1127 }
 1128 
 1129 static void
 1130 gc82543checklink(Ctlr* ctlr)
 1131 {
 1132         int ctrl, status, rxcw;
 1133 
 1134         ctrl = csr32r(ctlr, Ctrl);
 1135         status = csr32r(ctlr, Status);
 1136         rxcw = csr32r(ctlr, Rxcw);
 1137 
 1138         if(!(status & Lu)){
 1139                 if(!(ctrl & (Swdpin1|Slu)) && !(rxcw & Rxconfig)){
 1140                         csr32w(ctlr, Txcw, ctlr->txcw & ~Ane);
 1141                         ctrl |= (Slu|Fd);
 1142                         if(ctlr->txcw & As)
 1143                                 ctrl |= Rfce;
 1144                         if(ctlr->txcw & Ps)
 1145                                 ctrl |= Tfce;
 1146                         csr32w(ctlr, Ctrl, ctrl);
 1147                 }
 1148         }
 1149         else if((ctrl & Slu) && (rxcw & Rxconfig)){
 1150                 csr32w(ctlr, Txcw, ctlr->txcw);
 1151                 ctrl &= ~(Slu|Fd);
 1152                 csr32w(ctlr, Ctrl, ctrl);
 1153         }
 1154 }
 1155 
 1156 static void
 1157 gc82543shutdown(Ether* ether)
 1158 {
 1159         gc82543detach(ether->ctlr);
 1160 }
 1161 
 1162 static int
 1163 gc82543reset(Ctlr* ctlr)
 1164 {
 1165         int ctl;
 1166         int te;
 1167 
 1168         /*
 1169          * Read the EEPROM, validate the checksum
 1170          * then get the device back to a power-on state.
 1171          */
 1172         if(at93c46r(ctlr) != 0xBABA)
 1173                 return -1;
 1174 
 1175         gc82543detach(ctlr);
 1176 
 1177         te = ctlr->eeprom[Icw2];
 1178         if((te & 0x3000) == 0){
 1179                 ctlr->fcrtl = 0x00002000;
 1180                 ctlr->fcrth = 0x00004000;
 1181                 ctlr->txcw = Ane|TxcwFd;
 1182         }
 1183         else if((te & 0x3000) == 0x2000){
 1184                 ctlr->fcrtl = 0;
 1185                 ctlr->fcrth = 0;
 1186                 ctlr->txcw = Ane|TxcwFd|As;
 1187         }
 1188         else{
 1189                 ctlr->fcrtl = 0x00002000;
 1190                 ctlr->fcrth = 0x00004000;
 1191                 ctlr->txcw = Ane|TxcwFd|As|Ps;
 1192         }
 1193 
 1194         csr32w(ctlr, Txcw, ctlr->txcw);
 1195 
 1196         csr32w(ctlr, Ctrlext, (te & 0x00f0)<<4);
 1197 
 1198         csr32w(ctlr, Tctl, csr32r(ctlr, Tctl)|(64<<ColdSHIFT));
 1199 
 1200         te = ctlr->eeprom[Icw1];
 1201         ctl = ((te & 0x01E0)<<17)|(te & 0x0010)<<3;
 1202         csr32w(ctlr, Ctrl, ctl);
 1203 
 1204         delay(10);
 1205 
 1206         /*
 1207          * Flow control - values from the datasheet.
 1208          */
 1209         csr32w(ctlr, Fcal, 0x00C28001);
 1210         csr32w(ctlr, Fcah, 0x00000100);
 1211         csr32w(ctlr, Fct, 0x00008808);
 1212         csr32w(ctlr, Fcttv, 0x00000100);
 1213 
 1214         csr32w(ctlr, Fcrtl, ctlr->fcrtl);
 1215         csr32w(ctlr, Fcrth, ctlr->fcrth);
 1216 
 1217         ctlr->im = Lsc;
 1218         gc82543checklink(ctlr);
 1219 
 1220         return 0;
 1221 }
 1222 
 1223 static void
 1224 gc82543watchdog(void* arg)
 1225 {
 1226         Ether *edev;
 1227         Ctlr *ctlr;
 1228 
 1229         edev = arg;
 1230         for(;;){
 1231                 tsleep(&up->sleep, return0, 0, 1000);
 1232 
 1233                 ctlr = edev->ctlr;
 1234                 if(ctlr == nil){
 1235                         print("%s: exiting\n", up->text);
 1236                         pexit("disabled", 0);
 1237                 }
 1238 
 1239                 gc82543checklink(ctlr);
 1240                 gc82543replenish(ctlr);
 1241         }
 1242 }
 1243 
 1244 static void
 1245 gc82543pci(void)
 1246 {
 1247         int cls;
 1248         void *mem;
 1249         Pcidev *p;
 1250         Ctlr *ctlr;
 1251 
 1252         p = nil;
 1253         while(p = pcimatch(p, 0, 0)){
 1254                 if(p->ccrb != 0x02 || p->ccru != 0)
 1255                         continue;
 1256 
 1257                 switch((p->did<<16)|p->vid){
 1258                 case (0x1000<<16)|0x8086:       /* LSI L2A1157 (82542) */
 1259                 case (0x1004<<16)|0x8086:       /* Intel PRO/1000 T */
 1260                 case (0x1008<<16)|0x8086:       /* Intel PRO/1000 XT */
 1261                 default:
 1262                         continue;
 1263                 case (0x1001<<16)|0x8086:       /* Intel PRO/1000 F */
 1264                         break;
 1265                 }
 1266 
 1267                 mem = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
 1268                 if(mem == 0){
 1269                         print("gc82543: can't map %8.8luX\n", p->mem[0].bar);
 1270                         continue;
 1271                 }
 1272                 cls = pcicfgr8(p, PciCLS);
 1273                 switch(cls){
 1274                         case 0x00:
 1275                         case 0xFF:
 1276                                 print("82543gc: unusable cache line size\n");
 1277                                 continue;
 1278                         case 0x08:
 1279                                 break;
 1280                         default:
 1281                                 print("82543gc: cache line size %d, expected 32\n",
 1282                                         cls*4);
 1283                 }
 1284                 ctlr = malloc(sizeof(Ctlr));
 1285                 ctlr->port = p->mem[0].bar & ~0x0F;
 1286                 ctlr->pcidev = p;
 1287                 ctlr->id = (p->did<<16)|p->vid;
 1288                 ctlr->nic = mem;
 1289 
 1290                 if(gc82543reset(ctlr)){
 1291                         free(ctlr);
 1292                         continue;
 1293                 }
 1294 
 1295                 if(gc82543ctlrhead != nil)
 1296                         gc82543ctlrtail->next = ctlr;
 1297                 else
 1298                         gc82543ctlrhead = ctlr;
 1299                 gc82543ctlrtail = ctlr;
 1300         }
 1301 }
 1302 
 1303 static int
 1304 gc82543pnp(Ether* edev)
 1305 {
 1306         int i;
 1307         Ctlr *ctlr;
 1308         uchar ea[Eaddrlen];
 1309 
 1310         if(gc82543ctlrhead == nil)
 1311                 gc82543pci();
 1312 
 1313         /*
 1314          * Any adapter matches if no edev->port is supplied,
 1315          * otherwise the ports must match.
 1316          */
 1317         for(ctlr = gc82543ctlrhead; ctlr != nil; ctlr = ctlr->next){
 1318                 if(ctlr->active)
 1319                         continue;
 1320                 if(edev->port == 0 || edev->port == ctlr->port){
 1321                         ctlr->active = 1;
 1322                         break;
 1323                 }
 1324         }
 1325         if(ctlr == nil)
 1326                 return -1;
 1327 
 1328         edev->ctlr = ctlr;
 1329         edev->port = ctlr->port;
 1330         edev->irq = ctlr->pcidev->intl;
 1331         edev->tbdf = ctlr->pcidev->tbdf;
 1332         edev->mbps = 1000;
 1333 
 1334         /*
 1335          * Check if the adapter's station address is to be overridden.
 1336          * If not, read it from the EEPROM and set in ether->ea prior to
 1337          * loading the station address in the hardware.
 1338          */
 1339         memset(ea, 0, Eaddrlen);
 1340         if(memcmp(ea, edev->ea, Eaddrlen) == 0){
 1341                 for(i = Ea; i < Eaddrlen/2; i++){
 1342                         edev->ea[2*i] = ctlr->eeprom[i];
 1343                         edev->ea[2*i+1] = ctlr->eeprom[i]>>8;
 1344                 }
 1345         }
 1346         gc82543init(edev);
 1347 
 1348         /*
 1349          * Linkage to the generic ethernet driver.
 1350          */
 1351         edev->attach = gc82543attach;
 1352         edev->transmit = gc82543transmit;
 1353         edev->interrupt = gc82543interrupt;
 1354         edev->ifstat = gc82543ifstat;
 1355         edev->shutdown = gc82543shutdown;
 1356         edev->ctl = gc82543ctl;
 1357         edev->arg = edev;
 1358         edev->promiscuous = gc82543promiscuous;
 1359         edev->multicast = gc82543multicast;
 1360 
 1361         return 0;
 1362 }
 1363 
 1364 void
 1365 ether82543gclink(void)
 1366 {
 1367         addethercard("82543GC", gc82543pnp);
 1368 }

Cache object: 0a970572aa67943eee95e84e4e0d48c0


[ 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.