[BACK]Return to if_ex.c CVS log [TXT][DIR] Up to [local] / sys / dev / isa

Annotation of sys/dev/isa/if_ex.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: if_ex.c,v 1.16 2007/06/06 09:44:30 henning Exp $      */
        !             2: /*
        !             3:  * Copyright (c) 1997, Donald A. Schmidt
        !             4:  * Copyright (c) 1996, Javier Martín Rueda (jmrueda@diatel.upm.es)
        !             5:  * All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice unmodified, this list of conditions, and the following
        !            12:  *    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:  *
        !            17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            20:  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
        !            21:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            27:  * SUCH DAMAGE.
        !            28:  */
        !            29:
        !            30: /*
        !            31:  * Intel EtherExpress Pro/10 Ethernet driver
        !            32:  *
        !            33:  * Revision history:
        !            34:  *
        !            35:  * 30-Oct-1996: first beta version. Inet and BPF supported, but no multicast.
        !            36:  */
        !            37:
        !            38: #include "ex.h"
        !            39: #if NEX > 0
        !            40: #include "bpfilter.h"
        !            41:
        !            42: #include <sys/param.h>
        !            43: #include <sys/systm.h>
        !            44: #include <sys/conf.h>
        !            45: #include <sys/sockio.h>
        !            46: #include <sys/mbuf.h>
        !            47: #include <sys/socket.h>
        !            48: #include <sys/device.h>
        !            49:
        !            50: #include <net/if.h>
        !            51:
        !            52: #ifdef INET
        !            53: #include <netinet/in.h>
        !            54: #include <netinet/if_ether.h>
        !            55: #endif
        !            56:
        !            57: #if NBPFILTER > 0
        !            58: #include <net/bpf.h>
        !            59: #endif
        !            60:
        !            61: #include <machine/cpu.h>
        !            62: #include <machine/bus.h>
        !            63:
        !            64: #include <dev/isa/isavar.h>
        !            65: #include <dev/isa/if_exreg.h>
        !            66:
        !            67:
        !            68: #ifdef EXDEBUG
        !            69: #define Start_End 1
        !            70: #define Rcvd_Pkts 2
        !            71: #define Sent_Pkts 4
        !            72: #define Status    8
        !            73: static int debug_mask = 0;
        !            74: static int exintr_count = 0;
        !            75: #define DODEBUG(level, action) if (level & debug_mask) action
        !            76: #else
        !            77: #define DODEBUG(level, action)
        !            78: #endif
        !            79:
        !            80:
        !            81: #define Conn_BNC 1
        !            82: #define Conn_TPE 2
        !            83: #define Conn_AUI 3
        !            84:
        !            85: struct ex_softc {
        !            86:        struct arpcom arpcom;   /* Ethernet common data */
        !            87:        int iobase;             /* I/O base address. */
        !            88:        u_short connector;      /* Connector type. */
        !            89:        u_short irq_no;         /* IRQ number. */
        !            90:        u_int mem_size;         /* Total memory size, in bytes. */
        !            91:        u_int rx_mem_size;      /* Rx memory size (by default, first 3/4 of
        !            92:                                   total memory). */
        !            93:        u_int rx_lower_limit,
        !            94:              rx_upper_limit;   /* Lower and upper limits of receive buffer. */
        !            95:        u_int rx_head;          /* Head of receive ring buffer. */
        !            96:        u_int tx_mem_size;      /* Tx memory size (by default, last quarter of
        !            97:                                   total memory). */
        !            98:        u_int tx_lower_limit,
        !            99:              tx_upper_limit;   /* Lower and upper limits of transmit buffer. */
        !           100:        u_int tx_head, tx_tail; /* Head and tail of transmit ring buffer. */
        !           101:        u_int tx_last;          /* Pointer to beginning of last frame in the
        !           102:                                   chain. */
        !           103:        bus_space_tag_t sc_iot; /* ISA i/o space tag */
        !           104:        bus_space_handle_t sc_ioh; /* ISA i/o space handle */
        !           105:        void *sc_ih;            /* Device interrupt handler */
        !           106: };
        !           107:
        !           108: /* static struct ex_softc ex_sc[NEX]; XXX would it be better to malloc(3)
        !           109:                                        the memory? */
        !           110:
        !           111: static char irq2eemap[] = { -1, -1, 0, 1, -1, 2, -1, -1, -1, 0, 3, 4, -1, -1,
        !           112:                            -1, -1 };
        !           113: static u_char ee2irqmap[] = { 9, 3, 5, 10, 11, 0, 0, 0 };
        !           114:
        !           115: static int ex_probe(struct device *, void *, void *);
        !           116: static void ex_attach(struct device *, struct device *, void *);
        !           117: static void ex_init(struct ex_softc *);
        !           118: static void ex_start(struct ifnet *);
        !           119: static void ex_stop(struct ex_softc *);
        !           120: static int ex_ioctl(struct ifnet *, u_long, caddr_t);
        !           121: static void ex_reset(struct ex_softc *);
        !           122: static void ex_watchdog(struct ifnet *);
        !           123:
        !           124: static u_short eeprom_read(struct ex_softc *, int);
        !           125: static int look_for_card(struct isa_attach_args *, struct ex_softc *sc);
        !           126: static int exintr(void *);
        !           127: static void ex_tx_intr(struct ex_softc *);
        !           128: static void ex_rx_intr(struct ex_softc *);
        !           129:
        !           130:
        !           131: struct cfattach ex_ca = {
        !           132:        sizeof(struct ex_softc), ex_probe, ex_attach
        !           133: };
        !           134:
        !           135: struct cfdriver ex_cd = {
        !           136:        NULL, "ex", DV_IFNET
        !           137: };
        !           138:
        !           139: #define BANK_SEL(X) bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMD_REG, \
        !           140:        (X))
        !           141: #define ISA_GET(offset) bus_space_read_1(sc->sc_iot, sc->sc_ioh, (offset))
        !           142: #define ISA_PUT(offset, value) bus_space_write_1(sc->sc_iot, sc->sc_ioh, \
        !           143:        (offset), (value))
        !           144: #define ISA_GET_2(offset) bus_space_read_2(sc->sc_iot, sc->sc_ioh, \
        !           145:        (offset))
        !           146: #define ISA_PUT_2(offset, value) bus_space_write_2(sc->sc_iot, sc->sc_ioh, \
        !           147:        (offset), (value))
        !           148: #define ISA_GET_2_MULTI(offset, addr, count) bus_space_read_multi_2( \
        !           149:        sc->sc_iot, sc->sc_ioh, (offset), (addr), (count))
        !           150: #define ISA_PUT_2_MULTI(offset, addr, count) bus_space_write_multi_2( \
        !           151:        sc->sc_iot, sc->sc_ioh, (offset), (addr), (count))
        !           152:
        !           153:
        !           154: static int
        !           155: look_for_card(ia, sc)
        !           156:        struct isa_attach_args *ia;
        !           157:        struct ex_softc *sc;
        !           158: {
        !           159:        int count1, count2;
        !           160:
        !           161:        /*
        !           162:         * Check for the i82595 signature, and check that the round robin
        !           163:         * counter actually advances.
        !           164:         */
        !           165:        if (((count1 = ISA_GET(ID_REG)) & Id_Mask) != Id_Sig)
        !           166:                return(0);
        !           167:        count2 = ISA_GET(ID_REG);
        !           168:        count2 = ISA_GET(ID_REG);
        !           169:        count2 = ISA_GET(ID_REG);
        !           170:        if ((count2 & Counter_bits) == ((count1 + 0xc0) & Counter_bits))
        !           171:                return(1);
        !           172:        else
        !           173:                return(0);
        !           174: }
        !           175:
        !           176:
        !           177: int
        !           178: ex_probe(parent, match, aux)
        !           179:        struct device *parent;
        !           180:        void *match, *aux;
        !           181: {
        !           182:        struct ex_softc *sc = match;
        !           183:        struct isa_attach_args *ia = aux;
        !           184:        u_short eaddr_tmp;
        !           185:        int tmp;
        !           186:
        !           187:        DODEBUG(Start_End, printf("ex_probe: start\n"););
        !           188:
        !           189:        if ((ia->ia_iobase >= 0x200) && (ia->ia_iobase <= 0x3a0)) {
        !           190:                sc->sc_iot = ia->ia_iot;
        !           191:                if(bus_space_map(sc->sc_iot, ia->ia_iobase, EX_IOSIZE, 0,
        !           192:                    &sc->sc_ioh))
        !           193:                        return(0);
        !           194:
        !           195:                if (!look_for_card(ia, sc)) {
        !           196:                        bus_space_unmap(sc->sc_iot, sc->sc_ioh, EX_IOSIZE);
        !           197:                        return(0);
        !           198:                }
        !           199:        } else
        !           200:                return(0);
        !           201:
        !           202:        ia->ia_iosize = EX_IOSIZE;
        !           203:
        !           204:        /*
        !           205:         * Reset the card.
        !           206:         */
        !           207:        ISA_PUT(CMD_REG, Reset_CMD);
        !           208:        delay(200);
        !           209:
        !           210:        /*
        !           211:         * Fill in several fields of the softc structure:
        !           212:         *      - I/O base address.
        !           213:         *      - Hardware Ethernet address.
        !           214:         *      - IRQ number (if not supplied in config file, read it from
        !           215:         *        EEPROM).
        !           216:         *      - Connector type.
        !           217:         */
        !           218:        sc->iobase = ia->ia_iobase;
        !           219:        eaddr_tmp = eeprom_read(sc, EE_Eth_Addr_Lo);
        !           220:        sc->arpcom.ac_enaddr[5] = eaddr_tmp & 0xff;
        !           221:        sc->arpcom.ac_enaddr[4] = eaddr_tmp >> 8;
        !           222:        eaddr_tmp = eeprom_read(sc, EE_Eth_Addr_Mid);
        !           223:        sc->arpcom.ac_enaddr[3] = eaddr_tmp & 0xff;
        !           224:        sc->arpcom.ac_enaddr[2] = eaddr_tmp >> 8;
        !           225:        eaddr_tmp = eeprom_read(sc, EE_Eth_Addr_Hi);
        !           226:        sc->arpcom.ac_enaddr[1] = eaddr_tmp & 0xff;
        !           227:        sc->arpcom.ac_enaddr[0] = eaddr_tmp >> 8;
        !           228:        tmp = eeprom_read(sc, EE_IRQ_No) & IRQ_No_Mask;
        !           229:        if (ia->ia_irq > 0) {
        !           230:                if (ee2irqmap[tmp] != ia->ia_irq)
        !           231:                        printf("ex: WARING: board's EEPROM is configured for IRQ %d, using %d\n", ee2irqmap[tmp], ia->ia_irq);
        !           232:                sc->irq_no = ia->ia_irq;
        !           233:        }
        !           234:        else {
        !           235:                sc->irq_no = ee2irqmap[tmp];
        !           236:                ia->ia_irq = sc->irq_no;
        !           237:        }
        !           238:        if (sc->irq_no == 0) {
        !           239:                printf("ex: invalid IRQ.\n");
        !           240:                return(0);
        !           241:        }
        !           242:        BANK_SEL(Bank2_Sel);
        !           243:        tmp = ISA_GET(REG3);
        !           244:        if (tmp & TPE_bit)
        !           245:                sc->connector = Conn_TPE;
        !           246:        else if (tmp & BNC_bit)
        !           247:                sc->connector = Conn_BNC;
        !           248:        else
        !           249:                sc->connector = Conn_AUI;
        !           250:        sc->mem_size = CARD_RAM_SIZE;   /* XXX This should be read from the card
        !           251:                                               itself. */
        !           252:
        !           253:        BANK_SEL(Bank0_Sel);
        !           254:
        !           255:        DODEBUG(Start_End, printf("ex_probe: finish\n"););
        !           256:        return(1);
        !           257: }
        !           258:
        !           259:
        !           260: void
        !           261: ex_attach(parent, self, aux)
        !           262:        struct device *parent, *self;
        !           263:        void *aux;
        !           264: {
        !           265:        struct ex_softc *sc = (void *)self;
        !           266:        struct isa_attach_args *ia = aux;
        !           267:        struct ifnet *ifp = &sc->arpcom.ac_if;
        !           268:
        !           269:        /* struct ifaddr *ifa;  XXX what are these for? */
        !           270:        /* struct sockaddr_dl *sdl; */
        !           271:
        !           272:        DODEBUG(Start_End, printf("ex_attach: start\n"););
        !           273:
        !           274:        /*
        !           275:         * Initialize the ifnet structure.
        !           276:
        !           277:         */
        !           278:        ifp->if_softc = sc;
        !           279:        bcopy(self->dv_xname, ifp->if_xname, IFNAMSIZ);
        !           280:        ifp->if_start = ex_start;
        !           281:        ifp->if_ioctl = ex_ioctl;
        !           282:        ifp->if_watchdog = ex_watchdog;
        !           283:        ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST; /* XXX not done yet.
        !           284:                                                       | IFF_MULTICAST */
        !           285:        IFQ_SET_READY(&ifp->if_snd);
        !           286:
        !           287:        /*
        !           288:         * Attach the interface.
        !           289:         */
        !           290:        if_attach(ifp);
        !           291:        ether_ifattach(ifp);
        !           292:        printf(": address %s, connecter ",
        !           293:            ether_sprintf(sc->arpcom.ac_enaddr));
        !           294:        switch(sc->connector) {
        !           295:                case Conn_TPE: printf("TPE\n"); break;
        !           296:                case Conn_BNC: printf("BNC\n"); break;
        !           297:                case Conn_AUI: printf("AUI\n"); break;
        !           298:                default: printf("???\n");
        !           299:        }
        !           300:
        !           301:        sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
        !           302:            IPL_NET, exintr, sc, self->dv_xname);
        !           303:        ex_init(sc);
        !           304:
        !           305:        DODEBUG(Start_End, printf("ex_attach: finish\n"););
        !           306: }
        !           307:
        !           308:
        !           309: void
        !           310: ex_init(sc)
        !           311:        struct ex_softc *sc;
        !           312: {
        !           313:        struct ifnet *ifp = &sc->arpcom.ac_if;
        !           314:        int s, i;
        !           315:        unsigned short temp_reg;
        !           316:
        !           317:        DODEBUG(Start_End, printf("ex_init: start\n"););
        !           318:
        !           319:        if (TAILQ_EMPTY(&ifp->if_addrlist))
        !           320:                return;
        !           321:        s = splnet();
        !           322:        sc->arpcom.ac_if.if_timer = 0;
        !           323:
        !           324:        /*
        !           325:         * Load the ethernet address into the card.
        !           326:         */
        !           327:        BANK_SEL(Bank2_Sel);
        !           328:        temp_reg = ISA_GET(EEPROM_REG);
        !           329:        if (temp_reg & Trnoff_Enable)
        !           330:                ISA_PUT(EEPROM_REG, temp_reg & ~Trnoff_Enable);
        !           331:        for (i = 0; i < ETHER_ADDR_LEN; i++)
        !           332:                ISA_PUT(I_ADDR_REG0 + i, sc->arpcom.ac_enaddr[i]);
        !           333:        /*
        !           334:         * - Setup transmit chaining and discard bad received frames.
        !           335:         * - Match broadcast.
        !           336:         * - Clear test mode.
        !           337:         * - Set receiving mode.
        !           338:         * - Set IRQ number.
        !           339:         */
        !           340:        ISA_PUT(REG1, ISA_GET(REG1) | Tx_Chn_Int_Md | Tx_Chn_ErStp |
        !           341:            Disc_Bad_Fr);
        !           342:        ISA_PUT(REG2, ISA_GET(REG2) | No_SA_Ins | RX_CRC_InMem);
        !           343:        ISA_PUT(REG3, (ISA_GET(REG3) & 0x3f));
        !           344:        BANK_SEL(Bank1_Sel);
        !           345:        ISA_PUT(INT_NO_REG, (ISA_GET(INT_NO_REG) & 0xf8) |
        !           346:            irq2eemap[sc->irq_no]);
        !           347:
        !           348:        /*
        !           349:         * Divide the available memory in the card into rcv and xmt buffers.
        !           350:         * By default, I use the first 3/4 of the memory for the rcv buffer,
        !           351:         * and the remaining 1/4 of the memory for the xmt buffer.
        !           352:         */
        !           353:        sc->rx_mem_size = sc->mem_size * 3 / 4;
        !           354:        sc->tx_mem_size = sc->mem_size - sc->rx_mem_size;
        !           355:        sc->rx_lower_limit = 0x0000;
        !           356:        sc->rx_upper_limit = sc->rx_mem_size - 2;
        !           357:        sc->tx_lower_limit = sc->rx_mem_size;
        !           358:        sc->tx_upper_limit = sc->mem_size - 2;
        !           359:        ISA_PUT(RCV_LOWER_LIMIT_REG, sc->rx_lower_limit >> 8);
        !           360:         ISA_PUT(RCV_UPPER_LIMIT_REG, sc->rx_upper_limit >> 8);
        !           361:         ISA_PUT(XMT_LOWER_LIMIT_REG, sc->tx_lower_limit >> 8);
        !           362:        ISA_PUT(XMT_UPPER_LIMIT_REG, sc->tx_upper_limit >> 8);
        !           363:
        !           364:        /*
        !           365:         * Enable receive and transmit interrupts, and clear any pending int.
        !           366:         */
        !           367:        ISA_PUT(REG1, ISA_GET(REG1) | TriST_INT);
        !           368:        BANK_SEL(Bank0_Sel);
        !           369:        ISA_PUT(MASK_REG, All_Int & ~(Rx_Int | Tx_Int));
        !           370:        ISA_PUT(STATUS_REG, All_Int);
        !           371:
        !           372:        /*
        !           373:         * Initialize receive and transmit ring buffers.
        !           374:         */
        !           375:        ISA_PUT_2(RCV_BAR, sc->rx_lower_limit);
        !           376:        sc->rx_head = sc->rx_lower_limit;
        !           377:        ISA_PUT_2(RCV_STOP_REG, sc->rx_upper_limit | 0xfe);
        !           378:        ISA_PUT_2(XMT_BAR, sc->tx_lower_limit);
        !           379:        sc->tx_head = sc->tx_tail = sc->tx_lower_limit;
        !           380:
        !           381:        ifp->if_flags |= IFF_RUNNING;
        !           382:        ifp->if_flags &= ~IFF_OACTIVE;
        !           383:        DODEBUG(Status, printf("OIDLE init\n"););
        !           384:
        !           385:        /*
        !           386:         * Final reset of the board, and enable operation.
        !           387:         */
        !           388:        ISA_PUT(CMD_REG, Sel_Reset_CMD);
        !           389:        delay(2);
        !           390:        ISA_PUT(CMD_REG, Rcv_Enable_CMD);
        !           391:
        !           392:        ex_start(ifp);
        !           393:        splx(s);
        !           394:
        !           395:        DODEBUG(Start_End, printf("ex_init: finish\n"););
        !           396: }
        !           397:
        !           398:
        !           399: void
        !           400: ex_start(ifp)
        !           401:        struct ifnet *ifp;
        !           402: {
        !           403:        register struct ex_softc *sc = ifp->if_softc;
        !           404:        int i, s, len, data_len, avail, dest, next;
        !           405:        unsigned char tmp16[2];
        !           406:        struct mbuf *opkt;
        !           407:        register struct mbuf *m;
        !           408:
        !           409:        DODEBUG(Start_End, printf("ex_start: start\n"););
        !           410:
        !           411:        s = splnet();
        !           412:
        !           413:        /*
        !           414:         * Main loop: send outgoing packets to network card until there are no
        !           415:         * more packets left, or the card cannot accept any more yet.
        !           416:         */
        !           417:        while (!(ifp->if_flags & IFF_OACTIVE)) {
        !           418:                IFQ_POLL(&ifp->if_snd, opkt);
        !           419:                if (opkt == NULL)
        !           420:                        break;
        !           421:
        !           422:                /*
        !           423:                 * Ensure there is enough free transmit buffer space for this
        !           424:                 * packet, including its header. Note: the header cannot wrap
        !           425:                 * around the end of the transmit buffer and must be kept
        !           426:                 * together, so we allow space for twice the length of the
        !           427:                 * header, just in case.
        !           428:                 */
        !           429:                for (len = 0, m = opkt; m != NULL; m = m->m_next)
        !           430:                        len += m->m_len;
        !           431:                data_len = len;
        !           432:                DODEBUG(Sent_Pkts, printf("1. Sending packet with %d data bytes. ", data_len););
        !           433:                if (len & 1)
        !           434:                        len += XMT_HEADER_LEN + 1;
        !           435:                else
        !           436:                        len += XMT_HEADER_LEN;
        !           437:                if ((i = sc->tx_tail - sc->tx_head) >= 0)
        !           438:                        avail = sc->tx_mem_size - i;
        !           439:                else
        !           440:                        avail = -i;
        !           441:                DODEBUG(Sent_Pkts, printf("i=%d, avail=%d\n", i, avail););
        !           442:                if (avail >= len + XMT_HEADER_LEN) {
        !           443:                        IFQ_DEQUEUE(&ifp->if_snd, opkt);
        !           444:
        !           445: #ifdef EX_PSA_INTR
        !           446:                        /*
        !           447:                         * Disable rx and tx interrupts, to avoid corruption of
        !           448:                         * the host address register by interrupt service
        !           449:                         * routines. XXX Is this necessary with splnet()
        !           450:                         * enabled?
        !           451:                         */
        !           452:                        ISA_WRITE(MASK_REG, All_Int);
        !           453: #endif
        !           454:
        !           455:                        /*
        !           456:                         * Compute the start and end addresses of this frame
        !           457:                         * in the tx buffer.
        !           458:                         */
        !           459:                        dest = sc->tx_tail;
        !           460:                        next = dest + len;
        !           461:                        if (next > sc->tx_upper_limit) {
        !           462:                                if ((sc->tx_upper_limit + 2 - sc->tx_tail) <=
        !           463:                                    XMT_HEADER_LEN) {
        !           464:                                        dest = sc->tx_lower_limit;
        !           465:                                        next = dest + len;
        !           466:                                } else
        !           467:                                        next = sc->tx_lower_limit + next -
        !           468:                                            sc->tx_upper_limit - 2;
        !           469:                        }
        !           470:
        !           471:                        /* Build the packet frame in the card's ring buffer. */
        !           472:                        DODEBUG(Sent_Pkts, printf("2. dest=%d, next=%d. ", dest, next););
        !           473:                        ISA_PUT_2(HOST_ADDR_REG, dest);
        !           474:                        ISA_PUT_2(IO_PORT_REG, Transmit_CMD);
        !           475:                        ISA_PUT_2(IO_PORT_REG, 0);
        !           476:                        ISA_PUT_2(IO_PORT_REG, next);
        !           477:                        ISA_PUT_2(IO_PORT_REG, data_len);
        !           478:
        !           479:                        /*
        !           480:                         * Output the packet data to the card. Ensure all
        !           481:                         * transfers are 16-bit wide, even if individual mbufs
        !           482:                         * have odd length.
        !           483:                         */
        !           484:
        !           485:                        for (m = opkt, i = 0; m != NULL; m = m->m_next) {
        !           486:                                DODEBUG(Sent_Pkts, printf("[%d]", m->m_len););
        !           487:                                if (i) {
        !           488:                                        tmp16[1] = *(mtod(m, caddr_t));
        !           489:                                        ISA_PUT_2_MULTI(IO_PORT_REG, tmp16, 1);
        !           490:                                }
        !           491:                                ISA_PUT_2_MULTI(IO_PORT_REG, mtod(m, caddr_t)
        !           492:                                    + i, (m->m_len - i) / 2);
        !           493:                                if ((i = (m->m_len - i) & 1))
        !           494:                                        tmp16[0] = *(mtod(m, caddr_t) +
        !           495:                                            m->m_len - 1);
        !           496:                        }
        !           497:                        if (i)
        !           498:                                ISA_PUT_2_MULTI(IO_PORT_REG, tmp16, 1);
        !           499:
        !           500:                        /*
        !           501:                         * If there were other frames chained, update the
        !           502:                         * chain in the last one.
        !           503:                         */
        !           504:                        if (sc->tx_head != sc->tx_tail) {
        !           505:                                if (sc->tx_tail != dest) {
        !           506:                                        ISA_PUT_2(HOST_ADDR_REG,
        !           507:                                            sc->tx_last + XMT_Chain_Point);
        !           508:                                        ISA_PUT_2(IO_PORT_REG, dest);
        !           509:                                }
        !           510:                                ISA_PUT_2(HOST_ADDR_REG, sc->tx_last +
        !           511:                                    XMT_Byte_Count);
        !           512:                                i = ISA_GET_2(IO_PORT_REG);
        !           513:                                ISA_PUT_2(HOST_ADDR_REG, sc->tx_last +
        !           514:                                    XMT_Byte_Count);
        !           515:                                ISA_PUT_2(IO_PORT_REG, i | Ch_bit);
        !           516:                        }
        !           517:
        !           518:                        /*
        !           519:                         * Resume normal operation of the card:
        !           520:                         * -Make a dummy read to flush the DRAM write pipeline.
        !           521:                         * -Enable receive and transmit interrupts.
        !           522:                         * -Send Transmit or Resume_XMT command, as appropriate.
        !           523:                         */
        !           524:                        ISA_GET_2(IO_PORT_REG);
        !           525: #ifdef EX_PSA_INTR
        !           526:                        ISA_PUT_2(MASK_REG, All_Int & ~(Rx_Int | Tx_Int));
        !           527: #endif
        !           528:                        if (sc->tx_head == sc->tx_tail) {
        !           529:                                ISA_PUT_2(XMT_BAR, dest);
        !           530:                                ISA_PUT(CMD_REG, Transmit_CMD);
        !           531:                                sc->tx_head = dest;
        !           532:                                DODEBUG(Sent_Pkts, printf("Transmit\n"););
        !           533:                        } else {
        !           534:                                ISA_PUT(CMD_REG, Resume_XMT_List_CMD);
        !           535:                                DODEBUG(Sent_Pkts, printf("Resume\n"););
        !           536:                        }
        !           537:                        sc->tx_last = dest;
        !           538:                        sc->tx_tail = next;
        !           539: #if NBPFILTER > 0
        !           540:                        if (ifp->if_bpf != NULL)
        !           541:                                bpf_mtap(ifp->if_bpf, opkt,
        !           542:                                    BPF_DIRECTION_OUT);
        !           543: #endif
        !           544:                        ifp->if_timer = 2;
        !           545:                        ifp->if_opackets++;
        !           546:                        m_freem(opkt);
        !           547:                } else {
        !           548:                        ifp->if_flags |= IFF_OACTIVE;
        !           549:                        DODEBUG(Status, printf("OACTIVE start\n"););
        !           550:                }
        !           551:        }
        !           552:
        !           553:        splx(s);
        !           554:
        !           555:        DODEBUG(Start_End, printf("ex_start: finish\n"););
        !           556: }
        !           557:
        !           558:
        !           559: void
        !           560: ex_stop(sc)
        !           561:        struct ex_softc *sc;
        !           562: {
        !           563:        DODEBUG(Start_End, printf("ex_stop: start\n"););
        !           564:
        !           565:        /*
        !           566:         * Disable card operation:
        !           567:         * - Disable the interrupt line.
        !           568:         * - Flush transmission and disable reception.
        !           569:         * - Mask and clear all interrupts.
        !           570:         * - Reset the 82595.
        !           571:         */
        !           572:        BANK_SEL(Bank1_Sel);
        !           573:        ISA_PUT(REG1, ISA_GET(REG1) & ~TriST_INT);
        !           574:        BANK_SEL(Bank0_Sel);
        !           575:        ISA_PUT(CMD_REG, Rcv_Stop);
        !           576:        sc->tx_head = sc->tx_tail = sc->tx_lower_limit;
        !           577:        sc->tx_last = 0; /* XXX I think these two lines are not necessary,
        !           578:                                because ex_init will always be called again
        !           579:                                to reinit the interface. */
        !           580:        ISA_PUT(MASK_REG, All_Int);
        !           581:        ISA_PUT(STATUS_REG, All_Int);
        !           582:        ISA_PUT(CMD_REG, Reset_CMD);
        !           583:        delay(200);
        !           584:
        !           585:        DODEBUG(Start_End, printf("ex_stop: finish\n"););
        !           586: }
        !           587:
        !           588:
        !           589: int
        !           590: exintr(arg)
        !           591:        void *arg;
        !           592: {
        !           593:        struct ex_softc *sc = arg;
        !           594:        struct ifnet *ifp = &sc->arpcom.ac_if;
        !           595:        int int_status, send_pkts;
        !           596:        int handled;
        !           597:
        !           598:        DODEBUG(Start_End, printf("exintr: start\n"););
        !           599:
        !           600: #ifdef EXDEBUG
        !           601:        if (++exintr_count != 1)
        !           602:                printf("WARNING: nested interrupt (%d). Mail the author.\n",
        !           603:                    exintr_count);
        !           604: #endif
        !           605:
        !           606:        send_pkts = 0;
        !           607:        while ((int_status = ISA_GET(STATUS_REG)) & (Tx_Int | Rx_Int)) {
        !           608:                if (int_status & Rx_Int) {
        !           609:                        ISA_PUT(STATUS_REG, Rx_Int);
        !           610:                        handled = 1;
        !           611:                        ex_rx_intr(sc);
        !           612:                } else if (int_status & Tx_Int) {
        !           613:                        ISA_PUT(STATUS_REG, Tx_Int);
        !           614:                        handled = 1;
        !           615:                        ex_tx_intr(sc);
        !           616:                        send_pkts = 1;
        !           617:                } else
        !           618:                        handled = 0;
        !           619:        }
        !           620:
        !           621:        /*
        !           622:         * If any packet has been transmitted, and there are queued packets to
        !           623:         * be sent, attempt to send more packets to the network card.
        !           624:         */
        !           625:
        !           626:        if (send_pkts && IFQ_IS_EMPTY(&ifp->if_snd) == 0)
        !           627:                ex_start(ifp);
        !           628: #ifdef EXDEBUG
        !           629:        exintr_count--;
        !           630: #endif
        !           631:        DODEBUG(Start_End, printf("exintr: finish\n"););
        !           632:
        !           633:        return handled;
        !           634: }
        !           635:
        !           636:
        !           637: void
        !           638: ex_tx_intr(sc)
        !           639:        struct ex_softc *sc;
        !           640: {
        !           641:        register struct ifnet *ifp = &sc->arpcom.ac_if;
        !           642:        int tx_status;
        !           643:
        !           644:        DODEBUG(Start_End, printf("ex_tx_intr: start\n"););
        !           645:        /*
        !           646:         * - Cancel the watchdog.
        !           647:         * For all packets transmitted since last transmit interrupt:
        !           648:         * - Advance chain pointer to next queued packet.
        !           649:         * - Update statistics.
        !           650:         */
        !           651:        ifp->if_timer = 0;
        !           652:        while (sc->tx_head != sc->tx_tail) {
        !           653:                ISA_PUT_2(HOST_ADDR_REG, sc->tx_head);
        !           654:                if (! ISA_GET_2(IO_PORT_REG) & Done_bit)
        !           655:                        break;
        !           656:                tx_status = ISA_GET_2(IO_PORT_REG);
        !           657:                sc->tx_head = ISA_GET_2(IO_PORT_REG);
        !           658:                if (tx_status & TX_OK_bit)
        !           659:                        ifp->if_opackets++;
        !           660:                else
        !           661:                        ifp->if_oerrors++;
        !           662:                ifp->if_collisions += tx_status & No_Collisions_bits;
        !           663:        }
        !           664:
        !           665:        /* The card should be ready to accept more packets now. */
        !           666:        ifp->if_flags &= ~IFF_OACTIVE;
        !           667:        DODEBUG(Status, printf("OIDLE tx_intr\n"););
        !           668:
        !           669:        DODEBUG(Start_End, printf("ex_tx_intr: finish\n"););
        !           670: }
        !           671:
        !           672:
        !           673: void
        !           674: ex_rx_intr(sc)
        !           675:        struct ex_softc *sc;
        !           676: {
        !           677:        register struct ifnet *ifp = &sc->arpcom.ac_if;
        !           678:        int rx_status, pkt_len, QQQ;
        !           679:        register struct mbuf *m, *ipkt;
        !           680:
        !           681:        DODEBUG(Start_End, printf("ex_rx_intr: start\n"););
        !           682:        /*
        !           683:         * For all packets received since last receive interrupt:
        !           684:         * - If packet ok, read it into a new mbuf and queue it to interface,
        !           685:         *   updating statistics.
        !           686:         * - If packet bad, just discard it, and update statistics.
        !           687:         * Finally, advance receive stop limit in card's memory to new location.
        !           688:         */
        !           689:        ISA_PUT_2(HOST_ADDR_REG, sc->rx_head);
        !           690:        while (ISA_GET_2(IO_PORT_REG) == RCV_Done) {
        !           691:                rx_status = ISA_GET_2(IO_PORT_REG);
        !           692:                sc->rx_head = ISA_GET_2(IO_PORT_REG);
        !           693:                QQQ = pkt_len = ISA_GET_2(IO_PORT_REG);
        !           694:                if (rx_status & RCV_OK_bit) {
        !           695:                        MGETHDR(m, M_DONTWAIT, MT_DATA);
        !           696:                        ipkt = m;
        !           697:                        if (ipkt == NULL)
        !           698:                                ifp->if_iqdrops++;
        !           699:                        else {
        !           700:                                ipkt->m_pkthdr.rcvif = ifp;
        !           701:                                ipkt->m_pkthdr.len = pkt_len;
        !           702:                                ipkt->m_len = MHLEN;
        !           703:                                while (pkt_len > 0) {
        !           704:                                        if (pkt_len > MINCLSIZE) {
        !           705:                                                MCLGET(m, M_DONTWAIT);
        !           706:                                                if (m->m_flags & M_EXT)
        !           707:                                                        m->m_len = MCLBYTES;
        !           708:                                                else {
        !           709:                                                        m_freem(ipkt);
        !           710:                                                        ifp->if_iqdrops++;
        !           711:                                                        goto rx_another;
        !           712:                                                }
        !           713:                                        }
        !           714:                                        m->m_len = min(m->m_len, pkt_len);
        !           715:                                        /*
        !           716:                                         * NOTE: I'm assuming that all mbufs
        !           717:                                         * allocated are of even length, except
        !           718:                                         * for the last one in an odd-length
        !           719:                                         * packet.
        !           720:                                         */
        !           721:                                        ISA_GET_2_MULTI(IO_PORT_REG,
        !           722:                                            mtod(m, caddr_t), m->m_len / 2);
        !           723:                                        if (m->m_len & 1)
        !           724:                                                *(mtod(m, caddr_t) +
        !           725:                                                    m->m_len - 1) =
        !           726:                                                    ISA_GET(IO_PORT_REG);
        !           727:                                        pkt_len -= m->m_len;
        !           728:                                        if (pkt_len > 0) {
        !           729:                                                MGET(m->m_next, M_DONTWAIT,
        !           730:                                                    MT_DATA);
        !           731:                                        if (m->m_next == NULL) {
        !           732:                                                m_freem(ipkt);
        !           733:                                                ifp->if_iqdrops++;
        !           734:                                                goto rx_another;
        !           735:                                        }
        !           736:                                        m = m->m_next;
        !           737:                                        m->m_len = MLEN;
        !           738:                                }
        !           739:                        }
        !           740: #ifdef EXDEBUG
        !           741:                        if (debug_mask & Rcvd_Pkts) {
        !           742:                                if ((eh->ether_dhost[5] != 0xff) ||
        !           743:                                    (eh->ether_dhost[0] != 0xff)) {
        !           744:                                        printf("Receive packet with %d data bytes: %6D -> ", QQQ, eh->ether_shost, ":");
        !           745:                                        printf("%6D\n", eh->ether_dhost, ":");
        !           746:                                } /* QQQ */
        !           747:                        }
        !           748: #endif
        !           749: #if NBPFILTER > 0
        !           750:                        if (ifp->if_bpf != NULL)
        !           751:                                bpf_mtap(ifp->if_bpf, ipkt,
        !           752:                                    BPF_DIRECTION_IN);
        !           753: #endif
        !           754:                        ether_input_mbuf(ifp, ipkt);
        !           755:                        ifp->if_ipackets++;
        !           756:                }
        !           757:        } else
        !           758:                ifp->if_ierrors++;
        !           759:                ISA_PUT_2(HOST_ADDR_REG, sc->rx_head);
        !           760:                rx_another: ;
        !           761:        }
        !           762:        if (sc->rx_head < sc->rx_lower_limit + 2)
        !           763:                ISA_PUT_2(RCV_STOP_REG, sc->rx_upper_limit);
        !           764:        else
        !           765:                ISA_PUT_2(RCV_STOP_REG, sc->rx_head - 2);
        !           766:
        !           767:        DODEBUG(Start_End, printf("ex_rx_intr: finish\n"););
        !           768: }
        !           769:
        !           770:
        !           771: int
        !           772: ex_ioctl(ifp, cmd, data)
        !           773:        register struct ifnet *ifp;
        !           774:        u_long cmd;
        !           775:        caddr_t data;
        !           776: {
        !           777:        register struct ifaddr *ifa = (struct ifaddr *) data;
        !           778:        struct ex_softc *sc = ifp->if_softc;
        !           779:        struct ifreq *ifr = (struct ifreq *) data;
        !           780:        int s, error = 0;
        !           781:
        !           782:        DODEBUG(Start_End, printf("ex_ioctl: start "););
        !           783:
        !           784:        s = splnet();
        !           785:
        !           786:        switch(cmd) {
        !           787:                case SIOCSIFADDR:
        !           788:                        DODEBUG(Start_End, printf("SIOCSIFADDR"););
        !           789:                        ifp->if_flags |= IFF_UP;
        !           790:
        !           791:                        switch(ifa->ifa_addr->sa_family) {
        !           792: #ifdef INET
        !           793:                                case AF_INET:
        !           794:                                        ex_init(sc);
        !           795:                                        arp_ifinit((struct arpcom *) ifp, ifa);
        !           796:                                        break;
        !           797: #endif
        !           798:     default:
        !           799:       ex_init(sc);
        !           800:       break;
        !           801:     }
        !           802:     break;
        !           803:   case SIOCGIFADDR:
        !           804:     {
        !           805:       struct sockaddr *sa;
        !           806:
        !           807:       DODEBUG(Start_End, printf("SIOCGIFADDR"););
        !           808:       sa = (struct sockaddr *) &ifr->ifr_data;
        !           809:       bcopy((caddr_t) sc->arpcom.ac_enaddr, (caddr_t) sa->sa_data,
        !           810:            ETHER_ADDR_LEN);
        !           811:     }
        !           812:   break;
        !           813:   case SIOCSIFFLAGS:
        !           814:     DODEBUG(Start_End, printf("SIOCSIFFLAGS"););
        !           815:     if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) {
        !           816:       ifp->if_flags &= ~IFF_RUNNING;
        !           817:       ex_stop(sc);
        !           818:     }
        !           819:     else
        !           820:       ex_init(sc);
        !           821:     break;
        !           822: #ifdef NODEF
        !           823:   case SIOCGHWADDR:
        !           824:     DODEBUG(Start_End, printf("SIOCGHWADDR"););
        !           825:     bcopy((caddr_t) sc->sc_addr, (caddr_t) &ifr->ifr_data, sizeof(sc->sc_addr));
        !           826:     break;
        !           827: #endif
        !           828:   case SIOCSIFMTU:
        !           829:     DODEBUG(Start_End, printf("SIOCSIFMTU"););
        !           830:     if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) {
        !           831:       error = EINVAL;
        !           832:     } else if (ifp->if_mtu != ifr->ifr_mtu) {
        !           833:       ifp->if_mtu = ifr->ifr_mtu;
        !           834:     }
        !           835:     break;
        !           836:   case SIOCADDMULTI:
        !           837:     DODEBUG(Start_End, printf("SIOCADDMULTI"););
        !           838:   case SIOCDELMULTI:
        !           839:     DODEBUG(Start_End, printf("SIOCDELMULTI"););
        !           840:     /* XXX Support not done yet. */
        !           841:     error = EINVAL;
        !           842:     break;
        !           843:   default:
        !           844:     DODEBUG(Start_End, printf("unknown"););
        !           845:     error = EINVAL;
        !           846:   }
        !           847:
        !           848:   splx(s);
        !           849:
        !           850:   DODEBUG(Start_End, printf("\nex_ioctl: finish\n"););
        !           851:   return(error);
        !           852: }
        !           853:
        !           854:
        !           855: void
        !           856: ex_reset(sc)
        !           857:        struct ex_softc *sc;
        !           858: {
        !           859:        int s;
        !           860:
        !           861:        DODEBUG(Start_End, printf("ex_reset: start\n"););
        !           862:
        !           863:        s = splnet();
        !           864:        ex_stop(sc);
        !           865:        ex_init(sc);
        !           866:        splx(s);
        !           867:
        !           868:        DODEBUG(Start_End, printf("ex_reset: finish\n"););
        !           869: }
        !           870:
        !           871:
        !           872: void
        !           873: ex_watchdog(ifp)
        !           874:        struct ifnet *ifp;
        !           875: {
        !           876:        struct ex_softc *sc = ifp->if_softc;
        !           877:
        !           878:        DODEBUG(Start_End, printf("ex_watchdog: start\n"););
        !           879:
        !           880:        ifp->if_flags &= ~IFF_OACTIVE;
        !           881:        DODEBUG(Status, printf("OIDLE watchdog\n"););
        !           882:        ifp->if_oerrors++;
        !           883:        ex_reset(sc);
        !           884:        ex_start(ifp);
        !           885:
        !           886:        DODEBUG(Start_End, printf("ex_watchdog: finish\n"););
        !           887: }
        !           888:
        !           889:
        !           890: static u_short
        !           891: eeprom_read(sc, location)
        !           892:        struct ex_softc *sc;
        !           893:        int location;
        !           894: {
        !           895:        int i;
        !           896:        u_short data = 0;
        !           897:        int read_cmd = location | EE_READ_CMD;
        !           898:        short ctrl_val = EECS;
        !           899:
        !           900:        BANK_SEL(Bank2_Sel);
        !           901:        ISA_PUT(EEPROM_REG, EECS);
        !           902:        for (i = 8; i >= 0; i--) {
        !           903:                short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI :
        !           904:                    ctrl_val;
        !           905:                ISA_PUT(EEPROM_REG, outval);
        !           906:                ISA_PUT(EEPROM_REG, outval | EESK);
        !           907:                delay(3);
        !           908:                ISA_PUT(EEPROM_REG, outval);
        !           909:                delay(2);
        !           910:        }
        !           911:        ISA_PUT(EEPROM_REG, ctrl_val);
        !           912:        for (i = 16; i > 0; i--) {
        !           913:                ISA_PUT(EEPROM_REG, ctrl_val | EESK);
        !           914:                delay(3);
        !           915:                data = (data << 1) | ((ISA_GET(EEPROM_REG) & EEDO) ? 1 : 0);
        !           916:                ISA_PUT(EEPROM_REG, ctrl_val);
        !           917:                delay(2);
        !           918:        }
        !           919:        ctrl_val &= ~EECS;
        !           920:        ISA_PUT(EEPROM_REG, ctrl_val | EESK);
        !           921:        delay(3);
        !           922:        ISA_PUT(EEPROM_REG, ctrl_val);
        !           923:        delay(2);
        !           924:        BANK_SEL(Bank0_Sel);
        !           925:        return(data);
        !           926: }
        !           927:
        !           928: #endif /* NEX > 0 */

CVSweb