Add bus_space and busdma support for sparc64.
This commit is contained in:
parent
8f24e75043
commit
adebde5f2d
File diff suppressed because it is too large
Load Diff
33
sys/sparc64/include/bus_memio.h
Normal file
33
sys/sparc64/include/bus_memio.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 1997 Justin Gibbs.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: FreeBSD: src/sys/i386/include/bus_memio.h,v 1.2 1999/08/28
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _MACHINE_BUS_MEMIO_H_
|
||||
#define _MACHINE_BUS_MEMIO_H_
|
||||
#endif /* _MACHINE_BUS_MEMIO_H_ */
|
33
sys/sparc64/include/bus_pio.h
Normal file
33
sys/sparc64/include/bus_pio.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 1997 Justin Gibbs.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: FreeBSD: src/sys/i386/include/bus_pio.h,v 1.2 1999/08/28
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _MACHINE_BUS_PIO_H_
|
||||
#define _MACHINE_BUS_PIO_H_
|
||||
#endif /* _MACHINE_BUS_PIO_H_ */
|
@ -80,17 +80,55 @@
|
||||
__asm __volatile("flushw" : :); \
|
||||
} while (0)
|
||||
|
||||
#define ldxa(va, asi) ({ \
|
||||
u_long __r; \
|
||||
__asm __volatile("ldxa [%1] %2, %0" \
|
||||
/* Generate ld*a/st*a functions for non-constant ASI's. */
|
||||
#define LDNC_GEN(tp, o) \
|
||||
static __inline tp \
|
||||
o ## _nc(caddr_t va, int asi) \
|
||||
{ \
|
||||
tp r; \
|
||||
__asm __volatile("wr %2, 0, %%asi;" #o " [%1] %%asi, %0"\
|
||||
: "=r" (r) : "r" (va), "r" (asi)); \
|
||||
return (r); \
|
||||
}
|
||||
|
||||
LDNC_GEN(u_char, lduba);
|
||||
LDNC_GEN(u_short, lduha);
|
||||
LDNC_GEN(u_int, lduwa);
|
||||
LDNC_GEN(u_long, ldxa);
|
||||
|
||||
#define LD_GENERIC(va, asi, op, type) ({ \
|
||||
type __r; \
|
||||
__asm __volatile(#op " [%1] %2, %0" \
|
||||
: "=r" (__r) : "r" (va), "n" (asi)); \
|
||||
__r; \
|
||||
})
|
||||
|
||||
#define stxa(va, asi, val) do { \
|
||||
__asm __volatile("stxa %0, [%1] %2" \
|
||||
#define lduba(va, asi) LD_GENERIC(va, asi, lduba, u_char)
|
||||
#define lduha(va, asi) LD_GENERIC(va, asi, lduha, u_short)
|
||||
#define lduwa(va, asi) LD_GENERIC(va, asi, lduwa, u_int)
|
||||
#define ldxa(va, asi) LD_GENERIC(va, asi, ldxa, u_long)
|
||||
|
||||
#define STNC_GEN(tp, o) \
|
||||
static __inline void \
|
||||
o ## _nc(caddr_t va, int asi, tp val) \
|
||||
{ \
|
||||
__asm __volatile("wr %2, 0, %%asi;" #o " %0, [%1] %%asi"\
|
||||
: : "r" (val), "r" (va), "r" (asi)); \
|
||||
}
|
||||
|
||||
STNC_GEN(u_char, stba);
|
||||
STNC_GEN(u_short, stha);
|
||||
STNC_GEN(u_int, stwa);
|
||||
STNC_GEN(u_long, stxa);
|
||||
|
||||
#define ST_GENERIC(va, asi, val, op) \
|
||||
__asm __volatile(#op " %0, [%1] %2" \
|
||||
: : "r" (val), "r" (va), "n" (asi)); \
|
||||
} while (0)
|
||||
|
||||
#define stba(va, asi, val) ST_GENERIC(va, asi, val, stba)
|
||||
#define stha(va, asi, val) ST_GENERIC(va, asi, val, stha)
|
||||
#define stwa(va, asi, val) ST_GENERIC(va, asi, val, stwa)
|
||||
#define stxa(va, asi, val) ST_GENERIC(va, asi, val, stxa)
|
||||
|
||||
#define membar(mask) do { \
|
||||
__asm __volatile("membar %0" : : "n" (mask)); \
|
||||
@ -140,6 +178,9 @@ critical_exit(critical_t pil)
|
||||
wrpr(pil, pil, 0);
|
||||
}
|
||||
|
||||
void ascopyfrom(u_long sasi, vm_offset_t src, caddr_t dst, size_t len);
|
||||
void ascopyto(caddr_t src, u_long dasi, vm_offset_t dst, size_t len);
|
||||
|
||||
/*
|
||||
* Ultrasparc II doesn't implement popc in hardware. Suck.
|
||||
*/
|
||||
@ -165,4 +206,7 @@ ffs(int mask)
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef LDNC_GEN
|
||||
#undef STNC_GEN
|
||||
|
||||
#endif /* !_MACHINE_CPUFUNC_H_ */
|
||||
|
613
sys/sparc64/sparc64/bus_machdep.c
Normal file
613
sys/sparc64/sparc64/bus_machdep.c
Normal file
@ -0,0 +1,613 @@
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||||
* NASA Ames Research Center.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1997, 1998 Justin T. Gibbs.
|
||||
* All rights reserved.
|
||||
* Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)machdep.c 8.6 (Berkeley) 1/14/94
|
||||
* from: NetBSD: machdep.c,v 1.111 2001/09/15 07:13:40 eeh Exp
|
||||
* and
|
||||
* from: FreeBSD: src/sys/i386/i386/busdma_machdep.c,v 1.24 2001/08/15
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_extern.h>
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_param.h>
|
||||
|
||||
#include <machine/asi.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/cache.h>
|
||||
#include <machine/pmap.h>
|
||||
|
||||
/* ASI's for bus access. */
|
||||
int bus_type_asi[] = {
|
||||
ASI_PHYS_BYPASS_EC_WITH_EBIT, /* UPA */
|
||||
ASI_PHYS_BYPASS_EC_WITH_EBIT, /* SBUS */
|
||||
ASI_PHYS_BYPASS_EC_WITH_EBIT_L, /* PCI configuration space */
|
||||
ASI_PHYS_BYPASS_EC_WITH_EBIT_L, /* PCI memory space */
|
||||
ASI_PHYS_BYPASS_EC_WITH_EBIT_L, /* PCI I/O space */
|
||||
0
|
||||
};
|
||||
|
||||
int bus_stream_asi[] = {
|
||||
ASI_PHYS_BYPASS_EC_WITH_EBIT, /* UPA */
|
||||
ASI_PHYS_BYPASS_EC_WITH_EBIT, /* SBUS */
|
||||
ASI_PHYS_BYPASS_EC_WITH_EBIT, /* PCI configuration space */
|
||||
ASI_PHYS_BYPASS_EC_WITH_EBIT, /* PCI memory space */
|
||||
ASI_PHYS_BYPASS_EC_WITH_EBIT, /* PCI I/O space */
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
* busdma support code.
|
||||
* Note: there is no support for bounce buffers yet.
|
||||
*/
|
||||
|
||||
static int nexus_dmamap_create(bus_dma_tag_t, int, bus_dmamap_t *);
|
||||
static int nexus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
|
||||
static int nexus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t,
|
||||
bus_dmamap_callback_t *, void *, int);
|
||||
static void nexus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
|
||||
static void nexus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t);
|
||||
static int nexus_dmamem_alloc(bus_dma_tag_t, void **, int, bus_dmamap_t *);
|
||||
static void nexus_dmamem_free(bus_dma_tag_t, void *, bus_dmamap_t);
|
||||
|
||||
|
||||
bus_dma_tag_t sparc64_root_dma_tag;
|
||||
|
||||
/*
|
||||
* Allocate a device specific dma_tag.
|
||||
*/
|
||||
int
|
||||
bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
|
||||
bus_size_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr,
|
||||
bus_dma_filter_t *filter, void *filterarg, bus_size_t maxsize,
|
||||
int nsegments, bus_size_t maxsegsz, int flags, bus_dma_tag_t *dmat)
|
||||
{
|
||||
|
||||
bus_dma_tag_t newtag, eparent;
|
||||
|
||||
/* Return a NULL tag on failure */
|
||||
*dmat = NULL;
|
||||
|
||||
newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF, M_NOWAIT);
|
||||
if (newtag == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
/* Ugh... */
|
||||
eparent = parent != NULL ? parent : sparc64_root_dma_tag;
|
||||
memcpy(newtag, eparent, sizeof(*newtag));
|
||||
if (parent != NULL)
|
||||
newtag->parent = parent;
|
||||
newtag->alignment = alignment;
|
||||
newtag->boundary = boundary;
|
||||
newtag->lowaddr = trunc_page((vm_offset_t)lowaddr) + (PAGE_SIZE - 1);
|
||||
newtag->highaddr = trunc_page((vm_offset_t)highaddr) + (PAGE_SIZE - 1);
|
||||
newtag->filter = filter;
|
||||
newtag->filterarg = filterarg;
|
||||
newtag->maxsize = maxsize;
|
||||
newtag->nsegments = nsegments;
|
||||
newtag->maxsegsz = maxsegsz;
|
||||
newtag->flags = flags;
|
||||
newtag->ref_count = 1; /* Count ourself */
|
||||
newtag->map_count = 0;
|
||||
|
||||
/* Take into account any restrictions imposed by our parent tag */
|
||||
if (parent != NULL) {
|
||||
newtag->lowaddr = ulmin(parent->lowaddr, newtag->lowaddr);
|
||||
newtag->highaddr = ulmax(parent->highaddr, newtag->highaddr);
|
||||
/*
|
||||
* XXX Not really correct??? Probably need to honor boundary
|
||||
* all the way up the inheritence chain.
|
||||
*/
|
||||
newtag->boundary = ulmax(parent->boundary, newtag->boundary);
|
||||
if (parent != NULL)
|
||||
parent->ref_count++;
|
||||
}
|
||||
|
||||
*dmat = newtag;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
bus_dma_tag_destroy(bus_dma_tag_t dmat)
|
||||
{
|
||||
|
||||
if (dmat != NULL) {
|
||||
if (dmat->map_count != 0)
|
||||
return (EBUSY);
|
||||
|
||||
while (dmat != NULL) {
|
||||
bus_dma_tag_t parent;
|
||||
|
||||
parent = dmat->parent;
|
||||
dmat->ref_count--;
|
||||
if (dmat->ref_count == 0) {
|
||||
free(dmat, M_DEVBUF);
|
||||
/*
|
||||
* Last reference count, so
|
||||
* release our reference
|
||||
* count on our parent.
|
||||
*/
|
||||
dmat = parent;
|
||||
} else
|
||||
dmat = NULL;
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Common function for DMA map creation. May be called by bus-specific
|
||||
* DMA map creation functions.
|
||||
*/
|
||||
static int
|
||||
nexus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)
|
||||
{
|
||||
|
||||
/* Not much to do...? */
|
||||
*mapp = malloc(sizeof(**mapp), M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
dmat->map_count++;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Common function for DMA map destruction. May be called by bus-specific
|
||||
* DMA map destruction functions.
|
||||
*/
|
||||
static int
|
||||
nexus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)
|
||||
{
|
||||
|
||||
free(map, M_DEVBUF);
|
||||
dmat->map_count--;
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define BUS_DMAMAP_NSEGS ((BUS_SPACE_MAXSIZE / PAGE_SIZE) + 1)
|
||||
|
||||
/*
|
||||
* Common function for loading a DMA map with a linear buffer. May
|
||||
* be called by bus-specific DMA map load functions.
|
||||
*
|
||||
* Most SPARCs have IOMMUs in the bus controllers. In those cases
|
||||
* they only need one segment and will use virtual addresses for DVMA.
|
||||
* Those bus controllers should intercept these vectors and should
|
||||
* *NEVER* call nexus_dmamap_load() which is used only by devices that
|
||||
* bypass DVMA.
|
||||
*/
|
||||
static int
|
||||
nexus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
|
||||
bus_size_t buflen, bus_dmamap_callback_t *callback, void *callback_arg,
|
||||
int flags)
|
||||
{
|
||||
vm_offset_t vaddr;
|
||||
vm_offset_t paddr;
|
||||
#ifdef __GNUC__
|
||||
bus_dma_segment_t dm_segments[dmat->nsegments];
|
||||
#else
|
||||
bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS];
|
||||
#endif
|
||||
bus_dma_segment_t *sg;
|
||||
int seg;
|
||||
int error;
|
||||
vm_offset_t nextpaddr;
|
||||
bus_size_t size;
|
||||
|
||||
error = 0;
|
||||
|
||||
vaddr = (vm_offset_t)buf;
|
||||
sg = &dm_segments[0];
|
||||
seg = 1;
|
||||
sg->ds_len = 0;
|
||||
|
||||
map->buf = buf;
|
||||
map->buflen = buflen;
|
||||
map->start = (bus_addr_t)buf;
|
||||
|
||||
nextpaddr = 0;
|
||||
do {
|
||||
paddr = pmap_kextract(vaddr);
|
||||
size = PAGE_SIZE - (paddr & PAGE_MASK);
|
||||
if (size > buflen)
|
||||
size = buflen;
|
||||
|
||||
if (sg->ds_len == 0) {
|
||||
sg->ds_addr = paddr;
|
||||
sg->ds_len = size;
|
||||
} else if (paddr == nextpaddr) {
|
||||
sg->ds_len += size;
|
||||
} else {
|
||||
/* Go to the next segment */
|
||||
sg++;
|
||||
seg++;
|
||||
if (seg > dmat->nsegments)
|
||||
break;
|
||||
sg->ds_addr = paddr;
|
||||
sg->ds_len = size;
|
||||
}
|
||||
vaddr += size;
|
||||
nextpaddr = paddr + size;
|
||||
buflen -= size;
|
||||
} while (buflen > 0);
|
||||
|
||||
if (buflen != 0) {
|
||||
printf("bus_dmamap_load: Too many segs! buf_len = 0x%lx\n",
|
||||
(u_long)buflen);
|
||||
error = EFBIG;
|
||||
}
|
||||
|
||||
(*callback)(callback_arg, dm_segments, seg, error);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Common function for unloading a DMA map. May be called by
|
||||
* bus-specific DMA map unload functions.
|
||||
*/
|
||||
static void
|
||||
nexus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
|
||||
{
|
||||
|
||||
/* Nothing to do...? */
|
||||
}
|
||||
|
||||
/*
|
||||
* Common function for DMA map synchronization. May be called
|
||||
* by bus-specific DMA map synchronization functions.
|
||||
*/
|
||||
static void
|
||||
nexus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
|
||||
{
|
||||
|
||||
/*
|
||||
* We sync out our caches, but the bus must do the same.
|
||||
*
|
||||
* Actually a #Sync is expensive. We should optimize.
|
||||
*/
|
||||
if ((op == BUS_DMASYNC_PREREAD) || (op == BUS_DMASYNC_PREWRITE)) {
|
||||
/*
|
||||
* Don't really need to do anything, but flush any pending
|
||||
* writes anyway.
|
||||
*/
|
||||
membar(Sync);
|
||||
}
|
||||
if (op == BUS_DMASYNC_POSTREAD) {
|
||||
/*
|
||||
* Invalidate the caches (it is unclear whether that is really
|
||||
* needed. The manual only mentions that PCI transactions are
|
||||
* cache coherent).
|
||||
*/
|
||||
ecache_flush((vm_offset_t)map->buf,
|
||||
(vm_offset_t)map->buf + map->buflen - 1);
|
||||
}
|
||||
if (op == BUS_DMASYNC_POSTWRITE) {
|
||||
/* Nothing to do. Handled by the bus controller. */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper functions for buses that use their private dmamem_alloc/dmamem_free
|
||||
* versions.
|
||||
* These differ from the dmamap_alloc() functions in that they create a tag
|
||||
* that is specifically for use with dmamem_alloc'ed memory.
|
||||
* These are primitive now, but I expect that some fields of the map will need
|
||||
* to be filled soon.
|
||||
*/
|
||||
int
|
||||
sparc64_dmamem_alloc_map(bus_dma_tag_t dmat, bus_dmamap_t *mapp)
|
||||
{
|
||||
|
||||
*mapp = malloc(sizeof(**mapp), M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
if (*mapp == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
dmat->map_count++;
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
sparc64_dmamem_free_map(bus_dma_tag_t dmat, bus_dmamap_t map)
|
||||
{
|
||||
|
||||
free(map, M_DEVBUF);
|
||||
dmat->map_count--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Common function for DMA-safe memory allocation. May be called
|
||||
* by bus-specific DMA memory allocation functions.
|
||||
*/
|
||||
static int
|
||||
nexus_dmamem_alloc(bus_dma_tag_t dmat, void **vaddr, int flags,
|
||||
bus_dmamap_t *mapp)
|
||||
{
|
||||
|
||||
if ((dmat->maxsize <= PAGE_SIZE)) {
|
||||
*vaddr = malloc(dmat->maxsize, M_DEVBUF,
|
||||
(flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK);
|
||||
} else {
|
||||
/*
|
||||
* XXX: Use contigmalloc until it is merged into this facility
|
||||
* and handles multi-seg allocations. Nobody is doing multi-seg
|
||||
* allocations yet though.
|
||||
*/
|
||||
*vaddr = contigmalloc(dmat->maxsize, M_DEVBUF,
|
||||
(flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK,
|
||||
0ul, dmat->lowaddr, dmat->alignment ? dmat->alignment : 1UL,
|
||||
dmat->boundary);
|
||||
}
|
||||
if (*vaddr == NULL) {
|
||||
free(*mapp, M_DEVBUF);
|
||||
return (ENOMEM);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Common function for freeing DMA-safe memory. May be called by
|
||||
* bus-specific DMA memory free functions.
|
||||
*/
|
||||
static void
|
||||
nexus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)
|
||||
{
|
||||
|
||||
sparc64_dmamem_free_map(dmat, map);
|
||||
if ((dmat->maxsize <= PAGE_SIZE))
|
||||
free(vaddr, M_DEVBUF);
|
||||
else
|
||||
contigfree(vaddr, dmat->maxsize, M_DEVBUF);
|
||||
}
|
||||
|
||||
struct bus_dma_tag nexus_dmatag = {
|
||||
NULL,
|
||||
NULL,
|
||||
8,
|
||||
0,
|
||||
0,
|
||||
0x3ffffffff,
|
||||
NULL, /* XXX */
|
||||
NULL,
|
||||
0x3ffffffff, /* XXX */
|
||||
0xff, /* XXX */
|
||||
0xffffffff, /* XXX */
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
nexus_dmamap_create,
|
||||
nexus_dmamap_destroy,
|
||||
nexus_dmamap_load,
|
||||
nexus_dmamap_unload,
|
||||
nexus_dmamap_sync,
|
||||
|
||||
nexus_dmamem_alloc,
|
||||
nexus_dmamem_free,
|
||||
};
|
||||
|
||||
/*
|
||||
* Helpers to map/unmap bus memory
|
||||
*/
|
||||
int
|
||||
sparc64_bus_mem_map(bus_type_t iospace, bus_addr_t addr,
|
||||
bus_size_t size, int flags, vm_offset_t vaddr, void **hp)
|
||||
{
|
||||
vm_offset_t v;
|
||||
vm_offset_t pa;
|
||||
u_long pm_flags;
|
||||
|
||||
size = round_page(size);
|
||||
if (size == 0) {
|
||||
printf("sparc64_bus_map: zero size\n");
|
||||
return (EINVAL);
|
||||
}
|
||||
switch (iospace) {
|
||||
case PCI_CONFIG_BUS_SPACE:
|
||||
case PCI_IO_BUS_SPACE:
|
||||
case PCI_MEMORY_BUS_SPACE:
|
||||
pm_flags = TD_IE;
|
||||
break;
|
||||
default:
|
||||
pm_flags = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(flags & BUS_SPACE_MAP_CACHEABLE))
|
||||
pm_flags |= TD_E;
|
||||
|
||||
if (vaddr != NULL)
|
||||
v = trunc_page(vaddr);
|
||||
else {
|
||||
if ((v = kmem_alloc_nofault(kernel_map, size)) == NULL)
|
||||
panic("sparc64_bus_map: cannot allocate virtual "
|
||||
"memory");
|
||||
}
|
||||
|
||||
/* note: preserve page offset */
|
||||
*hp = (void *)(v | ((u_long)addr & PAGE_MASK));
|
||||
|
||||
pa = trunc_page(addr);
|
||||
if ((flags & BUS_SPACE_MAP_READONLY) == 0)
|
||||
pm_flags |= TD_W;
|
||||
|
||||
do {
|
||||
pmap_kenter_flags(v, pa, pm_flags);
|
||||
v += PAGE_SIZE;
|
||||
pa += PAGE_SIZE;
|
||||
} while ((size -= PAGE_SIZE) > 0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
sparc64_bus_mem_unmap(void *bh, bus_size_t size)
|
||||
{
|
||||
vm_offset_t va ;
|
||||
vm_offset_t endva;
|
||||
|
||||
va = trunc_page((vm_offset_t)bh);
|
||||
endva = va + round_page(size);
|
||||
for (; va < endva; va += PAGE_SIZE)
|
||||
pmap_kremove(va);
|
||||
kmem_free(kernel_map, va, size);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fake up a bus tag, for use by console drivers in early boot when the regular
|
||||
* means to allocate resources are not yet available.
|
||||
* Note that these tags are not eligible for bus_space_barrier operations.
|
||||
* Addr is the physical address of the desired start of the handle.
|
||||
*/
|
||||
bus_space_handle_t
|
||||
sparc64_fake_bustag(int space, bus_addr_t addr, struct bus_space_tag *ptag)
|
||||
{
|
||||
|
||||
ptag->cookie = NULL;
|
||||
ptag->parent = NULL;
|
||||
ptag->type = space;
|
||||
ptag->bus_barrier = NULL;
|
||||
return (addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Base bus space handlers.
|
||||
*/
|
||||
static void nexus_bus_barrier(bus_space_tag_t, bus_space_handle_t,
|
||||
bus_size_t, bus_size_t, int);
|
||||
|
||||
static void
|
||||
nexus_bus_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset,
|
||||
bus_size_t size, int flags)
|
||||
{
|
||||
|
||||
/*
|
||||
* We have lots of alternatives depending on whether we're
|
||||
* synchronizing loads with loads, loads with stores, stores
|
||||
* with loads, or stores with stores. The only ones that seem
|
||||
* generic are #Sync and #MemIssue. I'll use #Sync for safety.
|
||||
*/
|
||||
switch(flags) {
|
||||
case BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE:
|
||||
case BUS_SPACE_BARRIER_READ:
|
||||
case BUS_SPACE_BARRIER_WRITE:
|
||||
membar(Sync);
|
||||
break;
|
||||
default:
|
||||
panic("sparc64_bus_barrier: unknown flags");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
struct bus_space_tag nexus_bustag = {
|
||||
NULL, /* cookie */
|
||||
NULL, /* parent bus tag */
|
||||
UPA_BUS_SPACE, /* type */
|
||||
nexus_bus_barrier, /* bus_space_barrier */
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user