[BACK]Return to if_iy.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / isa

Annotation of src/sys/dev/isa/if_iy.c, Revision 1.6

1.5       is          1: /*     $NetBSD: if_iy.c,v 1.4 1996/05/12 23:52:53 mycroft Exp $        */
1.1       is          2: /* #define IYDEBUG */
                      3: /* #define IYMEMDEBUG */
                      4: /*-
                      5:  * Copyright (c) 1996 Ignatios Souvatzis.
                      6:  * All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product contains software developed by Ignatios Souvatzis for
                     19:  *     the NetBSD project.
                     20:  * 4. The names of the author may not be used to endorse or promote products
                     21:  *    derived from this software without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  */
                     35:
                     36: #include "bpfilter.h"
                     37:
                     38: #include <sys/param.h>
                     39: #include <sys/systm.h>
                     40: #include <sys/mbuf.h>
                     41: #include <sys/buf.h>
                     42: #include <sys/protosw.h>
                     43: #include <sys/socket.h>
                     44: #include <sys/ioctl.h>
                     45: #include <sys/errno.h>
                     46: #include <sys/syslog.h>
                     47: #include <sys/device.h>
                     48:
                     49: #include <net/if.h>
                     50: #include <net/if_types.h>
                     51: #include <net/if_dl.h>
                     52: #include <net/netisr.h>
                     53: #include <net/route.h>
                     54:
                     55: #if NBPFILTER > 0
                     56: #include <net/bpf.h>
                     57: #include <net/bpfdesc.h>
                     58: #endif
                     59:
                     60: #ifdef INET
                     61: #include <netinet/in.h>
                     62: #include <netinet/in_systm.h>
                     63: #include <netinet/in_var.h>
                     64: #include <netinet/ip.h>
                     65: #include <netinet/if_ether.h>
                     66: #endif
                     67:
                     68: #ifdef NS
                     69: #include <netns/ns.h>
                     70: #include <netns/ns_if.h>
                     71: #endif
                     72:
                     73: #include <vm/vm.h>
                     74:
                     75: #include <machine/cpu.h>
1.6     ! is         76: #include <machine/bus.h>
1.4       mycroft    77: #include <machine/intr.h>
1.1       is         78:
                     79: #include <dev/isa/isareg.h>
                     80: #include <dev/isa/isavar.h>
                     81: #include <dev/ic/i82595reg.h>
                     82:
                     83: #define        ETHER_MIN_LEN   64
                     84: #define        ETHER_MAX_LEN   1518
                     85:
                     86: /*
                     87:  * Ethernet status, per interface.
                     88:  */
                     89: struct iy_softc {
                     90:        struct device sc_dev;
                     91:        void *sc_ih;
                     92:
1.6     ! is         93:        bus_chipset_tag_t sc_bc;
        !            94:        bus_io_handle_t sc_ioh;
        !            95:
1.1       is         96:        struct arpcom sc_arpcom;
                     97:
                     98: #define MAX_MBS 8
                     99:        struct mbuf *mb[MAX_MBS];
                    100:        int next_mb, last_mb;
                    101:
                    102:        int mappedirq;
                    103:
                    104:        int hard_vers;
                    105:
                    106:        int promisc;
                    107:
                    108:        int sram, tx_size, rx_size;
                    109:
                    110:        int tx_start, tx_end, tx_last;
                    111:        int rx_start;
                    112:
                    113: #ifdef IYDEBUG
                    114:        int sc_debug;
                    115: #endif
                    116: };
                    117:
1.2       thorpej   118: void iywatchdog __P((struct ifnet *));
1.1       is        119: int iyioctl __P((struct ifnet *, u_long, caddr_t));
                    120: int iyintr __P((void *));
                    121: void iyinit __P((struct iy_softc *));
                    122: void iystop __P((struct iy_softc *));
                    123: void iystart __P((struct ifnet *));
                    124:
                    125: void iy_intr_rx __P((struct iy_softc *));
                    126: void iy_intr_tx __P((struct iy_softc *));
                    127: void eepro_reset_595 __P((struct iy_softc *));
                    128: int eepro_probe __P((struct iy_softc *, struct isa_attach_args *));
                    129: u_short eepro_read_eeprom __P((struct iy_softc *, int));
                    130:
                    131: void iyreset __P((struct iy_softc *));
                    132: void iy_readframe __P((struct iy_softc *, int));
                    133: void iy_drop_packet_buffer __P((struct iy_softc *));
                    134: void iy_find_mem_size __P((struct iy_softc *));
                    135: void iyrint __P((struct iy_softc *));
                    136: void iytint __P((struct iy_softc *));
                    137: void iyxmit __P((struct iy_softc *));
1.6     ! is        138: void iyget __P((struct iy_softc *, bus_chipset_tag_t, bus_io_handle_t, int));
1.1       is        139: void iymbuffill __P((void *));
                    140: void iymbufempty __P((void *));
                    141: void iyprobemem __P((struct iy_softc *));
                    142:
                    143: /*
                    144:  * void iymeminit __P((void *, struct iy_softc *));
                    145:  * static int iy_mc_setup __P((struct iy_softc *, void *));
                    146:  * static void iy_mc_reset __P((struct iy_softc *));
                    147:  */
                    148: #ifdef IYDEBUGX
                    149: void print_rbd __P((volatile struct iy_recv_buf_desc *));
                    150:
                    151: int in_ifrint = 0;
                    152: int in_iftint = 0;
                    153: #endif
                    154:
                    155: int iyprobe __P((struct device *, void *, void *));
                    156: void iyattach __P((struct device *, struct device *, void *));
                    157:
1.6     ! is        158: static u_int16_t eepromread __P((bus_chipset_tag_t, bus_io_handle_t,
        !           159:                                 bus_io_size_t, int));
1.1       is        160:
                    161: struct cfattach iy_ca = {
                    162:        sizeof(struct iy_softc), iyprobe, iyattach
                    163: };
                    164:
                    165: struct cfdriver iy_cd = {
                    166:        NULL, "iy", DV_IFNET
                    167: };
                    168:
                    169: static u_int8_t eepro_irqmap[] = EEPP_INTMAP;
                    170: static u_int8_t eepro_revirqmap[] = EEPP_RINTMAP;
                    171:
                    172: int
                    173: iyprobe(parent, match, aux)
                    174:        struct device *parent;
                    175:        void *match, *aux;
                    176: {
                    177:        struct iy_softc *sc = match;
                    178:        struct isa_attach_args *ia = aux;
                    179:
                    180:        u_int16_t eaddr[8];
1.6     ! is        181:
        !           182:        bus_chipset_tag_t bc;
        !           183:        bus_io_handle_t ioh;
        !           184:
1.1       is        185:        int i;
                    186:
                    187:        u_int16_t checksum = 0;
                    188:        u_int16_t eepromtmp;
                    189:        u_int8_t c, d;
                    190:
1.6     ! is        191:        bc = ia->ia_bc;
1.1       is        192:
1.6     ! is        193:        if (bus_io_map(bc, ia->ia_iobase, 16, &ioh))
        !           194:                goto out;
        !           195:
        !           196:        /* check here for addresses already given to other devices */
1.1       is        197:
                    198:
                    199:        /* try to find the round robin sig: */
                    200:
1.6     ! is        201:        c = bus_io_read_1(bc, ioh, ID_REG);
1.1       is        202:        if (c & ID_REG_MASK != ID_REG_SIG)
1.6     ! is        203:                goto out;
1.1       is        204:
1.6     ! is        205:        d = bus_io_read_1(bc, ioh, ID_REG);
1.1       is        206:        if (d & ID_REG_MASK != ID_REG_SIG)
1.6     ! is        207:                goto out;
1.1       is        208:
                    209:        if (((d-c) & R_ROBIN_BITS) != 0x40)
1.6     ! is        210:                goto out;
1.1       is        211:
1.6     ! is        212:        d = bus_io_read_1(bc, ioh, ID_REG);
1.1       is        213:        if (d & ID_REG_MASK != ID_REG_SIG)
1.6     ! is        214:                goto out;
1.1       is        215:
                    216:        if (((d-c) & R_ROBIN_BITS) != 0x80)
1.6     ! is        217:                goto out;
1.1       is        218:
1.6     ! is        219:        d = bus_io_read_1(bc, ioh, ID_REG);
1.1       is        220:        if (d & ID_REG_MASK != ID_REG_SIG)
1.6     ! is        221:                goto out;
1.1       is        222:
                    223:        if (((d-c) & R_ROBIN_BITS) != 0xC0)
1.6     ! is        224:                goto out;
1.1       is        225:
1.6     ! is        226:        d = bus_io_read_1(bc, ioh, ID_REG);
1.1       is        227:        if (d & ID_REG_MASK != ID_REG_SIG)
1.6     ! is        228:                goto out;
1.1       is        229:
                    230:        if (((d-c) & R_ROBIN_BITS) != 0x00)
1.6     ! is        231:                goto out;
1.1       is        232:
                    233: #ifdef IYDEBUG
                    234:                printf("eepro_probe verified working ID reg.\n");
                    235: #endif
                    236:
                    237:        for (i=0; i<64; ++i) {
1.6     ! is        238:                eepromtmp = eepromread(bc, ioh, EEPROM_REG, i);
1.1       is        239:                checksum += eepromtmp;
                    240:                if (i<(sizeof(eaddr)/sizeof(*eaddr)))
                    241:                        eaddr[i] = eepromtmp;
                    242:        }
                    243:        if (checksum != EEPP_CHKSUM)
                    244:                printf("wrong EEPROM checksum 0x%x should be 0x%x\n",
                    245:                    checksum, EEPP_CHKSUM);
                    246:
                    247:
1.6     ! is        248:        if ((eaddr[EEPPEther0] != eepromread(bc, ioh, EEPROM_REG, EEPPEther0a)) &&
        !           249:            (eaddr[EEPPEther1] != eepromread(bc, ioh, EEPROM_REG, EEPPEther1a)) &&
        !           250:            (eaddr[EEPPEther2] != eepromread(bc, ioh, EEPROM_REG, EEPPEther2a)))
1.1       is        251:                printf("EEPROM Ethernet address differs from copy\n");
                    252:
                    253:         sc->sc_arpcom.ac_enaddr[1] = eaddr[EEPPEther0] & 0xFF;
                    254:         sc->sc_arpcom.ac_enaddr[0] = eaddr[EEPPEther0] >> 8;
                    255:         sc->sc_arpcom.ac_enaddr[3] = eaddr[EEPPEther1] & 0xFF;
                    256:         sc->sc_arpcom.ac_enaddr[2] = eaddr[EEPPEther1] >> 8;
                    257:         sc->sc_arpcom.ac_enaddr[5] = eaddr[EEPPEther2] & 0xFF;
                    258:         sc->sc_arpcom.ac_enaddr[4] = eaddr[EEPPEther2] >> 8;
                    259:
                    260:        if (ia->ia_irq == IRQUNK)
                    261:                ia->ia_irq = eepro_irqmap[eaddr[EEPPW1] & EEPP_Int];
                    262:
                    263:        if (ia->ia_irq >= sizeof(eepro_revirqmap))
1.6     ! is        264:                goto out;
1.1       is        265:
                    266:        if ((sc->mappedirq = eepro_revirqmap[ia->ia_irq]) == -1)
1.6     ! is        267:                goto out;
1.1       is        268:
                    269:        sc->hard_vers = eaddr[EEPW6] & EEPP_BoardRev;
                    270:
                    271:        /* now lets reset the chip */
                    272:
1.6     ! is        273:        bus_io_write_1(bc, ioh, COMMAND_REG, RESET_CMD);
1.1       is        274:        delay(200);
                    275:
1.6     ! is        276:        /*
        !           277:         * XXX Sould always unmap, but we can't yet.
        !           278:         * XXX Need to squish "indirect" first.
        !           279:         */
1.1       is        280:                ia->ia_iosize = 16;
1.6     ! is        281:
        !           282:        sc->sc_bc = bc;
        !           283:        sc->sc_ioh = ioh;
1.1       is        284:        return 1;               /* found */
1.6     ! is        285: out:
        !           286:        bus_io_unmap(bc, ioh, 16);
        !           287:        return 0;
1.1       is        288: }
                    289:
                    290: void
                    291: iyattach(parent, self, aux)
                    292:        struct device *parent, *self;
                    293:        void *aux;
                    294: {
                    295:        struct iy_softc *sc = (void *)self;
                    296:        struct isa_attach_args *ia = aux;
                    297:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1.6     ! is        298:        bus_chipset_tag_t bc;
        !           299:        bus_io_handle_t ioh;
        !           300:
        !           301:        /*
        !           302:         * XXX Should re-map io and mem, but can't
        !           303:         * XXX until we squish "indirect" brokenness.
        !           304:         */
        !           305:        bc = sc->sc_bc;                 /* XXX */
        !           306:        ioh = sc->sc_ioh;               /* XXX */
1.1       is        307:
1.2       thorpej   308:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
                    309:        ifp->if_softc = sc;
1.1       is        310:        ifp->if_start = iystart;
                    311:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
                    312:                                        /* XXX todo: | IFF_MULTICAST */
                    313:
                    314:        iyprobemem(sc);
                    315:
                    316:        ifp->if_ioctl = iyioctl;
                    317:        ifp->if_watchdog = iywatchdog;
                    318:
                    319:        /* Attach the interface. */
                    320:        if_attach(ifp);
                    321:        ether_ifattach(ifp);
                    322:        printf(": address %s, chip rev. %d, %d kB SRAM\n",
                    323:            ether_sprintf(sc->sc_arpcom.ac_enaddr),
                    324:            sc->hard_vers, sc->sram/1024);
                    325: #if NBPFILTER > 0
                    326:        bpfattach(&sc->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB,
                    327:            sizeof(struct ether_header));
                    328: #endif
                    329:
                    330:        sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
                    331:            IPL_NET, iyintr, sc);
                    332: }
                    333:
                    334: void
                    335: iystop(sc)
                    336: struct iy_softc *sc;
                    337: {
1.6     ! is        338:        bus_chipset_tag_t bc;
        !           339:        bus_io_handle_t ioh;
1.1       is        340: #ifdef IYDEBUG
                    341:        u_int p, v;
                    342: #endif
                    343:
1.6     ! is        344:        bc = sc->sc_bc;
        !           345:        ioh = sc->sc_ioh;
1.1       is        346:
1.6     ! is        347:        bus_io_write_1(bc, ioh, COMMAND_REG, RCV_DISABLE_CMD);
1.1       is        348:
1.6     ! is        349:        bus_io_write_1(bc, ioh, INT_MASK_REG, ALL_INTS);
        !           350:        bus_io_write_1(bc, ioh, STATUS_REG, ALL_INTS);
1.1       is        351:
1.6     ! is        352:        bus_io_write_1(bc, ioh, COMMAND_REG, RESET_CMD);
1.1       is        353:        delay(200);
                    354: #ifdef IYDEBUG
                    355:        printf("%s: dumping tx chain (st 0x%x end 0x%x last 0x%x)\n",
                    356:                    sc->sc_dev.dv_xname, sc->tx_start, sc->tx_end, sc->tx_last);
                    357:        p = sc->tx_last;
                    358:        if (!p)
                    359:                p = sc->tx_start;
                    360:        do {
1.6     ! is        361:                bus_io_write_2(bc, ioh, HOST_ADDR_REG, p);
        !           362:                v = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1       is        363:                printf("0x%04x: %b ", p, v, "\020\006Ab\010Dn");
1.6     ! is        364:                v = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1       is        365:                printf("0x%b", v, "\020\6MAX_COL\7HRT_BEAT\010TX_DEF\011UND_RUN\012JERR\013LST_CRS\014LTCOL\016TX_OK\020COLL");
1.6     ! is        366:                p = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1       is        367:                printf(" 0x%04x", p);
1.6     ! is        368:                v = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1       is        369:                printf(" 0x%b\n", v, "\020\020Ch");
                    370:
                    371:        } while (v & 0x8000);
                    372: #endif
                    373:        sc->tx_start = sc->tx_end = sc->rx_size;
                    374:        sc->tx_last = 0;
                    375:        sc->sc_arpcom.ac_if.if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
                    376:
                    377:        iymbufempty((void *)sc);
                    378: }
                    379:
                    380: void
                    381: iyreset(sc)
                    382: struct iy_softc *sc;
                    383: {
                    384:        int s;
                    385:        s = splimp();
                    386:        iystop(sc);
                    387:        iyinit(sc);
                    388:        splx(s);
                    389: }
                    390:
                    391: void
                    392: iyinit(sc)
                    393: struct iy_softc *sc;
                    394: {
                    395:        int i;
                    396:        unsigned temp;
                    397:        struct ifnet *ifp;
1.6     ! is        398:        bus_chipset_tag_t bc;
        !           399:        bus_io_handle_t ioh;
        !           400:
        !           401:        bc = sc->sc_bc;
        !           402:        ioh = sc->sc_ioh;
1.1       is        403:
                    404:        ifp = &sc->sc_arpcom.ac_if;
                    405: #ifdef IYDEBUG
                    406:        printf("ifp is %p\n", ifp);
                    407: #endif
                    408:
1.6     ! is        409:        bus_io_write_1(bc, ioh, 0, BANK_SEL(2));
1.1       is        410:
1.6     ! is        411:        temp = bus_io_read_1(bc, ioh, EEPROM_REG);
1.1       is        412:        if (temp & 0x10)
1.6     ! is        413:                bus_io_write_1(bc, ioh, EEPROM_REG, temp & ~0x10);
1.1       is        414:
                    415:        for (i=0; i<6; ++i) {
1.6     ! is        416:                bus_io_write_1(bc, ioh, I_ADD(i), sc->sc_arpcom.ac_enaddr[i]);
1.1       is        417:        }
                    418:
1.6     ! is        419:        temp = bus_io_read_1(bc, ioh, REG1);
        !           420:        bus_io_write_1(bc, ioh, REG1, temp | XMT_CHAIN_INT | XMT_CHAIN_ERRSTOP |
1.1       is        421:            RCV_DISCARD_BAD);
                    422:
1.6     ! is        423:        temp = bus_io_read_1(bc, ioh, RECV_MODES_REG);
        !           424:        bus_io_write_1(bc, ioh, RECV_MODES_REG, temp | MATCH_BRDCST);
1.1       is        425: #ifdef IYDEBUG
                    426:        printf("%s: RECV_MODES were %b set to %b\n",
                    427:            sc->sc_dev.dv_xname,
                    428:            temp, "\020\1PRMSC\2NOBRDST\3SEECRC\4LENGTH\5NOSaIns\6MultiIA",
                    429:            temp|MATCH_BRDCST,
                    430:            "\020\1PRMSC\2NOBRDST\3SEECRC\4LENGTH\5NOSaIns\6MultiIA");
                    431: #endif
                    432:
                    433:
                    434:        DELAY(500000); /* for the hardware to test for the connector */
                    435:
1.6     ! is        436:        temp = bus_io_read_1(bc, ioh, MEDIA_SELECT);
1.1       is        437: #ifdef IYDEBUG
1.5       is        438:        printf("%s: media select was 0x%b ", sc->sc_dev.dv_xname,
1.1       is        439:            temp, "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC");
                    440: #endif
1.5       is        441:        temp = (temp & TEST_MODE_MASK);
1.6     ! is        442:
1.5       is        443:        switch(ifp->if_flags & (IFF_LINK0 | IFF_LINK1)) {
                    444:        case IFF_LINK0:
1.6     ! is        445:                temp &= ~ (BNC_BIT | TPE_BIT);
        !           446:                break;
1.5       is        447:
                    448:        case IFF_LINK1:
1.6     ! is        449:                temp = temp & ~TPE_BIT | BNC_BIT;
        !           450:                break;
        !           451:
1.5       is        452:        case IFF_LINK0|IFF_LINK1:
1.6     ! is        453:                temp = temp & ~BNC_BIT | TPE_BIT;
        !           454:                break;
1.5       is        455:        default:
1.6     ! is        456:                /* nothing; leave as it is */
1.5       is        457:        }
                    458:
1.6     ! is        459:
        !           460:        bus_io_write_1(bc, ioh, MEDIA_SELECT, temp);
1.1       is        461: #ifdef IYDEBUG
                    462:        printf("changed to 0x%b\n",
                    463:            temp, "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC");
                    464: #endif
                    465:
1.6     ! is        466:        bus_io_write_1(bc, ioh, 0, BANK_SEL(1));
1.1       is        467:
1.6     ! is        468:        temp = bus_io_read_1(bc, ioh, INT_NO_REG);
        !           469:        bus_io_write_1(bc, ioh, INT_NO_REG, (temp & 0xf8) | sc->mappedirq);
1.1       is        470:
                    471: #ifdef IYDEBUG
                    472:        printf("%s: int no was %b\n", sc->sc_dev.dv_xname,
                    473:            temp, "\020\4bad_irq\010flash/boot present");
1.6     ! is        474:        temp = bus_io_read_1(bc, ioh, INT_NO_REG);
1.1       is        475:        printf("%s: int no now 0x%02x\n", sc->sc_dev.dv_xname,
                    476:            temp, "\020\4BAD IRQ\010flash/boot present");
                    477: #endif
                    478:
                    479:
1.6     ! is        480:        bus_io_write_1(bc, ioh, RCV_LOWER_LIMIT_REG, 0);
        !           481:        bus_io_write_1(bc, ioh, RCV_UPPER_LIMIT_REG, (sc->rx_size - 2) >> 8);
        !           482:        bus_io_write_1(bc, ioh, XMT_LOWER_LIMIT_REG, sc->rx_size >> 8);
        !           483:        bus_io_write_1(bc, ioh, XMT_UPPER_LIMIT_REG, sc->sram >> 8);
1.1       is        484:
1.6     ! is        485:        temp = bus_io_read_1(bc, ioh, REG1);
1.1       is        486: #ifdef IYDEBUG
                    487:        printf("%s: HW access is %b\n", sc->sc_dev.dv_xname,
                    488:            temp, "\020\2WORD_WIDTH\010INT_ENABLE");
                    489: #endif
1.6     ! is        490:        bus_io_write_1(bc, ioh, REG1, temp | INT_ENABLE); /* XXX what about WORD_WIDTH? */
1.1       is        491:
                    492: #ifdef IYDEBUG
1.6     ! is        493:        temp = bus_io_read_1(bc, ioh, REG1);
1.1       is        494:        printf("%s: HW access is %b\n", sc->sc_dev.dv_xname,
                    495:            temp, "\020\2WORD_WIDTH\010INT_ENABLE");
                    496: #endif
                    497:
1.6     ! is        498:        bus_io_write_1(bc, ioh, 0, BANK_SEL(0));
1.1       is        499:
1.6     ! is        500:        bus_io_write_1(bc, ioh, INT_MASK_REG, ALL_INTS & ~(RX_BIT|TX_BIT));
        !           501:        bus_io_write_1(bc, ioh, STATUS_REG, ALL_INTS); /* clear ints */
1.1       is        502:
1.6     ! is        503:        bus_io_write_2(bc, ioh, RCV_START_LOW, 0);
        !           504:        bus_io_write_2(bc, ioh, RCV_STOP_LOW,  sc->rx_size - 2);
1.1       is        505:        sc->rx_start = 0;
                    506:
1.6     ! is        507:        bus_io_write_1(bc, ioh, 0, SEL_RESET_CMD);
1.1       is        508:        DELAY(200);
                    509:
1.6     ! is        510:        bus_io_write_2(bc, ioh, XMT_ADDR_REG, sc->rx_size);
1.1       is        511:
                    512:        sc->tx_start = sc->tx_end = sc->rx_size;
                    513:        sc->tx_last = 0;
                    514:
1.6     ! is        515:        bus_io_write_1(bc, ioh, 0, RCV_ENABLE_CMD);
1.1       is        516:
                    517:        ifp->if_flags |= IFF_RUNNING;
                    518:        ifp->if_flags &= ~IFF_OACTIVE;
                    519: }
                    520:
                    521: void
                    522: iystart(ifp)
                    523: struct ifnet *ifp;
                    524: {
                    525:        struct iy_softc *sc;
1.6     ! is        526:
1.1       is        527:
                    528:        struct mbuf *m0, *m;
                    529:        u_int len, pad, last, end;
                    530:        u_int llen, residual;
                    531:        int avail;
                    532:        caddr_t data;
                    533:        u_int16_t resval, stat;
1.6     ! is        534:        bus_chipset_tag_t bc;
        !           535:        bus_io_handle_t ioh;
1.1       is        536:
                    537: #ifdef IYDEBUG
                    538:        printf("iystart called\n");
                    539: #endif
                    540:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
                    541:                 return;
                    542:
1.2       thorpej   543:        sc = ifp->if_softc;
1.6     ! is        544:        bc = sc->sc_bc;
        !           545:        ioh = sc->sc_ioh;
1.1       is        546:
                    547:        while ((m0 = ifp->if_snd.ifq_head) != NULL) {
                    548: #ifdef IYDEBUG
                    549:                printf("%s: trying to write another packet to the hardware\n",
                    550:                    sc->sc_dev.dv_xname);
                    551: #endif
                    552:
                    553:                /* We need to use m->m_pkthdr.len, so require the header */
                    554:                if ((m0->m_flags & M_PKTHDR) == 0)
                    555:                        panic("iystart: no header mbuf");
                    556:
                    557:                len = m0->m_pkthdr.len;
                    558:                pad = len & 1;
                    559:
                    560: #ifdef IYDEBUG
                    561:                printf("%s: length is %d.\n", sc->sc_dev.dv_xname, len);
                    562: #endif
                    563:                if (len < ETHER_MIN_LEN) {
                    564:                        pad = ETHER_MIN_LEN - len;
                    565:                }
                    566:
                    567:                if (len + pad > ETHER_MAX_LEN) {
                    568:                        /* packet is obviously too large: toss it */
                    569:                        ++ifp->if_oerrors;
                    570:                        IF_DEQUEUE(&ifp->if_snd, m0);
                    571:                        m_freem(m0);
                    572:                        continue;
                    573:                }
                    574:
                    575: #if NBPFILTER > 0
                    576:                if (ifp->if_bpf)
                    577:                        bpf_mtap(ifp->if_bpf, m0);
                    578: #endif
                    579:
                    580:                avail = sc->tx_start - sc->tx_end;
                    581:                if (avail <= 0)
                    582:                        avail += sc->tx_size;
                    583:
                    584: #ifdef IYDEBUG
                    585:                printf("%s: avail is %d.\n", sc->sc_dev.dv_xname, avail);
                    586: #endif
                    587:                /*
                    588:                 * we MUST RUN at splnet here  ---
                    589:                 * XXX todo: or even turn off the boards ints ??? hm...
                    590:                 */
                    591:
                    592:                        /* See if there is room to put another packet in the buffer. */
                    593:
                    594:                if ((len+pad+2*I595_XMT_HDRLEN) > avail) {
                    595:                        printf("%s: len = %d, avail = %d, setting OACTIVE\n",
                    596:                            sc->sc_dev.dv_xname, len, avail);
                    597:                        ifp->if_flags |= IFF_OACTIVE;
                    598:                        return;
                    599:                }
                    600:
                    601:                /* we know it fits in the hardware now, so dequeue it */
                    602:                IF_DEQUEUE(&ifp->if_snd, m0);
                    603:
                    604:                last = sc->tx_end;
                    605:                end = last + pad + len + I595_XMT_HDRLEN;
                    606:
                    607:                if (end >= sc->sram) {
                    608:                        if ((sc->sram - last) <= I595_XMT_HDRLEN) {
                    609:                                /* keep header in one piece */
                    610:                                last = sc->rx_size;
                    611:                                end = last + pad + len + I595_XMT_HDRLEN;
                    612:                        } else
                    613:                                end -= sc->tx_size;
                    614:                }
                    615:
1.6     ! is        616:                bus_io_write_2(bc, ioh, HOST_ADDR_REG, last);
        !           617:                bus_io_write_2(bc, ioh, MEM_PORT_REG, XMT_CMD);
        !           618:                bus_io_write_2(bc, ioh, MEM_PORT_REG, 0);
        !           619:                bus_io_write_2(bc, ioh, MEM_PORT_REG, 0);
        !           620:                bus_io_write_2(bc, ioh, MEM_PORT_REG, len + pad);
1.1       is        621:
                    622:                residual = resval = 0;
                    623:
                    624:                while ((m = m0)!=0) {
                    625:                        data = mtod(m, caddr_t);
                    626:                        llen = m->m_len;
                    627:                        if (residual) {
                    628: #ifdef IYDEBUG
                    629:                                printf("%s: merging residual with next mbuf.\n",
                    630:                                    sc->sc_dev.dv_xname);
                    631: #endif
                    632:                                resval |= *data << 8;
1.6     ! is        633:                                bus_io_write_2(bc, ioh, MEM_PORT_REG, resval);
1.1       is        634:                                --llen;
                    635:                                ++data;
                    636:                        }
                    637:                        if (llen > 1)
1.6     ! is        638:                                bus_io_write_multi_2(bc, ioh, MEM_PORT_REG,
        !           639:                                    data, llen>>1);
1.1       is        640:                        residual = llen & 1;
                    641:                        if (residual) {
                    642:                                resval = *(data + llen - 1);
                    643: #ifdef IYDEBUG
                    644:                                printf("%s: got odd mbuf to send.\n",
                    645:                                    sc->sc_dev.dv_xname);
                    646: #endif
                    647:                        }
                    648:
                    649:                        MFREE(m, m0);
                    650:                }
                    651:
                    652:                if (residual)
1.6     ! is        653:                        bus_io_write_2(bc, ioh, MEM_PORT_REG, resval);
1.1       is        654:
                    655:                pad >>= 1;
                    656:                while (pad-- > 0)
1.6     ! is        657:                        bus_io_write_2(bc, ioh, MEM_PORT_REG, 0);
1.1       is        658:
                    659: #ifdef IYDEBUG
                    660:                printf("%s: new last = 0x%x, end = 0x%x.\n",
                    661:                    sc->sc_dev.dv_xname, last, end);
                    662:                printf("%s: old start = 0x%x, end = 0x%x, last = 0x%x\n",
                    663:                    sc->sc_dev.dv_xname, sc->tx_start, sc->tx_end, sc->tx_last);
                    664: #endif
                    665:
                    666:                if (sc->tx_start != sc->tx_end) {
1.6     ! is        667:                        bus_io_write_2(bc, ioh, HOST_ADDR_REG, sc->tx_last + XMT_COUNT);
        !           668:                        stat = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1       is        669:
1.6     ! is        670:                        bus_io_write_2(bc, ioh, HOST_ADDR_REG, sc->tx_last + XMT_CHAIN);
        !           671:                        bus_io_write_2(bc, ioh, MEM_PORT_REG, last);
        !           672:                        bus_io_write_2(bc, ioh, MEM_PORT_REG, stat | CHAIN);
1.1       is        673: #ifdef IYDEBUG
                    674:                        printf("%s: setting 0x%x to 0x%x\n",
                    675:                            sc->sc_dev.dv_xname, sc->tx_last + XMT_COUNT,
                    676:                            stat | CHAIN);
                    677: #endif
                    678:                }
1.6     ! is        679:                stat = bus_io_read_2(bc, ioh, MEM_PORT_REG); /* dummy read */
1.1       is        680:
                    681:                /* XXX todo: enable ints here if disabled */
                    682:
                    683:                ++ifp->if_opackets;
                    684:
                    685:                if (sc->tx_start == sc->tx_end) {
1.6     ! is        686:                        bus_io_write_2(bc, ioh, XMT_ADDR_REG, last);
        !           687:                        bus_io_write_1(bc, ioh, 0, XMT_CMD);
1.1       is        688:                        sc->tx_start = last;
                    689: #ifdef IYDEBUG
                    690:                        printf("%s: writing 0x%x to XAR and giving XCMD\n",
                    691:                            sc->sc_dev.dv_xname, last);
                    692: #endif
                    693:                } else {
1.6     ! is        694:                        bus_io_write_1(bc, ioh, 0, RESUME_XMT_CMD);
1.1       is        695: #ifdef IYDEBUG
                    696:                        printf("%s: giving RESUME_XCMD\n",
                    697:                            sc->sc_dev.dv_xname);
                    698: #endif
                    699:                }
                    700:                sc->tx_last = last;
                    701:                sc->tx_end = end;
                    702:        }
                    703: }
                    704:
                    705:
                    706: static __inline void
1.6     ! is        707: eepromwritebit(bc, ioh, ioff, what)
        !           708:        bus_chipset_tag_t bc;
        !           709:        bus_io_handle_t ioh;
        !           710:        bus_io_size_t ioff;
        !           711:        int what;
1.1       is        712: {
1.6     ! is        713:        bus_io_write_1(bc, ioh, ioff, what);
1.1       is        714:        delay(1);
1.6     ! is        715:        bus_io_write_1(bc, ioh, ioff, what|EESK);
1.1       is        716:        delay(1);
1.6     ! is        717:        bus_io_write_1(bc, ioh, ioff, what);
1.1       is        718:        delay(1);
                    719: }
                    720:
                    721: static __inline int
1.6     ! is        722: eepromreadbit(bc, ioh, ioff)
        !           723:        bus_chipset_tag_t bc;
        !           724:        bus_io_handle_t ioh;
        !           725:        bus_io_size_t ioff;
1.1       is        726: {
                    727:        int b;
                    728:
1.6     ! is        729:        bus_io_write_1(bc, ioh, ioff, EECS|EESK);
1.1       is        730:        delay(1);
1.6     ! is        731:        b = bus_io_read_1(bc, ioh, ioff);
        !           732:        bus_io_write_1(bc, ioh, ioff, EECS);
1.1       is        733:        delay(1);
                    734:
                    735:        return ((b & EEDO) != 0);
                    736: }
                    737:
                    738: static u_int16_t
1.6     ! is        739: eepromread(bc, ioh, ioff, offset)
        !           740:        bus_chipset_tag_t bc;
        !           741:        bus_io_handle_t ioh;
        !           742:        bus_io_size_t ioff;
        !           743:        int offset;
1.1       is        744: {
                    745:        volatile int i;
                    746:        volatile int j;
                    747:        volatile u_int16_t readval;
                    748:
1.6     ! is        749:        bus_io_write_1(bc, ioh, 0, BANK_SEL(2));
1.1       is        750:        delay(1);
1.6     ! is        751:        bus_io_write_1(bc, ioh, ioff, EECS); /* XXXX??? */
1.1       is        752:        delay(1);
                    753:
1.6     ! is        754:        eepromwritebit(bc, ioh, ioff, EECS|EEDI);
        !           755:        eepromwritebit(bc, ioh, ioff, EECS|EEDI);
        !           756:        eepromwritebit(bc, ioh, ioff, EECS);
1.1       is        757:
                    758:        for (j=5; j>=0; --j) {
                    759:                if ((offset>>j) & 1)
1.6     ! is        760:                        eepromwritebit(bc, ioh, ioff, EECS|EEDI);
1.1       is        761:                else
1.6     ! is        762:                        eepromwritebit(bc, ioh, ioff, EECS);
1.1       is        763:        }
                    764:
                    765:        for (readval=0, i=0; i<16; ++i) {
                    766:                readval<<=1;
1.6     ! is        767:                readval |= eepromreadbit(bc, ioh, ioff);
1.1       is        768:        }
                    769:
1.6     ! is        770:        bus_io_write_1(bc, ioh, ioff, 0|EESK);
1.1       is        771:        delay(1);
1.6     ! is        772:        bus_io_write_1(bc, ioh, ioff, 0);
1.1       is        773:
1.6     ! is        774:        bus_io_write_1(bc, ioh, ioff, BANK_SEL(0));
1.1       is        775:
                    776:        return readval;
                    777: }
                    778:
                    779: /*
                    780:  * Device timeout/watchdog routine.  Entered if the device neglects to generate
                    781:  * an interrupt after a transmit has been started on it.
                    782:  */
                    783: void
1.2       thorpej   784: iywatchdog(ifp)
1.3       is        785:        struct ifnet *ifp;
1.1       is        786: {
1.2       thorpej   787:        struct iy_softc *sc = ifp->if_softc;
1.1       is        788:
                    789:        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
                    790:        ++sc->sc_arpcom.ac_if.if_oerrors;
                    791:        iyreset(sc);
                    792: }
                    793:
                    794: /*
                    795:  * What to do upon receipt of an interrupt.
                    796:  */
                    797: int
                    798: iyintr(arg)
                    799:        void *arg;
                    800: {
                    801:        struct iy_softc *sc = arg;
1.6     ! is        802:        bus_chipset_tag_t bc;
        !           803:        bus_io_handle_t ioh;
        !           804:
1.1       is        805:        register u_short status;
                    806:
1.6     ! is        807:        bc = sc->sc_bc;
        !           808:        ioh = sc->sc_ioh;
        !           809:
        !           810:        status = bus_io_read_1(bc, ioh, STATUS_REG);
1.1       is        811: #ifdef IYDEBUG
                    812:        if (status & ALL_INTS) {
                    813:                printf("%s: got interupt %b", sc->sc_dev.dv_xname, status,
                    814:                    "\020\1RX_STP\2RX\3TX\4EXEC");
                    815:                if (status & EXEC_INT)
1.6     ! is        816:                        printf(" event %b\n", bus_io_read_1(bc, ioh, 0),
1.1       is        817:                            "\020\6ABORT");
                    818:                else
                    819:                        printf("\n");
                    820:        }
                    821: #endif
                    822:        if ((status & (RX_INT | TX_INT) == 0))
                    823:                return 0;
                    824:
                    825:        if (status & RX_INT) {
                    826:                iy_intr_rx(sc);
1.6     ! is        827:                bus_io_write_1(bc, ioh, STATUS_REG, RX_INT);
1.1       is        828:        } else if (status & TX_INT) {
                    829:                iy_intr_tx(sc);
1.6     ! is        830:                bus_io_write_1(bc, ioh, STATUS_REG, TX_INT);
1.1       is        831:        }
                    832:        return 1;
                    833: }
                    834:
                    835: void
1.6     ! is        836: iyget(sc, bc, ioh, rxlen)
        !           837:        struct iy_softc *sc;
        !           838:        bus_chipset_tag_t bc;
        !           839:        bus_io_handle_t ioh;
        !           840:        int rxlen;
1.1       is        841: {
                    842:        struct mbuf *m, *top, **mp;
                    843:        struct ether_header *eh;
                    844:        struct ifnet *ifp;
                    845:        int len;
                    846:
                    847:        ifp = &sc->sc_arpcom.ac_if;
                    848:
                    849:        m = sc->mb[sc->next_mb];
                    850:        sc->mb[sc->next_mb] = 0;
                    851:        if (m == 0) {
                    852:                MGETHDR(m, M_DONTWAIT, MT_DATA);
                    853:                if (m == 0)
                    854:                        goto dropped;
                    855:        } else {
                    856:                if (sc->last_mb == sc->next_mb)
                    857:                        timeout(iymbuffill, sc, 1);
                    858:                sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
                    859:                m->m_data = m->m_pktdat;
                    860:                m->m_flags = M_PKTHDR;
                    861:        }
                    862:        m->m_pkthdr.rcvif = ifp;
                    863:        m->m_pkthdr.len = rxlen;
                    864:        len = MHLEN;
                    865:        top = 0;
                    866:        mp = &top;
                    867:
                    868:        while (rxlen > 0) {
                    869:                if (top) {
                    870:                        m = sc->mb[sc->next_mb];
                    871:                        sc->mb[sc->next_mb] = 0;
                    872:                        if (m == 0) {
                    873:                                MGET(m, M_DONTWAIT, MT_DATA);
                    874:                                if (m == 0) {
                    875:                                        m_freem(top);
                    876:                                        goto dropped;
                    877:                                }
                    878:                        } else {
                    879:                                sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
                    880:                        }
                    881:                        len = MLEN;
                    882:                }
                    883:                if (rxlen >= MINCLSIZE) {
                    884:                        MCLGET(m, M_DONTWAIT);
                    885:                        if (m->m_flags & M_EXT)
                    886:                                len = MCLBYTES;
                    887:                }
                    888:                len = min(rxlen, len);
                    889:                if (len > 1) {
                    890:                        len &= ~1;
1.6     ! is        891:
        !           892:                        bus_io_read_multi_2(bc, ioh, MEM_PORT_REG,
        !           893:                            mtod(m, caddr_t), len/2);
1.1       is        894:                } else {
                    895: #ifdef IYDEBUG
                    896:                        printf("%s: received odd mbuf\n", sc->sc_dev.dv_xname);
                    897: #endif
1.6     ! is        898:                        *(mtod(m, caddr_t)) = bus_io_read_2(bc, ioh,
        !           899:                            MEM_PORT_REG);
1.1       is        900:                }
                    901:                m->m_len = len;
                    902:                rxlen -= len;
                    903:                *mp = m;
                    904:                mp = &m->m_next;
                    905:        }
                    906:        /* XXX receive the top here */
                    907:        ++ifp->if_ipackets;
                    908:
                    909:        eh = mtod(top, struct ether_header *);
                    910:
                    911: #if NBPFILTER > 0
                    912:        if (ifp->if_bpf) {
                    913:                bpf_mtap(ifp->if_bpf, top);
                    914:                if ((ifp->if_flags & IFF_PROMISC) &&
                    915:                    (eh->ether_dhost[0] & 1) == 0 &&
                    916:                    bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
                    917:                                sizeof(eh->ether_dhost)) != 0) {
                    918:                        m_freem(top);
                    919:                        return;
                    920:                }
                    921:        }
                    922: #endif
                    923:        m_adj(top, sizeof(struct ether_header));
                    924:        ether_input(ifp, eh, top);
                    925:        return;
                    926:
                    927: dropped:
                    928:        ++ifp->if_ierrors;
                    929:        return;
                    930: }
                    931: void
                    932: iy_intr_rx(sc)
                    933: struct iy_softc *sc;
                    934: {
                    935:        struct ifnet *ifp;
1.6     ! is        936:        bus_chipset_tag_t bc;
        !           937:        bus_io_handle_t ioh;
        !           938:
1.1       is        939:        u_int rxadrs, rxevnt, rxstatus, rxnext, rxlen;
                    940:
1.6     ! is        941:        bc = sc->sc_bc;
        !           942:        ioh = sc->sc_ioh;
1.1       is        943:        ifp = &sc->sc_arpcom.ac_if;
                    944:
                    945:        rxadrs = sc->rx_start;
1.6     ! is        946:        bus_io_write_2(bc, ioh, HOST_ADDR_REG, rxadrs);
        !           947:        rxevnt = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1       is        948:        rxnext = 0;
                    949:
                    950:        while (rxevnt == RCV_DONE) {
1.6     ! is        951:                rxstatus = bus_io_read_2(bc, ioh, MEM_PORT_REG);
        !           952:                rxnext = bus_io_read_2(bc, ioh, MEM_PORT_REG);
        !           953:                rxlen = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1       is        954: #ifdef IYDEBUG
                    955:                printf("%s: pck at 0x%04x stat %b next 0x%x len 0x%x\n",
                    956:                    sc->sc_dev.dv_xname, rxadrs, rxstatus,
                    957:                    "\020\1RCLD\2IA_MCH\010SHORT\011OVRN\013ALGERR"
                    958:                    "\014CRCERR\015LENERR\016RCVOK\020TYP",
                    959:                    rxnext, rxlen);
                    960: #endif
1.6     ! is        961:                iyget(sc, bc, ioh, rxlen);
1.1       is        962:
                    963:                /* move stop address */
1.6     ! is        964:                bus_io_write_2(bc, ioh, RCV_STOP_LOW,
1.1       is        965:                            rxnext == 0 ? sc->rx_size - 2 : rxnext - 2);
                    966:
1.6     ! is        967:                bus_io_write_2(bc, ioh, HOST_ADDR_REG, rxnext);
1.1       is        968:                rxadrs = rxnext;
1.6     ! is        969:                rxevnt = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1       is        970:        }
                    971:        sc->rx_start = rxnext;
                    972: }
                    973:
                    974: void
                    975: iy_intr_tx(sc)
                    976: struct iy_softc *sc;
                    977: {
1.6     ! is        978:        bus_chipset_tag_t bc;
        !           979:        bus_io_handle_t ioh;
1.1       is        980:        struct ifnet *ifp;
                    981:        u_int txstatus, txstat2, txlen, txnext;
                    982:
                    983:        ifp = &sc->sc_arpcom.ac_if;
1.6     ! is        984:        bc = sc->sc_bc;
        !           985:        ioh = sc->sc_ioh;
        !           986:
1.1       is        987:        while (sc->tx_start != sc->tx_end) {
1.6     ! is        988:                bus_io_write_2(bc, ioh, HOST_ADDR_REG, sc->tx_start);
        !           989:                txstatus = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1       is        990:                if ((txstatus & (TX_DONE|CMD_MASK)) != (TX_DONE|XMT_CMD))
                    991:                        break;
                    992:
1.6     ! is        993:                txstat2 = bus_io_read_2(bc, ioh, MEM_PORT_REG);
        !           994:                txnext = bus_io_read_2(bc, ioh, MEM_PORT_REG);
        !           995:                txlen = bus_io_read_2(bc, ioh, MEM_PORT_REG);
1.1       is        996: #ifdef IYDEBUG
                    997:                printf("txstat 0x%x stat2 0x%b next 0x%x len 0x%x\n",
                    998:                    txstatus, txstat2, "\020\6MAX_COL\7HRT_BEAT\010TX_DEF"
                    999:                    "\011UND_RUN\012JERR\013LST_CRS\014LTCOL\016TX_OK\020COLL",
                   1000:                        txnext, txlen);
                   1001: #endif
                   1002:                if (txlen & CHAIN)
                   1003:                        sc->tx_start = txnext;
                   1004:                else
                   1005:                        sc->tx_start = sc->tx_end;
                   1006:                ifp->if_flags &= ~IFF_OACTIVE;
                   1007:
                   1008:                if ((txstat2 & 0x2000) == 0)
                   1009:                        ++ifp->if_oerrors;
                   1010:                if (txstat2 & 0x000f)
                   1011:                        ifp->if_oerrors += txstat2 & 0x000f;
                   1012:        }
                   1013:        ifp->if_flags &= ~IFF_OACTIVE;
                   1014: }
                   1015:
                   1016: #if 0
                   1017: /*
                   1018:  * Compare two Ether/802 addresses for equality, inlined and unrolled for
                   1019:  * speed.  I'd love to have an inline assembler version of this...
                   1020:  */
                   1021: static inline int
                   1022: ether_equal(one, two)
                   1023:        u_char *one, *two;
                   1024: {
                   1025:
                   1026:        if (one[0] != two[0] || one[1] != two[1] || one[2] != two[2] ||
                   1027:            one[3] != two[3] || one[4] != two[4] || one[5] != two[5])
                   1028:                return 0;
                   1029:        return 1;
                   1030: }
                   1031:
                   1032: /*
                   1033:  * Check for a valid address.  to_bpf is filled in with one of the following:
                   1034:  *   0 -> BPF doesn't get this packet
                   1035:  *   1 -> BPF does get this packet
                   1036:  *   2 -> BPF does get this packet, but we don't
                   1037:  * Return value is true if the packet is for us, and false otherwise.
                   1038:  *
                   1039:  * This routine is a mess, but it's also critical that it be as fast
                   1040:  * as possible.  It could be made cleaner if we can assume that the
                   1041:  * only client which will fiddle with IFF_PROMISC is BPF.  This is
                   1042:  * probably a good assumption, but we do not make it here.  (Yet.)
                   1043:  */
                   1044: static inline int
                   1045: check_eh(sc, eh, to_bpf)
                   1046:        struct iy_softc *sc;
                   1047:        struct ether_header *eh;
                   1048:        int *to_bpf;
                   1049: {
                   1050:        int i;
                   1051:
                   1052:        switch (sc->promisc) {
                   1053:        case IFF_ALLMULTI:
                   1054:                /*
                   1055:                 * Receiving all multicasts, but no unicasts except those
                   1056:                 * destined for us.
                   1057:                 */
                   1058: #if NBPFILTER > 0
                   1059:                *to_bpf = (sc->sc_arpcom.ac_if.iy_bpf != 0); /* BPF gets this packet if anybody cares */
                   1060: #endif
                   1061:                if (eh->ether_dhost[0] & 1)
                   1062:                        return 1;
                   1063:                if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr))
                   1064:                        return 1;
                   1065:                return 0;
                   1066:
                   1067:        case IFF_PROMISC:
                   1068:                /*
                   1069:                 * Receiving all packets.  These need to be passed on to BPF.
                   1070:                 */
                   1071: #if NBPFILTER > 0
                   1072:                *to_bpf = (sc->sc_arpcom.ac_if.iy_bpf != 0);
                   1073: #endif
                   1074:                /* If for us, accept and hand up to BPF */
                   1075:                if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr))
                   1076:                        return 1;
                   1077:
                   1078: #if NBPFILTER > 0
                   1079:                if (*to_bpf)
                   1080:                        *to_bpf = 2; /* we don't need to see it */
                   1081: #endif
                   1082:
                   1083:                /*
                   1084:                 * Not a multicast, so BPF wants to see it but we don't.
                   1085:                 */
                   1086:                if (!(eh->ether_dhost[0] & 1))
                   1087:                        return 1;
                   1088:
                   1089:                /*
                   1090:                 * If it's one of our multicast groups, accept it and pass it
                   1091:                 * up.
                   1092:                 */
                   1093:                for (i = 0; i < sc->mcast_count; i++) {
                   1094:                        if (ether_equal(eh->ether_dhost, (u_char *)&sc->mcast_addrs[i])) {
                   1095: #if NBPFILTER > 0
                   1096:                                if (*to_bpf)
                   1097:                                        *to_bpf = 1;
                   1098: #endif
                   1099:                                return 1;
                   1100:                        }
                   1101:                }
                   1102:                return 1;
                   1103:
                   1104:        case IFF_ALLMULTI | IFF_PROMISC:
                   1105:                /*
                   1106:                 * Acting as a multicast router, and BPF running at the same
                   1107:                 * time.  Whew!  (Hope this is a fast machine...)
                   1108:                 */
                   1109: #if NBPFILTER > 0
                   1110:                *to_bpf = (sc->sc_arpcom.ac_if.iy_bpf != 0);
                   1111: #endif
                   1112:                /* We want to see multicasts. */
                   1113:                if (eh->ether_dhost[0] & 1)
                   1114:                        return 1;
                   1115:
                   1116:                /* We want to see our own packets */
                   1117:                if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr))
                   1118:                        return 1;
                   1119:
                   1120:                /* Anything else goes to BPF but nothing else. */
                   1121: #if NBPFILTER > 0
                   1122:                if (*to_bpf)
                   1123:                        *to_bpf = 2;
                   1124: #endif
                   1125:                return 1;
                   1126:
                   1127:        case 0:
                   1128:                /*
                   1129:                 * Only accept unicast packets destined for us, or multicasts
                   1130:                 * for groups that we belong to.  For now, we assume that the
                   1131:                 * '586 will only return packets that we asked it for.  This
                   1132:                 * isn't strictly true (it uses hashing for the multicast
                   1133:                 * filter), but it will do in this case, and we want to get out
                   1134:                 * of here as quickly as possible.
                   1135:                 */
                   1136: #if NBPFILTER > 0
                   1137:                *to_bpf = (sc->sc_arpcom.ac_if.iy_bpf != 0);
                   1138: #endif
                   1139:                return 1;
                   1140:        }
                   1141:
                   1142: #ifdef DIAGNOSTIC
                   1143:        panic("check_eh: impossible");
                   1144: #endif
                   1145: }
                   1146: #endif
                   1147:
                   1148: int
                   1149: iyioctl(ifp, cmd, data)
                   1150:        register struct ifnet *ifp;
                   1151:        u_long cmd;
                   1152:        caddr_t data;
                   1153: {
                   1154:        struct iy_softc *sc;
                   1155:        struct ifaddr *ifa;
                   1156:        struct ifreq *ifr;
                   1157:        int s, error = 0;
                   1158:
1.2       thorpej  1159:        sc = ifp->if_softc;
1.1       is       1160:        ifa = (struct ifaddr *)data;
                   1161:        ifr = (struct ifreq *)data;
                   1162:
                   1163: #ifdef IYDEBUG
1.2       thorpej  1164:        printf("iyioctl called with ifp 0x%p (%s) cmd 0x%x data 0x%p\n",
                   1165:            ifp, ifp->if_xname, cmd, data);
1.1       is       1166: #endif
                   1167:
                   1168:        s = splimp();
                   1169:
                   1170:        switch (cmd) {
                   1171:
                   1172:        case SIOCSIFADDR:
                   1173:                ifp->if_flags |= IFF_UP;
                   1174:
                   1175:                switch (ifa->ifa_addr->sa_family) {
                   1176: #ifdef INET
                   1177:                case AF_INET:
                   1178:                        iyinit(sc);
                   1179:                        arp_ifinit(&sc->sc_arpcom, ifa);
                   1180:                        break;
                   1181: #endif
                   1182: #ifdef NS
                   1183:                /* XXX - This code is probably wrong. */
                   1184:                case AF_NS:
                   1185:                    {
                   1186:                        struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
                   1187:
                   1188:                        if (ns_nullhost(*ina))
                   1189:                                ina->x_host =
                   1190:                                    *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
                   1191:                        else
                   1192:                                bcopy(ina->x_host.c_host,
                   1193:                                    sc->sc_arpcom.ac_enaddr,
                   1194:                                    sizeof(sc->sc_arpcom.ac_enaddr));
                   1195:                        /* Set new address. */
                   1196:                        iyinit(sc);
                   1197:                        break;
                   1198:                    }
                   1199: #endif /* NS */
                   1200:                default:
                   1201:                        iyinit(sc);
                   1202:                        break;
                   1203:                }
                   1204:                break;
                   1205:
                   1206:        case SIOCSIFFLAGS:
                   1207:                sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
                   1208:                if ((ifp->if_flags & IFF_UP) == 0 &&
                   1209:                    (ifp->if_flags & IFF_RUNNING) != 0) {
                   1210:                        /*
                   1211:                         * If interface is marked down and it is running, then
                   1212:                         * stop it.
                   1213:                         */
                   1214:                        iystop(sc);
                   1215:                        ifp->if_flags &= ~IFF_RUNNING;
                   1216:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
                   1217:                           (ifp->if_flags & IFF_RUNNING) == 0) {
                   1218:                        /*
                   1219:                         * If interface is marked up and it is stopped, then
                   1220:                         * start it.
                   1221:                         */
                   1222:                        iyinit(sc);
                   1223:                } else {
                   1224:                        /*
                   1225:                         * Reset the interface to pick up changes in any other
                   1226:                         * flags that affect hardware registers.
                   1227:                         */
                   1228:                        iystop(sc);
                   1229:                        iyinit(sc);
                   1230:                }
                   1231: #ifdef IYDEBUGX
                   1232:                if (ifp->if_flags & IFF_DEBUG)
                   1233:                        sc->sc_debug = IFY_ALL;
                   1234:                else
                   1235:                        sc->sc_debug = 0;
                   1236: #endif
                   1237:                break;
                   1238:
                   1239: #if 0 /* XXX */
                   1240:        case SIOCADDMULTI:
                   1241:        case SIOCDELMULTI:
                   1242:                error = (cmd == SIOCADDMULTI) ?
                   1243:                    ether_addmulti(ifr, &sc->sc_arpcom):
                   1244:                    ether_delmulti(ifr, &sc->sc_arpcom);
                   1245:
                   1246:                if (error == ENETRESET) {
                   1247:                        /*
                   1248:                         * Multicast list has changed; set the hardware filter
                   1249:                         * accordingly.
                   1250:                         */
                   1251:                        iy_mc_reset(sc); /* XXX */
                   1252:                        error = 0;
                   1253:                }
                   1254:                break;
                   1255: #endif
                   1256:        default:
                   1257:                error = EINVAL;
                   1258:        }
                   1259:        splx(s);
                   1260:        return error;
                   1261: }
                   1262:
                   1263: #if 0
                   1264: static void
                   1265: iy_mc_reset(sc)
                   1266:        struct iy_softc *sc;
                   1267: {
                   1268:        struct ether_multi *enm;
                   1269:        struct ether_multistep step;
                   1270:
                   1271:        /*
                   1272:         * Step through the list of addresses.
                   1273:         */
                   1274:        sc->mcast_count = 0;
                   1275:        ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
                   1276:        while (enm) {
                   1277:                if (sc->mcast_count >= MAXMCAST ||
                   1278:                    bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
                   1279:                        sc->sc_arpcom.ac_if.if_flags |= IFF_ALLMULTI;
                   1280:                        iyioctl(&sc->sc_arpcom.ac_if, SIOCSIFFLAGS, (void *)0);
                   1281:                        goto setflag;
                   1282:                }
                   1283:
                   1284:                bcopy(enm->enm_addrlo, &sc->mcast_addrs[sc->mcast_count], 6);
                   1285:                sc->mcast_count++;
                   1286:                ETHER_NEXT_MULTI(step, enm);
                   1287:        }
                   1288:        setflag:
                   1289:        sc->want_mcsetup = 1;
                   1290: }
                   1291:
                   1292: #ifdef IYDEBUG
                   1293: void
                   1294: print_rbd(rbd)
                   1295:        volatile struct ie_recv_buf_desc *rbd;
                   1296: {
                   1297:
                   1298:        printf("RBD at %08lx:\nactual %04x, next %04x, buffer %08x\n"
                   1299:            "length %04x, mbz %04x\n", (u_long)rbd, rbd->ie_rbd_actual,
                   1300:            rbd->ie_rbd_next, rbd->ie_rbd_buffer, rbd->ie_rbd_length,
                   1301:            rbd->mbz);
                   1302: }
                   1303: #endif
                   1304: #endif
                   1305:
                   1306: void
                   1307: iymbuffill(arg)
                   1308:        void *arg;
                   1309: {
                   1310:        struct iy_softc *sc = (struct iy_softc *)arg;
                   1311:        int s, i;
                   1312:
                   1313:        s = splimp();
                   1314:        i = sc->last_mb;
                   1315:        do {
                   1316:                if (sc->mb[i] == NULL)
                   1317:                        MGET(sc->mb[i], M_DONTWAIT, MT_DATA);
                   1318:                if (sc->mb[i] == NULL)
                   1319:                        break;
                   1320:                i = (i + 1) % MAX_MBS;
                   1321:        } while (i != sc->next_mb);
                   1322:        sc->last_mb = i;
                   1323:        /* If the queue was not filled, try again. */
                   1324:        if (sc->last_mb != sc->next_mb)
                   1325:                timeout(iymbuffill, sc, 1);
                   1326:        splx(s);
                   1327: }
                   1328:
                   1329:
                   1330: void
                   1331: iymbufempty(arg)
                   1332:        void *arg;
                   1333: {
                   1334:        struct iy_softc *sc = (struct iy_softc *)arg;
                   1335:        int s, i;
                   1336:
                   1337:        s = splimp();
                   1338:        for (i = 0; i<MAX_MBS; i++) {
                   1339:                if (sc->mb[i]) {
                   1340:                        m_freem(sc->mb[i]);
                   1341:                        sc->mb[i] = NULL;
                   1342:                }
                   1343:        }
                   1344:        sc->last_mb = sc->next_mb = 0;
                   1345:        untimeout(iymbuffill, sc);
                   1346:        splx(s);
                   1347: }
                   1348:
                   1349: void
                   1350: iyprobemem(sc)
                   1351:        struct iy_softc *sc;
                   1352: {
1.6     ! is       1353:        bus_chipset_tag_t bc;
        !          1354:        bus_io_handle_t ioh;
1.1       is       1355:        int testing;
                   1356:
1.6     ! is       1357:        bc = sc->sc_bc;
        !          1358:        ioh = sc->sc_ioh;
1.1       is       1359:
1.6     ! is       1360:        bus_io_write_2(bc, ioh, HOST_ADDR_REG, 4096-2);
        !          1361:        bus_io_write_2(bc, ioh, MEM_PORT_REG, 0);
1.1       is       1362:
                   1363:        for (testing=65536; testing >= 4096; testing >>= 1) {
1.6     ! is       1364:                bus_io_write_2(bc, ioh, HOST_ADDR_REG, testing-2);
        !          1365:                bus_io_write_2(bc, ioh, MEM_PORT_REG, 0xdead);
        !          1366:                bus_io_write_2(bc, ioh, HOST_ADDR_REG, testing-2);
        !          1367:                if (bus_io_read_2(bc, ioh, MEM_PORT_REG) != 0xdead) {
1.1       is       1368: #ifdef IYMEMDEBUG
                   1369:                        printf("%s: Didn't keep 0xdead at 0x%x\n",
                   1370:                            sc->sc_dev.dv_xname, testing-2);
                   1371: #endif
                   1372:                        continue;
                   1373:                }
                   1374:
1.6     ! is       1375:                bus_io_write_2(bc, ioh, HOST_ADDR_REG, testing-2);
        !          1376:                bus_io_write_2(bc, ioh, MEM_PORT_REG, 0xbeef);
        !          1377:                bus_io_write_2(bc, ioh, HOST_ADDR_REG, testing-2);
        !          1378:                if (bus_io_read_2(bc, ioh, MEM_PORT_REG) != 0xbeef) {
1.1       is       1379: #ifdef IYMEMDEBUG
                   1380:                        printf("%s: Didn't keep 0xbeef at 0x%x\n",
                   1381:                            sc->sc_dev.dv_xname, testing-2);
                   1382: #endif
                   1383:                        continue;
                   1384:                }
                   1385:
1.6     ! is       1386:                bus_io_write_2(bc, ioh, HOST_ADDR_REG, 0);
        !          1387:                bus_io_write_2(bc, ioh, MEM_PORT_REG, 0);
        !          1388:                bus_io_write_2(bc, ioh, HOST_ADDR_REG, testing >> 1);
        !          1389:                bus_io_write_2(bc, ioh, MEM_PORT_REG, testing >> 1);
        !          1390:                bus_io_write_2(bc, ioh, HOST_ADDR_REG, 0);
        !          1391:                if (bus_io_read_2(bc, ioh, MEM_PORT_REG) == (testing >> 1)) {
1.1       is       1392: #ifdef IYMEMDEBUG
                   1393:                        printf("%s: 0x%x alias of 0x0\n",
                   1394:                            sc->sc_dev.dv_xname, testing >> 1);
                   1395: #endif
                   1396:                        continue;
                   1397:                }
                   1398:
                   1399:                break;
                   1400:        }
                   1401:
                   1402:        sc->sram = testing;
                   1403:
                   1404:        switch(testing) {
                   1405:                case 65536:
                   1406:                        /* 4 NFS packets + overhead RX, 2 NFS + overhead TX  */
                   1407:                        sc->rx_size = 44*1024;
                   1408:                        break;
                   1409:
                   1410:                case 32768:
                   1411:                        /* 2 NFS packets + overhead RX, 1 NFS + overhead TX  */
                   1412:                        sc->rx_size = 22*1024;
                   1413:                        break;
                   1414:
                   1415:                case 16384:
                   1416:                        /* 1 NFS packet + overhead RX, 4 big packets TX */
                   1417:                        sc->rx_size = 10*1024;
                   1418:                        break;
                   1419:                default:
                   1420:                        sc->rx_size = testing/2;
                   1421:                        break;
                   1422:        }
                   1423:        sc->tx_size = testing - sc->rx_size;
                   1424: }

CVSweb <webmaster@jp.NetBSD.org>