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