Home | History | Annotate | Line # | Download | only in pci
btvmeii.c revision 1.23
      1  1.23   msaitoh /* $NetBSD: btvmeii.c,v 1.23 2019/03/01 09:26:00 msaitoh 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.23   msaitoh __KERNEL_RCSID(0, "$NetBSD: btvmeii.c,v 1.23 2019/03/01 09:26:00 msaitoh 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.1  drochner 	config_found(self, &vaa, 0);
    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.2  drochner 	/* no point in sleeping unless someone can free memory. */
    437   1.2  drochner 	ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
    438   1.2  drochner 	if (ih == NULL)
    439   1.2  drochner 		panic("b3_2706_map_vmeint: can't malloc handler info");
    440   1.2  drochner 
    441   1.2  drochner 	lv = (long)handle; /* XXX */
    442   1.2  drochner 
    443   1.2  drochner 	ih->ih_fun = func;
    444   1.2  drochner 	ih->ih_arg = arg;
    445   1.2  drochner 	ih->ih_level = lv >> 8;
    446   1.2  drochner 	ih->ih_vector = lv & 0xff;
    447   1.2  drochner 	ih->ih_prior = prior;
    448   1.2  drochner 	ih->ih_count = 0;
    449   1.2  drochner 
    450   1.2  drochner 	s = splhigh();
    451   1.2  drochner 	TAILQ_INSERT_TAIL(&(sc->intrhdls), ih, ih_next);
    452   1.2  drochner 	splx(s);
    453   1.2  drochner 
    454   1.2  drochner 	return (ih);
    455   1.1  drochner }
    456   1.1  drochner 
    457   1.1  drochner void
    458  1.15       dsl b3_2706_disestablish_vmeint(void *vsc, void *cookie)
    459   1.1  drochner {
    460   1.2  drochner 	struct b3_2706_vmeintrhand *ih = cookie;
    461   1.2  drochner 	int s;
    462   1.2  drochner 
    463   1.2  drochner 	if (!ih) {
    464   1.2  drochner 		printf("b3_2706_unmap_vmeint: NULL arg\n");
    465   1.2  drochner 		return;
    466   1.2  drochner 	}
    467   1.2  drochner 
    468   1.2  drochner 	s = splhigh();
    469   1.2  drochner 	TAILQ_REMOVE(&(sc->intrhdls), ih, ih_next);
    470   1.2  drochner 	splx(s);
    471   1.2  drochner 
    472   1.2  drochner 	free(ih, M_DEVBUF);
    473   1.2  drochner }
    474   1.2  drochner 
    475   1.2  drochner void
    476  1.16       dsl b3_2706_vmeint(void *vsc, int level, int vector)
    477   1.2  drochner {
    478   1.2  drochner 	struct b3_2706_vmeintrhand *ih;
    479   1.2  drochner 	int found;
    480   1.2  drochner 
    481   1.2  drochner #ifdef BIT3DEBUG
    482   1.2  drochner 	printf("b3_2706_vmeint: VME IRQ %d, vec %x\n", level, vector);
    483   1.2  drochner #endif
    484   1.2  drochner 	found = 0;
    485   1.2  drochner 
    486   1.2  drochner 	for (ih = sc->intrhdls.tqh_first; ih;
    487   1.2  drochner 	     ih = ih->ih_next.tqe_next) {
    488   1.2  drochner 		if ((ih->ih_level == level) &&
    489   1.2  drochner 		    ((ih->ih_vector == -1) ||
    490   1.2  drochner 		     (ih->ih_vector == vector))) {
    491   1.2  drochner 			int s, res;
    492   1.2  drochner 			/*
    493   1.2  drochner 			 * We should raise the interrupt level
    494   1.2  drochner 			 * to ih->ih_prior here. How to do this
    495  1.12       wiz 			 * machine-independently?
    496   1.2  drochner 			 * To be safe, raise to the maximum.
    497   1.2  drochner 			 */
    498   1.2  drochner 			s = splhigh();
    499   1.2  drochner 			found |= (res = (*(ih->ih_fun))(ih->ih_arg));
    500   1.2  drochner 			splx(s);
    501   1.2  drochner 			if (res)
    502   1.2  drochner 				ih->ih_count++;
    503   1.2  drochner 			if (res == 1)
    504   1.2  drochner 				break;
    505   1.2  drochner 		}
    506   1.2  drochner 	}
    507   1.2  drochner 	if (!found)
    508   1.2  drochner 		sc->strayintrs++;
    509   1.1  drochner }
    510   1.1  drochner 
    511   1.1  drochner int
    512   1.1  drochner b3_2706_dmamap_create(vsc, len, am, datasize, swap,
    513   1.1  drochner 		      nsegs, segsz, bound,
    514   1.1  drochner 		      flags, mapp)
    515   1.1  drochner 	void *vsc;
    516   1.1  drochner 	vme_size_t len;
    517   1.1  drochner 	vme_am_t am;
    518   1.1  drochner 	vme_datasize_t datasize;
    519   1.1  drochner 	vme_swap_t swap;
    520   1.1  drochner 	int nsegs;
    521   1.1  drochner 	vme_size_t segsz;
    522   1.1  drochner 	vme_addr_t bound;
    523   1.1  drochner 	int flags;
    524   1.1  drochner 	bus_dmamap_t *mapp;
    525   1.1  drochner {
    526   1.1  drochner 	return (EINVAL);
    527   1.1  drochner }
    528   1.1  drochner 
    529   1.1  drochner void
    530  1.15       dsl b3_2706_dmamap_destroy(void *vsc, bus_dmamap_t map)
    531   1.1  drochner {
    532   1.1  drochner }
    533   1.1  drochner 
    534   1.1  drochner int
    535  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)
    536   1.1  drochner {
    537   1.1  drochner 	return (EINVAL);
    538   1.1  drochner }
    539   1.1  drochner 
    540   1.1  drochner void
    541  1.15       dsl b3_2706_dmamem_free(void *vsc, bus_dma_segment_t *segs, int nsegs)
    542   1.1  drochner {
    543   1.1  drochner }
    544   1.1  drochner 
    545   1.1  drochner #undef sc
    546