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

Cache object: e81d4e5e40758d0df5bff42148c00928


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