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
111static void	mlx_adjqparam(struct mlx_softc *, int, int);
112static int	mlx_ccb_submit(struct mlx_softc *, struct mlx_ccb *);
113static int	mlx_check(struct mlx_softc *, int);
114static void	mlx_describe(struct mlx_softc *);
115static void	*mlx_enquire(struct mlx_softc *, int, size_t,
116			     void (*)(struct mlx_ccb *), int);
117static int	mlx_fw_message(struct mlx_softc *, int, int, int);
118static void	mlx_pause_action(struct mlx_softc *);
119static void	mlx_pause_done(struct mlx_ccb *);
120static void	mlx_periodic(struct mlx_softc *);
121static void	mlx_periodic_enquiry(struct mlx_ccb *);
122static void	mlx_periodic_eventlog_poll(struct mlx_softc *);
123static void	mlx_periodic_eventlog_respond(struct mlx_ccb *);
124static void	mlx_periodic_rebuild(struct mlx_ccb *);
125static void	mlx_periodic_thread(void *);
126static int	mlx_print(void *, const char *);
127static int	mlx_rebuild(struct mlx_softc *, int, int);
128static void	mlx_shutdown(void *);
129static int	mlx_user_command(struct mlx_softc *, struct mlx_usercommand *);
130
131dev_type_open(mlxopen);
132dev_type_close(mlxclose);
133dev_type_ioctl(mlxioctl);
134
135const 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
150static struct	lwp *mlx_periodic_lwp;
151static void	*mlx_sdh;
152
153static 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
170static 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
186static 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
212static 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 */
259void
260mlx_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 */
520static void
521mlx_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 */
555int
556mlx_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 */
650static int
651mlx_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 */
666static void
667mlx_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 */
680static void
681mlx_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 */
700int
701mlxopen(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 */
719int
720mlxclose(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 */
732int
733mlxioctl(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
953static void
954mlx_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
969static void
970mlx_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 */
1061static void
1062mlx_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 */
1221static void
1222mlx_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 */
1270static void
1271mlx_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 */
1375static void
1376mlx_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 */
1447static void
1448mlx_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
1496static void
1497mlx_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 */
1528static void *
1529mlx_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 */
1597int
1598mlx_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 */
1632static int
1633mlx_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 */
1674static int
1675mlx_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 */
1717static int
1718mlx_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 */
1842int
1843mlx_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 */
1869void
1870mlx_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 */
1887void
1888mlx_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 */
1911int
1912mlx_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 */
1958void
1959mlx_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 */
1982int
1983mlx_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 */
2019int
2020mlx_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 */
2045static int
2046mlx_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 */
2077const char *
2078mlx_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 */
2102int
2103mlx_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 */
2156static int
2157mlx_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
2223MODULE(MODULE_CLASS_DRIVER, mlx, NULL);
2224
2225#ifdef _MODULE
2226CFDRIVER_DECL(cac, DV_DISK, NULL);
2227#endif
2228
2229static int
2230mlx_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