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