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