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