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