summaryrefslogtreecommitdiff
path: root/sys/arch/macppc
diff options
context:
space:
mode:
authorJason Wright <jason@cvs.openbsd.org>2001-12-12 19:18:24 +0000
committerJason Wright <jason@cvs.openbsd.org>2001-12-12 19:18:24 +0000
commit018ee021078abdaf33a0e4d21a39e9064a3236fe (patch)
tree7e23ac3ceb99b697f8ee19cde15fc369e246b002 /sys/arch/macppc
parentd5e6e059f60c76132da18a9bd58d384f0a204529 (diff)
Full suite of bus_dma functions (except bus_dmamap_load_raw)... this allows
the crypto layer and drivers using bus_dmamap_load_mbuf() to work (tested with hifn and dc); Mostly from NetBSD
Diffstat (limited to 'sys/arch/macppc')
-rw-r--r--sys/arch/macppc/macppc/dma.c176
1 files changed, 137 insertions, 39 deletions
diff --git a/sys/arch/macppc/macppc/dma.c b/sys/arch/macppc/macppc/dma.c
index 05692de52e6..5c27994b736 100644
--- a/sys/arch/macppc/macppc/dma.c
+++ b/sys/arch/macppc/macppc/dma.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dma.c,v 1.8 2001/12/08 02:24:06 art Exp $ */
+/* $OpenBSD: dma.c,v 1.9 2001/12/12 19:18:23 jason Exp $ */
/* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */
/*-
@@ -122,49 +122,38 @@ _dmamap_destroy(t, map)
free(map, M_DEVBUF);
}
-/*
- * Common function for loading a DMA map with a linear buffer. May
- * be called by bus-specific DMA map load functions.
- */
+int _dmamap_load_buffer __P((bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t,
+ struct proc *, int, paddr_t *, int *, int));
+
int
-_dmamap_load(t, map, buf, buflen, p, flags)
+_dmamap_load_buffer(t, map, buf, buflen, p, flags, lastaddrp, segp, first)
bus_dma_tag_t t;
bus_dmamap_t map;
void *buf;
bus_size_t buflen;
struct proc *p;
int flags;
+ paddr_t *lastaddrp;
+ int *segp;
+ int first;
{
bus_size_t sgsize;
bus_addr_t curaddr, lastaddr, baddr, bmask;
- caddr_t vaddr = buf;
- int first, seg;
- pmap_t pmap;
- bus_size_t saved_buflen;
+ vaddr_t vaddr = (vaddr_t)buf;
+ int seg;
- /*
- * Make sure that on error condition we return "no valid mappings".
- */
- map->dm_nsegs = 0;
- map->dm_mapsize = 0;
-
- if (buflen > map->_dm_size)
- return (EINVAL);
-
- if (p != NULL)
- pmap = p->p_vmspace->vm_map.pmap;
- else
- pmap = pmap_kernel();
+ lastaddr = *lastaddrp;
+ bmask = ~(map->_dm_boundary - 1);
- lastaddr = ~0; /* XXX gcc */
- bmask = ~(map->_dm_boundary - 1);
-
- saved_buflen = buflen;
- for (first = 1, seg = 0; buflen > 0; ) {
+ for (seg = *segp; buflen > 0; ) {
/*
* Get the physical address for this segment.
*/
- pmap_extract(pmap, (vm_offset_t)vaddr, (paddr_t *)&curaddr);
+ if (p != NULL)
+ (void) pmap_extract(p->p_vmspace->vm_map.pmap,
+ vaddr, (paddr_t *)&curaddr);
+ else
+ curaddr = vtophys(vaddr);
/*
* Compute the segment size, and adjust counts.
@@ -183,7 +172,7 @@ _dmamap_load(t, map, buf, buflen, p, flags)
}
/*
- * Insert chunk into a segment, coalescing with
+ * Insert chunk into a segment, coalescing with the
* previous segment if possible.
*/
if (first) {
@@ -194,7 +183,7 @@ _dmamap_load(t, map, buf, buflen, p, flags)
if (curaddr == lastaddr &&
(map->dm_segs[seg].ds_len + sgsize) <=
map->_dm_maxsegsz &&
- (map->_dm_boundary == 0 ||
+ (map->_dm_boundary == 0 ||
(map->dm_segs[seg].ds_addr & bmask) ==
(curaddr & bmask)))
map->dm_segs[seg].ds_len += sgsize;
@@ -211,29 +200,94 @@ _dmamap_load(t, map, buf, buflen, p, flags)
buflen -= sgsize;
}
+ *segp = seg;
+ *lastaddrp = lastaddr;
+
/*
* Did we fit?
*/
if (buflen != 0)
- return (EFBIG); /* XXX better return value here? */
+ return (EFBIG); /* XX better return value here? */
- map->dm_nsegs = seg + 1;
- map->dm_mapsize = saved_buflen;
return (0);
}
/*
+ * Common function for loading a DMA map with a linear buffer. May
+ * be called by bus-specific DMA map load functions.
+ */
+int
+_dmamap_load(t, map, buf, buflen, p, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ void *buf;
+ bus_size_t buflen;
+ struct proc *p;
+ int flags;
+{
+ paddr_t lastaddr;
+ int seg, error;
+
+ /*
+ * Make sure that on error condition we return "no valid mappings".
+ */
+ map->dm_mapsize = 0;
+ map->dm_nsegs = 0;
+
+ if (buflen > map->_dm_size)
+ return (EINVAL);
+
+ seg = 0;
+ error = _dmamap_load_buffer(t, map, buf, buflen, p, flags,
+ &lastaddr, &seg, 1);
+ if (error == 0) {
+ map->dm_mapsize = buflen;
+ map->dm_nsegs = seg + 1;
+ }
+ return (error);
+}
+
+/*
* Like _bus_dmamap_load(), but for mbufs.
*/
int
-_dmamap_load_mbuf(t, map, m, flags)
+_dmamap_load_mbuf(t, map, m0, flags)
bus_dma_tag_t t;
bus_dmamap_t map;
- struct mbuf *m;
+ struct mbuf *m0;
int flags;
{
+ paddr_t lastaddr;
+ int seg, error, first;
+ struct mbuf *m;
- panic("_bus_dmamap_load: not implemented");
+ /*
+ * Make sure that on error condition we return "no valid mappings".
+ */
+ map->dm_mapsize = 0;
+ map->dm_nsegs = 0;
+
+#ifdef DIAGNOSTIC
+ if ((m0->m_flags & M_PKTHDR) == 0)
+ panic("_bus_dmamap_load_mbuf: no packet header");
+#endif
+
+ if (m0->m_pkthdr.len > map->_dm_size)
+ return (EINVAL);
+
+ first = 1;
+ seg = 0;
+ error = 0;
+ for (m = m0; m != NULL && error == 0; m = m->m_next) {
+ error = _dmamap_load_buffer(t, map, m->m_data, m->m_len,
+ NULL, flags, &lastaddr, &seg, first);
+ first = 0;
+ }
+ if (error == 0) {
+ map->dm_mapsize = m0->m_pkthdr.len;
+ map->dm_nsegs = seg + 1;
+ }
+ return (error);
}
/*
@@ -246,8 +300,52 @@ _dmamap_load_uio(t, map, uio, flags)
struct uio *uio;
int flags;
{
- /* XXX Need a real implementation. */
- return (EOPNOTSUPP);
+ paddr_t lastaddr;
+ int seg, i, error, first;
+ bus_size_t minlen, resid;
+ struct proc *p = NULL;
+ struct iovec *iov;
+ caddr_t addr;
+
+ /*
+ * Make sure that on error condition we return "no valid mappings".
+ */
+ map->dm_mapsize = 0;
+ map->dm_nsegs = 0;
+
+ resid = uio->uio_resid;
+ iov = uio->uio_iov;
+
+ if (uio->uio_segflg == UIO_USERSPACE) {
+ p = uio->uio_procp;
+#ifdef DIAGNOSTIC
+ if (p == NULL)
+ panic("_bus_dmamap_load_uio: USERSPACE but no proc");
+#endif
+ }
+
+ first = 1;
+ seg = 0;
+ error = 0;
+ for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) {
+ /*
+ * Now at the first iovec to load. Load each iovec
+ * until we have exhausted the residual count.
+ */
+ minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len;
+ addr = (caddr_t)iov[i].iov_base;
+
+ error = _dmamap_load_buffer(t, map, addr, minlen,
+ p, flags, &lastaddr, &seg, first);
+ first = 0;
+
+ resid -= minlen;
+ }
+ if (error == 0) {
+ map->dm_mapsize = uio->uio_resid;
+ map->dm_nsegs = seg + 1;
+ }
+ return (error);
}
/*