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

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

1.1     ! nbrk        1: /*     $OpenBSD: if_ec.c,v 1.10 2006/10/20 17:02:24 brad Exp $ */
        !             2: /*     $NetBSD: if_ec.c,v 1.9 1998/07/05 06:49:12 jonathan Exp $       */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
        !            10:  * NASA Ames Research Center.
        !            11:  *
        !            12:  * Redistribution and use in source and binary forms, with or without
        !            13:  * modification, are permitted provided that the following conditions
        !            14:  * are met:
        !            15:  * 1. Redistributions of source code must retain the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer.
        !            17:  * 2. Redistributions in binary form must reproduce the above copyright
        !            18:  *    notice, this list of conditions and the following disclaimer in the
        !            19:  *    documentation and/or other materials provided with the distribution.
        !            20:  * 3. All advertising materials mentioning features or use of this software
        !            21:  *    must display the following acknowledgement:
        !            22:  *     This product includes software developed by the NetBSD
        !            23:  *     Foundation, Inc. and its contributors.
        !            24:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            25:  *    contributors may be used to endorse or promote products derived
        !            26:  *    from this software without specific prior written permission.
        !            27:  *
        !            28:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            29:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            30:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            31:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            32:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            33:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            34:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            35:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            36:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            37:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            38:  * POSSIBILITY OF SUCH DAMAGE.
        !            39:  */
        !            40:
        !            41: /*
        !            42:  * Device driver for National Semiconductor DS8390/WD83C690 based ethernet
        !            43:  * adapters.
        !            44:  *
        !            45:  * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
        !            46:  *
        !            47:  * Copyright (C) 1993, David Greenman.  This software may be used, modified,
        !            48:  * copied, distributed, and sold, in both source and binary form provided that
        !            49:  * the above copyright and these terms are retained.  Under no circumstances is
        !            50:  * the author responsible for the proper functioning of this software, nor does
        !            51:  * the author assume any responsibility for damages incurred with its use.
        !            52:  */
        !            53:
        !            54: /*
        !            55:  * Device driver for the 3Com Etherlink II (3c503).
        !            56:  */
        !            57:
        !            58: #include "bpfilter.h"
        !            59:
        !            60: #include <sys/param.h>
        !            61: #include <sys/systm.h>
        !            62: #include <sys/device.h>
        !            63: #include <sys/socket.h>
        !            64: #include <sys/mbuf.h>
        !            65: #include <sys/syslog.h>
        !            66:
        !            67: #include <net/if.h>
        !            68: #include <net/if_dl.h>
        !            69: #include <net/if_types.h>
        !            70: #include <net/if_media.h>
        !            71:
        !            72: #ifdef INET
        !            73: #include <netinet/in.h>
        !            74: #include <netinet/in_systm.h>
        !            75: #include <netinet/in_var.h>
        !            76: #include <netinet/ip.h>
        !            77: #include <netinet/if_ether.h>
        !            78: #endif
        !            79:
        !            80: #if NBPFILTER > 0
        !            81: #include <net/bpf.h>
        !            82: #endif
        !            83:
        !            84: #include <machine/bus.h>
        !            85: #include <machine/intr.h>
        !            86:
        !            87: #include <dev/isa/isareg.h>
        !            88: #include <dev/isa/isavar.h>
        !            89:
        !            90: #include <dev/ic/dp8390reg.h>
        !            91: #include <dev/ic/dp8390var.h>
        !            92:
        !            93: #include <dev/isa/if_ecreg.h>
        !            94:
        !            95: struct ec_softc {
        !            96:        struct dp8390_softc sc_dp8390;
        !            97:
        !            98:        bus_space_tag_t sc_asict;       /* space tag for ASIC */
        !            99:        bus_space_handle_t sc_asich;    /* space handle for ASIC */
        !           100:
        !           101:        int sc_16bitp;                  /* are we 16 bit? */
        !           102:
        !           103:        void *sc_ih;                    /* interrupt handle */
        !           104: };
        !           105:
        !           106: int    ec_probe(struct device *, void *, void *);
        !           107: void   ec_attach(struct device *, struct device *, void *);
        !           108:
        !           109: struct cfattach ec_ca = {
        !           110:        sizeof(struct ec_softc), ec_probe, ec_attach
        !           111: };
        !           112:
        !           113: int    ec_set_media(struct ec_softc *, int);
        !           114:
        !           115: void   ec_media_init(struct dp8390_softc *);
        !           116:
        !           117: int    ec_mediachange(struct dp8390_softc *);
        !           118: void   ec_mediastatus(struct dp8390_softc *, struct ifmediareq *);
        !           119:
        !           120: void   ec_init_card(struct dp8390_softc *);
        !           121: int    ec_write_mbuf(struct dp8390_softc *, struct mbuf *, int);
        !           122: int    ec_ring_copy(struct dp8390_softc *, int, caddr_t, u_short);
        !           123: void   ec_read_hdr(struct dp8390_softc *, int, struct dp8390_ring *);
        !           124: int    ec_fake_test_mem(struct dp8390_softc *);
        !           125: int    ec_test_mem(struct dp8390_softc *);
        !           126:
        !           127: __inline void ec_readmem(struct ec_softc *, int, u_int8_t *, int);
        !           128:
        !           129: static const int ec_iobase[] = {
        !           130:        0x2e0, 0x2a0, 0x280, 0x250, 0x350, 0x330, 0x310, 0x300,
        !           131: };
        !           132: #define        NEC_IOBASE      (sizeof(ec_iobase) / sizeof(ec_iobase[0]))
        !           133:
        !           134: static const int ec_membase[] = {
        !           135:        MADDRUNK, MADDRUNK, MADDRUNK, MADDRUNK, 0xc8000, 0xcc000,
        !           136:        0xd8000, 0xdc000,
        !           137: };
        !           138: #define        NEC_MEMBASE     (sizeof(ec_membase) / sizeof(ec_membase[0]))
        !           139:
        !           140: struct cfdriver ec_cd = {
        !           141:        NULL, "ec", DV_IFNET
        !           142: };
        !           143:
        !           144: int
        !           145: ec_probe(struct device *parent, void *match, void *aux)
        !           146: {
        !           147:        struct isa_attach_args *ia = aux;
        !           148:        bus_space_tag_t nict, asict, memt;
        !           149:        bus_space_handle_t nich, asich, memh;
        !           150:        bus_size_t memsize;
        !           151:        int nich_valid, asich_valid, memh_valid;
        !           152:        int i, rv = 0;
        !           153:        u_int8_t x;
        !           154:
        !           155:        nict = asict = ia->ia_iot;
        !           156:        memt = ia->ia_memt;
        !           157:
        !           158:        nich_valid = asich_valid = memh_valid = 0;
        !           159:
        !           160:        /*
        !           161:         * Hmm, a 16-bit card has 16k of memory, but only an 8k window
        !           162:         * to it.
        !           163:         */
        !           164:        memsize = 8192;
        !           165:
        !           166:        /* Disallow wildcarded i/o addresses. */
        !           167:        if (ia->ia_iobase == -1 /* ISACF_PORT_DEFAULT */)
        !           168:                return (0);
        !           169:
        !           170:        /* Disallow wildcarded mem address. */
        !           171:        if (ia->ia_maddr == -1 /* ISACF_IOMEM_DEFAULT */)
        !           172:                return (0);
        !           173:
        !           174:        /* Validate the i/o base. */
        !           175:        for (i = 0; i < NEC_IOBASE; i++)
        !           176:                if (ia->ia_iobase == ec_iobase[i])
        !           177:                        break;
        !           178:        if (i == NEC_IOBASE)
        !           179:                return (0);
        !           180:
        !           181:        /* Validate the mem base. */
        !           182:        for (i = 0; i < NEC_MEMBASE; i++) {
        !           183:                if (ec_membase[i] == MADDRUNK)
        !           184:                        continue;
        !           185:                if (ia->ia_maddr == ec_membase[i])
        !           186:                        break;
        !           187:        }
        !           188:        if (i == NEC_MEMBASE)
        !           189:                return (0);
        !           190:
        !           191:        /* Attempt to map the NIC space. */
        !           192:        if (bus_space_map(nict, ia->ia_iobase + ELINK2_NIC_OFFSET,
        !           193:            ELINK2_NIC_PORTS, 0, &nich))
        !           194:                goto out;
        !           195:        nich_valid = 1;
        !           196:
        !           197:        /* Attempt to map the ASIC space. */
        !           198:        if (bus_space_map(asict, ia->ia_iobase + ELINK2_ASIC_OFFSET,
        !           199:            ELINK2_ASIC_PORTS, 0, &asich))
        !           200:                goto out;
        !           201:        asich_valid = 1;
        !           202:
        !           203:        /* Attempt to map the memory space. */
        !           204:        if (bus_space_map(memt, ia->ia_maddr, memsize, 0, &memh))
        !           205:                goto out;
        !           206:        memh_valid = 1;
        !           207:
        !           208:        /*
        !           209:         * Verify that the kernel configured I/O address matches the
        !           210:         * board configured I/O address.
        !           211:         *
        !           212:         * This is really only useful to see if something that looks like
        !           213:         * the board is there; after all, we're already talking to it at
        !           214:         * this point.
        !           215:         */
        !           216:        x = bus_space_read_1(asict, asich, ELINK2_BCFR);
        !           217:        if (x == 0 || (x & (x - 1)) != 0)
        !           218:                goto out;
        !           219:        i = ffs(x) - 1;
        !           220:        if (ia->ia_iobase != ec_iobase[i])
        !           221:                goto out;
        !           222:
        !           223:        /*
        !           224:         * ...and for the memory address.  Note we do not support
        !           225:         * cards configured with shared memory disabled.
        !           226:         */
        !           227:        x = bus_space_read_1(asict, asich, ELINK2_PCFR);
        !           228:        if (x == 0 || (x & (x - 1)) != 0)
        !           229:                goto out;
        !           230:        i = ffs(x) - 1;
        !           231:        if (ia->ia_maddr != ec_membase[i])
        !           232:                goto out;
        !           233:
        !           234:        /* So, we say we've found it! */
        !           235:        ia->ia_iosize = ELINK2_NIC_PORTS;
        !           236:        ia->ia_msize = memsize;
        !           237:        rv = 1;
        !           238:
        !           239:  out:
        !           240:        if (nich_valid)
        !           241:                bus_space_unmap(nict, nich, ELINK2_NIC_PORTS);
        !           242:        if (asich_valid)
        !           243:                bus_space_unmap(asict, asich, ELINK2_ASIC_PORTS);
        !           244:        if (memh_valid)
        !           245:                bus_space_unmap(memt, memh, memsize);
        !           246:        return (rv);
        !           247: }
        !           248:
        !           249: void
        !           250: ec_attach(struct device *parent, struct device *self, void *aux)
        !           251: {
        !           252:        struct ec_softc *esc = (struct ec_softc *)self;
        !           253:        struct dp8390_softc *sc = &esc->sc_dp8390;
        !           254:        struct isa_attach_args *ia = aux;
        !           255:        bus_space_tag_t nict, asict, memt;
        !           256:        bus_space_handle_t nich, asich, memh;
        !           257:        bus_size_t memsize;
        !           258:        u_int8_t tmp;
        !           259:        int i;
        !           260:
        !           261:        printf("\n");
        !           262:
        !           263:        nict = asict = ia->ia_iot;
        !           264:        memt = ia->ia_memt;
        !           265:
        !           266:        /*
        !           267:         * Hmm, a 16-bit card has 16k of memory, but only an 8k window
        !           268:         * to it.
        !           269:         */
        !           270:        memsize = 8192;
        !           271:
        !           272:        /* Map the NIC space. */
        !           273:        if (bus_space_map(nict, ia->ia_iobase + ELINK2_NIC_OFFSET,
        !           274:            ELINK2_NIC_PORTS, 0, &nich)) {
        !           275:                printf("%s: can't map nic i/o space\n",
        !           276:                    sc->sc_dev.dv_xname);
        !           277:                return;
        !           278:        }
        !           279:
        !           280:        /* Map the ASIC space. */
        !           281:        if (bus_space_map(asict, ia->ia_iobase + ELINK2_ASIC_OFFSET,
        !           282:            ELINK2_ASIC_PORTS, 0, &asich)) {
        !           283:                printf("%s: can't map asic i/o space\n",
        !           284:                    sc->sc_dev.dv_xname);
        !           285:                return;
        !           286:        }
        !           287:
        !           288:        /* Map the memory space. */
        !           289:        if (bus_space_map(memt, ia->ia_maddr, memsize, 0, &memh)) {
        !           290:                printf("%s: can't map shared memory\n",
        !           291:                    sc->sc_dev.dv_xname);
        !           292:                return;
        !           293:        }
        !           294:
        !           295:        esc->sc_asict = asict;
        !           296:        esc->sc_asich = asich;
        !           297:
        !           298:        sc->sc_regt = nict;
        !           299:        sc->sc_regh = nich;
        !           300:
        !           301:        sc->sc_buft = memt;
        !           302:        sc->sc_bufh = memh;
        !           303:
        !           304:        /* Interface is always enabled. */
        !           305:        sc->sc_enabled = 1;
        !           306:
        !           307:        /* Registers are linear. */
        !           308:        for (i = 0; i < 16; i++)
        !           309:                sc->sc_reg_map[i] = i;
        !           310:
        !           311:        /* Now we can use the NIC_{GET,PUT}() macros. */
        !           312:
        !           313:        /*
        !           314:         * Reset NIC and ASIC.  Enable on-board transeiver throughout
        !           315:         * reset sequence since it will lock up if the cable isn't
        !           316:         * connected if we don't.
        !           317:         */
        !           318:        bus_space_write_1(asict, asich, ELINK2_CR,
        !           319:            ELINK2_CR_RST | ELINK2_CR_XSEL);
        !           320:
        !           321:        /* Wait for a while, then un-reset it. */
        !           322:        delay(50);
        !           323:
        !           324:        /*
        !           325:         * The 3Com ASIC defaults to rather strange settings for the CR
        !           326:         * after a reset.  It's important to set it again after the
        !           327:         * following write (this is done when we map the PROM below).
        !           328:         */
        !           329:        bus_space_write_1(asict, asich, ELINK2_CR, ELINK2_CR_XSEL);
        !           330:
        !           331:        /* Wait a bit for the NIC to recover from the reset. */
        !           332:        delay(5000);
        !           333:
        !           334:        /*
        !           335:         * Get the station address from on-board ROM.
        !           336:         *
        !           337:         * First, map Ethernet address PROM over the top of where the NIC
        !           338:         * registers normally appear.
        !           339:         */
        !           340:        bus_space_write_1(asict, asich, ELINK2_CR,
        !           341:            ELINK2_CR_XSEL | ELINK2_CR_EALO);
        !           342:
        !           343:        for (i = 0; i < ETHER_ADDR_LEN; i++)
        !           344:                sc->sc_arpcom.ac_enaddr[i] = NIC_GET(nict, nich, i);
        !           345:
        !           346:        /*
        !           347:         * Unmap PROM - select NIC registers.  The proper setting of the
        !           348:         * transciever is set in later in ec_init_card() via dp8390_init().
        !           349:         */
        !           350:        bus_space_write_1(asict, asich, ELINK2_CR, ELINK2_CR_XSEL);
        !           351:
        !           352:        /* Determine if this is an 8-bit or 16-bit board. */
        !           353:
        !           354:        /* Select page 0 registers. */
        !           355:        NIC_PUT(nict, nich, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
        !           356:
        !           357:        /*
        !           358:         * Attempt to clear WTS.  If it doesn't clear, then this is a
        !           359:         * 16-bit board.
        !           360:         */
        !           361:        NIC_PUT(nict, nich, ED_P0_DCR, 0);
        !           362:
        !           363:        /* Select page 2 registers. */
        !           364:        NIC_PUT(nict, nich, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_2 | ED_CR_STP);
        !           365:
        !           366:        /* The 3c503 forces the WTS bit to a one if this is a 16-bit board. */
        !           367:        if (NIC_GET(nict, nich, ED_P2_DCR) & ED_DCR_WTS)
        !           368:                esc->sc_16bitp = 1;
        !           369:        else
        !           370:                esc->sc_16bitp = 0;
        !           371:
        !           372:        printf("%s: 3Com 3c503 Ethernet (%s-bit)",
        !           373:            sc->sc_dev.dv_xname, esc->sc_16bitp ? "16" : "8");
        !           374:
        !           375:        /* Select page 0 registers. */
        !           376:        NIC_PUT(nict, nich, ED_P2_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
        !           377:
        !           378:        sc->cr_proto = ED_CR_RD2;
        !           379:
        !           380:        /*
        !           381:         * DCR gets:
        !           382:         *
        !           383:         *      FIFO threshold to 8, No auto-init Remote DMA,
        !           384:         *      byte order=80x86.
        !           385:         *
        !           386:         * 16-bit cards also get word-wide DMA transfers.
        !           387:         */
        !           388:        sc->dcr_reg = ED_DCR_FT1 | ED_DCR_LS |
        !           389:            (esc->sc_16bitp ? ED_DCR_WTS : 0);
        !           390:
        !           391:        sc->test_mem = ec_fake_test_mem;
        !           392:        sc->ring_copy = ec_ring_copy;
        !           393:        sc->write_mbuf = ec_write_mbuf;
        !           394:        sc->read_hdr = ec_read_hdr;
        !           395:
        !           396:        sc->sc_media_init = ec_media_init;
        !           397:
        !           398:        sc->sc_mediachange = ec_mediachange;
        !           399:        sc->sc_mediastatus = ec_mediastatus;
        !           400:
        !           401:        sc->mem_start = 0;
        !           402:        sc->mem_size = memsize;
        !           403:
        !           404:        /* Do generic parts of attach. */
        !           405:        if (dp8390_config(sc)) {
        !           406:                printf(": configuration failed\n");
        !           407:                return;
        !           408:        }
        !           409:
        !           410:        /*
        !           411:         * We need to override the way dp8390_config() set up our
        !           412:         * shared memory.
        !           413:         *
        !           414:         * We have an entire 8k window to put the transmit buffers on the
        !           415:         * 16-bit boards.  But since the 16bit 3c503's shared memory is only
        !           416:         * fast enough to overlap the loading of one full-size packet, trying
        !           417:         * to load more than 2 buffers can actually leave the transmitter idle
        !           418:         * during the load.  So 2 seems the best value.  (Although a mix of
        !           419:         * variable-sized packets might change this assumption.  Nonetheless,
        !           420:         * we optimize for linear transfers of same-size packets.)
        !           421:         */
        !           422:        if (esc->sc_16bitp) {
        !           423:                if (sc->sc_dev.dv_cfdata->cf_flags & DP8390_NO_MULTI_BUFFERING)
        !           424:                        sc->txb_cnt = 1;
        !           425:                else
        !           426:                        sc->txb_cnt = 2;
        !           427:
        !           428:                sc->tx_page_start = ELINK2_TX_PAGE_OFFSET_16BIT;
        !           429:                sc->rec_page_start = ELINK2_RX_PAGE_OFFSET_16BIT;
        !           430:                sc->rec_page_stop = (memsize >> ED_PAGE_SHIFT) +
        !           431:                    sc->rec_page_start;
        !           432:                sc->mem_ring = sc->mem_start;
        !           433:        } else {
        !           434:                sc->txb_cnt = 1;
        !           435:                sc->tx_page_start = ELINK2_TX_PAGE_OFFSET_8BIT;
        !           436:                sc->rec_page_start = sc->tx_page_start + ED_TXBUF_SIZE;
        !           437:                sc->rec_page_stop = (memsize >> ED_PAGE_SHIFT) +
        !           438:                    sc->tx_page_start;
        !           439:                sc->mem_ring = sc->mem_start +
        !           440:                    (ED_TXBUF_SIZE << ED_PAGE_SHIFT);
        !           441:        }
        !           442:
        !           443:        /*
        !           444:         * Initialize CA page start/stop registers.  Probably only needed
        !           445:         * if doing DMA, but what the Hell.
        !           446:         */
        !           447:        bus_space_write_1(asict, asich, ELINK2_PSTR, sc->rec_page_start);
        !           448:        bus_space_write_1(asict, asich, ELINK2_PSPR, sc->rec_page_stop);
        !           449:
        !           450:        /*
        !           451:         * Program the IRQ.
        !           452:         */
        !           453:        switch (ia->ia_irq) {
        !           454:        case 9: tmp = ELINK2_IDCFR_IRQ2; break;
        !           455:        case 3: tmp = ELINK2_IDCFR_IRQ3; break;
        !           456:        case 4: tmp = ELINK2_IDCFR_IRQ4; break;
        !           457:        case 5: tmp = ELINK2_IDCFR_IRQ5; break;
        !           458:                break;
        !           459:
        !           460:        case IRQUNK:
        !           461:                printf("%s: wildcarded IRQ is not allowed\n",
        !           462:                    sc->sc_dev.dv_xname);
        !           463:                return;
        !           464:
        !           465:        default:
        !           466:                printf("%s: invalid IRQ %d, must be 3, 4, 5, or 9\n",
        !           467:                    sc->sc_dev.dv_xname, ia->ia_irq);
        !           468:                return;
        !           469:        }
        !           470:
        !           471:        bus_space_write_1(asict, asich, ELINK2_IDCFR, tmp);
        !           472:
        !           473:        /*
        !           474:         * Initialize the GA configuration register.  Set bank and enable
        !           475:         * shared memory.
        !           476:         */
        !           477:        bus_space_write_1(asict, asich, ELINK2_GACFR,
        !           478:            ELINK2_GACFR_RSEL | ELINK2_GACFR_MBS0);
        !           479:
        !           480:        /*
        !           481:         * Intialize "Vector Pointer" registers.  These gawd-awful things
        !           482:         * are compared to 20 bits of the address on the ISA, and if they
        !           483:         * match, the shared memory is disabled.  We se them to 0xffff0...
        !           484:         * allegedly the reset vector.
        !           485:         */
        !           486:        bus_space_write_1(asict, asich, ELINK2_VPTR2, 0xff);
        !           487:        bus_space_write_1(asict, asich, ELINK2_VPTR1, 0xff);
        !           488:        bus_space_write_1(asict, asich, ELINK2_VPTR0, 0x00);
        !           489:
        !           490:        /*
        !           491:         * Now run the real memory test.
        !           492:         */
        !           493:        if (ec_test_mem(sc)) {
        !           494:                printf("%s: memory test failed\n", sc->sc_dev.dv_xname);
        !           495:                return;
        !           496:        }
        !           497:
        !           498:        /* Establish interrupt handler. */
        !           499:        esc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
        !           500:            IPL_NET, dp8390_intr, sc, sc->sc_dev.dv_xname);
        !           501:        if (esc->sc_ih == NULL)
        !           502:                printf("%s: can't establish interrupt\n", sc->sc_dev.dv_xname);
        !           503: }
        !           504:
        !           505: int
        !           506: ec_fake_test_mem(struct dp8390_softc *sc)
        !           507: {
        !           508:        /*
        !           509:         * We have to do this after we initialize the GA, but we
        !           510:         * have to do that after calling dp8390_config(), which
        !           511:         * wants to test memory.  Put this noop here, and then
        !           512:         * actually test memory later.
        !           513:         */
        !           514:        return (0);
        !           515: }
        !           516:
        !           517: int
        !           518: ec_test_mem(struct dp8390_softc *sc)
        !           519: {
        !           520:        struct ec_softc *esc = (struct ec_softc *)sc;
        !           521:        bus_space_tag_t memt = sc->sc_buft;
        !           522:        bus_space_handle_t memh = sc->sc_bufh;
        !           523:        bus_size_t memsize = sc->mem_size;
        !           524:        int i;
        !           525:
        !           526:        if (esc->sc_16bitp)
        !           527:                bus_space_set_region_2(memt, memh, 0, 0, memsize >> 1);
        !           528:        else
        !           529:                bus_space_set_region_1(memt, memh, 0, 0, memsize);
        !           530:
        !           531:        if (esc->sc_16bitp) {
        !           532:                for (i = 0; i < memsize; i += 2) {
        !           533:                        if (bus_space_read_2(memt, memh, i) != 0)
        !           534:                                goto fail;
        !           535:                }
        !           536:        } else {
        !           537:                for (i = 0; i < memsize; i++) {
        !           538:                        if (bus_space_read_1(memt, memh, i) != 0)
        !           539:                                goto fail;
        !           540:                }
        !           541:        }
        !           542:
        !           543:        return (0);
        !           544:
        !           545:  fail:
        !           546:        printf("%s: failed to clear shared memory at offset 0x%x\n",
        !           547:            sc->sc_dev.dv_xname, i);
        !           548:        return (1);
        !           549: }
        !           550:
        !           551: /*
        !           552:  * Given a NIC memory source address and a host memory destination address,
        !           553:  * copy 'len' from NIC to host using shared memory.  The 'len' is rounded
        !           554:  * up to a word - ok as long as mbufs are word-sized.
        !           555:  */
        !           556: __inline void
        !           557: ec_readmem(struct ec_softc *esc, int from, u_int8_t *to, int len)
        !           558: {
        !           559:        bus_space_tag_t memt = esc->sc_dp8390.sc_buft;
        !           560:        bus_space_handle_t memh = esc->sc_dp8390.sc_bufh;
        !           561:
        !           562:        if (len & 1)
        !           563:                ++len;
        !           564:
        !           565:        if (esc->sc_16bitp)
        !           566:                bus_space_read_region_2(memt, memh, from, (u_int16_t *)to,
        !           567:                    len >> 1);
        !           568:        else
        !           569:                bus_space_read_region_1(memt, memh, from, to, len);
        !           570: }
        !           571:
        !           572: int
        !           573: ec_write_mbuf(struct dp8390_softc *sc, struct mbuf *m, int buf)
        !           574: {
        !           575:        struct ec_softc *esc = (struct ec_softc *)sc;
        !           576:        bus_space_tag_t asict = esc->sc_asict;
        !           577:        bus_space_handle_t asich = esc->sc_asich;
        !           578:        bus_space_tag_t memt = esc->sc_dp8390.sc_buft;
        !           579:        bus_space_handle_t memh = esc->sc_dp8390.sc_bufh;
        !           580:        u_int8_t *data, savebyte[2];
        !           581:        int savelen, len, leftover;
        !           582: #ifdef DIAGNOSTIC
        !           583:        u_int8_t *lim;
        !           584: #endif
        !           585:
        !           586:        savelen = m->m_pkthdr.len;
        !           587:
        !           588:        /*
        !           589:         * 8-bit boards are simple: we're already in the correct
        !           590:         * page, and no alignment tricks are necessary.
        !           591:         */
        !           592:        if (esc->sc_16bitp == 0) {
        !           593:                for (; m != NULL; buf += m->m_len, m = m->m_next)
        !           594:                        bus_space_write_region_1(memt, memh, buf,
        !           595:                            mtod(m, u_int8_t *), m->m_len);
        !           596:                return (savelen);
        !           597:        }
        !           598:
        !           599:        /*
        !           600:         * If it's a 16-bit board, we have transmit buffers
        !           601:         * in a different page; switch to it.
        !           602:         */
        !           603:        if (esc->sc_16bitp)
        !           604:                bus_space_write_1(asict, asich, ELINK2_GACFR,
        !           605:                    ELINK2_GACFR_RSEL);
        !           606:
        !           607:        /* Start out with no leftover data. */
        !           608:        leftover = 0;
        !           609:        savebyte[0] = savebyte[1] = 0;
        !           610:
        !           611:        for (; m != NULL; m = m->m_next) {
        !           612:                len = m->m_len;
        !           613:                if (len == 0)
        !           614:                        continue;
        !           615:                data = mtod(m, u_int8_t *);
        !           616: #ifdef DIAGNOSTIC
        !           617:                lim = data + len;
        !           618: #endif
        !           619:                while (len > 0) {
        !           620:                        if (leftover) {
        !           621:                                /*
        !           622:                                 * Data left over (from mbuf or realignment).
        !           623:                                 * Buffer the next byte, and write it and
        !           624:                                 * the leftover data out.
        !           625:                                 */
        !           626:                                savebyte[1] = *data++;
        !           627:                                len--;
        !           628:                                bus_space_write_2(memt, memh, buf,
        !           629:                                    *(u_int16_t *)savebyte);
        !           630:                                buf += 2;
        !           631:                                leftover = 0;
        !           632:                        } else if (ALIGNED_POINTER(data, u_int16_t) == 0) {
        !           633:                                /*
        !           634:                                 * Unaligned data; buffer the next byte.
        !           635:                                 */
        !           636:                                savebyte[0] = *data++;
        !           637:                                len--;
        !           638:                                leftover = 1;
        !           639:                        } else {
        !           640:                                /*
        !           641:                                 * Aligned data; output contiguous words as
        !           642:                                 * much as we can, then buffer the remaining
        !           643:                                 * byte, if any.
        !           644:                                 */
        !           645:                                leftover = len & 1;
        !           646:                                len &= ~1;
        !           647:                                bus_space_write_region_2(memt, memh, buf,
        !           648:                                    (u_int16_t *)data, len >> 1);
        !           649:                                data += len;
        !           650:                                buf += len;
        !           651:                                if (leftover)
        !           652:                                        savebyte[0] = *data++;
        !           653:                                len = 0;
        !           654:                        }
        !           655:                }
        !           656:                if (len < 0)
        !           657:                        panic("ec_write_mbuf: negative len");
        !           658: #ifdef DIAGNOSTIC
        !           659:                if (data != lim)
        !           660:                        panic("ec_write_mbuf: data != lim");
        !           661: #endif
        !           662:        }
        !           663:        if (leftover) {
        !           664:                savebyte[1] = 0;
        !           665:                bus_space_write_2(memt, memh, buf, *(u_int16_t *)savebyte);
        !           666:        }
        !           667:
        !           668:        /*
        !           669:         * Switch back to receive page.
        !           670:         */
        !           671:        if (esc->sc_16bitp)
        !           672:                bus_space_write_1(asict, asich, ELINK2_GACFR,
        !           673:                    ELINK2_GACFR_RSEL | ELINK2_GACFR_MBS0);
        !           674:
        !           675:        return (savelen);
        !           676: }
        !           677:
        !           678: int
        !           679: ec_ring_copy(struct dp8390_softc *sc, int src, caddr_t dst,
        !           680:     u_short amount)
        !           681: {
        !           682:        struct ec_softc *esc = (struct ec_softc *)sc;
        !           683:        u_short tmp_amount;
        !           684:
        !           685:        /* Does copy wrap to lower addr in ring buffer? */
        !           686:        if (src + amount > sc->mem_end) {
        !           687:                tmp_amount = sc->mem_end - src;
        !           688:
        !           689:                /* Copy amount up to end of NIC memory. */
        !           690:                ec_readmem(esc, src, dst, tmp_amount);
        !           691:
        !           692:                amount -= tmp_amount;
        !           693:                src = sc->mem_ring;
        !           694:                dst += tmp_amount;
        !           695:        }
        !           696:
        !           697:        ec_readmem(esc, src, dst, amount);
        !           698:
        !           699:        return (src + amount);
        !           700: }
        !           701:
        !           702: void
        !           703: ec_read_hdr(struct dp8390_softc *sc, int packet_ptr,
        !           704:     struct dp8390_ring *packet_hdrp)
        !           705: {
        !           706:        struct ec_softc *esc = (struct ec_softc *)sc;
        !           707:
        !           708:        ec_readmem(esc, packet_ptr, (u_int8_t *)packet_hdrp,
        !           709:            sizeof(struct dp8390_ring));
        !           710: #if BYTE_ORDER == BIG_ENDIAN
        !           711:        packet_hdrp->count = swap16(packet_hdrp->count);
        !           712: #endif
        !           713: }
        !           714:
        !           715: void
        !           716: ec_media_init(struct dp8390_softc *sc)
        !           717: {
        !           718:        ifmedia_init(&sc->sc_media, 0, dp8390_mediachange, dp8390_mediastatus);
        !           719:        ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_10_2, 0, NULL);
        !           720:        ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_10_5, 0, NULL);
        !           721:        ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_10_2);
        !           722: }
        !           723:
        !           724: int
        !           725: ec_mediachange(struct dp8390_softc *sc)
        !           726: {
        !           727:        struct ec_softc *esc = (struct ec_softc *)sc;
        !           728:        struct ifmedia *ifm = &sc->sc_media;
        !           729:
        !           730:        return (ec_set_media(esc, ifm->ifm_media));
        !           731: }
        !           732:
        !           733: void
        !           734: ec_mediastatus(struct dp8390_softc *sc, struct ifmediareq *ifmr)
        !           735: {
        !           736:        struct ifmedia *ifm = &sc->sc_media;
        !           737:
        !           738:        /*
        !           739:         * The currently selected media is always the active media.
        !           740:         */
        !           741:        ifmr->ifm_active = ifm->ifm_cur->ifm_media;
        !           742: }
        !           743:
        !           744: void
        !           745: ec_init_card(struct dp8390_softc *sc)
        !           746: {
        !           747:        struct ec_softc *esc = (struct ec_softc *)sc;
        !           748:        struct ifmedia *ifm = &sc->sc_media;
        !           749:
        !           750:        (void) ec_set_media(esc, ifm->ifm_cur->ifm_media);
        !           751: }
        !           752:
        !           753: int
        !           754: ec_set_media(struct ec_softc *esc, int media)
        !           755: {
        !           756:        u_int8_t new;
        !           757:
        !           758:        if (IFM_TYPE(media) != IFM_ETHER)
        !           759:                return (EINVAL);
        !           760:
        !           761:        switch (IFM_SUBTYPE(media)) {
        !           762:        case IFM_10_2:
        !           763:                new = ELINK2_CR_XSEL;
        !           764:                break;
        !           765:
        !           766:        case IFM_10_5:
        !           767:                new = 0;
        !           768:                break;
        !           769:
        !           770:        default:
        !           771:                return (EINVAL);
        !           772:        }
        !           773:
        !           774:        bus_space_write_1(esc->sc_asict, esc->sc_asich, ELINK2_CR, new);
        !           775:        return (0);
        !           776: }

CVSweb