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