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