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

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

1.1     ! nbrk        1: /*     $OpenBSD: if_eg.c,v 1.30 2007/01/07 15:15:58 miod Exp $ */
        !             2: /*     $NetBSD: if_eg.c,v 1.26 1996/05/12 23:52:27 mycroft Exp $       */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1993 Dean Huxley <dean@fsa.ca>
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. All advertising materials mentioning features or use of this software
        !            17:  *    must display the following acknowledgement:
        !            18:  *      This product includes software developed by Dean Huxley.
        !            19:  * 4. The name of Dean Huxley may not be used to endorse or promote products
        !            20:  *    derived from this software without specific prior written permission.
        !            21:  *
        !            22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            23:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            24:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            25:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            26:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            27:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            28:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            29:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            30:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            31:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            32:  */
        !            33: /*
        !            34:  * Support for 3Com 3c505 Etherlink+ card.
        !            35:  */
        !            36:
        !            37: /* To do:
        !            38:  * - multicast
        !            39:  * - promiscuous
        !            40:  */
        !            41: #include "bpfilter.h"
        !            42:
        !            43: #include <sys/types.h>
        !            44: #include <sys/param.h>
        !            45: #include <sys/mbuf.h>
        !            46: #include <sys/socket.h>
        !            47: #include <sys/ioctl.h>
        !            48: #include <sys/errno.h>
        !            49: #include <sys/syslog.h>
        !            50: #include <sys/systm.h>
        !            51: #include <sys/selinfo.h>
        !            52: #include <sys/device.h>
        !            53:
        !            54: #include <net/if.h>
        !            55: #include <net/if_dl.h>
        !            56: #include <net/if_types.h>
        !            57: #include <net/netisr.h>
        !            58:
        !            59: #ifdef INET
        !            60: #include <netinet/in.h>
        !            61: #include <netinet/in_systm.h>
        !            62: #include <netinet/in_var.h>
        !            63: #include <netinet/ip.h>
        !            64: #include <netinet/if_ether.h>
        !            65: #endif
        !            66:
        !            67: #if NBPFILTER > 0
        !            68: #include <net/bpf.h>
        !            69: #endif
        !            70:
        !            71: #include <machine/cpu.h>
        !            72: #include <machine/intr.h>
        !            73:
        !            74: #include <dev/isa/isavar.h>
        !            75: #include <dev/isa/if_egreg.h>
        !            76: #include <dev/isa/elink.h>
        !            77:
        !            78: /* for debugging convenience */
        !            79: #ifdef EGDEBUG
        !            80: #define DPRINTF(x) printf x
        !            81: #else
        !            82: #define DPRINTF(x)
        !            83: #endif
        !            84:
        !            85: #define EG_INLEN       10
        !            86: #define EG_BUFLEN      0x0670
        !            87:
        !            88: /*
        !            89:  * Ethernet software status per interface.
        !            90:  */
        !            91: struct eg_softc {
        !            92:        struct device sc_dev;
        !            93:        void *sc_ih;
        !            94:        bus_space_tag_t sc_bst;
        !            95:        bus_space_handle_t sc_bsh;
        !            96:        struct arpcom sc_arpcom;        /* Ethernet common part */
        !            97:        u_char  eg_rom_major;           /* Cards ROM version (major number) */
        !            98:        u_char  eg_rom_minor;           /* Cards ROM version (minor number) */
        !            99:        short   eg_ram;                 /* Amount of RAM on the card */
        !           100:        u_char  eg_pcb[64];             /* Primary Command Block buffer */
        !           101:        u_char  eg_incount;             /* Number of buffers currently used */
        !           102:        u_char  *eg_inbuf;              /* Incoming packet buffer */
        !           103:        u_char  *eg_outbuf;             /* Outgoing packet buffer */
        !           104: };
        !           105:
        !           106: int egprobe(struct device *, void *, void *);
        !           107: void egattach(struct device *, struct device *, void *);
        !           108:
        !           109: struct cfattach eg_ca = {
        !           110:        sizeof(struct eg_softc), egprobe, egattach
        !           111: };
        !           112:
        !           113: struct cfdriver eg_cd = {
        !           114:        NULL, "eg", DV_IFNET
        !           115: };
        !           116:
        !           117: int egintr(void *);
        !           118: void eginit(struct eg_softc *);
        !           119: int egioctl(struct ifnet *, u_long, caddr_t);
        !           120: void egrecv(struct eg_softc *);
        !           121: void egstart(struct ifnet *);
        !           122: void egwatchdog(struct ifnet *);
        !           123: void egreset(struct eg_softc *);
        !           124: void egread(struct eg_softc *, caddr_t, int);
        !           125: struct mbuf *egget(struct eg_softc *, caddr_t, int);
        !           126: void egstop(struct eg_softc *);
        !           127:
        !           128: static __inline void egprintpcb(struct eg_softc *);
        !           129: static __inline void egprintstat(u_char);
        !           130: static int egoutPCB(struct eg_softc *, u_char);
        !           131: static int egreadPCBstat(struct eg_softc *, u_char);
        !           132: static int egreadPCBready(struct eg_softc *);
        !           133: static int egwritePCB(struct eg_softc *);
        !           134: static int egreadPCB(struct eg_softc *);
        !           135:
        !           136: /*
        !           137:  * Support stuff
        !           138:  */
        !           139:
        !           140: static __inline void
        !           141: egprintpcb(sc)
        !           142:        struct eg_softc *sc;
        !           143: {
        !           144:        int i;
        !           145:
        !           146:        for (i = 0; i < sc->eg_pcb[1] + 2; i++)
        !           147:                DPRINTF(("pcb[%2d] = %x\n", i, sc->eg_pcb[i]));
        !           148: }
        !           149:
        !           150:
        !           151: static __inline void
        !           152: egprintstat(b)
        !           153:        u_char b;
        !           154: {
        !           155:        DPRINTF(("%s %s %s %s %s %s %s\n",
        !           156:            (b & EG_STAT_HCRE)?"HCRE":"",
        !           157:            (b & EG_STAT_ACRF)?"ACRF":"",
        !           158:            (b & EG_STAT_DIR )?"DIR ":"",
        !           159:            (b & EG_STAT_DONE)?"DONE":"",
        !           160:            (b & EG_STAT_ASF3)?"ASF3":"",
        !           161:            (b & EG_STAT_ASF2)?"ASF2":"",
        !           162:            (b & EG_STAT_ASF1)?"ASF1":""));
        !           163: }
        !           164:
        !           165: static int
        !           166: egoutPCB(sc, b)
        !           167:        struct eg_softc *sc;
        !           168:        u_char b;
        !           169: {
        !           170:        bus_space_tag_t bst = sc->sc_bst;
        !           171:        bus_space_handle_t bsh = sc->sc_bsh;
        !           172:        int i;
        !           173:
        !           174:        for (i = 0; i < 4000; i++) {
        !           175:                if (bus_space_read_1(bst, bsh, EG_STATUS) & EG_STAT_HCRE) {
        !           176:                        bus_space_write_1(bst, bsh, EG_COMMAND, b);
        !           177:                        return 0;
        !           178:                }
        !           179:                delay(10);
        !           180:        }
        !           181:        DPRINTF(("egoutPCB failed\n"));
        !           182:        return (1);
        !           183: }
        !           184:
        !           185: static int
        !           186: egreadPCBstat(sc, statb)
        !           187:        struct eg_softc *sc;
        !           188:        u_char statb;
        !           189: {
        !           190:        bus_space_tag_t bst = sc->sc_bst;
        !           191:        bus_space_handle_t bsh = sc->sc_bsh;
        !           192:        int i;
        !           193:
        !           194:        for (i=0; i < 5000; i++) {
        !           195:                if ((bus_space_read_1(bst, bsh, EG_STATUS) & EG_PCB_STAT) !=
        !           196:                    EG_PCB_NULL)
        !           197:                        break;
        !           198:                delay(10);
        !           199:        }
        !           200:        if ((bus_space_read_1(bst, bsh, EG_STATUS) & EG_PCB_STAT) == statb)
        !           201:                return (0);
        !           202:        return (1);
        !           203: }
        !           204:
        !           205: static int
        !           206: egreadPCBready(sc)
        !           207:        struct eg_softc *sc;
        !           208: {
        !           209:        bus_space_tag_t bst = sc->sc_bst;
        !           210:        bus_space_handle_t bsh = sc->sc_bsh;
        !           211:        int i;
        !           212:
        !           213:        for (i=0; i < 10000; i++) {
        !           214:                if (bus_space_read_1(bst, bsh, EG_STATUS) & EG_STAT_ACRF)
        !           215:                        return (0);
        !           216:                delay(5);
        !           217:        }
        !           218:        DPRINTF(("PCB read not ready status %02x\n",
        !           219:            bus_space_read_1(bst, bsh, EG_STATUS)));
        !           220:        return (1);
        !           221: }
        !           222:
        !           223: static int
        !           224: egwritePCB(sc)
        !           225:        struct eg_softc *sc;
        !           226: {
        !           227:        bus_space_tag_t bst = sc->sc_bst;
        !           228:        bus_space_handle_t bsh = sc->sc_bsh;
        !           229:        int i;
        !           230:        u_char len;
        !           231:
        !           232:        bus_space_write_1(bst, bsh, EG_CONTROL,
        !           233:            (bus_space_read_1(bst, bsh, EG_CONTROL) & ~EG_PCB_STAT) |
        !           234:            EG_PCB_NULL);
        !           235:
        !           236:        len = sc->eg_pcb[1] + 2;
        !           237:        for (i = 0; i < len; i++)
        !           238:                egoutPCB(sc, sc->eg_pcb[i]);
        !           239:
        !           240:        for (i=0; i < 4000; i++) {
        !           241:                if (bus_space_read_1(bst, bsh, EG_STATUS) & EG_STAT_HCRE)
        !           242:                        break;
        !           243:                delay(10);
        !           244:        }
        !           245:
        !           246:        bus_space_write_1(bst, bsh, EG_CONTROL,
        !           247:            (bus_space_read_1(bst, bsh, EG_CONTROL) & ~EG_PCB_STAT) |
        !           248:            EG_PCB_DONE);
        !           249:
        !           250:        egoutPCB(sc, len);
        !           251:
        !           252:        if (egreadPCBstat(sc, EG_PCB_ACCEPT))
        !           253:                return (1);
        !           254:        return (0);
        !           255: }
        !           256:
        !           257: static int
        !           258: egreadPCB(sc)
        !           259:        struct eg_softc *sc;
        !           260: {
        !           261:        bus_space_tag_t bst = sc->sc_bst;
        !           262:        bus_space_handle_t bsh = sc->sc_bsh;
        !           263:        int i;
        !           264:        u_char b;
        !           265:
        !           266:        bus_space_write_1(bst, bsh, EG_CONTROL,
        !           267:            (bus_space_read_1(bst, bsh, EG_CONTROL) & ~EG_PCB_STAT) |
        !           268:            EG_PCB_NULL);
        !           269:
        !           270:        bzero(sc->eg_pcb, sizeof(sc->eg_pcb));
        !           271:
        !           272:        if (egreadPCBready(sc))
        !           273:                return (1);
        !           274:
        !           275:        sc->eg_pcb[0] = bus_space_read_1(bst, bsh, EG_COMMAND);
        !           276:
        !           277:        if (egreadPCBready(sc))
        !           278:                return (1);
        !           279:
        !           280:        sc->eg_pcb[1] = bus_space_read_1(bst, bsh, EG_COMMAND);
        !           281:
        !           282:        if (sc->eg_pcb[1] > 62) {
        !           283:                DPRINTF(("len %d too large\n", sc->eg_pcb[1]));
        !           284:                return (1);
        !           285:        }
        !           286:
        !           287:        for (i = 0; i < sc->eg_pcb[1]; i++) {
        !           288:                if (egreadPCBready(sc))
        !           289:                        return (1);
        !           290:                sc->eg_pcb[2+i] = bus_space_read_1(bst, bsh, EG_COMMAND);
        !           291:        }
        !           292:        if (egreadPCBready(sc))
        !           293:                return (1);
        !           294:        if (egreadPCBstat(sc, EG_PCB_DONE))
        !           295:                return (1);
        !           296:        if ((b = bus_space_read_1(bst, bsh, EG_COMMAND)) != sc->eg_pcb[1] + 2) {
        !           297:                DPRINTF(("%d != %d\n", b, sc->eg_pcb[1] + 2));
        !           298:                return (1);
        !           299:        }
        !           300:
        !           301:        bus_space_write_1(bst, bsh, EG_CONTROL,
        !           302:            (bus_space_read_1(bst, bsh, EG_CONTROL) & ~EG_PCB_STAT) |
        !           303:            EG_PCB_ACCEPT);
        !           304:
        !           305:        return (0);
        !           306: }
        !           307:
        !           308: /*
        !           309:  * Real stuff
        !           310:  */
        !           311:
        !           312: int
        !           313: egprobe(parent, match, aux)
        !           314:        struct device *parent;
        !           315:        void *match, *aux;
        !           316: {
        !           317:        struct eg_softc *sc = match;
        !           318:        struct isa_attach_args *ia = aux;
        !           319:        bus_space_tag_t bst = sc->sc_bst = ia->ia_iot;
        !           320:        bus_space_handle_t bsh;
        !           321:        int i;
        !           322:
        !           323:        if ((ia->ia_iobase & ~0x07f0) != 0) {
        !           324:                DPRINTF(("Weird iobase %x\n", ia->ia_iobase));
        !           325:                return (0);
        !           326:        }
        !           327:
        !           328:        if (bus_space_map(bst, ia->ia_iobase, EG_IO_PORTS, 0, &bsh)) {
        !           329:                DPRINTF(("%s: can't map I/O space\n", sc->sc_dev.dv_xname));
        !           330:                return (0);
        !           331:        }
        !           332:        sc->sc_bsh = bsh;
        !           333:
        !           334:        /* hard reset card */
        !           335:        bus_space_write_1(bst, bsh, EG_CONTROL, EG_CTL_RESET);
        !           336:        bus_space_write_1(bst, bsh, EG_CONTROL, 0);
        !           337:        for (i = 0; i < 5000; i++) {
        !           338:                delay(1000);
        !           339:                if ((bus_space_read_1(bst, bsh, EG_STATUS) & EG_PCB_STAT) ==
        !           340:                    EG_PCB_NULL)
        !           341:                        break;
        !           342:        }
        !           343:        if ((bus_space_read_1(bst, bsh, EG_STATUS) & EG_PCB_STAT) !=
        !           344:            EG_PCB_NULL) {
        !           345:                DPRINTF(("eg: Reset failed\n"));
        !           346:                goto lose;
        !           347:        }
        !           348:        sc->eg_pcb[0] = EG_CMD_GETINFO; /* Get Adapter Info */
        !           349:        sc->eg_pcb[1] = 0;
        !           350:        if (egwritePCB(sc) != 0)
        !           351:                goto lose;
        !           352:
        !           353:        if (egreadPCB(sc) != 0) {
        !           354:                egprintpcb(sc);
        !           355:                goto lose;
        !           356:        }
        !           357:
        !           358:        if (sc->eg_pcb[0] != EG_RSP_GETINFO || /* Get Adapter Info Response */
        !           359:            sc->eg_pcb[1] != 0x0a) {
        !           360:                egprintpcb(sc);
        !           361:                goto lose;
        !           362:        }
        !           363:        sc->eg_rom_major = sc->eg_pcb[3];
        !           364:        sc->eg_rom_minor = sc->eg_pcb[2];
        !           365:        sc->eg_ram = sc->eg_pcb[6] | (sc->eg_pcb[7] << 8);
        !           366:
        !           367:        ia->ia_iosize = 0x08;
        !           368:        ia->ia_msize = 0;
        !           369:        bus_space_unmap(bst, bsh, EG_IO_PORTS);
        !           370:        return (1);
        !           371:
        !           372: lose:
        !           373:        bus_space_unmap(bst, bsh, EG_IO_PORTS);
        !           374:        return (0);
        !           375: }
        !           376:
        !           377: void
        !           378: egattach(parent, self, aux)
        !           379:        struct device *parent, *self;
        !           380:        void *aux;
        !           381: {
        !           382:        struct eg_softc *sc = (void *)self;
        !           383:        struct isa_attach_args *ia = aux;
        !           384:        bus_space_tag_t bst = sc->sc_bst = ia->ia_iot;
        !           385:        bus_space_handle_t bsh;
        !           386:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           387:
        !           388:        if (bus_space_map(bst, ia->ia_iobase, EG_IO_PORTS, 0, &bsh)) {
        !           389:                printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
        !           390:                return;
        !           391:        }
        !           392:        sc->sc_bsh = bsh;
        !           393:
        !           394:        egstop(sc);
        !           395:
        !           396:        sc->eg_pcb[0] = EG_CMD_GETEADDR; /* Get Station address */
        !           397:        sc->eg_pcb[1] = 0;
        !           398:        if (egwritePCB(sc) != 0) {
        !           399:                DPRINTF(("write error\n"));
        !           400:                return;
        !           401:        }
        !           402:        if (egreadPCB(sc) != 0) {
        !           403:                DPRINTF(("read error\n"));
        !           404:                egprintpcb(sc);
        !           405:                return;
        !           406:        }
        !           407:
        !           408:        /* check Get station address response */
        !           409:        if (sc->eg_pcb[0] != EG_RSP_GETEADDR || sc->eg_pcb[1] != 0x06) {
        !           410:                DPRINTF(("parse error\n"));
        !           411:                egprintpcb(sc);
        !           412:                return;
        !           413:        }
        !           414:        bcopy(&sc->eg_pcb[2], sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
        !           415:
        !           416:        printf(": ROM v%d.%02d %dk address %s\n",
        !           417:            sc->eg_rom_major, sc->eg_rom_minor, sc->eg_ram,
        !           418:            ether_sprintf(sc->sc_arpcom.ac_enaddr));
        !           419:
        !           420:        sc->eg_pcb[0] = EG_CMD_SETEADDR; /* Set station address */
        !           421:        if (egwritePCB(sc) != 0) {
        !           422:                DPRINTF(("write error2\n"));
        !           423:                return;
        !           424:        }
        !           425:        if (egreadPCB(sc) != 0) {
        !           426:                DPRINTF(("read error2\n"));
        !           427:                egprintpcb(sc);
        !           428:                return;
        !           429:        }
        !           430:        if (sc->eg_pcb[0] != EG_RSP_SETEADDR || sc->eg_pcb[1] != 0x02 ||
        !           431:            sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0) {
        !           432:                DPRINTF(("parse error2\n"));
        !           433:                egprintpcb(sc);
        !           434:                return;
        !           435:        }
        !           436:
        !           437:        /* Initialize ifnet structure. */
        !           438:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
        !           439:        ifp->if_softc = sc;
        !           440:        ifp->if_start = egstart;
        !           441:        ifp->if_ioctl = egioctl;
        !           442:        ifp->if_watchdog = egwatchdog;
        !           443:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
        !           444:        IFQ_SET_READY(&ifp->if_snd);
        !           445:
        !           446:        /* Now we can attach the interface. */
        !           447:        if_attach(ifp);
        !           448:        ether_ifattach(ifp);
        !           449:
        !           450:        sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
        !           451:            IPL_NET, egintr, sc, sc->sc_dev.dv_xname);
        !           452: }
        !           453:
        !           454: void
        !           455: eginit(sc)
        !           456:        register struct eg_softc *sc;
        !           457: {
        !           458:        bus_space_tag_t bst = sc->sc_bst;
        !           459:        bus_space_handle_t bsh = sc->sc_bsh;
        !           460:        register struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           461:
        !           462:        /* soft reset the board */
        !           463:        bus_space_write_1(bst, bsh, EG_CONTROL, EG_CTL_FLSH);
        !           464:        delay(100);
        !           465:        bus_space_write_1(bst, bsh, EG_CONTROL, EG_CTL_ATTN);
        !           466:        delay(100);
        !           467:        bus_space_write_1(bst, bsh, EG_CONTROL, 0);
        !           468:        delay(200);
        !           469:
        !           470:        sc->eg_pcb[0] = EG_CMD_CONFIG82586; /* Configure 82586 */
        !           471:        sc->eg_pcb[1] = 2;
        !           472:        sc->eg_pcb[2] = 3; /* receive broadcast & multicast */
        !           473:        sc->eg_pcb[3] = 0;
        !           474:        if (egwritePCB(sc) != 0)
        !           475:                DPRINTF(("write error3\n"));
        !           476:
        !           477:        if (egreadPCB(sc) != 0) {
        !           478:                DPRINTF(("read error3\n"));
        !           479:                egprintpcb(sc);
        !           480:        } else if (sc->eg_pcb[2] != 0 || sc->eg_pcb[3] != 0)
        !           481:                printf("%s: configure card command failed\n",
        !           482:                    sc->sc_dev.dv_xname);
        !           483:
        !           484:        if (sc->eg_inbuf == 0)
        !           485:                sc->eg_inbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT);
        !           486:        sc->eg_incount = 0;
        !           487:
        !           488:        if (sc->eg_outbuf == 0)
        !           489:                sc->eg_outbuf = malloc(EG_BUFLEN, M_TEMP, M_NOWAIT);
        !           490:
        !           491:        bus_space_write_1(bst, bsh, EG_CONTROL, EG_CTL_CMDE);
        !           492:
        !           493:        sc->eg_incount = 0;
        !           494:        egrecv(sc);
        !           495:
        !           496:        /* Interface is now `running', with no output active. */
        !           497:        ifp->if_flags |= IFF_RUNNING;
        !           498:        ifp->if_flags &= ~IFF_OACTIVE;
        !           499:
        !           500:        /* Attempt to start output, if any. */
        !           501:        egstart(ifp);
        !           502: }
        !           503:
        !           504: void
        !           505: egrecv(sc)
        !           506:        struct eg_softc *sc;
        !           507: {
        !           508:
        !           509:        while (sc->eg_incount < EG_INLEN) {
        !           510:                sc->eg_pcb[0] = EG_CMD_RECVPACKET;
        !           511:                sc->eg_pcb[1] = 0x08;
        !           512:                sc->eg_pcb[2] = 0; /* address not used.. we send zero */
        !           513:                sc->eg_pcb[3] = 0;
        !           514:                sc->eg_pcb[4] = 0;
        !           515:                sc->eg_pcb[5] = 0;
        !           516:                sc->eg_pcb[6] = EG_BUFLEN & 0xff; /* our buffer size */
        !           517:                sc->eg_pcb[7] = (EG_BUFLEN >> 8) & 0xff;
        !           518:                sc->eg_pcb[8] = 0; /* timeout, 0 == none */
        !           519:                sc->eg_pcb[9] = 0;
        !           520:                if (egwritePCB(sc) != 0)
        !           521:                        break;
        !           522:                sc->eg_incount++;
        !           523:        }
        !           524: }
        !           525:
        !           526: void
        !           527: egstart(ifp)
        !           528:        struct ifnet *ifp;
        !           529: {
        !           530:        struct eg_softc *sc = ifp->if_softc;
        !           531:        bus_space_tag_t bst = sc->sc_bst;
        !           532:        bus_space_handle_t bsh = sc->sc_bsh;
        !           533:        struct mbuf *m0, *m;
        !           534:        caddr_t buffer;
        !           535:        int len;
        !           536:        u_short *ptr;
        !           537:        u_int i;
        !           538:
        !           539:        /* Don't transmit if interface is busy or not running */
        !           540:        if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
        !           541:                return;
        !           542:
        !           543: loop:
        !           544:        /* Dequeue the next datagram. */
        !           545:        IFQ_DEQUEUE(&ifp->if_snd, m0);
        !           546:        if (m0 == 0)
        !           547:                return;
        !           548:
        !           549:        ifp->if_flags |= IFF_OACTIVE;
        !           550:
        !           551:        /* We need to use m->m_pkthdr.len, so require the header */
        !           552:        if ((m0->m_flags & M_PKTHDR) == 0)
        !           553:                panic("egstart: no header mbuf");
        !           554:        len = max(m0->m_pkthdr.len, ETHER_MIN_LEN);
        !           555:
        !           556: #if NBPFILTER > 0
        !           557:        if (ifp->if_bpf)
        !           558:                bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
        !           559: #endif
        !           560:
        !           561:        sc->eg_pcb[0] = EG_CMD_SENDPACKET;
        !           562:        sc->eg_pcb[1] = 0x06;
        !           563:        sc->eg_pcb[2] = 0; /* address not used, we send zero */
        !           564:        sc->eg_pcb[3] = 0;
        !           565:        sc->eg_pcb[4] = 0;
        !           566:        sc->eg_pcb[5] = 0;
        !           567:        sc->eg_pcb[6] = len; /* length of packet */
        !           568:        sc->eg_pcb[7] = len >> 8;
        !           569:        if (egwritePCB(sc) != 0) {
        !           570:                DPRINTF(("egwritePCB in egstart failed\n"));
        !           571:                ifp->if_oerrors++;
        !           572:                ifp->if_flags &= ~IFF_OACTIVE;
        !           573:                m_freem(m0);
        !           574:                goto loop;
        !           575:        }
        !           576:
        !           577:        buffer = sc->eg_outbuf;
        !           578:        for (m = m0; m != 0; m = m->m_next) {
        !           579:                bcopy(mtod(m, caddr_t), buffer, m->m_len);
        !           580:                buffer += m->m_len;
        !           581:        }
        !           582:        if (len > m0->m_pkthdr.len)
        !           583:                bzero(buffer, len - m0->m_pkthdr.len);
        !           584:
        !           585:        /* set direction bit: host -> adapter */
        !           586:        bus_space_write_1(bst, bsh, EG_CONTROL,
        !           587:            bus_space_read_1(bst, bsh, EG_CONTROL) & ~EG_CTL_DIR);
        !           588:
        !           589:        for (ptr = (u_short *)sc->eg_outbuf; len > 0; len -= 2) {
        !           590:                bus_space_write_2(bst, bsh, EG_DATA, *ptr++);
        !           591:                for (i = 10000; i != 0; i--) {
        !           592:                        if (bus_space_read_1(bst, bsh, EG_STATUS) & EG_STAT_HRDY)
        !           593:                                break;
        !           594:                        delay(10);
        !           595:                }
        !           596:                if (i == 0) {
        !           597:                        printf("%s: start failed\n", sc->sc_dev.dv_xname);
        !           598:                        break;
        !           599:                }
        !           600:        }
        !           601:
        !           602:        m_freem(m0);
        !           603: }
        !           604:
        !           605: int
        !           606: egintr(arg)
        !           607:        void *arg;
        !           608: {
        !           609:        struct eg_softc *sc = arg;
        !           610:        bus_space_tag_t bst = sc->sc_bst;
        !           611:        bus_space_handle_t bsh = sc->sc_bsh;
        !           612:        int ret = 0;
        !           613:        int i, len;
        !           614:        u_short *ptr;
        !           615:
        !           616:        while (bus_space_read_1(bst, bsh, EG_STATUS) & EG_STAT_ACRF) {
        !           617:                ret = 1;
        !           618:                egreadPCB(sc);
        !           619:                switch (sc->eg_pcb[0]) {
        !           620:                case EG_RSP_RECVPACKET:
        !           621:                        len = sc->eg_pcb[6] | (sc->eg_pcb[7] << 8);
        !           622:
        !           623:                        /* Set direction bit : Adapter -> host */
        !           624:                        bus_space_write_1(bst, bsh, EG_CONTROL,
        !           625:                            bus_space_read_1(bst, bsh, EG_CONTROL) |
        !           626:                            EG_CTL_DIR);
        !           627:
        !           628:                        for (ptr = (u_short *)sc->eg_inbuf; len > 0; len -= 2) {
        !           629:                                for (i = 10000; i != 0; i--) {
        !           630:                                        if (bus_space_read_1(bst, bsh, EG_STATUS) & EG_STAT_HRDY)
        !           631:                                                break;
        !           632:                                        delay(10);
        !           633:                                }
        !           634:                                if (i == 0) {
        !           635:                                        printf("%s: receive failed\n",
        !           636:                                            sc->sc_dev.dv_xname);
        !           637:                                        break;
        !           638:                                }
        !           639:                                *ptr++ = bus_space_read_2(bst, bsh, EG_DATA);
        !           640:                        }
        !           641:
        !           642:                        if (len <= 0) {
        !           643:                                len = sc->eg_pcb[8] | (sc->eg_pcb[9] << 8);
        !           644:                                egread(sc, sc->eg_inbuf, len);
        !           645:
        !           646:                                sc->eg_incount--;
        !           647:                                egrecv(sc);
        !           648:                        }
        !           649:                        break;
        !           650:
        !           651:                case EG_RSP_SENDPACKET:
        !           652:                        if (sc->eg_pcb[6] || sc->eg_pcb[7]) {
        !           653:                                DPRINTF(("packet dropped\n"));
        !           654:                                sc->sc_arpcom.ac_if.if_oerrors++;
        !           655:                        } else
        !           656:                                sc->sc_arpcom.ac_if.if_opackets++;
        !           657:                        sc->sc_arpcom.ac_if.if_collisions +=
        !           658:                            sc->eg_pcb[8] & 0xf;
        !           659:                        sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
        !           660:                        egstart(&sc->sc_arpcom.ac_if);
        !           661:                        break;
        !           662:
        !           663:                case EG_RSP_GETSTATS:
        !           664:                        DPRINTF(("Card Statistics\n"));
        !           665:                        bcopy(&sc->eg_pcb[2], &i, sizeof(i));
        !           666:                        DPRINTF(("Receive Packets %d\n", i));
        !           667:                        bcopy(&sc->eg_pcb[6], &i, sizeof(i));
        !           668:                        DPRINTF(("Transmit Packets %d\n", i));
        !           669:                        DPRINTF(("CRC errors %d\n", *(short *)&sc->eg_pcb[10]));
        !           670:                        DPRINTF(("alignment errors %d\n",
        !           671:                            *(short *)&sc->eg_pcb[12]));
        !           672:                        DPRINTF(("no resources errors %d\n",
        !           673:                            *(short *)&sc->eg_pcb[14]));
        !           674:                        DPRINTF(("overrun errors %d\n",
        !           675:                            *(short *)&sc->eg_pcb[16]));
        !           676:                        break;
        !           677:
        !           678:                default:
        !           679:                        DPRINTF(("egintr: Unknown response %x??\n",
        !           680:                            sc->eg_pcb[0]));
        !           681:                        egprintpcb(sc);
        !           682:                        break;
        !           683:                }
        !           684:        }
        !           685:
        !           686:        return (ret);
        !           687: }
        !           688:
        !           689: /*
        !           690:  * Pass a packet up to the higher levels.
        !           691:  */
        !           692: void
        !           693: egread(sc, buf, len)
        !           694:        struct eg_softc *sc;
        !           695:        caddr_t buf;
        !           696:        int len;
        !           697: {
        !           698:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           699:        struct mbuf *m;
        !           700:
        !           701:        if (len <= sizeof(struct ether_header) ||
        !           702:            len > ETHER_MAX_LEN) {
        !           703:                printf("%s: invalid packet size %d; dropping\n",
        !           704:                    sc->sc_dev.dv_xname, len);
        !           705:                ifp->if_ierrors++;
        !           706:                return;
        !           707:        }
        !           708:
        !           709:        /* Pull packet off interface. */
        !           710:        m = egget(sc, buf, len);
        !           711:        if (m == 0) {
        !           712:                ifp->if_ierrors++;
        !           713:                return;
        !           714:        }
        !           715:
        !           716:        ifp->if_ipackets++;
        !           717:
        !           718: #if NBPFILTER > 0
        !           719:        /*
        !           720:         * Check if there's a BPF listener on this interface.
        !           721:         * If so, hand off the raw packet to BPF.
        !           722:         */
        !           723:        if (ifp->if_bpf)
        !           724:                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
        !           725: #endif
        !           726:
        !           727:        ether_input_mbuf(ifp, m);
        !           728: }
        !           729:
        !           730: /*
        !           731:  * convert buf into mbufs
        !           732:  */
        !           733: struct mbuf *
        !           734: egget(sc, buf, totlen)
        !           735:        struct eg_softc *sc;
        !           736:        caddr_t buf;
        !           737:        int totlen;
        !           738: {
        !           739:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           740:        struct mbuf *top, **mp, *m;
        !           741:        int len;
        !           742:
        !           743:        MGETHDR(m, M_DONTWAIT, MT_DATA);
        !           744:        if (m == 0)
        !           745:                return (0);
        !           746:        m->m_pkthdr.rcvif = ifp;
        !           747:        m->m_pkthdr.len = totlen;
        !           748:        len = MHLEN;
        !           749:        top = 0;
        !           750:        mp = &top;
        !           751:
        !           752:        while (totlen > 0) {
        !           753:                if (top) {
        !           754:                        MGET(m, M_DONTWAIT, MT_DATA);
        !           755:                        if (m == 0) {
        !           756:                                m_freem(top);
        !           757:                                return (0);
        !           758:                        }
        !           759:                        len = MLEN;
        !           760:                }
        !           761:                if (totlen >= MINCLSIZE) {
        !           762:                        MCLGET(m, M_DONTWAIT);
        !           763:                        if (m->m_flags & M_EXT)
        !           764:                                len = MCLBYTES;
        !           765:                }
        !           766:                m->m_len = len = min(totlen, len);
        !           767:                bcopy((caddr_t)buf, mtod(m, caddr_t), len);
        !           768:                buf += len;
        !           769:                totlen -= len;
        !           770:                *mp = m;
        !           771:                mp = &m->m_next;
        !           772:        }
        !           773:
        !           774:        return (top);
        !           775: }
        !           776:
        !           777: int
        !           778: egioctl(ifp, cmd, data)
        !           779:        register struct ifnet *ifp;
        !           780:        u_long cmd;
        !           781:        caddr_t data;
        !           782: {
        !           783:        struct eg_softc *sc = ifp->if_softc;
        !           784:        struct ifaddr *ifa = (struct ifaddr *)data;
        !           785:        int s, error = 0;
        !           786:
        !           787:        s = splnet();
        !           788:
        !           789:        if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
        !           790:                splx(s);
        !           791:                return (error);
        !           792:        }
        !           793:
        !           794:        switch (cmd) {
        !           795:
        !           796:        case SIOCSIFADDR:
        !           797:                ifp->if_flags |= IFF_UP;
        !           798:
        !           799:                switch (ifa->ifa_addr->sa_family) {
        !           800: #ifdef INET
        !           801:                case AF_INET:
        !           802:                        eginit(sc);
        !           803:                        arp_ifinit(&sc->sc_arpcom, ifa);
        !           804:                        break;
        !           805: #endif
        !           806:                default:
        !           807:                        eginit(sc);
        !           808:                        break;
        !           809:                }
        !           810:                break;
        !           811:
        !           812:        case SIOCSIFFLAGS:
        !           813:                if ((ifp->if_flags & IFF_UP) == 0 &&
        !           814:                    (ifp->if_flags & IFF_RUNNING) != 0) {
        !           815:                        /*
        !           816:                         * If interface is marked down and it is running, then
        !           817:                         * stop it.
        !           818:                         */
        !           819:                        egstop(sc);
        !           820:                        ifp->if_flags &= ~IFF_RUNNING;
        !           821:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
        !           822:                           (ifp->if_flags & IFF_RUNNING) == 0) {
        !           823:                        /*
        !           824:                         * If interface is marked up and it is stopped, then
        !           825:                         * start it.
        !           826:                         */
        !           827:                        eginit(sc);
        !           828:                } else {
        !           829:                        sc->eg_pcb[0] = EG_CMD_GETSTATS;
        !           830:                        sc->eg_pcb[1] = 0;
        !           831:                        if (egwritePCB(sc) != 0)
        !           832:                                DPRINTF(("write error\n"));
        !           833:                        /*
        !           834:                         * XXX deal with flags changes:
        !           835:                         * IFF_MULTICAST, IFF_PROMISC,
        !           836:                         * IFF_LINK0, IFF_LINK1,
        !           837:                         */
        !           838:                }
        !           839:                break;
        !           840:
        !           841:        default:
        !           842:                error = EINVAL;
        !           843:                break;
        !           844:        }
        !           845:
        !           846:        splx(s);
        !           847:        return (error);
        !           848: }
        !           849:
        !           850: void
        !           851: egreset(sc)
        !           852:        struct eg_softc *sc;
        !           853: {
        !           854:        int s;
        !           855:
        !           856:        DPRINTF(("egreset()\n"));
        !           857:        s = splnet();
        !           858:        egstop(sc);
        !           859:        eginit(sc);
        !           860:        splx(s);
        !           861: }
        !           862:
        !           863: void
        !           864: egwatchdog(ifp)
        !           865:        struct ifnet *ifp;
        !           866: {
        !           867:        struct eg_softc *sc = ifp->if_softc;
        !           868:
        !           869:        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
        !           870:        sc->sc_arpcom.ac_if.if_oerrors++;
        !           871:
        !           872:        egreset(sc);
        !           873: }
        !           874:
        !           875: void
        !           876: egstop(sc)
        !           877:        register struct eg_softc *sc;
        !           878: {
        !           879:        bus_space_tag_t bst = sc->sc_bst;
        !           880:        bus_space_handle_t bsh = sc->sc_bsh;
        !           881:
        !           882:        bus_space_write_1(bst, bsh, EG_CONTROL, 0);
        !           883: }

CVSweb