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/ether82557.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 82557 Fast Ethernet PCI Bus LAN Controller
    3  * as found on the Intel EtherExpress PRO/100B. This chip is full
    4  * of smarts, unfortunately they're not all in the right place.
    5  * To do:
    6  *      the PCI scanning code could be made common to other adapters;
    7  *      auto-negotiation, full-duplex;
    8  *      optionally use memory-mapped registers;
    9  *      detach for PCI reset problems (also towards loadable drivers).
   10  */
   11 #include "u.h"
   12 #include "../port/lib.h"
   13 #include "mem.h"
   14 #include "dat.h"
   15 #include "fns.h"
   16 #include "io.h"
   17 #include "../port/error.h"
   18 #include "../port/netif.h"
   19 
   20 #include "etherif.h"
   21 
   22 enum {
   23         Nrfd            = 64,           /* receive frame area */
   24         Ncb             = 64,           /* maximum control blocks queued */
   25 
   26         NullPointer     = 0xFFFFFFFF,   /* 82557 NULL pointer */
   27 };
   28 
   29 enum {                                  /* CSR */
   30         Status          = 0x00,         /* byte or word (word includes Ack) */
   31         Ack             = 0x01,         /* byte */
   32         CommandR        = 0x02,         /* byte or word (word includes Interrupt) */
   33         Interrupt       = 0x03,         /* byte */
   34         General         = 0x04,         /* dword */
   35         Port            = 0x08,         /* dword */
   36         Fcr             = 0x0C,         /* Flash control register */
   37         Ecr             = 0x0E,         /* EEPROM control register */
   38         Mcr             = 0x10,         /* MDI control register */
   39         Gstatus         = 0x1D,         /* General status register */
   40 };
   41 
   42 enum {                                  /* Status */
   43         RUidle          = 0x0000,
   44         RUsuspended     = 0x0004,
   45         RUnoresources   = 0x0008,
   46         RUready         = 0x0010,
   47         RUrbd           = 0x0020,       /* bit */
   48         RUstatus        = 0x003F,       /* mask */
   49 
   50         CUidle          = 0x0000,
   51         CUsuspended     = 0x0040,
   52         CUactive        = 0x0080,
   53         CUstatus        = 0x00C0,       /* mask */
   54 
   55         StatSWI         = 0x0400,       /* SoftWare generated Interrupt */
   56         StatMDI         = 0x0800,       /* MDI r/w done */
   57         StatRNR         = 0x1000,       /* Receive unit Not Ready */
   58         StatCNA         = 0x2000,       /* Command unit Not Active (Active->Idle) */
   59         StatFR          = 0x4000,       /* Finished Receiving */
   60         StatCX          = 0x8000,       /* Command eXecuted */
   61         StatTNO         = 0x8000,       /* Transmit NOT OK */
   62 };
   63 
   64 enum {                                  /* Command (byte) */
   65         CUnop           = 0x00,
   66         CUstart         = 0x10,
   67         CUresume        = 0x20,
   68         LoadDCA         = 0x40,         /* Load Dump Counters Address */
   69         DumpSC          = 0x50,         /* Dump Statistical Counters */
   70         LoadCUB         = 0x60,         /* Load CU Base */
   71         ResetSA         = 0x70,         /* Dump and Reset Statistical Counters */
   72 
   73         RUstart         = 0x01,
   74         RUresume        = 0x02,
   75         RUabort         = 0x04,
   76         LoadHDS         = 0x05,         /* Load Header Data Size */
   77         LoadRUB         = 0x06,         /* Load RU Base */
   78         RBDresume       = 0x07,         /* Resume frame reception */
   79 };
   80 
   81 enum {                                  /* Interrupt (byte) */
   82         InterruptM      = 0x01,         /* interrupt Mask */
   83         InterruptSI     = 0x02,         /* Software generated Interrupt */
   84 };
   85 
   86 enum {                                  /* Ecr */
   87         EEsk            = 0x01,         /* serial clock */
   88         EEcs            = 0x02,         /* chip select */
   89         EEdi            = 0x04,         /* serial data in */
   90         EEdo            = 0x08,         /* serial data out */
   91 
   92         EEstart         = 0x04,         /* start bit */
   93         EEread          = 0x02,         /* read opcode */
   94 };
   95 
   96 enum {                                  /* Mcr */
   97         MDIread         = 0x08000000,   /* read opcode */
   98         MDIwrite        = 0x04000000,   /* write opcode */
   99         MDIready        = 0x10000000,   /* ready bit */
  100         MDIie           = 0x20000000,   /* interrupt enable */
  101 };
  102 
  103 typedef struct Rfd {
  104         int     field;
  105         ulong   link;
  106         ulong   rbd;
  107         ushort  count;
  108         ushort  size;
  109 
  110         uchar   data[1700];
  111 } Rfd;
  112 
  113 enum {                                  /* field */
  114         RfdCollision    = 0x00000001,
  115         RfdIA           = 0x00000002,   /* IA match */
  116         RfdRxerr        = 0x00000010,   /* PHY character error */
  117         RfdType         = 0x00000020,   /* Type frame */
  118         RfdRunt         = 0x00000080,
  119         RfdOverrun      = 0x00000100,
  120         RfdBuffer       = 0x00000200,
  121         RfdAlignment    = 0x00000400,
  122         RfdCRC          = 0x00000800,
  123 
  124         RfdOK           = 0x00002000,   /* frame received OK */
  125         RfdC            = 0x00008000,   /* reception Complete */
  126         RfdSF           = 0x00080000,   /* Simplified or Flexible (1) Rfd */
  127         RfdH            = 0x00100000,   /* Header RFD */
  128 
  129         RfdI            = 0x20000000,   /* Interrupt after completion */
  130         RfdS            = 0x40000000,   /* Suspend after completion */
  131         RfdEL           = 0x80000000,   /* End of List */
  132 };
  133 
  134 enum {                                  /* count */
  135         RfdF            = 0x4000,
  136         RfdEOF          = 0x8000,
  137 };
  138 
  139 typedef struct Cb Cb;
  140 typedef struct Cb {
  141         ushort  status;
  142         ushort  command;
  143         ulong   link;
  144         union {
  145                 uchar   data[24];       /* CbIAS + CbConfigure */
  146                 struct {
  147                         ulong   tbd;
  148                         ushort  count;
  149                         uchar   threshold;
  150                         uchar   number;
  151 
  152                         ulong   tba;
  153                         ushort  tbasz;
  154                         ushort  pad;
  155                 };
  156         };
  157 
  158         Block*  bp;
  159         Cb*     next;
  160 } Cb;
  161 
  162 enum {                                  /* action command */
  163         CbU             = 0x1000,       /* transmit underrun */
  164         CbOK            = 0x2000,       /* DMA completed OK */
  165         CbC             = 0x8000,       /* execution Complete */
  166 
  167         CbNOP           = 0x0000,
  168         CbIAS           = 0x0001,       /* Individual Address Setup */
  169         CbConfigure     = 0x0002,
  170         CbMAS           = 0x0003,       /* Multicast Address Setup */
  171         CbTransmit      = 0x0004,
  172         CbDump          = 0x0006,
  173         CbDiagnose      = 0x0007,
  174         CbCommand       = 0x0007,       /* mask */
  175 
  176         CbSF            = 0x0008,       /* Flexible-mode CbTransmit */
  177 
  178         CbI             = 0x2000,       /* Interrupt after completion */
  179         CbS             = 0x4000,       /* Suspend after completion */
  180         CbEL            = 0x8000,       /* End of List */
  181 };
  182 
  183 enum {                                  /* CbTransmit count */
  184         CbEOF           = 0x8000,
  185 };
  186 
  187 typedef struct Ctlr Ctlr;
  188 typedef struct Ctlr {
  189         Lock    slock;                  /* attach */
  190         int     state;
  191 
  192         int     port;
  193         Pcidev* pcidev;
  194         Ctlr*   next;
  195         int     active;
  196 
  197         int     eepromsz;               /* address size in bits */
  198         ushort* eeprom;
  199 
  200         Lock    miilock;
  201 
  202         int     tick;
  203 
  204         Lock    rlock;                  /* registers */
  205         int     command;                /* last command issued */
  206 
  207         Block*  rfdhead;                /* receive side */
  208         Block*  rfdtail;
  209         int     nrfd;
  210 
  211         Lock    cblock;                 /* transmit side */
  212         int     action;
  213         int     nop;
  214         uchar   configdata[24];
  215         int     threshold;
  216         int     ncb;
  217         Cb*     cbr;
  218         Cb*     cbhead;
  219         Cb*     cbtail;
  220         int     cbq;
  221         int     cbqmax;
  222         int     cbqmaxhw;
  223 
  224         Lock    dlock;                  /* dump statistical counters */
  225         ulong   dump[17];
  226 } Ctlr;
  227 
  228 static Ctlr* ctlrhead;
  229 static Ctlr* ctlrtail;
  230 
  231 static uchar configdata[24] = {
  232         0x16,                           /* byte count */
  233         0x08,                           /* Rx/Tx FIFO limit */
  234         0x00,                           /* adaptive IFS */
  235         0x00,   
  236         0x00,                           /* Rx DMA maximum byte count */
  237 //      0x80,                           /* Tx DMA maximum byte count */
  238         0x00,                           /* Tx DMA maximum byte count */
  239         0x32,                           /* !late SCB, CNA interrupts */
  240         0x03,                           /* discard short Rx frames */
  241         0x00,                           /* 503/MII */
  242 
  243         0x00,   
  244         0x2E,                           /* normal operation, NSAI */
  245         0x00,                           /* linear priority */
  246         0x60,                           /* inter-frame spacing */
  247         0x00,   
  248         0xF2,   
  249         0xC8,                           /* 503, promiscuous mode off */
  250         0x00,   
  251         0x40,   
  252         0xF3,                           /* transmit padding enable */
  253         0x80,                           /* full duplex pin enable */
  254         0x3F,                           /* no Multi IA */
  255         0x05,                           /* no Multi Cast ALL */
  256 };
  257 
  258 #define csr8r(c, r)     (inb((c)->port+(r)))
  259 #define csr16r(c, r)    (ins((c)->port+(r)))
  260 #define csr32r(c, r)    (inl((c)->port+(r)))
  261 #define csr8w(c, r, b)  (outb((c)->port+(r), (int)(b)))
  262 #define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w)))
  263 #define csr32w(c, r, l) (outl((c)->port+(r), (ulong)(l)))
  264 
  265 static void
  266 command(Ctlr* ctlr, int c, int v)
  267 {
  268         int timeo;
  269 
  270         ilock(&ctlr->rlock);
  271 
  272         /*
  273          * Only back-to-back CUresume can be done
  274          * without waiting for any previous command to complete.
  275          * This should be the common case.
  276          * Unfortunately there's a chip errata where back-to-back
  277          * CUresumes can be lost, the fix is to always wait.
  278         if(c == CUresume && ctlr->command == CUresume){
  279                 csr8w(ctlr, CommandR, c);
  280                 iunlock(&ctlr->rlock);
  281                 return;
  282         }
  283          */
  284 
  285         for(timeo = 0; timeo < 100; timeo++){
  286                 if(!csr8r(ctlr, CommandR))
  287                         break;
  288                 microdelay(1);
  289         }
  290         if(timeo >= 100){
  291                 ctlr->command = -1;
  292                 iunlock(&ctlr->rlock);
  293                 iprint("i82557: command %#ux %#ux timeout\n", c, v);
  294                 return;
  295         }
  296 
  297         switch(c){
  298 
  299         case CUstart:
  300         case LoadDCA:
  301         case LoadCUB:
  302         case RUstart:
  303         case LoadHDS:
  304         case LoadRUB:
  305                 csr32w(ctlr, General, v);
  306                 break;
  307 
  308         /*
  309         case CUnop:
  310         case CUresume:
  311         case DumpSC:
  312         case ResetSA:
  313         case RUresume:
  314         case RUabort:
  315          */
  316         default:
  317                 break;
  318         }
  319         csr8w(ctlr, CommandR, c);
  320         ctlr->command = c;
  321 
  322         iunlock(&ctlr->rlock);
  323 }
  324 
  325 static Block*
  326 rfdalloc(ulong link)
  327 {
  328         Block *bp;
  329         Rfd *rfd;
  330 
  331         if(bp = iallocb(sizeof(Rfd))){
  332                 rfd = (Rfd*)bp->rp;
  333                 rfd->field = 0;
  334                 rfd->link = link;
  335                 rfd->rbd = NullPointer;
  336                 rfd->count = 0;
  337                 rfd->size = sizeof(Etherpkt);
  338         }
  339 
  340         return bp;
  341 }
  342 
  343 static void
  344 watchdog(void* arg)
  345 {
  346         Ether *ether;
  347         Ctlr *ctlr;
  348         static void txstart(Ether*);
  349 
  350         ether = arg;
  351         for(;;){
  352                 tsleep(&up->sleep, return0, 0, 4000);
  353 
  354                 /*
  355                  * Hmmm. This doesn't seem right. Currently
  356                  * the device can't be disabled but it may be in
  357                  * the future.
  358                  */
  359                 ctlr = ether->ctlr;
  360                 if(ctlr == nil || ctlr->state == 0){
  361                         print("%s: exiting\n", up->text);
  362                         pexit("disabled", 0);
  363                 }
  364 
  365                 ilock(&ctlr->cblock);
  366                 if(ctlr->tick++){
  367                         ctlr->action = CbMAS;
  368                         txstart(ether);
  369                 }
  370                 iunlock(&ctlr->cblock);
  371         }
  372 }
  373 
  374 static void
  375 attach(Ether* ether)
  376 {
  377         Ctlr *ctlr;
  378         char name[KNAMELEN];
  379 
  380         ctlr = ether->ctlr;
  381         lock(&ctlr->slock);
  382         if(ctlr->state == 0){
  383                 ilock(&ctlr->rlock);
  384                 csr8w(ctlr, Interrupt, 0);
  385                 iunlock(&ctlr->rlock);
  386                 command(ctlr, RUstart, PADDR(ctlr->rfdhead->rp));
  387                 ctlr->state = 1;
  388 
  389                 /*
  390                  * Start the watchdog timer for the receive lockup errata
  391                  * unless the EEPROM compatibility word indicates it may be
  392                  * omitted.
  393                  */
  394                 if((ctlr->eeprom[0x03] & 0x0003) != 0x0003){
  395                         snprint(name, KNAMELEN, "#l%dwatchdog", ether->ctlrno);
  396                         kproc(name, watchdog, ether);
  397                 }
  398         }
  399         unlock(&ctlr->slock);
  400 }
  401 
  402 static long
  403 ifstat(Ether* ether, void* a, long n, ulong offset)
  404 {
  405         char *p;
  406         int i, len, phyaddr;
  407         Ctlr *ctlr;
  408         ulong dump[17];
  409 
  410         ctlr = ether->ctlr;
  411         lock(&ctlr->dlock);
  412 
  413         /*
  414          * Start the command then
  415          * wait for completion status,
  416          * should be 0xA005.
  417          */
  418         ctlr->dump[16] = 0;
  419         command(ctlr, DumpSC, 0);
  420         while(ctlr->dump[16] == 0)
  421                 ;
  422 
  423         ether->oerrs = ctlr->dump[1]+ctlr->dump[2]+ctlr->dump[3];
  424         ether->crcs = ctlr->dump[10];
  425         ether->frames = ctlr->dump[11];
  426         ether->buffs = ctlr->dump[12]+ctlr->dump[15];
  427         ether->overflows = ctlr->dump[13];
  428 
  429         if(n == 0){
  430                 unlock(&ctlr->dlock);
  431                 return 0;
  432         }
  433 
  434         memmove(dump, ctlr->dump, sizeof(dump));
  435         unlock(&ctlr->dlock);
  436 
  437         p = malloc(READSTR);
  438         len = snprint(p, READSTR, "transmit good frames: %lud\n", dump[0]);
  439         len += snprint(p+len, READSTR-len, "transmit maximum collisions errors: %lud\n", dump[1]);
  440         len += snprint(p+len, READSTR-len, "transmit late collisions errors: %lud\n", dump[2]);
  441         len += snprint(p+len, READSTR-len, "transmit underrun errors: %lud\n", dump[3]);
  442         len += snprint(p+len, READSTR-len, "transmit lost carrier sense: %lud\n", dump[4]);
  443         len += snprint(p+len, READSTR-len, "transmit deferred: %lud\n", dump[5]);
  444         len += snprint(p+len, READSTR-len, "transmit single collisions: %lud\n", dump[6]);
  445         len += snprint(p+len, READSTR-len, "transmit multiple collisions: %lud\n", dump[7]);
  446         len += snprint(p+len, READSTR-len, "transmit total collisions: %lud\n", dump[8]);
  447         len += snprint(p+len, READSTR-len, "receive good frames: %lud\n", dump[9]);
  448         len += snprint(p+len, READSTR-len, "receive CRC errors: %lud\n", dump[10]);
  449         len += snprint(p+len, READSTR-len, "receive alignment errors: %lud\n", dump[11]);
  450         len += snprint(p+len, READSTR-len, "receive resource errors: %lud\n", dump[12]);
  451         len += snprint(p+len, READSTR-len, "receive overrun errors: %lud\n", dump[13]);
  452         len += snprint(p+len, READSTR-len, "receive collision detect errors: %lud\n", dump[14]);
  453         len += snprint(p+len, READSTR-len, "receive short frame errors: %lud\n", dump[15]);
  454         len += snprint(p+len, READSTR-len, "nop: %d\n", ctlr->nop);
  455         if(ctlr->cbqmax > ctlr->cbqmaxhw)
  456                 ctlr->cbqmaxhw = ctlr->cbqmax;
  457         len += snprint(p+len, READSTR-len, "cbqmax: %d\n", ctlr->cbqmax);
  458         ctlr->cbqmax = 0;
  459         len += snprint(p+len, READSTR-len, "threshold: %d\n", ctlr->threshold);
  460 
  461         len += snprint(p+len, READSTR-len, "eeprom:");
  462         for(i = 0; i < (1<<ctlr->eepromsz); i++){
  463                 if(i && ((i & 0x07) == 0))
  464                         len += snprint(p+len, READSTR-len, "\n       ");
  465                 len += snprint(p+len, READSTR-len, " %4.4ux", ctlr->eeprom[i]);
  466         }
  467 
  468         if((ctlr->eeprom[6] & 0x1F00) && !(ctlr->eeprom[6] & 0x8000)){
  469                 phyaddr = ctlr->eeprom[6] & 0x00FF;
  470                 len += snprint(p+len, READSTR-len, "\nphy %2d:", phyaddr);
  471                 for(i = 0; i < 6; i++){
  472                         static int miir(Ctlr*, int, int);
  473 
  474                         len += snprint(p+len, READSTR-len, " %4.4ux",
  475                                 miir(ctlr, phyaddr, i));
  476                 }
  477         }
  478 
  479         snprint(p+len, READSTR-len, "\n");
  480         n = readstr(offset, a, n, p);
  481         free(p);
  482 
  483         return n;
  484 }
  485 
  486 static void
  487 txstart(Ether* ether)
  488 {
  489         Ctlr *ctlr;
  490         Block *bp;
  491         Cb *cb;
  492 
  493         ctlr = ether->ctlr;
  494         while(ctlr->cbq < (ctlr->ncb-1)){
  495                 cb = ctlr->cbhead->next;
  496                 if(ctlr->action == 0){
  497                         bp = qget(ether->oq);
  498                         if(bp == nil)
  499                                 break;
  500 
  501                         cb->command = CbS|CbSF|CbTransmit;
  502                         cb->tbd = PADDR(&cb->tba);
  503                         cb->count = 0;
  504                         cb->threshold = ctlr->threshold;
  505                         cb->number = 1;
  506                         cb->tba = PADDR(bp->rp);
  507                         cb->bp = bp;
  508                         cb->tbasz = BLEN(bp);
  509                 }
  510                 else if(ctlr->action == CbConfigure){
  511                         cb->command = CbS|CbConfigure;
  512                         memmove(cb->data, ctlr->configdata, sizeof(ctlr->configdata));
  513                         ctlr->action = 0;
  514                 }
  515                 else if(ctlr->action == CbIAS){
  516                         cb->command = CbS|CbIAS;
  517                         memmove(cb->data, ether->ea, Eaddrlen);
  518                         ctlr->action = 0;
  519                 }
  520                 else if(ctlr->action == CbMAS){
  521                         cb->command = CbS|CbMAS;
  522                         memset(cb->data, 0, sizeof(cb->data));
  523                         ctlr->action = 0;
  524                 }
  525                 else{
  526                         print("#l%d: action %#ux\n", ether->ctlrno, ctlr->action);
  527                         ctlr->action = 0;
  528                         break;
  529                 }
  530                 cb->status = 0;
  531 
  532                 coherence();
  533                 ctlr->cbhead->command &= ~CbS;
  534                 ctlr->cbhead = cb;
  535                 ctlr->cbq++;
  536         }
  537 
  538         /*
  539          * Workaround for some broken HUB chips
  540          * when connected at 10Mb/s half-duplex.
  541          */
  542         if(ctlr->nop){
  543                 command(ctlr, CUnop, 0);
  544                 microdelay(1);
  545         }
  546         command(ctlr, CUresume, 0);
  547 
  548         if(ctlr->cbq > ctlr->cbqmax)
  549                 ctlr->cbqmax = ctlr->cbq;
  550 }
  551 
  552 static void
  553 configure(Ether* ether, int promiscuous)
  554 {
  555         Ctlr *ctlr;
  556 
  557         ctlr = ether->ctlr;
  558         ilock(&ctlr->cblock);
  559         if(promiscuous){
  560                 ctlr->configdata[6] |= 0x80;            /* Save Bad Frames */
  561                 //ctlr->configdata[6] &= ~0x40;         /* !Discard Overrun Rx Frames */
  562                 ctlr->configdata[7] &= ~0x01;           /* !Discard Short Rx Frames */
  563                 ctlr->configdata[15] |= 0x01;           /* Promiscuous mode */
  564                 ctlr->configdata[18] &= ~0x01;          /* (!Padding enable?), !stripping enable */
  565                 ctlr->configdata[21] |= 0x08;           /* Multi Cast ALL */
  566         }
  567         else{
  568                 ctlr->configdata[6] &= ~0x80;
  569                 //ctlr->configdata[6] |= 0x40;
  570                 ctlr->configdata[7] |= 0x01;
  571                 ctlr->configdata[15] &= ~0x01;
  572                 ctlr->configdata[18] |= 0x01;           /* 0x03? */
  573                 ctlr->configdata[21] &= ~0x08;
  574         }
  575         ctlr->action = CbConfigure;
  576         txstart(ether);
  577         iunlock(&ctlr->cblock);
  578 }
  579 
  580 static void
  581 promiscuous(void* arg, int on)
  582 {
  583         configure(arg, on);
  584 }
  585 
  586 static void
  587 multicast(void* ether, uchar *addr, int add)
  588 {
  589         USED(addr);
  590         /*
  591          * TODO: if (add) add addr to list of mcast addrs in controller
  592          *      else remove addr from list of mcast addrs in controller
  593          * enable multicast input (see CbMAS) instead of promiscuous mode.
  594          */
  595         if (add)
  596                 configure(ether, 1);
  597 }
  598 
  599 static void
  600 transmit(Ether* ether)
  601 {
  602         Ctlr *ctlr;
  603 
  604         ctlr = ether->ctlr;
  605         ilock(&ctlr->cblock);
  606         txstart(ether);
  607         iunlock(&ctlr->cblock);
  608 }
  609 
  610 static void
  611 receive(Ether* ether)
  612 {
  613         Rfd *rfd;
  614         Ctlr *ctlr;
  615         int count;
  616         Block *bp, *pbp, *xbp;
  617 
  618         ctlr = ether->ctlr;
  619         bp = ctlr->rfdhead;
  620         for(rfd = (Rfd*)bp->rp; rfd->field & RfdC; rfd = (Rfd*)bp->rp){
  621                 /*
  622                  * If it's an OK receive frame
  623                  * 1) save the count 
  624                  * 2) if it's small, try to allocate a block and copy
  625                  *    the data, then adjust the necessary fields for reuse;
  626                  * 3) if it's big, try to allocate a new Rfd and if
  627                  *    successful
  628                  *      adjust the received buffer pointers for the
  629                  *        actual data received;
  630                  *      initialise the replacement buffer to point to
  631                  *        the next in the ring;
  632                  *      initialise bp to point to the replacement;
  633                  * 4) if there's a good packet, pass it on for disposal.
  634                  */
  635                 if(rfd->field & RfdOK){
  636                         pbp = nil;
  637                         count = rfd->count & 0x3FFF;
  638                         if((count < ETHERMAXTU/4) && (pbp = iallocb(count))){
  639                                 memmove(pbp->rp, bp->rp+offsetof(Rfd, data[0]), count);
  640                                 pbp->wp = pbp->rp + count;
  641 
  642                                 rfd->count = 0;
  643                                 rfd->field = 0;
  644                         }
  645                         else if(xbp = rfdalloc(rfd->link)){
  646                                 bp->rp += offsetof(Rfd, data[0]);
  647                                 bp->wp = bp->rp + count;
  648 
  649                                 xbp->next = bp->next;
  650                                 bp->next = 0;
  651 
  652                                 pbp = bp;
  653                                 bp = xbp;
  654                         }
  655                         if(pbp != nil)
  656                                 etheriq(ether, pbp, 1);
  657                 }
  658                 else{
  659                         rfd->count = 0;
  660                         rfd->field = 0;
  661                 }
  662 
  663                 /*
  664                  * The ring tail pointer follows the head with with one
  665                  * unused buffer in between to defeat hardware prefetch;
  666                  * once the tail pointer has been bumped on to the next
  667                  * and the new tail has the Suspend bit set, it can be
  668                  * removed from the old tail buffer.
  669                  * As a replacement for the current head buffer may have
  670                  * been allocated above, ensure that the new tail points
  671                  * to it (next and link).
  672                  */
  673                 rfd = (Rfd*)ctlr->rfdtail->rp;
  674                 ctlr->rfdtail = ctlr->rfdtail->next;
  675                 ctlr->rfdtail->next = bp;
  676                 ((Rfd*)ctlr->rfdtail->rp)->link = PADDR(bp->rp);
  677                 ((Rfd*)ctlr->rfdtail->rp)->field |= RfdS;
  678                 coherence();
  679                 rfd->field &= ~RfdS;
  680 
  681                 /*
  682                  * Finally done with the current (possibly replaced)
  683                  * head, move on to the next and maintain the sentinel
  684                  * between tail and head.
  685                  */
  686                 ctlr->rfdhead = bp->next;
  687                 bp = ctlr->rfdhead;
  688         }
  689 }
  690 
  691 static void
  692 interrupt(Ureg*, void* arg)
  693 {
  694         Cb* cb;
  695         Ctlr *ctlr;
  696         Ether *ether;
  697         int status;
  698 
  699         ether = arg;
  700         ctlr = ether->ctlr;
  701 
  702         for(;;){
  703                 ilock(&ctlr->rlock);
  704                 status = csr16r(ctlr, Status);
  705                 csr8w(ctlr, Ack, (status>>8) & 0xFF);
  706                 iunlock(&ctlr->rlock);
  707 
  708                 if(!(status & (StatCX|StatFR|StatCNA|StatRNR|StatMDI|StatSWI)))
  709                         break;
  710 
  711                 /*
  712                  * If the watchdog timer for the receiver lockup errata is running,
  713                  * let it know the receiver is active.
  714                  */
  715                 if(status & (StatFR|StatRNR)){
  716                         ilock(&ctlr->cblock);
  717                         ctlr->tick = 0;
  718                         iunlock(&ctlr->cblock);
  719                 }
  720 
  721                 if(status & StatFR){
  722                         receive(ether);
  723                         status &= ~StatFR;
  724                 }
  725 
  726                 if(status & StatRNR){
  727                         command(ctlr, RUresume, 0);
  728                         status &= ~StatRNR;
  729                 }
  730 
  731                 if(status & StatCNA){
  732                         ilock(&ctlr->cblock);
  733 
  734                         cb = ctlr->cbtail;
  735                         while(ctlr->cbq){
  736                                 if(!(cb->status & CbC))
  737                                         break;
  738                                 if(cb->bp){
  739                                         freeb(cb->bp);
  740                                         cb->bp = nil;
  741                                 }
  742                                 if((cb->status & CbU) && ctlr->threshold < 0xE0)
  743                                         ctlr->threshold++;
  744 
  745                                 ctlr->cbq--;
  746                                 cb = cb->next;
  747                         }
  748                         ctlr->cbtail = cb;
  749 
  750                         txstart(ether);
  751                         iunlock(&ctlr->cblock);
  752 
  753                         status &= ~StatCNA;
  754                 }
  755 
  756                 if(status & (StatCX|StatFR|StatCNA|StatRNR|StatMDI|StatSWI))
  757                         panic("#l%d: status %#ux\n", ether->ctlrno, status);
  758         }
  759 }
  760 
  761 static void
  762 ctlrinit(Ctlr* ctlr)
  763 {
  764         int i;
  765         Block *bp;
  766         Rfd *rfd;
  767         ulong link;
  768 
  769         /*
  770          * Create the Receive Frame Area (RFA) as a ring of allocated
  771          * buffers.
  772          * A sentinel buffer is maintained between the last buffer in
  773          * the ring (marked with RfdS) and the head buffer to defeat the
  774          * hardware prefetch of the next RFD and allow dynamic buffer
  775          * allocation.
  776          */
  777         link = NullPointer;
  778         for(i = 0; i < Nrfd; i++){
  779                 bp = rfdalloc(link);
  780                 if(ctlr->rfdhead == nil)
  781                         ctlr->rfdtail = bp;
  782                 bp->next = ctlr->rfdhead;
  783                 ctlr->rfdhead = bp;
  784                 link = PADDR(bp->rp);
  785         }
  786         ctlr->rfdtail->next = ctlr->rfdhead;
  787         rfd = (Rfd*)ctlr->rfdtail->rp;
  788         rfd->link = PADDR(ctlr->rfdhead->rp);
  789         rfd->field |= RfdS;
  790         ctlr->rfdhead = ctlr->rfdhead->next;
  791 
  792         /*
  793          * Create a ring of control blocks for the
  794          * transmit side.
  795          */
  796         ilock(&ctlr->cblock);
  797         ctlr->cbr = malloc(ctlr->ncb*sizeof(Cb));
  798         for(i = 0; i < ctlr->ncb; i++){
  799                 ctlr->cbr[i].status = CbC|CbOK;
  800                 ctlr->cbr[i].command = CbS|CbNOP;
  801                 ctlr->cbr[i].link = PADDR(&ctlr->cbr[NEXT(i, ctlr->ncb)].status);
  802                 ctlr->cbr[i].next = &ctlr->cbr[NEXT(i, ctlr->ncb)];
  803         }
  804         ctlr->cbhead = ctlr->cbr;
  805         ctlr->cbtail = ctlr->cbr;
  806         ctlr->cbq = 0;
  807 
  808         memmove(ctlr->configdata, configdata, sizeof(configdata));
  809         ctlr->threshold = 80;
  810         ctlr->tick = 0;
  811 
  812         iunlock(&ctlr->cblock);
  813 }
  814 
  815 static int
  816 miir(Ctlr* ctlr, int phyadd, int regadd)
  817 {
  818         int mcr, timo;
  819 
  820         lock(&ctlr->miilock);
  821         csr32w(ctlr, Mcr, MDIread|(phyadd<<21)|(regadd<<16));
  822         mcr = 0;
  823         for(timo = 64; timo; timo--){
  824                 mcr = csr32r(ctlr, Mcr);
  825                 if(mcr & MDIready)
  826                         break;
  827                 microdelay(1);
  828         }
  829         unlock(&ctlr->miilock);
  830 
  831         if(mcr & MDIready)
  832                 return mcr & 0xFFFF;
  833 
  834         return -1;
  835 }
  836 
  837 static int
  838 miiw(Ctlr* ctlr, int phyadd, int regadd, int data)
  839 {
  840         int mcr, timo;
  841 
  842         lock(&ctlr->miilock);
  843         csr32w(ctlr, Mcr, MDIwrite|(phyadd<<21)|(regadd<<16)|(data & 0xFFFF));
  844         mcr = 0;
  845         for(timo = 64; timo; timo--){
  846                 mcr = csr32r(ctlr, Mcr);
  847                 if(mcr & MDIready)
  848                         break;
  849                 microdelay(1);
  850         }
  851         unlock(&ctlr->miilock);
  852 
  853         if(mcr & MDIready)
  854                 return 0;
  855 
  856         return -1;
  857 }
  858 
  859 static int
  860 hy93c46r(Ctlr* ctlr, int r)
  861 {
  862         int data, i, op, size;
  863 
  864         /*
  865          * Hyundai HY93C46 or equivalent serial EEPROM.
  866          * This sequence for reading a 16-bit register 'r'
  867          * in the EEPROM is taken straight from Section
  868          * 3.3.4.2 of the Intel 82557 User's Guide.
  869          */
  870 reread:
  871         csr16w(ctlr, Ecr, EEcs);
  872         op = EEstart|EEread;
  873         for(i = 2; i >= 0; i--){
  874                 data = (((op>>i) & 0x01)<<2)|EEcs;
  875                 csr16w(ctlr, Ecr, data);
  876                 csr16w(ctlr, Ecr, data|EEsk);
  877                 microdelay(1);
  878                 csr16w(ctlr, Ecr, data);
  879                 microdelay(1);
  880         }
  881 
  882         /*
  883          * First time through must work out the EEPROM size.
  884          */
  885         if((size = ctlr->eepromsz) == 0)
  886                 size = 8;
  887 
  888         for(size = size-1; size >= 0; size--){
  889                 data = (((r>>size) & 0x01)<<2)|EEcs;
  890                 csr16w(ctlr, Ecr, data);
  891                 csr16w(ctlr, Ecr, data|EEsk);
  892                 delay(1);
  893                 csr16w(ctlr, Ecr, data);
  894                 microdelay(1);
  895                 if(!(csr16r(ctlr, Ecr) & EEdo))
  896                         break;
  897         }
  898 
  899         data = 0;
  900         for(i = 15; i >= 0; i--){
  901                 csr16w(ctlr, Ecr, EEcs|EEsk);
  902                 microdelay(1);
  903                 if(csr16r(ctlr, Ecr) & EEdo)
  904                         data |= (1<<i);
  905                 csr16w(ctlr, Ecr, EEcs);
  906                 microdelay(1);
  907         }
  908 
  909         csr16w(ctlr, Ecr, 0);
  910 
  911         if(ctlr->eepromsz == 0){
  912                 ctlr->eepromsz = 8-size;
  913                 ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
  914                 goto reread;
  915         }
  916 
  917         return data;
  918 }
  919 
  920 static void
  921 i82557pci(void)
  922 {
  923         Pcidev *p;
  924         Ctlr *ctlr;
  925         int i, nop, port;
  926 
  927         p = nil;
  928         nop = 0;
  929         while(p = pcimatch(p, 0x8086, 0)){
  930                 switch(p->did){
  931                 default:
  932                         continue;
  933                 case 0x1031:            /* Intel 82562EM */
  934                 case 0x1050:            /* Intel 82562EZ */
  935                 case 0x1039:            /* Intel 82801BD PRO/100 VE */
  936                 case 0x103A:            /* Intel 82562 PRO/100 VE */
  937                 case 0x103D:            /* Intel 82562 PRO/100 VE */
  938                 case 0x1064:            /* Intel 82562 PRO/100 VE */
  939                 case 0x2449:            /* Intel 82562ET */
  940                 case 0x27DC:            /* Intel 82801G PRO/100 VE */
  941                         nop = 1;
  942                         /*FALLTHROUGH*/
  943                 case 0x1209:            /* Intel 82559ER */
  944                 case 0x1229:            /* Intel 8255[789] */
  945                 case 0x1030:            /* Intel 82559 InBusiness 10/100  */
  946                         break;
  947                 }
  948 
  949                 if(pcigetpms(p) > 0){
  950                         pcisetpms(p, 0);
  951         
  952                         for(i = 0; i < 6; i++)
  953                                 pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar);
  954                         pcicfgw8(p, PciINTL, p->intl);
  955                         pcicfgw8(p, PciLTR, p->ltr);
  956                         pcicfgw8(p, PciCLS, p->cls);
  957                         pcicfgw16(p, PciPCR, p->pcr);
  958                 }
  959 
  960                 /*
  961                  * bar[0] is the memory-mapped register address (4KB),
  962                  * bar[1] is the I/O port register address (32 bytes) and
  963                  * bar[2] is for the flash ROM (1MB).
  964                  */
  965                 port = p->mem[1].bar & ~0x01;
  966                 if(ioalloc(port, p->mem[1].size, 0, "i82557") < 0){
  967                         print("i82557: port %#ux in use\n", port);
  968                         continue;
  969                 }
  970 
  971                 ctlr = malloc(sizeof(Ctlr));
  972                 ctlr->port = port;
  973                 ctlr->pcidev = p;
  974                 ctlr->nop = nop;
  975 
  976                 if(ctlrhead != nil)
  977                         ctlrtail->next = ctlr;
  978                 else
  979                         ctlrhead = ctlr;
  980                 ctlrtail = ctlr;
  981 
  982                 pcisetbme(p);
  983         }
  984 }
  985 
  986 static char* mediatable[9] = {
  987         "10BASE-T",                             /* TP */
  988         "10BASE-2",                             /* BNC */
  989         "10BASE-5",                             /* AUI */
  990         "100BASE-TX",
  991         "10BASE-TFD",
  992         "100BASE-TXFD",
  993         "100BASE-T4",
  994         "100BASE-FX",
  995         "100BASE-FXFD",
  996 };
  997 
  998 static int
  999 scanphy(Ctlr* ctlr)
 1000 {
 1001         int i, oui, x;
 1002 
 1003         for(i = 0; i < 32; i++){
 1004                 if((oui = miir(ctlr, i, 2)) == -1 || oui == 0 || oui == 0xFFFF)
 1005                         continue;
 1006                 oui <<= 6;
 1007                 x = miir(ctlr, i, 3);
 1008                 oui |= x>>10;
 1009                 //print("phy%d: oui %#ux reg1 %#ux\n", i, oui, miir(ctlr, i, 1));
 1010 
 1011                 ctlr->eeprom[6] = i;
 1012                 if(oui == 0xAA00)
 1013                         ctlr->eeprom[6] |= 0x07<<8;
 1014                 else if(oui == 0x80017){
 1015                         if(x & 0x01)
 1016                                 ctlr->eeprom[6] |= 0x0A<<8;
 1017                         else
 1018                                 ctlr->eeprom[6] |= 0x04<<8;
 1019                 }
 1020                 return i;
 1021         }
 1022         return -1;
 1023 }
 1024 
 1025 static void
 1026 shutdown(Ether* ether)
 1027 {
 1028         Ctlr *ctlr = ether->ctlr;
 1029 
 1030 print("ether82557 shutting down\n");
 1031         csr32w(ctlr, Port, 0);
 1032         delay(1);
 1033         csr8w(ctlr, Interrupt, InterruptM);
 1034 }
 1035 
 1036 
 1037 static int
 1038 reset(Ether* ether)
 1039 {
 1040         int anar, anlpar, bmcr, bmsr, i, k, medium, phyaddr, x;
 1041         unsigned short sum;
 1042         uchar ea[Eaddrlen];
 1043         Ctlr *ctlr;
 1044 
 1045         if(ctlrhead == nil)
 1046                 i82557pci();
 1047 
 1048         /*
 1049          * Any adapter matches if no ether->port is supplied,
 1050          * otherwise the ports must match.
 1051          */
 1052         for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
 1053                 if(ctlr->active)
 1054                         continue;
 1055                 if(ether->port == 0 || ether->port == ctlr->port){
 1056                         ctlr->active = 1;
 1057                         break;
 1058                 }
 1059         }
 1060         if(ctlr == nil)
 1061                 return -1;
 1062 
 1063         /*
 1064          * Initialise the Ctlr structure.
 1065          * Perform a software reset after which should ensure busmastering
 1066          * is still enabled. The EtherExpress PRO/100B appears to leave
 1067          * the PCI configuration alone (see the 'To do' list above) so punt
 1068          * for now.
 1069          * Load the RUB and CUB registers for linear addressing (0).
 1070          */
 1071         ether->ctlr = ctlr;
 1072         ether->port = ctlr->port;
 1073         ether->irq = ctlr->pcidev->intl;
 1074         ether->tbdf = ctlr->pcidev->tbdf;
 1075 
 1076         ilock(&ctlr->rlock);
 1077         csr32w(ctlr, Port, 0);
 1078         delay(1);
 1079         csr8w(ctlr, Interrupt, InterruptM);
 1080         iunlock(&ctlr->rlock);
 1081 
 1082         command(ctlr, LoadRUB, 0);
 1083         command(ctlr, LoadCUB, 0);
 1084         command(ctlr, LoadDCA, PADDR(ctlr->dump));
 1085 
 1086         /*
 1087          * Initialise the receive frame, transmit ring and configuration areas.
 1088          */
 1089         ctlr->ncb = Ncb;
 1090         ctlrinit(ctlr);
 1091 
 1092         /*
 1093          * Read the EEPROM.
 1094          * Do a dummy read first to get the size
 1095          * and allocate ctlr->eeprom.
 1096          */
 1097         hy93c46r(ctlr, 0);
 1098         sum = 0;
 1099         for(i = 0; i < (1<<ctlr->eepromsz); i++){
 1100                 x = hy93c46r(ctlr, i);
 1101                 ctlr->eeprom[i] = x;
 1102                 sum += x;
 1103         }
 1104         if(sum != 0xBABA)
 1105                 print("#l%d: EEPROM checksum - %#4.4ux\n", ether->ctlrno, sum);
 1106 
 1107         /*
 1108          * Eeprom[6] indicates whether there is a PHY and whether
 1109          * it's not 10Mb-only, in which case use the given PHY address
 1110          * to set any PHY specific options and determine the speed.
 1111          * Unfortunately, sometimes the EEPROM is blank except for
 1112          * the ether address and checksum; in this case look at the
 1113          * controller type and if it's am 82558 or 82559 it has an
 1114          * embedded PHY so scan for that.
 1115          * If no PHY, assume 82503 (serial) operation.
 1116          */
 1117         if((ctlr->eeprom[6] & 0x1F00) && !(ctlr->eeprom[6] & 0x8000))
 1118                 phyaddr = ctlr->eeprom[6] & 0x00FF;
 1119         else
 1120         switch(ctlr->pcidev->rid){
 1121         case 0x01:                      /* 82557 A-step */
 1122         case 0x02:                      /* 82557 B-step */
 1123         case 0x03:                      /* 82557 C-step */
 1124         default:
 1125                 phyaddr = -1;
 1126                 break;
 1127         case 0x04:                      /* 82558 A-step */
 1128         case 0x05:                      /* 82558 B-step */
 1129         case 0x06:                      /* 82559 A-step */
 1130         case 0x07:                      /* 82559 B-step */
 1131         case 0x08:                      /* 82559 C-step */
 1132         case 0x09:                      /* 82559ER A-step */
 1133                 phyaddr = scanphy(ctlr);
 1134                 break;
 1135         }
 1136         if(phyaddr >= 0){
 1137                 /*
 1138                  * Resolve the highest common ability of the two
 1139                  * link partners. In descending order:
 1140                  *      0x0100          100BASE-TX Full Duplex
 1141                  *      0x0200          100BASE-T4
 1142                  *      0x0080          100BASE-TX
 1143                  *      0x0040          10BASE-T Full Duplex
 1144                  *      0x0020          10BASE-T
 1145                  */
 1146                 anar = miir(ctlr, phyaddr, 0x04);
 1147                 anlpar = miir(ctlr, phyaddr, 0x05) & 0x03E0;
 1148                 anar &= anlpar;
 1149                 bmcr = 0;
 1150                 if(anar & 0x380)
 1151                         bmcr = 0x2000;
 1152                 if(anar & 0x0140)
 1153                         bmcr |= 0x0100;
 1154 
 1155                 switch((ctlr->eeprom[6]>>8) & 0x001F){
 1156 
 1157                 case 0x04:                              /* DP83840 */
 1158                 case 0x0A:                              /* DP83840A */
 1159                         /*
 1160                          * The DP83840[A] requires some tweaking for
 1161                          * reliable operation.
 1162                          * The manual says bit 10 should be unconditionally
 1163                          * set although it supposedly only affects full-duplex
 1164                          * operation (an & 0x0140).
 1165                          */
 1166                         x = miir(ctlr, phyaddr, 0x17) & ~0x0520;
 1167                         x |= 0x0420;
 1168                         for(i = 0; i < ether->nopt; i++){
 1169                                 if(cistrcmp(ether->opt[i], "congestioncontrol"))
 1170                                         continue;
 1171                                 x |= 0x0100;
 1172                                 break;
 1173                         }
 1174                         miiw(ctlr, phyaddr, 0x17, x);
 1175 
 1176                         /*
 1177                          * If the link partner can't autonegotiate, determine
 1178                          * the speed from elsewhere.
 1179                          */
 1180                         if(anlpar == 0){
 1181                                 miir(ctlr, phyaddr, 0x01);
 1182                                 bmsr = miir(ctlr, phyaddr, 0x01);
 1183                                 x = miir(ctlr, phyaddr, 0x19);
 1184                                 if((bmsr & 0x0004) && !(x & 0x0040))
 1185                                         bmcr = 0x2000;
 1186                         }
 1187                         break;
 1188 
 1189                 case 0x07:                              /* Intel 82555 */
 1190                         /*
 1191                          * Auto-negotiation may fail if the other end is
 1192                          * a DP83840A and the cable is short.
 1193                          */
 1194                         miir(ctlr, phyaddr, 0x01);
 1195                         bmsr = miir(ctlr, phyaddr, 0x01);
 1196                         if((miir(ctlr, phyaddr, 0) & 0x1000) && !(bmsr & 0x0020)){
 1197                                 miiw(ctlr, phyaddr, 0x1A, 0x2010);
 1198                                 x = miir(ctlr, phyaddr, 0);
 1199                                 miiw(ctlr, phyaddr, 0, 0x0200|x);
 1200                                 for(i = 0; i < 3000; i++){
 1201                                         delay(1);
 1202                                         if(miir(ctlr, phyaddr, 0x01) & 0x0020)
 1203                                                 break;
 1204                                 }
 1205                                 miiw(ctlr, phyaddr, 0x1A, 0x2000);
 1206                                         
 1207                                 anar = miir(ctlr, phyaddr, 0x04);
 1208                                 anlpar = miir(ctlr, phyaddr, 0x05) & 0x03E0;
 1209                                 anar &= anlpar;
 1210                                 bmcr = 0;
 1211                                 if(anar & 0x380)
 1212                                         bmcr = 0x2000;
 1213                                 if(anar & 0x0140)
 1214                                         bmcr |= 0x0100;
 1215                         }
 1216                         break;
 1217                 }
 1218 
 1219                 /*
 1220                  * Force speed and duplex if no auto-negotiation.
 1221                  */
 1222                 if(anlpar == 0){
 1223                         medium = -1;
 1224                         for(i = 0; i < ether->nopt; i++){
 1225                                 for(k = 0; k < nelem(mediatable); k++){
 1226                                         if(cistrcmp(mediatable[k], ether->opt[i]))
 1227                                                 continue;
 1228                                         medium = k;
 1229                                         break;
 1230                                 }
 1231                 
 1232                                 switch(medium){
 1233                                 default:
 1234                                         break;
 1235 
 1236                                 case 0x00:                      /* 10BASE-T */
 1237                                 case 0x01:                      /* 10BASE-2 */
 1238                                 case 0x02:                      /* 10BASE-5 */
 1239                                         bmcr &= ~(0x2000|0x0100);
 1240                                         ctlr->configdata[19] &= ~0x40;
 1241                                         break;
 1242 
 1243                                 case 0x03:                      /* 100BASE-TX */
 1244                                 case 0x06:                      /* 100BASE-T4 */
 1245                                 case 0x07:                      /* 100BASE-FX */
 1246                                         ctlr->configdata[19] &= ~0x40;
 1247                                         bmcr |= 0x2000;
 1248                                         break;
 1249 
 1250                                 case 0x04:                      /* 10BASE-TFD */
 1251                                         bmcr = (bmcr & ~0x2000)|0x0100;
 1252                                         ctlr->configdata[19] |= 0x40;
 1253                                         break;
 1254 
 1255                                 case 0x05:                      /* 100BASE-TXFD */
 1256                                 case 0x08:                      /* 100BASE-FXFD */
 1257                                         bmcr |= 0x2000|0x0100;
 1258                                         ctlr->configdata[19] |= 0x40;
 1259                                         break;
 1260                                 }
 1261                         }
 1262                         if(medium != -1)
 1263                                 miiw(ctlr, phyaddr, 0x00, bmcr);
 1264                 }
 1265 
 1266                 if(bmcr & 0x2000)
 1267                         ether->mbps = 100;
 1268 
 1269                 ctlr->configdata[8] = 1;
 1270                 ctlr->configdata[15] &= ~0x80;
 1271         }
 1272         else{
 1273                 ctlr->configdata[8] = 0;
 1274                 ctlr->configdata[15] |= 0x80;
 1275         }
 1276 
 1277         /*
 1278          * Workaround for some broken HUB chips when connected at 10Mb/s
 1279          * half-duplex.
 1280          * This is a band-aid, but as there's no dynamic auto-negotiation
 1281          * code at the moment, only deactivate the workaround code in txstart
 1282          * if the link is 100Mb/s.
 1283          */
 1284         if(ether->mbps != 10)
 1285                 ctlr->nop = 0;
 1286 
 1287         /*
 1288          * Load the chip configuration and start it off.
 1289          */
 1290         if(ether->oq == 0)
 1291                 ether->oq = qopen(256*1024, Qmsg, 0, 0);
 1292         configure(ether, 0);
 1293         command(ctlr, CUstart, PADDR(&ctlr->cbr->status));
 1294 
 1295         /*
 1296          * Check if the adapter's station address is to be overridden.
 1297          * If not, read it from the EEPROM and set in ether->ea prior to loading
 1298          * the station address with the Individual Address Setup command.
 1299          */
 1300         memset(ea, 0, Eaddrlen);
 1301         if(memcmp(ea, ether->ea, Eaddrlen) == 0){
 1302                 for(i = 0; i < Eaddrlen/2; i++){
 1303                         x = ctlr->eeprom[i];
 1304                         ether->ea[2*i] = x;
 1305                         ether->ea[2*i+1] = x>>8;
 1306                 }
 1307         }
 1308 
 1309         ilock(&ctlr->cblock);
 1310         ctlr->action = CbIAS;
 1311         txstart(ether);
 1312         iunlock(&ctlr->cblock);
 1313 
 1314         /*
 1315          * Linkage to the generic ethernet driver.
 1316          */
 1317         ether->attach = attach;
 1318         ether->transmit = transmit;
 1319         ether->interrupt = interrupt;
 1320         ether->ifstat = ifstat;
 1321         ether->shutdown = shutdown;
 1322 
 1323         ether->promiscuous = promiscuous;
 1324         ether->multicast = multicast;
 1325         ether->arg = ether;
 1326 
 1327         return 0;
 1328 }
 1329 
 1330 void
 1331 ether82557link(void)
 1332 {
 1333         addethercard("i82557",  reset);
 1334 }

Cache object: d984343da7080f75cb2b7e4e2ced208a


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