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