Home | History | Annotate | Line # | Download | only in dev
vme_machdep.c revision 1.34.4.5
      1  1.34.4.5  nathanw /*	$NetBSD: vme_machdep.c,v 1.34.4.5 2002/08/27 23:45:30 nathanw Exp $	*/
      2  1.34.4.2       pk 
      3  1.34.4.2       pk /*-
      4  1.34.4.2       pk  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
      5  1.34.4.2       pk  * All rights reserved.
      6  1.34.4.2       pk  *
      7  1.34.4.2       pk  * This code is derived from software contributed to The NetBSD Foundation
      8  1.34.4.2       pk  * by Paul Kranenburg.
      9  1.34.4.2       pk  *
     10  1.34.4.2       pk  * Redistribution and use in source and binary forms, with or without
     11  1.34.4.2       pk  * modification, are permitted provided that the following conditions
     12  1.34.4.2       pk  * are met:
     13  1.34.4.2       pk  * 1. Redistributions of source code must retain the above copyright
     14  1.34.4.2       pk  *    notice, this list of conditions and the following disclaimer.
     15  1.34.4.2       pk  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.34.4.2       pk  *    notice, this list of conditions and the following disclaimer in the
     17  1.34.4.2       pk  *    documentation and/or other materials provided with the distribution.
     18  1.34.4.2       pk  * 3. All advertising materials mentioning features or use of this software
     19  1.34.4.2       pk  *    must display the following acknowledgement:
     20  1.34.4.2       pk  *        This product includes software developed by the NetBSD
     21  1.34.4.2       pk  *        Foundation, Inc. and its contributors.
     22  1.34.4.2       pk  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  1.34.4.2       pk  *    contributors may be used to endorse or promote products derived
     24  1.34.4.2       pk  *    from this software without specific prior written permission.
     25  1.34.4.2       pk  *
     26  1.34.4.2       pk  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  1.34.4.2       pk  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  1.34.4.2       pk  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  1.34.4.2       pk  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  1.34.4.2       pk  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  1.34.4.2       pk  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  1.34.4.2       pk  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  1.34.4.2       pk  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  1.34.4.2       pk  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  1.34.4.2       pk  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  1.34.4.2       pk  * POSSIBILITY OF SUCH DAMAGE.
     37  1.34.4.2       pk  */
     38  1.34.4.2       pk 
     39  1.34.4.2       pk #include <sys/param.h>
     40  1.34.4.2       pk #include <sys/extent.h>
     41  1.34.4.2       pk #include <sys/systm.h>
     42  1.34.4.2       pk #include <sys/device.h>
     43  1.34.4.2       pk #include <sys/malloc.h>
     44  1.34.4.2       pk #include <sys/errno.h>
     45  1.34.4.2       pk 
     46  1.34.4.2       pk #include <sys/proc.h>
     47  1.34.4.2       pk #include <sys/user.h>
     48  1.34.4.2       pk #include <sys/syslog.h>
     49  1.34.4.2       pk 
     50  1.34.4.2       pk #include <uvm/uvm_extern.h>
     51  1.34.4.2       pk 
     52  1.34.4.2       pk #define _SPARC_BUS_DMA_PRIVATE
     53  1.34.4.2       pk #include <machine/bus.h>
     54  1.34.4.2       pk #include <sparc/sparc/iommuvar.h>
     55  1.34.4.2       pk #include <machine/autoconf.h>
     56  1.34.4.2       pk #include <machine/oldmon.h>
     57  1.34.4.2       pk #include <machine/cpu.h>
     58  1.34.4.2       pk #include <machine/ctlreg.h>
     59  1.34.4.2       pk 
     60  1.34.4.2       pk #include <dev/vme/vmereg.h>
     61  1.34.4.2       pk #include <dev/vme/vmevar.h>
     62  1.34.4.2       pk 
     63  1.34.4.2       pk #include <sparc/sparc/asm.h>
     64  1.34.4.2       pk #include <sparc/sparc/vaddrs.h>
     65  1.34.4.2       pk #include <sparc/sparc/cpuvar.h>
     66  1.34.4.2       pk #include <sparc/dev/vmereg.h>
     67  1.34.4.2       pk 
     68  1.34.4.2       pk struct sparcvme_softc {
     69  1.34.4.2       pk 	struct device	 sc_dev;	/* base device */
     70  1.34.4.2       pk 	bus_space_tag_t	 sc_bustag;
     71  1.34.4.2       pk 	bus_dma_tag_t	 sc_dmatag;
     72  1.34.4.2       pk 	struct vmebusreg *sc_reg; 	/* VME control registers */
     73  1.34.4.2       pk 	struct vmebusvec *sc_vec;	/* VME interrupt vector */
     74  1.34.4.2       pk 	struct rom_range *sc_range;	/* ROM range property */
     75  1.34.4.2       pk 	int		 sc_nrange;
     76  1.34.4.2       pk 	volatile u_int32_t *sc_ioctags;	/* VME IO-cache tag registers */
     77  1.34.4.2       pk 	volatile u_int32_t *sc_iocflush;/* VME IO-cache flush registers */
     78  1.34.4.2       pk 	int 		 (*sc_vmeintr) __P((void *));
     79  1.34.4.2       pk };
     80  1.34.4.2       pk struct  sparcvme_softc *sparcvme_sc;/*XXX*/
     81  1.34.4.2       pk 
     82  1.34.4.2       pk /* autoconfiguration driver */
     83  1.34.4.2       pk static int	vmematch_iommu  __P((struct device *, struct cfdata *, void *));
     84  1.34.4.2       pk static void	vmeattach_iommu __P((struct device *, struct device *, void *));
     85  1.34.4.2       pk static int	vmematch_mainbus  __P((struct device *, struct cfdata *, void *));
     86  1.34.4.2       pk static void	vmeattach_mainbus __P((struct device *, struct device *, void *));
     87  1.34.4.2       pk #if defined(SUN4)
     88  1.34.4.2       pk int 		vmeintr4  __P((void *));
     89  1.34.4.2       pk #endif
     90  1.34.4.2       pk #if defined(SUN4M)
     91  1.34.4.2       pk int 		vmeintr4m __P((void *));
     92  1.34.4.2       pk static int	sparc_vme_error __P((void));
     93  1.34.4.2       pk #endif
     94  1.34.4.2       pk 
     95  1.34.4.2       pk 
     96  1.34.4.2       pk static int	sparc_vme_probe __P((void *, vme_addr_t, vme_size_t,
     97  1.34.4.2       pk 				vme_am_t, vme_datasize_t,
     98  1.34.4.2       pk 	int (*) __P((void *, bus_space_tag_t, bus_space_handle_t)), void *));
     99  1.34.4.2       pk static int	sparc_vme_map __P((void *, vme_addr_t, vme_size_t, vme_am_t,
    100  1.34.4.2       pk 				   vme_datasize_t, vme_swap_t,
    101  1.34.4.2       pk 				   bus_space_tag_t *, bus_space_handle_t *,
    102  1.34.4.2       pk 				   vme_mapresc_t *));
    103  1.34.4.2       pk static void	sparc_vme_unmap __P((void *, vme_mapresc_t));
    104  1.34.4.2       pk static int	sparc_vme_intr_map __P((void *, int, int, vme_intr_handle_t *));
    105  1.34.4.2       pk static const struct evcnt *sparc_vme_intr_evcnt __P((void *,
    106  1.34.4.2       pk 						     vme_intr_handle_t));
    107  1.34.4.2       pk static void *	sparc_vme_intr_establish __P((void *, vme_intr_handle_t, int,
    108  1.34.4.2       pk 					      int (*) __P((void *)), void *));
    109  1.34.4.2       pk static void	sparc_vme_intr_disestablish __P((void *, void *));
    110  1.34.4.2       pk 
    111  1.34.4.2       pk static int	vmebus_translate __P((struct sparcvme_softc *, vme_am_t,
    112  1.34.4.3  nathanw 				      vme_addr_t, bus_addr_t *));
    113  1.34.4.2       pk #if defined(SUN4M)
    114  1.34.4.2       pk static void	sparc_vme_iommu_barrier __P(( bus_space_tag_t, bus_space_handle_t,
    115  1.34.4.2       pk 					  bus_size_t, bus_size_t, int));
    116  1.34.4.2       pk 
    117  1.34.4.2       pk #endif
    118  1.34.4.2       pk 
    119  1.34.4.2       pk /*
    120  1.34.4.2       pk  * DMA functions.
    121  1.34.4.2       pk  */
    122  1.34.4.2       pk static void	sparc_vct_dmamap_destroy __P((void *, bus_dmamap_t));
    123  1.34.4.2       pk 
    124  1.34.4.2       pk #if defined(SUN4)
    125  1.34.4.2       pk static int	sparc_vct4_dmamap_create __P((void *, vme_size_t, vme_am_t,
    126  1.34.4.2       pk 		    vme_datasize_t, vme_swap_t, int, vme_size_t, vme_addr_t,
    127  1.34.4.2       pk 		    int, bus_dmamap_t *));
    128  1.34.4.2       pk static int	sparc_vme4_dmamap_load __P((bus_dma_tag_t, bus_dmamap_t, void *,
    129  1.34.4.2       pk 		    bus_size_t, struct proc *, int));
    130  1.34.4.2       pk static void	sparc_vme4_dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t));
    131  1.34.4.2       pk static void	sparc_vme4_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t,
    132  1.34.4.2       pk 		    bus_addr_t, bus_size_t, int));
    133  1.34.4.2       pk #endif
    134  1.34.4.2       pk 
    135  1.34.4.2       pk #if defined(SUN4M)
    136  1.34.4.2       pk static int	sparc_vct_iommu_dmamap_create __P((void *, vme_size_t, vme_am_t,
    137  1.34.4.2       pk 		    vme_datasize_t, vme_swap_t, int, vme_size_t, vme_addr_t,
    138  1.34.4.2       pk 		    int, bus_dmamap_t *));
    139  1.34.4.2       pk static int	sparc_vme_iommu_dmamap_create __P((bus_dma_tag_t, bus_size_t,
    140  1.34.4.2       pk 		    int, bus_size_t, bus_size_t, int, bus_dmamap_t *));
    141  1.34.4.2       pk 
    142  1.34.4.2       pk static int	sparc_vme_iommu_dmamap_load __P((bus_dma_tag_t, bus_dmamap_t,
    143  1.34.4.2       pk 		    void *, bus_size_t, struct proc *, int));
    144  1.34.4.2       pk static void	sparc_vme_iommu_dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t));
    145  1.34.4.2       pk static void	sparc_vme_iommu_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t,
    146  1.34.4.2       pk 		    bus_addr_t, bus_size_t, int));
    147  1.34.4.2       pk #endif
    148  1.34.4.2       pk 
    149  1.34.4.2       pk static int	sparc_vme_dmamem_map __P((bus_dma_tag_t, bus_dma_segment_t *,
    150  1.34.4.2       pk 		    int, size_t, caddr_t *, int));
    151  1.34.4.2       pk #if 0
    152  1.34.4.2       pk static void	sparc_vme_dmamap_destroy __P((bus_dma_tag_t, bus_dmamap_t));
    153  1.34.4.2       pk static void	sparc_vme_dmamem_unmap __P((bus_dma_tag_t, caddr_t, size_t));
    154  1.34.4.2       pk static paddr_t	sparc_vme_dmamem_mmap __P((bus_dma_tag_t,
    155  1.34.4.2       pk 		    bus_dma_segment_t *, int, off_t, int, int));
    156  1.34.4.2       pk #endif
    157  1.34.4.2       pk 
    158  1.34.4.2       pk int sparc_vme_mmap_cookie __P((vme_addr_t, vme_am_t, bus_space_handle_t *));
    159  1.34.4.2       pk 
    160  1.34.4.2       pk struct cfattach vme_mainbus_ca = {
    161  1.34.4.2       pk 	sizeof(struct sparcvme_softc), vmematch_mainbus, vmeattach_mainbus
    162  1.34.4.2       pk };
    163  1.34.4.2       pk 
    164  1.34.4.2       pk struct cfattach vme_iommu_ca = {
    165  1.34.4.2       pk 	sizeof(struct sparcvme_softc), vmematch_iommu, vmeattach_iommu
    166  1.34.4.2       pk };
    167  1.34.4.2       pk 
    168  1.34.4.2       pk int	(*vmeerr_handler) __P((void));
    169  1.34.4.2       pk 
    170  1.34.4.2       pk #define VMEMOD_D32 0x40 /* ??? */
    171  1.34.4.2       pk 
    172  1.34.4.2       pk /* If the PROM does not provide the `ranges' property, we make up our own */
    173  1.34.4.2       pk struct rom_range vmebus_translations[] = {
    174  1.34.4.2       pk #define _DS (VME_AM_MBO | VME_AM_SUPER | VME_AM_DATA)
    175  1.34.4.2       pk 	{ VME_AM_A16|_DS, 0, PMAP_VME16, 0xffff0000, 0 },
    176  1.34.4.2       pk 	{ VME_AM_A24|_DS, 0, PMAP_VME16, 0xff000000, 0 },
    177  1.34.4.2       pk 	{ VME_AM_A32|_DS, 0, PMAP_VME16, 0x00000000, 0 },
    178  1.34.4.2       pk 	{ VME_AM_A16|VMEMOD_D32|_DS, 0, PMAP_VME32, 0xffff0000, 0 },
    179  1.34.4.2       pk 	{ VME_AM_A24|VMEMOD_D32|_DS, 0, PMAP_VME32, 0xff000000, 0 },
    180  1.34.4.2       pk 	{ VME_AM_A32|VMEMOD_D32|_DS, 0, PMAP_VME32, 0x00000000, 0 }
    181  1.34.4.2       pk #undef _DS
    182  1.34.4.2       pk };
    183  1.34.4.2       pk 
    184  1.34.4.2       pk /*
    185  1.34.4.2       pk  * The VME bus logic on sun4 machines maps DMA requests in the first MB
    186  1.34.4.2       pk  * of VME space to the last MB of DVMA space. `vme_dvmamap' is used
    187  1.34.4.2       pk  * for DVMA space allocations. The DMA addresses returned by
    188  1.34.4.2       pk  * bus_dmamap_load*() must be relocated by -VME4_DVMA_BASE.
    189  1.34.4.2       pk  */
    190  1.34.4.2       pk struct extent *vme_dvmamap;
    191  1.34.4.2       pk 
    192  1.34.4.2       pk /*
    193  1.34.4.2       pk  * The VME hardware on the sun4m IOMMU maps the first 8MB of 32-bit
    194  1.34.4.2       pk  * VME space to the last 8MB of DVMA space and the first 1MB of
    195  1.34.4.2       pk  * 24-bit VME space to the first 1MB of the last 8MB of DVMA space
    196  1.34.4.2       pk  * (thus 24-bit VME space overlaps the first 1MB of of 32-bit space).
    197  1.34.4.2       pk  * The following constants define subregions in the IOMMU DVMA map
    198  1.34.4.2       pk  * for VME DVMA allocations.  The DMA addresses returned by
    199  1.34.4.2       pk  * bus_dmamap_load*() must be relocated by -VME_IOMMU_DVMA_BASE.
    200  1.34.4.2       pk  */
    201  1.34.4.2       pk #define VME_IOMMU_DVMA_BASE		0xff800000
    202  1.34.4.2       pk #define VME_IOMMU_DVMA_AM24_BASE	VME_IOMMU_DVMA_BASE
    203  1.34.4.2       pk #define VME_IOMMU_DVMA_AM24_END		0xff900000
    204  1.34.4.2       pk #define VME_IOMMU_DVMA_AM32_BASE	VME_IOMMU_DVMA_BASE
    205  1.34.4.2       pk #define VME_IOMMU_DVMA_AM32_END		IOMMU_DVMA_END
    206  1.34.4.2       pk 
    207  1.34.4.2       pk struct sparc_bus_space_tag sparc_vme_bus_tag = {
    208  1.34.4.2       pk 	NULL, /* cookie */
    209  1.34.4.2       pk 	NULL, /* parent bus tag */
    210  1.34.4.2       pk 	NULL, /* bus_map */
    211  1.34.4.2       pk 	NULL, /* bus_unmap */
    212  1.34.4.2       pk 	NULL, /* bus_subregion */
    213  1.34.4.2       pk 	NULL  /* barrier */
    214  1.34.4.2       pk };
    215  1.34.4.2       pk 
    216  1.34.4.2       pk struct vme_chipset_tag sparc_vme_chipset_tag = {
    217  1.34.4.2       pk 	NULL,
    218  1.34.4.2       pk 	sparc_vme_map,
    219  1.34.4.2       pk 	sparc_vme_unmap,
    220  1.34.4.2       pk 	sparc_vme_probe,
    221  1.34.4.2       pk 	sparc_vme_intr_map,
    222  1.34.4.2       pk 	sparc_vme_intr_evcnt,
    223  1.34.4.2       pk 	sparc_vme_intr_establish,
    224  1.34.4.2       pk 	sparc_vme_intr_disestablish,
    225  1.34.4.2       pk 	0, 0, 0 /* bus specific DMA stuff */
    226  1.34.4.2       pk };
    227  1.34.4.2       pk 
    228  1.34.4.2       pk 
    229  1.34.4.2       pk #if defined(SUN4)
    230  1.34.4.2       pk struct sparc_bus_dma_tag sparc_vme4_dma_tag = {
    231  1.34.4.2       pk 	NULL,	/* cookie */
    232  1.34.4.2       pk 	_bus_dmamap_create,
    233  1.34.4.2       pk 	_bus_dmamap_destroy,
    234  1.34.4.2       pk 	sparc_vme4_dmamap_load,
    235  1.34.4.2       pk 	_bus_dmamap_load_mbuf,
    236  1.34.4.2       pk 	_bus_dmamap_load_uio,
    237  1.34.4.2       pk 	_bus_dmamap_load_raw,
    238  1.34.4.2       pk 	sparc_vme4_dmamap_unload,
    239  1.34.4.2       pk 	sparc_vme4_dmamap_sync,
    240  1.34.4.2       pk 
    241  1.34.4.2       pk 	_bus_dmamem_alloc,
    242  1.34.4.2       pk 	_bus_dmamem_free,
    243  1.34.4.2       pk 	sparc_vme_dmamem_map,
    244  1.34.4.2       pk 	_bus_dmamem_unmap,
    245  1.34.4.2       pk 	_bus_dmamem_mmap
    246  1.34.4.2       pk };
    247  1.34.4.2       pk #endif
    248  1.34.4.2       pk 
    249  1.34.4.2       pk #if defined(SUN4M)
    250  1.34.4.2       pk struct sparc_bus_dma_tag sparc_vme_iommu_dma_tag = {
    251  1.34.4.2       pk 	NULL,	/* cookie */
    252  1.34.4.2       pk 	sparc_vme_iommu_dmamap_create,
    253  1.34.4.2       pk 	_bus_dmamap_destroy,
    254  1.34.4.2       pk 	sparc_vme_iommu_dmamap_load,
    255  1.34.4.2       pk 	_bus_dmamap_load_mbuf,
    256  1.34.4.2       pk 	_bus_dmamap_load_uio,
    257  1.34.4.2       pk 	_bus_dmamap_load_raw,
    258  1.34.4.2       pk 	sparc_vme_iommu_dmamap_unload,
    259  1.34.4.2       pk 	sparc_vme_iommu_dmamap_sync,
    260  1.34.4.2       pk 
    261  1.34.4.2       pk 	_bus_dmamem_alloc,
    262  1.34.4.2       pk 	_bus_dmamem_free,
    263  1.34.4.2       pk 	sparc_vme_dmamem_map,
    264  1.34.4.2       pk 	_bus_dmamem_unmap,
    265  1.34.4.2       pk 	_bus_dmamem_mmap
    266  1.34.4.2       pk };
    267  1.34.4.2       pk #endif
    268  1.34.4.2       pk 
    269  1.34.4.2       pk 
    270  1.34.4.2       pk int
    271  1.34.4.2       pk vmematch_mainbus(parent, cf, aux)
    272  1.34.4.2       pk 	struct device *parent;
    273  1.34.4.2       pk 	struct cfdata *cf;
    274  1.34.4.2       pk 	void *aux;
    275  1.34.4.2       pk {
    276  1.34.4.2       pk 	struct mainbus_attach_args *ma = aux;
    277  1.34.4.2       pk 
    278  1.34.4.2       pk 	if (!CPU_ISSUN4)
    279  1.34.4.2       pk 		return (0);
    280  1.34.4.2       pk 
    281  1.34.4.2       pk 	return (strcmp("vme", ma->ma_name) == 0);
    282  1.34.4.2       pk }
    283  1.34.4.2       pk 
    284  1.34.4.2       pk int
    285  1.34.4.2       pk vmematch_iommu(parent, cf, aux)
    286  1.34.4.2       pk 	struct device *parent;
    287  1.34.4.2       pk 	struct cfdata *cf;
    288  1.34.4.2       pk 	void *aux;
    289  1.34.4.2       pk {
    290  1.34.4.2       pk 	struct iommu_attach_args *ia = aux;
    291  1.34.4.2       pk 
    292  1.34.4.2       pk 	return (strcmp("vme", ia->iom_name) == 0);
    293  1.34.4.2       pk }
    294  1.34.4.2       pk 
    295  1.34.4.2       pk 
    296  1.34.4.2       pk void
    297  1.34.4.2       pk vmeattach_mainbus(parent, self, aux)
    298  1.34.4.2       pk 	struct device *parent, *self;
    299  1.34.4.2       pk 	void *aux;
    300  1.34.4.2       pk {
    301  1.34.4.2       pk #if defined(SUN4)
    302  1.34.4.2       pk 	struct mainbus_attach_args *ma = aux;
    303  1.34.4.2       pk 	struct sparcvme_softc *sc = (struct sparcvme_softc *)self;
    304  1.34.4.2       pk 	struct vmebus_attach_args vba;
    305  1.34.4.2       pk 
    306  1.34.4.2       pk 	if (self->dv_unit > 0) {
    307  1.34.4.2       pk 		printf(" unsupported\n");
    308  1.34.4.2       pk 		return;
    309  1.34.4.2       pk 	}
    310  1.34.4.2       pk 
    311  1.34.4.2       pk 	sc->sc_bustag = ma->ma_bustag;
    312  1.34.4.2       pk 	sc->sc_dmatag = ma->ma_dmatag;
    313  1.34.4.2       pk 
    314  1.34.4.2       pk 	/* VME interrupt entry point */
    315  1.34.4.2       pk 	sc->sc_vmeintr = vmeintr4;
    316  1.34.4.2       pk 
    317  1.34.4.2       pk /*XXX*/	sparc_vme_chipset_tag.cookie = self;
    318  1.34.4.2       pk /*XXX*/	sparc_vme_chipset_tag.vct_dmamap_create = sparc_vct4_dmamap_create;
    319  1.34.4.2       pk /*XXX*/	sparc_vme_chipset_tag.vct_dmamap_destroy = sparc_vct_dmamap_destroy;
    320  1.34.4.2       pk /*XXX*/	sparc_vme4_dma_tag._cookie = self;
    321  1.34.4.2       pk 
    322  1.34.4.2       pk #if 0
    323  1.34.4.2       pk 	sparc_vme_bus_tag.parent = ma->ma_bustag;
    324  1.34.4.2       pk 	vba.vba_bustag = &sparc_vme_bus_tag;
    325  1.34.4.2       pk #endif
    326  1.34.4.2       pk 	vba.va_vct = &sparc_vme_chipset_tag;
    327  1.34.4.2       pk 	vba.va_bdt = &sparc_vme4_dma_tag;
    328  1.34.4.2       pk 	vba.va_slaveconfig = 0;
    329  1.34.4.2       pk 
    330  1.34.4.2       pk 	/* Fall back to our own `range' construction */
    331  1.34.4.2       pk 	sc->sc_range = vmebus_translations;
    332  1.34.4.2       pk 	sc->sc_nrange =
    333  1.34.4.2       pk 		sizeof(vmebus_translations)/sizeof(vmebus_translations[0]);
    334  1.34.4.2       pk 
    335  1.34.4.2       pk 	vme_dvmamap = extent_create("vmedvma", VME4_DVMA_BASE, VME4_DVMA_END,
    336  1.34.4.2       pk 				    M_DEVBUF, 0, 0, EX_NOWAIT);
    337  1.34.4.2       pk 	if (vme_dvmamap == NULL)
    338  1.34.4.2       pk 		panic("vme: unable to allocate DVMA map");
    339  1.34.4.2       pk 
    340  1.34.4.2       pk 	printf("\n");
    341  1.34.4.2       pk 	(void)config_found(self, &vba, 0);
    342  1.34.4.2       pk 
    343  1.34.4.2       pk #endif
    344  1.34.4.2       pk 	return;
    345  1.34.4.2       pk }
    346  1.34.4.2       pk 
    347  1.34.4.2       pk /* sun4m vmebus */
    348  1.34.4.2       pk void
    349  1.34.4.2       pk vmeattach_iommu(parent, self, aux)
    350  1.34.4.2       pk 	struct device *parent, *self;
    351  1.34.4.2       pk 	void *aux;
    352  1.34.4.2       pk {
    353  1.34.4.2       pk #if defined(SUN4M)
    354  1.34.4.2       pk 	struct sparcvme_softc *sc = (struct sparcvme_softc *)self;
    355  1.34.4.2       pk 	struct iommu_attach_args *ia = aux;
    356  1.34.4.2       pk 	struct vmebus_attach_args vba;
    357  1.34.4.2       pk 	bus_space_handle_t bh;
    358  1.34.4.2       pk 	int node;
    359  1.34.4.2       pk 	int cline;
    360  1.34.4.2       pk 
    361  1.34.4.2       pk 	if (self->dv_unit > 0) {
    362  1.34.4.2       pk 		printf(" unsupported\n");
    363  1.34.4.2       pk 		return;
    364  1.34.4.2       pk 	}
    365  1.34.4.2       pk 
    366  1.34.4.2       pk 	sc->sc_bustag = ia->iom_bustag;
    367  1.34.4.2       pk 	sc->sc_dmatag = ia->iom_dmatag;
    368  1.34.4.2       pk 
    369  1.34.4.2       pk 	/* VME interrupt entry point */
    370  1.34.4.2       pk 	sc->sc_vmeintr = vmeintr4m;
    371  1.34.4.2       pk 
    372  1.34.4.2       pk /*XXX*/	sparc_vme_chipset_tag.cookie = self;
    373  1.34.4.2       pk /*XXX*/	sparc_vme_chipset_tag.vct_dmamap_create = sparc_vct_iommu_dmamap_create;
    374  1.34.4.2       pk /*XXX*/	sparc_vme_chipset_tag.vct_dmamap_destroy = sparc_vct_dmamap_destroy;
    375  1.34.4.2       pk /*XXX*/	sparc_vme_iommu_dma_tag._cookie = self;
    376  1.34.4.2       pk 	sparc_vme_bus_tag.sparc_bus_barrier = sparc_vme_iommu_barrier;
    377  1.34.4.2       pk 
    378  1.34.4.2       pk #if 0
    379  1.34.4.2       pk 	vba.vba_bustag = &sparc_vme_bus_tag;
    380  1.34.4.2       pk #endif
    381  1.34.4.2       pk 	vba.va_vct = &sparc_vme_chipset_tag;
    382  1.34.4.2       pk 	vba.va_bdt = &sparc_vme_iommu_dma_tag;
    383  1.34.4.2       pk 	vba.va_slaveconfig = 0;
    384  1.34.4.2       pk 
    385  1.34.4.2       pk 	node = ia->iom_node;
    386  1.34.4.2       pk 
    387  1.34.4.2       pk 	/*
    388  1.34.4.2       pk 	 * Map VME control space
    389  1.34.4.2       pk 	 */
    390  1.34.4.2       pk 	if (ia->iom_nreg < 2) {
    391  1.34.4.2       pk 		printf("%s: only %d register sets\n", self->dv_xname,
    392  1.34.4.2       pk 			ia->iom_nreg);
    393  1.34.4.2       pk 		return;
    394  1.34.4.2       pk 	}
    395  1.34.4.2       pk 
    396  1.34.4.3  nathanw 	if (bus_space_map(ia->iom_bustag,
    397  1.34.4.5  nathanw 			  (bus_addr_t) BUS_ADDR(ia->iom_reg[0].oa_space,
    398  1.34.4.5  nathanw 						ia->iom_reg[0].oa_base),
    399  1.34.4.5  nathanw 			  (bus_size_t)ia->iom_reg[0].oa_size,
    400  1.34.4.2       pk 			  BUS_SPACE_MAP_LINEAR,
    401  1.34.4.3  nathanw 			  &bh) != 0) {
    402  1.34.4.2       pk 		panic("%s: can't map vmebusreg", self->dv_xname);
    403  1.34.4.2       pk 	}
    404  1.34.4.2       pk 	sc->sc_reg = (struct vmebusreg *)bh;
    405  1.34.4.2       pk 
    406  1.34.4.3  nathanw 	if (bus_space_map(ia->iom_bustag,
    407  1.34.4.5  nathanw 			  (bus_addr_t) BUS_ADDR(ia->iom_reg[1].oa_space,
    408  1.34.4.5  nathanw 						ia->iom_reg[1].oa_base),
    409  1.34.4.5  nathanw 			  (bus_size_t)ia->iom_reg[1].oa_size,
    410  1.34.4.2       pk 			  BUS_SPACE_MAP_LINEAR,
    411  1.34.4.3  nathanw 			  &bh) != 0) {
    412  1.34.4.2       pk 		panic("%s: can't map vmebusvec", self->dv_xname);
    413  1.34.4.2       pk 	}
    414  1.34.4.2       pk 	sc->sc_vec = (struct vmebusvec *)bh;
    415  1.34.4.2       pk 
    416  1.34.4.2       pk 	/*
    417  1.34.4.2       pk 	 * Map VME IO cache tags and flush control.
    418  1.34.4.2       pk 	 */
    419  1.34.4.3  nathanw 	if (bus_space_map(ia->iom_bustag,
    420  1.34.4.3  nathanw 			  (bus_addr_t) BUS_ADDR(
    421  1.34.4.5  nathanw 				ia->iom_reg[1].oa_space,
    422  1.34.4.5  nathanw 				ia->iom_reg[1].oa_base + VME_IOC_TAGOFFSET),
    423  1.34.4.2       pk 			  VME_IOC_SIZE,
    424  1.34.4.2       pk 			  BUS_SPACE_MAP_LINEAR,
    425  1.34.4.3  nathanw 			  &bh) != 0) {
    426  1.34.4.2       pk 		panic("%s: can't map IOC tags", self->dv_xname);
    427  1.34.4.2       pk 	}
    428  1.34.4.2       pk 	sc->sc_ioctags = (u_int32_t *)bh;
    429  1.34.4.2       pk 
    430  1.34.4.3  nathanw 	if (bus_space_map(ia->iom_bustag,
    431  1.34.4.3  nathanw 			  (bus_addr_t) BUS_ADDR(
    432  1.34.4.5  nathanw 				ia->iom_reg[1].oa_space,
    433  1.34.4.5  nathanw 				ia->iom_reg[1].oa_base + VME_IOC_FLUSHOFFSET),
    434  1.34.4.2       pk 			  VME_IOC_SIZE,
    435  1.34.4.2       pk 			  BUS_SPACE_MAP_LINEAR,
    436  1.34.4.3  nathanw 			  &bh) != 0) {
    437  1.34.4.2       pk 		panic("%s: can't map IOC flush registers", self->dv_xname);
    438  1.34.4.2       pk 	}
    439  1.34.4.2       pk 	sc->sc_iocflush = (u_int32_t *)bh;
    440  1.34.4.2       pk 
    441  1.34.4.2       pk /*XXX*/	sparc_vme_bus_tag.cookie = sc->sc_reg;
    442  1.34.4.2       pk 
    443  1.34.4.2       pk 	/*
    444  1.34.4.2       pk 	 * Get "range" property.
    445  1.34.4.2       pk 	 */
    446  1.34.4.2       pk 	if (PROM_getprop(node, "ranges", sizeof(struct rom_range),
    447  1.34.4.2       pk 		    &sc->sc_nrange, (void **)&sc->sc_range) != 0) {
    448  1.34.4.2       pk 		panic("%s: can't get ranges property", self->dv_xname);
    449  1.34.4.2       pk 	}
    450  1.34.4.2       pk 
    451  1.34.4.2       pk 	sparcvme_sc = sc;
    452  1.34.4.2       pk 	vmeerr_handler = sparc_vme_error;
    453  1.34.4.2       pk 
    454  1.34.4.2       pk 	/*
    455  1.34.4.2       pk 	 * Invalidate all IO-cache entries.
    456  1.34.4.2       pk 	 */
    457  1.34.4.2       pk 	for (cline = VME_IOC_SIZE/VME_IOC_LINESZ; cline > 0;) {
    458  1.34.4.2       pk 		sc->sc_ioctags[--cline] = 0;
    459  1.34.4.2       pk 	}
    460  1.34.4.2       pk 
    461  1.34.4.2       pk 	/* Enable IO-cache */
    462  1.34.4.2       pk 	sc->sc_reg->vmebus_cr |= VMEBUS_CR_C;
    463  1.34.4.2       pk 
    464  1.34.4.2       pk 	printf(": version 0x%x\n",
    465  1.34.4.2       pk 	       sc->sc_reg->vmebus_cr & VMEBUS_CR_IMPL);
    466  1.34.4.2       pk 
    467  1.34.4.2       pk 	(void)config_found(self, &vba, 0);
    468  1.34.4.2       pk #endif
    469  1.34.4.2       pk }
    470  1.34.4.2       pk 
    471  1.34.4.2       pk #if defined(SUN4M)
    472  1.34.4.2       pk static int
    473  1.34.4.2       pk sparc_vme_error()
    474  1.34.4.2       pk {
    475  1.34.4.2       pk 	struct sparcvme_softc *sc = sparcvme_sc;
    476  1.34.4.2       pk 	u_int32_t afsr, afpa;
    477  1.34.4.2       pk 	char bits[64];
    478  1.34.4.2       pk 
    479  1.34.4.2       pk 	afsr = sc->sc_reg->vmebus_afsr;
    480  1.34.4.2       pk 	afpa = sc->sc_reg->vmebus_afar;
    481  1.34.4.2       pk 	printf("VME error:\n\tAFSR %s\n",
    482  1.34.4.2       pk 		bitmask_snprintf(afsr, VMEBUS_AFSR_BITS, bits, sizeof(bits)));
    483  1.34.4.2       pk 	printf("\taddress: 0x%x%x\n", afsr, afpa);
    484  1.34.4.2       pk 	return (0);
    485  1.34.4.2       pk }
    486  1.34.4.2       pk #endif
    487  1.34.4.2       pk 
    488  1.34.4.2       pk int
    489  1.34.4.3  nathanw vmebus_translate(sc, mod, addr, bap)
    490  1.34.4.2       pk 	struct sparcvme_softc *sc;
    491  1.34.4.2       pk 	vme_am_t	mod;
    492  1.34.4.2       pk 	vme_addr_t	addr;
    493  1.34.4.2       pk 	bus_addr_t	*bap;
    494  1.34.4.2       pk {
    495  1.34.4.2       pk 	int i;
    496  1.34.4.2       pk 
    497  1.34.4.2       pk 	for (i = 0; i < sc->sc_nrange; i++) {
    498  1.34.4.3  nathanw 		struct rom_range *rp = &sc->sc_range[i];
    499  1.34.4.2       pk 
    500  1.34.4.3  nathanw 		if (rp->cspace != mod)
    501  1.34.4.2       pk 			continue;
    502  1.34.4.2       pk 
    503  1.34.4.2       pk 		/* We've found the connection to the parent bus */
    504  1.34.4.3  nathanw 		*bap = BUS_ADDR(rp->pspace, rp->poffset + addr);
    505  1.34.4.2       pk 		return (0);
    506  1.34.4.2       pk 	}
    507  1.34.4.2       pk 	return (ENOENT);
    508  1.34.4.2       pk }
    509  1.34.4.2       pk 
    510  1.34.4.2       pk struct vmeprobe_myarg {
    511  1.34.4.2       pk 	int (*cb) __P((void *, bus_space_tag_t, bus_space_handle_t));
    512  1.34.4.2       pk 	void *cbarg;
    513  1.34.4.2       pk 	bus_space_tag_t tag;
    514  1.34.4.2       pk 	int res; /* backwards */
    515  1.34.4.2       pk };
    516  1.34.4.2       pk 
    517  1.34.4.2       pk static int vmeprobe_mycb __P((void *, void *));
    518  1.34.4.2       pk static int
    519  1.34.4.2       pk vmeprobe_mycb(bh, arg)
    520  1.34.4.2       pk 	void *bh, *arg;
    521  1.34.4.2       pk {
    522  1.34.4.2       pk 	struct vmeprobe_myarg *a = arg;
    523  1.34.4.2       pk 
    524  1.34.4.2       pk 	a->res = (*a->cb)(a->cbarg, a->tag, (bus_space_handle_t)bh);
    525  1.34.4.2       pk 	return (!a->res);
    526  1.34.4.2       pk }
    527  1.34.4.2       pk 
    528  1.34.4.2       pk int
    529  1.34.4.2       pk sparc_vme_probe(cookie, addr, len, mod, datasize, callback, arg)
    530  1.34.4.2       pk 	void *cookie;
    531  1.34.4.2       pk 	vme_addr_t addr;
    532  1.34.4.2       pk 	vme_size_t len;
    533  1.34.4.2       pk 	vme_am_t mod;
    534  1.34.4.2       pk 	vme_datasize_t datasize;
    535  1.34.4.2       pk 	int (*callback) __P((void *, bus_space_tag_t, bus_space_handle_t));
    536  1.34.4.2       pk 	void *arg;
    537  1.34.4.2       pk {
    538  1.34.4.2       pk 	struct sparcvme_softc *sc = (struct sparcvme_softc *)cookie;
    539  1.34.4.2       pk 	bus_addr_t paddr;
    540  1.34.4.2       pk 	bus_size_t size;
    541  1.34.4.2       pk 	struct vmeprobe_myarg myarg;
    542  1.34.4.2       pk 	int res, i;
    543  1.34.4.2       pk 
    544  1.34.4.3  nathanw 	if (vmebus_translate(sc, mod, addr, &paddr) != 0)
    545  1.34.4.2       pk 		return (EINVAL);
    546  1.34.4.2       pk 
    547  1.34.4.2       pk 	size = (datasize == VME_D8 ? 1 : (datasize == VME_D16 ? 2 : 4));
    548  1.34.4.2       pk 
    549  1.34.4.2       pk 	if (callback) {
    550  1.34.4.2       pk 		myarg.cb = callback;
    551  1.34.4.2       pk 		myarg.cbarg = arg;
    552  1.34.4.2       pk 		myarg.tag = sc->sc_bustag;
    553  1.34.4.2       pk 		myarg.res = 0;
    554  1.34.4.3  nathanw 		res = bus_space_probe(sc->sc_bustag, paddr, size, 0,
    555  1.34.4.2       pk 				      0, vmeprobe_mycb, &myarg);
    556  1.34.4.2       pk 		return (res ? 0 : (myarg.res ? myarg.res : EIO));
    557  1.34.4.2       pk 	}
    558  1.34.4.2       pk 
    559  1.34.4.2       pk 	for (i = 0; i < len / size; i++) {
    560  1.34.4.2       pk 		myarg.res = 0;
    561  1.34.4.3  nathanw 		res = bus_space_probe(sc->sc_bustag, paddr, size, 0,
    562  1.34.4.2       pk 				      0, 0, 0);
    563  1.34.4.2       pk 		if (res == 0)
    564  1.34.4.2       pk 			return (EIO);
    565  1.34.4.2       pk 		paddr += size;
    566  1.34.4.2       pk 	}
    567  1.34.4.2       pk 	return (0);
    568  1.34.4.2       pk }
    569  1.34.4.2       pk 
    570  1.34.4.2       pk int
    571  1.34.4.2       pk sparc_vme_map(cookie, addr, size, mod, datasize, swap, tp, hp, rp)
    572  1.34.4.2       pk 	void *cookie;
    573  1.34.4.2       pk 	vme_addr_t addr;
    574  1.34.4.2       pk 	vme_size_t size;
    575  1.34.4.2       pk 	vme_am_t mod;
    576  1.34.4.2       pk 	vme_datasize_t datasize;
    577  1.34.4.2       pk 	vme_swap_t swap;
    578  1.34.4.2       pk 	bus_space_tag_t *tp;
    579  1.34.4.2       pk 	bus_space_handle_t *hp;
    580  1.34.4.2       pk 	vme_mapresc_t *rp;
    581  1.34.4.2       pk {
    582  1.34.4.2       pk 	struct sparcvme_softc *sc = (struct sparcvme_softc *)cookie;
    583  1.34.4.2       pk 	bus_addr_t paddr;
    584  1.34.4.2       pk 	int error;
    585  1.34.4.2       pk 
    586  1.34.4.3  nathanw 	error = vmebus_translate(sc, mod, addr, &paddr);
    587  1.34.4.2       pk 	if (error != 0)
    588  1.34.4.2       pk 		return (error);
    589  1.34.4.2       pk 
    590  1.34.4.2       pk 	*tp = sc->sc_bustag;
    591  1.34.4.3  nathanw 	return (bus_space_map(sc->sc_bustag, paddr, size, 0, hp));
    592  1.34.4.2       pk }
    593  1.34.4.2       pk 
    594  1.34.4.2       pk int
    595  1.34.4.2       pk sparc_vme_mmap_cookie(addr, mod, hp)
    596  1.34.4.2       pk 	vme_addr_t addr;
    597  1.34.4.2       pk 	vme_am_t mod;
    598  1.34.4.2       pk 	bus_space_handle_t *hp;
    599  1.34.4.2       pk {
    600  1.34.4.2       pk 	struct sparcvme_softc *sc = sparcvme_sc;
    601  1.34.4.2       pk 	bus_addr_t paddr;
    602  1.34.4.2       pk 	int error;
    603  1.34.4.2       pk 
    604  1.34.4.3  nathanw 	error = vmebus_translate(sc, mod, addr, &paddr);
    605  1.34.4.2       pk 	if (error != 0)
    606  1.34.4.2       pk 		return (error);
    607  1.34.4.2       pk 
    608  1.34.4.3  nathanw 	return (bus_space_mmap(sc->sc_bustag, paddr, 0,
    609  1.34.4.2       pk 		0/*prot is ignored*/, 0));
    610  1.34.4.2       pk }
    611  1.34.4.2       pk 
    612  1.34.4.2       pk #if defined(SUN4M)
    613  1.34.4.2       pk void
    614  1.34.4.2       pk sparc_vme_iommu_barrier(t, h, offset, size, flags)
    615  1.34.4.2       pk 	bus_space_tag_t t;
    616  1.34.4.2       pk 	bus_space_handle_t h;
    617  1.34.4.2       pk 	bus_size_t offset;
    618  1.34.4.2       pk 	bus_size_t size;
    619  1.34.4.2       pk 	int flags;
    620  1.34.4.2       pk {
    621  1.34.4.2       pk 	struct vmebusreg *vbp = (struct vmebusreg *)t->cookie;
    622  1.34.4.2       pk 
    623  1.34.4.2       pk 	/* Read async fault status to flush write-buffers */
    624  1.34.4.2       pk 	(*(volatile int *)&vbp->vmebus_afsr);
    625  1.34.4.2       pk }
    626  1.34.4.2       pk #endif
    627  1.34.4.2       pk 
    628  1.34.4.2       pk 
    629  1.34.4.2       pk 
    630  1.34.4.2       pk /*
    631  1.34.4.2       pk  * VME Interrupt Priority Level to sparc Processor Interrupt Level.
    632  1.34.4.2       pk  */
    633  1.34.4.2       pk static int vme_ipl_to_pil[] = {
    634  1.34.4.2       pk 	0,
    635  1.34.4.2       pk 	2,
    636  1.34.4.2       pk 	3,
    637  1.34.4.2       pk 	5,
    638  1.34.4.2       pk 	7,
    639  1.34.4.2       pk 	9,
    640  1.34.4.2       pk 	11,
    641  1.34.4.2       pk 	13
    642  1.34.4.2       pk };
    643  1.34.4.2       pk 
    644  1.34.4.2       pk 
    645  1.34.4.2       pk /*
    646  1.34.4.2       pk  * All VME device interrupts go through vmeintr(). This function reads
    647  1.34.4.2       pk  * the VME vector from the bus, then dispatches the device interrupt
    648  1.34.4.2       pk  * handler.  All handlers for devices that map to the same Processor
    649  1.34.4.2       pk  * Interrupt Level (according to the table above) are on a linked list
    650  1.34.4.2       pk  * of `sparc_vme_intr_handle' structures. The head of which is passed
    651  1.34.4.2       pk  * down as the argument to `vmeintr(void *arg)'.
    652  1.34.4.2       pk  */
    653  1.34.4.2       pk struct sparc_vme_intr_handle {
    654  1.34.4.2       pk 	struct intrhand ih;
    655  1.34.4.2       pk 	struct sparc_vme_intr_handle *next;
    656  1.34.4.2       pk 	int	vec;		/* VME interrupt vector */
    657  1.34.4.2       pk 	int	pri;		/* VME interrupt priority */
    658  1.34.4.2       pk 	struct sparcvme_softc *sc;/*XXX*/
    659  1.34.4.2       pk };
    660  1.34.4.2       pk 
    661  1.34.4.2       pk #if defined(SUN4)
    662  1.34.4.2       pk int
    663  1.34.4.2       pk vmeintr4(arg)
    664  1.34.4.2       pk 	void *arg;
    665  1.34.4.2       pk {
    666  1.34.4.2       pk 	struct sparc_vme_intr_handle *ihp = (vme_intr_handle_t)arg;
    667  1.34.4.2       pk 	int level, vec;
    668  1.34.4.2       pk 	int rv = 0;
    669  1.34.4.2       pk 
    670  1.34.4.2       pk 	level = (ihp->pri << 1) | 1;
    671  1.34.4.2       pk 
    672  1.34.4.2       pk 	vec = ldcontrolb((caddr_t)(AC_VMEINTVEC | level));
    673  1.34.4.2       pk 
    674  1.34.4.2       pk 	if (vec == -1) {
    675  1.34.4.2       pk #ifdef DEBUG
    676  1.34.4.2       pk 		/*
    677  1.34.4.2       pk 		 * This seems to happen only with the i82586 based
    678  1.34.4.2       pk 		 * `ie1' boards.
    679  1.34.4.2       pk 		 */
    680  1.34.4.2       pk 		printf("vme: spurious interrupt at VME level %d\n", ihp->pri);
    681  1.34.4.2       pk #endif
    682  1.34.4.2       pk 		return (1); /* XXX - pretend we handled it, for now */
    683  1.34.4.2       pk 	}
    684  1.34.4.2       pk 
    685  1.34.4.2       pk 	for (; ihp; ihp = ihp->next)
    686  1.34.4.2       pk 		if (ihp->vec == vec && ihp->ih.ih_fun)
    687  1.34.4.2       pk 			rv |= (ihp->ih.ih_fun)(ihp->ih.ih_arg);
    688  1.34.4.2       pk 
    689  1.34.4.2       pk 	return (rv);
    690  1.34.4.2       pk }
    691  1.34.4.2       pk #endif
    692  1.34.4.2       pk 
    693  1.34.4.2       pk #if defined(SUN4M)
    694  1.34.4.2       pk int
    695  1.34.4.2       pk vmeintr4m(arg)
    696  1.34.4.2       pk 	void *arg;
    697  1.34.4.2       pk {
    698  1.34.4.2       pk 	struct sparc_vme_intr_handle *ihp = (vme_intr_handle_t)arg;
    699  1.34.4.2       pk 	int level, vec;
    700  1.34.4.2       pk 	int rv = 0;
    701  1.34.4.2       pk 
    702  1.34.4.2       pk 	level = (ihp->pri << 1) | 1;
    703  1.34.4.2       pk 
    704  1.34.4.2       pk #if 0
    705  1.34.4.2       pk 	int pending;
    706  1.34.4.2       pk 
    707  1.34.4.2       pk 	/* Flush VME <=> Sbus write buffers */
    708  1.34.4.2       pk 	(*(volatile int *)&ihp->sc->sc_reg->vmebus_afsr);
    709  1.34.4.2       pk 
    710  1.34.4.2       pk 	pending = *((int*)ICR_SI_PEND);
    711  1.34.4.2       pk 	if ((pending & SINTR_VME(ihp->pri)) == 0) {
    712  1.34.4.2       pk 		printf("vmeintr: non pending at pri %x(p 0x%x)\n",
    713  1.34.4.2       pk 			ihp->pri, pending);
    714  1.34.4.2       pk 		return (0);
    715  1.34.4.2       pk 	}
    716  1.34.4.2       pk #endif
    717  1.34.4.2       pk #if 0
    718  1.34.4.2       pk 	/* Why gives this a bus timeout sometimes? */
    719  1.34.4.2       pk 	vec = ihp->sc->sc_vec->vmebusvec[level];
    720  1.34.4.2       pk #else
    721  1.34.4.2       pk 	/* so, arrange to catch the fault... */
    722  1.34.4.2       pk 	{
    723  1.34.4.2       pk 	extern struct user *proc0paddr;
    724  1.34.4.2       pk 	extern int fkbyte __P((caddr_t, struct pcb *));
    725  1.34.4.2       pk 	caddr_t addr = (caddr_t)&ihp->sc->sc_vec->vmebusvec[level];
    726  1.34.4.2       pk 	struct pcb *xpcb;
    727  1.34.4.2       pk 	u_long saveonfault;
    728  1.34.4.2       pk 	int s;
    729  1.34.4.2       pk 
    730  1.34.4.2       pk 	s = splhigh();
    731  1.34.4.4  nathanw 	if (curlwp == NULL)
    732  1.34.4.2       pk 		xpcb = (struct pcb *)proc0paddr;
    733  1.34.4.2       pk 	else
    734  1.34.4.4  nathanw 		xpcb = &curlwp->l_addr->u_pcb;
    735  1.34.4.2       pk 
    736  1.34.4.2       pk 	saveonfault = (u_long)xpcb->pcb_onfault;
    737  1.34.4.2       pk 	vec = fkbyte(addr, xpcb);
    738  1.34.4.2       pk 	xpcb->pcb_onfault = (caddr_t)saveonfault;
    739  1.34.4.2       pk 
    740  1.34.4.2       pk 	splx(s);
    741  1.34.4.2       pk 	}
    742  1.34.4.2       pk #endif
    743  1.34.4.2       pk 
    744  1.34.4.2       pk 	if (vec == -1) {
    745  1.34.4.2       pk #ifdef DEBUG
    746  1.34.4.2       pk 		/*
    747  1.34.4.2       pk 		 * This seems to happen only with the i82586 based
    748  1.34.4.2       pk 		 * `ie1' boards.
    749  1.34.4.2       pk 		 */
    750  1.34.4.2       pk 		printf("vme: spurious interrupt at VME level %d\n", ihp->pri);
    751  1.34.4.2       pk 		printf("    ICR_SI_PEND=0x%x; VME AFSR=0x%x; VME AFAR=0x%x\n",
    752  1.34.4.2       pk 			*((int*)ICR_SI_PEND),
    753  1.34.4.2       pk 			ihp->sc->sc_reg->vmebus_afsr,
    754  1.34.4.2       pk 			ihp->sc->sc_reg->vmebus_afar);
    755  1.34.4.2       pk #endif
    756  1.34.4.2       pk 		return (1); /* XXX - pretend we handled it, for now */
    757  1.34.4.2       pk 	}
    758  1.34.4.2       pk 
    759  1.34.4.2       pk 	for (; ihp; ihp = ihp->next)
    760  1.34.4.2       pk 		if (ihp->vec == vec && ihp->ih.ih_fun)
    761  1.34.4.2       pk 			rv |= (ihp->ih.ih_fun)(ihp->ih.ih_arg);
    762  1.34.4.2       pk 
    763  1.34.4.2       pk 	return (rv);
    764  1.34.4.2       pk }
    765  1.34.4.2       pk #endif
    766  1.34.4.2       pk 
    767  1.34.4.2       pk int
    768  1.34.4.2       pk sparc_vme_intr_map(cookie, level, vec, ihp)
    769  1.34.4.2       pk 	void *cookie;
    770  1.34.4.2       pk 	int level;
    771  1.34.4.2       pk 	int vec;
    772  1.34.4.2       pk 	vme_intr_handle_t *ihp;
    773  1.34.4.2       pk {
    774  1.34.4.2       pk 	struct sparc_vme_intr_handle *ih;
    775  1.34.4.2       pk 
    776  1.34.4.2       pk 	ih = (vme_intr_handle_t)
    777  1.34.4.2       pk 	    malloc(sizeof(struct sparc_vme_intr_handle), M_DEVBUF, M_NOWAIT);
    778  1.34.4.2       pk 	ih->pri = level;
    779  1.34.4.2       pk 	ih->vec = vec;
    780  1.34.4.2       pk 	ih->sc = cookie;/*XXX*/
    781  1.34.4.2       pk 	*ihp = ih;
    782  1.34.4.2       pk 	return (0);
    783  1.34.4.2       pk }
    784  1.34.4.2       pk 
    785  1.34.4.2       pk const struct evcnt *
    786  1.34.4.2       pk sparc_vme_intr_evcnt(cookie, vih)
    787  1.34.4.2       pk 	void *cookie;
    788  1.34.4.2       pk 	vme_intr_handle_t vih;
    789  1.34.4.2       pk {
    790  1.34.4.2       pk 
    791  1.34.4.2       pk 	/* XXX for now, no evcnt parent reported */
    792  1.34.4.2       pk 	return NULL;
    793  1.34.4.2       pk }
    794  1.34.4.2       pk 
    795  1.34.4.2       pk void *
    796  1.34.4.2       pk sparc_vme_intr_establish(cookie, vih, pri, func, arg)
    797  1.34.4.2       pk 	void *cookie;
    798  1.34.4.2       pk 	vme_intr_handle_t vih;
    799  1.34.4.2       pk 	int pri;
    800  1.34.4.2       pk 	int (*func) __P((void *));
    801  1.34.4.2       pk 	void *arg;
    802  1.34.4.2       pk {
    803  1.34.4.2       pk 	struct sparcvme_softc *sc = (struct sparcvme_softc *)cookie;
    804  1.34.4.2       pk 	struct sparc_vme_intr_handle *svih =
    805  1.34.4.2       pk 			(struct sparc_vme_intr_handle *)vih;
    806  1.34.4.2       pk 	struct intrhand *ih;
    807  1.34.4.2       pk 	int level;
    808  1.34.4.2       pk 
    809  1.34.4.2       pk 	/* XXX pri == svih->pri ??? */
    810  1.34.4.2       pk 
    811  1.34.4.2       pk 	/* Translate VME priority to processor IPL */
    812  1.34.4.2       pk 	level = vme_ipl_to_pil[svih->pri];
    813  1.34.4.2       pk 
    814  1.34.4.2       pk 	svih->ih.ih_fun = func;
    815  1.34.4.2       pk 	svih->ih.ih_arg = arg;
    816  1.34.4.2       pk 	svih->next = NULL;
    817  1.34.4.2       pk 
    818  1.34.4.2       pk 	/* ensure the interrupt subsystem will call us at this level */
    819  1.34.4.2       pk 	for (ih = intrhand[level]; ih != NULL; ih = ih->ih_next)
    820  1.34.4.2       pk 		if (ih->ih_fun == sc->sc_vmeintr)
    821  1.34.4.2       pk 			break;
    822  1.34.4.2       pk 
    823  1.34.4.2       pk 	if (ih == NULL) {
    824  1.34.4.2       pk 		ih = (struct intrhand *)
    825  1.34.4.2       pk 			malloc(sizeof(struct intrhand), M_DEVBUF, M_NOWAIT);
    826  1.34.4.2       pk 		if (ih == NULL)
    827  1.34.4.2       pk 			panic("vme_addirq");
    828  1.34.4.2       pk 		bzero(ih, sizeof *ih);
    829  1.34.4.2       pk 		ih->ih_fun = sc->sc_vmeintr;
    830  1.34.4.2       pk 		ih->ih_arg = vih;
    831  1.34.4.2       pk 		intr_establish(level, ih);
    832  1.34.4.2       pk 	} else {
    833  1.34.4.2       pk 		svih->next = (vme_intr_handle_t)ih->ih_arg;
    834  1.34.4.2       pk 		ih->ih_arg = vih;
    835  1.34.4.2       pk 	}
    836  1.34.4.2       pk 	return (NULL);
    837  1.34.4.2       pk }
    838  1.34.4.2       pk 
    839  1.34.4.2       pk void
    840  1.34.4.2       pk sparc_vme_unmap(cookie, resc)
    841  1.34.4.2       pk 	void * cookie;
    842  1.34.4.2       pk 	vme_mapresc_t resc;
    843  1.34.4.2       pk {
    844  1.34.4.2       pk 	/* Not implemented */
    845  1.34.4.2       pk 	panic("sparc_vme_unmap");
    846  1.34.4.2       pk }
    847  1.34.4.2       pk 
    848  1.34.4.2       pk void
    849  1.34.4.2       pk sparc_vme_intr_disestablish(cookie, a)
    850  1.34.4.2       pk 	void *cookie;
    851  1.34.4.2       pk 	void *a;
    852  1.34.4.2       pk {
    853  1.34.4.2       pk 	/* Not implemented */
    854  1.34.4.2       pk 	panic("sparc_vme_intr_disestablish");
    855  1.34.4.2       pk }
    856  1.34.4.2       pk 
    857  1.34.4.2       pk 
    858  1.34.4.2       pk 
    859  1.34.4.2       pk /*
    860  1.34.4.2       pk  * VME DMA functions.
    861  1.34.4.2       pk  */
    862  1.34.4.2       pk 
    863  1.34.4.2       pk static void
    864  1.34.4.2       pk sparc_vct_dmamap_destroy(cookie, map)
    865  1.34.4.2       pk 	void *cookie;
    866  1.34.4.2       pk 	bus_dmamap_t map;
    867  1.34.4.2       pk {
    868  1.34.4.2       pk 	struct sparcvme_softc *sc = (struct sparcvme_softc *)cookie;
    869  1.34.4.2       pk 	bus_dmamap_destroy(sc->sc_dmatag, map);
    870  1.34.4.2       pk }
    871  1.34.4.2       pk 
    872  1.34.4.2       pk #if defined(SUN4)
    873  1.34.4.2       pk static int
    874  1.34.4.2       pk sparc_vct4_dmamap_create(cookie, size, am, datasize, swap, nsegments, maxsegsz,
    875  1.34.4.2       pk 			  boundary, flags, dmamp)
    876  1.34.4.2       pk 	void *cookie;
    877  1.34.4.2       pk 	vme_size_t size;
    878  1.34.4.2       pk 	vme_am_t am;
    879  1.34.4.2       pk 	vme_datasize_t datasize;
    880  1.34.4.2       pk 	vme_swap_t swap;
    881  1.34.4.2       pk 	int nsegments;
    882  1.34.4.2       pk 	vme_size_t maxsegsz;
    883  1.34.4.2       pk 	vme_addr_t boundary;
    884  1.34.4.2       pk 	int flags;
    885  1.34.4.2       pk 	bus_dmamap_t *dmamp;
    886  1.34.4.2       pk {
    887  1.34.4.2       pk 	struct sparcvme_softc *sc = (struct sparcvme_softc *)cookie;
    888  1.34.4.2       pk 
    889  1.34.4.2       pk 	/* Allocate a base map through parent bus ops */
    890  1.34.4.2       pk 	return (bus_dmamap_create(sc->sc_dmatag, size, nsegments, maxsegsz,
    891  1.34.4.2       pk 				  boundary, flags, dmamp));
    892  1.34.4.2       pk }
    893  1.34.4.2       pk 
    894  1.34.4.2       pk int
    895  1.34.4.2       pk sparc_vme4_dmamap_load(t, map, buf, buflen, p, flags)
    896  1.34.4.2       pk 	bus_dma_tag_t t;
    897  1.34.4.2       pk 	bus_dmamap_t map;
    898  1.34.4.2       pk 	void *buf;
    899  1.34.4.2       pk 	bus_size_t buflen;
    900  1.34.4.2       pk 	struct proc *p;
    901  1.34.4.2       pk 	int flags;
    902  1.34.4.2       pk {
    903  1.34.4.2       pk 	bus_addr_t dva;
    904  1.34.4.2       pk 	bus_size_t sgsize;
    905  1.34.4.2       pk 	vaddr_t va, voff;
    906  1.34.4.2       pk 	pmap_t pmap;
    907  1.34.4.2       pk 	int pagesz = PAGE_SIZE;
    908  1.34.4.2       pk 	int error;
    909  1.34.4.2       pk 
    910  1.34.4.2       pk 	cpuinfo.cache_flush(buf, buflen); /* XXX - move to bus_dma_sync */
    911  1.34.4.2       pk 
    912  1.34.4.2       pk 	va = (vaddr_t)buf;
    913  1.34.4.2       pk 	voff = va & (pagesz - 1);
    914  1.34.4.2       pk 	va &= -pagesz;
    915  1.34.4.2       pk 
    916  1.34.4.2       pk 	/*
    917  1.34.4.2       pk 	 * Allocate an integral number of pages from DVMA space
    918  1.34.4.2       pk 	 * covering the passed buffer.
    919  1.34.4.2       pk 	 */
    920  1.34.4.2       pk 	sgsize = (buflen + voff + pagesz - 1) & -pagesz;
    921  1.34.4.2       pk 	error = extent_alloc(vme_dvmamap, sgsize, pagesz,
    922  1.34.4.2       pk 			     map->_dm_boundary,
    923  1.34.4.2       pk 			     (flags & BUS_DMA_NOWAIT) == 0
    924  1.34.4.2       pk 					? EX_WAITOK
    925  1.34.4.2       pk 					: EX_NOWAIT,
    926  1.34.4.2       pk 			     (u_long *)&dva);
    927  1.34.4.2       pk 	if (error != 0)
    928  1.34.4.2       pk 		return (error);
    929  1.34.4.2       pk 
    930  1.34.4.2       pk 	map->dm_mapsize = buflen;
    931  1.34.4.2       pk 	map->dm_nsegs = 1;
    932  1.34.4.2       pk 	/* Adjust DVMA address to VME view */
    933  1.34.4.2       pk 	map->dm_segs[0].ds_addr = dva + voff - VME4_DVMA_BASE;
    934  1.34.4.2       pk 	map->dm_segs[0].ds_len = buflen;
    935  1.34.4.2       pk 	map->dm_segs[0]._ds_sgsize = sgsize;
    936  1.34.4.2       pk 
    937  1.34.4.2       pk 	pmap = (p == NULL) ? pmap_kernel() : p->p_vmspace->vm_map.pmap;
    938  1.34.4.2       pk 
    939  1.34.4.2       pk 	for (; sgsize != 0; ) {
    940  1.34.4.2       pk 		paddr_t pa;
    941  1.34.4.2       pk 		/*
    942  1.34.4.2       pk 		 * Get the physical address for this page.
    943  1.34.4.2       pk 		 */
    944  1.34.4.2       pk 		(void) pmap_extract(pmap, va, &pa);
    945  1.34.4.2       pk 
    946  1.34.4.2       pk #ifdef notyet
    947  1.34.4.2       pk 		if (have_iocache)
    948  1.34.4.2       pk 			pa |= PG_IOC;
    949  1.34.4.2       pk #endif
    950  1.34.4.2       pk 		pmap_enter(pmap_kernel(), dva,
    951  1.34.4.2       pk 			   pa | PMAP_NC,
    952  1.34.4.2       pk 			   VM_PROT_READ|VM_PROT_WRITE, PMAP_WIRED);
    953  1.34.4.2       pk 
    954  1.34.4.2       pk 		dva += pagesz;
    955  1.34.4.2       pk 		va += pagesz;
    956  1.34.4.2       pk 		sgsize -= pagesz;
    957  1.34.4.2       pk 	}
    958  1.34.4.2       pk 	pmap_update(pmap_kernel());
    959  1.34.4.2       pk 
    960  1.34.4.2       pk 	return (0);
    961  1.34.4.2       pk }
    962  1.34.4.2       pk 
    963  1.34.4.2       pk void
    964  1.34.4.2       pk sparc_vme4_dmamap_unload(t, map)
    965  1.34.4.2       pk 	bus_dma_tag_t t;
    966  1.34.4.2       pk 	bus_dmamap_t map;
    967  1.34.4.2       pk {
    968  1.34.4.2       pk 	bus_dma_segment_t *segs = map->dm_segs;
    969  1.34.4.2       pk 	int nsegs = map->dm_nsegs;
    970  1.34.4.2       pk 	bus_addr_t dva;
    971  1.34.4.2       pk 	bus_size_t len;
    972  1.34.4.2       pk 	int i, s, error;
    973  1.34.4.2       pk 
    974  1.34.4.2       pk 	for (i = 0; i < nsegs; i++) {
    975  1.34.4.2       pk 		/* Go from VME to CPU view */
    976  1.34.4.2       pk 		dva = segs[i].ds_addr + VME4_DVMA_BASE;
    977  1.34.4.2       pk 		dva &= -PAGE_SIZE;
    978  1.34.4.2       pk 		len = segs[i]._ds_sgsize;
    979  1.34.4.2       pk 
    980  1.34.4.2       pk 		/* Remove double-mapping in DVMA space */
    981  1.34.4.2       pk 		pmap_remove(pmap_kernel(), dva, dva + len);
    982  1.34.4.2       pk 
    983  1.34.4.2       pk 		/* Release DVMA space */
    984  1.34.4.2       pk 		s = splhigh();
    985  1.34.4.2       pk 		error = extent_free(vme_dvmamap, dva, len, EX_NOWAIT);
    986  1.34.4.2       pk 		splx(s);
    987  1.34.4.2       pk 		if (error != 0)
    988  1.34.4.2       pk 			printf("warning: %ld of DVMA space lost\n", len);
    989  1.34.4.2       pk 	}
    990  1.34.4.2       pk 	pmap_update(pmap_kernel());
    991  1.34.4.2       pk 
    992  1.34.4.2       pk 	/* Mark the mappings as invalid. */
    993  1.34.4.2       pk 	map->dm_mapsize = 0;
    994  1.34.4.2       pk 	map->dm_nsegs = 0;
    995  1.34.4.2       pk }
    996  1.34.4.2       pk 
    997  1.34.4.2       pk void
    998  1.34.4.2       pk sparc_vme4_dmamap_sync(t, map, offset, len, ops)
    999  1.34.4.2       pk 	bus_dma_tag_t t;
   1000  1.34.4.2       pk 	bus_dmamap_t map;
   1001  1.34.4.2       pk 	bus_addr_t offset;
   1002  1.34.4.2       pk 	bus_size_t len;
   1003  1.34.4.2       pk 	int ops;
   1004  1.34.4.2       pk {
   1005  1.34.4.2       pk 
   1006  1.34.4.2       pk 	/*
   1007  1.34.4.2       pk 	 * XXX Should perform cache flushes as necessary (e.g. 4/200 W/B).
   1008  1.34.4.2       pk 	 *     Currently the cache is flushed in bus_dma_load()...
   1009  1.34.4.2       pk 	 */
   1010  1.34.4.2       pk }
   1011  1.34.4.2       pk #endif /* SUN4 */
   1012  1.34.4.2       pk 
   1013  1.34.4.2       pk #if defined(SUN4M)
   1014  1.34.4.2       pk static int
   1015  1.34.4.2       pk sparc_vme_iommu_dmamap_create (t, size, nsegments, maxsegsz,
   1016  1.34.4.2       pk 				boundary, flags, dmamp)
   1017  1.34.4.2       pk 	bus_dma_tag_t t;
   1018  1.34.4.2       pk 	bus_size_t size;
   1019  1.34.4.2       pk 	int nsegments;
   1020  1.34.4.2       pk 	bus_size_t maxsegsz;
   1021  1.34.4.2       pk 	bus_size_t boundary;
   1022  1.34.4.2       pk 	int flags;
   1023  1.34.4.2       pk 	bus_dmamap_t *dmamp;
   1024  1.34.4.2       pk {
   1025  1.34.4.2       pk 
   1026  1.34.4.2       pk 	printf("sparc_vme_dmamap_create: please use `vme_dmamap_create'\n");
   1027  1.34.4.2       pk 	return (EINVAL);
   1028  1.34.4.2       pk }
   1029  1.34.4.2       pk 
   1030  1.34.4.2       pk static int
   1031  1.34.4.2       pk sparc_vct_iommu_dmamap_create(cookie, size, am, datasize, swap, nsegments,
   1032  1.34.4.2       pk 			      maxsegsz, boundary, flags, dmamp)
   1033  1.34.4.2       pk 	void *cookie;
   1034  1.34.4.2       pk 	vme_size_t size;
   1035  1.34.4.2       pk 	vme_am_t am;
   1036  1.34.4.2       pk 	vme_datasize_t datasize;
   1037  1.34.4.2       pk 	vme_swap_t swap;
   1038  1.34.4.2       pk 	int nsegments;
   1039  1.34.4.2       pk 	vme_size_t maxsegsz;
   1040  1.34.4.2       pk 	vme_addr_t boundary;
   1041  1.34.4.2       pk 	int flags;
   1042  1.34.4.2       pk 	bus_dmamap_t *dmamp;
   1043  1.34.4.2       pk {
   1044  1.34.4.2       pk 	struct sparcvme_softc *sc = (struct sparcvme_softc *)cookie;
   1045  1.34.4.2       pk 	bus_dmamap_t map;
   1046  1.34.4.2       pk 	int error;
   1047  1.34.4.2       pk 
   1048  1.34.4.2       pk 	/* Allocate a base map through parent bus ops */
   1049  1.34.4.2       pk 	error = bus_dmamap_create(sc->sc_dmatag, size, nsegments, maxsegsz,
   1050  1.34.4.2       pk 				  boundary, flags, &map);
   1051  1.34.4.2       pk 	if (error != 0)
   1052  1.34.4.2       pk 		return (error);
   1053  1.34.4.2       pk 
   1054  1.34.4.2       pk 	/*
   1055  1.34.4.2       pk 	 * Each I/O cache line maps to a 8K section of VME DVMA space, so
   1056  1.34.4.2       pk 	 * we must ensure that DVMA alloctions are always 8K aligned.
   1057  1.34.4.2       pk 	 */
   1058  1.34.4.2       pk 	map->_dm_align = VME_IOC_PAGESZ;
   1059  1.34.4.2       pk 
   1060  1.34.4.2       pk 	/* Set map region based on Address Modifier */
   1061  1.34.4.2       pk 	switch ((am & VME_AM_ADRSIZEMASK)) {
   1062  1.34.4.2       pk 	case VME_AM_A16:
   1063  1.34.4.2       pk 	case VME_AM_A24:
   1064  1.34.4.2       pk 		/* 1 MB of DVMA space */
   1065  1.34.4.2       pk 		map->_dm_ex_start = VME_IOMMU_DVMA_AM24_BASE;
   1066  1.34.4.2       pk 		map->_dm_ex_end   = VME_IOMMU_DVMA_AM24_END;
   1067  1.34.4.2       pk 		break;
   1068  1.34.4.2       pk 	case VME_AM_A32:
   1069  1.34.4.2       pk 		/* 8 MB of DVMA space */
   1070  1.34.4.2       pk 		map->_dm_ex_start = VME_IOMMU_DVMA_AM32_BASE;
   1071  1.34.4.2       pk 		map->_dm_ex_end   = VME_IOMMU_DVMA_AM32_END;
   1072  1.34.4.2       pk 		break;
   1073  1.34.4.2       pk 	}
   1074  1.34.4.2       pk 
   1075  1.34.4.2       pk 	*dmamp = map;
   1076  1.34.4.2       pk 	return (0);
   1077  1.34.4.2       pk }
   1078  1.34.4.2       pk 
   1079  1.34.4.2       pk int
   1080  1.34.4.2       pk sparc_vme_iommu_dmamap_load(t, map, buf, buflen, p, flags)
   1081  1.34.4.2       pk 	bus_dma_tag_t t;
   1082  1.34.4.2       pk 	bus_dmamap_t map;
   1083  1.34.4.2       pk 	void *buf;
   1084  1.34.4.2       pk 	bus_size_t buflen;
   1085  1.34.4.2       pk 	struct proc *p;
   1086  1.34.4.2       pk 	int flags;
   1087  1.34.4.2       pk {
   1088  1.34.4.2       pk 	struct sparcvme_softc	*sc = (struct sparcvme_softc *)t->_cookie;
   1089  1.34.4.2       pk 	volatile u_int32_t	*ioctags;
   1090  1.34.4.2       pk 	int			error;
   1091  1.34.4.2       pk 
   1092  1.34.4.2       pk 	/* Round request to a multiple of the I/O cache size */
   1093  1.34.4.2       pk 	buflen = (buflen + VME_IOC_PAGESZ - 1) & -VME_IOC_PAGESZ;
   1094  1.34.4.2       pk 	error = bus_dmamap_load(sc->sc_dmatag, map, buf, buflen, p, flags);
   1095  1.34.4.2       pk 	if (error != 0)
   1096  1.34.4.2       pk 		return (error);
   1097  1.34.4.2       pk 
   1098  1.34.4.2       pk 	/* Allocate I/O cache entries for this range */
   1099  1.34.4.2       pk 	ioctags = sc->sc_ioctags + VME_IOC_LINE(map->dm_segs[0].ds_addr);
   1100  1.34.4.2       pk 	while (buflen > 0) {
   1101  1.34.4.2       pk 		*ioctags = VME_IOC_IC | VME_IOC_W;
   1102  1.34.4.2       pk 		ioctags += VME_IOC_LINESZ/sizeof(*ioctags);
   1103  1.34.4.2       pk 		buflen -= VME_IOC_PAGESZ;
   1104  1.34.4.2       pk 	}
   1105  1.34.4.2       pk 
   1106  1.34.4.2       pk 	/*
   1107  1.34.4.2       pk 	 * Adjust DVMA address to VME view.
   1108  1.34.4.2       pk 	 * Note: the DVMA base address is the same for all
   1109  1.34.4.2       pk 	 * VME address spaces.
   1110  1.34.4.2       pk 	 */
   1111  1.34.4.2       pk 	map->dm_segs[0].ds_addr -= VME_IOMMU_DVMA_BASE;
   1112  1.34.4.2       pk 	return (0);
   1113  1.34.4.2       pk }
   1114  1.34.4.2       pk 
   1115  1.34.4.2       pk 
   1116  1.34.4.2       pk void
   1117  1.34.4.2       pk sparc_vme_iommu_dmamap_unload(t, map)
   1118  1.34.4.2       pk 	bus_dma_tag_t t;
   1119  1.34.4.2       pk 	bus_dmamap_t map;
   1120  1.34.4.2       pk {
   1121  1.34.4.2       pk 	struct sparcvme_softc	*sc = (struct sparcvme_softc *)t->_cookie;
   1122  1.34.4.2       pk 	volatile u_int32_t	*flushregs;
   1123  1.34.4.2       pk 	int			len;
   1124  1.34.4.2       pk 
   1125  1.34.4.2       pk 	/* Go from VME to CPU view */
   1126  1.34.4.2       pk 	map->dm_segs[0].ds_addr += VME_IOMMU_DVMA_BASE;
   1127  1.34.4.2       pk 
   1128  1.34.4.2       pk 	/* Flush VME I/O cache */
   1129  1.34.4.2       pk 	len = map->dm_segs[0]._ds_sgsize;
   1130  1.34.4.2       pk 	flushregs = sc->sc_iocflush + VME_IOC_LINE(map->dm_segs[0].ds_addr);
   1131  1.34.4.2       pk 	while (len > 0) {
   1132  1.34.4.2       pk 		*flushregs = 0;
   1133  1.34.4.2       pk 		flushregs += VME_IOC_LINESZ/sizeof(*flushregs);
   1134  1.34.4.2       pk 		len -= VME_IOC_PAGESZ;
   1135  1.34.4.2       pk 	}
   1136  1.34.4.2       pk 
   1137  1.34.4.2       pk 	/*
   1138  1.34.4.2       pk 	 * Start a read from `tag space' which will not complete until
   1139  1.34.4.2       pk 	 * all cache flushes have finished
   1140  1.34.4.2       pk 	 */
   1141  1.34.4.2       pk 	(*sc->sc_ioctags);
   1142  1.34.4.2       pk 
   1143  1.34.4.2       pk 	bus_dmamap_unload(sc->sc_dmatag, map);
   1144  1.34.4.2       pk }
   1145  1.34.4.2       pk 
   1146  1.34.4.2       pk void
   1147  1.34.4.2       pk sparc_vme_iommu_dmamap_sync(t, map, offset, len, ops)
   1148  1.34.4.2       pk 	bus_dma_tag_t t;
   1149  1.34.4.2       pk 	bus_dmamap_t map;
   1150  1.34.4.2       pk 	bus_addr_t offset;
   1151  1.34.4.2       pk 	bus_size_t len;
   1152  1.34.4.2       pk 	int ops;
   1153  1.34.4.2       pk {
   1154  1.34.4.2       pk 
   1155  1.34.4.2       pk 	/*
   1156  1.34.4.2       pk 	 * XXX Should perform cache flushes as necessary.
   1157  1.34.4.2       pk 	 */
   1158  1.34.4.2       pk }
   1159  1.34.4.2       pk #endif /* SUN4M */
   1160  1.34.4.2       pk 
   1161  1.34.4.2       pk int
   1162  1.34.4.2       pk sparc_vme_dmamem_map(t, segs, nsegs, size, kvap, flags)
   1163  1.34.4.2       pk 	bus_dma_tag_t t;
   1164  1.34.4.2       pk 	bus_dma_segment_t *segs;
   1165  1.34.4.2       pk 	int nsegs;
   1166  1.34.4.2       pk 	size_t size;
   1167  1.34.4.2       pk 	caddr_t *kvap;
   1168  1.34.4.2       pk 	int flags;
   1169  1.34.4.2       pk {
   1170  1.34.4.2       pk 	struct sparcvme_softc	*sc = (struct sparcvme_softc *)t->_cookie;
   1171  1.34.4.2       pk 
   1172  1.34.4.2       pk 	return (bus_dmamem_map(sc->sc_dmatag, segs, nsegs, size, kvap, flags));
   1173  1.34.4.2       pk }
   1174