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

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

1.1     ! nbrk        1: /*     $OpenBSD: if_gem_pci.c,v 1.28 2007/04/19 19:00:01 kettenis Exp $        */
        !             2: /*     $NetBSD: if_gem_pci.c,v 1.1 2001/09/16 00:11:42 eeh Exp $ */
        !             3:
        !             4: /*
        !             5:  *
        !             6:  * Copyright (C) 2001 Eduardo Horvath.
        !             7:  * All rights reserved.
        !             8:  *
        !             9:  *
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  *
        !            19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR  ``AS IS'' AND
        !            20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR  BE LIABLE
        !            23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            29:  * SUCH DAMAGE.
        !            30:  *
        !            31:  */
        !            32:
        !            33: /*
        !            34:  * PCI bindings for Sun GEM ethernet controllers.
        !            35:  */
        !            36:
        !            37: #include <sys/param.h>
        !            38: #include <sys/systm.h>
        !            39: #include <sys/malloc.h>
        !            40: #include <sys/kernel.h>
        !            41: #include <sys/socket.h>
        !            42: #include <sys/errno.h>
        !            43: #include <sys/device.h>
        !            44:
        !            45: #include <machine/endian.h>
        !            46:
        !            47: #include <net/if.h>
        !            48: #include <net/if_dl.h>
        !            49: #include <net/if_media.h>
        !            50:
        !            51: #ifdef INET
        !            52: #include <netinet/in.h>
        !            53: #include <netinet/if_ether.h>
        !            54: #endif
        !            55:
        !            56: #if NBPFILTER > 0
        !            57: #include <net/bpf.h>
        !            58: #endif
        !            59:
        !            60: #include <machine/bus.h>
        !            61: #include <machine/intr.h>
        !            62:
        !            63: #ifdef __sparc64__
        !            64: #include <dev/ofw/openfirm.h>
        !            65: #endif
        !            66:
        !            67: #include <dev/mii/mii.h>
        !            68: #include <dev/mii/miivar.h>
        !            69: #include <dev/mii/mii_bitbang.h>
        !            70:
        !            71: #include <dev/ic/gemreg.h>
        !            72: #include <dev/ic/gemvar.h>
        !            73:
        !            74: #include <dev/pci/pcivar.h>
        !            75: #include <dev/pci/pcireg.h>
        !            76: #include <dev/pci/pcidevs.h>
        !            77:
        !            78: struct gem_pci_softc {
        !            79:        struct  gem_softc       gsc_gem;        /* GEM device */
        !            80:        bus_space_tag_t         gsc_memt;
        !            81:        bus_space_handle_t      gsc_memh;
        !            82:        void                    *gsc_ih;
        !            83: };
        !            84:
        !            85: int    gem_match_pci(struct device *, void *, void *);
        !            86: void   gem_attach_pci(struct device *, struct device *, void *);
        !            87: int    gem_pci_enaddr(struct gem_softc *, struct pci_attach_args *);
        !            88:
        !            89: struct cfattach gem_pci_ca = {
        !            90:        sizeof(struct gem_pci_softc), gem_match_pci, gem_attach_pci
        !            91: };
        !            92:
        !            93: /*
        !            94:  * Attach routines need to be split out to different bus-specific files.
        !            95:  */
        !            96:
        !            97: const struct pci_matchid gem_pci_devices[] = {
        !            98:        { PCI_VENDOR_SUN, PCI_PRODUCT_SUN_ERINETWORK },
        !            99:        { PCI_VENDOR_SUN, PCI_PRODUCT_SUN_GEMNETWORK },
        !           100:        { PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_INTREPID2_GMAC },
        !           101:        { PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_K2_GMAC },
        !           102:        { PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_PANGEA_GMAC },
        !           103:        { PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_SHASTA_GMAC },
        !           104:        { PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_UNINORTHGMAC },
        !           105:        { PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_UNINORTH2GMAC },
        !           106: };
        !           107:
        !           108: int
        !           109: gem_match_pci(struct device *parent, void *cf, void *aux)
        !           110: {
        !           111:        return (pci_matchbyid((struct pci_attach_args *)aux, gem_pci_devices,
        !           112:            sizeof(gem_pci_devices)/sizeof(gem_pci_devices[0])));
        !           113: }
        !           114:
        !           115: #define        PROMHDR_PTR_DATA        0x18
        !           116: #define        PROMDATA_PTR_VPD        0x08
        !           117: #define        PROMDATA_DATA2          0x0a
        !           118:
        !           119: static const u_int8_t gem_promhdr[] = { 0x55, 0xaa };
        !           120: static const u_int8_t gem_promdat[] = {
        !           121:        'P', 'C', 'I', 'R',
        !           122:        PCI_VENDOR_SUN & 0xff, PCI_VENDOR_SUN >> 8,
        !           123:        PCI_PRODUCT_SUN_GEMNETWORK & 0xff, PCI_PRODUCT_SUN_GEMNETWORK >> 8
        !           124: };
        !           125:
        !           126: static const u_int8_t gem_promdat2[] = {
        !           127:        0x18, 0x00,                     /* structure length */
        !           128:        0x00,                           /* structure revision */
        !           129:        0x00,                           /* interface revision */
        !           130:        PCI_SUBCLASS_NETWORK_ETHERNET,  /* subclass code */
        !           131:        PCI_CLASS_NETWORK               /* class code */
        !           132: };
        !           133:
        !           134: int
        !           135: gem_pci_enaddr(struct gem_softc *sc, struct pci_attach_args *pa)
        !           136: {
        !           137:        struct pci_vpd *vpd;
        !           138:        bus_space_handle_t romh;
        !           139:        bus_space_tag_t romt;
        !           140:        bus_size_t romsize;
        !           141:        u_int8_t buf[32];
        !           142:        pcireg_t address, mask;
        !           143:        int dataoff, vpdoff;
        !           144:        int rv = -1;
        !           145:
        !           146:        address = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG);
        !           147:        pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, 0xfffffffe);
        !           148:        mask = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG);
        !           149:        address |= PCI_ROM_ENABLE;
        !           150:        pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, address);
        !           151:
        !           152:        romt = pa->pa_memt;
        !           153:        romsize = PCI_ROM_SIZE(mask);
        !           154:        if (bus_space_map(romt, PCI_ROM_ADDR(address), romsize, 0, &romh)) {
        !           155:                romsize = 0;
        !           156:                goto fail;
        !           157:        }
        !           158:
        !           159:        bus_space_read_region_1(romt, romh, 0, buf, sizeof(buf));
        !           160:        if (bcmp(buf, gem_promhdr, sizeof(gem_promhdr)))
        !           161:                goto fail;
        !           162:
        !           163:        dataoff = buf[PROMHDR_PTR_DATA] | (buf[PROMHDR_PTR_DATA + 1] << 8);
        !           164:        if (dataoff < 0x1c)
        !           165:                goto fail;
        !           166:
        !           167:        bus_space_read_region_1(romt, romh, dataoff, buf, sizeof(buf));
        !           168:        if (bcmp(buf, gem_promdat, sizeof(gem_promdat)) ||
        !           169:            bcmp(buf + PROMDATA_DATA2, gem_promdat2, sizeof(gem_promdat2)))
        !           170:                goto fail;
        !           171:
        !           172:        vpdoff = buf[PROMDATA_PTR_VPD] | (buf[PROMDATA_PTR_VPD + 1] << 8);
        !           173:        if (vpdoff < 0x1c)
        !           174:                goto fail;
        !           175:
        !           176:        bus_space_read_region_1(romt, romh, vpdoff, buf, sizeof(buf));
        !           177:
        !           178:        /*
        !           179:         * The VPD of gem is not in PCI 2.2 standard format.  The length
        !           180:         * in the resource header is in big endian.
        !           181:         */
        !           182:        vpd = (struct pci_vpd *)(buf + 3);
        !           183:        if (!PCI_VPDRES_ISLARGE(buf[0]) ||
        !           184:            PCI_VPDRES_LARGE_NAME(buf[0]) != PCI_VPDRES_TYPE_VPD)
        !           185:                goto fail;
        !           186:        if (vpd->vpd_key0 != 'N' || vpd->vpd_key1 != 'A')
        !           187:                goto fail;
        !           188:
        !           189:        bcopy(buf + 6, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
        !           190:        rv = 0;
        !           191:
        !           192:  fail:
        !           193:        if (romsize != 0)
        !           194:                bus_space_unmap(romt, romh, romsize);
        !           195:
        !           196:        address = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG);
        !           197:        address &= ~PCI_ROM_ENABLE;
        !           198:        pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, address);
        !           199:
        !           200:        return (rv);
        !           201: }
        !           202:
        !           203: void
        !           204: gem_attach_pci(struct device *parent, struct device *self, void *aux)
        !           205: {
        !           206:        struct pci_attach_args *pa = aux;
        !           207:        struct gem_pci_softc *gsc = (void *)self;
        !           208:        struct gem_softc *sc = &gsc->gsc_gem;
        !           209:        pci_intr_handle_t ih;
        !           210: #ifdef __sparc64__
        !           211:        /* XXX the following declarations should be elsewhere */
        !           212:        extern void myetheraddr(u_char *);
        !           213: #endif
        !           214:        const char *intrstr = NULL;
        !           215:        bus_size_t size;
        !           216:        int type, gotenaddr = 0;
        !           217:
        !           218:        if (pa->pa_memt) {
        !           219:                type = PCI_MAPREG_TYPE_MEM;
        !           220:                sc->sc_bustag = pa->pa_memt;
        !           221:        } else {
        !           222:                type = PCI_MAPREG_TYPE_IO;
        !           223:                sc->sc_bustag = pa->pa_iot;
        !           224:        }
        !           225:
        !           226:        sc->sc_dmatag = pa->pa_dmat;
        !           227:
        !           228:        sc->sc_pci = 1; /* XXXXX should all be done in bus_dma. */
        !           229:
        !           230:        if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SUN_GEMNETWORK)
        !           231:                sc->sc_variant = GEM_SUN_GEM;
        !           232:        else if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SUN_ERINETWORK)
        !           233:                sc->sc_variant = GEM_SUN_ERI;
        !           234:        else if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_APPLE_INTREPID2_GMAC)
        !           235:                sc->sc_variant = GEM_APPLE_GMAC;
        !           236:        else if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_APPLE_PANGEA_GMAC)
        !           237:                sc->sc_variant = GEM_APPLE_GMAC;
        !           238:        else if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_APPLE_SHASTA_GMAC)
        !           239:                sc->sc_variant = GEM_APPLE_GMAC;
        !           240:        else if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_APPLE_UNINORTHGMAC)
        !           241:                sc->sc_variant = GEM_APPLE_GMAC;
        !           242:        else if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_APPLE_UNINORTH2GMAC)
        !           243:                sc->sc_variant = GEM_APPLE_GMAC;
        !           244:        else if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_APPLE_K2_GMAC)
        !           245:                sc->sc_variant = GEM_APPLE_K2_GMAC;
        !           246:
        !           247: #define PCI_GEM_BASEADDR       0x10
        !           248:        if (pci_mapreg_map(pa, PCI_GEM_BASEADDR, type, 0,
        !           249:            &gsc->gsc_memt, &gsc->gsc_memh, NULL, &size, 0) != 0) {
        !           250:                printf(": could not map registers\n");
        !           251:                return;
        !           252:        }
        !           253:
        !           254:        sc->sc_bustag = gsc->gsc_memt;
        !           255:        sc->sc_h1 = gsc->gsc_memh;
        !           256:
        !           257:        if (bus_space_subregion(sc->sc_bustag, sc->sc_h1,
        !           258:            GEM_PCI_BANK2_OFFSET, GEM_PCI_BANK2_SIZE, &sc->sc_h2)) {
        !           259:                printf(": unable to create bank 2 subregion\n");
        !           260:                bus_space_unmap(gsc->gsc_memt, gsc->gsc_memh, size);
        !           261:                return;
        !           262:        }
        !           263:
        !           264:        if (gem_pci_enaddr(sc, pa) == 0)
        !           265:                gotenaddr = 1;
        !           266:
        !           267: #ifdef __sparc64__
        !           268:        if (!gotenaddr) {
        !           269:                if (OF_getprop(PCITAG_NODE(pa->pa_tag), "local-mac-address",
        !           270:                    sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN) <= 0)
        !           271:                        myetheraddr(sc->sc_arpcom.ac_enaddr);
        !           272:                gotenaddr = 1;
        !           273:        }
        !           274: #endif
        !           275: #ifdef __powerpc__
        !           276:        if (!gotenaddr) {
        !           277:                pci_ether_hw_addr(pa->pa_pc, sc->sc_arpcom.ac_enaddr);
        !           278:                gotenaddr = 1;
        !           279:        }
        !           280: #endif
        !           281:
        !           282:        sc->sc_burst = 16;      /* XXX */
        !           283:
        !           284:        if (pci_intr_map(pa, &ih) != 0) {
        !           285:                printf(": couldn't map interrupt\n");
        !           286:                bus_space_unmap(gsc->gsc_memt, gsc->gsc_memh, size);
        !           287:                return;
        !           288:        }
        !           289:        intrstr = pci_intr_string(pa->pa_pc, ih);
        !           290:        gsc->gsc_ih = pci_intr_establish(pa->pa_pc,
        !           291:            ih, IPL_NET, gem_intr, sc, self->dv_xname);
        !           292:        if (gsc->gsc_ih == NULL) {
        !           293:                printf(": couldn't establish interrupt");
        !           294:                if (intrstr != NULL)
        !           295:                        printf(" at %s", intrstr);
        !           296:                printf("\n");
        !           297:                bus_space_unmap(gsc->gsc_memt, gsc->gsc_memh, size);
        !           298:                return;
        !           299:        }
        !           300:
        !           301:        printf(": %s", intrstr);
        !           302:
        !           303:        /*
        !           304:         * call the main configure
        !           305:         */
        !           306:        gem_config(sc);
        !           307: }

CVSweb