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/icp_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: icp_pci.c,v 1.9 2003/06/29 01:20:50 thorpej Exp $      */
    2 
    3 /*-
    4  * Copyright (c) 2002 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  * Copyright (c) 1999, 2000 Niklas Hallqvist.  All rights reserved.
   41  *
   42  * Redistribution and use in source and binary forms, with or without
   43  * modification, are permitted provided that the following conditions
   44  * are met:
   45  * 1. Redistributions of source code must retain the above copyright
   46  *    notice, this list of conditions and the following disclaimer.
   47  * 2. Redistributions in binary form must reproduce the above copyright
   48  *    notice, this list of conditions and the following disclaimer in the
   49  *    documentation and/or other materials provided with the distribution.
   50  * 3. All advertising materials mentioning features or use of this software
   51  *    must display the following acknowledgement:
   52  *      This product includes software developed by Niklas Hallqvist.
   53  * 4. The name of the author may not be used to endorse or promote products
   54  *    derived from this software without specific prior written permission.
   55  *
   56  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   57  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   58  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   59  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   60  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   61  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   62  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   63  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   64  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   65  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   66  *
   67  * from OpenBSD: icp_pci.c,v 1.11 2001/06/12 15:40:30 niklas Exp
   68  */
   69 
   70 /*
   71  * This driver would not have written if it was not for the hardware donations
   72  * from both ICP-Vortex and Öko.neT.  I want to thank them for their support.
   73  *
   74  * Re-worked for NetBSD by Andrew Doran.  Test hardware kindly supplied by
   75  * Intel.
   76  */
   77 
   78 #include <sys/cdefs.h>
   79 __KERNEL_RCSID(0, "$NetBSD: icp_pci.c,v 1.9 2003/06/29 01:20:50 thorpej Exp $");
   80 
   81 #include <sys/param.h>
   82 #include <sys/systm.h>
   83 #include <sys/device.h>
   84 #include <sys/kernel.h>
   85 #include <sys/queue.h>
   86 #include <sys/buf.h>
   87 #include <sys/endian.h>
   88 #include <sys/conf.h>
   89 
   90 #include <uvm/uvm_extern.h>
   91 
   92 #include <machine/bus.h>
   93 
   94 #include <dev/pci/pcireg.h>
   95 #include <dev/pci/pcivar.h>
   96 #include <dev/pci/pcidevs.h>
   97 
   98 #include <dev/ic/icpreg.h>
   99 #include <dev/ic/icpvar.h>
  100 
  101 /* Product numbers for Fibre-Channel are greater than or equal to 0x200 */
  102 #define ICP_PCI_PRODUCT_FC      0x200
  103 
  104 /* Mapping registers for various areas */
  105 #define ICP_PCI_DPMEM           0x10
  106 #define ICP_PCINEW_IOMEM        0x10
  107 #define ICP_PCINEW_IO           0x14
  108 #define ICP_PCINEW_DPMEM        0x18
  109 
  110 /* PCI SRAM structure */
  111 #define ICP_MAGIC       0x00    /* u_int32_t, controller ID from BIOS */
  112 #define ICP_NEED_DEINIT 0x04    /* u_int16_t, switch between BIOS/driver */
  113 #define ICP_SWITCH_SUPPORT 0x06 /* u_int8_t, see ICP_NEED_DEINIT */
  114 #define ICP_OS_USED     0x10    /* u_int8_t [16], OS code per service */
  115 #define ICP_FW_MAGIC    0x3c    /* u_int8_t, controller ID from firmware */
  116 #define ICP_SRAM_SZ     0x40
  117 
  118 /* DPRAM PCI controllers */
  119 #define ICP_DPR_IF      0x00    /* interface area */
  120 #define ICP_6SR         (0xff0 - ICP_SRAM_SZ)
  121 #define ICP_SEMA1       0xff1   /* volatile u_int8_t, command semaphore */
  122 #define ICP_IRQEN       0xff5   /* u_int8_t, board interrupts enable */
  123 #define ICP_EVENT       0xff8   /* u_int8_t, release event */
  124 #define ICP_IRQDEL      0xffc   /* u_int8_t, acknowledge board interrupt */
  125 #define ICP_DPRAM_SZ    0x1000
  126 
  127 /* PLX register structure (new PCI controllers) */
  128 #define ICP_CFG_REG     0x00    /* u_int8_t, DPRAM cfg. (2: < 1MB, 0: any) */
  129 #define ICP_SEMA0_REG   0x40    /* volatile u_int8_t, command semaphore */
  130 #define ICP_SEMA1_REG   0x41    /* volatile u_int8_t, status semaphore */
  131 #define ICP_PLX_STATUS  0x44    /* volatile u_int16_t, command status */
  132 #define ICP_PLX_SERVICE 0x46    /* u_int16_t, service */
  133 #define ICP_PLX_INFO    0x48    /* u_int32_t [2], additional info */
  134 #define ICP_LDOOR_REG   0x60    /* u_int8_t, PCI to local doorbell */
  135 #define ICP_EDOOR_REG   0x64    /* volatile u_int8_t, local to PCI doorbell */
  136 #define ICP_CONTROL0    0x68    /* u_int8_t, control0 register (unused) */
  137 #define ICP_CONTROL1    0x69    /* u_int8_t, board interrupts enable */
  138 #define ICP_PLX_SZ      0x80
  139 
  140 /* DPRAM new PCI controllers */
  141 #define ICP_IC          0x00    /* interface */
  142 #define ICP_PCINEW_6SR  (0x4000 - ICP_SRAM_SZ)
  143                                 /* SRAM structure */
  144 #define ICP_PCINEW_SZ   0x4000
  145 
  146 /* i960 register structure (PCI MPR controllers) */
  147 #define ICP_MPR_SEMA0   0x10    /* volatile u_int8_t, command semaphore */
  148 #define ICP_MPR_SEMA1   0x12    /* volatile u_int8_t, status semaphore */
  149 #define ICP_MPR_STATUS  0x14    /* volatile u_int16_t, command status */
  150 #define ICP_MPR_SERVICE 0x16    /* u_int16_t, service */
  151 #define ICP_MPR_INFO    0x18    /* u_int32_t [2], additional info */
  152 #define ICP_MPR_LDOOR   0x20    /* u_int8_t, PCI to local doorbell */
  153 #define ICP_MPR_EDOOR   0x2c    /* volatile u_int8_t, locl to PCI doorbell */
  154 #define ICP_EDOOR_EN    0x34    /* u_int8_t, board interrupts enable */
  155 #define ICP_SEVERITY    0xefc   /* u_int8_t, event severity */
  156 #define ICP_EVT_BUF     0xf00   /* u_int8_t [256], event buffer */
  157 #define ICP_I960_SZ     0x1000
  158 
  159 /* DPRAM PCI MPR controllers */
  160 #define ICP_I960R       0x00    /* 4KB i960 registers */
  161 #define ICP_MPR_IC      ICP_I960_SZ
  162                                 /* interface area */
  163 #define ICP_MPR_6SR     (ICP_I960_SZ + 0x3000 - ICP_SRAM_SZ)
  164                                 /* SRAM structure */
  165 #define ICP_MPR_SZ      0x4000
  166 
  167 int     icp_pci_match(struct device *, struct cfdata *, void *);
  168 void    icp_pci_attach(struct device *, struct device *, void *);
  169 void    icp_pci_enable_intr(struct icp_softc *);
  170 int     icp_pci_find_class(struct pci_attach_args *);
  171 
  172 void    icp_pci_copy_cmd(struct icp_softc *, struct icp_ccb *);
  173 u_int8_t icp_pci_get_status(struct icp_softc *);
  174 void    icp_pci_intr(struct icp_softc *, struct icp_intr_ctx *);
  175 void    icp_pci_release_event(struct icp_softc *, struct icp_ccb *);
  176 void    icp_pci_set_sema0(struct icp_softc *);
  177 int     icp_pci_test_busy(struct icp_softc *);
  178 
  179 void    icp_pcinew_copy_cmd(struct icp_softc *, struct icp_ccb *);
  180 u_int8_t icp_pcinew_get_status(struct icp_softc *);
  181 void    icp_pcinew_intr(struct icp_softc *, struct icp_intr_ctx *);
  182 void    icp_pcinew_release_event(struct icp_softc *, struct icp_ccb *);
  183 void    icp_pcinew_set_sema0(struct icp_softc *);
  184 int     icp_pcinew_test_busy(struct icp_softc *);
  185 
  186 void    icp_mpr_copy_cmd(struct icp_softc *, struct icp_ccb *);
  187 u_int8_t icp_mpr_get_status(struct icp_softc *);
  188 void    icp_mpr_intr(struct icp_softc *, struct icp_intr_ctx *);
  189 void    icp_mpr_release_event(struct icp_softc *, struct icp_ccb *);
  190 void    icp_mpr_set_sema0(struct icp_softc *);
  191 int     icp_mpr_test_busy(struct icp_softc *);
  192 
  193 CFATTACH_DECL(icp_pci, sizeof(struct icp_softc),
  194     icp_pci_match, icp_pci_attach, NULL, NULL);
  195 
  196 struct icp_pci_ident {
  197         u_short gpi_vendor;
  198         u_short gpi_product;
  199         u_short gpi_class;
  200 } const icp_pci_ident[] = {
  201         { PCI_VENDOR_VORTEX,    PCI_PRODUCT_VORTEX_GDT_60x0,    ICP_PCI },
  202         { PCI_VENDOR_VORTEX,    PCI_PRODUCT_VORTEX_GDT_6000B,   ICP_PCI },
  203 
  204         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_GDT_RAID1,    ICP_MPR },
  205         { PCI_VENDOR_INTEL,     PCI_PRODUCT_INTEL_GDT_RAID2,    ICP_MPR },
  206 };
  207 
  208 int
  209 icp_pci_find_class(struct pci_attach_args *pa)
  210 {
  211         const struct icp_pci_ident *gpi, *maxgpi;
  212 
  213         gpi = icp_pci_ident;
  214         maxgpi = gpi + sizeof(icp_pci_ident) / sizeof(icp_pci_ident[0]);
  215 
  216         for (; gpi < maxgpi; gpi++)
  217                 if (PCI_VENDOR(pa->pa_id) == gpi->gpi_vendor &&
  218                     PCI_PRODUCT(pa->pa_id) == gpi->gpi_product)
  219                         return (gpi->gpi_class);
  220 
  221         /*
  222          * ICP-Vortex only make RAID controllers, so we employ a heuristic
  223          * to match unlisted boards.
  224          */
  225         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_VORTEX)
  226                 return (PCI_PRODUCT(pa->pa_id) < 0x100 ? ICP_PCINEW : ICP_MPR);
  227 
  228         return (-1);
  229 }
  230 
  231 int
  232 icp_pci_match(struct device *parent, struct cfdata *match, void *aux)
  233 {
  234         struct pci_attach_args *pa;
  235 
  236         pa = aux;
  237 
  238         if (PCI_CLASS(pa->pa_class) == PCI_CLASS_I2O)
  239                 return (0);
  240 
  241         return (icp_pci_find_class(pa) != -1);
  242 }
  243 
  244 void
  245 icp_pci_attach(struct device *parent, struct device *self, void *aux)
  246 {
  247         struct pci_attach_args *pa;
  248         struct icp_softc *icp;
  249         bus_space_tag_t dpmemt, iomemt, iot;
  250         bus_space_handle_t dpmemh, iomemh, ioh;
  251         bus_addr_t dpmembase, iomembase, iobase;
  252         bus_size_t dpmemsize, iomemsize, iosize;
  253         u_int32_t status;
  254 #define DPMEM_MAPPED            1
  255 #define IOMEM_MAPPED            2
  256 #define IO_MAPPED               4
  257 #define INTR_ESTABLISHED        8
  258         int retries;
  259         u_int8_t protocol;
  260         pci_intr_handle_t ih;
  261         const char *intrstr;
  262 
  263         pa = aux;
  264         status = 0;
  265         icp = (struct icp_softc *)self;
  266         icp->icp_class = icp_pci_find_class(pa);
  267 
  268         aprint_naive(": RAID controller\n");
  269         aprint_normal(": ");
  270 
  271         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_VORTEX &&
  272             PCI_PRODUCT(pa->pa_id) >= ICP_PCI_PRODUCT_FC)
  273                 icp->icp_class |= ICP_FC;
  274 
  275         if (pci_mapreg_map(pa,
  276             ICP_CLASS(icp) == ICP_PCINEW ? ICP_PCINEW_DPMEM : ICP_PCI_DPMEM,
  277             PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &dpmemt,
  278             &dpmemh, &dpmembase, &dpmemsize)) {
  279                 if (pci_mapreg_map(pa,
  280                     ICP_CLASS(icp) == ICP_PCINEW ? ICP_PCINEW_DPMEM :
  281                     ICP_PCI_DPMEM,
  282                     PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT_1M, 0,
  283                     &dpmemt, &dpmemh, &dpmembase, &dpmemsize)) {
  284                         aprint_error("cannot map DPMEM\n");
  285                         goto bail_out;
  286                 }
  287         }
  288         status |= DPMEM_MAPPED;
  289         icp->icp_dpmemt = dpmemt;
  290         icp->icp_dpmemh = dpmemh;
  291         icp->icp_dpmembase = dpmembase;
  292         icp->icp_dmat = pa->pa_dmat;
  293 
  294         /*
  295          * The ICP_PCINEW series also has two other regions to map.
  296          */
  297         if (ICP_CLASS(icp) == ICP_PCINEW) {
  298                 if (pci_mapreg_map(pa, ICP_PCINEW_IOMEM, PCI_MAPREG_TYPE_MEM,
  299                     0, &iomemt, &iomemh, &iomembase, &iomemsize)) {
  300                         aprint_error("cannot map memory mapped I/O ports\n");
  301                         goto bail_out;
  302                 }
  303                 status |= IOMEM_MAPPED;
  304 
  305                 if (pci_mapreg_map(pa, ICP_PCINEW_IO, PCI_MAPREG_TYPE_IO, 0,
  306                     &iot, &ioh, &iobase, &iosize)) {
  307                         aprint_error("cannot map I/O ports\n");
  308                         goto bail_out;
  309                 }
  310                 status |= IO_MAPPED;
  311                 icp->icp_iot = iot;
  312                 icp->icp_ioh = ioh;
  313                 icp->icp_iobase = iobase;
  314         }
  315 
  316         switch (ICP_CLASS(icp)) {
  317         case ICP_PCI:
  318                 bus_space_set_region_4(dpmemt, dpmemh, 0, 0,
  319                     ICP_DPR_IF_SZ >> 2);
  320                 if (bus_space_read_1(dpmemt, dpmemh, 0) != 0) {
  321                         aprint_error("cannot write to DPMEM\n");
  322                         goto bail_out;
  323                 }
  324 
  325 #if 0
  326                 /* disable board interrupts, deinit services */
  327                 icph_writeb(0xff, &dp6_ptr->io.irqdel);
  328                 icph_writeb(0x00, &dp6_ptr->io.irqen);
  329                 icph_writeb(0x00, &dp6_ptr->u.ic.S_Status);
  330                 icph_writeb(0x00, &dp6_ptr->u.ic.Cmd_Index);
  331 
  332                 icph_writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]);
  333                 icph_writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx);
  334                 icph_writeb(0, &dp6_ptr->io.event);
  335                 retries = INIT_RETRIES;
  336                 icph_delay(20);
  337                 while (icph_readb(&dp6_ptr->u.ic.S_Status) != 0xff) {
  338                   if (--retries == 0) {
  339                     printk("initialization error (DEINIT failed)\n");
  340                     icph_munmap(ha->brd);
  341                     return 0;
  342                   }
  343                   icph_delay(1);
  344                 }
  345                 prot_ver = (unchar)icph_readl(&dp6_ptr->u.ic.S_Info[0]);
  346                 icph_writeb(0, &dp6_ptr->u.ic.S_Status);
  347                 icph_writeb(0xff, &dp6_ptr->io.irqdel);
  348                 if (prot_ver != PROTOCOL_VERSION) {
  349                   printk("illegal protocol version\n");
  350                   icph_munmap(ha->brd);
  351                   return 0;
  352                 }
  353 
  354                 ha->type = ICP_PCI;
  355                 ha->ic_all_size = sizeof(dp6_ptr->u);
  356 
  357                 /* special command to controller BIOS */
  358                 icph_writel(0x00, &dp6_ptr->u.ic.S_Info[0]);
  359                 icph_writel(0x00, &dp6_ptr->u.ic.S_Info[1]);
  360                 icph_writel(0x01, &dp6_ptr->u.ic.S_Info[2]);
  361                 icph_writel(0x00, &dp6_ptr->u.ic.S_Info[3]);
  362                 icph_writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx);
  363                 icph_writeb(0, &dp6_ptr->io.event);
  364                 retries = INIT_RETRIES;
  365                 icph_delay(20);
  366                 while (icph_readb(&dp6_ptr->u.ic.S_Status) != 0xfe) {
  367                   if (--retries == 0) {
  368                     printk("initialization error\n");
  369                     icph_munmap(ha->brd);
  370                     return 0;
  371                   }
  372                   icph_delay(1);
  373                 }
  374                 icph_writeb(0, &dp6_ptr->u.ic.S_Status);
  375                 icph_writeb(0xff, &dp6_ptr->io.irqdel);
  376 #endif
  377 
  378                 icp->icp_ic_all_size = ICP_DPRAM_SZ;
  379 
  380                 icp->icp_copy_cmd = icp_pci_copy_cmd;
  381                 icp->icp_get_status = icp_pci_get_status;
  382                 icp->icp_intr = icp_pci_intr;
  383                 icp->icp_release_event = icp_pci_release_event;
  384                 icp->icp_set_sema0 = icp_pci_set_sema0;
  385                 icp->icp_test_busy = icp_pci_test_busy;
  386 
  387                 break;
  388 
  389         case ICP_PCINEW:
  390                 bus_space_set_region_4(dpmemt, dpmemh, 0, 0,
  391                     ICP_DPR_IF_SZ >> 2);
  392                 if (bus_space_read_1(dpmemt, dpmemh, 0) != 0) {
  393                         aprint_error("cannot write to DPMEM\n");
  394                         goto bail_out;
  395                 }
  396 
  397 #if 0
  398                 /* disable board interrupts, deinit services */
  399                 outb(0x00,PTR2USHORT(&ha->plx->control1));
  400                 outb(0xff,PTR2USHORT(&ha->plx->edoor_reg));
  401 
  402                 icph_writeb(0x00, &dp6c_ptr->u.ic.S_Status);
  403                 icph_writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index);
  404 
  405                 icph_writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]);
  406                 icph_writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx);
  407 
  408                 outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
  409 
  410                 retries = INIT_RETRIES;
  411                 icph_delay(20);
  412                 while (icph_readb(&dp6c_ptr->u.ic.S_Status) != 0xff) {
  413                   if (--retries == 0) {
  414                     printk("initialization error (DEINIT failed)\n");
  415                     icph_munmap(ha->brd);
  416                     return 0;
  417                   }
  418                   icph_delay(1);
  419                 }
  420                 prot_ver = (unchar)icph_readl(&dp6c_ptr->u.ic.S_Info[0]);
  421                 icph_writeb(0, &dp6c_ptr->u.ic.Status);
  422                 if (prot_ver != PROTOCOL_VERSION) {
  423                   printk("illegal protocol version\n");
  424                   icph_munmap(ha->brd);
  425                   return 0;
  426                 }
  427 
  428                 ha->type = ICP_PCINEW;
  429                 ha->ic_all_size = sizeof(dp6c_ptr->u);
  430 
  431                 /* special command to controller BIOS */
  432                 icph_writel(0x00, &dp6c_ptr->u.ic.S_Info[0]);
  433                 icph_writel(0x00, &dp6c_ptr->u.ic.S_Info[1]);
  434                 icph_writel(0x01, &dp6c_ptr->u.ic.S_Info[2]);
  435                 icph_writel(0x00, &dp6c_ptr->u.ic.S_Info[3]);
  436                 icph_writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx);
  437 
  438                 outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
  439 
  440                 retries = INIT_RETRIES;
  441                 icph_delay(20);
  442                 while (icph_readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) {
  443                   if (--retries == 0) {
  444                     printk("initialization error\n");
  445                     icph_munmap(ha->brd);
  446                     return 0;
  447                   }
  448                   icph_delay(1);
  449                 }
  450                 icph_writeb(0, &dp6c_ptr->u.ic.S_Status);
  451 #endif
  452 
  453                 icp->icp_ic_all_size = ICP_PCINEW_SZ;
  454 
  455                 icp->icp_copy_cmd = icp_pcinew_copy_cmd;
  456                 icp->icp_get_status = icp_pcinew_get_status;
  457                 icp->icp_intr = icp_pcinew_intr;
  458                 icp->icp_release_event = icp_pcinew_release_event;
  459                 icp->icp_set_sema0 = icp_pcinew_set_sema0;
  460                 icp->icp_test_busy = icp_pcinew_test_busy;
  461 
  462                 break;
  463 
  464         case ICP_MPR:
  465                 bus_space_write_4(dpmemt, dpmemh, ICP_MPR_IC, ICP_MPR_MAGIC);
  466                 if (bus_space_read_4(dpmemt, dpmemh, ICP_MPR_IC) !=
  467                     ICP_MPR_MAGIC) {
  468                         aprint_error(
  469                             "cannot access DPMEM at 0x%lx (shadowed?)\n",
  470                             (u_long)dpmembase);
  471                         goto bail_out;
  472                 }
  473 
  474                 /*
  475                  * XXX Here the Linux driver has a weird remapping logic I
  476                  * don't understand.  My controller does not need it, and I
  477                  * cannot see what purpose it serves, therefore I did not
  478                  * do anything similar.
  479                  */
  480 
  481                 bus_space_set_region_4(dpmemt, dpmemh, ICP_I960_SZ, 0,
  482                     ICP_DPR_IF_SZ >> 2);
  483 
  484                 /* Disable everything. */
  485                 bus_space_write_1(dpmemt, dpmemh, ICP_EDOOR_EN,
  486                     bus_space_read_1(dpmemt, dpmemh, ICP_EDOOR_EN) | 4);
  487                 bus_space_write_1(dpmemt, dpmemh, ICP_MPR_EDOOR, 0xff);
  488                 bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_STATUS,
  489                     0);
  490                 bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_CMD_INDEX,
  491                     0);
  492 
  493                 bus_space_write_4(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_INFO,
  494                     htole32(dpmembase));
  495                 bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_CMD_INDX,
  496                     0xff);
  497                 bus_space_write_1(dpmemt, dpmemh, ICP_MPR_LDOOR, 1);
  498 
  499                 DELAY(20);
  500                 retries = 1000000;
  501                 while (bus_space_read_1(dpmemt, dpmemh,
  502                     ICP_MPR_IC + ICP_S_STATUS) != 0xff) {
  503                         if (--retries == 0) {
  504                                 aprint_error("DEINIT failed\n");
  505                                 goto bail_out;
  506                         }
  507                         DELAY(1);
  508                 }
  509 
  510                 protocol = (u_int8_t)bus_space_read_4(dpmemt, dpmemh,
  511                     ICP_MPR_IC + ICP_S_INFO);
  512                 bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_STATUS,
  513                     0);
  514                 if (protocol != ICP_PROTOCOL_VERSION) {
  515                         aprint_error("unsupported protocol %d\n", protocol);
  516                         goto bail_out;
  517                 }
  518 
  519                 /* special commnd to controller BIOS */
  520                 bus_space_write_4(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_INFO, 0);
  521                 bus_space_write_4(dpmemt, dpmemh,
  522                     ICP_MPR_IC + ICP_S_INFO + sizeof(u_int32_t), 0);
  523                 bus_space_write_4(dpmemt, dpmemh,
  524                     ICP_MPR_IC + ICP_S_INFO + 2 * sizeof(u_int32_t), 1);
  525                 bus_space_write_4(dpmemt, dpmemh,
  526                     ICP_MPR_IC + ICP_S_INFO + 3 * sizeof(u_int32_t), 0);
  527                 bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_CMD_INDX,
  528                     0xfe);
  529                 bus_space_write_1(dpmemt, dpmemh, ICP_MPR_LDOOR, 1);
  530 
  531                 DELAY(20);
  532                 retries = 1000000;
  533                 while (bus_space_read_1(dpmemt, dpmemh,
  534                     ICP_MPR_IC + ICP_S_STATUS) != 0xfe) {
  535                         if (--retries == 0) {
  536                                 aprint_error("initialization error\n");
  537                                 goto bail_out;
  538                         }
  539                         DELAY(1);
  540                 }
  541 
  542                 bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_STATUS,
  543                     0);
  544 
  545                 icp->icp_copy_cmd = icp_mpr_copy_cmd;
  546                 icp->icp_get_status = icp_mpr_get_status;
  547                 icp->icp_intr = icp_mpr_intr;
  548                 icp->icp_release_event = icp_mpr_release_event;
  549                 icp->icp_set_sema0 = icp_mpr_set_sema0;
  550                 icp->icp_test_busy = icp_mpr_test_busy;
  551                 break;
  552         }
  553 
  554         if (pci_intr_map(pa, &ih)) {
  555                 aprint_error("couldn't map interrupt\n");
  556                 goto bail_out;
  557         }
  558         intrstr = pci_intr_string(pa->pa_pc, ih);
  559         icp->icp_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, icp_intr, icp);
  560         if (icp->icp_ih == NULL) {
  561                 aprint_error("couldn't establish interrupt");
  562                 if (intrstr != NULL)
  563                         aprint_normal(" at %s", intrstr);
  564                 aprint_normal("\n");
  565                 goto bail_out;
  566         }
  567         status |= INTR_ESTABLISHED;
  568 
  569         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL)
  570                 aprint_normal("Intel Storage RAID controller\n");
  571         else
  572                 aprint_normal("ICP-Vortex RAID controller\n");
  573 
  574         icp->icp_pci_bus = pa->pa_bus;
  575         icp->icp_pci_device = pa->pa_device;
  576         icp->icp_pci_device_id = PCI_PRODUCT(pa->pa_id);
  577         icp->icp_pci_subdevice_id = pci_conf_read(pa->pa_pc, pa->pa_tag,
  578             PCI_SUBSYS_ID_REG);
  579 
  580         if (icp_init(icp, intrstr))
  581                 goto bail_out;
  582 
  583         icp_pci_enable_intr(icp);
  584         return;
  585 
  586  bail_out:
  587         if ((status & DPMEM_MAPPED) != 0)
  588                 bus_space_unmap(dpmemt, dpmemh, dpmemsize);
  589         if ((status & IOMEM_MAPPED) != 0)
  590                 bus_space_unmap(iomemt, iomemh, iomembase);
  591         if ((status & IO_MAPPED) != 0)
  592                 bus_space_unmap(iot, ioh, iosize);
  593         if ((status & INTR_ESTABLISHED) != 0)
  594                 pci_intr_disestablish(pa->pa_pc, icp->icp_ih);
  595 }
  596 
  597 /*
  598  * Enable interrupts.
  599  */
  600 void
  601 icp_pci_enable_intr(struct icp_softc *icp) 
  602 {
  603 
  604         switch (ICP_CLASS(icp)) {
  605         case ICP_PCI:
  606                 bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh, ICP_IRQDEL,
  607                     1);
  608                 bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh,
  609                     ICP_CMD_INDEX, 0);
  610                 bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh, ICP_IRQEN,
  611                     1);
  612                 break;
  613 
  614         case ICP_PCINEW:
  615                 bus_space_write_1(icp->icp_iot, icp->icp_ioh, ICP_EDOOR_REG,
  616                     0xff);
  617                 bus_space_write_1(icp->icp_iot, icp->icp_ioh, ICP_CONTROL1, 3);
  618                 break;
  619 
  620         case ICP_MPR:
  621                 bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh,
  622                     ICP_MPR_EDOOR, 0xff);
  623                 bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh, ICP_EDOOR_EN,
  624                     bus_space_read_1(icp->icp_dpmemt, icp->icp_dpmemh,
  625                     ICP_EDOOR_EN) & ~4);
  626                 break;
  627         }
  628 }
  629 
  630 /*
  631  * "Old" PCI controller-specific functions.
  632  */
  633 
  634 void
  635 icp_pci_copy_cmd(struct icp_softc *icp, struct icp_ccb *ccb)
  636 {
  637 
  638         /* XXX Not yet implemented */
  639 }
  640 
  641 u_int8_t
  642 icp_pci_get_status(struct icp_softc *icp)
  643 {
  644 
  645         /* XXX Not yet implemented */
  646         return (0);
  647 }
  648 
  649 void
  650 icp_pci_intr(struct icp_softc *icp, struct icp_intr_ctx *ctx)
  651 {
  652 
  653         /* XXX Not yet implemented */
  654 }
  655 
  656 void
  657 icp_pci_release_event(struct icp_softc *icp, struct icp_ccb *ccb)
  658 {
  659 
  660         /* XXX Not yet implemented */
  661 }
  662 
  663 void
  664 icp_pci_set_sema0(struct icp_softc *icp)
  665 {
  666 
  667         bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh, ICP_SEMA0, 1);
  668 }
  669 
  670 int
  671 icp_pci_test_busy(struct icp_softc *icp)
  672 {
  673 
  674         /* XXX Not yet implemented */
  675         return (0);
  676 }
  677 
  678 /*
  679  * "New" PCI controller-specific functions.
  680  */
  681 
  682 void
  683 icp_pcinew_copy_cmd(struct icp_softc *icp, struct icp_ccb *ccb)
  684 {
  685 
  686         /* XXX Not yet implemented */
  687 }
  688 
  689 u_int8_t
  690 icp_pcinew_get_status(struct icp_softc *icp)
  691 {
  692 
  693         /* XXX Not yet implemented */
  694         return (0);
  695 }
  696 
  697 void
  698 icp_pcinew_intr(struct icp_softc *icp, struct icp_intr_ctx *ctx)
  699 {
  700 
  701         /* XXX Not yet implemented */
  702 }
  703 
  704 void
  705 icp_pcinew_release_event(struct icp_softc *icp, struct icp_ccb *ccb)
  706 {
  707 
  708         /* XXX Not yet implemented */
  709 }
  710 
  711 void
  712 icp_pcinew_set_sema0(struct icp_softc *icp)
  713 {
  714 
  715         bus_space_write_1(icp->icp_iot, icp->icp_ioh, ICP_SEMA0_REG, 1);
  716 }
  717 
  718 int
  719 icp_pcinew_test_busy(struct icp_softc *icp)
  720 {
  721 
  722         /* XXX Not yet implemented */
  723         return (0);
  724 }
  725 
  726 /*
  727  * MPR PCI controller-specific functions
  728  */
  729 
  730 void
  731 icp_mpr_copy_cmd(struct icp_softc *icp, struct icp_ccb *ic)
  732 {
  733 
  734         bus_space_write_2(icp->icp_dpmemt, icp->icp_dpmemh,
  735             ICP_MPR_IC + ICP_COMM_QUEUE + 0 * ICP_COMM_Q_SZ + ICP_OFFSET,
  736             ICP_DPR_CMD);
  737         bus_space_write_2(icp->icp_dpmemt, icp->icp_dpmemh,
  738             ICP_MPR_IC + ICP_COMM_QUEUE + 0 * ICP_COMM_Q_SZ + ICP_SERV_ID,
  739             ic->ic_service);
  740         bus_space_write_region_4(icp->icp_dpmemt, icp->icp_dpmemh,
  741             ICP_MPR_IC + ICP_DPR_CMD, (u_int32_t *)&ic->ic_cmd,
  742             ic->ic_cmdlen >> 2);
  743 }
  744 
  745 u_int8_t
  746 icp_mpr_get_status(struct icp_softc *icp)
  747 {
  748 
  749         return (bus_space_read_1(icp->icp_dpmemt, icp->icp_dpmemh,
  750             ICP_MPR_EDOOR));
  751 }
  752 
  753 void
  754 icp_mpr_intr(struct icp_softc *icp, struct icp_intr_ctx *ctx)
  755 {
  756 
  757         if ((ctx->istatus & 0x80) != 0) {       /* error flag */
  758                 ctx->istatus &= ~0x80;
  759                 ctx->cmd_status = bus_space_read_2(icp->icp_dpmemt,
  760                     icp->icp_dpmemh, ICP_MPR_STATUS);
  761         } else
  762                 ctx->cmd_status = ICP_S_OK;
  763         
  764         ctx->service = bus_space_read_2(icp->icp_dpmemt, icp->icp_dpmemh,
  765             ICP_MPR_SERVICE);
  766         ctx->info = bus_space_read_4(icp->icp_dpmemt, icp->icp_dpmemh,
  767             ICP_MPR_INFO);
  768         ctx->info2 = bus_space_read_4(icp->icp_dpmemt, icp->icp_dpmemh,
  769             ICP_MPR_INFO + sizeof(u_int32_t));
  770 
  771         if (ctx->istatus == ICP_ASYNCINDEX) {
  772                 if (ctx->service != ICP_SCREENSERVICE &&
  773                     (icp->icp_fw_vers & 0xff) >= 0x1a) {
  774                         int i;
  775 
  776                         icp->icp_evt.severity =
  777                             bus_space_read_1(icp->icp_dpmemt,
  778                                 icp->icp_dpmemh, ICP_SEVERITY);
  779                         for (i = 0;
  780                              i < sizeof(icp->icp_evt.event_string); i++) {
  781                                 icp->icp_evt.event_string[i] =
  782                                     bus_space_read_1(icp->icp_dpmemt,
  783                                     icp->icp_dpmemh, ICP_EVT_BUF + i);
  784                                 if (icp->icp_evt.event_string[i] == '\0')
  785                                         break;
  786                         }
  787                 }
  788         }
  789 
  790         bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh, ICP_MPR_EDOOR,
  791             0xff);
  792         bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh, ICP_MPR_SEMA1, 0);
  793 }
  794 
  795 void
  796 icp_mpr_release_event(struct icp_softc *icp, struct icp_ccb *ic)
  797 {
  798 
  799         bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh, ICP_MPR_LDOOR, 1);
  800 }
  801 
  802 void
  803 icp_mpr_set_sema0(struct icp_softc *icp)
  804 {
  805 
  806         bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh, ICP_MPR_SEMA0, 1);
  807 }
  808 
  809 int
  810 icp_mpr_test_busy(struct icp_softc *icp)
  811 {
  812 
  813         return (bus_space_read_1(icp->icp_dpmemt, icp->icp_dpmemh,
  814             ICP_MPR_SEMA0) & 1);
  815 }

Cache object: 999d8fe9ba97030437324a61a81b21e8


[ 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.