Handle bus_dma aligment properly.
This commit is contained in:
parent
7753949047
commit
3f2289a3d7
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: iommu.c,v 1.20 2000/07/02 14:00:38 mrg Exp $ */
|
/* $NetBSD: iommu.c,v 1.21 2000/07/07 02:50:21 eeh Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2000 Matthew R. Green
|
* Copyright (c) 1999, 2000 Matthew R. Green
|
||||||
|
@ -240,7 +240,7 @@ iommu_init(name, is, tsbsize)
|
||||||
(unsigned int)is->is_dvmabase,
|
(unsigned int)is->is_dvmabase,
|
||||||
(unsigned int)IOTSB_VEND);
|
(unsigned int)IOTSB_VEND);
|
||||||
is->is_dvmamap = extent_create(name,
|
is->is_dvmamap = extent_create(name,
|
||||||
is->is_dvmabase, IOTSB_VEND,
|
is->is_dvmabase, (u_long)IOTSB_VEND,
|
||||||
M_DEVBUF, 0, 0, EX_NOWAIT);
|
M_DEVBUF, 0, 0, EX_NOWAIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,21 +255,27 @@ iommu_reset(is)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Need to do 64-bit stores */
|
/* Need to do 64-bit stores */
|
||||||
bus_space_write_8(is->is_bustag, &is->is_iommu->iommu_tsb, 0, is->is_ptsb);
|
bus_space_write_8(is->is_bustag,
|
||||||
|
(bus_space_handle_t)(u_long)&is->is_iommu->iommu_tsb,
|
||||||
|
0, is->is_ptsb);
|
||||||
/* Enable IOMMU in diagnostic mode */
|
/* Enable IOMMU in diagnostic mode */
|
||||||
bus_space_write_8(is->is_bustag, &is->is_iommu->iommu_cr, 0,
|
bus_space_write_8(is->is_bustag,
|
||||||
is->is_cr|IOMMUCR_DE);
|
(bus_space_handle_t)(u_long)&is->is_iommu->iommu_cr, 0,
|
||||||
|
is->is_cr|IOMMUCR_DE);
|
||||||
|
|
||||||
|
|
||||||
if (!is->is_sb)
|
if (!is->is_sb)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Enable diagnostics mode? */
|
/* Enable diagnostics mode? */
|
||||||
bus_space_write_8(is->is_bustag, &is->is_sb->strbuf_ctl, 0, STRBUF_EN);
|
bus_space_write_8(is->is_bustag,
|
||||||
|
(bus_space_handle_t)(u_long)&is->is_sb->strbuf_ctl,
|
||||||
|
0, STRBUF_EN);
|
||||||
|
|
||||||
/* No streaming buffers? Disable them */
|
/* No streaming buffers? Disable them */
|
||||||
if (bus_space_read_8(is->is_bustag,
|
if (bus_space_read_8(is->is_bustag,
|
||||||
(bus_space_handle_t)(u_long)&is->is_sb->strbuf_ctl, 0) == 0)
|
(bus_space_handle_t)(u_long)&is->is_sb->strbuf_ctl,
|
||||||
|
0) == 0)
|
||||||
is->is_sb = 0;
|
is->is_sb = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,15 +301,15 @@ iommu_enter(is, va, pa, flags)
|
||||||
|
|
||||||
/* Is the streamcache flush really needed? */
|
/* Is the streamcache flush really needed? */
|
||||||
if (is->is_sb) {
|
if (is->is_sb) {
|
||||||
bus_space_write_8(is->is_bustag, &is->is_sb->strbuf_pgflush, 0,
|
bus_space_write_8(is->is_bustag, (bus_space_handle_t)(u_long)
|
||||||
va);
|
&is->is_sb->strbuf_pgflush, 0, va);
|
||||||
iommu_strbuf_flush(is);
|
iommu_strbuf_flush(is);
|
||||||
}
|
}
|
||||||
DPRINTF(IDB_DVMA, ("Clearing TSB slot %d for va %p\n",
|
DPRINTF(IDB_DVMA, ("Clearing TSB slot %d for va %p\n",
|
||||||
(int)IOTSBSLOT(va,is->is_tsbsize), va));
|
(int)IOTSBSLOT(va,is->is_tsbsize), va));
|
||||||
is->is_tsb[IOTSBSLOT(va,is->is_tsbsize)] = tte;
|
is->is_tsb[IOTSBSLOT(va,is->is_tsbsize)] = tte;
|
||||||
bus_space_write_8(is->is_bustag, &is->is_iommu->iommu_flush,
|
bus_space_write_8(is->is_bustag, (bus_space_handle_t)(u_long)
|
||||||
0, va);
|
&is->is_iommu->iommu_flush, 0, va);
|
||||||
DPRINTF(IDB_DVMA, ("iommu_enter: va %lx pa %lx TSB[%lx]@%p=%lx\n",
|
DPRINTF(IDB_DVMA, ("iommu_enter: va %lx pa %lx TSB[%lx]@%p=%lx\n",
|
||||||
va, (long)pa, IOTSBSLOT(va,is->is_tsbsize),
|
va, (long)pa, IOTSBSLOT(va,is->is_tsbsize),
|
||||||
&is->is_tsb[IOTSBSLOT(va,is->is_tsbsize)],
|
&is->is_tsb[IOTSBSLOT(va,is->is_tsbsize)],
|
||||||
|
@ -347,8 +353,8 @@ iommu_remove(is, va, len)
|
||||||
(long)&is->is_tsb[IOTSBSLOT(va,is->is_tsbsize)],
|
(long)&is->is_tsb[IOTSBSLOT(va,is->is_tsbsize)],
|
||||||
(long)(is->is_tsb[IOTSBSLOT(va,is->is_tsbsize)]),
|
(long)(is->is_tsb[IOTSBSLOT(va,is->is_tsbsize)]),
|
||||||
(u_long)len));
|
(u_long)len));
|
||||||
bus_space_write_8(is->is_bustag,
|
bus_space_write_8(is->is_bustag, (bus_space_handle_t)(u_long)
|
||||||
&is->is_sb->strbuf_pgflush, 0, va);
|
&is->is_sb->strbuf_pgflush, 0, va);
|
||||||
if (len <= NBPG)
|
if (len <= NBPG)
|
||||||
iommu_strbuf_flush(is);
|
iommu_strbuf_flush(is);
|
||||||
DPRINTF(IDB_DVMA, ("iommu_remove: flushed va %p TSB[%lx]@%p=%lx, %lu bytes left\n",
|
DPRINTF(IDB_DVMA, ("iommu_remove: flushed va %p TSB[%lx]@%p=%lx, %lu bytes left\n",
|
||||||
|
@ -365,7 +371,8 @@ iommu_remove(is, va, len)
|
||||||
len -= NBPG;
|
len -= NBPG;
|
||||||
|
|
||||||
is->is_tsb[IOTSBSLOT(va,is->is_tsbsize)] = 0;
|
is->is_tsb[IOTSBSLOT(va,is->is_tsbsize)] = 0;
|
||||||
bus_space_write_8(is->is_bustag, &is->is_iommu->iommu_flush, 0, va);
|
bus_space_write_8(is->is_bustag, (bus_space_handle_t)(u_long)
|
||||||
|
&is->is_iommu->iommu_flush, 0, va);
|
||||||
va += NBPG;
|
va += NBPG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -405,7 +412,8 @@ iommu_strbuf_flush(is)
|
||||||
|
|
||||||
is->is_flush = 0;
|
is->is_flush = 0;
|
||||||
membar_sync();
|
membar_sync();
|
||||||
bus_space_write_8(is->is_bustag, &is->is_sb->strbuf_flushsync, 0, is->is_flushpa);
|
bus_space_write_8(is->is_bustag, (bus_space_handle_t)(u_long)
|
||||||
|
&is->is_sb->strbuf_flushsync, 0, is->is_flushpa);
|
||||||
membar_sync();
|
membar_sync();
|
||||||
|
|
||||||
microtime(&flushtimeout);
|
microtime(&flushtimeout);
|
||||||
|
@ -452,7 +460,8 @@ iommu_dvmamap_load(t, is, map, buf, buflen, p, flags)
|
||||||
int err;
|
int err;
|
||||||
bus_size_t sgsize;
|
bus_size_t sgsize;
|
||||||
paddr_t curaddr;
|
paddr_t curaddr;
|
||||||
u_long dvmaddr, align;
|
u_long dvmaddr;
|
||||||
|
bus_size_t align, boundary;
|
||||||
vaddr_t vaddr = (vaddr_t)buf;
|
vaddr_t vaddr = (vaddr_t)buf;
|
||||||
pmap_t pmap;
|
pmap_t pmap;
|
||||||
|
|
||||||
|
@ -478,12 +487,15 @@ iommu_dvmamap_load(t, is, map, buf, buflen, p, flags)
|
||||||
sgsize = round_page(buflen + ((int)vaddr & PGOFSET));
|
sgsize = round_page(buflen + ((int)vaddr & PGOFSET));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX Need to implement "don't dma across this boundry".
|
* A boundary presented to bus_dmamem_alloc() takes precedence
|
||||||
|
* over boundary in the map.
|
||||||
*/
|
*/
|
||||||
align = max(map->_dm_boundary, NBPG);
|
if ((boundary = (map->dm_segs[0]._ds_boundary)) == 0)
|
||||||
|
boundary = map->_dm_boundary;
|
||||||
|
align = max(map->dm_segs[0]._ds_align, NBPG);
|
||||||
s = splhigh();
|
s = splhigh();
|
||||||
err = extent_alloc(is->is_dvmamap, sgsize, align,
|
err = extent_alloc(is->is_dvmamap, sgsize, align,
|
||||||
map->_dm_boundary, EX_NOWAIT|EX_BOUNDZERO, (u_long *)&dvmaddr);
|
boundary, EX_NOWAIT|EX_BOUNDZERO, (u_long *)&dvmaddr);
|
||||||
splx(s);
|
splx(s);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -598,7 +610,7 @@ iommu_dvmamap_load_raw(t, is, map, segs, nsegs, size, flags)
|
||||||
int err;
|
int err;
|
||||||
bus_size_t sgsize;
|
bus_size_t sgsize;
|
||||||
paddr_t pa;
|
paddr_t pa;
|
||||||
u_long boundary, align;
|
bus_size_t boundary, align;
|
||||||
u_long dvmaddr;
|
u_long dvmaddr;
|
||||||
struct pglist *mlist;
|
struct pglist *mlist;
|
||||||
int pagesz = PAGE_SIZE;
|
int pagesz = PAGE_SIZE;
|
||||||
|
@ -633,7 +645,7 @@ iommu_dvmamap_load_raw(t, is, map, segs, nsegs, size, flags)
|
||||||
if ((boundary = segs[0]._ds_boundary) == 0)
|
if ((boundary = segs[0]._ds_boundary) == 0)
|
||||||
boundary = map->_dm_boundary;
|
boundary = map->_dm_boundary;
|
||||||
|
|
||||||
align = max(map->_dm_boundary, NBPG);
|
align = max(segs[0]._ds_align, NBPG);
|
||||||
s = splhigh();
|
s = splhigh();
|
||||||
err = extent_alloc(is->is_dvmamap, sgsize, align, boundary,
|
err = extent_alloc(is->is_dvmamap, sgsize, align, boundary,
|
||||||
((flags & BUS_DMA_NOWAIT) == 0 ? EX_WAITOK : EX_NOWAIT)|EX_BOUNDZERO,
|
((flags & BUS_DMA_NOWAIT) == 0 ? EX_WAITOK : EX_NOWAIT)|EX_BOUNDZERO,
|
||||||
|
@ -712,8 +724,9 @@ iommu_dvmamap_sync(t, is, map, offset, len, ops)
|
||||||
DPRINTF(IDB_DVMA,
|
DPRINTF(IDB_DVMA,
|
||||||
("iommu_dvmamap_sync: flushing va %p, %lu "
|
("iommu_dvmamap_sync: flushing va %p, %lu "
|
||||||
"bytes left\n", (long)va, (u_long)len));
|
"bytes left\n", (long)va, (u_long)len));
|
||||||
bus_space_write_8(is->is_bustag,
|
bus_space_write_8(is->is_bustag,
|
||||||
&is->is_sb->strbuf_pgflush, 0, va);
|
(bus_space_handle_t)(u_long)
|
||||||
|
&is->is_sb->strbuf_pgflush, 0, va);
|
||||||
if (len <= NBPG) {
|
if (len <= NBPG) {
|
||||||
iommu_strbuf_flush(is);
|
iommu_strbuf_flush(is);
|
||||||
len = 0;
|
len = 0;
|
||||||
|
@ -750,7 +763,7 @@ iommu_dvmamem_alloc(t, is, size, alignment, boundary, segs, nsegs, rsegs, flags)
|
||||||
DPRINTF(IDB_DVMA, ("iommu_dvmamem_alloc: sz %qx align %qx bound %qx "
|
DPRINTF(IDB_DVMA, ("iommu_dvmamem_alloc: sz %qx align %qx bound %qx "
|
||||||
"segp %p flags %d\n", size, alignment, boundary, segs, flags));
|
"segp %p flags %d\n", size, alignment, boundary, segs, flags));
|
||||||
return (bus_dmamem_alloc(t->_parent, size, alignment, boundary,
|
return (bus_dmamem_alloc(t->_parent, size, alignment, boundary,
|
||||||
segs, nsegs, rsegs, flags));
|
segs, nsegs, rsegs, flags|BUS_DMA_DVMA));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: bus.h,v 1.19 2000/06/29 14:10:16 pk Exp $ */
|
/* $NetBSD: bus.h,v 1.20 2000/07/07 02:50:19 eeh Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
|
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
|
||||||
|
@ -870,11 +870,15 @@ bus_space_copy_region_8(t, h1, o1, h2, o2, c)
|
||||||
#define BUS_DMA_ALLOCNOW 0x02 /* perform resource allocation now */
|
#define BUS_DMA_ALLOCNOW 0x02 /* perform resource allocation now */
|
||||||
#define BUS_DMA_COHERENT 0x04 /* hint: map memory DMA coherent */
|
#define BUS_DMA_COHERENT 0x04 /* hint: map memory DMA coherent */
|
||||||
#define BUS_DMA_NOWRITE 0x08 /* I suppose the following two should default on */
|
#define BUS_DMA_NOWRITE 0x08 /* I suppose the following two should default on */
|
||||||
#define BUS_DMA_NOCACHE 0x10
|
#define BUS_DMA_BUS1 0x10
|
||||||
#define BUS_DMA_BUS2 0x20
|
#define BUS_DMA_BUS2 0x20
|
||||||
#define BUS_DMA_BUS3 0x40
|
#define BUS_DMA_BUS3 0x40
|
||||||
#define BUS_DMA_BUS4 0x80
|
#define BUS_DMA_BUS4 0x80
|
||||||
|
|
||||||
|
|
||||||
|
#define BUS_DMA_NOCACHE BUS_DMA_BUS1
|
||||||
|
#define BUS_DMA_DVMA BUS_DMA_BUS2 /* Don't bother with alignment */
|
||||||
|
|
||||||
/* Forwards needed by prototypes below. */
|
/* Forwards needed by prototypes below. */
|
||||||
struct mbuf;
|
struct mbuf;
|
||||||
struct uio;
|
struct uio;
|
||||||
|
@ -900,6 +904,7 @@ struct sparc_bus_dma_segment {
|
||||||
bus_addr_t ds_addr; /* DVMA address */
|
bus_addr_t ds_addr; /* DVMA address */
|
||||||
bus_size_t ds_len; /* length of transfer */
|
bus_size_t ds_len; /* length of transfer */
|
||||||
bus_size_t _ds_boundary; /* don't cross this */
|
bus_size_t _ds_boundary; /* don't cross this */
|
||||||
|
bus_size_t _ds_align; /* align to this */
|
||||||
void *_ds_mlist; /* XXX - dmamap_alloc'ed pages */
|
void *_ds_mlist; /* XXX - dmamap_alloc'ed pages */
|
||||||
};
|
};
|
||||||
typedef struct sparc_bus_dma_segment bus_dma_segment_t;
|
typedef struct sparc_bus_dma_segment bus_dma_segment_t;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: machdep.c,v 1.74 2000/06/30 22:58:02 eeh Exp $ */
|
/* $NetBSD: machdep.c,v 1.75 2000/07/07 02:50:20 eeh Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
|
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
|
||||||
|
@ -1044,7 +1044,8 @@ _bus_dmamap_create(t, size, nsegments, maxsegsz, boundary, flags, dmamp)
|
||||||
map->_dm_segcnt = nsegments;
|
map->_dm_segcnt = nsegments;
|
||||||
map->_dm_maxsegsz = maxsegsz;
|
map->_dm_maxsegsz = maxsegsz;
|
||||||
map->_dm_boundary = boundary;
|
map->_dm_boundary = boundary;
|
||||||
map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT|BUS_DMA_COHERENT|BUS_DMA_NOWRITE|BUS_DMA_NOCACHE);
|
map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT|BUS_DMA_COHERENT|
|
||||||
|
BUS_DMA_NOWRITE|BUS_DMA_NOCACHE);
|
||||||
map->dm_mapsize = 0; /* no valid mappings */
|
map->dm_mapsize = 0; /* no valid mappings */
|
||||||
map->dm_nsegs = 0;
|
map->dm_nsegs = 0;
|
||||||
|
|
||||||
|
@ -1261,6 +1262,16 @@ _bus_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags)
|
||||||
(flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL)
|
(flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL)
|
||||||
return (ENOMEM);
|
return (ENOMEM);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the bus uses DVMA then ignore boundary and alignment.
|
||||||
|
*/
|
||||||
|
segs[0]._ds_boundary = boundary;
|
||||||
|
segs[0]._ds_align = alignment;
|
||||||
|
if (flags & BUS_DMA_DVMA) {
|
||||||
|
boundary = 0;
|
||||||
|
alignment = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate pages from the VM system.
|
* Allocate pages from the VM system.
|
||||||
*/
|
*/
|
||||||
|
@ -1276,7 +1287,6 @@ _bus_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags)
|
||||||
*/
|
*/
|
||||||
segs[0].ds_addr = NULL; /* UPA does not map things */
|
segs[0].ds_addr = NULL; /* UPA does not map things */
|
||||||
segs[0].ds_len = size;
|
segs[0].ds_len = size;
|
||||||
segs[0]._ds_boundary = boundary;
|
|
||||||
*rsegs = 1;
|
*rsegs = 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue