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