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