diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-07-13 19:50:01 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-07-13 19:50:01 +0000 |
commit | 2a4b8ea3d55e1875ad3e17a8ab967ab24b4a3518 (patch) | |
tree | 059077a2e39f9356fd4fa5966010cf33a4328ecc /sys/arch/sparc/include | |
parent | 17390d84c2173e5c927a38499f6d8829c8389aec (diff) |
Add a somewhat minimal bus_dma(9) implementation. Only fully implemented for
the sun4m iommu. Bits and pieces from NetBSD, with some additional tweaks
and a bus_dmamap_load_mbuf() implementation from myself.
ok miod@
Diffstat (limited to 'sys/arch/sparc/include')
-rw-r--r-- | sys/arch/sparc/include/bus.h | 188 |
1 files changed, 187 insertions, 1 deletions
diff --git a/sys/arch/sparc/include/bus.h b/sys/arch/sparc/include/bus.h index c47a71e8bd7..d938939cc89 100644 --- a/sys/arch/sparc/include/bus.h +++ b/sys/arch/sparc/include/bus.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bus.h,v 1.6 2006/01/01 00:41:02 millert Exp $ */ +/* $OpenBSD: bus.h,v 1.7 2009/07/13 19:50:00 kettenis Exp $ */ /* * Copyright (c) 2003, Miodrag Vallat. * @@ -497,4 +497,190 @@ bus_space_read_raw_region_4(bus_space_tag_t tag, bus_space_handle_t handle, } } +/* + * Flags used in various bus DMA methods. + */ +#define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */ +#define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */ +#define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */ +#define BUS_DMA_COHERENT 0x004 /* hint: map memory DMA coherent */ +#define BUS_DMA_STREAMING 0x008 /* hint: sequential, unidirectional */ +#define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x020 +#define BUS_DMA_BUS3 0x040 +#define BUS_DMA_BUS4 0x080 +#define BUS_DMA_READ 0x100 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */ +#define BUS_DMA_NOCACHE 0x400 /* hint: map non-cached memory */ +#define BUS_DMA_ZERO 0x800 /* zero memory in dmamem_alloc */ + +/* For devices that have a 24-bit address space */ +#define BUS_DMA_24BIT BUS_DMA_BUS1 + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct uio; + +/* + * Operations performed by bus_dmamap_sync(). + */ +#define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ +#define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ +#define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ +#define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ + +typedef struct sparc_bus_dma_tag *bus_dma_tag_t; +typedef struct sparc_bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct sparc_bus_dma_segment { + bus_addr_t ds_addr; /* DVMA address */ + bus_size_t ds_len; /* length of transfer */ + bus_size_t _ds_sgsize; /* size of allocated DVMA segment */ + void *_ds_mlist; /* page list when dmamem_alloc'ed */ + vaddr_t _ds_va; /* VA when dmamem_map'ed */ +}; +typedef struct sparc_bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ +struct sparc_bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + void (*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + void (*_dmamem_free)(bus_dma_tag_t, + bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, void *, size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int); +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, o, l, ops) \ + (void)((t)->_dmamap_sync ? \ + (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) : (void)0) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t), (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t), (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) + +#define bus_dmatag_subregion(t, mna, mxa, nt, f) EOPNOTSUPP +#define bus_dmatag_destroy(t) + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct sparc_bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxmaxsegsz; /* fixed largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_flags; /* misc. flags */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + u_long _dm_align; /* DVMA alignment; must be a + multiple of the page size */ + u_long _dm_ex_start; /* constraints on DVMA map */ + u_long _dm_ex_end; /* allocations; used by the VME bus + driver and by the IOMMU driver + when mapping 24-bit devices */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_maxsegsz; /* largest possible segment */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +int _bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t, + bus_size_t, int, bus_dmamap_t *); +void _bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); +int _bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int); +int _bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, + struct uio *, int); +int _bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +void _bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t); +void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, + bus_size_t, int); + +int _bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, + bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags); +void _bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs); +void _bus_dmamem_unmap(bus_dma_tag_t tag, void *kva, + size_t size); +paddr_t _bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs, + int nsegs, off_t off, int prot, int flags); + +int _bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, + bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags, + vaddr_t low, vaddr_t high); + +vaddr_t _bus_dma_valloc_skewed(size_t, u_long, u_long, u_long); + #endif /* _SPARC_BUS_H_ */ |