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

1.53.2.2! thorpej     1: /*     $NetBSD: if_iy.c,v 1.53.2.1 2001/08/03 04:13:09 lukem Exp $     */
1.1       is          2: /* #define IYDEBUG */
                      3: /* #define IYMEMDEBUG */
1.30      is          4:
1.1       is          5: /*-
1.52      is          6:  * Copyright (c) 1996,2001 The NetBSD Foundation, Inc.
1.1       is          7:  * All rights reserved.
                      8:  *
1.30      is          9:  * This code is derived from software contributed to The NetBSD Foundation
                     10:  * by Ignatios Souvatzis.
                     11:  *
1.1       is         12:  * Redistribution and use in source and binary forms, with or without
                     13:  * modification, are permitted provided that the following conditions
                     14:  * are met:
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  * 2. Redistributions in binary form must reproduce the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer in the
                     19:  *    documentation and/or other materials provided with the distribution.
                     20:  * 3. All advertising materials mentioning features or use of this software
                     21:  *    must display the following acknowledgement:
1.30      is         22:  *        This product includes software developed by the NetBSD
                     23:  *        Foundation, Inc. and its contributors.
                     24:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     25:  *    contributors may be used to endorse or promote products derived
                     26:  *    from this software without specific prior written permission.
1.1       is         27:  *
1.30      is         28:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     29:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     30:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     31:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     32:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     33:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     34:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     35:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     36:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     37:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     38:  * POSSIBILITY OF SUCH DAMAGE.
1.27      is         39:  */
                     40:
                     41: /*
                     42:  * Supported hardware:
                     43:  *
                     44:  * - Intel EtherExpress Pro/10.
                     45:  * - possibly other boards using the i82595 chip and no special tweaks.
1.1       is         46:  */
                     47:
1.53.2.2! thorpej    48: #include <sys/cdefs.h>
        !            49: __KERNEL_RCSID(0, "$NetBSD: if_iy.c,v 1.57 2002/01/07 21:47:08 thorpej Exp $");
        !            50:
1.22      jonathan   51: #include "opt_inet.h"
1.23      jonathan   52: #include "opt_ns.h"
1.1       is         53: #include "bpfilter.h"
1.14      explorer   54: #include "rnd.h"
1.1       is         55:
                     56: #include <sys/param.h>
                     57: #include <sys/systm.h>
                     58: #include <sys/mbuf.h>
                     59: #include <sys/buf.h>
                     60: #include <sys/protosw.h>
                     61: #include <sys/socket.h>
                     62: #include <sys/ioctl.h>
                     63: #include <sys/errno.h>
                     64: #include <sys/syslog.h>
                     65: #include <sys/device.h>
1.41      is         66: #include <sys/endian.h>
1.14      explorer   67: #if NRND > 0
                     68: #include <sys/rnd.h>
                     69: #endif
1.1       is         70:
                     71: #include <net/if.h>
                     72: #include <net/if_types.h>
                     73: #include <net/if_dl.h>
1.10      is         74:
                     75: #include <net/if_ether.h>
1.1       is         76:
                     77: #if NBPFILTER > 0
                     78: #include <net/bpf.h>
                     79: #include <net/bpfdesc.h>
                     80: #endif
                     81:
                     82: #ifdef INET
                     83: #include <netinet/in.h>
                     84: #include <netinet/in_systm.h>
                     85: #include <netinet/in_var.h>
                     86: #include <netinet/ip.h>
1.10      is         87: #include <netinet/if_inarp.h>
1.1       is         88: #endif
                     89:
                     90: #ifdef NS
                     91: #include <netns/ns.h>
                     92: #include <netns/ns_if.h>
                     93: #endif
                     94:
1.18      bouyer     95: #if defined(SIOCSIFMEDIA)
                     96: #include <net/if_media.h>
                     97: #endif
1.1       is         98:
                     99: #include <machine/cpu.h>
1.6       is        100: #include <machine/bus.h>
1.4       mycroft   101: #include <machine/intr.h>
1.1       is        102:
                    103: #include <dev/isa/isareg.h>
                    104: #include <dev/isa/isavar.h>
                    105: #include <dev/ic/i82595reg.h>
                    106:
1.41      is        107: /* XXX why isn't this centralized? */
                    108: #ifndef __BUS_SPACE_HAS_STREAM_METHODS
                    109: #define bus_space_write_stream_2       bus_space_write_2
                    110: #define bus_space_write_multi_stream_2 bus_space_write_multi_2
                    111: #define bus_space_read_stream_2                bus_space_read_2
                    112: #define bus_space_read_multi_stream_2  bus_space_read_multi_2
                    113: #endif /* __BUS_SPACE_HAS_STREAM_METHODS */
                    114:
1.1       is        115: /*
                    116:  * Ethernet status, per interface.
                    117:  */
                    118: struct iy_softc {
                    119:        struct device sc_dev;
                    120:        void *sc_ih;
                    121:
1.9       thorpej   122:        bus_space_tag_t sc_iot;
                    123:        bus_space_handle_t sc_ioh;
1.6       is        124:
1.10      is        125:        struct ethercom sc_ethercom;
1.1       is        126:
1.18      bouyer    127:        struct ifmedia iy_ifmedia;
                    128:        int iy_media;
                    129:
1.1       is        130:        int mappedirq;
                    131:
                    132:        int hard_vers;
                    133:
                    134:        int promisc;
                    135:
                    136:        int sram, tx_size, rx_size;
                    137:
                    138:        int tx_start, tx_end, tx_last;
                    139:        int rx_start;
                    140:
1.26      is        141:        int doing_mc_setup;
1.1       is        142: #ifdef IYDEBUG
                    143:        int sc_debug;
                    144: #endif
1.14      explorer  145:
                    146: #if NRND > 0
                    147:        rndsource_element_t rnd_source;
                    148: #endif
1.1       is        149: };
                    150:
1.2       thorpej   151: void iywatchdog __P((struct ifnet *));
1.1       is        152: int iyioctl __P((struct ifnet *, u_long, caddr_t));
                    153: int iyintr __P((void *));
                    154: void iyinit __P((struct iy_softc *));
                    155: void iystop __P((struct iy_softc *));
                    156: void iystart __P((struct ifnet *));
                    157:
                    158: void iy_intr_rx __P((struct iy_softc *));
                    159: void iy_intr_tx __P((struct iy_softc *));
                    160:
                    161: void iyreset __P((struct iy_softc *));
                    162: void iy_readframe __P((struct iy_softc *, int));
                    163: void iy_drop_packet_buffer __P((struct iy_softc *));
                    164: void iy_find_mem_size __P((struct iy_softc *));
                    165: void iyrint __P((struct iy_softc *));
                    166: void iytint __P((struct iy_softc *));
                    167: void iyxmit __P((struct iy_softc *));
1.26      is        168: static void iy_mc_setup __P((struct iy_softc *));
                    169: static void iy_mc_reset __P((struct iy_softc *));
1.9       thorpej   170: void iyget __P((struct iy_softc *, bus_space_tag_t, bus_space_handle_t, int));
1.1       is        171: void iyprobemem __P((struct iy_softc *));
1.10      is        172: static __inline void eepromwritebit __P((bus_space_tag_t, bus_space_handle_t,
                    173:     int));
                    174: static __inline int eepromreadbit __P((bus_space_tag_t, bus_space_handle_t));
1.26      is        175:
1.1       is        176: #ifdef IYDEBUGX
                    177: void print_rbd __P((volatile struct iy_recv_buf_desc *));
                    178:
                    179: int in_ifrint = 0;
                    180: int in_iftint = 0;
                    181: #endif
                    182:
1.18      bouyer    183: int iy_mediachange __P((struct ifnet *));
                    184: void iy_mediastatus __P((struct ifnet *, struct ifmediareq *));
                    185:
1.17      drochner  186: int iyprobe __P((struct device *, struct cfdata *, void *));
1.1       is        187: void iyattach __P((struct device *, struct device *, void *));
                    188:
1.10      is        189: static u_int16_t eepromread __P((bus_space_tag_t, bus_space_handle_t, int));
                    190:
                    191: static int eepromreadall __P((bus_space_tag_t, bus_space_handle_t, u_int16_t *,
                    192:     int));
1.1       is        193:
                    194: struct cfattach iy_ca = {
                    195:        sizeof(struct iy_softc), iyprobe, iyattach
                    196: };
                    197:
                    198: static u_int8_t eepro_irqmap[] = EEPP_INTMAP;
                    199: static u_int8_t eepro_revirqmap[] = EEPP_RINTMAP;
                    200:
                    201: int
                    202: iyprobe(parent, match, aux)
                    203:        struct device *parent;
1.17      drochner  204:        struct cfdata *match;
                    205:        void *aux;
1.1       is        206: {
                    207:        struct isa_attach_args *ia = aux;
                    208:        u_int16_t eaddr[8];
1.9       thorpej   209:        bus_space_tag_t iot;
                    210:        bus_space_handle_t ioh;
1.1       is        211:        u_int8_t c, d;
1.53.2.2! thorpej   212:        int irq;
        !           213:
        !           214:        if (ia->ia_nio < 1)
        !           215:                return (0);
        !           216:        if (ia->ia_nirq < 1)
        !           217:                return (0);
        !           218:
        !           219:        if (ISA_DIRECT_CONFIG(ia))
        !           220:                return (0);
1.1       is        221:
1.9       thorpej   222:        iot = ia->ia_iot;
1.15      drochner  223:
1.53.2.2! thorpej   224:        if (ia->ia_io[0].ir_addr == ISACF_PORT_DEFAULT)
1.15      drochner  225:                return 0;
                    226:
1.53.2.2! thorpej   227:        if (bus_space_map(iot, ia->ia_io[0].ir_addr, 16, 0, &ioh))
1.10      is        228:                return 0;
1.1       is        229:
                    230:        /* try to find the round robin sig: */
                    231:
1.9       thorpej   232:        c = bus_space_read_1(iot, ioh, ID_REG);
1.10      is        233:        if ((c & ID_REG_MASK) != ID_REG_SIG)
1.6       is        234:                goto out;
1.1       is        235:
1.9       thorpej   236:        d = bus_space_read_1(iot, ioh, ID_REG);
1.10      is        237:        if ((d & ID_REG_MASK) != ID_REG_SIG)
1.6       is        238:                goto out;
1.1       is        239:
                    240:        if (((d-c) & R_ROBIN_BITS) != 0x40)
1.6       is        241:                goto out;
1.1       is        242:
1.9       thorpej   243:        d = bus_space_read_1(iot, ioh, ID_REG);
1.10      is        244:        if ((d & ID_REG_MASK) != ID_REG_SIG)
1.6       is        245:                goto out;
1.1       is        246:
                    247:        if (((d-c) & R_ROBIN_BITS) != 0x80)
1.6       is        248:                goto out;
1.1       is        249:
1.9       thorpej   250:        d = bus_space_read_1(iot, ioh, ID_REG);
1.10      is        251:        if ((d & ID_REG_MASK) != ID_REG_SIG)
1.6       is        252:                goto out;
1.1       is        253:
                    254:        if (((d-c) & R_ROBIN_BITS) != 0xC0)
1.6       is        255:                goto out;
1.1       is        256:
1.9       thorpej   257:        d = bus_space_read_1(iot, ioh, ID_REG);
1.10      is        258:        if ((d & ID_REG_MASK) != ID_REG_SIG)
1.6       is        259:                goto out;
1.1       is        260:
                    261:        if (((d-c) & R_ROBIN_BITS) != 0x00)
1.6       is        262:                goto out;
1.1       is        263:
                    264: #ifdef IYDEBUG
1.10      is        265:                printf("iyprobe verified working ID reg.\n");
1.1       is        266: #endif
                    267:
1.10      is        268:        if (eepromreadall(iot, ioh, eaddr, 8))
                    269:                goto out;
1.1       is        270:
1.53.2.2! thorpej   271:        if (ia->ia_irq[0].ir_irq == ISACF_IRQ_DEFAULT)
        !           272:                irq = eepro_irqmap[eaddr[EEPPW1] & EEPP_Int];
        !           273:        else
        !           274:                irq = ia->ia_irq[0].ir_irq;
1.1       is        275:
1.53.2.2! thorpej   276:        if (irq >= sizeof(eepro_revirqmap))
1.6       is        277:                goto out;
1.1       is        278:
1.53.2.2! thorpej   279:        if (eepro_revirqmap[irq] == 0xff)
1.6       is        280:                goto out;
1.1       is        281:
                    282:        /* now lets reset the chip */
                    283:
1.9       thorpej   284:        bus_space_write_1(iot, ioh, COMMAND_REG, RESET_CMD);
1.1       is        285:        delay(200);
                    286:
1.53.2.2! thorpej   287:        ia->ia_nio = 1;
        !           288:        ia->ia_io[0].ir_size = 16;
        !           289:
        !           290:        ia->ia_nirq = 1;
        !           291:        ia->ia_irq[0].ir_irq = irq;
        !           292:
        !           293:        ia->ia_niomem = 0;
        !           294:        ia->ia_ndrq = 0;
1.6       is        295:
1.10      is        296:        bus_space_unmap(iot, ioh, 16);
1.1       is        297:        return 1;               /* found */
1.6       is        298: out:
1.9       thorpej   299:        bus_space_unmap(iot, ioh, 16);
1.6       is        300:        return 0;
1.1       is        301: }
                    302:
                    303: void
                    304: iyattach(parent, self, aux)
                    305:        struct device *parent, *self;
                    306:        void *aux;
                    307: {
                    308:        struct iy_softc *sc = (void *)self;
                    309:        struct isa_attach_args *ia = aux;
1.10      is        310:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1.9       thorpej   311:        bus_space_tag_t iot;
                    312:        bus_space_handle_t ioh;
1.10      is        313:        unsigned temp;
                    314:        u_int16_t eaddr[8];
                    315:        u_int8_t myaddr[ETHER_ADDR_LEN];
                    316:        int eirq;
1.6       is        317:
1.10      is        318:        iot = ia->ia_iot;
                    319:
1.53.2.2! thorpej   320:        if (bus_space_map(iot, ia->ia_io[0].ir_addr, 16, 0, &ioh)) {
1.16      thorpej   321:                printf(": can't map i/o space\n");
                    322:                return;
                    323:        }
1.10      is        324:
                    325:        sc->sc_iot = iot;
                    326:        sc->sc_ioh = ioh;
                    327:
1.53.2.2! thorpej   328:        sc->mappedirq = eepro_revirqmap[ia->ia_irq[0].ir_irq];
1.10      is        329:
                    330:        /* now let's reset the chip */
                    331:
                    332:        bus_space_write_1(iot, ioh, COMMAND_REG, RESET_CMD);
                    333:        delay(200);
                    334:
                    335:        iyprobemem(sc);
1.1       is        336:
1.53.2.1  lukem     337:        strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
1.2       thorpej   338:        ifp->if_softc = sc;
1.1       is        339:        ifp->if_start = iystart;
1.26      is        340:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS
                    341:            | IFF_MULTICAST;
                    342:
                    343:        sc->doing_mc_setup = 0;
1.1       is        344:
                    345:        ifp->if_ioctl = iyioctl;
                    346:        ifp->if_watchdog = iywatchdog;
                    347:
1.45      thorpej   348:        IFQ_SET_READY(&ifp->if_snd);
                    349:
1.10      is        350:        (void)eepromreadall(iot, ioh, eaddr, 8);
                    351:        sc->hard_vers = eaddr[EEPW6] & EEPP_BoardRev;
                    352:
                    353: #ifdef DIAGNOSTICS
                    354:        if ((eaddr[EEPPEther0] !=
                    355:             eepromread(iot, ioh, EEPPEther0a)) &&
                    356:            (eaddr[EEPPEther1] !=
                    357:             eepromread(iot, ioh, EEPPEther1a)) &&
                    358:            (eaddr[EEPPEther2] !=
                    359:             eepromread(iot, ioh, EEPPEther2a)))
                    360:
                    361:                printf("EEPROM Ethernet address differs from copy\n");
                    362: #endif
                    363:
                    364:         myaddr[1] = eaddr[EEPPEther0] & 0xFF;
                    365:         myaddr[0] = eaddr[EEPPEther0] >> 8;
                    366:         myaddr[3] = eaddr[EEPPEther1] & 0xFF;
                    367:         myaddr[2] = eaddr[EEPPEther1] >> 8;
                    368:         myaddr[5] = eaddr[EEPPEther2] & 0xFF;
                    369:         myaddr[4] = eaddr[EEPPEther2] >> 8;
                    370:
1.18      bouyer    371:        ifmedia_init(&sc->iy_ifmedia, 0, iy_mediachange, iy_mediastatus);
                    372:        ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_10_2, 0, NULL);
                    373:        ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_10_5, 0, NULL);
                    374:        ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_10_T, 0, NULL);
                    375:        ifmedia_add(&sc->iy_ifmedia, IFM_ETHER | IFM_AUTO, 0, NULL);
                    376:        ifmedia_set(&sc->iy_ifmedia, IFM_ETHER | IFM_AUTO);
1.1       is        377:        /* Attach the interface. */
                    378:        if_attach(ifp);
1.10      is        379:        ether_ifattach(ifp, myaddr);
                    380:        printf(": address %s, rev. %d, %d kB\n",
                    381:            ether_sprintf(myaddr),
1.1       is        382:            sc->hard_vers, sc->sram/1024);
1.10      is        383:
                    384:        eirq = eepro_irqmap[eaddr[EEPPW1] & EEPP_Int];
1.53.2.2! thorpej   385:        if (eirq != ia->ia_irq[0].ir_irq)
1.10      is        386:                printf("%s: EEPROM irq setting %d ignored\n",
                    387:                    sc->sc_dev.dv_xname, eirq);
1.1       is        388:
1.53.2.2! thorpej   389:        sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq,
        !           390:            IST_EDGE, IPL_NET, iyintr, sc);
1.10      is        391:
1.14      explorer  392: #if NRND > 0
1.32      explorer  393:        rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
                    394:                          RND_TYPE_NET, 0);
1.14      explorer  395: #endif
                    396:
1.10      is        397:        temp = bus_space_read_1(iot, ioh, INT_NO_REG);
                    398:        bus_space_write_1(iot, ioh, INT_NO_REG, (temp & 0xf8) | sc->mappedirq);
1.1       is        399: }
                    400:
                    401: void
                    402: iystop(sc)
                    403: struct iy_softc *sc;
                    404: {
1.9       thorpej   405:        bus_space_tag_t iot;
                    406:        bus_space_handle_t ioh;
1.1       is        407: #ifdef IYDEBUG
                    408:        u_int p, v;
                    409: #endif
                    410:
1.9       thorpej   411:        iot = sc->sc_iot;
1.6       is        412:        ioh = sc->sc_ioh;
1.1       is        413:
1.9       thorpej   414:        bus_space_write_1(iot, ioh, COMMAND_REG, RCV_DISABLE_CMD);
1.1       is        415:
1.9       thorpej   416:        bus_space_write_1(iot, ioh, INT_MASK_REG, ALL_INTS);
                    417:        bus_space_write_1(iot, ioh, STATUS_REG, ALL_INTS);
1.1       is        418:
1.9       thorpej   419:        bus_space_write_1(iot, ioh, COMMAND_REG, RESET_CMD);
1.1       is        420:        delay(200);
                    421: #ifdef IYDEBUG
1.8       christos  422:        printf("%s: dumping tx chain (st 0x%x end 0x%x last 0x%x)\n",
1.1       is        423:                    sc->sc_dev.dv_xname, sc->tx_start, sc->tx_end, sc->tx_last);
                    424:        p = sc->tx_last;
                    425:        if (!p)
                    426:                p = sc->tx_start;
                    427:        do {
1.42      tv        428:                char sbuf[128];
                    429:
1.9       thorpej   430:                bus_space_write_2(iot, ioh, HOST_ADDR_REG, p);
1.42      tv        431:
1.41      is        432:                v = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG));
1.42      tv        433:                bitmask_snprintf(v, "\020\006Ab\010Dn", sbuf, sizeof(sbuf));
                    434:                printf("0x%04x: %s ", p, sbuf);
                    435:
1.41      is        436:                v = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG));
1.42      tv        437:                bitmask_snprintf(v, "\020\6MAX_COL\7HRT_BEAT\010TX_DEF\011UND_RUN\012JERR\013LST_CRS\014LTCOL\016TX_OK\020COLL",
                    438:                                 sbuf, sizeof(sbuf));
                    439:                printf("0x%s", sbuf);
                    440:
1.41      is        441:                p = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG));
1.8       christos  442:                printf(" 0x%04x", p);
1.42      tv        443:
1.41      is        444:                v = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG));
1.42      tv        445:                bitmask_snprintf(v, "\020\020Ch", sbuf, sizeof(sbuf));
                    446:                printf(" 0x%s\n", sbuf);
                    447:
1.1       is        448:        } while (v & 0x8000);
                    449: #endif
                    450:        sc->tx_start = sc->tx_end = sc->rx_size;
                    451:        sc->tx_last = 0;
1.10      is        452:        sc->sc_ethercom.ec_if.if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
1.1       is        453: }
                    454:
                    455: void
                    456: iyreset(sc)
                    457: struct iy_softc *sc;
                    458: {
                    459:        int s;
1.29      mycroft   460:        s = splnet();
1.1       is        461:        iystop(sc);
                    462:        iyinit(sc);
                    463:        splx(s);
                    464: }
                    465:
                    466: void
                    467: iyinit(sc)
                    468: struct iy_softc *sc;
                    469: {
                    470:        int i;
                    471:        unsigned temp;
                    472:        struct ifnet *ifp;
1.9       thorpej   473:        bus_space_tag_t iot;
                    474:        bus_space_handle_t ioh;
1.6       is        475:
1.9       thorpej   476:        iot = sc->sc_iot;
1.6       is        477:        ioh = sc->sc_ioh;
1.1       is        478:
1.10      is        479:        ifp = &sc->sc_ethercom.ec_if;
1.1       is        480: #ifdef IYDEBUG
1.8       christos  481:        printf("ifp is %p\n", ifp);
1.1       is        482: #endif
                    483:
1.9       thorpej   484:        bus_space_write_1(iot, ioh, 0, BANK_SEL(2));
1.1       is        485:
1.9       thorpej   486:        temp = bus_space_read_1(iot, ioh, EEPROM_REG);
1.1       is        487:        if (temp & 0x10)
1.9       thorpej   488:                bus_space_write_1(iot, ioh, EEPROM_REG, temp & ~0x10);
1.1       is        489:
                    490:        for (i=0; i<6; ++i) {
1.10      is        491:                bus_space_write_1(iot, ioh, I_ADD(i), LLADDR(ifp->if_sadl)[i]);
1.1       is        492:        }
                    493:
1.9       thorpej   494:        temp = bus_space_read_1(iot, ioh, REG1);
1.10      is        495:        bus_space_write_1(iot, ioh, REG1,
1.49      is        496:            temp | /* XMT_CHAIN_INT | XMT_CHAIN_ERRSTOP | */ RCV_DISCARD_BAD);
1.1       is        497:
1.25      is        498:        if (ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI)) {
                    499:                temp = MATCH_ALL;
                    500:        } else
1.51      is        501:                temp = MATCH_BRDCST;
1.25      is        502:
                    503:        bus_space_write_1(iot, ioh, RECV_MODES_REG, temp);
1.26      is        504:
1.1       is        505: #ifdef IYDEBUG
1.42      tv        506:        {
                    507:                char sbuf[128];
                    508:
                    509:                bitmask_snprintf(temp, "\020\1PRMSC\2NOBRDST\3SEECRC\4LENGTH\5NOSaIns\6MultiIA",
                    510:                                 sbuf, sizeof(sbuf));
                    511:                printf("%s: RECV_MODES set to %s\n", sc->sc_dev.dv_xname, sbuf);
                    512:        }
1.1       is        513: #endif
1.26      is        514:        /* XXX VOODOO */
                    515:        temp = bus_space_read_1(iot, ioh, MEDIA_SELECT);
                    516:        bus_space_write_1(iot, ioh, MEDIA_SELECT, temp);
                    517:        /* XXX END OF VOODOO */
1.1       is        518:
                    519:
1.10      is        520:        delay(500000); /* for the hardware to test for the connector */
1.1       is        521:
1.9       thorpej   522:        temp = bus_space_read_1(iot, ioh, MEDIA_SELECT);
1.1       is        523: #ifdef IYDEBUG
1.42      tv        524:        {
                    525:                char sbuf[128];
                    526:
                    527:                bitmask_snprintf(temp, "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC",
                    528:                                 sbuf, sizeof(sbuf));
                    529:                printf("%s: media select was 0x%s ", sc->sc_dev.dv_xname, sbuf);
                    530:        }
1.1       is        531: #endif
1.5       is        532:        temp = (temp & TEST_MODE_MASK);
1.6       is        533:
1.18      bouyer    534:        switch(IFM_SUBTYPE(sc->iy_ifmedia.ifm_media)) {
                    535:        case IFM_10_5:
1.6       is        536:                temp &= ~ (BNC_BIT | TPE_BIT);
                    537:                break;
1.5       is        538:
1.18      bouyer    539:        case IFM_10_2:
1.10      is        540:                temp = (temp & ~TPE_BIT) | BNC_BIT;
1.6       is        541:                break;
                    542:
1.18      bouyer    543:        case IFM_10_T:
1.10      is        544:                temp = (temp & ~BNC_BIT) | TPE_BIT;
1.6       is        545:                break;
1.5       is        546:        default:
1.53      lukem     547:                ;
1.6       is        548:                /* nothing; leave as it is */
1.5       is        549:        }
1.18      bouyer    550:        switch (temp & (BNC_BIT | TPE_BIT)) {
                    551:        case BNC_BIT:
                    552:                sc->iy_media = IFM_ETHER | IFM_10_2;
                    553:                break;
                    554:        case TPE_BIT:
                    555:                sc->iy_media = IFM_ETHER | IFM_10_T;
                    556:                break;
                    557:        default:
                    558:                sc->iy_media = IFM_ETHER | IFM_10_5;
                    559:        }
1.6       is        560:
1.9       thorpej   561:        bus_space_write_1(iot, ioh, MEDIA_SELECT, temp);
1.1       is        562: #ifdef IYDEBUG
1.42      tv        563:        {
                    564:                char sbuf[128];
                    565:
                    566:                bitmask_snprintf(temp, "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC",
                    567:                                 sbuf, sizeof(sbuf));
                    568:                printf("changed to 0x%s\n", sbuf);
                    569:        }
1.1       is        570: #endif
                    571:
1.10      is        572:        bus_space_write_1(iot, ioh, 0, BANK_SEL(0));
                    573:        bus_space_write_1(iot, ioh, INT_MASK_REG, ALL_INTS);
1.9       thorpej   574:        bus_space_write_1(iot, ioh, 0, BANK_SEL(1));
1.1       is        575:
1.9       thorpej   576:        temp = bus_space_read_1(iot, ioh, INT_NO_REG);
                    577:        bus_space_write_1(iot, ioh, INT_NO_REG, (temp & 0xf8) | sc->mappedirq);
1.1       is        578:
                    579: #ifdef IYDEBUG
1.42      tv        580:        {
                    581:                char sbuf[128];
                    582:
                    583:                bitmask_snprintf(temp, "\020\4bad_irq\010flash/boot present",
                    584:                                 sbuf, sizeof(sbuf));
                    585:                printf("%s: int no was %s\n", sc->sc_dev.dv_xname, sbuf);
                    586:
                    587:                temp = bus_space_read_1(iot, ioh, INT_NO_REG);
                    588:                bitmask_snprintf(temp, "\020\4bad_irq\010flash/boot present",
                    589:                                 sbuf, sizeof(sbuf));
                    590:                printf("%s: int no now %s\n", sc->sc_dev.dv_xname, sbuf);
                    591:        }
1.1       is        592: #endif
                    593:
1.9       thorpej   594:        bus_space_write_1(iot, ioh, RCV_LOWER_LIMIT_REG, 0);
1.48      is        595:        bus_space_write_1(iot, ioh, RCV_UPPER_LIMIT_REG, (sc->rx_size -2) >>8);
                    596:        bus_space_write_1(iot, ioh, XMT_LOWER_LIMIT_REG, sc->rx_size >>8);
                    597:        bus_space_write_1(iot, ioh, XMT_UPPER_LIMIT_REG, (sc->sram - 2) >>8);
1.1       is        598:
1.9       thorpej   599:        temp = bus_space_read_1(iot, ioh, REG1);
1.1       is        600: #ifdef IYDEBUG
1.42      tv        601:        {
                    602:                char sbuf[128];
                    603:
                    604:                bitmask_snprintf(temp, "\020\2WORD_WIDTH\010INT_ENABLE",
                    605:                                 sbuf, sizeof(sbuf));
                    606:                printf("%s: HW access is %s\n", sc->sc_dev.dv_xname, sbuf);
                    607:        }
1.1       is        608: #endif
1.9       thorpej   609:        bus_space_write_1(iot, ioh, REG1, temp | INT_ENABLE); /* XXX what about WORD_WIDTH? */
1.1       is        610:
                    611: #ifdef IYDEBUG
1.42      tv        612:        {
                    613:                char sbuf[128];
                    614:
                    615:                temp = bus_space_read_1(iot, ioh, REG1);
                    616:                bitmask_snprintf(temp, "\020\2WORD_WIDTH\010INT_ENABLE",
                    617:                                 sbuf, sizeof(sbuf));
                    618:                printf("%s: HW access is %s\n", sc->sc_dev.dv_xname, sbuf);
                    619:        }
1.1       is        620: #endif
                    621:
1.9       thorpej   622:        bus_space_write_1(iot, ioh, 0, BANK_SEL(0));
1.1       is        623:
1.9       thorpej   624:        bus_space_write_1(iot, ioh, INT_MASK_REG, ALL_INTS & ~(RX_BIT|TX_BIT));
                    625:        bus_space_write_1(iot, ioh, STATUS_REG, ALL_INTS); /* clear ints */
1.1       is        626:
1.50      is        627:        bus_space_write_1(iot, ioh, RCV_COPY_THRESHOLD, 0);
                    628:
1.9       thorpej   629:        bus_space_write_2(iot, ioh, RCV_START_LOW, 0);
                    630:        bus_space_write_2(iot, ioh, RCV_STOP_LOW,  sc->rx_size - 2);
1.1       is        631:        sc->rx_start = 0;
                    632:
1.9       thorpej   633:        bus_space_write_1(iot, ioh, 0, SEL_RESET_CMD);
1.10      is        634:        delay(200);
1.1       is        635:
1.9       thorpej   636:        bus_space_write_2(iot, ioh, XMT_ADDR_REG, sc->rx_size);
1.1       is        637:
                    638:        sc->tx_start = sc->tx_end = sc->rx_size;
                    639:        sc->tx_last = 0;
                    640:
1.9       thorpej   641:        bus_space_write_1(iot, ioh, 0, RCV_ENABLE_CMD);
1.1       is        642:
                    643:        ifp->if_flags |= IFF_RUNNING;
                    644:        ifp->if_flags &= ~IFF_OACTIVE;
                    645: }
                    646:
                    647: void
                    648: iystart(ifp)
                    649: struct ifnet *ifp;
                    650: {
                    651:        struct iy_softc *sc;
1.6       is        652:
1.1       is        653:
                    654:        struct mbuf *m0, *m;
                    655:        u_int len, pad, last, end;
                    656:        u_int llen, residual;
                    657:        int avail;
                    658:        caddr_t data;
1.52      is        659:        unsigned temp;
1.1       is        660:        u_int16_t resval, stat;
1.9       thorpej   661:        bus_space_tag_t iot;
                    662:        bus_space_handle_t ioh;
1.1       is        663:
                    664: #ifdef IYDEBUG
1.8       christos  665:        printf("iystart called\n");
1.1       is        666: #endif
1.26      is        667:        sc = ifp->if_softc;
                    668:
1.1       is        669:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
                    670:                 return;
                    671:
1.52      is        672:        iy_intr_tx(sc);
                    673:
1.9       thorpej   674:        iot = sc->sc_iot;
1.6       is        675:        ioh = sc->sc_ioh;
1.1       is        676:
1.45      thorpej   677:        for (;;) {
                    678:                IFQ_POLL(&ifp->if_snd, m0);
                    679:                if (m0 == NULL)
                    680:                        break;
1.1       is        681: #ifdef IYDEBUG
1.8       christos  682:                printf("%s: trying to write another packet to the hardware\n",
1.1       is        683:                    sc->sc_dev.dv_xname);
                    684: #endif
                    685:
                    686:                /* We need to use m->m_pkthdr.len, so require the header */
                    687:                if ((m0->m_flags & M_PKTHDR) == 0)
                    688:                        panic("iystart: no header mbuf");
                    689:
                    690:                len = m0->m_pkthdr.len;
                    691:                pad = len & 1;
                    692:
                    693: #ifdef IYDEBUG
1.8       christos  694:                printf("%s: length is %d.\n", sc->sc_dev.dv_xname, len);
1.1       is        695: #endif
1.35      thorpej   696:                if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN)) {
                    697:                        pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len;
1.1       is        698:                }
                    699:
                    700:                if (len + pad > ETHER_MAX_LEN) {
                    701:                        /* packet is obviously too large: toss it */
                    702:                        ++ifp->if_oerrors;
                    703:                        IF_DEQUEUE(&ifp->if_snd, m0);
                    704:                        m_freem(m0);
                    705:                        continue;
                    706:                }
                    707:
                    708: #if NBPFILTER > 0
                    709:                if (ifp->if_bpf)
                    710:                        bpf_mtap(ifp->if_bpf, m0);
                    711: #endif
                    712:
                    713:                avail = sc->tx_start - sc->tx_end;
                    714:                if (avail <= 0)
                    715:                        avail += sc->tx_size;
                    716:
                    717: #ifdef IYDEBUG
1.8       christos  718:                printf("%s: avail is %d.\n", sc->sc_dev.dv_xname, avail);
1.1       is        719: #endif
                    720:                /*
                    721:                 * we MUST RUN at splnet here  ---
                    722:                 * XXX todo: or even turn off the boards ints ??? hm...
                    723:                 */
                    724:
                    725:                        /* See if there is room to put another packet in the buffer. */
                    726:
                    727:                if ((len+pad+2*I595_XMT_HDRLEN) > avail) {
1.20      is        728: #ifdef IYDEBUG
1.8       christos  729:                        printf("%s: len = %d, avail = %d, setting OACTIVE\n",
1.1       is        730:                            sc->sc_dev.dv_xname, len, avail);
1.20      is        731: #endif
1.52      is        732:                        /* mark interface as full ... */
1.1       is        733:                        ifp->if_flags |= IFF_OACTIVE;
1.52      is        734:
                    735:                        /* and wait for any transmission result */
                    736:                        bus_space_write_1(iot, ioh, 0, BANK_SEL(2));
                    737:
                    738:                        temp = bus_space_read_1(iot, ioh, REG1);
                    739:                        bus_space_write_1(iot, ioh, REG1,
                    740:                                temp & ~XMT_CHAIN_INT);
                    741:
                    742:                        bus_space_write_1(iot, ioh, 0, BANK_SEL(0));
                    743:
1.1       is        744:                        return;
                    745:                }
                    746:
                    747:                /* we know it fits in the hardware now, so dequeue it */
1.45      thorpej   748:                IFQ_DEQUEUE(&ifp->if_snd, m0);
1.1       is        749:
                    750:                last = sc->tx_end;
                    751:                end = last + pad + len + I595_XMT_HDRLEN;
                    752:
                    753:                if (end >= sc->sram) {
                    754:                        if ((sc->sram - last) <= I595_XMT_HDRLEN) {
                    755:                                /* keep header in one piece */
                    756:                                last = sc->rx_size;
                    757:                                end = last + pad + len + I595_XMT_HDRLEN;
                    758:                        } else
                    759:                                end -= sc->tx_size;
                    760:                }
                    761:
1.9       thorpej   762:                bus_space_write_2(iot, ioh, HOST_ADDR_REG, last);
1.41      is        763:                bus_space_write_stream_2(iot, ioh, MEM_PORT_REG,
                    764:                        htole16(XMT_CMD));
                    765:
1.9       thorpej   766:                bus_space_write_2(iot, ioh, MEM_PORT_REG, 0);
                    767:                bus_space_write_2(iot, ioh, MEM_PORT_REG, 0);
1.41      is        768:
                    769:                bus_space_write_stream_2(iot, ioh, MEM_PORT_REG,
                    770:                        htole16(len + pad));
1.1       is        771:
                    772:                residual = resval = 0;
                    773:
                    774:                while ((m = m0)!=0) {
                    775:                        data = mtod(m, caddr_t);
                    776:                        llen = m->m_len;
                    777:                        if (residual) {
                    778: #ifdef IYDEBUG
1.8       christos  779:                                printf("%s: merging residual with next mbuf.\n",
1.1       is        780:                                    sc->sc_dev.dv_xname);
                    781: #endif
                    782:                                resval |= *data << 8;
1.41      is        783:                                bus_space_write_stream_2(iot, ioh,
                    784:                                        MEM_PORT_REG, resval);
1.1       is        785:                                --llen;
                    786:                                ++data;
                    787:                        }
                    788:                        if (llen > 1)
1.41      is        789:                                bus_space_write_multi_stream_2(iot, ioh,
                    790:                                        MEM_PORT_REG, data, llen>>1);
1.1       is        791:                        residual = llen & 1;
                    792:                        if (residual) {
                    793:                                resval = *(data + llen - 1);
                    794: #ifdef IYDEBUG
1.8       christos  795:                                printf("%s: got odd mbuf to send.\n",
1.1       is        796:                                    sc->sc_dev.dv_xname);
                    797: #endif
                    798:                        }
                    799:
                    800:                        MFREE(m, m0);
                    801:                }
                    802:
                    803:                if (residual)
1.41      is        804:                        bus_space_write_stream_2(iot, ioh, MEM_PORT_REG,
                    805:                                resval);
1.1       is        806:
                    807:                pad >>= 1;
                    808:                while (pad-- > 0)
1.41      is        809:                        bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, 0);
1.1       is        810:
                    811: #ifdef IYDEBUG
1.8       christos  812:                printf("%s: new last = 0x%x, end = 0x%x.\n",
1.1       is        813:                    sc->sc_dev.dv_xname, last, end);
1.8       christos  814:                printf("%s: old start = 0x%x, end = 0x%x, last = 0x%x\n",
1.1       is        815:                    sc->sc_dev.dv_xname, sc->tx_start, sc->tx_end, sc->tx_last);
                    816: #endif
                    817:
                    818:                if (sc->tx_start != sc->tx_end) {
1.41      is        819:                        bus_space_write_2(iot, ioh, HOST_ADDR_REG,
                    820:                                sc->tx_last + XMT_COUNT);
1.1       is        821:
1.41      is        822:                        /*
                    823:                         * XXX We keep stat in le order, to potentially save
                    824:                         * a byte swap.
                    825:                         */
                    826:                        stat = bus_space_read_stream_2(iot, ioh, MEM_PORT_REG);
                    827:
                    828:                        bus_space_write_2(iot, ioh, HOST_ADDR_REG,
                    829:                                sc->tx_last + XMT_CHAIN);
                    830:
                    831:                        bus_space_write_stream_2(iot, ioh, MEM_PORT_REG,
                    832:                                htole16(last));
                    833:
                    834:                        bus_space_write_stream_2(iot, ioh, MEM_PORT_REG,
                    835:                                stat | htole16(CHAIN));
1.1       is        836: #ifdef IYDEBUG
1.8       christos  837:                        printf("%s: setting 0x%x to 0x%x\n",
1.1       is        838:                            sc->sc_dev.dv_xname, sc->tx_last + XMT_COUNT,
1.41      is        839:                            le16toh(stat) | CHAIN);
1.1       is        840: #endif
                    841:                }
1.9       thorpej   842:                stat = bus_space_read_2(iot, ioh, MEM_PORT_REG); /* dummy read */
1.1       is        843:
                    844:                /* XXX todo: enable ints here if disabled */
                    845:
                    846:                ++ifp->if_opackets;
                    847:
                    848:                if (sc->tx_start == sc->tx_end) {
1.9       thorpej   849:                        bus_space_write_2(iot, ioh, XMT_ADDR_REG, last);
                    850:                        bus_space_write_1(iot, ioh, 0, XMT_CMD);
1.1       is        851:                        sc->tx_start = last;
                    852: #ifdef IYDEBUG
1.8       christos  853:                        printf("%s: writing 0x%x to XAR and giving XCMD\n",
1.1       is        854:                            sc->sc_dev.dv_xname, last);
                    855: #endif
                    856:                } else {
1.9       thorpej   857:                        bus_space_write_1(iot, ioh, 0, RESUME_XMT_CMD);
1.1       is        858: #ifdef IYDEBUG
1.8       christos  859:                        printf("%s: giving RESUME_XCMD\n",
1.1       is        860:                            sc->sc_dev.dv_xname);
                    861: #endif
                    862:                }
                    863:                sc->tx_last = last;
                    864:                sc->tx_end = end;
                    865:        }
1.52      is        866:        /* and wait only for end of transmission chain */
                    867:        bus_space_write_1(iot, ioh, 0, BANK_SEL(2));
                    868:
                    869:        temp = bus_space_read_1(iot, ioh, REG1);
                    870:        bus_space_write_1(iot, ioh, REG1, temp | XMT_CHAIN_INT);
                    871:
                    872:        bus_space_write_1(iot, ioh, 0, BANK_SEL(0));
1.1       is        873: }
                    874:
                    875:
                    876: static __inline void
1.10      is        877: eepromwritebit(iot, ioh, what)
1.9       thorpej   878:        bus_space_tag_t iot;
                    879:        bus_space_handle_t ioh;
1.6       is        880:        int what;
1.1       is        881: {
1.10      is        882:        bus_space_write_1(iot, ioh, EEPROM_REG, what);
1.1       is        883:        delay(1);
1.10      is        884:        bus_space_write_1(iot, ioh, EEPROM_REG, what|EESK);
1.1       is        885:        delay(1);
1.10      is        886:        bus_space_write_1(iot, ioh, EEPROM_REG, what);
1.1       is        887:        delay(1);
                    888: }
                    889:
                    890: static __inline int
1.10      is        891: eepromreadbit(iot, ioh)
1.9       thorpej   892:        bus_space_tag_t iot;
                    893:        bus_space_handle_t ioh;
1.1       is        894: {
                    895:        int b;
                    896:
1.10      is        897:        bus_space_write_1(iot, ioh, EEPROM_REG, EECS|EESK);
1.1       is        898:        delay(1);
1.10      is        899:        b = bus_space_read_1(iot, ioh, EEPROM_REG);
                    900:        bus_space_write_1(iot, ioh, EEPROM_REG, EECS);
1.1       is        901:        delay(1);
                    902:
                    903:        return ((b & EEDO) != 0);
                    904: }
                    905:
                    906: static u_int16_t
1.10      is        907: eepromread(iot, ioh, offset)
1.9       thorpej   908:        bus_space_tag_t iot;
                    909:        bus_space_handle_t ioh;
1.6       is        910:        int offset;
1.1       is        911: {
                    912:        volatile int i;
                    913:        volatile int j;
                    914:        volatile u_int16_t readval;
                    915:
1.9       thorpej   916:        bus_space_write_1(iot, ioh, 0, BANK_SEL(2));
1.1       is        917:        delay(1);
1.10      is        918:        bus_space_write_1(iot, ioh, EEPROM_REG, EECS); /* XXXX??? */
1.1       is        919:        delay(1);
                    920:
1.10      is        921:        eepromwritebit(iot, ioh, EECS|EEDI);
                    922:        eepromwritebit(iot, ioh, EECS|EEDI);
                    923:        eepromwritebit(iot, ioh, EECS);
1.1       is        924:
                    925:        for (j=5; j>=0; --j) {
                    926:                if ((offset>>j) & 1)
1.10      is        927:                        eepromwritebit(iot, ioh, EECS|EEDI);
1.1       is        928:                else
1.10      is        929:                        eepromwritebit(iot, ioh, EECS);
1.1       is        930:        }
                    931:
                    932:        for (readval=0, i=0; i<16; ++i) {
                    933:                readval<<=1;
1.10      is        934:                readval |= eepromreadbit(iot, ioh);
1.1       is        935:        }
                    936:
1.10      is        937:        bus_space_write_1(iot, ioh, EEPROM_REG, 0|EESK);
1.1       is        938:        delay(1);
1.10      is        939:        bus_space_write_1(iot, ioh, EEPROM_REG, 0);
1.1       is        940:
1.10      is        941:        bus_space_write_1(iot, ioh, COMMAND_REG, BANK_SEL(0));
1.1       is        942:
                    943:        return readval;
                    944: }
                    945:
                    946: /*
                    947:  * Device timeout/watchdog routine.  Entered if the device neglects to generate
                    948:  * an interrupt after a transmit has been started on it.
                    949:  */
                    950: void
1.2       thorpej   951: iywatchdog(ifp)
1.3       is        952:        struct ifnet *ifp;
1.1       is        953: {
1.2       thorpej   954:        struct iy_softc *sc = ifp->if_softc;
1.1       is        955:
                    956:        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
1.10      is        957:        ++sc->sc_ethercom.ec_if.if_oerrors;
1.1       is        958:        iyreset(sc);
                    959: }
                    960:
                    961: /*
                    962:  * What to do upon receipt of an interrupt.
                    963:  */
                    964: int
                    965: iyintr(arg)
                    966:        void *arg;
                    967: {
1.52      is        968:        struct iy_softc *sc;
                    969:        struct ifnet *ifp;
1.9       thorpej   970:        bus_space_tag_t iot;
                    971:        bus_space_handle_t ioh;
1.6       is        972:
1.36      augustss  973:        u_short status;
1.1       is        974:
1.52      is        975:        sc = arg;
1.9       thorpej   976:        iot = sc->sc_iot;
1.6       is        977:        ioh = sc->sc_ioh;
                    978:
1.52      is        979:        ifp = &sc->sc_ethercom.ec_if;
                    980:
1.9       thorpej   981:        status = bus_space_read_1(iot, ioh, STATUS_REG);
1.1       is        982: #ifdef IYDEBUG
                    983:        if (status & ALL_INTS) {
1.42      tv        984:                char sbuf[128];
                    985:
                    986:                bitmask_snprintf(status, "\020\1RX_STP\2RX\3TX\4EXEC",
                    987:                                 sbuf, sizeof(sbuf));
                    988:                printf("%s: got interupt %s", sc->sc_dev.dv_xname, sbuf);
                    989:
                    990:                if (status & EXEC_INT) {
                    991:                        bitmask_snprintf(bus_space_read_1(iot, ioh, 0),
                    992:                                         "\020\6ABORT", sbuf, sizeof(sbuf));
                    993:                        printf(" event %s\n", sbuf);
                    994:                } else
1.8       christos  995:                        printf("\n");
1.1       is        996:        }
                    997: #endif
1.26      is        998:        if ((status & (RX_INT | TX_INT)) == 0)
1.1       is        999:                return 0;
                   1000:
                   1001:        if (status & RX_INT) {
                   1002:                iy_intr_rx(sc);
1.9       thorpej  1003:                bus_space_write_1(iot, ioh, STATUS_REG, RX_INT);
1.26      is       1004:        }
                   1005:        if (status & TX_INT) {
1.52      is       1006:                /* Tell feeders we may be able to accept more data... */
                   1007:                ifp->if_flags &= ~IFF_OACTIVE;
                   1008:                /* and get more data. */
                   1009:                iystart(ifp);
1.9       thorpej  1010:                bus_space_write_1(iot, ioh, STATUS_REG, TX_INT);
1.1       is       1011:        }
1.14      explorer 1012:
                   1013: #if NRND > 0
                   1014:        rnd_add_uint32(&sc->rnd_source, status);
                   1015: #endif
                   1016:
1.1       is       1017:        return 1;
                   1018: }
                   1019:
                   1020: void
1.9       thorpej  1021: iyget(sc, iot, ioh, rxlen)
1.6       is       1022:        struct iy_softc *sc;
1.9       thorpej  1023:        bus_space_tag_t iot;
                   1024:        bus_space_handle_t ioh;
1.6       is       1025:        int rxlen;
1.1       is       1026: {
                   1027:        struct mbuf *m, *top, **mp;
                   1028:        struct ifnet *ifp;
                   1029:        int len;
                   1030:
1.10      is       1031:        ifp = &sc->sc_ethercom.ec_if;
1.1       is       1032:
1.13      mycroft  1033:        MGETHDR(m, M_DONTWAIT, MT_DATA);
                   1034:        if (m == 0)
                   1035:                goto dropped;
1.1       is       1036:        m->m_pkthdr.rcvif = ifp;
                   1037:        m->m_pkthdr.len = rxlen;
                   1038:        len = MHLEN;
                   1039:        top = 0;
                   1040:        mp = &top;
                   1041:
                   1042:        while (rxlen > 0) {
                   1043:                if (top) {
1.13      mycroft  1044:                        MGET(m, M_DONTWAIT, MT_DATA);
1.1       is       1045:                        if (m == 0) {
1.13      mycroft  1046:                                m_freem(top);
                   1047:                                goto dropped;
1.1       is       1048:                        }
                   1049:                        len = MLEN;
                   1050:                }
                   1051:                if (rxlen >= MINCLSIZE) {
                   1052:                        MCLGET(m, M_DONTWAIT);
1.12      mycroft  1053:                        if ((m->m_flags & M_EXT) == 0) {
1.13      mycroft  1054:                                m_free(m);
1.11      mycroft  1055:                                m_freem(top);
                   1056:                                goto dropped;
                   1057:                        }
                   1058:                        len = MCLBYTES;
1.1       is       1059:                }
                   1060:                len = min(rxlen, len);
                   1061:                if (len > 1) {
                   1062:                        len &= ~1;
1.6       is       1063:
1.41      is       1064:                        bus_space_read_multi_stream_2(iot, ioh, MEM_PORT_REG,
1.6       is       1065:                            mtod(m, caddr_t), len/2);
1.1       is       1066:                } else {
                   1067: #ifdef IYDEBUG
1.8       christos 1068:                        printf("%s: received odd mbuf\n", sc->sc_dev.dv_xname);
1.1       is       1069: #endif
1.41      is       1070:                        *(mtod(m, caddr_t)) = bus_space_read_stream_2(iot, ioh,
1.6       is       1071:                            MEM_PORT_REG);
1.1       is       1072:                }
                   1073:                m->m_len = len;
                   1074:                rxlen -= len;
                   1075:                *mp = m;
                   1076:                mp = &m->m_next;
                   1077:        }
                   1078:        /* XXX receive the top here */
                   1079:        ++ifp->if_ipackets;
                   1080:
                   1081: #if NBPFILTER > 0
1.43      thorpej  1082:        if (ifp->if_bpf)
1.1       is       1083:                bpf_mtap(ifp->if_bpf, top);
                   1084: #endif
1.34      thorpej  1085:        (*ifp->if_input)(ifp, top);
1.1       is       1086:        return;
                   1087:
                   1088: dropped:
                   1089:        ++ifp->if_ierrors;
                   1090:        return;
                   1091: }
1.26      is       1092:
1.1       is       1093: void
                   1094: iy_intr_rx(sc)
                   1095: struct iy_softc *sc;
                   1096: {
                   1097:        struct ifnet *ifp;
1.9       thorpej  1098:        bus_space_tag_t iot;
                   1099:        bus_space_handle_t ioh;
1.6       is       1100:
1.1       is       1101:        u_int rxadrs, rxevnt, rxstatus, rxnext, rxlen;
                   1102:
1.9       thorpej  1103:        iot = sc->sc_iot;
1.6       is       1104:        ioh = sc->sc_ioh;
1.10      is       1105:        ifp = &sc->sc_ethercom.ec_if;
1.1       is       1106:
                   1107:        rxadrs = sc->rx_start;
1.9       thorpej  1108:        bus_space_write_2(iot, ioh, HOST_ADDR_REG, rxadrs);
1.41      is       1109:        rxevnt = le16toh(bus_space_read_stream_2(iot, ioh, MEM_PORT_REG));
1.1       is       1110:        rxnext = 0;
                   1111:
                   1112:        while (rxevnt == RCV_DONE) {
1.41      is       1113:                rxstatus = le16toh(bus_space_read_stream_2(iot, ioh,
                   1114:                                MEM_PORT_REG));
                   1115:                rxnext = le16toh(bus_space_read_stream_2(iot, ioh,
                   1116:                                MEM_PORT_REG));
                   1117:                rxlen = le16toh(bus_space_read_stream_2(iot, ioh,
                   1118:                                MEM_PORT_REG));
1.1       is       1119: #ifdef IYDEBUG
1.42      tv       1120:                {
                   1121:                        char sbuf[128];
                   1122:
                   1123:                        bitmask_snprintf(rxstatus, "\020\1RCLD\2IA_MCH\010SHORT\011OVRN\013ALGERR\014CRCERR\015LENERR\016RCVOK\020TYP",
                   1124:                                         sbuf, sizeof(sbuf));
                   1125:                        printf("%s: pck at 0x%04x stat %s next 0x%x len 0x%x\n",
                   1126:                            sc->sc_dev.dv_xname, rxadrs, sbuf, rxnext, rxlen);
                   1127:                }
1.1       is       1128: #endif
1.9       thorpej  1129:                iyget(sc, iot, ioh, rxlen);
1.1       is       1130:
                   1131:                /* move stop address */
1.9       thorpej  1132:                bus_space_write_2(iot, ioh, RCV_STOP_LOW,
1.1       is       1133:                            rxnext == 0 ? sc->rx_size - 2 : rxnext - 2);
                   1134:
1.9       thorpej  1135:                bus_space_write_2(iot, ioh, HOST_ADDR_REG, rxnext);
1.1       is       1136:                rxadrs = rxnext;
1.41      is       1137:                rxevnt = le16toh(bus_space_read_stream_2(iot, ioh,
                   1138:                                MEM_PORT_REG));
1.1       is       1139:        }
                   1140:        sc->rx_start = rxnext;
                   1141: }
                   1142:
                   1143: void
                   1144: iy_intr_tx(sc)
                   1145: struct iy_softc *sc;
                   1146: {
1.9       thorpej  1147:        bus_space_tag_t iot;
                   1148:        bus_space_handle_t ioh;
1.1       is       1149:        struct ifnet *ifp;
                   1150:        u_int txstatus, txstat2, txlen, txnext;
                   1151:
1.10      is       1152:        ifp = &sc->sc_ethercom.ec_if;
1.9       thorpej  1153:        iot = sc->sc_iot;
1.6       is       1154:        ioh = sc->sc_ioh;
                   1155:
1.1       is       1156:        while (sc->tx_start != sc->tx_end) {
1.9       thorpej  1157:                bus_space_write_2(iot, ioh, HOST_ADDR_REG, sc->tx_start);
1.41      is       1158:                txstatus = le16toh(bus_space_read_stream_2(iot, ioh,
                   1159:                        MEM_PORT_REG));
                   1160:
1.1       is       1161:                if ((txstatus & (TX_DONE|CMD_MASK)) != (TX_DONE|XMT_CMD))
                   1162:                        break;
                   1163:
1.41      is       1164:                txstat2 = le16toh(bus_space_read_stream_2(iot, ioh,
                   1165:                                MEM_PORT_REG));
                   1166:                txnext = le16toh(bus_space_read_stream_2(iot, ioh,
                   1167:                                MEM_PORT_REG));
                   1168:                txlen = le16toh(bus_space_read_stream_2(iot, ioh,
                   1169:                                MEM_PORT_REG));
1.1       is       1170: #ifdef IYDEBUG
1.42      tv       1171:                {
                   1172:                        char sbuf[128];
                   1173:
                   1174:                        bitmask_snprintf(txstat2, "\020\6MAX_COL\7HRT_BEAT\010TX_DEF\011UND_RUN\012JERR\013LST_CRS\014LTCOL\016TX_OK\020COLL",
                   1175:                                         sbuf, sizeof(sbuf));
                   1176:                        printf("txstat 0x%x stat2 0x%s next 0x%x len 0x%x\n",
                   1177:                               txstatus, sbuf, txnext, txlen);
                   1178:                }
1.1       is       1179: #endif
                   1180:                if (txlen & CHAIN)
                   1181:                        sc->tx_start = txnext;
                   1182:                else
                   1183:                        sc->tx_start = sc->tx_end;
                   1184:                ifp->if_flags &= ~IFF_OACTIVE;
                   1185:
1.47      is       1186:                if (txstat2 & 0x0020)
                   1187:                        ifp->if_collisions += 16;
                   1188:                else
                   1189:                        ifp->if_collisions += txstat2 & 0x000f;
                   1190:
1.49      is       1191:                if ((txstat2 & 0x2000) == 0)
1.1       is       1192:                        ++ifp->if_oerrors;
                   1193:        }
                   1194: }
                   1195:
                   1196: int
                   1197: iyioctl(ifp, cmd, data)
1.36      augustss 1198:        struct ifnet *ifp;
1.1       is       1199:        u_long cmd;
                   1200:        caddr_t data;
                   1201: {
                   1202:        struct iy_softc *sc;
                   1203:        struct ifaddr *ifa;
                   1204:        struct ifreq *ifr;
                   1205:        int s, error = 0;
                   1206:
1.2       thorpej  1207:        sc = ifp->if_softc;
1.1       is       1208:        ifa = (struct ifaddr *)data;
                   1209:        ifr = (struct ifreq *)data;
                   1210:
                   1211: #ifdef IYDEBUG
1.42      tv       1212:        printf("iyioctl called with ifp 0x%p (%s) cmd 0x%lx data 0x%p\n",
1.2       thorpej  1213:            ifp, ifp->if_xname, cmd, data);
1.1       is       1214: #endif
                   1215:
1.29      mycroft  1216:        s = splnet();
1.1       is       1217:
                   1218:        switch (cmd) {
                   1219:
                   1220:        case SIOCSIFADDR:
                   1221:                ifp->if_flags |= IFF_UP;
                   1222:
                   1223:                switch (ifa->ifa_addr->sa_family) {
                   1224: #ifdef INET
                   1225:                case AF_INET:
                   1226:                        iyinit(sc);
1.10      is       1227:                        arp_ifinit(ifp, ifa);
1.1       is       1228:                        break;
                   1229: #endif
                   1230: #ifdef NS
                   1231:                /* XXX - This code is probably wrong. */
                   1232:                case AF_NS:
                   1233:                    {
                   1234:                        struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
                   1235:
                   1236:                        if (ns_nullhost(*ina))
1.10      is       1237:                                ina->x_host = *(union ns_host *)
1.38      is       1238:                                    LLADDR(ifp->if_sadl);
1.1       is       1239:                        else
1.53.2.1  lukem    1240:                                memcpy(LLADDR(ifp->if_sadl), ina->x_host.c_host,
1.10      is       1241:                                    ETHER_ADDR_LEN);
1.1       is       1242:                        /* Set new address. */
                   1243:                        iyinit(sc);
                   1244:                        break;
                   1245:                    }
                   1246: #endif /* NS */
                   1247:                default:
                   1248:                        iyinit(sc);
                   1249:                        break;
                   1250:                }
                   1251:                break;
                   1252:
                   1253:        case SIOCSIFFLAGS:
                   1254:                sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
                   1255:                if ((ifp->if_flags & IFF_UP) == 0 &&
                   1256:                    (ifp->if_flags & IFF_RUNNING) != 0) {
                   1257:                        /*
                   1258:                         * If interface is marked down and it is running, then
                   1259:                         * stop it.
                   1260:                         */
                   1261:                        iystop(sc);
                   1262:                        ifp->if_flags &= ~IFF_RUNNING;
                   1263:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
                   1264:                           (ifp->if_flags & IFF_RUNNING) == 0) {
                   1265:                        /*
                   1266:                         * If interface is marked up and it is stopped, then
                   1267:                         * start it.
                   1268:                         */
                   1269:                        iyinit(sc);
                   1270:                } else {
                   1271:                        /*
                   1272:                         * Reset the interface to pick up changes in any other
                   1273:                         * flags that affect hardware registers.
                   1274:                         */
                   1275:                        iystop(sc);
                   1276:                        iyinit(sc);
                   1277:                }
                   1278: #ifdef IYDEBUGX
                   1279:                if (ifp->if_flags & IFF_DEBUG)
                   1280:                        sc->sc_debug = IFY_ALL;
                   1281:                else
                   1282:                        sc->sc_debug = 0;
                   1283: #endif
                   1284:                break;
                   1285:
                   1286:        case SIOCADDMULTI:
                   1287:        case SIOCDELMULTI:
                   1288:                error = (cmd == SIOCADDMULTI) ?
1.10      is       1289:                    ether_addmulti(ifr, &sc->sc_ethercom):
                   1290:                    ether_delmulti(ifr, &sc->sc_ethercom);
1.1       is       1291:
                   1292:                if (error == ENETRESET) {
                   1293:                        /*
                   1294:                         * Multicast list has changed; set the hardware filter
                   1295:                         * accordingly.
                   1296:                         */
1.26      is       1297:                        iyreset(sc); /* XXX can't make it work otherwise */
                   1298:                        iy_mc_reset(sc);
1.1       is       1299:                        error = 0;
                   1300:                }
                   1301:                break;
1.28      rvb      1302:
1.18      bouyer   1303:        case SIOCSIFMEDIA:
                   1304:        case SIOCGIFMEDIA:
                   1305:                error = ifmedia_ioctl(ifp, ifr, &sc->iy_ifmedia, cmd);
                   1306:                break;
1.1       is       1307:        default:
                   1308:                error = EINVAL;
                   1309:        }
                   1310:        splx(s);
                   1311:        return error;
1.18      bouyer   1312: }
                   1313:
                   1314: int
                   1315: iy_mediachange(ifp)
                   1316:        struct ifnet *ifp;
                   1317: {
                   1318:        struct iy_softc *sc = ifp->if_softc;
                   1319:
                   1320:        if (IFM_TYPE(sc->iy_ifmedia.ifm_media) != IFM_ETHER)
                   1321:            return EINVAL;
                   1322:        switch(IFM_SUBTYPE(sc->iy_ifmedia.ifm_media)) {
                   1323:        case IFM_10_5:
                   1324:        case IFM_10_2:
                   1325:        case IFM_10_T:
                   1326:        case IFM_AUTO:
                   1327:            iystop(sc);
                   1328:            iyinit(sc);
                   1329:            return 0;
                   1330:        default:
                   1331:            return EINVAL;
                   1332:        }
                   1333: }
                   1334:
                   1335: void
                   1336: iy_mediastatus(ifp, ifmr)
                   1337:        struct ifnet *ifp;
                   1338:        struct ifmediareq *ifmr;
                   1339: {
                   1340:        struct iy_softc *sc = ifp->if_softc;
                   1341:
                   1342:        ifmr->ifm_active = sc->iy_media;
                   1343:        ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE;
1.1       is       1344: }
                   1345:
1.26      is       1346:
                   1347: static void
                   1348: iy_mc_setup(sc)
                   1349:        struct iy_softc *sc;
                   1350: {
                   1351:        struct ether_multi *enm;
                   1352:        struct ether_multistep step;
                   1353:        struct ethercom *ecp;
                   1354:        struct ifnet *ifp;
                   1355:        bus_space_tag_t iot;
                   1356:        bus_space_handle_t ioh;
                   1357:        int avail, last /*, end*/ , len;
                   1358:        int timeout;
1.40      is       1359:        volatile u_int16_t dum;
1.26      is       1360:        u_int8_t temp;
                   1361:
                   1362:
                   1363:        ecp = &sc->sc_ethercom;
                   1364:        ifp = &ecp->ec_if;
                   1365:
                   1366:        iot = sc->sc_iot;
                   1367:        ioh = sc->sc_ioh;
                   1368:
1.50      is       1369:        len = 6 * ecp->ec_multicnt;
1.26      is       1370:
                   1371:        avail = sc->tx_start - sc->tx_end;
                   1372:        if (avail <= 0)
                   1373:                avail += sc->tx_size;
1.37      is       1374:        if (ifp->if_flags & IFF_DEBUG)
                   1375:                printf("%s: iy_mc_setup called, %d addresses, "
                   1376:                    "%d/%d bytes needed/avail\n", ifp->if_xname,
                   1377:                    ecp->ec_multicnt, len + I595_XMT_HDRLEN, avail);
1.26      is       1378:
                   1379:        last = sc->rx_size;
                   1380:
                   1381:        bus_space_write_1(iot, ioh, 0, BANK_SEL(2));
1.51      is       1382:        bus_space_write_1(iot, ioh, RECV_MODES_REG, MATCH_BRDCST);
1.26      is       1383:        /* XXX VOODOO */
                   1384:        temp = bus_space_read_1(iot, ioh, MEDIA_SELECT);
                   1385:        bus_space_write_1(iot, ioh, MEDIA_SELECT, temp);
                   1386:        /* XXX END OF VOODOO */
                   1387:        bus_space_write_1(iot, ioh, 0, BANK_SEL(0));
                   1388:        bus_space_write_2(iot, ioh, HOST_ADDR_REG, last);
1.41      is       1389:        bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, htole16(MC_SETUP_CMD));
1.26      is       1390:        bus_space_write_2(iot, ioh, MEM_PORT_REG, 0);
                   1391:        bus_space_write_2(iot, ioh, MEM_PORT_REG, 0);
1.41      is       1392:        bus_space_write_stream_2(iot, ioh, MEM_PORT_REG, htole16(len));
1.26      is       1393:
                   1394:        ETHER_FIRST_MULTI(step, ecp, enm);
                   1395:        while(enm) {
1.41      is       1396:                bus_space_write_multi_stream_2(iot, ioh, MEM_PORT_REG,
1.26      is       1397:                    enm->enm_addrlo, 3);
                   1398:
                   1399:                ETHER_NEXT_MULTI(step, enm);
                   1400:        }
1.40      is       1401:        dum = bus_space_read_2(iot, ioh, MEM_PORT_REG); /* dummy read */
1.26      is       1402:        bus_space_write_2(iot, ioh, XMT_ADDR_REG, last);
                   1403:        bus_space_write_1(iot, ioh, 0, MC_SETUP_CMD);
                   1404:
                   1405:
                   1406:        sc->tx_start =  sc->rx_size;
                   1407:        sc->tx_end = sc->rx_size + I595_XMT_HDRLEN + len;
                   1408:
                   1409:        for (timeout=0; timeout<100; timeout++) {
                   1410:                DELAY(2);
                   1411:                if ((bus_space_read_1(iot, ioh, STATUS_REG) & EXEC_INT) == 0)
                   1412:                        continue;
                   1413:
                   1414:                temp = bus_space_read_1(iot, ioh, 0);
                   1415:                bus_space_write_1(iot, ioh, STATUS_REG, EXEC_INT);
                   1416: #ifdef DIAGNOSTIC
                   1417:                if (temp & 0x20) {
                   1418:                        printf("%s: mc setup failed, %d usec\n",
                   1419:                            sc->sc_dev.dv_xname, timeout * 2);
1.37      is       1420:                } else if (((temp & 0x0f) == 0x03) &&
                   1421:                            (ifp->if_flags & IFF_DEBUG)) {
1.26      is       1422:                                printf("%s: mc setup done, %d usec\n",
                   1423:                            sc->sc_dev.dv_xname, timeout * 2);
                   1424:                }
                   1425: #endif
                   1426:                break;
                   1427:        }
                   1428:        sc->tx_start = sc->tx_end;
1.38      is       1429:        ifp->if_flags &= ~IFF_OACTIVE;
1.26      is       1430:
                   1431: }
                   1432:
1.1       is       1433: static void
                   1434: iy_mc_reset(sc)
                   1435:        struct iy_softc *sc;
                   1436: {
                   1437:        struct ether_multi *enm;
                   1438:        struct ether_multistep step;
1.25      is       1439:        struct ethercom *ecp;
                   1440:        struct ifnet *ifp;
1.26      is       1441:        bus_space_tag_t iot;
                   1442:        bus_space_handle_t ioh;
                   1443:        u_int16_t temp;
1.25      is       1444:
                   1445:        ecp = &sc->sc_ethercom;
                   1446:        ifp = &ecp->ec_if;
1.1       is       1447:
1.26      is       1448:        iot = sc->sc_iot;
                   1449:        ioh = sc->sc_ioh;
                   1450:
1.25      is       1451:        if (ecp->ec_multicnt > 63) {
1.26      is       1452:                ifp->if_flags |= IFF_ALLMULTI;
1.25      is       1453:
1.26      is       1454:        } else if (ecp->ec_multicnt > 0) {
1.25      is       1455:                /*
                   1456:                 * Step through the list of addresses.
                   1457:                 */
                   1458:                ETHER_FIRST_MULTI(step, ecp, enm);
                   1459:                while(enm) {
1.53.2.1  lukem    1460:                        if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
1.26      is       1461:                                ifp->if_flags |= IFF_ALLMULTI;
                   1462:                                goto setupmulti;
1.25      is       1463:                        }
                   1464:                        ETHER_NEXT_MULTI(step, enm);
                   1465:                }
                   1466:                /* OK, we really need to do it now: */
1.26      is       1467: #if 0
                   1468:                if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE))
                   1469:                    != IFF_RUNNING) {
                   1470:                        ifp->if_flags |= IFF_OACTIVE;
                   1471:                        sc->want_mc_setup = 1;
                   1472:                        return;
1.25      is       1473:                }
1.26      is       1474: #endif
                   1475:                iy_mc_setup(sc);
1.25      is       1476:        } else {
1.26      is       1477:                ifp->if_flags &= ~IFF_ALLMULTI;
1.1       is       1478:        }
1.25      is       1479:
1.26      is       1480: setupmulti:
                   1481:        bus_space_write_1(iot, ioh, 0, BANK_SEL(2));
                   1482:        if (ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI)) {
                   1483:                temp = MATCH_ALL;
                   1484:        } else
1.51      is       1485:                temp = MATCH_BRDCST;
1.26      is       1486:
                   1487:        bus_space_write_1(iot, ioh, RECV_MODES_REG, temp);
                   1488:        /* XXX VOODOO */
                   1489:        temp = bus_space_read_1(iot, ioh, MEDIA_SELECT);
                   1490:        bus_space_write_1(iot, ioh, MEDIA_SELECT, temp);
                   1491:        /* XXX END OF VOODOO */
                   1492:
                   1493:        /* XXX TBD: setup hardware for all multicasts */
                   1494:        bus_space_write_1(iot, ioh, 0, BANK_SEL(0));
1.25      is       1495:        return;
1.1       is       1496: }
                   1497:
1.42      tv       1498: #ifdef IYDEBUGX
1.1       is       1499: void
                   1500: print_rbd(rbd)
                   1501:        volatile struct ie_recv_buf_desc *rbd;
                   1502: {
1.8       christos 1503:        printf("RBD at %08lx:\nactual %04x, next %04x, buffer %08x\n"
1.1       is       1504:            "length %04x, mbz %04x\n", (u_long)rbd, rbd->ie_rbd_actual,
                   1505:            rbd->ie_rbd_next, rbd->ie_rbd_buffer, rbd->ie_rbd_length,
                   1506:            rbd->mbz);
                   1507: }
                   1508: #endif
                   1509:
                   1510: void
                   1511: iyprobemem(sc)
                   1512:        struct iy_softc *sc;
                   1513: {
1.9       thorpej  1514:        bus_space_tag_t iot;
                   1515:        bus_space_handle_t ioh;
1.1       is       1516:        int testing;
                   1517:
1.9       thorpej  1518:        iot = sc->sc_iot;
1.6       is       1519:        ioh = sc->sc_ioh;
1.1       is       1520:
1.10      is       1521:        bus_space_write_1(iot, ioh, COMMAND_REG, BANK_SEL(0));
                   1522:        delay(1);
1.9       thorpej  1523:        bus_space_write_2(iot, ioh, HOST_ADDR_REG, 4096-2);
                   1524:        bus_space_write_2(iot, ioh, MEM_PORT_REG, 0);
1.1       is       1525:
                   1526:        for (testing=65536; testing >= 4096; testing >>= 1) {
1.9       thorpej  1527:                bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2);
                   1528:                bus_space_write_2(iot, ioh, MEM_PORT_REG, 0xdead);
                   1529:                bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2);
                   1530:                if (bus_space_read_2(iot, ioh, MEM_PORT_REG) != 0xdead) {
1.1       is       1531: #ifdef IYMEMDEBUG
1.8       christos 1532:                        printf("%s: Didn't keep 0xdead at 0x%x\n",
1.1       is       1533:                            sc->sc_dev.dv_xname, testing-2);
                   1534: #endif
                   1535:                        continue;
                   1536:                }
                   1537:
1.9       thorpej  1538:                bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2);
                   1539:                bus_space_write_2(iot, ioh, MEM_PORT_REG, 0xbeef);
                   1540:                bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing-2);
                   1541:                if (bus_space_read_2(iot, ioh, MEM_PORT_REG) != 0xbeef) {
1.1       is       1542: #ifdef IYMEMDEBUG
1.8       christos 1543:                        printf("%s: Didn't keep 0xbeef at 0x%x\n",
1.1       is       1544:                            sc->sc_dev.dv_xname, testing-2);
                   1545: #endif
                   1546:                        continue;
                   1547:                }
                   1548:
1.9       thorpej  1549:                bus_space_write_2(iot, ioh, HOST_ADDR_REG, 0);
                   1550:                bus_space_write_2(iot, ioh, MEM_PORT_REG, 0);
                   1551:                bus_space_write_2(iot, ioh, HOST_ADDR_REG, testing >> 1);
                   1552:                bus_space_write_2(iot, ioh, MEM_PORT_REG, testing >> 1);
                   1553:                bus_space_write_2(iot, ioh, HOST_ADDR_REG, 0);
                   1554:                if (bus_space_read_2(iot, ioh, MEM_PORT_REG) == (testing >> 1)) {
1.1       is       1555: #ifdef IYMEMDEBUG
1.8       christos 1556:                        printf("%s: 0x%x alias of 0x0\n",
1.1       is       1557:                            sc->sc_dev.dv_xname, testing >> 1);
                   1558: #endif
                   1559:                        continue;
                   1560:                }
                   1561:
                   1562:                break;
                   1563:        }
                   1564:
                   1565:        sc->sram = testing;
                   1566:
                   1567:        switch(testing) {
                   1568:                case 65536:
                   1569:                        /* 4 NFS packets + overhead RX, 2 NFS + overhead TX  */
                   1570:                        sc->rx_size = 44*1024;
                   1571:                        break;
                   1572:
                   1573:                case 32768:
                   1574:                        /* 2 NFS packets + overhead RX, 1 NFS + overhead TX  */
                   1575:                        sc->rx_size = 22*1024;
                   1576:                        break;
                   1577:
                   1578:                case 16384:
                   1579:                        /* 1 NFS packet + overhead RX, 4 big packets TX */
                   1580:                        sc->rx_size = 10*1024;
                   1581:                        break;
                   1582:                default:
                   1583:                        sc->rx_size = testing/2;
                   1584:                        break;
                   1585:        }
                   1586:        sc->tx_size = testing - sc->rx_size;
1.10      is       1587: }
                   1588:
                   1589: static int
                   1590: eepromreadall(iot, ioh, wordp, maxi)
                   1591:        bus_space_tag_t iot;
                   1592:        bus_space_handle_t ioh;
                   1593:        u_int16_t *wordp;
                   1594:        int maxi;
                   1595: {
                   1596:        int i;
                   1597:        u_int16_t checksum, tmp;
                   1598:
                   1599:        checksum = 0;
                   1600:
                   1601:        for (i=0; i<EEPP_LENGTH; ++i) {
                   1602:                tmp = eepromread(iot, ioh, i);
                   1603:                checksum += tmp;
                   1604:                if (i<maxi)
                   1605:                        wordp[i] = tmp;
                   1606:        }
                   1607:
                   1608:        if (checksum != EEPP_CHKSUM) {
                   1609: #ifdef IYDEBUG
                   1610:                printf("wrong EEPROM checksum 0x%x should be 0x%x\n",
                   1611:                    checksum, EEPP_CHKSUM);
                   1612: #endif
                   1613:                return 1;
                   1614:        }
                   1615:        return 0;
1.1       is       1616: }

CVSweb <webmaster@jp.NetBSD.org>