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

Annotation of sys/dev/ic/ne2000.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: ne2000.c,v 1.23 2006/11/07 01:46:59 brad Exp $        */
        !             2: /*     $NetBSD: ne2000.c,v 1.12 1998/06/10 01:15:50 thorpej 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:  * Common code shared by all NE2000-compatible Ethernet interfaces.
        !            56:  */
        !            57:
        !            58: #include <sys/param.h>
        !            59: #include <sys/systm.h>
        !            60: #include <sys/device.h>
        !            61: #include <sys/socket.h>
        !            62: #include <sys/mbuf.h>
        !            63: #include <sys/syslog.h>
        !            64:
        !            65: #include <net/if.h>
        !            66: #include <net/if_dl.h>
        !            67: #include <net/if_types.h>
        !            68: #include <net/if_media.h>
        !            69:
        !            70: #include <netinet/in.h>
        !            71: #include <netinet/if_ether.h>
        !            72:
        !            73: #include <machine/bus.h>
        !            74:
        !            75: #include <dev/ic/dp8390reg.h>
        !            76: #include <dev/ic/dp8390var.h>
        !            77:
        !            78: #include <dev/ic/ne2000reg.h>
        !            79: #include <dev/ic/ne2000var.h>
        !            80:
        !            81: #include <dev/ic/ax88190reg.h>
        !            82:
        !            83: int    ne2000_write_mbuf(struct dp8390_softc *, struct mbuf *, int);
        !            84: int    ne2000_ring_copy(struct dp8390_softc *, int, caddr_t, u_short);
        !            85: void   ne2000_read_hdr(struct dp8390_softc *, int, struct dp8390_ring *);
        !            86: int    ne2000_test_mem(struct dp8390_softc *);
        !            87:
        !            88: void   ne2000_writemem(bus_space_tag_t, bus_space_handle_t,
        !            89:            bus_space_tag_t, bus_space_handle_t, u_int8_t *, int, size_t, int);
        !            90: void   ne2000_readmem(bus_space_tag_t, bus_space_handle_t,
        !            91:            bus_space_tag_t, bus_space_handle_t, int, u_int8_t *, size_t, int);
        !            92:
        !            93: #define ASIC_BARRIER(asict, asich) \
        !            94:        bus_space_barrier((asict), (asich), 0, 0x10, \
        !            95:            BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)
        !            96:
        !            97: struct cfdriver ne_cd = {
        !            98:        NULL, "ne", DV_IFNET
        !            99: };
        !           100:
        !           101: int
        !           102: ne2000_attach(struct ne2000_softc *nsc, u_int8_t *myea)
        !           103: {
        !           104:        struct dp8390_softc *dsc = &nsc->sc_dp8390;
        !           105:        bus_space_tag_t nict = dsc->sc_regt;
        !           106:        bus_space_handle_t nich = dsc->sc_regh;
        !           107:        bus_space_tag_t asict = nsc->sc_asict;
        !           108:        bus_space_handle_t asich = nsc->sc_asich;
        !           109:        u_int8_t romdata[16];
        !           110:        int memsize, i, useword;
        !           111:
        !           112:        /*
        !           113:         * Detect it again unless caller specified it; this gives us
        !           114:         * the memory size.
        !           115:         */
        !           116:        if (nsc->sc_type == NE2000_TYPE_UNKNOWN)
        !           117:                nsc->sc_type = ne2000_detect(nsc);
        !           118:
        !           119:        /*
        !           120:         * 8k of memory for NE1000, 16k otherwise.
        !           121:         */
        !           122:        switch (nsc->sc_type) {
        !           123:        case NE2000_TYPE_UNKNOWN:
        !           124:        default:
        !           125:                printf(": where did the card go?\n");
        !           126:                return (1);
        !           127:        case NE2000_TYPE_NE1000:
        !           128:                memsize = 8192;
        !           129:                useword = 0;
        !           130:                break;
        !           131:        case NE2000_TYPE_NE2000:
        !           132:        case NE2000_TYPE_AX88190:               /* XXX really? */
        !           133:        case NE2000_TYPE_AX88790:
        !           134:        case NE2000_TYPE_DL10019:
        !           135:        case NE2000_TYPE_DL10022:
        !           136:                memsize = 8192 * 2;
        !           137:                useword = 1;
        !           138:                break;
        !           139:        }
        !           140:
        !           141:        nsc->sc_useword = useword;
        !           142:
        !           143:        dsc->cr_proto = ED_CR_RD2;
        !           144:        if (nsc->sc_type == NE2000_TYPE_AX88190 ||
        !           145:            nsc->sc_type == NE2000_TYPE_AX88790) {
        !           146:                dsc->rcr_proto = ED_RCR_INTT;
        !           147:                dsc->sc_flags |= DP8390_DO_AX88190_WORKAROUND;
        !           148:        } else
        !           149:                dsc->rcr_proto = 0;
        !           150:
        !           151:        /*
        !           152:         * DCR gets:
        !           153:         *
        !           154:         *      FIFO threshold to 8, No auto-init Remote DMA,
        !           155:         *      byte order=80x86.
        !           156:         *
        !           157:         * NE1000 gets byte-wide DMA, NE2000 gets word-wide DMA.
        !           158:         */
        !           159:        dsc->dcr_reg = ED_DCR_FT1 | ED_DCR_LS | (useword ? ED_DCR_WTS : 0);
        !           160:
        !           161:        dsc->test_mem = ne2000_test_mem;
        !           162:        dsc->ring_copy = ne2000_ring_copy;
        !           163:        dsc->write_mbuf = ne2000_write_mbuf;
        !           164:        dsc->read_hdr = ne2000_read_hdr;
        !           165:
        !           166:        /* Registers are linear. */
        !           167:        for (i = 0; i < 16; i++)
        !           168:                dsc->sc_reg_map[i] = i;
        !           169:
        !           170:        /*
        !           171:         * NIC memory doens't start at zero on an NE board.
        !           172:         * The start address is tied to the bus width.
        !           173:         * (It happens to be computed the same way as mem size.)
        !           174:         */
        !           175:        dsc->mem_start = memsize;
        !           176:
        !           177: #ifdef GWETHER
        !           178:        {
        !           179:                int x, mstart = 0;
        !           180:                int8_t pbuf0[ED_PAGE_SIZE], pbuf[ED_PAGE_SIZE],
        !           181:                    tbuf[ED_PAGE_SIZE];
        !           182:
        !           183:                for (i = 0; i < ED_PAGE_SIZE; i++)
        !           184:                        pbuf0[i] = 0;
        !           185:
        !           186:                /* Search for the start of RAM. */
        !           187:                for (x = 1; x < 256; x++) {
        !           188:                        ne2000_writemem(nict, nich, asict, asich, pbuf0,
        !           189:                            x << ED_PAGE_SHIFT, ED_PAGE_SIZE, useword);
        !           190:                        ne2000_readmem(nict, nich, asict, asich,
        !           191:                            x << ED_PAGE_SHIFT, tbuf, ED_PAGE_SIZE, useword);
        !           192:                        if (bcmp(pbuf0, tbuf, ED_PAGE_SIZE) == 0) {
        !           193:                                for (i = 0; i < ED_PAGE_SIZE; i++)
        !           194:                                        pbuf[i] = 255 - x;
        !           195:                                ne2000_writemem(nict, nich, asict, asich,
        !           196:                                    pbuf, x << ED_PAGE_SHIFT, ED_PAGE_SIZE,
        !           197:                                    useword);
        !           198:                                ne2000_readmem(nict, nich, asict, asich,
        !           199:                                    x << ED_PAGE_SHIFT, tbuf, ED_PAGE_SIZE,
        !           200:                                    useword);
        !           201:                                if (bcmp(pbuf, tbuf, ED_PAGE_SIZE) == 0) {
        !           202:                                        mstart = x << ED_PAGE_SHIFT;
        !           203:                                        memsize = ED_PAGE_SIZE;
        !           204:                                        break;
        !           205:                                }
        !           206:                        }
        !           207:                }
        !           208:
        !           209:                if (mstart == 0) {
        !           210:                        printf(": cannot find start of RAM\n");
        !           211:                        return;
        !           212:                }
        !           213:
        !           214:                /* Search for the end of RAM. */
        !           215:                for (++x; x < 256; x++) {
        !           216:                        ne2000_writemem(nict, nich, asict, asich, pbuf0,
        !           217:                            x << ED_PAGE_SHIFT, ED_PAGE_SIZE, useword);
        !           218:                        ne2000_readmem(nict, nich, asict, asich,
        !           219:                            x << ED_PAGE_SHIFT, tbuf, ED_PAGE_SIZE, useword);
        !           220:                        if (bcmp(pbuf0, tbuf, ED_PAGE_SIZE) == 0) {
        !           221:                                for (i = 0; i < ED_PAGE_SIZE; i++)
        !           222:                                        pbuf[i] = 255 - x;
        !           223:                                ne2000_writemem(nict, nich, asict, asich,
        !           224:                                    pbuf, x << ED_PAGE_SHIFT, ED_PAGE_SIZE,
        !           225:                                    useword);
        !           226:                                ne2000_readmem(nict, nich, asict, asich,
        !           227:                                    x << ED_PAGE_SHIFT, tbuf, ED_PAGE_SIZE,
        !           228:                                    useword);
        !           229:                                if (bcmp(pbuf, tbuf, ED_PAGE_SIZE) == 0)
        !           230:                                        memsize += ED_PAGE_SIZE;
        !           231:                                else
        !           232:                                        break;
        !           233:                        } else
        !           234:                                break;
        !           235:                }
        !           236:
        !           237:                printf(": RAM start 0x%x, size %d\n",
        !           238:                    mstart, memsize);
        !           239:
        !           240:                dsc->mem_start = mstart;
        !           241:        }
        !           242: #endif /* GWETHER */
        !           243:
        !           244:        dsc->mem_size = memsize;
        !           245:
        !           246:        if (myea == NULL) {
        !           247:                /* Read the station address. */
        !           248:                if (nsc->sc_type == NE2000_TYPE_AX88190 ||
        !           249:                    nsc->sc_type == NE2000_TYPE_AX88790) {
        !           250:                        /* Select page 0 registers. */
        !           251:                        NIC_BARRIER(nict, nich);
        !           252:                        bus_space_write_1(nict, nich, ED_P0_CR,
        !           253:                            ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
        !           254:                        NIC_BARRIER(nict, nich);
        !           255:                        /* Select word transfer. */
        !           256:                        bus_space_write_1(nict, nich, ED_P0_DCR, ED_DCR_WTS);
        !           257:                        NIC_BARRIER(nict, nich);
        !           258:                        ne2000_readmem(nict, nich, asict, asich,
        !           259:                            AX88190_NODEID_OFFSET, dsc->sc_arpcom.ac_enaddr,
        !           260:                            ETHER_ADDR_LEN, useword);
        !           261:                } else {
        !           262:                        ne2000_readmem(nict, nich, asict, asich, 0, romdata,
        !           263:                            sizeof(romdata), useword);
        !           264:                        for (i = 0; i < ETHER_ADDR_LEN; i++)
        !           265:                                dsc->sc_arpcom.ac_enaddr[i] =
        !           266:                                    romdata[i * (useword ? 2 : 1)];
        !           267:                }
        !           268:        } else
        !           269:                bcopy(myea, dsc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
        !           270:
        !           271:        /* Clear any pending interrupts that might have occurred above. */
        !           272:        NIC_BARRIER(nict, nich);
        !           273:        bus_space_write_1(nict, nich, ED_P0_ISR, 0xff);
        !           274:        NIC_BARRIER(nict, nich);
        !           275:
        !           276:        if (dsc->sc_media_init == NULL)
        !           277:                dsc->sc_media_init = dp8390_media_init;
        !           278:
        !           279:        if (dp8390_config(dsc)) {
        !           280:                printf(": setup failed\n");
        !           281:                return (1);
        !           282:        }
        !           283:
        !           284:        /*
        !           285:         * We need to compute mem_ring a bit differently; override the
        !           286:         * value set up in dp8390_config().
        !           287:         */
        !           288:        dsc->mem_ring =
        !           289:            dsc->mem_start + ((dsc->txb_cnt * ED_TXBUF_SIZE) << ED_PAGE_SHIFT);
        !           290:
        !           291:        return (0);
        !           292: }
        !           293:
        !           294: /*
        !           295:  * Detect an NE-2000 or compatible.  Returns a model code.
        !           296:  */
        !           297: int
        !           298: ne2000_detect(struct ne2000_softc *nsc)
        !           299: {
        !           300:        struct dp8390_softc *dsc = &nsc->sc_dp8390;
        !           301:        bus_space_tag_t nict = dsc->sc_regt;
        !           302:        bus_space_handle_t nich = dsc->sc_regh;
        !           303:        bus_space_tag_t asict = nsc->sc_asict;
        !           304:        bus_space_handle_t asich = nsc->sc_asich;
        !           305:        static u_int8_t test_pattern[32] = "THIS is A memory TEST pattern";
        !           306:        u_int8_t test_buffer[32], tmp;
        !           307:        int state, i, rv = 0;
        !           308:
        !           309:        state = dsc->sc_enabled;
        !           310:        dsc->sc_enabled = 0;
        !           311:
        !           312:        /* Reset the board. */
        !           313: #ifdef GWETHER
        !           314:        bus_space_write_1(asict, asich, NE2000_ASIC_RESET, 0);
        !           315:        ASIC_BARRIER(asict, asich);
        !           316:        delay(200);
        !           317: #endif /* GWETHER */
        !           318:        tmp = bus_space_read_1(asict, asich, NE2000_ASIC_RESET);
        !           319:        ASIC_BARRIER(asict, asich);
        !           320:        delay(10000);
        !           321:
        !           322:        /*
        !           323:         * I don't know if this is necessary; probably cruft leftover from
        !           324:         * Clarkson packet driver code. Doesn't do a thing on the boards I've
        !           325:         * tested. -DG [note that a outb(0x84, 0) seems to work here, and is
        !           326:         * non-invasive...but some boards don't seem to reset and I don't have
        !           327:         * complete documentation on what the 'right' thing to do is...so we do
        !           328:         * the invasive thing for now.  Yuck.]
        !           329:         */
        !           330:        bus_space_write_1(asict, asich, NE2000_ASIC_RESET, tmp);
        !           331:        ASIC_BARRIER(asict, asich);
        !           332:        delay(5000);
        !           333:
        !           334:        /*
        !           335:         * This is needed because some NE clones apparently don't reset the
        !           336:         * NIC properly (or the NIC chip doesn't reset fully on power-up).
        !           337:         * XXX - this makes the probe invasive!  Done against my better
        !           338:         * judgement.  -DLG
        !           339:         */
        !           340:        bus_space_write_1(nict, nich, ED_P0_CR,
        !           341:            ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
        !           342:        NIC_BARRIER(nict, nich);
        !           343:
        !           344:        delay(5000);
        !           345:
        !           346:        /*
        !           347:         * Generic probe routine for testing for the existence of a DS8390.
        !           348:         * Must be performed  after the NIC has just been reset.  This
        !           349:         * works by looking at certain register values that are guaranteed
        !           350:         * to be initialized a certain way after power-up or reset.
        !           351:         *
        !           352:         * Specifically:
        !           353:         *
        !           354:         *      Register                reset bits      set bits
        !           355:         *      --------                ----------      --------
        !           356:         *      CR                      TXP, STA        RD2, STP
        !           357:         *      ISR                                     RST
        !           358:         *      IMR                     <all>
        !           359:         *      DCR                                     LAS
        !           360:         *      TCR                     LB1, LB0
        !           361:         *
        !           362:         * We only look at CR and ISR, however, since looking at the others
        !           363:         * would require changing register pages, which would be intrusive
        !           364:         * if this isn't an 8390.
        !           365:         */
        !           366:
        !           367:        tmp = bus_space_read_1(nict, nich, ED_P0_CR);
        !           368:        if ((tmp & (ED_CR_RD2 | ED_CR_TXP | ED_CR_STA | ED_CR_STP)) !=
        !           369:            (ED_CR_RD2 | ED_CR_STP))
        !           370:                goto out;
        !           371:
        !           372:        tmp = bus_space_read_1(nict, nich, ED_P0_ISR);
        !           373:        if ((tmp & ED_ISR_RST) != ED_ISR_RST)
        !           374:                goto out;
        !           375:
        !           376:        bus_space_write_1(nict, nich,
        !           377:            ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
        !           378:        NIC_BARRIER(nict, nich);
        !           379:
        !           380:        for (i = 0; i < 100; i++) {
        !           381:                if ((bus_space_read_1(nict, nich, ED_P0_ISR) & ED_ISR_RST) ==
        !           382:                    ED_ISR_RST) {
        !           383:                        /* Ack the reset bit. */
        !           384:                        bus_space_write_1(nict, nich, ED_P0_ISR, ED_ISR_RST);
        !           385:                        NIC_BARRIER(nict, nich);
        !           386:                        break;
        !           387:                }
        !           388:                delay(100);
        !           389:        }
        !           390:
        !           391: #if 0
        !           392:        /* XXX */
        !           393:        if (i == 100)
        !           394:                goto out;
        !           395: #endif
        !           396:
        !           397:        /*
        !           398:         * Test the ability to read and write to the NIC memory.  This has
        !           399:         * the side effect of determining if this is an NE1000 or an NE2000.
        !           400:         */
        !           401:
        !           402:        /*
        !           403:         * This prevents packets from being stored in the NIC memory when
        !           404:         * the readmem routine turns on the start bit in the CR.
        !           405:         */
        !           406:        bus_space_write_1(nict, nich, ED_P0_RCR, ED_RCR_MON);
        !           407:        NIC_BARRIER(nict, nich);
        !           408:
        !           409:        /* Temporarily initialize DCR for byte operations. */
        !           410:        bus_space_write_1(nict, nich, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
        !           411:
        !           412:        bus_space_write_1(nict, nich, ED_P0_PSTART, 8192 >> ED_PAGE_SHIFT);
        !           413:        bus_space_write_1(nict, nich, ED_P0_PSTOP, 16384 >> ED_PAGE_SHIFT);
        !           414:
        !           415:        /*
        !           416:         * Write a test pattern in byte mode.  If this fails, then there
        !           417:         * probably isn't any memory at 8k - which likely means that the
        !           418:         * board is an NE2000.
        !           419:         */
        !           420:        ne2000_writemem(nict, nich, asict, asich, test_pattern, 8192,
        !           421:            sizeof(test_pattern), 0);
        !           422:        ne2000_readmem(nict, nich, asict, asich, 8192, test_buffer,
        !           423:            sizeof(test_buffer), 0);
        !           424:
        !           425:        if (bcmp(test_pattern, test_buffer, sizeof(test_pattern))) {
        !           426:                /* not an NE1000 - try NE2000 */
        !           427:                bus_space_write_1(nict, nich, ED_P0_DCR,
        !           428:                    ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
        !           429:                bus_space_write_1(nict, nich, ED_P0_PSTART,
        !           430:                    16384 >> ED_PAGE_SHIFT);
        !           431:                bus_space_write_1(nict, nich, ED_P0_PSTOP,
        !           432:                    32768 >> ED_PAGE_SHIFT);
        !           433:
        !           434:                /*
        !           435:                 * Write the test pattern in word mode.  If this also fails,
        !           436:                 * then we don't know what this board is.
        !           437:                 */
        !           438:                ne2000_writemem(nict, nich, asict, asich, test_pattern, 16384,
        !           439:                    sizeof(test_pattern), 1);
        !           440:                ne2000_readmem(nict, nich, asict, asich, 16384, test_buffer,
        !           441:                    sizeof(test_buffer), 1);
        !           442:
        !           443:                if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)))
        !           444:                        goto out;       /* not an NE2000 either */
        !           445:
        !           446:                rv = NE2000_TYPE_NE2000;
        !           447:        } else {
        !           448:                /* We're an NE1000. */
        !           449:                rv = NE2000_TYPE_NE1000;
        !           450:        }
        !           451:
        !           452:        /* Clear any pending interrupts that might have occurred above. */
        !           453:        NIC_BARRIER(nict, nich);
        !           454:        bus_space_write_1(nict, nich, ED_P0_ISR, 0xff);
        !           455:
        !           456:  out:
        !           457:        dsc->sc_enabled = state;
        !           458:
        !           459:        return (rv);
        !           460: }
        !           461:
        !           462: /*
        !           463:  * Write an mbuf chain to the destination NIC memory address using programmed
        !           464:  * I/O.
        !           465:  */
        !           466: int
        !           467: ne2000_write_mbuf(struct dp8390_softc *sc, struct mbuf *m, int buf)
        !           468: {
        !           469:        struct ne2000_softc *nsc = (struct ne2000_softc *)sc;
        !           470:        bus_space_tag_t nict = sc->sc_regt;
        !           471:        bus_space_handle_t nich = sc->sc_regh;
        !           472:        bus_space_tag_t asict = nsc->sc_asict;
        !           473:        bus_space_handle_t asich = nsc->sc_asich;
        !           474:        int savelen;
        !           475:        int maxwait = 100;      /* about 120us */
        !           476:
        !           477:        savelen = m->m_pkthdr.len;
        !           478:
        !           479:        /* Select page 0 registers. */
        !           480:        NIC_BARRIER(nict, nich);
        !           481:        bus_space_write_1(nict, nich, ED_P0_CR,
        !           482:            ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
        !           483:        NIC_BARRIER(nict, nich);
        !           484:
        !           485:        /* Reset remote DMA complete flag. */
        !           486:        bus_space_write_1(nict, nich, ED_P0_ISR, ED_ISR_RDC);
        !           487:        NIC_BARRIER(nict, nich);
        !           488:
        !           489:        /* Set up DMA byte count. */
        !           490:        bus_space_write_1(nict, nich, ED_P0_RBCR0, savelen);
        !           491:        bus_space_write_1(nict, nich, ED_P0_RBCR1, savelen >> 8);
        !           492:
        !           493:        /* Set up destination address in NIC mem. */
        !           494:        bus_space_write_1(nict, nich, ED_P0_RSAR0, buf);
        !           495:        bus_space_write_1(nict, nich, ED_P0_RSAR1, buf >> 8);
        !           496:
        !           497:        /* Set remote DMA write. */
        !           498:        NIC_BARRIER(nict, nich);
        !           499:        bus_space_write_1(nict, nich,
        !           500:            ED_P0_CR, ED_CR_RD1 | ED_CR_PAGE_0 | ED_CR_STA);
        !           501:        NIC_BARRIER(nict, nich);
        !           502:
        !           503:        /*
        !           504:         * Transfer the mbuf chain to the NIC memory.  NE2000 cards
        !           505:         * require that data be transferred as words, and only words,
        !           506:         * so that case requires some extra code to patch over odd-length
        !           507:         * mbufs.
        !           508:         */
        !           509:        if (nsc->sc_type == NE2000_TYPE_NE1000) {
        !           510:                /* NE1000s are easy. */
        !           511:                for (; m != 0; m = m->m_next) {
        !           512:                        if (m->m_len) {
        !           513:                                bus_space_write_multi_1(asict, asich,
        !           514:                                    NE2000_ASIC_DATA, mtod(m, u_int8_t *),
        !           515:                                    m->m_len);
        !           516:                        }
        !           517:                }
        !           518:        } else {
        !           519:                /* NE2000s are a bit trickier. */
        !           520:                u_int8_t *data, savebyte[2];
        !           521:                int l, leftover;
        !           522: #ifdef DIAGNOSTIC
        !           523:                u_int8_t *lim;
        !           524: #endif
        !           525:                /* Start out with no leftover data. */
        !           526:                leftover = 0;
        !           527:                savebyte[0] = savebyte[1] = 0;
        !           528:
        !           529:                for (; m != 0; m = m->m_next) {
        !           530:                        l = m->m_len;
        !           531:                        if (l == 0)
        !           532:                                continue;
        !           533:                        data = mtod(m, u_int8_t *);
        !           534: #ifdef DIAGNOSTIC
        !           535:                        lim = data + l;
        !           536: #endif
        !           537:                        while (l > 0) {
        !           538:                                if (leftover) {
        !           539:                                        /*
        !           540:                                         * Data left over (from mbuf or
        !           541:                                         * realignment).  Buffer the next
        !           542:                                         * byte, and write it and the
        !           543:                                         * leftover data out.
        !           544:                                         */
        !           545:                                        savebyte[1] = *data++;
        !           546:                                        l--;
        !           547:                                        bus_space_write_raw_multi_2(asict,
        !           548:                                            asich, NE2000_ASIC_DATA,
        !           549:                                            savebyte, 2);
        !           550:                                        leftover = 0;
        !           551:                                } else if (ALIGNED_POINTER(data,
        !           552:                                           u_int16_t) == 0) {
        !           553:                                        /*
        !           554:                                         * Unaligned data; buffer the next
        !           555:                                         * byte.
        !           556:                                         */
        !           557:                                        savebyte[0] = *data++;
        !           558:                                        l--;
        !           559:                                        leftover = 1;
        !           560:                                } else {
        !           561:                                        /*
        !           562:                                         * Aligned data; output contiguous
        !           563:                                         * words as much as we can, then
        !           564:                                         * buffer the remaining byte, if any.
        !           565:                                         */
        !           566:                                        leftover = l & 1;
        !           567:                                        l &= ~1;
        !           568:                                        bus_space_write_raw_multi_2(asict,
        !           569:                                            asich, NE2000_ASIC_DATA, data, l);
        !           570:                                        data += l;
        !           571:                                        if (leftover)
        !           572:                                                savebyte[0] = *data++;
        !           573:                                        l = 0;
        !           574:                                }
        !           575:                        }
        !           576:                        if (l < 0)
        !           577:                                panic("ne2000_write_mbuf: negative len");
        !           578: #ifdef DIAGNOSTIC
        !           579:                        if (data != lim)
        !           580:                                panic("ne2000_write_mbuf: data != lim");
        !           581: #endif
        !           582:                }
        !           583:                if (leftover) {
        !           584:                        savebyte[1] = 0;
        !           585:                        bus_space_write_raw_multi_2(asict, asich,
        !           586:                            NE2000_ASIC_DATA, savebyte, 2);
        !           587:                }
        !           588:        }
        !           589:        NIC_BARRIER(nict, nich);
        !           590:
        !           591:        /* AX88796 doesn't seem to have remote DMA complete */
        !           592:        if (sc->sc_flags & DP8390_NO_REMOTE_DMA_COMPLETE)
        !           593:                return (savelen);
        !           594:
        !           595:        /*
        !           596:         * Wait for remote DMA to complete.  This is necessary because on the
        !           597:         * transmit side, data is handled internally by the NIC in bursts, and
        !           598:         * we can't start another remote DMA until this one completes.  Not
        !           599:         * waiting causes really bad things to happen - like the NIC wedging
        !           600:         * the bus.
        !           601:         */
        !           602:        while (((bus_space_read_1(nict, nich, ED_P0_ISR) & ED_ISR_RDC) !=
        !           603:            ED_ISR_RDC) && --maxwait) {
        !           604:                bus_space_read_1(nict, nich, ED_P0_CRDA1);
        !           605:                bus_space_read_1(nict, nich, ED_P0_CRDA0);
        !           606:                NIC_BARRIER(nict, nich);
        !           607:                DELAY(1);
        !           608:        }
        !           609:
        !           610:        if (maxwait == 0) {
        !           611:                log(LOG_WARNING,
        !           612:                    "%s: remote transmit DMA failed to complete\n",
        !           613:                    sc->sc_dev.dv_xname);
        !           614:                dp8390_reset(sc);
        !           615:        }
        !           616:
        !           617:        return (savelen);
        !           618: }
        !           619:
        !           620: /*
        !           621:  * Given a source and destination address, copy 'amount' of a packet from
        !           622:  * the ring buffer into a linear destination buffer.  Takes into account
        !           623:  * ring-wrap.
        !           624:  */
        !           625: int
        !           626: ne2000_ring_copy(struct dp8390_softc *sc, int src, caddr_t dst,
        !           627:     u_short amount)
        !           628: {
        !           629:        struct ne2000_softc *nsc = (struct ne2000_softc *)sc;
        !           630:        bus_space_tag_t nict = sc->sc_regt;
        !           631:        bus_space_handle_t nich = sc->sc_regh;
        !           632:        bus_space_tag_t asict = nsc->sc_asict;
        !           633:        bus_space_handle_t asich = nsc->sc_asich;
        !           634:        u_short tmp_amount;
        !           635:        int useword = nsc->sc_useword;
        !           636:
        !           637:        /* Does copy wrap to lower addr in ring buffer? */
        !           638:        if (src + amount > sc->mem_end) {
        !           639:                tmp_amount = sc->mem_end - src;
        !           640:
        !           641:                /* Copy amount up to end of NIC memory. */
        !           642:                ne2000_readmem(nict, nich, asict, asich, src,
        !           643:                    (u_int8_t *)dst, tmp_amount, useword);
        !           644:
        !           645:                amount -= tmp_amount;
        !           646:                src = sc->mem_ring;
        !           647:                dst += tmp_amount;
        !           648:        }
        !           649:
        !           650:        ne2000_readmem(nict, nich, asict, asich, src, (u_int8_t *)dst,
        !           651:            amount, useword);
        !           652:
        !           653:        return (src + amount);
        !           654: }
        !           655:
        !           656: void
        !           657: ne2000_read_hdr(struct dp8390_softc *sc, int buf, struct dp8390_ring *hdr)
        !           658: {
        !           659:        struct ne2000_softc *nsc = (struct ne2000_softc *)sc;
        !           660:
        !           661:        ne2000_readmem(sc->sc_regt, sc->sc_regh, nsc->sc_asict, nsc->sc_asich,
        !           662:            buf, (u_int8_t *)hdr, sizeof(struct dp8390_ring),
        !           663:            nsc->sc_useword);
        !           664: #if BYTE_ORDER == BIG_ENDIAN
        !           665:        hdr->count = swap16(hdr->count);
        !           666: #endif
        !           667: }
        !           668:
        !           669: int
        !           670: ne2000_test_mem(struct dp8390_softc *sc)
        !           671: {
        !           672:        /* Noop. */
        !           673:        return (0);
        !           674: }
        !           675:
        !           676: /*
        !           677:  * Given a NIC memory source address and a host memory destination address,
        !           678:  * copy 'amount' from NIC to host using programmed i/o.  The 'amount' is
        !           679:  * rounded up to a word - ok as long as mbufs are word sized.
        !           680:  */
        !           681: void
        !           682: ne2000_readmem(bus_space_tag_t nict, bus_space_handle_t nich,
        !           683:     bus_space_tag_t asict, bus_space_handle_t asich, int src,
        !           684:     u_int8_t *dst, size_t amount, int useword)
        !           685: {
        !           686:
        !           687:        /* Select page 0 registers. */
        !           688:        NIC_BARRIER(nict, nich);
        !           689:        bus_space_write_1(nict, nich, ED_P0_CR,
        !           690:            ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
        !           691:        NIC_BARRIER(nict, nich);
        !           692:
        !           693:        /* Round up to a word. */
        !           694:        if (amount & 1)
        !           695:                ++amount;
        !           696:
        !           697:        /* Set up DMA byte count. */
        !           698:        bus_space_write_1(nict, nich, ED_P0_RBCR0, amount);
        !           699:        bus_space_write_1(nict, nich, ED_P0_RBCR1, amount >> 8);
        !           700:
        !           701:        /* Set up source address in NIC mem. */
        !           702:        bus_space_write_1(nict, nich, ED_P0_RSAR0, src);
        !           703:        bus_space_write_1(nict, nich, ED_P0_RSAR1, src >> 8);
        !           704:
        !           705:        NIC_BARRIER(nict, nich);
        !           706:        bus_space_write_1(nict, nich, ED_P0_CR,
        !           707:            ED_CR_RD0 | ED_CR_PAGE_0 | ED_CR_STA);
        !           708:
        !           709:        ASIC_BARRIER(asict, asich);
        !           710:        if (useword)
        !           711:                bus_space_read_raw_multi_2(asict, asich, NE2000_ASIC_DATA,
        !           712:                    dst, amount);
        !           713:        else
        !           714:                bus_space_read_multi_1(asict, asich, NE2000_ASIC_DATA,
        !           715:                    dst, amount);
        !           716: }
        !           717:
        !           718: /*
        !           719:  * Stripped down routine for writing a linear buffer to NIC memory.  Only
        !           720:  * used in the probe routine to test the memory.  'len' must be even.
        !           721:  */
        !           722: void
        !           723: ne2000_writemem(bus_space_tag_t nict, bus_space_handle_t nich,
        !           724:     bus_space_tag_t asict, bus_space_handle_t asich, u_int8_t *src,
        !           725:     int dst, size_t len, int useword)
        !           726: {
        !           727:        int maxwait = 100;      /* about 120us */
        !           728:
        !           729:        /* Select page 0 registers. */
        !           730:        NIC_BARRIER(nict, nich);
        !           731:        bus_space_write_1(nict, nich, ED_P0_CR,
        !           732:            ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
        !           733:        NIC_BARRIER(nict, nich);
        !           734:
        !           735:        /* Reset remote DMA complete flag. */
        !           736:        bus_space_write_1(nict, nich, ED_P0_ISR, ED_ISR_RDC);
        !           737:        NIC_BARRIER(nict, nich);
        !           738:
        !           739:        /* Set up DMA byte count. */
        !           740:        bus_space_write_1(nict, nich, ED_P0_RBCR0, len);
        !           741:        bus_space_write_1(nict, nich, ED_P0_RBCR1, len >> 8);
        !           742:
        !           743:        /* Set up destination address in NIC mem. */
        !           744:        bus_space_write_1(nict, nich, ED_P0_RSAR0, dst);
        !           745:        bus_space_write_1(nict, nich, ED_P0_RSAR1, dst >> 8);
        !           746:
        !           747:        /* Set remote DMA write. */
        !           748:        NIC_BARRIER(nict, nich);
        !           749:        bus_space_write_1(nict, nich, ED_P0_CR,
        !           750:            ED_CR_RD1 | ED_CR_PAGE_0 | ED_CR_STA);
        !           751:        NIC_BARRIER(nict, nich);
        !           752:
        !           753:        ASIC_BARRIER(asict, asich);
        !           754:        if (useword)
        !           755:                bus_space_write_raw_multi_2(asict, asich, NE2000_ASIC_DATA,
        !           756:                    src, len);
        !           757:        else
        !           758:                bus_space_write_multi_1(asict, asich, NE2000_ASIC_DATA,
        !           759:                    src, len);
        !           760:        ASIC_BARRIER(asict, asich);
        !           761:
        !           762:        /*
        !           763:         * Wait for remote DMA to complete.  This is necessary because on the
        !           764:         * transmit side, data is handled internally by the NIC in bursts, and
        !           765:         * we can't start another remote DMA until this one completes.  Not
        !           766:         * waiting causes really bad things to happen - like the NIC wedging
        !           767:         * the bus.
        !           768:         */
        !           769:        while (((bus_space_read_1(nict, nich, ED_P0_ISR) & ED_ISR_RDC) !=
        !           770:            ED_ISR_RDC) && --maxwait)
        !           771:                DELAY(1);
        !           772: }
        !           773:
        !           774: int
        !           775: ne2000_detach(struct ne2000_softc *sc, int flags)
        !           776: {
        !           777:        return (dp8390_detach(&sc->sc_dp8390, flags));
        !           778: }

CVSweb