diff --git a/pcie-wb/Makefile b/pcie-wb/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..a8273b1d47bf8ddac18efe95e1aaa7aba36216bb
--- /dev/null
+++ b/pcie-wb/Makefile
@@ -0,0 +1,32 @@
+#export PATH=$PATH:/share/eldk/bin:/share/eldk/usr/bin
+#export CROSS_COMPILE=ppc_4xxFP-
+#export ARCH=powerpc
+
+# This is useful if cross-compiling. Taken from kernel Makefile (CC changed)
+#AS      =$(CROSS_COMPILE)as
+#LD      =$(CROSS_COMPILE)ld
+#CC      =$(CROSS_COMPILE)gcc
+#CPP     =$(CC) -E
+#AR      =$(CROSS_COMPILE)ar
+#NM      =$(CROSS_COMPILE)nm
+#STRIP   =$(CROSS_COMPILE)strip
+#OBJCOPY =$(CROSS_COMPILE)objcopy
+#OBJDUMP =$(CROSS_COMPILE)objdump
+
+
+
+KERNELDIR ?= /common/usr/embedded/kernel/scu/linux-2.6.33.6/
+ifneq ($(KERNELRELEASE),)
+	obj-m	:= pci_char.o sleepy.o
+else
+	KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+	PWD       := $(shell pwd)
+
+all:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD)
+
+endif
+
+clean:
+	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
+
diff --git a/pcie-wb/irq_response.c b/pcie-wb/irq_response.c
new file mode 100644
index 0000000000000000000000000000000000000000..44eecbf5bd1e484dddaf3cc878a6440e0bc9bd2e
--- /dev/null
+++ b/pcie-wb/irq_response.c
@@ -0,0 +1,114 @@
+/*
+ * syscalls.c
+ * Program to illustrate common system calls. Doesn't actually
+ * perform any useful function, but will later be expanded into
+ * a program which does.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include "pci_char.h"
+
+#define FALSE 0
+#define TRUE 1
+#define BUFCOUNT 100
+#define TICK	8	/* 8 ns */
+
+
+int main()
+{
+  int fd_irq;					/* device file descriptor for blocking read */
+  int fd_rd;					/* device file descriptor for non-blocking read */
+  unsigned int cnt_value_irq;	/* buffer to hold data */
+  unsigned int cnt_value_rd;	/* buffer to hold data */
+  unsigned int diff_buffer[BUFCOUNT];
+  int status;					/* return status of system calls */
+  int i;
+  int arg;
+
+  /* open irq device */
+  status = fd_irq = open("/dev/pci_char0", O_RDWR);
+  if (status == -1) {
+    perror("error opening /dev/pci_char0");
+    return(1);
+  }
+  
+  /* open rd device after irq device */
+  status = fd_rd = open("/dev/pci_char1", O_RDWR);
+  if (status == -1) {
+    perror("error opening /dev/pci_char1");
+    return(1);
+  }
+
+  /* one tick is 8ns, so 1250000 ticks give 10µs */
+  arg = 1250000;	// 0.01s / 8*E-9s
+  //status = ioctl(fd_irq, SET_PERIOD, arg);
+   // if (status == -1) {
+  	//  perror("error from SET_PERIOD ioctl");
+   //     return(1);
+   // }
+
+  //status = ioctl(fd_irq, GET_PERIOD, arg);
+ // if (status == -1) {
+	//  perror("error from GET_PERIOD ioctl");
+   //   return(1);
+  //} else
+	//  printf("Period value is %d\n", status);
+
+
+  for (i = 0; i < BUFCOUNT; i++) {
+	  // blocking read
+	  status = read(fd_irq, &cnt_value_irq, sizeof(int));
+	  if (status == -1) {
+		perror("error reading from fd_irq");
+		return(1);
+	  }
+
+	  // non-blocking read
+	  status = read(fd_rd, &cnt_value_rd, sizeof(int));
+	  if (status == -1) {
+		  perror("error reading from fd_rd");
+		  return(1);
+	   }
+
+	  diff_buffer[i] = abs(cnt_value_irq-cnt_value_rd);
+
+  }
+
+  for (i = 0; i < BUFCOUNT; i++) {
+	  printf("%d\n", diff_buffer[i]);
+  }
+
+  close(fd_irq);
+  close(fd_rd);
+
+  return(0);
+
+  /* write some data */
+//  *buf = 1;
+//  while(1) {
+//  	status = write(fd, buf, 1);
+//  	if (status == -1) {
+//  		perror("error writing to /dev/pci_char0");
+//   		exit(1);
+//  	}
+
+
+  	
+  	//usleep(125000);			/* wait for 250ms */
+  //}
+
+  /* close the device */
+//  status = close(fd_irq);
+//  if (status == -1) {
+//    perror("error closing /dev/pci_char0");
+//    return(1);
+//  }
+
+  /* and exit */
+
+}
diff --git a/pcie-wb/ledloop.c b/pcie-wb/ledloop.c
new file mode 100644
index 0000000000000000000000000000000000000000..0eb8c6f0884ed8822f065d25f89b0d3ad8c93a1d
--- /dev/null
+++ b/pcie-wb/ledloop.c
@@ -0,0 +1,80 @@
+/*
+ * syscalls.c
+ * Program to illustrate common system calls. Doesn't actually
+ * perform any useful function, but will later be expanded into
+ * a program which does.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#define FALSE 0
+#define TRUE 1
+
+
+int main()
+{
+  int fd;						/* device file descriptor */
+  //int arg;					/* argument for ioctl call */
+  unsigned char buf[1];			/* buffer to hold data */
+  int status;					/* return status of system calls */
+  char up = TRUE;
+
+  /* open device */
+  status = fd = open("/dev/pci_char0", O_RDWR);
+  if (status == -1) {
+    perror("error opening /dev/pci_char0");
+    exit(1);
+  }
+
+  /* set a parameter using ioctl call */
+  
+  //arg = 8000; /* sampling rate */
+  /*status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg);
+  if (status == -1) {
+    perror("error from SOUND_PCM_WRITE_RATE ioctl");
+    exit(1);
+  }*/
+
+  /* read some data */
+  //status = read(fd, buf, sizeof(buf));
+  //if (status == -1) {
+  //  perror("error reading from /dev/dsp");
+  //  exit(1);
+  //}
+
+  /* write some data */
+  *buf = 1;
+  while(1) {
+  	status = write(fd, buf, 1);
+  	if (status == -1) {
+  		perror("error writing to /dev/pci_char0");
+   		exit(1);
+  	}
+
+	if (buf[0] == 0x80)		/* turn if highest bit is set */
+		up = FALSE;
+	else if (buf[0] == 0x01)
+		up = TRUE;
+
+	if (up == TRUE)
+  		buf[0] <<= 1;
+	else
+		buf[0] >>= 1;
+  	
+  	usleep(125000);			/* wait for 250ms */
+  }
+
+  /* close the device */
+  status = close(fd);
+  if (status == -1) {
+    perror("error closing /dev/pci_char0");
+    exit(1);
+  }
+
+  /* and exit */
+  return(0);
+}
diff --git a/pcie-wb/mmap.c b/pcie-wb/mmap.c
new file mode 100644
index 0000000000000000000000000000000000000000..6bcb27c0cda4197f63f2e79958c08e6f75585741
--- /dev/null
+++ b/pcie-wb/mmap.c
@@ -0,0 +1,80 @@
+/*
+ *  Accessing a PCI memory region using mmap() on /dev/mem
+ *
+ *  	Compile with 'gcc -Wall -O file.c -lpci -o peeker' (-O *is* mandatory)
+ *
+ *	Run with './peeker x y z' arguments can be derived from 'lspci -tvv'
+ *
+ *	Make sure (with lspci -vvs x:y.z) that "Region 0" is memory and that 
+ *	 "Region 1" is I/O.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <pci/pci.h>
+#include <sys/io.h>
+#include <sys/mman.h>
+#include <string.h>
+
+#include "pci_char.h"
+
+#define PCI_MEM_LEN (1<<18) 
+
+#define COUNT 100000
+
+int main( int argc, char *argv[]){
+
+
+  unsigned char* ptr_to_pci_mem;
+	unsigned int pci_mem_addr;
+ 	int buffer[COUNT];
+	int i;
+	FILE* fd;
+
+
+  /* Check IO permissions to be able to open /dev/mem
+   */
+  if(iopl(3)){
+    printf("Cannot get I/O permissions (being root helps)\n");
+    return -1;
+  }
+
+  pci_mem_addr = 0xfeac0000;
+  //pci_mem_addr += SCU_MASTER;
+
+  fd = fopen ( "/dev/mem", "r+w");
+
+  /* ...and map the PCI memory area (man 2 mmap for more info)
+   */ 
+  ptr_to_pci_mem =  mmap(	NULL,
+					 						PCI_MEM_LEN,
+					 						PROT_READ|PROT_WRITE,
+			 								MAP_SHARED,
+										 	fileno(fd), pci_mem_addr);
+
+
+
+  /* Voila! Two bytes of PCI memory out from the board
+   * You can also use the memcpy() family of functions
+   */
+  printf("Memory pointer: %p\n", ptr_to_pci_mem);
+  printf("PCI memory @%#x\n", pci_mem_addr);
+  for (i = 0; i< 30; i++) {
+	printf("addr %p : %#x\n",ptr_to_pci_mem + PCIE_BASE + 0x800+ i*4, *(ptr_to_pci_mem + PCIE_BASE + 0x800 + i*4) );
+  }
+  //printf("The 2nd byte on PCI memory is : %#x\n", *(ptr_to_pci_mem+2) );
+  
+  //memcpy(buffer, ptr_to_pci_mem, COUNT);
+
+//for (i=0; i < COUNT; i+=1) {
+ // 	buffer[i] = *(ptr_to_pci_mem++);
+	//	//*(ptr_to_pci_mem+1) = i;
+  //}
+  
+
+  munmap(ptr_to_pci_mem, PCI_MEM_LEN);
+  fclose(fd);
+  return 0;
+}
diff --git a/pcie-wb/pci_char.c b/pcie-wb/pci_char.c
new file mode 100644
index 0000000000000000000000000000000000000000..cf5f728b1db80d4e526bccffcc4587952fb43f79
--- /dev/null
+++ b/pcie-wb/pci_char.c
@@ -0,0 +1,507 @@
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/kdev_t.h>
+#include <linux/poll.h>
+#include <linux/interrupt.h>
+#include <linux/cdev.h>
+#include <linux/aer.h>
+
+#include <asm/io.h>		/*outb iowrite8 */
+#include <asm/spinlock.h>
+
+#include "pci_char.h"
+
+#define FALSE 0
+#define TRUE 1
+
+int use_mem = FALSE;			/* mem or io port */
+int use_msi = FALSE;			/* Message Signaled Interrupts enabled */
+
+static int  major_num  = 0;		/* major number for char device */
+static int  minor_num  = 0;		/* minor number for char device */
+static struct cdev *cdev_irq;
+static struct cdev *cdev_rd;
+
+struct pci_resource *pci_res0 = NULL;	/* ptrs to resource objects */
+struct pci_resource *pci_res1 = NULL;
+
+char name_str[] = "pci_char";
+char myirq = -1;						/* IRQ from PCI config reg */
+int instance_count = 0;					/* counting connected processes for housekeeping */
+
+static DECLARE_WAIT_QUEUE_HEAD(event_wq);
+static DEFINE_SPINLOCK(snapshot_lock);
+static DEFINE_SPINLOCK(period_lock);
+
+unsigned long short_buffer = 0;
+unsigned long volatile short_head;
+volatile unsigned long short_tail;
+
+
+static inline void short_incr_bp(volatile unsigned long *index, int delta)
+{
+	unsigned long new = *index + delta;
+	barrier();  /* Don't optimize these two together */
+	*index = (new >= (short_buffer + PAGE_SIZE)) ? short_buffer : new;
+}
+
+struct pci_resource {
+	int bar;						/* BAR number from 0 to 5 */
+	unsigned long start;			/* start addr of BAR */
+	unsigned long end;				/* end addr of BAR */
+	unsigned int size;
+	void *m_addr;					/* remapped addr */
+	int is_mem;
+};
+
+irq_handler_t my_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+
+	int ret;
+	int snapl_value;
+	int snaph_value;
+	int snap_value;
+	unsigned char *bptr = pci_res0->m_addr;
+	//int written;
+	
+	mb();
+	/* check if our device has triggered */
+	ret = ioread32(bptr + TMR_0_BASE);mb();
+	if (!(ret & 0x1))
+		return IRQ_NONE;
+
+
+	/* copy snapshot value from timer */
+	/* should be atomic */
+	spin_lock(&snapshot_lock);
+	/* trigger the latch of the counter value */
+	iowrite16(0x0, bptr + TMR_0_SNAPL);
+	rmb();	// has to be executed before reading
+	snapl_value = ioread16(bptr + TMR_0_SNAPL);rmb();
+	snaph_value = ioread16(bptr + TMR_0_SNAPH);rmb();
+	spin_unlock(&snapshot_lock);
+	snap_value = (int)(snaph_value << 16) | snapl_value;
+	//printk(KERN_ALERT "%s: snap_value = 0x%x\n", name_str, snap_value);
+	//snap_value = snap_value | (snaph_value << 32);
+	//written = sprintf((char *)short_head,"%08x\n", snap_value);
+	*(u32 *)short_head = snap_value;
+
+	short_incr_bp(&short_head, sizeof(u32));
+
+	/* wake up the reading process */
+	wake_up_interruptible(&event_wq);
+
+	/* clear the interrupting bit in the pio */
+	//iowrite32(0x0, bptr + PIO_BASE + EDGE_CAPTURE);
+	/* clear pending bit in edge capture register */
+	mb();
+	//iowrite32(0x0, bptr + TMR_EDGE_CAPTURE);
+	iowrite16(0x0, bptr + TMR_0_BASE);mb();
+
+
+
+	//printk(KERN_ALERT "%s: irq handler called\n", name_str);
+	return (irq_handler_t)IRQ_HANDLED;
+}
+
+
+int pci_skel_open (struct inode *inode, struct file *filp)
+{	
+	
+	int result;
+	unsigned char *bptr = pci_res0->m_addr;
+	int arg = IRQ_RATE;
+
+	instance_count++;
+
+	iowrite16(arg, bptr + TMR_0_PERIODL);
+	wmb();
+	iowrite16(arg >> 16, bptr + TMR_0_PERIODH);
+
+	/* we have a irq number and the first process is connecting */
+	if (myirq >= 0 && instance_count == 1) {
+		result = request_irq(	myirq,
+ 					(irq_handler_t)my_irq_handler,
+					IRQF_SHARED,
+					name_str,
+					pci_res0 /* used as dev_id */
+					);
+		if (result) {
+			printk(KERN_ALERT "%s: can't get IRQ %d\n", name_str, myirq);
+			myirq = -1;
+		} else {
+			/* enable irq */
+			/* enable MSI in MSI Control Register of PCI Endpoint */
+			result = ioread32(bptr + PCIE_BASE + MSI);
+			iowrite32(result |= (1UL << 16), bptr + PCIE_BASE + MSI);
+			
+			/* enable AVL_IRQ in MSI Control Register of PCI Endpoint */
+			result = ioread32(bptr + PCIE_BASE + MSI);
+			iowrite32(result |= (1UL << 7), bptr + PCIE_BASE + MSI);
+
+			mb();
+
+			iowrite16(0x7, bptr + TMR_0_CTRL);
+
+			ioread32(bptr + PCIE_BASE); /* dummy read */
+			mb();
+
+		}
+	}
+					
+	return 0;
+}
+
+int pci_rd_open (struct inode *inode, struct file *filp)
+{
+	return 0;
+}
+
+int pci_irq_release (struct inode *inode, struct file *filp)
+{
+	unsigned char *bptr = pci_res0->m_addr;
+	int result;
+
+	instance_count--;
+
+	/* we have a irq number and the last connected process is to be released*/
+	if (myirq && instance_count == 0)
+	{
+		free_irq(myirq, pci_res0 /* dev_id */);
+
+		mb();
+		/* disable timer irq */
+		iowrite16(0x0, bptr + TMR_0_CTRL);
+		mb();
+
+		/* disable AVL_IRQ in MSI Control Register of PCI Endpoint */
+		result = ioread32(bptr + PCIE_BASE + MSI);
+		iowrite32(result |= (0UL << 7), bptr + PCIE_BASE + MSI);
+		/* disable MSI in MSI Control Register of PCI Endpoint */
+		result = ioread32(bptr + PCIE_BASE + MSI);
+		iowrite32(result |= (0UL << 16), bptr + PCIE_BASE + MSI);
+
+		ioread32(bptr + PCIE_BASE); /* dummy read */
+		mb();
+
+	}
+	return 0;
+}
+
+int pci_rd_release (struct inode *inode, struct file *filp)
+{
+
+	return 0;
+}
+
+ssize_t pci_blocking_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
+{
+	int count0;
+
+	
+	/* there is no data so we are going to wait. */
+	/* but only if there is no wakeup call pending */
+	wait_event_interruptible(event_wq, short_head != short_tail);
+
+	/* now we should have at least one event in the buffer */
+
+	/* count0 is the number of readable data bytes */
+	count0 = short_head - short_tail;
+	if (count0 < 0) /* wrapped */
+		count0 = short_buffer + PAGE_SIZE - short_tail;
+	//printk(KERN_ALERT "%s: read count0 = %d\n", name_str, count0);
+	if (count0 < count) count = count0;
+	if (copy_to_user(buf, (char *)short_tail, count))
+		return -EFAULT;
+	short_incr_bp (&short_tail, count);
+	return count;
+}
+
+ssize_t pci_nonblocking_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
+{
+	int snapl_value;
+	int snaph_value;
+	int snap_value;
+	unsigned char *bptr = pci_res0->m_addr;
+
+	/* copy snapshot value from timer */
+	/* should be atomic */
+	spin_lock(&snapshot_lock);
+	/* trigger the latch of the counter value */
+	iowrite16(0x0, bptr + TMR_0_SNAPL);
+	rmb();	// has to be executed before reading
+	snapl_value = ioread16(bptr + TMR_0_SNAPL);rmb();
+	snaph_value = ioread16(bptr + TMR_0_SNAPH);rmb();
+	spin_unlock(&snapshot_lock);
+	snap_value = (int)(snaph_value << 16) | snapl_value;
+
+	if (copy_to_user(buf, &snap_value, 4))
+			return -EFAULT;
+
+	return 4;
+}
+
+ssize_t pci_skel_write(struct file *filp, const char __user *buf, size_t count,
+		loff_t *f_pos)
+{
+  		return 0;
+}
+
+int pci_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,  unsigned long arg) {
+	
+	int retval = 0;
+	unsigned char *bptr = pci_res0->m_addr;
+	
+	if(_IOC_TYPE(cmd) != PCI_CHAR_MAGIC) return -ENOTTY;
+	if(_IOC_NR(cmd) > PCI_CHAR_MAXNR) return -ENOTTY;
+	
+	switch(cmd) {
+		/*case SET_PERIOD:
+			//printk(KERN_ALERT "%s: periodl 0x%x\n", name_str, arg);
+			 should be atomic
+			spin_lock(&period_lock);
+			iowrite16(arg, bptr + TMR_0_PERIODL);
+			wmb();
+			iowrite16(arg >> 16, bptr + TMR_0_PERIODH);
+			spin_unlock(&period_lock);
+			break;
+		case GET_PERIOD:
+			spin_lock(&period_lock);
+			retval = ioread16(bptr + TMR_0_PERIODL);
+			rmb();
+			retval = ioread16(bptr + TMR_0_PERIODH) << 16 | retval;
+			spin_unlock(&period_lock);
+			printk(KERN_ALERT "%s: period value is 0x%x\n", name_str, retval);
+			return retval;
+			break;*/
+			
+		default:
+			return -ENOTTY;
+	}
+	return retval;
+}
+
+
+unsigned int pci_skel_poll(struct file *filp, poll_table *wait)
+{
+	return POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM;
+}
+
+struct file_operations pci_irq_fops = {
+	.owner	 = THIS_MODULE,
+	.read	 = pci_blocking_read,
+	.write	 = pci_skel_write,
+	.ioctl   = pci_ioctl,		
+	.poll	 = pci_skel_poll,
+	.open	 = pci_skel_open,
+	.release = pci_irq_release,
+};
+
+struct file_operations pci_rd_fops = {
+	.owner	 = THIS_MODULE,
+	.read	 = pci_nonblocking_read,
+	.poll	 = pci_skel_poll,
+	.open	 = pci_rd_open,
+	.release = pci_rd_release,
+};
+
+static struct pci_device_id ids[] = {
+	{ PCI_DEVICE(ALTERA_ID, DEVICE_ID), },
+	{ PCI_DEVICE(0x1002, 0x4750), },
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, ids);
+
+static unsigned char skel_get_revision(struct pci_dev *dev)
+{
+	u8 revision;
+
+	pci_read_config_byte(dev, PCI_REVISION_ID, &revision);
+	return revision;
+}
+
+static int probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	/* Do probing type stuff here.  
+	 * Like calling request_region();
+	 * reading BARs
+	 * reading IRQ
+	 * register char dev
+	 */
+	int result;
+	int is_mem;
+	dev_t dev_irq = MKDEV(major_num, minor_num);
+	dev_t dev_rd = MKDEV(major_num, minor_num);
+
+	if (skel_get_revision(pdev) != 0x01) {
+		printk(KERN_ALERT "%s: revision ID wrong!\n", name_str);
+		return -ENODEV;
+	}
+
+	/* enable pcie error reporting */
+	result = pci_enable_pcie_error_reporting(pdev);
+	if (result) {
+		printk(KERN_ALERT "Could not enable pcie error reporting.\n");
+	}
+
+	/* enable message signaled interrupts */
+	result = pci_enable_msi(pdev);
+	/* could not use MSI? */
+	if (result) {
+	/* resort to legacy interrupts */
+		printk(KERN_ALERT "Could not enable MSI interrupting, staying with legacy.\n");
+	/* MSI enabled, remember for cleanup */
+	} else {
+		use_msi = TRUE;
+		printk(KERN_ALERT "Enabled MSI interrupting.\n");
+	}
+
+	pci_res0 = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);	/* mem for object */
+	if (!pci_res0) {
+		printk(KERN_ALERT "%s: could not alloc mem for pci_res0!\n", name_str);
+		goto err_pci_res0;
+	}
+
+	/*init of pci_res0 */
+	pci_res0->bar = 0;
+	pci_res0->start = pci_resource_start(pdev, 0);
+	pci_res0->end = pci_resource_end(pdev, 0);
+	pci_res0->size = pci_res0->end - pci_res0->start + 1;
+
+	is_mem = pci_resource_flags(pdev, 0);
+	is_mem = is_mem & IORESOURCE_MEM;
+	pci_res0->is_mem = is_mem;
+
+	printk(KERN_ALERT "%s: BAR0  0x%lx - 0x%lx\n", name_str, pci_res0->start, pci_res0->end);
+
+	if (!request_mem_region(pci_res0->start, pci_res0->size, name_str)) {
+			printk(KERN_ALERT "%s: request_mem_region failed\n", name_str);
+			goto err_mem_region;
+	}
+	
+	pci_res0->m_addr = ioremap_nocache(pci_res0->start, pci_res0->size);
+	printk(KERN_ALERT "%s: ioremap to %lx\n", name_str, (unsigned long)pci_res0->m_addr);
+
+	/* get irq number from pci */
+	myirq = pdev->irq;
+	printk(KERN_ALERT "%s: using IRQ number %d\n", name_str, myirq);
+
+	/* alloc DEV_COUNT device number */
+	result  = alloc_chrdev_region (&dev_irq, FIRSTMINOR, DEV_COUNT, name_str);
+	if(result < 0) {
+		printk(KERN_ALERT "%s: ERROR unable to get major number\n", name_str);
+		goto err_alloc_chrdev;
+	} else {
+		major_num = MAJOR(dev_irq);
+		printk(KERN_ALERT "%s: My major nummber is: %d\n", name_str, major_num);
+	};
+
+	// assign dev_rd the next minor number
+	dev_rd = MKDEV(major_num, MINOR(dev_irq) + 1);
+
+	// allocate cdev structures
+	cdev_irq = cdev_alloc();
+	cdev_rd = cdev_alloc();
+
+	if((cdev_irq == NULL) || (cdev_rd == NULL)){
+		printk("%s: ERROR allocate cdev structur failure\n", name_str);
+		goto err_cdev_alloc;
+	}
+
+	cdev_irq->owner  = THIS_MODULE;
+	cdev_irq->ops    = &pci_irq_fops;
+
+	cdev_rd->owner  = THIS_MODULE;
+	cdev_rd->ops    = &pci_rd_fops;
+
+	result = cdev_add(cdev_irq, dev_irq, 1);
+	if(result < 0){
+		printk("%s: cdev_add dev_irq failed\n", name_str);
+		goto err_alloc_chrdev;
+	} else
+		printk("%s: added cdev_irq\n", name_str);
+
+	result = cdev_add(cdev_rd, dev_rd, 1);
+	if(result < 0){
+		printk("%s: cdev_add dev_rd failed\\n", name_str);
+		goto err_cdev_add;
+	} else
+		printk("%s: added cdev_rd\n", name_str);
+
+
+	short_buffer = __get_free_pages(GFP_KERNEL,0);  //never fails
+	short_head = short_tail = short_buffer;
+
+	return pci_enable_device(pdev);
+
+	/* cleaning up */
+	err_cdev_add:
+		cdev_del(cdev_irq);
+	err_cdev_alloc:
+		unregister_chrdev_region (MKDEV(major_num, minor_num), DEV_COUNT);
+	err_alloc_chrdev:
+		iounmap(pci_res0->m_addr);
+		release_mem_region(pci_res0->start, pci_res0->size);
+	err_mem_region:
+		kfree(pci_res0);
+	err_pci_res0:
+		return -EIO;
+}
+
+static void remove(struct pci_dev *pdev)
+{
+	
+	/* clean up any allocated resources and stuff here.
+	 * like call release_mem_region();
+	 */
+
+	printk(KERN_ALERT "%s: releasing resources\n", name_str);
+	if (cdev_rd)
+		cdev_del(cdev_rd);
+	if (cdev_irq)
+		cdev_del(cdev_irq);
+	if (major_num) {
+		unregister_chrdev_region (MKDEV(major_num, minor_num), DEV_COUNT);
+		printk(KERN_ALERT "%s: released major number %i\n", name_str, major_num);
+	}
+	if (use_msi)
+		pci_disable_msi(pdev);
+
+	iounmap(pci_res0->m_addr);
+	release_mem_region(pci_res0->start, pci_res0->size);
+	printk(KERN_ALERT "%s: released io 0x%lx\n", name_str, pci_res0->start);
+	if (pci_res0 != NULL)
+		kfree(pci_res0);
+}
+
+static int err_handler(struct pci_dev *pdev) {
+	printk(KERN_ALERT "%s:  err handler called!\n", name_str);
+	return 0;
+}
+
+static struct pci_driver pci_driver = {
+	.name = name_str,
+	.id_table = ids,
+	.probe = probe,
+	.remove = remove,
+	.err_handler = err_handler,
+};
+
+static int __init pci_skel_init(void)
+{
+	return pci_register_driver(&pci_driver);
+}
+
+static void __exit pci_skel_exit(void)
+{	
+	pci_unregister_driver(&pci_driver);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(pci_skel_init);
+module_exit(pci_skel_exit);
diff --git a/pcie-wb/pci_char.h b/pcie-wb/pci_char.h
new file mode 100644
index 0000000000000000000000000000000000000000..375f95e293db85906b7b73007dcf97c82f276ec9
--- /dev/null
+++ b/pcie-wb/pci_char.h
@@ -0,0 +1,58 @@
+#ifndef PCI_CHAR_DRIVER_H_
+#define PCI_CHAR_DRIVER_H_
+
+#endif /*PCI_CHAR_DRIVER_H_*/
+
+#include <linux/ioctl.h>
+
+#define PCI_CHAR_MAGIC	'S'
+
+#define SET_PERIOD			_IO(PCI_CHAR_MAGIC, 0)
+#define GET_PERIOD			_IO(PCI_CHAR_MAGIC, 1)
+
+#define PCI_CHAR_MAXNR	3
+
+#define	ALTERA_ID 0x1172
+#define DEVICE_ID 0x0004
+#define FIRSTMINOR 0
+#define DEV_COUNT 2
+
+#define ONCHIP_RAM_OFFSET 	0x4000
+#define SCU_ADDR			0x4030
+#define SCU_TIMING			0x4040
+#define SCU_WR_DATA 		0x4020
+#define SCU_CTRL			0x4050
+#define SCU_RD_DATA			0x4060
+#define SCU_STATUS			0x4070
+#define SCU_MASTER			0x1000000
+
+#define	SCU_RD				'R'
+#define SCU_WR				'W'
+#define SCU_TM				'T'
+
+
+#define PCIE_BASE			0x20000
+#define MSI					0x050
+#define TMR_BASE			0x24000
+#define TMR_DIR				(TMR_BASE +	0x8)
+#define TMR_EDGE_CAPTURE	(TMR_BASE + 0x18)
+#define TMR_IRQ_MASK		(TMR_BASE +	0x10)
+#define TMR_SNAP		0x24020
+#define TMR_0_BASE		0x24080
+#define TMR_0_CTRL		(TMR_0_BASE + 0x8)
+#define TMR_0_PERIODL	(TMR_0_BASE + 0x10)
+#define TMR_0_PERIODH	(TMR_0_BASE + 0x18)
+#define TMR_0_SNAPL		(TMR_0_BASE + 0x20)
+#define TMR_0_SNAPH		(TMR_0_BASE + 0x28)
+
+
+#define EVENT_BUFFER_SIZE	100
+#define IRQ_RATE			1250000
+
+
+
+struct scu_cycle_data {
+	unsigned int data;				/* 16 bit data */
+	unsigned int addr;				/* 20 bit addr */
+	char type;						/* SCU_RD, SCU_WR, SCU_TM */
+};
diff --git a/pcie-wb/pci_char.mod.c b/pcie-wb/pci_char.mod.c
new file mode 100644
index 0000000000000000000000000000000000000000..6e658253eb98b50e1502675e89be6df49cb6815b
--- /dev/null
+++ b/pcie-wb/pci_char.mod.c
@@ -0,0 +1,22 @@
+#include <linux/module.h>
+#include <linux/vermagic.h>
+#include <linux/compiler.h>
+
+MODULE_INFO(vermagic, VERMAGIC_STRING);
+
+struct module __this_module
+__attribute__((section(".gnu.linkonce.this_module"))) = {
+ .name = KBUILD_MODNAME,
+ .init = init_module,
+#ifdef CONFIG_MODULE_UNLOAD
+ .exit = cleanup_module,
+#endif
+ .arch = MODULE_ARCH_INIT,
+};
+
+static const char __module_depends[]
+__used
+__attribute__((section(".modinfo"))) =
+"depends=";
+
+MODULE_ALIAS("pci:v00001172d00000004sv*sd*bc*sc*i*");
diff --git a/pcie-wb/pci_char_load b/pcie-wb/pci_char_load
new file mode 100755
index 0000000000000000000000000000000000000000..75167ab11e88f741953595ab32756ae90d621f46
--- /dev/null
+++ b/pcie-wb/pci_char_load
@@ -0,0 +1,16 @@
+#!/bin/sh
+module="pci_char"
+device="pci_char"
+mode="664"
+
+# invoke insmod with all arguments we got
+# and use a pathname, as newer modutils don't look in . by default
+/sbin/insmod ./$module.ko $* || exit 1
+
+#remove stale nodes
+rm -f /dev/${device}[0-3]
+
+major=$(awk "\$2==\"$module\" {print \$1}" /proc/devices)
+
+mknod /dev/${device}0 c $major 0
+mknod /dev/${device}1 c $major 1
diff --git a/pcie-wb/scu_test.c b/pcie-wb/scu_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..f7b7a1f81afec6c8652ad8bcb31ce30fb32d864e
--- /dev/null
+++ b/pcie-wb/scu_test.c
@@ -0,0 +1,81 @@
+/*
+ * syscalls.c
+ * Program to illustrate common system calls. Doesn't actually
+ * perform any useful function, but will later be expanded into
+ * a program which does.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <stdlib.h>
+
+#include "pci_char_driver.h"
+
+#define FALSE 0
+#define TRUE 1
+
+
+#define BUFSIZE		1
+
+
+int main()
+{
+  	int fd;						/* device file descriptor */
+  	int i = 0, j = 0;
+  	unsigned int wbuf[BUFSIZE];			/* buffer to hold data */
+  	unsigned int rbuf[BUFSIZE];
+  	int status;					/* return status of system calls */
+  	char up = TRUE;
+  	struct scu_cycle_data *scu_buf = malloc(sizeof(struct scu_cycle_data));
+
+  	/* open device */
+  	status = fd = open("/dev/pci", O_RDWR);
+  	if (status == -1) {
+    	perror("error opening /dev/pci");
+    	exit(1);
+  	}
+
+	
+	
+	
+	
+ 	/* reset of the SCU Macro */
+	status = ioctl(fd, PCI_CHAR_RESET);
+	if (status == -1) {
+		perror("error from PCI_CHAR_RESET");
+	    exit(1);
+	}
+	
+	scu_buf->addr = 0x00002;
+  		scu_buf->addr <<= 2;
+  		scu_buf->data = 0xAFFE;
+  		scu_buf->type = SCU_WR;
+  		status = write(fd, scu_buf, sizeof(struct scu_cycle_data));
+  		if (status == -1) {
+  			perror("error writing to SCU bus!");
+  			exit(1);
+  	}
+  	
+  	//for (j=0; j<1000; j++) {
+  		status = read(fd, scu_buf, sizeof(struct scu_cycle_data));
+  		if (status == -1) {
+  			perror("error reading from SCU bus!");
+  			exit(1);
+  		}
+		
+  	//}
+  
+
+  /* close the device */
+  status = close(fd);
+  if (status == -1) {
+    perror("error closing /dev/pci");
+    exit(1);
+  }
+
+  /* and exit */
+  return(0);
+}
diff --git a/pcie-wb/sleepy.c b/pcie-wb/sleepy.c
new file mode 100644
index 0000000000000000000000000000000000000000..7a96e2fd433dbb766c38cfbd94f2cebb05404c4e
--- /dev/null
+++ b/pcie-wb/sleepy.c
@@ -0,0 +1,85 @@
+/*
+ * sleepy.c -- the writers awake the readers
+ *
+ * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
+ * Copyright (C) 2001 O'Reilly & Associates
+ *
+ * The source code in this file can be freely used, adapted,
+ * and redistributed in source or binary form, so long as an
+ * acknowledgment appears in derived source files.  The citation
+ * should list that the code comes from the book "Linux Device
+ * Drivers" by Alessandro Rubini and Jonathan Corbet, published
+ * by O'Reilly & Associates.   No warranty is attached;
+ * we cannot take responsibility for errors or fitness for use.
+ *
+ * $Id: sleepy.c,v 1.7 2004/09/26 07:02:43 gregkh Exp $
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/sched.h>  /* current and everything */
+#include <linux/kernel.h> /* printk() */
+#include <linux/fs.h>     /* everything... */
+#include <linux/types.h>  /* size_t */
+#include <linux/wait.h>
+
+MODULE_LICENSE("GPL");
+
+static int sleepy_major = 0;
+
+static DECLARE_WAIT_QUEUE_HEAD(wq);
+static int flag = 0;
+
+ssize_t sleepy_read (struct file *filp, char __user *buf, size_t count, loff_t *pos)
+{
+	printk(KERN_ALERT "process %i (%s) going to sleep\n",
+			current->pid, current->comm);
+	wait_event_interruptible(wq, flag != 0);
+	flag = 0;
+	printk(KERN_DEBUG "awoken %i (%s)\n", current->pid, current->comm);
+	return 0; /* EOF */
+}
+
+ssize_t sleepy_write (struct file *filp, const char __user *buf, size_t count,
+		loff_t *pos)
+{
+	printk(KERN_ALERT "process %i (%s) awakening the readers...\n",
+			current->pid, current->comm);
+	flag = 1;
+	wake_up_interruptible(&wq);
+	return count; /* succeed, to avoid retrial */
+}
+
+
+struct file_operations sleepy_fops = {
+	.owner = THIS_MODULE,
+	.read =  sleepy_read,
+	.write = sleepy_write,
+};
+
+
+int sleepy_init(void)
+{
+	int result;
+
+	/*
+	 * Register your major, and accept a dynamic number
+	 */
+	result = register_chrdev(sleepy_major, "sleepy", &sleepy_fops);
+	if (result < 0)
+		return result;
+	if (sleepy_major == 0)
+		sleepy_major = result; /* dynamic */
+	return 0;
+}
+
+void sleepy_cleanup(void)
+{
+	unregister_chrdev(sleepy_major, "sleepy");
+}
+
+module_init(sleepy_init);
+module_exit(sleepy_cleanup);
+
+
diff --git a/pcie-wb/sleepy.mod.c b/pcie-wb/sleepy.mod.c
new file mode 100644
index 0000000000000000000000000000000000000000..147b9f606a20424745b223749c95caab818e50d1
--- /dev/null
+++ b/pcie-wb/sleepy.mod.c
@@ -0,0 +1,21 @@
+#include <linux/module.h>
+#include <linux/vermagic.h>
+#include <linux/compiler.h>
+
+MODULE_INFO(vermagic, VERMAGIC_STRING);
+
+struct module __this_module
+__attribute__((section(".gnu.linkonce.this_module"))) = {
+ .name = KBUILD_MODNAME,
+ .init = init_module,
+#ifdef CONFIG_MODULE_UNLOAD
+ .exit = cleanup_module,
+#endif
+ .arch = MODULE_ARCH_INIT,
+};
+
+static const char __module_depends[]
+__used
+__attribute__((section(".modinfo"))) =
+"depends=";
+