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