Home | History | Annotate | Line # | Download | only in pci
btvmeii.c revision 1.24.10.1
      1  1.24.10.1   thorpej /* $NetBSD: btvmeii.c,v 1.24.10.1 2021/03/21 21:09:13 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.24.10.1   thorpej __KERNEL_RCSID(0, "$NetBSD: btvmeii.c,v 1.24.10.1 2021/03/21 21:09:13 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.13        ad #include <sys/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.19    cegger static int b3_2706_match(device_t, cfdata_t, void *);
     58       1.19    cegger static void b3_2706_attach(device_t, device_t, void *);
     59        1.1  drochner 
     60        1.1  drochner /* exported via tag structs */
     61       1.10     perry int b3_2706_map_vme(void *, vme_addr_t, vme_size_t,
     62        1.1  drochner 		      vme_am_t, vme_datasize_t, vme_swap_t,
     63       1.10     perry 		      bus_space_tag_t *, bus_space_handle_t *, vme_mapresc_t*);
     64       1.10     perry void b3_2706_unmap_vme(void *, vme_mapresc_t);
     65        1.1  drochner 
     66       1.10     perry int b3_2706_vme_probe(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.10     perry 			void *);
     70        1.1  drochner 
     71       1.10     perry int b3_2706_map_vmeint(void *, int, int, vme_intr_handle_t *);
     72       1.10     perry void *b3_2706_establish_vmeint(void *, vme_intr_handle_t, int,
     73       1.10     perry 				 int (*)(void *), void *);
     74       1.10     perry void b3_2706_disestablish_vmeint(void *, void *);
     75       1.10     perry void b3_2706_vmeint(void *, int, int);
     76        1.1  drochner 
     77       1.10     perry int b3_2706_dmamap_create(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.10     perry 			    int, bus_dmamap_t *);
     81       1.10     perry void b3_2706_dmamap_destroy(void *, bus_dmamap_t);
     82        1.1  drochner 
     83       1.10     perry int b3_2706_dmamem_alloc(void *, vme_size_t,
     84        1.1  drochner 			      vme_am_t, vme_datasize_t, vme_swap_t,
     85       1.10     perry 			      bus_dma_segment_t *, int, int *, int);
     86       1.10     perry void b3_2706_dmamem_free(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.10     perry 	int (*ih_fun)(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 univ_pci_data univdata;
    107        1.1  drochner 	bus_space_tag_t swapt, vmet;
    108        1.1  drochner 	bus_space_handle_t swaph;
    109        1.1  drochner 	bus_addr_t vmepbase;
    110        1.1  drochner 
    111        1.1  drochner 	int windowused[8];
    112        1.1  drochner 	struct b3_2706_vmemaprescs vmemaprescs[8];
    113        1.1  drochner 	struct extent *vmeext;
    114        1.1  drochner 	char vmemap[EXTENT_FIXED_STORAGE_SIZE(8)];
    115        1.1  drochner 
    116        1.1  drochner 	struct vme_chipset_tag sc_vct;
    117        1.2  drochner 
    118        1.2  drochner 	/* list of VME interrupt handlers */
    119        1.2  drochner 	TAILQ_HEAD(, b3_2706_vmeintrhand) intrhdls;
    120        1.2  drochner 	int strayintrs;
    121        1.1  drochner };
    122        1.1  drochner 
    123       1.22       chs CFATTACH_DECL_NEW(btvmeii, sizeof(struct b3_2706_softc),
    124        1.8   thorpej     b3_2706_match, b3_2706_attach, NULL, NULL);
    125        1.1  drochner 
    126        1.1  drochner /*
    127        1.1  drochner  * The adapter consists of a DEC PCI-PCI-bridge with two
    128        1.1  drochner  * PCI devices behind it: A Tundra Universe as device 4 and
    129        1.1  drochner  * some FPGA with glue logics as device 8.
    130        1.1  drochner  * As long as the autoconf code doesn't provide more support
    131       1.21       wiz  * for dependent devices, we have to duplicate a part of the
    132        1.1  drochner  * "ppb" functions here.
    133        1.1  drochner  */
    134        1.1  drochner 
    135        1.1  drochner static int
    136       1.19    cegger b3_2706_match(device_t parent, cfdata_t match, void *aux)
    137        1.1  drochner {
    138        1.1  drochner 	struct pci_attach_args *pa = aux;
    139        1.1  drochner 	pci_chipset_tag_t pc = pa->pa_pc;
    140        1.1  drochner 	int secbus;
    141        1.1  drochner 	pcitag_t tag;
    142        1.1  drochner 	pcireg_t id;
    143        1.1  drochner 
    144        1.1  drochner 	if ((PCI_VENDOR(pa->pa_id) != PCI_VENDOR_DEC)
    145        1.1  drochner 	    || (PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_DEC_21152))
    146        1.1  drochner 		return (0);
    147        1.1  drochner 
    148       1.23   msaitoh 	secbus = PCI_BRIDGE_BUS_NUM_SECONDARY(pci_conf_read(pc, pa->pa_tag,
    149       1.23   msaitoh 		PCI_BRIDGE_BUS_REG));
    150        1.1  drochner 	if (secbus == 0) {
    151        1.1  drochner 		printf("b3_2706_match: ppb not configured\n");
    152        1.1  drochner 		return (0);
    153        1.1  drochner 	}
    154        1.1  drochner 
    155        1.1  drochner 	tag = pci_make_tag(pc, secbus, 4, 0);
    156        1.1  drochner 	id = pci_conf_read(pc, tag, PCI_ID_REG);
    157        1.1  drochner 
    158        1.1  drochner 	if ((PCI_VENDOR(id) != PCI_VENDOR_NEWBRIDGE)
    159        1.1  drochner 	    || (PCI_PRODUCT(id) != PCI_PRODUCT_NEWBRIDGE_CA91CX42)) {
    160        1.1  drochner #ifdef DEBUG
    161        1.1  drochner 		printf("b3_2706_match: no tundra\n");
    162        1.1  drochner #endif
    163        1.1  drochner 		return (0);
    164        1.1  drochner 	}
    165        1.1  drochner 
    166        1.1  drochner 	tag = pci_make_tag(pc, secbus, 8, 0);
    167        1.1  drochner 	id = pci_conf_read(pc, tag, PCI_ID_REG);
    168        1.1  drochner 
    169        1.1  drochner 	if ((PCI_VENDOR(id) != PCI_VENDOR_BIT3)
    170        1.1  drochner 	    || (PCI_PRODUCT(id) != PCI_PRODUCT_BIT3_PCIVME2706)) {
    171        1.1  drochner #ifdef DEBUG
    172        1.1  drochner 		printf("b3_2706_match: no bit3 chip\n");
    173        1.1  drochner #endif
    174        1.1  drochner 		return (0);
    175        1.1  drochner 	}
    176        1.1  drochner 
    177        1.1  drochner 	return (5); /* beat "ppb" */
    178        1.1  drochner }
    179        1.1  drochner 
    180        1.1  drochner static void
    181       1.19    cegger b3_2706_attach(device_t parent, device_t self, void *aux)
    182        1.1  drochner {
    183       1.20    cegger 	struct b3_2706_softc *sc = device_private(self);
    184        1.1  drochner 	struct pci_attach_args *pa = aux;
    185        1.1  drochner 	pci_chipset_tag_t pc = pa->pa_pc;
    186        1.1  drochner 	struct pci_attach_args aa;
    187        1.1  drochner 	int secbus;
    188        1.1  drochner 	pcireg_t intr;
    189        1.1  drochner 	pcitag_t tag;
    190        1.1  drochner 	bus_addr_t swappbase;
    191        1.1  drochner 	int i;
    192        1.1  drochner 
    193        1.1  drochner 	struct vmebus_attach_args vaa;
    194        1.1  drochner 
    195        1.9   thorpej 	aprint_naive(": VME bus adapter\n");
    196        1.9   thorpej 	aprint_normal("\n");
    197        1.1  drochner 
    198       1.23   msaitoh 	secbus = PCI_BRIDGE_BUS_NUM_SECONDARY(pci_conf_read(pc, pa->pa_tag,
    199       1.23   msaitoh 		PCI_BRIDGE_BUS_REG));
    200        1.1  drochner 
    201        1.3   thorpej 	memcpy(&aa, pa, sizeof(struct pci_attach_args));
    202        1.1  drochner 	aa.pa_device = 4;
    203        1.1  drochner 	aa.pa_function = 0;
    204        1.1  drochner 	aa.pa_tag = pci_make_tag(pc, secbus, 4, 0);
    205        1.1  drochner 	aa.pa_intrswiz += 4;
    206        1.1  drochner 	intr = pci_conf_read(pc, aa.pa_tag, PCI_INTERRUPT_REG);
    207        1.1  drochner 	/*
    208        1.1  drochner 	 * swizzle it based on the number of
    209        1.1  drochner 	 * busses we're behind and our device
    210        1.1  drochner 	 * number.
    211        1.1  drochner 	 */
    212        1.1  drochner 	aa.pa_intrpin =	((1 + aa.pa_intrswiz - 1) % 4) + 1;
    213        1.1  drochner 	aa.pa_intrline = PCI_INTERRUPT_LINE(intr);
    214        1.1  drochner 
    215       1.14    cegger 	if (univ_pci_attach(&sc->univdata, &aa, device_xname(self),
    216        1.2  drochner 			    b3_2706_vmeint, sc)) {
    217       1.14    cegger 		aprint_error_dev(self, "error initializing universe chip\n");
    218        1.1  drochner 		return;
    219        1.1  drochner 	}
    220        1.1  drochner 
    221        1.2  drochner 	/*
    222        1.2  drochner 	 * don't waste KVM - the byteswap register is aliased in
    223        1.2  drochner 	 * a 512k window, we need it only once
    224        1.2  drochner 	 */
    225        1.1  drochner 	tag = pci_make_tag(pc, secbus, 8, 0);
    226        1.1  drochner 	sc->swapt = pa->pa_memt;
    227        1.1  drochner 	if (pci_mapreg_info(pc, tag, 0x10,
    228        1.1  drochner 			    PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT,
    229        1.1  drochner 			    &swappbase, 0, 0) ||
    230        1.1  drochner 	    bus_space_map(sc->swapt, swappbase, 4, 0, &sc->swaph)) {
    231       1.14    cegger 		aprint_error_dev(self, "can't map byteswap register\n");
    232        1.1  drochner 		return;
    233        1.1  drochner 	}
    234        1.2  drochner 	/*
    235        1.2  drochner 	 * Set up cycle specific byteswap mode.
    236        1.2  drochner 	 * XXX Readback yields "all-ones" for me, and it doesn't seem
    237        1.2  drochner 	 * to matter what I write into the register - the data don't
    238        1.2  drochner 	 * get swapped. Adapter fault or documentation bug?
    239        1.2  drochner 	 */
    240        1.2  drochner 	bus_space_write_4(sc->swapt, sc->swaph, 0, 0x00000490);
    241        1.2  drochner 
    242        1.2  drochner 	/* VME space is mapped as needed */
    243        1.1  drochner 	sc->vmet = pa->pa_memt;
    244        1.1  drochner 	if (pci_mapreg_info(pc, tag, 0x14,
    245        1.1  drochner 			    PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT,
    246        1.1  drochner 			    &sc->vmepbase, 0, 0)) {
    247       1.14    cegger 		aprint_error_dev(self, "VME range not assigned\n");
    248        1.1  drochner 		return;
    249        1.1  drochner 	}
    250        1.2  drochner #ifdef BIT3DEBUG
    251       1.14    cegger 	aprint_debug_dev(self, "VME window @%lx\n",
    252        1.9   thorpej 	    (long)sc->vmepbase);
    253        1.2  drochner #endif
    254        1.1  drochner 
    255        1.1  drochner 	for (i = 0; i < 8; i++) {
    256        1.1  drochner 		sc->windowused[i] = 0;
    257        1.1  drochner 	}
    258        1.1  drochner 	sc->vmeext = extent_create("pcivme", sc->vmepbase,
    259        1.1  drochner 				   sc->vmepbase + 32*1024*1024 - 1, M_DEVBUF,
    260        1.1  drochner 				   sc->vmemap, sizeof(sc->vmemap),
    261        1.1  drochner 				   EX_NOCOALESCE);
    262        1.1  drochner 
    263        1.1  drochner 	sc->sc_vct.cookie = self;
    264        1.1  drochner 	sc->sc_vct.vct_probe = b3_2706_vme_probe;
    265        1.1  drochner 	sc->sc_vct.vct_map = b3_2706_map_vme;
    266        1.1  drochner 	sc->sc_vct.vct_unmap = b3_2706_unmap_vme;
    267        1.1  drochner 	sc->sc_vct.vct_int_map = b3_2706_map_vmeint;
    268        1.1  drochner 	sc->sc_vct.vct_int_establish = b3_2706_establish_vmeint;
    269        1.1  drochner 	sc->sc_vct.vct_int_disestablish = b3_2706_disestablish_vmeint;
    270        1.1  drochner 	sc->sc_vct.vct_dmamap_create = b3_2706_dmamap_create;
    271        1.1  drochner 	sc->sc_vct.vct_dmamap_destroy = b3_2706_dmamap_destroy;
    272        1.1  drochner 	sc->sc_vct.vct_dmamem_alloc = b3_2706_dmamem_alloc;
    273        1.1  drochner 	sc->sc_vct.vct_dmamem_free = b3_2706_dmamem_free;
    274        1.1  drochner 
    275        1.1  drochner 	vaa.va_vct = &(sc->sc_vct);
    276        1.1  drochner 	vaa.va_bdt = pa->pa_dmat; /* XXX */
    277        1.2  drochner 	vaa.va_slaveconfig = 0; /* XXX CSR window? */
    278        1.1  drochner 
    279  1.24.10.1   thorpej 	config_found(self, &vaa, 0, CFARG_EOL);
    280        1.1  drochner }
    281        1.1  drochner 
    282        1.1  drochner #define sc ((struct b3_2706_softc*)vsc)
    283        1.1  drochner 
    284        1.1  drochner int
    285       1.15       dsl b3_2706_map_vme(void *vsc, vme_addr_t vmeaddr, vme_size_t len, vme_am_t am, vme_datasize_t datasizes, vme_swap_t swap, bus_space_tag_t *tag, bus_space_handle_t *handle, vme_mapresc_t *resc)
    286        1.1  drochner {
    287        1.1  drochner 	int idx, i, wnd, res;
    288        1.1  drochner 	unsigned long boundary, maplen, pcibase;
    289        1.1  drochner 	vme_addr_t vmebase, vmeend;
    290        1.1  drochner 	static int windoworder[8] = {1, 2, 3, 5, 6, 7, 0, 4};
    291        1.1  drochner 
    292        1.1  drochner 	/* prefer windows with fine granularity for small mappings */
    293        1.1  drochner 	wnd = -1;
    294        1.1  drochner 	if (len <= 32*1024)
    295        1.1  drochner 		idx = 6;
    296        1.1  drochner 	else
    297        1.1  drochner 		idx = 0;
    298        1.1  drochner 	for (i = 0; i < 8; i++) {
    299        1.1  drochner 		if (!sc->windowused[windoworder[idx]]) {
    300        1.1  drochner 			wnd = windoworder[idx];
    301        1.1  drochner 			sc->windowused[wnd] = 1;
    302        1.1  drochner 			break;
    303        1.1  drochner 		}
    304        1.1  drochner 		idx = (idx + 1) % 8;
    305        1.1  drochner 	}
    306        1.1  drochner 	if (wnd == -1)
    307        1.1  drochner 		return (ENOSPC);
    308        1.1  drochner 
    309        1.1  drochner 	boundary = (wnd & 3) ? 64*1024 : 4*1024;
    310        1.1  drochner 
    311        1.1  drochner 	/* first mapped address */
    312        1.1  drochner 	vmebase = vmeaddr & ~(boundary - 1);
    313        1.1  drochner 	/* base of last mapped page */
    314        1.1  drochner 	vmeend = (vmeaddr + len - 1) & ~(boundary - 1);
    315        1.1  drochner 	/* bytes in outgoing window required */
    316        1.1  drochner 	maplen = vmeend - vmebase + boundary;
    317        1.1  drochner 
    318        1.2  drochner 	if (extent_alloc(sc->vmeext, maplen, boundary, 0, EX_FAST, &pcibase)) {
    319        1.2  drochner 		sc->windowused[wnd] = 0;
    320        1.1  drochner 		return (ENOMEM);
    321        1.2  drochner 	}
    322        1.1  drochner 
    323        1.1  drochner 	res = univ_pci_mapvme(&sc->univdata, wnd, vmebase, maplen,
    324        1.1  drochner 			      am, datasizes, pcibase);
    325        1.1  drochner 	if (res) {
    326        1.1  drochner 		extent_free(sc->vmeext, pcibase, maplen, 0);
    327        1.2  drochner 		sc->windowused[wnd] = 0;
    328        1.1  drochner 		return (res);
    329        1.1  drochner 	}
    330        1.1  drochner 
    331        1.1  drochner 	res = bus_space_map(sc->vmet, pcibase + (vmeaddr - vmebase), len,
    332        1.1  drochner 			    0, handle);
    333        1.1  drochner 	if (res) {
    334        1.1  drochner 		univ_pci_unmapvme(&sc->univdata, wnd);
    335        1.1  drochner 		extent_free(sc->vmeext, pcibase, maplen, 0);
    336        1.2  drochner 		sc->windowused[wnd] = 0;
    337        1.1  drochner 		return (res);
    338        1.1  drochner 	}
    339        1.1  drochner 
    340        1.1  drochner 	*tag = sc->vmet;
    341        1.1  drochner 
    342        1.1  drochner 	/*
    343        1.1  drochner 	 * save all data needed for later unmapping
    344        1.1  drochner 	 */
    345        1.1  drochner 	sc->vmemaprescs[wnd].wnd = wnd;
    346        1.1  drochner 	sc->vmemaprescs[wnd].pcibase = pcibase;
    347        1.1  drochner 	sc->vmemaprescs[wnd].maplen = maplen;
    348        1.1  drochner 	sc->vmemaprescs[wnd].handle = *handle;
    349        1.1  drochner 	sc->vmemaprescs[wnd].len = len;
    350        1.1  drochner 	*resc = &sc->vmemaprescs[wnd];
    351        1.1  drochner 	return (0);
    352        1.1  drochner }
    353        1.1  drochner 
    354        1.1  drochner void
    355       1.15       dsl b3_2706_unmap_vme(void *vsc, vme_mapresc_t resc)
    356        1.1  drochner {
    357        1.1  drochner 	struct b3_2706_vmemaprescs *r = resc;
    358        1.1  drochner 
    359        1.1  drochner 	bus_space_unmap(sc->vmet, r->handle, r->len);
    360        1.1  drochner 	extent_free(sc->vmeext, r->pcibase, r->maplen, 0);
    361        1.1  drochner 
    362        1.1  drochner 	if (!sc->windowused[r->wnd])
    363        1.1  drochner 		panic("b3_2706_unmap_vme: bad window");
    364        1.1  drochner 	univ_pci_unmapvme(&sc->univdata, r->wnd);
    365        1.1  drochner 	sc->windowused[r->wnd] = 0;
    366        1.1  drochner }
    367        1.1  drochner 
    368        1.1  drochner int
    369       1.17       dsl b3_2706_vme_probe(void *vsc, vme_addr_t addr, vme_size_t len, vme_am_t am, vme_datasize_t datasize, int (*callback)(void *, bus_space_tag_t, bus_space_handle_t), void *cbarg)
    370        1.1  drochner {
    371        1.2  drochner 	bus_space_tag_t tag;
    372        1.2  drochner 	bus_space_handle_t handle;
    373        1.2  drochner 	vme_mapresc_t resc;
    374        1.2  drochner 	int res, i;
    375        1.2  drochner 	volatile u_int32_t dummy;
    376        1.2  drochner 
    377        1.2  drochner 	res = b3_2706_map_vme(vsc, addr, len, am, datasize, 0,
    378        1.2  drochner 			      &tag, &handle, &resc);
    379        1.2  drochner 	if (res)
    380        1.2  drochner 		return (res);
    381        1.2  drochner 
    382        1.2  drochner 	if (univ_pci_vmebuserr(&sc->univdata, 1))
    383        1.2  drochner 		printf("b3_2706_vme_badaddr: TA bit not clean - reset\n");
    384        1.2  drochner 
    385        1.2  drochner 	if (callback)
    386        1.2  drochner 		res = (*callback)(cbarg, tag, handle);
    387        1.2  drochner 	else {
    388        1.2  drochner 		for (i = 0; i < len;) {
    389        1.2  drochner 			switch (datasize) {
    390        1.2  drochner 			    case VME_D8:
    391        1.2  drochner 				dummy = bus_space_read_1(tag, handle, i);
    392        1.2  drochner 				i++;
    393        1.2  drochner 				break;
    394        1.2  drochner 			    case VME_D16:
    395        1.2  drochner 				dummy = bus_space_read_2(tag, handle, i);
    396        1.2  drochner 				i += 2;
    397        1.2  drochner 				break;
    398        1.2  drochner 			    case VME_D32:
    399        1.2  drochner 				dummy = bus_space_read_4(tag, handle, i);
    400        1.2  drochner 				i += 4;
    401        1.2  drochner 				break;
    402        1.2  drochner 			    default:
    403        1.2  drochner 				panic("b3_2706_vme_probe: invalid datasize %x",
    404        1.2  drochner 				      datasize);
    405        1.2  drochner 			}
    406        1.2  drochner 		}
    407        1.2  drochner 	}
    408        1.2  drochner 
    409        1.2  drochner 	if (univ_pci_vmebuserr(&sc->univdata, 0)) {
    410        1.2  drochner #ifdef BIT3DEBUG
    411        1.2  drochner 		printf("b3_2706_vme_badaddr: caught TA\n");
    412        1.2  drochner #endif
    413        1.2  drochner 		univ_pci_vmebuserr(&sc->univdata, 1);
    414        1.2  drochner 		res = EIO;
    415        1.2  drochner 	}
    416        1.2  drochner 
    417        1.2  drochner 	b3_2706_unmap_vme(vsc, resc);
    418        1.2  drochner 	return (res);
    419        1.1  drochner }
    420        1.1  drochner 
    421        1.1  drochner int
    422       1.16       dsl b3_2706_map_vmeint(void *vsc, int level, int vector, vme_intr_handle_t *handlep)
    423        1.1  drochner {
    424        1.2  drochner 
    425        1.2  drochner 	*handlep = (void *)(long)((level << 8) | vector); /* XXX */
    426        1.2  drochner 	return (0);
    427        1.1  drochner }
    428        1.1  drochner 
    429        1.1  drochner void *
    430       1.17       dsl b3_2706_establish_vmeint(void *vsc, vme_intr_handle_t handle, int prior, int (*func)(void *), void *arg)
    431        1.1  drochner {
    432        1.2  drochner 	struct b3_2706_vmeintrhand *ih;
    433        1.2  drochner 	long lv;
    434        1.2  drochner 	int s;
    435        1.2  drochner 
    436       1.24       chs 	ih = malloc(sizeof *ih, M_DEVBUF, M_WAITOK);
    437        1.2  drochner 
    438        1.2  drochner 	lv = (long)handle; /* XXX */
    439        1.2  drochner 
    440        1.2  drochner 	ih->ih_fun = func;
    441        1.2  drochner 	ih->ih_arg = arg;
    442        1.2  drochner 	ih->ih_level = lv >> 8;
    443        1.2  drochner 	ih->ih_vector = lv & 0xff;
    444        1.2  drochner 	ih->ih_prior = prior;
    445        1.2  drochner 	ih->ih_count = 0;
    446        1.2  drochner 
    447        1.2  drochner 	s = splhigh();
    448        1.2  drochner 	TAILQ_INSERT_TAIL(&(sc->intrhdls), ih, ih_next);
    449        1.2  drochner 	splx(s);
    450        1.2  drochner 
    451        1.2  drochner 	return (ih);
    452        1.1  drochner }
    453        1.1  drochner 
    454        1.1  drochner void
    455       1.15       dsl b3_2706_disestablish_vmeint(void *vsc, void *cookie)
    456        1.1  drochner {
    457        1.2  drochner 	struct b3_2706_vmeintrhand *ih = cookie;
    458        1.2  drochner 	int s;
    459        1.2  drochner 
    460        1.2  drochner 	if (!ih) {
    461        1.2  drochner 		printf("b3_2706_unmap_vmeint: NULL arg\n");
    462        1.2  drochner 		return;
    463        1.2  drochner 	}
    464        1.2  drochner 
    465        1.2  drochner 	s = splhigh();
    466        1.2  drochner 	TAILQ_REMOVE(&(sc->intrhdls), ih, ih_next);
    467        1.2  drochner 	splx(s);
    468        1.2  drochner 
    469        1.2  drochner 	free(ih, M_DEVBUF);
    470        1.2  drochner }
    471        1.2  drochner 
    472        1.2  drochner void
    473       1.16       dsl b3_2706_vmeint(void *vsc, int level, int vector)
    474        1.2  drochner {
    475        1.2  drochner 	struct b3_2706_vmeintrhand *ih;
    476        1.2  drochner 	int found;
    477        1.2  drochner 
    478        1.2  drochner #ifdef BIT3DEBUG
    479        1.2  drochner 	printf("b3_2706_vmeint: VME IRQ %d, vec %x\n", level, vector);
    480        1.2  drochner #endif
    481        1.2  drochner 	found = 0;
    482        1.2  drochner 
    483        1.2  drochner 	for (ih = sc->intrhdls.tqh_first; ih;
    484        1.2  drochner 	     ih = ih->ih_next.tqe_next) {
    485        1.2  drochner 		if ((ih->ih_level == level) &&
    486        1.2  drochner 		    ((ih->ih_vector == -1) ||
    487        1.2  drochner 		     (ih->ih_vector == vector))) {
    488        1.2  drochner 			int s, res;
    489        1.2  drochner 			/*
    490        1.2  drochner 			 * We should raise the interrupt level
    491        1.2  drochner 			 * to ih->ih_prior here. How to do this
    492       1.12       wiz 			 * machine-independently?
    493        1.2  drochner 			 * To be safe, raise to the maximum.
    494        1.2  drochner 			 */
    495        1.2  drochner 			s = splhigh();
    496        1.2  drochner 			found |= (res = (*(ih->ih_fun))(ih->ih_arg));
    497        1.2  drochner 			splx(s);
    498        1.2  drochner 			if (res)
    499        1.2  drochner 				ih->ih_count++;
    500        1.2  drochner 			if (res == 1)
    501        1.2  drochner 				break;
    502        1.2  drochner 		}
    503        1.2  drochner 	}
    504        1.2  drochner 	if (!found)
    505        1.2  drochner 		sc->strayintrs++;
    506        1.1  drochner }
    507        1.1  drochner 
    508        1.1  drochner int
    509        1.1  drochner b3_2706_dmamap_create(vsc, len, am, datasize, swap,
    510        1.1  drochner 		      nsegs, segsz, bound,
    511        1.1  drochner 		      flags, mapp)
    512        1.1  drochner 	void *vsc;
    513        1.1  drochner 	vme_size_t len;
    514        1.1  drochner 	vme_am_t am;
    515        1.1  drochner 	vme_datasize_t datasize;
    516        1.1  drochner 	vme_swap_t swap;
    517        1.1  drochner 	int nsegs;
    518        1.1  drochner 	vme_size_t segsz;
    519        1.1  drochner 	vme_addr_t bound;
    520        1.1  drochner 	int flags;
    521        1.1  drochner 	bus_dmamap_t *mapp;
    522        1.1  drochner {
    523        1.1  drochner 	return (EINVAL);
    524        1.1  drochner }
    525        1.1  drochner 
    526        1.1  drochner void
    527       1.15       dsl b3_2706_dmamap_destroy(void *vsc, bus_dmamap_t map)
    528        1.1  drochner {
    529        1.1  drochner }
    530        1.1  drochner 
    531        1.1  drochner int
    532       1.15       dsl b3_2706_dmamem_alloc(void *vsc, vme_size_t len, vme_am_t am, vme_datasize_t datasizes, vme_swap_t swap, bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags)
    533        1.1  drochner {
    534        1.1  drochner 	return (EINVAL);
    535        1.1  drochner }
    536        1.1  drochner 
    537        1.1  drochner void
    538       1.15       dsl b3_2706_dmamem_free(void *vsc, bus_dma_segment_t *segs, int nsegs)
    539        1.1  drochner {
    540        1.1  drochner }
    541        1.1  drochner 
    542        1.1  drochner #undef sc
    543