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