[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

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