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