Home | History | Annotate | Line # | Download | only in pci
btvmeii.c revision 1.7
      1  1.7   thorpej /* $NetBSD: btvmeii.c,v 1.7 2002/09/30 20:37:11 thorpej Exp $ */
      2  1.1  drochner 
      3  1.1  drochner /*
      4  1.1  drochner  * Copyright (c) 1999
      5  1.1  drochner  * 	Matthias Drochner.  All rights reserved.
      6  1.1  drochner  *
      7  1.1  drochner  * Redistribution and use in source and binary forms, with or without
      8  1.1  drochner  * modification, are permitted provided that the following conditions
      9  1.1  drochner  * are met:
     10  1.1  drochner  * 1. Redistributions of source code must retain the above copyright
     11  1.1  drochner  *    notice, this list of conditions, and the following disclaimer.
     12  1.1  drochner  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  drochner  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  drochner  *    documentation and/or other materials provided with the distribution.
     15  1.1  drochner  *
     16  1.1  drochner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  1.1  drochner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  1.1  drochner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  1.1  drochner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  1.1  drochner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  1.1  drochner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  1.1  drochner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  1.1  drochner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  1.1  drochner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  1.1  drochner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  1.1  drochner  * SUCH DAMAGE.
     27  1.1  drochner  */
     28  1.1  drochner 
     29  1.1  drochner /*
     30  1.1  drochner  * Driver for the Bit3/SBS PCI-VME adapter Model 2706.
     31  1.1  drochner  * Uses the common Tundra Universe code.
     32  1.1  drochner  */
     33  1.4     lukem 
     34  1.4     lukem #include <sys/cdefs.h>
     35  1.7   thorpej __KERNEL_RCSID(0, "$NetBSD: btvmeii.c,v 1.7 2002/09/30 20:37:11 thorpej Exp $");
     36  1.1  drochner 
     37  1.1  drochner #include <sys/param.h>
     38  1.1  drochner #include <sys/systm.h>
     39  1.5    simonb #include <sys/kernel.h>
     40  1.1  drochner #include <sys/device.h>
     41  1.1  drochner 
     42  1.1  drochner #include <dev/pci/pcireg.h>
     43  1.1  drochner #include <dev/pci/pcivar.h>
     44  1.1  drochner #include <dev/pci/pcidevs.h>
     45  1.1  drochner 
     46  1.1  drochner #include <machine/bus.h>
     47  1.1  drochner #include <sys/malloc.h>
     48  1.1  drochner #include <sys/extent.h>
     49  1.1  drochner 
     50  1.1  drochner #include <dev/pci/ppbreg.h>
     51  1.1  drochner 
     52  1.1  drochner #include <dev/vme/vmereg.h>
     53  1.1  drochner #include <dev/vme/vmevar.h>
     54  1.1  drochner 
     55  1.1  drochner #include <dev/pci/universe_pci_var.h>
     56  1.1  drochner 
     57  1.1  drochner static int b3_2706_match __P((struct device *, struct cfdata *, void *));
     58  1.1  drochner static void b3_2706_attach __P((struct device *, struct device *, void *));
     59  1.1  drochner 
     60  1.1  drochner /* exported via tag structs */
     61  1.1  drochner int b3_2706_map_vme __P((void *, vme_addr_t, vme_size_t,
     62  1.1  drochner 		      vme_am_t, vme_datasize_t, vme_swap_t,
     63  1.1  drochner 		      bus_space_tag_t *, bus_space_handle_t *, vme_mapresc_t*));
     64  1.1  drochner void b3_2706_unmap_vme __P((void *, vme_mapresc_t));
     65  1.1  drochner 
     66  1.1  drochner int b3_2706_vme_probe __P((void *, vme_addr_t, vme_size_t, vme_am_t,
     67  1.1  drochner 			vme_datasize_t,
     68  1.1  drochner 			int (*)(void *, bus_space_tag_t, bus_space_handle_t),
     69  1.1  drochner 			void *));
     70  1.1  drochner 
     71  1.1  drochner int b3_2706_map_vmeint __P((void *, int, int, vme_intr_handle_t *));
     72  1.1  drochner void *b3_2706_establish_vmeint __P((void *, vme_intr_handle_t, int,
     73  1.1  drochner 				 int (*)(void *), void *));
     74  1.1  drochner void b3_2706_disestablish_vmeint __P((void *, void *));
     75  1.2  drochner void b3_2706_vmeint __P((void *, int, int));
     76  1.1  drochner 
     77  1.1  drochner int b3_2706_dmamap_create __P((void *, vme_size_t,
     78  1.1  drochner 			    vme_am_t, vme_datasize_t, vme_swap_t,
     79  1.1  drochner 			    int, vme_size_t, vme_addr_t,
     80  1.1  drochner 			    int, bus_dmamap_t *));
     81  1.1  drochner void b3_2706_dmamap_destroy __P((void *, bus_dmamap_t));
     82  1.1  drochner 
     83  1.1  drochner int b3_2706_dmamem_alloc __P((void *, vme_size_t,
     84  1.1  drochner 			      vme_am_t, vme_datasize_t, vme_swap_t,
     85  1.1  drochner 			      bus_dma_segment_t *, int, int *, int));
     86  1.1  drochner void b3_2706_dmamem_free __P((void *, bus_dma_segment_t *, int));
     87  1.1  drochner 
     88  1.1  drochner struct b3_2706_vmemaprescs {
     89  1.1  drochner 	int wnd;
     90  1.1  drochner 	unsigned long pcibase, maplen;
     91  1.1  drochner 	bus_space_handle_t handle;
     92  1.1  drochner 	u_int32_t len;
     93  1.1  drochner };
     94  1.1  drochner 
     95  1.2  drochner struct b3_2706_vmeintrhand {
     96  1.2  drochner 	TAILQ_ENTRY(b3_2706_vmeintrhand) ih_next;
     97  1.2  drochner 	int (*ih_fun) __P((void*));
     98  1.2  drochner 	void *ih_arg;
     99  1.2  drochner 	int ih_level;
    100  1.2  drochner 	int ih_vector;
    101  1.2  drochner 	int ih_prior;
    102  1.2  drochner 	u_long ih_count;
    103  1.2  drochner };
    104  1.2  drochner 
    105  1.1  drochner struct b3_2706_softc {
    106  1.1  drochner 	struct device sc_dev;
    107  1.1  drochner 	struct univ_pci_data univdata;
    108  1.1  drochner 	bus_space_tag_t swapt, vmet;
    109  1.1  drochner 	bus_space_handle_t swaph;
    110  1.1  drochner 	bus_addr_t vmepbase;
    111  1.1  drochner 
    112  1.1  drochner 	int windowused[8];
    113  1.1  drochner 	struct b3_2706_vmemaprescs vmemaprescs[8];
    114  1.1  drochner 	struct extent *vmeext;
    115  1.1  drochner 	char vmemap[EXTENT_FIXED_STORAGE_SIZE(8)];
    116  1.1  drochner 
    117  1.1  drochner 	struct vme_chipset_tag sc_vct;
    118  1.2  drochner 
    119  1.2  drochner 	/* list of VME interrupt handlers */
    120  1.2  drochner 	TAILQ_HEAD(, b3_2706_vmeintrhand) intrhdls;
    121  1.2  drochner 	int strayintrs;
    122  1.1  drochner };
    123  1.1  drochner 
    124  1.7   thorpej CFATTACH_DECL(btvmeii, sizeof(struct b3_2706_softc),
    125  1.7   thorpej     b3_2706_match, b3_2706_attach, NULL, NULL)
    126  1.1  drochner 
    127  1.1  drochner /*
    128  1.1  drochner  * The adapter consists of a DEC PCI-PCI-bridge with two
    129  1.1  drochner  * PCI devices behind it: A Tundra Universe as device 4 and
    130  1.1  drochner  * some FPGA with glue logics as device 8.
    131  1.1  drochner  * As long as the autoconf code doesn't provide more support
    132  1.1  drochner  * for dependant devices, we have to duplicate a part of the
    133  1.1  drochner  * "ppb" functions here.
    134  1.1  drochner  */
    135  1.1  drochner 
    136  1.1  drochner static int
    137  1.1  drochner b3_2706_match(parent, match, aux)
    138  1.1  drochner 	struct device *parent;
    139  1.1  drochner 	struct cfdata *match;
    140  1.1  drochner 	void *aux;
    141  1.1  drochner {
    142  1.1  drochner 	struct pci_attach_args *pa = aux;
    143  1.1  drochner 	pci_chipset_tag_t pc = pa->pa_pc;
    144  1.1  drochner 	int secbus;
    145  1.1  drochner 	pcitag_t tag;
    146  1.1  drochner 	pcireg_t id;
    147  1.1  drochner 
    148  1.1  drochner 	if ((PCI_VENDOR(pa->pa_id) != PCI_VENDOR_DEC)
    149  1.1  drochner 	    || (PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_DEC_21152))
    150  1.1  drochner 		return (0);
    151  1.1  drochner 
    152  1.1  drochner 	secbus = PPB_BUSINFO_SECONDARY(pci_conf_read(pc, pa->pa_tag,
    153  1.1  drochner 						     PPB_REG_BUSINFO));
    154  1.1  drochner 	if (secbus == 0) {
    155  1.1  drochner 		printf("b3_2706_match: ppb not configured\n");
    156  1.1  drochner 		return (0);
    157  1.1  drochner 	}
    158  1.1  drochner 
    159  1.1  drochner 	tag = pci_make_tag(pc, secbus, 4, 0);
    160  1.1  drochner 	id = pci_conf_read(pc, tag, PCI_ID_REG);
    161  1.1  drochner 
    162  1.1  drochner 	if ((PCI_VENDOR(id) != PCI_VENDOR_NEWBRIDGE)
    163  1.1  drochner 	    || (PCI_PRODUCT(id) != PCI_PRODUCT_NEWBRIDGE_CA91CX42)) {
    164  1.1  drochner #ifdef DEBUG
    165  1.1  drochner 		printf("b3_2706_match: no tundra\n");
    166  1.1  drochner #endif
    167  1.1  drochner 		return (0);
    168  1.1  drochner 	}
    169  1.1  drochner 
    170  1.1  drochner 	tag = pci_make_tag(pc, secbus, 8, 0);
    171  1.1  drochner 	id = pci_conf_read(pc, tag, PCI_ID_REG);
    172  1.1  drochner 
    173  1.1  drochner 	if ((PCI_VENDOR(id) != PCI_VENDOR_BIT3)
    174  1.1  drochner 	    || (PCI_PRODUCT(id) != PCI_PRODUCT_BIT3_PCIVME2706)) {
    175  1.1  drochner #ifdef DEBUG
    176  1.1  drochner 		printf("b3_2706_match: no bit3 chip\n");
    177  1.1  drochner #endif
    178  1.1  drochner 		return (0);
    179  1.1  drochner 	}
    180  1.1  drochner 
    181  1.1  drochner 	return (5); /* beat "ppb" */
    182  1.1  drochner }
    183  1.1  drochner 
    184  1.1  drochner static void
    185  1.1  drochner b3_2706_attach(parent, self, aux)
    186  1.1  drochner 	struct device *parent, *self;
    187  1.1  drochner 	void *aux;
    188  1.1  drochner {
    189  1.1  drochner 	struct b3_2706_softc *sc = (struct b3_2706_softc *)self;
    190  1.1  drochner 	struct pci_attach_args *pa = aux;
    191  1.1  drochner 	pci_chipset_tag_t pc = pa->pa_pc;
    192  1.1  drochner 	struct pci_attach_args aa;
    193  1.1  drochner 	int secbus;
    194  1.1  drochner 	pcireg_t intr;
    195  1.1  drochner 	pcitag_t tag;
    196  1.1  drochner 	bus_addr_t swappbase;
    197  1.1  drochner 	int i;
    198  1.1  drochner 
    199  1.1  drochner 	struct vmebus_attach_args vaa;
    200  1.1  drochner 
    201  1.1  drochner 	printf("\n");
    202  1.1  drochner 
    203  1.1  drochner 	secbus = PPB_BUSINFO_SECONDARY(pci_conf_read(pc, pa->pa_tag,
    204  1.1  drochner 						     PPB_REG_BUSINFO));
    205  1.1  drochner 
    206  1.3   thorpej 	memcpy(&aa, pa, sizeof(struct pci_attach_args));
    207  1.1  drochner 	aa.pa_device = 4;
    208  1.1  drochner 	aa.pa_function = 0;
    209  1.1  drochner 	aa.pa_tag = pci_make_tag(pc, secbus, 4, 0);
    210  1.1  drochner 	aa.pa_intrswiz += 4;
    211  1.1  drochner 	intr = pci_conf_read(pc, aa.pa_tag, PCI_INTERRUPT_REG);
    212  1.1  drochner 	/*
    213  1.1  drochner 	 * swizzle it based on the number of
    214  1.1  drochner 	 * busses we're behind and our device
    215  1.1  drochner 	 * number.
    216  1.1  drochner 	 */
    217  1.1  drochner 	aa.pa_intrpin =	((1 + aa.pa_intrswiz - 1) % 4) + 1;
    218  1.1  drochner 	aa.pa_intrline = PCI_INTERRUPT_LINE(intr);
    219  1.1  drochner 
    220  1.2  drochner 	if (univ_pci_attach(&sc->univdata, &aa, self->dv_xname,
    221  1.2  drochner 			    b3_2706_vmeint, sc)) {
    222  1.1  drochner 		printf("%s: error initializing universe chip\n",
    223  1.1  drochner 		       self->dv_xname);
    224  1.1  drochner 		return;
    225  1.1  drochner 	}
    226  1.1  drochner 
    227  1.2  drochner 	/*
    228  1.2  drochner 	 * don't waste KVM - the byteswap register is aliased in
    229  1.2  drochner 	 * a 512k window, we need it only once
    230  1.2  drochner 	 */
    231  1.1  drochner 	tag = pci_make_tag(pc, secbus, 8, 0);
    232  1.1  drochner 	sc->swapt = pa->pa_memt;
    233  1.1  drochner 	if (pci_mapreg_info(pc, tag, 0x10,
    234  1.1  drochner 			    PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT,
    235  1.1  drochner 			    &swappbase, 0, 0) ||
    236  1.1  drochner 	    bus_space_map(sc->swapt, swappbase, 4, 0, &sc->swaph)) {
    237  1.1  drochner 		printf("%s: can't map byteswap register\n", self->dv_xname);
    238  1.1  drochner 		return;
    239  1.1  drochner 	}
    240  1.2  drochner 	/*
    241  1.2  drochner 	 * Set up cycle specific byteswap mode.
    242  1.2  drochner 	 * XXX Readback yields "all-ones" for me, and it doesn't seem
    243  1.2  drochner 	 * to matter what I write into the register - the data don't
    244  1.2  drochner 	 * get swapped. Adapter fault or documentation bug?
    245  1.2  drochner 	 */
    246  1.2  drochner 	bus_space_write_4(sc->swapt, sc->swaph, 0, 0x00000490);
    247  1.2  drochner 
    248  1.2  drochner 	/* VME space is mapped as needed */
    249  1.1  drochner 	sc->vmet = pa->pa_memt;
    250  1.1  drochner 	if (pci_mapreg_info(pc, tag, 0x14,
    251  1.1  drochner 			    PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT,
    252  1.1  drochner 			    &sc->vmepbase, 0, 0)) {
    253  1.1  drochner 		printf("%s: VME range not assigned\n", self->dv_xname);
    254  1.1  drochner 		return;
    255  1.1  drochner 	}
    256  1.2  drochner #ifdef BIT3DEBUG
    257  1.1  drochner 	printf("%s: VME window @%lx\n", self->dv_xname, (long)sc->vmepbase);
    258  1.2  drochner #endif
    259  1.1  drochner 
    260  1.1  drochner 	for (i = 0; i < 8; i++) {
    261  1.1  drochner 		sc->windowused[i] = 0;
    262  1.1  drochner 	}
    263  1.1  drochner 	sc->vmeext = extent_create("pcivme", sc->vmepbase,
    264  1.1  drochner 				   sc->vmepbase + 32*1024*1024 - 1, M_DEVBUF,
    265  1.1  drochner 				   sc->vmemap, sizeof(sc->vmemap),
    266  1.1  drochner 				   EX_NOCOALESCE);
    267  1.1  drochner 
    268  1.1  drochner 	sc->sc_vct.cookie = self;
    269  1.1  drochner 	sc->sc_vct.vct_probe = b3_2706_vme_probe;
    270  1.1  drochner 	sc->sc_vct.vct_map = b3_2706_map_vme;
    271  1.1  drochner 	sc->sc_vct.vct_unmap = b3_2706_unmap_vme;
    272  1.1  drochner 	sc->sc_vct.vct_int_map = b3_2706_map_vmeint;
    273  1.1  drochner 	sc->sc_vct.vct_int_establish = b3_2706_establish_vmeint;
    274  1.1  drochner 	sc->sc_vct.vct_int_disestablish = b3_2706_disestablish_vmeint;
    275  1.1  drochner 	sc->sc_vct.vct_dmamap_create = b3_2706_dmamap_create;
    276  1.1  drochner 	sc->sc_vct.vct_dmamap_destroy = b3_2706_dmamap_destroy;
    277  1.1  drochner 	sc->sc_vct.vct_dmamem_alloc = b3_2706_dmamem_alloc;
    278  1.1  drochner 	sc->sc_vct.vct_dmamem_free = b3_2706_dmamem_free;
    279  1.1  drochner 
    280  1.1  drochner 	vaa.va_vct = &(sc->sc_vct);
    281  1.1  drochner 	vaa.va_bdt = pa->pa_dmat; /* XXX */
    282  1.2  drochner 	vaa.va_slaveconfig = 0; /* XXX CSR window? */
    283  1.1  drochner 
    284  1.1  drochner 	config_found(self, &vaa, 0);
    285  1.1  drochner }
    286  1.1  drochner 
    287  1.1  drochner #define sc ((struct b3_2706_softc*)vsc)
    288  1.1  drochner 
    289  1.1  drochner int
    290  1.1  drochner b3_2706_map_vme(vsc, vmeaddr, len, am, datasizes, swap, tag, handle, resc)
    291  1.1  drochner 	void *vsc;
    292  1.1  drochner 	vme_addr_t vmeaddr;
    293  1.1  drochner 	vme_size_t len;
    294  1.1  drochner 	vme_am_t am;
    295  1.1  drochner 	vme_datasize_t datasizes;
    296  1.1  drochner 	vme_swap_t swap;
    297  1.1  drochner 	bus_space_tag_t *tag;
    298  1.1  drochner 	bus_space_handle_t *handle;
    299  1.1  drochner 	vme_mapresc_t *resc;
    300  1.1  drochner {
    301  1.1  drochner 	int idx, i, wnd, res;
    302  1.1  drochner 	unsigned long boundary, maplen, pcibase;
    303  1.1  drochner 	vme_addr_t vmebase, vmeend;
    304  1.1  drochner 	static int windoworder[8] = {1, 2, 3, 5, 6, 7, 0, 4};
    305  1.1  drochner 
    306  1.1  drochner 	/* prefer windows with fine granularity for small mappings */
    307  1.1  drochner 	wnd = -1;
    308  1.1  drochner 	if (len <= 32*1024)
    309  1.1  drochner 		idx = 6;
    310  1.1  drochner 	else
    311  1.1  drochner 		idx = 0;
    312  1.1  drochner 	for (i = 0; i < 8; i++) {
    313  1.1  drochner 		if (!sc->windowused[windoworder[idx]]) {
    314  1.1  drochner 			wnd = windoworder[idx];
    315  1.1  drochner 			sc->windowused[wnd] = 1;
    316  1.1  drochner 			break;
    317  1.1  drochner 		}
    318  1.1  drochner 		idx = (idx + 1) % 8;
    319  1.1  drochner 	}
    320  1.1  drochner 	if (wnd == -1)
    321  1.1  drochner 		return (ENOSPC);
    322  1.1  drochner 
    323  1.1  drochner 	boundary = (wnd & 3) ? 64*1024 : 4*1024;
    324  1.1  drochner 
    325  1.1  drochner 	/* first mapped address */
    326  1.1  drochner 	vmebase = vmeaddr & ~(boundary - 1);
    327  1.1  drochner 	/* base of last mapped page */
    328  1.1  drochner 	vmeend = (vmeaddr + len - 1) & ~(boundary - 1);
    329  1.1  drochner 	/* bytes in outgoing window required */
    330  1.1  drochner 	maplen = vmeend - vmebase + boundary;
    331  1.1  drochner 
    332  1.2  drochner 	if (extent_alloc(sc->vmeext, maplen, boundary, 0, EX_FAST, &pcibase)) {
    333  1.2  drochner 		sc->windowused[wnd] = 0;
    334  1.1  drochner 		return (ENOMEM);
    335  1.2  drochner 	}
    336  1.1  drochner 
    337  1.1  drochner 	res = univ_pci_mapvme(&sc->univdata, wnd, vmebase, maplen,
    338  1.1  drochner 			      am, datasizes, pcibase);
    339  1.1  drochner 	if (res) {
    340  1.1  drochner 		extent_free(sc->vmeext, pcibase, maplen, 0);
    341  1.2  drochner 		sc->windowused[wnd] = 0;
    342  1.1  drochner 		return (res);
    343  1.1  drochner 	}
    344  1.1  drochner 
    345  1.1  drochner 	res = bus_space_map(sc->vmet, pcibase + (vmeaddr - vmebase), len,
    346  1.1  drochner 			    0, handle);
    347  1.1  drochner 	if (res) {
    348  1.1  drochner 		univ_pci_unmapvme(&sc->univdata, wnd);
    349  1.1  drochner 		extent_free(sc->vmeext, pcibase, maplen, 0);
    350  1.2  drochner 		sc->windowused[wnd] = 0;
    351  1.1  drochner 		return (res);
    352  1.1  drochner 	}
    353  1.1  drochner 
    354  1.1  drochner 	*tag = sc->vmet;
    355  1.1  drochner 
    356  1.1  drochner 	/*
    357  1.1  drochner 	 * save all data needed for later unmapping
    358  1.1  drochner 	 */
    359  1.1  drochner 	sc->vmemaprescs[wnd].wnd = wnd;
    360  1.1  drochner 	sc->vmemaprescs[wnd].pcibase = pcibase;
    361  1.1  drochner 	sc->vmemaprescs[wnd].maplen = maplen;
    362  1.1  drochner 	sc->vmemaprescs[wnd].handle = *handle;
    363  1.1  drochner 	sc->vmemaprescs[wnd].len = len;
    364  1.1  drochner 	*resc = &sc->vmemaprescs[wnd];
    365  1.1  drochner 	return (0);
    366  1.1  drochner }
    367  1.1  drochner 
    368  1.1  drochner void
    369  1.1  drochner b3_2706_unmap_vme(vsc, resc)
    370  1.1  drochner 	void *vsc;
    371  1.1  drochner 	vme_mapresc_t resc;
    372  1.1  drochner {
    373  1.1  drochner 	struct b3_2706_vmemaprescs *r = resc;
    374  1.1  drochner 
    375  1.1  drochner 	bus_space_unmap(sc->vmet, r->handle, r->len);
    376  1.1  drochner 	extent_free(sc->vmeext, r->pcibase, r->maplen, 0);
    377  1.1  drochner 
    378  1.1  drochner 	if (!sc->windowused[r->wnd])
    379  1.1  drochner 		panic("b3_2706_unmap_vme: bad window");
    380  1.1  drochner 	univ_pci_unmapvme(&sc->univdata, r->wnd);
    381  1.1  drochner 	sc->windowused[r->wnd] = 0;
    382  1.1  drochner }
    383  1.1  drochner 
    384  1.1  drochner int
    385  1.1  drochner b3_2706_vme_probe(vsc, addr, len, am, datasize, callback, cbarg)
    386  1.1  drochner 	void *vsc;
    387  1.1  drochner 	vme_addr_t addr;
    388  1.1  drochner 	vme_size_t len;
    389  1.1  drochner 	vme_am_t am;
    390  1.1  drochner 	vme_datasize_t datasize;
    391  1.1  drochner 	int (*callback) __P((void *, bus_space_tag_t, bus_space_handle_t));
    392  1.1  drochner 	void *cbarg;
    393  1.1  drochner {
    394  1.2  drochner 	bus_space_tag_t tag;
    395  1.2  drochner 	bus_space_handle_t handle;
    396  1.2  drochner 	vme_mapresc_t resc;
    397  1.2  drochner 	int res, i;
    398  1.2  drochner 	volatile u_int32_t dummy;
    399  1.2  drochner 
    400  1.2  drochner 	res = b3_2706_map_vme(vsc, addr, len, am, datasize, 0,
    401  1.2  drochner 			      &tag, &handle, &resc);
    402  1.2  drochner 	if (res)
    403  1.2  drochner 		return (res);
    404  1.2  drochner 
    405  1.2  drochner 	if (univ_pci_vmebuserr(&sc->univdata, 1))
    406  1.2  drochner 		printf("b3_2706_vme_badaddr: TA bit not clean - reset\n");
    407  1.2  drochner 
    408  1.2  drochner 	if (callback)
    409  1.2  drochner 		res = (*callback)(cbarg, tag, handle);
    410  1.2  drochner 	else {
    411  1.2  drochner 		for (i = 0; i < len;) {
    412  1.2  drochner 			switch (datasize) {
    413  1.2  drochner 			    case VME_D8:
    414  1.2  drochner 				dummy = bus_space_read_1(tag, handle, i);
    415  1.2  drochner 				i++;
    416  1.2  drochner 				break;
    417  1.2  drochner 			    case VME_D16:
    418  1.2  drochner 				dummy = bus_space_read_2(tag, handle, i);
    419  1.2  drochner 				i += 2;
    420  1.2  drochner 				break;
    421  1.2  drochner 			    case VME_D32:
    422  1.2  drochner 				dummy = bus_space_read_4(tag, handle, i);
    423  1.2  drochner 				i += 4;
    424  1.2  drochner 				break;
    425  1.2  drochner 			    default:
    426  1.2  drochner 				panic("b3_2706_vme_probe: invalid datasize %x",
    427  1.2  drochner 				      datasize);
    428  1.2  drochner 			}
    429  1.2  drochner 		}
    430  1.2  drochner 	}
    431  1.2  drochner 
    432  1.2  drochner 	if (univ_pci_vmebuserr(&sc->univdata, 0)) {
    433  1.2  drochner #ifdef BIT3DEBUG
    434  1.2  drochner 		printf("b3_2706_vme_badaddr: caught TA\n");
    435  1.2  drochner #endif
    436  1.2  drochner 		univ_pci_vmebuserr(&sc->univdata, 1);
    437  1.2  drochner 		res = EIO;
    438  1.2  drochner 	}
    439  1.2  drochner 
    440  1.2  drochner 	b3_2706_unmap_vme(vsc, resc);
    441  1.2  drochner 	return (res);
    442  1.1  drochner }
    443  1.1  drochner 
    444  1.1  drochner int
    445  1.1  drochner b3_2706_map_vmeint(vsc, level, vector, handlep)
    446  1.1  drochner 	void *vsc;
    447  1.1  drochner 	int level, vector;
    448  1.1  drochner 	vme_intr_handle_t *handlep;
    449  1.1  drochner {
    450  1.2  drochner 
    451  1.2  drochner 	*handlep = (void *)(long)((level << 8) | vector); /* XXX */
    452  1.2  drochner 	return (0);
    453  1.1  drochner }
    454  1.1  drochner 
    455  1.1  drochner void *
    456  1.1  drochner b3_2706_establish_vmeint(vsc, handle, prior, func, arg)
    457  1.1  drochner 	void *vsc;
    458  1.1  drochner 	vme_intr_handle_t handle;
    459  1.1  drochner 	int prior;
    460  1.1  drochner 	int (*func) __P((void *));
    461  1.1  drochner 	void *arg;
    462  1.1  drochner {
    463  1.2  drochner 	struct b3_2706_vmeintrhand *ih;
    464  1.2  drochner 	long lv;
    465  1.2  drochner 	int s;
    466  1.2  drochner 
    467  1.2  drochner 	/* no point in sleeping unless someone can free memory. */
    468  1.2  drochner 	ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
    469  1.2  drochner 	if (ih == NULL)
    470  1.2  drochner 		panic("b3_2706_map_vmeint: can't malloc handler info");
    471  1.2  drochner 
    472  1.2  drochner 	lv = (long)handle; /* XXX */
    473  1.2  drochner 
    474  1.2  drochner 	ih->ih_fun = func;
    475  1.2  drochner 	ih->ih_arg = arg;
    476  1.2  drochner 	ih->ih_level = lv >> 8;
    477  1.2  drochner 	ih->ih_vector = lv & 0xff;
    478  1.2  drochner 	ih->ih_prior = prior;
    479  1.2  drochner 	ih->ih_count = 0;
    480  1.2  drochner 
    481  1.2  drochner 	s = splhigh();
    482  1.2  drochner 	TAILQ_INSERT_TAIL(&(sc->intrhdls), ih, ih_next);
    483  1.2  drochner 	splx(s);
    484  1.2  drochner 
    485  1.2  drochner 	return (ih);
    486  1.1  drochner }
    487  1.1  drochner 
    488  1.1  drochner void
    489  1.1  drochner b3_2706_disestablish_vmeint(vsc, cookie)
    490  1.1  drochner 	void *vsc;
    491  1.1  drochner 	void *cookie;
    492  1.1  drochner {
    493  1.2  drochner 	struct b3_2706_vmeintrhand *ih = cookie;
    494  1.2  drochner 	int s;
    495  1.2  drochner 
    496  1.2  drochner 	if (!ih) {
    497  1.2  drochner 		printf("b3_2706_unmap_vmeint: NULL arg\n");
    498  1.2  drochner 		return;
    499  1.2  drochner 	}
    500  1.2  drochner 
    501  1.2  drochner 	s = splhigh();
    502  1.2  drochner 	TAILQ_REMOVE(&(sc->intrhdls), ih, ih_next);
    503  1.2  drochner 	splx(s);
    504  1.2  drochner 
    505  1.2  drochner 	free(ih, M_DEVBUF);
    506  1.2  drochner }
    507  1.2  drochner 
    508  1.2  drochner void
    509  1.2  drochner b3_2706_vmeint(vsc, level, vector)
    510  1.2  drochner 	void *vsc;
    511  1.2  drochner 	int level, vector;
    512  1.2  drochner {
    513  1.2  drochner 	struct b3_2706_vmeintrhand *ih;
    514  1.2  drochner 	int found;
    515  1.2  drochner 
    516  1.2  drochner #ifdef BIT3DEBUG
    517  1.2  drochner 	printf("b3_2706_vmeint: VME IRQ %d, vec %x\n", level, vector);
    518  1.2  drochner #endif
    519  1.2  drochner 	found = 0;
    520  1.2  drochner 
    521  1.2  drochner 	for (ih = sc->intrhdls.tqh_first; ih;
    522  1.2  drochner 	     ih = ih->ih_next.tqe_next) {
    523  1.2  drochner 		if ((ih->ih_level == level) &&
    524  1.2  drochner 		    ((ih->ih_vector == -1) ||
    525  1.2  drochner 		     (ih->ih_vector == vector))) {
    526  1.2  drochner 			int s, res;
    527  1.2  drochner 			/*
    528  1.2  drochner 			 * We should raise the interrupt level
    529  1.2  drochner 			 * to ih->ih_prior here. How to do this
    530  1.2  drochner 			 * machine-independantly?
    531  1.2  drochner 			 * To be safe, raise to the maximum.
    532  1.2  drochner 			 */
    533  1.2  drochner 			s = splhigh();
    534  1.2  drochner 			found |= (res = (*(ih->ih_fun))(ih->ih_arg));
    535  1.2  drochner 			splx(s);
    536  1.2  drochner 			if (res)
    537  1.2  drochner 				ih->ih_count++;
    538  1.2  drochner 			if (res == 1)
    539  1.2  drochner 				break;
    540  1.2  drochner 		}
    541  1.2  drochner 	}
    542  1.2  drochner 	if (!found)
    543  1.2  drochner 		sc->strayintrs++;
    544  1.1  drochner }
    545  1.1  drochner 
    546  1.1  drochner int
    547  1.1  drochner b3_2706_dmamap_create(vsc, len, am, datasize, swap,
    548  1.1  drochner 		      nsegs, segsz, bound,
    549  1.1  drochner 		      flags, mapp)
    550  1.1  drochner 	void *vsc;
    551  1.1  drochner 	vme_size_t len;
    552  1.1  drochner 	vme_am_t am;
    553  1.1  drochner 	vme_datasize_t datasize;
    554  1.1  drochner 	vme_swap_t swap;
    555  1.1  drochner 	int nsegs;
    556  1.1  drochner 	vme_size_t segsz;
    557  1.1  drochner 	vme_addr_t bound;
    558  1.1  drochner 	int flags;
    559  1.1  drochner 	bus_dmamap_t *mapp;
    560  1.1  drochner {
    561  1.1  drochner 	return (EINVAL);
    562  1.1  drochner }
    563  1.1  drochner 
    564  1.1  drochner void
    565  1.1  drochner b3_2706_dmamap_destroy(vsc, map)
    566  1.1  drochner 	void *vsc;
    567  1.1  drochner 	bus_dmamap_t map;
    568  1.1  drochner {
    569  1.1  drochner }
    570  1.1  drochner 
    571  1.1  drochner int
    572  1.1  drochner b3_2706_dmamem_alloc(vsc, len, am, datasizes, swap, segs, nsegs, rsegs, flags)
    573  1.1  drochner 	void *vsc;
    574  1.1  drochner 	vme_size_t len;
    575  1.1  drochner 	vme_am_t am;
    576  1.1  drochner 	vme_datasize_t datasizes;
    577  1.1  drochner 	vme_swap_t swap;
    578  1.1  drochner 	bus_dma_segment_t *segs;
    579  1.1  drochner 	int nsegs;
    580  1.1  drochner 	int *rsegs;
    581  1.1  drochner 	int flags;
    582  1.1  drochner {
    583  1.1  drochner 	return (EINVAL);
    584  1.1  drochner }
    585  1.1  drochner 
    586  1.1  drochner void
    587  1.1  drochner b3_2706_dmamem_free(vsc, segs, nsegs)
    588  1.1  drochner 	void *vsc;
    589  1.1  drochner 	bus_dma_segment_t *segs;
    590  1.1  drochner 	int nsegs;
    591  1.1  drochner {
    592  1.1  drochner }
    593  1.1  drochner 
    594  1.1  drochner #undef sc
    595