Home | History | Annotate | Line # | Download | only in ic
aac.c revision 1.31
      1 /*	$NetBSD: aac.c,v 1.31 2007/05/24 15:07:47 briggs Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2002, 2007 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.31 2007/05/24 15:07:47 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 int	aac_enqueue_response(struct aac_softc *, int, struct aac_fib *);
    105 static void	aac_host_command(struct aac_softc *);
    106 static void	aac_host_response(struct aac_softc *);
    107 static int	aac_init(struct aac_softc *);
    108 static int	aac_print(void *, const char *);
    109 static void	aac_shutdown(void *);
    110 static void	aac_startup(struct aac_softc *);
    111 static int	aac_sync_command(struct aac_softc *, u_int32_t, u_int32_t,
    112 				 u_int32_t, u_int32_t, u_int32_t, u_int32_t *);
    113 static int	aac_sync_fib(struct aac_softc *, u_int32_t, u_int32_t, void *,
    114 			     u_int16_t, void *, u_int16_t *);
    115 
    116 #ifdef AAC_DEBUG
    117 static void	aac_print_fib(struct aac_softc *, struct aac_fib *, const char *);
    118 #endif
    119 
    120 /*
    121  * Adapter-space FIB queue manipulation.
    122  *
    123  * Note that the queue implementation here is a little funky; neither the PI or
    124  * CI will ever be zero.  This behaviour is a controller feature.
    125  */
    126 static struct {
    127 	int	size;
    128 	int	notify;
    129 } const aac_qinfo[] = {
    130 	{ AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL },
    131 	{ AAC_HOST_HIGH_CMD_ENTRIES, 0 },
    132 	{ AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY },
    133 	{ AAC_ADAP_HIGH_CMD_ENTRIES, 0 },
    134 	{ AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL },
    135 	{ AAC_HOST_HIGH_RESP_ENTRIES, 0 },
    136 	{ AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY },
    137 	{ AAC_ADAP_HIGH_RESP_ENTRIES, 0 }
    138 };
    139 
    140 #ifdef AAC_DEBUG
    141 int	aac_debug = AAC_DEBUG;
    142 #endif
    143 
    144 static void	*aac_sdh;
    145 
    146 extern struct	cfdriver aac_cd;
    147 
    148 int
    149 aac_attach(struct aac_softc *sc)
    150 {
    151 	struct aac_attach_args aaca;
    152 	int nsegs, i, rv, state, size;
    153 	struct aac_ccb *ac;
    154 	struct aac_fib *fib;
    155 	bus_addr_t fibpa;
    156 	int locs[AACCF_NLOCS];
    157 
    158 	SIMPLEQ_INIT(&sc->sc_ccb_free);
    159 	SIMPLEQ_INIT(&sc->sc_ccb_queue);
    160 	SIMPLEQ_INIT(&sc->sc_ccb_complete);
    161 
    162 	/*
    163 	 * Disable interrupts before we do anything.
    164 	 */
    165 	AAC_MASK_INTERRUPTS(sc);
    166 
    167 	/*
    168 	 * Initialise the adapter.
    169 	 */
    170 	if (aac_check_firmware(sc))
    171 		return (EINVAL);
    172 
    173 	if ((rv = aac_init(sc)) != 0)
    174 		return (rv);
    175 	aac_startup(sc);
    176 
    177 	/*
    178 	 * Print a little information about the controller.
    179 	 */
    180 	aac_describe_controller(sc);
    181 
    182 	/*
    183 	 * Initialize the ccbs.
    184 	 */
    185 	sc->sc_ccbs = malloc(sizeof(*ac) * AAC_NCCBS, M_DEVBUF,
    186 	    M_NOWAIT | M_ZERO);
    187 	if (sc->sc_ccbs == NULL) {
    188 		aprint_error("%s: memory allocation failure\n",
    189 		    sc->sc_dv.dv_xname);
    190 		return (ENOMEM);
    191 	}
    192 	state = 0;
    193 	size = sizeof(*fib) * AAC_NCCBS;
    194 
    195 	if ((rv = bus_dmamap_create(sc->sc_dmat, size, 1, size,
    196 	    0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_fibs_dmamap)) != 0) {
    197 		aprint_error("%s: cannot create fibs dmamap\n",
    198 		    sc->sc_dv.dv_xname);
    199 		goto bail_out;
    200 	}
    201 	state++;
    202 	if ((rv = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0,
    203 	    &sc->sc_fibs_seg, 1, &nsegs, BUS_DMA_NOWAIT)) != 0) {
    204 		aprint_error("%s: can't allocate fibs structure\n",
    205 		    sc->sc_dv.dv_xname);
    206 		goto bail_out;
    207 	}
    208 	state++;
    209 	if ((rv = bus_dmamem_map(sc->sc_dmat, &sc->sc_fibs_seg, nsegs, size,
    210 	    (void **)&sc->sc_fibs, 0)) != 0) {
    211 		aprint_error("%s: can't map fibs structure\n",
    212 		    sc->sc_dv.dv_xname);
    213 		goto bail_out;
    214 	}
    215 	state++;
    216 	if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_fibs_dmamap, sc->sc_fibs,
    217 	    size, NULL, BUS_DMA_NOWAIT)) != 0) {
    218 		aprint_error("%s: cannot load fibs dmamap\n",
    219 		    sc->sc_dv.dv_xname);
    220 		goto bail_out;
    221 	}
    222 	state++;
    223 
    224 	memset(sc->sc_fibs, 0, size);
    225 	fibpa = sc->sc_fibs_seg.ds_addr;
    226 	fib = sc->sc_fibs;
    227 
    228 	for (i = 0, ac = sc->sc_ccbs; i < AAC_NCCBS; i++, ac++) {
    229 		rv = bus_dmamap_create(sc->sc_dmat, AAC_MAX_XFER,
    230 		    AAC_MAX_SGENTRIES, AAC_MAX_XFER, 0,
    231 		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ac->ac_dmamap_xfer);
    232 		if (rv) {
    233 			while (--ac >= sc->sc_ccbs)
    234 				bus_dmamap_destroy(sc->sc_dmat,
    235 				    ac->ac_dmamap_xfer);
    236 			aprint_error("%s: cannot create ccb dmamap (%d)",
    237 			    sc->sc_dv.dv_xname, rv);
    238 			goto bail_out;
    239 		}
    240 
    241 		ac->ac_fib = fib++;
    242 		ac->ac_fibphys = fibpa;
    243 		fibpa += sizeof(*fib);
    244 		aac_ccb_free(sc, ac);
    245 	}
    246 
    247 	/*
    248 	 * Attach devices.
    249 	 */
    250 	for (i = 0; i < AAC_MAX_CONTAINERS; i++) {
    251 		if (!sc->sc_hdr[i].hd_present)
    252 			continue;
    253 		aaca.aaca_unit = i;
    254 
    255 		locs[AACCF_UNIT] = i;
    256 
    257 		config_found_sm_loc(&sc->sc_dv, "aac", locs, &aaca,
    258 				    aac_print, config_stdsubmatch);
    259 	}
    260 
    261 	/*
    262 	 * Enable interrupts, and register our shutdown hook.
    263 	 */
    264 	sc->sc_flags |= AAC_ONLINE;
    265 	AAC_UNMASK_INTERRUPTS(sc);
    266 	if (aac_sdh != NULL)
    267 		shutdownhook_establish(aac_shutdown, NULL);
    268 	return (0);
    269 
    270  bail_out:
    271  	bus_dmamap_unload(sc->sc_dmat, sc->sc_common_dmamap);
    272 	bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_common,
    273 	    sizeof(*sc->sc_common));
    274 	bus_dmamem_free(sc->sc_dmat, &sc->sc_common_seg, 1);
    275 	bus_dmamap_destroy(sc->sc_dmat, sc->sc_common_dmamap);
    276 
    277  	if (state > 3)
    278  		bus_dmamap_unload(sc->sc_dmat, sc->sc_fibs_dmamap);
    279 	if (state > 2)
    280 		bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_fibs, size);
    281 	if (state > 1)
    282 		bus_dmamem_free(sc->sc_dmat, &sc->sc_fibs_seg, 1);
    283 	if (state > 0)
    284 		bus_dmamap_destroy(sc->sc_dmat, sc->sc_fibs_dmamap);
    285 
    286 	free(sc->sc_ccbs, M_DEVBUF);
    287 	return (rv);
    288 }
    289 
    290 /*
    291  * Print autoconfiguration message for a sub-device.
    292  */
    293 static int
    294 aac_print(void *aux, const char *pnp)
    295 {
    296 	struct aac_attach_args *aaca;
    297 
    298 	aaca = aux;
    299 
    300 	if (pnp != NULL)
    301 		aprint_normal("block device at %s", pnp);
    302 	aprint_normal(" unit %d", aaca->aaca_unit);
    303 	return (UNCONF);
    304 }
    305 
    306 /*
    307  * Look up a text description of a numeric error code and return a pointer to
    308  * same.
    309  */
    310 const char *
    311 aac_describe_code(const struct aac_code_lookup *table, u_int32_t code)
    312 {
    313 	int i;
    314 
    315 	for (i = 0; table[i].string != NULL; i++)
    316 		if (table[i].code == code)
    317 			return (table[i].string);
    318 
    319 	return (table[i + 1].string);
    320 }
    321 
    322 /*
    323  * bitmask_snprintf(9) format string for the adapter options.
    324  */
    325 static const char *optfmt =
    326     "\20\1SNAPSHOT\2CLUSTERS\3WCACHE\4DATA64\5HOSTTIME\6RAID50"
    327     "\7WINDOW4GB"
    328     "\10SCSIUPGD\11SOFTERR\12NORECOND\13SGMAP64\14ALARM\15NONDASD";
    329 
    330 static void
    331 aac_describe_controller(struct aac_softc *sc)
    332 {
    333 	u_int8_t fmtbuf[256];
    334 	u_int8_t tbuf[AAC_FIB_DATASIZE];
    335 	u_int16_t bufsize;
    336 	struct aac_adapter_info *info;
    337 	u_int8_t arg;
    338 
    339 	arg = 0;
    340 	if (aac_sync_fib(sc, RequestAdapterInfo, 0, &arg, sizeof(arg), &tbuf,
    341 	    &bufsize)) {
    342 		aprint_error("%s: RequestAdapterInfo failed\n",
    343 		    sc->sc_dv.dv_xname);
    344 		return;
    345 	}
    346 	if (bufsize != sizeof(*info)) {
    347 		aprint_error("%s: "
    348 		    "RequestAdapterInfo returned wrong data size (%d != %zu)\n",
    349 		    sc->sc_dv.dv_xname, bufsize, sizeof(*info));
    350 		return;
    351 	}
    352 	info = (struct aac_adapter_info *)&tbuf[0];
    353 
    354 	aprint_normal("%s: %s at %dMHz, %dMB mem (%dMB cache), %s\n",
    355 	    sc->sc_dv.dv_xname,
    356 	    aac_describe_code(aac_cpu_variant, le32toh(info->CpuVariant)),
    357 	    le32toh(info->ClockSpeed),
    358 	    le32toh(info->TotalMem) / (1024 * 1024),
    359 	    le32toh(info->BufferMem) / (1024 * 1024),
    360 	    aac_describe_code(aac_battery_platform,
    361 			      le32toh(info->batteryPlatform)));
    362 
    363 	aprint_verbose("%s: Kernel %d.%d-%d [Build %d], ",
    364 	    sc->sc_dv.dv_xname,
    365 	    info->KernelRevision.external.comp.major,
    366 	    info->KernelRevision.external.comp.minor,
    367 	    info->KernelRevision.external.comp.dash,
    368 	    info->KernelRevision.buildNumber);
    369 
    370 	aprint_verbose("Monitor %d.%d-%d [Build %d], S/N %6X\n",
    371 	    info->MonitorRevision.external.comp.major,
    372 	    info->MonitorRevision.external.comp.minor,
    373 	    info->MonitorRevision.external.comp.dash,
    374 	    info->MonitorRevision.buildNumber,
    375 	    ((u_int32_t)info->SerialNumber & 0xffffff));
    376 
    377 	aprint_verbose("%s: Controller supports: %s\n",
    378 	    sc->sc_dv.dv_xname,
    379 	    bitmask_snprintf(sc->sc_supported_options, optfmt, fmtbuf,
    380 			     sizeof(fmtbuf)));
    381 
    382 	/* Save the kernel revision structure for later use. */
    383 	sc->sc_revision = info->KernelRevision;
    384 }
    385 
    386 /*
    387  * Retrieve the firmware version numbers.  Dell PERC2/QC cards with firmware
    388  * version 1.x are not compatible with this driver.
    389  */
    390 static int
    391 aac_check_firmware(struct aac_softc *sc)
    392 {
    393 	u_int32_t major, minor, opts;
    394 
    395 	if ((sc->sc_quirks & AAC_QUIRK_PERC2QC) != 0) {
    396 		if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0,
    397 		    NULL)) {
    398 			aprint_error("%s: error reading firmware version\n",
    399 			    sc->sc_dv.dv_xname);
    400 			return (1);
    401 		}
    402 
    403 		/* These numbers are stored as ASCII! */
    404 		major = (AAC_GET_MAILBOX(sc, 1) & 0xff) - 0x30;
    405 		minor = (AAC_GET_MAILBOX(sc, 2) & 0xff) - 0x30;
    406 		if (major == 1) {
    407 			aprint_error(
    408 			    "%s: firmware version %d.%d not supported.\n",
    409 			    sc->sc_dv.dv_xname, major, minor);
    410 			return (1);
    411 		}
    412 	}
    413 
    414 	if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, NULL)) {
    415 		aprint_error("%s: GETINFO failed\n", sc->sc_dv.dv_xname);
    416 		return (1);
    417 	}
    418 	opts = AAC_GET_MAILBOX(sc, 1);
    419 	sc->sc_supported_options = opts;
    420 
    421 	/* XXX -- Enable 64-bit sglists if we can */
    422 
    423 	return (0);
    424 }
    425 
    426 static int
    427 aac_init(struct aac_softc *sc)
    428 {
    429 	int nsegs, i, rv, state, norm, high;
    430 	struct aac_adapter_init	*ip;
    431 	u_int32_t code, qoff;
    432 
    433 	state = 0;
    434 
    435 	/*
    436 	 * First wait for the adapter to come ready.
    437 	 */
    438 	for (i = 0; i < AAC_BOOT_TIMEOUT * 1000; i++) {
    439 		code = AAC_GET_FWSTATUS(sc);
    440 		if ((code & AAC_SELF_TEST_FAILED) != 0) {
    441 			aprint_error("%s: FATAL: selftest failed\n",
    442 			    sc->sc_dv.dv_xname);
    443 			return (ENXIO);
    444 		}
    445 		if ((code & AAC_KERNEL_PANIC) != 0) {
    446 			aprint_error("%s: FATAL: controller kernel panic\n",
    447 			    sc->sc_dv.dv_xname);
    448 			return (ENXIO);
    449 		}
    450 		if ((code & AAC_UP_AND_RUNNING) != 0)
    451 			break;
    452 		DELAY(1000);
    453 	}
    454 	if (i == AAC_BOOT_TIMEOUT * 1000) {
    455 		aprint_error(
    456 		    "%s: FATAL: controller not coming ready, status %x\n",
    457 		    sc->sc_dv.dv_xname, code);
    458 		return (ENXIO);
    459 	}
    460 
    461 	if ((rv = bus_dmamap_create(sc->sc_dmat, sizeof(*sc->sc_common), 1,
    462 	    sizeof(*sc->sc_common), 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
    463 	    &sc->sc_common_dmamap)) != 0) {
    464 		aprint_error("%s: cannot create common dmamap\n",
    465 		    sc->sc_dv.dv_xname);
    466 		return (rv);
    467 	}
    468 	if ((rv = bus_dmamem_alloc(sc->sc_dmat, sizeof(*sc->sc_common),
    469 	    PAGE_SIZE, 0, &sc->sc_common_seg, 1, &nsegs,
    470 	    BUS_DMA_NOWAIT)) != 0) {
    471 		aprint_error("%s: can't allocate common structure\n",
    472 		    sc->sc_dv.dv_xname);
    473 		goto bail_out;
    474 	}
    475 	state++;
    476 	if ((rv = bus_dmamem_map(sc->sc_dmat, &sc->sc_common_seg, nsegs,
    477 	    sizeof(*sc->sc_common), (void **)&sc->sc_common, 0)) != 0) {
    478 		aprint_error("%s: can't map common structure\n",
    479 		    sc->sc_dv.dv_xname);
    480 		goto bail_out;
    481 	}
    482 	state++;
    483 	if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_common_dmamap,
    484 	    sc->sc_common, sizeof(*sc->sc_common), NULL,
    485 	    BUS_DMA_NOWAIT)) != 0) {
    486 		aprint_error("%s: cannot load common dmamap\n",
    487 		    sc->sc_dv.dv_xname);
    488 		goto bail_out;
    489 	}
    490 	state++;
    491 
    492 	memset(sc->sc_common, 0, sizeof(*sc->sc_common));
    493 
    494 	/*
    495 	 * Fill in the init structure.  This tells the adapter about the
    496 	 * physical location of various important shared data structures.
    497 	 */
    498 	ip = &sc->sc_common->ac_init;
    499 	ip->InitStructRevision = htole32(AAC_INIT_STRUCT_REVISION);
    500 
    501 	ip->AdapterFibsPhysicalAddress = htole32(sc->sc_common_seg.ds_addr +
    502 	    offsetof(struct aac_common, ac_fibs));
    503 	ip->AdapterFibsVirtualAddress = 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 	qoff = offsetof(struct aac_common, ac_qbuf) + AAC_QUEUE_ALIGN;
    530 	qoff &= ~(AAC_QUEUE_ALIGN - 1);
    531 	sc->sc_queues = (struct aac_queue_table *)((uintptr_t)sc->sc_common + qoff);
    532 	ip->CommHeaderAddress = htole32(sc->sc_common_seg.ds_addr +
    533 	    ((char *)sc->sc_queues - (char *)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, (void *)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 %zu)\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 		sc->sc_flags &= ~AAC_ONLINE;
    737 	}
    738 }
    739 
    740 /*
    741  * Take an interrupt.
    742  */
    743 int
    744 aac_intr(void *cookie)
    745 {
    746 	struct aac_softc *sc;
    747 	u_int16_t reason;
    748 	int claimed;
    749 
    750 	sc = cookie;
    751 	claimed = 0;
    752 
    753 	AAC_DPRINTF(AAC_D_INTR, ("aac_intr(%p) ", sc));
    754 
    755 	reason = AAC_GET_ISTATUS(sc);
    756 	AAC_DPRINTF(AAC_D_INTR, ("istatus 0x%04x ", reason));
    757 
    758 	/*
    759 	 * Controller wants to talk to the log.  XXX Should we defer this?
    760 	 */
    761 	if ((reason & AAC_DB_PRINTF) != 0) {
    762 		if (sc->sc_common->ac_printf[0] == '\0')
    763 			sc->sc_common->ac_printf[0] = ' ';
    764 		printf("%s: WARNING: adapter logged message:\n",
    765 			sc->sc_dv.dv_xname);
    766 		printf("%s:     %.*s", sc->sc_dv.dv_xname,
    767 			AAC_PRINTF_BUFSIZE, sc->sc_common->ac_printf);
    768 		sc->sc_common->ac_printf[0] = '\0';
    769 		AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF);
    770 		AAC_QNOTIFY(sc, AAC_DB_PRINTF);
    771 		claimed = 1;
    772 	}
    773 
    774 	/*
    775 	 * Controller has a message for us?
    776 	 */
    777 	if ((reason & AAC_DB_COMMAND_READY) != 0) {
    778 		aac_host_command(sc);
    779 		AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_READY);
    780 		claimed = 1;
    781 	}
    782 
    783 	/*
    784 	 * Controller has a response for us?
    785 	 */
    786 	if ((reason & AAC_DB_RESPONSE_READY) != 0) {
    787 		aac_host_response(sc);
    788 		AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
    789 		claimed = 1;
    790 	}
    791 
    792 	/*
    793 	 * Spurious interrupts that we don't use - reset the mask and clear
    794 	 * the interrupts.
    795 	 */
    796 	if ((reason & (AAC_DB_SYNC_COMMAND | AAC_DB_COMMAND_NOT_FULL |
    797             AAC_DB_RESPONSE_NOT_FULL)) != 0) {
    798 		AAC_UNMASK_INTERRUPTS(sc);
    799 		AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND |
    800 		    AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL);
    801 		claimed = 1;
    802 	}
    803 
    804 	return (claimed);
    805 }
    806 
    807 /*
    808  * Handle notification of one or more FIBs coming from the controller.
    809  */
    810 static void
    811 aac_host_command(struct aac_softc *sc)
    812 {
    813 	struct aac_fib *fib;
    814 	u_int32_t fib_size;
    815 
    816 	for (;;) {
    817 		if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size,
    818 		    &fib))
    819 			break;	/* nothing to do */
    820 
    821 		bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
    822 		    (char *)fib - (char *)sc->sc_common, sizeof(*fib),
    823 		    BUS_DMASYNC_POSTREAD);
    824 
    825 		switch (le16toh(fib->Header.Command)) {
    826 		case AifRequest:
    827 #ifdef notyet
    828 			aac_handle_aif(sc,
    829 			    (struct aac_aif_command *)&fib->data[0]);
    830 #endif
    831 			AAC_PRINT_FIB(sc, fib);
    832 			break;
    833 		default:
    834 			printf("%s: unknown command from controller\n",
    835 			    sc->sc_dv.dv_xname);
    836 			AAC_PRINT_FIB(sc, fib);
    837 			break;
    838 		}
    839 
    840 		bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
    841 		    (char *)fib - (char *)sc->sc_common, sizeof(*fib),
    842 		    BUS_DMASYNC_PREREAD);
    843 
    844 		if ((fib->Header.XferState == 0) ||
    845 		    (fib->Header.StructType != AAC_FIBTYPE_TFIB)) {
    846 			break; // continue; ???
    847 		}
    848 
    849 		/* XXX reply to FIBs requesting responses ?? */
    850 
    851 		/* Return the AIF/FIB to the controller */
    852 		if (le32toh(fib->Header.XferState) & AAC_FIBSTATE_FROMADAP) {
    853 			u_int16_t	size;
    854 
    855 			fib->Header.XferState |=
    856 				htole32(AAC_FIBSTATE_DONEHOST);
    857 			*(u_int32_t*)fib->data = htole32(ST_OK);
    858 
    859 			/* XXX Compute the Size field? */
    860 			size = le16toh(fib->Header.Size);
    861 			if (size > sizeof(struct aac_fib)) {
    862 				size = sizeof(struct aac_fib);
    863 				fib->Header.Size = htole16(size);
    864 			}
    865 
    866 			/*
    867 			 * Since we didn't generate this command, it can't
    868 			 * go through the normal process.
    869 			 */
    870 			aac_enqueue_response(sc,
    871 					AAC_ADAP_NORM_RESP_QUEUE, fib);
    872 		}
    873 	}
    874 }
    875 
    876 /*
    877  * Handle notification of one or more FIBs completed by the controller
    878  */
    879 static void
    880 aac_host_response(struct aac_softc *sc)
    881 {
    882 	struct aac_ccb *ac;
    883 	struct aac_fib *fib;
    884 	u_int32_t fib_size;
    885 
    886 	/*
    887 	 * Look for completed FIBs on our queue.
    888 	 */
    889 	for (;;) {
    890 		if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size,
    891 		    &fib))
    892 			break;	/* nothing to do */
    893 
    894 		bus_dmamap_sync(sc->sc_dmat, sc->sc_fibs_dmamap,
    895 		    (char *)fib - (char *)sc->sc_fibs, sizeof(*fib),
    896 		    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
    897 
    898 		if ((fib->Header.SenderData & 0x80000000) == 0) {
    899 			/* Not valid; not sent by us. */
    900 			AAC_PRINT_FIB(sc, fib);
    901 		} else {
    902 			ac = (struct aac_ccb *)((char *)sc->sc_ccbs +
    903 			    (fib->Header.SenderData & 0x7fffffff));
    904 			fib->Header.SenderData = 0;
    905 			SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_complete, ac, ac_chain);
    906 		}
    907 	}
    908 
    909 	/*
    910 	 * Deal with any completed commands.
    911 	 */
    912 	while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_complete)) != NULL) {
    913 		SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_complete, ac_chain);
    914 		ac->ac_flags |= AAC_CCB_COMPLETED;
    915 
    916 		if (ac->ac_intr != NULL)
    917 			(*ac->ac_intr)(ac);
    918 	}
    919 
    920 	/*
    921 	 * Try to submit more commands.
    922 	 */
    923 	if (! SIMPLEQ_EMPTY(&sc->sc_ccb_queue))
    924 		aac_ccb_enqueue(sc, NULL);
    925 }
    926 
    927 /*
    928  * Send a synchronous command to the controller and wait for a result.
    929  */
    930 static int
    931 aac_sync_command(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
    932 		 u_int32_t arg1, u_int32_t arg2, u_int32_t arg3, u_int32_t *sp)
    933 {
    934 	int i;
    935 	u_int32_t status;
    936 	int s;
    937 
    938 	s = splbio();
    939 
    940 	/* Populate the mailbox. */
    941 	AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3);
    942 
    943 	/* Ensure the sync command doorbell flag is cleared. */
    944 	AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
    945 
    946 	/* ... then set it to signal the adapter. */
    947 	AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND);
    948 	DELAY(AAC_SYNC_DELAY);
    949 
    950 	/* Spin waiting for the command to complete. */
    951 	for (i = 0; i < AAC_IMMEDIATE_TIMEOUT * 1000; i++) {
    952 		if (AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND)
    953 			break;
    954 		DELAY(1000);
    955 	}
    956 	if (i == AAC_IMMEDIATE_TIMEOUT * 1000) {
    957 		splx(s);
    958 		return (EIO);
    959 	}
    960 
    961 	/* Clear the completion flag. */
    962 	AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
    963 
    964 	/* Get the command status. */
    965 	status = AAC_GET_MAILBOXSTATUS(sc);
    966 	splx(s);
    967 	if (sp != NULL)
    968 		*sp = status;
    969 
    970 	return (0);	/* XXX Check command return status? */
    971 }
    972 
    973 /*
    974  * Send a synchronous FIB to the controller and wait for a result.
    975  */
    976 static int
    977 aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
    978 	     void *data, u_int16_t datasize, void *result,
    979 	     u_int16_t *resultsize)
    980 {
    981 	struct aac_fib *fib;
    982 	u_int32_t fibpa, status;
    983 
    984 	fib = &sc->sc_common->ac_sync_fib;
    985 	fibpa = sc->sc_common_seg.ds_addr +
    986 	    offsetof(struct aac_common, ac_sync_fib);
    987 
    988 	if (datasize > AAC_FIB_DATASIZE)
    989 		return (EINVAL);
    990 
    991 	/*
    992 	 * Set up the sync FIB.
    993 	 */
    994 	fib->Header.XferState = htole32(AAC_FIBSTATE_HOSTOWNED |
    995 	    AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_EMPTY | xferstate);
    996 	fib->Header.Command = htole16(command);
    997 	fib->Header.StructType = AAC_FIBTYPE_TFIB;
    998 	fib->Header.Size = htole16(sizeof(*fib) + datasize);
    999 	fib->Header.SenderSize = htole16(sizeof(*fib));
   1000 	fib->Header.SenderFibAddress = 0; /* not needed */
   1001 	fib->Header.ReceiverFibAddress = htole32(fibpa);
   1002 
   1003 	/*
   1004 	 * Copy in data.
   1005 	 */
   1006 	if (data != NULL) {
   1007 		memcpy(fib->data, data, datasize);
   1008 		fib->Header.XferState |=
   1009 		    htole32(AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_NORM);
   1010 	}
   1011 
   1012 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
   1013 	    (char *)fib - (char *)sc->sc_common, sizeof(*fib),
   1014 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
   1015 
   1016 	/*
   1017 	 * Give the FIB to the controller, wait for a response.
   1018 	 */
   1019 	if (aac_sync_command(sc, AAC_MONKER_SYNCFIB, fibpa, 0, 0, 0, &status))
   1020 		return (EIO);
   1021 	if (status != 1) {
   1022 		printf("%s: syncfib command %04x status %08x\n",
   1023 			sc->sc_dv.dv_xname, command, status);
   1024 	}
   1025 
   1026 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
   1027 	    (char *)fib - (char *)sc->sc_common, sizeof(*fib),
   1028 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
   1029 
   1030 	/*
   1031 	 * Copy out the result
   1032 	 */
   1033 	if (result != NULL) {
   1034 		*resultsize = le16toh(fib->Header.Size) - sizeof(fib->Header);
   1035 		memcpy(result, fib->data, *resultsize);
   1036 	}
   1037 
   1038 	return (0);
   1039 }
   1040 
   1041 struct aac_ccb *
   1042 aac_ccb_alloc(struct aac_softc *sc, int flags)
   1043 {
   1044 	struct aac_ccb *ac;
   1045 	int s;
   1046 
   1047 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_alloc(%p, 0x%x) ", sc, flags));
   1048 
   1049 	s = splbio();
   1050 	ac = SIMPLEQ_FIRST(&sc->sc_ccb_free);
   1051 #ifdef DIAGNOSTIC
   1052 	if (ac == NULL)
   1053 		panic("aac_ccb_get: no free CCBS");
   1054 #endif
   1055 	SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ac_chain);
   1056 	splx(s);
   1057 
   1058 	ac->ac_flags = flags;
   1059 	return (ac);
   1060 }
   1061 
   1062 void
   1063 aac_ccb_free(struct aac_softc *sc, struct aac_ccb *ac)
   1064 {
   1065 	int s;
   1066 
   1067 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_free(%p, %p) ", sc, ac));
   1068 
   1069 	ac->ac_flags = 0;
   1070 	ac->ac_intr = NULL;
   1071 	ac->ac_fib->Header.XferState = htole32(AAC_FIBSTATE_EMPTY);
   1072 	ac->ac_fib->Header.StructType = AAC_FIBTYPE_TFIB;
   1073 	ac->ac_fib->Header.Flags = 0;
   1074 	ac->ac_fib->Header.SenderSize = htole16(sizeof(*ac->ac_fib));
   1075 
   1076 #ifdef AAC_DEBUG
   1077 	/*
   1078 	 * These are duplicated in aac_ccb_submit() to cover the case where
   1079 	 * an intermediate stage may have destroyed them.  They're left
   1080 	 * initialised here for debugging purposes only.
   1081 	 */
   1082 	ac->ac_fib->Header.SenderFibAddress = htole32((u_int32_t)(intptr_t/*XXX LP64*/)ac->ac_fib);
   1083 	ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys);
   1084 #endif
   1085 
   1086 	s = splbio();
   1087 	SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ac, ac_chain);
   1088 	splx(s);
   1089 }
   1090 
   1091 int
   1092 aac_ccb_map(struct aac_softc *sc, struct aac_ccb *ac)
   1093 {
   1094 	int error;
   1095 
   1096 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_map(%p, %p) ", sc, ac));
   1097 
   1098 #ifdef DIAGNOSTIC
   1099 	if ((ac->ac_flags & AAC_CCB_MAPPED) != 0)
   1100 		panic("aac_ccb_map: already mapped");
   1101 #endif
   1102 
   1103 	error = bus_dmamap_load(sc->sc_dmat, ac->ac_dmamap_xfer, ac->ac_data,
   1104 	    ac->ac_datalen, NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
   1105 	    ((ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMA_READ : BUS_DMA_WRITE));
   1106 	if (error) {
   1107 		printf("%s: aac_ccb_map: ", sc->sc_dv.dv_xname);
   1108 		if (error == EFBIG)
   1109 			printf("more than %d DMA segs\n", AAC_MAX_SGENTRIES);
   1110 		else
   1111 			printf("error %d loading DMA map\n", error);
   1112 		return (error);
   1113 	}
   1114 
   1115 	bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen,
   1116 	    (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_PREREAD :
   1117 	    BUS_DMASYNC_PREWRITE);
   1118 
   1119 #ifdef DIAGNOSTIC
   1120 	ac->ac_flags |= AAC_CCB_MAPPED;
   1121 #endif
   1122 	return (0);
   1123 }
   1124 
   1125 void
   1126 aac_ccb_unmap(struct aac_softc *sc, struct aac_ccb *ac)
   1127 {
   1128 
   1129 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_unmap(%p, %p) ", sc, ac));
   1130 
   1131 #ifdef DIAGNOSTIC
   1132 	if ((ac->ac_flags & AAC_CCB_MAPPED) == 0)
   1133 		panic("aac_ccb_unmap: not mapped");
   1134 #endif
   1135 
   1136 	bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen,
   1137 	    (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_POSTREAD :
   1138 	    BUS_DMASYNC_POSTWRITE);
   1139 	bus_dmamap_unload(sc->sc_dmat, ac->ac_dmamap_xfer);
   1140 
   1141 #ifdef DIAGNOSTIC
   1142 	ac->ac_flags &= ~AAC_CCB_MAPPED;
   1143 #endif
   1144 }
   1145 
   1146 void
   1147 aac_ccb_enqueue(struct aac_softc *sc, struct aac_ccb *ac)
   1148 {
   1149 	int s;
   1150 
   1151 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_enqueue(%p, %p) ", sc, ac));
   1152 
   1153 	s = splbio();
   1154 
   1155 	if (ac != NULL)
   1156 		SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_queue, ac, ac_chain);
   1157 
   1158 	while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_queue)) != NULL) {
   1159 		if (aac_ccb_submit(sc, ac))
   1160 			break;
   1161 		SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_queue, ac_chain);
   1162 	}
   1163 
   1164 	splx(s);
   1165 }
   1166 
   1167 int
   1168 aac_ccb_submit(struct aac_softc *sc, struct aac_ccb *ac)
   1169 {
   1170 	u_int32_t	acidx;
   1171 
   1172 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_submit(%p, %p) ", sc, ac));
   1173 
   1174 	acidx = (u_int32_t) ((char *)ac - (char *)sc->sc_ccbs);
   1175 	/* Fix up the address values. */
   1176 	ac->ac_fib->Header.SenderFibAddress = htole32(acidx << 2);
   1177 	ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys);
   1178 
   1179 	/* Save a pointer to the command for speedy reverse-lookup. */
   1180 	ac->ac_fib->Header.SenderData = acidx | 0x80000000;
   1181 
   1182 	bus_dmamap_sync(sc->sc_dmat, sc->sc_fibs_dmamap,
   1183 	    (char *)ac->ac_fib - (char *)sc->sc_fibs, sizeof(*ac->ac_fib),
   1184 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
   1185 
   1186 	/* Put the FIB on the outbound queue. */
   1187 	return (aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE, ac->ac_fib));
   1188 }
   1189 
   1190 int
   1191 aac_ccb_poll(struct aac_softc *sc, struct aac_ccb *ac, int timo)
   1192 {
   1193 	int rv, s;
   1194 
   1195 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_poll(%p, %p, %d) ", sc, ac, timo));
   1196 
   1197 	s = splbio();
   1198 
   1199 	if ((rv = aac_ccb_submit(sc, ac)) != 0) {
   1200 		splx(s);
   1201 		return (rv);
   1202 	}
   1203 
   1204 	for (timo *= 1000; timo != 0; timo--) {
   1205 		aac_intr(sc);
   1206 		if ((ac->ac_flags & AAC_CCB_COMPLETED) != 0)
   1207 			break;
   1208 		DELAY(100);
   1209 	}
   1210 
   1211 	splx(s);
   1212 	return (timo == 0);
   1213 }
   1214 
   1215 /*
   1216  * Atomically insert an entry into the nominated queue, returns 0 on success
   1217  * or EBUSY if the queue is full.
   1218  *
   1219  * XXX Note that it would be more efficient to defer notifying the
   1220  * controller in the case where we may be inserting several entries in rapid
   1221  * succession, but implementing this usefully is difficult.
   1222  */
   1223 static int
   1224 aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_fib *fib)
   1225 {
   1226 	u_int32_t fib_size, fib_addr, pi, ci;
   1227 
   1228 	fib_size = le16toh(fib->Header.Size);
   1229 	fib_addr = le32toh(fib->Header.ReceiverFibAddress);
   1230 
   1231 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
   1232 	    (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
   1233 	    sizeof(sc->sc_common->ac_qbuf),
   1234 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
   1235 
   1236 	/* Get the producer/consumer indices.  */
   1237 	pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
   1238 	ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
   1239 
   1240 	/* Wrap the queue? */
   1241 	if (pi >= aac_qinfo[queue].size)
   1242 		pi = 0;
   1243 
   1244 	/* Check for queue full. */
   1245 	if ((pi + 1) == ci)
   1246 		return (EAGAIN);
   1247 
   1248 	/* Populate queue entry. */
   1249 	(sc->sc_qentries[queue] + pi)->aq_fib_size = htole32(fib_size);
   1250 	(sc->sc_qentries[queue] + pi)->aq_fib_addr = htole32(fib_addr);
   1251 
   1252 	/* Update producer index. */
   1253 	sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = htole32(pi + 1);
   1254 
   1255 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
   1256 	    (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
   1257 	    sizeof(sc->sc_common->ac_qbuf),
   1258 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
   1259 
   1260 	/* Notify the adapter if we know how. */
   1261 	if (aac_qinfo[queue].notify != 0)
   1262 		AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
   1263 
   1264 	return (0);
   1265 }
   1266 
   1267 /*
   1268  * Atomically remove one entry from the nominated queue, returns 0 on success
   1269  * or ENOENT if the queue is empty.
   1270  */
   1271 static int
   1272 aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
   1273 		struct aac_fib **fib_addr)
   1274 {
   1275 	struct aac_ccb *ac;
   1276 	u_int32_t pi, ci, idx;
   1277 	int notify;
   1278 
   1279 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
   1280 	    (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
   1281 	    sizeof(sc->sc_common->ac_qbuf),
   1282 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
   1283 
   1284 	/* Get the producer/consumer indices. */
   1285 	pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
   1286 	ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
   1287 
   1288 	/* Check for queue empty. */
   1289 	if (ci == pi)
   1290 		return (ENOENT);
   1291 
   1292 	notify = 0;
   1293 	if (ci == pi + 1)
   1294 		notify = 1;
   1295 
   1296 	/* Wrap the queue? */
   1297 	if (ci >= aac_qinfo[queue].size)
   1298 		ci = 0;
   1299 
   1300 	/* Fetch the entry. */
   1301 	*fib_size = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_size);
   1302 
   1303 	switch (queue) {
   1304 	case AAC_HOST_NORM_CMD_QUEUE:
   1305 	case AAC_HOST_HIGH_CMD_QUEUE:
   1306 		idx = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_addr);
   1307 		idx /= sizeof(struct aac_fib);
   1308 		*fib_addr = &sc->sc_common->ac_fibs[idx];
   1309 		break;
   1310 	case AAC_HOST_NORM_RESP_QUEUE:
   1311 	case AAC_HOST_HIGH_RESP_QUEUE:
   1312 		idx = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_addr);
   1313 		ac = (struct aac_ccb *) ((char *) sc->sc_ccbs + (idx >> 2));
   1314 		*fib_addr = ac->ac_fib;
   1315 		break;
   1316 	default:
   1317 		panic("Invalid queue in aac_dequeue_fib()");
   1318 		break;
   1319 	}
   1320 
   1321 	/* Update consumer index. */
   1322 	sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1;
   1323 
   1324 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
   1325 	    (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
   1326 	    sizeof(sc->sc_common->ac_qbuf),
   1327 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
   1328 
   1329 	/* If we have made the queue un-full, notify the adapter. */
   1330 	if (notify && (aac_qinfo[queue].notify != 0))
   1331 		AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
   1332 
   1333 	return (0);
   1334 }
   1335 
   1336 /*
   1337  * Put our response to an adapter-initiated fib (AIF) on the response queue.
   1338  */
   1339 static int
   1340 aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib)
   1341 {
   1342 	u_int32_t fib_size, fib_addr, pi, ci;
   1343 
   1344 	fib_size = le16toh(fib->Header.Size);
   1345 	fib_addr = fib->Header.SenderFibAddress;
   1346 	fib->Header.ReceiverFibAddress = fib_addr;
   1347 
   1348 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
   1349 	    (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
   1350 	    sizeof(sc->sc_common->ac_qbuf),
   1351 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
   1352 
   1353 	/* Get the producer/consumer indices.  */
   1354 	pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
   1355 	ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
   1356 
   1357 	/* Wrap the queue? */
   1358 	if (pi >= aac_qinfo[queue].size)
   1359 		pi = 0;
   1360 
   1361 	/* Check for queue full. */
   1362 	if ((pi + 1) == ci)
   1363 		return (EAGAIN);
   1364 
   1365 	/* Populate queue entry. */
   1366 	(sc->sc_qentries[queue] + pi)->aq_fib_size = htole32(fib_size);
   1367 	(sc->sc_qentries[queue] + pi)->aq_fib_addr = htole32(fib_addr);
   1368 
   1369 	/* Update producer index. */
   1370 	sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = htole32(pi + 1);
   1371 
   1372 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
   1373 	    (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
   1374 	    sizeof(sc->sc_common->ac_qbuf),
   1375 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
   1376 
   1377 	/* Notify the adapter if we know how. */
   1378 	if (aac_qinfo[queue].notify != 0)
   1379 		AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
   1380 
   1381 	return (0);
   1382 }
   1383 
   1384 #ifdef AAC_DEBUG
   1385 /*
   1386  * Print a FIB
   1387  */
   1388 static void
   1389 aac_print_fib(struct aac_softc *sc, struct aac_fib *fib,
   1390     const char *caller)
   1391 {
   1392 	struct aac_blockread *br;
   1393 	struct aac_blockwrite *bw;
   1394 	struct aac_sg_table *sg;
   1395 	char tbuf[512];
   1396 	int i;
   1397 
   1398 	printf("%s: FIB @ %p\n", caller, fib);
   1399 	bitmask_snprintf(le32toh(fib->Header.XferState),
   1400 	    "\20"
   1401 	    "\1HOSTOWNED"
   1402 	    "\2ADAPTEROWNED"
   1403 	    "\3INITIALISED"
   1404 	    "\4EMPTY"
   1405 	    "\5FROMPOOL"
   1406 	    "\6FROMHOST"
   1407 	    "\7FROMADAP"
   1408 	    "\10REXPECTED"
   1409 	    "\11RNOTEXPECTED"
   1410 	    "\12DONEADAP"
   1411 	    "\13DONEHOST"
   1412 	    "\14HIGH"
   1413 	    "\15NORM"
   1414 	    "\16ASYNC"
   1415 	    "\17PAGEFILEIO"
   1416 	    "\20SHUTDOWN"
   1417 	    "\21LAZYWRITE"
   1418 	    "\22ADAPMICROFIB"
   1419 	    "\23BIOSFIB"
   1420 	    "\24FAST_RESPONSE"
   1421 	    "\25APIFIB\n",
   1422 	    tbuf,
   1423 	    sizeof(tbuf));
   1424 
   1425 	printf("  XferState       %s\n", tbuf);
   1426 	printf("  Command         %d\n", le16toh(fib->Header.Command));
   1427 	printf("  StructType      %d\n", fib->Header.StructType);
   1428 	printf("  Flags           0x%x\n", fib->Header.Flags);
   1429 	printf("  Size            %d\n", le16toh(fib->Header.Size));
   1430 	printf("  SenderSize      %d\n", le16toh(fib->Header.SenderSize));
   1431 	printf("  SenderAddress   0x%x\n",
   1432 	    le32toh(fib->Header.SenderFibAddress));
   1433 	printf("  ReceiverAddress 0x%x\n",
   1434 	    le32toh(fib->Header.ReceiverFibAddress));
   1435 	printf("  SenderData      0x%x\n", fib->Header.SenderData);
   1436 
   1437 	switch (fib->Header.Command) {
   1438 	case ContainerCommand: {
   1439 		br = (struct aac_blockread *)fib->data;
   1440 		bw = (struct aac_blockwrite *)fib->data;
   1441 		sg = NULL;
   1442 
   1443 		if (le32toh(br->Command) == VM_CtBlockRead) {
   1444 			printf("  BlockRead: container %d  0x%x/%d\n",
   1445 			    le32toh(br->ContainerId), le32toh(br->BlockNumber),
   1446 			    le32toh(br->ByteCount));
   1447 			sg = &br->SgMap;
   1448 		}
   1449 		if (le32toh(bw->Command) == VM_CtBlockWrite) {
   1450 			printf("  BlockWrite: container %d  0x%x/%d (%s)\n",
   1451 			    le32toh(bw->ContainerId), le32toh(bw->BlockNumber),
   1452 			    le32toh(bw->ByteCount),
   1453 			    le32toh(bw->Stable) == CSTABLE ?
   1454 			    "stable" : "unstable");
   1455 			sg = &bw->SgMap;
   1456 		}
   1457 		if (sg != NULL) {
   1458 			printf("  %d s/g entries\n", le32toh(sg->SgCount));
   1459 			for (i = 0; i < le32toh(sg->SgCount); i++)
   1460 				printf("  0x%08x/%d\n",
   1461 				    le32toh(sg->SgEntry[i].SgAddress),
   1462 				    le32toh(sg->SgEntry[i].SgByteCount));
   1463 		}
   1464 		break;
   1465 	}
   1466 	default:
   1467 		// dump first 32 bytes of fib->data
   1468 		printf("  Raw data:");
   1469 		for (i = 0; i < 32; i++)
   1470 			printf(" %02x", fib->data[i]);
   1471 		printf("\n");
   1472 		break;
   1473 	}
   1474 }
   1475 #endif /* AAC_DEBUG */
   1476