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

Cache object: a1b84b40fb3bee42b0ce97566c03d6b3


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