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