[meego-commits] 5427: Changes to Trunk:Testing/dsp-tools

Felipe Contreras felipe.contreras at nokia.com
Thu Jul 8 18:04:37 UTC 2010


Hi,
I have made the following changes to dsp-tools in project Trunk:Testing. Please review and accept ASAP.

Thank You,
Felipe Contreras

[This message was auto-generated]

---

Request #5427:

  submit:   home:fcontrer/dsp-tools(r6) -> Trunk:Testing/dsp-tools


Message:
    Hi,

Updated to a newer version. I didn't tag 1.2.0 as I was hoping, so I'm using a
git version (57 patches on top of laster release).

Also, I applied reivew comments:
 - remove BuildRoot
 - add ExclusiveArch

I left the disttag because I want this spec to be distro-agnostic. OBS is
overriding the Version field anyway so there's no conflict.

State:   new          2010-07-08T06:00:07 fcontrer
Comment: None



old:
----
  0001-build-remove-dsp-manager.patch
  dsp-tools-1.2.0.tar.gz

new:
----
  dsp-tools-1.1.0.g57.tar.gz

spec files:
-----------
--- dsp-tools.spec
+++ dsp-tools.spec
@@ -1,5 +1,5 @@
 Name:		dsp-tools
-Version:	1.2.0
+Version:	1.1.0.g57
 Release:	1%{?dist}
 Summary:	Miscellaneous utilities for TI's C64x+ DSP
 
@@ -7,8 +7,8 @@
 License:	LGPLv2
 URL:		http://meego.gitorious.org/maemo-multimedia/dsp-tools
 Source0:	%{name}-%{version}.tar.gz
-Patch1:		0001-build-remove-dsp-manager.patch
-BuildRoot:	%(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
+
+ExclusiveArch:	%{arm}
 
 %description
 A bunch of tools useful for debugging/testing TI's C64x+ DSP.
@@ -16,7 +16,6 @@
 
 %prep
 %setup -q
-%patch1 -p1
 
 
 %build
@@ -36,9 +35,10 @@
 %defattr(-,root,root,-)
 %{_bindir}/dsp-load
 %{_bindir}/dsp-probe
-%{_bindir}/dsp-ping
+%{_bindir}/dsp-test
+%{_bindir}/dsp-exec
 
 
 %changelog
-* Fri May 07 2010 Felipe Contreras <felipe.contreras at gmail.com> - 1.1.0-1
+* Thu Jul 08 2010 Felipe Contreras <felipe.contreras at nokia.com> - 1.1.0.g57-1
 - Inital packaging

other changes:
--------------

++++++ dsp-tools-1.2.0.tar.gz -> dsp-tools-1.1.0.g57.tar.gz
--- .gitignore
+++ .gitignore
@@ -1,5 +1,4 @@
-*.o
-dsp-manager
+*.[od]
 dsp-load
 dsp-probe
-dsp-ping
+dsp-test
--- .version
+++ .version
@@ -1 +1 @@
-1.2.0
+1.1.0.g57
--- Makefile
+++ Makefile
@@ -1,31 +1,33 @@
 CROSS_COMPILE ?= arm-linux-
 CC := $(CROSS_COMPILE)gcc
 
-CFLAGS := -O2 -Wall -Wextra -Wno-unused-parameter
+CFLAGS := -O2 -Wall -Wextra -Wno-unused-parameter -std=c99
 
 override CFLAGS += -D_GNU_SOURCE
 
-ifdef NEW
-  override CFLAGS += -DNEW_API
+DSP_API := 1
+
+override CFLAGS += -DDSP_API=$(DSP_API)
+
+ifdef DEBUG
+  override CFLAGS += -DDEBUG
 endif
 
 version := $(shell ./get-version)
 
 all:
 
-# dsp-manager
-
-dsp-manager: dsp_manager.o dsp_bridge.o log.o
-bins += dsp-manager
-
 dsp-load: dsp_load.o dsp_bridge.o
 bins += dsp-load
 
 dsp-probe: dsp_probe.o dsp_bridge.o log.o
 bins += dsp-probe
 
-dsp-ping: dsp_ping.o dsp_bridge.o log.o
-bins += dsp-ping
+dsp-test: dsp_test.o dsp_bridge.o log.o
+bins += dsp-test
+
+dsp-exec: dsp_exec.o dsp_bridge.o log.o
+bins += dsp-exec
 
 all: $(bins)
 
@@ -39,20 +41,19 @@
 endif
 
 %.o:: %.c
-	$(QUIET_CC)$(CC) $(CFLAGS) $(INCLUDES) -o $@ -c $<
+	$(QUIET_CC)$(CC) $(CFLAGS) $(INCLUDES) -MMD -o $@ -c $<
 
 $(bins):
 	$(QUIET_LINK)$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
 
 clean:
-	$(QUIET_CLEAN)$(RM) $(bins) *.o
+	$(QUIET_CLEAN)$(RM) $(bins) *.o *.d
 
 install: $(bins)
-	install -m 755 dsp-manager -D $(D)/usr/sbin/dsp-manager
-	install -m 755 scripts/dsp-recover -D $(D)/usr/libexec/dsp-recover
 	install -m 755 dsp-load -D $(D)/usr/bin/dsp-load
 	install -m 755 dsp-probe -D $(D)/usr/bin/dsp-probe
-	install -m 755 dsp-ping -D $(D)/usr/bin/dsp-ping
+	install -m 755 dsp-test -D $(D)/usr/bin/dsp-test
+	install -m 755 dsp-exec -D $(D)/usr/bin/dsp-exec
 
 dist: base := dsp-tools-$(version)
 dist:
@@ -63,3 +64,5 @@
 	tar --append -f /tmp/$(base).tar --owner root --group root $(base)/.version
 	rm -r $(base)
 	gzip /tmp/$(base).tar
+
+-include *.d
--- README
+++ README
+= dsp-tools =
+
+Miscellaneous utilities for TI's C64x+ DSP.
+
+ * dsp-test: runs simple trivial tests
+ * dsp-load: prints the DSP CPU load and frequency
+ * dsp-probe: checks running tasks
+
+== building ==
+
+There are no dependencies, so just type 'make'. If you are using an old version
+of TI's dspbrdige driver, do 'make OLD=y'.
--- dmm_buffer.h
+++ dmm_buffer.h
+/*
+ * Copyright (C) 2009-2010 Felipe Contreras
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Authors:
+ * Felipe Contreras <felipe.contreras at nokia.com>
+ * Marco Ballesio <marco.ballesio at nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef DMM_BUFFER_H
+#define DMM_BUFFER_H
+
+#include <stdlib.h> /* for calloc, free */
+#include <unistd.h> /* for getpagesize */
+
+#include "dsp_bridge.h"
+#include "log.h"
+
+#define ROUND_UP(num, scale) (((num) + ((scale) - 1)) & ~((scale) - 1))
+
+typedef struct {
+	int handle;
+	dsp_node_t *node;
+	void *data;
+	void *allocated_data;
+	size_t size;
+	size_t len;
+	void *reserve;
+	void *map;
+	bool need_copy;
+	size_t alignment;
+	void *user_data;
+	bool used;
+	bool keyframe;
+} dmm_buffer_t;
+
+static inline dmm_buffer_t *
+dmm_buffer_new(int handle,
+	       dsp_node_t *node)
+{
+	dmm_buffer_t *b;
+	b = calloc(1, sizeof(*b));
+
+	pr_debug("%p", b);
+	b->handle = handle;
+	b->node = node;
+	b->alignment = 128;
+
+	return b;
+}
+
+static inline void
+dmm_buffer_free(dmm_buffer_t *b)
+{
+	pr_debug("%p", b);
+	if (!b)
+		return;
+	if (b->map)
+		dsp_unmap(b->handle, b->node, b->map);
+	if (b->reserve)
+		dsp_unreserve(b->handle, b->node, b->reserve);
+	free(b->allocated_data);
+	free(b);
+}
+
+static inline void
+dmm_buffer_map(dmm_buffer_t *b)
+{
+	pr_debug("%p", b);
+	if (b->map)
+		dsp_unmap(b->handle, b->node, b->map);
+	dsp_map(b->handle, b->node, b->data, b->size, b->reserve, &b->map, 0);
+}
+
+static inline void
+dmm_buffer_unmap(dmm_buffer_t *b)
+{
+	pr_debug("%p", b);
+	if (!b->map)
+		return;
+	dsp_unmap(b->handle, b->node, b->map);
+	b->map = NULL;
+}
+
+static inline void
+dmm_buffer_clean(dmm_buffer_t *b,
+		 size_t len)
+{
+	pr_debug(NULL, "%p", b);
+	dsp_flush(b->handle, b->node, b->data, len, 1);
+}
+
+static inline void
+dmm_buffer_invalidate(dmm_buffer_t *b,
+		      size_t len)
+{
+	pr_debug("%p", b);
+	dsp_invalidate(b->handle, b->node, b->data, len);
+}
+
+static inline void
+dmm_buffer_flush(dmm_buffer_t *b,
+		 size_t len)
+{
+	pr_debug("%p", b);
+	dsp_flush(b->handle, b->node, b->data, len, 0);
+}
+
+static inline void
+dmm_buffer_reserve(dmm_buffer_t *b,
+		   size_t size)
+{
+	size_t to_reserve;
+	size_t page_size;
+	page_size = getpagesize();
+	if (b->reserve) {
+		if (ROUND_UP(size, page_size) <= ROUND_UP(b->size, page_size))
+			goto leave;
+		dsp_unreserve(b->handle, b->node, b->reserve);
+	}
+	to_reserve = ROUND_UP(size, page_size) + page_size;
+	dsp_reserve(b->handle, b->node, to_reserve, &b->reserve);
+leave:
+	b->size = size;
+}
+
+static inline void
+dmm_buffer_allocate(dmm_buffer_t *b,
+		    size_t size)
+{
+	pr_debug("%p", b);
+	dmm_buffer_unmap(b);
+	free(b->allocated_data);
+	if (b->alignment != 0) {
+		if (posix_memalign(&b->allocated_data, b->alignment, ROUND_UP(size, b->alignment)) != 0)
+			b->allocated_data = NULL;
+		b->data = b->allocated_data;
+	}
+	else
+		b->data = b->allocated_data = malloc(size);
+	dmm_buffer_reserve(b, size);
+	dmm_buffer_map(b);
+}
+
+static inline void
+dmm_buffer_use(dmm_buffer_t *b,
+	       void *data,
+	       size_t size)
+{
+	pr_debug("%p", b);
+	dmm_buffer_unmap(b);
+	b->data = data;
+	dmm_buffer_reserve(b, size);
+	dmm_buffer_map(b);
+}
+
+#endif /* DMM_BUFFER_H */
--- dsp_bridge.c
+++ dsp_bridge.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2009 Felipe Contreras
+ * Copyright (C) 2009-2010 Felipe Contreras
+ * Copyright (C) 2009-2010 Nokia Corporation
  * Copyright (C) 2007 Texas Instruments, Incorporated
  *
  * Author: Felipe Contreras <felipe.contreras at gmail.com>
@@ -40,6 +41,10 @@
 #include <sys/mman.h> /* for mmap */
 #endif
 
+#if DSP_API < 2
+#include <errno.h>
+#endif
+
 /*
  * Dspbridge ioctl numbering scheme
  *
@@ -61,7 +66,7 @@
 #define DB_MODULE_MASK 0xE0
 #define DB_IOC_MASK    0x1F
 
-#ifdef NEW_API
+#if DSP_API >= 1
 
 #include <linux/ioctl.h>
 
@@ -76,7 +81,7 @@
 #define DB_IOC(module, num) \
 	(((module) & DB_MODULE_MASK) | ((num) & DB_IOC_MASK))
 
-#else /* NEW_API */
+#else
 
 #define DB_MGR  1
 #define DB_PROC 7
@@ -94,7 +99,7 @@
 #define _IOW(type, nr, size)	(nr)
 #define _IOWR(type, nr, size)	(nr)
 
-#endif /* NEW_API */
+#endif /* DSP_API */
 
 /* MGR Module */
 #define MGR_WAIT		_IOWR(DB, DB_IOC(DB_MGR, 4), unsigned long)
@@ -115,6 +120,10 @@
 #define PROC_INVALIDATEMEMORY	_IOW(DB, DB_IOC(DB_PROC, 16), unsigned long)
 #define PROC_GET_STATE		_IOWR(DB, DB_IOC(DB_PROC, 5), unsigned long)
 #define PROC_ENUMRESOURCES	_IOWR(DB, DB_IOC(DB_PROC, 4), unsigned long)
+#define PROC_ENUMNODE		_IOWR(DB, DB_IOC(DB_PROC, 3), unsigned long)
+#define PROC_STOP               _IOWR(DB, DB_IOC(DB_PROC, 15), unsigned long)
+#define PROC_LOAD               _IOW(DB, DB_IOC(DB_PROC, 7), unsigned long)
+#define PROC_START              _IOW(DB, DB_IOC(DB_PROC, 9), unsigned long)
 
 /* NODE Module */
 #define NODE_REGISTERNOTIFY	_IOWR(DB, DB_IOC(DB_NODE, 11), unsigned long)
@@ -128,11 +137,22 @@
 #define NODE_ALLOCMSGBUF	_IOWR(DB, DB_IOC(DB_NODE, 1), unsigned long)
 #define NODE_GETUUIDPROPS	_IOWR(DB, DB_IOC(DB_NODE, 14), unsigned long)
 #define NODE_ALLOCATE		_IOWR(DB, DB_IOC(DB_NODE, 0), unsigned long)
+#define NODE_CONNECT		_IOW(DB, DB_IOC(DB_NODE, 3), unsigned long)
 
 /* CMM Module */
 #define CMM_GETHANDLE		_IOR(DB, DB_IOC(DB_CMM, 2), unsigned long)
 #define CMM_GETINFO		_IOR(DB, DB_IOC(DB_CMM, 3), unsigned long)
 
+/* STRM Module */
+#define STRM_OPEN		_IOWR(DB, DB_IOC(DB_STRM, 7), unsigned long)
+#define STRM_CLOSE		_IOW(DB, DB_IOC(DB_STRM, 1), unsigned long)
+#define STRM_GETINFO		_IOWR(DB, DB_IOC(DB_STRM, 4), unsigned long)
+#define STRM_ALLOCATEBUFFER	_IOWR(DB, DB_IOC(DB_STRM, 0), unsigned long)
+#define STRM_IDLE		_IOW(DB, DB_IOC(DB_STRM, 5), unsigned long)
+#define STRM_RECLAIM		_IOWR(DB, DB_IOC(DB_STRM, 8), unsigned long)
+#define STRM_FREEBUFFER	_IOWR(DB, DB_IOC(DB_STRM, 2), unsigned long)
+#define STRM_ISSUE		_IOW(DB, DB_IOC(DB_STRM, 6), unsigned long)
+
 int dsp_open(void)
 {
 	return open("/dev/DspBridge", O_RDWR);
@@ -200,6 +220,52 @@
 	return DSP_SUCCEEDED(ioctl(handle, PROC_REGISTERNOTIFY, &arg));
 }
 
+struct proc_start {
+	void *proc_handle;
+};
+
+bool dsp_start(int handle,
+	       void *proc_handle)
+{
+	struct proc_start arg = {
+		.proc_handle = proc_handle,
+	};
+
+	return DSP_SUCCEEDED(ioctl(handle, PROC_START, &arg));
+}
+
+bool dsp_stop(int handle,
+	      void *proc_handle)
+{
+	struct proc_start arg = {
+		.proc_handle = proc_handle,
+	};
+
+	return DSP_SUCCEEDED(ioctl(handle, PROC_STOP, &arg));
+}
+
+struct proc_load {
+	void *proc_handle;
+	int argc;
+	char **argv;
+	char **env;
+};
+
+bool dsp_load(int handle,
+	      void *proc_handle,
+	      int argc, char **argv,
+	      char **env)
+{
+	struct proc_load arg = {
+		.proc_handle = proc_handle,
+		.argc = argc,
+		.argv = argv,
+		.env = env,
+	};
+
+	return DSP_SUCCEEDED(ioctl(handle, PROC_LOAD, &arg));
+}
+
 struct node_register_notify {
 	void *node_handle;
 	unsigned int event_mask;
@@ -243,7 +309,19 @@
 		.timeout = timeout,
 	};
 
+#if DSP_API >= 2
 	return DSP_SUCCEEDED(ioctl(handle, MGR_WAIT, &arg));
+#else
+	/*
+	 * Temporary hack since libc only saves errors -1 to -4095; 0x80008017
+	 * is not stored.
+	 */
+	int r;
+	r = ioctl(handle, MGR_WAIT, &arg);
+	if (r == (int)0x80008017)
+		errno = ETIME;
+	return DSP_SUCCEEDED(r);
+#endif
 }
 
 struct enum_node {
@@ -657,6 +735,8 @@
 #ifdef ALLOCATE_SM
 	if (!allocate_segments(handle, proc_handle, node)) {
 		dsp_node_delete(handle, node);
+		free(node->heap);
+		free(node);
 		return false;
 	}
 #endif
@@ -666,10 +746,41 @@
 	return true;
 }
 
+struct node_connect {
+	void *node_handle;
+	unsigned int stream;
+	void *other_node_handle;
+	unsigned int other_stream;
+	struct dsp_stream_attr *attrs;
+	void *params;
+};
+
+bool dsp_node_connect(int handle,
+		      dsp_node_t *node,
+		      unsigned int stream,
+		      dsp_node_t *other_node,
+		      unsigned int other_stream,
+		      struct dsp_stream_attr *attrs,
+		      void *params)
+{
+	struct node_connect arg = {
+		.node_handle = node->handle,
+		.stream = stream,
+		.other_node_handle = other_node->handle,
+		.other_stream = other_stream,
+		.attrs = attrs,
+		.params = params,
+	};
+
+	return DSP_SUCCEEDED(ioctl(handle, NODE_CONNECT, &arg));
+}
+
 bool dsp_node_free(int handle,
 		   dsp_node_t *node)
 {
+#ifdef ALLOCATE_SM
 	munmap(node->msgbuf_addr, node->msgbuf_size);
+#endif
 	dsp_node_delete(handle, node);
 	free(node->heap);
 	free(node);
@@ -825,7 +936,7 @@
 		.size = size,
 	};
 
-	return DSP_SUCCEEDED(ioctl(handle, PROC_GET_STATE, &arg));
+	return DSP_SUCCEEDED(ioctl(handle, PROC_ENUMRESOURCES, &arg));
 }
 
 struct enum_nodes {
@@ -851,5 +962,265 @@
 		.allocated = allocated,
 	};
 
-	return DSP_SUCCEEDED(ioctl(handle, PROC_ENUMRESOURCES, &arg));
+	return DSP_SUCCEEDED(ioctl(handle, PROC_ENUMNODE, &arg));
+}
+
+struct stream_attr {
+	void *event;
+	char *name;
+	void *base;
+	unsigned long size;
+	struct dsp_stream_attr_in *attrin;
+};
+
+struct stream_open {
+	void *node_handle;
+	unsigned int direction;
+	unsigned int index;
+	struct stream_attr *attr;
+	void *stream;
+};
+
+bool dsp_stream_open(int handle,
+		     dsp_node_t *node,
+		     unsigned int direction,
+		     unsigned int index,
+		     struct dsp_stream_attr_in *attrin,
+		     void *stream)
+{
+	struct stream_attr strm_attr = {
+		.attrin = attrin,
+	};
+	struct stream_open stream_arg = {
+		.node_handle = node->handle,
+		.direction = direction,
+		.index = index,
+		.attr = &strm_attr,
+		.stream = stream,
+	};
+
+	if (attrin && (attrin->mode == STRMMODE_ZEROCOPY ||
+		       attrin->mode == STRMMODE_RDMA)) {
+		struct dsp_cmm_info cmm_info;
+
+		if (!get_cmm_info(handle, NULL, &cmm_info))
+			return false;
+
+		if (cmm_info.segments > 0) {
+			void *base;
+			struct dsp_cmm_seg_info *seg;
+
+			seg = &cmm_info.info[0];
+			base = mmap(NULL, seg->size,
+				    PROT_READ | PROT_WRITE,
+				    MAP_SHARED | 0x2000 /* MAP_LOCKED */,
+				    handle, seg->base_pa);
+
+			if (!base)
+				return false;
+
+			strm_attr.base = base;
+			strm_attr.size = seg->size;
+		}
+	}
+
+	return DSP_SUCCEEDED(ioctl(handle, STRM_OPEN, &stream_arg));
+}
+
+struct stream_info {
+	enum dsp_stream_mode mode;
+	unsigned int segment;
+	void *base;
+	struct dsp_stream_info *info;
+};
+
+struct stream_get_info {
+	void *stream;
+	struct stream_info *info;
+	unsigned int size;
+};
+
+static inline bool get_stream_info(int handle,
+				   void *stream,
+				   struct stream_info *info,
+				   unsigned int size)
+{
+	struct stream_get_info arg = {
+		.stream = stream,
+		.info = info,
+		.size = size,
+	};
+
+	return DSP_SUCCEEDED(ioctl(handle, STRM_GETINFO, &arg));
+}
+
+bool dsp_stream_close(int handle,
+		      void *stream)
+{
+	struct stream_info info;
+	if (!get_stream_info(handle, stream, &info, sizeof(struct stream_info)))
+		return false;
+
+	if (info.base) {
+		struct dsp_cmm_info cmm_info;
+
+		if (!get_cmm_info(handle, NULL, &cmm_info))
+			return false;
+
+		if (cmm_info.segments > 0) {
+			struct dsp_cmm_seg_info *seg;
+			seg = &cmm_info.info[0];
+			if (munmap(info.base, seg->size))
+				return false;
+		}
+	}
+
+	return DSP_SUCCEEDED(ioctl(handle, STRM_CLOSE, &stream));
+}
+
+struct stream_idle {
+	void *stream;
+	bool flush;
+};
+
+bool dsp_stream_idle(int handle,
+		     void *stream,
+		     bool flush)
+{
+	struct stream_idle arg = {
+		.stream = stream,
+		.flush = flush,
+	};
+	return DSP_SUCCEEDED(ioctl(handle, STRM_IDLE, &arg));
+}
+
+struct stream_reclaim {
+	void *stream;
+	unsigned char **buff;
+	unsigned long *data_size;
+	unsigned long *buff_size;
+	unsigned long *flag;
+};
+
+bool dsp_stream_reclaim(int handle,
+			void *stream,
+			unsigned char **buff,
+			unsigned long *data_size,
+			unsigned long *buff_size,
+			unsigned long *flag)
+{
+	struct stream_reclaim arg = {
+		.stream = stream,
+		.buff = buff,
+		.data_size = data_size,
+		.buff_size = buff_size,
+		.flag = flag,
+	};
+	return DSP_SUCCEEDED(ioctl(handle, STRM_RECLAIM, &arg));
+}
+
+struct stream_issue {
+	void *stream;
+	unsigned char *buff;
+	unsigned long data_size;
+	unsigned long buff_size;
+	unsigned long flag;
+};
+
+bool dsp_stream_issue(int handle,
+		      void *stream,
+		      unsigned char *buff,
+		      unsigned long data_size,
+		      unsigned long buff_size,
+		      unsigned long flag)
+{
+	struct stream_issue arg = {
+		.stream = stream,
+		.buff = buff,
+		.data_size = data_size,
+		.buff_size = buff_size,
+		.flag = flag,
+	};
+	return DSP_SUCCEEDED(ioctl(handle, STRM_ISSUE, &arg));
+}
+
+bool dsp_stream_get_info(int handle,
+			 void *stream,
+			 struct dsp_stream_info *info,
+			 unsigned int size)
+{
+	struct stream_info stream_info = {
+		.info = info
+	};
+
+	return get_stream_info(handle, stream, &stream_info, size);
+}
+
+
+struct stream_allocate_buffer {
+	void *stream;
+	unsigned int size;
+	unsigned char **buff;
+	unsigned int num_buf;
+};
+
+bool dsp_stream_allocate_buffers(int handle,
+				 void *stream,
+				 unsigned int size,
+				 unsigned char **buff,
+				 unsigned int num_buf)
+{
+	unsigned int i;
+	struct stream_info info;
+	if (!get_stream_info(handle, stream, &info, sizeof(struct stream_info)))
+		return false;
+
+	if (info.segment > 0) {
+		struct stream_allocate_buffer arg = {
+			.stream = stream,
+			.size = size,
+			.buff = buff,
+			.num_buf = num_buf,
+		};
+
+		return DSP_SUCCEEDED(ioctl(handle, STRM_ALLOCATEBUFFER, &arg));
+	}
+
+	for (i = 0; i < num_buf; i++)
+		buff[i] = (unsigned char *) malloc(size);
+
+	return true;
+}
+
+struct stream_free_buffers {
+	void *stream;
+	unsigned char **buff;
+	unsigned int num_buf;
+};
+
+bool dsp_stream_free_buffers(int handle,
+			     void *stream,
+			     unsigned char **buff,
+			     unsigned int num_buf)
+{
+	unsigned int i;
+	struct stream_info info;
+	if (!get_stream_info(handle, stream, &info, sizeof(struct stream_info)))
+		return false;
+
+	if (info.segment) {
+		struct stream_free_buffers arg = {
+			.stream = stream,
+			.buff = buff,
+			.num_buf = num_buf,
+		};
+		return DSP_SUCCEEDED(ioctl(handle, STRM_FREEBUFFER, &arg));
+	}
+
+	for (i = 0; i < num_buf; i++) {
+		free(buff[i]);
+		buff[i] = NULL;
+	}
+
+	return true;
 }
--- dsp_bridge.h
+++ dsp_bridge.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Felipe Contreras
+ * Copyright (C) 2009-2010 Felipe Contreras
  *
  * Author: Felipe Contreras <felipe.contreras at gmail.com>
  *
@@ -44,7 +44,6 @@
 	uint8_t field_6[6];
 } dsp_uuid_t;
 
-
 typedef struct {
 	void *handle;
 	void *heap;
@@ -172,6 +171,51 @@
 	unsigned int stream_index;
 };
 
+enum dsp_stream_mode {
+	STRMMODE_PROCCOPY,
+	STRMMODE_ZEROCOPY,
+	STRMMODE_LDMA,
+	STRMMODE_RDMA
+};
+
+struct dsp_stream_attr {
+	unsigned int seg_id;
+	unsigned int buf_size;
+	unsigned int num_bufs;
+	unsigned int alignment;
+	unsigned int timeout;
+	enum dsp_stream_mode mode;
+	unsigned int dma_chnl_id;
+	unsigned int dma_priority;
+};
+
+struct dsp_stream_attr_in {
+	unsigned long cb;
+	unsigned int timeout;
+	unsigned int segment;
+	unsigned int alignment;
+	unsigned int num_bufs;
+	enum dsp_stream_mode mode;
+	unsigned int dma_chnl_id;
+	unsigned int dma_priority;
+};
+
+enum dsp_stream_state {
+	STREAM_IDLE,
+	STREAM_READY,
+	STREAM_PENDING,
+	STREAM_DONE
+};
+
+struct dsp_stream_info {
+	unsigned long cb;
+	unsigned int num_bufs_allowed;
+	unsigned int num_bufs_in_stream;
+	unsigned long num_bytes;
+	void *sync_handle;
+	enum dsp_stream_state state;
+};
+
 enum dsp_node_state {
 	NODE_ALLOCATED,
 	NODE_CREATED,
@@ -211,6 +255,17 @@
 bool dsp_detach(int handle,
 		void *proc_handle);
 
+bool dsp_start(int handle,
+	       void *proc_handle);
+
+bool dsp_stop(int handle,
+	      void *proc_handle);
+
+bool dsp_load(int handle,
+	      void *proc_handle,
+	      int argc, char **argv,
+	      char **env);
+
 bool dsp_node_allocate(int handle,
 		       void *proc_handle,
 		       const dsp_uuid_t *node_uuid,
@@ -221,6 +276,14 @@
 bool dsp_node_free(int handle,
 		   dsp_node_t *node);
 
+bool dsp_node_connect(int handle,
+		      dsp_node_t *node,
+		      unsigned int stream,
+		      dsp_node_t *other_node,
+		      unsigned int other_stream,
+		      struct dsp_stream_attr *attrs,
+		      void *params);
+
 bool dsp_node_create(int handle,
 		     dsp_node_t *node);
 
@@ -340,4 +403,48 @@
 		    unsigned *num_nodes,
 		    unsigned *allocated);
 
+bool dsp_stream_open(int handle,
+		     dsp_node_t *node,
+		     unsigned int direction,
+		     unsigned int index,
+		     struct dsp_stream_attr_in *attrin,
+		     void *stream);
+
+bool dsp_stream_close(int handle,
+		      void *stream);
+
+bool dsp_stream_idle(int handle,
+		     void *stream,
+		     bool flush);
+
+bool dsp_stream_reclaim(int handle,
+			void *stream,
+			unsigned char **buff,
+			unsigned long *data_size,
+			unsigned long *buff_size,
+			unsigned long *args);
+
+bool dsp_stream_issue(int handle,
+		      void *stream,
+		      unsigned char *buff,
+		      unsigned long data_size,
+		      unsigned long buff_size,
+		      unsigned long arg);
+
+bool dsp_stream_get_info(int handle,
+			 void *stream,
+			 struct dsp_stream_info *info,
+			 unsigned int size);
+
+bool dsp_stream_allocate_buffers(int handle,
+				 void *stream,
+				 unsigned int size,
+				 unsigned char **buff,
+				 unsigned int num_buf);
+
+bool dsp_stream_free_buffers(int handle,
+			     void *stream,
+			     unsigned char **buff,
+			     unsigned int num_buf);
+
 #endif /* DSP_BRIDGE_H */
--- dsp_exec.c
+++ dsp_exec.c
+/*
+ * Copyright (C) 2009-2010 Igalia S.L.
+ *
+ * Author: Víctor Manuel Jáquez Leal <vjaquez at igalia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include "dsp_bridge.h"
+#include "log.h"
+
+int
+main(int argc,
+     const char **argv)
+{
+	int ret = 0;
+	int dsp_handle;
+	void *proc;
+	char *cmd[1];
+
+	if (argc != 2) {
+		pr_err("Wrong arguments: %s <dsp_program>", argv[0]);
+		return -1;
+	}
+
+	dsp_handle = dsp_open();
+
+	if (dsp_handle < 0) {
+		pr_err("dsp open failed");
+		return -1;
+	}
+
+	if (!dsp_attach(dsp_handle, 0, NULL, &proc)) {
+		pr_err("dsp attach failed");
+		ret = -1;
+		goto leave;
+	}
+
+	if (!dsp_stop(dsp_handle, proc)) {
+		pr_err("dsp stop failed");
+		ret = -1;
+		goto leave;
+	}
+
+	cmd[0] = (char *) argv[1];
+	if (!dsp_load(dsp_handle, proc, 1, cmd, NULL)) {
+		pr_err("dsp load failed");
+		ret = -1;
+		goto leave;
+	}
+
+	if (!dsp_start(dsp_handle, proc)) {
+		pr_err("dsp start failed");
+		ret = -1;
+	}
+
+leave:
+	if (proc) {
+		if (!dsp_detach(dsp_handle, proc)) {
+			pr_err("dsp detach failed");
+			ret = -1;
+		}
+		proc = NULL;
+	}
+
+	if (dsp_handle > 0) {
+		if (dsp_close(dsp_handle) < 0) {
+			pr_err("dsp close failed");
+			return -1;
+		}
+	}
+
+	return ret;
+}
--- dsp_load.c
+++ dsp_load.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Nokia Corporation.
+ * Copyright (C) 2009-2010 Nokia Corporation
  *
  * Authors:
  * Felipe Contreras <felipe.contreras at nokia.com>
@@ -27,7 +27,7 @@
 
 #include "dsp_bridge.h"
 
-unsigned delay = 500; /* in ms */
+static unsigned delay = 500; /* in ms */
 
 static void
 display(void)
--- dsp_manager.c
+++ dsp_manager.c
-/*
- * Copyright (C) 2009 Nokia Corporation.
- * Copyright (C) 2009 Texas Instruments, Incorporated 
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#include <stdlib.h>
-#include <signal.h>
-#include <unistd.h> /* for sleep */
-
-#include "log.h"
-#include "dsp_bridge.h"
-
-#ifdef SYSLOG
-#include <syslog.h>
-#endif
-
-static int dsp_handle;
-static void *proc;
-
-const char *process = "dsp-manager";
-const char *recover_script = "/usr/libexec/dsp-recover";
-
-void reset_dsp(void)
-{
-	int ret;
-
-	dsp_detach(dsp_handle, proc);
-	dsp_close(dsp_handle);
-
-	ret = system(recover_script);
-
-	sleep(2);
-
-	if (ret == 0)
-		pr_info("recovered");
-	else
-		pr_err("couldn't recover");
-}
-
-void signal_handler(int n) {
-	pr_info("signal %d received", n);
-	reset_dsp();
-}
-
-bool attach(void)
-{
-	dsp_handle = dsp_open();
-
-	if (dsp_handle < 0) {
-		pr_err("could not open");
-		return false;
-	}
-
-	pr_info("opened");
-
-	if (!dsp_attach(dsp_handle, 0, NULL, &proc)) {
-		pr_err("could not attach");
-		return false;
-	}
-
-	pr_info("attached");
-
-	return true;
-}
-
-int main(void)
-{
-	struct dsp_notification *n_mmufault = NULL;
-	struct dsp_notification *n_syserror = NULL;
-	struct dsp_notification *n_objects[2];
-	int ret = -1;
-
-	signal(SIGUSR1, signal_handler);
-
-#ifdef SYSLOG
-	openlog(process, 0, LOG_USER);
-#endif
-
-	n_mmufault = calloc(1, sizeof(n_mmufault));
-	if (!n_mmufault) {
-		pr_err("not enough memory");
-		goto leave;
-	}
-
-	n_syserror = calloc(1, sizeof(n_syserror));
-	if (!n_syserror) {
-		pr_err("not enough memory");
-		goto leave;
-	}
-
-	while (true) {
-		unsigned int count;
-		unsigned int index = 0;
-
-		for (count = 0; count < 3; count++) {
-			if (attach()) {
-				pr_info("attached");
-				break;
-			}
-			pr_err("failed to attach, retry");
-			sleep(2);
-		}
-
-		if (count == 3) {
-			pr_err("could not attach");
-			goto leave;
-		}
-
-		if (!dsp_register_notify(dsp_handle, proc,
-					 DSP_MMUFAULT, 1,
-					 n_mmufault))
-		{
-			pr_err("failed to register for DSP_MMUFAULT");
-			goto leave;
-		}
-		n_objects[0] = n_mmufault;
-
-		if (!dsp_register_notify(dsp_handle, proc,
-					 DSP_SYSERROR, 1,
-					 n_syserror))
-		{
-			pr_err("failed to register for DSP_SYSERROR");
-			goto leave;
-		}
-		n_objects[1] = n_syserror;
-
-		pr_info("begin");
-
-		if (!dsp_wait_for_events(dsp_handle, n_objects, 2, &index, -1)) {
-			pr_err("failed waiting for events");
-			goto leave;
-		}
-
-		if (index == 0 || index == 1) {
-			pr_err("DSP crash detected: %u", index);
-			reset_dsp();
-		}
-		else
-			pr_err("what?");
-	}
-
-	ret = 0;
-
-leave:
-	free(n_mmufault);
-	free(n_syserror);
-	if (proc)
-		dsp_detach(dsp_handle, proc);
-	if (dsp_handle > 0)
-		dsp_close(dsp_handle);
-
-	pr_info("end");
-
-	return ret;
-}
--- dsp_ping.c
+++ dsp_ping.c
-/*
- * Copyright (C) 2009 Nokia Corporation.
- *
- * Author: Víctor M. Jáquez L. <vjaquez at igalia.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "dsp_bridge.h"
-#include "log.h"
-
-static int dsp_handle;
-static void *proc;
-static int count = 50;
-
-#define SNDIR "/lib/dsp"
-
-static inline dsp_node_t *
-create_node(void)
-{
-	dsp_node_t *node = NULL;
-
-	const dsp_uuid_t uuid = { 0x12a3c3c1, 0xd015, 0x11d4, 0x9f, 0x69,
-		{ 0x00, 0xc0, 0x4f, 0x3a, 0x59, 0xae } };
-
-	if (!dsp_register(dsp_handle, &uuid, DSP_DCD_LIBRARYTYPE,
-			  SNDIR "/pingdyn_3430.dll64P"))
-		return NULL;
-
-	if (!dsp_register(dsp_handle, &uuid, DSP_DCD_NODETYPE,
-			  SNDIR "/pingdyn_3430.dll64P"))
-		return NULL;
-
-	if (!dsp_node_allocate(dsp_handle, proc, &uuid, NULL, NULL,
-			       &node)) {
-		pr_err("dsp node allocate failed");
-		return NULL;
-	}
-
-	if (!dsp_node_create(dsp_handle, node)) {
-		pr_err("dsp node create failed");
-		return NULL;
-	}
-
-	return node;
-}
-
-static inline bool
-destroy_node(dsp_node_t *node)
-{
-	if (node) {
-		if (!dsp_node_free(dsp_handle, node)) {
-			pr_err("dsp node free failed");
-			return false;
-		}
-	}
-
-	return true;
-}
-
-static bool
-run_task(dsp_node_t *node)
-{
-	unsigned long exit_status;
-	unsigned int index;
-	struct dsp_notification event, *notifications;
-	int n;
-
-	if (!dsp_node_register_notify(dsp_handle, node,
-				      DSP_NODEMESSAGEREADY, 1,
-				      &event))
-		pr_err("dsp node register notify failed");
-
-	if (!dsp_node_run(dsp_handle, node)) {
-		pr_err("dsp node run failed");
-		return false;
-	}
-
-	notifications = &event;
-
-	for (n = 0; n < count; n++) {
-		if (!dsp_send_message(dsp_handle, node, 1, 0, 0)) {
-			pr_err("dsp node put message failed");
-			continue;
-		}
-
-		if (!dsp_wait_for_events(dsp_handle, &notifications,
-					 1, &index, -1)
-		    && index == 0) {
-			pr_err("dsp wait for events failed");
-			break;
-		}
-
-		dsp_msg_t msg;
-		if (dsp_node_get_message (dsp_handle, node, &msg, 0))
-			printf("Ping: Id %d Msg %d Mem %d\n",
-			       msg.cmd, msg.arg_1, msg.arg_2);
-	}
-
-	if (!dsp_node_terminate (dsp_handle, node, &exit_status)) {
-		pr_err("dsp node terminate failed: %lx", exit_status);
-		return false;
-	}
-
-	return true;
-}
-
-int
-main(int argc, char **argv)
-{
-	dsp_node_t *node;
-	int ret = 0;
-
-	if (argc == 2) {
-		long int c = strtol(argv[1], NULL, 0);
-		if (c > 0)
-			count = c;
-	}
-
-	dsp_handle = dsp_open();
-
-	if (dsp_handle < 0) {
-		pr_err("failed to open DSP");
-		return -1;
-	}
-
-	if (!dsp_attach(dsp_handle, 0, NULL, &proc)) {
-		pr_err("dsp attach failed");
-		ret = -1;
-		goto leave;
-	}
-
-	node = create_node();
-
-	if (!node) {
-		pr_err("dsp node creation failed");
-		ret = -1;
-		goto leave;
-	}
-
-	run_task(node);
-
-	destroy_node(node);
-
-leave:
-	if (proc) {
-		if (!dsp_detach(dsp_handle, proc)) {
-			pr_err("dsp detach failed");
-			ret = 1;
-			goto leave;
-		}
-		proc = NULL;
-	}
-
-	if (dsp_close(dsp_handle) < 0) {
-		pr_err("dsp close failed");
-		return -1;
-	}
-
-	return ret;
-}
--- dsp_probe.c
+++ dsp_probe.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Nokia Corporation.
+ * Copyright (C) 2009-2010 Nokia Corporation
  *
  * Author: Felipe Contreras <felipe.contreras at nokia.com>
  *
@@ -32,16 +32,16 @@
 node_type_to_str(enum dsp_node_type type)
 {
 	switch (type) {
-		case DSP_NODE_DEVICE:
-			return "device";
-		case DSP_NODE_MESSAGE:
-			return "message";
-		case DSP_NODE_TASK:
-			return "task";
-		case DSP_NODE_DAISSOCKET:
-			return "dais socket";
-		default:
-			return NULL;
+	case DSP_NODE_DEVICE:
+		return "device";
+	case DSP_NODE_MESSAGE:
+		return "message";
+	case DSP_NODE_TASK:
+		return "task";
+	case DSP_NODE_DAISSOCKET:
+		return "dais socket";
+	default:
+		return NULL;
 	}
 }
 
@@ -49,18 +49,18 @@
 node_status_to_str(enum dsp_node_state state)
 {
 	switch (state) {
-		case NODE_ALLOCATED:
-			return "allocated";
-		case NODE_CREATED:
-			return "created";
-		case NODE_RUNNING:
-			return "running";
-		case NODE_PAUSED:
-			return "paused";
-		case NODE_DONE:
-			return "done";
-		default:
-			return NULL;
+	case NODE_ALLOCATED:
+		return "allocated";
+	case NODE_CREATED:
+		return "created";
+	case NODE_RUNNING:
+		return "running";
+	case NODE_PAUSED:
+		return "paused";
+	case NODE_DONE:
+		return "done";
+	default:
+		return NULL;
 	}
 }
 
@@ -82,10 +82,10 @@
 {
 	struct dsp_ndb_props props;
 	unsigned num = 0, i;
-	void **tmp_table;
 	void *proc_handle;
-	unsigned node_count = 0, allocated_count = 0;
 	struct node_info *node_table;
+	void **tmp_table;
+	unsigned node_count = 0, allocated_count = 0;
 
 	if (!dsp_enum(dsp_handle, 0, &props, sizeof(props), &num)) {
 		pr_err("failed to enumerate nodes");
@@ -108,24 +108,24 @@
 	}
 
 	tmp_table = calloc(num, sizeof(*tmp_table));
-	if (!dsp_enum_nodes(dsp_handle, proc_handle, tmp_table, num,
-			    &node_count, &allocated_count)) {
-		pr_err("failed to enumerate nodes");
-		goto leave;
-	}
-
-	for (i = 0; i < node_count; i++) {
-		struct dsp_node_attr attr;
-		dsp_node_t node = { .handle = tmp_table[i] };
-		if (dsp_node_get_attr(dsp_handle, &node, &attr, sizeof(attr))) {
-			unsigned j;
-			for (j = 0; j < num; j++) {
-				if (uuidcmp(&node_table[j].id, &attr.info.props.uiNodeID)) {
-					node_table[j].state = attr.info.state;
-					break;
+	if (dsp_enum_nodes(dsp_handle, proc_handle, tmp_table, num,
+			   &node_count, &allocated_count))
+	{
+		for (i = 0; i < node_count; i++) {
+			struct dsp_node_attr attr;
+			dsp_node_t node = { .handle = tmp_table[i] };
+			if (dsp_node_get_attr(dsp_handle, &node, &attr, sizeof(attr))) {
+				unsigned j;
+				for (j = 0; j < num; j++) {
+					if (uuidcmp(&node_table[j].id, &attr.info.props.uiNodeID)) {
+						node_table[j].state = attr.info.state;
+						break;
+					}
 				}
 			}
 		}
+	} else {
+		pr_err("failed to list active nodes");
 	}
 
 	for (i = 0; i < num; i++) {
@@ -144,9 +144,8 @@
 	if (!dsp_detach(dsp_handle, proc_handle))
 		pr_err("dsp detach failed");
 
-leave:
-	free(node_table);
 	free(tmp_table);
+	free(node_table);
 
 	return true;
 }
--- dsp_test.c
+++ dsp_test.c
+/*
+ * Copyright (C) 2009-2010 Felipe Contreras
+ * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2009 Igalia S.L
+ *
+ * Author: Felipe Contreras <felipe.contreras at nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include "dmm_buffer.h"
+#include "dsp_bridge.h"
+#include "log.h"
+
+static unsigned long input_buffer_size = 0x1000;
+static unsigned long output_buffer_size = 0x1000;
+static bool done;
+static int ntimes;
+static bool do_fault;
+static bool do_ping;
+static bool do_write;
+
+static int dsp_handle;
+static void *proc;
+struct dsp_notification *events[3];
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+static void
+signal_handler(int signal)
+{
+	done = true;
+}
+
+static inline dsp_node_t *
+create_node(void)
+{
+	dsp_node_t *node;
+	const dsp_uuid_t test_uuid = { 0x3dac26d0, 0x6d4b, 0x11dd, 0xad, 0x8b,
+		{ 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } };
+
+	if (!dsp_register(dsp_handle, &test_uuid, DSP_DCD_LIBRARYTYPE, "/lib/dsp/test.dll64P"))
+		return false;
+
+	if (!dsp_register(dsp_handle, &test_uuid, DSP_DCD_NODETYPE, "/lib/dsp/test.dll64P"))
+		return false;
+
+	if (!dsp_node_allocate(dsp_handle, proc, &test_uuid, NULL, NULL, &node)) {
+		pr_err("dsp node allocate failed");
+		return NULL;
+	}
+
+	if (!dsp_node_create(dsp_handle, node)) {
+		pr_err("dsp node create failed");
+		return NULL;
+	}
+
+	pr_info("dsp node created");
+
+	return node;
+}
+
+static inline bool
+destroy_node(dsp_node_t *node)
+{
+	if (node) {
+		if (!dsp_node_free(dsp_handle, node)) {
+			pr_err("dsp node free failed");
+			return false;
+		}
+
+		pr_info("dsp node deleted");
+	}
+
+	return true;
+}
+
+static inline void
+configure_dsp_node(void *node,
+		   dmm_buffer_t *input_buffer,
+		   dmm_buffer_t *output_buffer)
+{
+	dsp_msg_t msg;
+
+	msg.cmd = 0;
+	msg.arg_1 = (uint32_t) input_buffer->map;
+	msg.arg_2 = (uint32_t) output_buffer->map;
+	if (do_fault)
+		msg.arg_2 = 0x12345678;
+	dsp_node_put_message(dsp_handle, node, &msg, -1);
+}
+
+static bool
+register_msgs(dsp_node_t *node)
+{
+	events[0] = calloc(1, sizeof(struct dsp_notification));
+	if (!dsp_node_register_notify(dsp_handle, node,
+				      DSP_NODEMESSAGEREADY, 1,
+				      events[0]))
+		return false;
+
+	events[1] = calloc(1, sizeof(struct dsp_notification));
+	if (!dsp_register_notify(dsp_handle, proc,
+				 DSP_MMUFAULT, 1,
+				 events[1]))
+		return false;
+
+	events[2] = calloc(1, sizeof(struct dsp_notification));
+	if (!dsp_register_notify(dsp_handle, proc,
+				 DSP_SYSERROR, 1,
+				 events[2]))
+		return false;
+
+	return true;
+}
+
+static bool
+check_events(dsp_node_t *node,
+	     dsp_msg_t *msg)
+{
+	unsigned int index = 0;
+	pr_debug("waiting for events");
+	if (!dsp_wait_for_events(dsp_handle, events, 3, &index, 1000)) {
+		pr_warning("failed waiting for events");
+		return false;
+	}
+
+	switch (index) {
+	case 0:
+		dsp_node_get_message(dsp_handle, node, msg, 100);
+		pr_debug("got dsp message: 0x%0x 0x%0x 0x%0x",
+			 msg->cmd, msg->arg_1, msg->arg_2);
+		return true;
+	case 1:
+		pr_err("got DSP MMUFAULT");
+		return false;
+	case 2:
+		pr_err("got DSP SYSERROR");
+		return false;
+	default:
+		pr_err("wrong event index");
+		return false;
+	}
+}
+
+void run_dmm(dsp_node_t *node,
+	     unsigned long times)
+{
+	dmm_buffer_t *input_buffer;
+	dmm_buffer_t *output_buffer;
+
+	input_buffer = dmm_buffer_new(dsp_handle, proc);
+	output_buffer = dmm_buffer_new(dsp_handle, proc);
+
+	dmm_buffer_allocate(input_buffer, input_buffer_size);
+	dmm_buffer_allocate(output_buffer, output_buffer_size);
+
+	configure_dsp_node(node, input_buffer, output_buffer);
+
+	pr_info("running %lu times", times);
+
+	while (!done) {
+		dsp_msg_t msg;
+
+		if (do_write) {
+			static unsigned char foo = 1;
+			unsigned int i;
+			for (i = 0; i < input_buffer->size; i++)
+				((char *) input_buffer->data)[i] = foo;
+			foo++;
+		}
+
+		dmm_buffer_clean(input_buffer, input_buffer->size);
+		dmm_buffer_invalidate(output_buffer, output_buffer->size);
+		msg.cmd = 1;
+		msg.arg_1 = input_buffer->size;
+		dsp_node_put_message(dsp_handle, node, &msg, -1);
+		if (!check_events(node, &msg)) {
+			done = true;
+			break;
+		}
+
+		if (--times == 0)
+			break;
+	}
+
+	dmm_buffer_unmap(output_buffer);
+	dmm_buffer_unmap(input_buffer);
+
+	dmm_buffer_free(output_buffer);
+	dmm_buffer_free(input_buffer);
+}
+
+void run_ping(dsp_node_t *node,
+	      unsigned long times)
+{
+	while (!done) {
+		dsp_msg_t msg;
+
+		if (!dsp_send_message(dsp_handle, node, 2, 0, 0)) {
+			pr_err("dsp node put message failed");
+			continue;
+		}
+
+		if (!check_events(node, &msg)) {
+			done = true;
+			break;
+		}
+
+		printf("ping: id=%d, msg=%d, mem=%d\n",
+		       msg.cmd, msg.arg_1, msg.arg_2);
+
+		if (--times == 0)
+			break;
+	}
+}
+
+static bool
+run_task(dsp_node_t *node,
+	 unsigned long times)
+{
+	unsigned long exit_status;
+
+	register_msgs(node);
+
+	if (!dsp_node_run(dsp_handle, node)) {
+		pr_err("dsp node run failed");
+		return false;
+	}
+
+	pr_info("dsp node running");
+
+	if (do_ping)
+		run_ping(node, times);
+	else
+		run_dmm(node, times);
+
+	if (!dsp_node_terminate(dsp_handle, node, &exit_status)) {
+		pr_err("dsp node terminate failed: %lx", exit_status);
+		return false;
+	}
+
+	pr_info("dsp node terminated");
+
+	return true;
+}
+
+static void
+handle_options(int *argc,
+	       const char ***argv)
+{
+	while (*argc > 0) {
+		const char *cmd = (*argv)[0];
+		if (cmd[0] != '-')
+			break;
+
+#ifdef DEBUG
+		if (!strcmp(cmd, "-d") || !strcmp(cmd, "--debug"))
+			debug_level = 3;
+#endif
+
+		if (!strcmp(cmd, "-n") || !strcmp(cmd, "--ntimes")) {
+			if (*argc < 2) {
+				pr_err("bad option");
+				exit(-1);
+			}
+			ntimes = atoi((*argv)[1]);
+			(*argv)++;
+			(*argc)--;
+		}
+
+		if (!strcmp(cmd, "-s") || !strcmp(cmd, "--size")) {
+			if (*argc < 2) {
+				pr_err("bad option");
+				exit(-1);
+			}
+			input_buffer_size = output_buffer_size = atol((*argv)[1]);
+			(*argv)++;
+			(*argc)--;
+		}
+
+		if (!strcmp(cmd, "-f") || !strcmp(cmd, "--fault"))
+			do_fault = 1;
+
+		if (!strcmp(cmd, "-p") || !strcmp(cmd, "--ping"))
+			do_ping = 1;
+
+		if (!strcmp(cmd, "-w") || !strcmp(cmd, "--write"))
+			do_write = 1;
+
+		(*argv)++;
+		(*argc)--;
+	}
+}
+
+int
+main(int argc,
+     const char **argv)
+{
+	dsp_node_t *node;
+	int ret = 0;
+	unsigned i;
+
+	signal(SIGINT, signal_handler);
+
+#ifdef DEBUG
+	debug_level = 2;
+#endif
+	ntimes = 1000;
+
+	argc--; argv++;
+	handle_options(&argc, &argv);
+
+	dsp_handle = dsp_open();
+
+	if (dsp_handle < 0) {
+		pr_err("dsp open failed");
+		return -1;
+	}
+
+	if (!dsp_attach(dsp_handle, 0, NULL, &proc)) {
+		pr_err("dsp attach failed");
+		ret = -1;
+		goto leave;
+	}
+
+	node = create_node();
+	if (!node) {
+		pr_err("dsp node creation failed");
+		ret = -1;
+		goto leave;
+	}
+
+	run_task(node, ntimes);
+	destroy_node(node);
+
+leave:
+	if (proc) {
+		if (!dsp_detach(dsp_handle, proc)) {
+			pr_err("dsp detach failed");
+			ret = -1;
+		}
+		proc = NULL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(events); i++)
+		free(events[i]);
+
+	if (dsp_handle > 0) {
+		if (dsp_close(dsp_handle) < 0) {
+			pr_err("dsp close failed");
+			return -1;
+		}
+	}
+
+	return ret;
+}
--- log.c
+++ log.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2009 Felipe Contreras
+ * Copyright (C) 2009-2010 Felipe Contreras
+ * Copyright (C) 2009-2010 Nokia Corporation
  *
  * Author: Felipe Contreras <felipe.contreras at gmail.com>
  *
@@ -29,19 +30,35 @@
 #include <syslog.h>
 #endif
 
+#ifdef DEBUG
+unsigned debug_level = 1;
+#endif
+
 #ifdef SYSLOG
 static inline int
 log_level_to_syslog(unsigned int level)
 {
 	switch (level) {
-		case 0: return LOG_ERR;
-		case 1: return LOG_WARNING;
-		case 2: return LOG_INFO;
-		default: return LOG_DEBUG;
+	case 0: return LOG_ERR;
+	case 1: return LOG_WARNING;
+	case 2: return LOG_INFO;
+	default: return LOG_DEBUG;
 	}
 }
 #endif
 
+static inline const char *
+log_level_to_string(unsigned int level)
+{
+	switch (level) {
+	case 0: return "error"; break;
+	case 1: return "warning"; break;
+	case 2: return "info"; break;
+	case 3: return "debug"; break;
+	default: return NULL; break;
+	}
+}
+
 void pr_helper(unsigned int level,
 	       const char *file,
 	       const char *function,
@@ -52,17 +69,30 @@
 	char *tmp;
 	va_list args;
 
+#ifdef DEBUG
+	if (level > debug_level)
+		return;
+#endif
+
 	va_start(args, fmt);
 
 	vasprintf(&tmp, fmt, args);
 
-	if (level <= 2) {
+	if (level <= 1) {
 #ifdef SYSLOG
 		syslog(log_level_to_syslog(level), "%s", tmp);
-#else
-		printf("%s: %s\n", function, tmp);
 #endif
+		fprintf(stderr, "%s: %s: %s\n",
+			log_level_to_string(level), function, tmp);
 	}
+#ifdef DEBUG
+	else if (level == 2)
+		fprintf(stderr, "%s: %s: %s\n",
+			log_level_to_string(level), function, tmp);
+	else if (level == 3)
+		fprintf(stderr, "%s: %s:%s(%u): %s\n",
+			log_level_to_string(level), file, function, line, tmp);
+#endif
 
 	free(tmp);
 
--- log.h
+++ log.h
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2009 Felipe Contreras
+ * Copyright (C) 2009-2010 Felipe Contreras
+ * Copyright (C) 2009-2010 Nokia Corporation
  *
  * Author: Felipe Contreras <felipe.contreras at gmail.com>
  *
@@ -22,7 +23,9 @@
 #ifndef LOG_H
 #define LOG_H
 
-/* #define DEBUG */
+#ifdef DEBUG
+extern int debug_level;
+#endif
 
 void pr_helper(unsigned int level,
 	       const char *file,
@@ -35,12 +38,13 @@
 
 #define pr_err(...) pr_base(0, __VA_ARGS__)
 #define pr_warning(...) pr_base(1, __VA_ARGS__)
-#define pr_info(...) pr_base(2, __VA_ARGS__)
 
 #ifdef DEBUG
+#define pr_info(...) pr_base(2, __VA_ARGS__)
 #define pr_debug(...) pr_base(3, __VA_ARGS__)
 #else
-#define pr_debug(...)
+#define pr_info(...) ({ if (0) pr_base(2, __VA_ARGS__); })
+#define pr_debug(...) ({ if (0) pr_base(3, __VA_ARGS__); })
 #endif
 
 #endif /* LOG_H */
--- scripts
+++ scripts
-(directory)
--- scripts/dsp-recover
+++ scripts/dsp-recover
-#!/bin/sh
-
-kill_users()
-{
-        users=$(for x in `lsof -t /dev/DspBridge`; do basename `cat /proc/$x/cmdline | tr '\0' ':' | cut -f1 -d :`; done)
-        logger -s -t "dsp-recover" "FIXME! killing users of 'bridgedriver': $users"
-        kill -9 `lsof -t /dev/DspBridge`
-        sleep 5
-}
-
-MODULE_USAGE=`grep bridgedriver /proc/modules | cut -d ' ' -f3`
-COUNT=0
-while [ $MODULE_USAGE -ne 0 ]
-do
-	MODULE_USAGE=`grep bridgedriver /proc/modules | cut -d ' ' -f3`
-	if [ $COUNT -ge 10 ]; then
-                logger -t "dsp-recover" "gave up waiting for 'bridgedriver' to become free"
-                kill_users
-		break
-	fi
-
-        sleep 1
-        COUNT=$(($COUNT + 1))
-done
-
-modprobe -r bridgedriver
-if [ $? == 0 ]; then
-        modprobe bridgedriver
-else
-        logger -t "dsp-recover" "initial restart failed, reloading image"
-        /lib/dsp/cexec.out -v -T /lib/dsp/baseimage.dof | grep -q failed
-        test $? != 0 # revert the result
-fi
-if [ $? == 0 ]; then
-        logger -t "dsp-recover" "DSP restarted"
-else
-        logger -t "dsp-recover" "couldn't restart the DSP"
-fi

++++++ deleted files:
--- 0001-build-remove-dsp-manager.patch



More information about the MeeGo-commits mailing list