diff --git a/include/kernel/xentium.h b/include/kernel/xentium.h
index b28eee9337ccf63b58a022d02489f24b4183837c..a922b64880fe880be709b0d1090a94f32967b03a 100644
--- a/include/kernel/xentium.h
+++ b/include/kernel/xentium.h
@@ -3,6 +3,17 @@
 
 #include <kernel/init.h>
 #include <kernel/elf.h>
+#include <data_proc_net.h>
+
+/* this structure is used in xentium kernels to define their parameters
+ * and capabilities
+ */
+struct xen_kernel_cfg {
+	char *name;
+	unsigned long op_code;
+	unsigned long crit_buf_lvl;
+};
+
 
 struct xen_module_section {
 	char *name;
@@ -30,6 +41,9 @@ struct xen_kernel {
 
 
 
-int xentium_kernel_load(struct xen_kernel *x, void *p);
+int xentium_kernel_add(void *p);
+void xentium_schedule_next(void);
+void xentium_input_task(struct proc_task *t);
+int xentium_config_output_node(op_func_t op_output);
 
 #endif /* _KERNEL_XENTIUM_H_ */
diff --git a/init/main.c b/init/main.c
index d5136abee861a6c66e3acfd4baf84760169db499..f54b9c7e11717218e596dad1091174c130b49e1e 100644
--- a/init/main.c
+++ b/init/main.c
@@ -35,6 +35,68 @@ static void kernel_init(void)
 }
 
 
+#include <data_proc_net.h>
+#include <kernel/xentium.h>
+
+int xen_op_output(unsigned long op_code, struct proc_task *t)
+{
+	ssize_t i;
+	ssize_t n;
+
+	unsigned int *p = NULL;
+
+
+	n = pt_get_nmemb(t);
+	printk("XEN OUT: op code %d, %d items\n", op_code, n);
+
+	if (!n)
+		goto exit;
+
+
+	p = (unsigned int *) pt_get_data(t);
+	if (!p)
+		goto exit;
+
+
+
+	for (i = 0; i < n; i++) {
+		printk("\t%d\n", p[i]);
+	}
+
+exit:
+	kfree(p);	/* clean up our data buffer */
+
+	pt_destroy(t);
+
+	return PN_TASK_SUCCESS;
+}
+
+void xen_new_input_task(size_t n)
+{
+	struct proc_task *t;
+
+	static int seq;
+
+	int i;
+	unsigned int *data;
+
+
+
+	data = kzalloc(sizeof(unsigned int) * n);
+
+	for (i = 0; i < n; i++)
+		data[i] = i;
+
+
+	t = pt_create(data, n, 3, 0, seq++);
+
+	BUG_ON(!t);
+
+	BUG_ON(pt_add_step(t, 0xdeadbeef, NULL));
+	BUG_ON(pt_add_step(t, 0xdeadbee0, NULL));
+
+	xentium_input_task(t);
+}
 
 
 
@@ -95,10 +157,25 @@ int main(void)
 
 
 
-#if 0
+#if 1
 	/* load all available Xentium kernels from the embedded modules image */
 	module_load_xen_kernels();
-	while(1);
+
+
+	xentium_config_output_node(xen_op_output);
+
+
+	xen_new_input_task(3);
+	xen_new_input_task(3);
+	xen_new_input_task(3);
+
+	xentium_schedule_next();
+	xentium_schedule_next();
+	xentium_schedule_next();
+	xentium_schedule_next();
+	xentium_schedule_next();
+
+
 #endif
 
 	return 0;
diff --git a/init/modules-image.c b/init/modules-image.c
index fb6954ee91c4a3dc23b1cb57135a6213f58ecf06..9584bfc02d9253773c72b0868bddd48148ba8e49 100644
--- a/init/modules-image.c
+++ b/init/modules-image.c
@@ -73,8 +73,6 @@ void module_load_xen_kernels(void)
 	char *fname;
 	void *file;
 
-	struct xen_kernel x;
-
 
 	list = ar_get_file_list(&mod_ar);
 
@@ -96,8 +94,8 @@ void module_load_xen_kernels(void)
 		if (!file)
 			pr_err(MSG "Failed to read file %s\n", fname);
 
-		if (xentium_kernel_load(&x, file))
-			pr_err(MSG "Error loading Xentium kernel %s\n", fname);
+		if (xentium_kernel_add(file))
+			pr_err(MSG "Error adding Xentium kernel %s\n", fname);
 
 		kfree(file);
 
diff --git a/kernel/xentium.c b/kernel/xentium.c
index d677b40c73b1616f3b61dde98cd2e593735474c2..6a46d5b30b8b42253f7f429a5280f506d17c8bf0 100644
--- a/kernel/xentium.c
+++ b/kernel/xentium.c
@@ -7,12 +7,15 @@
 #include <kernel/printk.h>
 #include <kernel/err.h>
 #include <kernel/xentium.h>
+#include <kernel/module.h>
 #include <kernel/kmem.h>
 #include <kernel/kernel.h>
 #include <asm-generic/swab.h>
 #include <kernel/string.h>
 #include <elf.h>
 
+#include <data_proc_net.h>
+
 
 
 
@@ -60,27 +63,48 @@ S_xen*       p_xen1               = (S_xen*)        (0x20100000);
 
 
 
-
-
-
-
-
-
 #define MSG "XEN: "
 
 
-
 /* if we need more space, this is how many entries we will add */
 #define KERNEL_REALLOC 10
+
 /* this is where we keep track of loaded modules */
 static struct {
+	struct proc_net *pn;
 	struct xen_kernel **x;
+	struct xen_kernel_cfg **cfg;
 	int    sz;
 	int    cnt;
 } _xen;
 
 
 
+/* this is scheduler, but we need to do the manual processing dance
+ * until we have threads, remmber:
+ * 
+ *  * pt = pn_get_next_pending_tracker(pn)
+ *
+ * while (1) {
+ *	t = pn_get_next_pending_task(pt)
+ *	ret = pt->op(pt_get_pend_step_op_code(t), t);
+ *	if (!pn_eval_task_status(pn, pt, t, ret))
+ *		pn_node_to_queue_tail(pn, pt);
+ *		abort_processing:
+ *	}
+ * }
+ *
+ * etc...
+ */
+
+static int op_xen_schedule_kernel(unsigned long op_code, struct proc_task *t)
+{
+	printk(MSG "scheduling kernel with op code %x\n", op_code);
+
+	return PN_TASK_SUCCESS;
+}
+
+
 
 /**
  * @brief setup the module structure
@@ -103,8 +127,8 @@ static int xentium_setup_kernel(struct xen_kernel *m)
 	m->ep       = m->ehdr->e_entry;
 
 
-
 	for (i = 0; i < m->ehdr->e_shnum; i++) {
+
 		shdr = elf_get_sec_by_idx(m->ehdr, i);
 		if (!shdr)
 			return -1;	
@@ -120,7 +144,6 @@ static int xentium_setup_kernel(struct xen_kernel *m)
 				m->align = shdr->sh_addralign;
 				pr_debug(MSG "align: %d\n", m->align);
 			}
-
 		}
 	}
 
@@ -267,7 +290,8 @@ static int xentium_load_kernel(struct xen_kernel *x)
 
 			/* we byte-swap all loadable sections, because the DMA
 			 * of the Xentium reverses everything back into little
-			 * endian words */
+			 * endian words
+			 */
 
 			p = (uint32_t *) sec->sh_addr;
 			for (i = 0; i < sec->sh_size / sizeof(uint32_t); i++)
@@ -300,22 +324,16 @@ error:
 }
 
 
-struct xen_kernel_cfg {
-	char *name;
-	unsigned long capabilities;
-	unsigned long crit_buf_lvl;
-};
-
 
 /**
  * load the kernels configuration data
  */
 
-int xentium_config_kernel(struct xen_kernel *x)
+struct xen_kernel_cfg *xentium_config_kernel(struct xen_kernel *x)
 {
 	unsigned long symaddr;
 
-	struct xen_kernel_cfg x_cfg;
+	struct xen_kernel_cfg *cfg;
 	size_t len = 0;
 	uint32_t *p;
 
@@ -323,10 +341,17 @@ int xentium_config_kernel(struct xen_kernel *x)
 
 	if (!elf_get_symbol_value(x->ehdr, "_xen_kernel_param", &symaddr)) {
 		pr_warn(MSG "Error, _xen_kernel_param not found\n");
-		return -1;
+		return NULL;
 	}
 
-	memcpy((void *) &x_cfg, (void *) symaddr, sizeof(struct xen_kernel));
+
+
+	cfg = (struct xen_kernel_cfg *) kzalloc(sizeof(struct xen_kernel_cfg));
+	if (!cfg)
+		return NULL;
+
+
+	memcpy(cfg, (void *) symaddr, sizeof(struct xen_kernel));
 	
 	/* everything but the "name" entry (which is mashed up from our
 	 * perspective) is already in correct (big endian) order.
@@ -335,19 +360,26 @@ int xentium_config_kernel(struct xen_kernel *x)
 	 * boundary, then swab32() on the buffer to restore the string.
 	 * The Xentium DMA will reverse endianess to little endian on the
 	 * relevant run time sections, we don't need to care about that.
+	 *
+	 * yes, this may "leak" a few (3) bytes, so don't store plain text
+	 * passwords there :D :D
+	 * XXX: alloc second char buffer of actual string size, then strncpy()
+	 *      and free the initial one (or just krealloc() >:-))
 	 */
 
-	while (x_cfg.name[len] != '\0') len++;
+	while (cfg->name[len] != '\0') len++;
 
-	len = ALIGN(len, sizeof(uint32_t));
+	len = ALIGN(len + sizeof(uint32_t), sizeof(uint32_t));
 
 	name = kmalloc(len);
-	if (!name)
-		return -1;
+	if (!name) {
+		kfree(cfg);
+		return NULL;
+	}
 
 	p = (uint32_t *) name;
 
-	memcpy(name, (void *) x_cfg.name, len);
+	memcpy(name, cfg->name, len);
 
 	len = len / sizeof(uint32_t);
 
@@ -356,20 +388,31 @@ int xentium_config_kernel(struct xen_kernel *x)
 		p[len] = swab32(p[len]);
 	} while (len);
 	
-	x_cfg.name = name;
+	cfg->name = name;
 
 	printk(MSG "Configuration of kernel %s:\n"
-	       MSG "\tcapabilities:          %x\n"
+	       MSG "\top code     :          %x\n"
 	       MSG "\tcritical buffer level: %d\n",
-	       x_cfg.name, x_cfg.capabilities, x_cfg.crit_buf_lvl);
+	       cfg->name, cfg->op_code, cfg->crit_buf_lvl);
 
 
-	return 0;
+	return cfg;
 }
 
+static int xentium_init(void);
 
-int xentium_kernel_load(struct xen_kernel *x, void *p)
+int xentium_kernel_add(void *p)
 {
+	struct xen_kernel *x;
+	struct xen_kernel_cfg *cfg = NULL;
+	struct proc_tracker *pt = NULL;
+
+
+	xentium_init();	/* XXX */
+
+	x = (struct xen_kernel *) kzalloc(sizeof(struct xen_kernel));
+	if (!x)
+		goto error;
 
 
 	/* the ELF binary starts with the ELF header */
@@ -391,14 +434,29 @@ int xentium_kernel_load(struct xen_kernel *x, void *p)
 		goto cleanup;
 
 
-	if (xentium_config_kernel(x))
+	cfg = xentium_config_kernel(x);
+	if (!cfg)
 		goto cleanup;
 
+	x->ehdr = NULL;	/* not used anymore */
 
+
+
+	pt = pt_track_create(op_xen_schedule_kernel,
+			     cfg->op_code,
+			     cfg->crit_buf_lvl);
+	if (!pt)
+		goto cleanup;
+
+	if (pn_add_node(_xen.pn, pt))
+		goto cleanup;
+
+
+
+
+
+#if 0
 	printk("starting xentium with ep %x\n", x->ep);
-#if 1
-	p_xen0->mlbx[0] = x->ep;
-#else
 	p_xen1->mlbx[0] = x->ep;
 #endif
 
@@ -406,17 +464,31 @@ int xentium_kernel_load(struct xen_kernel *x, void *p)
 	if (_xen.cnt == _xen.sz) {
 		_xen.x = krealloc(_xen.x, (_xen.sz + KERNEL_REALLOC) *
 				   sizeof(struct xen_kernel **));
+		_xen.cfg = krealloc(_xen.cfg, (_xen.sz + KERNEL_REALLOC) * 
+				    sizeof(struct xen_kernel_cfg **));
 
 		bzero(&_xen.x[_xen.sz], sizeof(struct xen_kernel **) *
 		      KERNEL_REALLOC);
+		
+		bzero(&_xen.cfg[_xen.sz], sizeof(struct xen_kernel_cfg **) *
+		      KERNEL_REALLOC);
+
 		_xen.sz += KERNEL_REALLOC;
 	}
 
-	_xen.x[_xen.cnt++] = x;
+	_xen.x[_xen.cnt] = x;
+	_xen.cfg[_xen.cnt] = cfg;
+
+	_xen.cnt++;
+
+
 
 	return 0;
 cleanup:
 	pr_err("cleanup\n");
+	kfree(x);
+	kfree(cfg);
+	pt_track_destroy(pt);
 #if 0
 	xentium_kernel_unload(m);
 #endif
@@ -425,3 +497,74 @@ error:
 	return -1;
 }
 
+
+/**
+ * define the output for the network
+ */
+
+int xentium_config_output_node(op_func_t op_output)
+{
+	if (pn_create_output_node(_xen.pn, op_output))
+		return -1;
+
+	return 0;
+}
+
+
+/**
+ * @brief add a new to the network
+ */
+
+void xentium_input_task(struct proc_task *t)
+{
+	pn_input_task(_xen.pn, t);
+	pn_process_inputs(_xen.pn);
+}
+
+
+/**
+ * @brief run a processing cycle 
+ */
+
+void xentium_schedule_next(void)
+{
+	pn_process_next(_xen.pn);
+
+	pn_process_outputs(_xen.pn);
+}
+
+
+/**
+ * @brief driver cleanup function
+ */
+
+static int xentium_exit(void)
+{
+	printk(MSG "module_exit() not implemented\n");
+
+	return 0;
+}
+
+
+/**
+ * @brief driver initialisation
+ */
+
+static int xentium_init(void)
+{
+
+
+	if (!_xen.pn) {
+		printk(MSG "initialising\n");
+	       _xen.pn = pn_create();
+	}
+
+	if (!_xen.pn)
+		return -ENOMEM;
+
+
+	return 0;
+}
+
+module_init(xentium_init);
+module_exit(xentium_exit);