Home | History | Annotate | Line # | Download | only in ic
mlx.c revision 1.69
      1 /*	$NetBSD: mlx.c,v 1.69 2021/04/24 23:36:55 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2001 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Andrew Doran.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 /*-
     33  * Copyright (c) 1999 Michael Smith
     34  * All rights reserved.
     35  *
     36  * Redistribution and use in source and binary forms, with or without
     37  * modification, are permitted provided that the following conditions
     38  * are met:
     39  * 1. Redistributions of source code must retain the above copyright
     40  *    notice, this list of conditions and the following disclaimer.
     41  * 2. Redistributions in binary form must reproduce the above copyright
     42  *    notice, this list of conditions and the following disclaimer in the
     43  *    documentation and/or other materials provided with the distribution.
     44  *
     45  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     46  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     47  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     48  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     49  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     50  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     51  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     52  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     53  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     54  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     55  * SUCH DAMAGE.
     56  *
     57  * from FreeBSD: mlx.c,v 1.14.2.3 2000/08/04 06:52:50 msmith Exp
     58  */
     59 
     60 /*
     61  * Driver for the Mylex DAC960 family of RAID controllers.
     62  *
     63  * TODO:
     64  *
     65  * o Test and enable channel pause.
     66  * o SCSI pass-through.
     67  */
     68 
     69 #include <sys/cdefs.h>
     70 __KERNEL_RCSID(0, "$NetBSD: mlx.c,v 1.69 2021/04/24 23:36:55 thorpej Exp $");
     71 
     72 #if defined(_KERNEL_OPT)
     73 #include "ld.h"
     74 #endif
     75 
     76 #include <sys/param.h>
     77 #include <sys/systm.h>
     78 #include <sys/kernel.h>
     79 #include <sys/device.h>
     80 #include <sys/queue.h>
     81 #include <sys/proc.h>
     82 #include <sys/buf.h>
     83 #include <sys/bufq.h>
     84 #include <sys/endian.h>
     85 #include <sys/malloc.h>
     86 #include <sys/conf.h>
     87 #include <sys/kthread.h>
     88 #include <sys/disk.h>
     89 #include <sys/kauth.h>
     90 #include <sys/module.h>
     91 #include <machine/vmparam.h>
     92 #include <sys/bus.h>
     93 
     94 #include <dev/ldvar.h>
     95 
     96 #include <dev/ic/mlxreg.h>
     97 #include <dev/ic/mlxio.h>
     98 #include <dev/ic/mlxvar.h>
     99 
    100 #include "ioconf.h"
    101 #include "locators.h"
    102 
    103 #define	MLX_TIMEOUT	60
    104 
    105 #ifdef DIAGNOSTIC
    106 #define	DPRINTF(x)	printf x
    107 #else
    108 #define	DPRINTF(x)
    109 #endif
    110 
    111 static void	mlx_adjqparam(struct mlx_softc *, int, int);
    112 static int	mlx_ccb_submit(struct mlx_softc *, struct mlx_ccb *);
    113 static int	mlx_check(struct mlx_softc *, int);
    114 static void	mlx_describe(struct mlx_softc *);
    115 static void	*mlx_enquire(struct mlx_softc *, int, size_t,
    116 			     void (*)(struct mlx_ccb *), int);
    117 static int	mlx_fw_message(struct mlx_softc *, int, int, int);
    118 static void	mlx_pause_action(struct mlx_softc *);
    119 static void	mlx_pause_done(struct mlx_ccb *);
    120 static void	mlx_periodic(struct mlx_softc *);
    121 static void	mlx_periodic_enquiry(struct mlx_ccb *);
    122 static void	mlx_periodic_eventlog_poll(struct mlx_softc *);
    123 static void	mlx_periodic_eventlog_respond(struct mlx_ccb *);
    124 static void	mlx_periodic_rebuild(struct mlx_ccb *);
    125 static void	mlx_periodic_thread(void *);
    126 static int	mlx_print(void *, const char *);
    127 static int	mlx_rebuild(struct mlx_softc *, int, int);
    128 static void	mlx_shutdown(void *);
    129 static int	mlx_user_command(struct mlx_softc *, struct mlx_usercommand *);
    130 
    131 dev_type_open(mlxopen);
    132 dev_type_close(mlxclose);
    133 dev_type_ioctl(mlxioctl);
    134 
    135 const struct cdevsw mlx_cdevsw = {
    136 	.d_open = mlxopen,
    137 	.d_close = mlxclose,
    138 	.d_read = noread,
    139 	.d_write = nowrite,
    140 	.d_ioctl = mlxioctl,
    141 	.d_stop = nostop,
    142 	.d_tty = notty,
    143 	.d_poll = nopoll,
    144 	.d_mmap = nommap,
    145 	.d_kqfilter = nokqfilter,
    146 	.d_discard = nodiscard,
    147 	.d_flag = D_OTHER
    148 };
    149 
    150 static struct	lwp *mlx_periodic_lwp;
    151 static void	*mlx_sdh;
    152 
    153 static struct {
    154 	int	hwid;
    155 	const char	*name;
    156 } const mlx_cname[] = {
    157 	{ 0x00, "960E/960M" },
    158 	{ 0x01, "960P/PD" },
    159 	{ 0x02,	"960PL" },
    160 	{ 0x10, "960PG" },
    161 	{ 0x11, "960PJ" },
    162 	{ 0x12, "960PR" },
    163 	{ 0x13,	"960PT" },
    164 	{ 0x14, "960PTL0" },
    165 	{ 0x15, "960PRL" },
    166 	{ 0x16, "960PTL1" },
    167 	{ 0x20, "1164PVX" },
    168 };
    169 
    170 static const char * const mlx_sense_msgs[] = {
    171 	"because write recovery failed",
    172 	"because of SCSI bus reset failure",
    173 	"because of double check condition",
    174 	"because it was removed",
    175 	"because of gross error on SCSI chip",
    176 	"because of bad tag returned from drive",
    177 	"because of timeout on SCSI command",
    178 	"because of reset SCSI command issued from system",
    179 	"because busy or parity error count exceeded limit",
    180 	"because of 'kill drive' command from system",
    181 	"because of selection timeout",
    182 	"due to SCSI phase sequence error",
    183 	"due to unknown status"
    184 };
    185 
    186 static const char * const mlx_status_msgs[] = {
    187 	"normal completion",				/* 0 */
    188 	"irrecoverable data error",			/* 1 */
    189 	"drive does not exist, or is offline",		/* 2 */
    190 	"attempt to write beyond end of drive",		/* 3 */
    191 	"bad data encountered",				/* 4 */
    192 	"invalid log entry request",			/* 5 */
    193 	"attempt to rebuild online drive",		/* 6 */
    194 	"new disk failed during rebuild",		/* 7 */
    195 	"invalid channel/target",			/* 8 */
    196 	"rebuild/check already in progress",		/* 9 */
    197 	"one or more disks are dead",			/* 10 */
    198 	"invalid or non-redundant drive",		/* 11 */
    199 	"channel is busy",				/* 12 */
    200 	"channel is not stopped",			/* 13 */
    201 	"rebuild successfully terminated",		/* 14 */
    202 	"unsupported command",				/* 15 */
    203 	"check condition received",			/* 16 */
    204 	"device is busy",				/* 17 */
    205 	"selection or command timeout",			/* 18 */
    206 	"command terminated abnormally",		/* 19 */
    207 	"controller wedged",				/* 20 */
    208 	"software timeout",				/* 21 */
    209 	"command busy (?)",				/* 22 */
    210 };
    211 
    212 static struct {
    213 	u_char	command;
    214 	u_char	msg;		/* Index into mlx_status_msgs[]. */
    215 	u_short	status;
    216 } const mlx_msgs[] = {
    217 	{ MLX_CMD_READSG,	1,	0x0001 },
    218 	{ MLX_CMD_READSG,	1,	0x0002 },
    219 	{ MLX_CMD_READSG,	3,	0x0105 },
    220 	{ MLX_CMD_READSG,	4,	0x010c },
    221 	{ MLX_CMD_WRITESG,	1,	0x0001 },
    222 	{ MLX_CMD_WRITESG,	1,	0x0002 },
    223 	{ MLX_CMD_WRITESG,	3,	0x0105 },
    224 	{ MLX_CMD_READSG_OLD,	1,	0x0001 },
    225 	{ MLX_CMD_READSG_OLD,	1,	0x0002 },
    226 	{ MLX_CMD_READSG_OLD,	3,	0x0105 },
    227 	{ MLX_CMD_WRITESG_OLD,	1,	0x0001 },
    228 	{ MLX_CMD_WRITESG_OLD,	1,	0x0002 },
    229 	{ MLX_CMD_WRITESG_OLD,	3,	0x0105 },
    230 	{ MLX_CMD_LOGOP,	5,	0x0105 },
    231 	{ MLX_CMD_REBUILDASYNC,	6,	0x0002 },
    232 	{ MLX_CMD_REBUILDASYNC,	7,	0x0004 },
    233 	{ MLX_CMD_REBUILDASYNC,	8,	0x0105 },
    234 	{ MLX_CMD_REBUILDASYNC,	9,	0x0106 },
    235 	{ MLX_CMD_REBUILDASYNC,	14,	0x0107 },
    236 	{ MLX_CMD_CHECKASYNC,	10,	0x0002 },
    237 	{ MLX_CMD_CHECKASYNC,	11,	0x0105 },
    238 	{ MLX_CMD_CHECKASYNC,	9,	0x0106 },
    239 	{ MLX_CMD_STOPCHANNEL,	12,	0x0106 },
    240 	{ MLX_CMD_STOPCHANNEL,	8,	0x0105 },
    241 	{ MLX_CMD_STARTCHANNEL,	13,	0x0005 },
    242 	{ MLX_CMD_STARTCHANNEL,	8,	0x0105 },
    243 	{ MLX_CMD_DIRECT_CDB,	16,	0x0002 },
    244 	{ MLX_CMD_DIRECT_CDB,	17,	0x0008 },
    245 	{ MLX_CMD_DIRECT_CDB,	18,	0x000e },
    246 	{ MLX_CMD_DIRECT_CDB,	19,	0x000f },
    247 	{ MLX_CMD_DIRECT_CDB,	8,	0x0105 },
    248 
    249 	{ 0,			20,	MLX_STATUS_WEDGED },
    250 	{ 0,			21,	MLX_STATUS_LOST },
    251 	{ 0,			22,	MLX_STATUS_BUSY },
    252 
    253 	{ 0,			14,	0x0104 },
    254 };
    255 
    256 /*
    257  * Initialise the controller and our interface.
    258  */
    259 void
    260 mlx_init(struct mlx_softc *mlx, const char *intrstr)
    261 {
    262 	struct mlx_ccb *mc;
    263 	struct mlx_enquiry_old *meo;
    264 	struct mlx_enquiry2 *me2;
    265 	struct mlx_cinfo *ci;
    266 	int rv, fwminor, hscode, hserr, hsparam1, hsparam2, hsmsg;
    267 	int size, i, rseg;
    268 	const char *wantfwstr;
    269 	bus_dma_segment_t seg;
    270 
    271 	SIMPLEQ_INIT(&mlx->mlx_ccb_queue);
    272 	SLIST_INIT(&mlx->mlx_ccb_freelist);
    273 	TAILQ_INIT(&mlx->mlx_ccb_worklist);
    274 
    275 	if (intrstr != NULL)
    276 		printf("%s: interrupting at %s\n", device_xname(mlx->mlx_dv),
    277 		    intrstr);
    278 
    279 	/*
    280 	 * Allocate the scatter/gather lists.
    281 	 */
    282         size = MLX_SGL_SIZE * MLX_MAX_QUEUECNT;
    283 
    284 	if ((rv = bus_dmamem_alloc(mlx->mlx_dmat, size, PAGE_SIZE, 0, &seg, 1,
    285 	    &rseg, BUS_DMA_NOWAIT)) != 0) {
    286 		aprint_error_dev(mlx->mlx_dv,
    287 		    "unable to allocate sglists, rv = %d\n", rv);
    288 		return;
    289 	}
    290 
    291 	if ((rv = bus_dmamem_map(mlx->mlx_dmat, &seg, rseg, size,
    292 	    (void **)&mlx->mlx_sgls,
    293 	    BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
    294 		aprint_error_dev(mlx->mlx_dv,
    295 		    "unable to map sglists, rv = %d\n", rv);
    296 		return;
    297 	}
    298 
    299 	if ((rv = bus_dmamap_create(mlx->mlx_dmat, size, 1, size, 0,
    300 	    BUS_DMA_NOWAIT, &mlx->mlx_dmamap)) != 0) {
    301 		aprint_error_dev(mlx->mlx_dv,
    302 		    "unable to create sglist DMA map, rv = %d\n", rv);
    303 		return;
    304 	}
    305 
    306 	if ((rv = bus_dmamap_load(mlx->mlx_dmat, mlx->mlx_dmamap,
    307 	    mlx->mlx_sgls, size, NULL, BUS_DMA_NOWAIT)) != 0) {
    308 		aprint_error_dev(mlx->mlx_dv,
    309 		    "unable to load sglist DMA map, rv = %d\n", rv);
    310 		return;
    311 	}
    312 
    313 	mlx->mlx_sgls_paddr = mlx->mlx_dmamap->dm_segs[0].ds_addr;
    314 	memset(mlx->mlx_sgls, 0, size);
    315 
    316 	/*
    317 	 * Allocate and initialize the CCBs.
    318 	 */
    319 	mc = malloc(sizeof(*mc) * MLX_MAX_QUEUECNT, M_DEVBUF, M_WAITOK);
    320 	mlx->mlx_ccbs = mc;
    321 
    322 	for (i = 0; i < MLX_MAX_QUEUECNT; i++, mc++) {
    323 		mc->mc_ident = i;
    324 		rv = bus_dmamap_create(mlx->mlx_dmat, MLX_MAX_XFER,
    325 		    MLX_MAX_SEGS, MLX_MAX_XFER, 0,
    326 		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
    327 		    &mc->mc_xfer_map);
    328 		if (rv != 0)
    329 			break;
    330 		mlx->mlx_nccbs++;
    331 		mlx_ccb_free(mlx, mc);
    332 	}
    333 	if (mlx->mlx_nccbs != MLX_MAX_QUEUECNT)
    334 		printf("%s: %d/%d CCBs usable\n", device_xname(mlx->mlx_dv),
    335 		    mlx->mlx_nccbs, MLX_MAX_QUEUECNT);
    336 
    337 	/* Disable interrupts before we start talking to the controller */
    338 	(*mlx->mlx_intaction)(mlx, 0);
    339 
    340 	/* If we've got a reset routine, then reset the controller now. */
    341 	if (mlx->mlx_reset != NULL) {
    342 		printf("%s: resetting controller...\n",
    343 		    device_xname(mlx->mlx_dv));
    344 		if ((*mlx->mlx_reset)(mlx) != 0) {
    345 			aprint_error_dev(mlx->mlx_dv, "reset failed\n");
    346 			return;
    347 		}
    348 	}
    349 
    350 	/*
    351 	 * Wait for the controller to come ready, handshaking with the
    352 	 * firmware if required.  This is typically only necessary on
    353 	 * platforms where the controller BIOS does not run.
    354 	 */
    355 	hsmsg = 0;
    356 
    357 	for (;;) {
    358 		hscode = (*mlx->mlx_fw_handshake)(mlx, &hserr, &hsparam1,
    359 		    &hsparam2);
    360 		if (hscode == 0) {
    361 			if (hsmsg != 0)
    362 				printf("%s: initialization complete\n",
    363 				    device_xname(mlx->mlx_dv));
    364 			break;
    365 		}
    366 
    367 		/* Report first time around... */
    368 		if (hsmsg == 0) {
    369 			printf("%s: initializing (may take some time)...\n",
    370 			    device_xname(mlx->mlx_dv));
    371 			hsmsg = 1;
    372 		}
    373 
    374 		/* Did we get a real message? */
    375 		if (hscode == 2) {
    376 			hscode = mlx_fw_message(mlx, hserr, hsparam1, hsparam2);
    377 
    378 			/* Fatal initialisation error? */
    379 			if (hscode != 0)
    380 				return;
    381 		}
    382 	}
    383 
    384 	/*
    385 	 * Do quirk/feature related things.
    386 	 */
    387 	ci = &mlx->mlx_ci;
    388 
    389 	if (ci->ci_iftype > 1) {
    390 		me2 = mlx_enquire(mlx, MLX_CMD_ENQUIRY2,
    391 		    sizeof(struct mlx_enquiry2), NULL, 0);
    392 		if (me2 == NULL) {
    393 			aprint_error_dev(mlx->mlx_dv, "ENQUIRY2 failed\n");
    394 			return;
    395 		}
    396 
    397 		ci->ci_firmware_id[0] = me2->me_firmware_id[0];
    398 		ci->ci_firmware_id[1] = me2->me_firmware_id[1];
    399 		ci->ci_firmware_id[2] = me2->me_firmware_id[2];
    400 		ci->ci_firmware_id[3] = me2->me_firmware_id[3];
    401 		ci->ci_hardware_id = me2->me_hardware_id[0];
    402 		ci->ci_mem_size = le32toh(me2->me_mem_size);
    403 		ci->ci_max_sg = le16toh(me2->me_max_sg);
    404 		ci->ci_max_commands = le16toh(me2->me_max_commands);
    405 		ci->ci_nchan = me2->me_actual_channels;
    406 
    407 		free(me2, M_DEVBUF);
    408 	}
    409 
    410 	if (ci->ci_iftype <= 2) {
    411 		/*
    412 		 * These controllers may not report the firmware version in
    413 		 * the ENQUIRY2 response, or may not even support it.
    414 		 */
    415 		meo = mlx_enquire(mlx, MLX_CMD_ENQUIRY_OLD,
    416 		    sizeof(struct mlx_enquiry_old), NULL, 0);
    417 		if (meo == NULL) {
    418 			aprint_error_dev(mlx->mlx_dv, "ENQUIRY_OLD failed\n");
    419 			return;
    420 		}
    421 		ci->ci_firmware_id[0] = meo->me_fwmajor;
    422 		ci->ci_firmware_id[1] = meo->me_fwminor;
    423 		ci->ci_firmware_id[2] = 0;
    424 		ci->ci_firmware_id[3] = '0';
    425 
    426 		if (ci->ci_iftype == 1) {
    427 			ci->ci_hardware_id = 0;	/* XXX */
    428 			ci->ci_mem_size = 0;	/* XXX */
    429 			ci->ci_max_sg = 17;	/* XXX */
    430 			ci->ci_max_commands = meo->me_max_commands;
    431 		}
    432 
    433 		free(meo, M_DEVBUF);
    434 	}
    435 
    436 	wantfwstr = NULL;
    437 	fwminor = ci->ci_firmware_id[1];
    438 
    439 	switch (ci->ci_firmware_id[0]) {
    440 	case 2:
    441 		if (ci->ci_iftype == 1) {
    442 			if (fwminor < 14)
    443 				wantfwstr = "2.14";
    444 		} else if (fwminor < 42)
    445 			wantfwstr = "2.42";
    446 		break;
    447 
    448 	case 3:
    449 		if (fwminor < 51)
    450 			wantfwstr = "3.51";
    451 		break;
    452 
    453 	case 4:
    454 		if (fwminor < 6)
    455 			wantfwstr = "4.06";
    456 		break;
    457 
    458 	case 5:
    459 		if (fwminor < 7)
    460 			wantfwstr = "5.07";
    461 		break;
    462 	}
    463 
    464 	/* Print a little information about the controller. */
    465 	mlx_describe(mlx);
    466 
    467 	if (wantfwstr != NULL) {
    468 		printf("%s: WARNING: this f/w revision is not recommended\n",
    469 		    device_xname(mlx->mlx_dv));
    470 		printf("%s: WARNING: use revision %s or later\n",
    471 		    device_xname(mlx->mlx_dv), wantfwstr);
    472 	}
    473 
    474 	/* We don't (yet) know where the event log is up to. */
    475 	mlx->mlx_currevent = -1;
    476 
    477 	/* No user-requested background operation is in progress. */
    478 	mlx->mlx_bg = 0;
    479 	mlx->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
    480 
    481 	/* Set maximum number of queued commands for `regular' operations. */
    482 	mlx->mlx_max_queuecnt =
    483 	    uimin(ci->ci_max_commands, MLX_MAX_QUEUECNT) -
    484 	    MLX_NCCBS_CONTROL;
    485 #ifdef DIAGNOSTIC
    486 	if (mlx->mlx_max_queuecnt < MLX_NCCBS_CONTROL + MLX_MAX_DRIVES)
    487 		printf("%s: WARNING: few CCBs available\n",
    488 		    device_xname(mlx->mlx_dv));
    489 	if (ci->ci_max_sg < MLX_MAX_SEGS) {
    490 		aprint_error_dev(mlx->mlx_dv,
    491 		    "oops, not enough S/G segments\n");
    492 		return;
    493 	}
    494 #endif
    495 
    496 	/* Attach child devices and enable interrupts. */
    497 	mlx_configure(mlx, 0);
    498 	(*mlx->mlx_intaction)(mlx, 1);
    499 	mlx->mlx_flags |= MLXF_INITOK;
    500 
    501 	if (mlx_sdh == NULL) {
    502 		/*
    503 		 * Set our `shutdownhook' before we start any device
    504 		 * activity.
    505 		 */
    506 		mlx_sdh = shutdownhook_establish(mlx_shutdown, NULL);
    507 
    508 		/* Create a status monitoring thread. */
    509 		rv = kthread_create(PRI_NONE, 0, NULL, mlx_periodic_thread,
    510 		    NULL, &mlx_periodic_lwp, "mlxtask");
    511 		if (rv != 0)
    512 			aprint_error_dev(mlx->mlx_dv,
    513 			    "mlx_init: unable to create thread (%d)\n", rv);
    514 	}
    515 }
    516 
    517 /*
    518  * Tell the world about the controller.
    519  */
    520 static void
    521 mlx_describe(struct mlx_softc *mlx)
    522 {
    523 	struct mlx_cinfo *ci;
    524 	static char tbuf[80];
    525 	const char *model;
    526 	int i;
    527 
    528 	model = NULL;
    529 	ci = &mlx->mlx_ci;
    530 
    531 	for (i = 0; i < sizeof(mlx_cname) / sizeof(mlx_cname[0]); i++)
    532 		if (ci->ci_hardware_id == mlx_cname[i].hwid) {
    533 			model = mlx_cname[i].name;
    534 			break;
    535 		}
    536 
    537 	if (model == NULL) {
    538 		snprintf(tbuf, sizeof(tbuf), " model 0x%x", ci->ci_hardware_id);
    539 		model = tbuf;
    540 	}
    541 
    542 	printf("%s: DAC%s, %d channel%s, firmware %d.%02d-%c-%02d",
    543 	    device_xname(mlx->mlx_dv), model, ci->ci_nchan,
    544 	    ci->ci_nchan > 1 ? "s" : "",
    545 	    ci->ci_firmware_id[0], ci->ci_firmware_id[1],
    546 	    ci->ci_firmware_id[3], ci->ci_firmware_id[2]);
    547 	if (ci->ci_mem_size != 0)
    548 		printf(", %dMB RAM", ci->ci_mem_size >> 20);
    549 	printf("\n");
    550 }
    551 
    552 /*
    553  * Locate disk resources and attach children to them.
    554  */
    555 int
    556 mlx_configure(struct mlx_softc *mlx, int waitok)
    557 {
    558 	struct mlx_enquiry *me;
    559 	struct mlx_enquiry_old *meo;
    560 	struct mlx_enq_sys_drive *mes;
    561 	struct mlx_sysdrive *ms;
    562 	struct mlx_attach_args mlxa;
    563 	int i, nunits;
    564 	u_int size;
    565 	int locs[MLXCF_NLOCS];
    566 
    567 	mlx->mlx_flags |= MLXF_RESCANNING;
    568 
    569 	if (mlx->mlx_ci.ci_iftype <= 2) {
    570 		meo = mlx_enquire(mlx, MLX_CMD_ENQUIRY_OLD,
    571 		    sizeof(struct mlx_enquiry_old), NULL, waitok);
    572 		if (meo == NULL) {
    573 			aprint_error_dev(mlx->mlx_dv, "ENQUIRY_OLD failed\n");
    574 			goto out;
    575 		}
    576 		mlx->mlx_numsysdrives = meo->me_num_sys_drvs;
    577 		free(meo, M_DEVBUF);
    578 	} else {
    579 		me = mlx_enquire(mlx, MLX_CMD_ENQUIRY,
    580 		    sizeof(struct mlx_enquiry), NULL, waitok);
    581 		if (me == NULL) {
    582 			aprint_error_dev(mlx->mlx_dv, "ENQUIRY failed\n");
    583 			goto out;
    584 		}
    585 		mlx->mlx_numsysdrives = me->me_num_sys_drvs;
    586 		free(me, M_DEVBUF);
    587 	}
    588 
    589 	mes = mlx_enquire(mlx, MLX_CMD_ENQSYSDRIVE,
    590 	    sizeof(*mes) * MLX_MAX_DRIVES, NULL, waitok);
    591 	if (mes == NULL) {
    592 		aprint_error_dev(mlx->mlx_dv, "error fetching drive status\n");
    593 		goto out;
    594 	}
    595 
    596 	/* Allow 1 queued command per unit while re-configuring. */
    597 	mlx_adjqparam(mlx, 1, 0);
    598 
    599 	ms = &mlx->mlx_sysdrive[0];
    600 	nunits = 0;
    601 	for (i = 0; i < MLX_MAX_DRIVES; i++, ms++) {
    602 		size = le32toh(mes[i].sd_size);
    603 		ms->ms_state = mes[i].sd_state;
    604 
    605 		/*
    606 		 * If an existing device has changed in some way (e.g. no
    607 		 * longer present) then detach it.
    608 		 */
    609 		if (ms->ms_dv != NULL && (size != ms->ms_size ||
    610 		    (mes[i].sd_raidlevel & 0xf) != ms->ms_raidlevel))
    611 			config_detach(ms->ms_dv, DETACH_FORCE);
    612 
    613 		ms->ms_size = size;
    614 		ms->ms_raidlevel = mes[i].sd_raidlevel & 0xf;
    615 		ms->ms_state = mes[i].sd_state;
    616 		ms->ms_dv = NULL;
    617 
    618 		if (i >= mlx->mlx_numsysdrives)
    619 			continue;
    620 		if (size == 0xffffffffU || size == 0)
    621 			continue;
    622 
    623 		/*
    624 		 * Attach a new device.
    625 		 */
    626 		mlxa.mlxa_unit = i;
    627 
    628 		locs[MLXCF_UNIT] = i;
    629 
    630 		ms->ms_dv = config_found(mlx->mlx_dv, &mlxa, mlx_print,
    631 		    CFARG_SUBMATCH, config_stdsubmatch,
    632 		    CFARG_LOCATORS, locs,
    633 		    CFARG_EOL);
    634 		nunits += (ms->ms_dv != NULL);
    635 	}
    636 
    637 	free(mes, M_DEVBUF);
    638 
    639 	if (nunits != 0)
    640 		mlx_adjqparam(mlx, mlx->mlx_max_queuecnt / nunits,
    641 		    mlx->mlx_max_queuecnt % nunits);
    642  out:
    643  	mlx->mlx_flags &= ~MLXF_RESCANNING;
    644 
    645 	return 0;
    646 }
    647 
    648 /*
    649  * Print autoconfiguration message for a sub-device.
    650  */
    651 static int
    652 mlx_print(void *aux, const char *pnp)
    653 {
    654 	struct mlx_attach_args *mlxa;
    655 
    656 	mlxa = (struct mlx_attach_args *)aux;
    657 
    658 	if (pnp != NULL)
    659 		aprint_normal("block device at %s", pnp);
    660 	aprint_normal(" unit %d", mlxa->mlxa_unit);
    661 	return (UNCONF);
    662 }
    663 
    664 /*
    665  * Shut down all configured `mlx' devices.
    666  */
    667 static void
    668 mlx_shutdown(void *cookie)
    669 {
    670 	struct mlx_softc *mlx;
    671 	int i;
    672 
    673 	for (i = 0; i < mlx_cd.cd_ndevs; i++)
    674 		if ((mlx = device_lookup_private(&mlx_cd, i)) != NULL)
    675 			mlx_flush(mlx, 0);
    676 }
    677 
    678 /*
    679  * Adjust queue parameters for all child devices.
    680  */
    681 static void
    682 mlx_adjqparam(struct mlx_softc *mlx, int mpu, int slop)
    683 {
    684 #if NLD > 0
    685 	struct ld_softc *ld;
    686 	int i;
    687 
    688 	for (i = 0; i < ld_cd.cd_ndevs; i++) {
    689 		if ((ld = device_lookup_private(&ld_cd, i)) == NULL)
    690 			continue;
    691 		if (device_parent(ld->sc_dv) != mlx->mlx_dv)
    692 			continue;
    693 		ldadjqparam(ld, mpu + (slop-- > 0));
    694 	}
    695 #endif
    696 }
    697 
    698 /*
    699  * Accept an open operation on the control device.
    700  */
    701 int
    702 mlxopen(dev_t dev, int flag, int mode, struct lwp *l)
    703 {
    704 	struct mlx_softc *mlx;
    705 
    706 	if ((mlx = device_lookup_private(&mlx_cd, minor(dev))) == NULL)
    707 		return (ENXIO);
    708 	if ((mlx->mlx_flags & MLXF_INITOK) == 0)
    709 		return (ENXIO);
    710 	if ((mlx->mlx_flags & MLXF_OPEN) != 0)
    711 		return (EBUSY);
    712 
    713 	mlx->mlx_flags |= MLXF_OPEN;
    714 	return (0);
    715 }
    716 
    717 /*
    718  * Accept the last close on the control device.
    719  */
    720 int
    721 mlxclose(dev_t dev, int flag, int mode, struct lwp *l)
    722 {
    723 	struct mlx_softc *mlx;
    724 
    725 	mlx = device_lookup_private(&mlx_cd, minor(dev));
    726 	mlx->mlx_flags &= ~MLXF_OPEN;
    727 	return (0);
    728 }
    729 
    730 /*
    731  * Handle control operations.
    732  */
    733 int
    734 mlxioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
    735 {
    736 	struct mlx_softc *mlx;
    737 	struct mlx_rebuild_request *rb;
    738 	struct mlx_rebuild_status *rs;
    739 	struct mlx_pause *mp;
    740 	struct mlx_sysdrive *ms;
    741 	int i, rv, *arg, result;
    742 
    743 	mlx = device_lookup_private(&mlx_cd, minor(dev));
    744 
    745 	rb = (struct mlx_rebuild_request *)data;
    746 	rs = (struct mlx_rebuild_status *)data;
    747 	arg = (int *)data;
    748 	rv = 0;
    749 
    750 	switch (cmd) {
    751 	case MLX_RESCAN_DRIVES:
    752 		/*
    753 		 * Scan the controller to see whether new drives have
    754 		 * appeared, or old ones disappeared.
    755 		 */
    756 		mlx_configure(mlx, 1);
    757 		return (0);
    758 
    759 	case MLX_PAUSE_CHANNEL:
    760 		/*
    761 		 * Pause one or more SCSI channels for a period of time, to
    762 		 * assist in the process of hot-swapping devices.
    763 		 *
    764 		 * Note that at least the 3.51 firmware on the DAC960PL
    765 		 * doesn't seem to do this right.
    766 		 */
    767 		if ((mlx->mlx_flags & MLXF_PAUSEWORKS) == 0)
    768 			return (EOPNOTSUPP);
    769 
    770 		mp = (struct mlx_pause *)data;
    771 
    772 		if ((mp->mp_which == MLX_PAUSE_CANCEL) &&
    773 		    (mlx->mlx_pause.mp_when != 0)) {
    774 			/* Cancel a pending pause operation. */
    775 			mlx->mlx_pause.mp_which = 0;
    776 			break;
    777 		}
    778 
    779 		/* Fix for legal channels. */
    780 		mp->mp_which &= ((1 << mlx->mlx_ci.ci_nchan) -1);
    781 
    782 		/* Check time values. */
    783 		if (mp->mp_when < 0 || mp->mp_when > 3600 ||
    784 		    mp->mp_howlong < 1 || mp->mp_howlong > (0xf * 30)) {
    785 			rv = EINVAL;
    786 			break;
    787 		}
    788 
    789 		/* Check for a pause currently running. */
    790 		if ((mlx->mlx_pause.mp_which != 0) &&
    791 		    (mlx->mlx_pause.mp_when == 0)) {
    792 			rv = EBUSY;
    793 			break;
    794 		}
    795 
    796 		/* Looks ok, go with it. */
    797 		mlx->mlx_pause.mp_which = mp->mp_which;
    798 		mlx->mlx_pause.mp_when = time_second + mp->mp_when;
    799 		mlx->mlx_pause.mp_howlong =
    800 		    mlx->mlx_pause.mp_when + mp->mp_howlong;
    801 
    802 		return (0);
    803 
    804 	case MLX_COMMAND:
    805 		rv = kauth_authorize_device_passthru(l->l_cred, dev,
    806 		    KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL, data);
    807 		if (rv)
    808 			return (rv);
    809 
    810 		/*
    811 		 * Accept a command passthrough-style.
    812 		 */
    813 		return (mlx_user_command(mlx, (struct mlx_usercommand *)data));
    814 
    815 	case MLX_REBUILDASYNC:
    816 		/*
    817 		 * Start a rebuild on a given SCSI disk
    818 		 */
    819 		if (mlx->mlx_bg != 0) {
    820 			rb->rr_status = 0x0106;
    821 			rv = EBUSY;
    822 			break;
    823 		}
    824 
    825 		rb->rr_status = mlx_rebuild(mlx, rb->rr_channel, rb->rr_target);
    826 		switch (rb->rr_status) {
    827 		case 0:
    828 			rv = 0;
    829 			break;
    830 		case 0x10000:
    831 			rv = ENOMEM;	/* Couldn't set up the command. */
    832 			break;
    833 		case 0x0002:
    834 			rv = EBUSY;
    835 			break;
    836 		case 0x0104:
    837 			rv = EIO;
    838 			break;
    839 		case 0x0105:
    840 			rv = ERANGE;
    841 			break;
    842 		case 0x0106:
    843 			rv = EBUSY;
    844 			break;
    845 		default:
    846 			rv = EINVAL;
    847 			break;
    848 		}
    849 
    850 		if (rv == 0)
    851 			mlx->mlx_bg = MLX_BG_REBUILD;
    852 
    853 		return (0);
    854 
    855 	case MLX_REBUILDSTAT:
    856 		/*
    857 		 * Get the status of the current rebuild or consistency check.
    858 		 */
    859 		*rs = mlx->mlx_rebuildstat;
    860 		return (0);
    861 
    862 	case MLX_GET_SYSDRIVE:
    863 		/*
    864 		 * Return the system drive number matching the `ld' device
    865 		 * unit in (arg), if it happens to belong to us.
    866 		 */
    867 		for (i = 0; i < MLX_MAX_DRIVES; i++) {
    868 			ms = &mlx->mlx_sysdrive[i];
    869 			if (ms->ms_dv != NULL)
    870 				if (device_xname(ms->ms_dv)[2] == '0' + *arg) {
    871 					*arg = i;
    872 					return (0);
    873 				}
    874 		}
    875 		return (ENOENT);
    876 
    877 	case MLX_GET_CINFO:
    878 		/*
    879 		 * Return controller info.
    880 		 */
    881 		memcpy(arg, &mlx->mlx_ci, sizeof(mlx->mlx_ci));
    882 		return (0);
    883 	}
    884 
    885 	switch (cmd) {
    886 	case MLXD_DETACH:
    887 	case MLXD_STATUS:
    888 	case MLXD_CHECKASYNC:
    889 		if ((u_int)*arg >= MLX_MAX_DRIVES)
    890 			return (EINVAL);
    891 		ms = &mlx->mlx_sysdrive[*arg];
    892 		if (*arg > MLX_MAX_DRIVES || ms->ms_dv == NULL)
    893 			return (ENOENT);
    894 		break;
    895 
    896 	default:
    897 		return (ENOTTY);
    898 	}
    899 
    900 	switch (cmd) {
    901 	case MLXD_DETACH:
    902 		/*
    903 		 * Disconnect from the specified drive; it may be about to go
    904 		 * away.
    905 		 */
    906 		return (config_detach(ms->ms_dv, 0));
    907 
    908 	case MLXD_STATUS:
    909 		/*
    910 		 * Return the current status of this drive.
    911 		 */
    912 		*arg = ms->ms_state;
    913 		return (0);
    914 
    915 	case MLXD_CHECKASYNC:
    916 		/*
    917 		 * Start a background consistency check on this drive.
    918 		 */
    919 		if (mlx->mlx_bg != 0) {
    920 			*arg = 0x0106;
    921 			return (EBUSY);
    922 		}
    923 
    924 		switch (result = mlx_check(mlx, *arg)) {
    925 		case 0:
    926 			rv = 0;
    927 			break;
    928 		case 0x10000:
    929 			rv = ENOMEM;	/* Couldn't set up the command. */
    930 			break;
    931 		case 0x0002:
    932 			rv = EIO;
    933 			break;
    934 		case 0x0105:
    935 			rv = ERANGE;
    936 			break;
    937 		case 0x0106:
    938 			rv = EBUSY;
    939 			break;
    940 		default:
    941 			rv = EINVAL;
    942 			break;
    943 		}
    944 
    945 		if (rv == 0)
    946 			mlx->mlx_bg = MLX_BG_CHECK;
    947 		*arg = result;
    948 		return (rv);
    949 	}
    950 
    951 	return (ENOTTY);	/* XXX shut up gcc */
    952 }
    953 
    954 static void
    955 mlx_periodic_thread(void *cookie)
    956 {
    957 	struct mlx_softc *mlx;
    958 	int i;
    959 
    960 	for (;;) {
    961 		for (i = 0; i < mlx_cd.cd_ndevs; i++)
    962 			if ((mlx = device_lookup_private(&mlx_cd, i)) != NULL)
    963 				if (mlx->mlx_ci.ci_iftype > 1)
    964 					mlx_periodic(mlx);
    965 
    966 		tsleep(mlx_periodic_thread, PWAIT, "mlxzzz", hz * 2);
    967 	}
    968 }
    969 
    970 static void
    971 mlx_periodic(struct mlx_softc *mlx)
    972 {
    973 	struct mlx_ccb *mc, *nmc;
    974 	int etype, s;
    975 
    976 	if ((mlx->mlx_pause.mp_which != 0) &&
    977 	    (mlx->mlx_pause.mp_when > 0) &&
    978 	    (time_second >= mlx->mlx_pause.mp_when)) {
    979 	    	/*
    980 	    	 * Start bus pause.
    981 	    	 */
    982 		mlx_pause_action(mlx);
    983 		mlx->mlx_pause.mp_when = 0;
    984 	} else if ((mlx->mlx_pause.mp_which != 0) &&
    985 		   (mlx->mlx_pause.mp_when == 0)) {
    986 		/*
    987 		 * Stop pause if required.
    988 		 */
    989 		if (time_second >= mlx->mlx_pause.mp_howlong) {
    990 			mlx_pause_action(mlx);
    991 			mlx->mlx_pause.mp_which = 0;
    992 		}
    993 	} else if (time_second > (mlx->mlx_lastpoll + 10)) {
    994 		/*
    995 		 * Run normal periodic activities...
    996 		 */
    997 		mlx->mlx_lastpoll = time_second;
    998 
    999 		/*
   1000 		 * Check controller status.
   1001 		 */
   1002 		if ((mlx->mlx_flags & MLXF_PERIODIC_CTLR) == 0) {
   1003 			mlx->mlx_flags |= MLXF_PERIODIC_CTLR;
   1004 
   1005 			if (mlx->mlx_ci.ci_iftype <= 2)
   1006 				etype = MLX_CMD_ENQUIRY_OLD;
   1007 			else
   1008 				etype =  MLX_CMD_ENQUIRY;
   1009 
   1010 			mlx_enquire(mlx, etype, uimax(sizeof(struct mlx_enquiry),
   1011 			    sizeof(struct mlx_enquiry_old)),
   1012 			    mlx_periodic_enquiry, 1);
   1013 		}
   1014 
   1015 		/*
   1016 		 * Check system drive status.
   1017 		 */
   1018 		if ((mlx->mlx_flags & MLXF_PERIODIC_DRIVE) == 0) {
   1019 			mlx->mlx_flags |= MLXF_PERIODIC_DRIVE;
   1020 			mlx_enquire(mlx, MLX_CMD_ENQSYSDRIVE,
   1021 			    sizeof(struct mlx_enq_sys_drive) * MLX_MAX_DRIVES,
   1022 			    mlx_periodic_enquiry, 1);
   1023 		}
   1024 	}
   1025 
   1026 	/*
   1027 	 * Get drive rebuild/check status.
   1028 	 */
   1029 	if ((mlx->mlx_flags & MLXF_PERIODIC_REBUILD) == 0) {
   1030 		mlx->mlx_flags |= MLXF_PERIODIC_REBUILD;
   1031 		mlx_enquire(mlx, MLX_CMD_REBUILDSTAT,
   1032 		    sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild, 1);
   1033 	}
   1034 
   1035 	/*
   1036 	 * Time-out busy CCBs.
   1037 	 */
   1038 	s = splbio();
   1039 	for (mc = TAILQ_FIRST(&mlx->mlx_ccb_worklist); mc != NULL; mc = nmc) {
   1040 		nmc = TAILQ_NEXT(mc, mc_chain.tailq);
   1041 		if (mc->mc_expiry > time_second) {
   1042 			/*
   1043 			 * The remaining CCBs will expire after this one, so
   1044 			 * there's no point in going further.
   1045 			 */
   1046 			break;
   1047 		}
   1048 		TAILQ_REMOVE(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq);
   1049 		mc->mc_status = MLX_STATUS_LOST;
   1050 		if (mc->mc_mx.mx_handler != NULL)
   1051 			(*mc->mc_mx.mx_handler)(mc);
   1052 		else if ((mc->mc_flags & MC_WAITING) != 0)
   1053 			wakeup(mc);
   1054 	}
   1055 	splx(s);
   1056 }
   1057 
   1058 /*
   1059  * Handle the result of an ENQUIRY command instigated by periodic status
   1060  * polling.
   1061  */
   1062 static void
   1063 mlx_periodic_enquiry(struct mlx_ccb *mc)
   1064 {
   1065 	struct mlx_softc *mlx;
   1066 	struct mlx_enquiry *me;
   1067 	struct mlx_enquiry_old *meo;
   1068 	struct mlx_enq_sys_drive *mes;
   1069 	struct mlx_sysdrive *dr;
   1070 	const char *statestr;
   1071 	int i, j;
   1072 	u_int lsn;
   1073 
   1074 	mlx = device_private(mc->mc_mx.mx_dv);
   1075 	mlx_ccb_unmap(mlx, mc);
   1076 
   1077 	/*
   1078 	 * Command completed OK?
   1079 	 */
   1080 	if (mc->mc_status != 0) {
   1081 		aprint_error_dev(mlx->mlx_dv, "periodic enquiry failed - %s\n",
   1082 		    mlx_ccb_diagnose(mc));
   1083 		goto out;
   1084 	}
   1085 
   1086 	/*
   1087 	 * Respond to command.
   1088 	 */
   1089 	switch (mc->mc_mbox[0]) {
   1090 	case MLX_CMD_ENQUIRY_OLD:
   1091 		/*
   1092 		 * This is currently a bit fruitless, as we don't know how
   1093 		 * to extract the eventlog pointer yet.
   1094 		 */
   1095 		me = (struct mlx_enquiry *)mc->mc_mx.mx_context;
   1096 		meo = (struct mlx_enquiry_old *)mc->mc_mx.mx_context;
   1097 
   1098 		/* Convert data in-place to new format */
   1099 		i = sizeof(me->me_dead) / sizeof(me->me_dead[0]);
   1100 		while (--i >= 0) {
   1101 			me->me_dead[i].dd_chan = meo->me_dead[i].dd_chan;
   1102 			me->me_dead[i].dd_targ = meo->me_dead[i].dd_targ;
   1103 		}
   1104 
   1105 		me->me_misc_flags = 0;
   1106 		me->me_rebuild_count = meo->me_rebuild_count;
   1107 		me->me_dead_count = meo->me_dead_count;
   1108 		me->me_critical_sd_count = meo->me_critical_sd_count;
   1109 		me->me_event_log_seq_num = 0;
   1110 		me->me_offline_sd_count = meo->me_offline_sd_count;
   1111 		me->me_max_commands = meo->me_max_commands;
   1112 		me->me_rebuild_flag = meo->me_rebuild_flag;
   1113 		me->me_fwmajor = meo->me_fwmajor;
   1114 		me->me_fwminor = meo->me_fwminor;
   1115 		me->me_status_flags = meo->me_status_flags;
   1116 		me->me_flash_age = meo->me_flash_age;
   1117 
   1118 		i = sizeof(me->me_drvsize) / sizeof(me->me_drvsize[0]);
   1119 		j = sizeof(meo->me_drvsize) / sizeof(meo->me_drvsize[0]);
   1120 
   1121 		while (--i >= 0) {
   1122 			if (i >= j)
   1123 				me->me_drvsize[i] = 0;
   1124 			else
   1125 				me->me_drvsize[i] = meo->me_drvsize[i];
   1126 		}
   1127 
   1128 		me->me_num_sys_drvs = meo->me_num_sys_drvs;
   1129 
   1130 		/* FALLTHROUGH */
   1131 
   1132 	case MLX_CMD_ENQUIRY:
   1133 		/*
   1134 		 * Generic controller status update.  We could do more with
   1135 		 * this than just checking the event log.
   1136 		 */
   1137 		me = (struct mlx_enquiry *)mc->mc_mx.mx_context;
   1138 		lsn = le16toh(me->me_event_log_seq_num);
   1139 
   1140 		if (mlx->mlx_currevent == -1) {
   1141 			/* Initialise our view of the event log. */
   1142 			mlx->mlx_currevent = lsn;
   1143 			mlx->mlx_lastevent = lsn;
   1144 		} else if (lsn != mlx->mlx_lastevent &&
   1145 			   (mlx->mlx_flags & MLXF_EVENTLOG_BUSY) == 0) {
   1146 			/* Record where current events are up to */
   1147 			mlx->mlx_currevent = lsn;
   1148 
   1149 			/* Mark the event log as busy. */
   1150 			mlx->mlx_flags |= MLXF_EVENTLOG_BUSY;
   1151 
   1152 			/* Drain new eventlog entries. */
   1153 			mlx_periodic_eventlog_poll(mlx);
   1154 		}
   1155 		break;
   1156 
   1157 	case MLX_CMD_ENQSYSDRIVE:
   1158 		/*
   1159 		 * Perform drive status comparison to see if something
   1160 		 * has failed.  Don't perform the comparison if we're
   1161 		 * reconfiguring, since the system drive table will be
   1162 		 * changing.
   1163 		 */
   1164 		if ((mlx->mlx_flags & MLXF_RESCANNING) != 0)
   1165 			break;
   1166 
   1167 		mes = (struct mlx_enq_sys_drive *)mc->mc_mx.mx_context;
   1168 		dr = &mlx->mlx_sysdrive[0];
   1169 
   1170 		for (i = 0; i < mlx->mlx_numsysdrives; i++, dr++) {
   1171 			/* Has state been changed by controller? */
   1172 			if (dr->ms_state != mes[i].sd_state) {
   1173 				switch (mes[i].sd_state) {
   1174 				case MLX_SYSD_OFFLINE:
   1175 					statestr = "offline";
   1176 					break;
   1177 
   1178 				case MLX_SYSD_ONLINE:
   1179 					statestr = "online";
   1180 					break;
   1181 
   1182 				case MLX_SYSD_CRITICAL:
   1183 					statestr = "critical";
   1184 					break;
   1185 
   1186 				default:
   1187 					statestr = "unknown";
   1188 					break;
   1189 				}
   1190 
   1191 				printf("%s: unit %d %s\n",
   1192 				    device_xname(mlx->mlx_dv), i, statestr);
   1193 
   1194 				/* Save new state. */
   1195 				dr->ms_state = mes[i].sd_state;
   1196 			}
   1197 		}
   1198 		break;
   1199 
   1200 #ifdef DIAGNOSTIC
   1201 	default:
   1202 		printf("%s: mlx_periodic_enquiry: eh?\n",
   1203 		    device_xname(mlx->mlx_dv));
   1204 		break;
   1205 #endif
   1206 	}
   1207 
   1208  out:
   1209 	if (mc->mc_mbox[0] == MLX_CMD_ENQSYSDRIVE)
   1210 		mlx->mlx_flags &= ~MLXF_PERIODIC_DRIVE;
   1211 	else
   1212 		mlx->mlx_flags &= ~MLXF_PERIODIC_CTLR;
   1213 
   1214 	free(mc->mc_mx.mx_context, M_DEVBUF);
   1215 	mlx_ccb_free(mlx, mc);
   1216 }
   1217 
   1218 /*
   1219  * Instigate a poll for one event log message on (mlx).  We only poll for
   1220  * one message at a time, to keep our command usage down.
   1221  */
   1222 static void
   1223 mlx_periodic_eventlog_poll(struct mlx_softc *mlx)
   1224 {
   1225 	struct mlx_ccb *mc;
   1226 	void *result;
   1227 	int rv;
   1228 
   1229 	result = NULL;
   1230 
   1231 	if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0)
   1232 		goto out;
   1233 
   1234 	if ((result = malloc(1024, M_DEVBUF, M_WAITOK)) == NULL) {
   1235 		rv = ENOMEM;
   1236 		goto out;
   1237 	}
   1238 	if ((rv = mlx_ccb_map(mlx, mc, result, 1024, MC_XFER_IN)) != 0)
   1239 		goto out;
   1240 	if (mc->mc_nsgent != 1) {
   1241 		mlx_ccb_unmap(mlx, mc);
   1242 		printf("mlx_periodic_eventlog_poll: too many segs\n");
   1243 		goto out;
   1244 	}
   1245 
   1246 	/* Build the command to get one log entry. */
   1247 	mlx_make_type3(mc, MLX_CMD_LOGOP, MLX_LOGOP_GET, 1,
   1248 	    mlx->mlx_lastevent, 0, 0, mc->mc_xfer_phys, 0);
   1249 
   1250 	mc->mc_mx.mx_handler = mlx_periodic_eventlog_respond;
   1251 	mc->mc_mx.mx_dv = mlx->mlx_dv;
   1252 	mc->mc_mx.mx_context = result;
   1253 
   1254 	/* Start the command. */
   1255 	mlx_ccb_enqueue(mlx, mc);
   1256 
   1257  out:
   1258 	if (rv != 0) {
   1259 		if (mc != NULL)
   1260 			mlx_ccb_free(mlx, mc);
   1261 		if (result != NULL)
   1262 			free(result, M_DEVBUF);
   1263 	}
   1264 }
   1265 
   1266 /*
   1267  * Handle the result of polling for a log message, generate diagnostic
   1268  * output.  If this wasn't the last message waiting for us, we'll go collect
   1269  * another.
   1270  */
   1271 static void
   1272 mlx_periodic_eventlog_respond(struct mlx_ccb *mc)
   1273 {
   1274 	struct mlx_softc *mlx;
   1275 	struct mlx_eventlog_entry *el;
   1276 	const char *reason;
   1277 	u_int8_t sensekey, chan, targ;
   1278 
   1279 	mlx = device_private(mc->mc_mx.mx_dv);
   1280 	el = mc->mc_mx.mx_context;
   1281 	mlx_ccb_unmap(mlx, mc);
   1282 
   1283 	mlx->mlx_lastevent++;
   1284 
   1285 	if (mc->mc_status == 0) {
   1286 		switch (el->el_type) {
   1287 		case MLX_LOGMSG_SENSE:		/* sense data */
   1288 			sensekey = el->el_sense & 0x0f;
   1289 			chan = (el->el_target >> 4) & 0x0f;
   1290 			targ = el->el_target & 0x0f;
   1291 
   1292 			/*
   1293 			 * This is the only sort of message we understand at
   1294 			 * the moment.  The tests here are probably
   1295 			 * incomplete.
   1296 			 */
   1297 
   1298 			/*
   1299 			 * Mylex vendor-specific message indicating a drive
   1300 			 * was killed?
   1301 			 */
   1302 			if (sensekey == 9 && el->el_asc == 0x80) {
   1303 				if (el->el_asq < sizeof(mlx_sense_msgs) /
   1304 				    sizeof(mlx_sense_msgs[0]))
   1305 					reason = mlx_sense_msgs[el->el_asq];
   1306 				else
   1307 					reason = "for unknown reason";
   1308 
   1309 				printf("%s: physical drive %d:%d killed %s\n",
   1310 				    device_xname(mlx->mlx_dv), chan, targ,
   1311 				    reason);
   1312 			}
   1313 
   1314 			/*
   1315 			 * SCSI drive was reset?
   1316 			 */
   1317 			if (sensekey == 6 && el->el_asc == 0x29)
   1318 				printf("%s: physical drive %d:%d reset\n",
   1319 				    device_xname(mlx->mlx_dv), chan, targ);
   1320 
   1321 			/*
   1322 			 * SCSI drive error?
   1323 			 */
   1324 			if (!(sensekey == 0 ||
   1325 			    (sensekey == 2 &&
   1326 			    el->el_asc == 0x04 &&
   1327 			    (el->el_asq == 0x01 || el->el_asq == 0x02)))) {
   1328 				printf("%s: physical drive %d:%d error log: "
   1329 				    "sense = %d asc = %x asq = %x\n",
   1330 				    device_xname(mlx->mlx_dv), chan, targ,
   1331 				    sensekey, el->el_asc, el->el_asq);
   1332 				printf("%s:   info = %d:%d:%d:%d "
   1333 				    " csi = %d:%d:%d:%d\n",
   1334 				    device_xname(mlx->mlx_dv),
   1335 				    el->el_information[0],
   1336 				    el->el_information[1],
   1337 				    el->el_information[2],
   1338 				    el->el_information[3],
   1339 				    el->el_csi[0], el->el_csi[1],
   1340 				    el->el_csi[2], el->el_csi[3]);
   1341 			}
   1342 
   1343 			break;
   1344 
   1345 		default:
   1346 			aprint_error_dev(mlx->mlx_dv,
   1347 			    "unknown log message type 0x%x\n", el->el_type);
   1348 			break;
   1349 		}
   1350 	} else {
   1351 		aprint_error_dev(mlx->mlx_dv,
   1352 		    "error reading message log - %s\n", mlx_ccb_diagnose(mc));
   1353 
   1354 		/*
   1355 		 * Give up on all the outstanding messages, as we may have
   1356 		 * come unsynched.
   1357 		 */
   1358 		mlx->mlx_lastevent = mlx->mlx_currevent;
   1359 	}
   1360 
   1361 	free(mc->mc_mx.mx_context, M_DEVBUF);
   1362 	mlx_ccb_free(mlx, mc);
   1363 
   1364 	/*
   1365 	 * Is there another message to obtain?
   1366 	 */
   1367 	if (mlx->mlx_lastevent != mlx->mlx_currevent)
   1368 		mlx_periodic_eventlog_poll(mlx);
   1369 	else
   1370 		mlx->mlx_flags &= ~MLXF_EVENTLOG_BUSY;
   1371 }
   1372 
   1373 /*
   1374  * Handle check/rebuild operations in progress.
   1375  */
   1376 static void
   1377 mlx_periodic_rebuild(struct mlx_ccb *mc)
   1378 {
   1379 	struct mlx_softc *mlx;
   1380 	const char *opstr;
   1381 	struct mlx_rebuild_status *mr;
   1382 
   1383 	mlx = device_private(mc->mc_mx.mx_dv);
   1384 	mr = mc->mc_mx.mx_context;
   1385 	mlx_ccb_unmap(mlx, mc);
   1386 
   1387 	switch (mc->mc_status) {
   1388 	case 0:
   1389 		/*
   1390 		 * Operation running, update stats.
   1391 		 */
   1392 		mlx->mlx_rebuildstat = *mr;
   1393 
   1394 		/* Spontaneous rebuild/check? */
   1395 		if (mlx->mlx_bg == 0) {
   1396 			mlx->mlx_bg = MLX_BG_SPONTANEOUS;
   1397 			printf("%s: background check/rebuild started\n",
   1398 			    device_xname(mlx->mlx_dv));
   1399 		}
   1400 		break;
   1401 
   1402 	case 0x0105:
   1403 		/*
   1404 		 * Nothing running, finalise stats and report.
   1405 		 */
   1406 		switch (mlx->mlx_bg) {
   1407 		case MLX_BG_CHECK:
   1408 			/* XXX Print drive? */
   1409 			opstr = "consistency check";
   1410 			break;
   1411 
   1412 		case MLX_BG_REBUILD:
   1413 			/* XXX Print channel:target? */
   1414 			opstr = "drive rebuild";
   1415 			break;
   1416 
   1417 		case MLX_BG_SPONTANEOUS:
   1418 		default:
   1419 			/*
   1420 			 * If we have previously been non-idle, report the
   1421 			 * transition
   1422 			 */
   1423 			if (mlx->mlx_rebuildstat.rs_code !=
   1424 			    MLX_REBUILDSTAT_IDLE)
   1425 				opstr = "background check/rebuild";
   1426 			else
   1427 				opstr = NULL;
   1428 		}
   1429 
   1430 		if (opstr != NULL)
   1431 			printf("%s: %s completed\n", device_xname(mlx->mlx_dv),
   1432 			    opstr);
   1433 
   1434 		mlx->mlx_bg = 0;
   1435 		mlx->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
   1436 		break;
   1437 	}
   1438 
   1439 	free(mc->mc_mx.mx_context, M_DEVBUF);
   1440 	mlx_ccb_free(mlx, mc);
   1441 	mlx->mlx_flags &= ~MLXF_PERIODIC_REBUILD;
   1442 }
   1443 
   1444 /*
   1445  * It's time to perform a channel pause action for (mlx), either start or
   1446  * stop the pause.
   1447  */
   1448 static void
   1449 mlx_pause_action(struct mlx_softc *mlx)
   1450 {
   1451 	struct mlx_ccb *mc;
   1452 	int failsafe, i, cmd;
   1453 
   1454 	/* What are we doing here? */
   1455 	if (mlx->mlx_pause.mp_when == 0) {
   1456 		cmd = MLX_CMD_STARTCHANNEL;
   1457 		failsafe = 0;
   1458 	} else {
   1459 		cmd = MLX_CMD_STOPCHANNEL;
   1460 
   1461 		/*
   1462 		 * Channels will always start again after the failsafe
   1463 		 * period, which is specified in multiples of 30 seconds.
   1464 		 * This constrains us to a maximum pause of 450 seconds.
   1465 		 */
   1466 		failsafe = ((mlx->mlx_pause.mp_howlong - time_second) + 5) / 30;
   1467 
   1468 		if (failsafe > 0xf) {
   1469 			failsafe = 0xf;
   1470 			mlx->mlx_pause.mp_howlong =
   1471 			     time_second + (0xf * 30) - 5;
   1472 		}
   1473 	}
   1474 
   1475 	/* Build commands for every channel requested. */
   1476 	for (i = 0; i < mlx->mlx_ci.ci_nchan; i++) {
   1477 		if ((1 << i) & mlx->mlx_pause.mp_which) {
   1478 			if (mlx_ccb_alloc(mlx, &mc, 1) != 0) {
   1479 				aprint_error_dev(mlx->mlx_dv,
   1480 				    "%s failed for channel %d\n",
   1481 				    cmd == MLX_CMD_STOPCHANNEL ?
   1482 				    "pause" : "resume", i);
   1483 				continue;
   1484 			}
   1485 
   1486 			/* Build the command. */
   1487 			mlx_make_type2(mc, cmd, (failsafe << 4) | i, 0, 0,
   1488 			    0, 0, 0, 0, 0);
   1489 			mc->mc_mx.mx_handler = mlx_pause_done;
   1490 			mc->mc_mx.mx_dv = mlx->mlx_dv;
   1491 
   1492 			mlx_ccb_enqueue(mlx, mc);
   1493 		}
   1494 	}
   1495 }
   1496 
   1497 static void
   1498 mlx_pause_done(struct mlx_ccb *mc)
   1499 {
   1500 	struct mlx_softc *mlx;
   1501 	int command, channel;
   1502 
   1503 	mlx = device_private(mc->mc_mx.mx_dv);
   1504 	command = mc->mc_mbox[0];
   1505 	channel = mc->mc_mbox[2] & 0xf;
   1506 
   1507 	if (mc->mc_status != 0)
   1508 		aprint_error_dev(mlx->mlx_dv, "%s command failed - %s\n",
   1509 		    command == MLX_CMD_STOPCHANNEL ? "pause" : "resume",
   1510 		    mlx_ccb_diagnose(mc));
   1511 	else if (command == MLX_CMD_STOPCHANNEL)
   1512 		printf("%s: channel %d pausing for %ld seconds\n",
   1513 		    device_xname(mlx->mlx_dv), channel,
   1514 		    (long)(mlx->mlx_pause.mp_howlong - time_second));
   1515 	else
   1516 		printf("%s: channel %d resuming\n", device_xname(mlx->mlx_dv),
   1517 		    channel);
   1518 
   1519 	mlx_ccb_free(mlx, mc);
   1520 }
   1521 
   1522 /*
   1523  * Perform an Enquiry command using a type-3 command buffer and a return a
   1524  * single linear result buffer.  If the completion function is specified, it
   1525  * will be called with the completed command (and the result response will
   1526  * not be valid until that point).  Otherwise, the command will either be
   1527  * busy-waited for (interrupts must be blocked), or slept for.
   1528  */
   1529 static void *
   1530 mlx_enquire(struct mlx_softc *mlx, int command, size_t bufsize,
   1531 	    void (*handler)(struct mlx_ccb *mc), int waitok)
   1532 {
   1533 	struct mlx_ccb *mc;
   1534 	void *result;
   1535 	int rv, mapped;
   1536 
   1537 	result = NULL;
   1538 	mapped = 0;
   1539 
   1540 	if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0)
   1541 		goto out;
   1542 
   1543 	result = malloc(bufsize, M_DEVBUF, waitok ? M_WAITOK : M_NOWAIT);
   1544 	if (result == NULL) {
   1545 		printf("mlx_enquire: malloc() failed\n");
   1546 		goto out;
   1547 	}
   1548 	if ((rv = mlx_ccb_map(mlx, mc, result, bufsize, MC_XFER_IN)) != 0)
   1549 		goto out;
   1550 	mapped = 1;
   1551 	if (mc->mc_nsgent != 1) {
   1552 		printf("mlx_enquire: too many segs\n");
   1553 		goto out;
   1554 	}
   1555 
   1556 	/* Build an enquiry command. */
   1557 	mlx_make_type2(mc, command, 0, 0, 0, 0, 0, 0, mc->mc_xfer_phys, 0);
   1558 
   1559 	/* Do we want a completion callback? */
   1560 	if (handler != NULL) {
   1561 		mc->mc_mx.mx_context = result;
   1562 		mc->mc_mx.mx_dv = mlx->mlx_dv;
   1563 		mc->mc_mx.mx_handler = handler;
   1564 		mlx_ccb_enqueue(mlx, mc);
   1565 	} else {
   1566 		/* Run the command in either polled or wait mode. */
   1567 		if (waitok)
   1568 			rv = mlx_ccb_wait(mlx, mc);
   1569 		else
   1570 			rv = mlx_ccb_poll(mlx, mc, 5000);
   1571 	}
   1572 
   1573  out:
   1574 	/* We got a command, but nobody else will free it. */
   1575 	if (handler == NULL && mc != NULL) {
   1576 		if (mapped)
   1577 			mlx_ccb_unmap(mlx, mc);
   1578 		mlx_ccb_free(mlx, mc);
   1579 	}
   1580 
   1581 	/* We got an error, and we allocated a result. */
   1582 	if (rv != 0 && result != NULL) {
   1583 		if (mc != NULL)
   1584 			mlx_ccb_free(mlx, mc);
   1585 		free(result, M_DEVBUF);
   1586 		result = NULL;
   1587 	}
   1588 
   1589 	return (result);
   1590 }
   1591 
   1592 /*
   1593  * Perform a Flush command on the nominated controller.
   1594  *
   1595  * May be called with interrupts enabled or disabled; will not return until
   1596  * the flush operation completes or fails.
   1597  */
   1598 int
   1599 mlx_flush(struct mlx_softc *mlx, int async)
   1600 {
   1601 	struct mlx_ccb *mc;
   1602 	int rv;
   1603 
   1604 	if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0)
   1605 		goto out;
   1606 
   1607 	/* Build a flush command and fire it off. */
   1608 	mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0);
   1609 
   1610 	if (async)
   1611 		rv = mlx_ccb_wait(mlx, mc);
   1612 	else
   1613 		rv = mlx_ccb_poll(mlx, mc, MLX_TIMEOUT * 1000);
   1614 	if (rv != 0)
   1615 		goto out;
   1616 
   1617 	/* Command completed OK? */
   1618 	if (mc->mc_status != 0) {
   1619 		aprint_error_dev(mlx->mlx_dv, "FLUSH failed - %s\n",
   1620 		    mlx_ccb_diagnose(mc));
   1621 		rv = EIO;
   1622 	}
   1623  out:
   1624 	if (mc != NULL)
   1625 		mlx_ccb_free(mlx, mc);
   1626 
   1627 	return (rv);
   1628 }
   1629 
   1630 /*
   1631  * Start a background consistency check on (drive).
   1632  */
   1633 static int
   1634 mlx_check(struct mlx_softc *mlx, int drive)
   1635 {
   1636 	struct mlx_ccb *mc;
   1637 	int rv;
   1638 
   1639 	/* Get ourselves a command buffer. */
   1640 	rv = 0x10000;
   1641 
   1642 	if (mlx_ccb_alloc(mlx, &mc, 1) != 0)
   1643 		goto out;
   1644 
   1645 	/* Build a checkasync command, set the "fix it" flag. */
   1646 	mlx_make_type2(mc, MLX_CMD_CHECKASYNC, 0, 0, 0, 0, 0, drive | 0x80,
   1647 	    0, 0);
   1648 
   1649 	/* Start the command and wait for it to be returned. */
   1650 	if (mlx_ccb_wait(mlx, mc) != 0)
   1651 		goto out;
   1652 
   1653 	/* Command completed OK? */
   1654 	if (mc->mc_status != 0)
   1655 		aprint_error_dev(mlx->mlx_dv, "CHECK ASYNC failed - %s\n",
   1656 		    mlx_ccb_diagnose(mc));
   1657 	else
   1658 		printf("%s: consistency check started",
   1659 		    device_xname(mlx->mlx_sysdrive[drive].ms_dv));
   1660 
   1661 	rv = mc->mc_status;
   1662  out:
   1663 	if (mc != NULL)
   1664 		mlx_ccb_free(mlx, mc);
   1665 
   1666 	return (rv);
   1667 }
   1668 
   1669 /*
   1670  * Start a background rebuild of the physical drive at (channel),(target).
   1671  *
   1672  * May be called with interrupts enabled or disabled; will return as soon as
   1673  * the operation has started or been refused.
   1674  */
   1675 static int
   1676 mlx_rebuild(struct mlx_softc *mlx, int channel, int target)
   1677 {
   1678 	struct mlx_ccb *mc;
   1679 	int error;
   1680 
   1681 	error = 0x10000;
   1682 	if (mlx_ccb_alloc(mlx, &mc, 1) != 0)
   1683 		goto out;
   1684 
   1685 	/* Build a rebuildasync command, set the "fix it" flag. */
   1686 	mlx_make_type2(mc, MLX_CMD_REBUILDASYNC, channel, target, 0, 0, 0, 0,
   1687 	    0, 0);
   1688 
   1689 	/* Start the command and wait for it to be returned. */
   1690 	if (mlx_ccb_wait(mlx, mc) != 0)
   1691 		goto out;
   1692 
   1693 	/* Command completed OK? */
   1694 	if (mc->mc_status != 0)
   1695 		aprint_normal_dev(mlx->mlx_dv, "REBUILD ASYNC failed - %s\n",
   1696 		    mlx_ccb_diagnose(mc));
   1697 	else
   1698 		aprint_normal_dev(mlx->mlx_dv, "rebuild started for %d:%d\n",
   1699 		    channel, target);
   1700 
   1701 	error = mc->mc_status;
   1702 
   1703  out:
   1704 	if (mc != NULL)
   1705 		mlx_ccb_free(mlx, mc);
   1706 
   1707 	return (error);
   1708 }
   1709 
   1710 /*
   1711  * Take a command from user-space and try to run it.
   1712  *
   1713  * XXX Note that this can't perform very much in the way of error checking,
   1714  * XXX and as such, applications _must_ be considered trustworthy.
   1715  *
   1716  * XXX Commands using S/G for data are not supported.
   1717  */
   1718 static int
   1719 mlx_user_command(struct mlx_softc *mlx, struct mlx_usercommand *mu)
   1720 {
   1721 	struct mlx_ccb *mc;
   1722 	struct mlx_dcdb *dcdb;
   1723 	void *kbuf;
   1724 	int rv, mapped;
   1725 
   1726 	if ((mu->mu_bufdir & ~MU_XFER_MASK) != 0)
   1727 		return (EINVAL);
   1728 
   1729 	kbuf = NULL;
   1730 	dcdb = NULL;
   1731 	mapped = 0;
   1732 
   1733 	/* Get ourselves a command and copy in from user space. */
   1734 	if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0) {
   1735 		DPRINTF(("mlx_user_command: mlx_ccb_alloc = %d\n", rv));
   1736 		goto out;
   1737 	}
   1738 
   1739 	memcpy(mc->mc_mbox, mu->mu_command, sizeof(mc->mc_mbox));
   1740 
   1741 	/*
   1742 	 * If we need a buffer for data transfer, allocate one and copy in
   1743 	 * its initial contents.
   1744 	 */
   1745 	if (mu->mu_datasize > 0) {
   1746 		if (mu->mu_datasize > MAXPHYS)
   1747 			return (EINVAL);
   1748 
   1749 		kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK);
   1750 		if (kbuf == NULL) {
   1751 			DPRINTF(("mlx_user_command: malloc = NULL\n"));
   1752 			rv = ENOMEM;
   1753 			goto out;
   1754 		}
   1755 
   1756 		if ((mu->mu_bufdir & MU_XFER_OUT) != 0) {
   1757 			rv = copyin(mu->mu_buf, kbuf, mu->mu_datasize);
   1758 			if (rv != 0) {
   1759 				DPRINTF(("mlx_user_command: copyin = %d\n",
   1760 				    rv));
   1761 				goto out;
   1762 			}
   1763 		}
   1764 
   1765 		/* Map the buffer so the controller can see it. */
   1766 		rv = mlx_ccb_map(mlx, mc, kbuf, mu->mu_datasize, mu->mu_bufdir);
   1767 		if (rv != 0) {
   1768 			DPRINTF(("mlx_user_command: mlx_ccb_map = %d\n", rv));
   1769 			goto out;
   1770 		}
   1771 		if (mc->mc_nsgent > 1) {
   1772 			DPRINTF(("mlx_user_command: too many s/g entries\n"));
   1773 			rv = EFBIG;
   1774 			goto out;
   1775 		}
   1776 		mapped = 1;
   1777 		/*
   1778 		 * If this is a passthrough SCSI command, the DCDB is packed at
   1779 		 * the beginning of the data area.  Fix up the DCDB to point to
   1780 		 * the correct physical address and override any bufptr
   1781 		 * supplied by the caller since we know what it's meant to be.
   1782 		 */
   1783 		if (mc->mc_mbox[0] == MLX_CMD_DIRECT_CDB) {
   1784 			dcdb = (struct mlx_dcdb *)kbuf;
   1785 			dcdb->dcdb_physaddr = mc->mc_xfer_phys + sizeof(*dcdb);
   1786 			mu->mu_bufptr = 8;
   1787 		}
   1788 	}
   1789 
   1790 
   1791 	/*
   1792 	 * If there's a data buffer, fix up the command's buffer pointer.
   1793 	 */
   1794 	if (mu->mu_datasize > 0) {
   1795 		/* Range check the pointer to physical buffer address. */
   1796 		if (mu->mu_bufptr < 0 ||
   1797 		    mu->mu_bufptr > sizeof(mu->mu_command) - 4) {
   1798 			DPRINTF(("mlx_user_command: bufptr botch\n"));
   1799 			rv = EINVAL;
   1800 			goto out;
   1801 		}
   1802 
   1803 		mc->mc_mbox[mu->mu_bufptr] = mc->mc_xfer_phys;
   1804 		mc->mc_mbox[mu->mu_bufptr+1] = mc->mc_xfer_phys >> 8;
   1805 		mc->mc_mbox[mu->mu_bufptr+2] = mc->mc_xfer_phys >> 16;
   1806 		mc->mc_mbox[mu->mu_bufptr+3] = mc->mc_xfer_phys >> 24;
   1807 	}
   1808 
   1809 	/* Submit the command and wait. */
   1810 	if ((rv = mlx_ccb_wait(mlx, mc)) != 0) {
   1811 #ifdef DEBUG
   1812 		printf("mlx_user_command: mlx_ccb_wait = %d\n", rv);
   1813 #endif
   1814 	}
   1815 
   1816  out:
   1817 	if (mc != NULL) {
   1818 		/* Copy out status and data */
   1819 		mu->mu_status = mc->mc_status;
   1820 		if (mapped)
   1821 			mlx_ccb_unmap(mlx, mc);
   1822 		mlx_ccb_free(mlx, mc);
   1823 	}
   1824 
   1825 	if (kbuf != NULL) {
   1826 		if (mu->mu_datasize > 0 && (mu->mu_bufdir & MU_XFER_IN) != 0) {
   1827 			rv = copyout(kbuf, mu->mu_buf, mu->mu_datasize);
   1828 #ifdef DIAGNOSTIC
   1829 			if (rv != 0)
   1830 				printf("mlx_user_command: copyout = %d\n", rv);
   1831 #endif
   1832 		}
   1833 	}
   1834 	if (kbuf != NULL)
   1835 		free(kbuf, M_DEVBUF);
   1836 
   1837 	return (rv);
   1838 }
   1839 
   1840 /*
   1841  * Allocate and initialise a CCB.
   1842  */
   1843 int
   1844 mlx_ccb_alloc(struct mlx_softc *mlx, struct mlx_ccb **mcp, int control)
   1845 {
   1846 	struct mlx_ccb *mc;
   1847 	int s;
   1848 
   1849 	s = splbio();
   1850 	mc = SLIST_FIRST(&mlx->mlx_ccb_freelist);
   1851 	if (control) {
   1852 		if (mlx->mlx_nccbs_ctrl >= MLX_NCCBS_CONTROL) {
   1853 			splx(s);
   1854 			*mcp = NULL;
   1855 			return (EAGAIN);
   1856 		}
   1857 		mc->mc_flags |= MC_CONTROL;
   1858 		mlx->mlx_nccbs_ctrl++;
   1859 	}
   1860 	SLIST_REMOVE_HEAD(&mlx->mlx_ccb_freelist, mc_chain.slist);
   1861 	splx(s);
   1862 
   1863 	*mcp = mc;
   1864 	return (0);
   1865 }
   1866 
   1867 /*
   1868  * Free a CCB.
   1869  */
   1870 void
   1871 mlx_ccb_free(struct mlx_softc *mlx, struct mlx_ccb *mc)
   1872 {
   1873 	int s;
   1874 
   1875 	s = splbio();
   1876 	if ((mc->mc_flags & MC_CONTROL) != 0)
   1877 		mlx->mlx_nccbs_ctrl--;
   1878 	mc->mc_flags = 0;
   1879 	SLIST_INSERT_HEAD(&mlx->mlx_ccb_freelist, mc, mc_chain.slist);
   1880 	splx(s);
   1881 }
   1882 
   1883 /*
   1884  * If a CCB is specified, enqueue it.  Pull CCBs off the software queue in
   1885  * the order that they were enqueued and try to submit their mailboxes to
   1886  * the controller for execution.
   1887  */
   1888 void
   1889 mlx_ccb_enqueue(struct mlx_softc *mlx, struct mlx_ccb *mc)
   1890 {
   1891 	int s;
   1892 
   1893 	s = splbio();
   1894 
   1895 	if (mc != NULL)
   1896 		SIMPLEQ_INSERT_TAIL(&mlx->mlx_ccb_queue, mc, mc_chain.simpleq);
   1897 
   1898 	while ((mc = SIMPLEQ_FIRST(&mlx->mlx_ccb_queue)) != NULL) {
   1899 		if (mlx_ccb_submit(mlx, mc) != 0)
   1900 			break;
   1901 		SIMPLEQ_REMOVE_HEAD(&mlx->mlx_ccb_queue, mc_chain.simpleq);
   1902 		TAILQ_INSERT_TAIL(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq);
   1903 	}
   1904 
   1905 	splx(s);
   1906 }
   1907 
   1908 /*
   1909  * Map the specified CCB's data buffer onto the bus, and fill the
   1910  * scatter-gather list.
   1911  */
   1912 int
   1913 mlx_ccb_map(struct mlx_softc *mlx, struct mlx_ccb *mc, void *data, int size,
   1914 	    int dir)
   1915 {
   1916 	struct mlx_sgentry *sge;
   1917 	int nsegs, i, rv, sgloff;
   1918 	bus_dmamap_t xfer;
   1919 
   1920 	xfer = mc->mc_xfer_map;
   1921 
   1922 	rv = bus_dmamap_load(mlx->mlx_dmat, xfer, data, size, NULL,
   1923 	    BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
   1924 	    ((dir & MC_XFER_IN) ? BUS_DMA_READ : BUS_DMA_WRITE));
   1925 	if (rv != 0)
   1926 		return (rv);
   1927 
   1928 	nsegs = xfer->dm_nsegs;
   1929 	mc->mc_xfer_size = size;
   1930 	mc->mc_flags |= dir;
   1931 	mc->mc_nsgent = nsegs;
   1932 	mc->mc_xfer_phys = xfer->dm_segs[0].ds_addr;
   1933 
   1934 	sgloff = MLX_SGL_SIZE * mc->mc_ident;
   1935 	sge = (struct mlx_sgentry *)((char *)mlx->mlx_sgls + sgloff);
   1936 
   1937 	for (i = 0; i < nsegs; i++, sge++) {
   1938 		sge->sge_addr = htole32(xfer->dm_segs[i].ds_addr);
   1939 		sge->sge_count = htole32(xfer->dm_segs[i].ds_len);
   1940 	}
   1941 
   1942 	if ((dir & MC_XFER_OUT) != 0)
   1943 		i = BUS_DMASYNC_PREWRITE;
   1944 	else
   1945 		i = 0;
   1946 	if ((dir & MC_XFER_IN) != 0)
   1947 		i |= BUS_DMASYNC_PREREAD;
   1948 
   1949 	bus_dmamap_sync(mlx->mlx_dmat, xfer, 0, mc->mc_xfer_size, i);
   1950 	bus_dmamap_sync(mlx->mlx_dmat, mlx->mlx_dmamap, sgloff,
   1951 	    MLX_SGL_SIZE, BUS_DMASYNC_PREWRITE);
   1952 
   1953 	return (0);
   1954 }
   1955 
   1956 /*
   1957  * Unmap the specified CCB's data buffer.
   1958  */
   1959 void
   1960 mlx_ccb_unmap(struct mlx_softc *mlx, struct mlx_ccb *mc)
   1961 {
   1962 	int i;
   1963 
   1964 	bus_dmamap_sync(mlx->mlx_dmat, mlx->mlx_dmamap,
   1965 	    MLX_SGL_SIZE * mc->mc_ident, MLX_SGL_SIZE,
   1966 	    BUS_DMASYNC_POSTWRITE);
   1967 
   1968 	if ((mc->mc_flags & MC_XFER_OUT) != 0)
   1969 		i = BUS_DMASYNC_POSTWRITE;
   1970 	else
   1971 		i = 0;
   1972 	if ((mc->mc_flags & MC_XFER_IN) != 0)
   1973 		i |= BUS_DMASYNC_POSTREAD;
   1974 
   1975 	bus_dmamap_sync(mlx->mlx_dmat, mc->mc_xfer_map, 0, mc->mc_xfer_size, i);
   1976 	bus_dmamap_unload(mlx->mlx_dmat, mc->mc_xfer_map);
   1977 }
   1978 
   1979 /*
   1980  * Submit the CCB, and busy-wait for it to complete.  Return non-zero on
   1981  * timeout or submission error.  Must be called with interrupts blocked.
   1982  */
   1983 int
   1984 mlx_ccb_poll(struct mlx_softc *mlx, struct mlx_ccb *mc, int timo)
   1985 {
   1986 	int rv;
   1987 
   1988 	mc->mc_mx.mx_handler = NULL;
   1989 
   1990 	if ((rv = mlx_ccb_submit(mlx, mc)) != 0)
   1991 		return (rv);
   1992 	TAILQ_INSERT_TAIL(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq);
   1993 
   1994 	for (timo *= 10; timo != 0; timo--) {
   1995 		mlx_intr(mlx);
   1996 		if (mc->mc_status != MLX_STATUS_BUSY)
   1997 			break;
   1998 		DELAY(100);
   1999 	}
   2000 
   2001 	if (timo != 0) {
   2002 		if (mc->mc_status != 0) {
   2003 			aprint_error_dev(mlx->mlx_dv, "command failed - %s\n",
   2004 			    mlx_ccb_diagnose(mc));
   2005 			rv = EIO;
   2006 		} else
   2007 			rv = 0;
   2008 	} else {
   2009 		printf("%s: command timed out\n", device_xname(mlx->mlx_dv));
   2010 		rv = EIO;
   2011 	}
   2012 
   2013 	return (rv);
   2014 }
   2015 
   2016 /*
   2017  * Enqueue the CCB, and sleep until it completes.  Return non-zero on
   2018  * timeout or error.
   2019  */
   2020 int
   2021 mlx_ccb_wait(struct mlx_softc *mlx, struct mlx_ccb *mc)
   2022 {
   2023 	int s;
   2024 
   2025 	mc->mc_flags |= MC_WAITING;
   2026 	mc->mc_mx.mx_handler = NULL;
   2027 
   2028 	s = splbio();
   2029 	mlx_ccb_enqueue(mlx, mc);
   2030 	tsleep(mc, PRIBIO, "mlxwccb", 0);
   2031 	splx(s);
   2032 
   2033 	if (mc->mc_status != 0) {
   2034 		aprint_error_dev(mlx->mlx_dv, "command failed - %s\n",
   2035 		    mlx_ccb_diagnose(mc));
   2036 		return (EIO);
   2037 	}
   2038 
   2039 	return (0);
   2040 }
   2041 
   2042 /*
   2043  * Try to submit a CCB's mailbox to the controller for execution.  Return
   2044  * non-zero on timeout or error.  Must be called with interrupts blocked.
   2045  */
   2046 static int
   2047 mlx_ccb_submit(struct mlx_softc *mlx, struct mlx_ccb *mc)
   2048 {
   2049 	int i, s, r;
   2050 
   2051 	/* Save the ident so we can handle this command when complete. */
   2052 	mc->mc_mbox[1] = (u_int8_t)(mc->mc_ident + 1);
   2053 
   2054 	/* Mark the command as currently being processed. */
   2055 	mc->mc_status = MLX_STATUS_BUSY;
   2056 	mc->mc_expiry = time_second + MLX_TIMEOUT;
   2057 
   2058 	/* Spin waiting for the mailbox. */
   2059 	for (i = 100; i != 0; i--) {
   2060 		s = splbio();
   2061 		r = (*mlx->mlx_submit)(mlx, mc);
   2062 		splx(s);
   2063 		if (r != 0)
   2064 			break;
   2065 		DELAY(100);
   2066 	}
   2067 	if (i != 0)
   2068 		return (0);
   2069 
   2070 	DPRINTF(("mlx_ccb_submit: rejected; queueing\n"));
   2071 	mc->mc_status = MLX_STATUS_WEDGED;
   2072 	return (EIO);
   2073 }
   2074 
   2075 /*
   2076  * Return a string that describes why a command has failed.
   2077  */
   2078 const char *
   2079 mlx_ccb_diagnose(struct mlx_ccb *mc)
   2080 {
   2081 	static char tbuf[80];
   2082 	int i;
   2083 
   2084 	for (i = 0; i < sizeof(mlx_msgs) / sizeof(mlx_msgs[0]); i++)
   2085 		if ((mc->mc_mbox[0] == mlx_msgs[i].command ||
   2086 		    mlx_msgs[i].command == 0) &&
   2087 		    mc->mc_status == mlx_msgs[i].status) {
   2088 			snprintf(tbuf, sizeof(tbuf), "%s (0x%x)",
   2089 			    mlx_status_msgs[mlx_msgs[i].msg], mc->mc_status);
   2090 			return (tbuf);
   2091 		}
   2092 
   2093 	snprintf(tbuf, sizeof(tbuf), "unknown response 0x%x for command 0x%x",
   2094 	    (int)mc->mc_status, (int)mc->mc_mbox[0]);
   2095 
   2096 	return (tbuf);
   2097 }
   2098 
   2099 /*
   2100  * Poll the controller for completed commands.  Returns non-zero if one or
   2101  * more commands were completed.  Must be called with interrupts blocked.
   2102  */
   2103 int
   2104 mlx_intr(void *cookie)
   2105 {
   2106 	struct mlx_softc *mlx;
   2107 	struct mlx_ccb *mc;
   2108 	int result;
   2109 	u_int ident, status;
   2110 
   2111 	mlx = cookie;
   2112 	result = 0;
   2113 
   2114 	while ((*mlx->mlx_findcomplete)(mlx, &ident, &status) != 0) {
   2115 		result = 1;
   2116 		ident--;
   2117 
   2118 		if (ident >= MLX_MAX_QUEUECNT) {
   2119 			aprint_error_dev(mlx->mlx_dv,
   2120 			    "bad completion returned\n");
   2121 			continue;
   2122 		}
   2123 
   2124 		mc = mlx->mlx_ccbs + ident;
   2125 
   2126 		if (mc->mc_status != MLX_STATUS_BUSY) {
   2127 			aprint_error_dev(mlx->mlx_dv,
   2128 			    "bad completion returned\n");
   2129 			continue;
   2130 		}
   2131 
   2132 		TAILQ_REMOVE(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq);
   2133 
   2134 		/* Record status and notify the initiator, if requested. */
   2135 		mc->mc_status = status;
   2136 		if (mc->mc_mx.mx_handler != NULL)
   2137 			(*mc->mc_mx.mx_handler)(mc);
   2138 		else if ((mc->mc_flags & MC_WAITING) != 0)
   2139 			wakeup(mc);
   2140 	}
   2141 
   2142 	/* If we've completed any commands, try posting some more. */
   2143 	if (result)
   2144 		mlx_ccb_enqueue(mlx, NULL);
   2145 
   2146 	return (result);
   2147 }
   2148 
   2149 /*
   2150  * Emit a string describing the firmware handshake status code, and return a
   2151  * flag indicating whether the code represents a fatal error.
   2152  *
   2153  * Error code interpretations are from the Linux driver, and don't directly
   2154  * match the messages printed by Mylex's BIOS.  This may change if
   2155  * documentation on the codes is forthcoming.
   2156  */
   2157 static int
   2158 mlx_fw_message(struct mlx_softc *mlx, int error, int param1, int param2)
   2159 {
   2160 	const char *fmt;
   2161 
   2162 	switch (error) {
   2163 	case 0x00:
   2164 		fmt = "physical drive %d:%d not responding";
   2165 		break;
   2166 
   2167 	case 0x08:
   2168 		/*
   2169 		 * We could be neater about this and give some indication
   2170 		 * when we receive more of them.
   2171 		 */
   2172 		if ((mlx->mlx_flags & MLXF_SPINUP_REPORTED) == 0) {
   2173 			printf("%s: spinning up drives...\n",
   2174 			    device_xname(mlx->mlx_dv));
   2175 			mlx->mlx_flags |= MLXF_SPINUP_REPORTED;
   2176 		}
   2177 		return (0);
   2178 
   2179 	case 0x30:
   2180 		fmt = "configuration checksum error";
   2181 		break;
   2182 
   2183 	case 0x60:
   2184 		fmt = "mirror race recovery failed";
   2185 		break;
   2186 
   2187 	case 0x70:
   2188 		fmt = "mirror race recovery in progress";
   2189 		break;
   2190 
   2191 	case 0x90:
   2192 		fmt = "physical drive %d:%d COD mismatch";
   2193 		break;
   2194 
   2195 	case 0xa0:
   2196 		fmt = "logical drive installation aborted";
   2197 		break;
   2198 
   2199 	case 0xb0:
   2200 		fmt = "mirror race on a critical system drive";
   2201 		break;
   2202 
   2203 	case 0xd0:
   2204 		fmt = "new controller configuration found";
   2205 		break;
   2206 
   2207 	case 0xf0:
   2208 		aprint_error_dev(mlx->mlx_dv, "FATAL MEMORY PARITY ERROR\n");
   2209 		return (1);
   2210 
   2211 	default:
   2212 		aprint_error_dev(mlx->mlx_dv,
   2213 		    "unknown firmware init error %02x:%02x:%02x\n",
   2214 		    error, param1, param2);
   2215 		return (0);
   2216 	}
   2217 
   2218 	aprint_normal_dev(mlx->mlx_dv, fmt, param2, param1);
   2219 	aprint_normal("\n");
   2220 
   2221 	return (0);
   2222 }
   2223 
   2224 MODULE(MODULE_CLASS_DRIVER, mlx, NULL);
   2225 
   2226 #ifdef _MODULE
   2227 CFDRIVER_DECL(cac, DV_DISK, NULL);
   2228 #endif
   2229 
   2230 static int
   2231 mlx_modcmd(modcmd_t cmd, void *opaque)
   2232 {
   2233 	int error = 0;
   2234 
   2235 #ifdef _MODULE
   2236 	switch (cmd) {
   2237 	case MODULE_CMD_INIT:
   2238 		error = config_cfdriver_attach(&mlx_cd);
   2239 		break;
   2240 	case MODULE_CMD_FINI:
   2241 		error = config_cfdriver_detach(&mlx_cd);
   2242 		break;
   2243 	default:
   2244 		error = ENOTTY;
   2245 		break;
   2246 	}
   2247 #endif
   2248 	return error;
   2249 }
   2250