xref: /netbsd-src/sys/dev/ic/aac.c (revision e5548b402ae4c44fb816de42c7bba9581ce23ef5)
1 /*	$NetBSD: aac.c,v 1.25 2005/11/26 21:33:46 jdolecek Exp $	*/
2 
3 /*-
4  * Copyright (c) 2002 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  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 /*-
40  * Copyright (c) 2001 Scott Long
41  * Copyright (c) 2001 Adaptec, Inc.
42  * Copyright (c) 2000 Michael Smith
43  * Copyright (c) 2000 BSDi
44  * Copyright (c) 2000 Niklas Hallqvist
45  * All rights reserved.
46  *
47  * Redistribution and use in source and binary forms, with or without
48  * modification, are permitted provided that the following conditions
49  * are met:
50  * 1. Redistributions of source code must retain the above copyright
51  *    notice, this list of conditions and the following disclaimer.
52  * 2. Redistributions in binary form must reproduce the above copyright
53  *    notice, this list of conditions and the following disclaimer in the
54  *    documentation and/or other materials provided with the distribution.
55  *
56  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
57  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
60  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66  * SUCH DAMAGE.
67  */
68 
69 /*
70  * Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters.
71  *
72  * TODO:
73  *
74  * o Management interface.
75  * o Look again at some of the portability issues.
76  * o Handle various AIFs (e.g., notification that a container is going away).
77  */
78 
79 #include <sys/cdefs.h>
80 __KERNEL_RCSID(0, "$NetBSD: aac.c,v 1.25 2005/11/26 21:33:46 jdolecek Exp $");
81 
82 #include <sys/param.h>
83 #include <sys/systm.h>
84 #include <sys/buf.h>
85 #include <sys/device.h>
86 #include <sys/kernel.h>
87 #include <sys/malloc.h>
88 
89 #include <machine/bus.h>
90 
91 #include <uvm/uvm_extern.h>
92 
93 #include <dev/ic/aacreg.h>
94 #include <dev/ic/aacvar.h>
95 #include <dev/ic/aac_tables.h>
96 
97 #include "locators.h"
98 
99 static int	aac_check_firmware(struct aac_softc *);
100 static void	aac_describe_controller(struct aac_softc *);
101 static int	aac_dequeue_fib(struct aac_softc *, int, u_int32_t *,
102 				struct aac_fib **);
103 static int	aac_enqueue_fib(struct aac_softc *, int, struct aac_fib *);
104 static void	aac_host_command(struct aac_softc *);
105 static void	aac_host_response(struct aac_softc *);
106 static int	aac_init(struct aac_softc *);
107 static int	aac_print(void *, const char *);
108 static void	aac_shutdown(void *);
109 static void	aac_startup(struct aac_softc *);
110 static int	aac_sync_command(struct aac_softc *, u_int32_t, u_int32_t,
111 				 u_int32_t, u_int32_t, u_int32_t, u_int32_t *);
112 static int	aac_sync_fib(struct aac_softc *, u_int32_t, u_int32_t, void *,
113 			     u_int16_t, void *, u_int16_t *);
114 
115 #ifdef AAC_DEBUG
116 static void	aac_print_fib(struct aac_softc *, struct aac_fib *, const char *);
117 #endif
118 
119 /*
120  * Adapter-space FIB queue manipulation.
121  *
122  * Note that the queue implementation here is a little funky; neither the PI or
123  * CI will ever be zero.  This behaviour is a controller feature.
124  */
125 static struct {
126 	int	size;
127 	int	notify;
128 } const aac_qinfo[] = {
129 	{ AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL },
130 	{ AAC_HOST_HIGH_CMD_ENTRIES, 0 },
131 	{ AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY },
132 	{ AAC_ADAP_HIGH_CMD_ENTRIES, 0 },
133 	{ AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL },
134 	{ AAC_HOST_HIGH_RESP_ENTRIES, 0 },
135 	{ AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY },
136 	{ AAC_ADAP_HIGH_RESP_ENTRIES, 0 }
137 };
138 
139 #ifdef AAC_DEBUG
140 int	aac_debug = AAC_DEBUG;
141 #endif
142 
143 static void	*aac_sdh;
144 
145 extern struct	cfdriver aac_cd;
146 
147 int
148 aac_attach(struct aac_softc *sc)
149 {
150 	struct aac_attach_args aaca;
151 	int nsegs, i, rv, state, size;
152 	struct aac_ccb *ac;
153 	struct aac_fib *fib;
154 	bus_addr_t fibpa;
155 	int locs[AACCF_NLOCS];
156 
157 	SIMPLEQ_INIT(&sc->sc_ccb_free);
158 	SIMPLEQ_INIT(&sc->sc_ccb_queue);
159 	SIMPLEQ_INIT(&sc->sc_ccb_complete);
160 
161 	/*
162 	 * Disable interrupts before we do anything.
163 	 */
164 	AAC_MASK_INTERRUPTS(sc);
165 
166 	/*
167 	 * Initialise the adapter.
168 	 */
169 	if (aac_check_firmware(sc))
170 		return (EINVAL);
171 
172 	if ((rv = aac_init(sc)) != 0)
173 		return (rv);
174 	aac_startup(sc);
175 
176 	/*
177 	 * Print a little information about the controller.
178 	 */
179 	aac_describe_controller(sc);
180 
181 	/*
182 	 * Initialize the ccbs.
183 	 */
184 	sc->sc_ccbs = malloc(sizeof(*ac) * AAC_NCCBS, M_DEVBUF,
185 	    M_NOWAIT | M_ZERO);
186 	if (sc->sc_ccbs == NULL) {
187 		aprint_error("%s: memory allocation failure\n",
188 		    sc->sc_dv.dv_xname);
189 		return (ENOMEM);
190 	}
191 	state = 0;
192 	size = sizeof(*fib) * AAC_NCCBS;
193 
194 	if ((rv = bus_dmamap_create(sc->sc_dmat, size, 1, size,
195 	    0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_fibs_dmamap)) != 0) {
196 		aprint_error("%s: cannot create fibs dmamap\n",
197 		    sc->sc_dv.dv_xname);
198 		goto bail_out;
199 	}
200 	state++;
201 	if ((rv = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0,
202 	    &sc->sc_fibs_seg, 1, &nsegs, BUS_DMA_NOWAIT)) != 0) {
203 		aprint_error("%s: can't allocate fibs structure\n",
204 		    sc->sc_dv.dv_xname);
205 		goto bail_out;
206 	}
207 	state++;
208 	if ((rv = bus_dmamem_map(sc->sc_dmat, &sc->sc_fibs_seg, nsegs, size,
209 	    (caddr_t *)&sc->sc_fibs, 0)) != 0) {
210 		aprint_error("%s: can't map fibs structure\n",
211 		    sc->sc_dv.dv_xname);
212 		goto bail_out;
213 	}
214 	state++;
215 	if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_fibs_dmamap, sc->sc_fibs,
216 	    size, NULL, BUS_DMA_NOWAIT)) != 0) {
217 		aprint_error("%s: cannot load fibs dmamap\n",
218 		    sc->sc_dv.dv_xname);
219 		goto bail_out;
220 	}
221 	state++;
222 
223 	memset(sc->sc_fibs, 0, size);
224 	fibpa = sc->sc_fibs_seg.ds_addr;
225 	fib = sc->sc_fibs;
226 
227 	for (i = 0, ac = sc->sc_ccbs; i < AAC_NCCBS; i++, ac++) {
228 		rv = bus_dmamap_create(sc->sc_dmat, AAC_MAX_XFER,
229 		    AAC_MAX_SGENTRIES, AAC_MAX_XFER, 0,
230 		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ac->ac_dmamap_xfer);
231 		if (rv) {
232 			while (--ac >= sc->sc_ccbs)
233 				bus_dmamap_destroy(sc->sc_dmat,
234 				    ac->ac_dmamap_xfer);
235 			aprint_error("%s: cannot create ccb dmamap (%d)",
236 			    sc->sc_dv.dv_xname, rv);
237 			goto bail_out;
238 		}
239 
240 		ac->ac_fib = fib++;
241 		ac->ac_fibphys = fibpa;
242 		fibpa += sizeof(*fib);
243 		aac_ccb_free(sc, ac);
244 	}
245 
246 	/*
247 	 * Attach devices.
248 	 */
249 	for (i = 0; i < AAC_MAX_CONTAINERS; i++) {
250 		if (!sc->sc_hdr[i].hd_present)
251 			continue;
252 		aaca.aaca_unit = i;
253 
254 		locs[AACCF_UNIT] = i;
255 
256 		config_found_sm_loc(&sc->sc_dv, "aac", locs, &aaca,
257 				    aac_print, config_stdsubmatch);
258 	}
259 
260 	/*
261 	 * Enable interrupts, and register our shutdown hook.
262 	 */
263 	sc->sc_flags |= AAC_ONLINE;
264 	AAC_UNMASK_INTERRUPTS(sc);
265 	if (aac_sdh != NULL)
266 		shutdownhook_establish(aac_shutdown, NULL);
267 	return (0);
268 
269  bail_out:
270  	bus_dmamap_unload(sc->sc_dmat, sc->sc_common_dmamap);
271 	bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_common,
272 	    sizeof(*sc->sc_common));
273 	bus_dmamem_free(sc->sc_dmat, &sc->sc_common_seg, 1);
274 	bus_dmamap_destroy(sc->sc_dmat, sc->sc_common_dmamap);
275 
276  	if (state > 3)
277  		bus_dmamap_unload(sc->sc_dmat, sc->sc_fibs_dmamap);
278 	if (state > 2)
279 		bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_fibs, size);
280 	if (state > 1)
281 		bus_dmamem_free(sc->sc_dmat, &sc->sc_fibs_seg, 1);
282 	if (state > 0)
283 		bus_dmamap_destroy(sc->sc_dmat, sc->sc_fibs_dmamap);
284 
285 	free(sc->sc_ccbs, M_DEVBUF);
286 	return (rv);
287 }
288 
289 /*
290  * Print autoconfiguration message for a sub-device.
291  */
292 static int
293 aac_print(void *aux, const char *pnp)
294 {
295 	struct aac_attach_args *aaca;
296 
297 	aaca = aux;
298 
299 	if (pnp != NULL)
300 		aprint_normal("block device at %s", pnp);
301 	aprint_normal(" unit %d", aaca->aaca_unit);
302 	return (UNCONF);
303 }
304 
305 /*
306  * Look up a text description of a numeric error code and return a pointer to
307  * same.
308  */
309 const char *
310 aac_describe_code(const struct aac_code_lookup *table, u_int32_t code)
311 {
312 	int i;
313 
314 	for (i = 0; table[i].string != NULL; i++)
315 		if (table[i].code == code)
316 			return (table[i].string);
317 
318 	return (table[i + 1].string);
319 }
320 
321 /*
322  * bitmask_snprintf(9) format string for the adapter options.
323  */
324 static const char *optfmt =
325     "\20\1SNAPSHOT\2CLUSTERS\3WCACHE\4DATA64\5HOSTTIME\6RAID50"
326     "\7WINDOW4GB"
327     "\10SCSIUPGD\11SOFTERR\12NORECOND\13SGMAP64\14ALARM\15NONDASD";
328 
329 static void
330 aac_describe_controller(struct aac_softc *sc)
331 {
332 	u_int8_t fmtbuf[256];
333 	u_int8_t tbuf[AAC_FIB_DATASIZE];
334 	u_int16_t bufsize;
335 	struct aac_adapter_info *info;
336 	u_int8_t arg;
337 
338 	arg = 0;
339 	if (aac_sync_fib(sc, RequestAdapterInfo, 0, &arg, sizeof(arg), &tbuf,
340 	    &bufsize)) {
341 		aprint_error("%s: RequestAdapterInfo failed\n",
342 		    sc->sc_dv.dv_xname);
343 		return;
344 	}
345 	if (bufsize != sizeof(*info)) {
346 		aprint_error("%s: "
347 		    "RequestAdapterInfo returned wrong data size (%d != %lu)\n",
348 		    sc->sc_dv.dv_xname, bufsize, (long unsigned) sizeof(*info));
349 		return;
350 	}
351 	info = (struct aac_adapter_info *)&tbuf[0];
352 
353 	aprint_normal("%s: %s at %dMHz, %dMB mem (%dMB cache), %s\n",
354 	    sc->sc_dv.dv_xname,
355 	    aac_describe_code(aac_cpu_variant, le32toh(info->CpuVariant)),
356 	    le32toh(info->ClockSpeed),
357 	    le32toh(info->TotalMem) / (1024 * 1024),
358 	    le32toh(info->BufferMem) / (1024 * 1024),
359 	    aac_describe_code(aac_battery_platform,
360 			      le32toh(info->batteryPlatform)));
361 
362 	aprint_verbose("%s: Kernel %d.%d-%d [Build %d], ",
363 	    sc->sc_dv.dv_xname,
364 	    info->KernelRevision.external.comp.major,
365 	    info->KernelRevision.external.comp.minor,
366 	    info->KernelRevision.external.comp.dash,
367 	    info->KernelRevision.buildNumber);
368 
369 	aprint_verbose("Monitor %d.%d-%d [Build %d], S/N %6X\n",
370 	    info->MonitorRevision.external.comp.major,
371 	    info->MonitorRevision.external.comp.minor,
372 	    info->MonitorRevision.external.comp.dash,
373 	    info->MonitorRevision.buildNumber,
374 	    ((u_int32_t)info->SerialNumber & 0xffffff));
375 
376 	aprint_verbose("%s: Controller supports: %s\n",
377 	    sc->sc_dv.dv_xname,
378 	    bitmask_snprintf(sc->sc_supported_options, optfmt, fmtbuf,
379 			     sizeof(fmtbuf)));
380 
381 	/* Save the kernel revision structure for later use. */
382 	sc->sc_revision = info->KernelRevision;
383 }
384 
385 /*
386  * Retrieve the firmware version numbers.  Dell PERC2/QC cards with firmware
387  * version 1.x are not compatible with this driver.
388  */
389 static int
390 aac_check_firmware(struct aac_softc *sc)
391 {
392 	u_int32_t major, minor, opts;
393 
394 	if ((sc->sc_quirks & AAC_QUIRK_PERC2QC) != 0) {
395 		if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0,
396 		    NULL)) {
397 			aprint_error("%s: error reading firmware version\n",
398 			    sc->sc_dv.dv_xname);
399 			return (1);
400 		}
401 
402 		/* These numbers are stored as ASCII! */
403 		major = (AAC_GET_MAILBOX(sc, 1) & 0xff) - 0x30;
404 		minor = (AAC_GET_MAILBOX(sc, 2) & 0xff) - 0x30;
405 		if (major == 1) {
406 			aprint_error(
407 			    "%s: firmware version %d.%d not supported.\n",
408 			    sc->sc_dv.dv_xname, major, minor);
409 			return (1);
410 		}
411 	}
412 
413 	if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, NULL)) {
414 		aprint_error("%s: GETINFO failed\n", sc->sc_dv.dv_xname);
415 		return (1);
416 	}
417 	opts = AAC_GET_MAILBOX(sc, 1);
418 	sc->sc_supported_options = opts;
419 
420 	/* XXX -- Enable 64-bit sglists if we can */
421 
422 	return (0);
423 }
424 
425 static int
426 aac_init(struct aac_softc *sc)
427 {
428 	int nsegs, i, rv, state, norm, high;
429 	struct aac_adapter_init	*ip;
430 	u_int32_t code, qoff;
431 
432 	state = 0;
433 
434 	/*
435 	 * First wait for the adapter to come ready.
436 	 */
437 	for (i = 0; i < AAC_BOOT_TIMEOUT * 1000; i++) {
438 		code = AAC_GET_FWSTATUS(sc);
439 		if ((code & AAC_SELF_TEST_FAILED) != 0) {
440 			aprint_error("%s: FATAL: selftest failed\n",
441 			    sc->sc_dv.dv_xname);
442 			return (ENXIO);
443 		}
444 		if ((code & AAC_KERNEL_PANIC) != 0) {
445 			aprint_error("%s: FATAL: controller kernel panic\n",
446 			    sc->sc_dv.dv_xname);
447 			return (ENXIO);
448 		}
449 		if ((code & AAC_UP_AND_RUNNING) != 0)
450 			break;
451 		DELAY(1000);
452 	}
453 	if (i == AAC_BOOT_TIMEOUT * 1000) {
454 		aprint_error(
455 		    "%s: FATAL: controller not coming ready, status %x\n",
456 		    sc->sc_dv.dv_xname, code);
457 		return (ENXIO);
458 	}
459 
460 	if ((rv = bus_dmamap_create(sc->sc_dmat, sizeof(*sc->sc_common), 1,
461 	    sizeof(*sc->sc_common), 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
462 	    &sc->sc_common_dmamap)) != 0) {
463 		aprint_error("%s: cannot create common dmamap\n",
464 		    sc->sc_dv.dv_xname);
465 		return (rv);
466 	}
467 	if ((rv = bus_dmamem_alloc(sc->sc_dmat, sizeof(*sc->sc_common),
468 	    PAGE_SIZE, 0, &sc->sc_common_seg, 1, &nsegs,
469 	    BUS_DMA_NOWAIT)) != 0) {
470 		aprint_error("%s: can't allocate common structure\n",
471 		    sc->sc_dv.dv_xname);
472 		goto bail_out;
473 	}
474 	state++;
475 	if ((rv = bus_dmamem_map(sc->sc_dmat, &sc->sc_common_seg, nsegs,
476 	    sizeof(*sc->sc_common), (caddr_t *)&sc->sc_common, 0)) != 0) {
477 		aprint_error("%s: can't map common structure\n",
478 		    sc->sc_dv.dv_xname);
479 		goto bail_out;
480 	}
481 	state++;
482 	if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_common_dmamap,
483 	    sc->sc_common, sizeof(*sc->sc_common), NULL,
484 	    BUS_DMA_NOWAIT)) != 0) {
485 		aprint_error("%s: cannot load common dmamap\n",
486 		    sc->sc_dv.dv_xname);
487 		goto bail_out;
488 	}
489 	state++;
490 
491 	memset(sc->sc_common, 0, sizeof(*sc->sc_common));
492 
493 	/*
494 	 * Fill in the init structure.  This tells the adapter about the
495 	 * physical location of various important shared data structures.
496 	 */
497 	ip = &sc->sc_common->ac_init;
498 	ip->InitStructRevision = htole32(AAC_INIT_STRUCT_REVISION);
499 
500 	ip->AdapterFibsPhysicalAddress = htole32(sc->sc_common_seg.ds_addr +
501 	    offsetof(struct aac_common, ac_fibs));
502 	ip->AdapterFibsVirtualAddress =
503 	    (void *)(intptr_t) htole32(&sc->sc_common->ac_fibs[0]);
504 	ip->AdapterFibsSize =
505 	    htole32(AAC_ADAPTER_FIBS * sizeof(struct aac_fib));
506 	ip->AdapterFibAlign = htole32(sizeof(struct aac_fib));
507 
508 	ip->PrintfBufferAddress = htole32(sc->sc_common_seg.ds_addr +
509 	    offsetof(struct aac_common, ac_printf));
510 	ip->PrintfBufferSize = htole32(AAC_PRINTF_BUFSIZE);
511 
512 	ip->HostPhysMemPages = 0;	/* not used? */
513 	ip->HostElapsedSeconds = 0;	/* reset later if invalid */
514 
515 	/*
516 	 * Initialise FIB queues.  Note that it appears that the layout of
517 	 * the indexes and the segmentation of the entries is mandated by
518 	 * the adapter, which is only told about the base of the queue index
519 	 * fields.
520 	 *
521 	 * The initial values of the indices are assumed to inform the
522 	 * adapter of the sizes of the respective queues.
523 	 *
524 	 * The Linux driver uses a much more complex scheme whereby several
525 	 * header records are kept for each queue.  We use a couple of
526 	 * generic list manipulation functions which 'know' the size of each
527 	 * list by virtue of a table.
528 	 */
529 	qoff = offsetof(struct aac_common, ac_qbuf) + AAC_QUEUE_ALIGN;
530 	qoff &= ~(AAC_QUEUE_ALIGN - 1);
531 	sc->sc_queues = (struct aac_queue_table *)((uintptr_t)sc->sc_common + qoff);
532 	ip->CommHeaderAddress = htole32(sc->sc_common_seg.ds_addr +
533 	    ((caddr_t)sc->sc_queues - (caddr_t)sc->sc_common));
534 	memset(sc->sc_queues, 0, sizeof(struct aac_queue_table));
535 
536 	norm = htole32(AAC_HOST_NORM_CMD_ENTRIES);
537 	high = htole32(AAC_HOST_HIGH_CMD_ENTRIES);
538 
539 	sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
540 	    norm;
541 	sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
542 	    norm;
543 	sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
544 	    high;
545 	sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
546 	    high;
547 
548 	norm = htole32(AAC_ADAP_NORM_CMD_ENTRIES);
549 	high = htole32(AAC_ADAP_HIGH_CMD_ENTRIES);
550 
551 	sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
552 	    norm;
553 	sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
554 	    norm;
555 	sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
556 	    high;
557 	sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
558 	    high;
559 
560 	norm = htole32(AAC_HOST_NORM_RESP_ENTRIES);
561 	high = htole32(AAC_HOST_HIGH_RESP_ENTRIES);
562 
563 	sc->sc_queues->
564 	    qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm;
565 	sc->sc_queues->
566 	    qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm;
567 	sc->sc_queues->
568 	    qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high;
569 	sc->sc_queues->
570 	    qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high;
571 
572 	norm = htole32(AAC_ADAP_NORM_RESP_ENTRIES);
573 	high = htole32(AAC_ADAP_HIGH_RESP_ENTRIES);
574 
575 	sc->sc_queues->
576 	    qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm;
577 	sc->sc_queues->
578 	    qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm;
579 	sc->sc_queues->
580 	    qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high;
581 	sc->sc_queues->
582 	    qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high;
583 
584 	sc->sc_qentries[AAC_HOST_NORM_CMD_QUEUE] =
585 	    &sc->sc_queues->qt_HostNormCmdQueue[0];
586 	sc->sc_qentries[AAC_HOST_HIGH_CMD_QUEUE] =
587 	    &sc->sc_queues->qt_HostHighCmdQueue[0];
588 	sc->sc_qentries[AAC_ADAP_NORM_CMD_QUEUE] =
589 	    &sc->sc_queues->qt_AdapNormCmdQueue[0];
590 	sc->sc_qentries[AAC_ADAP_HIGH_CMD_QUEUE] =
591 	    &sc->sc_queues->qt_AdapHighCmdQueue[0];
592 	sc->sc_qentries[AAC_HOST_NORM_RESP_QUEUE] =
593 	    &sc->sc_queues->qt_HostNormRespQueue[0];
594 	sc->sc_qentries[AAC_HOST_HIGH_RESP_QUEUE] =
595 	    &sc->sc_queues->qt_HostHighRespQueue[0];
596 	sc->sc_qentries[AAC_ADAP_NORM_RESP_QUEUE] =
597 	    &sc->sc_queues->qt_AdapNormRespQueue[0];
598 	sc->sc_qentries[AAC_ADAP_HIGH_RESP_QUEUE] =
599 	    &sc->sc_queues->qt_AdapHighRespQueue[0];
600 
601 	/*
602 	 * Do controller-type-specific initialisation
603 	 */
604 	switch (sc->sc_hwif) {
605 	case AAC_HWIF_I960RX:
606 		AAC_SETREG4(sc, AAC_RX_ODBR, ~0);
607 		break;
608 	}
609 
610 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 0,
611 	    sizeof(*sc->sc_common),
612 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
613 
614 	/*
615 	 * Give the init structure to the controller.
616 	 */
617 	if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT,
618 	    sc->sc_common_seg.ds_addr + offsetof(struct aac_common, ac_init),
619 	    0, 0, 0, NULL)) {
620 		aprint_error("%s: error establishing init structure\n",
621 		    sc->sc_dv.dv_xname);
622 		rv = EIO;
623 		goto bail_out;
624 	}
625 
626 	return (0);
627 
628  bail_out:
629  	if (state > 2)
630  		bus_dmamap_unload(sc->sc_dmat, sc->sc_common_dmamap);
631 	if (state > 1)
632 		bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_common,
633 		    sizeof(*sc->sc_common));
634 	if (state > 0)
635 		bus_dmamem_free(sc->sc_dmat, &sc->sc_common_seg, 1);
636 	bus_dmamap_destroy(sc->sc_dmat, sc->sc_common_dmamap);
637 
638 	return (rv);
639 }
640 
641 /*
642  * Probe for containers, create disks.
643  */
644 static void
645 aac_startup(struct aac_softc *sc)
646 {
647 	struct aac_mntinfo mi;
648 	struct aac_mntinforesponse mir;
649 	struct aac_drive *hd;
650 	u_int16_t rsize;
651 	int i;
652 
653 	/*
654 	 * Loop over possible containers.
655 	 */
656 	hd = sc->sc_hdr;
657 
658 	for (i = 0; i < AAC_MAX_CONTAINERS; i++, hd++) {
659 		/*
660 		 * Request information on this container.
661 		 */
662 		memset(&mi, 0, sizeof(mi));
663 		mi.Command = htole32(VM_NameServe);
664 		mi.MntType = htole32(FT_FILESYS);
665 		mi.MntCount = htole32(i);
666 		if (aac_sync_fib(sc, ContainerCommand, 0, &mi, sizeof(mi), &mir,
667 		    &rsize)) {
668 			aprint_error("%s: error probing container %d\n",
669 			    sc->sc_dv.dv_xname, i);
670 			continue;
671 		}
672 		if (rsize != sizeof(mir)) {
673 			aprint_error("%s: container info response wrong size "
674 			    "(%d should be %lu)\n",
675 			    sc->sc_dv.dv_xname, rsize, (long unsigned) sizeof(mir));
676 			continue;
677 		}
678 
679 		/*
680 		 * Check container volume type for validity.  Note that many
681 		 * of the possible types may never show up.
682 		 */
683 		if (le32toh(mir.Status) != ST_OK ||
684 		    le32toh(mir.MntTable[0].VolType) == CT_NONE)
685 			continue;
686 
687 		hd->hd_present = 1;
688 		hd->hd_size = le32toh(mir.MntTable[0].Capacity);
689 		hd->hd_devtype = le32toh(mir.MntTable[0].VolType);
690 		hd->hd_size &= ~0x1f;
691 		sc->sc_nunits++;
692 	}
693 }
694 
695 static void
696 aac_shutdown(void *cookie)
697 {
698 	struct aac_softc *sc;
699 	struct aac_close_command cc;
700 	u_int32_t i;
701 
702 	for (i = 0; i < aac_cd.cd_ndevs; i++) {
703 		if ((sc = device_lookup(&aac_cd, i)) == NULL)
704 			continue;
705 		if ((sc->sc_flags & AAC_ONLINE) == 0)
706 			continue;
707 
708 		AAC_MASK_INTERRUPTS(sc);
709 
710 		/*
711 		 * Send a Container shutdown followed by a HostShutdown FIB
712 		 * to the controller to convince it that we don't want to
713 		 * talk to it anymore.  We've been closed and all I/O
714 		 * completed already
715 		 */
716 		memset(&cc, 0, sizeof(cc));
717 		cc.Command = htole32(VM_CloseAll);
718 		cc.ContainerId = 0xffffffff;
719 		if (aac_sync_fib(sc, ContainerCommand, 0, &cc, sizeof(cc),
720 		    NULL, NULL)) {
721 			printf("%s: unable to halt controller\n",
722 			    sc->sc_dv.dv_xname);
723 			continue;
724 		}
725 
726 		/*
727 		 * Note that issuing this command to the controller makes it
728 		 * shut down but also keeps it from coming back up without a
729 		 * reset of the PCI bus.
730 		 */
731 		if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN,
732 		    &i, sizeof(i), NULL, NULL))
733 			printf("%s: unable to halt controller\n",
734 			    sc->sc_dv.dv_xname);
735 
736 		sc->sc_flags &= ~AAC_ONLINE;
737 	}
738 }
739 
740 /*
741  * Take an interrupt.
742  */
743 int
744 aac_intr(void *cookie)
745 {
746 	struct aac_softc *sc;
747 	u_int16_t reason;
748 	int claimed;
749 
750 	sc = cookie;
751 	claimed = 0;
752 
753 	AAC_DPRINTF(AAC_D_INTR, ("aac_intr(%p) ", sc));
754 
755 	reason = AAC_GET_ISTATUS(sc);
756 	AAC_DPRINTF(AAC_D_INTR, ("istatus 0x%04x ", reason));
757 
758 	/*
759 	 * Controller wants to talk to the log.  XXX Should we defer this?
760 	 */
761 	if ((reason & AAC_DB_PRINTF) != 0) {
762 		if (sc->sc_common->ac_printf[0] != '\0') {
763 			printf("%s: WARNING: adapter logged message:\n",
764 			    sc->sc_dv.dv_xname);
765 			printf("%s:     %.*s", sc->sc_dv.dv_xname,
766 			    AAC_PRINTF_BUFSIZE, sc->sc_common->ac_printf);
767 			sc->sc_common->ac_printf[0] = '\0';
768 		}
769 		AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF);
770 		AAC_QNOTIFY(sc, AAC_DB_PRINTF);
771 		claimed = 1;
772 	}
773 
774 	/*
775 	 * Controller has a message for us?
776 	 */
777 	if ((reason & AAC_DB_COMMAND_READY) != 0) {
778 		aac_host_command(sc);
779 		AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_READY);
780 		claimed = 1;
781 	}
782 
783 	/*
784 	 * Controller has a response for us?
785 	 */
786 	if ((reason & AAC_DB_RESPONSE_READY) != 0) {
787 		aac_host_response(sc);
788 		AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
789 		claimed = 1;
790 	}
791 
792 	/*
793 	 * Spurious interrupts that we don't use - reset the mask and clear
794 	 * the interrupts.
795 	 */
796 	if ((reason & (AAC_DB_SYNC_COMMAND | AAC_DB_COMMAND_NOT_FULL |
797             AAC_DB_RESPONSE_NOT_FULL)) != 0) {
798 		AAC_UNMASK_INTERRUPTS(sc);
799 		AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND |
800 		    AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL);
801 		claimed = 1;
802 	}
803 
804 	return (claimed);
805 }
806 
807 /*
808  * Handle notification of one or more FIBs coming from the controller.
809  */
810 static void
811 aac_host_command(struct aac_softc *sc)
812 {
813 	struct aac_fib *fib;
814 	u_int32_t fib_size;
815 
816 	for (;;) {
817 		if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size,
818 		    &fib))
819 			break;	/* nothing to do */
820 
821 		bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
822 		    (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib),
823 		    BUS_DMASYNC_POSTREAD);
824 
825 		switch (le16toh(fib->Header.Command)) {
826 		case AifRequest:
827 #ifdef notyet
828 			aac_handle_aif(sc,
829 			    (struct aac_aif_command *)&fib->data[0]);
830 #endif
831 			break;
832 		default:
833 			printf("%s: unknown command from controller\n",
834 			    sc->sc_dv.dv_xname);
835 			AAC_PRINT_FIB(sc, fib);
836 			break;
837 		}
838 
839 		bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
840 		    (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib),
841 		    BUS_DMASYNC_PREREAD);
842 
843 		/* XXX reply to FIBs requesting responses ?? */
844 		/* XXX how do we return these FIBs to the controller? */
845 	}
846 }
847 
848 /*
849  * Handle notification of one or more FIBs completed by the controller
850  */
851 static void
852 aac_host_response(struct aac_softc *sc)
853 {
854 	struct aac_ccb *ac;
855 	struct aac_fib *fib;
856 	u_int32_t fib_size;
857 
858 	/*
859 	 * Look for completed FIBs on our queue.
860 	 */
861 	for (;;) {
862 		if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size,
863 		    &fib))
864 			break;	/* nothing to do */
865 
866 		bus_dmamap_sync(sc->sc_dmat, sc->sc_fibs_dmamap,
867 		    (caddr_t)fib - (caddr_t)sc->sc_fibs, sizeof(*fib),
868 		    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
869 
870 		if ((fib->Header.SenderData & 0x80000000) == 0) {
871 			/* Not valid; not sent by us. */
872 			AAC_PRINT_FIB(sc, fib);
873 		} else {
874 			ac = (struct aac_ccb *)((caddr_t)sc->sc_ccbs +
875 			    (fib->Header.SenderData & 0x7fffffff));
876 			fib->Header.SenderData = 0;
877 			SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_complete, ac, ac_chain);
878 		}
879 	}
880 
881 	/*
882 	 * Deal with any completed commands.
883 	 */
884 	while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_complete)) != NULL) {
885 		SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_complete, ac_chain);
886 		ac->ac_flags |= AAC_CCB_COMPLETED;
887 
888 		if (ac->ac_intr != NULL)
889 			(*ac->ac_intr)(ac);
890 	}
891 
892 	/*
893 	 * Try to submit more commands.
894 	 */
895 	if (! SIMPLEQ_EMPTY(&sc->sc_ccb_queue))
896 		aac_ccb_enqueue(sc, NULL);
897 }
898 
899 /*
900  * Send a synchronous command to the controller and wait for a result.
901  */
902 static int
903 aac_sync_command(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
904 		 u_int32_t arg1, u_int32_t arg2, u_int32_t arg3, u_int32_t *sp)
905 {
906 	int i;
907 	u_int32_t status;
908 	int s;
909 
910 	s = splbio();
911 
912 	/* Populate the mailbox. */
913 	AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3);
914 
915 	/* Ensure the sync command doorbell flag is cleared. */
916 	AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
917 
918 	/* ... then set it to signal the adapter. */
919 	AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND);
920 	DELAY(AAC_SYNC_DELAY);
921 
922 	/* Spin waiting for the command to complete. */
923 	for (i = 0; i < AAC_IMMEDIATE_TIMEOUT * 1000; i++) {
924 		if (AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND)
925 			break;
926 		DELAY(1000);
927 	}
928 	if (i == AAC_IMMEDIATE_TIMEOUT * 1000) {
929 		splx(s);
930 		return (EIO);
931 	}
932 
933 	/* Clear the completion flag. */
934 	AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
935 
936 	/* Get the command status. */
937 	status = AAC_GET_MAILBOXSTATUS(sc);
938 	splx(s);
939 	if (sp != NULL)
940 		*sp = status;
941 
942 	return (0);	/* XXX Check command return status? */
943 }
944 
945 /*
946  * Send a synchronous FIB to the controller and wait for a result.
947  */
948 static int
949 aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
950 	     void *data, u_int16_t datasize, void *result,
951 	     u_int16_t *resultsize)
952 {
953 	struct aac_fib *fib;
954 	u_int32_t fibpa, status;
955 
956 	fib = &sc->sc_common->ac_sync_fib;
957 	fibpa = sc->sc_common_seg.ds_addr +
958 	    offsetof(struct aac_common, ac_sync_fib);
959 
960 	if (datasize > AAC_FIB_DATASIZE)
961 		return (EINVAL);
962 
963 	/*
964 	 * Set up the sync FIB.
965 	 */
966 	fib->Header.XferState = htole32(AAC_FIBSTATE_HOSTOWNED |
967 	    AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_EMPTY | xferstate);
968 	fib->Header.Command = htole16(command);
969 	fib->Header.StructType = AAC_FIBTYPE_TFIB;
970 	fib->Header.Size = htole16(sizeof(*fib) + datasize);
971 	fib->Header.SenderSize = htole16(sizeof(*fib));
972 	fib->Header.SenderFibAddress = 0; /* htole32((u_int32_t)fib);	* XXX */
973 	fib->Header.ReceiverFibAddress = htole32(fibpa);
974 
975 	/*
976 	 * Copy in data.
977 	 */
978 	if (data != NULL) {
979 		memcpy(fib->data, data, datasize);
980 		fib->Header.XferState |=
981 		    htole32(AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_NORM);
982 	}
983 
984 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
985 	    (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib),
986 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
987 
988 	/*
989 	 * Give the FIB to the controller, wait for a response.
990 	 */
991 	if (aac_sync_command(sc, AAC_MONKER_SYNCFIB, fibpa, 0, 0, 0, &status))
992 		return (EIO);
993 	if (status != 1) {
994 		printf("%s: syncfib command %04x status %08x\n",
995 			sc->sc_dv.dv_xname, command, status);
996 	}
997 
998 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
999 	    (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib),
1000 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
1001 
1002 	/*
1003 	 * Copy out the result
1004 	 */
1005 	if (result != NULL) {
1006 		*resultsize = le16toh(fib->Header.Size) - sizeof(fib->Header);
1007 		memcpy(result, fib->data, *resultsize);
1008 	}
1009 
1010 	return (0);
1011 }
1012 
1013 struct aac_ccb *
1014 aac_ccb_alloc(struct aac_softc *sc, int flags)
1015 {
1016 	struct aac_ccb *ac;
1017 	int s;
1018 
1019 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_alloc(%p, 0x%x) ", sc, flags));
1020 
1021 	s = splbio();
1022 	ac = SIMPLEQ_FIRST(&sc->sc_ccb_free);
1023 #ifdef DIAGNOSTIC
1024 	if (ac == NULL)
1025 		panic("aac_ccb_get: no free CCBS");
1026 #endif
1027 	SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ac_chain);
1028 	splx(s);
1029 
1030 	ac->ac_flags = flags;
1031 	return (ac);
1032 }
1033 
1034 void
1035 aac_ccb_free(struct aac_softc *sc, struct aac_ccb *ac)
1036 {
1037 	int s;
1038 
1039 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_free(%p, %p) ", sc, ac));
1040 
1041 	ac->ac_flags = 0;
1042 	ac->ac_intr = NULL;
1043 	ac->ac_fib->Header.XferState = htole32(AAC_FIBSTATE_EMPTY);
1044 	ac->ac_fib->Header.StructType = AAC_FIBTYPE_TFIB;
1045 	ac->ac_fib->Header.Flags = 0;
1046 	ac->ac_fib->Header.SenderSize = htole16(sizeof(*ac->ac_fib));
1047 
1048 #ifdef AAC_DEBUG
1049 	/*
1050 	 * These are duplicated in aac_ccb_submit() to cover the case where
1051 	 * an intermediate stage may have destroyed them.  They're left
1052 	 * initialised here for debugging purposes only.
1053 	 */
1054 	ac->ac_fib->Header.SenderFibAddress = htole32((u_int32_t)(intptr_t/*XXX LP54*/)ac->ac_fib);
1055 	ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys);
1056 #endif
1057 
1058 	s = splbio();
1059 	SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ac, ac_chain);
1060 	splx(s);
1061 }
1062 
1063 int
1064 aac_ccb_map(struct aac_softc *sc, struct aac_ccb *ac)
1065 {
1066 	int error;
1067 
1068 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_map(%p, %p) ", sc, ac));
1069 
1070 #ifdef DIAGNOSTIC
1071 	if ((ac->ac_flags & AAC_CCB_MAPPED) != 0)
1072 		panic("aac_ccb_map: already mapped");
1073 #endif
1074 
1075 	error = bus_dmamap_load(sc->sc_dmat, ac->ac_dmamap_xfer, ac->ac_data,
1076 	    ac->ac_datalen, NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
1077 	    ((ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMA_READ : BUS_DMA_WRITE));
1078 	if (error) {
1079 		printf("%s: aac_ccb_map: ", sc->sc_dv.dv_xname);
1080 		if (error == EFBIG)
1081 			printf("more than %d DMA segs\n", AAC_MAX_SGENTRIES);
1082 		else
1083 			printf("error %d loading DMA map\n", error);
1084 		return (error);
1085 	}
1086 
1087 	bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen,
1088 	    (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_PREREAD :
1089 	    BUS_DMASYNC_PREWRITE);
1090 
1091 #ifdef DIAGNOSTIC
1092 	ac->ac_flags |= AAC_CCB_MAPPED;
1093 #endif
1094 	return (0);
1095 }
1096 
1097 void
1098 aac_ccb_unmap(struct aac_softc *sc, struct aac_ccb *ac)
1099 {
1100 
1101 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_unmap(%p, %p) ", sc, ac));
1102 
1103 #ifdef DIAGNOSTIC
1104 	if ((ac->ac_flags & AAC_CCB_MAPPED) == 0)
1105 		panic("aac_ccb_unmap: not mapped");
1106 #endif
1107 
1108 	bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen,
1109 	    (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_POSTREAD :
1110 	    BUS_DMASYNC_POSTWRITE);
1111 	bus_dmamap_unload(sc->sc_dmat, ac->ac_dmamap_xfer);
1112 
1113 #ifdef DIAGNOSTIC
1114 	ac->ac_flags &= ~AAC_CCB_MAPPED;
1115 #endif
1116 }
1117 
1118 void
1119 aac_ccb_enqueue(struct aac_softc *sc, struct aac_ccb *ac)
1120 {
1121 	int s;
1122 
1123 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_enqueue(%p, %p) ", sc, ac));
1124 
1125 	s = splbio();
1126 
1127 	if (ac != NULL)
1128 		SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_queue, ac, ac_chain);
1129 
1130 	while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_queue)) != NULL) {
1131 		if (aac_ccb_submit(sc, ac))
1132 			break;
1133 		SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_queue, ac_chain);
1134 	}
1135 
1136 	splx(s);
1137 }
1138 
1139 int
1140 aac_ccb_submit(struct aac_softc *sc, struct aac_ccb *ac)
1141 {
1142 
1143 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_submit(%p, %p) ", sc, ac));
1144 
1145 	/* Fix up the address values. */
1146 	ac->ac_fib->Header.SenderFibAddress = htole32((u_int32_t)(intptr_t/*XXX LP64*/)ac->ac_fib);
1147 	ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys);
1148 
1149 	/* Save a pointer to the command for speedy reverse-lookup. */
1150 	ac->ac_fib->Header.SenderData =
1151 	    (u_int32_t)((caddr_t)ac - (caddr_t)sc->sc_ccbs) | 0x80000000;
1152 
1153 	bus_dmamap_sync(sc->sc_dmat, sc->sc_fibs_dmamap,
1154 	    (caddr_t)ac->ac_fib - (caddr_t)sc->sc_fibs, sizeof(*ac->ac_fib),
1155 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1156 
1157 	/* Put the FIB on the outbound queue. */
1158 	return (aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE, ac->ac_fib));
1159 }
1160 
1161 int
1162 aac_ccb_poll(struct aac_softc *sc, struct aac_ccb *ac, int timo)
1163 {
1164 	int rv, s;
1165 
1166 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_poll(%p, %p, %d) ", sc, ac, timo));
1167 
1168 	s = splbio();
1169 
1170 	if ((rv = aac_ccb_submit(sc, ac)) != 0) {
1171 		splx(s);
1172 		return (rv);
1173 	}
1174 
1175 	for (timo *= 1000; timo != 0; timo--) {
1176 		aac_intr(sc);
1177 		if ((ac->ac_flags & AAC_CCB_COMPLETED) != 0)
1178 			break;
1179 		DELAY(100);
1180 	}
1181 
1182 	splx(s);
1183 	return (timo == 0);
1184 }
1185 
1186 /*
1187  * Atomically insert an entry into the nominated queue, returns 0 on success
1188  * or EBUSY if the queue is full.
1189  *
1190  * XXX Note that it would be more efficient to defer notifying the
1191  * controller in the case where we may be inserting several entries in rapid
1192  * succession, but implementing this usefully is difficult.
1193  */
1194 static int
1195 aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_fib *fib)
1196 {
1197 	u_int32_t fib_size, fib_addr, pi, ci;
1198 
1199 	fib_size = le16toh(fib->Header.Size);
1200 	fib_addr = le32toh(fib->Header.ReceiverFibAddress);
1201 
1202 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1203 	    (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common,
1204 	    sizeof(sc->sc_common->ac_qbuf),
1205 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
1206 
1207 	/* Get the producer/consumer indices.  */
1208 	pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
1209 	ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
1210 
1211 	/* Wrap the queue? */
1212 	if (pi >= aac_qinfo[queue].size)
1213 		pi = 0;
1214 
1215 	/* Check for queue full. */
1216 	if ((pi + 1) == ci)
1217 		return (EAGAIN);
1218 
1219 	/* Populate queue entry. */
1220 	(sc->sc_qentries[queue] + pi)->aq_fib_size = htole32(fib_size);
1221 	(sc->sc_qentries[queue] + pi)->aq_fib_addr = htole32(fib_addr);
1222 
1223 	/* Update producer index. */
1224 	sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = htole32(pi + 1);
1225 
1226 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1227 	    (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common,
1228 	    sizeof(sc->sc_common->ac_qbuf),
1229 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1230 
1231 	/* Notify the adapter if we know how. */
1232 	if (aac_qinfo[queue].notify != 0)
1233 		AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1234 
1235 	return (0);
1236 }
1237 
1238 /*
1239  * Atomically remove one entry from the nominated queue, returns 0 on success
1240  * or ENOENT if the queue is empty.
1241  */
1242 static int
1243 aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
1244 		struct aac_fib **fib_addr)
1245 {
1246 	u_int32_t pi, ci;
1247 	int notify;
1248 
1249 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1250 	    (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common,
1251 	    sizeof(sc->sc_common->ac_qbuf),
1252 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
1253 
1254 	/* Get the producer/consumer indices. */
1255 	pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
1256 	ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
1257 
1258 	/* Check for queue empty. */
1259 	if (ci == pi)
1260 		return (ENOENT);
1261 
1262 	notify = 0;
1263 	if (ci == pi + 1)
1264 		notify = 1;
1265 
1266 	/* Wrap the queue? */
1267 	if (ci >= aac_qinfo[queue].size)
1268 		ci = 0;
1269 
1270 	/* Fetch the entry. */
1271 	*fib_size = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_size);
1272 	*fib_addr = (void *)(intptr_t) le32toh(
1273 	    (sc->sc_qentries[queue] + ci)->aq_fib_addr);
1274 
1275 	/* Update consumer index. */
1276 	sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1;
1277 
1278 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
1279 	    (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common,
1280 	    sizeof(sc->sc_common->ac_qbuf),
1281 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1282 
1283 	/* If we have made the queue un-full, notify the adapter. */
1284 	if (notify && (aac_qinfo[queue].notify != 0))
1285 		AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
1286 
1287 	return (0);
1288 }
1289 
1290 #ifdef AAC_DEBUG
1291 /*
1292  * Print a FIB
1293  */
1294 static void
1295 aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, const char *caller)
1296 {
1297 	struct aac_blockread *br;
1298 	struct aac_blockwrite *bw;
1299 	struct aac_sg_table *sg;
1300 	char tbuf[512];
1301 	int i;
1302 
1303 	printf("%s: FIB @ %p\n", caller, fib);
1304 	bitmask_snprintf(le32toh(fib->Header.XferState),
1305 	    "\20"
1306 	    "\1HOSTOWNED"
1307 	    "\2ADAPTEROWNED"
1308 	    "\3INITIALISED"
1309 	    "\4EMPTY"
1310 	    "\5FROMPOOL"
1311 	    "\6FROMHOST"
1312 	    "\7FROMADAP"
1313 	    "\10REXPECTED"
1314 	    "\11RNOTEXPECTED"
1315 	    "\12DONEADAP"
1316 	    "\13DONEHOST"
1317 	    "\14HIGH"
1318 	    "\15NORM"
1319 	    "\16ASYNC"
1320 	    "\17PAGEFILEIO"
1321 	    "\20SHUTDOWN"
1322 	    "\21LAZYWRITE"
1323 	    "\22ADAPMICROFIB"
1324 	    "\23BIOSFIB"
1325 	    "\24FAST_RESPONSE"
1326 	    "\25APIFIB\n",
1327 	    tbuf,
1328 	    sizeof(tbuf));
1329 
1330 	printf("  XferState       %s\n", tbuf);
1331 	printf("  Command         %d\n", le16toh(fib->Header.Command));
1332 	printf("  StructType      %d\n", fib->Header.StructType);
1333 	printf("  Flags           0x%x\n", fib->Header.Flags);
1334 	printf("  Size            %d\n", le16toh(fib->Header.Size));
1335 	printf("  SenderSize      %d\n", le16toh(fib->Header.SenderSize));
1336 	printf("  SenderAddress   0x%x\n",
1337 	    le32toh(fib->Header.SenderFibAddress));
1338 	printf("  ReceiverAddress 0x%x\n",
1339 	    le32toh(fib->Header.ReceiverFibAddress));
1340 	printf("  SenderData      0x%x\n", fib->Header.SenderData);
1341 
1342 	switch (fib->Header.Command) {
1343 	case ContainerCommand: {
1344 		br = (struct aac_blockread *)fib->data;
1345 		bw = (struct aac_blockwrite *)fib->data;
1346 		sg = NULL;
1347 
1348 		if (le32toh(br->Command) == VM_CtBlockRead) {
1349 			printf("  BlockRead: container %d  0x%x/%d\n",
1350 			    le32toh(br->ContainerId), le32toh(br->BlockNumber),
1351 			    le32toh(br->ByteCount));
1352 			sg = &br->SgMap;
1353 		}
1354 		if (le32toh(bw->Command) == VM_CtBlockWrite) {
1355 			printf("  BlockWrite: container %d  0x%x/%d (%s)\n",
1356 			    le32toh(bw->ContainerId), le32toh(bw->BlockNumber),
1357 			    le32toh(bw->ByteCount),
1358 			    le32toh(bw->Stable) == CSTABLE ?
1359 			    "stable" : "unstable");
1360 			sg = &bw->SgMap;
1361 		}
1362 		if (sg != NULL) {
1363 			printf("  %d s/g entries\n", le32toh(sg->SgCount));
1364 			for (i = 0; i < le32toh(sg->SgCount); i++)
1365 				printf("  0x%08x/%d\n",
1366 				    le32toh(sg->SgEntry[i].SgAddress),
1367 				    le32toh(sg->SgEntry[i].SgByteCount));
1368 		}
1369 		break;
1370 	}
1371 	default:
1372 		// dump first 32 bytes of fib->data
1373 		printf("  Raw data:");
1374 		for (i = 0; i < 32; i++)
1375 			printf(" %02x", fib->data[i]);
1376 		printf("\n");
1377 		break;
1378 	}
1379 }
1380 #endif /* AAC_DEBUG */
1381