Home | History | Annotate | Line # | Download | only in ic
mlx.c revision 1.66
      1 /*	$NetBSD: mlx.c,v 1.66 2017/10/28 04:53:55 riastradh 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.66 2017/10/28 04:53:55 riastradh 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_NOWAIT);
    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 	    min(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_sm_loc(mlx->mlx_dv, "mlx", locs,
    631 				&mlxa, mlx_print, config_stdsubmatch);
    632 		nunits += (ms->ms_dv != NULL);
    633 	}
    634 
    635 	free(mes, M_DEVBUF);
    636 
    637 	if (nunits != 0)
    638 		mlx_adjqparam(mlx, mlx->mlx_max_queuecnt / nunits,
    639 		    mlx->mlx_max_queuecnt % nunits);
    640  out:
    641  	mlx->mlx_flags &= ~MLXF_RESCANNING;
    642 
    643 	return 0;
    644 }
    645 
    646 /*
    647  * Print autoconfiguration message for a sub-device.
    648  */
    649 static int
    650 mlx_print(void *aux, const char *pnp)
    651 {
    652 	struct mlx_attach_args *mlxa;
    653 
    654 	mlxa = (struct mlx_attach_args *)aux;
    655 
    656 	if (pnp != NULL)
    657 		aprint_normal("block device at %s", pnp);
    658 	aprint_normal(" unit %d", mlxa->mlxa_unit);
    659 	return (UNCONF);
    660 }
    661 
    662 /*
    663  * Shut down all configured `mlx' devices.
    664  */
    665 static void
    666 mlx_shutdown(void *cookie)
    667 {
    668 	struct mlx_softc *mlx;
    669 	int i;
    670 
    671 	for (i = 0; i < mlx_cd.cd_ndevs; i++)
    672 		if ((mlx = device_lookup_private(&mlx_cd, i)) != NULL)
    673 			mlx_flush(mlx, 0);
    674 }
    675 
    676 /*
    677  * Adjust queue parameters for all child devices.
    678  */
    679 static void
    680 mlx_adjqparam(struct mlx_softc *mlx, int mpu, int slop)
    681 {
    682 #if NLD > 0
    683 	struct ld_softc *ld;
    684 	int i;
    685 
    686 	for (i = 0; i < ld_cd.cd_ndevs; i++) {
    687 		if ((ld = device_lookup_private(&ld_cd, i)) == NULL)
    688 			continue;
    689 		if (device_parent(ld->sc_dv) != mlx->mlx_dv)
    690 			continue;
    691 		ldadjqparam(ld, mpu + (slop-- > 0));
    692 	}
    693 #endif
    694 }
    695 
    696 /*
    697  * Accept an open operation on the control device.
    698  */
    699 int
    700 mlxopen(dev_t dev, int flag, int mode, struct lwp *l)
    701 {
    702 	struct mlx_softc *mlx;
    703 
    704 	if ((mlx = device_lookup_private(&mlx_cd, minor(dev))) == NULL)
    705 		return (ENXIO);
    706 	if ((mlx->mlx_flags & MLXF_INITOK) == 0)
    707 		return (ENXIO);
    708 	if ((mlx->mlx_flags & MLXF_OPEN) != 0)
    709 		return (EBUSY);
    710 
    711 	mlx->mlx_flags |= MLXF_OPEN;
    712 	return (0);
    713 }
    714 
    715 /*
    716  * Accept the last close on the control device.
    717  */
    718 int
    719 mlxclose(dev_t dev, int flag, int mode, struct lwp *l)
    720 {
    721 	struct mlx_softc *mlx;
    722 
    723 	mlx = device_lookup_private(&mlx_cd, minor(dev));
    724 	mlx->mlx_flags &= ~MLXF_OPEN;
    725 	return (0);
    726 }
    727 
    728 /*
    729  * Handle control operations.
    730  */
    731 int
    732 mlxioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
    733 {
    734 	struct mlx_softc *mlx;
    735 	struct mlx_rebuild_request *rb;
    736 	struct mlx_rebuild_status *rs;
    737 	struct mlx_pause *mp;
    738 	struct mlx_sysdrive *ms;
    739 	int i, rv, *arg, result;
    740 
    741 	mlx = device_lookup_private(&mlx_cd, minor(dev));
    742 
    743 	rb = (struct mlx_rebuild_request *)data;
    744 	rs = (struct mlx_rebuild_status *)data;
    745 	arg = (int *)data;
    746 	rv = 0;
    747 
    748 	switch (cmd) {
    749 	case MLX_RESCAN_DRIVES:
    750 		/*
    751 		 * Scan the controller to see whether new drives have
    752 		 * appeared, or old ones disappeared.
    753 		 */
    754 		mlx_configure(mlx, 1);
    755 		return (0);
    756 
    757 	case MLX_PAUSE_CHANNEL:
    758 		/*
    759 		 * Pause one or more SCSI channels for a period of time, to
    760 		 * assist in the process of hot-swapping devices.
    761 		 *
    762 		 * Note that at least the 3.51 firmware on the DAC960PL
    763 		 * doesn't seem to do this right.
    764 		 */
    765 		if ((mlx->mlx_flags & MLXF_PAUSEWORKS) == 0)
    766 			return (EOPNOTSUPP);
    767 
    768 		mp = (struct mlx_pause *)data;
    769 
    770 		if ((mp->mp_which == MLX_PAUSE_CANCEL) &&
    771 		    (mlx->mlx_pause.mp_when != 0)) {
    772 			/* Cancel a pending pause operation. */
    773 			mlx->mlx_pause.mp_which = 0;
    774 			break;
    775 		}
    776 
    777 		/* Fix for legal channels. */
    778 		mp->mp_which &= ((1 << mlx->mlx_ci.ci_nchan) -1);
    779 
    780 		/* Check time values. */
    781 		if (mp->mp_when < 0 || mp->mp_when > 3600 ||
    782 		    mp->mp_howlong < 1 || mp->mp_howlong > (0xf * 30)) {
    783 			rv = EINVAL;
    784 			break;
    785 		}
    786 
    787 		/* Check for a pause currently running. */
    788 		if ((mlx->mlx_pause.mp_which != 0) &&
    789 		    (mlx->mlx_pause.mp_when == 0)) {
    790 			rv = EBUSY;
    791 			break;
    792 		}
    793 
    794 		/* Looks ok, go with it. */
    795 		mlx->mlx_pause.mp_which = mp->mp_which;
    796 		mlx->mlx_pause.mp_when = time_second + mp->mp_when;
    797 		mlx->mlx_pause.mp_howlong =
    798 		    mlx->mlx_pause.mp_when + mp->mp_howlong;
    799 
    800 		return (0);
    801 
    802 	case MLX_COMMAND:
    803 		rv = kauth_authorize_device_passthru(l->l_cred, dev,
    804 		    KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL, data);
    805 		if (rv)
    806 			return (rv);
    807 
    808 		/*
    809 		 * Accept a command passthrough-style.
    810 		 */
    811 		return (mlx_user_command(mlx, (struct mlx_usercommand *)data));
    812 
    813 	case MLX_REBUILDASYNC:
    814 		/*
    815 		 * Start a rebuild on a given SCSI disk
    816 		 */
    817 		if (mlx->mlx_bg != 0) {
    818 			rb->rr_status = 0x0106;
    819 			rv = EBUSY;
    820 			break;
    821 		}
    822 
    823 		rb->rr_status = mlx_rebuild(mlx, rb->rr_channel, rb->rr_target);
    824 		switch (rb->rr_status) {
    825 		case 0:
    826 			rv = 0;
    827 			break;
    828 		case 0x10000:
    829 			rv = ENOMEM;	/* Couldn't set up the command. */
    830 			break;
    831 		case 0x0002:
    832 			rv = EBUSY;
    833 			break;
    834 		case 0x0104:
    835 			rv = EIO;
    836 			break;
    837 		case 0x0105:
    838 			rv = ERANGE;
    839 			break;
    840 		case 0x0106:
    841 			rv = EBUSY;
    842 			break;
    843 		default:
    844 			rv = EINVAL;
    845 			break;
    846 		}
    847 
    848 		if (rv == 0)
    849 			mlx->mlx_bg = MLX_BG_REBUILD;
    850 
    851 		return (0);
    852 
    853 	case MLX_REBUILDSTAT:
    854 		/*
    855 		 * Get the status of the current rebuild or consistency check.
    856 		 */
    857 		*rs = mlx->mlx_rebuildstat;
    858 		return (0);
    859 
    860 	case MLX_GET_SYSDRIVE:
    861 		/*
    862 		 * Return the system drive number matching the `ld' device
    863 		 * unit in (arg), if it happens to belong to us.
    864 		 */
    865 		for (i = 0; i < MLX_MAX_DRIVES; i++) {
    866 			ms = &mlx->mlx_sysdrive[i];
    867 			if (ms->ms_dv != NULL)
    868 				if (device_xname(ms->ms_dv)[2] == '0' + *arg) {
    869 					*arg = i;
    870 					return (0);
    871 				}
    872 		}
    873 		return (ENOENT);
    874 
    875 	case MLX_GET_CINFO:
    876 		/*
    877 		 * Return controller info.
    878 		 */
    879 		memcpy(arg, &mlx->mlx_ci, sizeof(mlx->mlx_ci));
    880 		return (0);
    881 	}
    882 
    883 	switch (cmd) {
    884 	case MLXD_DETACH:
    885 	case MLXD_STATUS:
    886 	case MLXD_CHECKASYNC:
    887 		if ((u_int)*arg >= MLX_MAX_DRIVES)
    888 			return (EINVAL);
    889 		ms = &mlx->mlx_sysdrive[*arg];
    890 		if (*arg > MLX_MAX_DRIVES || ms->ms_dv == NULL)
    891 			return (ENOENT);
    892 		break;
    893 
    894 	default:
    895 		return (ENOTTY);
    896 	}
    897 
    898 	switch (cmd) {
    899 	case MLXD_DETACH:
    900 		/*
    901 		 * Disconnect from the specified drive; it may be about to go
    902 		 * away.
    903 		 */
    904 		return (config_detach(ms->ms_dv, 0));
    905 
    906 	case MLXD_STATUS:
    907 		/*
    908 		 * Return the current status of this drive.
    909 		 */
    910 		*arg = ms->ms_state;
    911 		return (0);
    912 
    913 	case MLXD_CHECKASYNC:
    914 		/*
    915 		 * Start a background consistency check on this drive.
    916 		 */
    917 		if (mlx->mlx_bg != 0) {
    918 			*arg = 0x0106;
    919 			return (EBUSY);
    920 		}
    921 
    922 		switch (result = mlx_check(mlx, *arg)) {
    923 		case 0:
    924 			rv = 0;
    925 			break;
    926 		case 0x10000:
    927 			rv = ENOMEM;	/* Couldn't set up the command. */
    928 			break;
    929 		case 0x0002:
    930 			rv = EIO;
    931 			break;
    932 		case 0x0105:
    933 			rv = ERANGE;
    934 			break;
    935 		case 0x0106:
    936 			rv = EBUSY;
    937 			break;
    938 		default:
    939 			rv = EINVAL;
    940 			break;
    941 		}
    942 
    943 		if (rv == 0)
    944 			mlx->mlx_bg = MLX_BG_CHECK;
    945 		*arg = result;
    946 		return (rv);
    947 	}
    948 
    949 	return (ENOTTY);	/* XXX shut up gcc */
    950 }
    951 
    952 static void
    953 mlx_periodic_thread(void *cookie)
    954 {
    955 	struct mlx_softc *mlx;
    956 	int i;
    957 
    958 	for (;;) {
    959 		for (i = 0; i < mlx_cd.cd_ndevs; i++)
    960 			if ((mlx = device_lookup_private(&mlx_cd, i)) != NULL)
    961 				if (mlx->mlx_ci.ci_iftype > 1)
    962 					mlx_periodic(mlx);
    963 
    964 		tsleep(mlx_periodic_thread, PWAIT, "mlxzzz", hz * 2);
    965 	}
    966 }
    967 
    968 static void
    969 mlx_periodic(struct mlx_softc *mlx)
    970 {
    971 	struct mlx_ccb *mc, *nmc;
    972 	int etype, s;
    973 
    974 	if ((mlx->mlx_pause.mp_which != 0) &&
    975 	    (mlx->mlx_pause.mp_when > 0) &&
    976 	    (time_second >= mlx->mlx_pause.mp_when)) {
    977 	    	/*
    978 	    	 * Start bus pause.
    979 	    	 */
    980 		mlx_pause_action(mlx);
    981 		mlx->mlx_pause.mp_when = 0;
    982 	} else if ((mlx->mlx_pause.mp_which != 0) &&
    983 		   (mlx->mlx_pause.mp_when == 0)) {
    984 		/*
    985 		 * Stop pause if required.
    986 		 */
    987 		if (time_second >= mlx->mlx_pause.mp_howlong) {
    988 			mlx_pause_action(mlx);
    989 			mlx->mlx_pause.mp_which = 0;
    990 		}
    991 	} else if (time_second > (mlx->mlx_lastpoll + 10)) {
    992 		/*
    993 		 * Run normal periodic activities...
    994 		 */
    995 		mlx->mlx_lastpoll = time_second;
    996 
    997 		/*
    998 		 * Check controller status.
    999 		 */
   1000 		if ((mlx->mlx_flags & MLXF_PERIODIC_CTLR) == 0) {
   1001 			mlx->mlx_flags |= MLXF_PERIODIC_CTLR;
   1002 
   1003 			if (mlx->mlx_ci.ci_iftype <= 2)
   1004 				etype = MLX_CMD_ENQUIRY_OLD;
   1005 			else
   1006 				etype =  MLX_CMD_ENQUIRY;
   1007 
   1008 			mlx_enquire(mlx, etype, max(sizeof(struct mlx_enquiry),
   1009 			    sizeof(struct mlx_enquiry_old)),
   1010 			    mlx_periodic_enquiry, 1);
   1011 		}
   1012 
   1013 		/*
   1014 		 * Check system drive status.
   1015 		 */
   1016 		if ((mlx->mlx_flags & MLXF_PERIODIC_DRIVE) == 0) {
   1017 			mlx->mlx_flags |= MLXF_PERIODIC_DRIVE;
   1018 			mlx_enquire(mlx, MLX_CMD_ENQSYSDRIVE,
   1019 			    sizeof(struct mlx_enq_sys_drive) * MLX_MAX_DRIVES,
   1020 			    mlx_periodic_enquiry, 1);
   1021 		}
   1022 	}
   1023 
   1024 	/*
   1025 	 * Get drive rebuild/check status.
   1026 	 */
   1027 	if ((mlx->mlx_flags & MLXF_PERIODIC_REBUILD) == 0) {
   1028 		mlx->mlx_flags |= MLXF_PERIODIC_REBUILD;
   1029 		mlx_enquire(mlx, MLX_CMD_REBUILDSTAT,
   1030 		    sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild, 1);
   1031 	}
   1032 
   1033 	/*
   1034 	 * Time-out busy CCBs.
   1035 	 */
   1036 	s = splbio();
   1037 	for (mc = TAILQ_FIRST(&mlx->mlx_ccb_worklist); mc != NULL; mc = nmc) {
   1038 		nmc = TAILQ_NEXT(mc, mc_chain.tailq);
   1039 		if (mc->mc_expiry > time_second) {
   1040 			/*
   1041 			 * The remaining CCBs will expire after this one, so
   1042 			 * there's no point in going further.
   1043 			 */
   1044 			break;
   1045 		}
   1046 		TAILQ_REMOVE(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq);
   1047 		mc->mc_status = MLX_STATUS_LOST;
   1048 		if (mc->mc_mx.mx_handler != NULL)
   1049 			(*mc->mc_mx.mx_handler)(mc);
   1050 		else if ((mc->mc_flags & MC_WAITING) != 0)
   1051 			wakeup(mc);
   1052 	}
   1053 	splx(s);
   1054 }
   1055 
   1056 /*
   1057  * Handle the result of an ENQUIRY command instigated by periodic status
   1058  * polling.
   1059  */
   1060 static void
   1061 mlx_periodic_enquiry(struct mlx_ccb *mc)
   1062 {
   1063 	struct mlx_softc *mlx;
   1064 	struct mlx_enquiry *me;
   1065 	struct mlx_enquiry_old *meo;
   1066 	struct mlx_enq_sys_drive *mes;
   1067 	struct mlx_sysdrive *dr;
   1068 	const char *statestr;
   1069 	int i, j;
   1070 	u_int lsn;
   1071 
   1072 	mlx = device_private(mc->mc_mx.mx_dv);
   1073 	mlx_ccb_unmap(mlx, mc);
   1074 
   1075 	/*
   1076 	 * Command completed OK?
   1077 	 */
   1078 	if (mc->mc_status != 0) {
   1079 		aprint_error_dev(mlx->mlx_dv, "periodic enquiry failed - %s\n",
   1080 		    mlx_ccb_diagnose(mc));
   1081 		goto out;
   1082 	}
   1083 
   1084 	/*
   1085 	 * Respond to command.
   1086 	 */
   1087 	switch (mc->mc_mbox[0]) {
   1088 	case MLX_CMD_ENQUIRY_OLD:
   1089 		/*
   1090 		 * This is currently a bit fruitless, as we don't know how
   1091 		 * to extract the eventlog pointer yet.
   1092 		 */
   1093 		me = (struct mlx_enquiry *)mc->mc_mx.mx_context;
   1094 		meo = (struct mlx_enquiry_old *)mc->mc_mx.mx_context;
   1095 
   1096 		/* Convert data in-place to new format */
   1097 		i = sizeof(me->me_dead) / sizeof(me->me_dead[0]);
   1098 		while (--i >= 0) {
   1099 			me->me_dead[i].dd_chan = meo->me_dead[i].dd_chan;
   1100 			me->me_dead[i].dd_targ = meo->me_dead[i].dd_targ;
   1101 		}
   1102 
   1103 		me->me_misc_flags = 0;
   1104 		me->me_rebuild_count = meo->me_rebuild_count;
   1105 		me->me_dead_count = meo->me_dead_count;
   1106 		me->me_critical_sd_count = meo->me_critical_sd_count;
   1107 		me->me_event_log_seq_num = 0;
   1108 		me->me_offline_sd_count = meo->me_offline_sd_count;
   1109 		me->me_max_commands = meo->me_max_commands;
   1110 		me->me_rebuild_flag = meo->me_rebuild_flag;
   1111 		me->me_fwmajor = meo->me_fwmajor;
   1112 		me->me_fwminor = meo->me_fwminor;
   1113 		me->me_status_flags = meo->me_status_flags;
   1114 		me->me_flash_age = meo->me_flash_age;
   1115 
   1116 		i = sizeof(me->me_drvsize) / sizeof(me->me_drvsize[0]);
   1117 		j = sizeof(meo->me_drvsize) / sizeof(meo->me_drvsize[0]);
   1118 
   1119 		while (--i >= 0) {
   1120 			if (i >= j)
   1121 				me->me_drvsize[i] = 0;
   1122 			else
   1123 				me->me_drvsize[i] = meo->me_drvsize[i];
   1124 		}
   1125 
   1126 		me->me_num_sys_drvs = meo->me_num_sys_drvs;
   1127 
   1128 		/* FALLTHROUGH */
   1129 
   1130 	case MLX_CMD_ENQUIRY:
   1131 		/*
   1132 		 * Generic controller status update.  We could do more with
   1133 		 * this than just checking the event log.
   1134 		 */
   1135 		me = (struct mlx_enquiry *)mc->mc_mx.mx_context;
   1136 		lsn = le16toh(me->me_event_log_seq_num);
   1137 
   1138 		if (mlx->mlx_currevent == -1) {
   1139 			/* Initialise our view of the event log. */
   1140 			mlx->mlx_currevent = lsn;
   1141 			mlx->mlx_lastevent = lsn;
   1142 		} else if (lsn != mlx->mlx_lastevent &&
   1143 			   (mlx->mlx_flags & MLXF_EVENTLOG_BUSY) == 0) {
   1144 			/* Record where current events are up to */
   1145 			mlx->mlx_currevent = lsn;
   1146 
   1147 			/* Mark the event log as busy. */
   1148 			mlx->mlx_flags |= MLXF_EVENTLOG_BUSY;
   1149 
   1150 			/* Drain new eventlog entries. */
   1151 			mlx_periodic_eventlog_poll(mlx);
   1152 		}
   1153 		break;
   1154 
   1155 	case MLX_CMD_ENQSYSDRIVE:
   1156 		/*
   1157 		 * Perform drive status comparison to see if something
   1158 		 * has failed.  Don't perform the comparison if we're
   1159 		 * reconfiguring, since the system drive table will be
   1160 		 * changing.
   1161 		 */
   1162 		if ((mlx->mlx_flags & MLXF_RESCANNING) != 0)
   1163 			break;
   1164 
   1165 		mes = (struct mlx_enq_sys_drive *)mc->mc_mx.mx_context;
   1166 		dr = &mlx->mlx_sysdrive[0];
   1167 
   1168 		for (i = 0; i < mlx->mlx_numsysdrives; i++, dr++) {
   1169 			/* Has state been changed by controller? */
   1170 			if (dr->ms_state != mes[i].sd_state) {
   1171 				switch (mes[i].sd_state) {
   1172 				case MLX_SYSD_OFFLINE:
   1173 					statestr = "offline";
   1174 					break;
   1175 
   1176 				case MLX_SYSD_ONLINE:
   1177 					statestr = "online";
   1178 					break;
   1179 
   1180 				case MLX_SYSD_CRITICAL:
   1181 					statestr = "critical";
   1182 					break;
   1183 
   1184 				default:
   1185 					statestr = "unknown";
   1186 					break;
   1187 				}
   1188 
   1189 				printf("%s: unit %d %s\n",
   1190 				    device_xname(mlx->mlx_dv), i, statestr);
   1191 
   1192 				/* Save new state. */
   1193 				dr->ms_state = mes[i].sd_state;
   1194 			}
   1195 		}
   1196 		break;
   1197 
   1198 #ifdef DIAGNOSTIC
   1199 	default:
   1200 		printf("%s: mlx_periodic_enquiry: eh?\n",
   1201 		    device_xname(mlx->mlx_dv));
   1202 		break;
   1203 #endif
   1204 	}
   1205 
   1206  out:
   1207 	if (mc->mc_mbox[0] == MLX_CMD_ENQSYSDRIVE)
   1208 		mlx->mlx_flags &= ~MLXF_PERIODIC_DRIVE;
   1209 	else
   1210 		mlx->mlx_flags &= ~MLXF_PERIODIC_CTLR;
   1211 
   1212 	free(mc->mc_mx.mx_context, M_DEVBUF);
   1213 	mlx_ccb_free(mlx, mc);
   1214 }
   1215 
   1216 /*
   1217  * Instigate a poll for one event log message on (mlx).  We only poll for
   1218  * one message at a time, to keep our command usage down.
   1219  */
   1220 static void
   1221 mlx_periodic_eventlog_poll(struct mlx_softc *mlx)
   1222 {
   1223 	struct mlx_ccb *mc;
   1224 	void *result;
   1225 	int rv;
   1226 
   1227 	result = NULL;
   1228 
   1229 	if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0)
   1230 		goto out;
   1231 
   1232 	if ((result = malloc(1024, M_DEVBUF, M_WAITOK)) == NULL) {
   1233 		rv = ENOMEM;
   1234 		goto out;
   1235 	}
   1236 	if ((rv = mlx_ccb_map(mlx, mc, result, 1024, MC_XFER_IN)) != 0)
   1237 		goto out;
   1238 	if (mc->mc_nsgent != 1) {
   1239 		mlx_ccb_unmap(mlx, mc);
   1240 		printf("mlx_periodic_eventlog_poll: too many segs\n");
   1241 		goto out;
   1242 	}
   1243 
   1244 	/* Build the command to get one log entry. */
   1245 	mlx_make_type3(mc, MLX_CMD_LOGOP, MLX_LOGOP_GET, 1,
   1246 	    mlx->mlx_lastevent, 0, 0, mc->mc_xfer_phys, 0);
   1247 
   1248 	mc->mc_mx.mx_handler = mlx_periodic_eventlog_respond;
   1249 	mc->mc_mx.mx_dv = mlx->mlx_dv;
   1250 	mc->mc_mx.mx_context = result;
   1251 
   1252 	/* Start the command. */
   1253 	mlx_ccb_enqueue(mlx, mc);
   1254 
   1255  out:
   1256 	if (rv != 0) {
   1257 		if (mc != NULL)
   1258 			mlx_ccb_free(mlx, mc);
   1259 		if (result != NULL)
   1260 			free(result, M_DEVBUF);
   1261 	}
   1262 }
   1263 
   1264 /*
   1265  * Handle the result of polling for a log message, generate diagnostic
   1266  * output.  If this wasn't the last message waiting for us, we'll go collect
   1267  * another.
   1268  */
   1269 static void
   1270 mlx_periodic_eventlog_respond(struct mlx_ccb *mc)
   1271 {
   1272 	struct mlx_softc *mlx;
   1273 	struct mlx_eventlog_entry *el;
   1274 	const char *reason;
   1275 	u_int8_t sensekey, chan, targ;
   1276 
   1277 	mlx = device_private(mc->mc_mx.mx_dv);
   1278 	el = mc->mc_mx.mx_context;
   1279 	mlx_ccb_unmap(mlx, mc);
   1280 
   1281 	mlx->mlx_lastevent++;
   1282 
   1283 	if (mc->mc_status == 0) {
   1284 		switch (el->el_type) {
   1285 		case MLX_LOGMSG_SENSE:		/* sense data */
   1286 			sensekey = el->el_sense & 0x0f;
   1287 			chan = (el->el_target >> 4) & 0x0f;
   1288 			targ = el->el_target & 0x0f;
   1289 
   1290 			/*
   1291 			 * This is the only sort of message we understand at
   1292 			 * the moment.  The tests here are probably
   1293 			 * incomplete.
   1294 			 */
   1295 
   1296 			/*
   1297 			 * Mylex vendor-specific message indicating a drive
   1298 			 * was killed?
   1299 			 */
   1300 			if (sensekey == 9 && el->el_asc == 0x80) {
   1301 				if (el->el_asq < sizeof(mlx_sense_msgs) /
   1302 				    sizeof(mlx_sense_msgs[0]))
   1303 					reason = mlx_sense_msgs[el->el_asq];
   1304 				else
   1305 					reason = "for unknown reason";
   1306 
   1307 				printf("%s: physical drive %d:%d killed %s\n",
   1308 				    device_xname(mlx->mlx_dv), chan, targ,
   1309 				    reason);
   1310 			}
   1311 
   1312 			/*
   1313 			 * SCSI drive was reset?
   1314 			 */
   1315 			if (sensekey == 6 && el->el_asc == 0x29)
   1316 				printf("%s: physical drive %d:%d reset\n",
   1317 				    device_xname(mlx->mlx_dv), chan, targ);
   1318 
   1319 			/*
   1320 			 * SCSI drive error?
   1321 			 */
   1322 			if (!(sensekey == 0 ||
   1323 			    (sensekey == 2 &&
   1324 			    el->el_asc == 0x04 &&
   1325 			    (el->el_asq == 0x01 || el->el_asq == 0x02)))) {
   1326 				printf("%s: physical drive %d:%d error log: "
   1327 				    "sense = %d asc = %x asq = %x\n",
   1328 				    device_xname(mlx->mlx_dv), chan, targ,
   1329 				    sensekey, el->el_asc, el->el_asq);
   1330 				printf("%s:   info = %d:%d:%d:%d "
   1331 				    " csi = %d:%d:%d:%d\n",
   1332 				    device_xname(mlx->mlx_dv),
   1333 				    el->el_information[0],
   1334 				    el->el_information[1],
   1335 				    el->el_information[2],
   1336 				    el->el_information[3],
   1337 				    el->el_csi[0], el->el_csi[1],
   1338 				    el->el_csi[2], el->el_csi[3]);
   1339 			}
   1340 
   1341 			break;
   1342 
   1343 		default:
   1344 			aprint_error_dev(mlx->mlx_dv,
   1345 			    "unknown log message type 0x%x\n", el->el_type);
   1346 			break;
   1347 		}
   1348 	} else {
   1349 		aprint_error_dev(mlx->mlx_dv,
   1350 		    "error reading message log - %s\n", mlx_ccb_diagnose(mc));
   1351 
   1352 		/*
   1353 		 * Give up on all the outstanding messages, as we may have
   1354 		 * come unsynched.
   1355 		 */
   1356 		mlx->mlx_lastevent = mlx->mlx_currevent;
   1357 	}
   1358 
   1359 	free(mc->mc_mx.mx_context, M_DEVBUF);
   1360 	mlx_ccb_free(mlx, mc);
   1361 
   1362 	/*
   1363 	 * Is there another message to obtain?
   1364 	 */
   1365 	if (mlx->mlx_lastevent != mlx->mlx_currevent)
   1366 		mlx_periodic_eventlog_poll(mlx);
   1367 	else
   1368 		mlx->mlx_flags &= ~MLXF_EVENTLOG_BUSY;
   1369 }
   1370 
   1371 /*
   1372  * Handle check/rebuild operations in progress.
   1373  */
   1374 static void
   1375 mlx_periodic_rebuild(struct mlx_ccb *mc)
   1376 {
   1377 	struct mlx_softc *mlx;
   1378 	const char *opstr;
   1379 	struct mlx_rebuild_status *mr;
   1380 
   1381 	mlx = device_private(mc->mc_mx.mx_dv);
   1382 	mr = mc->mc_mx.mx_context;
   1383 	mlx_ccb_unmap(mlx, mc);
   1384 
   1385 	switch (mc->mc_status) {
   1386 	case 0:
   1387 		/*
   1388 		 * Operation running, update stats.
   1389 		 */
   1390 		mlx->mlx_rebuildstat = *mr;
   1391 
   1392 		/* Spontaneous rebuild/check? */
   1393 		if (mlx->mlx_bg == 0) {
   1394 			mlx->mlx_bg = MLX_BG_SPONTANEOUS;
   1395 			printf("%s: background check/rebuild started\n",
   1396 			    device_xname(mlx->mlx_dv));
   1397 		}
   1398 		break;
   1399 
   1400 	case 0x0105:
   1401 		/*
   1402 		 * Nothing running, finalise stats and report.
   1403 		 */
   1404 		switch (mlx->mlx_bg) {
   1405 		case MLX_BG_CHECK:
   1406 			/* XXX Print drive? */
   1407 			opstr = "consistency check";
   1408 			break;
   1409 
   1410 		case MLX_BG_REBUILD:
   1411 			/* XXX Print channel:target? */
   1412 			opstr = "drive rebuild";
   1413 			break;
   1414 
   1415 		case MLX_BG_SPONTANEOUS:
   1416 		default:
   1417 			/*
   1418 			 * If we have previously been non-idle, report the
   1419 			 * transition
   1420 			 */
   1421 			if (mlx->mlx_rebuildstat.rs_code !=
   1422 			    MLX_REBUILDSTAT_IDLE)
   1423 				opstr = "background check/rebuild";
   1424 			else
   1425 				opstr = NULL;
   1426 		}
   1427 
   1428 		if (opstr != NULL)
   1429 			printf("%s: %s completed\n", device_xname(mlx->mlx_dv),
   1430 			    opstr);
   1431 
   1432 		mlx->mlx_bg = 0;
   1433 		mlx->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
   1434 		break;
   1435 	}
   1436 
   1437 	free(mc->mc_mx.mx_context, M_DEVBUF);
   1438 	mlx_ccb_free(mlx, mc);
   1439 	mlx->mlx_flags &= ~MLXF_PERIODIC_REBUILD;
   1440 }
   1441 
   1442 /*
   1443  * It's time to perform a channel pause action for (mlx), either start or
   1444  * stop the pause.
   1445  */
   1446 static void
   1447 mlx_pause_action(struct mlx_softc *mlx)
   1448 {
   1449 	struct mlx_ccb *mc;
   1450 	int failsafe, i, cmd;
   1451 
   1452 	/* What are we doing here? */
   1453 	if (mlx->mlx_pause.mp_when == 0) {
   1454 		cmd = MLX_CMD_STARTCHANNEL;
   1455 		failsafe = 0;
   1456 	} else {
   1457 		cmd = MLX_CMD_STOPCHANNEL;
   1458 
   1459 		/*
   1460 		 * Channels will always start again after the failsafe
   1461 		 * period, which is specified in multiples of 30 seconds.
   1462 		 * This constrains us to a maximum pause of 450 seconds.
   1463 		 */
   1464 		failsafe = ((mlx->mlx_pause.mp_howlong - time_second) + 5) / 30;
   1465 
   1466 		if (failsafe > 0xf) {
   1467 			failsafe = 0xf;
   1468 			mlx->mlx_pause.mp_howlong =
   1469 			     time_second + (0xf * 30) - 5;
   1470 		}
   1471 	}
   1472 
   1473 	/* Build commands for every channel requested. */
   1474 	for (i = 0; i < mlx->mlx_ci.ci_nchan; i++) {
   1475 		if ((1 << i) & mlx->mlx_pause.mp_which) {
   1476 			if (mlx_ccb_alloc(mlx, &mc, 1) != 0) {
   1477 				aprint_error_dev(mlx->mlx_dv,
   1478 				    "%s failed for channel %d\n",
   1479 				    cmd == MLX_CMD_STOPCHANNEL ?
   1480 				    "pause" : "resume", i);
   1481 				continue;
   1482 			}
   1483 
   1484 			/* Build the command. */
   1485 			mlx_make_type2(mc, cmd, (failsafe << 4) | i, 0, 0,
   1486 			    0, 0, 0, 0, 0);
   1487 			mc->mc_mx.mx_handler = mlx_pause_done;
   1488 			mc->mc_mx.mx_dv = mlx->mlx_dv;
   1489 
   1490 			mlx_ccb_enqueue(mlx, mc);
   1491 		}
   1492 	}
   1493 }
   1494 
   1495 static void
   1496 mlx_pause_done(struct mlx_ccb *mc)
   1497 {
   1498 	struct mlx_softc *mlx;
   1499 	int command, channel;
   1500 
   1501 	mlx = device_private(mc->mc_mx.mx_dv);
   1502 	command = mc->mc_mbox[0];
   1503 	channel = mc->mc_mbox[2] & 0xf;
   1504 
   1505 	if (mc->mc_status != 0)
   1506 		aprint_error_dev(mlx->mlx_dv, "%s command failed - %s\n",
   1507 		    command == MLX_CMD_STOPCHANNEL ? "pause" : "resume",
   1508 		    mlx_ccb_diagnose(mc));
   1509 	else if (command == MLX_CMD_STOPCHANNEL)
   1510 		printf("%s: channel %d pausing for %ld seconds\n",
   1511 		    device_xname(mlx->mlx_dv), channel,
   1512 		    (long)(mlx->mlx_pause.mp_howlong - time_second));
   1513 	else
   1514 		printf("%s: channel %d resuming\n", device_xname(mlx->mlx_dv),
   1515 		    channel);
   1516 
   1517 	mlx_ccb_free(mlx, mc);
   1518 }
   1519 
   1520 /*
   1521  * Perform an Enquiry command using a type-3 command buffer and a return a
   1522  * single linear result buffer.  If the completion function is specified, it
   1523  * will be called with the completed command (and the result response will
   1524  * not be valid until that point).  Otherwise, the command will either be
   1525  * busy-waited for (interrupts must be blocked), or slept for.
   1526  */
   1527 static void *
   1528 mlx_enquire(struct mlx_softc *mlx, int command, size_t bufsize,
   1529 	    void (*handler)(struct mlx_ccb *mc), int waitok)
   1530 {
   1531 	struct mlx_ccb *mc;
   1532 	void *result;
   1533 	int rv, mapped;
   1534 
   1535 	result = NULL;
   1536 	mapped = 0;
   1537 
   1538 	if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0)
   1539 		goto out;
   1540 
   1541 	result = malloc(bufsize, M_DEVBUF, waitok ? M_WAITOK : M_NOWAIT);
   1542 	if (result == NULL) {
   1543 		printf("mlx_enquire: malloc() failed\n");
   1544 		goto out;
   1545 	}
   1546 	if ((rv = mlx_ccb_map(mlx, mc, result, bufsize, MC_XFER_IN)) != 0)
   1547 		goto out;
   1548 	mapped = 1;
   1549 	if (mc->mc_nsgent != 1) {
   1550 		printf("mlx_enquire: too many segs\n");
   1551 		goto out;
   1552 	}
   1553 
   1554 	/* Build an enquiry command. */
   1555 	mlx_make_type2(mc, command, 0, 0, 0, 0, 0, 0, mc->mc_xfer_phys, 0);
   1556 
   1557 	/* Do we want a completion callback? */
   1558 	if (handler != NULL) {
   1559 		mc->mc_mx.mx_context = result;
   1560 		mc->mc_mx.mx_dv = mlx->mlx_dv;
   1561 		mc->mc_mx.mx_handler = handler;
   1562 		mlx_ccb_enqueue(mlx, mc);
   1563 	} else {
   1564 		/* Run the command in either polled or wait mode. */
   1565 		if (waitok)
   1566 			rv = mlx_ccb_wait(mlx, mc);
   1567 		else
   1568 			rv = mlx_ccb_poll(mlx, mc, 5000);
   1569 	}
   1570 
   1571  out:
   1572 	/* We got a command, but nobody else will free it. */
   1573 	if (handler == NULL && mc != NULL) {
   1574 		if (mapped)
   1575 			mlx_ccb_unmap(mlx, mc);
   1576 		mlx_ccb_free(mlx, mc);
   1577 	}
   1578 
   1579 	/* We got an error, and we allocated a result. */
   1580 	if (rv != 0 && result != NULL) {
   1581 		if (mc != NULL)
   1582 			mlx_ccb_free(mlx, mc);
   1583 		free(result, M_DEVBUF);
   1584 		result = NULL;
   1585 	}
   1586 
   1587 	return (result);
   1588 }
   1589 
   1590 /*
   1591  * Perform a Flush command on the nominated controller.
   1592  *
   1593  * May be called with interrupts enabled or disabled; will not return until
   1594  * the flush operation completes or fails.
   1595  */
   1596 int
   1597 mlx_flush(struct mlx_softc *mlx, int async)
   1598 {
   1599 	struct mlx_ccb *mc;
   1600 	int rv;
   1601 
   1602 	if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0)
   1603 		goto out;
   1604 
   1605 	/* Build a flush command and fire it off. */
   1606 	mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0);
   1607 
   1608 	if (async)
   1609 		rv = mlx_ccb_wait(mlx, mc);
   1610 	else
   1611 		rv = mlx_ccb_poll(mlx, mc, MLX_TIMEOUT * 1000);
   1612 	if (rv != 0)
   1613 		goto out;
   1614 
   1615 	/* Command completed OK? */
   1616 	if (mc->mc_status != 0) {
   1617 		aprint_error_dev(mlx->mlx_dv, "FLUSH failed - %s\n",
   1618 		    mlx_ccb_diagnose(mc));
   1619 		rv = EIO;
   1620 	}
   1621  out:
   1622 	if (mc != NULL)
   1623 		mlx_ccb_free(mlx, mc);
   1624 
   1625 	return (rv);
   1626 }
   1627 
   1628 /*
   1629  * Start a background consistency check on (drive).
   1630  */
   1631 static int
   1632 mlx_check(struct mlx_softc *mlx, int drive)
   1633 {
   1634 	struct mlx_ccb *mc;
   1635 	int rv;
   1636 
   1637 	/* Get ourselves a command buffer. */
   1638 	rv = 0x10000;
   1639 
   1640 	if (mlx_ccb_alloc(mlx, &mc, 1) != 0)
   1641 		goto out;
   1642 
   1643 	/* Build a checkasync command, set the "fix it" flag. */
   1644 	mlx_make_type2(mc, MLX_CMD_CHECKASYNC, 0, 0, 0, 0, 0, drive | 0x80,
   1645 	    0, 0);
   1646 
   1647 	/* Start the command and wait for it to be returned. */
   1648 	if (mlx_ccb_wait(mlx, mc) != 0)
   1649 		goto out;
   1650 
   1651 	/* Command completed OK? */
   1652 	if (mc->mc_status != 0)
   1653 		aprint_error_dev(mlx->mlx_dv, "CHECK ASYNC failed - %s\n",
   1654 		    mlx_ccb_diagnose(mc));
   1655 	else
   1656 		printf("%s: consistency check started",
   1657 		    device_xname(mlx->mlx_sysdrive[drive].ms_dv));
   1658 
   1659 	rv = mc->mc_status;
   1660  out:
   1661 	if (mc != NULL)
   1662 		mlx_ccb_free(mlx, mc);
   1663 
   1664 	return (rv);
   1665 }
   1666 
   1667 /*
   1668  * Start a background rebuild of the physical drive at (channel),(target).
   1669  *
   1670  * May be called with interrupts enabled or disabled; will return as soon as
   1671  * the operation has started or been refused.
   1672  */
   1673 static int
   1674 mlx_rebuild(struct mlx_softc *mlx, int channel, int target)
   1675 {
   1676 	struct mlx_ccb *mc;
   1677 	int error;
   1678 
   1679 	error = 0x10000;
   1680 	if (mlx_ccb_alloc(mlx, &mc, 1) != 0)
   1681 		goto out;
   1682 
   1683 	/* Build a rebuildasync command, set the "fix it" flag. */
   1684 	mlx_make_type2(mc, MLX_CMD_REBUILDASYNC, channel, target, 0, 0, 0, 0,
   1685 	    0, 0);
   1686 
   1687 	/* Start the command and wait for it to be returned. */
   1688 	if (mlx_ccb_wait(mlx, mc) != 0)
   1689 		goto out;
   1690 
   1691 	/* Command completed OK? */
   1692 	if (mc->mc_status != 0)
   1693 		aprint_normal_dev(mlx->mlx_dv, "REBUILD ASYNC failed - %s\n",
   1694 		    mlx_ccb_diagnose(mc));
   1695 	else
   1696 		aprint_normal_dev(mlx->mlx_dv, "rebuild started for %d:%d\n",
   1697 		    channel, target);
   1698 
   1699 	error = mc->mc_status;
   1700 
   1701  out:
   1702 	if (mc != NULL)
   1703 		mlx_ccb_free(mlx, mc);
   1704 
   1705 	return (error);
   1706 }
   1707 
   1708 /*
   1709  * Take a command from user-space and try to run it.
   1710  *
   1711  * XXX Note that this can't perform very much in the way of error checking,
   1712  * XXX and as such, applications _must_ be considered trustworthy.
   1713  *
   1714  * XXX Commands using S/G for data are not supported.
   1715  */
   1716 static int
   1717 mlx_user_command(struct mlx_softc *mlx, struct mlx_usercommand *mu)
   1718 {
   1719 	struct mlx_ccb *mc;
   1720 	struct mlx_dcdb *dcdb;
   1721 	void *kbuf;
   1722 	int rv, mapped;
   1723 
   1724 	if ((mu->mu_bufdir & ~MU_XFER_MASK) != 0)
   1725 		return (EINVAL);
   1726 
   1727 	kbuf = NULL;
   1728 	dcdb = NULL;
   1729 	mapped = 0;
   1730 
   1731 	/* Get ourselves a command and copy in from user space. */
   1732 	if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0) {
   1733 		DPRINTF(("mlx_user_command: mlx_ccb_alloc = %d\n", rv));
   1734 		goto out;
   1735 	}
   1736 
   1737 	memcpy(mc->mc_mbox, mu->mu_command, sizeof(mc->mc_mbox));
   1738 
   1739 	/*
   1740 	 * If we need a buffer for data transfer, allocate one and copy in
   1741 	 * its initial contents.
   1742 	 */
   1743 	if (mu->mu_datasize > 0) {
   1744 		if (mu->mu_datasize > MAXPHYS)
   1745 			return (EINVAL);
   1746 
   1747 		kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK);
   1748 		if (kbuf == NULL) {
   1749 			DPRINTF(("mlx_user_command: malloc = NULL\n"));
   1750 			rv = ENOMEM;
   1751 			goto out;
   1752 		}
   1753 
   1754 		if ((mu->mu_bufdir & MU_XFER_OUT) != 0) {
   1755 			rv = copyin(mu->mu_buf, kbuf, mu->mu_datasize);
   1756 			if (rv != 0) {
   1757 				DPRINTF(("mlx_user_command: copyin = %d\n",
   1758 				    rv));
   1759 				goto out;
   1760 			}
   1761 		}
   1762 
   1763 		/* Map the buffer so the controller can see it. */
   1764 		rv = mlx_ccb_map(mlx, mc, kbuf, mu->mu_datasize, mu->mu_bufdir);
   1765 		if (rv != 0) {
   1766 			DPRINTF(("mlx_user_command: mlx_ccb_map = %d\n", rv));
   1767 			goto out;
   1768 		}
   1769 		if (mc->mc_nsgent > 1) {
   1770 			DPRINTF(("mlx_user_command: too many s/g entries\n"));
   1771 			rv = EFBIG;
   1772 			goto out;
   1773 		}
   1774 		mapped = 1;
   1775 		/*
   1776 		 * If this is a passthrough SCSI command, the DCDB is packed at
   1777 		 * the beginning of the data area.  Fix up the DCDB to point to
   1778 		 * the correct physical address and override any bufptr
   1779 		 * supplied by the caller since we know what it's meant to be.
   1780 		 */
   1781 		if (mc->mc_mbox[0] == MLX_CMD_DIRECT_CDB) {
   1782 			dcdb = (struct mlx_dcdb *)kbuf;
   1783 			dcdb->dcdb_physaddr = mc->mc_xfer_phys + sizeof(*dcdb);
   1784 			mu->mu_bufptr = 8;
   1785 		}
   1786 	}
   1787 
   1788 
   1789 	/*
   1790 	 * If there's a data buffer, fix up the command's buffer pointer.
   1791 	 */
   1792 	if (mu->mu_datasize > 0) {
   1793 		/* Range check the pointer to physical buffer address. */
   1794 		if (mu->mu_bufptr < 0 ||
   1795 		    mu->mu_bufptr > sizeof(mu->mu_command) - 4) {
   1796 			DPRINTF(("mlx_user_command: bufptr botch\n"));
   1797 			rv = EINVAL;
   1798 			goto out;
   1799 		}
   1800 
   1801 		mc->mc_mbox[mu->mu_bufptr] = mc->mc_xfer_phys;
   1802 		mc->mc_mbox[mu->mu_bufptr+1] = mc->mc_xfer_phys >> 8;
   1803 		mc->mc_mbox[mu->mu_bufptr+2] = mc->mc_xfer_phys >> 16;
   1804 		mc->mc_mbox[mu->mu_bufptr+3] = mc->mc_xfer_phys >> 24;
   1805 	}
   1806 
   1807 	/* Submit the command and wait. */
   1808 	if ((rv = mlx_ccb_wait(mlx, mc)) != 0) {
   1809 #ifdef DEBUG
   1810 		printf("mlx_user_command: mlx_ccb_wait = %d\n", rv);
   1811 #endif
   1812 	}
   1813 
   1814  out:
   1815 	if (mc != NULL) {
   1816 		/* Copy out status and data */
   1817 		mu->mu_status = mc->mc_status;
   1818 		if (mapped)
   1819 			mlx_ccb_unmap(mlx, mc);
   1820 		mlx_ccb_free(mlx, mc);
   1821 	}
   1822 
   1823 	if (kbuf != NULL) {
   1824 		if (mu->mu_datasize > 0 && (mu->mu_bufdir & MU_XFER_IN) != 0) {
   1825 			rv = copyout(kbuf, mu->mu_buf, mu->mu_datasize);
   1826 #ifdef DIAGNOSTIC
   1827 			if (rv != 0)
   1828 				printf("mlx_user_command: copyout = %d\n", rv);
   1829 #endif
   1830 		}
   1831 	}
   1832 	if (kbuf != NULL)
   1833 		free(kbuf, M_DEVBUF);
   1834 
   1835 	return (rv);
   1836 }
   1837 
   1838 /*
   1839  * Allocate and initialise a CCB.
   1840  */
   1841 int
   1842 mlx_ccb_alloc(struct mlx_softc *mlx, struct mlx_ccb **mcp, int control)
   1843 {
   1844 	struct mlx_ccb *mc;
   1845 	int s;
   1846 
   1847 	s = splbio();
   1848 	mc = SLIST_FIRST(&mlx->mlx_ccb_freelist);
   1849 	if (control) {
   1850 		if (mlx->mlx_nccbs_ctrl >= MLX_NCCBS_CONTROL) {
   1851 			splx(s);
   1852 			*mcp = NULL;
   1853 			return (EAGAIN);
   1854 		}
   1855 		mc->mc_flags |= MC_CONTROL;
   1856 		mlx->mlx_nccbs_ctrl++;
   1857 	}
   1858 	SLIST_REMOVE_HEAD(&mlx->mlx_ccb_freelist, mc_chain.slist);
   1859 	splx(s);
   1860 
   1861 	*mcp = mc;
   1862 	return (0);
   1863 }
   1864 
   1865 /*
   1866  * Free a CCB.
   1867  */
   1868 void
   1869 mlx_ccb_free(struct mlx_softc *mlx, struct mlx_ccb *mc)
   1870 {
   1871 	int s;
   1872 
   1873 	s = splbio();
   1874 	if ((mc->mc_flags & MC_CONTROL) != 0)
   1875 		mlx->mlx_nccbs_ctrl--;
   1876 	mc->mc_flags = 0;
   1877 	SLIST_INSERT_HEAD(&mlx->mlx_ccb_freelist, mc, mc_chain.slist);
   1878 	splx(s);
   1879 }
   1880 
   1881 /*
   1882  * If a CCB is specified, enqueue it.  Pull CCBs off the software queue in
   1883  * the order that they were enqueued and try to submit their mailboxes to
   1884  * the controller for execution.
   1885  */
   1886 void
   1887 mlx_ccb_enqueue(struct mlx_softc *mlx, struct mlx_ccb *mc)
   1888 {
   1889 	int s;
   1890 
   1891 	s = splbio();
   1892 
   1893 	if (mc != NULL)
   1894 		SIMPLEQ_INSERT_TAIL(&mlx->mlx_ccb_queue, mc, mc_chain.simpleq);
   1895 
   1896 	while ((mc = SIMPLEQ_FIRST(&mlx->mlx_ccb_queue)) != NULL) {
   1897 		if (mlx_ccb_submit(mlx, mc) != 0)
   1898 			break;
   1899 		SIMPLEQ_REMOVE_HEAD(&mlx->mlx_ccb_queue, mc_chain.simpleq);
   1900 		TAILQ_INSERT_TAIL(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq);
   1901 	}
   1902 
   1903 	splx(s);
   1904 }
   1905 
   1906 /*
   1907  * Map the specified CCB's data buffer onto the bus, and fill the
   1908  * scatter-gather list.
   1909  */
   1910 int
   1911 mlx_ccb_map(struct mlx_softc *mlx, struct mlx_ccb *mc, void *data, int size,
   1912 	    int dir)
   1913 {
   1914 	struct mlx_sgentry *sge;
   1915 	int nsegs, i, rv, sgloff;
   1916 	bus_dmamap_t xfer;
   1917 
   1918 	xfer = mc->mc_xfer_map;
   1919 
   1920 	rv = bus_dmamap_load(mlx->mlx_dmat, xfer, data, size, NULL,
   1921 	    BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
   1922 	    ((dir & MC_XFER_IN) ? BUS_DMA_READ : BUS_DMA_WRITE));
   1923 	if (rv != 0)
   1924 		return (rv);
   1925 
   1926 	nsegs = xfer->dm_nsegs;
   1927 	mc->mc_xfer_size = size;
   1928 	mc->mc_flags |= dir;
   1929 	mc->mc_nsgent = nsegs;
   1930 	mc->mc_xfer_phys = xfer->dm_segs[0].ds_addr;
   1931 
   1932 	sgloff = MLX_SGL_SIZE * mc->mc_ident;
   1933 	sge = (struct mlx_sgentry *)((char *)mlx->mlx_sgls + sgloff);
   1934 
   1935 	for (i = 0; i < nsegs; i++, sge++) {
   1936 		sge->sge_addr = htole32(xfer->dm_segs[i].ds_addr);
   1937 		sge->sge_count = htole32(xfer->dm_segs[i].ds_len);
   1938 	}
   1939 
   1940 	if ((dir & MC_XFER_OUT) != 0)
   1941 		i = BUS_DMASYNC_PREWRITE;
   1942 	else
   1943 		i = 0;
   1944 	if ((dir & MC_XFER_IN) != 0)
   1945 		i |= BUS_DMASYNC_PREREAD;
   1946 
   1947 	bus_dmamap_sync(mlx->mlx_dmat, xfer, 0, mc->mc_xfer_size, i);
   1948 	bus_dmamap_sync(mlx->mlx_dmat, mlx->mlx_dmamap, sgloff,
   1949 	    MLX_SGL_SIZE, BUS_DMASYNC_PREWRITE);
   1950 
   1951 	return (0);
   1952 }
   1953 
   1954 /*
   1955  * Unmap the specified CCB's data buffer.
   1956  */
   1957 void
   1958 mlx_ccb_unmap(struct mlx_softc *mlx, struct mlx_ccb *mc)
   1959 {
   1960 	int i;
   1961 
   1962 	bus_dmamap_sync(mlx->mlx_dmat, mlx->mlx_dmamap,
   1963 	    MLX_SGL_SIZE * mc->mc_ident, MLX_SGL_SIZE,
   1964 	    BUS_DMASYNC_POSTWRITE);
   1965 
   1966 	if ((mc->mc_flags & MC_XFER_OUT) != 0)
   1967 		i = BUS_DMASYNC_POSTWRITE;
   1968 	else
   1969 		i = 0;
   1970 	if ((mc->mc_flags & MC_XFER_IN) != 0)
   1971 		i |= BUS_DMASYNC_POSTREAD;
   1972 
   1973 	bus_dmamap_sync(mlx->mlx_dmat, mc->mc_xfer_map, 0, mc->mc_xfer_size, i);
   1974 	bus_dmamap_unload(mlx->mlx_dmat, mc->mc_xfer_map);
   1975 }
   1976 
   1977 /*
   1978  * Submit the CCB, and busy-wait for it to complete.  Return non-zero on
   1979  * timeout or submission error.  Must be called with interrupts blocked.
   1980  */
   1981 int
   1982 mlx_ccb_poll(struct mlx_softc *mlx, struct mlx_ccb *mc, int timo)
   1983 {
   1984 	int rv;
   1985 
   1986 	mc->mc_mx.mx_handler = NULL;
   1987 
   1988 	if ((rv = mlx_ccb_submit(mlx, mc)) != 0)
   1989 		return (rv);
   1990 	TAILQ_INSERT_TAIL(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq);
   1991 
   1992 	for (timo *= 10; timo != 0; timo--) {
   1993 		mlx_intr(mlx);
   1994 		if (mc->mc_status != MLX_STATUS_BUSY)
   1995 			break;
   1996 		DELAY(100);
   1997 	}
   1998 
   1999 	if (timo != 0) {
   2000 		if (mc->mc_status != 0) {
   2001 			aprint_error_dev(mlx->mlx_dv, "command failed - %s\n",
   2002 			    mlx_ccb_diagnose(mc));
   2003 			rv = EIO;
   2004 		} else
   2005 			rv = 0;
   2006 	} else {
   2007 		printf("%s: command timed out\n", device_xname(mlx->mlx_dv));
   2008 		rv = EIO;
   2009 	}
   2010 
   2011 	return (rv);
   2012 }
   2013 
   2014 /*
   2015  * Enqueue the CCB, and sleep until it completes.  Return non-zero on
   2016  * timeout or error.
   2017  */
   2018 int
   2019 mlx_ccb_wait(struct mlx_softc *mlx, struct mlx_ccb *mc)
   2020 {
   2021 	int s;
   2022 
   2023 	mc->mc_flags |= MC_WAITING;
   2024 	mc->mc_mx.mx_handler = NULL;
   2025 
   2026 	s = splbio();
   2027 	mlx_ccb_enqueue(mlx, mc);
   2028 	tsleep(mc, PRIBIO, "mlxwccb", 0);
   2029 	splx(s);
   2030 
   2031 	if (mc->mc_status != 0) {
   2032 		aprint_error_dev(mlx->mlx_dv, "command failed - %s\n",
   2033 		    mlx_ccb_diagnose(mc));
   2034 		return (EIO);
   2035 	}
   2036 
   2037 	return (0);
   2038 }
   2039 
   2040 /*
   2041  * Try to submit a CCB's mailbox to the controller for execution.  Return
   2042  * non-zero on timeout or error.  Must be called with interrupts blocked.
   2043  */
   2044 static int
   2045 mlx_ccb_submit(struct mlx_softc *mlx, struct mlx_ccb *mc)
   2046 {
   2047 	int i, s, r;
   2048 
   2049 	/* Save the ident so we can handle this command when complete. */
   2050 	mc->mc_mbox[1] = (u_int8_t)(mc->mc_ident + 1);
   2051 
   2052 	/* Mark the command as currently being processed. */
   2053 	mc->mc_status = MLX_STATUS_BUSY;
   2054 	mc->mc_expiry = time_second + MLX_TIMEOUT;
   2055 
   2056 	/* Spin waiting for the mailbox. */
   2057 	for (i = 100; i != 0; i--) {
   2058 		s = splbio();
   2059 		r = (*mlx->mlx_submit)(mlx, mc);
   2060 		splx(s);
   2061 		if (r != 0)
   2062 			break;
   2063 		DELAY(100);
   2064 	}
   2065 	if (i != 0)
   2066 		return (0);
   2067 
   2068 	DPRINTF(("mlx_ccb_submit: rejected; queueing\n"));
   2069 	mc->mc_status = MLX_STATUS_WEDGED;
   2070 	return (EIO);
   2071 }
   2072 
   2073 /*
   2074  * Return a string that describes why a command has failed.
   2075  */
   2076 const char *
   2077 mlx_ccb_diagnose(struct mlx_ccb *mc)
   2078 {
   2079 	static char tbuf[80];
   2080 	int i;
   2081 
   2082 	for (i = 0; i < sizeof(mlx_msgs) / sizeof(mlx_msgs[0]); i++)
   2083 		if ((mc->mc_mbox[0] == mlx_msgs[i].command ||
   2084 		    mlx_msgs[i].command == 0) &&
   2085 		    mc->mc_status == mlx_msgs[i].status) {
   2086 			snprintf(tbuf, sizeof(tbuf), "%s (0x%x)",
   2087 			    mlx_status_msgs[mlx_msgs[i].msg], mc->mc_status);
   2088 			return (tbuf);
   2089 		}
   2090 
   2091 	snprintf(tbuf, sizeof(tbuf), "unknown response 0x%x for command 0x%x",
   2092 	    (int)mc->mc_status, (int)mc->mc_mbox[0]);
   2093 
   2094 	return (tbuf);
   2095 }
   2096 
   2097 /*
   2098  * Poll the controller for completed commands.  Returns non-zero if one or
   2099  * more commands were completed.  Must be called with interrupts blocked.
   2100  */
   2101 int
   2102 mlx_intr(void *cookie)
   2103 {
   2104 	struct mlx_softc *mlx;
   2105 	struct mlx_ccb *mc;
   2106 	int result;
   2107 	u_int ident, status;
   2108 
   2109 	mlx = cookie;
   2110 	result = 0;
   2111 
   2112 	while ((*mlx->mlx_findcomplete)(mlx, &ident, &status) != 0) {
   2113 		result = 1;
   2114 		ident--;
   2115 
   2116 		if (ident >= MLX_MAX_QUEUECNT) {
   2117 			aprint_error_dev(mlx->mlx_dv,
   2118 			    "bad completion returned\n");
   2119 			continue;
   2120 		}
   2121 
   2122 		mc = mlx->mlx_ccbs + ident;
   2123 
   2124 		if (mc->mc_status != MLX_STATUS_BUSY) {
   2125 			aprint_error_dev(mlx->mlx_dv,
   2126 			    "bad completion returned\n");
   2127 			continue;
   2128 		}
   2129 
   2130 		TAILQ_REMOVE(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq);
   2131 
   2132 		/* Record status and notify the initiator, if requested. */
   2133 		mc->mc_status = status;
   2134 		if (mc->mc_mx.mx_handler != NULL)
   2135 			(*mc->mc_mx.mx_handler)(mc);
   2136 		else if ((mc->mc_flags & MC_WAITING) != 0)
   2137 			wakeup(mc);
   2138 	}
   2139 
   2140 	/* If we've completed any commands, try posting some more. */
   2141 	if (result)
   2142 		mlx_ccb_enqueue(mlx, NULL);
   2143 
   2144 	return (result);
   2145 }
   2146 
   2147 /*
   2148  * Emit a string describing the firmware handshake status code, and return a
   2149  * flag indicating whether the code represents a fatal error.
   2150  *
   2151  * Error code interpretations are from the Linux driver, and don't directly
   2152  * match the messages printed by Mylex's BIOS.  This may change if
   2153  * documentation on the codes is forthcoming.
   2154  */
   2155 static int
   2156 mlx_fw_message(struct mlx_softc *mlx, int error, int param1, int param2)
   2157 {
   2158 	const char *fmt;
   2159 
   2160 	switch (error) {
   2161 	case 0x00:
   2162 		fmt = "physical drive %d:%d not responding";
   2163 		break;
   2164 
   2165 	case 0x08:
   2166 		/*
   2167 		 * We could be neater about this and give some indication
   2168 		 * when we receive more of them.
   2169 		 */
   2170 		if ((mlx->mlx_flags & MLXF_SPINUP_REPORTED) == 0) {
   2171 			printf("%s: spinning up drives...\n",
   2172 			    device_xname(mlx->mlx_dv));
   2173 			mlx->mlx_flags |= MLXF_SPINUP_REPORTED;
   2174 		}
   2175 		return (0);
   2176 
   2177 	case 0x30:
   2178 		fmt = "configuration checksum error";
   2179 		break;
   2180 
   2181 	case 0x60:
   2182 		fmt = "mirror race recovery failed";
   2183 		break;
   2184 
   2185 	case 0x70:
   2186 		fmt = "mirror race recovery in progress";
   2187 		break;
   2188 
   2189 	case 0x90:
   2190 		fmt = "physical drive %d:%d COD mismatch";
   2191 		break;
   2192 
   2193 	case 0xa0:
   2194 		fmt = "logical drive installation aborted";
   2195 		break;
   2196 
   2197 	case 0xb0:
   2198 		fmt = "mirror race on a critical system drive";
   2199 		break;
   2200 
   2201 	case 0xd0:
   2202 		fmt = "new controller configuration found";
   2203 		break;
   2204 
   2205 	case 0xf0:
   2206 		aprint_error_dev(mlx->mlx_dv, "FATAL MEMORY PARITY ERROR\n");
   2207 		return (1);
   2208 
   2209 	default:
   2210 		aprint_error_dev(mlx->mlx_dv,
   2211 		    "unknown firmware init error %02x:%02x:%02x\n",
   2212 		    error, param1, param2);
   2213 		return (0);
   2214 	}
   2215 
   2216 	aprint_normal_dev(mlx->mlx_dv, fmt, param2, param1);
   2217 	aprint_normal("\n");
   2218 
   2219 	return (0);
   2220 }
   2221 
   2222 MODULE(MODULE_CLASS_DRIVER, mlx, NULL);
   2223 
   2224 #ifdef _MODULE
   2225 CFDRIVER_DECL(cac, DV_DISK, NULL);
   2226 #endif
   2227 
   2228 static int
   2229 mlx_modcmd(modcmd_t cmd, void *opaque)
   2230 {
   2231 	int error = 0;
   2232 
   2233 #ifdef _MODULE
   2234 	switch (cmd) {
   2235 	case MODULE_CMD_INIT:
   2236 		error = config_cfdriver_attach(&mlx_cd);
   2237 		break;
   2238 	case MODULE_CMD_FINI:
   2239 		error = config_cfdriver_detach(&mlx_cd);
   2240 		break;
   2241 	default:
   2242 		error = ENOTTY;
   2243 		break;
   2244 	}
   2245 #endif
   2246 	return error;
   2247 }
   2248