/* $OpenBSD: sli_pci.c,v 1.4 2007/05/19 04:10:20 dlg Exp $ */ /* * Copyright (c) 2007 David Gwynne <dlg@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/device.h> #include <machine/bus.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcidevs.h> #include <scsi/scsi_all.h> #include <scsi/scsiconf.h> #include <dev/ic/slireg.h> #include <dev/ic/slivar.h> int sli_pci_match(struct device *, void *, void *); void sli_pci_attach(struct device *, struct device *, void *); int sli_pci_detach(struct device *, int); struct sli_pci_softc { struct sli_softc psc_sli; pci_chipset_tag_t psc_pc; pcitag_t psc_tag; void *psc_ih; }; struct cfattach sli_pci_ca = { sizeof(struct sli_pci_softc), sli_pci_match, sli_pci_attach, sli_pci_detach }; static const struct pci_matchid sli_pci_devices[] = { { PCI_VENDOR_EMULEX, PCI_PRODUCT_EMULEX_LP8000 } }; int sli_pci_match(struct device *parent, void *match, void *aux) { return (pci_matchbyid((struct pci_attach_args *)aux, sli_pci_devices, sizeof(sli_pci_devices) / sizeof(sli_pci_devices[0]))); } void sli_pci_attach(struct device *parent, struct device *self, void *aux) { struct sli_pci_softc *psc = (struct sli_pci_softc *)self; struct sli_softc *sc = &psc->psc_sli; struct pci_attach_args *pa = aux; pcireg_t memtype; pci_intr_handle_t ih; psc->psc_pc = pa->pa_pc; psc->psc_tag = pa->pa_tag; psc->psc_ih = NULL; sc->sc_dmat = pa->pa_dmat; sc->sc_ios_slim = 0; sc->sc_ios_reg = 0; memtype = pci_mapreg_type(psc->psc_pc, psc->psc_tag, SLI_PCI_BAR_SLIM); if (pci_mapreg_map(pa, SLI_PCI_BAR_SLIM, memtype, 0, &sc->sc_iot_slim, &sc->sc_ioh_slim, NULL, &sc->sc_ios_slim, 0) != 0) { printf(": unable to map SLIM bar\n"); return; } memtype = pci_mapreg_type(psc->psc_pc, psc->psc_tag, SLI_PCI_BAR_REGISTER); if (pci_mapreg_map(pa, SLI_PCI_BAR_REGISTER, memtype, 0, &sc->sc_iot_reg, &sc->sc_ioh_reg, NULL, &sc->sc_ios_reg, 0) != 0) { printf(": unable to map REGISTER bar\n"); goto unmap_slim; } if (pci_intr_map(pa, &ih)) { printf(": unable to map interrupt\n"); goto unmap_reg; } printf(": %s", pci_intr_string(psc->psc_pc, ih)); if (sli_attach(sc) != 0) { /* error already printed by sli_attach() */ goto unmap_reg; } psc->psc_ih = pci_intr_establish(psc->psc_pc, ih, IPL_BIO, sli_intr, sc, DEVNAME(sc)); if (psc->psc_ih == NULL) { printf("%s: unable to establish interrupt\n"); goto detach; } return; detach: sli_detach(sc, DETACH_FORCE|DETACH_QUIET); unmap_reg: bus_space_unmap(sc->sc_iot_reg, sc->sc_ioh_reg, sc->sc_ios_reg); sc->sc_ios_reg = 0; unmap_slim: bus_space_unmap(sc->sc_iot_slim, sc->sc_ioh_slim, sc->sc_ios_slim); sc->sc_ios_slim = 0; } int sli_pci_detach(struct device *self, int flags) { struct sli_pci_softc *psc = (struct sli_pci_softc *)self; struct sli_softc *sc = &psc->psc_sli; int rv; rv = sli_detach(sc, flags); if (rv != 0) return (rv); return (0); }