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