Annotation of Net2/arch/i386/isa/if_ed.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Device driver for National Semiconductor DS8390 based ethernet
                      3:  *   adapters. By David Greenman, 29-April-1993
                      4:  *
                      5:  * Copyright (C) 1993, David Greenman. This software may be used, modified,
                      6:  *   copied, distributed, and sold, in both source and binary form provided
                      7:  *   that the above copyright and these terms are retained. Under no
                      8:  *   circumstances is the author responsible for the proper functioning
                      9:  *   of this software, nor does the author assume any responsibility
                     10:  *   for damages incurred with its use.
                     11:  *
                     12:  * Currently supports the Western Digital/SMC 8003 and 8013 series
                     13:  *   and the 3Com 3c503
                     14:  */
                     15: 
                     16: /*
                     17:  *     if_ed.c,v 1.2.2.5 1993/07/27 06:00:45 cgd Exp
                     18:  */
                     19:  
                     20: #include "ed.h"
                     21: #if    NED > 0
                     22: #include "bpfilter.h"
                     23: 
                     24: #include "param.h"
                     25: #include "systm.h"
                     26: #include "select.h"
                     27: #include "errno.h"
                     28: #include "ioctl.h"
                     29: #include "mbuf.h"
                     30: #include "socket.h"
                     31: #include "syslog.h"
                     32: 
                     33: #include "net/if.h"
                     34: #include "net/if_dl.h"
                     35: #include "net/if_types.h"
                     36: #include "net/netisr.h"
                     37: 
                     38: #ifdef INET
                     39: #include "netinet/in.h"
                     40: #include "netinet/in_systm.h"
                     41: #include "netinet/in_var.h"
                     42: #include "netinet/ip.h"
                     43: #include "netinet/if_ether.h"
                     44: #endif
                     45: 
                     46: #ifdef NS
                     47: #include "netns/ns.h"
                     48: #include "netns/ns_if.h"
                     49: #endif
                     50: 
                     51: #if NBPFILTER > 0
                     52: #include "net/bpf.h"
                     53: #include "net/bpfdesc.h"
                     54: #endif
                     55: 
                     56: #include "i386/isa/isa.h"
                     57: #include "i386/isa/isa_device.h"
                     58: #include "i386/isa/icu.h"
                     59: #include "i386/isa/if_edreg.h"
                     60: 
                     61: #include "i386/include/pio.h"
                     62: 
                     63:  
                     64: /*
                     65:  * ed_softc: per line info and status
                     66:  */
                     67: struct ed_softc {
                     68:        struct  arpcom arpcom;  /* ethernet common */
                     69: 
                     70:        char    *type_str;      /* pointer to type string */
                     71:        u_char  vendor;         /* interface vendor */
                     72:        u_char  type;           /* interface type code */
                     73: 
                     74:        u_short vector;         /* interrupt vector */
                     75:        u_short asic_addr;      /* ASIC I/O bus address */
                     76:        u_short nic_addr;       /* NIC (DS8390) I/O bus address */
                     77: 
                     78:        caddr_t smem_start;     /* shared memory start address */
                     79:        caddr_t smem_end;       /* shared memory end address */
                     80:        u_long  smem_size;      /* total shared memory size */
                     81:        caddr_t smem_ring;      /* start of RX ring-buffer (in smem) */
                     82: 
                     83:        caddr_t bpf;            /* BPF "magic cookie" */
                     84: 
                     85:        u_char  memwidth;       /* width of access to card mem 8 or 16 */
                     86:        u_char  xmit_busy;      /* transmitter is busy */
                     87:        u_char  txb_cnt;        /* Number of transmit buffers */
                     88:        u_char  txb_next;       /* Pointer to next buffer ready to xmit */
                     89:        u_short txb_next_len;   /* next xmit buffer length */
                     90:        u_char  data_buffered;  /* data has been buffered in interface memory */
                     91:        u_char  tx_page_start;  /* first page of TX buffer area */
                     92: 
                     93:        u_char  rec_page_start; /* first page of RX ring-buffer */
                     94:        u_char  rec_page_stop;  /* last page of RX ring-buffer */
                     95:        u_char  next_packet;    /* pointer to next unread RX packet */
                     96: } ed_softc[NED];
                     97: 
                     98: int    ed_attach(), ed_init(), edintr(), ed_ioctl(), ed_probe(),
                     99:        ed_start(), ed_reset(), ed_watchdog();
                    100: 
                    101: static void ed_stop();
                    102: 
                    103: static inline void ed_rint();
                    104: static inline void ed_xmit();
                    105: static inline char *ed_ring_copy();
                    106: 
                    107: extern int ether_output();
                    108: 
                    109: struct isa_driver eddriver = {
                    110:        ed_probe,
                    111:        ed_attach,
                    112:        "ed"
                    113: };
                    114: /* 
                    115:  * Interrupt conversion table for WD/SMC ASIC
                    116:  * (IRQ* are defined in icu.h)
                    117:  */
                    118: static unsigned short ed_intr_mask[] = {
                    119:        IRQ9,
                    120:        IRQ3,
                    121:        IRQ5,
                    122:        IRQ7,
                    123:        IRQ10,
                    124:        IRQ11,
                    125:        IRQ15,
                    126:        IRQ4
                    127: };
                    128:        
                    129: #define        ETHER_MIN_LEN   64
                    130: #define ETHER_MAX_LEN  1518
                    131: #define        ETHER_ADDR_LEN  6
                    132: #define        ETHER_HDR_SIZE  14
                    133: 
                    134: /*
                    135:  * Determine if the device is present
                    136:  *
                    137:  *   on entry:
                    138:  *     a pointer to an isa_device struct
                    139:  *   on exit:
                    140:  *     NULL if device not found
                    141:  *     or # of i/o addresses used (if found)
                    142:  */
                    143: int
                    144: ed_probe(isa_dev)
                    145:        struct isa_device *isa_dev;
                    146: {
                    147:        struct ed_softc *sc = &ed_softc[isa_dev->id_unit];
                    148:        int i, x;
                    149:        u_int memsize;
                    150:        u_char iptr, memwidth, sum, tmp;
                    151: 
                    152:        /*
                    153:         * Setup initial i/o address for ASIC and NIC
                    154:         */
                    155:        sc->asic_addr = isa_dev->id_iobase;
                    156:        sc->vector = isa_dev->id_irq;
                    157:        sc->smem_start = (caddr_t)isa_dev->id_maddr;
                    158:  
                    159:        /*
                    160:         * Attempt to do a checksum over the station address PROM.
                    161:         * This is mapped differently on the WD80x3 and 3C503, so if
                    162:         *      it fails, it might be a 3C503. There is a problem with
                    163:         *      this, though: some clone WD boards don't pass the
                    164:         *      checksum test. Danpex boards for one. We need to do
                    165:         *      additional checking for this case.
                    166:         */
                    167:        for (sum = 0, i = 0; i < 8; ++i) {
                    168:                sum += inb(sc->asic_addr + ED_WD_PROM + i);
                    169:        }
                    170:        
                    171:        if (sum == ED_WD_ROM_CHECKSUM_TOTAL) {
                    172:                goto type_WD80x3;
                    173:        } else {
                    174:                /*
                    175:                 * Do additional checking to make sure its a 3Com and
                    176:                 * not a broken WD clone
                    177:                 */
                    178:                goto type_3Com;
                    179:        }
                    180: 
                    181: type_WD80x3:
                    182:        /*
                    183:         * Looks like a WD/SMC board
                    184:         */
                    185: 
                    186:        sc->vendor = ED_VENDOR_WD_SMC;
                    187:        sc->type = inb(sc->asic_addr + ED_WD_CARD_ID);
                    188: 
                    189:        sc->nic_addr = sc->asic_addr + ED_WD_NIC_OFFSET;
                    190: 
                    191:        /* reset card to force it into a known state. */
                    192:        outb(sc->asic_addr + ED_WD_MSR, ED_WD_MSR_RST);
                    193:        DELAY(100);
                    194:        outb(sc->asic_addr + ED_WD_MSR, inb(sc->asic_addr + ED_WD_MSR) & ~ED_WD_MSR_RST);
                    195:        /* wait in the case this card is reading it's EEROM */
                    196:        DELAY(5000);
                    197: 
                    198:        /*
                    199:         * Set initial values for width/size.
                    200:         */
                    201:        switch (sc->type) {
                    202:        case ED_TYPE_WD8003S:
                    203:                sc->type_str = "WD8003S";
                    204:                memsize = 8192;
                    205:                memwidth = 8;
                    206:                break;
                    207:        case ED_TYPE_WD8003E:
                    208:                sc->type_str = "WD8003E";
                    209:                memsize = 8192;
                    210:                memwidth = 8;
                    211:                break;
                    212:        case ED_TYPE_WD8013EBT:
                    213:                sc->type_str = "WD8013EBT";
                    214:                memsize = 16384;
                    215:                memwidth = 16;
                    216:                break;
                    217:        case ED_TYPE_WD8013EB:          /* also WD8003EP */
                    218:                if (inb(sc->asic_addr + ED_WD_ICR)
                    219:                        & ED_WD_ICR_16BIT) {
                    220:                        memwidth = 16;
                    221:                        memsize = 16384;
                    222:                        sc->type_str = "WD8013EB";
                    223:                } else {
                    224:                        sc->type_str = "WD8003EP";
                    225:                        memsize = 8192;
                    226:                        memwidth = 8;
                    227:                }
                    228:                break;
                    229:        case ED_TYPE_WD8013EBP:
                    230:                sc->type_str = "WD8013EBP";
                    231:                memsize = 16384;
                    232:                memwidth = 16;
                    233:                break;
                    234:        case ED_TYPE_WD8013EPC:
                    235:                sc->type_str = "WD8013EPC";
                    236:                memsize = 16384;
                    237:                memwidth = 16;
                    238:                break;
                    239:        default:
                    240:                sc->type_str = "unknown";
                    241:                memsize = 8192;
                    242:                memwidth = 8;
                    243:                break;
                    244:        }
                    245:        /*
                    246:         * Make some adjustments to initial values depending on what is
                    247:         *      found in the ICR.
                    248:         */
                    249:        if ((memwidth==16)
                    250:                && ((inb(sc->asic_addr + ED_WD_ICR) & ED_WD_ICR_16BIT) == 0)) {
                    251:                memwidth = 8;
                    252:                memsize = 8192;
                    253:        }
                    254:        if (inb(sc->asic_addr + ED_WD_ICR) & ED_WD_ICR_MSZ) {
                    255:                memsize = 32768;
                    256:        }
                    257: 
                    258: #if ED_DEBUG
                    259:        printf("type=%s memwidth=%d memsize=%d id_msize=%d\n",
                    260:                sc->type_str,memwidth,memsize,isa_dev->id_msize);
                    261:        for (i=0; i<8; i++)
                    262:                printf("%x -> %x\n", i, inb(sc->asic_addr + i));
                    263: #endif
                    264:        /*
                    265:         * Allow the user to override the autoconfiguration
                    266:         */
                    267:        if (isa_dev->id_msize)
                    268:                memsize = isa_dev->id_msize;
                    269:        /*
                    270:         * (note that if the user specifies both of the following flags
                    271:         *      that '8bit' mode intentionally has precedence)
                    272:         */
                    273:        if (isa_dev->id_flags & ED_FLAGS_FORCE_16BIT_MODE)
                    274:                memwidth = 16;
                    275:        if (isa_dev->id_flags & ED_FLAGS_FORCE_8BIT_MODE)
                    276:                memwidth = 8;
                    277: 
                    278:        /*
                    279:         * Check 83C584 interrupt configuration register if this board has one
                    280:         *      XXX - we could also check the IO address register. But why
                    281:         *              bother...if we get past this, it *has* to be correct.
                    282:         */
                    283:        if (sc->type & ED_WD_SOFTCONFIG) {
                    284:                /*
                    285:                 * Assemble together the encoded interrupt number.
                    286:                 */
                    287:                iptr = (inb(isa_dev->id_iobase + ED_WD_ICR) & ED_WD_ICR_IR2) |
                    288:                        ((inb(isa_dev->id_iobase + ED_WD_IRR) &
                    289:                                (ED_WD_IRR_IR0 | ED_WD_IRR_IR1)) >> 5);
                    290:                /*
                    291:                 * Translate it using translation table, and check for correctness.
                    292:                 */
                    293:                if (ed_intr_mask[iptr] != isa_dev->id_irq) {
                    294:                        printf("ed%d: kernel configured irq doesn't match board configured irq\n",
                    295:                                isa_dev->id_unit);
                    296:                        return(0);
                    297:                }
                    298:                /*
                    299:                 * Enable the interrupt.
                    300:                 */
                    301:                outb(isa_dev->id_iobase + ED_WD_IRR,
                    302:                        inb(isa_dev->id_iobase + ED_WD_IRR) | ED_WD_IRR_IEN);
                    303:        }
                    304: 
                    305:        sc->memwidth = memwidth;
                    306:        /*
                    307:         * allocate one xmit buffer if < 16k, two buffers otherwise
                    308:         */
                    309:        if ((memsize < 16384) || (isa_dev->id_msize & ED_FLAGS_NO_DOUBLE_BUFFERING)) {
                    310:                sc->smem_ring = sc->smem_start + (ED_PAGE_SIZE * ED_TXBUF_SIZE);
                    311:                sc->txb_cnt = 1;
                    312:                sc->rec_page_start = ED_TXBUF_SIZE;
                    313:        } else {
                    314:                sc->smem_ring = sc->smem_start + (ED_PAGE_SIZE * ED_TXBUF_SIZE * 2);
                    315:                sc->txb_cnt = 2;
                    316:                sc->rec_page_start = ED_TXBUF_SIZE * 2;
                    317:        }
                    318:        sc->smem_size = memsize;
                    319:        sc->smem_end = sc->smem_start + memsize;
                    320:        sc->rec_page_stop = memsize / ED_PAGE_SIZE;
                    321:        sc->tx_page_start = ED_WD_PAGE_OFFSET;
                    322: 
                    323:        /*
                    324:         * Get station address from on-board ROM
                    325:         */
                    326:        for (i = 0; i < ETHER_ADDR_LEN; ++i)
                    327:                sc->arpcom.ac_enaddr[i] = inb(sc->asic_addr + ED_WD_PROM + i);
                    328: 
                    329:        /*
                    330:         * Set address and enable interface shared memory.
                    331:         */
                    332:         outb(sc->asic_addr + ED_WD_MSR, ((kvtop(sc->smem_start) >> 13) &
                    333:                ED_WD_MSR_ADDR) | ED_WD_MSR_MENB);
                    334: 
                    335:        /*
                    336:         * Set upper address bits and 8/16 bit access to shared memory
                    337:         */
                    338:        if (sc->type & ED_WD_SOFTCONFIG) {
                    339:                if (memwidth == 8) {
                    340:                        outb(sc->asic_addr + ED_WD_LAAR,
                    341:                        ((kvtop(sc->smem_start) >> 19) & ED_WD_LAAR_ADDRHI));
                    342:                } else {
                    343:                        outb(sc->asic_addr + ED_WD_LAAR,
                    344:                                ED_WD_LAAR_L16EN | ED_WD_LAAR_M16EN |
                    345:                                ((kvtop(sc->smem_start) >> 19) & ED_WD_LAAR_ADDRHI));
                    346:                }
                    347:        }
                    348: 
                    349:        /*
                    350:         * Now zero memory and verify that it is clear
                    351:         */
                    352:        bzero(sc->smem_start, memsize);
                    353: 
                    354:        for (i = 0; i < memsize; ++i)
                    355:                if (sc->smem_start[i]) {
                    356:                        printf("ed%d: failed to clear shared memory at %x - check configuration\n",
                    357:                                isa_dev->id_unit, sc->smem_start + i);
                    358: 
                    359:                        /*
                    360:                         * Disable 16 bit access to shared memory
                    361:                         */
                    362:                        if (memwidth == 16)
                    363:                                outb(sc->asic_addr + ED_WD_LAAR,
                    364:                                        inb(sc->asic_addr + ED_WD_LAAR)
                    365:                                        & ~ED_WD_LAAR_M16EN);
                    366: 
                    367:                        return(0);
                    368:                }
                    369:        
                    370:        /*
                    371:         * Disable 16bit access to shared memory - we leave it disabled so
                    372:         *      that 1) machines reboot properly when the board is set
                    373:         *      16 bit mode and there are conflicting 8bit devices/ROMS
                    374:         *      in the same 128k address space as this boards shared
                    375:         *      memory. and 2) so that other 8 bit devices with shared
                    376:         *      memory can be used in this 128k region, too.
                    377:         */
                    378:        if (memwidth == 16)
                    379:                outb(sc->asic_addr + ED_WD_LAAR, inb(sc->asic_addr + ED_WD_LAAR)
                    380:                        & ~ED_WD_LAAR_M16EN);
                    381: 
                    382:        isa_dev->id_msize = memsize;
                    383:        return (ED_WD_IO_PORTS);
                    384: 
                    385: type_3Com:
                    386:        /*
                    387:         * Looks like a 3Com board
                    388:         */
                    389: 
                    390:        sc->vendor = ED_VENDOR_3COM;
                    391:        sc->asic_addr = isa_dev->id_iobase + ED_3COM_ASIC_OFFSET;
                    392:        sc->nic_addr = isa_dev->id_iobase + ED_3COM_NIC_OFFSET;
                    393: 
                    394:        sc->type_str = "3c503";
                    395: 
                    396:        memsize = 8192;
                    397: 
                    398:        /*
                    399:         * Verify that the kernel configured I/O address matches the board
                    400:         *      configured address
                    401:         */
                    402:        switch (inb(sc->asic_addr + ED_3COM_BCFR)) {
                    403:        case ED_3COM_BCFR_300:
                    404:                if (isa_dev->id_iobase != 0x300)
                    405:                        return(0);
                    406:                break;
                    407:        case ED_3COM_BCFR_310:
                    408:                if (isa_dev->id_iobase != 0x310)
                    409:                        return(0);
                    410:                break;
                    411:        case ED_3COM_BCFR_330:
                    412:                if (isa_dev->id_iobase != 0x330)
                    413:                        return(0);
                    414:                break;
                    415:        case ED_3COM_BCFR_350:
                    416:                if (isa_dev->id_iobase != 0x350)
                    417:                        return(0);
                    418:                break;
                    419:        case ED_3COM_BCFR_250:
                    420:                if (isa_dev->id_iobase != 0x250)
                    421:                        return(0);
                    422:                break;
                    423:        case ED_3COM_BCFR_280:
                    424:                if (isa_dev->id_iobase != 0x280)
                    425:                        return(0);
                    426:                break;
                    427:        case ED_3COM_BCFR_2A0:
                    428:                if (isa_dev->id_iobase != 0x2a0)
                    429:                        return(0);
                    430:                break;
                    431:        case ED_3COM_BCFR_2E0:
                    432:                if (isa_dev->id_iobase != 0x2e0)
                    433:                        return(0);
                    434:                break;
                    435:        default:
                    436:                return(0);
                    437:        }
                    438: 
                    439:        /*
                    440:         * Verify that the kernel shared memory address matches the
                    441:         *      board configured address.
                    442:         */
                    443:        switch (inb(sc->asic_addr + ED_3COM_PCFR)) {
                    444:        case ED_3COM_PCFR_DC000:
                    445:                if (kvtop(isa_dev->id_maddr) != 0xdc000)
                    446:                        return(0);
                    447:                break;
                    448:        case ED_3COM_PCFR_D8000:
                    449:                if (kvtop(isa_dev->id_maddr) != 0xd8000)
                    450:                        return(0);
                    451:                break;
                    452:        case ED_3COM_PCFR_CC000:
                    453:                if (kvtop(isa_dev->id_maddr) != 0xcc000)
                    454:                        return(0);
                    455:                break;
                    456:        case ED_3COM_PCFR_C8000:
                    457:                if (kvtop(isa_dev->id_maddr) != 0xc8000)
                    458:                        return(0);
                    459:                break;
                    460:        default:
                    461:                return(0);
                    462:        }
                    463: 
                    464:        /*
                    465:         * Reset NIC and ASIC
                    466:         */
                    467:        outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_RST);
                    468:        /*
                    469:         * Wait for a while, then un-reset it
                    470:         */
                    471:        DELAY(5000);
                    472:        outb(sc->asic_addr + ED_3COM_CR, 0);
                    473: 
                    474:        /*
                    475:         * Wait a bit for the NIC to recover from the reset
                    476:         */
                    477:        DELAY(5000);
                    478: 
                    479:        /*
                    480:         * The 3Com ASIC defaults to rather strange settings for the CR after
                    481:         *      a reset - it's important to set it so that the NIC I/O
                    482:         *      registers are mapped. The above setting of it to '0' only
                    483:         *      resets the reset condition - the CR is *not* set to zeros.
                    484:         */
                    485:        outb(sc->asic_addr + ED_3COM_CR, 0);
                    486: 
                    487:        /*
                    488:         * Determine if this is an 8bit or 16bit board
                    489:         */
                    490: 
                    491:        /*
                    492:         * select page 0 registers
                    493:         */
                    494:         outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STP);
                    495: 
                    496:        /*
                    497:         * Attempt to clear WTS bit. If it doesn't clear, then this is a
                    498:         *      16bit board.
                    499:         */
                    500:        outb(sc->nic_addr + ED_P0_DCR, 0);
                    501: 
                    502:        /*
                    503:         * select page 2 registers
                    504:         */
                    505:        outb(sc->nic_addr + ED_P0_CR, ED_CR_PAGE_2|ED_CR_RD2|ED_CR_STP);
                    506: 
                    507:        /*
                    508:         * The 3c503 forces the WTS bit to a one if this is a 16bit board
                    509:         */
                    510:        if (inb(sc->nic_addr + ED_P2_DCR) & ED_DCR_WTS)
                    511:                memwidth = 16;
                    512:        else
                    513:                memwidth = 8;
                    514: 
                    515:        /*
                    516:         * select page 0 registers
                    517:         */
                    518:         outb(sc->nic_addr + ED_P2_CR, ED_CR_RD2|ED_CR_STP);
                    519: 
                    520:        sc->txb_cnt = 1;
                    521: 
                    522:        sc->tx_page_start = ED_3COM_PAGE_OFFSET;
                    523:        sc->rec_page_start = ED_TXBUF_SIZE + ED_3COM_PAGE_OFFSET;
                    524:        sc->rec_page_stop = memsize / ED_PAGE_SIZE + ED_3COM_PAGE_OFFSET;
                    525: 
                    526:        sc->smem_size = memsize;
                    527:        sc->smem_end = sc->smem_start + memsize;
                    528:        sc->smem_ring = sc->smem_start + (ED_PAGE_SIZE * ED_TXBUF_SIZE);
                    529: 
                    530:        sc->memwidth = memwidth;
                    531: 
                    532:        /*
                    533:         * Initialize GA page start/stop registers. Probably only needed
                    534:         *      if doing DMA, but what the hell.
                    535:         */
                    536:        outb(sc->asic_addr + ED_3COM_PSTR, sc->rec_page_start);
                    537:        outb(sc->asic_addr + ED_3COM_PSPR, sc->rec_page_stop);
                    538: 
                    539:        /*
                    540:         * Set IRQ. 3c503 only allows a choice of irq 2-5.
                    541:         */
                    542:        switch (isa_dev->id_irq) {
                    543:        case IRQ2:
                    544:                outb(sc->asic_addr + ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ2);
                    545:                break;
                    546:        case IRQ3:
                    547:                outb(sc->asic_addr + ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ3);
                    548:                break;
                    549:        case IRQ4:
                    550:                outb(sc->asic_addr + ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ4);
                    551:                break;
                    552:        case IRQ5:
                    553:                outb(sc->asic_addr + ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ5);
                    554:                break;
                    555:        default:
                    556:                printf("ed%d: Invalid irq configuration\n", isa_dev->id_unit);
                    557:                return(0);
                    558:        }
                    559: 
                    560:        /*
                    561:         * Initialize GA configuration register. Set bank and enable smem.
                    562:         */
                    563:        outb(sc->asic_addr + ED_3COM_GACFR, ED_3COM_GACFR_RSEL |
                    564:                ED_3COM_GACFR_MBS0);
                    565: 
                    566:        /*
                    567:         * Initialize "Vector Pointer" registers. These gawd-awful things
                    568:         *      are compared to 20 bits of the address on ISA, and if they
                    569:         *      match, the shared memory is disabled. We set them to
                    570:         *      0xffff0...allegedly the reset vector.
                    571:         */
                    572:        outb(sc->asic_addr + ED_3COM_VPTR2, 0xff);
                    573:        outb(sc->asic_addr + ED_3COM_VPTR1, 0xff);
                    574:        outb(sc->asic_addr + ED_3COM_VPTR0, 0x00);
                    575: 
                    576:        /*
                    577:         * Get station address from on-board ROM
                    578:         */
                    579:        /*
                    580:         * First, map ethernet address PROM over the top of where the NIC
                    581:         *      registers normally appear.
                    582:         */
                    583:        outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_EALO);
                    584: 
                    585:        for (i = 0; i < ETHER_ADDR_LEN; ++i)
                    586:                sc->arpcom.ac_enaddr[i] = inb(sc->nic_addr + i);
                    587: 
                    588:        /*
                    589:         * Unmap PROM - select NIC registers. Tranceiver remains disabled at
                    590:         *      this point. It's enabled in ed_init so that the attach code
                    591:         *      is given a chance to set the default based on a compile-time
                    592:         *      config option
                    593:         */
                    594:        outb(sc->asic_addr + ED_3COM_CR, 0);
                    595: 
                    596: #if 0
                    597: printf("Starting write\n");
                    598: for (i = 0; i < 8192; ++i)
                    599:        bzero(sc->smem_start, 8192);
                    600: printf("Done.\n");
                    601: #endif
                    602: #if 0
                    603: { char test_buf[1024];
                    604: printf("starting write\n");
                    605:        for (i = 0; i < 8*8192; ++i)
                    606:        bcopy(test_buf, sc->smem_start, 1024);
                    607: printf("starting read\n");
                    608:        for (i = 0; i < 8*8192; ++i)
                    609:        bcopy(sc->smem_start, test_buf, 1024);
                    610: printf("done.\n");
                    611: }
                    612: #endif
                    613: 
                    614:        /*
                    615:         * Zero memory and verify that it is clear
                    616:         */
                    617:        bzero(sc->smem_start, memsize);
                    618: 
                    619:        for (i = 0; i < memsize; ++i)
                    620:                if (sc->smem_start[i]) {
                    621:                        printf("ed%d: failed to clear shared memory at %x - check configuration\n",
                    622:                                isa_dev->id_unit, sc->smem_start + i);
                    623:                        return(0);
                    624:                }
                    625: 
                    626:        isa_dev->id_msize = memsize;
                    627:        return(ED_3COM_IO_PORTS);
                    628: }
                    629:  
                    630: /*
                    631:  * Install interface into kernel networking data structures
                    632:  */
                    633: int
                    634: ed_attach(isa_dev)
                    635:        struct isa_device *isa_dev;
                    636: {
                    637:        struct ed_softc *sc = &ed_softc[isa_dev->id_unit];
                    638:        struct ifnet *ifp = &sc->arpcom.ac_if;
                    639:        struct ifaddr *ifa;
                    640:        struct sockaddr_dl *sdl;
                    641:  
                    642:        /*
                    643:         * Set interface to stopped condition (reset)
                    644:         */
                    645:        ed_stop(isa_dev->id_unit);
                    646: 
                    647:        /*
                    648:         * Initialize ifnet structure
                    649:         */
                    650:        ifp->if_unit = isa_dev->id_unit;
                    651:        ifp->if_name = "ed" ;
                    652:        ifp->if_mtu = ETHERMTU;
                    653:        ifp->if_init = ed_init;
                    654:        ifp->if_output = ether_output;
                    655:        ifp->if_start = ed_start;
                    656:        ifp->if_ioctl = ed_ioctl;
                    657:        ifp->if_reset = ed_reset;
                    658:        ifp->if_watchdog = ed_watchdog;
                    659: 
                    660:        /*
                    661:         * Set default state for LLC0 flag (used to disable the tranceiver
                    662:         *      for AUI operation), based on compile-time config option.
                    663:         */
                    664:        if (isa_dev->id_flags & ED_FLAGS_DISABLE_TRANCEIVER)
                    665:                ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS
                    666:                        | IFF_LLC0);
                    667:        else
                    668:                ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS);
                    669: 
                    670:        /*
                    671:         * Attach the interface
                    672:         */
                    673:        if_attach(ifp);
                    674: 
                    675:        /*
                    676:         * Search down the ifa address list looking for the AF_LINK type entry
                    677:         */
                    678:        ifa = ifp->if_addrlist;
                    679:        while ((ifa != 0) && (ifa->ifa_addr != 0) &&
                    680:            (ifa->ifa_addr->sa_family != AF_LINK))
                    681:                ifa = ifa->ifa_next;
                    682:        /*
                    683:         * If we find an AF_LINK type entry we fill in the hardware address.
                    684:         *      This is useful for netstat(1) to keep track of which interface
                    685:         *      is which.
                    686:         */
                    687:        if ((ifa != 0) && (ifa->ifa_addr != 0)) {
                    688:                /*
                    689:                 * Fill in the link-level address for this interface
                    690:                 */
                    691:                sdl = (struct sockaddr_dl *)ifa->ifa_addr;
                    692:                sdl->sdl_type = IFT_ETHER;
                    693:                sdl->sdl_alen = ETHER_ADDR_LEN;
                    694:                sdl->sdl_slen = 0;
                    695:                bcopy(sc->arpcom.ac_enaddr, LLADDR(sdl), ETHER_ADDR_LEN);
                    696:        }
                    697: 
                    698:        /*
                    699:         * Print additional info when attached
                    700:         */
                    701:        printf("ed%d: address %s, type %s (%dbit) %s\n", isa_dev->id_unit,
                    702:                ether_sprintf(sc->arpcom.ac_enaddr), sc->type_str,
                    703:                sc->memwidth, ((sc->vendor == ED_VENDOR_3COM) &&
                    704:                        (ifp->if_flags & IFF_LLC0)) ? "tranceiver disabled" : "");
                    705: 
                    706:        /*
                    707:         * If BPF is in the kernel, call the attach for it
                    708:         */
                    709: #if NBPFILTER > 0
                    710:        bpfattach(&sc->bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
                    711: #endif
                    712: 
                    713: }
                    714:  
                    715: /*
                    716:  * Reset interface.
                    717:  */
                    718: int
                    719: ed_reset(unit)
                    720:        int unit;
                    721: {
                    722:        int s;
                    723: 
                    724:        s = splnet();
                    725: 
                    726:        /*
                    727:         * Stop interface and re-initialize.
                    728:         */
                    729:        ed_stop(unit);
                    730:        ed_init(unit);
                    731: 
                    732:        s = splx(s);
                    733: }
                    734:  
                    735: /*
                    736:  * Take interface offline.
                    737:  */
                    738: void
                    739: ed_stop(unit)
                    740:        int unit;
                    741: {
                    742:        struct ed_softc *sc = &ed_softc[unit];
                    743:        int n = 5000;
                    744:  
                    745:        /*
                    746:         * Stop everything on the interface, and select page 0 registers.
                    747:         */
                    748:        outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STP);
                    749: 
                    750:        /*
                    751:         * Wait for interface to enter stopped state, but limit # of checks
                    752:         *      to 'n' (about 5ms). It shouldn't even take 5us on modern
                    753:         *      DS8390's, but just in case it's an old one.
                    754:         */
                    755:        while (((inb(sc->nic_addr + ED_P0_ISR) & ED_ISR_RST) == 0) && --n);
                    756: 
                    757: }
                    758: 
                    759: /*
                    760:  * Device timeout/watchdog routine. Entered if the device neglects to
                    761:  *     generate an interrupt after a transmit has been started on it.
                    762:  */
                    763: int
                    764: ed_watchdog(unit)
                    765:        int unit;
                    766: {
                    767:        log(LOG_ERR, "ed%d: device timeout\n", unit);
                    768: 
                    769:        ed_reset(unit);
                    770: }
                    771: 
                    772: /*
                    773:  * Initialize device. 
                    774:  */
                    775: ed_init(unit)
                    776:        int unit;
                    777: {
                    778:        struct ed_softc *sc = &ed_softc[unit];
                    779:        struct ifnet *ifp = &sc->arpcom.ac_if;
                    780:        int i, s;
                    781:        u_char  command;
                    782: 
                    783: 
                    784:        /* address not known */
                    785:        if (ifp->if_addrlist == (struct ifaddr *)0) return;
                    786: 
                    787:        /*
                    788:         * Initialize the NIC in the exact order outlined in the NS manual.
                    789:         *      This init procedure is "mandatory"...don't change what or when
                    790:         *      things happen.
                    791:         */
                    792:        s = splnet();
                    793: 
                    794:        /* reset transmitter flags */
                    795:        sc->data_buffered = 0;
                    796:        sc->xmit_busy = 0;
                    797:        sc->arpcom.ac_if.if_timer = 0;
                    798: 
                    799:        sc->txb_next = 0;
                    800: 
                    801:        /* This variable is used below - don't move this assignment */
                    802:        sc->next_packet = sc->rec_page_start + 1;
                    803: 
                    804:        /*
                    805:         * Set interface for page 0, Remote DMA complete, Stopped
                    806:         */
                    807:        outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STP);
                    808: 
                    809:        if (sc->memwidth == 16) {
                    810:                /*
                    811:                 * Set FIFO threshold to 8, No auto-init Remote DMA,
                    812:                 *      byte order=80x86, word-wide DMA xfers
                    813:                 */
                    814:                outb(sc->nic_addr + ED_P0_DCR, ED_DCR_FT1|ED_DCR_WTS);
                    815:        } else {
                    816:                /*
                    817:                 * Same as above, but byte-wide DMA xfers
                    818:                 */
                    819:                outb(sc->nic_addr + ED_P0_DCR, ED_DCR_FT1);
                    820:        }
                    821: 
                    822:        /*
                    823:         * Clear Remote Byte Count Registers
                    824:         */
                    825:        outb(sc->nic_addr + ED_P0_RBCR0, 0);
                    826:        outb(sc->nic_addr + ED_P0_RBCR1, 0);
                    827: 
                    828:        /*
                    829:         * Enable reception of broadcast packets
                    830:         */
                    831:        outb(sc->nic_addr + ED_P0_RCR, ED_RCR_AB);
                    832: 
                    833:        /*
                    834:         * Place NIC in internal loopback mode
                    835:         */
                    836:        outb(sc->nic_addr + ED_P0_TCR, ED_TCR_LB0);
                    837: 
                    838:        /*
                    839:         * Initialize transmit/receive (ring-buffer) Page Start
                    840:         */
                    841:        outb(sc->nic_addr + ED_P0_TPSR, sc->tx_page_start);
                    842:        outb(sc->nic_addr + ED_P0_PSTART, sc->rec_page_start);
                    843: 
                    844:        /*
                    845:         * Initialize Receiver (ring-buffer) Page Stop and Boundry
                    846:         */
                    847:        outb(sc->nic_addr + ED_P0_PSTOP, sc->rec_page_stop);
                    848:        outb(sc->nic_addr + ED_P0_BNRY, sc->rec_page_start);
                    849: 
                    850:        /*
                    851:         * Clear all interrupts. A '1' in each bit position clears the
                    852:         *      corresponding flag.
                    853:         */
                    854:        outb(sc->nic_addr + ED_P0_ISR, 0xff);
                    855: 
                    856:        /*
                    857:         * Enable the following interrupts: receive/transmit complete,
                    858:         *      receive/transmit error, and Receiver OverWrite.
                    859:         *
                    860:         * Counter overflow and Remote DMA complete are *not* enabled.
                    861:         */
                    862:        outb(sc->nic_addr + ED_P0_IMR,
                    863:                ED_IMR_PRXE|ED_IMR_PTXE|ED_IMR_RXEE|ED_IMR_TXEE|ED_IMR_OVWE);
                    864: 
                    865:        /*
                    866:         * Program Command Register for page 1
                    867:         */
                    868:        outb(sc->nic_addr + ED_P0_CR, ED_CR_PAGE_1|ED_CR_RD2|ED_CR_STP);
                    869: 
                    870:        /*
                    871:         * Copy out our station address
                    872:         */
                    873:        for (i = 0; i < ETHER_ADDR_LEN; ++i)
                    874:                outb(sc->nic_addr + ED_P1_PAR0 + i, sc->arpcom.ac_enaddr[i]);
                    875: 
                    876: #if NBPFILTER > 0
                    877:        /*
                    878:         * Initialize multicast address hashing registers to accept
                    879:         *       all multicasts (only used when in promiscuous mode)
                    880:         */
                    881:        for (i = 0; i < 8; ++i)
                    882:                outb(sc->nic_addr + ED_P1_MAR0 + i, 0xff);
                    883: #endif
                    884: 
                    885:        /*
                    886:         * Set Current Page pointer to next_packet (initialized above)
                    887:         */
                    888:        outb(sc->nic_addr + ED_P1_CURR, sc->next_packet);
                    889: 
                    890:        /*
                    891:         * Set Command Register for page 0, Remote DMA complete,
                    892:         *      and interface Start.
                    893:         */
                    894:        outb(sc->nic_addr + ED_P1_CR, ED_CR_RD2|ED_CR_STA);
                    895: 
                    896:        /*
                    897:         * Take interface out of loopback
                    898:         */
                    899:        outb(sc->nic_addr + ED_P0_TCR, 0);
                    900: 
                    901:        /*
                    902:         * If this is a 3Com board, the tranceiver must be software enabled
                    903:         *      (there is no settable hardware default).
                    904:         */
                    905:        if (sc->vendor == ED_VENDOR_3COM) {
                    906:                if (ifp->if_flags & IFF_LLC0) {
                    907:                        outb(sc->asic_addr + ED_3COM_CR, 0);
                    908:                } else {
                    909:                        outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_XSEL);
                    910:                }
                    911:        }
                    912: 
                    913:        /*
                    914:         * Set 'running' flag, and clear output active flag.
                    915:         */
                    916:        ifp->if_flags |= IFF_RUNNING;
                    917:        ifp->if_flags &= ~IFF_OACTIVE;
                    918: 
                    919:        /*
                    920:         * ...and attempt to start output
                    921:         */
                    922:        ed_start(ifp);
                    923: 
                    924:        (void) splx(s);
                    925: }
                    926:  
                    927: /*
                    928:  * This routine actually starts the transmission on the interface
                    929:  */
                    930: static inline void ed_xmit(ifp)
                    931:        struct ifnet *ifp;
                    932: {
                    933:        struct ed_softc *sc = &ed_softc[ifp->if_unit];
                    934:        u_short len = sc->txb_next_len;
                    935: 
                    936:        /*
                    937:         * Set NIC for page 0 register access
                    938:         */
                    939:        outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STA);
                    940: 
                    941:        /*
                    942:         * Set TX buffer start page
                    943:         */
                    944:        outb(sc->nic_addr + ED_P0_TPSR, sc->tx_page_start +
                    945:                sc->txb_next * ED_TXBUF_SIZE);
                    946: 
                    947:        /*
                    948:         * Set TX length
                    949:         */
                    950:        outb(sc->nic_addr + ED_P0_TBCR0, len & 0xff);
                    951:        outb(sc->nic_addr + ED_P0_TBCR1, len >> 8);
                    952: 
                    953:        /*
                    954:         * Set page 0, Remote DMA complete, Transmit Packet, and *Start*
                    955:         */
                    956:        outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_TXP|ED_CR_STA);
                    957: 
                    958:        sc->xmit_busy = 1;
                    959:        sc->data_buffered = 0;
                    960:        
                    961:        /*
                    962:         * Switch buffers if we are doing double-buffered transmits
                    963:         */
                    964:        if ((sc->txb_next == 0) && (sc->txb_cnt > 1)) 
                    965:                sc->txb_next = 1;
                    966:        else
                    967:                sc->txb_next = 0;
                    968: 
                    969:        /*
                    970:         * Set a timer just in case we never hear from the board again
                    971:         */
                    972:        ifp->if_timer = 2;
                    973: }
                    974: 
                    975: /*
                    976:  * Start output on interface.
                    977:  * We make two assumptions here:
                    978:  *  1) that the current priority is set to splnet _before_ this code
                    979:  *     is called *and* is returned to the appropriate priority after
                    980:  *     return
                    981:  *  2) that the IFF_OACTIVE flag is checked before this code is called
                    982:  *     (i.e. that the output part of the interface is idle)
                    983:  */
                    984: int
                    985: ed_start(ifp)
                    986:        struct ifnet *ifp;
                    987: {
                    988:        struct ed_softc *sc = &ed_softc[ifp->if_unit];
                    989:        struct mbuf *m0, *m;
                    990:        caddr_t buffer;
                    991:        int len;
                    992:        u_char laar_tmp;
                    993: 
                    994: outloop:
                    995:        /*
                    996:         * See if there is room to send more data (i.e. one or both of the
                    997:         *      buffers is empty).
                    998:         */
                    999:        if (sc->data_buffered)
                   1000:                if (sc->xmit_busy) {
                   1001:                        /*
                   1002:                         * No room. Indicate this to the outside world
                   1003:                         *      and exit.
                   1004:                         */
                   1005:                        ifp->if_flags |= IFF_OACTIVE;
                   1006:                        return;
                   1007:                } else {
                   1008:                        /*
                   1009:                         * Data is buffered, but we're not transmitting, so
                   1010:                         *      start the xmit on the buffered data.
                   1011:                         * Note that ed_xmit() resets the data_buffered flag
                   1012:                         *      before returning.
                   1013:                         */
                   1014:                        ed_xmit(ifp);
                   1015:                }
                   1016: 
                   1017:        IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
                   1018:        if (m == 0) {
                   1019:        /*
                   1020:         * The following isn't pretty; we are using the !OACTIVE flag to
                   1021:         * indicate to the outside world that we can accept an additional
                   1022:         * packet rather than that the transmitter is _actually_
                   1023:         * active. Indeed, the transmitter may be active, but if we haven't
                   1024:         * filled the secondary buffer with data then we still want to
                   1025:         * accept more.
                   1026:         * Note that it isn't necessary to test the data_buffered flag -
                   1027:         * we wouldn't have tried to de-queue the packet in the first place
                   1028:         * if it was set.
                   1029:         */
                   1030:                ifp->if_flags &= ~IFF_OACTIVE;
                   1031:                return;
                   1032:        }
                   1033: 
                   1034:        /*
                   1035:         * Copy the mbuf chain into the transmit buffer
                   1036:         */
                   1037:        /*
                   1038:         * Enable 16bit access to shared memory on WD/SMC boards
                   1039:         */
                   1040:        if (sc->memwidth == 16)
                   1041:                if (sc->vendor == ED_VENDOR_WD_SMC) {
                   1042:                        laar_tmp = inb(sc->asic_addr + ED_WD_LAAR);
                   1043:                        outb(sc->asic_addr + ED_WD_LAAR, laar_tmp | ED_WD_LAAR_M16EN);
                   1044:                }
                   1045: 
                   1046:        buffer = sc->smem_start + (sc->txb_next * ED_TXBUF_SIZE * ED_PAGE_SIZE);
                   1047:        len = 0;
                   1048:        for (m0 = m; m != 0; m = m->m_next) {
                   1049:                bcopy(mtod(m, caddr_t), buffer, m->m_len);
                   1050:                buffer += m->m_len;
                   1051:                len += m->m_len;
                   1052:        }
                   1053: 
                   1054:        /*
                   1055:         * Restore previous shared mem access type
                   1056:         */
                   1057:        if (sc->memwidth == 16)
                   1058:                if (sc->vendor == ED_VENDOR_WD_SMC) {
                   1059:                        outb(sc->asic_addr + ED_WD_LAAR, laar_tmp);
                   1060:                }
                   1061: 
                   1062:        sc->txb_next_len = MAX(len, ETHER_MIN_LEN);
                   1063: 
                   1064:        if (sc->txb_cnt > 1)
                   1065:                /*
                   1066:                 * only set 'buffered' flag if doing multiple buffers
                   1067:                 */
                   1068:                sc->data_buffered = 1;
                   1069: 
                   1070:        if (sc->xmit_busy == 0)
                   1071:                ed_xmit(ifp);
                   1072:        /*
                   1073:         * If there is BPF support in the configuration, tap off here.
                   1074:         *   The following has support for converting trailer packets
                   1075:         *   back to normal.
                   1076:         */
                   1077: #if NBPFILTER > 0
                   1078:        if (sc->bpf) {
                   1079:                u_short etype;
                   1080:                int off, datasize, resid;
                   1081:                struct ether_header *eh;
                   1082:                struct trailer_header {
                   1083:                        u_short ether_type;
                   1084:                        u_short ether_residual;
                   1085:                } trailer_header;
                   1086:                char ether_packet[ETHER_MAX_LEN];
                   1087:                char *ep;
                   1088: 
                   1089:                ep = ether_packet;
                   1090: 
                   1091:                /*
                   1092:                 * We handle trailers below:
                   1093:                 * Copy ether header first, then residual data,
                   1094:                 * then data. Put all this in a temporary buffer
                   1095:                 * 'ether_packet' and send off to bpf. Since the
                   1096:                 * system has generated this packet, we assume
                   1097:                 * that all of the offsets in the packet are
                   1098:                 * correct; if they're not, the system will almost
                   1099:                 * certainly crash in m_copydata.
                   1100:                 * We make no assumptions about how the data is
                   1101:                 * arranged in the mbuf chain (i.e. how much
                   1102:                 * data is in each mbuf, if mbuf clusters are
                   1103:                 * used, etc.), which is why we use m_copydata
                   1104:                 * to get the ether header rather than assume
                   1105:                 * that this is located in the first mbuf.
                   1106:                 */
                   1107:                /* copy ether header */
                   1108:                m_copydata(m0, 0, sizeof(struct ether_header), ep);
                   1109:                eh = (struct ether_header *) ep;
                   1110:                ep += sizeof(struct ether_header);
                   1111:                etype = ntohs(eh->ether_type);
                   1112:                if (etype >= ETHERTYPE_TRAIL &&
                   1113:                    etype < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
                   1114:                        datasize = ((etype - ETHERTYPE_TRAIL) << 9);
                   1115:                        off = datasize + sizeof(struct ether_header);
                   1116: 
                   1117:                        /* copy trailer_header into a data structure */
                   1118:                        m_copydata(m0, off, sizeof(struct trailer_header),
                   1119:                                &trailer_header.ether_type);
                   1120: 
                   1121:                        /* copy residual data */
                   1122:                        m_copydata(m0, off+sizeof(struct trailer_header),
                   1123:                                resid = ntohs(trailer_header.ether_residual) -
                   1124:                                sizeof(struct trailer_header), ep);
                   1125:                        ep += resid;
                   1126: 
                   1127:                        /* copy data */
                   1128:                        m_copydata(m0, sizeof(struct ether_header),
                   1129:                                datasize, ep);
                   1130:                        ep += datasize;
                   1131: 
                   1132:                        /* restore original ether packet type */
                   1133:                        eh->ether_type = trailer_header.ether_type;
                   1134: 
                   1135:                        bpf_tap(sc->bpf, ether_packet, ep - ether_packet);
                   1136:                } else
                   1137:                        bpf_mtap(sc->bpf, m0);
                   1138:        }
                   1139: #endif
                   1140: 
                   1141:        m_freem(m0);
                   1142: 
                   1143:        /*
                   1144:         * If we are doing double-buffering, a buffer might be free to
                   1145:         *      fill with another packet, so loop back to the top.
                   1146:         */
                   1147:        if (sc->txb_cnt > 1)
                   1148:                goto outloop;
                   1149:        else {
                   1150:                ifp->if_flags |= IFF_OACTIVE;
                   1151:                return;
                   1152:        }
                   1153: }
                   1154:  
                   1155: /*
                   1156:  * Ethernet interface receiver interrupt.
                   1157:  */
                   1158: static inline void /* only called from one place, so may as well integrate */
                   1159: ed_rint(unit)
                   1160:        int unit;
                   1161: {
                   1162:        register struct ed_softc *sc = &ed_softc[unit];
                   1163:        u_char boundry, current;
                   1164:        u_short len;
                   1165:        struct ed_ring *packet_ptr;
                   1166: 
                   1167:        /*
                   1168:         * Set NIC to page 1 registers to get 'current' pointer
                   1169:         */
                   1170:        outb(sc->nic_addr + ED_P0_CR, ED_CR_PAGE_1|ED_CR_RD2|ED_CR_STA);
                   1171: 
                   1172:        /*
                   1173:         * 'sc->next_packet' is the logical beginning of the ring-buffer - i.e.
                   1174:         *      it points to where new data has been buffered. The 'CURR'
                   1175:         *      (current) register points to the logical end of the ring-buffer
                   1176:         *      - i.e. it points to where additional new data will be added.
                   1177:         *      We loop here until the logical beginning equals the logical
                   1178:         *      end (or in other words, until the ring-buffer is empty).
                   1179:         */
                   1180:        while (sc->next_packet != inb(sc->nic_addr + ED_P1_CURR)) {
                   1181: 
                   1182:                /* get pointer to this buffer header structure */
                   1183:                packet_ptr = (struct ed_ring *)(sc->smem_ring +
                   1184:                         (sc->next_packet - sc->rec_page_start) * ED_PAGE_SIZE);
                   1185: 
                   1186:                /*
                   1187:                 * The byte count includes the FCS - Frame Check Sequence (a
                   1188:                 *      32 bit CRC).
                   1189:                 */
                   1190:                len = packet_ptr->count;
                   1191:                if ((len >= ETHER_MIN_LEN) && (len <= ETHER_MAX_LEN)) {
                   1192:                        /*
                   1193:                         * Go get packet. len - 4 removes CRC from length.
                   1194:                         * (packet_ptr + 1) points to data just after the packet ring
                   1195:                         *      header (+4 bytes)
                   1196:                         */
                   1197:                        ed_get_packet(sc, (caddr_t)(packet_ptr + 1), len - 4);
                   1198:                        ++sc->arpcom.ac_if.if_ipackets;
                   1199:                } else {
                   1200:                        /*
                   1201:                         * Really BAD...probably indicates that the ring pointers
                   1202:                         *      are corrupted. Also seen on early rev chips under
                   1203:                         *      high load - the byte order of the length gets switched.
                   1204:                         */
                   1205:                        log(LOG_ERR,
                   1206:                                "ed%d: shared memory corrupt - invalid packet length %d\n",
                   1207:                                unit, len);
                   1208:                        ed_reset(unit);
                   1209:                        return;
                   1210:                }
                   1211: 
                   1212:                /*
                   1213:                 * Update next packet pointer
                   1214:                 */
                   1215:                sc->next_packet = packet_ptr->next_packet;
                   1216: 
                   1217:                /*
                   1218:                 * Update NIC boundry pointer - being careful to keep it
                   1219:                 *      one buffer behind. (as recommended by NS databook)
                   1220:                 */
                   1221:                boundry = sc->next_packet - 1;
                   1222:                if (boundry < sc->rec_page_start)
                   1223:                        boundry = sc->rec_page_stop - 1;
                   1224: 
                   1225:                /*
                   1226:                 * Set NIC to page 0 registers to update boundry register
                   1227:                 */
                   1228:                outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STA);
                   1229: 
                   1230:                outb(sc->nic_addr + ED_P0_BNRY, boundry);
                   1231: 
                   1232:                /*
                   1233:                 * Set NIC to page 1 registers before looping to top (prepare to
                   1234:                 *      get 'CURR' current pointer)
                   1235:                 */
                   1236:                outb(sc->nic_addr + ED_P0_CR, ED_CR_PAGE_1|ED_CR_RD2|ED_CR_STA);
                   1237:        }
                   1238: }
                   1239: 
                   1240: /*
                   1241:  * Ethernet interface interrupt processor
                   1242:  */
                   1243: int
                   1244: edintr(unit)
                   1245:        int unit;
                   1246: {
                   1247:        struct ed_softc *sc = &ed_softc[unit];
                   1248:        u_char isr;
                   1249: 
                   1250:        /*
                   1251:         * Set NIC to page 0 registers
                   1252:         */
                   1253:        outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STA);
                   1254: 
                   1255:        /*
                   1256:         * loop until there are no more new interrupts
                   1257:         */
                   1258:        while (isr = inb(sc->nic_addr + ED_P0_ISR)) {
                   1259: 
                   1260:                /*
                   1261:                 * reset all the bits that we are 'acknowleging'
                   1262:                 *      by writing a '1' to each bit position that was set
                   1263:                 * (writing a '1' *clears* the bit)
                   1264:                 */
                   1265:                outb(sc->nic_addr + ED_P0_ISR, isr);
                   1266: 
                   1267:                /*
                   1268:                 * Transmit error. If a TX completed with an error, we end up
                   1269:                 *      throwing the packet away. Really the only error that is
                   1270:                 *      possible is excessive collisions, and in this case it is
                   1271:                 *      best to allow the automatic mechanisms of TCP to backoff
                   1272:                 *      the flow. Of course, with UDP we're screwed, but this is
                   1273:                 *      expected when a network is heavily loaded.
                   1274:                 */
                   1275:                if (isr & ED_ISR_TXE) {
                   1276:                        u_char tsr = inb(sc->nic_addr + ED_P0_TSR);
                   1277:                        u_char ncr = inb(sc->nic_addr + ED_P0_NCR);
                   1278: 
                   1279:                        /*
                   1280:                         * Excessive collisions (16)
                   1281:                         */
                   1282:                        if ((tsr & ED_TSR_ABT) && (ncr == 0)) {
                   1283:                                /*
                   1284:                                 *    When collisions total 16, the P0_NCR will
                   1285:                                 * indicate 0, and the TSR_ABT is set.
                   1286:                                 */
                   1287:                                sc->arpcom.ac_if.if_collisions += 16;
                   1288:                        } else
                   1289:                                sc->arpcom.ac_if.if_collisions += ncr;
                   1290: 
                   1291:                        /*
                   1292:                         * update output errors counter
                   1293:                         */
                   1294:                        ++sc->arpcom.ac_if.if_oerrors;
                   1295: 
                   1296:                        /*
                   1297:                         * reset tx busy and output active flags
                   1298:                         */
                   1299:                        sc->xmit_busy = 0;
                   1300:                        sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
                   1301: 
                   1302:                        /*
                   1303:                         * clear watchdog timer
                   1304:                         */
                   1305:                        sc->arpcom.ac_if.if_timer = 0;
                   1306:                }
                   1307:                                
                   1308:                        
                   1309:                /*
                   1310:                 * Receiver Error. One or more of: CRC error, frame alignment error
                   1311:                 *      FIFO overrun, or missed packet.
                   1312:                 */
                   1313:                if (isr & ED_ISR_RXE) {
                   1314:                        ++sc->arpcom.ac_if.if_ierrors;
                   1315: #ifdef ED_DEBUG
                   1316:                        printf("ed%d: receive error %x\n", unit,
                   1317:                                inb(sc->nic_addr + ED_P0_RSR));
                   1318: #endif
                   1319:                }
                   1320: 
                   1321:                /*
                   1322:                 * Overwrite warning. In order to make sure that a lockup
                   1323:                 *      of the local DMA hasn't occurred, we reset and
                   1324:                 *      re-init the NIC. The NSC manual suggests only a
                   1325:                 *      partial reset/re-init is necessary - but some
                   1326:                 *      chips seem to want more. The DMA lockup has been
                   1327:                 *      seen only with early rev chips - Methinks this
                   1328:                 *      bug was fixed in later revs. -DG
                   1329:                 */
                   1330:                if (isr & ED_ISR_OVW) {
                   1331:                        ++sc->arpcom.ac_if.if_ierrors;
                   1332:                        log(LOG_WARNING,
                   1333:                                "ed%d: warning - receiver ring buffer overrun\n",
                   1334:                                unit);
                   1335:                        /*
                   1336:                         * Stop/reset/re-init NIC
                   1337:                         */
                   1338:                        ed_reset(unit);
                   1339:                }
                   1340: 
                   1341:                /*
                   1342:                 * Transmission completed normally.
                   1343:                 */
                   1344:                if (isr & ED_ISR_PTX) {
                   1345: 
                   1346:                        /*
                   1347:                         * reset tx busy and output active flags
                   1348:                         */
                   1349:                        sc->xmit_busy = 0;
                   1350:                        sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
                   1351: 
                   1352:                        /*
                   1353:                         * clear watchdog timer
                   1354:                         */
                   1355:                        sc->arpcom.ac_if.if_timer = 0;
                   1356: 
                   1357:                        /*
                   1358:                         * Update total number of successfully transmitted
                   1359:                         *      packets.
                   1360:                         */
                   1361:                        ++sc->arpcom.ac_if.if_opackets;
                   1362: 
                   1363:                        /*
                   1364:                         * Add in total number of collisions on last
                   1365:                         *      transmission.
                   1366:                         */
                   1367:                        sc->arpcom.ac_if.if_collisions += inb(sc->nic_addr +
                   1368:                                ED_P0_TBCR0);
                   1369:                }
                   1370: 
                   1371:                /*
                   1372:                 * Receive Completion. Go and get the packet. 
                   1373:                 *      XXX - Doing this on an error is dubious because there
                   1374:                 *         shouldn't be any data to get (we've configured the
                   1375:                 *         interface to not accept packets with errors).
                   1376:                 */
                   1377:                if (isr & (ED_ISR_PRX|ED_ISR_RXE)) {
                   1378:                        /*
                   1379:                         * Enable access to shared memory on WD/SMC boards
                   1380:                         */
                   1381:                        if (sc->memwidth == 16)
                   1382:                                if (sc->vendor == ED_VENDOR_WD_SMC) {
                   1383:                                        outb(sc->asic_addr + ED_WD_LAAR,
                   1384:                                                inb(sc->asic_addr + ED_WD_LAAR)
                   1385:                                                | ED_WD_LAAR_M16EN);
                   1386:                                }
                   1387: 
                   1388:                        ed_rint (unit);
                   1389: 
                   1390:                        /*
                   1391:                         * Disable access to shared memory
                   1392:                         */
                   1393:                        if (sc->memwidth == 16)
                   1394:                                if (sc->vendor == ED_VENDOR_WD_SMC) {
                   1395:                                        outb(sc->asic_addr + ED_WD_LAAR,
                   1396:                                                inb(sc->asic_addr + ED_WD_LAAR)
                   1397:                                                & ~ED_WD_LAAR_M16EN);
                   1398:                                }
                   1399:                }
                   1400: 
                   1401:                /*
                   1402:                 * If it looks like the transmitter can take more data,
                   1403:                 *      attempt to start output on the interface. If data is
                   1404:                 *      already buffered and ready to go, send it first.
                   1405:                 */
                   1406:                if ((sc->arpcom.ac_if.if_flags & IFF_OACTIVE) == 0) {
                   1407:                        if (sc->data_buffered)
                   1408:                                ed_xmit(&sc->arpcom.ac_if);
                   1409:                        ed_start(&sc->arpcom.ac_if);
                   1410:                }
                   1411: 
                   1412:                /*
                   1413:                 * return NIC CR to standard state: page 0, remote DMA complete,
                   1414:                 *      start (toggling the TXP bit off, even if was just set
                   1415:                 *      in the transmit routine, is *okay* - it is 'edge'
                   1416:                 *      triggered from low to high)
                   1417:                 */
                   1418:                outb(sc->nic_addr + ED_P0_CR, ED_CR_RD2|ED_CR_STA);
                   1419: 
                   1420:                /*
                   1421:                 * If the Network Talley Counters overflow, read them to
                   1422:                 *      reset them. It appears that old 8390's won't
                   1423:                 *      clear the ISR flag otherwise - resulting in an
                   1424:                 *      infinite loop.
                   1425:                 */
                   1426:                if (isr & ED_ISR_CNT) {
                   1427:                        (void) inb(sc->nic_addr + ED_P0_CNTR0);
                   1428:                        (void) inb(sc->nic_addr + ED_P0_CNTR1);
                   1429:                        (void) inb(sc->nic_addr + ED_P0_CNTR2);
                   1430:                }
                   1431:        }
                   1432: }
                   1433:  
                   1434: /*
                   1435:  * Process an ioctl request. This code needs some work - it looks
                   1436:  *     pretty ugly.
                   1437:  */
                   1438: int
                   1439: ed_ioctl(ifp, command, data)
                   1440:        register struct ifnet *ifp;
                   1441:        int command;
                   1442:        caddr_t data;
                   1443: {
                   1444:        register struct ifaddr *ifa = (struct ifaddr *)data;
                   1445:        struct ed_softc *sc = &ed_softc[ifp->if_unit];
                   1446:        struct ifreq *ifr = (struct ifreq *)data;
                   1447:        int s, error = 0;
                   1448: 
                   1449:        s = splnet();
                   1450: 
                   1451:        switch (command) {
                   1452: 
                   1453:        case SIOCSIFADDR:
                   1454:                ifp->if_flags |= IFF_UP;
                   1455: 
                   1456:                switch (ifa->ifa_addr->sa_family) {
                   1457: #ifdef INET
                   1458:                case AF_INET:
                   1459:                        ed_init(ifp->if_unit);  /* before arpwhohas */
                   1460:                        /*
                   1461:                         * See if another station has *our* IP address.
                   1462:                         * i.e.: There is an address conflict! If a
                   1463:                         * conflict exists, a message is sent to the
                   1464:                         * console.
                   1465:                         */
                   1466:                        ((struct arpcom *)ifp)->ac_ipaddr =
                   1467:                                IA_SIN(ifa)->sin_addr;
                   1468:                        arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
                   1469:                        break;
                   1470: #endif
                   1471: #ifdef NS
                   1472:                /*
                   1473:                 * XXX - This code is probably wrong
                   1474:                 */
                   1475:                case AF_NS:
                   1476:                    {
                   1477:                        register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
                   1478: 
                   1479:                        if (ns_nullhost(*ina))
                   1480:                                ina->x_host =
                   1481:                                        *(union ns_host *)(sc->arpcom.ac_enaddr);
                   1482:                        else {
                   1483:                                /* 
                   1484:                                 * 
                   1485:                                 */
                   1486:                                bcopy((caddr_t)ina->x_host.c_host,
                   1487:                                    (caddr_t)sc->arpcom.ac_enaddr,
                   1488:                                        sizeof(sc->arpcom.ac_enaddr));
                   1489:                        }
                   1490:                        /*
                   1491:                         * Set new address
                   1492:                         */
                   1493:                        ed_init(ifp->if_unit);
                   1494:                        break;
                   1495:                    }
                   1496: #endif
                   1497:                default:
                   1498:                        ed_init(ifp->if_unit);
                   1499:                        break;
                   1500:                }
                   1501:                break;
                   1502: 
                   1503:        case SIOCSIFFLAGS:
                   1504:                /*
                   1505:                 * If interface is marked down and it is running, then stop it
                   1506:                 */
                   1507:                if (((ifp->if_flags & IFF_UP) == 0) &&
                   1508:                    (ifp->if_flags & IFF_RUNNING)) {
                   1509:                        ed_stop(ifp->if_unit);
                   1510:                        ifp->if_flags &= ~IFF_RUNNING;
                   1511:                } else {
                   1512:                /*
                   1513:                 * If interface is marked up and it is stopped, then start it
                   1514:                 */
                   1515:                        if ((ifp->if_flags & IFF_UP) &&
                   1516:                            ((ifp->if_flags & IFF_RUNNING) == 0))
                   1517:                                ed_init(ifp->if_unit);
                   1518:                }
                   1519: #if NBPFILTER > 0
                   1520:                if (ifp->if_flags & IFF_PROMISC) {
                   1521:                        /*
                   1522:                         * Set promiscuous mode on interface.
                   1523:                         *      XXX - for multicasts to work, we would need to
                   1524:                         *              write 1's in all bits of multicast
                   1525:                         *              hashing array. For now we assume that
                   1526:                         *              this was done in ed_init().
                   1527:                         */
                   1528:                        outb(sc->nic_addr + ED_P0_RCR,
                   1529:                                ED_RCR_PRO|ED_RCR_AM|ED_RCR_AB);
                   1530:                } else {
                   1531:                        /*
                   1532:                         * XXX - for multicasts to work, we would need to
                   1533:                         *      rewrite the multicast hashing array with the
                   1534:                         *      proper hash (would have been destroyed above).
                   1535:                         */
                   1536:                        outb(sc->nic_addr + ED_P0_RCR, ED_RCR_AB);
                   1537:                }
                   1538: #endif
                   1539:                /*
                   1540:                 * An unfortunate hack to provide the (required) software control
                   1541:                 *      of the tranceiver for 3Com boards. The LLC0 flag disables
                   1542:                 *      the tranceiver if set.
                   1543:                 */
                   1544:                if (sc->vendor == ED_VENDOR_3COM) {
                   1545:                        if (ifp->if_flags & IFF_LLC0) {
                   1546:                                outb(sc->asic_addr + ED_3COM_CR, 0);
                   1547:                        } else {
                   1548:                                outb(sc->asic_addr + ED_3COM_CR, ED_3COM_CR_XSEL);
                   1549:                        }
                   1550:                }
                   1551: 
                   1552:                break;
                   1553: 
                   1554:        default:
                   1555:                error = EINVAL;
                   1556:        }
                   1557:        (void) splx(s);
                   1558:        return (error);
                   1559: }
                   1560:  
                   1561: /*
                   1562:  * Macro to calculate a new address within shared memory when given an offset
                   1563:  *     from an address, taking into account ring-wrap.
                   1564:  */
                   1565: #define        ringoffset(sc, start, off, type) \
                   1566:        ((type)( ((caddr_t)(start)+(off) >= (sc)->smem_end) ? \
                   1567:                (((caddr_t)(start)+(off))) - (sc)->smem_end \
                   1568:                + (sc)->smem_ring: \
                   1569:                ((caddr_t)(start)+(off)) ))
                   1570: 
                   1571: /*
                   1572:  * Retreive packet from shared memory and send to the next level up via
                   1573:  *     ether_input(). If there is a BPF listener, give a copy to BPF, too.
                   1574:  */
                   1575: ed_get_packet(sc, buf, len)
                   1576:        struct ed_softc *sc;
                   1577:        char *buf;
                   1578:        u_short len;
                   1579: {
                   1580:        struct ether_header *eh;
                   1581:        struct mbuf *m, *head, *ed_ring_to_mbuf();
                   1582:        u_short off;
                   1583:        int resid;
                   1584:        u_short etype;
                   1585:        struct trailer_header {
                   1586:                u_short trail_type;
                   1587:                u_short trail_residual;
                   1588:        } trailer_header;
                   1589: 
                   1590:        /* Allocate a header mbuf */
                   1591:        MGETHDR(m, M_DONTWAIT, MT_DATA);
                   1592:        if (m == 0)
                   1593:                goto bad;
                   1594:        m->m_pkthdr.rcvif = &sc->arpcom.ac_if;
                   1595:        m->m_pkthdr.len = len;
                   1596:        m->m_len = 0;
                   1597:        head = m;
                   1598: 
                   1599:        eh = (struct ether_header *)buf;
                   1600: 
                   1601:        /* The following sillines is to make NFS happy */
                   1602: #define EROUND ((sizeof(struct ether_header) + 3) & ~3)
                   1603: #define EOFF   (EROUND - sizeof(struct ether_header))
                   1604: 
                   1605:        /*
                   1606:         * The following assumes there is room for
                   1607:         * the ether header in the header mbuf
                   1608:         */
                   1609:        head->m_data += EOFF;
                   1610:        bcopy(buf, mtod(head, caddr_t), sizeof(struct ether_header));
                   1611:        buf += sizeof(struct ether_header);
                   1612:        head->m_len += sizeof(struct ether_header);
                   1613:        len -= sizeof(struct ether_header);
                   1614: 
                   1615:        etype = ntohs((u_short)eh->ether_type);
                   1616: 
                   1617:        /*
                   1618:         * Deal with trailer protocol:
                   1619:         * If trailer protocol, calculate the datasize as 'off',
                   1620:         * which is also the offset to the trailer header.
                   1621:         * Set resid to the amount of packet data following the
                   1622:         * trailer header.
                   1623:         * Finally, copy residual data into mbuf chain.
                   1624:         */
                   1625:        if (etype >= ETHERTYPE_TRAIL &&
                   1626:            etype < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
                   1627: 
                   1628:                off = (etype - ETHERTYPE_TRAIL) << 9;
                   1629:                if ((off + sizeof(struct trailer_header)) > len)
                   1630:                        goto bad;       /* insanity */
                   1631: 
                   1632:                eh->ether_type = *ringoffset(sc, buf, off, u_short *);
                   1633:                resid = ntohs(*ringoffset(sc, buf, off+2, u_short *));
                   1634: 
                   1635:                if ((off + resid) > len) goto bad;      /* insanity */
                   1636: 
                   1637:                resid -= sizeof(struct trailer_header);
                   1638:                if (resid < 0) goto bad;        /* insanity */
                   1639: 
                   1640:                m = ed_ring_to_mbuf(sc, ringoffset(sc, buf, off+4, char *), head, resid);
                   1641:                if (m == 0) goto bad;
                   1642: 
                   1643:                len = off;
                   1644:                head->m_pkthdr.len -= 4; /* subtract trailer header */
                   1645:        }
                   1646: 
                   1647:        /*
                   1648:         * Pull packet off interface. Or if this was a trailer packet,
                   1649:         * the data portion is appended.
                   1650:         */
                   1651:        m = ed_ring_to_mbuf(sc, buf, m, len);
                   1652:        if (m == 0) goto bad;
                   1653: 
                   1654: #if NBPFILTER > 0
                   1655:        /*
                   1656:         * Check if there's a BPF listener on this interface.
                   1657:         * If so, hand off the raw packet to bpf. 
                   1658:         */
                   1659:        if (sc->bpf) {
                   1660:                bpf_mtap(sc->bpf, head);
                   1661: 
                   1662:                /*
                   1663:                 * Note that the interface cannot be in promiscuous mode if
                   1664:                 * there are no BPF listeners.  And if we are in promiscuous
                   1665:                 * mode, we have to check if this packet is really ours.
                   1666:                 *
                   1667:                 * XXX This test does not support multicasts.
                   1668:                 */
                   1669:                if ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) &&
                   1670:                        bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
                   1671:                                sizeof(eh->ether_dhost)) != 0 &&
                   1672:                        bcmp(eh->ether_dhost, etherbroadcastaddr,
                   1673:                                sizeof(eh->ether_dhost)) != 0) {
                   1674: 
                   1675:                        m_freem(head);
                   1676:                        return;
                   1677:                }
                   1678:        }
                   1679: #endif
                   1680: 
                   1681:        /*
                   1682:         * Fix up data start offset in mbuf to point past ether header
                   1683:         */
                   1684:        m_adj(head, sizeof(struct ether_header));
                   1685: 
                   1686:        /*
                   1687:         * silly ether_input routine needs 'type' in host byte order
                   1688:         */
                   1689:        eh->ether_type = ntohs(eh->ether_type);
                   1690: 
                   1691:        ether_input(&sc->arpcom.ac_if, eh, head);
                   1692:        return;
                   1693: 
                   1694: bad:   if (head)
                   1695:                m_freem(head);
                   1696:        return;
                   1697: }
                   1698: 
                   1699: /*
                   1700:  * Supporting routines
                   1701:  */
                   1702: 
                   1703: /*
                   1704:  * Given a source and destination address, copy 'amount' of a packet from
                   1705:  *     the ring buffer into a linear destination buffer. Takes into account
                   1706:  *     ring-wrap.
                   1707:  */
                   1708: static inline char *
                   1709: ed_ring_copy(sc,src,dst,amount)
                   1710:        struct ed_softc *sc;
                   1711:        char    *src;
                   1712:        char    *dst;
                   1713:        u_short amount;
                   1714: {
                   1715:        u_short tmp_amount;
                   1716: 
                   1717:        /* does copy wrap to lower addr in ring buffer? */
                   1718:        if (src + amount > sc->smem_end) {
                   1719:                tmp_amount = sc->smem_end - src;
                   1720:                bcopy(src,dst,tmp_amount); /* copy amount up to end of smem */
                   1721:                amount -= tmp_amount;
                   1722:                src = sc->smem_ring;
                   1723:                dst += tmp_amount;
                   1724:        }
                   1725: 
                   1726:        bcopy(src, dst, amount);
                   1727: 
                   1728:        return(src + amount);
                   1729: }
                   1730: 
                   1731: /*
                   1732:  * Copy data from receive buffer to end of mbuf chain
                   1733:  * allocate additional mbufs as needed. return pointer
                   1734:  * to last mbuf in chain.
                   1735:  * sc = ed info (softc)
                   1736:  * src = pointer in ed ring buffer
                   1737:  * dst = pointer to last mbuf in mbuf chain to copy to
                   1738:  * amount = amount of data to copy
                   1739:  */
                   1740: struct mbuf *
                   1741: ed_ring_to_mbuf(sc,src,dst,total_len)
                   1742:        struct ed_softc *sc;
                   1743:        char *src;
                   1744:        struct mbuf *dst;
                   1745:        u_short total_len;
                   1746: {
                   1747:        register struct mbuf *m = dst;
                   1748: 
                   1749:        while (total_len) {
                   1750:                register u_short amount = min(total_len, M_TRAILINGSPACE(m));
                   1751: 
                   1752:                if (amount == 0) { /* no more data in this mbuf, alloc another */
                   1753:                        /*
                   1754:                         * If there is enough data for an mbuf cluster, attempt
                   1755:                         *      to allocate one of those, otherwise, a regular
                   1756:                         *      mbuf will do.
                   1757:                         * Note that a regular mbuf is always required, even if
                   1758:                         *      we get a cluster - getting a cluster does not
                   1759:                         *      allocate any mbufs, and one is needed to assign
                   1760:                         *      the cluster to. The mbuf that has a cluster
                   1761:                         *      extension can not be used to contain data - only
                   1762:                         *      the cluster can contain data.
                   1763:                         */ 
                   1764:                        dst = m;
                   1765:                        MGET(m, M_DONTWAIT, MT_DATA);
                   1766:                        if (m == 0)
                   1767:                                return (0);
                   1768: 
                   1769:                        if (total_len >= MINCLSIZE)
                   1770:                                MCLGET(m, M_DONTWAIT);
                   1771: 
                   1772:                        m->m_len = 0;
                   1773:                        dst->m_next = m;
                   1774:                        amount = min(total_len, M_TRAILINGSPACE(m));
                   1775:                }
                   1776: 
                   1777:                src = ed_ring_copy(sc, src, mtod(m, caddr_t) + m->m_len, amount);
                   1778: 
                   1779:                m->m_len += amount;
                   1780:                total_len -= amount;
                   1781: 
                   1782:        }
                   1783:        return (m);
                   1784: }
                   1785: #endif
                   1786: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.