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