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/ether8139.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  * Realtek 8139 (but not the 8129).
    3  * Error recovery for the various over/under -flow conditions
    4  * may need work.
    5  */
    6 #include "u.h"
    7 #include "../port/lib.h"
    8 #include "mem.h"
    9 #include "dat.h"
   10 #include "fns.h"
   11 #include "io.h"
   12 #include "../port/error.h"
   13 #include "../port/netif.h"
   14 
   15 #include "etherif.h"
   16 
   17 enum {                                  /* registers */
   18         Idr0            = 0x0000,       /* MAC address */
   19         Mar0            = 0x0008,       /* Multicast address */
   20         Tsd0            = 0x0010,       /* Transmit Status Descriptor0 */
   21         Tsad0           = 0x0020,       /* Transmit Start Address Descriptor0 */
   22         Rbstart         = 0x0030,       /* Receive Buffer Start Address */
   23         Erbcr           = 0x0034,       /* Early Receive Byte Count */
   24         Ersr            = 0x0036,       /* Early Receive Status */
   25         Cr              = 0x0037,       /* Command Register */
   26         Capr            = 0x0038,       /* Current Address of Packet Read */
   27         Cbr             = 0x003A,       /* Current Buffer Address */
   28         Imr             = 0x003C,       /* Interrupt Mask */
   29         Isr             = 0x003E,       /* Interrupt Status */
   30         Tcr             = 0x0040,       /* Transmit Configuration */
   31         Rcr             = 0x0044,       /* Receive Configuration */
   32         Tctr            = 0x0048,       /* Timer Count */
   33         Mpc             = 0x004C,       /* Missed Packet Counter */
   34         Cr9346          = 0x0050,       /* 9346 Command Register */
   35         Config0         = 0x0051,       /* Configuration Register 0 */
   36         Config1         = 0x0052,       /* Configuration Register 1 */
   37         TimerInt        = 0x0054,       /* Timer Interrupt */
   38         Msr             = 0x0058,       /* Media Status */
   39         Config3         = 0x0059,       /* Configuration Register 3 */
   40         Config4         = 0x005A,       /* Configuration Register 4 */
   41         Mulint          = 0x005C,       /* Multiple Interrupt Select */
   42         RerID           = 0x005E,       /* PCI Revision ID */
   43         Tsad            = 0x0060,       /* Transmit Status of all Descriptors */
   44 
   45         Bmcr            = 0x0062,       /* Basic Mode Control */
   46         Bmsr            = 0x0064,       /* Basic Mode Status */
   47         Anar            = 0x0066,       /* Auto-Negotiation Advertisment */
   48         Anlpar          = 0x0068,       /* Auto-Negotiation Link Partner */
   49         Aner            = 0x006A,       /* Auto-Negotiation Expansion */
   50         Dis             = 0x006C,       /* Disconnect Counter */
   51         Fcsc            = 0x006E,       /* False Carrier Sense Counter */
   52         Nwaytr          = 0x0070,       /* N-way Test */
   53         Rec             = 0x0072,       /* RX_ER Counter */
   54         Cscr            = 0x0074,       /* CS Configuration */
   55         Phy1parm        = 0x0078,       /* PHY Parameter 1 */
   56         Twparm          = 0x007C,       /* Twister Parameter */
   57         Phy2parm        = 0x0080,       /* PHY Parameter 2 */
   58 };
   59 
   60 enum {                                  /* Cr */
   61         Bufe            = 0x01,         /* Rx Buffer Empty */
   62         Te              = 0x04,         /* Transmitter Enable */
   63         Re              = 0x08,         /* Receiver Enable */
   64         Rst             = 0x10,         /* Software Reset */
   65 };
   66 
   67 enum {                                  /* Imr/Isr */
   68         Rok             = 0x0001,       /* Receive OK */
   69         Rer             = 0x0002,       /* Receive Error */
   70         Tok             = 0x0004,       /* Transmit OK */
   71         Ter             = 0x0008,       /* Transmit Error */
   72         Rxovw           = 0x0010,       /* Receive Buffer Overflow */
   73         PunLc           = 0x0020,       /* Packet Underrun or Link Change */
   74         Fovw            = 0x0040,       /* Receive FIFO Overflow */
   75         Clc             = 0x2000,       /* Cable Length Change */
   76         Timerbit        = 0x4000,       /* Timer */
   77         Serr            = 0x8000,       /* System Error */
   78 };
   79 
   80 enum {                                  /* Tcr */
   81         Clrabt          = 0x00000001,   /* Clear Abort */
   82         TxrrSHIFT       = 4,            /* Transmit Retry Count */
   83         TxrrMASK        = 0x000000F0,
   84         MtxdmaSHIFT     = 8,            /* Max. DMA Burst Size */
   85         MtxdmaMASK      = 0x00000700,
   86         Mtxdma2048      = 0x00000700,
   87         Acrc            = 0x00010000,   /* Append CRC (not) */
   88         LbkSHIFT        = 17,           /* Loopback Test */
   89         LbkMASK         = 0x00060000,
   90         Rtl8139ArevG    = 0x00800000,   /* RTL8139A Rev. G ID */
   91         IfgSHIFT        = 24,           /* Interframe Gap */
   92         IfgMASK         = 0x03000000,
   93         HwveridSHIFT    = 26,           /* Hardware Version ID */
   94         HwveridMASK     = 0x7C000000,
   95 };
   96 
   97 enum {                                  /* Rcr */
   98         Aap             = 0x00000001,   /* Accept All Packets */
   99         Apm             = 0x00000002,   /* Accept Physical Match */
  100         Am              = 0x00000004,   /* Accept Multicast */
  101         Ab              = 0x00000008,   /* Accept Broadcast */
  102         Ar              = 0x00000010,   /* Accept Runt */
  103         Aer             = 0x00000020,   /* Accept Error */
  104         Sel9356         = 0x00000040,   /* 9356 EEPROM used */
  105         Wrap            = 0x00000080,   /* Rx Buffer Wrap Control */
  106         MrxdmaSHIFT     = 8,            /* Max. DMA Burst Size */
  107         MrxdmaMASK      = 0x00000700,
  108         Mrxdmaunlimited = 0x00000700,
  109         RblenSHIFT      = 11,           /* Receive Buffer Length */
  110         RblenMASK       = 0x00001800,
  111         Rblen8K         = 0x00000000,   /* 8KB+16 */
  112         Rblen16K        = 0x00000800,   /* 16KB+16 */
  113         Rblen32K        = 0x00001000,   /* 32KB+16 */
  114         Rblen64K        = 0x00001800,   /* 64KB+16 */
  115         RxfthSHIFT      = 13,           /* Receive Buffer Length */
  116         RxfthMASK       = 0x0000E000,
  117         Rxfth256        = 0x00008000,
  118         Rxfthnone       = 0x0000E000,
  119         Rer8            = 0x00010000,   /* Accept Error Packets > 8 bytes */
  120         MulERINT        = 0x00020000,   /* Multiple Early Interrupt Select */
  121         ErxthSHIFT      = 24,           /* Early Rx Threshold */
  122         ErxthMASK       = 0x0F000000,
  123         Erxthnone       = 0x00000000,
  124 };
  125 
  126 enum {                                  /* Received Packet Status */
  127         Rcok            = 0x0001,       /* Receive Completed OK */
  128         Fae             = 0x0002,       /* Frame Alignment Error */
  129         Crc             = 0x0004,       /* CRC Error */
  130         Long            = 0x0008,       /* Long Packet */
  131         Runt            = 0x0010,       /* Runt Packet Received */
  132         Ise             = 0x0020,       /* Invalid Symbol Error */
  133         Bar             = 0x2000,       /* Broadcast Address Received */
  134         Pam             = 0x4000,       /* Physical Address Matched */
  135         Mar             = 0x8000,       /* Multicast Address Received */
  136 };
  137 
  138 enum {                                  /* Media Status Register */
  139         Rxpf            = 0x01,         /* Pause Flag */
  140         Txpf            = 0x02,         /* Pause Flag */
  141         Linkb           = 0x04,         /* Inverse of Link Status */
  142         Speed10         = 0x08,         /* 10Mbps */
  143         Auxstatus       = 0x10,         /* Aux. Power Present Status */
  144         Rxfce           = 0x40,         /* Receive Flow Control Enable */
  145         Txfce           = 0x80,         /* Transmit Flow Control Enable */
  146 };
  147 
  148 typedef struct Td Td;
  149 struct Td {                     /* Soft Transmit Descriptor */
  150         int     tsd;
  151         int     tsad;
  152         uchar*  data;
  153         Block*  bp;
  154 };
  155 
  156 enum {                                  /* Tsd0 */
  157         SizeSHIFT       = 0,            /* Descriptor Size */
  158         SizeMASK        = 0x00001FFF,
  159         Own             = 0x00002000,
  160         Tun             = 0x00004000,   /* Transmit FIFO Underrun */
  161         Tcok            = 0x00008000,   /* Transmit COmpleted OK */
  162         EtxthSHIFT      = 16,           /* Early Tx Threshold */
  163         EtxthMASK       = 0x001F0000,
  164         NccSHIFT        = 24,           /* Number of Collisions Count */
  165         NccMASK         = 0x0F000000,
  166         Cdh             = 0x10000000,   /* CD Heartbeat */
  167         Owc             = 0x20000000,   /* Out of Window Collision */
  168         Tabt            = 0x40000000,   /* Transmit Abort */
  169         Crs             = 0x80000000,   /* Carrier Sense Lost */
  170 };
  171 
  172 enum {
  173         Rblen           = Rblen64K,     /* Receive Buffer Length */
  174         Ntd             = 4,            /* Number of Transmit Descriptors */
  175         Tdbsz           = ROUNDUP(sizeof(Etherpkt), 4),
  176 };
  177 
  178 typedef struct Ctlr Ctlr;
  179 typedef struct Ctlr {
  180         int     port;
  181         Pcidev* pcidev;
  182         Ctlr*   next;
  183         int     active;
  184         int     id;
  185 
  186         QLock   alock;                  /* attach */
  187         Lock    ilock;                  /* init */
  188         void*   alloc;                  /* base of per-Ctlr allocated data */
  189 
  190         int     pcie;                   /* flag: pci-express device? */
  191 
  192         uvlong  mchash;                 /* multicast hash */
  193 
  194         int     rcr;                    /* receive configuration register */
  195         uchar*  rbstart;                /* receive buffer */
  196         int     rblen;                  /* receive buffer length */
  197         int     ierrs;                  /* receive errors */
  198 
  199         Lock    tlock;                  /* transmit */
  200         Td      td[Ntd];
  201         int     ntd;                    /* descriptors active */
  202         int     tdh;                    /* host index into td */
  203         int     tdi;                    /* interface index into td */
  204         int     etxth;                  /* early transmit threshold */
  205         int     taligned;               /* packet required no alignment */
  206         int     tunaligned;             /* packet required alignment */
  207 
  208         int     dis;                    /* disconnect counter */
  209         int     fcsc;                   /* false carrier sense counter */
  210         int     rec;                    /* RX_ER counter */
  211         uint    mcast;
  212 } Ctlr;
  213 
  214 static Ctlr* ctlrhead;
  215 static Ctlr* ctlrtail;
  216 
  217 #define csr8r(c, r)     (inb((c)->port+(r)))
  218 #define csr16r(c, r)    (ins((c)->port+(r)))
  219 #define csr32r(c, r)    (inl((c)->port+(r)))
  220 #define csr8w(c, r, b)  (outb((c)->port+(r), (int)(b)))
  221 #define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w)))
  222 #define csr32w(c, r, l) (outl((c)->port+(r), (ulong)(l)))
  223 
  224 static void
  225 rtl8139promiscuous(void* arg, int on)
  226 {
  227         Ether *edev;
  228         Ctlr * ctlr;
  229 
  230         edev = arg;
  231         ctlr = edev->ctlr;
  232         ilock(&ctlr->ilock);
  233 
  234         if(on)
  235                 ctlr->rcr |= Aap;
  236         else
  237                 ctlr->rcr &= ~Aap;
  238         csr32w(ctlr, Rcr, ctlr->rcr);
  239         iunlock(&ctlr->ilock);
  240 }
  241 
  242 enum {
  243         /* everyone else uses 0x04c11db7, but they both produce the same crc */
  244         Etherpolybe = 0x04c11db6,
  245         Bytemask = (1<<8) - 1,
  246 };
  247 
  248 static ulong
  249 ethercrcbe(uchar *addr, long len)
  250 {
  251         int i, j;
  252         ulong c, crc, carry;
  253 
  254         crc = ~0UL;
  255         for (i = 0; i < len; i++) {
  256                 c = addr[i];
  257                 for (j = 0; j < 8; j++) {
  258                         carry = ((crc & (1UL << 31))? 1: 0) ^ (c & 1);
  259                         crc <<= 1;
  260                         c >>= 1;
  261                         if (carry)
  262                                 crc = (crc ^ Etherpolybe) | carry;
  263                 }
  264         }
  265         return crc;
  266 }
  267 
  268 static ulong
  269 swabl(ulong l)
  270 {
  271         return l>>24 | (l>>8) & (Bytemask<<8) |
  272                 (l<<8) & (Bytemask<<16) | l<<24;
  273 }
  274 
  275 static void
  276 rtl8139multicast(void* ether, uchar *eaddr, int add)
  277 {
  278         Ether *edev;
  279         Ctlr *ctlr;
  280 
  281         if (!add)
  282                 return; /* ok to keep receiving on old mcast addrs */
  283 
  284         edev = ether;
  285         ctlr = edev->ctlr;
  286         ilock(&ctlr->ilock);
  287 
  288         ctlr->mchash |= 1ULL << (ethercrcbe(eaddr, Eaddrlen) >> 26);
  289 
  290         ctlr->rcr |= Am;
  291         csr32w(ctlr, Rcr, ctlr->rcr);
  292 
  293         /* pci-e variants reverse the order of the hash byte registers */
  294         if (0 && ctlr->pcie) {
  295                 csr32w(ctlr, Mar0,   swabl(ctlr->mchash>>32));
  296                 csr32w(ctlr, Mar0+4, swabl(ctlr->mchash));
  297         } else {
  298                 csr32w(ctlr, Mar0,   ctlr->mchash);
  299                 csr32w(ctlr, Mar0+4, ctlr->mchash>>32);
  300         }
  301 
  302         iunlock(&ctlr->ilock);
  303 }
  304 
  305 static long
  306 rtl8139ifstat(Ether* edev, void* a, long n, ulong offset)
  307 {
  308         int l;
  309         char *p;
  310         Ctlr *ctlr;
  311 
  312         ctlr = edev->ctlr;
  313         p = malloc(READSTR);
  314         l = snprint(p, READSTR, "rcr %#8.8ux\n", ctlr->rcr);
  315         l += snprint(p+l, READSTR-l, "multicast %ud\n", ctlr->mcast);
  316         l += snprint(p+l, READSTR-l, "ierrs %d\n", ctlr->ierrs);
  317         l += snprint(p+l, READSTR-l, "etxth %d\n", ctlr->etxth);
  318         l += snprint(p+l, READSTR-l, "taligned %d\n", ctlr->taligned);
  319         l += snprint(p+l, READSTR-l, "tunaligned %d\n", ctlr->tunaligned);
  320         ctlr->dis += csr16r(ctlr, Dis);
  321         l += snprint(p+l, READSTR-l, "dis %d\n", ctlr->dis);
  322         ctlr->fcsc += csr16r(ctlr, Fcsc);
  323         l += snprint(p+l, READSTR-l, "fcscnt %d\n", ctlr->fcsc);
  324         ctlr->rec += csr16r(ctlr, Rec);
  325         l += snprint(p+l, READSTR-l, "rec %d\n", ctlr->rec);
  326 
  327         l += snprint(p+l, READSTR-l, "Tcr %#8.8lux\n", csr32r(ctlr, Tcr));
  328         l += snprint(p+l, READSTR-l, "Config0 %#2.2ux\n", csr8r(ctlr, Config0));
  329         l += snprint(p+l, READSTR-l, "Config1 %#2.2ux\n", csr8r(ctlr, Config1));
  330         l += snprint(p+l, READSTR-l, "Msr %#2.2ux\n", csr8r(ctlr, Msr));
  331         l += snprint(p+l, READSTR-l, "Config3 %#2.2ux\n", csr8r(ctlr, Config3));
  332         l += snprint(p+l, READSTR-l, "Config4 %#2.2ux\n", csr8r(ctlr, Config4));
  333 
  334         l += snprint(p+l, READSTR-l, "Bmcr %#4.4ux\n", csr16r(ctlr, Bmcr));
  335         l += snprint(p+l, READSTR-l, "Bmsr %#4.4ux\n", csr16r(ctlr, Bmsr));
  336         l += snprint(p+l, READSTR-l, "Anar %#4.4ux\n", csr16r(ctlr, Anar));
  337         l += snprint(p+l, READSTR-l, "Anlpar %#4.4ux\n", csr16r(ctlr, Anlpar));
  338         l += snprint(p+l, READSTR-l, "Aner %#4.4ux\n", csr16r(ctlr, Aner));
  339         l += snprint(p+l, READSTR-l, "Nwaytr %#4.4ux\n", csr16r(ctlr, Nwaytr));
  340         snprint(p+l, READSTR-l, "Cscr %#4.4ux\n", csr16r(ctlr, Cscr));
  341         n = readstr(offset, a, n, p);
  342         free(p);
  343 
  344         return n;
  345 }
  346 
  347 static int
  348 rtl8139reset(Ctlr* ctlr)
  349 {
  350         int timeo;
  351 
  352         /*
  353          * Soft reset the controller.
  354          */
  355         csr8w(ctlr, Cr, Rst);
  356         for(timeo = 0; timeo < 1000; timeo++){
  357                 if(!(csr8r(ctlr, Cr) & Rst))
  358                         return 0;
  359                 delay(1);
  360         }
  361 
  362         return -1;
  363 }
  364 
  365 static void
  366 rtl8139halt(Ctlr* ctlr)
  367 {
  368         int i;
  369 
  370         csr8w(ctlr, Cr, 0);
  371         csr16w(ctlr, Imr, 0);
  372         csr16w(ctlr, Isr, ~0);
  373 
  374         for(i = 0; i < Ntd; i++){
  375                 if(ctlr->td[i].bp == nil)
  376                         continue;
  377                 freeb(ctlr->td[i].bp);
  378                 ctlr->td[i].bp = nil;
  379         }
  380 }
  381 
  382 static void
  383 rtl8139init(Ether* edev)
  384 {
  385         int i;
  386         ulong r;
  387         Ctlr *ctlr;
  388         uchar *alloc;
  389 
  390         ctlr = edev->ctlr;
  391         ilock(&ctlr->ilock);
  392 
  393         rtl8139halt(ctlr);
  394 
  395         /*
  396          * MAC Address.
  397          */
  398         r = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];
  399         csr32w(ctlr, Idr0, r);
  400         r = (edev->ea[5]<<8)|edev->ea[4];
  401         csr32w(ctlr, Idr0+4, r);
  402 
  403         /*
  404          * Receiver
  405          */
  406         alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 32);
  407         ctlr->rbstart = alloc;
  408         alloc += ctlr->rblen+16;
  409         memset(ctlr->rbstart, 0, ctlr->rblen+16);
  410         csr32w(ctlr, Rbstart, PCIWADDR(ctlr->rbstart));
  411         ctlr->rcr = Rxfth256|Rblen|Mrxdmaunlimited|Ab|Am|Apm;
  412 
  413         /*
  414          * Transmitter.
  415          */
  416         for(i = 0; i < Ntd; i++){
  417                 ctlr->td[i].tsd = Tsd0+i*4;
  418                 ctlr->td[i].tsad = Tsad0+i*4;
  419                 ctlr->td[i].data = alloc;
  420                 alloc += Tdbsz;
  421                 ctlr->td[i].bp = nil;
  422         }
  423         ctlr->ntd = ctlr->tdh = ctlr->tdi = 0;
  424         ctlr->etxth = 128/32;
  425 
  426         /*
  427          * Interrupts.
  428          */
  429         csr32w(ctlr, TimerInt, 0);
  430         csr16w(ctlr, Imr, Serr|Timerbit|Fovw|PunLc|Rxovw|Ter|Tok|Rer|Rok);
  431         csr32w(ctlr, Mpc, 0);
  432 
  433         /*
  434          * Enable receiver/transmitter.
  435          * Need to enable before writing the Rcr or it won't take.
  436          */
  437         csr8w(ctlr, Cr, Te|Re);
  438         csr32w(ctlr, Tcr, Mtxdma2048);
  439         csr32w(ctlr, Rcr, ctlr->rcr);
  440         csr32w(ctlr, Mar0,   0);
  441         csr32w(ctlr, Mar0+4, 0);
  442         ctlr->mchash = 0;
  443 
  444         iunlock(&ctlr->ilock);
  445 }
  446 
  447 static void
  448 rtl8139attach(Ether* edev)
  449 {
  450         Ctlr *ctlr;
  451 
  452         ctlr = edev->ctlr;
  453         qlock(&ctlr->alock);
  454         if(ctlr->alloc == nil){
  455                 ctlr->rblen = 1<<((Rblen>>RblenSHIFT)+13);
  456                 ctlr->alloc = mallocz(ctlr->rblen+16 + Ntd*Tdbsz + 32, 0);
  457                 rtl8139init(edev);
  458         }
  459         qunlock(&ctlr->alock);
  460 }
  461 
  462 static void
  463 rtl8139txstart(Ether* edev)
  464 {
  465         Td *td;
  466         int size;
  467         Block *bp;
  468         Ctlr *ctlr;
  469 
  470         ctlr = edev->ctlr;
  471         while(ctlr->ntd < Ntd){
  472                 bp = qget(edev->oq);
  473                 if(bp == nil)
  474                         break;
  475                 size = BLEN(bp);
  476 
  477                 td = &ctlr->td[ctlr->tdh];
  478                 if(((int)bp->rp) & 0x03){
  479                         memmove(td->data, bp->rp, size);
  480                         freeb(bp);
  481                         csr32w(ctlr, td->tsad, PCIWADDR(td->data));
  482                         ctlr->tunaligned++;
  483                 }
  484                 else{
  485                         td->bp = bp;
  486                         csr32w(ctlr, td->tsad, PCIWADDR(bp->rp));
  487                         ctlr->taligned++;
  488                 }
  489                 csr32w(ctlr, td->tsd, (ctlr->etxth<<EtxthSHIFT)|size);
  490 
  491                 ctlr->ntd++;
  492                 ctlr->tdh = NEXT(ctlr->tdh, Ntd);
  493         }
  494 }
  495 
  496 static void
  497 rtl8139transmit(Ether* edev)
  498 {
  499         Ctlr *ctlr;
  500 
  501         ctlr = edev->ctlr;
  502         ilock(&ctlr->tlock);
  503         rtl8139txstart(edev);
  504         iunlock(&ctlr->tlock);
  505 }
  506 
  507 static void
  508 rtl8139receive(Ether* edev)
  509 {
  510         Block *bp;
  511         Ctlr *ctlr;
  512         ushort capr;
  513         uchar cr, *p;
  514         int l, length, status;
  515 
  516         ctlr = edev->ctlr;
  517 
  518         /*
  519          * Capr is where the host is reading from,
  520          * Cbr is where the NIC is currently writing.
  521          */
  522         capr = (csr16r(ctlr, Capr)+16) % ctlr->rblen;
  523         while(!(csr8r(ctlr, Cr) & Bufe)){
  524                 p = ctlr->rbstart+capr;
  525 
  526                 /*
  527                  * Apparently the packet length may be 0xFFF0 if
  528                  * the NIC is still copying the packet into memory.
  529                  */
  530                 length = (*(p+3)<<8)|*(p+2);
  531                 if(length == 0xFFF0)
  532                         break;
  533                 status = (*(p+1)<<8)|*p;
  534 
  535                 if(!(status & Rcok)){
  536                         if(status & (Ise|Fae))
  537                                 edev->frames++;
  538                         if(status & Crc)
  539                                 edev->crcs++;
  540                         if(status & (Runt|Long))
  541                                 edev->buffs++;
  542 
  543                         /*
  544                          * Reset the receiver.
  545                          * Also may have to restore the multicast list
  546                          * here too if it ever gets used.
  547                          */
  548                         cr = csr8r(ctlr, Cr);
  549                         csr8w(ctlr, Cr, cr & ~Re);
  550                         csr32w(ctlr, Rbstart, PCIWADDR(ctlr->rbstart));
  551                         csr8w(ctlr, Cr, cr);
  552                         csr32w(ctlr, Rcr, ctlr->rcr);
  553 
  554                         continue;
  555                 }
  556 
  557                 /*
  558                  * Receive Completed OK.
  559                  * Very simplistic; there are ways this could be done
  560                  * without copying, but the juice probably isn't worth
  561                  * the squeeze.
  562                  * The packet length includes a 4 byte CRC on the end.
  563                  */
  564                 capr = (capr+4) % ctlr->rblen;
  565                 p = ctlr->rbstart+capr;
  566                 capr = (capr+length) % ctlr->rblen;
  567                 if(status & Mar)
  568                         ctlr->mcast++;
  569 
  570                 if((bp = iallocb(length)) != nil){
  571                         if(p+length >= ctlr->rbstart+ctlr->rblen){
  572                                 l = ctlr->rbstart+ctlr->rblen - p;
  573                                 memmove(bp->wp, p, l);
  574                                 bp->wp += l;
  575                                 length -= l;
  576                                 p = ctlr->rbstart;
  577                         }
  578                         if(length > 0){
  579                                 memmove(bp->wp, p, length);
  580                                 bp->wp += length;
  581                         }
  582                         bp->wp -= 4;
  583                         etheriq(edev, bp, 1);
  584                 }
  585 
  586                 capr = ROUNDUP(capr, 4);
  587                 csr16w(ctlr, Capr, capr-16);
  588         }
  589 }
  590 
  591 static void
  592 rtl8139interrupt(Ureg*, void* arg)
  593 {
  594         Td *td;
  595         Ctlr *ctlr;
  596         Ether *edev;
  597         int isr, msr, tsd;
  598 
  599         edev = arg;
  600         ctlr = edev->ctlr;
  601 
  602         while((isr = csr16r(ctlr, Isr)) != 0){
  603                 csr16w(ctlr, Isr, isr);
  604                 if(isr & (Fovw|PunLc|Rxovw|Rer|Rok)){
  605                         rtl8139receive(edev);
  606                         if(!(isr & Rok))
  607                                 ctlr->ierrs++;
  608                         isr &= ~(Fovw|Rxovw|Rer|Rok);
  609                 }
  610 
  611                 if(isr & (Ter|Tok)){
  612                         ilock(&ctlr->tlock);
  613                         while(ctlr->ntd){
  614                                 td = &ctlr->td[ctlr->tdi];
  615                                 tsd = csr32r(ctlr, td->tsd);
  616                                 if(!(tsd & (Tabt|Tun|Tcok)))
  617                                         break;
  618 
  619                                 if(!(tsd & Tcok)){
  620                                         if(tsd & Tun){
  621                                                 if(ctlr->etxth < ETHERMAXTU/32)
  622                                                         ctlr->etxth++;
  623                                         }
  624                                         edev->oerrs++;
  625                                 }
  626 
  627                                 if(td->bp != nil){
  628                                         freeb(td->bp);
  629                                         td->bp = nil;
  630                                 }
  631 
  632                                 ctlr->ntd--;
  633                                 ctlr->tdi = NEXT(ctlr->tdi, Ntd);
  634                         }
  635                         rtl8139txstart(edev);
  636                         iunlock(&ctlr->tlock);
  637                         isr &= ~(Ter|Tok);
  638                 }
  639 
  640                 if(isr & PunLc){
  641                         /*
  642                          * Maybe the link changed - do we care very much?
  643                          */
  644                         msr = csr8r(ctlr, Msr);
  645                         if(!(msr & Linkb)){
  646                                 if(!(msr & Speed10) && edev->mbps != 100){
  647                                         edev->mbps = 100;
  648                                         qsetlimit(edev->oq, 256*1024);
  649                                 }
  650                                 else if((msr & Speed10) && edev->mbps != 10){
  651                                         edev->mbps = 10;
  652                                         qsetlimit(edev->oq, 65*1024);
  653                                 }
  654                         }
  655                         isr &= ~(Clc|PunLc);
  656                 }
  657 
  658                 /*
  659                  * Only Serr|Timerbit should be left by now.
  660                  * Should anything be done to tidy up? TimerInt isn't
  661                  * used so that can be cleared. A PCI bus error is indicated
  662                  * by Serr, that's pretty serious; is there anyhing to do
  663                  * other than try to reinitialise the chip?
  664                  */
  665                 if((isr & (Serr|Timerbit)) != 0){
  666                         iprint("rtl8139interrupt: imr %#4.4ux isr %#4.4ux\n",
  667                                 csr16r(ctlr, Imr), isr);
  668                         if(isr & Timerbit)
  669                                 csr32w(ctlr, TimerInt, 0);
  670                         if(isr & Serr)
  671                                 rtl8139init(edev);
  672                 }
  673         }
  674 }
  675 
  676 static Ctlr*
  677 rtl8139match(Ether* edev, int id)
  678 {
  679         Pcidev *p;
  680         Ctlr *ctlr;
  681         int i, port;
  682 
  683         /*
  684          * Any adapter matches if no edev->port is supplied,
  685          * otherwise the ports must match.
  686          */
  687         for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
  688                 if(ctlr->active)
  689                         continue;
  690                 p = ctlr->pcidev;
  691                 if(((p->did<<16)|p->vid) != id)
  692                         continue;
  693                 port = p->mem[0].bar & ~0x01;
  694                 if(edev->port != 0 && edev->port != port)
  695                         continue;
  696 
  697                 if(ioalloc(port, p->mem[0].size, 0, "rtl8139") < 0){
  698                         print("rtl8139: port %#ux in use\n", port);
  699                         continue;
  700                 }
  701 
  702                 if(pcigetpms(p) > 0){
  703                         pcisetpms(p, 0);
  704         
  705                         for(i = 0; i < 6; i++)
  706                                 pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar);
  707                         pcicfgw8(p, PciINTL, p->intl);
  708                         pcicfgw8(p, PciLTR, p->ltr);
  709                         pcicfgw8(p, PciCLS, p->cls);
  710                         pcicfgw16(p, PciPCR, p->pcr);
  711                 }
  712 
  713                 ctlr->port = port;
  714                 if(rtl8139reset(ctlr)) {
  715                         iofree(port);
  716                         continue;
  717                 }
  718                 pcisetbme(p);
  719 
  720                 ctlr->active = 1;
  721                 return ctlr;
  722         }
  723         return nil;
  724 }
  725 
  726 static struct {
  727         char*   name;
  728         int     id;
  729 } rtl8139pci[] = {
  730         { "rtl8139",    (0x8139<<16)|0x10EC, }, /* generic */
  731         { "smc1211",    (0x1211<<16)|0x1113, }, /* SMC EZ-Card */
  732         { "dfe-538tx",  (0x1300<<16)|0x1186, }, /* D-Link DFE-538TX */
  733         { "dfe-560txd", (0x1340<<16)|0x1186, }, /* D-Link DFE-560TXD */
  734         { nil },
  735 };
  736 
  737 static int
  738 rtl8139pnp(Ether* edev)
  739 {
  740         int i, id;
  741         Pcidev *p;
  742         Ctlr *ctlr;
  743         uchar ea[Eaddrlen];
  744 
  745         /*
  746          * Make a list of all ethernet controllers
  747          * if not already done.
  748          */
  749         if(ctlrhead == nil){
  750                 p = nil;
  751                 while(p = pcimatch(p, 0, 0)){
  752                         if(p->ccrb != 0x02 || p->ccru != 0)
  753                                 continue;
  754                         ctlr = malloc(sizeof(Ctlr));
  755                         ctlr->pcidev = p;
  756                         ctlr->id = (p->did<<16)|p->vid;
  757 
  758                         if(ctlrhead != nil)
  759                                 ctlrtail->next = ctlr;
  760                         else
  761                                 ctlrhead = ctlr;
  762                         ctlrtail = ctlr;
  763                 }
  764         }
  765 
  766         /*
  767          * Is it an RTL8139 under a different name?
  768          * Normally a search is made through all the found controllers
  769          * for one which matches any of the known vid+did pairs.
  770          * If a vid+did pair is specified a search is made for that
  771          * specific controller only.
  772          */
  773         id = 0;
  774         for(i = 0; i < edev->nopt; i++){
  775                 if(cistrncmp(edev->opt[i], "id=", 3) == 0)
  776                         id = strtol(&edev->opt[i][3], nil, 0);
  777         }
  778 
  779         ctlr = nil;
  780         if(id != 0)
  781                 ctlr = rtl8139match(edev, id);
  782         else for(i = 0; rtl8139pci[i].name; i++){
  783                 if((ctlr = rtl8139match(edev, rtl8139pci[i].id)) != nil)
  784                         break;
  785         }
  786         if(ctlr == nil)
  787                 return -1;
  788 
  789         edev->ctlr = ctlr;
  790         edev->port = ctlr->port;
  791         edev->irq = ctlr->pcidev->intl;
  792         edev->tbdf = ctlr->pcidev->tbdf;
  793 
  794         /*
  795          * Check if the adapter's station address is to be overridden.
  796          * If not, read it from the device and set in edev->ea.
  797          */
  798         memset(ea, 0, Eaddrlen);
  799         if(memcmp(ea, edev->ea, Eaddrlen) == 0){
  800                 i = csr32r(ctlr, Idr0);
  801                 edev->ea[0] = i;
  802                 edev->ea[1] = i>>8;
  803                 edev->ea[2] = i>>16;
  804                 edev->ea[3] = i>>24;
  805                 i = csr32r(ctlr, Idr0+4);
  806                 edev->ea[4] = i;
  807                 edev->ea[5] = i>>8;
  808         }
  809 
  810         edev->attach = rtl8139attach;
  811         edev->transmit = rtl8139transmit;
  812         edev->interrupt = rtl8139interrupt;
  813         edev->ifstat = rtl8139ifstat;
  814 
  815         edev->arg = edev;
  816         edev->promiscuous = rtl8139promiscuous;
  817         edev->multicast = rtl8139multicast;
  818 //      edev->shutdown = rtl8139shutdown;
  819 
  820         /*
  821          * This should be much more dynamic but will do for now.
  822          */
  823         if((csr8r(ctlr, Msr) & (Speed10|Linkb)) == 0)
  824                 edev->mbps = 100;
  825 
  826         return 0;
  827 }
  828 
  829 void
  830 ether8139link(void)
  831 {
  832         addethercard("rtl8139", rtl8139pnp);
  833 }

Cache object: 41d09a8ec3091e4bd90fbc4d39109b07


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