The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/pci/cac_pci.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 8b132eb59b3758ed2af306bb618549b2


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.