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