Home | History | Annotate | Line # | Download | only in ic
aac.c revision 1.29.2.1
      1  1.29.2.1   xtraeme /*	$NetBSD: aac.c,v 1.29.2.1 2007/11/25 09:20:33 xtraeme Exp $	*/
      2       1.1        ad 
      3       1.1        ad /*-
      4  1.29.2.1   xtraeme  * Copyright (c) 2002, 2007 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.29.2.1   xtraeme __KERNEL_RCSID(0, "$NetBSD: aac.c,v 1.29.2.1 2007/11/25 09:20:33 xtraeme Exp $");
     81       1.1        ad 
     82       1.1        ad #include <sys/param.h>
     83       1.1        ad #include <sys/systm.h>
     84       1.1        ad #include <sys/buf.h>
     85       1.1        ad #include <sys/device.h>
     86       1.1        ad #include <sys/kernel.h>
     87       1.1        ad #include <sys/malloc.h>
     88       1.1        ad 
     89       1.1        ad #include <machine/bus.h>
     90       1.1        ad 
     91       1.1        ad #include <uvm/uvm_extern.h>
     92       1.1        ad 
     93       1.1        ad #include <dev/ic/aacreg.h>
     94       1.1        ad #include <dev/ic/aacvar.h>
     95       1.1        ad #include <dev/ic/aac_tables.h>
     96       1.1        ad 
     97      1.13  drochner #include "locators.h"
     98      1.13  drochner 
     99  1.29.2.1   xtraeme static int	aac_new_intr(void *);
    100  1.29.2.1   xtraeme static int	aac_alloc_commands(struct aac_softc *);
    101  1.29.2.1   xtraeme #ifdef notyet
    102  1.29.2.1   xtraeme static void	aac_free_commands(struct aac_softc *);
    103  1.29.2.1   xtraeme #endif
    104      1.12   thorpej static int	aac_check_firmware(struct aac_softc *);
    105      1.12   thorpej static void	aac_describe_controller(struct aac_softc *);
    106      1.12   thorpej static int	aac_dequeue_fib(struct aac_softc *, int, u_int32_t *,
    107      1.12   thorpej 				struct aac_fib **);
    108  1.29.2.1   xtraeme static int	aac_enqueue_fib(struct aac_softc *, int, struct aac_ccb *);
    109  1.29.2.1   xtraeme static int	aac_enqueue_response(struct aac_softc *, int, struct aac_fib *);
    110      1.12   thorpej static void	aac_host_command(struct aac_softc *);
    111      1.12   thorpej static void	aac_host_response(struct aac_softc *);
    112      1.12   thorpej static int	aac_init(struct aac_softc *);
    113      1.12   thorpej static int	aac_print(void *, const char *);
    114      1.12   thorpej static void	aac_shutdown(void *);
    115      1.12   thorpej static void	aac_startup(struct aac_softc *);
    116      1.12   thorpej static int	aac_sync_command(struct aac_softc *, u_int32_t, u_int32_t,
    117      1.12   thorpej 				 u_int32_t, u_int32_t, u_int32_t, u_int32_t *);
    118      1.12   thorpej static int	aac_sync_fib(struct aac_softc *, u_int32_t, u_int32_t, void *,
    119      1.12   thorpej 			     u_int16_t, void *, u_int16_t *);
    120       1.1        ad 
    121       1.1        ad #ifdef AAC_DEBUG
    122      1.24  jdolecek static void	aac_print_fib(struct aac_softc *, struct aac_fib *, const char *);
    123       1.1        ad #endif
    124       1.1        ad 
    125       1.1        ad /*
    126       1.1        ad  * Adapter-space FIB queue manipulation.
    127       1.1        ad  *
    128       1.1        ad  * Note that the queue implementation here is a little funky; neither the PI or
    129       1.1        ad  * CI will ever be zero.  This behaviour is a controller feature.
    130       1.1        ad  */
    131       1.1        ad static struct {
    132       1.1        ad 	int	size;
    133       1.1        ad 	int	notify;
    134       1.1        ad } const aac_qinfo[] = {
    135       1.1        ad 	{ AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL },
    136       1.1        ad 	{ AAC_HOST_HIGH_CMD_ENTRIES, 0 },
    137       1.1        ad 	{ AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY },
    138       1.1        ad 	{ AAC_ADAP_HIGH_CMD_ENTRIES, 0 },
    139       1.1        ad 	{ AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL },
    140       1.1        ad 	{ AAC_HOST_HIGH_RESP_ENTRIES, 0 },
    141       1.1        ad 	{ AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY },
    142       1.1        ad 	{ AAC_ADAP_HIGH_RESP_ENTRIES, 0 }
    143       1.1        ad };
    144       1.1        ad 
    145       1.1        ad #ifdef AAC_DEBUG
    146       1.1        ad int	aac_debug = AAC_DEBUG;
    147       1.1        ad #endif
    148       1.1        ad 
    149  1.29.2.1   xtraeme MALLOC_DEFINE(M_AACBUF, "aacbuf", "Buffers for aac(4)");
    150  1.29.2.1   xtraeme 
    151      1.12   thorpej static void	*aac_sdh;
    152       1.1        ad 
    153       1.1        ad extern struct	cfdriver aac_cd;
    154       1.1        ad 
    155       1.1        ad int
    156       1.1        ad aac_attach(struct aac_softc *sc)
    157       1.1        ad {
    158       1.1        ad 	struct aac_attach_args aaca;
    159  1.29.2.1   xtraeme 	int i, rv;
    160      1.22  drochner 	int locs[AACCF_NLOCS];
    161       1.1        ad 
    162       1.1        ad 	SIMPLEQ_INIT(&sc->sc_ccb_free);
    163       1.1        ad 	SIMPLEQ_INIT(&sc->sc_ccb_queue);
    164       1.1        ad 	SIMPLEQ_INIT(&sc->sc_ccb_complete);
    165       1.1        ad 
    166       1.1        ad 	/*
    167       1.1        ad 	 * Disable interrupts before we do anything.
    168       1.1        ad 	 */
    169       1.1        ad 	AAC_MASK_INTERRUPTS(sc);
    170       1.1        ad 
    171       1.1        ad 	/*
    172       1.1        ad 	 * Initialise the adapter.
    173       1.1        ad 	 */
    174       1.1        ad 	if (aac_check_firmware(sc))
    175       1.1        ad 		return (EINVAL);
    176       1.1        ad 
    177       1.1        ad 	if ((rv = aac_init(sc)) != 0)
    178       1.1        ad 		return (rv);
    179  1.29.2.1   xtraeme 
    180  1.29.2.1   xtraeme 	if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) {
    181  1.29.2.1   xtraeme 		rv = sc->sc_intr_set(sc, aac_new_intr, sc);
    182  1.29.2.1   xtraeme 		if (rv)
    183  1.29.2.1   xtraeme 			return (rv);
    184  1.29.2.1   xtraeme 	}
    185  1.29.2.1   xtraeme 
    186       1.1        ad 	aac_startup(sc);
    187       1.1        ad 
    188      1.16     perry 	/*
    189       1.1        ad 	 * Print a little information about the controller.
    190       1.1        ad 	 */
    191       1.1        ad 	aac_describe_controller(sc);
    192       1.1        ad 
    193       1.1        ad 	/*
    194  1.29.2.1   xtraeme 	 * Attach devices.
    195       1.1        ad 	 */
    196  1.29.2.1   xtraeme 	for (i = 0; i < AAC_MAX_CONTAINERS; i++) {
    197  1.29.2.1   xtraeme 		if (!sc->sc_hdr[i].hd_present)
    198  1.29.2.1   xtraeme 			continue;
    199  1.29.2.1   xtraeme 		aaca.aaca_unit = i;
    200  1.29.2.1   xtraeme 
    201  1.29.2.1   xtraeme 		locs[AACCF_UNIT] = i;
    202  1.29.2.1   xtraeme 
    203  1.29.2.1   xtraeme 		config_found_sm_loc(&sc->sc_dv, "aac", locs, &aaca,
    204  1.29.2.1   xtraeme 				    aac_print, config_stdsubmatch);
    205       1.1        ad 	}
    206       1.1        ad 
    207  1.29.2.1   xtraeme 	/*
    208  1.29.2.1   xtraeme 	 * Enable interrupts, and register our shutdown hook.
    209  1.29.2.1   xtraeme 	 */
    210  1.29.2.1   xtraeme 	sc->sc_flags |= AAC_ONLINE;
    211  1.29.2.1   xtraeme 	AAC_UNMASK_INTERRUPTS(sc);
    212  1.29.2.1   xtraeme 	if (aac_sdh != NULL)
    213  1.29.2.1   xtraeme 		shutdownhook_establish(aac_shutdown, NULL);
    214  1.29.2.1   xtraeme 	return (0);
    215  1.29.2.1   xtraeme }
    216  1.29.2.1   xtraeme 
    217  1.29.2.1   xtraeme static int
    218  1.29.2.1   xtraeme aac_alloc_commands(struct aac_softc *sc)
    219  1.29.2.1   xtraeme {
    220  1.29.2.1   xtraeme 	struct aac_fibmap *fm;
    221  1.29.2.1   xtraeme 	struct aac_ccb *ac;
    222  1.29.2.1   xtraeme 	bus_addr_t fibpa;
    223  1.29.2.1   xtraeme 	int size, nsegs;
    224  1.29.2.1   xtraeme 	int i, error;
    225  1.29.2.1   xtraeme 	int state;
    226  1.29.2.1   xtraeme 
    227  1.29.2.1   xtraeme 	if (sc->sc_total_fibs + sc->sc_max_fibs_alloc > sc->sc_max_fibs)
    228  1.29.2.1   xtraeme 		return ENOMEM;
    229  1.29.2.1   xtraeme 
    230  1.29.2.1   xtraeme 	fm = malloc(sizeof(struct aac_fibmap), M_AACBUF, M_NOWAIT|M_ZERO);
    231  1.29.2.1   xtraeme 	if (fm == NULL)
    232  1.29.2.1   xtraeme 		return ENOMEM;
    233  1.29.2.1   xtraeme 
    234  1.29.2.1   xtraeme 	size = sc->sc_max_fibs_alloc * sc->sc_max_fib_size;
    235  1.29.2.1   xtraeme 
    236  1.29.2.1   xtraeme 	state = 0;
    237  1.29.2.1   xtraeme 	error = bus_dmamap_create(sc->sc_dmat, size, 1, size,
    238  1.29.2.1   xtraeme 	    0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &fm->fm_fibmap);
    239  1.29.2.1   xtraeme 	if (error != 0) {
    240  1.29.2.1   xtraeme 		aprint_error("%s: cannot create fibs dmamap (%d)\n",
    241  1.29.2.1   xtraeme 		    sc->sc_dv.dv_xname, error);
    242       1.1        ad 		goto bail_out;
    243       1.1        ad 	}
    244       1.1        ad 	state++;
    245  1.29.2.1   xtraeme 	error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0,
    246  1.29.2.1   xtraeme 	    &fm->fm_fibseg, 1, &nsegs, BUS_DMA_NOWAIT);
    247  1.29.2.1   xtraeme 	if (error != 0) {
    248  1.29.2.1   xtraeme 		aprint_error("%s: can't allocate fibs structure (%d)\n",
    249  1.29.2.1   xtraeme 		    sc->sc_dv.dv_xname, error);
    250       1.1        ad 		goto bail_out;
    251       1.1        ad 	}
    252       1.1        ad 	state++;
    253  1.29.2.1   xtraeme 	error = bus_dmamem_map(sc->sc_dmat, &fm->fm_fibseg, nsegs, size,
    254  1.29.2.1   xtraeme 	    (caddr_t *) &fm->fm_fibs, 0);
    255  1.29.2.1   xtraeme 	if (error != 0) {
    256  1.29.2.1   xtraeme 		aprint_error("%s: can't map fibs structure (%d)\n",
    257  1.29.2.1   xtraeme 		    sc->sc_dv.dv_xname, error);
    258       1.1        ad 		goto bail_out;
    259       1.1        ad 	}
    260       1.1        ad 	state++;
    261  1.29.2.1   xtraeme 	error = bus_dmamap_load(sc->sc_dmat, fm->fm_fibmap, fm->fm_fibs,
    262  1.29.2.1   xtraeme 	    size, NULL, BUS_DMA_NOWAIT);
    263  1.29.2.1   xtraeme 	if (error != 0) {
    264  1.29.2.1   xtraeme 		aprint_error("%s: cannot load fibs dmamap (%d)\n",
    265  1.29.2.1   xtraeme 		    sc->sc_dv.dv_xname, error);
    266       1.1        ad 		goto bail_out;
    267       1.1        ad 	}
    268       1.1        ad 
    269  1.29.2.1   xtraeme 	fm->fm_ccbs = sc->sc_ccbs + sc->sc_total_fibs;
    270  1.29.2.1   xtraeme 	fibpa = fm->fm_fibseg.ds_addr;
    271  1.29.2.1   xtraeme 
    272  1.29.2.1   xtraeme 	memset(fm->fm_fibs, 0, size);
    273  1.29.2.1   xtraeme 	for (i = 0; i < sc->sc_max_fibs_alloc; i++) {
    274  1.29.2.1   xtraeme 		ac = fm->fm_ccbs + i;
    275  1.29.2.1   xtraeme 
    276  1.29.2.1   xtraeme 		error = bus_dmamap_create(sc->sc_dmat, AAC_MAX_XFER(sc),
    277  1.29.2.1   xtraeme 		    sc->sc_max_sgs, AAC_MAX_XFER(sc), 0,
    278       1.1        ad 		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ac->ac_dmamap_xfer);
    279  1.29.2.1   xtraeme 		if (error) {
    280  1.29.2.1   xtraeme 			while (--i >= 0) {
    281  1.29.2.1   xtraeme 				ac = fm->fm_ccbs + i;
    282       1.1        ad 				bus_dmamap_destroy(sc->sc_dmat,
    283       1.1        ad 				    ac->ac_dmamap_xfer);
    284  1.29.2.1   xtraeme 				sc->sc_total_fibs--;
    285  1.29.2.1   xtraeme 			}
    286       1.8   thorpej 			aprint_error("%s: cannot create ccb dmamap (%d)",
    287  1.29.2.1   xtraeme 			    sc->sc_dv.dv_xname, error);
    288       1.1        ad 			goto bail_out;
    289       1.1        ad 		}
    290       1.1        ad 
    291  1.29.2.1   xtraeme 		ac->ac_fibmap = fm;
    292  1.29.2.1   xtraeme 		ac->ac_fib = (struct aac_fib *)
    293  1.29.2.1   xtraeme 		    ((char *) fm->fm_fibs + i * sc->sc_max_fib_size);
    294  1.29.2.1   xtraeme 		ac->ac_fibphys = fibpa + i * sc->sc_max_fib_size;
    295       1.1        ad 		aac_ccb_free(sc, ac);
    296  1.29.2.1   xtraeme 		sc->sc_total_fibs++;
    297       1.1        ad 	}
    298       1.1        ad 
    299  1.29.2.1   xtraeme 	TAILQ_INSERT_TAIL(&sc->sc_fibmap_tqh, fm, fm_link);
    300      1.13  drochner 
    301  1.29.2.1   xtraeme 	return 0;
    302  1.29.2.1   xtraeme bail_out:
    303  1.29.2.1   xtraeme 	if (state > 3)
    304  1.29.2.1   xtraeme 		bus_dmamap_unload(sc->sc_dmat, fm->fm_fibmap);
    305  1.29.2.1   xtraeme 	if (state > 2)
    306  1.29.2.1   xtraeme 		bus_dmamem_unmap(sc->sc_dmat, (void *) fm->fm_fibs, size);
    307  1.29.2.1   xtraeme 	if (state > 1)
    308  1.29.2.1   xtraeme 		bus_dmamem_free(sc->sc_dmat, &fm->fm_fibseg, 1);
    309       1.1        ad 
    310  1.29.2.1   xtraeme 	bus_dmamap_destroy(sc->sc_dmat, fm->fm_fibmap);
    311       1.1        ad 
    312  1.29.2.1   xtraeme 	free(fm, M_AACBUF);
    313       1.1        ad 
    314  1.29.2.1   xtraeme 	return error;
    315  1.29.2.1   xtraeme }
    316       1.1        ad 
    317  1.29.2.1   xtraeme #ifdef notyet
    318  1.29.2.1   xtraeme static void
    319  1.29.2.1   xtraeme aac_free_commands(struct aac_softc *sc)
    320  1.29.2.1   xtraeme {
    321       1.1        ad }
    322  1.29.2.1   xtraeme #endif
    323       1.1        ad 
    324       1.1        ad /*
    325       1.1        ad  * Print autoconfiguration message for a sub-device.
    326       1.1        ad  */
    327      1.12   thorpej static int
    328       1.1        ad aac_print(void *aux, const char *pnp)
    329       1.1        ad {
    330       1.1        ad 	struct aac_attach_args *aaca;
    331       1.1        ad 
    332       1.1        ad 	aaca = aux;
    333       1.1        ad 
    334       1.1        ad 	if (pnp != NULL)
    335       1.7   thorpej 		aprint_normal("block device at %s", pnp);
    336       1.7   thorpej 	aprint_normal(" unit %d", aaca->aaca_unit);
    337       1.1        ad 	return (UNCONF);
    338       1.1        ad }
    339       1.1        ad 
    340       1.1        ad /*
    341       1.1        ad  * Look up a text description of a numeric error code and return a pointer to
    342       1.1        ad  * same.
    343       1.1        ad  */
    344       1.1        ad const char *
    345       1.1        ad aac_describe_code(const struct aac_code_lookup *table, u_int32_t code)
    346       1.1        ad {
    347       1.1        ad 	int i;
    348       1.1        ad 
    349       1.1        ad 	for (i = 0; table[i].string != NULL; i++)
    350       1.1        ad 		if (table[i].code == code)
    351       1.1        ad 			return (table[i].string);
    352       1.1        ad 
    353       1.1        ad 	return (table[i + 1].string);
    354       1.1        ad }
    355       1.1        ad 
    356      1.17    briggs /*
    357      1.17    briggs  * bitmask_snprintf(9) format string for the adapter options.
    358      1.17    briggs  */
    359      1.19  christos static const char *optfmt =
    360      1.17    briggs     "\20\1SNAPSHOT\2CLUSTERS\3WCACHE\4DATA64\5HOSTTIME\6RAID50"
    361      1.17    briggs     "\7WINDOW4GB"
    362      1.17    briggs     "\10SCSIUPGD\11SOFTERR\12NORECOND\13SGMAP64\14ALARM\15NONDASD";
    363      1.17    briggs 
    364      1.12   thorpej static void
    365       1.1        ad aac_describe_controller(struct aac_softc *sc)
    366       1.1        ad {
    367      1.17    briggs 	u_int8_t fmtbuf[256];
    368      1.19  christos 	u_int8_t tbuf[AAC_FIB_DATASIZE];
    369       1.1        ad 	u_int16_t bufsize;
    370       1.1        ad 	struct aac_adapter_info *info;
    371       1.1        ad 	u_int8_t arg;
    372       1.1        ad 
    373       1.1        ad 	arg = 0;
    374      1.19  christos 	if (aac_sync_fib(sc, RequestAdapterInfo, 0, &arg, sizeof(arg), &tbuf,
    375       1.1        ad 	    &bufsize)) {
    376       1.8   thorpej 		aprint_error("%s: RequestAdapterInfo failed\n",
    377       1.8   thorpej 		    sc->sc_dv.dv_xname);
    378       1.1        ad 		return;
    379       1.1        ad 	}
    380       1.1        ad 	if (bufsize != sizeof(*info)) {
    381       1.8   thorpej 		aprint_error("%s: "
    382      1.26       chs 		    "RequestAdapterInfo returned wrong data size (%d != %zu)\n",
    383      1.26       chs 		    sc->sc_dv.dv_xname, bufsize, sizeof(*info));
    384       1.1        ad 		return;
    385       1.1        ad 	}
    386      1.19  christos 	info = (struct aac_adapter_info *)&tbuf[0];
    387       1.1        ad 
    388      1.15    briggs 	aprint_normal("%s: %s at %dMHz, %dMB mem (%dMB cache), %s\n",
    389       1.1        ad 	    sc->sc_dv.dv_xname,
    390       1.1        ad 	    aac_describe_code(aac_cpu_variant, le32toh(info->CpuVariant)),
    391       1.1        ad 	    le32toh(info->ClockSpeed),
    392      1.15    briggs 	    le32toh(info->TotalMem) / (1024 * 1024),
    393       1.1        ad 	    le32toh(info->BufferMem) / (1024 * 1024),
    394       1.1        ad 	    aac_describe_code(aac_battery_platform,
    395      1.15    briggs 			      le32toh(info->batteryPlatform)));
    396      1.15    briggs 
    397      1.15    briggs 	aprint_verbose("%s: Kernel %d.%d-%d [Build %d], ",
    398      1.15    briggs 	    sc->sc_dv.dv_xname,
    399       1.1        ad 	    info->KernelRevision.external.comp.major,
    400       1.1        ad 	    info->KernelRevision.external.comp.minor,
    401      1.15    briggs 	    info->KernelRevision.external.comp.dash,
    402      1.15    briggs 	    info->KernelRevision.buildNumber);
    403      1.15    briggs 
    404      1.15    briggs 	aprint_verbose("Monitor %d.%d-%d [Build %d], S/N %6X\n",
    405      1.15    briggs 	    info->MonitorRevision.external.comp.major,
    406      1.15    briggs 	    info->MonitorRevision.external.comp.minor,
    407      1.15    briggs 	    info->MonitorRevision.external.comp.dash,
    408      1.15    briggs 	    info->MonitorRevision.buildNumber,
    409      1.15    briggs 	    ((u_int32_t)info->SerialNumber & 0xffffff));
    410       1.1        ad 
    411      1.17    briggs 	aprint_verbose("%s: Controller supports: %s\n",
    412      1.17    briggs 	    sc->sc_dv.dv_xname,
    413      1.17    briggs 	    bitmask_snprintf(sc->sc_supported_options, optfmt, fmtbuf,
    414      1.17    briggs 			     sizeof(fmtbuf)));
    415      1.17    briggs 
    416       1.1        ad 	/* Save the kernel revision structure for later use. */
    417       1.1        ad 	sc->sc_revision = info->KernelRevision;
    418       1.1        ad }
    419       1.1        ad 
    420       1.1        ad /*
    421       1.1        ad  * Retrieve the firmware version numbers.  Dell PERC2/QC cards with firmware
    422       1.1        ad  * version 1.x are not compatible with this driver.
    423       1.1        ad  */
    424      1.12   thorpej static int
    425       1.1        ad aac_check_firmware(struct aac_softc *sc)
    426       1.1        ad {
    427  1.29.2.1   xtraeme 	u_int32_t major, minor, opts, atusize = 0, status = 0;
    428  1.29.2.1   xtraeme 	u_int32_t calcsgs;
    429       1.1        ad 
    430       1.1        ad 	if ((sc->sc_quirks & AAC_QUIRK_PERC2QC) != 0) {
    431       1.1        ad 		if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0,
    432       1.1        ad 		    NULL)) {
    433       1.8   thorpej 			aprint_error("%s: error reading firmware version\n",
    434       1.1        ad 			    sc->sc_dv.dv_xname);
    435       1.1        ad 			return (1);
    436       1.1        ad 		}
    437       1.1        ad 
    438       1.1        ad 		/* These numbers are stored as ASCII! */
    439      1.17    briggs 		major = (AAC_GET_MAILBOX(sc, 1) & 0xff) - 0x30;
    440      1.17    briggs 		minor = (AAC_GET_MAILBOX(sc, 2) & 0xff) - 0x30;
    441       1.1        ad 		if (major == 1) {
    442       1.8   thorpej 			aprint_error(
    443       1.8   thorpej 			    "%s: firmware version %d.%d not supported.\n",
    444       1.1        ad 			    sc->sc_dv.dv_xname, major, minor);
    445       1.1        ad 			return (1);
    446       1.1        ad 		}
    447       1.1        ad 	}
    448       1.1        ad 
    449  1.29.2.1   xtraeme 	if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, &status)) {
    450  1.29.2.1   xtraeme 		if (status != AAC_SRB_STS_INVALID_REQUEST) {
    451  1.29.2.1   xtraeme 			aprint_error("%s: GETINFO failed, status 0x%08x\n",
    452  1.29.2.1   xtraeme 				     sc->sc_dv.dv_xname, status);
    453  1.29.2.1   xtraeme 			return (1);
    454  1.29.2.1   xtraeme 		}
    455  1.29.2.1   xtraeme 	} else {
    456  1.29.2.1   xtraeme 		opts = AAC_GET_MAILBOX(sc, 1);
    457  1.29.2.1   xtraeme 		atusize = AAC_GET_MAILBOX(sc, 2);
    458  1.29.2.1   xtraeme 		sc->sc_supported_options = opts;
    459  1.29.2.1   xtraeme 
    460  1.29.2.1   xtraeme 		if (((opts & AAC_SUPPORTED_4GB_WINDOW) != 0) &&
    461  1.29.2.1   xtraeme 		    ((sc->sc_quirks & AAC_QUIRK_NO4GB) == 0) )
    462  1.29.2.1   xtraeme 			sc->sc_quirks |= AAC_QUIRK_4GB_WINDOW;
    463  1.29.2.1   xtraeme 
    464  1.29.2.1   xtraeme 		if (((opts & AAC_SUPPORTED_SGMAP_HOST64) != 0) &&
    465  1.29.2.1   xtraeme 		    (sizeof(bus_addr_t) > 4)) {
    466  1.29.2.1   xtraeme 			aprint_normal("%s: Enabling 64-bit address support\n",
    467  1.29.2.1   xtraeme 				      sc->sc_dv.dv_xname);
    468  1.29.2.1   xtraeme 			sc->sc_quirks |= AAC_QUIRK_SG_64BIT;
    469  1.29.2.1   xtraeme 		}
    470  1.29.2.1   xtraeme 		if ((opts & AAC_SUPPORTED_NEW_COMM) &&
    471  1.29.2.1   xtraeme 		    (sc->sc_if.aif_send_command != NULL)) {
    472  1.29.2.1   xtraeme 			sc->sc_quirks |= AAC_QUIRK_NEW_COMM;
    473  1.29.2.1   xtraeme 		}
    474  1.29.2.1   xtraeme #ifdef notyet
    475  1.29.2.1   xtraeme 		if (opts & AAC_SUPPORTED_64BIT_ARRAYSIZE)
    476  1.29.2.1   xtraeme 			sc->sc_quirks |= AAC_QUIRK_ARRAY_64BIT;
    477  1.29.2.1   xtraeme #endif
    478  1.29.2.1   xtraeme 	}
    479  1.29.2.1   xtraeme 
    480  1.29.2.1   xtraeme 	sc->sc_max_fibs = (sc->sc_quirks & AAC_QUIRK_256FIBS) ? 256 : 512;
    481  1.29.2.1   xtraeme 
    482  1.29.2.1   xtraeme 	if (   (sc->sc_quirks & AAC_QUIRK_NEW_COMM)
    483  1.29.2.1   xtraeme 	    && (sc->sc_regsize < atusize)) {
    484  1.29.2.1   xtraeme 		aprint_error("%s: Not enabling new comm i/f -- "
    485  1.29.2.1   xtraeme 			     "atusize 0x%08x, regsize 0x%08x\n",
    486  1.29.2.1   xtraeme 			     sc->sc_dv.dv_xname, atusize,
    487  1.29.2.1   xtraeme 			     (u_int32_t) sc->sc_regsize);
    488  1.29.2.1   xtraeme 		sc->sc_quirks &= ~AAC_QUIRK_NEW_COMM;
    489  1.29.2.1   xtraeme 	}
    490  1.29.2.1   xtraeme #if 0
    491  1.29.2.1   xtraeme 	if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) {
    492  1.29.2.1   xtraeme 		aprint_error("%s: Not enabling new comm i/f -- "
    493  1.29.2.1   xtraeme 			     "driver not ready yet\n",
    494  1.29.2.1   xtraeme 			     sc->sc_dv.dv_xname);
    495  1.29.2.1   xtraeme 		sc->sc_quirks &= ~AAC_QUIRK_NEW_COMM;
    496      1.17    briggs 	}
    497  1.29.2.1   xtraeme #endif
    498      1.17    briggs 
    499  1.29.2.1   xtraeme 	sc->sc_max_fib_size = sizeof(struct aac_fib);
    500  1.29.2.1   xtraeme 	sc->sc_max_sectors = 128;	/* 64KB */
    501  1.29.2.1   xtraeme 	if (sc->sc_quirks & AAC_QUIRK_SG_64BIT)
    502  1.29.2.1   xtraeme 		sc->sc_max_sgs = (sc->sc_max_fib_size
    503  1.29.2.1   xtraeme 					- sizeof(struct aac_blockwrite64)
    504  1.29.2.1   xtraeme 					+ sizeof(struct aac_sg_table64))
    505  1.29.2.1   xtraeme 				      / sizeof(struct aac_sg_table64);
    506  1.29.2.1   xtraeme 	else
    507  1.29.2.1   xtraeme 		sc->sc_max_sgs = (sc->sc_max_fib_size
    508  1.29.2.1   xtraeme 					- sizeof(struct aac_blockwrite)
    509  1.29.2.1   xtraeme 					+ sizeof(struct aac_sg_table))
    510  1.29.2.1   xtraeme 				      / sizeof(struct aac_sg_table);
    511  1.29.2.1   xtraeme 
    512  1.29.2.1   xtraeme 	if (!aac_sync_command(sc, AAC_MONKER_GETCOMMPREF, 0, 0, 0, 0, NULL)) {
    513  1.29.2.1   xtraeme 		u_int32_t	opt1, opt2, opt3;
    514  1.29.2.1   xtraeme 		u_int32_t	tmpval;
    515  1.29.2.1   xtraeme 
    516  1.29.2.1   xtraeme 		opt1 = AAC_GET_MAILBOX(sc, 1);
    517  1.29.2.1   xtraeme 		opt2 = AAC_GET_MAILBOX(sc, 2);
    518  1.29.2.1   xtraeme 		opt3 = AAC_GET_MAILBOX(sc, 3);
    519  1.29.2.1   xtraeme 		if (!opt1 || !opt2 || !opt3) {
    520  1.29.2.1   xtraeme 			aprint_verbose("%s: GETCOMMPREF appears untrustworthy."
    521  1.29.2.1   xtraeme 			    "  Ignoring.\n", sc->sc_dv.dv_xname);
    522  1.29.2.1   xtraeme 		} else {
    523  1.29.2.1   xtraeme 			sc->sc_max_fib_size = le32toh(opt1) & 0xffff;
    524  1.29.2.1   xtraeme 			sc->sc_max_sectors = (le32toh(opt1) >> 16) << 1;
    525  1.29.2.1   xtraeme 			tmpval = (le32toh(opt2) >> 16);
    526  1.29.2.1   xtraeme 			if (tmpval < sc->sc_max_sgs) {
    527  1.29.2.1   xtraeme 				sc->sc_max_sgs = tmpval;
    528  1.29.2.1   xtraeme 			}
    529  1.29.2.1   xtraeme 			tmpval = (le32toh(opt3) & 0xffff);
    530  1.29.2.1   xtraeme 			if (tmpval < sc->sc_max_fibs) {
    531  1.29.2.1   xtraeme 				sc->sc_max_fibs = tmpval;
    532  1.29.2.1   xtraeme 			}
    533  1.29.2.1   xtraeme 		}
    534  1.29.2.1   xtraeme 	}
    535  1.29.2.1   xtraeme 	if (sc->sc_max_fib_size > PAGE_SIZE)
    536  1.29.2.1   xtraeme 		sc->sc_max_fib_size = PAGE_SIZE;
    537  1.29.2.1   xtraeme 
    538  1.29.2.1   xtraeme 	if (sc->sc_quirks & AAC_QUIRK_SG_64BIT)
    539  1.29.2.1   xtraeme 		calcsgs = (sc->sc_max_fib_size
    540  1.29.2.1   xtraeme 			   - sizeof(struct aac_blockwrite64)
    541  1.29.2.1   xtraeme 			   + sizeof(struct aac_sg_table64))
    542  1.29.2.1   xtraeme 			      / sizeof(struct aac_sg_table64);
    543  1.29.2.1   xtraeme 	else
    544  1.29.2.1   xtraeme 		calcsgs = (sc->sc_max_fib_size
    545  1.29.2.1   xtraeme 			   - sizeof(struct aac_blockwrite)
    546  1.29.2.1   xtraeme 			   + sizeof(struct aac_sg_table))
    547  1.29.2.1   xtraeme 			      / sizeof(struct aac_sg_table);
    548  1.29.2.1   xtraeme 
    549  1.29.2.1   xtraeme 	if (calcsgs < sc->sc_max_sgs) {
    550  1.29.2.1   xtraeme 		sc->sc_max_sgs = calcsgs;
    551  1.29.2.1   xtraeme 	}
    552  1.29.2.1   xtraeme 
    553  1.29.2.1   xtraeme 	sc->sc_max_fibs_alloc = PAGE_SIZE / sc->sc_max_fib_size;
    554      1.17    briggs 
    555       1.1        ad 	return (0);
    556       1.1        ad }
    557       1.1        ad 
    558      1.12   thorpej static int
    559       1.1        ad aac_init(struct aac_softc *sc)
    560       1.1        ad {
    561       1.1        ad 	int nsegs, i, rv, state, norm, high;
    562       1.1        ad 	struct aac_adapter_init	*ip;
    563      1.21     darcy 	u_int32_t code, qoff;
    564       1.1        ad 
    565       1.1        ad 	state = 0;
    566       1.1        ad 
    567       1.1        ad 	/*
    568       1.1        ad 	 * First wait for the adapter to come ready.
    569       1.1        ad 	 */
    570       1.1        ad 	for (i = 0; i < AAC_BOOT_TIMEOUT * 1000; i++) {
    571       1.1        ad 		code = AAC_GET_FWSTATUS(sc);
    572       1.1        ad 		if ((code & AAC_SELF_TEST_FAILED) != 0) {
    573       1.8   thorpej 			aprint_error("%s: FATAL: selftest failed\n",
    574       1.1        ad 			    sc->sc_dv.dv_xname);
    575       1.1        ad 			return (ENXIO);
    576       1.1        ad 		}
    577       1.1        ad 		if ((code & AAC_KERNEL_PANIC) != 0) {
    578       1.8   thorpej 			aprint_error("%s: FATAL: controller kernel panic\n",
    579       1.1        ad 			    sc->sc_dv.dv_xname);
    580       1.1        ad 			return (ENXIO);
    581       1.1        ad 		}
    582       1.1        ad 		if ((code & AAC_UP_AND_RUNNING) != 0)
    583       1.1        ad 			break;
    584       1.1        ad 		DELAY(1000);
    585       1.1        ad 	}
    586       1.1        ad 	if (i == AAC_BOOT_TIMEOUT * 1000) {
    587       1.8   thorpej 		aprint_error(
    588       1.8   thorpej 		    "%s: FATAL: controller not coming ready, status %x\n",
    589       1.1        ad 		    sc->sc_dv.dv_xname, code);
    590       1.1        ad 		return (ENXIO);
    591       1.1        ad 	}
    592       1.1        ad 
    593  1.29.2.1   xtraeme 	sc->sc_aif_fib = malloc(sizeof(struct aac_fib), M_AACBUF,
    594  1.29.2.1   xtraeme 	    M_NOWAIT | M_ZERO);
    595  1.29.2.1   xtraeme 	if (sc->sc_aif_fib == NULL) {
    596  1.29.2.1   xtraeme 		aprint_error("%s: cannot alloc fib structure\n",
    597  1.29.2.1   xtraeme 		    sc->sc_dv.dv_xname);
    598  1.29.2.1   xtraeme 		return (ENOMEM);
    599  1.29.2.1   xtraeme 	}
    600       1.1        ad 	if ((rv = bus_dmamap_create(sc->sc_dmat, sizeof(*sc->sc_common), 1,
    601       1.1        ad 	    sizeof(*sc->sc_common), 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
    602       1.1        ad 	    &sc->sc_common_dmamap)) != 0) {
    603       1.8   thorpej 		aprint_error("%s: cannot create common dmamap\n",
    604       1.1        ad 		    sc->sc_dv.dv_xname);
    605  1.29.2.1   xtraeme 		goto bail_out;
    606       1.1        ad 	}
    607  1.29.2.1   xtraeme 	state++;
    608       1.1        ad 	if ((rv = bus_dmamem_alloc(sc->sc_dmat, sizeof(*sc->sc_common),
    609       1.1        ad 	    PAGE_SIZE, 0, &sc->sc_common_seg, 1, &nsegs,
    610       1.1        ad 	    BUS_DMA_NOWAIT)) != 0) {
    611       1.8   thorpej 		aprint_error("%s: can't allocate common structure\n",
    612       1.1        ad 		    sc->sc_dv.dv_xname);
    613       1.1        ad 		goto bail_out;
    614       1.1        ad 	}
    615       1.1        ad 	state++;
    616       1.1        ad 	if ((rv = bus_dmamem_map(sc->sc_dmat, &sc->sc_common_seg, nsegs,
    617  1.29.2.1   xtraeme 	    sizeof(*sc->sc_common), (caddr_t *) &sc->sc_common, 0)) != 0) {
    618       1.8   thorpej 		aprint_error("%s: can't map common structure\n",
    619       1.1        ad 		    sc->sc_dv.dv_xname);
    620       1.1        ad 		goto bail_out;
    621       1.1        ad 	}
    622       1.1        ad 	state++;
    623       1.1        ad 	if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_common_dmamap,
    624       1.1        ad 	    sc->sc_common, sizeof(*sc->sc_common), NULL,
    625       1.1        ad 	    BUS_DMA_NOWAIT)) != 0) {
    626       1.8   thorpej 		aprint_error("%s: cannot load common dmamap\n",
    627       1.8   thorpej 		    sc->sc_dv.dv_xname);
    628       1.1        ad 		goto bail_out;
    629       1.1        ad 	}
    630       1.1        ad 	state++;
    631       1.1        ad 
    632       1.1        ad 	memset(sc->sc_common, 0, sizeof(*sc->sc_common));
    633       1.1        ad 
    634  1.29.2.1   xtraeme 	TAILQ_INIT(&sc->sc_fibmap_tqh);
    635  1.29.2.1   xtraeme 	sc->sc_ccbs = malloc(sizeof(struct aac_ccb) * sc->sc_max_fibs, M_AACBUF,
    636  1.29.2.1   xtraeme 	    M_NOWAIT | M_ZERO);
    637  1.29.2.1   xtraeme 	if (sc->sc_ccbs == NULL) {
    638  1.29.2.1   xtraeme 		aprint_error("%s: memory allocation failure getting ccbs\n",
    639  1.29.2.1   xtraeme 		    sc->sc_dv.dv_xname);
    640  1.29.2.1   xtraeme 		rv = ENOMEM;
    641  1.29.2.1   xtraeme 		goto bail_out;
    642  1.29.2.1   xtraeme 	}
    643  1.29.2.1   xtraeme 	state++;
    644  1.29.2.1   xtraeme 	while (sc->sc_total_fibs < AAC_PREALLOCATE_FIBS(sc)) {
    645  1.29.2.1   xtraeme 		if (aac_alloc_commands(sc) != 0)
    646  1.29.2.1   xtraeme 			break;
    647  1.29.2.1   xtraeme 	}
    648  1.29.2.1   xtraeme 	if (sc->sc_total_fibs == 0)
    649  1.29.2.1   xtraeme 		goto bail_out;
    650  1.29.2.1   xtraeme 
    651       1.1        ad 	/*
    652       1.1        ad 	 * Fill in the init structure.  This tells the adapter about the
    653       1.1        ad 	 * physical location of various important shared data structures.
    654       1.1        ad 	 */
    655       1.1        ad 	ip = &sc->sc_common->ac_init;
    656       1.1        ad 	ip->InitStructRevision = htole32(AAC_INIT_STRUCT_REVISION);
    657  1.29.2.1   xtraeme 	if (sc->sc_max_fib_size > sizeof(struct aac_fib)) {
    658  1.29.2.1   xtraeme 		ip->InitStructRevision = htole32(AAC_INIT_STRUCT_REVISION_4);
    659  1.29.2.1   xtraeme 		sc->sc_quirks |= AAC_QUIRK_RAW_IO;
    660  1.29.2.1   xtraeme 	}
    661  1.29.2.1   xtraeme 	ip->MiniPortRevision = htole32(AAC_INIT_STRUCT_MINIPORT_REVISION);
    662       1.1        ad 
    663       1.1        ad 	ip->AdapterFibsPhysicalAddress = htole32(sc->sc_common_seg.ds_addr +
    664       1.1        ad 	    offsetof(struct aac_common, ac_fibs));
    665  1.29.2.1   xtraeme 	ip->AdapterFibsVirtualAddress = 0;
    666       1.1        ad 	ip->AdapterFibsSize =
    667       1.1        ad 	    htole32(AAC_ADAPTER_FIBS * sizeof(struct aac_fib));
    668       1.1        ad 	ip->AdapterFibAlign = htole32(sizeof(struct aac_fib));
    669       1.1        ad 
    670       1.1        ad 	ip->PrintfBufferAddress = htole32(sc->sc_common_seg.ds_addr +
    671       1.1        ad 	    offsetof(struct aac_common, ac_printf));
    672       1.1        ad 	ip->PrintfBufferSize = htole32(AAC_PRINTF_BUFSIZE);
    673       1.1        ad 
    674  1.29.2.1   xtraeme 	/*
    675  1.29.2.1   xtraeme 	 * The adapter assumes that pages are 4K in size, except on some
    676  1.29.2.1   xtraeme 	 * broken firmware versions that do the page->byte conversion twice,
    677  1.29.2.1   xtraeme 	 * therefore 'assuming' that this value is in 16MB units (2^24).
    678  1.29.2.1   xtraeme 	 * Round up since the granularity is so high.
    679  1.29.2.1   xtraeme 	 */
    680  1.29.2.1   xtraeme 	ip->HostPhysMemPages = ctob(physmem) / AAC_PAGE_SIZE;
    681  1.29.2.1   xtraeme 	if (sc->sc_quirks & AAC_QUIRK_BROKEN_MMAP) {
    682  1.29.2.1   xtraeme 		ip->HostPhysMemPages =
    683  1.29.2.1   xtraeme 		    (ip->HostPhysMemPages + AAC_PAGE_SIZE) / AAC_PAGE_SIZE;
    684  1.29.2.1   xtraeme 	}
    685       1.1        ad 	ip->HostElapsedSeconds = 0;	/* reset later if invalid */
    686       1.1        ad 
    687  1.29.2.1   xtraeme 	ip->InitFlags = 0;
    688  1.29.2.1   xtraeme 	if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) {
    689  1.29.2.1   xtraeme 		ip->InitFlags = htole32(AAC_INITFLAGS_NEW_COMM_SUPPORTED);
    690  1.29.2.1   xtraeme 		aprint_normal("%s: New comm. interface enabled\n",
    691  1.29.2.1   xtraeme 				sc->sc_dv.dv_xname);
    692  1.29.2.1   xtraeme 	}
    693  1.29.2.1   xtraeme 
    694  1.29.2.1   xtraeme 	ip->MaxIoCommands = htole32(sc->sc_max_fibs);
    695  1.29.2.1   xtraeme 	ip->MaxIoSize = htole32(sc->sc_max_sectors << 9);
    696  1.29.2.1   xtraeme 	ip->MaxFibSize = htole32(sc->sc_max_fib_size);
    697  1.29.2.1   xtraeme 
    698       1.1        ad 	/*
    699       1.1        ad 	 * Initialise FIB queues.  Note that it appears that the layout of
    700       1.1        ad 	 * the indexes and the segmentation of the entries is mandated by
    701       1.1        ad 	 * the adapter, which is only told about the base of the queue index
    702       1.1        ad 	 * fields.
    703       1.1        ad 	 *
    704       1.1        ad 	 * The initial values of the indices are assumed to inform the
    705       1.1        ad 	 * adapter of the sizes of the respective queues.
    706       1.1        ad 	 *
    707       1.1        ad 	 * The Linux driver uses a much more complex scheme whereby several
    708       1.1        ad 	 * header records are kept for each queue.  We use a couple of
    709       1.1        ad 	 * generic list manipulation functions which 'know' the size of each
    710       1.1        ad 	 * list by virtue of a table.
    711       1.1        ad 	 */
    712      1.21     darcy 	qoff = offsetof(struct aac_common, ac_qbuf) + AAC_QUEUE_ALIGN;
    713      1.21     darcy 	qoff &= ~(AAC_QUEUE_ALIGN - 1);
    714      1.21     darcy 	sc->sc_queues = (struct aac_queue_table *)((uintptr_t)sc->sc_common + qoff);
    715       1.1        ad 	ip->CommHeaderAddress = htole32(sc->sc_common_seg.ds_addr +
    716  1.29.2.1   xtraeme 	    ((char *)sc->sc_queues - (char *)sc->sc_common));
    717       1.1        ad 	memset(sc->sc_queues, 0, sizeof(struct aac_queue_table));
    718       1.1        ad 
    719       1.1        ad 	norm = htole32(AAC_HOST_NORM_CMD_ENTRIES);
    720       1.1        ad 	high = htole32(AAC_HOST_HIGH_CMD_ENTRIES);
    721       1.1        ad 
    722       1.1        ad 	sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
    723       1.1        ad 	    norm;
    724       1.1        ad 	sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
    725       1.1        ad 	    norm;
    726       1.1        ad 	sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
    727       1.1        ad 	    high;
    728       1.1        ad 	sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
    729       1.1        ad 	    high;
    730       1.1        ad 
    731       1.1        ad 	norm = htole32(AAC_ADAP_NORM_CMD_ENTRIES);
    732       1.1        ad 	high = htole32(AAC_ADAP_HIGH_CMD_ENTRIES);
    733       1.1        ad 
    734       1.1        ad 	sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
    735       1.1        ad 	    norm;
    736       1.1        ad 	sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
    737       1.1        ad 	    norm;
    738       1.1        ad 	sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
    739       1.1        ad 	    high;
    740       1.1        ad 	sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
    741       1.1        ad 	    high;
    742       1.1        ad 
    743       1.1        ad 	norm = htole32(AAC_HOST_NORM_RESP_ENTRIES);
    744       1.1        ad 	high = htole32(AAC_HOST_HIGH_RESP_ENTRIES);
    745       1.1        ad 
    746       1.1        ad 	sc->sc_queues->
    747       1.1        ad 	    qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm;
    748       1.1        ad 	sc->sc_queues->
    749       1.1        ad 	    qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm;
    750       1.1        ad 	sc->sc_queues->
    751       1.1        ad 	    qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high;
    752       1.1        ad 	sc->sc_queues->
    753       1.1        ad 	    qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high;
    754       1.1        ad 
    755       1.1        ad 	norm = htole32(AAC_ADAP_NORM_RESP_ENTRIES);
    756       1.1        ad 	high = htole32(AAC_ADAP_HIGH_RESP_ENTRIES);
    757       1.1        ad 
    758       1.1        ad 	sc->sc_queues->
    759       1.1        ad 	    qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm;
    760       1.1        ad 	sc->sc_queues->
    761       1.1        ad 	    qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm;
    762       1.1        ad 	sc->sc_queues->
    763       1.1        ad 	    qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high;
    764       1.1        ad 	sc->sc_queues->
    765       1.1        ad 	    qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high;
    766       1.1        ad 
    767       1.1        ad 	sc->sc_qentries[AAC_HOST_NORM_CMD_QUEUE] =
    768       1.1        ad 	    &sc->sc_queues->qt_HostNormCmdQueue[0];
    769       1.1        ad 	sc->sc_qentries[AAC_HOST_HIGH_CMD_QUEUE] =
    770       1.1        ad 	    &sc->sc_queues->qt_HostHighCmdQueue[0];
    771       1.1        ad 	sc->sc_qentries[AAC_ADAP_NORM_CMD_QUEUE] =
    772       1.1        ad 	    &sc->sc_queues->qt_AdapNormCmdQueue[0];
    773       1.1        ad 	sc->sc_qentries[AAC_ADAP_HIGH_CMD_QUEUE] =
    774       1.1        ad 	    &sc->sc_queues->qt_AdapHighCmdQueue[0];
    775       1.1        ad 	sc->sc_qentries[AAC_HOST_NORM_RESP_QUEUE] =
    776       1.1        ad 	    &sc->sc_queues->qt_HostNormRespQueue[0];
    777       1.1        ad 	sc->sc_qentries[AAC_HOST_HIGH_RESP_QUEUE] =
    778       1.1        ad 	    &sc->sc_queues->qt_HostHighRespQueue[0];
    779       1.1        ad 	sc->sc_qentries[AAC_ADAP_NORM_RESP_QUEUE] =
    780       1.1        ad 	    &sc->sc_queues->qt_AdapNormRespQueue[0];
    781       1.1        ad 	sc->sc_qentries[AAC_ADAP_HIGH_RESP_QUEUE] =
    782       1.1        ad 	    &sc->sc_queues->qt_AdapHighRespQueue[0];
    783       1.1        ad 
    784       1.1        ad 	/*
    785       1.1        ad 	 * Do controller-type-specific initialisation
    786       1.1        ad 	 */
    787       1.1        ad 	switch (sc->sc_hwif) {
    788       1.1        ad 	case AAC_HWIF_I960RX:
    789       1.1        ad 		AAC_SETREG4(sc, AAC_RX_ODBR, ~0);
    790       1.1        ad 		break;
    791       1.1        ad 	}
    792       1.1        ad 
    793       1.1        ad 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 0,
    794       1.1        ad 	    sizeof(*sc->sc_common),
    795       1.1        ad 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    796       1.1        ad 
    797       1.1        ad 	/*
    798       1.1        ad 	 * Give the init structure to the controller.
    799       1.1        ad 	 */
    800      1.16     perry 	if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT,
    801       1.1        ad 	    sc->sc_common_seg.ds_addr + offsetof(struct aac_common, ac_init),
    802       1.1        ad 	    0, 0, 0, NULL)) {
    803       1.8   thorpej 		aprint_error("%s: error establishing init structure\n",
    804       1.1        ad 		    sc->sc_dv.dv_xname);
    805       1.1        ad 		rv = EIO;
    806       1.1        ad 		goto bail_out;
    807       1.1        ad 	}
    808       1.1        ad 
    809       1.1        ad 	return (0);
    810       1.1        ad 
    811       1.1        ad  bail_out:
    812  1.29.2.1   xtraeme  	if (state > 4)
    813  1.29.2.1   xtraeme  		free(sc->sc_ccbs, M_AACBUF);
    814  1.29.2.1   xtraeme  	if (state > 3)
    815       1.1        ad  		bus_dmamap_unload(sc->sc_dmat, sc->sc_common_dmamap);
    816  1.29.2.1   xtraeme 	if (state > 2)
    817  1.29.2.1   xtraeme 		bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_common,
    818       1.1        ad 		    sizeof(*sc->sc_common));
    819  1.29.2.1   xtraeme 	if (state > 1)
    820       1.1        ad 		bus_dmamem_free(sc->sc_dmat, &sc->sc_common_seg, 1);
    821  1.29.2.1   xtraeme 	if (state > 0)
    822  1.29.2.1   xtraeme 		bus_dmamap_destroy(sc->sc_dmat, sc->sc_common_dmamap);
    823  1.29.2.1   xtraeme 
    824  1.29.2.1   xtraeme 	free(sc->sc_aif_fib, M_AACBUF);
    825       1.1        ad 
    826       1.1        ad 	return (rv);
    827       1.1        ad }
    828       1.1        ad 
    829       1.1        ad /*
    830       1.1        ad  * Probe for containers, create disks.
    831       1.1        ad  */
    832      1.12   thorpej static void
    833       1.1        ad aac_startup(struct aac_softc *sc)
    834       1.1        ad {
    835       1.1        ad 	struct aac_mntinfo mi;
    836       1.1        ad 	struct aac_mntinforesponse mir;
    837       1.1        ad 	struct aac_drive *hd;
    838       1.1        ad 	u_int16_t rsize;
    839       1.1        ad 	int i;
    840       1.1        ad 
    841       1.1        ad 	/*
    842       1.1        ad 	 * Loop over possible containers.
    843       1.1        ad 	 */
    844       1.1        ad 	hd = sc->sc_hdr;
    845       1.1        ad 
    846       1.1        ad 	for (i = 0; i < AAC_MAX_CONTAINERS; i++, hd++) {
    847       1.1        ad 		/*
    848       1.1        ad 		 * Request information on this container.
    849       1.1        ad 		 */
    850      1.10        ad 		memset(&mi, 0, sizeof(mi));
    851      1.10        ad 		mi.Command = htole32(VM_NameServe);
    852      1.10        ad 		mi.MntType = htole32(FT_FILESYS);
    853       1.1        ad 		mi.MntCount = htole32(i);
    854       1.1        ad 		if (aac_sync_fib(sc, ContainerCommand, 0, &mi, sizeof(mi), &mir,
    855       1.1        ad 		    &rsize)) {
    856       1.8   thorpej 			aprint_error("%s: error probing container %d\n",
    857       1.1        ad 			    sc->sc_dv.dv_xname, i);
    858       1.1        ad 			continue;
    859       1.1        ad 		}
    860       1.1        ad 		if (rsize != sizeof(mir)) {
    861       1.8   thorpej 			aprint_error("%s: container info response wrong size "
    862      1.26       chs 			    "(%d should be %zu)\n",
    863      1.26       chs 			    sc->sc_dv.dv_xname, rsize, sizeof(mir));
    864       1.1        ad 			continue;
    865       1.1        ad 		}
    866       1.1        ad 
    867      1.16     perry 		/*
    868       1.1        ad 		 * Check container volume type for validity.  Note that many
    869       1.1        ad 		 * of the possible types may never show up.
    870       1.1        ad 		 */
    871       1.1        ad 		if (le32toh(mir.Status) != ST_OK ||
    872       1.1        ad 		    le32toh(mir.MntTable[0].VolType) == CT_NONE)
    873       1.1        ad 			continue;
    874       1.1        ad 
    875       1.1        ad 		hd->hd_present = 1;
    876       1.1        ad 		hd->hd_size = le32toh(mir.MntTable[0].Capacity);
    877       1.1        ad 		hd->hd_devtype = le32toh(mir.MntTable[0].VolType);
    878       1.1        ad 		hd->hd_size &= ~0x1f;
    879       1.1        ad 		sc->sc_nunits++;
    880       1.1        ad 	}
    881       1.1        ad }
    882       1.1        ad 
    883      1.12   thorpej static void
    884      1.29  christos aac_shutdown(void *cookie)
    885       1.1        ad {
    886       1.1        ad 	struct aac_softc *sc;
    887       1.1        ad 	struct aac_close_command cc;
    888       1.1        ad 	u_int32_t i;
    889       1.1        ad 
    890       1.1        ad 	for (i = 0; i < aac_cd.cd_ndevs; i++) {
    891       1.1        ad 		if ((sc = device_lookup(&aac_cd, i)) == NULL)
    892       1.1        ad 			continue;
    893       1.1        ad 		if ((sc->sc_flags & AAC_ONLINE) == 0)
    894       1.1        ad 			continue;
    895       1.1        ad 
    896       1.1        ad 		AAC_MASK_INTERRUPTS(sc);
    897       1.1        ad 
    898      1.16     perry 		/*
    899       1.1        ad 		 * Send a Container shutdown followed by a HostShutdown FIB
    900       1.1        ad 		 * to the controller to convince it that we don't want to
    901       1.1        ad 		 * talk to it anymore.  We've been closed and all I/O
    902       1.1        ad 		 * completed already
    903       1.1        ad 		 */
    904      1.10        ad 		memset(&cc, 0, sizeof(cc));
    905       1.1        ad 		cc.Command = htole32(VM_CloseAll);
    906       1.1        ad 		cc.ContainerId = 0xffffffff;
    907       1.1        ad 		if (aac_sync_fib(sc, ContainerCommand, 0, &cc, sizeof(cc),
    908       1.1        ad 		    NULL, NULL)) {
    909       1.1        ad 			printf("%s: unable to halt controller\n",
    910       1.1        ad 			    sc->sc_dv.dv_xname);
    911       1.1        ad 			continue;
    912       1.1        ad 		}
    913       1.1        ad 
    914       1.1        ad 		/*
    915       1.1        ad 		 * Note that issuing this command to the controller makes it
    916       1.1        ad 		 * shut down but also keeps it from coming back up without a
    917       1.1        ad 		 * reset of the PCI bus.
    918       1.1        ad 		 */
    919       1.1        ad 		if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN,
    920       1.1        ad 		    &i, sizeof(i), NULL, NULL))
    921       1.1        ad 			printf("%s: unable to halt controller\n",
    922       1.1        ad 			    sc->sc_dv.dv_xname);
    923      1.17    briggs 
    924      1.17    briggs 		sc->sc_flags &= ~AAC_ONLINE;
    925       1.1        ad 	}
    926       1.1        ad }
    927       1.1        ad 
    928  1.29.2.1   xtraeme static int
    929  1.29.2.1   xtraeme aac_new_intr(void *cookie)
    930  1.29.2.1   xtraeme {
    931  1.29.2.1   xtraeme 	struct aac_softc *sc;
    932  1.29.2.1   xtraeme 	u_int32_t index, fast;
    933  1.29.2.1   xtraeme 	struct aac_ccb *ac;
    934  1.29.2.1   xtraeme 	struct aac_fib *fib;
    935  1.29.2.1   xtraeme 	struct aac_fibmap *fm;
    936  1.29.2.1   xtraeme 	int i;
    937  1.29.2.1   xtraeme 
    938  1.29.2.1   xtraeme 	sc = (struct aac_softc *) cookie;
    939  1.29.2.1   xtraeme 
    940  1.29.2.1   xtraeme 	for (;;) {
    941  1.29.2.1   xtraeme 		index = AAC_GET_OUTB_QUEUE(sc);
    942  1.29.2.1   xtraeme 		if (index == 0xffffffff)
    943  1.29.2.1   xtraeme 			index = AAC_GET_OUTB_QUEUE(sc);
    944  1.29.2.1   xtraeme 		if (index == 0xffffffff)
    945  1.29.2.1   xtraeme 			break;
    946  1.29.2.1   xtraeme 		if (index & 2) {
    947  1.29.2.1   xtraeme 			if (index == 0xfffffffe) {
    948  1.29.2.1   xtraeme 				/* XXX This means that the controller wants
    949  1.29.2.1   xtraeme 				 * more work.  Ignore it for now.
    950  1.29.2.1   xtraeme 				 */
    951  1.29.2.1   xtraeme 				continue;
    952  1.29.2.1   xtraeme 			}
    953  1.29.2.1   xtraeme 			/* AIF */
    954  1.29.2.1   xtraeme 			index &= ~2;
    955  1.29.2.1   xtraeme 			fib = sc->sc_aif_fib;
    956  1.29.2.1   xtraeme 			for (i = 0; i < sizeof(struct aac_fib)/4; i++) {
    957  1.29.2.1   xtraeme 				((u_int32_t*)fib)[i] =
    958  1.29.2.1   xtraeme 				    AAC_GETREG4(sc, index + i*4);
    959  1.29.2.1   xtraeme 			}
    960  1.29.2.1   xtraeme #ifdef notyet
    961  1.29.2.1   xtraeme 			aac_handle_aif(sc, &fib);
    962  1.29.2.1   xtraeme #endif
    963  1.29.2.1   xtraeme 
    964  1.29.2.1   xtraeme 			AAC_SET_OUTB_QUEUE(sc, index);
    965  1.29.2.1   xtraeme 			AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
    966  1.29.2.1   xtraeme 		} else {
    967  1.29.2.1   xtraeme 			fast = index & 1;
    968  1.29.2.1   xtraeme 			ac = sc->sc_ccbs + (index >> 2);
    969  1.29.2.1   xtraeme 			fib = ac->ac_fib;
    970  1.29.2.1   xtraeme 			fm = ac->ac_fibmap;
    971  1.29.2.1   xtraeme 			if (fast) {
    972  1.29.2.1   xtraeme 				bus_dmamap_sync(sc->sc_dmat, fm->fm_fibmap,
    973  1.29.2.1   xtraeme 				    (char *)fib - (char *)fm->fm_fibs,
    974  1.29.2.1   xtraeme 				    sc->sc_max_fib_size,
    975  1.29.2.1   xtraeme 				    BUS_DMASYNC_POSTWRITE |
    976  1.29.2.1   xtraeme 				    BUS_DMASYNC_POSTREAD);
    977  1.29.2.1   xtraeme 				fib->Header.XferState |=
    978  1.29.2.1   xtraeme 				    htole32(AAC_FIBSTATE_DONEADAP);
    979  1.29.2.1   xtraeme 				*((u_int32_t *)(fib->data)) =
    980  1.29.2.1   xtraeme 				    htole32(AAC_ERROR_NORMAL);
    981  1.29.2.1   xtraeme 			}
    982  1.29.2.1   xtraeme 			ac->ac_flags |= AAC_CCB_COMPLETED;
    983  1.29.2.1   xtraeme 
    984  1.29.2.1   xtraeme 			if (ac->ac_intr != NULL)
    985  1.29.2.1   xtraeme 				(*ac->ac_intr)(ac);
    986  1.29.2.1   xtraeme 			else
    987  1.29.2.1   xtraeme 				wakeup(ac);
    988  1.29.2.1   xtraeme 		}
    989  1.29.2.1   xtraeme 	}
    990  1.29.2.1   xtraeme 
    991  1.29.2.1   xtraeme 	/*
    992  1.29.2.1   xtraeme 	 * Try to submit more commands.
    993  1.29.2.1   xtraeme 	 */
    994  1.29.2.1   xtraeme 	if (! SIMPLEQ_EMPTY(&sc->sc_ccb_queue))
    995  1.29.2.1   xtraeme 		aac_ccb_enqueue(sc, NULL);
    996  1.29.2.1   xtraeme 
    997  1.29.2.1   xtraeme 	return 1;
    998  1.29.2.1   xtraeme }
    999  1.29.2.1   xtraeme 
   1000       1.1        ad /*
   1001       1.1        ad  * Take an interrupt.
   1002       1.1        ad  */
   1003       1.1        ad int
   1004       1.1        ad aac_intr(void *cookie)
   1005       1.1        ad {
   1006       1.1        ad 	struct aac_softc *sc;
   1007       1.1        ad 	u_int16_t reason;
   1008       1.1        ad 	int claimed;
   1009       1.1        ad 
   1010       1.1        ad 	sc = cookie;
   1011       1.1        ad 	claimed = 0;
   1012       1.1        ad 
   1013       1.1        ad 	AAC_DPRINTF(AAC_D_INTR, ("aac_intr(%p) ", sc));
   1014       1.1        ad 
   1015       1.1        ad 	reason = AAC_GET_ISTATUS(sc);
   1016  1.29.2.1   xtraeme 	AAC_CLEAR_ISTATUS(sc, reason);
   1017  1.29.2.1   xtraeme 
   1018       1.1        ad 	AAC_DPRINTF(AAC_D_INTR, ("istatus 0x%04x ", reason));
   1019       1.1        ad 
   1020       1.1        ad 	/*
   1021       1.1        ad 	 * Controller wants to talk to the log.  XXX Should we defer this?
   1022       1.1        ad 	 */
   1023       1.1        ad 	if ((reason & AAC_DB_PRINTF) != 0) {
   1024  1.29.2.1   xtraeme 		if (sc->sc_common->ac_printf[0] == '\0')
   1025  1.29.2.1   xtraeme 			sc->sc_common->ac_printf[0] = ' ';
   1026  1.29.2.1   xtraeme 		printf("%s: WARNING: adapter logged message:\n",
   1027  1.29.2.1   xtraeme 			sc->sc_dv.dv_xname);
   1028  1.29.2.1   xtraeme 		printf("%s:     %.*s", sc->sc_dv.dv_xname,
   1029  1.29.2.1   xtraeme 			AAC_PRINTF_BUFSIZE, sc->sc_common->ac_printf);
   1030  1.29.2.1   xtraeme 		sc->sc_common->ac_printf[0] = '\0';
   1031       1.1        ad 		AAC_QNOTIFY(sc, AAC_DB_PRINTF);
   1032       1.1        ad 		claimed = 1;
   1033       1.1        ad 	}
   1034       1.1        ad 
   1035       1.1        ad 	/*
   1036       1.1        ad 	 * Controller has a message for us?
   1037       1.1        ad 	 */
   1038       1.1        ad 	if ((reason & AAC_DB_COMMAND_READY) != 0) {
   1039       1.1        ad 		aac_host_command(sc);
   1040       1.1        ad 		claimed = 1;
   1041       1.1        ad 	}
   1042       1.1        ad 
   1043       1.1        ad 	/*
   1044       1.1        ad 	 * Controller has a response for us?
   1045       1.1        ad 	 */
   1046       1.1        ad 	if ((reason & AAC_DB_RESPONSE_READY) != 0) {
   1047       1.1        ad 		aac_host_response(sc);
   1048       1.1        ad 		claimed = 1;
   1049       1.1        ad 	}
   1050       1.1        ad 
   1051       1.1        ad 	/*
   1052       1.1        ad 	 * Spurious interrupts that we don't use - reset the mask and clear
   1053       1.1        ad 	 * the interrupts.
   1054       1.1        ad 	 */
   1055       1.1        ad 	if ((reason & (AAC_DB_SYNC_COMMAND | AAC_DB_COMMAND_NOT_FULL |
   1056       1.1        ad             AAC_DB_RESPONSE_NOT_FULL)) != 0) {
   1057       1.1        ad 		AAC_UNMASK_INTERRUPTS(sc);
   1058       1.1        ad 		AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND |
   1059       1.1        ad 		    AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL);
   1060       1.1        ad 		claimed = 1;
   1061       1.1        ad 	}
   1062       1.1        ad 
   1063       1.1        ad 	return (claimed);
   1064       1.1        ad }
   1065       1.1        ad 
   1066       1.1        ad /*
   1067       1.1        ad  * Handle notification of one or more FIBs coming from the controller.
   1068       1.1        ad  */
   1069      1.12   thorpej static void
   1070       1.1        ad aac_host_command(struct aac_softc *sc)
   1071       1.1        ad {
   1072       1.1        ad 	struct aac_fib *fib;
   1073       1.1        ad 	u_int32_t fib_size;
   1074       1.1        ad 
   1075       1.1        ad 	for (;;) {
   1076       1.1        ad 		if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size,
   1077       1.1        ad 		    &fib))
   1078       1.1        ad 			break;	/* nothing to do */
   1079       1.1        ad 
   1080       1.1        ad 		bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
   1081  1.29.2.1   xtraeme 		    (char *)fib - (char *)sc->sc_common, sizeof(*fib),
   1082       1.1        ad 		    BUS_DMASYNC_POSTREAD);
   1083       1.1        ad 
   1084       1.1        ad 		switch (le16toh(fib->Header.Command)) {
   1085       1.1        ad 		case AifRequest:
   1086       1.1        ad #ifdef notyet
   1087       1.1        ad 			aac_handle_aif(sc,
   1088       1.1        ad 			    (struct aac_aif_command *)&fib->data[0]);
   1089       1.1        ad #endif
   1090  1.29.2.1   xtraeme 			AAC_PRINT_FIB(sc, fib);
   1091       1.1        ad 			break;
   1092       1.1        ad 		default:
   1093       1.1        ad 			printf("%s: unknown command from controller\n",
   1094       1.1        ad 			    sc->sc_dv.dv_xname);
   1095       1.1        ad 			AAC_PRINT_FIB(sc, fib);
   1096       1.1        ad 			break;
   1097       1.1        ad 		}
   1098       1.1        ad 
   1099       1.1        ad 		bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
   1100  1.29.2.1   xtraeme 		    (char *)fib - (char *)sc->sc_common, sizeof(*fib),
   1101       1.1        ad 		    BUS_DMASYNC_PREREAD);
   1102       1.1        ad 
   1103  1.29.2.1   xtraeme 		if ((fib->Header.XferState == 0) ||
   1104  1.29.2.1   xtraeme 		    (fib->Header.StructType != AAC_FIBTYPE_TFIB)) {
   1105  1.29.2.1   xtraeme 			break; // continue; ???
   1106  1.29.2.1   xtraeme 		}
   1107  1.29.2.1   xtraeme 
   1108       1.1        ad 		/* XXX reply to FIBs requesting responses ?? */
   1109  1.29.2.1   xtraeme 
   1110  1.29.2.1   xtraeme 		/* Return the AIF/FIB to the controller */
   1111  1.29.2.1   xtraeme 		if (le32toh(fib->Header.XferState) & AAC_FIBSTATE_FROMADAP) {
   1112  1.29.2.1   xtraeme 			u_int16_t	size;
   1113  1.29.2.1   xtraeme 
   1114  1.29.2.1   xtraeme 			fib->Header.XferState |=
   1115  1.29.2.1   xtraeme 				htole32(AAC_FIBSTATE_DONEHOST);
   1116  1.29.2.1   xtraeme 			*(u_int32_t*)fib->data = htole32(ST_OK);
   1117  1.29.2.1   xtraeme 
   1118  1.29.2.1   xtraeme 			/* XXX Compute the Size field? */
   1119  1.29.2.1   xtraeme 			size = le16toh(fib->Header.Size);
   1120  1.29.2.1   xtraeme 			if (size > sizeof(struct aac_fib)) {
   1121  1.29.2.1   xtraeme 				size = sizeof(struct aac_fib);
   1122  1.29.2.1   xtraeme 				fib->Header.Size = htole16(size);
   1123  1.29.2.1   xtraeme 			}
   1124  1.29.2.1   xtraeme 
   1125  1.29.2.1   xtraeme 			/*
   1126  1.29.2.1   xtraeme 			 * Since we didn't generate this command, it can't
   1127  1.29.2.1   xtraeme 			 * go through the normal process.
   1128  1.29.2.1   xtraeme 			 */
   1129  1.29.2.1   xtraeme 			aac_enqueue_response(sc,
   1130  1.29.2.1   xtraeme 					AAC_ADAP_NORM_RESP_QUEUE, fib);
   1131  1.29.2.1   xtraeme 		}
   1132       1.1        ad 	}
   1133       1.1        ad }
   1134       1.1        ad 
   1135       1.1        ad /*
   1136       1.1        ad  * Handle notification of one or more FIBs completed by the controller
   1137       1.1        ad  */
   1138      1.12   thorpej static void
   1139       1.1        ad aac_host_response(struct aac_softc *sc)
   1140       1.1        ad {
   1141       1.1        ad 	struct aac_ccb *ac;
   1142       1.1        ad 	struct aac_fib *fib;
   1143       1.1        ad 	u_int32_t fib_size;
   1144       1.1        ad 
   1145       1.1        ad 	/*
   1146       1.1        ad 	 * Look for completed FIBs on our queue.
   1147       1.1        ad 	 */
   1148       1.1        ad 	for (;;) {
   1149       1.1        ad 		if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size,
   1150       1.1        ad 		    &fib))
   1151       1.1        ad 			break;	/* nothing to do */
   1152       1.1        ad 
   1153       1.1        ad 		if ((fib->Header.SenderData & 0x80000000) == 0) {
   1154       1.1        ad 			/* Not valid; not sent by us. */
   1155       1.1        ad 			AAC_PRINT_FIB(sc, fib);
   1156       1.1        ad 		} else {
   1157  1.29.2.1   xtraeme 			ac = (struct aac_ccb *)(sc->sc_ccbs +
   1158       1.1        ad 			    (fib->Header.SenderData & 0x7fffffff));
   1159       1.1        ad 			fib->Header.SenderData = 0;
   1160       1.1        ad 			SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_complete, ac, ac_chain);
   1161       1.1        ad 		}
   1162       1.1        ad 	}
   1163       1.1        ad 
   1164       1.1        ad 	/*
   1165       1.1        ad 	 * Deal with any completed commands.
   1166       1.1        ad 	 */
   1167       1.1        ad 	while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_complete)) != NULL) {
   1168       1.3     lukem 		SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_complete, ac_chain);
   1169       1.1        ad 		ac->ac_flags |= AAC_CCB_COMPLETED;
   1170       1.1        ad 
   1171       1.1        ad 		if (ac->ac_intr != NULL)
   1172       1.1        ad 			(*ac->ac_intr)(ac);
   1173  1.29.2.1   xtraeme 		else
   1174  1.29.2.1   xtraeme 			wakeup(ac);
   1175       1.1        ad 	}
   1176       1.1        ad 
   1177       1.1        ad 	/*
   1178       1.1        ad 	 * Try to submit more commands.
   1179       1.1        ad 	 */
   1180       1.3     lukem 	if (! SIMPLEQ_EMPTY(&sc->sc_ccb_queue))
   1181       1.1        ad 		aac_ccb_enqueue(sc, NULL);
   1182       1.1        ad }
   1183       1.1        ad 
   1184       1.1        ad /*
   1185       1.1        ad  * Send a synchronous command to the controller and wait for a result.
   1186       1.1        ad  */
   1187      1.12   thorpej static int
   1188       1.1        ad aac_sync_command(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
   1189       1.1        ad 		 u_int32_t arg1, u_int32_t arg2, u_int32_t arg3, u_int32_t *sp)
   1190       1.1        ad {
   1191       1.1        ad 	int i;
   1192       1.1        ad 	u_int32_t status;
   1193       1.1        ad 	int s;
   1194       1.1        ad 
   1195       1.1        ad 	s = splbio();
   1196       1.1        ad 
   1197       1.1        ad 	/* Populate the mailbox. */
   1198       1.1        ad 	AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3);
   1199       1.1        ad 
   1200       1.1        ad 	/* Ensure the sync command doorbell flag is cleared. */
   1201       1.1        ad 	AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
   1202       1.1        ad 
   1203       1.1        ad 	/* ... then set it to signal the adapter. */
   1204       1.1        ad 	AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND);
   1205       1.1        ad 	DELAY(AAC_SYNC_DELAY);
   1206       1.1        ad 
   1207       1.1        ad 	/* Spin waiting for the command to complete. */
   1208       1.1        ad 	for (i = 0; i < AAC_IMMEDIATE_TIMEOUT * 1000; i++) {
   1209      1.11  christos 		if (AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND)
   1210       1.1        ad 			break;
   1211       1.1        ad 		DELAY(1000);
   1212       1.1        ad 	}
   1213       1.1        ad 	if (i == AAC_IMMEDIATE_TIMEOUT * 1000) {
   1214       1.1        ad 		splx(s);
   1215       1.1        ad 		return (EIO);
   1216       1.1        ad 	}
   1217       1.1        ad 
   1218       1.1        ad 	/* Clear the completion flag. */
   1219       1.1        ad 	AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
   1220       1.1        ad 
   1221       1.1        ad 	/* Get the command status. */
   1222       1.1        ad 	status = AAC_GET_MAILBOXSTATUS(sc);
   1223       1.1        ad 	splx(s);
   1224       1.1        ad 	if (sp != NULL)
   1225       1.1        ad 		*sp = status;
   1226       1.1        ad 
   1227       1.1        ad 	return (0);	/* XXX Check command return status? */
   1228       1.1        ad }
   1229       1.1        ad 
   1230       1.1        ad /*
   1231       1.1        ad  * Send a synchronous FIB to the controller and wait for a result.
   1232       1.1        ad  */
   1233      1.12   thorpej static int
   1234       1.1        ad aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
   1235       1.1        ad 	     void *data, u_int16_t datasize, void *result,
   1236       1.1        ad 	     u_int16_t *resultsize)
   1237       1.1        ad {
   1238       1.1        ad 	struct aac_fib *fib;
   1239       1.1        ad 	u_int32_t fibpa, status;
   1240       1.1        ad 
   1241       1.1        ad 	fib = &sc->sc_common->ac_sync_fib;
   1242       1.1        ad 	fibpa = sc->sc_common_seg.ds_addr +
   1243       1.1        ad 	    offsetof(struct aac_common, ac_sync_fib);
   1244       1.1        ad 
   1245       1.1        ad 	if (datasize > AAC_FIB_DATASIZE)
   1246       1.1        ad 		return (EINVAL);
   1247       1.1        ad 
   1248       1.1        ad 	/*
   1249       1.1        ad 	 * Set up the sync FIB.
   1250       1.1        ad 	 */
   1251       1.1        ad 	fib->Header.XferState = htole32(AAC_FIBSTATE_HOSTOWNED |
   1252       1.1        ad 	    AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_EMPTY | xferstate);
   1253       1.1        ad 	fib->Header.Command = htole16(command);
   1254       1.1        ad 	fib->Header.StructType = AAC_FIBTYPE_TFIB;
   1255       1.1        ad 	fib->Header.Size = htole16(sizeof(*fib) + datasize);
   1256       1.1        ad 	fib->Header.SenderSize = htole16(sizeof(*fib));
   1257  1.29.2.1   xtraeme 	fib->Header.SenderFibAddress = 0; /* not needed */
   1258       1.1        ad 	fib->Header.ReceiverFibAddress = htole32(fibpa);
   1259       1.1        ad 
   1260       1.1        ad 	/*
   1261       1.1        ad 	 * Copy in data.
   1262       1.1        ad 	 */
   1263       1.1        ad 	if (data != NULL) {
   1264       1.1        ad 		memcpy(fib->data, data, datasize);
   1265       1.1        ad 		fib->Header.XferState |=
   1266       1.1        ad 		    htole32(AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_NORM);
   1267       1.1        ad 	}
   1268       1.1        ad 
   1269       1.1        ad 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
   1270  1.29.2.1   xtraeme 	    (char *)fib - (char *)sc->sc_common, sizeof(*fib),
   1271       1.1        ad 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
   1272       1.1        ad 
   1273       1.1        ad 	/*
   1274       1.1        ad 	 * Give the FIB to the controller, wait for a response.
   1275       1.1        ad 	 */
   1276       1.1        ad 	if (aac_sync_command(sc, AAC_MONKER_SYNCFIB, fibpa, 0, 0, 0, &status))
   1277       1.1        ad 		return (EIO);
   1278      1.17    briggs 	if (status != 1) {
   1279      1.17    briggs 		printf("%s: syncfib command %04x status %08x\n",
   1280      1.17    briggs 			sc->sc_dv.dv_xname, command, status);
   1281      1.17    briggs 	}
   1282       1.1        ad 
   1283       1.1        ad 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
   1284  1.29.2.1   xtraeme 	    (char *)fib - (char *)sc->sc_common, sizeof(*fib),
   1285       1.1        ad 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
   1286       1.1        ad 
   1287      1.16     perry 	/*
   1288       1.1        ad 	 * Copy out the result
   1289       1.1        ad 	 */
   1290       1.1        ad 	if (result != NULL) {
   1291       1.1        ad 		*resultsize = le16toh(fib->Header.Size) - sizeof(fib->Header);
   1292       1.1        ad 		memcpy(result, fib->data, *resultsize);
   1293       1.1        ad 	}
   1294       1.1        ad 
   1295       1.1        ad 	return (0);
   1296       1.1        ad }
   1297       1.1        ad 
   1298       1.1        ad struct aac_ccb *
   1299       1.1        ad aac_ccb_alloc(struct aac_softc *sc, int flags)
   1300       1.1        ad {
   1301       1.1        ad 	struct aac_ccb *ac;
   1302       1.1        ad 	int s;
   1303       1.1        ad 
   1304       1.1        ad 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_alloc(%p, 0x%x) ", sc, flags));
   1305       1.1        ad 
   1306       1.1        ad 	s = splbio();
   1307       1.1        ad 	ac = SIMPLEQ_FIRST(&sc->sc_ccb_free);
   1308  1.29.2.1   xtraeme 	if (ac == NULL) {
   1309  1.29.2.1   xtraeme 		if (aac_alloc_commands(sc)) {
   1310  1.29.2.1   xtraeme 			splx(s);
   1311  1.29.2.1   xtraeme 			return NULL;
   1312  1.29.2.1   xtraeme 		}
   1313  1.29.2.1   xtraeme 		ac = SIMPLEQ_FIRST(&sc->sc_ccb_free);
   1314  1.29.2.1   xtraeme 	}
   1315       1.1        ad #ifdef DIAGNOSTIC
   1316       1.1        ad 	if (ac == NULL)
   1317       1.1        ad 		panic("aac_ccb_get: no free CCBS");
   1318       1.1        ad #endif
   1319       1.3     lukem 	SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ac_chain);
   1320       1.1        ad 	splx(s);
   1321       1.1        ad 
   1322       1.1        ad 	ac->ac_flags = flags;
   1323       1.1        ad 	return (ac);
   1324       1.1        ad }
   1325       1.1        ad 
   1326       1.1        ad void
   1327       1.1        ad aac_ccb_free(struct aac_softc *sc, struct aac_ccb *ac)
   1328       1.1        ad {
   1329       1.1        ad 	int s;
   1330       1.1        ad 
   1331       1.1        ad 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_free(%p, %p) ", sc, ac));
   1332       1.1        ad 
   1333       1.1        ad 	ac->ac_flags = 0;
   1334       1.1        ad 	ac->ac_intr = NULL;
   1335       1.1        ad 	ac->ac_fib->Header.XferState = htole32(AAC_FIBSTATE_EMPTY);
   1336       1.1        ad 	ac->ac_fib->Header.StructType = AAC_FIBTYPE_TFIB;
   1337       1.1        ad 	ac->ac_fib->Header.Flags = 0;
   1338  1.29.2.1   xtraeme 	ac->ac_fib->Header.SenderSize = htole16(sc->sc_max_fib_size);
   1339       1.1        ad 
   1340       1.1        ad #ifdef AAC_DEBUG
   1341      1.16     perry 	/*
   1342       1.1        ad 	 * These are duplicated in aac_ccb_submit() to cover the case where
   1343       1.1        ad 	 * an intermediate stage may have destroyed them.  They're left
   1344       1.1        ad 	 * initialised here for debugging purposes only.
   1345       1.1        ad 	 */
   1346  1.29.2.1   xtraeme 	ac->ac_fib->Header.SenderFibAddress =
   1347  1.29.2.1   xtraeme 	    htole32(((u_int32_t) (ac - sc->sc_ccbs)) << 2);
   1348       1.1        ad 	ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys);
   1349       1.1        ad #endif
   1350       1.1        ad 
   1351       1.1        ad 	s = splbio();
   1352       1.1        ad 	SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ac, ac_chain);
   1353       1.1        ad 	splx(s);
   1354       1.1        ad }
   1355       1.1        ad 
   1356       1.1        ad int
   1357       1.1        ad aac_ccb_map(struct aac_softc *sc, struct aac_ccb *ac)
   1358       1.1        ad {
   1359       1.1        ad 	int error;
   1360       1.1        ad 
   1361       1.1        ad 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_map(%p, %p) ", sc, ac));
   1362       1.1        ad 
   1363       1.1        ad #ifdef DIAGNOSTIC
   1364       1.1        ad 	if ((ac->ac_flags & AAC_CCB_MAPPED) != 0)
   1365       1.1        ad 		panic("aac_ccb_map: already mapped");
   1366       1.1        ad #endif
   1367       1.1        ad 
   1368       1.1        ad 	error = bus_dmamap_load(sc->sc_dmat, ac->ac_dmamap_xfer, ac->ac_data,
   1369       1.1        ad 	    ac->ac_datalen, NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
   1370       1.1        ad 	    ((ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMA_READ : BUS_DMA_WRITE));
   1371       1.1        ad 	if (error) {
   1372       1.1        ad 		printf("%s: aac_ccb_map: ", sc->sc_dv.dv_xname);
   1373       1.1        ad 		if (error == EFBIG)
   1374  1.29.2.1   xtraeme 			printf("more than %d DMA segs\n", sc->sc_max_sgs);
   1375       1.1        ad 		else
   1376       1.9       wiz 			printf("error %d loading DMA map\n", error);
   1377       1.1        ad 		return (error);
   1378       1.1        ad 	}
   1379       1.1        ad 
   1380       1.1        ad 	bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen,
   1381       1.1        ad 	    (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_PREREAD :
   1382       1.1        ad 	    BUS_DMASYNC_PREWRITE);
   1383       1.1        ad 
   1384       1.1        ad #ifdef DIAGNOSTIC
   1385       1.1        ad 	ac->ac_flags |= AAC_CCB_MAPPED;
   1386       1.1        ad #endif
   1387       1.1        ad 	return (0);
   1388       1.1        ad }
   1389       1.1        ad 
   1390       1.1        ad void
   1391       1.1        ad aac_ccb_unmap(struct aac_softc *sc, struct aac_ccb *ac)
   1392       1.1        ad {
   1393       1.1        ad 
   1394       1.1        ad 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_unmap(%p, %p) ", sc, ac));
   1395       1.1        ad 
   1396       1.1        ad #ifdef DIAGNOSTIC
   1397       1.1        ad 	if ((ac->ac_flags & AAC_CCB_MAPPED) == 0)
   1398       1.1        ad 		panic("aac_ccb_unmap: not mapped");
   1399       1.1        ad #endif
   1400       1.1        ad 
   1401       1.1        ad 	bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen,
   1402       1.1        ad 	    (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_POSTREAD :
   1403       1.1        ad 	    BUS_DMASYNC_POSTWRITE);
   1404       1.1        ad 	bus_dmamap_unload(sc->sc_dmat, ac->ac_dmamap_xfer);
   1405       1.1        ad 
   1406       1.1        ad #ifdef DIAGNOSTIC
   1407       1.1        ad 	ac->ac_flags &= ~AAC_CCB_MAPPED;
   1408       1.1        ad #endif
   1409       1.1        ad }
   1410       1.1        ad 
   1411       1.1        ad void
   1412       1.1        ad aac_ccb_enqueue(struct aac_softc *sc, struct aac_ccb *ac)
   1413       1.1        ad {
   1414       1.1        ad 	int s;
   1415       1.1        ad 
   1416       1.1        ad 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_enqueue(%p, %p) ", sc, ac));
   1417       1.1        ad 
   1418       1.1        ad 	s = splbio();
   1419       1.1        ad 
   1420       1.1        ad 	if (ac != NULL)
   1421       1.1        ad 		SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_queue, ac, ac_chain);
   1422       1.1        ad 
   1423       1.1        ad 	while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_queue)) != NULL) {
   1424       1.1        ad 		if (aac_ccb_submit(sc, ac))
   1425       1.1        ad 			break;
   1426       1.3     lukem 		SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_queue, ac_chain);
   1427       1.1        ad 	}
   1428       1.1        ad 
   1429       1.1        ad 	splx(s);
   1430       1.1        ad }
   1431       1.1        ad 
   1432       1.1        ad int
   1433       1.1        ad aac_ccb_submit(struct aac_softc *sc, struct aac_ccb *ac)
   1434       1.1        ad {
   1435  1.29.2.1   xtraeme 	struct aac_fibmap *fm;
   1436  1.29.2.1   xtraeme 	u_int32_t acidx;
   1437       1.1        ad 
   1438       1.1        ad 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_submit(%p, %p) ", sc, ac));
   1439       1.1        ad 
   1440  1.29.2.1   xtraeme 	acidx = (u_int32_t) (ac - sc->sc_ccbs);
   1441       1.1        ad 	/* Fix up the address values. */
   1442  1.29.2.1   xtraeme 	ac->ac_fib->Header.SenderFibAddress = htole32(acidx << 2);
   1443       1.1        ad 	ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys);
   1444       1.1        ad 
   1445       1.1        ad 	/* Save a pointer to the command for speedy reverse-lookup. */
   1446  1.29.2.1   xtraeme 	ac->ac_fib->Header.SenderData = acidx | 0x80000000;
   1447       1.1        ad 
   1448  1.29.2.1   xtraeme 	fm = ac->ac_fibmap;
   1449  1.29.2.1   xtraeme 	bus_dmamap_sync(sc->sc_dmat, fm->fm_fibmap,
   1450  1.29.2.1   xtraeme 	    (char *)ac->ac_fib - (char *)fm->fm_fibs, sc->sc_max_fib_size,
   1451       1.1        ad 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
   1452       1.1        ad 
   1453       1.1        ad 	/* Put the FIB on the outbound queue. */
   1454  1.29.2.1   xtraeme 	if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) {
   1455  1.29.2.1   xtraeme 		int count = 10000000L;
   1456  1.29.2.1   xtraeme 		while (AAC_SEND_COMMAND(sc, ac) != 0) {
   1457  1.29.2.1   xtraeme 			if (--count == 0) {
   1458  1.29.2.1   xtraeme 				panic("aac: fixme!");
   1459  1.29.2.1   xtraeme 				return EAGAIN;
   1460  1.29.2.1   xtraeme 			}
   1461  1.29.2.1   xtraeme 			DELAY(5);
   1462  1.29.2.1   xtraeme 		}
   1463  1.29.2.1   xtraeme 		return 0;
   1464  1.29.2.1   xtraeme 	} else {
   1465  1.29.2.1   xtraeme 		return (aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE, ac));
   1466  1.29.2.1   xtraeme 	}
   1467       1.1        ad }
   1468       1.1        ad 
   1469       1.1        ad int
   1470       1.1        ad aac_ccb_poll(struct aac_softc *sc, struct aac_ccb *ac, int timo)
   1471       1.1        ad {
   1472       1.1        ad 	int rv, s;
   1473       1.1        ad 
   1474       1.1        ad 	AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_poll(%p, %p, %d) ", sc, ac, timo));
   1475       1.1        ad 
   1476       1.1        ad 	s = splbio();
   1477       1.1        ad 
   1478       1.1        ad 	if ((rv = aac_ccb_submit(sc, ac)) != 0) {
   1479       1.1        ad 		splx(s);
   1480       1.1        ad 		return (rv);
   1481       1.1        ad 	}
   1482       1.1        ad 
   1483       1.1        ad 	for (timo *= 1000; timo != 0; timo--) {
   1484  1.29.2.1   xtraeme 		if (sc->sc_quirks & AAC_QUIRK_NEW_COMM)
   1485  1.29.2.1   xtraeme 			aac_new_intr(sc);
   1486  1.29.2.1   xtraeme 		else
   1487  1.29.2.1   xtraeme 			aac_intr(sc);
   1488       1.1        ad 		if ((ac->ac_flags & AAC_CCB_COMPLETED) != 0)
   1489       1.1        ad 			break;
   1490       1.1        ad 		DELAY(100);
   1491       1.1        ad 	}
   1492       1.1        ad 
   1493       1.1        ad 	splx(s);
   1494       1.1        ad 	return (timo == 0);
   1495       1.1        ad }
   1496       1.1        ad 
   1497       1.1        ad /*
   1498       1.1        ad  * Atomically insert an entry into the nominated queue, returns 0 on success
   1499       1.1        ad  * or EBUSY if the queue is full.
   1500       1.1        ad  *
   1501       1.1        ad  * XXX Note that it would be more efficient to defer notifying the
   1502       1.1        ad  * controller in the case where we may be inserting several entries in rapid
   1503       1.1        ad  * succession, but implementing this usefully is difficult.
   1504       1.1        ad  */
   1505      1.12   thorpej static int
   1506  1.29.2.1   xtraeme aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_ccb *ac)
   1507       1.1        ad {
   1508       1.1        ad 	u_int32_t fib_size, fib_addr, pi, ci;
   1509       1.1        ad 
   1510  1.29.2.1   xtraeme 	fib_size = le16toh(ac->ac_fib->Header.Size);
   1511  1.29.2.1   xtraeme 	fib_addr = le32toh(ac->ac_fib->Header.ReceiverFibAddress);
   1512       1.1        ad 
   1513       1.1        ad 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
   1514  1.29.2.1   xtraeme 	    (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
   1515       1.1        ad 	    sizeof(sc->sc_common->ac_qbuf),
   1516       1.1        ad 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
   1517       1.1        ad 
   1518       1.1        ad 	/* Get the producer/consumer indices.  */
   1519       1.1        ad 	pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
   1520       1.1        ad 	ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
   1521       1.1        ad 
   1522       1.1        ad 	/* Wrap the queue? */
   1523       1.1        ad 	if (pi >= aac_qinfo[queue].size)
   1524       1.1        ad 		pi = 0;
   1525       1.1        ad 
   1526       1.1        ad 	/* Check for queue full. */
   1527       1.1        ad 	if ((pi + 1) == ci)
   1528       1.1        ad 		return (EAGAIN);
   1529       1.1        ad 
   1530       1.1        ad 	/* Populate queue entry. */
   1531       1.1        ad 	(sc->sc_qentries[queue] + pi)->aq_fib_size = htole32(fib_size);
   1532       1.1        ad 	(sc->sc_qentries[queue] + pi)->aq_fib_addr = htole32(fib_addr);
   1533       1.1        ad 
   1534       1.1        ad 	/* Update producer index. */
   1535       1.1        ad 	sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = htole32(pi + 1);
   1536       1.1        ad 
   1537       1.1        ad 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
   1538  1.29.2.1   xtraeme 	    (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
   1539       1.1        ad 	    sizeof(sc->sc_common->ac_qbuf),
   1540       1.1        ad 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
   1541       1.1        ad 
   1542       1.1        ad 	/* Notify the adapter if we know how. */
   1543       1.1        ad 	if (aac_qinfo[queue].notify != 0)
   1544       1.1        ad 		AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
   1545       1.1        ad 
   1546       1.1        ad 	return (0);
   1547       1.1        ad }
   1548       1.1        ad 
   1549       1.1        ad /*
   1550       1.1        ad  * Atomically remove one entry from the nominated queue, returns 0 on success
   1551       1.1        ad  * or ENOENT if the queue is empty.
   1552       1.1        ad  */
   1553      1.12   thorpej static int
   1554       1.1        ad aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
   1555       1.1        ad 		struct aac_fib **fib_addr)
   1556       1.1        ad {
   1557  1.29.2.1   xtraeme 	struct aac_fibmap *fm;
   1558  1.29.2.1   xtraeme 	struct aac_ccb *ac;
   1559  1.29.2.1   xtraeme 	u_int32_t pi, ci, idx;
   1560       1.1        ad 	int notify;
   1561       1.1        ad 
   1562       1.1        ad 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
   1563  1.29.2.1   xtraeme 	    (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
   1564       1.1        ad 	    sizeof(sc->sc_common->ac_qbuf),
   1565       1.1        ad 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
   1566       1.1        ad 
   1567       1.1        ad 	/* Get the producer/consumer indices. */
   1568       1.1        ad 	pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
   1569       1.1        ad 	ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
   1570       1.1        ad 
   1571       1.1        ad 	/* Check for queue empty. */
   1572       1.1        ad 	if (ci == pi)
   1573       1.1        ad 		return (ENOENT);
   1574       1.1        ad 
   1575       1.1        ad 	notify = 0;
   1576       1.1        ad 	if (ci == pi + 1)
   1577       1.1        ad 		notify = 1;
   1578       1.1        ad 
   1579       1.1        ad 	/* Wrap the queue? */
   1580       1.1        ad 	if (ci >= aac_qinfo[queue].size)
   1581       1.1        ad 		ci = 0;
   1582       1.1        ad 
   1583       1.1        ad 	/* Fetch the entry. */
   1584       1.1        ad 	*fib_size = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_size);
   1585  1.29.2.1   xtraeme 
   1586  1.29.2.1   xtraeme 	switch (queue) {
   1587  1.29.2.1   xtraeme 	case AAC_HOST_NORM_CMD_QUEUE:
   1588  1.29.2.1   xtraeme 	case AAC_HOST_HIGH_CMD_QUEUE:
   1589  1.29.2.1   xtraeme 		idx = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_addr);
   1590  1.29.2.1   xtraeme 		idx /= sizeof(struct aac_fib);
   1591  1.29.2.1   xtraeme 		*fib_addr = &sc->sc_common->ac_fibs[idx];
   1592  1.29.2.1   xtraeme 		break;
   1593  1.29.2.1   xtraeme 	case AAC_HOST_NORM_RESP_QUEUE:
   1594  1.29.2.1   xtraeme 	case AAC_HOST_HIGH_RESP_QUEUE:
   1595  1.29.2.1   xtraeme 		idx = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_addr);
   1596  1.29.2.1   xtraeme 		ac = sc->sc_ccbs + (idx >> 2);
   1597  1.29.2.1   xtraeme 		*fib_addr = ac->ac_fib;
   1598  1.29.2.1   xtraeme 		if (idx & 0x01) {
   1599  1.29.2.1   xtraeme 			fm = ac->ac_fibmap;
   1600  1.29.2.1   xtraeme 			bus_dmamap_sync(sc->sc_dmat, fm->fm_fibmap,
   1601  1.29.2.1   xtraeme 			    (char *)ac->ac_fib - (char *)fm->fm_fibs,
   1602  1.29.2.1   xtraeme 			    sc->sc_max_fib_size,
   1603  1.29.2.1   xtraeme 			    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
   1604  1.29.2.1   xtraeme 			ac->ac_fib->Header.XferState |=
   1605  1.29.2.1   xtraeme 				htole32(AAC_FIBSTATE_DONEADAP);
   1606  1.29.2.1   xtraeme 			*((u_int32_t*)(ac->ac_fib->data)) =
   1607  1.29.2.1   xtraeme 				htole32(AAC_ERROR_NORMAL);
   1608  1.29.2.1   xtraeme 		}
   1609  1.29.2.1   xtraeme 		break;
   1610  1.29.2.1   xtraeme 	default:
   1611  1.29.2.1   xtraeme 		panic("Invalid queue in aac_dequeue_fib()");
   1612  1.29.2.1   xtraeme 		break;
   1613  1.29.2.1   xtraeme 	}
   1614       1.1        ad 
   1615       1.1        ad 	/* Update consumer index. */
   1616       1.1        ad 	sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1;
   1617       1.1        ad 
   1618       1.1        ad 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
   1619  1.29.2.1   xtraeme 	    (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
   1620       1.1        ad 	    sizeof(sc->sc_common->ac_qbuf),
   1621       1.1        ad 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
   1622       1.1        ad 
   1623       1.1        ad 	/* If we have made the queue un-full, notify the adapter. */
   1624       1.1        ad 	if (notify && (aac_qinfo[queue].notify != 0))
   1625       1.1        ad 		AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
   1626       1.1        ad 
   1627       1.1        ad 	return (0);
   1628       1.1        ad }
   1629       1.1        ad 
   1630  1.29.2.1   xtraeme /*
   1631  1.29.2.1   xtraeme  * Put our response to an adapter-initiated fib (AIF) on the response queue.
   1632  1.29.2.1   xtraeme  */
   1633  1.29.2.1   xtraeme static int
   1634  1.29.2.1   xtraeme aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib)
   1635  1.29.2.1   xtraeme {
   1636  1.29.2.1   xtraeme 	u_int32_t fib_size, fib_addr, pi, ci;
   1637  1.29.2.1   xtraeme 
   1638  1.29.2.1   xtraeme 	fib_size = le16toh(fib->Header.Size);
   1639  1.29.2.1   xtraeme 	fib_addr = fib->Header.SenderFibAddress;
   1640  1.29.2.1   xtraeme 	fib->Header.ReceiverFibAddress = fib_addr;
   1641  1.29.2.1   xtraeme 
   1642  1.29.2.1   xtraeme 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
   1643  1.29.2.1   xtraeme 	    (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
   1644  1.29.2.1   xtraeme 	    sizeof(sc->sc_common->ac_qbuf),
   1645  1.29.2.1   xtraeme 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
   1646  1.29.2.1   xtraeme 
   1647  1.29.2.1   xtraeme 	/* Get the producer/consumer indices.  */
   1648  1.29.2.1   xtraeme 	pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
   1649  1.29.2.1   xtraeme 	ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
   1650  1.29.2.1   xtraeme 
   1651  1.29.2.1   xtraeme 	/* Wrap the queue? */
   1652  1.29.2.1   xtraeme 	if (pi >= aac_qinfo[queue].size)
   1653  1.29.2.1   xtraeme 		pi = 0;
   1654  1.29.2.1   xtraeme 
   1655  1.29.2.1   xtraeme 	/* Check for queue full. */
   1656  1.29.2.1   xtraeme 	if ((pi + 1) == ci)
   1657  1.29.2.1   xtraeme 		return (EAGAIN);
   1658  1.29.2.1   xtraeme 
   1659  1.29.2.1   xtraeme 	/* Populate queue entry. */
   1660  1.29.2.1   xtraeme 	(sc->sc_qentries[queue] + pi)->aq_fib_size = htole32(fib_size);
   1661  1.29.2.1   xtraeme 	(sc->sc_qentries[queue] + pi)->aq_fib_addr = htole32(fib_addr);
   1662  1.29.2.1   xtraeme 
   1663  1.29.2.1   xtraeme 	/* Update producer index. */
   1664  1.29.2.1   xtraeme 	sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = htole32(pi + 1);
   1665  1.29.2.1   xtraeme 
   1666  1.29.2.1   xtraeme 	bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
   1667  1.29.2.1   xtraeme 	    (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
   1668  1.29.2.1   xtraeme 	    sizeof(sc->sc_common->ac_qbuf),
   1669  1.29.2.1   xtraeme 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
   1670  1.29.2.1   xtraeme 
   1671  1.29.2.1   xtraeme 	/* Notify the adapter if we know how. */
   1672  1.29.2.1   xtraeme 	if (aac_qinfo[queue].notify != 0)
   1673  1.29.2.1   xtraeme 		AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
   1674  1.29.2.1   xtraeme 
   1675  1.29.2.1   xtraeme 	return (0);
   1676  1.29.2.1   xtraeme }
   1677  1.29.2.1   xtraeme 
   1678       1.1        ad #ifdef AAC_DEBUG
   1679       1.1        ad /*
   1680       1.1        ad  * Print a FIB
   1681       1.1        ad  */
   1682      1.12   thorpej static void
   1683      1.29  christos aac_print_fib(struct aac_softc *sc, struct aac_fib *fib,
   1684      1.28  christos     const char *caller)
   1685       1.1        ad {
   1686       1.1        ad 	struct aac_blockread *br;
   1687       1.1        ad 	struct aac_blockwrite *bw;
   1688       1.1        ad 	struct aac_sg_table *sg;
   1689      1.19  christos 	char tbuf[512];
   1690       1.1        ad 	int i;
   1691       1.1        ad 
   1692       1.1        ad 	printf("%s: FIB @ %p\n", caller, fib);
   1693       1.1        ad 	bitmask_snprintf(le32toh(fib->Header.XferState),
   1694       1.1        ad 	    "\20"
   1695       1.1        ad 	    "\1HOSTOWNED"
   1696       1.1        ad 	    "\2ADAPTEROWNED"
   1697       1.1        ad 	    "\3INITIALISED"
   1698       1.1        ad 	    "\4EMPTY"
   1699       1.1        ad 	    "\5FROMPOOL"
   1700       1.1        ad 	    "\6FROMHOST"
   1701       1.1        ad 	    "\7FROMADAP"
   1702       1.1        ad 	    "\10REXPECTED"
   1703       1.1        ad 	    "\11RNOTEXPECTED"
   1704       1.1        ad 	    "\12DONEADAP"
   1705       1.1        ad 	    "\13DONEHOST"
   1706       1.1        ad 	    "\14HIGH"
   1707       1.1        ad 	    "\15NORM"
   1708       1.1        ad 	    "\16ASYNC"
   1709       1.1        ad 	    "\17PAGEFILEIO"
   1710       1.1        ad 	    "\20SHUTDOWN"
   1711       1.1        ad 	    "\21LAZYWRITE"
   1712       1.1        ad 	    "\22ADAPMICROFIB"
   1713       1.1        ad 	    "\23BIOSFIB"
   1714       1.1        ad 	    "\24FAST_RESPONSE"
   1715       1.1        ad 	    "\25APIFIB\n",
   1716      1.19  christos 	    tbuf,
   1717      1.19  christos 	    sizeof(tbuf));
   1718       1.1        ad 
   1719      1.19  christos 	printf("  XferState       %s\n", tbuf);
   1720       1.1        ad 	printf("  Command         %d\n", le16toh(fib->Header.Command));
   1721       1.1        ad 	printf("  StructType      %d\n", fib->Header.StructType);
   1722       1.1        ad 	printf("  Flags           0x%x\n", fib->Header.Flags);
   1723       1.1        ad 	printf("  Size            %d\n", le16toh(fib->Header.Size));
   1724       1.1        ad 	printf("  SenderSize      %d\n", le16toh(fib->Header.SenderSize));
   1725       1.1        ad 	printf("  SenderAddress   0x%x\n",
   1726       1.1        ad 	    le32toh(fib->Header.SenderFibAddress));
   1727       1.1        ad 	printf("  ReceiverAddress 0x%x\n",
   1728       1.1        ad 	    le32toh(fib->Header.ReceiverFibAddress));
   1729       1.1        ad 	printf("  SenderData      0x%x\n", fib->Header.SenderData);
   1730       1.1        ad 
   1731       1.1        ad 	switch (fib->Header.Command) {
   1732       1.1        ad 	case ContainerCommand: {
   1733       1.1        ad 		br = (struct aac_blockread *)fib->data;
   1734       1.1        ad 		bw = (struct aac_blockwrite *)fib->data;
   1735       1.1        ad 		sg = NULL;
   1736       1.1        ad 
   1737       1.1        ad 		if (le32toh(br->Command) == VM_CtBlockRead) {
   1738      1.16     perry 			printf("  BlockRead: container %d  0x%x/%d\n",
   1739       1.1        ad 			    le32toh(br->ContainerId), le32toh(br->BlockNumber),
   1740       1.1        ad 			    le32toh(br->ByteCount));
   1741       1.1        ad 			sg = &br->SgMap;
   1742       1.1        ad 		}
   1743       1.1        ad 		if (le32toh(bw->Command) == VM_CtBlockWrite) {
   1744      1.16     perry 			printf("  BlockWrite: container %d  0x%x/%d (%s)\n",
   1745       1.1        ad 			    le32toh(bw->ContainerId), le32toh(bw->BlockNumber),
   1746       1.1        ad 			    le32toh(bw->ByteCount),
   1747       1.1        ad 			    le32toh(bw->Stable) == CSTABLE ?
   1748       1.1        ad 			    "stable" : "unstable");
   1749       1.1        ad 			sg = &bw->SgMap;
   1750       1.1        ad 		}
   1751       1.1        ad 		if (sg != NULL) {
   1752       1.1        ad 			printf("  %d s/g entries\n", le32toh(sg->SgCount));
   1753       1.1        ad 			for (i = 0; i < le32toh(sg->SgCount); i++)
   1754       1.1        ad 				printf("  0x%08x/%d\n",
   1755       1.1        ad 				    le32toh(sg->SgEntry[i].SgAddress),
   1756       1.1        ad 				    le32toh(sg->SgEntry[i].SgByteCount));
   1757       1.1        ad 		}
   1758       1.1        ad 		break;
   1759       1.1        ad 	}
   1760       1.1        ad 	default:
   1761      1.24  jdolecek 		// dump first 32 bytes of fib->data
   1762      1.24  jdolecek 		printf("  Raw data:");
   1763      1.24  jdolecek 		for (i = 0; i < 32; i++)
   1764      1.24  jdolecek 			printf(" %02x", fib->data[i]);
   1765      1.24  jdolecek 		printf("\n");
   1766       1.1        ad 		break;
   1767       1.1        ad 	}
   1768       1.1        ad }
   1769      1.12   thorpej #endif /* AAC_DEBUG */
   1770