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