root/dev/pci/cac_pci.c

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

DEFINITIONS

This source file includes following definitions.
  1. cac_pci_findtype
  2. cac_pci_match
  3. cac_pci_attach
  4. cac_pci_l0_submit
  5. cac_pci_l0_completed
  6. cac_pci_l0_intr_pending
  7. cac_pci_l0_intr_enable
  8. cac_pci_l0_fifo_full

    1 /*      $OpenBSD: cac_pci.c,v 1.10 2005/08/09 04:10:10 mickey Exp $     */
    2 /*      $NetBSD: cac_pci.c,v 1.10 2001/01/10 16:48:04 ad Exp $  */
    3 
    4 /*-
    5  * Copyright (c) 2000 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Andrew Doran.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *        This product includes software developed by the NetBSD
   22  *        Foundation, Inc. and its contributors.
   23  * 4. Neither the name of The NetBSD Foundation nor the names of its
   24  *    contributors may be used to endorse or promote products derived
   25  *    from this software without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 /*
   41  * PCI front-end for cac(4) driver.
   42  */
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/kernel.h>
   47 #include <sys/device.h>
   48 #include <sys/queue.h>
   49 
   50 #include <machine/endian.h>
   51 #include <machine/bus.h>
   52 
   53 #include <dev/pci/pcidevs.h>
   54 #include <dev/pci/pcivar.h>
   55 
   56 #include <scsi/scsi_all.h>
   57 #include <scsi/scsi_disk.h>
   58 #include <scsi/scsiconf.h>
   59 
   60 #include <dev/ic/cacreg.h>
   61 #include <dev/ic/cacvar.h>
   62 
   63 void    cac_pci_attach(struct device *, struct device *, void *);
   64 const struct    cac_pci_type *cac_pci_findtype(struct pci_attach_args *);
   65 int     cac_pci_match(struct device *, void *, void *);
   66 
   67 struct  cac_ccb *cac_pci_l0_completed(struct cac_softc *);
   68 int     cac_pci_l0_fifo_full(struct cac_softc *);
   69 void    cac_pci_l0_intr_enable(struct cac_softc *, int);
   70 int     cac_pci_l0_intr_pending(struct cac_softc *);
   71 void    cac_pci_l0_submit(struct cac_softc *, struct cac_ccb *);
   72 
   73 struct cfattach cac_pci_ca = {
   74         sizeof(struct cac_softc), cac_pci_match, cac_pci_attach
   75 };
   76 
   77 static const struct cac_linkage cac_pci_l0 = {
   78         cac_pci_l0_completed,
   79         cac_pci_l0_fifo_full,
   80         cac_pci_l0_intr_enable,
   81         cac_pci_l0_intr_pending,
   82         cac_pci_l0_submit
   83 };
   84 
   85 #define CT_STARTFW      0x01    /* Need to start controller firmware */
   86 
   87 static const
   88 struct cac_pci_type {
   89         int     ct_subsysid;
   90         int     ct_flags;
   91         const struct    cac_linkage *ct_linkage;
   92         char    *ct_typestr;
   93 } cac_pci_type[] = {
   94         { 0x40300e11,   0,              &cac_l0,        "SMART-2/P" },
   95         { 0x40310e11,   0,              &cac_l0,        "SMART-2SL" },
   96         { 0x40320e11,   0,              &cac_l0,        "Smart Array 3200" },
   97         { 0x40330e11,   0,              &cac_l0,        "Smart Array 3100ES" },
   98         { 0x40340e11,   0,              &cac_l0,        "Smart Array 221" },
   99         { 0x40400e11,   CT_STARTFW,     &cac_pci_l0,    "Integrated Array" },
  100         { 0x40480e11,   CT_STARTFW,     &cac_pci_l0,    "RAID LC2" },
  101         { 0x40500e11,   0,              &cac_pci_l0,    "Smart Array 4200" },
  102         { 0x40510e11,   0,              &cac_pci_l0,    "Smart Array 4200ES" },
  103         { 0x40580e11,   0,              &cac_pci_l0,    "Smart Array 431" },
  104 };
  105 
  106 static const
  107 struct cac_pci_product {
  108         u_short cp_vendor;
  109         u_short cp_product;
  110 } cac_pci_product[] = {
  111         { PCI_VENDOR_COMPAQ,    PCI_PRODUCT_COMPAQ_SMART2P },
  112         { PCI_VENDOR_DEC,       PCI_PRODUCT_DEC_CPQ42XX },
  113         { PCI_VENDOR_SYMBIOS,   PCI_PRODUCT_SYMBIOS_1510 },
  114 };
  115 
  116 const struct cac_pci_type *
  117 cac_pci_findtype(pa)
  118         struct pci_attach_args *pa;
  119 {
  120         const struct cac_pci_type *ct;
  121         const struct cac_pci_product *cp;
  122         pcireg_t subsysid;
  123         int i;
  124 
  125         cp = cac_pci_product;
  126         i = 0;
  127         while (i < sizeof(cac_pci_product) / sizeof(cac_pci_product[0])) {
  128                 if (PCI_VENDOR(pa->pa_id) == cp->cp_vendor &&
  129                     PCI_PRODUCT(pa->pa_id) == cp->cp_product)
  130                         break;
  131                 cp++;
  132                 i++;
  133         }
  134         if (i == sizeof(cac_pci_product) / sizeof(cac_pci_product[0]))
  135                 return (NULL);
  136 
  137         subsysid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
  138         ct = cac_pci_type;
  139         i = 0;
  140         while (i < sizeof(cac_pci_type) / sizeof(cac_pci_type[0])) {
  141                 if (subsysid == ct->ct_subsysid)
  142                         break;
  143                 ct++;
  144                 i++;
  145         }
  146         if (i == sizeof(cac_pci_type) / sizeof(cac_pci_type[0]))
  147                 return (NULL);
  148 
  149         return (ct);
  150 }
  151 
  152 int
  153 cac_pci_match(parent, match, aux)
  154         struct device *parent;
  155         void *match, *aux;
  156 {
  157 
  158         return (cac_pci_findtype(aux) != NULL);
  159 }
  160 
  161 void
  162 cac_pci_attach(parent, self, aux)
  163         struct device *parent;
  164         struct device *self;
  165         void *aux;
  166 {
  167         struct pci_attach_args *pa;
  168         const struct cac_pci_type *ct;
  169         struct cac_softc *sc;
  170         pci_chipset_tag_t pc;
  171         pci_intr_handle_t ih;
  172         const char *intrstr;
  173         pcireg_t reg;
  174         bus_size_t size;
  175         int memr, ior, i;
  176 
  177         sc = (struct cac_softc *)self;
  178         pa = (struct pci_attach_args *)aux;
  179         pc = pa->pa_pc;
  180         ct = cac_pci_findtype(pa);
  181 
  182         /*
  183          * Map the PCI register window.
  184          */
  185         memr = -1;
  186         ior = -1;
  187 
  188         for (i = 0x10; i <= 0x14; i += 4) {
  189                 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, i);
  190 
  191                 if (PCI_MAPREG_TYPE(reg) == PCI_MAPREG_TYPE_IO) {
  192                         if (ior == -1 && PCI_MAPREG_IO_SIZE(reg) != 0)
  193                                 ior = i;
  194                 } else {
  195                         if (memr == -1 && PCI_MAPREG_MEM_SIZE(reg) != 0)
  196                                 memr = i;
  197                 }
  198         }
  199 
  200         if (memr != -1) {
  201                 if (pci_mapreg_map(pa, memr, PCI_MAPREG_TYPE_MEM, 0,
  202                     &sc->sc_iot, &sc->sc_ioh, NULL, &size, 0))
  203                         memr = -1;
  204                 else
  205                         ior = -1;
  206         }
  207         if (ior != -1)
  208                 if (pci_mapreg_map(pa, ior, PCI_MAPREG_TYPE_IO, 0,
  209                     &sc->sc_iot, &sc->sc_ioh, NULL, &size, 0))
  210                         ior = -1;
  211         if (memr == -1 && ior == -1) {
  212                 printf("%s: can't map i/o or memory space\n", self->dv_xname);
  213                 return;
  214         }
  215 
  216         sc->sc_dmat = pa->pa_dmat;
  217 
  218         /* Map and establish the interrupt. */
  219         if (pci_intr_map(pa, &ih)) {
  220                 printf(": can't map interrupt\n");
  221                 bus_space_unmap(sc->sc_iot, sc->sc_ioh, size);
  222                 return;
  223         }
  224         intrstr = pci_intr_string(pc, ih);
  225         sc->sc_ih = pci_intr_establish(pc, ih, IPL_BIO, cac_intr,
  226             sc, sc->sc_dv.dv_xname);
  227         if (sc->sc_ih == NULL) {
  228                 printf(": can't establish interrupt");
  229                 if (intrstr != NULL)
  230                         printf(" at %s", intrstr);
  231                 printf("\n");
  232                 bus_space_unmap(sc->sc_iot, sc->sc_ioh, size);
  233                 return;
  234         }
  235 
  236         printf(": %s Compaq %s\n", intrstr, ct->ct_typestr);
  237 
  238         /* Now attach to the bus-independent code. */
  239         sc->sc_cl = ct->ct_linkage;
  240         cac_init(sc, (ct->ct_flags & CT_STARTFW) != 0);
  241 }
  242 
  243 void
  244 cac_pci_l0_submit(struct cac_softc *sc, struct cac_ccb *ccb)
  245 {
  246 
  247         bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
  248             sc->sc_dmamap->dm_mapsize,
  249             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
  250         cac_outl(sc, CAC_42REG_CMD_FIFO, ccb->ccb_paddr);
  251 }
  252 
  253 struct cac_ccb *
  254 cac_pci_l0_completed(struct cac_softc *sc)
  255 {
  256         struct cac_ccb *ccb;
  257         u_int32_t off;
  258 
  259         if ((off = cac_inl(sc, CAC_42REG_DONE_FIFO)) == 0xffffffffU)
  260                 return (NULL);
  261 
  262         cac_outl(sc, CAC_42REG_DONE_FIFO, 0);
  263         off = (off & ~3) - sc->sc_ccbs_paddr;
  264         ccb = (struct cac_ccb *)(sc->sc_ccbs + off);
  265 
  266         bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
  267             sc->sc_dmamap->dm_mapsize,
  268             BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
  269 
  270         return (ccb);
  271 }
  272 
  273 int
  274 cac_pci_l0_intr_pending(struct cac_softc *sc)
  275 {
  276 
  277         return ((cac_inl(sc, CAC_42REG_STATUS) & CAC_42_EXTINT) != 0);
  278 }
  279 
  280 void
  281 cac_pci_l0_intr_enable(struct cac_softc *sc, int state)
  282 {
  283 
  284         cac_outl(sc, CAC_42REG_INTR_MASK, (state ? 0 : 8));     /* XXX */
  285 }
  286 
  287 int
  288 cac_pci_l0_fifo_full(struct cac_softc *sc)
  289 {
  290 
  291         return (cac_inl(sc, CAC_42REG_CMD_FIFO) != 0);
  292 }

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