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/mlx/mlx.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 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 1999 Michael Smith
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  *
   28  *      $FreeBSD$
   29  */
   30 
   31 /*
   32  * Driver for the Mylex DAC960 family of RAID controllers.
   33  */
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/bio.h>
   38 #include <sys/lock.h>
   39 #include <sys/malloc.h>
   40 #include <sys/mutex.h>
   41 #include <sys/kernel.h>
   42 #include <sys/sx.h>
   43 
   44 #include <sys/bus.h>
   45 #include <sys/conf.h>
   46 #include <sys/stat.h>
   47 
   48 #include <machine/resource.h>
   49 #include <machine/bus.h>
   50 #include <machine/clock.h>
   51 #include <sys/rman.h>
   52 
   53 #include <geom/geom_disk.h>
   54 
   55 #include <dev/mlx/mlxio.h>
   56 #include <dev/mlx/mlxvar.h>
   57 #include <dev/mlx/mlxreg.h>
   58 
   59 static struct cdevsw mlx_cdevsw = {
   60         .d_version =    D_VERSION,
   61         .d_open =       mlx_open,
   62         .d_close =      mlx_close,
   63         .d_ioctl =      mlx_ioctl,
   64         .d_name =       "mlx",
   65 };
   66 
   67 devclass_t      mlx_devclass;
   68 
   69 /*
   70  * Per-interface accessor methods
   71  */
   72 static int                      mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
   73 static int                      mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
   74 static void                     mlx_v3_intaction(struct mlx_softc *sc, int action);
   75 static int                      mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2, int first);
   76 
   77 static int                      mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
   78 static int                      mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
   79 static void                     mlx_v4_intaction(struct mlx_softc *sc, int action);
   80 static int                      mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2, int first);
   81 
   82 static int                      mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
   83 static int                      mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
   84 static void                     mlx_v5_intaction(struct mlx_softc *sc, int action);
   85 static int                      mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2, int first);
   86 
   87 /*
   88  * Status monitoring
   89  */
   90 static void                     mlx_periodic(void *data);
   91 static void                     mlx_periodic_enquiry(struct mlx_command *mc);
   92 static void                     mlx_periodic_eventlog_poll(struct mlx_softc *sc);
   93 static void                     mlx_periodic_eventlog_respond(struct mlx_command *mc);
   94 static void                     mlx_periodic_rebuild(struct mlx_command *mc);
   95 
   96 /*
   97  * Channel Pause
   98  */
   99 static void                     mlx_pause_action(struct mlx_softc *sc);
  100 static void                     mlx_pause_done(struct mlx_command *mc);
  101 
  102 /*
  103  * Command submission.
  104  */
  105 static void                     *mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, 
  106                                              void (*complete)(struct mlx_command *mc));
  107 static int                      mlx_flush(struct mlx_softc *sc);
  108 static int                      mlx_check(struct mlx_softc *sc, int drive);
  109 static int                      mlx_rebuild(struct mlx_softc *sc, int channel, int target);
  110 static int                      mlx_wait_command(struct mlx_command *mc);
  111 static int                      mlx_poll_command(struct mlx_command *mc);
  112 void                            mlx_startio_cb(void *arg,
  113                                                bus_dma_segment_t *segs,
  114                                                int nsegments, int error);
  115 static void                     mlx_startio(struct mlx_softc *sc);
  116 static void                     mlx_completeio(struct mlx_command *mc);
  117 static int                      mlx_user_command(struct mlx_softc *sc,
  118                                                  struct mlx_usercommand *mu);
  119 void                            mlx_user_cb(void *arg, bus_dma_segment_t *segs,
  120                                             int nsegments, int error);
  121 
  122 /*
  123  * Command buffer allocation.
  124  */
  125 static struct mlx_command       *mlx_alloccmd(struct mlx_softc *sc);
  126 static void                     mlx_releasecmd(struct mlx_command *mc);
  127 static void                     mlx_freecmd(struct mlx_command *mc);
  128 
  129 /*
  130  * Command management.
  131  */
  132 static int                      mlx_getslot(struct mlx_command *mc);
  133 static void                     mlx_setup_dmamap(struct mlx_command *mc,
  134                                                  bus_dma_segment_t *segs,
  135                                                  int nsegments, int error);
  136 static void                     mlx_unmapcmd(struct mlx_command *mc);
  137 static int                      mlx_shutdown_locked(struct mlx_softc *sc);
  138 static int                      mlx_start(struct mlx_command *mc);
  139 static int                      mlx_done(struct mlx_softc *sc, int startio);
  140 static void                     mlx_complete(struct mlx_softc *sc);
  141 
  142 /*
  143  * Debugging.
  144  */
  145 static char                     *mlx_diagnose_command(struct mlx_command *mc);
  146 static void                     mlx_describe_controller(struct mlx_softc *sc);
  147 static int                      mlx_fw_message(struct mlx_softc *sc, int status, int param1, int param2);
  148 
  149 /*
  150  * Utility functions.
  151  */
  152 static struct mlx_sysdrive      *mlx_findunit(struct mlx_softc *sc, int unit);
  153 
  154 /********************************************************************************
  155  ********************************************************************************
  156                                                                 Public Interfaces
  157  ********************************************************************************
  158  ********************************************************************************/
  159 
  160 /********************************************************************************
  161  * Free all of the resources associated with (sc)
  162  *
  163  * Should not be called if the controller is active.
  164  */
  165 void
  166 mlx_free(struct mlx_softc *sc)
  167 {
  168     struct mlx_command  *mc;
  169 
  170     debug_called(1);
  171 
  172     /* destroy control device */
  173     if (sc->mlx_dev_t != NULL)
  174         destroy_dev(sc->mlx_dev_t);
  175 
  176     if (sc->mlx_intr)
  177         bus_teardown_intr(sc->mlx_dev, sc->mlx_irq, sc->mlx_intr);
  178 
  179     /* cancel status timeout */
  180     MLX_IO_LOCK(sc);
  181     callout_stop(&sc->mlx_timeout);
  182 
  183     /* throw away any command buffers */
  184     while ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) {
  185         TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
  186         mlx_freecmd(mc);
  187     }
  188     MLX_IO_UNLOCK(sc);
  189     callout_drain(&sc->mlx_timeout);
  190 
  191     /* destroy data-transfer DMA tag */
  192     if (sc->mlx_buffer_dmat)
  193         bus_dma_tag_destroy(sc->mlx_buffer_dmat);
  194 
  195     /* free and destroy DMA memory and tag for s/g lists */
  196     if (sc->mlx_sgbusaddr)
  197         bus_dmamap_unload(sc->mlx_sg_dmat, sc->mlx_sg_dmamap);
  198     if (sc->mlx_sgtable)
  199         bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
  200     if (sc->mlx_sg_dmat)
  201         bus_dma_tag_destroy(sc->mlx_sg_dmat);
  202 
  203     /* disconnect the interrupt handler */
  204     if (sc->mlx_irq != NULL)
  205         bus_release_resource(sc->mlx_dev, SYS_RES_IRQ, 0, sc->mlx_irq);
  206 
  207     /* destroy the parent DMA tag */
  208     if (sc->mlx_parent_dmat)
  209         bus_dma_tag_destroy(sc->mlx_parent_dmat);
  210 
  211     /* release the register window mapping */
  212     if (sc->mlx_mem != NULL)
  213         bus_release_resource(sc->mlx_dev, sc->mlx_mem_type, sc->mlx_mem_rid, sc->mlx_mem);
  214 
  215     /* free controller enquiry data */
  216     if (sc->mlx_enq2 != NULL)
  217         free(sc->mlx_enq2, M_DEVBUF);
  218 
  219     sx_destroy(&sc->mlx_config_lock);
  220     mtx_destroy(&sc->mlx_io_lock);
  221 }
  222 
  223 /********************************************************************************
  224  * Map the scatter/gather table into bus space
  225  */
  226 static void
  227 mlx_dma_map_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
  228 {
  229     struct mlx_softc    *sc = (struct mlx_softc *)arg;
  230 
  231     debug_called(1);
  232 
  233     /* save base of s/g table's address in bus space */
  234     sc->mlx_sgbusaddr = segs->ds_addr;
  235 }
  236 
  237 static int
  238 mlx_sglist_map(struct mlx_softc *sc)
  239 {
  240     size_t      segsize;
  241     int         error, ncmd;
  242 
  243     debug_called(1);
  244 
  245     /* destroy any existing mappings */
  246     if (sc->mlx_sgbusaddr)
  247         bus_dmamap_unload(sc->mlx_sg_dmat, sc->mlx_sg_dmamap);
  248     if (sc->mlx_sgtable)
  249         bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
  250     if (sc->mlx_sg_dmat)
  251         bus_dma_tag_destroy(sc->mlx_sg_dmat);
  252     sc->mlx_sgbusaddr = 0;
  253     sc->mlx_sgtable = NULL;
  254     sc->mlx_sg_dmat = NULL;
  255 
  256     /*
  257      * Create a single tag describing a region large enough to hold all of
  258      * the s/g lists we will need.  If we're called early on, we don't know how
  259      * many commands we're going to be asked to support, so only allocate enough
  260      * for a couple.
  261      */
  262     if (sc->mlx_enq2 == NULL) {
  263         ncmd = 2;
  264     } else {
  265         ncmd = sc->mlx_enq2->me_max_commands;
  266     }
  267     segsize = sizeof(struct mlx_sgentry) * MLX_NSEG * ncmd;
  268     error = bus_dma_tag_create(sc->mlx_parent_dmat,     /* parent */
  269                                1, 0,                    /* alignment,boundary */
  270                                BUS_SPACE_MAXADDR,       /* lowaddr */
  271                                BUS_SPACE_MAXADDR,       /* highaddr */
  272                                NULL, NULL,              /* filter, filterarg */
  273                                segsize, 1,              /* maxsize, nsegments */
  274                                BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
  275                                0,                       /* flags */
  276                                NULL, NULL,              /* lockfunc, lockarg */
  277                                &sc->mlx_sg_dmat);
  278     if (error != 0) {
  279         device_printf(sc->mlx_dev, "can't allocate scatter/gather DMA tag\n");
  280         return(ENOMEM);
  281     }
  282 
  283     /*
  284      * Allocate enough s/g maps for all commands and permanently map them into
  285      * controller-visible space.
  286      *  
  287      * XXX this assumes we can get enough space for all the s/g maps in one 
  288      * contiguous slab.  We may need to switch to a more complex arrangement
  289      * where we allocate in smaller chunks and keep a lookup table from slot
  290      * to bus address.
  291      */
  292     error = bus_dmamem_alloc(sc->mlx_sg_dmat, (void **)&sc->mlx_sgtable,
  293                              BUS_DMA_NOWAIT, &sc->mlx_sg_dmamap);
  294     if (error) {
  295         device_printf(sc->mlx_dev, "can't allocate s/g table\n");
  296         return(ENOMEM);
  297     }
  298     (void)bus_dmamap_load(sc->mlx_sg_dmat, sc->mlx_sg_dmamap, sc->mlx_sgtable,
  299                           segsize, mlx_dma_map_sg, sc, 0);
  300     return(0);
  301 }
  302 
  303 /********************************************************************************
  304  * Initialise the controller and softc
  305  */
  306 int
  307 mlx_attach(struct mlx_softc *sc)
  308 {
  309     struct mlx_enquiry_old      *meo;
  310     int                         rid, error, fwminor, hscode, hserror, hsparam1, hsparam2, hsmsg;
  311 
  312     debug_called(1);
  313 
  314     /*
  315      * Initialise per-controller queues.
  316      */
  317     TAILQ_INIT(&sc->mlx_work);
  318     TAILQ_INIT(&sc->mlx_freecmds);
  319     bioq_init(&sc->mlx_bioq);
  320 
  321     /* 
  322      * Select accessor methods based on controller interface type.
  323      */
  324     switch(sc->mlx_iftype) {
  325     case MLX_IFTYPE_2:
  326     case MLX_IFTYPE_3:
  327         sc->mlx_tryqueue        = mlx_v3_tryqueue;
  328         sc->mlx_findcomplete    = mlx_v3_findcomplete;
  329         sc->mlx_intaction       = mlx_v3_intaction;
  330         sc->mlx_fw_handshake    = mlx_v3_fw_handshake;
  331         break;
  332     case MLX_IFTYPE_4:
  333         sc->mlx_tryqueue        = mlx_v4_tryqueue;
  334         sc->mlx_findcomplete    = mlx_v4_findcomplete;
  335         sc->mlx_intaction       = mlx_v4_intaction;
  336         sc->mlx_fw_handshake    = mlx_v4_fw_handshake;
  337         break;
  338     case MLX_IFTYPE_5:
  339         sc->mlx_tryqueue        = mlx_v5_tryqueue;
  340         sc->mlx_findcomplete    = mlx_v5_findcomplete;
  341         sc->mlx_intaction       = mlx_v5_intaction;
  342         sc->mlx_fw_handshake    = mlx_v5_fw_handshake;
  343         break;
  344     default:
  345         return(ENXIO);          /* should never happen */
  346     }
  347 
  348     /* disable interrupts before we start talking to the controller */
  349     MLX_IO_LOCK(sc);
  350     sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
  351     MLX_IO_UNLOCK(sc);
  352 
  353     /* 
  354      * Wait for the controller to come ready, handshake with the firmware if required.
  355      * This is typically only necessary on platforms where the controller BIOS does not
  356      * run.
  357      */
  358     hsmsg = 0;
  359     DELAY(1000);
  360     while ((hscode = sc->mlx_fw_handshake(sc, &hserror, &hsparam1, &hsparam2,
  361         hsmsg == 0)) != 0) {
  362         /* report first time around... */
  363         if (hsmsg == 0) {
  364             device_printf(sc->mlx_dev, "controller initialisation in progress...\n");
  365             hsmsg = 1;
  366         }
  367         /* did we get a real message? */
  368         if (hscode == 2) {
  369             hscode = mlx_fw_message(sc, hserror, hsparam1, hsparam2);
  370             /* fatal initialisation error? */
  371             if (hscode != 0) {
  372                 return(ENXIO);
  373             }
  374         }
  375     }
  376     if (hsmsg == 1)
  377         device_printf(sc->mlx_dev, "initialisation complete.\n");
  378 
  379     /* 
  380      * Allocate and connect our interrupt.
  381      */
  382     rid = 0;
  383     sc->mlx_irq = bus_alloc_resource_any(sc->mlx_dev, SYS_RES_IRQ, &rid,
  384         RF_SHAREABLE | RF_ACTIVE);
  385     if (sc->mlx_irq == NULL) {
  386         device_printf(sc->mlx_dev, "can't allocate interrupt\n");
  387         return(ENXIO);
  388     }
  389     error = bus_setup_intr(sc->mlx_dev, sc->mlx_irq, INTR_TYPE_BIO |
  390         INTR_ENTROPY | INTR_MPSAFE, NULL, mlx_intr, sc, &sc->mlx_intr);
  391     if (error) {
  392         device_printf(sc->mlx_dev, "can't set up interrupt\n");
  393         return(ENXIO);
  394     }
  395 
  396     /*
  397      * Create DMA tag for mapping buffers into controller-addressable space.
  398      */
  399     error = bus_dma_tag_create(sc->mlx_parent_dmat,     /* parent */
  400                                1, 0,                    /* align, boundary */
  401                                BUS_SPACE_MAXADDR,       /* lowaddr */
  402                                BUS_SPACE_MAXADDR,       /* highaddr */
  403                                NULL, NULL,              /* filter, filterarg */
  404                                MLX_MAXPHYS,             /* maxsize */
  405                                MLX_NSEG,                /* nsegments */
  406                                BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
  407                                0,                       /* flags */
  408                                busdma_lock_mutex,       /* lockfunc */
  409                                &sc->mlx_io_lock,        /* lockarg */
  410                                &sc->mlx_buffer_dmat);
  411     if (error != 0) {
  412         device_printf(sc->mlx_dev, "can't allocate buffer DMA tag\n");
  413         return(ENOMEM);
  414     }
  415 
  416     /*
  417      * Create some initial scatter/gather mappings so we can run the probe
  418      * commands.
  419      */
  420     error = mlx_sglist_map(sc);
  421     if (error != 0) {
  422         device_printf(sc->mlx_dev, "can't make initial s/g list mapping\n");
  423         return(error);
  424     }
  425 
  426     /*
  427      * We don't (yet) know where the event log is up to.
  428      */
  429     sc->mlx_currevent = -1;
  430 
  431     /* 
  432      * Obtain controller feature information
  433      */
  434     MLX_IO_LOCK(sc);
  435     if ((sc->mlx_enq2 = mlx_enquire(sc, MLX_CMD_ENQUIRY2, sizeof(struct mlx_enquiry2), NULL)) == NULL) {
  436         MLX_IO_UNLOCK(sc);
  437         device_printf(sc->mlx_dev, "ENQUIRY2 failed\n");
  438         return(ENXIO);
  439     }
  440 
  441     /*
  442      * Do quirk/feature related things.
  443      */
  444     fwminor = (sc->mlx_enq2->me_firmware_id >> 8) & 0xff;
  445     switch(sc->mlx_iftype) {
  446     case MLX_IFTYPE_2:
  447         /* These controllers don't report the firmware version in the ENQUIRY2 response */
  448         if ((meo = mlx_enquire(sc, MLX_CMD_ENQUIRY_OLD, sizeof(struct mlx_enquiry_old), NULL)) == NULL) {
  449             MLX_IO_UNLOCK(sc);
  450             device_printf(sc->mlx_dev, "ENQUIRY_OLD failed\n");
  451             return(ENXIO);
  452         }
  453         sc->mlx_enq2->me_firmware_id = ('' << 24) | (0 << 16) | (meo->me_fwminor << 8) | meo->me_fwmajor;
  454         
  455         /* XXX require 2.42 or better (PCI) */
  456         if (meo->me_fwminor < 42) {
  457             device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
  458             device_printf(sc->mlx_dev, " *** WARNING *** Use revision 2.42 or later\n");
  459         }
  460         free(meo, M_DEVBUF);
  461         break;
  462     case MLX_IFTYPE_3:
  463         /* XXX certify 3.52? */
  464         if (fwminor < 51) {
  465             device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
  466             device_printf(sc->mlx_dev, " *** WARNING *** Use revision 3.51 or later\n");
  467         }
  468         break;
  469     case MLX_IFTYPE_4:
  470         /* XXX certify firmware versions? */
  471         if (fwminor < 6) {
  472             device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
  473             device_printf(sc->mlx_dev, " *** WARNING *** Use revision 4.06 or later\n");
  474         }
  475         break;
  476     case MLX_IFTYPE_5:
  477         if (fwminor < 7) {
  478             device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
  479             device_printf(sc->mlx_dev, " *** WARNING *** Use revision 5.07 or later\n");
  480         }
  481         break;
  482     default:
  483         MLX_IO_UNLOCK(sc);
  484         return(ENXIO);          /* should never happen */
  485     }
  486     MLX_IO_UNLOCK(sc);
  487 
  488     /*
  489      * Create the final scatter/gather mappings now that we have characterised the controller.
  490      */
  491     error = mlx_sglist_map(sc);
  492     if (error != 0) {
  493         device_printf(sc->mlx_dev, "can't make final s/g list mapping\n");
  494         return(error);
  495     }
  496 
  497     /*
  498      * No user-requested background operation is in progress.
  499      */
  500     sc->mlx_background = 0;
  501     sc->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
  502 
  503     /*
  504      * Create the control device.
  505      */
  506     sc->mlx_dev_t = make_dev(&mlx_cdevsw, 0, UID_ROOT, GID_OPERATOR, 
  507                              S_IRUSR | S_IWUSR, "mlx%d", device_get_unit(sc->mlx_dev));
  508     sc->mlx_dev_t->si_drv1 = sc;
  509 
  510     /*
  511      * Start the timeout routine.
  512      */
  513     callout_reset(&sc->mlx_timeout, hz, mlx_periodic, sc);
  514 
  515     /* print a little information about the controller */
  516     mlx_describe_controller(sc);
  517 
  518     return(0);
  519 }
  520 
  521 /********************************************************************************
  522  * Locate disk resources and attach children to them.
  523  */
  524 void
  525 mlx_startup(struct mlx_softc *sc)
  526 {
  527     struct mlx_enq_sys_drive    *mes;
  528     struct mlx_sysdrive         *dr;
  529     int                         i, error;
  530 
  531     debug_called(1);
  532     
  533     /*
  534      * Scan all the system drives and attach children for those that
  535      * don't currently have them.
  536      */
  537     MLX_IO_LOCK(sc);
  538     mes = mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(*mes) * MLX_MAXDRIVES, NULL);
  539     MLX_IO_UNLOCK(sc);
  540     if (mes == NULL) {
  541         device_printf(sc->mlx_dev, "error fetching drive status\n");
  542         return;
  543     }
  544     
  545     /* iterate over drives returned */
  546     MLX_CONFIG_LOCK(sc);
  547     for (i = 0, dr = &sc->mlx_sysdrive[0];
  548          (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff);
  549          i++, dr++) {
  550         /* are we already attached to this drive? */
  551         if (dr->ms_disk == 0) {
  552             /* pick up drive information */
  553             dr->ms_size = mes[i].sd_size;
  554             dr->ms_raidlevel = mes[i].sd_raidlevel & 0xf;
  555             dr->ms_state = mes[i].sd_state;
  556 
  557             /* generate geometry information */
  558             if (sc->mlx_geom == MLX_GEOM_128_32) {
  559                 dr->ms_heads = 128;
  560                 dr->ms_sectors = 32;
  561                 dr->ms_cylinders = dr->ms_size / (128 * 32);
  562             } else {        /* MLX_GEOM_255/63 */
  563                 dr->ms_heads = 255;
  564                 dr->ms_sectors = 63;
  565                 dr->ms_cylinders = dr->ms_size / (255 * 63);
  566             }
  567             dr->ms_disk =  device_add_child(sc->mlx_dev, /*"mlxd"*/NULL, -1);
  568             if (dr->ms_disk == 0)
  569                 device_printf(sc->mlx_dev, "device_add_child failed\n");
  570             device_set_ivars(dr->ms_disk, dr);
  571         }
  572     }
  573     free(mes, M_DEVBUF);
  574     if ((error = bus_generic_attach(sc->mlx_dev)) != 0)
  575         device_printf(sc->mlx_dev, "bus_generic_attach returned %d", error);
  576 
  577     /* mark controller back up */
  578     MLX_IO_LOCK(sc);
  579     sc->mlx_state &= ~MLX_STATE_SHUTDOWN;
  580 
  581     /* enable interrupts */
  582     sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
  583     MLX_IO_UNLOCK(sc);
  584     MLX_CONFIG_UNLOCK(sc);
  585 }
  586 
  587 /********************************************************************************
  588  * Disconnect from the controller completely, in preparation for unload.
  589  */
  590 int
  591 mlx_detach(device_t dev)
  592 {
  593     struct mlx_softc    *sc = device_get_softc(dev);
  594     struct mlxd_softc   *mlxd;
  595     int                 i, error;
  596 
  597     debug_called(1);
  598 
  599     error = EBUSY;
  600     MLX_CONFIG_LOCK(sc);
  601     if (sc->mlx_state & MLX_STATE_OPEN)
  602         goto out;
  603 
  604     for (i = 0; i < MLX_MAXDRIVES; i++) {
  605         if (sc->mlx_sysdrive[i].ms_disk != 0) {
  606             mlxd = device_get_softc(sc->mlx_sysdrive[i].ms_disk);
  607             if (mlxd->mlxd_flags & MLXD_OPEN) {         /* drive is mounted, abort detach */
  608                 device_printf(sc->mlx_sysdrive[i].ms_disk, "still open, can't detach\n");
  609                 goto out;
  610             }
  611         }
  612     }
  613     if ((error = mlx_shutdown(dev)))
  614         goto out;
  615     MLX_CONFIG_UNLOCK(sc);
  616 
  617     mlx_free(sc);
  618 
  619     return (0);
  620  out:
  621     MLX_CONFIG_UNLOCK(sc);
  622     return(error);
  623 }
  624 
  625 /********************************************************************************
  626  * Bring the controller down to a dormant state and detach all child devices.
  627  *
  628  * This function is called before detach, system shutdown, or before performing
  629  * an operation which may add or delete system disks.  (Call mlx_startup to
  630  * resume normal operation.)
  631  *
  632  * Note that we can assume that the bioq on the controller is empty, as we won't
  633  * allow shutdown if any device is open.
  634  */
  635 int
  636 mlx_shutdown(device_t dev)
  637 {
  638     struct mlx_softc    *sc = device_get_softc(dev);
  639     int                 error;
  640 
  641     MLX_CONFIG_LOCK(sc);
  642     error = mlx_shutdown_locked(sc);
  643     MLX_CONFIG_UNLOCK(sc);
  644     return (error);
  645 }
  646 
  647 static int
  648 mlx_shutdown_locked(struct mlx_softc *sc)
  649 {
  650     int                 i, error;
  651 
  652     debug_called(1);
  653 
  654     MLX_CONFIG_ASSERT_LOCKED(sc);
  655 
  656     MLX_IO_LOCK(sc);
  657     sc->mlx_state |= MLX_STATE_SHUTDOWN;
  658     sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
  659 
  660     /* flush controller */
  661     device_printf(sc->mlx_dev, "flushing cache...");
  662     if (mlx_flush(sc)) {
  663         printf("failed\n");
  664     } else {
  665         printf("done\n");
  666     }
  667     MLX_IO_UNLOCK(sc);
  668     
  669     /* delete all our child devices */
  670     for (i = 0; i < MLX_MAXDRIVES; i++) {
  671         if (sc->mlx_sysdrive[i].ms_disk != 0) {
  672             if ((error = device_delete_child(sc->mlx_dev, sc->mlx_sysdrive[i].ms_disk)) != 0)
  673                 return (error);
  674             sc->mlx_sysdrive[i].ms_disk = 0;
  675         }
  676     }
  677 
  678     return (0);
  679 }
  680 
  681 /********************************************************************************
  682  * Bring the controller to a quiescent state, ready for system suspend.
  683  */
  684 int
  685 mlx_suspend(device_t dev)
  686 {
  687     struct mlx_softc    *sc = device_get_softc(dev);
  688 
  689     debug_called(1);
  690 
  691     MLX_IO_LOCK(sc);
  692     sc->mlx_state |= MLX_STATE_SUSPEND;
  693     
  694     /* flush controller */
  695     device_printf(sc->mlx_dev, "flushing cache...");
  696     printf("%s\n", mlx_flush(sc) ? "failed" : "done");
  697 
  698     sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
  699     MLX_IO_UNLOCK(sc);
  700 
  701     return(0);
  702 }
  703 
  704 /********************************************************************************
  705  * Bring the controller back to a state ready for operation.
  706  */
  707 int
  708 mlx_resume(device_t dev)
  709 {
  710     struct mlx_softc    *sc = device_get_softc(dev);
  711 
  712     debug_called(1);
  713 
  714     MLX_IO_LOCK(sc);
  715     sc->mlx_state &= ~MLX_STATE_SUSPEND;
  716     sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
  717     MLX_IO_UNLOCK(sc);
  718 
  719     return(0);
  720 }
  721 
  722 /*******************************************************************************
  723  * Take an interrupt, or be poked by other code to look for interrupt-worthy
  724  * status.
  725  */
  726 void
  727 mlx_intr(void *arg)
  728 {
  729     struct mlx_softc    *sc = (struct mlx_softc *)arg;
  730 
  731     debug_called(1);
  732 
  733     /* collect finished commands, queue anything waiting */
  734     MLX_IO_LOCK(sc);
  735     mlx_done(sc, 1);
  736     MLX_IO_UNLOCK(sc);
  737 };
  738 
  739 /*******************************************************************************
  740  * Receive a buf structure from a child device and queue it on a particular
  741  * disk resource, then poke the disk resource to start as much work as it can.
  742  */
  743 int
  744 mlx_submit_buf(struct mlx_softc *sc, struct bio *bp)
  745 {
  746     
  747     debug_called(1);
  748 
  749     MLX_IO_ASSERT_LOCKED(sc);
  750     bioq_insert_tail(&sc->mlx_bioq, bp);
  751     sc->mlx_waitbufs++;
  752     mlx_startio(sc);
  753     return(0);
  754 }
  755 
  756 /********************************************************************************
  757  * Accept an open operation on the control device.
  758  */
  759 int
  760 mlx_open(struct cdev *dev, int flags, int fmt, struct thread *td)
  761 {
  762     struct mlx_softc    *sc = dev->si_drv1;
  763 
  764     MLX_CONFIG_LOCK(sc);
  765     MLX_IO_LOCK(sc);
  766     sc->mlx_state |= MLX_STATE_OPEN;
  767     MLX_IO_UNLOCK(sc);
  768     MLX_CONFIG_UNLOCK(sc);
  769     return(0);
  770 }
  771 
  772 /********************************************************************************
  773  * Accept the last close on the control device.
  774  */
  775 int
  776 mlx_close(struct cdev *dev, int flags, int fmt, struct thread *td)
  777 {
  778     struct mlx_softc    *sc = dev->si_drv1;
  779 
  780     MLX_CONFIG_LOCK(sc);
  781     MLX_IO_LOCK(sc);
  782     sc->mlx_state &= ~MLX_STATE_OPEN;
  783     MLX_IO_UNLOCK(sc);
  784     MLX_CONFIG_UNLOCK(sc);
  785     return (0);
  786 }
  787 
  788 /********************************************************************************
  789  * Handle controller-specific control operations.
  790  */
  791 int
  792 mlx_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td)
  793 {
  794     struct mlx_softc            *sc = dev->si_drv1;
  795     struct mlx_rebuild_request  *rb = (struct mlx_rebuild_request *)addr;
  796     struct mlx_rebuild_status   *rs = (struct mlx_rebuild_status *)addr;
  797     int                         *arg = (int *)addr;
  798     struct mlx_pause            *mp;
  799     struct mlx_sysdrive         *dr;
  800     struct mlxd_softc           *mlxd;
  801     int                         i, error;
  802     
  803     switch(cmd) {
  804         /*
  805          * Enumerate connected system drives; returns the first system drive's
  806          * unit number if *arg is -1, or the next unit after *arg if it's
  807          * a valid unit on this controller.
  808          */
  809     case MLX_NEXT_CHILD:
  810         /* search system drives */
  811         MLX_CONFIG_LOCK(sc);
  812         for (i = 0; i < MLX_MAXDRIVES; i++) {
  813             /* is this one attached? */
  814             if (sc->mlx_sysdrive[i].ms_disk != 0) {
  815                 /* looking for the next one we come across? */
  816                 if (*arg == -1) {
  817                     *arg = device_get_unit(sc->mlx_sysdrive[i].ms_disk);
  818                     MLX_CONFIG_UNLOCK(sc);
  819                     return(0);
  820                 }
  821                 /* we want the one after this one */
  822                 if (*arg == device_get_unit(sc->mlx_sysdrive[i].ms_disk))
  823                     *arg = -1;
  824             }
  825         }
  826         MLX_CONFIG_UNLOCK(sc);
  827         return(ENOENT);
  828 
  829         /*
  830          * Scan the controller to see whether new drives have appeared.
  831          */
  832     case MLX_RESCAN_DRIVES:
  833         mtx_lock(&Giant);
  834         mlx_startup(sc);
  835         mtx_unlock(&Giant);     
  836         return(0);
  837 
  838         /*
  839          * Disconnect from the specified drive; it may be about to go 
  840          * away.
  841          */
  842     case MLX_DETACH_DRIVE:                      /* detach one drive */
  843         MLX_CONFIG_LOCK(sc);
  844         if (((dr = mlx_findunit(sc, *arg)) == NULL) || 
  845             ((mlxd = device_get_softc(dr->ms_disk)) == NULL)) {
  846             MLX_CONFIG_UNLOCK(sc);
  847             return(ENOENT);
  848         }
  849 
  850         device_printf(dr->ms_disk, "detaching...");
  851         error = 0;
  852         if (mlxd->mlxd_flags & MLXD_OPEN) {
  853             error = EBUSY;
  854             goto detach_out;
  855         }
  856         
  857         /* flush controller */
  858         MLX_IO_LOCK(sc);
  859         if (mlx_flush(sc)) {
  860             MLX_IO_UNLOCK(sc);
  861             error = EBUSY;
  862             goto detach_out;
  863         }
  864         MLX_IO_UNLOCK(sc);
  865 
  866         /* nuke drive */
  867         if ((error = device_delete_child(sc->mlx_dev, dr->ms_disk)) != 0)
  868             goto detach_out;
  869         dr->ms_disk = 0;
  870 
  871     detach_out:
  872         MLX_CONFIG_UNLOCK(sc);
  873         if (error) {
  874             printf("failed\n");
  875         } else {
  876             printf("done\n");
  877         }
  878         return(error);
  879 
  880         /*
  881          * Pause one or more SCSI channels for a period of time, to assist
  882          * in the process of hot-swapping devices.
  883          *
  884          * Note that at least the 3.51 firmware on the DAC960PL doesn't seem
  885          * to do this right.
  886          */
  887     case MLX_PAUSE_CHANNEL:                     /* schedule a channel pause */
  888         /* Does this command work on this firmware? */
  889         if (!(sc->mlx_feature & MLX_FEAT_PAUSEWORKS))
  890             return(EOPNOTSUPP);
  891 
  892         /* check time values */
  893         mp = (struct mlx_pause *)addr;
  894         if ((mp->mp_when < 0) || (mp->mp_when > 3600))
  895             return(EINVAL);
  896         if ((mp->mp_howlong < 1) || (mp->mp_howlong > (0xf * 30)))
  897             return(EINVAL);
  898 
  899         MLX_IO_LOCK(sc);
  900         if ((mp->mp_which == MLX_PAUSE_CANCEL) && (sc->mlx_pause.mp_when != 0)) {
  901             /* cancel a pending pause operation */
  902             sc->mlx_pause.mp_which = 0;
  903         } else {
  904             /* fix for legal channels */
  905             mp->mp_which &= ((1 << sc->mlx_enq2->me_actual_channels) -1);
  906             
  907             /* check for a pause currently running */
  908             if ((sc->mlx_pause.mp_which != 0) && (sc->mlx_pause.mp_when == 0)) {
  909                 MLX_IO_UNLOCK(sc);
  910                 return(EBUSY);
  911             }
  912 
  913             /* looks ok, go with it */
  914             sc->mlx_pause.mp_which = mp->mp_which;
  915             sc->mlx_pause.mp_when = time_second + mp->mp_when;
  916             sc->mlx_pause.mp_howlong = sc->mlx_pause.mp_when + mp->mp_howlong;
  917         }
  918         MLX_IO_UNLOCK(sc);
  919         return(0);
  920 
  921         /*
  922          * Accept a command passthrough-style.
  923          */
  924     case MLX_COMMAND:
  925         return(mlx_user_command(sc, (struct mlx_usercommand *)addr));
  926 
  927         /*
  928          * Start a rebuild on a given SCSI disk
  929          */
  930     case MLX_REBUILDASYNC:
  931         MLX_IO_LOCK(sc);
  932         if (sc->mlx_background != 0) {
  933             MLX_IO_UNLOCK(sc);
  934             rb->rr_status = 0x0106;
  935             return(EBUSY);
  936         }
  937         rb->rr_status = mlx_rebuild(sc, rb->rr_channel, rb->rr_target);
  938         switch (rb->rr_status) {
  939         case 0:
  940             error = 0;
  941             break;
  942         case 0x10000:
  943             error = ENOMEM;             /* couldn't set up the command */
  944             break;
  945         case 0x0002:    
  946             error = EBUSY;
  947             break;
  948         case 0x0104:
  949             error = EIO;
  950             break;
  951         case 0x0105:
  952             error = ERANGE;
  953             break;
  954         case 0x0106:
  955             error = EBUSY;
  956             break;
  957         default:
  958             error = EINVAL;
  959             break;
  960         }
  961         if (error == 0)
  962             sc->mlx_background = MLX_BACKGROUND_REBUILD;
  963         MLX_IO_UNLOCK(sc);
  964         return(error);
  965         
  966         /*
  967          * Get the status of the current rebuild or consistency check.
  968          */
  969     case MLX_REBUILDSTAT:
  970         MLX_IO_LOCK(sc);
  971         *rs = sc->mlx_rebuildstat;
  972         MLX_IO_UNLOCK(sc);
  973         return(0);
  974 
  975         /*
  976          * Return the per-controller system drive number matching the
  977          * disk device number in (arg), if it happens to belong to us.
  978          */
  979     case MLX_GET_SYSDRIVE:
  980         error = ENOENT;
  981         MLX_CONFIG_LOCK(sc);
  982         mtx_lock(&Giant);
  983         mlxd = (struct mlxd_softc *)devclass_get_softc(mlxd_devclass, *arg);
  984         mtx_unlock(&Giant);
  985         if ((mlxd != NULL) && (mlxd->mlxd_drive >= sc->mlx_sysdrive) && 
  986             (mlxd->mlxd_drive < (sc->mlx_sysdrive + MLX_MAXDRIVES))) {
  987             error = 0;
  988             *arg = mlxd->mlxd_drive - sc->mlx_sysdrive;
  989         }
  990         MLX_CONFIG_UNLOCK(sc);
  991         return(error);
  992         
  993     default:    
  994         return(ENOTTY);
  995     }
  996 }
  997 
  998 /********************************************************************************
  999  * Handle operations requested by a System Drive connected to this controller.
 1000  */
 1001 int
 1002 mlx_submit_ioctl(struct mlx_softc *sc, struct mlx_sysdrive *drive, u_long cmd, 
 1003                 caddr_t addr, int32_t flag, struct thread *td)
 1004 {
 1005     int                         *arg = (int *)addr;
 1006     int                         error, result;
 1007 
 1008     switch(cmd) {
 1009         /*
 1010          * Return the current status of this drive.
 1011          */
 1012     case MLXD_STATUS:
 1013         MLX_IO_LOCK(sc);
 1014         *arg = drive->ms_state;
 1015         MLX_IO_UNLOCK(sc);
 1016         return(0);
 1017         
 1018         /*
 1019          * Start a background consistency check on this drive.
 1020          */
 1021     case MLXD_CHECKASYNC:               /* start a background consistency check */
 1022         MLX_IO_LOCK(sc);
 1023         if (sc->mlx_background != 0) {
 1024             MLX_IO_UNLOCK(sc);
 1025             *arg = 0x0106;
 1026             return(EBUSY);
 1027         }
 1028         result = mlx_check(sc, drive - &sc->mlx_sysdrive[0]);
 1029         switch (result) {
 1030         case 0:
 1031             error = 0;
 1032             break;
 1033         case 0x10000:
 1034             error = ENOMEM;             /* couldn't set up the command */
 1035             break;
 1036         case 0x0002:    
 1037             error = EIO;
 1038             break;
 1039         case 0x0105:
 1040             error = ERANGE;
 1041             break;
 1042         case 0x0106:
 1043             error = EBUSY;
 1044             break;
 1045         default:
 1046             error = EINVAL;
 1047             break;
 1048         }
 1049         if (error == 0)
 1050             sc->mlx_background = MLX_BACKGROUND_CHECK;
 1051         MLX_IO_UNLOCK(sc);
 1052         *arg = result;
 1053         return(error);
 1054 
 1055     }
 1056     return(ENOIOCTL);
 1057 }
 1058 
 1059 
 1060 /********************************************************************************
 1061  ********************************************************************************
 1062                                                                 Status Monitoring
 1063  ********************************************************************************
 1064  ********************************************************************************/
 1065 
 1066 /********************************************************************************
 1067  * Fire off commands to periodically check the status of connected drives.
 1068  */
 1069 static void
 1070 mlx_periodic(void *data)
 1071 {
 1072     struct mlx_softc *sc = (struct mlx_softc *)data;
 1073 
 1074     debug_called(1);
 1075     MLX_IO_ASSERT_LOCKED(sc);
 1076 
 1077     /*
 1078      * Run a bus pause? 
 1079      */
 1080     if ((sc->mlx_pause.mp_which != 0) &&
 1081         (sc->mlx_pause.mp_when > 0) &&
 1082         (time_second >= sc->mlx_pause.mp_when)){
 1083 
 1084         mlx_pause_action(sc);           /* pause is running */
 1085         sc->mlx_pause.mp_when = 0;
 1086         sysbeep(500, hz);
 1087 
 1088         /* 
 1089          * Bus pause still running?
 1090          */
 1091     } else if ((sc->mlx_pause.mp_which != 0) &&
 1092                (sc->mlx_pause.mp_when == 0)) {
 1093 
 1094         /* time to stop bus pause? */
 1095         if (time_second >= sc->mlx_pause.mp_howlong) {
 1096             mlx_pause_action(sc);
 1097             sc->mlx_pause.mp_which = 0; /* pause is complete */
 1098             sysbeep(500, hz);
 1099         } else {
 1100             sysbeep((time_second % 5) * 100 + 500, hz/8);
 1101         }
 1102 
 1103         /* 
 1104          * Run normal periodic activities? 
 1105          */
 1106     } else if (time_second > (sc->mlx_lastpoll + 10)) {
 1107         sc->mlx_lastpoll = time_second;
 1108 
 1109         /* 
 1110          * Check controller status.
 1111          *
 1112          * XXX Note that this may not actually launch a command in situations of high load.
 1113          */
 1114         mlx_enquire(sc, (sc->mlx_iftype == MLX_IFTYPE_2) ? MLX_CMD_ENQUIRY_OLD : MLX_CMD_ENQUIRY, 
 1115                     imax(sizeof(struct mlx_enquiry), sizeof(struct mlx_enquiry_old)), mlx_periodic_enquiry);
 1116 
 1117         /*
 1118          * Check system drive status.
 1119          *
 1120          * XXX This might be better left to event-driven detection, eg. I/O to an offline
 1121          *     drive will detect it's offline, rebuilds etc. should detect the drive is back
 1122          *     online.
 1123          */
 1124         mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(struct mlx_enq_sys_drive) * MLX_MAXDRIVES, 
 1125                         mlx_periodic_enquiry);
 1126                 
 1127     }
 1128 
 1129     /* get drive rebuild/check status */
 1130     /* XXX should check sc->mlx_background if this is only valid while in progress */
 1131     mlx_enquire(sc, MLX_CMD_REBUILDSTAT, sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild);
 1132 
 1133     /* deal with possibly-missed interrupts and timed-out commands */
 1134     mlx_done(sc, 1);
 1135 
 1136     /* reschedule another poll next second or so */
 1137     callout_reset(&sc->mlx_timeout, hz, mlx_periodic, sc);
 1138 }
 1139 
 1140 /********************************************************************************
 1141  * Handle the result of an ENQUIRY command instigated by periodic status polling.
 1142  */
 1143 static void
 1144 mlx_periodic_enquiry(struct mlx_command *mc)
 1145 {
 1146     struct mlx_softc            *sc = mc->mc_sc;
 1147 
 1148     debug_called(1);
 1149     MLX_IO_ASSERT_LOCKED(sc);
 1150 
 1151     /* Command completed OK? */
 1152     if (mc->mc_status != 0) {
 1153         device_printf(sc->mlx_dev, "periodic enquiry failed - %s\n", mlx_diagnose_command(mc));
 1154         goto out;
 1155     }
 1156 
 1157     /* respond to command */
 1158     switch(mc->mc_mailbox[0]) {
 1159         /*
 1160          * This is currently a bit fruitless, as we don't know how to extract the eventlog
 1161          * pointer yet.
 1162          */
 1163     case MLX_CMD_ENQUIRY_OLD:
 1164     {
 1165         struct mlx_enquiry              *me = (struct mlx_enquiry *)mc->mc_data;
 1166         struct mlx_enquiry_old          *meo = (struct mlx_enquiry_old *)mc->mc_data;
 1167         int                             i;
 1168 
 1169         /* convert data in-place to new format */
 1170         for (i = (sizeof(me->me_dead) / sizeof(me->me_dead[0])) - 1; i >= 0; i--) {
 1171             me->me_dead[i].dd_chan = meo->me_dead[i].dd_chan;
 1172             me->me_dead[i].dd_targ = meo->me_dead[i].dd_targ;
 1173         }
 1174         me->me_misc_flags        = 0;
 1175         me->me_rebuild_count     = meo->me_rebuild_count;
 1176         me->me_dead_count        = meo->me_dead_count;
 1177         me->me_critical_sd_count = meo->me_critical_sd_count;
 1178         me->me_event_log_seq_num = 0;
 1179         me->me_offline_sd_count  = meo->me_offline_sd_count;
 1180         me->me_max_commands      = meo->me_max_commands;
 1181         me->me_rebuild_flag      = meo->me_rebuild_flag;
 1182         me->me_fwmajor           = meo->me_fwmajor;
 1183         me->me_fwminor           = meo->me_fwminor;
 1184         me->me_status_flags      = meo->me_status_flags;
 1185         me->me_flash_age         = meo->me_flash_age;
 1186         for (i = (sizeof(me->me_drvsize) / sizeof(me->me_drvsize[0])) - 1; i >= 0; i--) {
 1187             if (i > ((sizeof(meo->me_drvsize) / sizeof(meo->me_drvsize[0])) - 1)) {
 1188                 me->me_drvsize[i] = 0;          /* drive beyond supported range */
 1189             } else {
 1190                 me->me_drvsize[i] = meo->me_drvsize[i];
 1191             }
 1192         }
 1193         me->me_num_sys_drvs = meo->me_num_sys_drvs;
 1194     }
 1195     /* FALLTHROUGH */
 1196 
 1197         /*
 1198          * Generic controller status update.  We could do more with this than just
 1199          * checking the event log.
 1200          */
 1201     case MLX_CMD_ENQUIRY:
 1202     {
 1203         struct mlx_enquiry              *me = (struct mlx_enquiry *)mc->mc_data;
 1204         
 1205         if (sc->mlx_currevent == -1) {
 1206             /* initialise our view of the event log */
 1207             sc->mlx_currevent = sc->mlx_lastevent = me->me_event_log_seq_num;
 1208         } else if ((me->me_event_log_seq_num != sc->mlx_lastevent) && !(sc->mlx_flags & MLX_EVENTLOG_BUSY)) {
 1209             /* record where current events are up to */
 1210             sc->mlx_currevent = me->me_event_log_seq_num;
 1211             debug(1, "event log pointer was %d, now %d\n", sc->mlx_lastevent, sc->mlx_currevent);
 1212 
 1213             /* mark the event log as busy */
 1214             sc->mlx_flags |= MLX_EVENTLOG_BUSY;
 1215             
 1216             /* drain new eventlog entries */
 1217             mlx_periodic_eventlog_poll(sc);
 1218         }
 1219         break;
 1220     }
 1221     case MLX_CMD_ENQSYSDRIVE:
 1222     {
 1223         struct mlx_enq_sys_drive        *mes = (struct mlx_enq_sys_drive *)mc->mc_data;
 1224         struct mlx_sysdrive             *dr;
 1225         int                             i;
 1226         
 1227         for (i = 0, dr = &sc->mlx_sysdrive[0]; 
 1228              (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff); 
 1229              i++) {
 1230 
 1231             /* has state been changed by controller? */
 1232             if (dr->ms_state != mes[i].sd_state) {
 1233                 switch(mes[i].sd_state) {
 1234                 case MLX_SYSD_OFFLINE:
 1235                     device_printf(dr->ms_disk, "drive offline\n");
 1236                     break;
 1237                 case MLX_SYSD_ONLINE:
 1238                     device_printf(dr->ms_disk, "drive online\n");
 1239                     break;
 1240                 case MLX_SYSD_CRITICAL:
 1241                     device_printf(dr->ms_disk, "drive critical\n");
 1242                     break;
 1243                 }
 1244                 /* save new state */
 1245                 dr->ms_state = mes[i].sd_state;
 1246             }
 1247         }
 1248         break;
 1249     }
 1250     default:
 1251         device_printf(sc->mlx_dev, "%s: unknown command 0x%x", __func__, mc->mc_mailbox[0]);
 1252         break;
 1253     }
 1254 
 1255  out:
 1256     free(mc->mc_data, M_DEVBUF);
 1257     mlx_releasecmd(mc);
 1258 }
 1259 
 1260 static void
 1261 mlx_eventlog_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
 1262 {
 1263     struct mlx_command *mc;
 1264 
 1265     mc = (struct mlx_command *)arg;
 1266     mlx_setup_dmamap(mc, segs, nsegments, error);
 1267 
 1268     /* build the command to get one entry */
 1269     mlx_make_type3(mc, MLX_CMD_LOGOP, MLX_LOGOP_GET, 1,
 1270                    mc->mc_sc->mlx_lastevent, 0, 0, mc->mc_dataphys, 0);
 1271     mc->mc_complete = mlx_periodic_eventlog_respond;
 1272     mc->mc_private = mc;
 1273 
 1274     /* start the command */
 1275     if (mlx_start(mc) != 0) {
 1276         mlx_releasecmd(mc);
 1277         free(mc->mc_data, M_DEVBUF);
 1278         mc->mc_data = NULL;
 1279     }
 1280     
 1281 }
 1282 
 1283 /********************************************************************************
 1284  * Instigate a poll for one event log message on (sc).
 1285  * We only poll for one message at a time, to keep our command usage down.
 1286  */
 1287 static void
 1288 mlx_periodic_eventlog_poll(struct mlx_softc *sc)
 1289 {
 1290     struct mlx_command  *mc;
 1291     void                *result = NULL;
 1292     int                 error = 0;
 1293 
 1294     debug_called(1);
 1295     MLX_IO_ASSERT_LOCKED(sc);
 1296 
 1297     /* get ourselves a command buffer */
 1298     error = 1;
 1299     if ((mc = mlx_alloccmd(sc)) == NULL)
 1300         goto out;
 1301 
 1302     /* allocate the response structure */
 1303     if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF,
 1304                          M_NOWAIT)) == NULL)
 1305         goto out;
 1306 
 1307     /* get a command slot */
 1308     if (mlx_getslot(mc))
 1309         goto out;
 1310 
 1311     /* map the command so the controller can see it */
 1312     mc->mc_data = result;
 1313     mc->mc_length = /*sizeof(struct mlx_eventlog_entry)*/1024;
 1314     error = bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data,
 1315                             mc->mc_length, mlx_eventlog_cb, mc, BUS_DMA_NOWAIT);
 1316 
 1317  out:
 1318     if (error != 0) {
 1319         if (mc != NULL)
 1320             mlx_releasecmd(mc);
 1321         if ((result != NULL) && (mc->mc_data != NULL))
 1322             free(result, M_DEVBUF);
 1323     }
 1324 }
 1325 
 1326 /********************************************************************************
 1327  * Handle the result of polling for a log message, generate diagnostic output.
 1328  * If this wasn't the last message waiting for us, we'll go collect another.
 1329  */
 1330 static char *mlx_sense_messages[] = {
 1331     "because write recovery failed",
 1332     "because of SCSI bus reset failure",
 1333     "because of double check condition",
 1334     "because it was removed",
 1335     "because of gross error on SCSI chip",
 1336     "because of bad tag returned from drive",
 1337     "because of timeout on SCSI command",
 1338     "because of reset SCSI command issued from system",
 1339     "because busy or parity error count exceeded limit",
 1340     "because of 'kill drive' command from system",
 1341     "because of selection timeout",
 1342     "due to SCSI phase sequence error",
 1343     "due to unknown status"
 1344 };
 1345 
 1346 static void
 1347 mlx_periodic_eventlog_respond(struct mlx_command *mc)
 1348 {
 1349     struct mlx_softc            *sc = mc->mc_sc;
 1350     struct mlx_eventlog_entry   *el = (struct mlx_eventlog_entry *)mc->mc_data;
 1351     char                        *reason;
 1352 
 1353     debug_called(1);
 1354     MLX_IO_ASSERT_LOCKED(sc);
 1355 
 1356     sc->mlx_lastevent++;                /* next message... */
 1357     if (mc->mc_status == 0) {
 1358 
 1359         /* handle event log message */
 1360         switch(el->el_type) {
 1361             /*
 1362              * This is the only sort of message we understand at the moment.
 1363              * The tests here are probably incomplete.
 1364              */
 1365         case MLX_LOGMSG_SENSE:  /* sense data */
 1366             /* Mylex vendor-specific message indicating a drive was killed? */
 1367             if ((el->el_sensekey == 9) &&
 1368                 (el->el_asc == 0x80)) {
 1369                 if (el->el_asq < nitems(mlx_sense_messages)) {
 1370                     reason = mlx_sense_messages[el->el_asq];
 1371                 } else {
 1372                     reason = "for unknown reason";
 1373                 }
 1374                 device_printf(sc->mlx_dev, "physical drive %d:%d killed %s\n",
 1375                               el->el_channel, el->el_target, reason);
 1376             }
 1377             /* SCSI drive was reset? */
 1378             if ((el->el_sensekey == 6) && (el->el_asc == 0x29)) {
 1379                 device_printf(sc->mlx_dev, "physical drive %d:%d reset\n", 
 1380                               el->el_channel, el->el_target);
 1381             }
 1382             /* SCSI drive error? */
 1383             if (!((el->el_sensekey == 0) ||
 1384                   ((el->el_sensekey == 2) &&
 1385                    (el->el_asc == 0x04) &&
 1386                    ((el->el_asq == 0x01) ||
 1387                     (el->el_asq == 0x02))))) {
 1388                 device_printf(sc->mlx_dev, "physical drive %d:%d error log: sense = %d asc = %x asq = %x\n",
 1389                               el->el_channel, el->el_target, el->el_sensekey, el->el_asc, el->el_asq);
 1390                 device_printf(sc->mlx_dev, "  info %4D csi %4D\n", el->el_information, ":", el->el_csi, ":");
 1391             }
 1392             break;
 1393             
 1394         default:
 1395             device_printf(sc->mlx_dev, "unknown log message type 0x%x\n", el->el_type);
 1396             break;
 1397         }
 1398     } else {
 1399         device_printf(sc->mlx_dev, "error reading message log - %s\n", mlx_diagnose_command(mc));
 1400         /* give up on all the outstanding messages, as we may have come unsynched */
 1401         sc->mlx_lastevent = sc->mlx_currevent;
 1402     }
 1403         
 1404     /* dispose of command and data */
 1405     free(mc->mc_data, M_DEVBUF);
 1406     mlx_releasecmd(mc);
 1407 
 1408     /* is there another message to obtain? */
 1409     if (sc->mlx_lastevent != sc->mlx_currevent) {
 1410         mlx_periodic_eventlog_poll(sc);
 1411     } else {
 1412         /* clear log-busy status */
 1413         sc->mlx_flags &= ~MLX_EVENTLOG_BUSY;
 1414     }
 1415 }
 1416 
 1417 /********************************************************************************
 1418  * Handle check/rebuild operations in progress.
 1419  */
 1420 static void
 1421 mlx_periodic_rebuild(struct mlx_command *mc)
 1422 {
 1423     struct mlx_softc            *sc = mc->mc_sc;
 1424     struct mlx_rebuild_status   *mr = (struct mlx_rebuild_status *)mc->mc_data;
 1425 
 1426     MLX_IO_ASSERT_LOCKED(sc);
 1427     switch(mc->mc_status) {
 1428     case 0:                             /* operation running, update stats */
 1429         sc->mlx_rebuildstat = *mr;
 1430 
 1431         /* spontaneous rebuild/check? */
 1432         if (sc->mlx_background == 0) {
 1433             sc->mlx_background = MLX_BACKGROUND_SPONTANEOUS;
 1434             device_printf(sc->mlx_dev, "background check/rebuild operation started\n");
 1435         }
 1436         break;
 1437 
 1438     case 0x0105:                        /* nothing running, finalise stats and report */
 1439         switch(sc->mlx_background) {
 1440         case MLX_BACKGROUND_CHECK:
 1441             device_printf(sc->mlx_dev, "consistency check completed\n");        /* XXX print drive? */
 1442             break;
 1443         case MLX_BACKGROUND_REBUILD:
 1444             device_printf(sc->mlx_dev, "drive rebuild completed\n");    /* XXX print channel/target? */
 1445             break;
 1446         case MLX_BACKGROUND_SPONTANEOUS:
 1447         default:
 1448             /* if we have previously been non-idle, report the transition */
 1449             if (sc->mlx_rebuildstat.rs_code != MLX_REBUILDSTAT_IDLE) {
 1450                 device_printf(sc->mlx_dev, "background check/rebuild operation completed\n");
 1451             }
 1452         }
 1453         sc->mlx_background = 0;
 1454         sc->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
 1455         break;
 1456     }
 1457     free(mc->mc_data, M_DEVBUF);
 1458     mlx_releasecmd(mc);
 1459 }
 1460 
 1461 /********************************************************************************
 1462  ********************************************************************************
 1463                                                                     Channel Pause
 1464  ********************************************************************************
 1465  ********************************************************************************/
 1466 
 1467 /********************************************************************************
 1468  * It's time to perform a channel pause action for (sc), either start or stop
 1469  * the pause.
 1470  */
 1471 static void
 1472 mlx_pause_action(struct mlx_softc *sc)
 1473 {
 1474     struct mlx_command  *mc;
 1475     int                 failsafe, i, command;
 1476 
 1477     MLX_IO_ASSERT_LOCKED(sc);
 1478 
 1479     /* What are we doing here? */
 1480     if (sc->mlx_pause.mp_when == 0) {
 1481         command = MLX_CMD_STARTCHANNEL;
 1482         failsafe = 0;
 1483 
 1484     } else {
 1485         command = MLX_CMD_STOPCHANNEL;
 1486 
 1487         /* 
 1488          * Channels will always start again after the failsafe period, 
 1489          * which is specified in multiples of 30 seconds.
 1490          * This constrains us to a maximum pause of 450 seconds.
 1491          */
 1492         failsafe = ((sc->mlx_pause.mp_howlong - time_second) + 5) / 30;
 1493         if (failsafe > 0xf) {
 1494             failsafe = 0xf;
 1495             sc->mlx_pause.mp_howlong = time_second + (0xf * 30) - 5;
 1496         }
 1497     }
 1498 
 1499     /* build commands for every channel requested */
 1500     for (i = 0; i < sc->mlx_enq2->me_actual_channels; i++) {
 1501         if ((1 << i) & sc->mlx_pause.mp_which) {
 1502 
 1503             /* get ourselves a command buffer */
 1504             if ((mc = mlx_alloccmd(sc)) == NULL)
 1505                 goto fail;
 1506             /* get a command slot */
 1507             mc->mc_flags |= MLX_CMD_PRIORITY;
 1508             if (mlx_getslot(mc))
 1509                 goto fail;
 1510 
 1511             /* build the command */
 1512             mlx_make_type2(mc, command, (failsafe << 4) | i, 0, 0, 0, 0, 0, 0, 0);
 1513             mc->mc_complete = mlx_pause_done;
 1514             mc->mc_private = sc;                /* XXX not needed */
 1515             if (mlx_start(mc))
 1516                 goto fail;
 1517             /* command submitted OK */
 1518             return;
 1519     
 1520         fail:
 1521             device_printf(sc->mlx_dev, "%s failed for channel %d\n", 
 1522                           command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", i);
 1523             if (mc != NULL)
 1524                 mlx_releasecmd(mc);
 1525         }
 1526     }
 1527 }
 1528 
 1529 static void
 1530 mlx_pause_done(struct mlx_command *mc)
 1531 {
 1532     struct mlx_softc    *sc = mc->mc_sc;
 1533     int                 command = mc->mc_mailbox[0];
 1534     int                 channel = mc->mc_mailbox[2] & 0xf;
 1535 
 1536     MLX_IO_ASSERT_LOCKED(sc);
 1537     if (mc->mc_status != 0) {
 1538         device_printf(sc->mlx_dev, "%s command failed - %s\n", 
 1539                       command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", mlx_diagnose_command(mc));
 1540     } else if (command == MLX_CMD_STOPCHANNEL) {
 1541         device_printf(sc->mlx_dev, "channel %d pausing for %ld seconds\n", 
 1542                       channel, (long)(sc->mlx_pause.mp_howlong - time_second));
 1543     } else {
 1544         device_printf(sc->mlx_dev, "channel %d resuming\n", channel);
 1545     }
 1546     mlx_releasecmd(mc);
 1547 }
 1548 
 1549 /********************************************************************************
 1550  ********************************************************************************
 1551                                                                Command Submission
 1552  ********************************************************************************
 1553  ********************************************************************************/
 1554 
 1555 static void
 1556 mlx_enquire_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
 1557 {
 1558     struct mlx_softc *sc;
 1559     struct mlx_command *mc;
 1560 
 1561     mc = (struct mlx_command *)arg;
 1562     if (error)
 1563         return;
 1564 
 1565     mlx_setup_dmamap(mc, segs, nsegments, error);
 1566 
 1567     /* build an enquiry command */
 1568     sc = mc->mc_sc;
 1569     mlx_make_type2(mc, mc->mc_command, 0, 0, 0, 0, 0, 0, mc->mc_dataphys, 0);
 1570 
 1571     /* do we want a completion callback? */
 1572     if (mc->mc_complete != NULL) {
 1573         if ((error = mlx_start(mc)) != 0)
 1574             return;
 1575     } else {
 1576         /* run the command in either polled or wait mode */
 1577         if ((sc->mlx_state & MLX_STATE_INTEN) ? mlx_wait_command(mc) :
 1578                                                 mlx_poll_command(mc))
 1579             return;
 1580     
 1581         /* command completed OK? */
 1582         if (mc->mc_status != 0) {
 1583             device_printf(sc->mlx_dev, "ENQUIRY failed - %s\n",
 1584                           mlx_diagnose_command(mc));
 1585             return;
 1586         }
 1587     }
 1588 }
 1589 
 1590 /********************************************************************************
 1591  * Perform an Enquiry command using a type-3 command buffer and a return a single
 1592  * linear result buffer.  If the completion function is specified, it will
 1593  * be called with the completed command (and the result response will not be
 1594  * valid until that point).  Otherwise, the command will either be busy-waited
 1595  * for (interrupts not enabled), or slept for.
 1596  */
 1597 static void *
 1598 mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, void (* complete)(struct mlx_command *mc))
 1599 {
 1600     struct mlx_command  *mc;
 1601     void                *result;
 1602     int                 error;
 1603 
 1604     debug_called(1);
 1605     MLX_IO_ASSERT_LOCKED(sc);
 1606 
 1607     /* get ourselves a command buffer */
 1608     error = 1;
 1609     result = NULL;
 1610     if ((mc = mlx_alloccmd(sc)) == NULL)
 1611         goto out;
 1612     /* allocate the response structure */
 1613     if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL)
 1614         goto out;
 1615     /* get a command slot */
 1616     mc->mc_flags |= MLX_CMD_PRIORITY | MLX_CMD_DATAOUT;
 1617     if (mlx_getslot(mc))
 1618         goto out;
 1619 
 1620     /* map the command so the controller can see it */
 1621     mc->mc_data = result;
 1622     mc->mc_length = bufsize;
 1623     mc->mc_command = command;
 1624 
 1625     if (complete != NULL) {
 1626         mc->mc_complete = complete;
 1627         mc->mc_private = mc;
 1628     }
 1629 
 1630     error = bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data,
 1631                             mc->mc_length, mlx_enquire_cb, mc, BUS_DMA_NOWAIT);
 1632 
 1633  out:
 1634     /* we got a command, but nobody else will free it */
 1635     if ((mc != NULL) && (mc->mc_complete == NULL))
 1636         mlx_releasecmd(mc);
 1637     /* we got an error, and we allocated a result */
 1638     if ((error != 0) && (result != NULL)) {
 1639         free(result, M_DEVBUF);
 1640         result = NULL;
 1641     }
 1642     return(result);
 1643 }
 1644 
 1645 
 1646 /********************************************************************************
 1647  * Perform a Flush command on the nominated controller.
 1648  *
 1649  * May be called with interrupts enabled or disabled; will not return until
 1650  * the flush operation completes or fails.
 1651  */
 1652 static int
 1653 mlx_flush(struct mlx_softc *sc)
 1654 {
 1655     struct mlx_command  *mc;
 1656     int                 error;
 1657 
 1658     debug_called(1);
 1659     MLX_IO_ASSERT_LOCKED(sc);
 1660 
 1661     /* get ourselves a command buffer */
 1662     error = 1;
 1663     if ((mc = mlx_alloccmd(sc)) == NULL)
 1664         goto out;
 1665     /* get a command slot */
 1666     if (mlx_getslot(mc))
 1667         goto out;
 1668 
 1669     /* build a flush command */
 1670     mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0);
 1671 
 1672     /* can't assume that interrupts are going to work here, so play it safe */
 1673     if (mlx_poll_command(mc))
 1674         goto out;
 1675     
 1676     /* command completed OK? */
 1677     if (mc->mc_status != 0) {
 1678         device_printf(sc->mlx_dev, "FLUSH failed - %s\n", mlx_diagnose_command(mc));
 1679         goto out;
 1680     }
 1681     
 1682     error = 0;                  /* success */
 1683  out:
 1684     if (mc != NULL)
 1685         mlx_releasecmd(mc);
 1686     return(error);
 1687 }
 1688 
 1689 /********************************************************************************
 1690  * Start a background consistency check on (drive).
 1691  *
 1692  * May be called with interrupts enabled or disabled; will return as soon as the
 1693  * operation has started or been refused.
 1694  */
 1695 static int
 1696 mlx_check(struct mlx_softc *sc, int drive)
 1697 {
 1698     struct mlx_command  *mc;
 1699     int                 error;
 1700 
 1701     debug_called(1);
 1702     MLX_IO_ASSERT_LOCKED(sc);
 1703 
 1704     /* get ourselves a command buffer */
 1705     error = 0x10000;
 1706     if ((mc = mlx_alloccmd(sc)) == NULL)
 1707         goto out;
 1708     /* get a command slot */
 1709     if (mlx_getslot(mc))
 1710         goto out;
 1711 
 1712     /* build a checkasync command, set the "fix it" flag */
 1713     mlx_make_type2(mc, MLX_CMD_CHECKASYNC, 0, 0, 0, 0, 0, drive | 0x80, 0, 0);
 1714 
 1715     /* start the command and wait for it to be returned */
 1716     if (mlx_wait_command(mc))
 1717         goto out;
 1718     
 1719     /* command completed OK? */
 1720     if (mc->mc_status != 0) {   
 1721         device_printf(sc->mlx_dev, "CHECK ASYNC failed - %s\n", mlx_diagnose_command(mc));
 1722     } else {
 1723         device_printf(sc->mlx_sysdrive[drive].ms_disk, "consistency check started");
 1724     }
 1725     error = mc->mc_status;
 1726 
 1727  out:
 1728     if (mc != NULL)
 1729         mlx_releasecmd(mc);
 1730     return(error);
 1731 }
 1732 
 1733 /********************************************************************************
 1734  * Start a background rebuild of the physical drive at (channel),(target).
 1735  *
 1736  * May be called with interrupts enabled or disabled; will return as soon as the
 1737  * operation has started or been refused.
 1738  */
 1739 static int
 1740 mlx_rebuild(struct mlx_softc *sc, int channel, int target)
 1741 {
 1742     struct mlx_command  *mc;
 1743     int                 error;
 1744 
 1745     debug_called(1);
 1746     MLX_IO_ASSERT_LOCKED(sc);
 1747 
 1748     /* get ourselves a command buffer */
 1749     error = 0x10000;
 1750     if ((mc = mlx_alloccmd(sc)) == NULL)
 1751         goto out;
 1752     /* get a command slot */
 1753     if (mlx_getslot(mc))
 1754         goto out;
 1755 
 1756     /* build a checkasync command, set the "fix it" flag */
 1757     mlx_make_type2(mc, MLX_CMD_REBUILDASYNC, channel, target, 0, 0, 0, 0, 0, 0);
 1758 
 1759     /* start the command and wait for it to be returned */
 1760     if (mlx_wait_command(mc))
 1761         goto out;
 1762     
 1763     /* command completed OK? */
 1764     if (mc->mc_status != 0) {   
 1765         device_printf(sc->mlx_dev, "REBUILD ASYNC failed - %s\n", mlx_diagnose_command(mc));
 1766     } else {
 1767         device_printf(sc->mlx_dev, "drive rebuild started for %d:%d\n", channel, target);
 1768     }
 1769     error = mc->mc_status;
 1770 
 1771  out:
 1772     if (mc != NULL)
 1773         mlx_releasecmd(mc);
 1774     return(error);
 1775 }
 1776 
 1777 /********************************************************************************
 1778  * Run the command (mc) and return when it completes.
 1779  *
 1780  * Interrupts need to be enabled; returns nonzero on error.
 1781  */
 1782 static int
 1783 mlx_wait_command(struct mlx_command *mc)
 1784 {
 1785     struct mlx_softc    *sc = mc->mc_sc;
 1786     int                 error, count;
 1787 
 1788     debug_called(1);
 1789     MLX_IO_ASSERT_LOCKED(sc);
 1790 
 1791     mc->mc_complete = NULL;
 1792     mc->mc_private = mc;                /* wake us when you're done */
 1793     if ((error = mlx_start(mc)) != 0)
 1794         return(error);
 1795 
 1796     count = 0;
 1797     /* XXX better timeout? */
 1798     while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 30)) {
 1799         mtx_sleep(mc->mc_private, &sc->mlx_io_lock, PRIBIO | PCATCH, "mlxwcmd", hz);
 1800     }
 1801 
 1802     if (mc->mc_status != 0) {
 1803         device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc));
 1804         return(EIO);
 1805     }
 1806     return(0);
 1807 }
 1808 
 1809 
 1810 /********************************************************************************
 1811  * Start the command (mc) and busy-wait for it to complete.
 1812  *
 1813  * Should only be used when interrupts can't be relied upon. Returns 0 on 
 1814  * success, nonzero on error.
 1815  * Successfully completed commands are dequeued.
 1816  */
 1817 static int
 1818 mlx_poll_command(struct mlx_command *mc)
 1819 {
 1820     struct mlx_softc    *sc = mc->mc_sc;
 1821     int                 error, count;
 1822 
 1823     debug_called(1);
 1824     MLX_IO_ASSERT_LOCKED(sc);
 1825 
 1826     mc->mc_complete = NULL;
 1827     mc->mc_private = NULL;      /* we will poll for it */
 1828     if ((error = mlx_start(mc)) != 0)
 1829         return(error);
 1830     
 1831     count = 0;
 1832     do {
 1833         /* poll for completion */
 1834         mlx_done(mc->mc_sc, 1);
 1835         
 1836     } while ((mc->mc_status == MLX_STATUS_BUSY) && (count++ < 15000000));
 1837     if (mc->mc_status != MLX_STATUS_BUSY) {
 1838         TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
 1839         return(0);
 1840     }
 1841     device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc));
 1842     return(EIO);
 1843 }
 1844 
 1845 void
 1846 mlx_startio_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
 1847 {
 1848     struct mlx_command  *mc;
 1849     struct mlxd_softc   *mlxd;
 1850     struct mlx_softc    *sc;
 1851     struct bio          *bp;
 1852     int                 blkcount;
 1853     int                 driveno;
 1854     int                 cmd;
 1855 
 1856     mc = (struct mlx_command *)arg;
 1857     mlx_setup_dmamap(mc, segs, nsegments, error);
 1858 
 1859     sc = mc->mc_sc;
 1860     bp = mc->mc_private;
 1861 
 1862     if (bp->bio_cmd == BIO_READ) {
 1863         mc->mc_flags |= MLX_CMD_DATAIN;
 1864         cmd = MLX_CMD_READSG;
 1865     } else {
 1866         mc->mc_flags |= MLX_CMD_DATAOUT;
 1867         cmd = MLX_CMD_WRITESG;
 1868     }
 1869 
 1870     /* build a suitable I/O command (assumes 512-byte rounded transfers) */
 1871     mlxd = bp->bio_disk->d_drv1;
 1872     driveno = mlxd->mlxd_drive - sc->mlx_sysdrive;
 1873     blkcount = howmany(bp->bio_bcount, MLX_BLKSIZE);
 1874 
 1875     if ((bp->bio_pblkno + blkcount) > sc->mlx_sysdrive[driveno].ms_size)
 1876         device_printf(sc->mlx_dev,
 1877                       "I/O beyond end of unit (%lld,%d > %lu)\n", 
 1878                       (long long)bp->bio_pblkno, blkcount,
 1879                       (u_long)sc->mlx_sysdrive[driveno].ms_size);
 1880 
 1881     /*
 1882      * Build the I/O command.  Note that the SG list type bits are set to zero,
 1883      * denoting the format of SG list that we are using.
 1884      */
 1885     if (sc->mlx_iftype == MLX_IFTYPE_2) {
 1886         mlx_make_type1(mc, (cmd == MLX_CMD_WRITESG) ? MLX_CMD_WRITESG_OLD :
 1887                                                       MLX_CMD_READSG_OLD,
 1888                        blkcount & 0xff,         /* xfer length low byte */
 1889                        bp->bio_pblkno,          /* physical block number */
 1890                        driveno,                 /* target drive number */
 1891                        mc->mc_sgphys,           /* location of SG list */
 1892                        mc->mc_nsgent & 0x3f);   /* size of SG list */
 1893         } else {
 1894         mlx_make_type5(mc, cmd, 
 1895                        blkcount & 0xff,         /* xfer length low byte */
 1896                        (driveno << 3) | ((blkcount >> 8) & 0x07),
 1897                                                 /* target+length high 3 bits */
 1898                        bp->bio_pblkno,          /* physical block number */
 1899                        mc->mc_sgphys,           /* location of SG list */
 1900                        mc->mc_nsgent & 0x3f);   /* size of SG list */
 1901     }
 1902 
 1903     /* try to give command to controller */
 1904     if (mlx_start(mc) != 0) {
 1905         /* fail the command */
 1906         mc->mc_status = MLX_STATUS_WEDGED;
 1907         mlx_completeio(mc);
 1908     }
 1909 
 1910     sc->mlx_state &= ~MLX_STATE_QFROZEN;
 1911 }
 1912 
 1913 /********************************************************************************
 1914  * Pull as much work off the softc's work queue as possible and give it to the
 1915  * controller.  Leave a couple of slots free for emergencies.
 1916  */
 1917 static void
 1918 mlx_startio(struct mlx_softc *sc)
 1919 {
 1920     struct mlx_command  *mc;
 1921     struct bio          *bp;
 1922     int                 error;
 1923 
 1924     MLX_IO_ASSERT_LOCKED(sc);
 1925 
 1926     /* spin until something prevents us from doing any work */
 1927     for (;;) {
 1928         if (sc->mlx_state & MLX_STATE_QFROZEN)
 1929             break;
 1930 
 1931         /* see if there's work to be done */
 1932         if ((bp = bioq_first(&sc->mlx_bioq)) == NULL)
 1933             break;
 1934         /* get a command */
 1935         if ((mc = mlx_alloccmd(sc)) == NULL)
 1936             break;
 1937         /* get a slot for the command */
 1938         if (mlx_getslot(mc) != 0) {
 1939             mlx_releasecmd(mc);
 1940             break;
 1941         }
 1942         /* get the buf containing our work */
 1943         bioq_remove(&sc->mlx_bioq, bp);
 1944         sc->mlx_waitbufs--;
 1945         
 1946         /* connect the buf to the command */
 1947         mc->mc_complete = mlx_completeio;
 1948         mc->mc_private = bp;
 1949         mc->mc_data = bp->bio_data;
 1950         mc->mc_length = bp->bio_bcount;
 1951         
 1952         /* map the command so the controller can work with it */
 1953         error = bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data,
 1954                                 mc->mc_length, mlx_startio_cb, mc, 0);
 1955         if (error == EINPROGRESS) {
 1956             sc->mlx_state |= MLX_STATE_QFROZEN;
 1957             break;
 1958         }
 1959     }
 1960 }
 1961 
 1962 /********************************************************************************
 1963  * Handle completion of an I/O command.
 1964  */
 1965 static void
 1966 mlx_completeio(struct mlx_command *mc)
 1967 {
 1968     struct mlx_softc    *sc = mc->mc_sc;
 1969     struct bio          *bp = mc->mc_private;
 1970     struct mlxd_softc   *mlxd = bp->bio_disk->d_drv1;
 1971 
 1972     MLX_IO_ASSERT_LOCKED(sc);
 1973     if (mc->mc_status != MLX_STATUS_OK) {       /* could be more verbose here? */
 1974         bp->bio_error = EIO;
 1975         bp->bio_flags |= BIO_ERROR;
 1976 
 1977         switch(mc->mc_status) {
 1978         case MLX_STATUS_RDWROFFLINE:            /* system drive has gone offline */
 1979             device_printf(mlxd->mlxd_dev, "drive offline\n");
 1980             /* should signal this with a return code */
 1981             mlxd->mlxd_drive->ms_state = MLX_SYSD_OFFLINE;
 1982             break;
 1983 
 1984         default:                                /* other I/O error */
 1985             device_printf(sc->mlx_dev, "I/O error - %s\n", mlx_diagnose_command(mc));
 1986 #if 0
 1987             device_printf(sc->mlx_dev, "  b_bcount %ld  blkcount %ld  b_pblkno %d\n", 
 1988                           bp->bio_bcount, bp->bio_bcount / MLX_BLKSIZE, bp->bio_pblkno);
 1989             device_printf(sc->mlx_dev, "  %13D\n", mc->mc_mailbox, " ");
 1990 #endif
 1991             break;
 1992         }
 1993     }
 1994     mlx_releasecmd(mc);
 1995     mlxd_intr(bp);
 1996 }
 1997 
 1998 void
 1999 mlx_user_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
 2000 {
 2001     struct mlx_usercommand *mu;
 2002     struct mlx_command *mc;
 2003     struct mlx_dcdb     *dcdb;
 2004 
 2005     mc = (struct mlx_command *)arg;
 2006     if (error)
 2007         return;
 2008 
 2009     mlx_setup_dmamap(mc, segs, nsegments, error);
 2010 
 2011     mu = (struct mlx_usercommand *)mc->mc_private;
 2012     dcdb = NULL;
 2013 
 2014     /* 
 2015      * If this is a passthrough SCSI command, the DCDB is packed at the 
 2016      * beginning of the data area.  Fix up the DCDB to point to the correct
 2017      * physical address and override any bufptr supplied by the caller since
 2018      * we know what it's meant to be.
 2019      */
 2020     if (mc->mc_mailbox[0] == MLX_CMD_DIRECT_CDB) {
 2021         dcdb = (struct mlx_dcdb *)mc->mc_data;
 2022         dcdb->dcdb_physaddr = mc->mc_dataphys + sizeof(*dcdb);
 2023         mu->mu_bufptr = 8;
 2024     }
 2025     
 2026     /* 
 2027      * If there's a data buffer, fix up the command's buffer pointer.
 2028      */
 2029     if (mu->mu_datasize > 0) {
 2030         mc->mc_mailbox[mu->mu_bufptr    ] =  mc->mc_dataphys        & 0xff;
 2031         mc->mc_mailbox[mu->mu_bufptr + 1] = (mc->mc_dataphys >> 8)  & 0xff;
 2032         mc->mc_mailbox[mu->mu_bufptr + 2] = (mc->mc_dataphys >> 16) & 0xff;
 2033         mc->mc_mailbox[mu->mu_bufptr + 3] = (mc->mc_dataphys >> 24) & 0xff;
 2034     }
 2035     debug(0, "command fixup");
 2036 
 2037     /* submit the command and wait */
 2038     if (mlx_wait_command(mc) != 0)
 2039         return;
 2040 
 2041 }
 2042 
 2043 /********************************************************************************
 2044  * Take a command from user-space and try to run it.
 2045  *
 2046  * XXX Note that this can't perform very much in the way of error checking, and
 2047  *     as such, applications _must_ be considered trustworthy.
 2048  * XXX Commands using S/G for data are not supported.
 2049  */
 2050 static int
 2051 mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu)
 2052 {
 2053     struct mlx_command  *mc;
 2054     void                *kbuf;
 2055     int                 error;
 2056     
 2057     debug_called(0);
 2058     
 2059     kbuf = NULL;
 2060     mc = NULL;
 2061     error = ENOMEM;
 2062 
 2063     /* get ourselves a command and copy in from user space */
 2064     MLX_IO_LOCK(sc);
 2065     if ((mc = mlx_alloccmd(sc)) == NULL) {
 2066         MLX_IO_UNLOCK(sc);
 2067         return(error);
 2068     }
 2069     bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox));
 2070     debug(0, "got command buffer");
 2071 
 2072     /*
 2073      * if we need a buffer for data transfer, allocate one and copy in its
 2074      * initial contents
 2075      */
 2076     if (mu->mu_datasize > 0) {
 2077         if (mu->mu_datasize > MLX_MAXPHYS) {
 2078             error = EINVAL;
 2079             goto out;
 2080         }
 2081         MLX_IO_UNLOCK(sc);
 2082         if (((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL) ||
 2083             (error = copyin(mu->mu_buf, kbuf, mu->mu_datasize))) {
 2084             MLX_IO_LOCK(sc);
 2085             goto out;
 2086         }
 2087         MLX_IO_LOCK(sc);
 2088         debug(0, "got kernel buffer");
 2089     }
 2090 
 2091     /* get a command slot */
 2092     if (mlx_getslot(mc))
 2093         goto out;
 2094     debug(0, "got a slot");
 2095 
 2096     if (mu->mu_datasize > 0) {
 2097 
 2098         /* range check the pointer to physical buffer address */
 2099         if ((mu->mu_bufptr < 0) || (mu->mu_bufptr > (sizeof(mu->mu_command) -
 2100                                                      sizeof(u_int32_t)))) {
 2101             error = EINVAL;
 2102             goto out;
 2103         }
 2104     }
 2105 
 2106     /* map the command so the controller can see it */
 2107     mc->mc_data = kbuf;
 2108     mc->mc_length = mu->mu_datasize;
 2109     mc->mc_private = mu;
 2110     error = bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data,
 2111                             mc->mc_length, mlx_user_cb, mc, BUS_DMA_NOWAIT);
 2112     if (error)
 2113         goto out;
 2114 
 2115     /* copy out status and data */
 2116     mu->mu_status = mc->mc_status;
 2117     if (mu->mu_datasize > 0) {
 2118         MLX_IO_UNLOCK(sc);
 2119         error = copyout(kbuf, mu->mu_buf, mu->mu_datasize);
 2120         MLX_IO_LOCK(sc);
 2121     }
 2122 
 2123  out:
 2124     mlx_releasecmd(mc);
 2125     MLX_IO_UNLOCK(sc);
 2126     if (kbuf != NULL)
 2127         free(kbuf, M_DEVBUF);
 2128     return(error);
 2129 }
 2130 
 2131 /********************************************************************************
 2132  ********************************************************************************
 2133                                                         Command I/O to Controller
 2134  ********************************************************************************
 2135  ********************************************************************************/
 2136 
 2137 /********************************************************************************
 2138  * Find a free command slot for (mc).
 2139  *
 2140  * Don't hand out a slot to a normal-priority command unless there are at least
 2141  * 4 slots free for priority commands.
 2142  */
 2143 static int
 2144 mlx_getslot(struct mlx_command *mc)
 2145 {
 2146     struct mlx_softc    *sc = mc->mc_sc;
 2147     int                 slot, limit;
 2148 
 2149     debug_called(1);
 2150 
 2151     MLX_IO_ASSERT_LOCKED(sc);
 2152 
 2153     /* 
 2154      * Enforce slot-usage limit, if we have the required information.
 2155      */
 2156     if (sc->mlx_enq2 != NULL) {
 2157         limit = sc->mlx_enq2->me_max_commands;
 2158     } else {
 2159         limit = 2;
 2160     }
 2161     if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ? limit : limit - 4))
 2162         return(EBUSY);
 2163 
 2164     /* 
 2165      * Allocate an outstanding command slot 
 2166      *
 2167      * XXX linear search is slow
 2168      */
 2169     for (slot = 0; slot < limit; slot++) {
 2170         debug(2, "try slot %d", slot);
 2171         if (sc->mlx_busycmd[slot] == NULL)
 2172             break;
 2173     }
 2174     if (slot < limit) {
 2175         sc->mlx_busycmd[slot] = mc;
 2176         sc->mlx_busycmds++;
 2177     }
 2178 
 2179     /* out of slots? */
 2180     if (slot >= limit)
 2181         return(EBUSY);
 2182 
 2183     debug(2, "got slot %d", slot);
 2184     mc->mc_slot = slot;
 2185     return(0);
 2186 }
 2187 
 2188 /********************************************************************************
 2189  * Map/unmap (mc)'s data in the controller's addressable space.
 2190  */
 2191 static void
 2192 mlx_setup_dmamap(struct mlx_command *mc, bus_dma_segment_t *segs, int nsegments,
 2193                  int error)
 2194 {
 2195     struct mlx_softc    *sc = mc->mc_sc;
 2196     struct mlx_sgentry  *sg;
 2197     int                 i;
 2198 
 2199     debug_called(1);
 2200 
 2201     /* XXX should be unnecessary */
 2202     if (sc->mlx_enq2 && (nsegments > sc->mlx_enq2->me_max_sg))
 2203         panic("MLX: too many s/g segments (%d, max %d)", nsegments,
 2204               sc->mlx_enq2->me_max_sg);
 2205 
 2206     /* get base address of s/g table */
 2207     sg = sc->mlx_sgtable + (mc->mc_slot * MLX_NSEG);
 2208 
 2209     /* save s/g table information in command */
 2210     mc->mc_nsgent = nsegments;
 2211     mc->mc_sgphys = sc->mlx_sgbusaddr +
 2212                    (mc->mc_slot * MLX_NSEG * sizeof(struct mlx_sgentry));
 2213     mc->mc_dataphys = segs[0].ds_addr;
 2214 
 2215     /* populate s/g table */
 2216     for (i = 0; i < nsegments; i++, sg++) {
 2217         sg->sg_addr = segs[i].ds_addr;
 2218         sg->sg_count = segs[i].ds_len;
 2219     }
 2220 
 2221     /* Make sure the buffers are visible on the bus. */
 2222     if (mc->mc_flags & MLX_CMD_DATAIN)
 2223         bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap,
 2224                         BUS_DMASYNC_PREREAD);
 2225     if (mc->mc_flags & MLX_CMD_DATAOUT)
 2226         bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap,
 2227                         BUS_DMASYNC_PREWRITE);
 2228 }
 2229 
 2230 static void
 2231 mlx_unmapcmd(struct mlx_command *mc)
 2232 {
 2233     struct mlx_softc    *sc = mc->mc_sc;
 2234 
 2235     debug_called(1);
 2236 
 2237     /* if the command involved data at all */
 2238     if (mc->mc_data != NULL) {
 2239         
 2240         if (mc->mc_flags & MLX_CMD_DATAIN)
 2241             bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTREAD);
 2242         if (mc->mc_flags & MLX_CMD_DATAOUT)
 2243             bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTWRITE);
 2244 
 2245         bus_dmamap_unload(sc->mlx_buffer_dmat, mc->mc_dmamap); 
 2246     }
 2247 }
 2248 
 2249 /********************************************************************************
 2250  * Try to deliver (mc) to the controller.
 2251  *
 2252  * Can be called at any interrupt level, with or without interrupts enabled.
 2253  */
 2254 static int
 2255 mlx_start(struct mlx_command *mc)
 2256 {
 2257     struct mlx_softc    *sc = mc->mc_sc;
 2258     int                 i;
 2259 
 2260     debug_called(1);
 2261 
 2262     /* save the slot number as ident so we can handle this command when complete */
 2263     mc->mc_mailbox[0x1] = mc->mc_slot;
 2264 
 2265     /* mark the command as currently being processed */
 2266     mc->mc_status = MLX_STATUS_BUSY;
 2267 
 2268     /* set a default 60-second timeout  XXX tunable?  XXX not currently used */
 2269     mc->mc_timeout = time_second + 60;
 2270 
 2271     /* spin waiting for the mailbox */
 2272     for (i = 100000; i > 0; i--) {
 2273         if (sc->mlx_tryqueue(sc, mc)) {
 2274             /* move command to work queue */
 2275             TAILQ_INSERT_TAIL(&sc->mlx_work, mc, mc_link);
 2276             return (0);
 2277         } else if (i > 1)
 2278             mlx_done(sc, 0);
 2279     }
 2280 
 2281     /* 
 2282      * We couldn't get the controller to take the command.  Revoke the slot
 2283      * that the command was given and return it with a bad status.
 2284      */
 2285     sc->mlx_busycmd[mc->mc_slot] = NULL;
 2286     device_printf(sc->mlx_dev, "controller wedged (not taking commands)\n");
 2287     mc->mc_status = MLX_STATUS_WEDGED;
 2288     mlx_complete(sc);
 2289     return(EIO);
 2290 }
 2291 
 2292 /********************************************************************************
 2293  * Poll the controller (sc) for completed commands.
 2294  * Update command status and free slots for reuse.  If any slots were freed,
 2295  * new commands may be posted.
 2296  *
 2297  * Returns nonzero if one or more commands were completed.
 2298  */
 2299 static int
 2300 mlx_done(struct mlx_softc *sc, int startio)
 2301 {
 2302     struct mlx_command  *mc;
 2303     int                 result;
 2304     u_int8_t            slot;
 2305     u_int16_t           status;
 2306     
 2307     debug_called(2);
 2308     MLX_IO_ASSERT_LOCKED(sc);
 2309 
 2310     result = 0;
 2311 
 2312     /* loop collecting completed commands */
 2313     for (;;) {
 2314         /* poll for a completed command's identifier and status */
 2315         if (sc->mlx_findcomplete(sc, &slot, &status)) {
 2316             result = 1;
 2317             mc = sc->mlx_busycmd[slot];                 /* find command */
 2318             if (mc != NULL) {                           /* paranoia */
 2319                 if (mc->mc_status == MLX_STATUS_BUSY) {
 2320                     mc->mc_status = status;             /* save status */
 2321 
 2322                     /* free slot for reuse */
 2323                     sc->mlx_busycmd[slot] = NULL;
 2324                     sc->mlx_busycmds--;
 2325                 } else {
 2326                     device_printf(sc->mlx_dev, "duplicate done event for slot %d\n", slot);
 2327                 }
 2328             } else {
 2329                 device_printf(sc->mlx_dev, "done event for nonbusy slot %d\n", slot);
 2330             }
 2331         } else {
 2332             break;
 2333         }
 2334     }
 2335 
 2336     /* if we've completed any commands, try posting some more */
 2337     if (result && startio)
 2338         mlx_startio(sc);
 2339 
 2340     /* handle completion and timeouts */
 2341     mlx_complete(sc);
 2342 
 2343     return(result);
 2344 }
 2345 
 2346 /********************************************************************************
 2347  * Perform post-completion processing for commands on (sc).
 2348  */
 2349 static void
 2350 mlx_complete(struct mlx_softc *sc) 
 2351 {
 2352     struct mlx_command  *mc, *nc;
 2353     
 2354     debug_called(2);
 2355     MLX_IO_ASSERT_LOCKED(sc);
 2356 
 2357     /* scan the list of busy/done commands */
 2358     mc = TAILQ_FIRST(&sc->mlx_work);
 2359     while (mc != NULL) {
 2360         nc = TAILQ_NEXT(mc, mc_link);
 2361 
 2362         /* Command has been completed in some fashion */
 2363         if (mc->mc_status != MLX_STATUS_BUSY) {
 2364         
 2365             /* unmap the command's data buffer */
 2366             mlx_unmapcmd(mc);
 2367             /*
 2368              * Does the command have a completion handler?
 2369              */
 2370             if (mc->mc_complete != NULL) {
 2371                 /* remove from list and give to handler */
 2372                 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
 2373                 mc->mc_complete(mc);
 2374 
 2375                 /* 
 2376                  * Is there a sleeper waiting on this command?
 2377                  */
 2378             } else if (mc->mc_private != NULL) {        /* sleeping caller wants to know about it */
 2379 
 2380                 /* remove from list and wake up sleeper */
 2381                 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
 2382                 wakeup_one(mc->mc_private);
 2383 
 2384                 /*
 2385                  * Leave the command for a caller that's polling for it.
 2386                  */
 2387             } else {
 2388             }
 2389         }
 2390         mc = nc;
 2391     }
 2392 }
 2393 
 2394 /********************************************************************************
 2395  ********************************************************************************
 2396                                                         Command Buffer Management
 2397  ********************************************************************************
 2398  ********************************************************************************/
 2399 
 2400 /********************************************************************************
 2401  * Get a new command buffer.
 2402  *
 2403  * This may return NULL in low-memory cases.
 2404  *
 2405  * Note that using malloc() is expensive (the command buffer is << 1 page) but
 2406  * necessary if we are to be a loadable module before the zone allocator is fixed.
 2407  *
 2408  * If possible, we recycle a command buffer that's been used before.
 2409  *
 2410  * XXX Note that command buffers are not cleaned out - it is the caller's 
 2411  *     responsibility to ensure that all required fields are filled in before
 2412  *     using a buffer.
 2413  */
 2414 static struct mlx_command *
 2415 mlx_alloccmd(struct mlx_softc *sc)
 2416 {
 2417     struct mlx_command  *mc;
 2418     int                 error;
 2419 
 2420     debug_called(1);
 2421 
 2422     MLX_IO_ASSERT_LOCKED(sc);
 2423     if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL)
 2424         TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
 2425 
 2426     /* allocate a new command buffer? */
 2427     if (mc == NULL) {
 2428         mc = (struct mlx_command *)malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT | M_ZERO);
 2429         if (mc != NULL) {
 2430             mc->mc_sc = sc;
 2431             error = bus_dmamap_create(sc->mlx_buffer_dmat, 0, &mc->mc_dmamap);
 2432             if (error) {
 2433                 free(mc, M_DEVBUF);
 2434                 return(NULL);
 2435             }
 2436         }
 2437     }
 2438     return(mc);
 2439 }
 2440 
 2441 /********************************************************************************
 2442  * Release a command buffer for recycling.
 2443  *
 2444  * XXX It might be a good idea to limit the number of commands we save for reuse
 2445  *     if it's shown that this list bloats out massively.
 2446  */
 2447 static void
 2448 mlx_releasecmd(struct mlx_command *mc)
 2449 {
 2450     
 2451     debug_called(1);
 2452 
 2453     MLX_IO_ASSERT_LOCKED(mc->mc_sc);
 2454     TAILQ_INSERT_HEAD(&mc->mc_sc->mlx_freecmds, mc, mc_link);
 2455 }
 2456 
 2457 /********************************************************************************
 2458  * Permanently discard a command buffer.
 2459  */
 2460 static void
 2461 mlx_freecmd(struct mlx_command *mc) 
 2462 {
 2463     struct mlx_softc    *sc = mc->mc_sc;
 2464     
 2465     debug_called(1);
 2466     bus_dmamap_destroy(sc->mlx_buffer_dmat, mc->mc_dmamap);
 2467     free(mc, M_DEVBUF);
 2468 }
 2469 
 2470 
 2471 /********************************************************************************
 2472  ********************************************************************************
 2473                                                 Type 3 interface accessor methods
 2474  ********************************************************************************
 2475  ********************************************************************************/
 2476 
 2477 /********************************************************************************
 2478  * Try to give (mc) to the controller.  Returns 1 if successful, 0 on failure
 2479  * (the controller is not ready to take a command).
 2480  */
 2481 static int
 2482 mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
 2483 {
 2484     int         i;
 2485     
 2486     debug_called(2);
 2487     MLX_IO_ASSERT_LOCKED(sc);
 2488 
 2489     /* ready for our command? */
 2490     if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_FULL)) {
 2491         /* copy mailbox data to window */
 2492         for (i = 0; i < 13; i++)
 2493             MLX_V3_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
 2494         
 2495         /* post command */
 2496         MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_FULL);
 2497         return(1);
 2498     }
 2499     return(0);
 2500 }
 2501 
 2502 /********************************************************************************
 2503  * See if a command has been completed, if so acknowledge its completion
 2504  * and recover the slot number and status code.
 2505  */
 2506 static int
 2507 mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
 2508 {
 2509 
 2510     debug_called(2);
 2511     MLX_IO_ASSERT_LOCKED(sc);
 2512 
 2513     /* status available? */
 2514     if (MLX_V3_GET_ODBR(sc) & MLX_V3_ODB_SAVAIL) {
 2515         *slot = MLX_V3_GET_STATUS_IDENT(sc);            /* get command identifier */
 2516         *status = MLX_V3_GET_STATUS(sc);                /* get status */
 2517 
 2518         /* acknowledge completion */
 2519         MLX_V3_PUT_ODBR(sc, MLX_V3_ODB_SAVAIL);
 2520         MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK);
 2521         return(1);
 2522     }
 2523     return(0);
 2524 }
 2525 
 2526 /********************************************************************************
 2527  * Enable/disable interrupts as requested. (No acknowledge required)
 2528  */
 2529 static void
 2530 mlx_v3_intaction(struct mlx_softc *sc, int action)
 2531 {
 2532     debug_called(1);
 2533     MLX_IO_ASSERT_LOCKED(sc);
 2534 
 2535     switch(action) {
 2536     case MLX_INTACTION_DISABLE:
 2537         MLX_V3_PUT_IER(sc, 0);
 2538         sc->mlx_state &= ~MLX_STATE_INTEN;
 2539         break;
 2540     case MLX_INTACTION_ENABLE:
 2541         MLX_V3_PUT_IER(sc, 1);
 2542         sc->mlx_state |= MLX_STATE_INTEN;
 2543         break;
 2544     }
 2545 }
 2546 
 2547 /********************************************************************************
 2548  * Poll for firmware error codes during controller initialisation.
 2549  * Returns 0 if initialisation is complete, 1 if still in progress but no 
 2550  * error has been fetched, 2 if an error has been retrieved.
 2551  */
 2552 static int 
 2553 mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2,
 2554     int first)
 2555 {
 2556     u_int8_t    fwerror;
 2557 
 2558     debug_called(2);
 2559 
 2560     /* first time around, clear any hardware completion status */
 2561     if (first) {
 2562         MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK);
 2563         DELAY(1000);
 2564     }
 2565 
 2566     /* init in progress? */
 2567     if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_INIT_BUSY))
 2568         return(0);
 2569 
 2570     /* test error value */
 2571     fwerror = MLX_V3_GET_FWERROR(sc);
 2572     if (!(fwerror & MLX_V3_FWERROR_PEND))
 2573         return(1);
 2574 
 2575     /* mask status pending bit, fetch status */
 2576     *error = fwerror & ~MLX_V3_FWERROR_PEND;
 2577     *param1 = MLX_V3_GET_FWERROR_PARAM1(sc);
 2578     *param2 = MLX_V3_GET_FWERROR_PARAM2(sc);
 2579 
 2580     /* acknowledge */
 2581     MLX_V3_PUT_FWERROR(sc, 0);
 2582 
 2583     return(2);
 2584 }
 2585 
 2586 /********************************************************************************
 2587  ********************************************************************************
 2588                                                 Type 4 interface accessor methods
 2589  ********************************************************************************
 2590  ********************************************************************************/
 2591 
 2592 /********************************************************************************
 2593  * Try to give (mc) to the controller.  Returns 1 if successful, 0 on failure
 2594  * (the controller is not ready to take a command).
 2595  */
 2596 static int
 2597 mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
 2598 {
 2599     int         i;
 2600     
 2601     debug_called(2);
 2602     MLX_IO_ASSERT_LOCKED(sc);
 2603 
 2604     /* ready for our command? */
 2605     if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_FULL)) {
 2606         /* copy mailbox data to window */
 2607         for (i = 0; i < 13; i++)
 2608             MLX_V4_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
 2609         
 2610         /* memory-mapped controller, so issue a write barrier to ensure the mailbox is filled */
 2611         bus_barrier(sc->mlx_mem, MLX_V4_MAILBOX, MLX_V4_MAILBOX_LENGTH,
 2612                           BUS_SPACE_BARRIER_WRITE);
 2613 
 2614         /* post command */
 2615         MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_HWMBOX_CMD);
 2616         return(1);
 2617     }
 2618     return(0);
 2619 }
 2620 
 2621 /********************************************************************************
 2622  * See if a command has been completed, if so acknowledge its completion
 2623  * and recover the slot number and status code.
 2624  */
 2625 static int
 2626 mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
 2627 {
 2628 
 2629     debug_called(2);
 2630     MLX_IO_ASSERT_LOCKED(sc);
 2631 
 2632     /* status available? */
 2633     if (MLX_V4_GET_ODBR(sc) & MLX_V4_ODB_HWSAVAIL) {
 2634         *slot = MLX_V4_GET_STATUS_IDENT(sc);            /* get command identifier */
 2635         *status = MLX_V4_GET_STATUS(sc);                /* get status */
 2636 
 2637         /* acknowledge completion */
 2638         MLX_V4_PUT_ODBR(sc, MLX_V4_ODB_HWMBOX_ACK);
 2639         MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK);
 2640         return(1);
 2641     }
 2642     return(0);
 2643 }
 2644 
 2645 /********************************************************************************
 2646  * Enable/disable interrupts as requested.
 2647  */
 2648 static void
 2649 mlx_v4_intaction(struct mlx_softc *sc, int action)
 2650 {
 2651     debug_called(1);
 2652     MLX_IO_ASSERT_LOCKED(sc);
 2653 
 2654     switch(action) {
 2655     case MLX_INTACTION_DISABLE:
 2656         MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK | MLX_V4_IER_DISINT);
 2657         sc->mlx_state &= ~MLX_STATE_INTEN;
 2658         break;
 2659     case MLX_INTACTION_ENABLE:
 2660         MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK & ~MLX_V4_IER_DISINT);
 2661         sc->mlx_state |= MLX_STATE_INTEN;
 2662         break;
 2663     }
 2664 }
 2665 
 2666 /********************************************************************************
 2667  * Poll for firmware error codes during controller initialisation.
 2668  * Returns 0 if initialisation is complete, 1 if still in progress but no 
 2669  * error has been fetched, 2 if an error has been retrieved.
 2670  */
 2671 static int 
 2672 mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2,
 2673     int first)
 2674 {
 2675     u_int8_t    fwerror;
 2676 
 2677     debug_called(2);
 2678 
 2679     /* first time around, clear any hardware completion status */
 2680     if (first) {
 2681         MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK);
 2682         DELAY(1000);
 2683     }
 2684 
 2685     /* init in progress? */
 2686     if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_INIT_BUSY))
 2687         return(0);
 2688 
 2689     /* test error value */
 2690     fwerror = MLX_V4_GET_FWERROR(sc);
 2691     if (!(fwerror & MLX_V4_FWERROR_PEND))
 2692         return(1);
 2693 
 2694     /* mask status pending bit, fetch status */
 2695     *error = fwerror & ~MLX_V4_FWERROR_PEND;
 2696     *param1 = MLX_V4_GET_FWERROR_PARAM1(sc);
 2697     *param2 = MLX_V4_GET_FWERROR_PARAM2(sc);
 2698 
 2699     /* acknowledge */
 2700     MLX_V4_PUT_FWERROR(sc, 0);
 2701 
 2702     return(2);
 2703 }
 2704 
 2705 /********************************************************************************
 2706  ********************************************************************************
 2707                                                 Type 5 interface accessor methods
 2708  ********************************************************************************
 2709  ********************************************************************************/
 2710 
 2711 /********************************************************************************
 2712  * Try to give (mc) to the controller.  Returns 1 if successful, 0 on failure
 2713  * (the controller is not ready to take a command).
 2714  */
 2715 static int
 2716 mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
 2717 {
 2718     int         i;
 2719 
 2720     debug_called(2);
 2721     MLX_IO_ASSERT_LOCKED(sc);
 2722 
 2723     /* ready for our command? */
 2724     if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_EMPTY) {
 2725         /* copy mailbox data to window */
 2726         for (i = 0; i < 13; i++)
 2727             MLX_V5_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
 2728 
 2729         /* post command */
 2730         MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_HWMBOX_CMD);
 2731         return(1);
 2732     }
 2733     return(0);
 2734 }
 2735 
 2736 /********************************************************************************
 2737  * See if a command has been completed, if so acknowledge its completion
 2738  * and recover the slot number and status code.
 2739  */
 2740 static int
 2741 mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
 2742 {
 2743 
 2744     debug_called(2);
 2745     MLX_IO_ASSERT_LOCKED(sc);
 2746 
 2747     /* status available? */
 2748     if (MLX_V5_GET_ODBR(sc) & MLX_V5_ODB_HWSAVAIL) {
 2749         *slot = MLX_V5_GET_STATUS_IDENT(sc);            /* get command identifier */
 2750         *status = MLX_V5_GET_STATUS(sc);                /* get status */
 2751 
 2752         /* acknowledge completion */
 2753         MLX_V5_PUT_ODBR(sc, MLX_V5_ODB_HWMBOX_ACK);
 2754         MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK);
 2755         return(1);
 2756     }
 2757     return(0);
 2758 }
 2759 
 2760 /********************************************************************************
 2761  * Enable/disable interrupts as requested.
 2762  */
 2763 static void
 2764 mlx_v5_intaction(struct mlx_softc *sc, int action)
 2765 {
 2766     debug_called(1);
 2767     MLX_IO_ASSERT_LOCKED(sc);
 2768 
 2769     switch(action) {
 2770     case MLX_INTACTION_DISABLE:
 2771         MLX_V5_PUT_IER(sc, 0xff & MLX_V5_IER_DISINT);
 2772         sc->mlx_state &= ~MLX_STATE_INTEN;
 2773         break;
 2774     case MLX_INTACTION_ENABLE:
 2775         MLX_V5_PUT_IER(sc, 0xff & ~MLX_V5_IER_DISINT);
 2776         sc->mlx_state |= MLX_STATE_INTEN;
 2777         break;
 2778     }
 2779 }
 2780 
 2781 /********************************************************************************
 2782  * Poll for firmware error codes during controller initialisation.
 2783  * Returns 0 if initialisation is complete, 1 if still in progress but no 
 2784  * error has been fetched, 2 if an error has been retrieved.
 2785  */
 2786 static int 
 2787 mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2,
 2788     int first)
 2789 {
 2790     u_int8_t    fwerror;
 2791 
 2792     debug_called(2);
 2793 
 2794     /* first time around, clear any hardware completion status */
 2795     if (first) {
 2796         MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK);
 2797         DELAY(1000);
 2798     }
 2799 
 2800     /* init in progress? */
 2801     if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_INIT_DONE)
 2802         return(0);
 2803 
 2804     /* test for error value */
 2805     fwerror = MLX_V5_GET_FWERROR(sc);
 2806     if (!(fwerror & MLX_V5_FWERROR_PEND))
 2807         return(1);
 2808 
 2809     /* mask status pending bit, fetch status */
 2810     *error = fwerror & ~MLX_V5_FWERROR_PEND;
 2811     *param1 = MLX_V5_GET_FWERROR_PARAM1(sc);
 2812     *param2 = MLX_V5_GET_FWERROR_PARAM2(sc);
 2813 
 2814     /* acknowledge */
 2815     MLX_V5_PUT_FWERROR(sc, 0xff);
 2816 
 2817     return(2);
 2818 }
 2819 
 2820 /********************************************************************************
 2821  ********************************************************************************
 2822                                                                         Debugging
 2823  ********************************************************************************
 2824  ********************************************************************************/
 2825 
 2826 /********************************************************************************
 2827  * Return a status message describing (mc)
 2828  */
 2829 static char *mlx_status_messages[] = {
 2830     "normal completion",                        /* 00 */
 2831     "irrecoverable data error",                 /* 01 */
 2832     "drive does not exist, or is offline",      /* 02 */
 2833     "attempt to write beyond end of drive",     /* 03 */
 2834     "bad data encountered",                     /* 04 */
 2835     "invalid log entry request",                /* 05 */
 2836     "attempt to rebuild online drive",          /* 06 */
 2837     "new disk failed during rebuild",           /* 07 */
 2838     "invalid channel/target",                   /* 08 */
 2839     "rebuild/check already in progress",        /* 09 */
 2840     "one or more disks are dead",               /* 10 */
 2841     "invalid or non-redundant drive",           /* 11 */
 2842     "channel is busy",                          /* 12 */
 2843     "channel is not stopped",                   /* 13 */
 2844     "rebuild successfully terminated",          /* 14 */
 2845     "unsupported command",                      /* 15 */
 2846     "check condition received",                 /* 16 */
 2847     "device is busy",                           /* 17 */
 2848     "selection or command timeout",             /* 18 */
 2849     "command terminated abnormally",            /* 19 */
 2850     ""
 2851 };
 2852 
 2853 static struct
 2854 {
 2855     int         command;
 2856     u_int16_t   status;
 2857     int         msg;
 2858 } mlx_messages[] = {
 2859     {MLX_CMD_READSG,            0x0001,  1},
 2860     {MLX_CMD_READSG,            0x0002,  1},
 2861     {MLX_CMD_READSG,            0x0105,  3},
 2862     {MLX_CMD_READSG,            0x010c,  4},
 2863     {MLX_CMD_WRITESG,           0x0001,  1},
 2864     {MLX_CMD_WRITESG,           0x0002,  1},
 2865     {MLX_CMD_WRITESG,           0x0105,  3},
 2866     {MLX_CMD_READSG_OLD,        0x0001,  1},
 2867     {MLX_CMD_READSG_OLD,        0x0002,  1},
 2868     {MLX_CMD_READSG_OLD,        0x0105,  3},
 2869     {MLX_CMD_WRITESG_OLD,       0x0001,  1},
 2870     {MLX_CMD_WRITESG_OLD,       0x0002,  1},
 2871     {MLX_CMD_WRITESG_OLD,       0x0105,  3},
 2872     {MLX_CMD_LOGOP,             0x0105,  5},
 2873     {MLX_CMD_REBUILDASYNC,      0x0002,  6},
 2874     {MLX_CMD_REBUILDASYNC,      0x0004,  7},
 2875     {MLX_CMD_REBUILDASYNC,      0x0105,  8},
 2876     {MLX_CMD_REBUILDASYNC,      0x0106,  9},
 2877     {MLX_CMD_REBUILDASYNC,      0x0107, 14},
 2878     {MLX_CMD_CHECKASYNC,        0x0002, 10},
 2879     {MLX_CMD_CHECKASYNC,        0x0105, 11},
 2880     {MLX_CMD_CHECKASYNC,        0x0106,  9},
 2881     {MLX_CMD_STOPCHANNEL,       0x0106, 12},
 2882     {MLX_CMD_STOPCHANNEL,       0x0105,  8},
 2883     {MLX_CMD_STARTCHANNEL,      0x0005, 13},
 2884     {MLX_CMD_STARTCHANNEL,      0x0105,  8},
 2885     {MLX_CMD_DIRECT_CDB,        0x0002, 16},
 2886     {MLX_CMD_DIRECT_CDB,        0x0008, 17},
 2887     {MLX_CMD_DIRECT_CDB,        0x000e, 18},
 2888     {MLX_CMD_DIRECT_CDB,        0x000f, 19},
 2889     {MLX_CMD_DIRECT_CDB,        0x0105,  8},
 2890     
 2891     {0,                         0x0104, 14},
 2892     {-1, 0, 0}
 2893 };
 2894 
 2895 static char *
 2896 mlx_diagnose_command(struct mlx_command *mc)
 2897 {
 2898     static char unkmsg[80];
 2899     int         i;
 2900     
 2901     /* look up message in table */
 2902     for (i = 0; mlx_messages[i].command != -1; i++)
 2903         if (((mc->mc_mailbox[0] == mlx_messages[i].command) || (mlx_messages[i].command == 0)) &&
 2904             (mc->mc_status == mlx_messages[i].status))
 2905             return(mlx_status_messages[mlx_messages[i].msg]);
 2906         
 2907     sprintf(unkmsg, "unknown response 0x%x for command 0x%x", (int)mc->mc_status, (int)mc->mc_mailbox[0]);
 2908     return(unkmsg);
 2909 }
 2910 
 2911 /*******************************************************************************
 2912  * Print a string describing the controller (sc)
 2913  */
 2914 static struct 
 2915 {
 2916     int         hwid;
 2917     char        *name;
 2918 } mlx_controller_names[] = {
 2919     {0x01,      "960P/PD"},
 2920     {0x02,      "960PL"},
 2921     {0x10,      "960PG"},
 2922     {0x11,      "960PJ"},
 2923     {0x12,      "960PR"},
 2924     {0x13,      "960PT"},
 2925     {0x14,      "960PTL0"},
 2926     {0x15,      "960PRL"},
 2927     {0x16,      "960PTL1"},
 2928     {0x20,      "1164PVX"},
 2929     {-1, NULL}
 2930 };
 2931 
 2932 static void
 2933 mlx_describe_controller(struct mlx_softc *sc) 
 2934 {
 2935     static char         buf[80];
 2936     char                *model;
 2937     int                 i;
 2938 
 2939     for (i = 0, model = NULL; mlx_controller_names[i].name != NULL; i++) {
 2940         if ((sc->mlx_enq2->me_hardware_id & 0xff) == mlx_controller_names[i].hwid) {
 2941             model = mlx_controller_names[i].name;
 2942             break;
 2943         }
 2944     }
 2945     if (model == NULL) {
 2946         sprintf(buf, " model 0x%x", sc->mlx_enq2->me_hardware_id & 0xff);
 2947         model = buf;
 2948     }
 2949     device_printf(sc->mlx_dev, "DAC%s, %d channel%s, firmware %d.%02d-%c-%02d, %dMB RAM\n",
 2950                   model, 
 2951                   sc->mlx_enq2->me_actual_channels, 
 2952                   sc->mlx_enq2->me_actual_channels > 1 ? "s" : "",
 2953                   sc->mlx_enq2->me_firmware_id & 0xff,
 2954                   (sc->mlx_enq2->me_firmware_id >> 8) & 0xff,
 2955                   (sc->mlx_enq2->me_firmware_id >> 24) & 0xff,
 2956                   (sc->mlx_enq2->me_firmware_id >> 16) & 0xff,
 2957                   sc->mlx_enq2->me_mem_size / (1024 * 1024));
 2958 
 2959     if (bootverbose) {
 2960         device_printf(sc->mlx_dev, "  Hardware ID                 0x%08x\n", sc->mlx_enq2->me_hardware_id);
 2961         device_printf(sc->mlx_dev, "  Firmware ID                 0x%08x\n", sc->mlx_enq2->me_firmware_id);
 2962         device_printf(sc->mlx_dev, "  Configured/Actual channels  %d/%d\n", sc->mlx_enq2->me_configured_channels,
 2963                       sc->mlx_enq2->me_actual_channels);
 2964         device_printf(sc->mlx_dev, "  Max Targets                 %d\n", sc->mlx_enq2->me_max_targets);
 2965         device_printf(sc->mlx_dev, "  Max Tags                    %d\n", sc->mlx_enq2->me_max_tags);
 2966         device_printf(sc->mlx_dev, "  Max System Drives           %d\n", sc->mlx_enq2->me_max_sys_drives);
 2967         device_printf(sc->mlx_dev, "  Max Arms                    %d\n", sc->mlx_enq2->me_max_arms);
 2968         device_printf(sc->mlx_dev, "  Max Spans                   %d\n", sc->mlx_enq2->me_max_spans);
 2969         device_printf(sc->mlx_dev, "  DRAM/cache/flash/NVRAM size %d/%d/%d/%d\n", sc->mlx_enq2->me_mem_size,
 2970                       sc->mlx_enq2->me_cache_size, sc->mlx_enq2->me_flash_size, sc->mlx_enq2->me_nvram_size);
 2971         device_printf(sc->mlx_dev, "  DRAM type                   %d\n", sc->mlx_enq2->me_mem_type);
 2972         device_printf(sc->mlx_dev, "  Clock Speed                 %dns\n", sc->mlx_enq2->me_clock_speed);
 2973         device_printf(sc->mlx_dev, "  Hardware Speed              %dns\n", sc->mlx_enq2->me_hardware_speed);
 2974         device_printf(sc->mlx_dev, "  Max Commands                %d\n", sc->mlx_enq2->me_max_commands);
 2975         device_printf(sc->mlx_dev, "  Max SG Entries              %d\n", sc->mlx_enq2->me_max_sg);
 2976         device_printf(sc->mlx_dev, "  Max DP                      %d\n", sc->mlx_enq2->me_max_dp);
 2977         device_printf(sc->mlx_dev, "  Max IOD                     %d\n", sc->mlx_enq2->me_max_iod);
 2978         device_printf(sc->mlx_dev, "  Max Comb                    %d\n", sc->mlx_enq2->me_max_comb);
 2979         device_printf(sc->mlx_dev, "  Latency                     %ds\n", sc->mlx_enq2->me_latency);
 2980         device_printf(sc->mlx_dev, "  SCSI Timeout                %ds\n", sc->mlx_enq2->me_scsi_timeout);
 2981         device_printf(sc->mlx_dev, "  Min Free Lines              %d\n", sc->mlx_enq2->me_min_freelines);
 2982         device_printf(sc->mlx_dev, "  Rate Constant               %d\n", sc->mlx_enq2->me_rate_const);
 2983         device_printf(sc->mlx_dev, "  MAXBLK                      %d\n", sc->mlx_enq2->me_maxblk);
 2984         device_printf(sc->mlx_dev, "  Blocking Factor             %d sectors\n", sc->mlx_enq2->me_blocking_factor);
 2985         device_printf(sc->mlx_dev, "  Cache Line Size             %d blocks\n", sc->mlx_enq2->me_cacheline);
 2986         device_printf(sc->mlx_dev, "  SCSI Capability             %s%dMHz, %d bit\n", 
 2987                       sc->mlx_enq2->me_scsi_cap & (1<<4) ? "differential " : "",
 2988                       (1 << ((sc->mlx_enq2->me_scsi_cap >> 2) & 3)) * 10,
 2989                       8 << (sc->mlx_enq2->me_scsi_cap & 0x3));
 2990         device_printf(sc->mlx_dev, "  Firmware Build Number       %d\n", sc->mlx_enq2->me_firmware_build);
 2991         device_printf(sc->mlx_dev, "  Fault Management Type       %d\n", sc->mlx_enq2->me_fault_mgmt_type);
 2992         device_printf(sc->mlx_dev, "  Features                    %b\n", sc->mlx_enq2->me_firmware_features,
 2993                       "\2\4Background Init\3Read Ahead\2MORE\1Cluster\n");
 2994         
 2995     }
 2996 }
 2997 
 2998 /*******************************************************************************
 2999  * Emit a string describing the firmware handshake status code, and return a flag 
 3000  * indicating whether the code represents a fatal error.
 3001  *
 3002  * Error code interpretations are from the Linux driver, and don't directly match
 3003  * the messages printed by Mylex's BIOS.  This may change if documentation on the
 3004  * codes is forthcoming.
 3005  */
 3006 static int
 3007 mlx_fw_message(struct mlx_softc *sc, int error, int param1, int param2)
 3008 {
 3009     switch(error) {
 3010     case 0x00:
 3011         device_printf(sc->mlx_dev, "physical drive %d:%d not responding\n", param2, param1);
 3012         break;
 3013     case 0x08:
 3014         /* we could be neater about this and give some indication when we receive more of them */
 3015         if (!(sc->mlx_flags & MLX_SPINUP_REPORTED)) {
 3016             device_printf(sc->mlx_dev, "spinning up drives...\n");
 3017             sc->mlx_flags |= MLX_SPINUP_REPORTED;
 3018         }
 3019         break;
 3020     case 0x30:
 3021         device_printf(sc->mlx_dev, "configuration checksum error\n");
 3022         break;
 3023     case 0x60:
 3024         device_printf(sc->mlx_dev, "mirror race recovery failed\n");
 3025         break;
 3026     case 0x70:
 3027         device_printf(sc->mlx_dev, "mirror race recovery in progress\n");
 3028         break;
 3029     case 0x90:
 3030         device_printf(sc->mlx_dev, "physical drive %d:%d COD mismatch\n", param2, param1);
 3031         break;
 3032     case 0xa0:
 3033         device_printf(sc->mlx_dev, "logical drive installation aborted\n");
 3034         break;
 3035     case 0xb0:
 3036         device_printf(sc->mlx_dev, "mirror race on a critical system drive\n");
 3037         break;
 3038     case 0xd0:
 3039         device_printf(sc->mlx_dev, "new controller configuration found\n");
 3040         break;
 3041     case 0xf0:
 3042         device_printf(sc->mlx_dev, "FATAL MEMORY PARITY ERROR\n");
 3043         return(1);
 3044     default:
 3045         device_printf(sc->mlx_dev, "unknown firmware initialisation error %02x:%02x:%02x\n", error, param1, param2);
 3046         break;
 3047     }
 3048     return(0);
 3049 }
 3050 
 3051 /********************************************************************************
 3052  ********************************************************************************
 3053                                                                 Utility Functions
 3054  ********************************************************************************
 3055  ********************************************************************************/
 3056 
 3057 /********************************************************************************
 3058  * Find the disk whose unit number is (unit) on this controller
 3059  */
 3060 static struct mlx_sysdrive *
 3061 mlx_findunit(struct mlx_softc *sc, int unit)
 3062 {
 3063     int         i;
 3064     
 3065     /* search system drives */
 3066     MLX_CONFIG_ASSERT_LOCKED(sc);
 3067     for (i = 0; i < MLX_MAXDRIVES; i++) {
 3068         /* is this one attached? */
 3069         if (sc->mlx_sysdrive[i].ms_disk != 0) {
 3070             /* is this the one? */
 3071             if (unit == device_get_unit(sc->mlx_sysdrive[i].ms_disk))
 3072                 return(&sc->mlx_sysdrive[i]);
 3073         }
 3074     }
 3075     return(NULL);
 3076 }

Cache object: 757a1577296c8970598e4916edf2a4df


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