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