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