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

Cache object: 3e2b201db906990f356227da2a2dcfda


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