Annotation of Net2/arch/i386/isa/if_ed.c, revision 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.