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

Cache object: fc0d5d67693b40678f010879053ed75a


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