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/mlx_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: mlx_pci.c,v 1.11 2002/10/02 16:51:43 thorpej Exp $     */
    2 
    3 /*-
    4  * Copyright (c) 2001 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 Michael Smith
   41  * All rights reserved.
   42  *
   43  * Redistribution and use in source and binary forms, with or without
   44  * modification, are permitted provided that the following conditions
   45  * are met:
   46  * 1. Redistributions of source code must retain the above copyright
   47  *    notice, this list of conditions and the following disclaimer.
   48  * 2. Redistributions in binary form must reproduce the above copyright
   49  *    notice, this list of conditions and the following disclaimer in the
   50  *    documentation and/or other materials provided with the distribution.
   51  *
   52  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   53  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   54  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   55  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   56  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   57  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   58  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   59  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   60  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   61  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   62  * SUCH DAMAGE.
   63  *
   64  * from FreeBSD: mlx_pci.c,v 1.4.2.4 2000/10/28 10:48:09 msmith Exp
   65  */
   66 
   67 /*
   68  * PCI front-end for the mlx(4) driver.
   69  */
   70 
   71 #include <sys/cdefs.h>
   72 __KERNEL_RCSID(0, "$NetBSD: mlx_pci.c,v 1.11 2002/10/02 16:51:43 thorpej Exp $");
   73 
   74 #include <sys/param.h>
   75 #include <sys/systm.h>
   76 #include <sys/kernel.h>
   77 #include <sys/device.h>
   78 #include <sys/queue.h>
   79 #include <sys/callout.h>
   80 
   81 #include <machine/endian.h>
   82 #include <machine/bus.h>
   83 
   84 #include <dev/ic/mlxreg.h>
   85 #include <dev/ic/mlxio.h>
   86 #include <dev/ic/mlxvar.h>
   87 
   88 #include <dev/pci/pcireg.h>
   89 #include <dev/pci/pcivar.h>
   90 #include <dev/pci/pcidevs.h>
   91 
   92 static void     mlx_pci_attach(struct device *, struct device *, void *);
   93 static int      mlx_pci_match(struct device *, struct cfdata *, void *);
   94 static const struct mlx_pci_ident *mlx_pci_findmpi(struct pci_attach_args *);
   95 
   96 static int      mlx_v3_submit(struct mlx_softc *, struct mlx_ccb *);
   97 static int      mlx_v3_findcomplete(struct mlx_softc *, u_int *, u_int *);
   98 static void     mlx_v3_intaction(struct mlx_softc *, int);
   99 static int      mlx_v3_fw_handshake(struct mlx_softc *, int *, int *, int *);
  100 #ifdef  MLX_RESET
  101 static int      mlx_v3_reset(struct mlx_softc *);
  102 #endif
  103 
  104 static int      mlx_v4_submit(struct mlx_softc *, struct mlx_ccb *);
  105 static int      mlx_v4_findcomplete(struct mlx_softc *, u_int *, u_int *);
  106 static void     mlx_v4_intaction(struct mlx_softc *, int);
  107 static int      mlx_v4_fw_handshake(struct mlx_softc *, int *, int *, int *);
  108 
  109 static int      mlx_v5_submit(struct mlx_softc *, struct mlx_ccb *);
  110 static int      mlx_v5_findcomplete(struct mlx_softc *, u_int *, u_int *);
  111 static void     mlx_v5_intaction(struct mlx_softc *, int);
  112 static int      mlx_v5_fw_handshake(struct mlx_softc *, int *, int *, int *);
  113 
  114 struct mlx_pci_ident {
  115         u_short mpi_vendor;
  116         u_short mpi_product;
  117         u_short mpi_subvendor;
  118         u_short mpi_subproduct;
  119         int     mpi_iftype;
  120 } static const mlx_pci_ident[] = {
  121         {
  122                 PCI_VENDOR_MYLEX,
  123                 PCI_PRODUCT_MYLEX_RAID_V2,
  124                 0x0000,
  125                 0x0000,
  126                 2,
  127         },
  128         {
  129                 PCI_VENDOR_MYLEX,
  130                 PCI_PRODUCT_MYLEX_RAID_V3,
  131                 0x0000,
  132                 0x0000,
  133                 3,
  134         },
  135         {
  136                 PCI_VENDOR_MYLEX,
  137                 PCI_PRODUCT_MYLEX_RAID_V4,
  138                 0x0000,
  139                 0x0000,
  140                 4,
  141         },
  142         {
  143                 PCI_VENDOR_DEC,
  144                 PCI_PRODUCT_DEC_SWXCR,
  145                 PCI_VENDOR_MYLEX,
  146                 PCI_PRODUCT_MYLEX_RAID_V5,
  147                 5,
  148         },
  149 };
  150 
  151 CFATTACH_DECL(mlx_pci, sizeof(struct mlx_softc),
  152     mlx_pci_match, mlx_pci_attach, NULL, NULL);
  153 
  154 /*
  155  * Try to find a `mlx_pci_ident' entry corresponding to this board.
  156  */
  157 static const struct mlx_pci_ident *
  158 mlx_pci_findmpi(struct pci_attach_args *pa)
  159 {
  160         const struct mlx_pci_ident *mpi, *maxmpi;
  161         pcireg_t reg;
  162 
  163         mpi = mlx_pci_ident;
  164         maxmpi = mpi + sizeof(mlx_pci_ident) / sizeof(mlx_pci_ident[0]);
  165 
  166         for (; mpi < maxmpi; mpi++) {
  167                 if (PCI_VENDOR(pa->pa_id) != mpi->mpi_vendor ||
  168                     PCI_PRODUCT(pa->pa_id) != mpi->mpi_product)
  169                         continue;
  170 
  171                 if (mpi->mpi_subvendor == 0x0000)
  172                         return (mpi);
  173 
  174                 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
  175 
  176                 if (PCI_VENDOR(reg) == mpi->mpi_subvendor &&
  177                     PCI_PRODUCT(reg) == mpi->mpi_subproduct)
  178                         return (mpi);
  179         }
  180 
  181         return (NULL);
  182 }
  183 
  184 /*
  185  * Match a supported board.
  186  */
  187 static int
  188 mlx_pci_match(struct device *parent, struct cfdata *cfdata, void *aux)
  189 {
  190 
  191         return (mlx_pci_findmpi(aux) != NULL);
  192 }
  193 
  194 /*
  195  * Attach a supported board.
  196  */
  197 static void
  198 mlx_pci_attach(struct device *parent, struct device *self, void *aux)
  199 {
  200         struct pci_attach_args *pa;
  201         struct mlx_softc *mlx;
  202         pci_chipset_tag_t pc;
  203         pci_intr_handle_t ih;
  204         bus_space_handle_t memh, ioh;
  205         bus_space_tag_t memt, iot;
  206         pcireg_t reg;
  207         const char *intrstr;
  208         int ior, memr, i;
  209         const struct mlx_pci_ident *mpi;
  210 
  211         mlx = (struct mlx_softc *)self;
  212         pa = aux;
  213         pc = pa->pa_pc;
  214         mpi = mlx_pci_findmpi(aux);
  215 
  216         mlx->mlx_dmat = pa->pa_dmat;
  217         mlx->mlx_ci.ci_iftype = mpi->mpi_iftype;
  218 
  219         printf(": Mylex RAID (v%d interface)\n", mpi->mpi_iftype);
  220 
  221         /*
  222          * Map the PCI register window.
  223          */
  224         memr = -1;
  225         ior = -1;
  226 
  227         for (i = 0x10; i <= 0x14; i += 4) {
  228                 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, i);
  229 
  230                 if (PCI_MAPREG_TYPE(reg) == PCI_MAPREG_TYPE_IO) {
  231                         if (ior == -1 && PCI_MAPREG_IO_SIZE(reg) != 0)
  232                                 ior = i;
  233                 } else {
  234                         if (memr == -1 && PCI_MAPREG_MEM_SIZE(reg) != 0)
  235                                 memr = i;
  236                 }
  237         }
  238 
  239         if (memr != -1)
  240                 if (pci_mapreg_map(pa, memr, PCI_MAPREG_TYPE_MEM, 0,
  241                     &memt, &memh, NULL, NULL))
  242                         memr = -1;
  243         if (ior != -1)
  244                 if (pci_mapreg_map(pa, ior, PCI_MAPREG_TYPE_IO, 0,
  245                     &iot, &ioh, NULL, NULL))
  246                         ior = -1;
  247 
  248         if (memr != -1) {
  249                 mlx->mlx_iot = memt;
  250                 mlx->mlx_ioh = memh;
  251         } else if (ior != -1) {
  252                 mlx->mlx_iot = iot;
  253                 mlx->mlx_ioh = ioh;
  254         } else {
  255                 printf("%s: can't map i/o or memory space\n", self->dv_xname);
  256                 return;
  257         }
  258 
  259         /* Enable the device. */
  260         reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
  261         pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
  262             reg | PCI_COMMAND_MASTER_ENABLE);
  263 
  264         /* Map and establish the interrupt. */
  265         if (pci_intr_map(pa, &ih)) {
  266                 printf("%s: can't map interrupt\n", self->dv_xname);
  267                 return;
  268         }
  269         intrstr = pci_intr_string(pc, ih);
  270         mlx->mlx_ih = pci_intr_establish(pc, ih, IPL_BIO, mlx_intr, mlx);
  271         if (mlx->mlx_ih == NULL) {
  272                 printf("%s: can't establish interrupt", self->dv_xname);
  273                 if (intrstr != NULL)
  274                         printf(" at %s", intrstr);
  275                 printf("\n");
  276                 return;
  277         }
  278 
  279         /* Select linkage based on controller interface type. */
  280         switch (mlx->mlx_ci.ci_iftype) {
  281         case 2:
  282         case 3:
  283                 mlx->mlx_submit = mlx_v3_submit;
  284                 mlx->mlx_findcomplete = mlx_v3_findcomplete;
  285                 mlx->mlx_intaction = mlx_v3_intaction;
  286                 mlx->mlx_fw_handshake = mlx_v3_fw_handshake;
  287 #ifdef MLX_RESET
  288                 mlx->mlx_reset = mlx_v3_reset;
  289 #endif
  290                 break;
  291 
  292         case 4:
  293                 mlx->mlx_submit = mlx_v4_submit;
  294                 mlx->mlx_findcomplete = mlx_v4_findcomplete;
  295                 mlx->mlx_intaction = mlx_v4_intaction;
  296                 mlx->mlx_fw_handshake = mlx_v4_fw_handshake;
  297                 break;
  298 
  299         case 5:
  300                 mlx->mlx_submit = mlx_v5_submit;
  301                 mlx->mlx_findcomplete = mlx_v5_findcomplete;
  302                 mlx->mlx_intaction = mlx_v5_intaction;
  303                 mlx->mlx_fw_handshake = mlx_v5_fw_handshake;
  304                 break;
  305         }
  306 
  307         mlx_init(mlx, intrstr);
  308 }
  309 
  310 /*
  311  * ================= V3 interface linkage =================
  312  */
  313 
  314 /*
  315  * Try to give (mc) to the controller.  Returns 1 if successful, 0 on
  316  * failure (the controller is not ready to take a command).
  317  *
  318  * Must be called at splbio or in a fashion that prevents reentry.
  319  */
  320 static int
  321 mlx_v3_submit(struct mlx_softc *mlx, struct mlx_ccb *mc)
  322 {
  323 
  324         /* Ready for our command? */
  325         if ((mlx_inb(mlx, MLX_V3REG_IDB) & MLX_V3_IDB_FULL) == 0) {
  326                 /* Copy mailbox data to window. */
  327                 bus_space_write_region_1(mlx->mlx_iot, mlx->mlx_ioh,
  328                     MLX_V3REG_MAILBOX, mc->mc_mbox, 13);
  329                 bus_space_barrier(mlx->mlx_iot, mlx->mlx_ioh,
  330                     MLX_V3REG_MAILBOX, 13,
  331                     BUS_SPACE_BARRIER_WRITE);
  332 
  333                 /* Post command. */
  334                 mlx_outb(mlx, MLX_V3REG_IDB, MLX_V3_IDB_FULL);
  335                 return (1);
  336         }
  337 
  338         return (0);
  339 }
  340 
  341 /*
  342  * See if a command has been completed, if so acknowledge its completion and
  343  * recover the slot number and status code.
  344  *
  345  * Must be called at splbio or in a fashion that prevents reentry.
  346  */
  347 static int
  348 mlx_v3_findcomplete(struct mlx_softc *mlx, u_int *slot, u_int *status)
  349 {
  350 
  351         /* Status available? */
  352         if ((mlx_inb(mlx, MLX_V3REG_ODB) & MLX_V3_ODB_SAVAIL) != 0) {
  353                 *slot = mlx_inb(mlx, MLX_V3REG_STATUS_IDENT);
  354                 *status = mlx_inw(mlx, MLX_V3REG_STATUS);
  355 
  356                 /* Acknowledge completion. */
  357                 mlx_outb(mlx, MLX_V3REG_ODB, MLX_V3_ODB_SAVAIL);
  358                 mlx_outb(mlx, MLX_V3REG_IDB, MLX_V3_IDB_SACK);
  359                 return (1);
  360         }
  361 
  362         return (0);
  363 }
  364 
  365 /*
  366  * Enable/disable interrupts as requested. (No acknowledge required)
  367  *
  368  * Must be called at splbio or in a fashion that prevents reentry.
  369  */
  370 static void
  371 mlx_v3_intaction(struct mlx_softc *mlx, int action)
  372 {
  373 
  374         mlx_outb(mlx, MLX_V3REG_IE, action != 0);
  375 }
  376 
  377 /*
  378  * Poll for firmware error codes during controller initialisation.
  379  *
  380  * Returns 0 if initialisation is complete, 1 if still in progress but no
  381  * error has been fetched, 2 if an error has been retrieved.
  382  */
  383 static int 
  384 mlx_v3_fw_handshake(struct mlx_softc *mlx, int *error, int *param1, int *param2)
  385 {
  386         u_int8_t fwerror;
  387 
  388         /* First time around, clear any hardware completion status. */
  389         if ((mlx->mlx_flags & MLXF_FW_INITTED) == 0) {
  390                 mlx_outb(mlx, MLX_V3REG_IDB, MLX_V3_IDB_SACK);
  391                 DELAY(1000);
  392                 mlx->mlx_flags |= MLXF_FW_INITTED;
  393         }
  394 
  395         /* Init in progress? */
  396         if ((mlx_inb(mlx, MLX_V3REG_IDB) & MLX_V3_IDB_INIT_BUSY) == 0)
  397                 return (0);
  398 
  399         /* Test error value. */
  400         fwerror = mlx_inb(mlx, MLX_V3REG_FWERROR);
  401 
  402         if ((fwerror & MLX_V3_FWERROR_PEND) == 0)
  403                 return (1);
  404 
  405         /* Mask status pending bit, fetch status. */
  406         *error = fwerror & ~MLX_V3_FWERROR_PEND;
  407         *param1 = mlx_inb(mlx, MLX_V3REG_FWERROR_PARAM1);
  408         *param2 = mlx_inb(mlx, MLX_V3REG_FWERROR_PARAM2);
  409 
  410         /* Acknowledge. */
  411         mlx_outb(mlx, MLX_V3REG_FWERROR, 0);
  412 
  413         return (2);
  414 }
  415 
  416 #ifdef MLX_RESET
  417 /*
  418  * Reset the controller.  Return non-zero on failure.
  419  */
  420 static int 
  421 mlx_v3_reset(struct mlx_softc *mlx)
  422 {
  423         int i;
  424 
  425         mlx_outb(mlx, MLX_V3REG_IDB, MLX_V3_IDB_SACK);
  426         delay(1000000);
  427 
  428         /* Wait up to 2 minutes for the bit to clear. */
  429         for (i = 120; i != 0; i--) {
  430                 delay(1000000);
  431                 if ((mlx_inb(mlx, MLX_V3REG_IDB) & MLX_V3_IDB_SACK) == 0)
  432                         break;
  433         }
  434         if (i == 0) {
  435                 /* ZZZ */
  436                 printf("mlx0: SACK didn't clear\n");
  437                 return (-1);
  438         }
  439 
  440         mlx_outb(mlx, MLX_V3REG_IDB, MLX_V3_IDB_RESET);
  441 
  442         /* Wait up to 5 seconds for the bit to clear. */
  443         for (i = 5; i != 0; i--) {
  444                 delay(1000000);
  445                 if ((mlx_inb(mlx, MLX_V3REG_IDB) & MLX_V3_IDB_RESET) == 0)
  446                         break;
  447         }
  448         if (i == 0) {
  449                 /* ZZZ */
  450                 printf("mlx0: RESET didn't clear\n");
  451                 return (-1);
  452         }
  453 
  454         return (0);
  455 }
  456 #endif  /* MLX_RESET */
  457 
  458 /*
  459  * ================= V4 interface linkage =================
  460  */
  461 
  462 /*
  463  * Try to give (mc) to the controller.  Returns 1 if successful, 0 on
  464  * failure (the controller is not ready to take a command).
  465  *
  466  * Must be called at splbio or in a fashion that prevents reentry.
  467  */
  468 static int
  469 mlx_v4_submit(struct mlx_softc *mlx, struct mlx_ccb *mc)
  470 {
  471 
  472         /* Ready for our command? */
  473         if ((mlx_inl(mlx, MLX_V4REG_IDB) & MLX_V4_IDB_FULL) == 0) {
  474                 /* Copy mailbox data to window. */
  475                 bus_space_write_region_1(mlx->mlx_iot, mlx->mlx_ioh,
  476                     MLX_V4REG_MAILBOX, mc->mc_mbox, 13);
  477                 bus_space_barrier(mlx->mlx_iot, mlx->mlx_ioh,
  478                     MLX_V4REG_MAILBOX, 13,
  479                     BUS_SPACE_BARRIER_WRITE);
  480 
  481                 /* Post command. */
  482                 mlx_outl(mlx, MLX_V4REG_IDB, MLX_V4_IDB_HWMBOX_CMD);
  483                 return (1);
  484         }
  485 
  486         return (0);
  487 }
  488 
  489 /*
  490  * See if a command has been completed, if so acknowledge its completion and
  491  * recover the slot number and status code.
  492  *
  493  * Must be called at splbio or in a fashion that prevents reentry.
  494  */
  495 static int
  496 mlx_v4_findcomplete(struct mlx_softc *mlx, u_int *slot, u_int *status)
  497 {
  498 
  499         /* Status available? */
  500         if ((mlx_inl(mlx, MLX_V4REG_ODB) & MLX_V4_ODB_HWSAVAIL) != 0) {
  501                 *slot = mlx_inb(mlx, MLX_V4REG_STATUS_IDENT);
  502                 *status = mlx_inw(mlx, MLX_V4REG_STATUS);
  503 
  504                 /* Acknowledge completion. */
  505                 mlx_outl(mlx, MLX_V4REG_ODB, MLX_V4_ODB_HWMBOX_ACK);
  506                 mlx_outl(mlx, MLX_V4REG_IDB, MLX_V4_IDB_SACK);
  507                 return (1);
  508         }
  509 
  510         return (0);
  511 }
  512 
  513 /*
  514  * Enable/disable interrupts as requested.
  515  *
  516  * Must be called at splbio or in a fashion that prevents reentry.
  517  */
  518 static void
  519 mlx_v4_intaction(struct mlx_softc *mlx, int action)
  520 {
  521         u_int32_t ier;
  522 
  523         if (!action)
  524                 ier = MLX_V4_IE_MASK | MLX_V4_IE_DISINT;
  525         else
  526                 ier = MLX_V4_IE_MASK & ~MLX_V4_IE_DISINT;
  527 
  528         mlx_outl(mlx, MLX_V4REG_IE, ier);
  529 }
  530 
  531 /*
  532  * Poll for firmware error codes during controller initialisation.
  533  *
  534  * Returns 0 if initialisation is complete, 1 if still in progress but no
  535  * error has been fetched, 2 if an error has been retrieved.
  536  */
  537 static int 
  538 mlx_v4_fw_handshake(struct mlx_softc *mlx, int *error, int *param1, int *param2)
  539 {
  540         u_int8_t fwerror;
  541 
  542         /* First time around, clear any hardware completion status. */
  543         if ((mlx->mlx_flags & MLXF_FW_INITTED) == 0) {
  544                 mlx_outl(mlx, MLX_V4REG_IDB, MLX_V4_IDB_SACK);
  545                 DELAY(1000);
  546                 mlx->mlx_flags |= MLXF_FW_INITTED;
  547         }
  548 
  549         /* Init in progress? */
  550         if ((mlx_inl(mlx, MLX_V4REG_IDB) & MLX_V4_IDB_INIT_BUSY) == 0)
  551                 return (0);
  552 
  553         /* Test error value */
  554         fwerror = mlx_inb(mlx, MLX_V4REG_FWERROR);
  555         if ((fwerror & MLX_V4_FWERROR_PEND) == 0)
  556                 return (1);
  557 
  558         /* Mask status pending bit, fetch status. */
  559         *error = fwerror & ~MLX_V4_FWERROR_PEND;
  560         *param1 = mlx_inb(mlx, MLX_V4REG_FWERROR_PARAM1);
  561         *param2 = mlx_inb(mlx, MLX_V4REG_FWERROR_PARAM2);
  562 
  563         /* Acknowledge. */
  564         mlx_outb(mlx, MLX_V4REG_FWERROR, 0);
  565 
  566         return (2);
  567 }
  568 
  569 /*
  570  * ================= V5 interface linkage =================
  571  */
  572 
  573 /*
  574  * Try to give (mc) to the controller.  Returns 1 if successful, 0 on failure
  575  * (the controller is not ready to take a command).
  576  *
  577  * Must be called at splbio or in a fashion that prevents reentry.
  578  */
  579 static int
  580 mlx_v5_submit(struct mlx_softc *mlx, struct mlx_ccb *mc)
  581 {
  582 
  583         /* Ready for our command? */
  584         if ((mlx_inb(mlx, MLX_V5REG_IDB) & MLX_V5_IDB_EMPTY) != 0) {
  585                 /* Copy mailbox data to window. */
  586                 bus_space_write_region_1(mlx->mlx_iot, mlx->mlx_ioh,
  587                     MLX_V5REG_MAILBOX, mc->mc_mbox, 13);
  588                 bus_space_barrier(mlx->mlx_iot, mlx->mlx_ioh,
  589                     MLX_V5REG_MAILBOX, 13,
  590                     BUS_SPACE_BARRIER_WRITE);
  591 
  592                 /* Post command */
  593                 mlx_outb(mlx, MLX_V5REG_IDB, MLX_V5_IDB_HWMBOX_CMD);
  594                 return (1);
  595         }
  596 
  597         return (0);
  598 }
  599 
  600 /*
  601  * See if a command has been completed, if so acknowledge its completion and
  602  * recover the slot number and status code.
  603  *
  604  * Must be called at splbio or in a fashion that prevents reentry.
  605  */
  606 static int
  607 mlx_v5_findcomplete(struct mlx_softc *mlx, u_int *slot, u_int *status)
  608 {
  609 
  610         /* Status available? */
  611         if ((mlx_inb(mlx, MLX_V5REG_ODB) & MLX_V5_ODB_HWSAVAIL) != 0) {
  612                 *slot = mlx_inb(mlx, MLX_V5REG_STATUS_IDENT);
  613                 *status = mlx_inw(mlx, MLX_V5REG_STATUS);
  614 
  615                 /* Acknowledge completion. */
  616                 mlx_outb(mlx, MLX_V5REG_ODB, MLX_V5_ODB_HWMBOX_ACK);
  617                 mlx_outb(mlx, MLX_V5REG_IDB, MLX_V5_IDB_SACK);
  618                 return (1);
  619         }
  620 
  621         return (0);
  622 }
  623 
  624 /*
  625  * Enable/disable interrupts as requested.
  626  *
  627  * Must be called at splbio or in a fashion that prevents reentry.
  628  */
  629 static void
  630 mlx_v5_intaction(struct mlx_softc *mlx, int action)
  631 {
  632         u_int8_t ier;
  633 
  634         if (!action)
  635                 ier = 0xff & MLX_V5_IE_DISINT;
  636         else
  637                 ier = 0xff & ~MLX_V5_IE_DISINT;
  638 
  639         mlx_outb(mlx, MLX_V5REG_IE, ier);
  640 }
  641 
  642 /*
  643  * Poll for firmware error codes during controller initialisation.
  644  *
  645  * Returns 0 if initialisation is complete, 1 if still in progress but no
  646  * error has been fetched, 2 if an error has been retrieved.
  647  */
  648 static int 
  649 mlx_v5_fw_handshake(struct mlx_softc *mlx, int *error, int *param1, int *param2)
  650 {
  651         u_int8_t fwerror;
  652 
  653         /* First time around, clear any hardware completion status. */
  654         if ((mlx->mlx_flags & MLXF_FW_INITTED) == 0) {
  655                 mlx_outb(mlx, MLX_V5REG_IDB, MLX_V5_IDB_SACK);
  656                 DELAY(1000);
  657                 mlx->mlx_flags |= MLXF_FW_INITTED;
  658         }
  659 
  660         /* Init in progress? */
  661         if ((mlx_inb(mlx, MLX_V5REG_IDB) & MLX_V5_IDB_INIT_DONE) != 0)
  662                 return (0);
  663 
  664         /* Test for error value. */
  665         fwerror = mlx_inb(mlx, MLX_V5REG_FWERROR);
  666         if ((fwerror & MLX_V5_FWERROR_PEND) == 0)
  667                 return (1);
  668 
  669         /* Mask status pending bit, fetch status. */
  670         *error = fwerror & ~MLX_V5_FWERROR_PEND;
  671         *param1 = mlx_inb(mlx, MLX_V5REG_FWERROR_PARAM1);
  672         *param2 = mlx_inb(mlx, MLX_V5REG_FWERROR_PARAM2);
  673 
  674         /* Acknowledge. */
  675         mlx_outb(mlx, MLX_V5REG_FWERROR, 0xff);
  676 
  677         return (2);
  678 }

Cache object: 5b2bc4bf5b2b41d4a8db35c2d4cf6ba3


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