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