PERFORCE change 182338 for review
Jakub Wojciech Klama
jceel at FreeBSD.org
Thu Aug 12 23:24:39 UTC 2010
http://p4web.freebsd.org/@@182338?ac=10
Change 182338 by jceel at jceel on 2010/08/12 23:24:18
Add channel allocation mechanism.
Affected files ...
.. //depot/projects/soc2010/jceel_dma/sys/arm/davinci/davinci_devices.c#4 edit
.. //depot/projects/soc2010/jceel_dma/sys/dev/gpdma/gpdma.c#3 edit
.. //depot/projects/soc2010/jceel_dma/sys/dev/gpdma/gpdma.h#3 edit
Differences ...
==== //depot/projects/soc2010/jceel_dma/sys/arm/davinci/davinci_devices.c#4 (text+ko) ====
@@ -30,9 +30,24 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <dev/gpdma/gpdma.h>
+#include <dev/gpdma/gpdma_cdev.h>
+
#include <arm/davinci/davincivar.h>
#include <arm/davinci/davincireg.h>
+struct gpdma_allocation davinci_edma_allocations[] = {
+ { "edma0", 12, 12, gpdma_memutils_init, NULL },
+ { "edma0", 13, 15, gpdma_cdev_init, NULL },
+ { "edma0", 24, 25, gpdma_cdev_init, NULL },
+ { "edma0", 30, 31, gpdma_cdev_init, NULL },
+ { "edma0", 45, 47, gpdma_cdev_init, NULL },
+ { "edma0", 55, 63, gpdma_cdev_init, NULL },
+ { NULL },
+};
+
+struct gpdma_allocation *gpdma_allocations = davinci_edma_allocations;
+
struct obio_device davinci_devices[] = {
{ "aintc", DAVINCI_AINTC_BASE, DAVINCI_AINTC_SIZE,
{ -1 },
==== //depot/projects/soc2010/jceel_dma/sys/dev/gpdma/gpdma.c#3 (text+ko) ====
@@ -45,8 +45,8 @@
#include <dev/gpdma/gpdma_cdev.h>
#include "gpdma_if.h"
+#undef DEBUG
#define DEBUG
-//#undef DEBUG
#ifdef DEBUG
#define debugf(fmt, args...) do { \
printf("gpdma: " fmt "\n", ##args); } while (0)
@@ -58,47 +58,54 @@
LIST_HEAD(, gpdma_engine) gpdma_engines;
struct mtx gpdma_engines_mtx;
+extern struct gpdma_allocation *gpdma_allocations __attribute__ ((weak));
static struct gpdma_engine *gpdma_engine_by_name(const char *);
static struct gpdma_engine *gpdma_engine_by_res(struct resource *);
-static void gpdma_dmamap_load_cb(void *, bus_dma_segment_t *, int, int);
-static void gpdma_dmamap_load_cb2(void *, bus_dma_segment_t *, int, bus_size_t, int);
+void gpdma_dmamap_load_cb(void *, bus_dma_segment_t *, int, int);
+void gpdma_dmamap_load_cb2(void *, bus_dma_segment_t *, int,
+ bus_size_t, int);
void gpdma_init(void *);
+static void gpdma_initialize_channels(struct gpdma_engine *,
+ struct gpdma_allocation *);
static int gpdma_check_transfer(struct gpdma_transfer *);
-static void
+struct gpdma_mapping
+{
+ int gm_error;
+ bus_addr_t gm_addr;
+ bus_size_t gm_len;
+};
+
+void
gpdma_dmamap_load_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
- bus_dma_segment_t *seg = (bus_dma_segment_t *)arg;
+ struct gpdma_mapping *map = (struct gpdma_mapping *)arg;
- KASSERT(nseg == 1, ("bus_dmamap_load returned nseg != 1"));
+// KASSERT(nseg == 1, ("bus_dmamap_load returned nseg != 1"));
- if (error) {
- printf("gpdma_dmamap_load_cb: error %d\n", error);
- panic("cannot map DMA memory");
+ map->gm_error = error;
+
+ if (segs != NULL) {
+ map->gm_addr = segs[0].ds_addr;
+ map->gm_len = segs[0].ds_len;
}
-
- seg->ds_addr = segs[0].ds_addr;
- seg->ds_len = segs[0].ds_len;
}
-static void
+void
gpdma_dmamap_load_cb2(void *arg, bus_dma_segment_t *segs, int nseg,
bus_size_t mapsize, int error)
{
- bus_dma_segment_t *seg = (bus_dma_segment_t *)arg;
+ struct gpdma_mapping *map = (struct gpdma_mapping *)arg;
KASSERT(nseg == 1, ("bus_dmamap_load returned nseg != 1"));
- printf("mapsize=%ld\n", mapsize);
-
- if (error) {
- printf("gpdma_dmamap_load_cb2: error %d\n", error);
- panic("cannot map DMA memory");
+ map->gm_error = error;
+
+ if (segs != NULL) {
+ map->gm_addr = segs[0].ds_addr;
+ map->gm_len = segs[0].ds_len;
}
-
- seg->ds_addr = segs[0].ds_addr;
- seg->ds_len = segs[0].ds_len;
}
static int
@@ -116,14 +123,43 @@
debugf("initialized");
}
+static void
+gpdma_initialize_channels(struct gpdma_engine *engine,
+ struct gpdma_allocation *alloc)
+{
+ int i, j;
+ struct resource **rv;
+
+ printf("gpdma_initialize_channels(engine=%p, alloc=%p)\n", engine, alloc);
+
+ for (i = 0; alloc[i].da_engine != NULL; i++) {
+
+ printf("alloc: name=%s start=%d end=%d func=%p\n", alloc[i].da_engine, alloc[i].da_start, alloc[i].da_end, alloc[i].da_initializer);
+
+ if (!strcmp(device_get_nameunit(engine->de_dev),
+ alloc[i].da_engine)) {
+ rv = malloc((alloc[i].da_end - alloc[i].da_start) *
+ sizeof(struct resource *), M_GPDMA, M_WAITOK);
+
+ for (j = alloc[i].da_start; j <= alloc[i].da_end; j++) {
+ rv[j - alloc[i].da_start] = gpdma_alloc_channel(
+ alloc[i].da_engine, j);
+
+ printf("allocated channel, res=%p\n", rv[j - alloc[i].da_start]);
+ }
+
+ alloc[i].da_initializer(rv,
+ alloc[i].da_end - alloc[i].da_start,
+ alloc[i].da_arg);
+ }
+ }
+}
+
int
gpdma_register_driver(device_t dev, const struct gpdma_capabilities *caps,
bus_dma_tag_t dmatag)
{
struct gpdma_engine *engine;
- struct gpdma_engine_cdev *cdev;
- struct resource *rv;
- int i;
engine = malloc(sizeof(struct gpdma_engine), M_GPDMA, M_WAITOK);
@@ -146,14 +182,9 @@
printf("registered new DMA engine: %s\n", device_get_nameunit(dev));
- LIST_INIT(&engine->de_cdevs);
-
- for (i = 0; i < 15; i++) {
- cdev = malloc(sizeof(*cdev), M_GPDMA, M_WAITOK);
- rv = gpdma_alloc_channel(device_get_nameunit(engine->de_dev), i);
- gpdma_make_cdev(engine, rv, &cdev->dec_cdev);
- LIST_INSERT_HEAD(&engine->de_cdevs, cdev, dec_link);
- }
+ //LIST_INIT(&engine->de_cdevs);
+ if (gpdma_allocations != NULL)
+ gpdma_initialize_channels(engine, gpdma_allocations);
return (0);
}
@@ -213,7 +244,7 @@
#endif
rv = rman_reserve_resource(&engine->de_rman, chno, chno, 1,
- RF_ACTIVE, NULL);
+ RF_ACTIVE, engine->de_dev);
return (rv);
}
@@ -235,6 +266,14 @@
return (engine->de_dmatag);
}
+const struct gpdma_capabilities *
+gpdma_get_caps(struct resource *res)
+{
+ struct gpdma_engine *engine = gpdma_engine_by_res(res);
+
+ return (engine->de_caps);
+}
+
int
gpdma_program_transfer(struct gpdma_transfer *xfer, void **cookiep)
{
@@ -280,6 +319,18 @@
return (GPDMA_STOP_CHANNEL(engine->de_dev, channel));
}
+int
+gpdma_get_transfer_status(void *cookie)
+{
+ struct gpdma_transfer *xfer = (struct gpdma_transfer *)cookie;
+ struct gpdma_engine *engine = xfer->dt_engine;
+ int channel = rman_get_start(xfer->dt_res);
+ int status;
+
+ GPDMA_POLL_CHANNEL(engine->de_dev, channel, &status);
+ return (status);
+}
+
struct gpdma_transfer *
gpdma_alloc_transfer(struct resource *res)
{
@@ -301,6 +352,7 @@
void
gpdma_free_transfer(struct gpdma_transfer *xfer)
{
+
free(xfer, M_GPDMA);
}
@@ -310,6 +362,7 @@
{
struct gpdma_buffer *buf = &xfer->dt_buffers[buffer];
+ buf->db_needsync = 0;
buf->db_addr = paddr;
buf->db_length = length;
return (0);
@@ -320,7 +373,7 @@
size_t length)
{
struct gpdma_buffer *buf = &xfer->dt_buffers[buffer];
- bus_dma_segment_t seg;
+ struct gpdma_mapping map;
bus_dma_tag_create(xfer->dt_engine->de_dmatag,
1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
@@ -328,14 +381,25 @@
NULL, NULL, &buf->db_dmatag);
bus_dmamap_create(buf->db_dmatag, 0, &buf->db_dmamap);
+
+ printf("gpdma_load_buffer_virt(xfer=%p buffer=%d addr=%p length=%d)\n", xfer, buffer, addr, length);
+ printf("buf=%p map=%p tag=%p\n", buf, buf->db_dmamap, buf->db_dmatag);
+
bus_dmamap_load(buf->db_dmatag, buf->db_dmamap, addr,
- length, gpdma_dmamap_load_cb, &seg, BUS_DMA_NOWAIT);
+ length, gpdma_dmamap_load_cb, &map, BUS_DMA_NOWAIT);
+
+ if (map.gm_error != 0)
+ return (map.gm_error);
- if (seg.ds_len != length)
+ if (map.gm_len != length)
return (EFBIG);
- buf->db_addr = seg.ds_addr;
- buf->db_length = seg.ds_len;
+ if (map.gm_addr == 0)
+ return (EINVAL);
+
+ buf->db_needsync = 1;
+ buf->db_addr = map.gm_addr;
+ buf->db_length = map.gm_len;
return (0);
}
@@ -343,9 +407,11 @@
gpdma_load_buffer_uio(struct gpdma_transfer *xfer, int buffer, struct uio *uio)
{
struct gpdma_buffer *buf = &xfer->dt_buffers[buffer];
- bus_dma_segment_t seg;
+ struct gpdma_mapping map;
bus_size_t length = uio->uio_resid;
+ printf("gpdma_load_buffer_uio: addr=%p\n", uio->uio_iov->iov_base);
+
bus_dma_tag_create(xfer->dt_engine->de_dmatag,
1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
NULL, NULL, length, 1, length, BUS_DMA_ALLOCNOW,
@@ -353,37 +419,48 @@
bus_dmamap_create(buf->db_dmatag, 0, &buf->db_dmamap);
bus_dmamap_load_uio(buf->db_dmatag, buf->db_dmamap, uio,
- gpdma_dmamap_load_cb2, &seg, BUS_DMA_NOWAIT);
+ gpdma_dmamap_load_cb2, &map, BUS_DMA_NOWAIT);
+
+ if (map.gm_error != 0)
+ return (map.gm_error);
- if (seg.ds_len != length)
+ if (map.gm_len != length)
return (EFBIG);
- buf->db_addr = seg.ds_addr;
- buf->db_length = seg.ds_len;
+ if (map.gm_addr == 0)
+ return (EINVAL);
+
+ buf->db_needsync = 1;
+ buf->db_addr = map.gm_addr;
+ buf->db_length = map.gm_len;
return (0);
}
inline void
gpdma_set_transfer_func(struct gpdma_transfer *xfer, int func)
{
+
xfer->dt_func = func;
}
inline void
gpdma_set_transfer_opts(struct gpdma_transfer *xfer, int flags)
{
+
xfer->dt_flags = flags;
}
inline void
gpdma_set_transfer_link(struct gpdma_transfer *xfer, struct gpdma_transfer *xfer2)
{
+
xfer->dt_next = xfer2;
}
inline void
gpdma_set_transfer_callback(struct gpdma_transfer *xfer, gpdma_callback_t cb, void *arg)
{
+
xfer->dt_callback = cb;
xfer->dt_callback_arg = arg;
}
@@ -391,30 +468,35 @@
inline void
gpdma_set_transfer_flags(struct gpdma_transfer *xfer, int flags)
{
+
xfer->dt_flags = flags;
}
inline int
gpdma_get_buffer_layout(struct gpdma_transfer *xfer, int buffer)
{
+
return (xfer->dt_buffers[buffer].db_type);
}
inline void
gpdma_set_buffer_layout(struct gpdma_transfer *xfer, int buffer, int type)
{
+
xfer->dt_buffers[buffer].db_type = type;
}
inline void
gpdma_set_buffer_flags(struct gpdma_transfer *xfer, int buffer, int flags)
{
+
xfer->dt_buffers[buffer].db_flags = flags;
}
inline void
gpdma_set_buffer_stride(struct gpdma_transfer *xfer, int buffer, int stride_width, int stride_spacing)
{
+
xfer->dt_buffers[buffer].db_stride_width = stride_width;
xfer->dt_buffers[buffer].db_stride_spacing = stride_spacing;
}
@@ -422,6 +504,7 @@
inline void
gpdma_set_buffer_fifo_width(struct gpdma_transfer *xfer, int buffer, int width)
{
+
xfer->dt_buffers[buffer].db_fifo_width = width;
}
==== //depot/projects/soc2010/jceel_dma/sys/dev/gpdma/gpdma.h#3 (text+ko) ====
@@ -44,6 +44,7 @@
typedef struct gpdma_engine *gpdma_engine_t;
typedef struct gpdma_transfer *gpdma_transfer_t;
typedef void (*gpdma_callback_t)(int status, void *arg);
+typedef void (*gpdma_initializer_t)(struct resource **res, int nch, void *arg);
enum gpdma_op {
GPDMA_FILL = 0x1,
@@ -78,6 +79,14 @@
LIST_HEAD(, gpdma_engine_cdev) de_cdevs;
};
+struct gpdma_allocation {
+ const char * da_engine;
+ int da_start;
+ int da_end;
+ gpdma_initializer_t da_initializer;
+ void * da_arg;
+};
+
struct gpdma_capabilities {
uint32_t dc_ops;
uint32_t dc_buffers;
@@ -107,6 +116,7 @@
void * db_immediate;
/* Private fields: */
+ int db_needsync;
bus_dma_tag_t db_dmatag;
bus_dmamap_t db_dmamap;
};
@@ -120,6 +130,7 @@
#define GPDMA_TRANSFER_NOINTR 0x4 /* don't generate callbacks */
#define GPDMA_TRANSFER_STRIDE_CALLBACK 0x8 /* callback on every stride */
#define GPDMA_TRANSFER_STRIDE_SYNC 0x10 /* sync on every stride */
+#define GPDMA_TRANSFER_BLOCKING 0x20 /* block until transfer completed */
gpdma_callback_t dt_callback;
void * dt_callback_arg;
struct gpdma_buffer dt_buffers[8];
@@ -145,14 +156,15 @@
struct resource *gpdma_alloc_channel(const char *name, int);
int gpdma_release_channel(struct resource *);
-
bus_dma_tag_t gpdma_get_dma_tag(struct resource *);
+const struct gpdma_capabilities *gpdma_get_caps(struct resource *);
gpdma_transfer_t gpdma_alloc_transfer(struct resource *);
void gpdma_free_transfer(gpdma_transfer_t);
int gpdma_program_transfer(gpdma_transfer_t, void **);
int gpdma_start_transfer(void *);
int gpdma_stop_transfer(void *);
+int gpdma_get_transfer_status(void *);
int gpdma_load_buffer_raw(gpdma_transfer_t, int, bus_addr_t, bus_size_t);
int gpdma_load_buffer_virt(gpdma_transfer_t, int, void *, size_t);
@@ -170,5 +182,7 @@
void gpdma_set_buffer_stride(gpdma_transfer_t, int, int, int);
void gpdma_set_buffer_fifo_width(gpdma_transfer_t, int, int);
+void gpdma_memutils_init(struct resource **, int, void *);
+
#endif /* _SYS_DEV_GPDMA_GPDMA_H */
More information about the p4-projects
mailing list