root/dev/pci/mpi_pci.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mpi_pci_match
  2. mpi_pci_attach
  3. mpi_pci_detach

    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 }

/* [<][>][^][v][top][bottom][index][help] */