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