Annotation of sys/dev/pci/mpi_pci.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: mpi_pci.c,v 1.14 2007/03/17 10:25:39 dlg Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
! 5: * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
! 6: *
! 7: * Permission to use, copy, modify, and distribute this software for any
! 8: * purpose with or without fee is hereby granted, provided that the above
! 9: * copyright notice and this permission notice appear in all copies.
! 10: *
! 11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 15: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 16: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 17: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 18: */
! 19:
! 20: #include <sys/param.h>
! 21: #include <sys/systm.h>
! 22: #include <sys/kernel.h>
! 23: #include <sys/malloc.h>
! 24: #include <sys/device.h>
! 25:
! 26: #include <machine/bus.h>
! 27:
! 28: #include <dev/pci/pcireg.h>
! 29: #include <dev/pci/pcivar.h>
! 30: #include <dev/pci/pcidevs.h>
! 31:
! 32: #include <scsi/scsi_all.h>
! 33: #include <scsi/scsiconf.h>
! 34:
! 35: #include <dev/ic/mpireg.h>
! 36: #include <dev/ic/mpivar.h>
! 37:
! 38: int mpi_pci_match(struct device *, void *, void *);
! 39: void mpi_pci_attach(struct device *, struct device *, void *);
! 40: int mpi_pci_detach(struct device *, int);
! 41:
! 42: struct mpi_pci_softc {
! 43: struct mpi_softc psc_mpi;
! 44:
! 45: pci_chipset_tag_t psc_pc;
! 46: pcitag_t psc_tag;
! 47:
! 48: void *psc_ih;
! 49: };
! 50:
! 51: struct cfattach mpi_pci_ca = {
! 52: sizeof(struct mpi_pci_softc), mpi_pci_match, mpi_pci_attach,
! 53: mpi_pci_detach
! 54: };
! 55:
! 56: #define PREAD(s, r) pci_conf_read((s)->psc_pc, (s)->psc_tag, (r))
! 57: #define PWRITE(s, r, v) pci_conf_write((s)->psc_pc, (s)->psc_tag, (r), (v))
! 58:
! 59: static const struct pci_matchid mpi_devices[] = {
! 60: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_1030 },
! 61: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC909 },
! 62: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC909A },
! 63: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC919 },
! 64: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC919_1 },
! 65: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC919X },
! 66: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC929 },
! 67: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC929_1 },
! 68: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC929X },
! 69: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC939X },
! 70: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC949E },
! 71: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_FC949X },
! 72: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1064 },
! 73: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1064A },
! 74: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1064E },
! 75: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1066 },
! 76: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1066E },
! 77: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1068 },
! 78: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1078 },
! 79: { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1068E }
! 80: };
! 81:
! 82: int
! 83: mpi_pci_match(struct device *parent, void *match, void *aux)
! 84: {
! 85: return (pci_matchbyid((struct pci_attach_args *)aux, mpi_devices,
! 86: sizeof(mpi_devices) / sizeof(mpi_devices[0])));
! 87: }
! 88:
! 89: void
! 90: mpi_pci_attach(struct device *parent, struct device *self, void *aux)
! 91: {
! 92: struct mpi_pci_softc *psc = (void *)self;
! 93: struct mpi_softc *sc = &psc->psc_mpi;
! 94: struct pci_attach_args *pa = aux;
! 95: pcireg_t memtype;
! 96: int r;
! 97: pci_intr_handle_t ih;
! 98: const char *intrstr;
! 99:
! 100: psc->psc_pc = pa->pa_pc;
! 101: psc->psc_tag = pa->pa_tag;
! 102: psc->psc_ih = NULL;
! 103: sc->sc_dmat = pa->pa_dmat;
! 104: sc->sc_ios = 0;
! 105:
! 106: /* find the appropriate memory base */
! 107: for (r = PCI_MAPREG_START; r < PCI_MAPREG_END; r += sizeof(memtype)) {
! 108: memtype = pci_mapreg_type(psc->psc_pc, psc->psc_tag, r);
! 109: if ((memtype & PCI_MAPREG_TYPE_MASK) == PCI_MAPREG_TYPE_MEM)
! 110: break;
! 111: }
! 112: if (r >= PCI_MAPREG_END) {
! 113: printf(": unable to locate system interface registers\n");
! 114: return;
! 115: }
! 116:
! 117: if (pci_mapreg_map(pa, r, memtype, 0, &sc->sc_iot, &sc->sc_ioh,
! 118: NULL, &sc->sc_ios, 0) != 0) {
! 119: printf(": unable to map system interface registers\n");
! 120: return;
! 121: }
! 122:
! 123: /* disable the expansion rom */
! 124: PWRITE(psc, PCI_ROM_REG, PREAD(psc, PCI_ROM_REG) & ~PCI_ROM_ENABLE);
! 125:
! 126: /* hook up the interrupt */
! 127: if (pci_intr_map(pa, &ih)) {
! 128: printf(": unable to map interrupt\n");
! 129: goto unmap;
! 130: }
! 131: intrstr = pci_intr_string(psc->psc_pc, ih);
! 132: psc->psc_ih = pci_intr_establish(psc->psc_pc, ih, IPL_BIO,
! 133: mpi_intr, sc, sc->sc_dev.dv_xname);
! 134: if (psc->psc_ih == NULL) {
! 135: printf(": unable to map interrupt%s%s\n",
! 136: intrstr == NULL ? "" : " at ",
! 137: intrstr == NULL ? "" : intrstr);
! 138: goto unmap;
! 139: }
! 140: printf(": %s", intrstr);
! 141:
! 142: if (pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG) ==
! 143: PCI_ID_CODE(PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_1030))
! 144: sc->sc_flags |= MPI_F_SPI;
! 145:
! 146: if (mpi_attach(sc) != 0) {
! 147: /* error printed by mpi_attach */
! 148: goto deintr;
! 149: }
! 150:
! 151: return;
! 152:
! 153: deintr:
! 154: pci_intr_disestablish(psc->psc_pc, psc->psc_ih);
! 155: psc->psc_ih = NULL;
! 156: unmap:
! 157: bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
! 158: sc->sc_ios = 0;
! 159: }
! 160:
! 161: int
! 162: mpi_pci_detach(struct device *self, int flags)
! 163: {
! 164: struct mpi_pci_softc *psc = (struct mpi_pci_softc *)self;
! 165: struct mpi_softc *sc = &psc->psc_mpi;
! 166:
! 167: mpi_detach(sc);
! 168:
! 169: if (psc->psc_ih != NULL) {
! 170: pci_intr_disestablish(psc->psc_pc, psc->psc_ih);
! 171: psc->psc_ih = NULL;
! 172: }
! 173: if (sc->sc_ios != 0) {
! 174: bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
! 175: sc->sc_ios = 0;
! 176: }
! 177:
! 178: return (0);
! 179: }
CVSweb