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