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