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