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

Annotation of sys/dev/pci/if_lmc_obsd.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: if_lmc_obsd.c,v 1.19 2005/11/07 00:29:21 brad Exp $ */
        !             2: /*     $NetBSD: if_lmc_nbsd.c,v 1.1 1999/03/25 03:32:43 explorer Exp $ */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1997-1999 LAN Media Corporation (LMC)
        !             6:  * All rights reserved.  www.lanmedia.com
        !             7:  *
        !             8:  * This code is written by Michael Graff <graff@vix.com> for LMC.
        !             9:  * The code is derived from permitted modifications to software created
        !            10:  * by Matt Thomas (matt@3am-software.com).
        !            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
        !            18:  *    copyright notice, this list of conditions and the following disclaimer
        !            19:  *    in the documentation and/or other materials provided with the
        !            20:  *    distribution.
        !            21:  * 3. All marketing or advertising materials mentioning features or
        !            22:  *    use of this software must display the following acknowledgement:
        !            23:  *      This product includes software developed by LAN Media Corporation
        !            24:  *      and its contributors.
        !            25:  * 4. Neither the name of LAN Media Corporation nor the names of its
        !            26:  *    contributors may be used to endorse or promote products derived
        !            27:  *    from this software without specific prior written permission.
        !            28:  *
        !            29:  * THIS SOFTWARE IS PROVIDED BY LAN MEDIA CORPORATION AND CONTRIBUTORS
        !            30:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            31:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            32:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            33:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            34:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            35:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            36:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            37:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            38:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
        !            39:  * THE POSSIBILITY OF SUCH DAMAGE.
        !            40:  */
        !            41:
        !            42: /*-
        !            43:  * Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com)
        !            44:  * All rights reserved.
        !            45:  *
        !            46:  * Redistribution and use in source and binary forms, with or without
        !            47:  * modification, are permitted provided that the following conditions
        !            48:  * are met:
        !            49:  * 1. Redistributions of source code must retain the above copyright
        !            50:  *    notice, this list of conditions and the following disclaimer.
        !            51:  * 2. The name of the author may not be used to endorse or promote products
        !            52:  *    derived from this software without specific prior written permission
        !            53:  *
        !            54:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            55:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            56:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            57:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            58:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            59:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            60:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            61:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            62:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            63:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            64:  */
        !            65:
        !            66: #include "bpfilter.h"
        !            67:
        !            68: #include <sys/param.h>
        !            69: #include <sys/systm.h>
        !            70: #include <sys/mbuf.h>
        !            71: #include <sys/socket.h>
        !            72: #include <sys/ioctl.h>
        !            73: #include <sys/errno.h>
        !            74: #include <sys/malloc.h>
        !            75: #include <sys/kernel.h>
        !            76: #include <sys/proc.h>  /* only for declaration of wakeup() used by vm.h */
        !            77: #include <sys/device.h>
        !            78:
        !            79: #include <dev/pci/pcidevs.h>
        !            80:
        !            81: #include <net/if.h>
        !            82: #include <net/if_types.h>
        !            83: #include <net/if_dl.h>
        !            84: #include <net/netisr.h>
        !            85:
        !            86: #if NBPFILTER > 0
        !            87: #include <net/bpf.h>
        !            88: #endif
        !            89:
        !            90: #include <net/if_sppp.h>
        !            91:
        !            92: #include <machine/bus.h>
        !            93:
        !            94: #include <dev/pci/pcireg.h>
        !            95: #include <dev/pci/pcivar.h>
        !            96: #include <dev/ic/dc21040reg.h>
        !            97:
        !            98: #include <dev/pci/if_lmc_types.h>
        !            99: #include <dev/pci/if_lmcioctl.h>
        !           100: #include <dev/pci/if_lmcvar.h>
        !           101:
        !           102: /*
        !           103:  * This file is INCLUDED (gross, I know, but...)
        !           104:  */
        !           105:
        !           106: static void lmc_shutdown(void *arg);
        !           107: static int lmc_busdma_init(lmc_softc_t * const sc);
        !           108: static int lmc_busdma_allocmem(lmc_softc_t * const sc, size_t size,
        !           109:        bus_dmamap_t *map_p, lmc_desc_t **desc_p);
        !           110:
        !           111: static int
        !           112: lmc_pci_probe(struct device *parent,
        !           113:               void *match,
        !           114:               void *aux)
        !           115: {
        !           116:        struct pci_attach_args *pa = (struct pci_attach_args *)aux;
        !           117:        u_int32_t id;
        !           118:
        !           119:        /*
        !           120:         * check first for the DEC chip we expect to find.  We expect
        !           121:         * 21140A, pass 2.2 or higher.
        !           122:         */
        !           123:        if (PCI_VENDORID(pa->pa_id) != PCI_VENDOR_DEC)
        !           124:                return 0;
        !           125:        if (PCI_CHIPID(pa->pa_id) != PCI_PRODUCT_DEC_21140)
        !           126:                return 0;
        !           127:        id = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CFRV) & 0xff;
        !           128:        if (id < 0x22)
        !           129:                return 0;
        !           130:
        !           131:        /*
        !           132:         * Next, check the subsystem ID and see if it matches what we
        !           133:         * expect.
        !           134:         */
        !           135:        id = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SSID);
        !           136:        if (PCI_VENDORID(id) != PCI_VENDOR_LMC)
        !           137:                return 0;
        !           138:        if ((PCI_CHIPID(id) != PCI_PRODUCT_LMC_HSSI)
        !           139:            && (PCI_CHIPID(id) != PCI_PRODUCT_LMC_HSSIC)
        !           140:            && (PCI_CHIPID(id) != PCI_PRODUCT_LMC_DS3)
        !           141:            && (PCI_CHIPID(id) != PCI_PRODUCT_LMC_SSI)
        !           142:            && (PCI_CHIPID(id) != PCI_PRODUCT_LMC_DS1))
        !           143:                return 0;
        !           144:
        !           145:        return 20; /* must be > than any other tulip driver */
        !           146: }
        !           147:
        !           148: static void  lmc_pci_attach(struct device * const parent,
        !           149:                             struct device * const self, void * const aux);
        !           150:
        !           151: struct cfattach lmc_ca = {
        !           152:     sizeof(lmc_softc_t), lmc_pci_probe, lmc_pci_attach
        !           153: };
        !           154:
        !           155: struct cfdriver lmc_cd = {
        !           156:        0, "lmc", DV_IFNET
        !           157: };
        !           158:
        !           159: static void
        !           160: lmc_pci_attach(struct device * const parent,
        !           161:                struct device * const self, void * const aux)
        !           162: {
        !           163:        u_int32_t revinfo, cfdainfo, id, ssid;
        !           164:        pci_intr_handle_t intrhandle;
        !           165:        const char *intrstr;
        !           166:        unsigned csroffset = LMC_PCI_CSROFFSET;
        !           167:        unsigned csrsize = LMC_PCI_CSRSIZE;
        !           168:        lmc_csrptr_t csr_base;
        !           169:        lmc_spl_t s;
        !           170:        lmc_intrfunc_t (*intr_rtn)(void *) = lmc_intr_normal;
        !           171:        lmc_softc_t * const sc = (lmc_softc_t *) self;
        !           172:        struct pci_attach_args * const pa = (struct pci_attach_args *) aux;
        !           173:        extern lmc_media_t lmc_hssi_media;
        !           174:        extern lmc_media_t lmc_ds3_media;
        !           175:        extern lmc_media_t lmc_t1_media;
        !           176:        extern lmc_media_t lmc_ssi_media;
        !           177:
        !           178:        revinfo  = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CFRV) & 0xFF;
        !           179:        id       = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CFID);
        !           180:        cfdainfo = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CFDA);
        !           181:        ssid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SSID);
        !           182:
        !           183:        switch (PCI_CHIPID(ssid)) {
        !           184:        case PCI_PRODUCT_LMC_HSSI:
        !           185:                printf(": HSSI\n");
        !           186:                sc->lmc_media = &lmc_hssi_media;
        !           187:                break;
        !           188:        case PCI_PRODUCT_LMC_HSSIC:
        !           189:                printf(": HSSIc\n");
        !           190:                sc->lmc_media = &lmc_hssi_media;
        !           191:                break;
        !           192:        case PCI_PRODUCT_LMC_DS3:
        !           193:                printf(": DS3\n");
        !           194:                sc->lmc_media = &lmc_ds3_media;
        !           195:                break;
        !           196:        case PCI_PRODUCT_LMC_SSI:
        !           197:                printf(": SSI\n");
        !           198:                sc->lmc_media = &lmc_ssi_media;
        !           199:                break;
        !           200:        case PCI_PRODUCT_LMC_DS1:
        !           201:                printf(": T1\n");
        !           202:                sc->lmc_media = &lmc_t1_media;
        !           203:                break;
        !           204:        }
        !           205:
        !           206:         sc->lmc_pci_busno = parent;
        !           207:         sc->lmc_pci_devno = pa->pa_device;
        !           208:
        !           209:        sc->lmc_chipid = LMC_21140A;
        !           210:        sc->lmc_features |= LMC_HAVE_STOREFWD;
        !           211:        if (sc->lmc_chipid == LMC_21140A && revinfo <= 0x22)
        !           212:                sc->lmc_features |= LMC_HAVE_RXBADOVRFLW;
        !           213:
        !           214:        if (cfdainfo & (TULIP_CFDA_SLEEP | TULIP_CFDA_SNOOZE)) {
        !           215:                cfdainfo &= ~(TULIP_CFDA_SLEEP | TULIP_CFDA_SNOOZE);
        !           216:                pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_CFDA, cfdainfo);
        !           217:                DELAY(11 * 1000);
        !           218:        }
        !           219:
        !           220:        bcopy(self->dv_xname, sc->lmc_if.if_xname, IFNAMSIZ);
        !           221:        sc->lmc_if.if_softc = sc;
        !           222:        sc->lmc_pc = pa->pa_pc;
        !           223:
        !           224:        sc->lmc_revinfo = revinfo;
        !           225:        sc->lmc_if.if_softc = sc;
        !           226:
        !           227:        csr_base = 0;
        !           228:        {
        !           229:                bus_space_tag_t iot, memt;
        !           230:                bus_space_handle_t ioh, memh;
        !           231:                int ioh_valid, memh_valid;
        !           232:
        !           233:                ioh_valid = (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO,
        !           234:                    0, &iot, &ioh, NULL, NULL, 0) == 0);
        !           235:                memh_valid = (pci_mapreg_map(pa, PCI_CBMA,
        !           236:                    PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &memt,
        !           237:                    &memh, NULL, NULL, 0) == 0);
        !           238:
        !           239:                if (memh_valid) {
        !           240:                        sc->lmc_bustag = memt;
        !           241:                        sc->lmc_bushandle = memh;
        !           242:                } else if (ioh_valid) {
        !           243:                        sc->lmc_bustag = iot;
        !           244:                        sc->lmc_bushandle = ioh;
        !           245:                } else {
        !           246:                        printf("%s: unable to map device registers\n",
        !           247:                               sc->lmc_dev.dv_xname);
        !           248:                        return;
        !           249:                }
        !           250:        }
        !           251:
        !           252:        sc->lmc_dmatag = pa->pa_dmat;
        !           253:        if ((lmc_busdma_init(sc)) != 0) {
        !           254:                printf("error initing bus_dma\n");
        !           255:                return;
        !           256:        }
        !           257:
        !           258:        lmc_initcsrs(sc, csr_base + csroffset, csrsize);
        !           259:        lmc_initring(sc, &sc->lmc_rxinfo, sc->lmc_rxdescs,
        !           260:                       LMC_RXDESCS);
        !           261:        lmc_initring(sc, &sc->lmc_txinfo, sc->lmc_txdescs,
        !           262:                       LMC_TXDESCS);
        !           263:
        !           264:        lmc_gpio_mkinput(sc, 0xff);
        !           265:        sc->lmc_gpio = 0;  /* drive no signals yet */
        !           266:
        !           267:        sc->lmc_media->defaults(sc);
        !           268:
        !           269:        sc->lmc_media->set_link_status(sc, LMC_LINK_DOWN); /* down */
        !           270:
        !           271:        /*
        !           272:         * Make sure there won't be any interrupts or such...
        !           273:         */
        !           274:        LMC_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET);
        !           275:
        !           276:        /*
        !           277:         * Wait 10 microseconds (actually 50 PCI cycles but at
        !           278:         * 33MHz that comes to two microseconds but wait a
        !           279:         * bit longer anyways)
        !           280:         */
        !           281:        DELAY(100);
        !           282:
        !           283:        lmc_read_macaddr(sc);
        !           284:
        !           285:         if (pci_intr_map(pa, &intrhandle)) {
        !           286:                 printf("%s: couldn't map interrupt\n",
        !           287:                        sc->lmc_dev.dv_xname);
        !           288:                return;
        !           289:        }
        !           290:        intrstr = pci_intr_string(pa->pa_pc, intrhandle);
        !           291:
        !           292:        sc->lmc_ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_NET,
        !           293:                                                intr_rtn, sc, self->dv_xname);
        !           294:
        !           295:        if (sc->lmc_ih == NULL) {
        !           296:                printf("%s: couldn't establish interrupt",
        !           297:                       sc->lmc_dev.dv_xname);
        !           298:                if (intrstr != NULL)
        !           299:                        printf(" at %s", intrstr);
        !           300:                printf("\n");
        !           301:                return;
        !           302:        }
        !           303:
        !           304:         printf("%s: pass %d.%d, serial " LMC_EADDR_FMT ", %s\n",
        !           305:                sc->lmc_dev.dv_xname,
        !           306:                (sc->lmc_revinfo & 0xF0) >> 4, sc->lmc_revinfo & 0x0F,
        !           307:                LMC_EADDR_ARGS(sc->lmc_enaddr), intrstr);
        !           308:
        !           309:         sc->lmc_ats = shutdownhook_establish(lmc_shutdown, sc);
        !           310:         if (sc->lmc_ats == NULL)
        !           311:                printf("%s: warning: couldn't establish shutdown hook\n",
        !           312:                       sc->lmc_xname);
        !           313:
        !           314:        s = LMC_RAISESPL();
        !           315:        lmc_dec_reset(sc);
        !           316:        lmc_reset(sc);
        !           317:        lmc_attach(sc);
        !           318:        LMC_RESTORESPL(s);
        !           319: }
        !           320:
        !           321: static void
        !           322: lmc_shutdown(void *arg)
        !           323: {
        !           324:        lmc_softc_t * const sc = arg;
        !           325:        LMC_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET);
        !           326:        DELAY(10);
        !           327:
        !           328:        sc->lmc_miireg16 = 0;  /* deassert ready, and all others too */
        !           329:        lmc_led_on(sc, LMC_MII16_LED_ALL);
        !           330: }
        !           331:
        !           332: static int
        !           333: lmc_busdma_allocmem(
        !           334:     lmc_softc_t * const sc,
        !           335:     size_t size,
        !           336:     bus_dmamap_t *map_p,
        !           337:     lmc_desc_t **desc_p)
        !           338: {
        !           339:     bus_dma_segment_t segs[1];
        !           340:     int nsegs, error;
        !           341:     error = bus_dmamem_alloc(sc->lmc_dmatag, size, 1, NBPG,
        !           342:                             segs, sizeof(segs)/sizeof(segs[0]),
        !           343:                             &nsegs, BUS_DMA_NOWAIT);
        !           344:     if (error == 0) {
        !           345:        void *desc;
        !           346:        error = bus_dmamem_map(sc->lmc_dmatag, segs, nsegs, size,
        !           347:                               (void *) &desc, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
        !           348:        if (error == 0) {
        !           349:            bus_dmamap_t map;
        !           350:            error = bus_dmamap_create(sc->lmc_dmatag, size, 1, size, 0,
        !           351:                                      BUS_DMA_NOWAIT, &map);
        !           352:            if (error == 0) {
        !           353:                error = bus_dmamap_load(sc->lmc_dmatag, map, desc,
        !           354:                                        size, NULL, BUS_DMA_NOWAIT);
        !           355:                if (error)
        !           356:                    bus_dmamap_destroy(sc->lmc_dmatag, map);
        !           357:                else
        !           358:                    *map_p = map;
        !           359:            }
        !           360:            if (error)
        !           361:                bus_dmamem_unmap(sc->lmc_dmatag, desc, size);
        !           362:        }
        !           363:        if (error)
        !           364:            bus_dmamem_free(sc->lmc_dmatag, segs, nsegs);
        !           365:        else
        !           366:            *desc_p = desc;
        !           367:     }
        !           368:     return error;
        !           369: }
        !           370:
        !           371: static int
        !           372: lmc_busdma_init(
        !           373:     lmc_softc_t * const sc)
        !           374: {
        !           375:     int error = 0;
        !           376:
        !           377:     /*
        !           378:      * Allocate space and dmamap for transmit ring
        !           379:      */
        !           380:     if (error == 0) {
        !           381:        error = lmc_busdma_allocmem(sc, sizeof(lmc_desc_t) * LMC_TXDESCS,
        !           382:                                      &sc->lmc_txdescmap,
        !           383:                                      &sc->lmc_txdescs);
        !           384:     }
        !           385:
        !           386:     /*
        !           387:      * Allocate dmamaps for each transmit descriptors
        !           388:      */
        !           389:     if (error == 0) {
        !           390:        while (error == 0 && sc->lmc_txmaps_free < LMC_TXDESCS) {
        !           391:            bus_dmamap_t map;
        !           392:            if ((error = LMC_TXMAP_CREATE(sc, &map)) == 0)
        !           393:                sc->lmc_txmaps[sc->lmc_txmaps_free++] = map;
        !           394:        }
        !           395:        if (error) {
        !           396:            while (sc->lmc_txmaps_free > 0)
        !           397:                bus_dmamap_destroy(sc->lmc_dmatag,
        !           398:                                   sc->lmc_txmaps[--sc->lmc_txmaps_free]);
        !           399:        }
        !           400:     }
        !           401:
        !           402:     /*
        !           403:      * Allocate space and dmamap for receive ring
        !           404:      */
        !           405:     if (error == 0) {
        !           406:        error = lmc_busdma_allocmem(sc, sizeof(lmc_desc_t) * LMC_RXDESCS,
        !           407:                                      &sc->lmc_rxdescmap,
        !           408:                                      &sc->lmc_rxdescs);
        !           409:     }
        !           410:
        !           411:     /*
        !           412:      * Allocate dmamaps for each receive descriptors
        !           413:      */
        !           414:     if (error == 0) {
        !           415:        while (error == 0 && sc->lmc_rxmaps_free < LMC_RXDESCS) {
        !           416:            bus_dmamap_t map;
        !           417:            if ((error = LMC_RXMAP_CREATE(sc, &map)) == 0)
        !           418:                sc->lmc_rxmaps[sc->lmc_rxmaps_free++] = map;
        !           419:        }
        !           420:        if (error) {
        !           421:            while (sc->lmc_rxmaps_free > 0)
        !           422:                bus_dmamap_destroy(sc->lmc_dmatag,
        !           423:                                   sc->lmc_rxmaps[--sc->lmc_rxmaps_free]);
        !           424:        }
        !           425:     }
        !           426:
        !           427:     return error;
        !           428: }

CVSweb