File:  [DragonFly] / src / sys / dev / raid / mlx / mlx.c
Revision 1.8: download - view: text, annotated - select for diffs
Wed May 19 22:52:47 2004 UTC (10 years, 6 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
Device layer rollup commit.

* cdevsw_add() is now required.  cdevsw_add() and cdevsw_remove() may specify
  a mask/match indicating the range of supported minor numbers.  Multiple
  cdevsw_add()'s using the same major number, but distinctly different
  ranges, may be issued.  All devices that failed to call cdevsw_add() before
  now do.

* cdevsw_remove() now automatically marks all devices within its supported
  range as being destroyed.

* vnode->v_rdev is no longer resolved when the vnode is created.  Instead,
  only v_udev (a newly added field) is resolved.  v_rdev is resolved when
  the vnode is opened and cleared on the last close.

* A great deal of code was making rather dubious assumptions with regards
  to the validity of devices associated with vnodes, primarily due to
  the persistence of a device structure due to being indexed by (major, minor)
  instead of by (cdevsw, major, minor).  In particular, if you run a program
  which connects to a USB device and then you pull the USB device and plug
  it back in, the vnode subsystem will continue to believe that the device
  is open when, in fact, it isn't (because it was destroyed and recreated).

  In particular, note that all the VFS mount procedures now check devices
  via v_udev instead of v_rdev prior to calling VOP_OPEN(), since v_rdev
  is NULL prior to the first open.

* The disk layer's device interaction has been rewritten.  The disk layer
  (i.e. the slice and disklabel management layer) no longer overloads
  its data onto the device structure representing the underlying physical
  disk.  Instead, the disk layer uses the new cdevsw_add() functionality
  to register its own cdevsw using the underlying device's major number,
  and simply does NOT register the underlying device's cdevsw.  No
  confusion is created because the device hash is now based on
  (cdevsw,major,minor) rather then (major,minor).

  NOTE: This also means that underlying raw disk devices may use the entire
  device minor number instead of having to reserve the bits used by the disk
  layer, and also means that can we (theoretically) stack a fully
  disklabel-supported 'disk' on top of any block device.

* The new reference counting scheme prevents this by associating a device
  with a cdevsw and disconnecting the device from its cdevsw when the cdevsw
  is removed.  Additionally, all udev2dev() lookups run through the cdevsw
  mask/match and only successfully find devices still associated with an
  active cdevsw.

* Major work on MFS:  MFS no longer shortcuts vnode and device creation.  It
  now creates a real vnode and a real device and implements real open and
  close VOPs.  Additionally, due to the disk layer changes, MFS is no longer
  limited to 255 mounts.  The new limit is 16 million.  Since MFS creates a
  real device node, mount_mfs will now create a real /dev/mfs<PID> device
  that can be read from userland (e.g. so you can dump an MFS filesystem).

* BUF AND DEVICE STRATEGY changes.  The struct buf contains a b_dev field.
  In order to properly handle stacked devices we now require that the b_dev
  field be initialized before the device strategy routine is called.  This
  required some additional work in various VFS implementations.  To enforce
  this requirement, biodone() now sets b_dev to NODEV.  The new disk layer
  will adjust b_dev before forwarding a request to the actual physical
  device.

* A bug in the ISO CD boot sequence which resulted in a panic has been fixed.

Testing by: lots of people, but David Rhodus found the most aggregious bugs.

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