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