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