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