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