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