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/etherga620.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  * Netgear GA620 Gigabit Ethernet Card.
    3  * Specific for the Alteon Tigon 2 and Intel Pentium or later.
    4  * To Do:
    5  *      cache alignment for PCI Write-and-Invalidate
    6  *      mini ring (what size)?
    7  *      tune coalescing values
    8  *      statistics formatting
    9  *      don't update Spi if nothing to send
   10  *      receive ring alignment
   11  *      watchdog for link management?
   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 #define malign(n)       xspanalloc((n), 32, 0)
   23 
   24 #include "etherif.h"
   25 #include "etherga620fw.h"
   26 
   27 enum {
   28         Mhc             = 0x0040,       /* Miscellaneous Host Control */
   29         Mlc             = 0x0044,       /* Miscellaneous Local Control */
   30         Mc              = 0x0050,       /* Miscellaneous Configuration */
   31         Ps              = 0x005C,       /* PCI State */
   32         Wba             = 0x0068,       /* Window Base Address */
   33         Wd              = 0x006C,       /* Window Data */
   34 
   35         DMAas           = 0x011C,       /* DMA Assist State */
   36 
   37         CPUAstate       = 0x0140,       /* CPU A State */
   38         CPUApc          = 0x0144,       /* CPU A Programme Counter */
   39 
   40         CPUBstate       = 0x0240,       /* CPU B State */
   41 
   42         Hi              = 0x0504,       /* Host In Interrupt Handler */
   43         Cpi             = 0x050C,       /* Command Producer Index */
   44         Spi             = 0x0514,       /* Send Producer Index */
   45         Rspi            = 0x051C,       /* Receive Standard Producer Index */
   46         Rjpi            = 0x0524,       /* Receive Jumbo Producer Index */
   47         Rmpi            = 0x052C,       /* Receive Mini Producer Index */
   48 
   49         Mac             = 0x0600,       /* MAC Address */
   50         Gip             = 0x0608,       /* General Information Pointer */
   51         Om              = 0x0618,       /* Operating Mode */
   52         DMArc           = 0x061C,       /* DMA Read Configuration */
   53         DMAwc           = 0x0620,       /* DMA Write Configuration */
   54         Tbr             = 0x0624,       /* Transmit Buffer Ratio */
   55         Eci             = 0x0628,       /* Event Consumer Index */
   56         Cci             = 0x062C,       /* Command Consumer Index */
   57 
   58         Rct             = 0x0630,       /* Receive Coalesced Ticks */
   59         Sct             = 0x0634,       /* Send Coalesced Ticks */
   60         St              = 0x0638,       /* Stat Ticks */
   61         SmcBD           = 0x063C,       /* Send Max. Coalesced BDs */
   62         RmcBD           = 0x0640,       /* Receive Max. Coalesced BDs */
   63         Nt              = 0x0644,       /* NIC Tracing */
   64         Gln             = 0x0648,       /* Gigabit Link Negotiation */
   65         Fln             = 0x064C,       /* 10/100 Link Negotiation */
   66         Ifx             = 0x065C,       /* Interface Index */
   67         IfMTU           = 0x0660,       /* Interface MTU */
   68         Mi              = 0x0664,       /* Mask Interrupts */
   69         Gls             = 0x0668,       /* Gigabit Link State */
   70         Fls             = 0x066C,       /* 10/100 Link State */
   71 
   72         Cr              = 0x0700,       /* Command Ring */
   73 
   74         Lmw             = 0x0800,       /* Local Memory Window */
   75 };
   76 
   77 enum {                                  /* Mhc */
   78         Is              = 0x00000001,   /* Interrupt State */
   79         Ci              = 0x00000002,   /* Clear Interrupt */
   80         Hr              = 0x00000008,   /* Hard Reset */
   81         Eebs            = 0x00000010,   /* Enable Endian Byte Swap */
   82         Eews            = 0x00000020,   /* Enable Endian Word (64-bit) swap */
   83         Mpio            = 0x00000040,   /* Mask PCI Interrupt Output */
   84 };
   85 
   86 enum {                                  /* Mlc */
   87         SRAM512         = 0x00000200,   /* SRAM Bank Size of 512KB */
   88         SRAMmask        = 0x00000300,
   89         EEclk           = 0x00100000,   /* Serial EEPROM Clock Output */
   90         EEdoe           = 0x00200000,   /* Serial EEPROM Data Out Enable */
   91         EEdo            = 0x00400000,   /* Serial EEPROM Data Out Value */
   92         EEdi            = 0x00800000,   /* Serial EEPROM Data Input */
   93 };
   94 
   95 enum {                                  /* Mc */
   96         SyncSRAM        = 0x00100000,   /* Set Synchronous SRAM Timing */
   97 };
   98 
   99 enum {                                  /* Ps */
  100         PCIwm32         = 0x000000C0,   /* Write Max DMA 32 */
  101         PCImrm          = 0x00020000,   /* Use Memory Read Multiple Command */
  102         PCI66           = 0x00080000,
  103         PCI32           = 0x00100000,
  104         PCIrcmd         = 0x06000000,   /* PCI Read Command */
  105         PCIwcmd         = 0x70000000,   /* PCI Write Command */
  106 };
  107 
  108 enum {                                  /* CPUAstate */
  109         CPUrf           = 0x00000010,   /* ROM Fail */
  110         CPUhalt         = 0x00010000,   /* Halt the internal CPU */
  111         CPUhie          = 0x00040000,   /* HALT instruction executed */
  112 };
  113 
  114 enum {                                  /* Om */
  115         BswapBD         = 0x00000002,   /* Byte Swap Buffer Descriptors */
  116         WswapBD         = 0x00000004,   /* Word Swap Buffer Descriptors */
  117         Warn            = 0x00000008,
  118         BswapDMA        = 0x00000010,   /* Byte Swap DMA Data */
  119         Only1DMA        = 0x00000040,   /* Only One DMA Active at a time */
  120         NoJFrag         = 0x00000200,   /* Don't Fragment Jumbo Frames */
  121         Fatal           = 0x40000000,
  122 };
  123 
  124 enum {                                  /* Lmw */
  125         Lmwsz           = 2*1024,       /* Local Memory Window Size */
  126 
  127         /*
  128          * legal values are 0x3800 iff Nsr is 128, 0x3000 iff Nsr is 256,
  129          * or 0x2000 iff Nsr is 512.
  130          */
  131         Sr              = 0x2000,       /* Send Ring (accessed via Lmw) */
  132 };
  133 
  134 enum {                                  /* Link */
  135         Lpref           = 0x00008000,   /* Preferred Link */
  136         L10MB           = 0x00010000,
  137         L100MB          = 0x00020000,
  138         L1000MB         = 0x00040000,
  139         Lfd             = 0x00080000,   /* Full Duplex */
  140         Lhd             = 0x00100000,   /* Half Duplex */
  141         Lefc            = 0x00200000,   /* Emit Flow Control Packets */
  142         Lofc            = 0x00800000,   /* Obey Flow Control Packets */
  143         Lean            = 0x20000000,   /* Enable Autonegotiation/Sensing */
  144         Le              = 0x40000000,   /* Link Enable */
  145 };
  146 
  147 typedef struct Host64 {
  148         uint    hi;
  149         uint    lo;
  150 } Host64;
  151 
  152 typedef struct Ere {                    /* Event Ring Element */
  153         int     event;                  /* event<<24 | code<<12 | index */
  154         int     unused;
  155 } Ere;
  156 
  157 typedef int Cmd;                        /* cmd<<24 | flags<<12 | index */
  158 
  159 typedef struct Rbd {                    /* Receive Buffer Descriptor */
  160         Host64  addr;
  161         int     indexlen;               /* ring-index<<16 | buffer-length */
  162         int     flags;                  /* only lower 16-bits */
  163         int     checksum;               /* ip<<16 | tcp/udp */
  164         int     error;                  /* only upper 16-bits */
  165         int     reserved;
  166         void*   opaque;                 /* passed to receive return ring */
  167 } Rbd;
  168 
  169 typedef struct Sbd {                    /* Send Buffer Descriptor */
  170         Host64  addr;
  171         int     lenflags;               /* len<<16 | flags */
  172         int     reserved;
  173 } Sbd;
  174 
  175 enum {                                  /* Buffer Descriptor Flags */
  176         Fend            = 0x00000004,   /* Frame Ends in this Buffer */
  177         Frjr            = 0x00000010,   /* Receive Jumbo Ring Buffer */
  178         Funicast        = 0x00000020,   /* Unicast packet (2-bit field) */
  179         Fmulticast      = 0x00000040,   /* Multicast packet */
  180         Fbroadcast      = 0x00000060,   /* Broadcast packet */
  181         Ferror          = 0x00000400,   /* Frame Has Error */
  182         Frmr            = 0x00001000,   /* Receive Mini Ring Buffer */
  183 };
  184 
  185 enum {                                  /* Buffer Error Flags */
  186         Ecrc            = 0x00010000,   /* bad CRC */
  187         Ecollision      = 0x00020000,   /* collision */
  188         Elink           = 0x00040000,   /* link lost */
  189         Ephy            = 0x00080000,   /* unspecified PHY frame decode error */
  190         Eodd            = 0x00100000,   /* odd number of nibbles */
  191         Emac            = 0x00200000,   /* unspecified MAC abort */
  192         Elen64          = 0x00400000,   /* short packet */
  193         Eresources      = 0x00800000,   /* MAC out of internal resources */
  194         Egiant          = 0x01000000,   /* packet too big */
  195 };
  196 
  197 typedef struct Rcb {                    /* Ring Control Block */
  198         Host64  addr;                   /* points to the Rbd ring */
  199         int     control;                /* max_len<<16 | flags */
  200         int     unused;
  201 } Rcb;
  202 
  203 enum {
  204         TcpUdpCksum     = 0x0001,       /* Perform TCP or UDP checksum */
  205         IpCksum         = 0x0002,       /* Perform IP checksum */
  206         NoPseudoHdrCksum= 0x0008,       /* Don't include the pseudo header */
  207         VlanAssist      = 0x0010,       /* Enable VLAN tagging */
  208         CoalUpdateOnly  = 0x0020,       /* Coalesce transmit interrupts */
  209         HostRing        = 0x0040,       /* Sr in host memory */
  210         SnapCksum       = 0x0080,       /* Parse + offload 802.3 SNAP frames */
  211         UseExtRxBd      = 0x0100,       /* Extended Rbd for Jumbo frames */
  212         RingDisabled    = 0x0200,       /* Jumbo or Mini RCB only */
  213 };
  214 
  215 typedef struct Gib {                    /* General Information Block */
  216         int     statistics[256];        /* Statistics */
  217         Rcb     ercb;                   /* Event Ring */
  218         Rcb     crcb;                   /* Command Ring */
  219         Rcb     srcb;                   /* Send Ring */
  220         Rcb     rsrcb;                  /* Receive Standard Ring */
  221         Rcb     rjrcb;                  /* Receive Jumbo Ring */
  222         Rcb     rmrcb;                  /* Receive Mini Ring */
  223         Rcb     rrrcb;                  /* Receive Return Ring */
  224         Host64  epp;                    /* Event Producer */
  225         Host64  rrrpp;                  /* Receive Return Ring Producer */
  226         Host64  scp;                    /* Send Consumer */
  227         Host64  rsp;                    /* Refresh Stats */
  228 } Gib;
  229 
  230 /*
  231  * these sizes are all fixed in the card,
  232  * except for Nsr, which has only 3 valid sizes.
  233  */
  234 enum {                                  /* Host/NIC Interface ring sizes */
  235         Ner             = 256,          /* event ring */
  236         Ncr             = 64,           /* command ring */
  237         Nsr             = 512,          /* send ring: 128, 256 or 512 */
  238         Nrsr            = 512,          /* receive standard ring */
  239         Nrjr            = 256,          /* receive jumbo ring */
  240         Nrmr            = 1024,         /* receive mini ring, optional */
  241         Nrrr            = 2048,         /* receive return ring */
  242 };
  243 
  244 enum {
  245         NrsrHI          = 72,           /* Fill-level of Rsr (m.b. < Nrsr) */
  246         NrsrLO          = 54,           /* Level at which to top-up ring */
  247         NrjrHI          = 0,            /* Fill-level of Rjr (m.b. < Nrjr) */
  248         NrjrLO          = 0,            /* Level at which to top-up ring */
  249         NrmrHI          = 0,            /* Fill-level of Rmr (m.b. < Nrmr) */
  250         NrmrLO          = 0,            /* Level at which to top-up ring */
  251 };
  252 
  253 typedef struct Ctlr Ctlr;
  254 struct Ctlr {
  255         int     port;
  256         Pcidev* pcidev;
  257         Ctlr*   next;
  258         int     active;
  259         int     id;
  260 
  261         uchar   ea[Eaddrlen];
  262 
  263         int*    nic;
  264         Gib*    gib;
  265 
  266         Ere*    er;
  267 
  268         Lock    srlock;
  269         Sbd*    sr;
  270         Block** srb;
  271         int     nsr;                    /* currently in send ring */
  272 
  273         Rbd*    rsr;
  274         int     nrsr;                   /* currently in Receive Standard Ring */
  275         Rbd*    rjr;
  276         int     nrjr;                   /* currently in Receive Jumbo Ring */
  277         Rbd*    rmr;
  278         int     nrmr;                   /* currently in Receive Mini Ring */
  279         Rbd*    rrr;
  280         int     rrrci;                  /* Receive Return Ring Consumer Index */
  281 
  282         int     epi[2];                 /* Event Producer Index */
  283         int     rrrpi[2];               /* Receive Return Ring Producer Index */
  284         int     sci[3];                 /* Send Consumer Index ([2] is host) */
  285 
  286         int     interrupts;             /* statistics */
  287         int     mi;
  288         uvlong  ticks;
  289 
  290         int     coalupdateonly;         /* tuning */
  291         int     hardwarecksum;
  292         int     rct;                    /* Receive Coalesce Ticks */
  293         int     sct;                    /* Send Coalesce Ticks */
  294         int     st;                     /* Stat Ticks */
  295         int     smcbd;                  /* Send Max. Coalesced BDs */
  296         int     rmcbd;                  /* Receive Max. Coalesced BDs */
  297 };
  298 
  299 static Ctlr* ctlrhead;
  300 static Ctlr* ctlrtail;
  301 
  302 #define csr32r(c, r)    (*((c)->nic+((r)/4)))
  303 #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
  304 
  305 static void
  306 sethost64(Host64* host64, void* addr)
  307 {
  308         uvlong uvl;
  309 
  310         uvl = PCIWADDR(addr);
  311         host64->hi = uvl>>32;
  312         host64->lo = uvl & 0xFFFFFFFFL;
  313 }
  314 
  315 static void
  316 ga620command(Ctlr* ctlr, int cmd, int flags, int index)
  317 {
  318         int cpi;
  319 
  320         cpi = csr32r(ctlr, Cpi);
  321         csr32w(ctlr, Cr+(cpi*4), cmd<<24 | flags<<12 | index);
  322         cpi = NEXT(cpi, Ncr);
  323         csr32w(ctlr, Cpi, cpi);
  324 }
  325 
  326 static void
  327 ga620attach(Ether* edev)
  328 {
  329         Ctlr *ctlr;
  330 
  331         ctlr = edev->ctlr;
  332         USED(ctlr);
  333 }
  334 
  335 static long
  336 ga620ifstat(Ether* edev, void* a, long n, ulong offset)
  337 {
  338         char *p;
  339         Ctlr *ctlr;
  340         int i, l, r;
  341 
  342         ctlr = edev->ctlr;
  343 
  344         if(n == 0)
  345                 return 0;
  346         p = malloc(READSTR);
  347         l = 0;
  348         for(i = 0; i < 256; i++){
  349                 if((r = ctlr->gib->statistics[i]) == 0)
  350                         continue;
  351                 l += snprint(p+l, READSTR-l, "%d: %ud\n", i, r);
  352         }
  353 
  354         l += snprint(p+l, READSTR-l, "interrupts: %ud\n", ctlr->interrupts);
  355         l += snprint(p+l, READSTR-l, "mi: %ud\n", ctlr->mi);
  356         l += snprint(p+l, READSTR-l, "ticks: %llud\n", ctlr->ticks);
  357         l += snprint(p+l, READSTR-l, "coalupdateonly: %d\n", ctlr->coalupdateonly);
  358         l += snprint(p+l, READSTR-l, "hardwarecksum: %d\n", ctlr->hardwarecksum);
  359         l += snprint(p+l, READSTR-l, "rct: %d\n", ctlr->rct);
  360         l += snprint(p+l, READSTR-l, "sct: %d\n", ctlr->sct);
  361         l += snprint(p+l, READSTR-l, "smcbd: %d\n", ctlr->smcbd);
  362         snprint(p+l, READSTR-l, "rmcbd: %d\n", ctlr->rmcbd);
  363 
  364         n = readstr(offset, a, n, p);
  365         free(p);
  366 
  367         return n;
  368 }
  369 
  370 static long
  371 ga620ctl(Ether* edev, void* buf, long n)
  372 {
  373         char *p;
  374         Cmdbuf *cb;
  375         Ctlr *ctlr;
  376         int control, i, r;
  377 
  378         ctlr = edev->ctlr;
  379         if(ctlr == nil)
  380                 error(Enonexist);
  381         r = 0;
  382         cb = parsecmd(buf, n);
  383         if(cb->nf < 2)
  384                 r = -1;
  385         else if(cistrcmp(cb->f[0], "coalupdateonly") == 0){
  386                 if(cistrcmp(cb->f[1], "off") == 0){
  387                         control = ctlr->gib->srcb.control;
  388                         control &= ~CoalUpdateOnly;
  389                         ctlr->gib->srcb.control = control;
  390                         ctlr->coalupdateonly = 0;
  391                 }
  392                 else if(cistrcmp(cb->f[1], "on") == 0){
  393                         control = ctlr->gib->srcb.control;
  394                         control |= CoalUpdateOnly;
  395                         ctlr->gib->srcb.control = control;
  396                         ctlr->coalupdateonly = 1;
  397                 }
  398                 else
  399                         r = -1;
  400         }
  401         else if(cistrcmp(cb->f[0], "hardwarecksum") == 0){
  402                 if(cistrcmp(cb->f[1], "off") == 0){
  403                         control = ctlr->gib->srcb.control;
  404                         control &= ~(TcpUdpCksum|NoPseudoHdrCksum);
  405                         ctlr->gib->srcb.control = control;
  406 
  407                         control = ctlr->gib->rsrcb.control;
  408                         control &= ~(TcpUdpCksum|NoPseudoHdrCksum);
  409                         ctlr->gib->rsrcb.control = control;
  410 
  411                         ctlr->hardwarecksum = 0;
  412                 }
  413                 else if(cistrcmp(cb->f[1], "on") == 0){
  414                         control = ctlr->gib->srcb.control;
  415                         control |= (TcpUdpCksum|NoPseudoHdrCksum);
  416                         ctlr->gib->srcb.control = control;
  417 
  418                         control = ctlr->gib->rsrcb.control;
  419                         control |= (TcpUdpCksum|NoPseudoHdrCksum);
  420                         ctlr->gib->rsrcb.control = control;
  421 
  422                         ctlr->hardwarecksum = 1;
  423                 }
  424                 else
  425                         r = -1;
  426         }
  427         else if(cistrcmp(cb->f[0], "rct") == 0){
  428                 i = strtol(cb->f[1], &p, 0);
  429                 if(i < 0 || p == cb->f[1])
  430                         r = -1;
  431                 else{
  432                         ctlr->rct = i;
  433                         csr32w(ctlr, Rct, ctlr->rct);
  434                 }
  435         }
  436         else if(cistrcmp(cb->f[0], "sct") == 0){
  437                 i = strtol(cb->f[1], &p, 0);
  438                 if(i < 0 || p == cb->f[1])
  439                         r = -1;
  440                 else{
  441                         ctlr->sct = i;
  442                         csr32w(ctlr, Sct, ctlr->sct);
  443                 }
  444         }
  445         else if(cistrcmp(cb->f[0], "st") == 0){
  446                 i = strtol(cb->f[1], &p, 0);
  447                 if(i < 0 || p == cb->f[1])
  448                         r = -1;
  449                 else{
  450                         ctlr->st = i;
  451                         csr32w(ctlr, St, ctlr->st);
  452                 }
  453         }
  454         else if(cistrcmp(cb->f[0], "smcbd") == 0){
  455                 i = strtol(cb->f[1], &p, 0);
  456                 if(i < 0 || p == cb->f[1])
  457                         r = -1;
  458                 else{
  459                         ctlr->smcbd = i;
  460                         csr32w(ctlr, SmcBD, ctlr->smcbd);
  461                 }
  462         }
  463         else if(cistrcmp(cb->f[0], "rmcbd") == 0){
  464                 i = strtol(cb->f[1], &p, 0);
  465                 if(i < 0 || p == cb->f[1])
  466                         r = -1;
  467                 else{
  468                         ctlr->rmcbd = i;
  469                         csr32w(ctlr, RmcBD, ctlr->rmcbd);
  470                 }
  471         }
  472         else
  473                 r = -1;
  474 
  475         free(cb);
  476         if(r == 0)
  477                 return n;
  478         return r;
  479 }
  480 
  481 static int
  482 _ga620transmit(Ether* edev)
  483 {
  484         Sbd *sbd;
  485         Block *bp;
  486         Ctlr *ctlr;
  487         int sci, spi, work;
  488 
  489         /*
  490          * For now there are no smarts here, just empty the
  491          * ring and try to fill it back up. Tuning comes later.
  492          */
  493         ctlr = edev->ctlr;
  494         ilock(&ctlr->srlock);
  495 
  496         /*
  497          * Free any completed packets.
  498          * Ctlr->sci[0] is where the NIC has got to consuming the ring.
  499          * Ctlr->sci[2] is where the host has got to tidying up after the
  500          * NIC has done with the packets.
  501          */
  502         work = 0;
  503         for(sci = ctlr->sci[2]; sci != ctlr->sci[0]; sci = NEXT(sci, Nsr)){
  504                 if(ctlr->srb[sci] == nil)
  505                         continue;
  506                 freeb(ctlr->srb[sci]);
  507                 ctlr->srb[sci] = nil;
  508                 work++;
  509         }
  510         ctlr->sci[2] = sci;
  511 
  512         sci = PREV(sci, Nsr);
  513         for(spi = csr32r(ctlr, Spi); spi != sci; spi = NEXT(spi, Nsr)){
  514                 if((bp = qget(edev->oq)) == nil)
  515                         break;
  516 
  517                 sbd = &ctlr->sr[spi];
  518                 sethost64(&sbd->addr, bp->rp);
  519                 sbd->lenflags = BLEN(bp)<<16 | Fend;
  520 
  521                 ctlr->srb[spi] = bp;
  522                 work++;
  523         }
  524         csr32w(ctlr, Spi, spi);
  525 
  526         iunlock(&ctlr->srlock);
  527 
  528         return work;
  529 }
  530 
  531 static void
  532 ga620transmit(Ether* edev)
  533 {
  534         _ga620transmit(edev);
  535 }
  536 
  537 static void
  538 ga620replenish(Ctlr* ctlr)
  539 {
  540         Rbd *rbd;
  541         int rspi;
  542         Block *bp;
  543 
  544         rspi = csr32r(ctlr, Rspi);
  545         while(ctlr->nrsr < NrsrHI){
  546                 if((bp = iallocb(ETHERMAXTU+4)) == nil)
  547                         break;
  548                 rbd = &ctlr->rsr[rspi];
  549                 sethost64(&rbd->addr, bp->rp);
  550                 rbd->indexlen = rspi<<16 | (ETHERMAXTU+4);
  551                 rbd->flags = 0;
  552                 rbd->opaque = bp;
  553 
  554                 rspi = NEXT(rspi, Nrsr);
  555                 ctlr->nrsr++;
  556         }
  557         csr32w(ctlr, Rspi, rspi);
  558 }
  559 
  560 static void
  561 ga620event(Ether *edev, int eci, int epi)
  562 {
  563         unsigned event, code;
  564         Ctlr *ctlr;
  565 
  566         ctlr = edev->ctlr;
  567         while(eci != epi){
  568                 event = ctlr->er[eci].event;
  569                 code = (event >> 12) & ((1<<12)-1);
  570                 switch(event>>24){
  571                 case 0x01:              /* firmware operational */
  572                         /* host stack (us) is up.  3rd arg of 2 means down. */
  573                         ga620command(ctlr, 0x01, 0x01, 0x00);
  574                         /*
  575                          * link negotiation: any speed is okay.
  576                          * 3rd arg of 1 selects gigabit only; 2 10/100 only.
  577                          */
  578                         ga620command(ctlr, 0x0B, 0x00, 0x00);
  579                         print("#l%d: ga620: port %8.8uX: firmware is up\n",
  580                                 edev->ctlrno, ctlr->port);
  581                         break;
  582                 case 0x04:              /* statistics updated */
  583                         break;
  584                 case 0x06:              /* link state changed */
  585                         switch (code) {
  586                         case 1:
  587                                 edev->mbps = 1000;
  588                                 break;
  589                         case 2:
  590                                 print("#l%d: link down\n", edev->ctlrno);
  591                                 break;
  592                         case 3:
  593                                 edev->mbps = 100;       /* it's 10 or 100 */
  594                                 break;
  595                         }
  596                         if (code != 2)
  597                                 print("#l%d: %dMbps link up\n",
  598                                         edev->ctlrno, edev->mbps);
  599                         break;
  600                 case 0x07:              /* event error */
  601                 default:
  602                         print("#l%d: ga620: er[%d] = %8.8uX\n", edev->ctlrno,
  603                                 eci, event);
  604                         break;
  605                 }
  606                 eci = NEXT(eci, Ner);
  607         }
  608         csr32w(ctlr, Eci, eci);
  609 }
  610 
  611 static void
  612 ga620receive(Ether* edev)
  613 {
  614         int len;
  615         Rbd *rbd;
  616         Block *bp;
  617         Ctlr* ctlr;
  618 
  619         ctlr = edev->ctlr;
  620         while(ctlr->rrrci != ctlr->rrrpi[0]){
  621                 rbd = &ctlr->rrr[ctlr->rrrci];
  622                 /*
  623                  * Errors are collected in the statistics block so
  624                  * no need to tally them here, let ifstat do the work.
  625                  */
  626                 len = rbd->indexlen & 0xFFFF;
  627                 if(!(rbd->flags & Ferror) && len != 0){
  628                         bp = rbd->opaque;
  629                         bp->wp = bp->rp+len;
  630                         etheriq(edev, bp, 1);
  631                 }
  632                 else
  633                         freeb(rbd->opaque);
  634                 rbd->opaque = nil;
  635 
  636                 if(rbd->flags & Frjr)
  637                         ctlr->nrjr--;
  638                 else if(rbd->flags & Frmr)
  639                         ctlr->nrmr--;
  640                 else
  641                         ctlr->nrsr--;
  642 
  643                 ctlr->rrrci = NEXT(ctlr->rrrci, Nrrr);
  644         }
  645 }
  646 
  647 static void
  648 ga620interrupt(Ureg*, void* arg)
  649 {
  650         int csr, ie, work;
  651         Ctlr *ctlr;
  652         Ether *edev;
  653         uvlong tsc0, tsc1;
  654 
  655         edev = arg;
  656         ctlr = edev->ctlr;
  657 
  658         if(!(csr32r(ctlr, Mhc) & Is))
  659                 return;
  660         cycles(&tsc0);
  661 
  662         ctlr->interrupts++;
  663         csr32w(ctlr, Hi, 1);
  664 
  665         ie = 0;
  666         work = 0;
  667         while(ie < 2){
  668                 if(ctlr->rrrci != ctlr->rrrpi[0]){
  669                         ga620receive(edev);
  670                         work = 1;
  671                 }
  672 
  673                 if(_ga620transmit(edev) != 0)
  674                         work = 1;
  675 
  676                 csr = csr32r(ctlr, Eci);
  677                 if(csr != ctlr->epi[0]){
  678                         ga620event(edev, csr, ctlr->epi[0]);
  679                         work = 1;
  680                 }
  681 
  682                 if(ctlr->nrsr <= NrsrLO)
  683                         ga620replenish(ctlr);
  684                 if(work == 0){
  685                         if(ie == 0)
  686                                 csr32w(ctlr, Hi, 0);
  687                         ie++;
  688                 }
  689                 work = 0;
  690         }
  691 
  692         cycles(&tsc1);
  693         ctlr->ticks += tsc1-tsc0;
  694 }
  695 
  696 static void
  697 ga620lmw(Ctlr* ctlr, int addr, int* data, int len)
  698 {
  699         int i, l, lmw, v;
  700 
  701         /*
  702          * Write to or clear ('data' == nil) 'len' bytes of the NIC
  703          * local memory at address 'addr'.
  704          * The destination address and count should be 32-bit aligned.
  705          */
  706         v = 0;
  707         while(len > 0){
  708                 /*
  709                  * 1) Set the window. The (Lmwsz-1) bits are ignored
  710                  *    in Wba when accessing through the local memory window;
  711                  * 2) Find the minimum of how many bytes still to
  712                  *    transfer and how many left in this window;
  713                  * 3) Create the offset into the local memory window in the
  714                  *    shared memory space then copy (or zero) the data;
  715                  * 4) Bump the counts.
  716                  */
  717                 csr32w(ctlr, Wba, addr);
  718 
  719                 l = ROUNDUP(addr+1, Lmwsz) - addr;
  720                 if(l > len)
  721                         l = len;
  722 
  723                 lmw = Lmw + (addr & (Lmwsz-1));
  724                 for(i = 0; i < l; i += 4){
  725                         if(data != nil)
  726                                 v = *data++;
  727                         csr32w(ctlr, lmw+i, v);
  728                 }
  729 
  730                 len -= l;
  731                 addr += l;
  732         }
  733 }
  734 
  735 static int
  736 ga620init(Ether* edev)
  737 {
  738         Ctlr *ctlr;
  739         Host64 host64;
  740         int csr, ea, i, flags;
  741 
  742         ctlr = edev->ctlr;
  743 
  744         /*
  745          * Load the MAC address.
  746          */
  747         ea = edev->ea[0]<<8 | edev->ea[1];
  748         csr32w(ctlr, Mac, ea);
  749         ea = edev->ea[2]<<24 | edev->ea[3]<<16 | edev->ea[4]<<8 | edev->ea[5];
  750         csr32w(ctlr, Mac+4, ea);
  751 
  752         /*
  753          * General Information Block.
  754          */
  755         ctlr->gib = malloc(sizeof(Gib));
  756         sethost64(&host64, ctlr->gib);
  757         csr32w(ctlr, Gip, host64.hi);
  758         csr32w(ctlr, Gip+4, host64.lo);
  759 
  760         /*
  761          * Event Ring.
  762          * This is located in host memory. Allocate the ring,
  763          * tell the NIC where it is and initialise the indices.
  764          */
  765         ctlr->er = malign(sizeof(Ere)*Ner);
  766         sethost64(&ctlr->gib->ercb.addr, ctlr->er);
  767         sethost64(&ctlr->gib->epp, ctlr->epi);
  768         csr32w(ctlr, Eci, 0);
  769 
  770         /*
  771          * Command Ring.
  772          * This is located in the General Communications Region
  773          * and so the value placed in the Rcb is unused, the NIC
  774          * knows where it is. Stick in the value according to
  775          * the datasheet anyway.
  776          * Initialise the ring and indices.
  777          */
  778         ctlr->gib->crcb.addr.lo = Cr-0x400;
  779         for(i = 0; i < Ncr*4; i += 4)
  780                 csr32w(ctlr, Cr+i, 0);
  781         csr32w(ctlr, Cpi, 0);
  782         csr32w(ctlr, Cci, 0);
  783 
  784         /*
  785          * Send Ring.
  786          * This ring is either in NIC memory at a fixed location depending
  787          * on how big the ring is or it is in host memory. If in NIC
  788          * memory it is accessed via the Local Memory Window; with a send
  789          * ring size of 128 the window covers the whole ring and then need
  790          * only be set once:
  791          *      ctlr->sr = (uchar*)ctlr->nic+Lmw;
  792          *      ga620lmw(ctlr, Sr, nil, sizeof(Sbd)*Nsr);
  793          *      ctlr->gib->srcb.addr.lo = Sr;
  794          * There is nowhere in the Sbd to hold the Block* associated
  795          * with this entry so an external array must be kept.
  796          */
  797         ctlr->sr = malign(sizeof(Sbd)*Nsr);
  798         sethost64(&ctlr->gib->srcb.addr, ctlr->sr);
  799         if(ctlr->hardwarecksum)
  800                 flags = TcpUdpCksum|NoPseudoHdrCksum|HostRing;
  801         else 
  802                 flags = HostRing;
  803         if(ctlr->coalupdateonly) 
  804                 flags |= CoalUpdateOnly;
  805         ctlr->gib->srcb.control = Nsr<<16 | flags;
  806         sethost64(&ctlr->gib->scp, ctlr->sci);
  807         csr32w(ctlr, Spi, 0);
  808         ctlr->srb = malloc(sizeof(Block*)*Nsr);
  809 
  810         /*
  811          * Receive Standard Ring.
  812          */
  813         ctlr->rsr = malign(sizeof(Rbd)*Nrsr);
  814         sethost64(&ctlr->gib->rsrcb.addr, ctlr->rsr);
  815         if(ctlr->hardwarecksum)
  816                 flags = TcpUdpCksum|NoPseudoHdrCksum;
  817         else
  818                 flags = 0;
  819         ctlr->gib->rsrcb.control = (ETHERMAXTU+4)<<16 | flags;
  820         csr32w(ctlr, Rspi, 0);
  821 
  822         /*
  823          * Jumbo and Mini Rings. Unused for now.
  824          */
  825         ctlr->gib->rjrcb.control = RingDisabled;
  826         ctlr->gib->rmrcb.control = RingDisabled;
  827 
  828         /*
  829          * Receive Return Ring.
  830          * This is located in host memory. Allocate the ring,
  831          * tell the NIC where it is and initialise the indices.
  832          */
  833         ctlr->rrr = malign(sizeof(Rbd)*Nrrr);
  834         sethost64(&ctlr->gib->rrrcb.addr, ctlr->rrr);
  835         ctlr->gib->rrrcb.control = Nrrr<<16 | 0;
  836         sethost64(&ctlr->gib->rrrpp, ctlr->rrrpi);
  837         ctlr->rrrci = 0;
  838 
  839         /*
  840          * Refresh Stats Pointer.
  841          * For now just point it at the existing statistics block.
  842          */
  843         sethost64(&ctlr->gib->rsp, ctlr->gib->statistics);
  844 
  845         /*
  846          * DMA configuration.
  847          * Use the recommended values.
  848          */
  849         csr32w(ctlr, DMArc, 0x80);
  850         csr32w(ctlr, DMAwc, 0x80);
  851 
  852         /*
  853          * Transmit Buffer Ratio.
  854          * Set to 1/3 of available buffer space (units are 1/64ths)
  855          * if using Jumbo packets, ~64KB otherwise (assume 1MB on NIC).
  856          */
  857         if(NrjrHI > 0 || Nsr > 128)
  858                 csr32w(ctlr, Tbr, 64/3);
  859         else
  860                 csr32w(ctlr, Tbr, 4);
  861 
  862         /*
  863          * Tuneable parameters.
  864          * These defaults are based on the tuning hints in the Alteon
  865          * Host/NIC Software Interface Definition and example software.
  866          */
  867         ctlr->rct = 1/*100*/;
  868         csr32w(ctlr, Rct, ctlr->rct);
  869         ctlr->sct = 0;
  870         csr32w(ctlr, Sct, ctlr->sct);
  871         ctlr->st = 1000000;
  872         csr32w(ctlr, St, ctlr->st);
  873         ctlr->smcbd = Nsr/4;
  874         csr32w(ctlr, SmcBD, ctlr->smcbd);
  875         ctlr->rmcbd = 4/*6*/;
  876         csr32w(ctlr, RmcBD, ctlr->rmcbd);
  877 
  878         /*
  879          * Enable DMA Assist Logic.
  880          */
  881         csr = csr32r(ctlr, DMAas) & ~0x03;
  882         csr32w(ctlr, DMAas, csr|0x01);
  883 
  884         /*
  885          * Link negotiation.
  886          * The bits are set here but the NIC must be given a command
  887          * once it is running to set negotiation in motion.
  888          */
  889         csr32w(ctlr, Gln, Le|Lean|Lofc|Lfd|L1000MB|Lpref);
  890         csr32w(ctlr, Fln, Le|Lean|Lhd|Lfd|L100MB|L10MB);
  891 
  892         /*
  893          * A unique index for this controller and the maximum packet
  894          * length expected.
  895          * For now only standard packets are expected.
  896          */
  897         csr32w(ctlr, Ifx, 1);
  898         csr32w(ctlr, IfMTU, ETHERMAXTU+4);
  899 
  900         /*
  901          * Enable Interrupts.
  902          * There are 3 ways to mask interrupts - a bit in the Mhc (which
  903          * is already cleared), the Mi register and the Hi mailbox.
  904          * Writing to the Hi mailbox has the side-effect of clearing the
  905          * PCI interrupt.
  906          */
  907         csr32w(ctlr, Mi, 0);
  908         csr32w(ctlr, Hi, 0);
  909 
  910         /*
  911          * Start the firmware.
  912          */
  913         csr32w(ctlr, CPUApc, tigon2FwStartAddr);
  914         csr = csr32r(ctlr, CPUAstate) & ~CPUhalt;
  915         csr32w(ctlr, CPUAstate, csr);
  916 
  917         return 0;
  918 }
  919 
  920 static int
  921 at24c32io(Ctlr* ctlr, char* op, int data)
  922 {
  923         char *lp, *p;
  924         int i, loop, mlc, r;
  925 
  926         mlc = csr32r(ctlr, Mlc);
  927 
  928         r = 0;
  929         loop = -1;
  930         lp = nil;
  931         for(p = op; *p != '\0'; p++){
  932                 switch(*p){
  933                 default:
  934                         return -1;
  935                 case ' ':
  936                         continue;
  937                 case ':':                       /* start of 8-bit loop */
  938                         if(lp != nil)
  939                                 return -1;
  940                         lp = p;
  941                         loop = 7;
  942                         continue;
  943                 case ';':                       /* end of 8-bit loop */
  944                         if(lp == nil)
  945                                 return -1;
  946                         loop--;
  947                         if(loop >= 0)
  948                                 p = lp;
  949                         else
  950                                 lp = nil;
  951                         continue;
  952                 case 'C':                       /* assert clock */
  953                         mlc |= EEclk;
  954                         break;
  955                 case 'c':                       /* deassert clock */
  956                         mlc &= ~EEclk;
  957                         break;
  958                 case 'D':                       /* next bit in 'data' byte */
  959                         if(loop < 0)
  960                                 return -1;
  961                         if(data & (1<<loop))
  962                                 mlc |= EEdo;
  963                         else
  964                                 mlc &= ~EEdo;
  965                         break;
  966                 case 'E':                       /* enable data output */
  967                         mlc |= EEdoe;
  968                         break;
  969                 case 'e':                       /* disable data output */
  970                         mlc &= ~EEdoe;
  971                         break;
  972                 case 'I':                       /* input bit */
  973                         i = (csr32r(ctlr, Mlc) & EEdi) != 0;
  974                         if(loop >= 0)
  975                                 r |= (i<<loop);
  976                         else
  977                                 r = i;
  978                         continue;
  979                 case 'O':                       /* assert data output */
  980                         mlc |= EEdo;
  981                         break;
  982                 case 'o':                       /* deassert data output */
  983                         mlc &= ~EEdo;
  984                         break;
  985                 }
  986                 csr32w(ctlr, Mlc, mlc);
  987                 microdelay(1);
  988         }
  989         if(loop >= 0)
  990                 return -1;
  991         return r;
  992 }
  993 
  994 static int
  995 at24c32r(Ctlr* ctlr, int addr)
  996 {
  997         int data;
  998 
  999         /*
 1000          * Read a byte at address 'addr' from the Atmel AT24C32
 1001          * Serial EEPROM. The 2-wire EEPROM access is controlled
 1002          * by 4 bits in Mlc. See the AT24C32 datasheet for
 1003          * protocol details.
 1004          */
 1005         /*
 1006          * Start condition - a high to low transition of data
 1007          * with the clock high must precede any other command.
 1008          */
 1009         at24c32io(ctlr, "OECoc", 0);
 1010 
 1011         /*
 1012          * Perform a random read at 'addr'. A dummy byte
 1013          * write sequence is performed to clock in the device
 1014          * and data word addresses (0 and 'addr' respectively).
 1015          */
 1016         data = -1;
 1017         if(at24c32io(ctlr, "oE :DCc; oeCIc", 0xA0) != 0)
 1018                 goto stop;
 1019         if(at24c32io(ctlr, "oE :DCc; oeCIc", addr>>8) != 0)
 1020                 goto stop;
 1021         if(at24c32io(ctlr, "oE :DCc; oeCIc", addr) != 0)
 1022                 goto stop;
 1023 
 1024         /*
 1025          * Now send another start condition followed by a
 1026          * request to read the device. The EEPROM responds
 1027          * by clocking out the data.
 1028          */
 1029         at24c32io(ctlr, "OECoc", 0);
 1030         if(at24c32io(ctlr, "oE :DCc; oeCIc", 0xA1) != 0)
 1031                 goto stop;
 1032         data = at24c32io(ctlr, ":CIc;", 0xA1);
 1033 
 1034 stop:
 1035         /*
 1036          * Stop condition - a low to high transition of data
 1037          * with the clock high is a stop condition. After a read
 1038          * sequence, the stop command will place the EEPROM in
 1039          * a standby power mode.
 1040          */
 1041         at24c32io(ctlr, "oECOc", 0);
 1042 
 1043         return data;
 1044 }
 1045 
 1046 static int
 1047 ga620detach(Ctlr* ctlr)
 1048 {
 1049         int timeo;
 1050 
 1051         /*
 1052          * Hard reset (don't know which endian so catch both);
 1053          * enable for little-endian mode;
 1054          * wait for code to be loaded from serial EEPROM or flash;
 1055          * make sure CPU A is halted.
 1056          */
 1057         csr32w(ctlr, Mhc, Hr<<24 | Hr);
 1058         csr32w(ctlr, Mhc, (Eews|Ci)<<24 | Eews|Ci);
 1059 
 1060         microdelay(1);
 1061         for(timeo = 0; timeo < 500000; timeo++){
 1062                 if((csr32r(ctlr, CPUAstate) & (CPUhie|CPUrf)) == CPUhie)
 1063                         break;
 1064                 microdelay(1);
 1065         }
 1066         if((csr32r(ctlr, CPUAstate) & (CPUhie|CPUrf)) != CPUhie)
 1067                 return -1;
 1068         csr32w(ctlr, CPUAstate, CPUhalt);
 1069 
 1070         /*
 1071          * After reset, CPU B seems to be stuck in 'CPUrf'.
 1072          * Worry about it later.
 1073          */
 1074         csr32w(ctlr, CPUBstate, CPUhalt);
 1075 
 1076         return 0;
 1077 }
 1078 
 1079 static void
 1080 ga620shutdown(Ether* ether)
 1081 {
 1082 print("ga620shutdown\n");
 1083         ga620detach(ether->ctlr);
 1084 }
 1085 
 1086 static int
 1087 ga620reset(Ctlr* ctlr)
 1088 {
 1089         int cls, csr, i, r;
 1090 
 1091         if(ga620detach(ctlr) < 0)
 1092                 return -1;
 1093 
 1094         /*
 1095          * Tigon 2 PCI NICs have 512KB SRAM per bank.
 1096          * Clear out any lingering serial EEPROM state
 1097          * bits.
 1098          */
 1099         csr = csr32r(ctlr, Mlc) & ~(EEdi|EEdo|EEdoe|EEclk|SRAMmask);
 1100         csr32w(ctlr, Mlc, SRAM512|csr);
 1101         csr = csr32r(ctlr, Mc);
 1102         csr32w(ctlr, Mc, SyncSRAM|csr);
 1103 
 1104         /*
 1105          * Initialise PCI State register.
 1106          * If PCI Write-and-Invalidate is enabled set the max write DMA
 1107          * value to the host cache-line size (32 on Pentium or later).
 1108          */
 1109         csr = csr32r(ctlr, Ps) & (PCI32|PCI66);
 1110         csr |= PCIwcmd|PCIrcmd|PCImrm;
 1111         if(ctlr->pcidev->pcr & 0x0010){
 1112                 cls = pcicfgr8(ctlr->pcidev, PciCLS) * 4;
 1113                 if(cls != 32)
 1114                         pcicfgw8(ctlr->pcidev, PciCLS, 32/4);
 1115                 csr |= PCIwm32;
 1116         }
 1117         csr32w(ctlr, Ps, csr);
 1118 
 1119         /*
 1120          * Operating Mode.
 1121          */
 1122         csr32w(ctlr, Om, Fatal|NoJFrag|BswapDMA|WswapBD);
 1123 
 1124         /*
 1125          * Snarf the MAC address from the serial EEPROM.
 1126          */
 1127         for(i = 0; i < Eaddrlen; i++){
 1128                 if((r = at24c32r(ctlr, 0x8E+i)) == -1)
 1129                         return -1;
 1130                 ctlr->ea[i] = r;
 1131         }
 1132 
 1133         /*
 1134          * Load the firmware.
 1135          */
 1136         ga620lmw(ctlr, tigon2FwTextAddr, tigon2FwText, tigon2FwTextLen);
 1137         ga620lmw(ctlr, tigon2FwRodataAddr, tigon2FwRodata, tigon2FwRodataLen);
 1138         ga620lmw(ctlr, tigon2FwDataAddr, tigon2FwData, tigon2FwDataLen);
 1139         ga620lmw(ctlr, tigon2FwSbssAddr, nil, tigon2FwSbssLen);
 1140         ga620lmw(ctlr, tigon2FwBssAddr, nil, tigon2FwBssLen);
 1141 
 1142         return 0;
 1143 }
 1144 
 1145 static void
 1146 ga620pci(void)
 1147 {
 1148         void *mem;
 1149         Pcidev *p;
 1150         Ctlr *ctlr;
 1151 
 1152         p = nil;
 1153         while(p = pcimatch(p, 0, 0)){
 1154                 if(p->ccrb != 0x02 || p->ccru != 0)
 1155                         continue;
 1156 
 1157                 switch(p->did<<16 | p->vid){
 1158                 default:
 1159                         continue;
 1160                 case 0x620A<<16 | 0x1385:       /* Netgear GA620 fiber */
 1161                 case 0x630A<<16 | 0x1385:       /* Netgear GA620T copper */
 1162                 case 0x0001<<16 | 0x12AE:       /* Alteon Acenic fiber
 1163                                                  * and DEC DEGPA-SA */
 1164                 case 0x0002<<16 | 0x12AE:       /* Alteon Acenic copper */
 1165                 case 0x0009<<16 | 0x10A9:       /* SGI Acenic */
 1166                         break;
 1167                 }
 1168 
 1169                 mem = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
 1170                 if(mem == 0){
 1171                         print("ga620: can't map %8.8luX\n", p->mem[0].bar);
 1172                         continue;
 1173                 }
 1174 
 1175                 ctlr = malloc(sizeof(Ctlr));
 1176                 ctlr->port = p->mem[0].bar & ~0x0F;
 1177                 ctlr->pcidev = p;
 1178                 ctlr->id = p->did<<16 | p->vid;
 1179 
 1180                 ctlr->nic = mem;
 1181                 if(ga620reset(ctlr)){
 1182                         free(ctlr);
 1183                         continue;
 1184                 }
 1185 
 1186                 if(ctlrhead != nil)
 1187                         ctlrtail->next = ctlr;
 1188                 else
 1189                         ctlrhead = ctlr;
 1190                 ctlrtail = ctlr;
 1191         }
 1192 }
 1193 
 1194 static void
 1195 ga620promiscuous(void *arg, int on)
 1196 {
 1197         Ether *ether = arg;
 1198 
 1199         /* 3rd arg: 1 enables, 2 disables */
 1200         ga620command(ether->ctlr, 0xa, (on? 1: 2), 0);
 1201 }
 1202 
 1203 static void
 1204 ga620multicast(void *arg, uchar *addr, int add)
 1205 {
 1206         Ether *ether = arg;
 1207 
 1208         USED(addr);
 1209         if (add)
 1210                 ga620command(ether->ctlr, 0xe, 1, 0);   /* 1 == enable */
 1211 }
 1212 
 1213 static int
 1214 ga620pnp(Ether* edev)
 1215 {
 1216         Ctlr *ctlr;
 1217         uchar ea[Eaddrlen];
 1218 
 1219         if(ctlrhead == nil)
 1220                 ga620pci();
 1221 
 1222         /*
 1223          * Any adapter matches if no edev->port is supplied,
 1224          * otherwise the ports must match.
 1225          */
 1226         for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
 1227                 if(ctlr->active)
 1228                         continue;
 1229                 if(edev->port == 0 || edev->port == ctlr->port){
 1230                         ctlr->active = 1;
 1231                         break;
 1232                 }
 1233         }
 1234         if(ctlr == nil)
 1235                 return -1;
 1236 
 1237         edev->ctlr = ctlr;
 1238         edev->port = ctlr->port;
 1239         edev->irq = ctlr->pcidev->intl;
 1240         edev->tbdf = ctlr->pcidev->tbdf;
 1241         edev->mbps = 1000;              /* placeholder */
 1242 
 1243         /*
 1244          * Check if the adapter's station address is to be overridden.
 1245          * If not, read it from the EEPROM and set in ether->ea prior to
 1246          * loading the station address in the hardware.
 1247          */
 1248         memset(ea, 0, Eaddrlen);
 1249         if(memcmp(ea, edev->ea, Eaddrlen) == 0)
 1250                 memmove(edev->ea, ctlr->ea, Eaddrlen);
 1251 
 1252         ga620init(edev);
 1253 
 1254         /*
 1255          * Linkage to the generic ethernet driver.
 1256          */
 1257         edev->attach = ga620attach;
 1258         edev->transmit = ga620transmit;
 1259         edev->interrupt = ga620interrupt;
 1260         edev->ifstat = ga620ifstat;
 1261         edev->ctl = ga620ctl;
 1262 
 1263         edev->arg = edev;
 1264         edev->promiscuous = ga620promiscuous;
 1265         edev->multicast = ga620multicast;
 1266         edev->shutdown = ga620shutdown;
 1267 
 1268         return 0;
 1269 }
 1270 
 1271 void
 1272 etherga620link(void)
 1273 {
 1274         addethercard("GA620", ga620pnp);
 1275 }

Cache object: 2bd929b45256f32bed527a991cc19a90


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