1/*	$NetBSD: aac.c,v 1.49 2021/08/07 16:19:11 thorpej Exp $	*/
2
3/*-
4 * Copyright (c) 2002, 2007 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) 2001 Scott Long
34 * Copyright (c) 2001 Adaptec, Inc.
35 * Copyright (c) 2000 Michael Smith
36 * Copyright (c) 2000 BSDi
37 * Copyright (c) 2000 Niklas Hallqvist
38 * All rights reserved.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 *    notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 *    notice, this list of conditions and the following disclaimer in the
47 *    documentation and/or other materials provided with the distribution.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 */
61
62/*
63 * Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters.
64 *
65 * TODO:
66 *
67 * o Management interface.
68 * o Look again at some of the portability issues.
69 * o Handle various AIFs (e.g., notification that a container is going away).
70 */
71
72#include <sys/cdefs.h>
73__KERNEL_RCSID(0, "$NetBSD: aac.c,v 1.49 2021/08/07 16:19:11 thorpej Exp $");
74
75#include <sys/param.h>
76#include <sys/systm.h>
77#include <sys/buf.h>
78#include <sys/device.h>
79#include <sys/kernel.h>
80#include <sys/malloc.h>
81#include <sys/proc.h>
82#include <sys/module.h>
83
84#include <sys/bus.h>
85
86#include <dev/ic/aacreg.h>
87#include <dev/ic/aacvar.h>
88#include <dev/ic/aac_tables.h>
89
90#include "locators.h"
91
92#include "ioconf.h"
93
94static int	aac_new_intr(void *);
95static int	aac_alloc_commands(struct aac_softc *);
96#ifdef notyet
97static void	aac_free_commands(struct aac_softc *);
98#endif
99static int	aac_check_firmware(struct aac_softc *);
100static void	aac_describe_controller(struct aac_softc *);
101static int	aac_dequeue_fib(struct aac_softc *, int, u_int32_t *,
102				struct aac_fib **);
103static int	aac_enqueue_fib(struct aac_softc *, int, struct aac_ccb *);
104static int	aac_enqueue_response(struct aac_softc *, int, struct aac_fib *);
105static void	aac_host_command(struct aac_softc *);
106static void	aac_host_response(struct aac_softc *);
107static int	aac_init(struct aac_softc *);
108static int	aac_print(void *, const char *);
109static void	aac_shutdown(void *);
110static void	aac_startup(struct aac_softc *);
111static int	aac_sync_command(struct aac_softc *, u_int32_t, u_int32_t,
112				 u_int32_t, u_int32_t, u_int32_t, u_int32_t *);
113static int	aac_sync_fib(struct aac_softc *, u_int32_t, u_int32_t, void *,
114			     u_int16_t, void *, u_int16_t *);
115
116#ifdef AAC_DEBUG
117static void	aac_print_fib(struct aac_softc *, struct aac_fib *, const char *);
118#endif
119
120/*
121 * Adapter-space FIB queue manipulation.
122 *
123 * Note that the queue implementation here is a little funky; neither the PI or
124 * CI will ever be zero.  This behaviour is a controller feature.
125 */
126static struct {
127	int	size;
128	int	notify;
129} const aac_qinfo[] = {
130	{ AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL },
131	{ AAC_HOST_HIGH_CMD_ENTRIES, 0 },
132	{ AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY },
133	{ AAC_ADAP_HIGH_CMD_ENTRIES, 0 },
134	{ AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL },
135	{ AAC_HOST_HIGH_RESP_ENTRIES, 0 },
136	{ AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY },
137	{ AAC_ADAP_HIGH_RESP_ENTRIES, 0 }
138};
139
140#ifdef AAC_DEBUG
141int	aac_debug = AAC_DEBUG;
142#endif
143
144MALLOC_DEFINE(M_AACBUF, "aacbuf", "Buffers for aac(4)");
145
146static void	*aac_sdh;
147
148int
149aac_attach(struct aac_softc *sc)
150{
151	int rv;
152
153	SIMPLEQ_INIT(&sc->sc_ccb_free);
154	SIMPLEQ_INIT(&sc->sc_ccb_queue);
155	SIMPLEQ_INIT(&sc->sc_ccb_complete);
156
157	/*
158	 * Disable interrupts before we do anything.
159	 */
160	AAC_MASK_INTERRUPTS(sc);
161
162	/*
163	 * Initialise the adapter.
164	 */
165	if (aac_check_firmware(sc))
166		return (EINVAL);
167
168	if ((rv = aac_init(sc)) != 0)
169		return (rv);
170
171	if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) {
172		rv = sc->sc_intr_set(sc, aac_new_intr, sc);
173		if (rv)
174			return (rv);
175	}
176
177	aac_startup(sc);
178
179	/*
180	 * Print a little information about the controller.
181	 */
182	aac_describe_controller(sc);
183
184	/*
185	 * Attach devices
186	 */
187	aac_devscan(sc);
188
189	/*
190	 * Enable interrupts, and register our shutdown hook.
191	 */
192	sc->sc_flags |= AAC_ONLINE;
193	AAC_UNMASK_INTERRUPTS(sc);
194	if (aac_sdh != NULL)
195		shutdownhook_establish(aac_shutdown, NULL);
196	return (0);
197}
198
199int
200aac_devscan(struct aac_softc *sc)
201{
202	struct aac_attach_args aaca;
203	int i;
204	int locs[AACCF_NLOCS];
205
206	for (i = 0; i < AAC_MAX_CONTAINERS; i++) {
207		if (!sc->sc_hdr[i].hd_present)
208			continue;
209		aaca.aaca_unit = i;
210
211		locs[AACCF_UNIT] = i;
212
213		config_found(sc->sc_dv, &aaca, aac_print,
214		    CFARGS(.submatch = config_stdsubmatch,
215			   .locators = locs));
216	}
217	return 0;
218}
219
220static int
221aac_alloc_commands(struct aac_softc *sc)
222{
223	struct aac_fibmap *fm;
224	struct aac_ccb *ac;
225	bus_addr_t fibpa;
226	int size, nsegs;
227	int i, error;
228	int state;
229
230	if (sc->sc_total_fibs + sc->sc_max_fibs_alloc > sc->sc_max_fibs)
231		return ENOMEM;
232
233	fm = malloc(sizeof(struct aac_fibmap), M_AACBUF, M_NOWAIT|M_ZERO);
234	if (fm == NULL)
235		return ENOMEM;
236
237	size = sc->sc_max_fibs_alloc * sc->sc_max_fib_size;
238
239	state = 0;
240	error = bus_dmamap_create(sc->sc_dmat, size, 1, size,
241	    0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &fm->fm_fibmap);
242	if (error != 0) {
243		aprint_error_dev(sc->sc_dv, "cannot create fibs dmamap (%d)\n",
244		    error);
245		goto bail_out;
246	}
247	state++;
248	error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0,
249	    &fm->fm_fibseg, 1, &nsegs, BUS_DMA_NOWAIT);
250	if (error != 0) {
251		aprint_error_dev(sc->sc_dv, "can't allocate fibs structure (%d)\n",
252		    error);
253		goto bail_out;
254	}
255	state++;
256	error = bus_dmamem_map(sc->sc_dmat, &fm->fm_fibseg, nsegs, size,
257	    (void **)&fm->fm_fibs, 0);
258	if (error != 0) {
259		aprint_error_dev(sc->sc_dv, "can't map fibs structure (%d)\n",
260		    error);
261		goto bail_out;
262	}
263	state++;
264	error = bus_dmamap_load(sc->sc_dmat, fm->fm_fibmap, fm->fm_fibs,
265	    size, NULL, BUS_DMA_NOWAIT);
266	if (error != 0) {
267		aprint_error_dev(sc->sc_dv, "cannot load fibs dmamap (%d)\n",
268		    error);
269		goto bail_out;
270	}
271
272	fm->fm_ccbs = sc->sc_ccbs + sc->sc_total_fibs;
273	fibpa = fm->fm_fibseg.ds_addr;
274
275	memset(fm->fm_fibs, 0, size);
276	for (i = 0; i < sc->sc_max_fibs_alloc; i++) {
277		ac = fm->fm_ccbs + i;
278
279		error = bus_dmamap_create(sc->sc_dmat, AAC_MAX_XFER(sc),
280		    sc->sc_max_sgs, AAC_MAX_XFER(sc), 0,
281		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ac->ac_dmamap_xfer);
282		if (error) {
283			while (--i >= 0) {
284				ac = fm->fm_ccbs + i;
285				bus_dmamap_destroy(sc->sc_dmat,
286				    ac->ac_dmamap_xfer);
287				sc->sc_total_fibs--;
288			}
289			aprint_error_dev(sc->sc_dv, "cannot create ccb dmamap (%d)",
290			    error);
291			goto bail_out;
292		}
293
294		ac->ac_fibmap = fm;
295		ac->ac_fib = (struct aac_fib *)
296		    ((char *) fm->fm_fibs + i * sc->sc_max_fib_size);
297		ac->ac_fibphys = fibpa + i * sc->sc_max_fib_size;
298		aac_ccb_free(sc, ac);
299		sc->sc_total_fibs++;
300	}
301
302	TAILQ_INSERT_TAIL(&sc->sc_fibmap_tqh, fm, fm_link);
303
304	return 0;
305bail_out:
306	if (state > 3)
307		bus_dmamap_unload(sc->sc_dmat, fm->fm_fibmap);
308	if (state > 2)
309		bus_dmamem_unmap(sc->sc_dmat, (void *) fm->fm_fibs, size);
310	if (state > 1)
311		bus_dmamem_free(sc->sc_dmat, &fm->fm_fibseg, 1);
312
313	bus_dmamap_destroy(sc->sc_dmat, fm->fm_fibmap);
314
315	free(fm, M_AACBUF);
316
317	return error;
318}
319
320#ifdef notyet
321static void
322aac_free_commands(struct aac_softc *sc)
323{
324}
325#endif
326
327/*
328 * Print autoconfiguration message for a sub-device.
329 */
330static int
331aac_print(void *aux, const char *pnp)
332{
333	struct aac_attach_args *aaca;
334
335	aaca = aux;
336
337	if (pnp != NULL)
338		aprint_normal("block device at %s", pnp);
339	aprint_normal(" unit %d", aaca->aaca_unit);
340	return (UNCONF);
341}
342
343/*
344 * Look up a text description of a numeric error code and return a pointer to
345 * same.
346 */
347const char *
348aac_describe_code(const struct aac_code_lookup *table, u_int32_t code)
349{
350	int i;
351
352	for (i = 0; table[i].string != NULL; i++)
353		if (table[i].code == code)
354			return (table[i].string);
355
356	return (table[i + 1].string);
357}
358
359/*
360 * snprintb(3) format string for the adapter options.
361 */
362static const char *optfmt =
363    "\20\1SNAPSHOT\2CLUSTERS\3WCACHE\4DATA64\5HOSTTIME\6RAID50"
364    "\7WINDOW4GB"
365    "\10SCSIUPGD\11SOFTERR\12NORECOND\13SGMAP64\14ALARM\15NONDASD";
366
367static void
368aac_describe_controller(struct aac_softc *sc)
369{
370	u_int8_t fmtbuf[256];
371	u_int8_t tbuf[AAC_FIB_DATASIZE];
372	u_int16_t bufsize;
373	struct aac_adapter_info *info;
374	u_int8_t arg;
375
376	arg = 0;
377	if (aac_sync_fib(sc, RequestAdapterInfo, 0, &arg, sizeof(arg), &tbuf,
378	    &bufsize)) {
379		aprint_error_dev(sc->sc_dv, "RequestAdapterInfo failed\n");
380		return;
381	}
382	if (bufsize != sizeof(*info)) {
383		aprint_error_dev(sc->sc_dv,
384		    "RequestAdapterInfo returned wrong data size (%d != %zu)\n",
385		    bufsize, sizeof(*info));
386		return;
387	}
388	info = (struct aac_adapter_info *)&tbuf[0];
389
390	aprint_normal_dev(sc->sc_dv, "%s at %dMHz, %dMB mem (%dMB cache), %s\n",
391	    aac_describe_code(aac_cpu_variant, le32toh(info->CpuVariant)),
392	    le32toh(info->ClockSpeed),
393	    le32toh(info->TotalMem) / (1024 * 1024),
394	    le32toh(info->BufferMem) / (1024 * 1024),
395	    aac_describe_code(aac_battery_platform,
396			      le32toh(info->batteryPlatform)));
397
398	aprint_verbose_dev(sc->sc_dv, "Kernel %d.%d-%d [Build %d], ",
399	    info->KernelRevision.external.comp.major,
400	    info->KernelRevision.external.comp.minor,
401	    info->KernelRevision.external.comp.dash,
402	    info->KernelRevision.buildNumber);
403
404	aprint_verbose("Monitor %d.%d-%d [Build %d], S/N %6X\n",
405	    info->MonitorRevision.external.comp.major,
406	    info->MonitorRevision.external.comp.minor,
407	    info->MonitorRevision.external.comp.dash,
408	    info->MonitorRevision.buildNumber,
409	    ((u_int32_t)info->SerialNumber & 0xffffff));
410
411	snprintb(fmtbuf, sizeof(fmtbuf), optfmt, sc->sc_supported_options);
412	aprint_verbose_dev(sc->sc_dv, "Controller supports: %s\n", fmtbuf);
413
414	/* Save the kernel revision structure for later use. */
415	sc->sc_revision = info->KernelRevision;
416}
417
418/*
419 * Retrieve the firmware version numbers.  Dell PERC2/QC cards with firmware
420 * version 1.x are not compatible with this driver.
421 */
422static int
423aac_check_firmware(struct aac_softc *sc)
424{
425	u_int32_t major, minor, opts, atusize = 0, status = 0;
426	u_int32_t calcsgs;
427
428	if ((sc->sc_quirks & AAC_QUIRK_PERC2QC) != 0) {
429		if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0,
430		    NULL)) {
431			aprint_error_dev(sc->sc_dv, "error reading firmware version\n");
432			return (1);
433		}
434
435		/* These numbers are stored as ASCII! */
436		major = (AAC_GET_MAILBOX(sc, 1) & 0xff) - 0x30;
437		minor = (AAC_GET_MAILBOX(sc, 2) & 0xff) - 0x30;
438		if (major == 1) {
439			aprint_error_dev(sc->sc_dv,
440			    "firmware version %d.%d not supported.\n",
441			    major, minor);
442			return (1);
443		}
444	}
445
446	if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, &status)) {
447		if (status != AAC_SRB_STS_INVALID_REQUEST) {
448			aprint_error_dev(sc->sc_dv, "GETINFO failed, status 0x%08x\n", status);
449			return (1);
450		}
451	} else {
452		opts = AAC_GET_MAILBOX(sc, 1);
453		atusize = AAC_GET_MAILBOX(sc, 2);
454		sc->sc_supported_options = opts;
455
456		if (((opts & AAC_SUPPORTED_4GB_WINDOW) != 0) &&
457		    ((sc->sc_quirks & AAC_QUIRK_NO4GB) == 0) )
458			sc->sc_quirks |= AAC_QUIRK_4GB_WINDOW;
459
460		if (((opts & AAC_SUPPORTED_SGMAP_HOST64) != 0) &&
461		    (sizeof(bus_addr_t) > 4)) {
462			aprint_normal_dev(sc->sc_dv, "Enabling 64-bit address support\n");
463			sc->sc_quirks |= AAC_QUIRK_SG_64BIT;
464		}
465		if ((opts & AAC_SUPPORTED_NEW_COMM) &&
466		    (sc->sc_if.aif_send_command != NULL)) {
467			sc->sc_quirks |= AAC_QUIRK_NEW_COMM;
468		}
469		if (opts & AAC_SUPPORTED_64BIT_ARRAYSIZE)
470			sc->sc_quirks |= AAC_QUIRK_ARRAY_64BIT;
471	}
472
473	sc->sc_max_fibs = (sc->sc_quirks & AAC_QUIRK_256FIBS) ? 256 : 512;
474
475	if (   (sc->sc_quirks & AAC_QUIRK_NEW_COMM)
476	    && (sc->sc_regsize < atusize)) {
477		aprint_error_dev(sc->sc_dv, "Not enabling new comm i/f -- "
478			     "atusize 0x%08x, regsize 0x%08x\n",
479			     atusize,
480			     (uint32_t) sc->sc_regsize);
481		sc->sc_quirks &= ~AAC_QUIRK_NEW_COMM;
482	}
483#if 0
484	if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) {
485		aprint_error_dev(sc->sc_dv, "Not enabling new comm i/f -- "
486			     "driver not ready yet\n");
487		sc->sc_quirks &= ~AAC_QUIRK_NEW_COMM;
488	}
489#endif
490
491	sc->sc_max_fib_size = sizeof(struct aac_fib);
492	sc->sc_max_sectors = 128;	/* 64KB */
493	if (sc->sc_quirks & AAC_QUIRK_SG_64BIT)
494		sc->sc_max_sgs = (sc->sc_max_fib_size
495					- sizeof(struct aac_blockwrite64)
496					+ sizeof(struct aac_sg_table64))
497				      / sizeof(struct aac_sg_table64);
498	else
499		sc->sc_max_sgs = (sc->sc_max_fib_size
500					- sizeof(struct aac_blockwrite)
501					+ sizeof(struct aac_sg_table))
502				      / sizeof(struct aac_sg_table);
503
504	if (!aac_sync_command(sc, AAC_MONKER_GETCOMMPREF, 0, 0, 0, 0, NULL)) {
505		u_int32_t	opt1, opt2, opt3;
506		u_int32_t	tmpval;
507
508		opt1 = AAC_GET_MAILBOX(sc, 1);
509		opt2 = AAC_GET_MAILBOX(sc, 2);
510		opt3 = AAC_GET_MAILBOX(sc, 3);
511		if (!opt1 || !opt2 || !opt3) {
512			aprint_verbose_dev(sc->sc_dv, "GETCOMMPREF appears untrustworthy."
513			    "  Ignoring.\n");
514		} else {
515			sc->sc_max_fib_size = le32toh(opt1) & 0xffff;
516			sc->sc_max_sectors = (le32toh(opt1) >> 16) << 1;
517			tmpval = (le32toh(opt2) >> 16);
518			if (tmpval < sc->sc_max_sgs) {
519				sc->sc_max_sgs = tmpval;
520			}
521			tmpval = (le32toh(opt3) & 0xffff);
522			if (tmpval < sc->sc_max_fibs) {
523				sc->sc_max_fibs = tmpval;
524			}
525		}
526	}
527	if (sc->sc_max_fib_size > PAGE_SIZE)
528		sc->sc_max_fib_size = PAGE_SIZE;
529
530	if (sc->sc_quirks & AAC_QUIRK_SG_64BIT)
531		calcsgs = (sc->sc_max_fib_size
532			   - sizeof(struct aac_blockwrite64)
533			   + sizeof(struct aac_sg_table64))
534			      / sizeof(struct aac_sg_table64);
535	else
536		calcsgs = (sc->sc_max_fib_size
537			   - sizeof(struct aac_blockwrite)
538			   + sizeof(struct aac_sg_table))
539			      / sizeof(struct aac_sg_table);
540
541	if (calcsgs < sc->sc_max_sgs) {
542		sc->sc_max_sgs = calcsgs;
543	}
544
545	sc->sc_max_fibs_alloc = PAGE_SIZE / sc->sc_max_fib_size;
546
547	if (sc->sc_max_fib_size > sizeof(struct aac_fib)) {
548		sc->sc_quirks |= AAC_QUIRK_RAW_IO;
549		aprint_debug_dev(sc->sc_dv, "Enable raw I/O\n");
550	}
551	if ((sc->sc_quirks & AAC_QUIRK_RAW_IO) &&
552	    (sc->sc_quirks & AAC_QUIRK_ARRAY_64BIT)) {
553		sc->sc_quirks |= AAC_QUIRK_LBA_64BIT;
554		aprint_normal_dev(sc->sc_dv, "Enable 64-bit array support\n");
555	}
556
557	return (0);
558}
559
560static int
561aac_init(struct aac_softc *sc)
562{
563	int nsegs, i, rv, state, norm, high;
564	struct aac_adapter_init	*ip;
565	u_int32_t code, qoff;
566
567	state = 0;
568
569	/*
570	 * First wait for the adapter to come ready.
571	 */
572	for (i = 0; i < AAC_BOOT_TIMEOUT * 1000; i++) {
573		code = AAC_GET_FWSTATUS(sc);
574		if ((code & AAC_SELF_TEST_FAILED) != 0) {
575			aprint_error_dev(sc->sc_dv, "FATAL: selftest failed\n");
576			return (ENXIO);
577		}
578		if ((code & AAC_KERNEL_PANIC) != 0) {
579			aprint_error_dev(sc->sc_dv, "FATAL: controller kernel panic\n");
580			return (ENXIO);
581		}
582		if ((code & AAC_UP_AND_RUNNING) != 0)
583			break;
584		DELAY(1000);
585	}
586	if (i == AAC_BOOT_TIMEOUT * 1000) {
587		aprint_error_dev(sc->sc_dv,
588		    "FATAL: controller not coming ready, status %x\n",
589		    code);
590		return (ENXIO);
591	}
592
593	sc->sc_aif_fib = malloc(sizeof(struct aac_fib), M_AACBUF,
594	    M_WAITOK | M_ZERO);
595	if ((rv = bus_dmamap_create(sc->sc_dmat, sizeof(*sc->sc_common), 1,
596	    sizeof(*sc->sc_common), 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
597	    &sc->sc_common_dmamap)) != 0) {
598		aprint_error_dev(sc->sc_dv, "cannot create common dmamap\n");
599		goto bail_out;
600	}
601	state++;
602	if ((rv = bus_dmamem_alloc(sc->sc_dmat, sizeof(*sc->sc_common),
603	    PAGE_SIZE, 0, &sc->sc_common_seg, 1, &nsegs,
604	    BUS_DMA_NOWAIT)) != 0) {
605		aprint_error_dev(sc->sc_dv, "can't allocate common structure\n");
606		goto bail_out;
607	}
608	state++;
609	if ((rv = bus_dmamem_map(sc->sc_dmat, &sc->sc_common_seg, nsegs,
610	    sizeof(*sc->sc_common), (void **)&sc->sc_common, 0)) != 0) {
611		aprint_error_dev(sc->sc_dv, "can't map common structure\n");
612		goto bail_out;
613	}
614	state++;
615	if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_common_dmamap,
616	    sc->sc_common, sizeof(*sc->sc_common), NULL,
617	    BUS_DMA_NOWAIT)) != 0) {
618		aprint_error_dev(sc->sc_dv, "cannot load common dmamap\n");
619		goto bail_out;
620	}
621	state++;
622
623	memset(sc->sc_common, 0, sizeof(*sc->sc_common));
624
625	TAILQ_INIT(&sc->sc_fibmap_tqh);
626	sc->sc_ccbs = malloc(sizeof(struct aac_ccb) * sc->sc_max_fibs, M_AACBUF,
627	    M_WAITOK | M_ZERO);
628	state++;
629	while (sc->sc_total_fibs < AAC_PREALLOCATE_FIBS(sc)) {
630		if (aac_alloc_commands(sc) != 0)
631			break;
632	}
633	if (sc->sc_total_fibs == 0)
634		goto bail_out;
635
636	/*
637	 * Fill in the init structure.  This tells the adapter about the
638	 * physical location of various important shared data structures.
639	 */
640	ip = &sc->sc_common->ac_init;
641	ip->InitStructRevision = htole32(AAC_INIT_STRUCT_REVISION);
642	if (sc->sc_quirks & AAC_QUIRK_RAW_IO)
643		ip->InitStructRevision = htole32(AAC_INIT_STRUCT_REVISION_4);
644	ip->MiniPortRevision = htole32(AAC_INIT_STRUCT_MINIPORT_REVISION);
645
646	ip->AdapterFibsPhysicalAddress = htole32(sc->sc_common_seg.ds_addr +
647	    offsetof(struct aac_common, ac_fibs));
648	ip->AdapterFibsVirtualAddress = 0;
649	ip->AdapterFibsSize =
650	    htole32(AAC_ADAPTER_FIBS * sizeof(struct aac_fib));
651	ip->AdapterFibAlign = htole32(sizeof(struct aac_fib));
652
653	ip->PrintfBufferAddress = htole32(sc->sc_common_seg.ds_addr +
654	    offsetof(struct aac_common, ac_printf));
655	ip->PrintfBufferSize = htole32(AAC_PRINTF_BUFSIZE);
656
657	/*
658	 * The adapter assumes that pages are 4K in size, except on some
659	 * broken firmware versions that do the page->byte conversion twice,
660	 * therefore 'assuming' that this value is in 16MB units (2^24).
661	 * Round up since the granularity is so high.
662	 */
663	ip->HostPhysMemPages = ctob(physmem) / AAC_PAGE_SIZE;
664	if (sc->sc_quirks & AAC_QUIRK_BROKEN_MMAP) {
665		ip->HostPhysMemPages =
666		    (ip->HostPhysMemPages + AAC_PAGE_SIZE) / AAC_PAGE_SIZE;
667	}
668	ip->HostElapsedSeconds = 0;	/* reset later if invalid */
669
670	ip->InitFlags = 0;
671	if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) {
672		ip->InitFlags = htole32(AAC_INITFLAGS_NEW_COMM_SUPPORTED);
673		aprint_normal_dev(sc->sc_dv, "New comm. interface enabled\n");
674	}
675
676	ip->MaxIoCommands = htole32(sc->sc_max_fibs);
677	ip->MaxIoSize = htole32(sc->sc_max_sectors << 9);
678	ip->MaxFibSize = htole32(sc->sc_max_fib_size);
679
680	/*
681	 * Initialise FIB queues.  Note that it appears that the layout of
682	 * the indexes and the segmentation of the entries is mandated by
683	 * the adapter, which is only told about the base of the queue index
684	 * fields.
685	 *
686	 * The initial values of the indices are assumed to inform the
687	 * adapter of the sizes of the respective queues.
688	 *
689	 * The Linux driver uses a much more complex scheme whereby several
690	 * header records are kept for each queue.  We use a couple of
691	 * generic list manipulation functions which 'know' the size of each
692	 * list by virtue of a table.
693	 */
694	qoff = offsetof(struct aac_common, ac_qbuf) + AAC_QUEUE_ALIGN;
695	qoff &= ~(AAC_QUEUE_ALIGN - 1);
696	sc->sc_queues = (struct aac_queue_table *)((uintptr_t)sc->sc_common + qoff);
697	ip->CommHeaderAddress = htole32(sc->sc_common_seg.ds_addr +
698	    ((char *)sc->sc_queues - (char *)sc->sc_common));
699	memset(sc->sc_queues, 0, sizeof(struct aac_queue_table));
700
701	norm = htole32(AAC_HOST_NORM_CMD_ENTRIES);
702	high = htole32(AAC_HOST_HIGH_CMD_ENTRIES);
703
704	sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
705	    norm;
706	sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
707	    norm;
708	sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
709	    high;
710	sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
711	    high;
712
713	norm = htole32(AAC_ADAP_NORM_CMD_ENTRIES);
714	high = htole32(AAC_ADAP_HIGH_CMD_ENTRIES);
715
716	sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
717	    norm;
718	sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
719	    norm;
720	sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
721	    high;
722	sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
723	    high;
724
725	norm = htole32(AAC_HOST_NORM_RESP_ENTRIES);
726	high = htole32(AAC_HOST_HIGH_RESP_ENTRIES);
727
728	sc->sc_queues->
729	    qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm;
730	sc->sc_queues->
731	    qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm;
732	sc->sc_queues->
733	    qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high;
734	sc->sc_queues->
735	    qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high;
736
737	norm = htole32(AAC_ADAP_NORM_RESP_ENTRIES);
738	high = htole32(AAC_ADAP_HIGH_RESP_ENTRIES);
739
740	sc->sc_queues->
741	    qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm;
742	sc->sc_queues->
743	    qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm;
744	sc->sc_queues->
745	    qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high;
746	sc->sc_queues->
747	    qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high;
748
749	sc->sc_qentries[AAC_HOST_NORM_CMD_QUEUE] =
750	    &sc->sc_queues->qt_HostNormCmdQueue[0];
751	sc->sc_qentries[AAC_HOST_HIGH_CMD_QUEUE] =
752	    &sc->sc_queues->qt_HostHighCmdQueue[0];
753	sc->sc_qentries[AAC_ADAP_NORM_CMD_QUEUE] =
754	    &sc->sc_queues->qt_AdapNormCmdQueue[0];
755	sc->sc_qentries[AAC_ADAP_HIGH_CMD_QUEUE] =
756	    &sc->sc_queues->qt_AdapHighCmdQueue[0];
757	sc->sc_qentries[AAC_HOST_NORM_RESP_QUEUE] =
758	    &sc->sc_queues->qt_HostNormRespQueue[0];
759	sc->sc_qentries[AAC_HOST_HIGH_RESP_QUEUE] =
760	    &sc->sc_queues->qt_HostHighRespQueue[0];
761	sc->sc_qentries[AAC_ADAP_NORM_RESP_QUEUE] =
762	    &sc->sc_queues->qt_AdapNormRespQueue[0];
763	sc->sc_qentries[AAC_ADAP_HIGH_RESP_QUEUE] =
764	    &sc->sc_queues->qt_AdapHighRespQueue[0];
765
766	/*
767	 * Do controller-type-specific initialisation
768	 */
769	switch (sc->sc_hwif) {
770	case AAC_HWIF_I960RX:
771		AAC_SETREG4(sc, AAC_RX_ODBR, ~0);
772		break;
773	}
774
775	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 0,
776	    sizeof(*sc->sc_common),
777	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
778
779	/*
780	 * Give the init structure to the controller.
781	 */
782	if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT,
783	    sc->sc_common_seg.ds_addr + offsetof(struct aac_common, ac_init),
784	    0, 0, 0, NULL)) {
785		aprint_error_dev(sc->sc_dv, "error establishing init structure\n");
786		rv = EIO;
787		goto bail_out;
788	}
789
790	return (0);
791
792 bail_out:
793 	if (state > 4)
794 		free(sc->sc_ccbs, M_AACBUF);
795 	if (state > 3)
796 		bus_dmamap_unload(sc->sc_dmat, sc->sc_common_dmamap);
797	if (state > 2)
798		bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_common,
799		    sizeof(*sc->sc_common));
800	if (state > 1)
801		bus_dmamem_free(sc->sc_dmat, &sc->sc_common_seg, 1);
802	if (state > 0)
803		bus_dmamap_destroy(sc->sc_dmat, sc->sc_common_dmamap);
804
805	free(sc->sc_aif_fib, M_AACBUF);
806
807	return (rv);
808}
809
810/*
811 * Probe for containers, create disks.
812 */
813static void
814aac_startup(struct aac_softc *sc)
815{
816	struct aac_mntinfo mi;
817	struct aac_mntinforesponse mir;
818	struct aac_drive *hd;
819	u_int16_t rsize;
820	size_t ersize;
821	int i;
822
823	/*
824	 * Loop over possible containers.
825	 */
826	hd = sc->sc_hdr;
827
828	for (i = 0; i < AAC_MAX_CONTAINERS; i++, hd++) {
829		/*
830		 * Request information on this container.
831		 */
832		memset(&mi, 0, sizeof(mi));
833		/* use 64-bit LBA if enabled */
834		if (sc->sc_quirks & AAC_QUIRK_LBA_64BIT) {
835			mi.Command = htole32(VM_NameServe64);
836			ersize = sizeof(mir);
837		} else {
838			mi.Command = htole32(VM_NameServe);
839			ersize = sizeof(mir) - sizeof(mir.MntTable[0].CapacityHigh);
840		}
841		mi.MntType = htole32(FT_FILESYS);
842		mi.MntCount = htole32(i);
843		if (aac_sync_fib(sc, ContainerCommand, 0, &mi, sizeof(mi), &mir,
844		    &rsize)) {
845			aprint_error_dev(sc->sc_dv, "error probing container %d\n", i);
846			continue;
847		}
848		if (rsize != ersize) {
849			aprint_error_dev(sc->sc_dv, "container info response wrong size "
850			    "(%d should be %zu)\n", rsize, ersize);
851			continue;
852		}
853
854		/*
855		 * Check container volume type for validity.  Note that many
856		 * of the possible types may never show up.
857		 */
858		if (le32toh(mir.Status) != ST_OK ||
859		    le32toh(mir.MntTable[0].VolType) == CT_NONE)
860			continue;
861
862		hd->hd_present = 1;
863		hd->hd_size = le32toh(mir.MntTable[0].Capacity);
864		if (sc->sc_quirks & AAC_QUIRK_LBA_64BIT)
865			hd->hd_size += (u_int64_t)
866			    le32toh(mir.MntTable[0].CapacityHigh) << 32;
867		hd->hd_devtype = le32toh(mir.MntTable[0].VolType);
868		hd->hd_size &= ~0x1f;
869		sc->sc_nunits++;
870	}
871}
872
873static void
874aac_shutdown(void *cookie)
875{
876	struct aac_softc *sc;
877	struct aac_close_command cc;
878	u_int32_t i;
879
880	for (i = 0; i < aac_cd.cd_ndevs; i++) {
881		if ((sc = device_lookup_private(&aac_cd, i)) == NULL)
882			continue;
883		if ((sc->sc_flags & AAC_ONLINE) == 0)
884			continue;
885
886		AAC_MASK_INTERRUPTS(sc);
887
888		/*
889		 * Send a Container shutdown followed by a HostShutdown FIB
890		 * to the controller to convince it that we don't want to
891		 * talk to it anymore.  We've been closed and all I/O
892		 * completed already
893		 */
894		memset(&cc, 0, sizeof(cc));
895		cc.Command = htole32(VM_CloseAll);
896		cc.ContainerId = 0xffffffff;
897		if (aac_sync_fib(sc, ContainerCommand, 0, &cc, sizeof(cc),
898		    NULL, NULL)) {
899			aprint_error_dev(sc->sc_dv, "unable to halt controller\n");
900			continue;
901		}
902
903		/*
904		 * Note that issuing this command to the controller makes it
905		 * shut down but also keeps it from coming back up without a
906		 * reset of the PCI bus.
907		 */
908		if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN,
909		    &i, sizeof(i), NULL, NULL))
910			aprint_error_dev(sc->sc_dv, "unable to halt controller\n");
911
912		sc->sc_flags &= ~AAC_ONLINE;
913	}
914}
915
916static int
917aac_new_intr(void *cookie)
918{
919	struct aac_softc *sc;
920	u_int32_t index, fast;
921	struct aac_ccb *ac;
922	struct aac_fib *fib;
923	struct aac_fibmap *fm;
924	int i;
925
926	sc = (struct aac_softc *) cookie;
927
928	for (;;) {
929		index = AAC_GET_OUTB_QUEUE(sc);
930		if (index == 0xffffffff)
931			index = AAC_GET_OUTB_QUEUE(sc);
932		if (index == 0xffffffff)
933			break;
934		if (index & 2) {
935			if (index == 0xfffffffe) {
936				/* XXX This means that the controller wants
937				 * more work.  Ignore it for now.
938				 */
939				continue;
940			}
941			/* AIF */
942			index &= ~2;
943			fib = sc->sc_aif_fib;
944			for (i = 0; i < sizeof(struct aac_fib)/4; i++) {
945				((u_int32_t*)fib)[i] =
946				    AAC_GETREG4(sc, index + i*4);
947			}
948#ifdef notyet
949			aac_handle_aif(sc, &fib);
950#endif
951
952			AAC_SET_OUTB_QUEUE(sc, index);
953			AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
954		} else {
955			fast = index & 1;
956			ac = sc->sc_ccbs + (index >> 2);
957			fib = ac->ac_fib;
958			fm = ac->ac_fibmap;
959			if (fast) {
960				bus_dmamap_sync(sc->sc_dmat, fm->fm_fibmap,
961				    (char *)fib - (char *)fm->fm_fibs,
962				    sc->sc_max_fib_size,
963				    BUS_DMASYNC_POSTWRITE |
964				    BUS_DMASYNC_POSTREAD);
965				fib->Header.XferState |=
966				    htole32(AAC_FIBSTATE_DONEADAP);
967				*((u_int32_t *)(fib->data)) =
968				    htole32(AAC_ERROR_NORMAL);
969			}
970			ac->ac_flags |= AAC_CCB_COMPLETED;
971
972			if (ac->ac_intr != NULL)
973				(*ac->ac_intr)(ac);
974			else
975				wakeup(ac);
976		}
977	}
978
979	/*
980	 * Try to submit more commands.
981	 */
982	if (! SIMPLEQ_EMPTY(&sc->sc_ccb_queue))
983		aac_ccb_enqueue(sc, NULL);
984
985	return 1;
986}
987
988/*
989 * Take an interrupt.
990 */
991int
992aac_intr(void *cookie)
993{
994	struct aac_softc *sc;
995	u_int16_t reason;
996	int claimed;
997
998	sc = cookie;
999	claimed = 0;
1000
1001	AAC_DPRINTF(AAC_D_INTR, ("aac_intr(%p) ", sc));
1002
1003	reason = AAC_GET_ISTATUS(sc);
1004	AAC_CLEAR_ISTATUS(sc, reason);
1005
1006	AAC_DPRINTF(AAC_D_INTR, ("istatus 0x%04x ", reason));
1007
1008	/*
1009	 * Controller wants to talk to the log.  XXX Should we defer this?
1010	 */
1011	if ((reason & AAC_DB_PRINTF) != 0) {
1012		if (sc->sc_common->ac_printf[0] == '\0')
1013			sc->sc_common->ac_printf[0] = ' ';
1014		printf("%s: WARNING: adapter logged message:\n",
1015			device_xname(sc->sc_dv));
1016		printf("%s:     %.*s", device_xname(sc->sc_dv),
1017			AAC_PRINTF_BUFSIZE, sc->sc_common->ac_printf);
1018		sc->sc_common->ac_printf[0] = '\0';
1019		AAC_QNOTIFY(sc, AAC_DB_PRINTF);
1020		claimed = 1;
1021	}
1022
1023	/*
1024	 * Controller has a message for us?
1025	 */
1026	if ((reason & AAC_DB_COMMAND_READY) != 0) {
1027		aac_host_command(sc);
1028		claimed = 1;
1029	}
1030
1031	/*
1032	 * Controller has a response for us?
1033	 */
1034	if ((reason & AAC_DB_RESPONSE_READY) != 0) {
1035		aac_host_response(sc);
1036		claimed = 1;
1037	}
1038
1039	/*
1040	 * Spurious interrupts that we don't use - reset the mask and clear
1041	 * the interrupts.
1042	 */
1043	if ((reason & (AAC_DB_SYNC_COMMAND | AAC_DB_COMMAND_NOT_FULL |
1044            AAC_DB_RESPONSE_NOT_FULL)) != 0) {
1045		AAC_UNMASK_INTERRUPTS(sc);
1046		AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND |
1047		    AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL);
1048		claimed = 1;
1049	}
1050
1051	return (claimed);
1052}
1053
1054/*
1055 * Handle notification of one or more FIBs coming from the controller.
1056 */
1057static void
1058aac_host_command(struct aac_softc *sc)
1059{
1060	struct aac_fib *fib;
1061	u_int32_t fib_size;
1062
1063	for (;;) {
1064		if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size,
1065		    &fib))
1066			break;	/* nothing to do */
1067
1068		bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1069		    (char *)fib - (char *)sc->sc_common, sizeof(*fib),
1070		    BUS_DMASYNC_POSTREAD);
1071
1072		switch (le16toh(fib->Header.Command)) {
1073		case AifRequest:
1074#ifdef notyet
1075			aac_handle_aif(sc,
1076			    (struct aac_aif_command *)&fib->data[0]);
1077#endif
1078			AAC_PRINT_FIB(sc, fib);
1079			break;
1080		default:
1081			aprint_error_dev(sc->sc_dv, "unknown command from controller\n");
1082			AAC_PRINT_FIB(sc, fib);
1083			break;
1084		}
1085
1086		bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1087		    (char *)fib - (char *)sc->sc_common, sizeof(*fib),
1088		    BUS_DMASYNC_PREREAD);
1089
1090		if ((fib->Header.XferState == 0) ||
1091		    (fib->Header.StructType != AAC_FIBTYPE_TFIB)) {
1092			break; // continue; ???
1093		}
1094
1095		/* XXX reply to FIBs requesting responses ?? */
1096
1097		/* Return the AIF/FIB to the controller */
1098		if (le32toh(fib->Header.XferState) & AAC_FIBSTATE_FROMADAP) {
1099			u_int16_t	size;
1100
1101			fib->Header.XferState |=
1102				htole32(AAC_FIBSTATE_DONEHOST);
1103			*(u_int32_t*)fib->data = htole32(ST_OK);
1104
1105			/* XXX Compute the Size field? */
1106			size = le16toh(fib->Header.Size);
1107			if (size > sizeof(struct aac_fib)) {
1108				size = sizeof(struct aac_fib);
1109				fib->Header.Size = htole16(size);
1110			}
1111
1112			/*
1113			 * Since we didn't generate this command, it can't
1114			 * go through the normal process.
1115			 */
1116			aac_enqueue_response(sc,
1117					AAC_ADAP_NORM_RESP_QUEUE, fib);
1118		}
1119	}
1120}
1121
1122/*
1123 * Handle notification of one or more FIBs completed by the controller
1124 */
1125static void
1126aac_host_response(struct aac_softc *sc)
1127{
1128	struct aac_ccb *ac;
1129	struct aac_fib *fib;
1130	u_int32_t fib_size;
1131
1132	/*
1133	 * Look for completed FIBs on our queue.
1134	 */
1135	for (;;) {
1136		if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size,
1137		    &fib))
1138			break;	/* nothing to do */
1139
1140		if ((fib->Header.SenderData & 0x80000000) == 0) {
1141			/* Not valid; not sent by us. */
1142			AAC_PRINT_FIB(sc, fib);
1143		} else {
1144			ac = (struct aac_ccb *)(sc->sc_ccbs +
1145			    (fib->Header.SenderData & 0x7fffffff));
1146			fib->Header.SenderData = 0;
1147			SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_complete, ac, ac_chain);
1148		}
1149	}
1150
1151	/*
1152	 * Deal with any completed commands.
1153	 */
1154	while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_complete)) != NULL) {
1155		SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_complete, ac_chain);
1156		ac->ac_flags |= AAC_CCB_COMPLETED;
1157
1158		if (ac->ac_intr != NULL)
1159			(*ac->ac_intr)(ac);
1160		else
1161			wakeup(ac);
1162	}
1163
1164	/*
1165	 * Try to submit more commands.
1166	 */
1167	if (! SIMPLEQ_EMPTY(&sc->sc_ccb_queue))
1168		aac_ccb_enqueue(sc, NULL);
1169}
1170
1171/*
1172 * Send a synchronous command to the controller and wait for a result.
1173 */
1174static int
1175aac_sync_command(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
1176		 u_int32_t arg1, u_int32_t arg2, u_int32_t arg3, u_int32_t *sp)
1177{
1178	int i;
1179	u_int32_t status;
1180	int s;
1181
1182	s = splbio();
1183
1184	/* Populate the mailbox. */
1185	AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3);
1186
1187	/* Ensure the sync command doorbell flag is cleared. */
1188	AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
1189
1190	/* ... then set it to signal the adapter. */
1191	AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND);
1192	DELAY(AAC_SYNC_DELAY);
1193
1194	/* Spin waiting for the command to complete. */
1195	for (i = 0; i < AAC_IMMEDIATE_TIMEOUT * 1000; i++) {
1196		if (AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND)
1197			break;
1198		DELAY(1000);
1199	}
1200	if (i == AAC_IMMEDIATE_TIMEOUT * 1000) {
1201		splx(s);
1202		return (EIO);
1203	}
1204
1205	/* Clear the completion flag. */
1206	AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
1207
1208	/* Get the command status. */
1209	status = AAC_GET_MAILBOXSTATUS(sc);
1210	splx(s);
1211	if (sp != NULL)
1212		*sp = status;
1213
1214	return (0);	/* XXX Check command return status? */
1215}
1216
1217/*
1218 * Send a synchronous FIB to the controller and wait for a result.
1219 */
1220static int
1221aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
1222	     void *data, u_int16_t datasize, void *result,
1223	     u_int16_t *resultsize)
1224{
1225	struct aac_fib *fib;
1226	u_int32_t fibpa, status;
1227
1228	fib = &sc->sc_common->ac_sync_fib;
1229	fibpa = sc->sc_common_seg.ds_addr +
1230	    offsetof(struct aac_common, ac_sync_fib);
1231
1232	if (datasize > AAC_FIB_DATASIZE)
1233		return (EINVAL);
1234
1235	/*
1236	 * Set up the sync FIB.
1237	 */
1238	fib->Header.XferState = htole32(AAC_FIBSTATE_HOSTOWNED |
1239	    AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_EMPTY | xferstate);
1240	fib->Header.Command = htole16(command);
1241	fib->Header.StructType = AAC_FIBTYPE_TFIB;
1242	fib->Header.Size = htole16(sizeof(*fib) + datasize);
1243	fib->Header.SenderSize = htole16(sizeof(*fib));
1244	fib->Header.SenderFibAddress = 0; /* not needed */
1245	fib->Header.ReceiverFibAddress = htole32(fibpa);
1246
1247	/*
1248	 * Copy in data.
1249	 */
1250	if (data != NULL) {
1251		memcpy(fib->data, data, datasize);
1252		fib->Header.XferState |=
1253		    htole32(AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_NORM);
1254	}
1255
1256	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1257	    (char *)fib - (char *)sc->sc_common, sizeof(*fib),
1258	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1259
1260	/*
1261	 * Give the FIB to the controller, wait for a response.
1262	 */
1263	if (aac_sync_command(sc, AAC_MONKER_SYNCFIB, fibpa, 0, 0, 0, &status))
1264		return (EIO);
1265	if (status != 1) {
1266		printf("%s: syncfib command %04x status %08x\n",
1267			device_xname(sc->sc_dv), command, status);
1268	}
1269
1270	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1271	    (char *)fib - (char *)sc->sc_common, sizeof(*fib),
1272	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
1273
1274	/*
1275	 * Copy out the result
1276	 */
1277	if (result != NULL) {
1278		*resultsize = le16toh(fib->Header.Size) - sizeof(fib->Header);
1279		memcpy(result, fib->data, *resultsize);
1280	}
1281
1282	return (0);
1283}
1284
1285struct aac_ccb *
1286aac_ccb_alloc(struct aac_softc *sc, int flags)
1287{
1288	struct aac_ccb *ac;
1289	int s;
1290
1291	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_alloc(%p, 0x%x) ", sc, flags));
1292
1293	s = splbio();
1294	ac = SIMPLEQ_FIRST(&sc->sc_ccb_free);
1295	if (ac == NULL) {
1296		if (aac_alloc_commands(sc)) {
1297			splx(s);
1298			return NULL;
1299		}
1300		ac = SIMPLEQ_FIRST(&sc->sc_ccb_free);
1301	}
1302#ifdef DIAGNOSTIC
1303	if (ac == NULL)
1304		panic("aac_ccb_get: no free CCBS");
1305#endif
1306	SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ac_chain);
1307	splx(s);
1308
1309	ac->ac_flags = flags;
1310	return (ac);
1311}
1312
1313void
1314aac_ccb_free(struct aac_softc *sc, struct aac_ccb *ac)
1315{
1316	int s;
1317
1318	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_free(%p, %p) ", sc, ac));
1319
1320	ac->ac_flags = 0;
1321	ac->ac_intr = NULL;
1322	ac->ac_fib->Header.XferState = htole32(AAC_FIBSTATE_EMPTY);
1323	ac->ac_fib->Header.StructType = AAC_FIBTYPE_TFIB;
1324	ac->ac_fib->Header.Flags = 0;
1325	ac->ac_fib->Header.SenderSize = htole16(sc->sc_max_fib_size);
1326
1327#ifdef AAC_DEBUG
1328	/*
1329	 * These are duplicated in aac_ccb_submit() to cover the case where
1330	 * an intermediate stage may have destroyed them.  They're left
1331	 * initialised here for debugging purposes only.
1332	 */
1333	ac->ac_fib->Header.SenderFibAddress =
1334	    htole32(((u_int32_t) (ac - sc->sc_ccbs)) << 2);
1335	ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys);
1336#endif
1337
1338	s = splbio();
1339	SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ac, ac_chain);
1340	splx(s);
1341}
1342
1343int
1344aac_ccb_map(struct aac_softc *sc, struct aac_ccb *ac)
1345{
1346	int error;
1347
1348	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_map(%p, %p) ", sc, ac));
1349
1350#ifdef DIAGNOSTIC
1351	if ((ac->ac_flags & AAC_CCB_MAPPED) != 0)
1352		panic("aac_ccb_map: already mapped");
1353#endif
1354
1355	error = bus_dmamap_load(sc->sc_dmat, ac->ac_dmamap_xfer, ac->ac_data,
1356	    ac->ac_datalen, NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
1357	    ((ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMA_READ : BUS_DMA_WRITE));
1358	if (error) {
1359		printf("%s: aac_ccb_map: ", device_xname(sc->sc_dv));
1360		if (error == EFBIG)
1361			printf("more than %d DMA segs\n", sc->sc_max_sgs);
1362		else
1363			printf("error %d loading DMA map\n", error);
1364		return (error);
1365	}
1366
1367	bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen,
1368	    (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_PREREAD :
1369	    BUS_DMASYNC_PREWRITE);
1370
1371#ifdef DIAGNOSTIC
1372	ac->ac_flags |= AAC_CCB_MAPPED;
1373#endif
1374	return (0);
1375}
1376
1377void
1378aac_ccb_unmap(struct aac_softc *sc, struct aac_ccb *ac)
1379{
1380
1381	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_unmap(%p, %p) ", sc, ac));
1382
1383#ifdef DIAGNOSTIC
1384	if ((ac->ac_flags & AAC_CCB_MAPPED) == 0)
1385		panic("aac_ccb_unmap: not mapped");
1386#endif
1387
1388	bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen,
1389	    (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_POSTREAD :
1390	    BUS_DMASYNC_POSTWRITE);
1391	bus_dmamap_unload(sc->sc_dmat, ac->ac_dmamap_xfer);
1392
1393#ifdef DIAGNOSTIC
1394	ac->ac_flags &= ~AAC_CCB_MAPPED;
1395#endif
1396}
1397
1398void
1399aac_ccb_enqueue(struct aac_softc *sc, struct aac_ccb *ac)
1400{
1401	int s;
1402
1403	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_enqueue(%p, %p) ", sc, ac));
1404
1405	s = splbio();
1406
1407	if (ac != NULL)
1408		SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_queue, ac, ac_chain);
1409
1410	while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_queue)) != NULL) {
1411		if (aac_ccb_submit(sc, ac))
1412			break;
1413		SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_queue, ac_chain);
1414	}
1415
1416	splx(s);
1417}
1418
1419int
1420aac_ccb_submit(struct aac_softc *sc, struct aac_ccb *ac)
1421{
1422	struct aac_fibmap *fm;
1423	u_int32_t acidx;
1424
1425	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_submit(%p, %p) ", sc, ac));
1426
1427	acidx = (u_int32_t) (ac - sc->sc_ccbs);
1428	/* Fix up the address values. */
1429	ac->ac_fib->Header.SenderFibAddress = htole32(acidx << 2);
1430	ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys);
1431
1432	/* Save a pointer to the command for speedy reverse-lookup. */
1433	ac->ac_fib->Header.SenderData = acidx | 0x80000000;
1434
1435	fm = ac->ac_fibmap;
1436	bus_dmamap_sync(sc->sc_dmat, fm->fm_fibmap,
1437	    (char *)ac->ac_fib - (char *)fm->fm_fibs, sc->sc_max_fib_size,
1438	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1439
1440	/* Put the FIB on the outbound queue. */
1441	if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) {
1442		int count = 10000000L;
1443		while (AAC_SEND_COMMAND(sc, ac) != 0) {
1444			if (--count == 0) {
1445				panic("aac: fixme!");
1446				return EAGAIN;
1447			}
1448			DELAY(5);
1449		}
1450		return 0;
1451	} else {
1452		return (aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE, ac));
1453	}
1454}
1455
1456int
1457aac_ccb_poll(struct aac_softc *sc, struct aac_ccb *ac, int timo)
1458{
1459	int rv, s;
1460
1461	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_poll(%p, %p, %d) ", sc, ac, timo));
1462
1463	s = splbio();
1464
1465	if ((rv = aac_ccb_submit(sc, ac)) != 0) {
1466		splx(s);
1467		return (rv);
1468	}
1469
1470	for (timo *= 1000; timo != 0; timo--) {
1471		if (sc->sc_quirks & AAC_QUIRK_NEW_COMM)
1472			aac_new_intr(sc);
1473		else
1474			aac_intr(sc);
1475		if ((ac->ac_flags & AAC_CCB_COMPLETED) != 0)
1476			break;
1477		DELAY(100);
1478	}
1479
1480	splx(s);
1481	return (timo == 0);
1482}
1483
1484/*
1485 * Atomically insert an entry into the nominated queue, returns 0 on success
1486 * or EBUSY if the queue is full.
1487 *
1488 * XXX Note that it would be more efficient to defer notifying the
1489 * controller in the case where we may be inserting several entries in rapid
1490 * succession, but implementing this usefully is difficult.
1491 */
1492static int
1493aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_ccb *ac)
1494{
1495	u_int32_t fib_size, fib_addr, pi, ci;
1496
1497	fib_size = le16toh(ac->ac_fib->Header.Size);
1498	fib_addr = le32toh(ac->ac_fib->Header.ReceiverFibAddress);
1499
1500	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1501	    (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
1502	    sizeof(sc->sc_common->ac_qbuf),
1503	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
1504
1505	/* Get the producer/consumer indices.  */
1506	pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
1507	ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
1508
1509	/* Wrap the queue? */
1510	if (pi >= aac_qinfo[queue].size)
1511		pi = 0;
1512
1513	/* Check for queue full. */
1514	if ((pi + 1) == ci)
1515		return (EAGAIN);
1516
1517	/* Populate queue entry. */
1518	(sc->sc_qentries[queue] + pi)->aq_fib_size = htole32(fib_size);
1519	(sc->sc_qentries[queue] + pi)->aq_fib_addr = htole32(fib_addr);
1520
1521	/* Update producer index. */
1522	sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = htole32(pi + 1);
1523
1524	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1525	    (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
1526	    sizeof(sc->sc_common->ac_qbuf),
1527	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1528
1529	/* Notify the adapter if we know how. */
1530	if (aac_qinfo[queue].notify != 0)
1531		AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1532
1533	return (0);
1534}
1535
1536/*
1537 * Atomically remove one entry from the nominated queue, returns 0 on success
1538 * or ENOENT if the queue is empty.
1539 */
1540static int
1541aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
1542		struct aac_fib **fib_addr)
1543{
1544	struct aac_fibmap *fm;
1545	struct aac_ccb *ac;
1546	u_int32_t pi, ci, idx;
1547	int notify;
1548
1549	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1550	    (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
1551	    sizeof(sc->sc_common->ac_qbuf),
1552	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
1553
1554	/* Get the producer/consumer indices. */
1555	pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
1556	ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
1557
1558	/* Check for queue empty. */
1559	if (ci == pi)
1560		return (ENOENT);
1561
1562	notify = 0;
1563	if (ci == pi + 1)
1564		notify = 1;
1565
1566	/* Wrap the queue? */
1567	if (ci >= aac_qinfo[queue].size)
1568		ci = 0;
1569
1570	/* Fetch the entry. */
1571	*fib_size = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_size);
1572
1573	switch (queue) {
1574	case AAC_HOST_NORM_CMD_QUEUE:
1575	case AAC_HOST_HIGH_CMD_QUEUE:
1576		idx = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_addr);
1577		idx /= sizeof(struct aac_fib);
1578		*fib_addr = &sc->sc_common->ac_fibs[idx];
1579		break;
1580	case AAC_HOST_NORM_RESP_QUEUE:
1581	case AAC_HOST_HIGH_RESP_QUEUE:
1582		idx = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_addr);
1583		ac = sc->sc_ccbs + (idx >> 2);
1584		*fib_addr = ac->ac_fib;
1585		if (idx & 0x01) {
1586			fm = ac->ac_fibmap;
1587			bus_dmamap_sync(sc->sc_dmat, fm->fm_fibmap,
1588			    (char *)ac->ac_fib - (char *)fm->fm_fibs,
1589			    sc->sc_max_fib_size,
1590			    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
1591			ac->ac_fib->Header.XferState |=
1592				htole32(AAC_FIBSTATE_DONEADAP);
1593			*((u_int32_t*)(ac->ac_fib->data)) =
1594				htole32(AAC_ERROR_NORMAL);
1595		}
1596		break;
1597	default:
1598		panic("Invalid queue in aac_dequeue_fib()");
1599		break;
1600	}
1601
1602	/* Update consumer index. */
1603	sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1;
1604
1605	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1606	    (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
1607	    sizeof(sc->sc_common->ac_qbuf),
1608	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1609
1610	/* If we have made the queue un-full, notify the adapter. */
1611	if (notify && (aac_qinfo[queue].notify != 0))
1612		AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1613
1614	return (0);
1615}
1616
1617/*
1618 * Put our response to an adapter-initiated fib (AIF) on the response queue.
1619 */
1620static int
1621aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib)
1622{
1623	u_int32_t fib_size, fib_addr, pi, ci;
1624
1625	fib_size = le16toh(fib->Header.Size);
1626	fib_addr = fib->Header.SenderFibAddress;
1627	fib->Header.ReceiverFibAddress = fib_addr;
1628
1629	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1630	    (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
1631	    sizeof(sc->sc_common->ac_qbuf),
1632	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
1633
1634	/* Get the producer/consumer indices.  */
1635	pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
1636	ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
1637
1638	/* Wrap the queue? */
1639	if (pi >= aac_qinfo[queue].size)
1640		pi = 0;
1641
1642	/* Check for queue full. */
1643	if ((pi + 1) == ci)
1644		return (EAGAIN);
1645
1646	/* Populate queue entry. */
1647	(sc->sc_qentries[queue] + pi)->aq_fib_size = htole32(fib_size);
1648	(sc->sc_qentries[queue] + pi)->aq_fib_addr = htole32(fib_addr);
1649
1650	/* Update producer index. */
1651	sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = htole32(pi + 1);
1652
1653	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1654	    (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
1655	    sizeof(sc->sc_common->ac_qbuf),
1656	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1657
1658	/* Notify the adapter if we know how. */
1659	if (aac_qinfo[queue].notify != 0)
1660		AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1661
1662	return (0);
1663}
1664
1665#ifdef AAC_DEBUG
1666/*
1667 * Print a FIB
1668 */
1669static void
1670aac_print_fib(struct aac_softc *sc, struct aac_fib *fib,
1671    const char *caller)
1672{
1673	struct aac_blockread *br;
1674	struct aac_blockwrite *bw;
1675	struct aac_sg_table *sg;
1676	char tbuf[512];
1677	int i;
1678
1679	printf("%s: FIB @ %p\n", caller, fib);
1680	snprintb(tbuf, sizeof(tbuf),
1681	    "\20"
1682	    "\1HOSTOWNED"
1683	    "\2ADAPTEROWNED"
1684	    "\3INITIALISED"
1685	    "\4EMPTY"
1686	    "\5FROMPOOL"
1687	    "\6FROMHOST"
1688	    "\7FROMADAP"
1689	    "\10REXPECTED"
1690	    "\11RNOTEXPECTED"
1691	    "\12DONEADAP"
1692	    "\13DONEHOST"
1693	    "\14HIGH"
1694	    "\15NORM"
1695	    "\16ASYNC"
1696	    "\17PAGEFILEIO"
1697	    "\20SHUTDOWN"
1698	    "\21LAZYWRITE"
1699	    "\22ADAPMICROFIB"
1700	    "\23BIOSFIB"
1701	    "\24FAST_RESPONSE"
1702	    "\25APIFIB\n", le32toh(fib->Header.XferState));
1703
1704	printf("  XferState       %s\n", tbuf);
1705	printf("  Command         %d\n", le16toh(fib->Header.Command));
1706	printf("  StructType      %d\n", fib->Header.StructType);
1707	printf("  Flags           0x%x\n", fib->Header.Flags);
1708	printf("  Size            %d\n", le16toh(fib->Header.Size));
1709	printf("  SenderSize      %d\n", le16toh(fib->Header.SenderSize));
1710	printf("  SenderAddress   0x%x\n",
1711	    le32toh(fib->Header.SenderFibAddress));
1712	printf("  ReceiverAddress 0x%x\n",
1713	    le32toh(fib->Header.ReceiverFibAddress));
1714	printf("  SenderData      0x%x\n", fib->Header.SenderData);
1715
1716	switch (fib->Header.Command) {
1717	case ContainerCommand: {
1718		br = (struct aac_blockread *)fib->data;
1719		bw = (struct aac_blockwrite *)fib->data;
1720		sg = NULL;
1721
1722		if (le32toh(br->Command) == VM_CtBlockRead) {
1723			printf("  BlockRead: container %d  0x%x/%d\n",
1724			    le32toh(br->ContainerId), le32toh(br->BlockNumber),
1725			    le32toh(br->ByteCount));
1726			sg = &br->SgMap;
1727		}
1728		if (le32toh(bw->Command) == VM_CtBlockWrite) {
1729			printf("  BlockWrite: container %d  0x%x/%d (%s)\n",
1730			    le32toh(bw->ContainerId), le32toh(bw->BlockNumber),
1731			    le32toh(bw->ByteCount),
1732			    le32toh(bw->Stable) == CSTABLE ?
1733			    "stable" : "unstable");
1734			sg = &bw->SgMap;
1735		}
1736		if (sg != NULL) {
1737			printf("  %d s/g entries\n", le32toh(sg->SgCount));
1738			for (i = 0; i < le32toh(sg->SgCount); i++)
1739				printf("  0x%08x/%d\n",
1740				    le32toh(sg->SgEntry[i].SgAddress),
1741				    le32toh(sg->SgEntry[i].SgByteCount));
1742		}
1743		break;
1744	}
1745	default:
1746		// dump first 32 bytes of fib->data
1747		printf("  Raw data:");
1748		for (i = 0; i < 32; i++)
1749			printf(" %02x", fib->data[i]);
1750		printf("\n");
1751		break;
1752	}
1753}
1754#endif /* AAC_DEBUG */
1755
1756MODULE(MODULE_CLASS_DRIVER, aac, "pci");
1757
1758#ifdef _MODULE
1759#include "ioconf.c"
1760#endif
1761
1762static int
1763aac_modcmd(modcmd_t cmd, void *opaque)
1764{
1765	int error = 0;
1766
1767#ifdef _MODULE
1768	switch (cmd) {
1769	case MODULE_CMD_INIT:
1770		error = config_init_component(cfdriver_ioconf_aac,
1771		    cfattach_ioconf_aac, cfdata_ioconf_aac);
1772		break;
1773	case MODULE_CMD_FINI:
1774		error = config_fini_component(cfdriver_ioconf_aac,
1775		    cfattach_ioconf_aac, cfdata_ioconf_aac);
1776		break;
1777	default:
1778		error = ENOTTY;
1779		break;
1780	}
1781#endif
1782
1783	return error;
1784}
1785