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