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