Nun mit meinen ersten Änderungen. hs1r0p0
authorheiko
Wed, 16 Jan 2002 15:54:58 +0100
changeset 3 fc24e3b47731
parent 2 3345048104fc
child 4 a90b94337569
Nun mit meinen ersten Änderungen.
.cvsignore
.cvsrc
Makefile
README.hs
me8100-driver
me8100.c
me8100.h
me8100_test_dio/Makefile
me8100_test_dio/me8100_test_dio.c
me8100_test_dio/rtest.c
me8100_test_dio/wtest.c
me8100_test_int/Makefile
me8100_test_int/me8100_test_int.c
me8100_test_int/test.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.cvsignore	Wed Jan 16 15:54:58 2002 +0100
@@ -0,0 +1,6 @@
+me8100_test_counter/me8100_test_counter
+me8100_test_dio/me8100_test_dio
+me8100_test_dio/wtest
+me8100_test_dio/rtest
+me8100_test_int/me8100_test_int
+me8100_test_int/test
--- a/.cvsrc	Wed Jan 16 14:02:54 2002 +0100
+++ b/.cvsrc	Wed Jan 16 15:54:58 2002 +0100
@@ -1,1 +1,2 @@
 -z
+diff -uN
--- a/Makefile	Wed Jan 16 14:02:54 2002 +0100
+++ b/Makefile	Wed Jan 16 15:54:58 2002 +0100
@@ -6,20 +6,25 @@
 # $make test8100i  	generates the executable test8100i
 # $make clean     	deletes all files including *.o and *~ 
 
-me8100.o:me8100.c me8100.h
-	gcc -c me8100.c -Wall -O
+# KERNEL_DIR should be set in environment
+#KERNEL_DIR = /usr/src/linux
 
-test8100:test8100.o
-	gcc -o test8100 test8100.o 
+SUBDIRS = me8100_test_dio me8100_test_int
+
+CPPFLAGS += -I$(KERNEL_DIR)/include
+CFLAGS += -O -Wall
 
-test8100.o:test8100.c me8100.h
-	gcc -c test8100.c -Wall -O
+.PHONY:	all clean
+
+all:	me8100.o 
+	for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done
 
-test8100i:test8100i.o
-	gcc -o test8100i test8100i.o 
+tags:	*.c *.h
+	ctags $^
 
-test8100i.o:test8100i.c me8100.h
-	gcc -c test8100i.c -Wall -O
+# Dependencies
+me8100.o: me8100.c me8100.h
 
 clean:
-	rm -f *.o *~
\ No newline at end of file
+	rm -f *.o *~ tags
+	for d in $(SUBDIRS); do $(MAKE) -C $$d $@; done
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.hs	Wed Jan 16 15:54:58 2002 +0100
@@ -0,0 +1,19 @@
+* Der Treiber sollte "policy"-free sein, d.h., wenn mehrere Leute den Treiber
+  gleichzeitig benutzen, ist das ok.  Dann ist eben ungewiß, wer den
+  Interrupt bekommt.  
+
+  Ein Locking könnte optional gemacht werden.
+
+  Ich weiß aber nicht, ob das der richtige Weg ist.  Zum Testen aber allemal.
+
+* Gibt es einen Grund, daß die Bits für das PLX-Register LOCAL_ als Prefix haben und nicht
+  ME8100_, wie alle anderen Bits und Konstanten?
+
+* Interrupt-Test: Warum müssen die IO-Ports hochohmg geschaltet werden, wenn ich auf
+  einen Interrupt warte?
+
+* Wenn auf den Control-Port ein Wort geschrieben wurde, dann sollte man dieses Wort auch
+  ruhig zurücklesen können.  (Notfalls im Treiber speichern.)
+
+* read(): Beim ersten Lesen den aktuellen Zustand, und dann blockieren, bis 
+  Interrupt kommt und weiterlesen... (?)
--- a/me8100-driver	Wed Jan 16 14:02:54 2002 +0100
+++ b/me8100-driver	Wed Jan 16 15:54:58 2002 +0100
@@ -21,7 +21,7 @@
 	echo -n "Starting me8100 driver "
 	/sbin/insmod -f $module.o || return=$rc_failed
 	rm -f /dev/${device}
-	rm -f /dev/${device}_[0-3]
+	rm -f /dev/${device}_[0-3]*
 	major=`cat /proc/devices | awk "\\$2==\"$module\" {print \\$1}"`
 
 	echo -n "with major number $major"
@@ -31,6 +31,14 @@
 	mknod /dev/${device}_1 c $major 1
 	mknod /dev/${device}_2 c $major 2
 	mknod /dev/${device}_3 c $major 3
+
+	mknod /dev/${device}_0a c $major 16		# Port A
+	mknod /dev/${device}_0b c $major 32		# Port B
+	mknod /dev/${device}_0c c $major 64		# Counter
+
+	mknod /dev/${device}_1a c $major 17
+	mknod /dev/${device}_1b c $major 33
+	mknod /dev/${device}_1c c $major 65
 	
 	# Set a default link to the first dev
 	ln -s /dev/${device}_0 /dev/${device}
--- a/me8100.c	Wed Jan 16 14:02:54 2002 +0100
+++ b/me8100.c	Wed Jan 16 15:54:58 2002 +0100
@@ -89,7 +89,7 @@
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -133,6 +133,7 @@
 			unsigned int , unsigned long ); 
 static int me8100_fasync(int, struct file *, int);
 static void me8100_isr(int, void *, struct pt_regs *);
+static ssize_t me8100_read(struct file *, char *, size_t, loff_t *);
 
 static int me8100_init_board(me8100_info_type *, struct pci_dev *);
 static int me8100_reset_board(me8100_info_type *);
@@ -171,31 +172,31 @@
 static int me8100_get_board_info(me8100_info_type *, me8100_info_type *);
 static int me8100_get_int_count(me8100_int_occur_type *, me8100_info_type *);
 
+static inline int DEVICE(int i) { return MINOR(i) & 0x0f; }
+static inline int SUBDEVICE(int i) { return MINOR(i) >> 4; }
+
 
 /* File operations provided by the driver */
 static struct file_operations me8100_file_operations = {
 #ifdef LINUX_24
-  THIS_MODULE,	        /* owner               */
+  owner:    THIS_MODULE,        /* owner               */
 #endif
-  NULL,		        /* lseek()             */
-  NULL,   		/* read()              */
-  NULL,    		/* write()             */
-  NULL,		        /* readdir()           */
-  NULL,		        /* poll()              */
-  me8100_ioctl,         /* ioctl()             */
-  NULL,   		/* mmap()              */
-  me8100_open,          /* open()              */
-  NULL,                 /* flush()             */
-  me8100_release,       /* release()           */
-  NULL,		        /* fsync()             */
-  me8100_fasync,        /* fasync()            */
-  NULL,		        /* check_media_change()*/
-  NULL,		        /* revalidate()        */
-  NULL                  /* lock()              */
+  llseek:   NULL,	        /* lseek()             */
+  read:	    me8100_read, 	/* read()              */
+  write:    NULL,    		/* write()             */
+  readdir:  NULL,	        /* readdir()           */
+  poll:	    NULL,	        /* poll()              */
+  ioctl:    me8100_ioctl,       /* ioctl()             */
+  mmap:	    NULL,   		/* mmap()              */
+  open:	    me8100_open,        /* open()              */
+  flush:    NULL,               /* flush()             */
+  release:  me8100_release,     /* release()           */
+  fsync:    NULL,		/* fsync()             */
+  fasync:   me8100_fasync,      /* fasync()            */
+  lock:	    NULL                /* lock()              */
 };
 
 
-
 /*
  * Routine:                                                                 
  *   init_module                                                               
@@ -206,6 +207,7 @@
  *     - Searches for PCI hardware.
  *     - Initializes detected ME8100 boards with me8100_init_board().
  *     - Installs the driver in the system with register_chrdev().
+ *     - Installs the me8100_isr(). //.hs
  *                                                                          
  * Parameter list:                                                          
  *   Name           Type          Access             Description            
@@ -474,6 +476,7 @@
   info->int1 = 0;
   info->int2 = 0;
   info->file_ptr = NULL;
+  info->fasync_ptr = NULL;
   info->board_in_use = 0;
   spin_lock_init(&info->use_lock);
 
@@ -486,6 +489,13 @@
     return result;
   }
 
+  result = request_irq(info->int_line,
+      me8100_isr, SA_INTERRUPT | SA_SHIRQ,
+      ME8100_NAME, (void *) info);
+  if(result){
+    printk(KERN_ERR"ME8100:me8100_open():Can't get interrupt line");
+    return result;
+  }
   return 0;
 }
 
@@ -543,8 +553,6 @@
  *   Function, which is executed, when a userprogramm makes the syscall     
  *   open. 
  *   Actions performed:
- *     - It installs the drivers interrupt service routine 
- *       me8100_isr in the system.
  *     - It remarks the board as used in the global data structure.
  *                                                                          
  * Parameter list:
@@ -565,37 +573,29 @@
  */
 static int me8100_open(struct inode *inode_ptr, struct file *file_ptr){
   int minor = 0;
-  int err = 0;
+  me8100_info_type *info;
+
+  PDEBUG("*** me8100_open() is executed for pid: %d\n", file_ptr->f_owner.pid);
 
-  PDEBUG("me8100_open() is executed\n");
+  minor = DEVICE(inode_ptr->i_rdev);
 
-  minor = MINOR(inode_ptr->i_rdev);
+  PDEBUG("*** device: %d, subdevice %d\n", DEVICE(inode_ptr->i_rdev),
+      SUBDEVICE(inode_ptr->i_rdev));
 
   if(minor >= me8100_board_count){
     printk(KERN_ERR"ME8100:me8100_open():Board %d doesn't exist\n", minor);
     return -ENODEV;
   }
-
-  spin_lock(&info_vec[minor].use_lock);
-  if(info_vec[minor].board_in_use){
-    printk(KERN_ERR"ME8100:me8100_open():Board %d already in use\n", minor);
-    spin_unlock(&info_vec[minor].use_lock);
-    return -EBUSY;
-  }
-  info_vec[minor].board_in_use = 1;
-  spin_unlock(&info_vec[minor].use_lock);
+  info = &info_vec[minor];
 
-  info_vec[minor].file_ptr = file_ptr;
+  spin_lock(&info->use_lock);
+  if(info->board_in_use){
+    printk(KERN_ERR "WARNING: ME8100:me8100_open():Board %d already in use\n", minor);
+  }
+  ++info->board_in_use;
+  spin_unlock(&info->use_lock);
 
-  err = request_irq(info_vec[minor].int_line,
-		    me8100_isr,
-		    SA_INTERRUPT | SA_SHIRQ,
-		    ME8100_NAME,
-		    (void *)&info_vec[minor]);
-  if(err){
-    printk(KERN_ERR"ME8100:me8100_open():Can't get interrupt line");
-    return err;
-  }
+  /* info->file_ptr = file_ptr; */  /* müssen wir uns nicht hier merken! */
 
   MOD_INC_USE_COUNT;
 
@@ -631,25 +631,26 @@
  * Modification:                                                            
  */
 static int me8100_release(struct inode *inode_ptr, struct file *file_ptr){
-  int minor = 0;
-  int err   = 0;
+  int minor;
+  int err;
+  me8100_info_type *info;
+
   
   PDEBUG("me8100_release() is executed\n");
 
-  minor = MINOR(inode_ptr->i_rdev);
+  minor = DEVICE(inode_ptr->i_rdev);
+  info = &info_vec[minor];
+
+  /* resetting the board on last close */
 
-  err = me8100_reset_board(&info_vec[minor]);
-  if(err){
-    printk(KERN_ERR"ME8100:me8100_release():Can't reset");
-    return err;
+  if (--info->board_in_use == 0) {
+    err = me8100_reset_board(info);
+    if(err){
+      printk(KERN_ERR"ME8100:me8100_release():Can't reset");
+      return err;
+    }
   }
-
-  free_irq(info_vec[minor].int_line, (void *) &info_vec[minor]);
-
-  /* Delete the fasync structure and free memory */
-  me8100_fasync(0, file_ptr, 0);
-
-  info_vec[minor].board_in_use = 0;
+  me8100_fasync(-1, file_ptr, 0);
 
   MOD_DEC_USE_COUNT;
   PDEBUG("me8100_release() is leaved\n");
@@ -697,7 +698,7 @@
 
   PDEBUG("me8100_ioctl() is executed\n");
 
-  minor = MINOR(inode_ptr->i_rdev);      
+  minor = DEVICE(inode_ptr->i_rdev);      
 
   if(_IOC_TYPE(service) != ME8100_MAGIC){
     printk(KERN_ERR"ME8100:Invalid ME8100_MAGIC\n");
@@ -805,21 +806,22 @@
  * Modufication:                                                            
  */
 static int me8100_fasync(int fd, struct file *file_ptr, int mode){
-  int val = 0;
-  struct fasync_struct *fasync_ptr;
+  int val;
+  int minor;
+  me8100_info_type *info;
 
-  fasync_ptr = file_ptr->private_data;
+  minor = DEVICE(file_ptr->f_dentry->d_inode->i_rdev);
+  info = &info_vec[minor];
 
   PDEBUG("me8100_fasync() is executed\n");
- 
-  val = fasync_helper(fd, file_ptr, mode, &fasync_ptr);
-  file_ptr->private_data = fasync_ptr;
+  PDEBUG("** fasync_ptr: %p\n", info->fasync_ptr);
+  val = fasync_helper(fd, file_ptr, mode, &info->fasync_ptr);
+  PDEBUG("** fasync_ptr: %p\n", info->fasync_ptr);
   return val;
 }
 
 
 
-
 /*
  * Routine:                                                                 
  *   me8100_get_board_info                                                  
@@ -1999,49 +2001,47 @@
  * Modification:                                                            
  */
 static void me8100_isr(int irq, void *dev_id, struct pt_regs *regs){
-  unsigned char icsr = 0;
-  unsigned short dummy = 0;
-  me8100_info_type *board_context;
-  struct fasync_struct *fasync_ptr;
+  unsigned char icsr;
+  unsigned short dummy;
+  me8100_info_type *info;
 
   PDEBUG("me8100_isr() is executed\n");
 
-  board_context = (me8100_info_type *) dev_id;
+  info = (me8100_info_type *) dev_id;
 
-  fasync_ptr = board_context->file_ptr->private_data;
-
-  if(irq != board_context->int_line){
+  if(irq != info->int_line){
     PDEBUG("me8100_isr():incorrect interrupt num: %d\n", irq);
     return;
   }
 
-  board_context->int1 = 0;
-  board_context->int2 = 0;
+  info->int1 = 0;
+  info->int2 = 0;
 
-  icsr = inb(board_context->plx_regbase + PLX_ICSR);
+  icsr = inb(info->plx_regbase + PLX_ICSR);
 
   if((icsr & 0x04)&&(icsr & 0x40)&&(icsr & 0x01)){
     PDEBUG("me8100_isr():Int1 occured\n");
-    board_context->int1 = 1;
-    board_context->int_count_1++;
-    dummy = inw(board_context->me8100_regbase + ME8100_RES_INT_REG_A); 
+    info->int1 = 1;
+    info->int_count_1++;
+    dummy = inw(info->me8100_regbase + ME8100_RES_INT_REG_A); 
   }
 
   if((icsr & 0x20)&&(icsr & 0x40)&&(icsr & 0x08)){
     PDEBUG("me8100_isr():Int2 occured\n");
-    board_context->int2 = 1;
-    board_context->int_count_2++;
-    dummy = inw(board_context->me8100_regbase + ME8100_RES_INT_REG_B); 
+    info->int2 = 1;
+    info->int_count_2++;
+    dummy = inw(info->me8100_regbase + ME8100_RES_INT_REG_B); 
   }
 
-  if(!(board_context->int1 || board_context->int2)){
+  if(!(info->int1 || info->int2)){
     PDEBUG("me8100_isr():Not this Board\n");
     return;
   }
 
-  if(fasync_ptr){
-    PDEBUG("me8100_isr():send signal to process\n");
-    kill_fasync(&fasync_ptr, SIGIO, POLL_IN);
+  if(info->fasync_ptr){
+    PDEBUG("*** me8100_isr():send signal to process %p->%d\n", 
+      info->fasync_ptr, info->fasync_ptr->fa_file->f_owner.pid);
+    kill_fasync(&info->fasync_ptr, SIGIO, POLL_IN);
   }
 } 
 
@@ -2067,9 +2067,15 @@
  */
 void cleanup_module(void){
   extern unsigned int major;
+  int minor;
   int err;
 
+
   PDEBUG("cleanup_module() is executed\n");
+
+  for (minor = me8100_board_count - 1; minor > -1; --minor) {
+    free_irq(info_vec[minor].int_line, (void *) &info_vec[minor]);
+  }
   
   if(major){
     err = unregister_chrdev(major, ME8100_NAME);
@@ -2077,3 +2083,13 @@
       printk(KERN_WARNING"ME8100:cleanup_module():cannot unregister major\n");
   }
 }
+
+ssize_t me8100_read(struct file * file_ptr, char *buffer, size_t len, loff_t *offset) {
+  PDEBUG("me8100_read() called\n");
+  return -EINVAL;
+}
+
+/* 
+  vim:sts=2 sw=2 aw ai sm: 
+ */
+
--- a/me8100.h	Wed Jan 16 14:02:54 2002 +0100
+++ b/me8100.h	Wed Jan 16 15:54:58 2002 +0100
@@ -47,11 +47,12 @@
 
 /* Please define this to enable debug mode */
 #undef ME8100_DEBUG
+#define ME8100_DEBUG
 
 #undef PDEBUG // only to be sure
 
 #ifdef ME8100_DEBUG
-# define PDEBUG(fmt, args...) printk(KERN_DEBUG"ME8100:" fmt, ##args)
+# define PDEBUG(fmt, args...) printk(KERN_DEBUG"ME8100: %d " fmt, current->pid, ##args)
 #else 
 # define PDEBUG(fmt, args...) // no debugging, do nothing
 #endif
@@ -101,10 +102,38 @@
 // Bit 6   INTB 0      ISA has here INTB 1
 // Bit 7   ENIO        1 = Enable  0 = high resistance
 // Bit 8-15 dont care
+// +---------------------------------------+
+// | 15 | 14 | 13 | 12 | 11 | 10 |  9 |  8 |
+// +---------------------------------------+
+// |    |    |    |    |    |    |    |    |
+// +---------------------------------------+
+//
+// +---------------------------------------+
+// |  7 |  6 |  5 |  4 |  3 |  2 |  1 |  0 |
+// +---------------------------------------+
+// |ENIO|INTB|INTB|SRC/|    |    |    |    |
+// |    |   0|   1|SINK|    |    |    |    |
+// +---------------------------------------+
+//   |     |    |   `-- 0  SINK
+//   |     |    |       1  SOURCE
+//   |     `----`------ 00 INT off
+//   |                  01 INT on pattern
+//   |                  10 INT on masked change
+//   |                  11 INT off
+//   `----------------- 0  IO enable
+//                      1  IO disable (high resistance)
 /*********************************************************/
 /* The ME8100_ID_REG_X contains on PCI boards static 81h */
 /*********************************************************/
 
+/* Some definitions to be written to the CTRL register */
+#define ME8100_CTL_ENIO		0x80
+#define ME8100_CTL_SOURCE	0x10
+#define ME8100_CTL_SINK		0x00
+
+#define ME8100_CTL_IRQ_PATTERN	0x40
+#define ME8100_CTL_IRQ_MASK	0x60
+
 /* ME8100 Register Set A */
 #define ME8100_ID_REG_A			0x00      //(r, )
 #define ME8100_CTRL_REG_A		0x00      //( ,w)
@@ -114,6 +143,7 @@
 #define ME8100_PATTERN_REG_A		0x08      //( ,w)
 #define ME8100_MASK_REG_A		0x0A      //( ,w)
 #define ME8100_INT_DI_REG_A		0x0A      //(r, )
+
 									
 /* ME8100 Register Set B */		
 #define ME8100_ID_REG_B			0x0C      //(r, )
@@ -155,6 +185,7 @@
   int int2;
 } me8100_int_occur_type;
 
+#ifdef __KERNEL__
 
 typedef struct{
   int board_count;                  /* index of the board after detection    */
@@ -178,8 +209,10 @@
   int board_in_use;                 /* Indicates if board is already in use  */
   spinlock_t use_lock;              /* Guards board in use                   */
   struct file *file_ptr;            /* Pointer to file structure of path     */
+  struct fasync_struct *fasync_ptr; /* .hs */
 } me8100_info_type;
 
+#endif	/* __KERNEL__ */
 
 /* ME8100 IOCTL's */
 #define ME8100_IOCTL_MAXNR 29
@@ -217,3 +250,4 @@
 #define ME8100_READ_ICSR        _IOR(ME8100_MAGIC, 27, unsigned char)
 #define ME8100_GET_BOARD_INFO   _IOR(ME8100_MAGIC, 28, me8100_info_type)
 #define ME8100_GET_INT_COUNT    _IOR(ME8100_MAGIC, 29, me8100_int_occur_type)
+
--- a/me8100_test_dio/Makefile	Wed Jan 16 14:02:54 2002 +0100
+++ b/me8100_test_dio/Makefile	Wed Jan 16 15:54:58 2002 +0100
@@ -5,11 +5,20 @@
 # $make 	  generates the executable me8100_test_dio
 # $make clean     deletes all files including *.o and *~ 
 
-me8100_test_dio:me8100_test_dio.o
-	gcc -o me8100_test_dio me8100_test_dio.o 
+# KERNEL_DIR should be set in environment.
+CPPFLAGS += -I.. -I$(KERNEL_DIR)/include
+CFLAGS += -Wall -O
+
+bin_PROGRAMS = me8100_test_dio wtest rtest
 
-me8100_test_dio.o:me8100_test_dio.c ../me8100.h
-	gcc -c me8100_test_dio.c -Wall -O
+.PHONY:	all clean
+
+all: $(bin_PROGRAMS)
+
+# Dependencies
+me8100_test_dio.o: me8100_test_dio.c ../me8100.h
+rtest.o: rtest.c ../me8100.h 
+wtest.o: rtest.c ../me8100.h
 
 clean:
-	rm -f *.o *~
\ No newline at end of file
+	rm -f core *.o *~ $(bin_PROGRAMS)
--- a/me8100_test_dio/me8100_test_dio.c	Wed Jan 16 14:02:54 2002 +0100
+++ b/me8100_test_dio/me8100_test_dio.c	Wed Jan 16 15:54:58 2002 +0100
@@ -171,7 +171,6 @@
     sleep(1);
   }
 
-
   /*--------------------------- READ FROM BOTH INPUT PORTS -----------------------*/
 
   printf("Please press return to read from both input ports :\n");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/me8100_test_dio/rtest.c	Wed Jan 16 15:54:58 2002 +0100
@@ -0,0 +1,56 @@
+/*
+ * Source File : me8100_test_dio.c
+ * Destination : me8100_test_dio
+ * Author      : GG (Guenter Gebhardt)                                 
+ *    
+ *                                                                     
+ * File History: Version   Date       Editor   Action                  
+ *---------------------------------------------------------------------
+ *               1.00.00   01.07.12   GG       first release           
+ *                                                                     
+ *---------------------------------------------------------------------
+ *                                                                     
+ * Description:
+ *   This program shows the use of the driver and the digital inputs
+ *   and outputs. First the outputs are tested in sink and source mode. 
+ *   Then the inputs are tested.
+ */
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+
+#include "me8100.h"
+
+int main(void){
+  int err = 0;
+  static int file_handle = -1;
+
+  unsigned short value_a;
+
+  printf("Read test, PID: %d\n", getpid());
+  file_handle = open("/dev/me8100_0", O_RDWR, 0);
+
+  if(file_handle < 0){
+    printf("Cannot open path !\n");
+    return 1;
+  }
+
+  for (;;) {
+    ioctl(file_handle, ME8100_READ_DI_A, &value_a);
+    printf("Read  %04x\n", value_a);
+    sleep(1);
+  }
+
+  err = close(file_handle);
+  if(err){
+    printf("Kann Pfad nicht schliessen\n");
+    return 1;
+  }
+
+  return 0;
+}
+/*
+	vim:sts=2 sw=2 aw ai sm:
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/me8100_test_dio/wtest.c	Wed Jan 16 15:54:58 2002 +0100
@@ -0,0 +1,69 @@
+/*
+ * Source File : me8100_test_dio.c
+ * Destination : me8100_test_dio
+ * Author      : GG (Guenter Gebhardt)                                 
+ *    
+ *                                                                     
+ * File History: Version   Date       Editor   Action                  
+ *---------------------------------------------------------------------
+ *               1.00.00   01.07.12   GG       first release           
+ *                                                                     
+ *---------------------------------------------------------------------
+ *                                                                     
+ * Description:
+ *   This program shows the use of the driver and the digital inputs
+ *   and outputs. First the outputs are tested in sink and source mode. 
+ *   Then the inputs are tested.
+ */
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+
+#include "me8100.h"
+
+int main(void){
+  int err = 0;
+  static int file_handle = -1;
+
+  unsigned short ctrl_a;
+  unsigned short value_a;
+
+  printf("Write test, PID: %d\n", getpid());
+  file_handle = open("/dev/me8100_0", O_RDWR, 0);
+
+  if(file_handle < 0){
+    printf("Cannot open path !\n");
+    return 1;
+  }
+
+  /* Write.
+   * HACK: The driver itself should remember the status
+   * of the IRQ bits in its control register
+   */
+  ctrl_a = ME8100_CTL_ENIO | ME8100_CTL_SOURCE | ME8100_CTL_IRQ_MASK;
+  err = ioctl(file_handle, ME8100_WRITE_CTRL_A, &ctrl_a);
+  if (err) {
+    fprintf(stderr, "Can't setup output to port A\n");
+    return 1;
+  }
+
+  value_a = 0x00;
+  for (value_a = 0x00; value_a < 0xffff; ++value_a) {
+    ioctl(file_handle, ME8100_WRITE_DO_A, &value_a);
+    printf("Wrote %04x\n", value_a);
+    sleep(3);
+  }
+
+  err = close(file_handle);
+  if(err){
+    printf("Kann Pfad nicht schliessen\n");
+    return 1;
+  }
+
+  return 0;
+}
+/*
+	vim:sts=2 sw=2 aw ai sm:
+*/
--- a/me8100_test_int/Makefile	Wed Jan 16 14:02:54 2002 +0100
+++ b/me8100_test_int/Makefile	Wed Jan 16 15:54:58 2002 +0100
@@ -5,11 +5,18 @@
 # $make 	  generates the executable me8100_test_int
 # $make clean     deletes all files including *.o and *~ 
 
-me8100_test_int:me8100_test_int.o
-	gcc -o me8100_test_int me8100_test_int.o 
+# KERNEL_DIR should be set in environment
+CPPFLAGS += -I.. -I$(KERNEL_DIR)/include
+CFLAGS += -O -Wall
+
+bin_PROGRAMS = me8100_test_int test
 
-me8100_test_int.o:me8100_test_int.c ../me8100.h
-	gcc -c me8100_test_int.c -Wall -O
+.PHONY:	all clean
+
+all:	$(bin_PROGRAMS)
+
+me8100_test_int.o: me8100_test_int.c ../me8100.h
+test.o:	test.c ../me8100.h
 
 clean:
-	rm -f *.o *~
\ No newline at end of file
+	rm -f core *.o *~ $(bin_PROGRAMS)
--- a/me8100_test_int/me8100_test_int.c	Wed Jan 16 14:02:54 2002 +0100
+++ b/me8100_test_int/me8100_test_int.c	Wed Jan 16 15:54:58 2002 +0100
@@ -27,7 +27,7 @@
 #include <signal.h>
 #include <linux/spinlock.h>
 
-#include "../me8100.h"
+#include "me8100.h"
 
 /* Prototypes */
 static void signal_handler(int);
@@ -230,3 +230,7 @@
 	 "int_count_2 = %04d\n\n", i, intcounts.int1, intcounts.int2);
   return;
 }
+
+/*
+ * vim:sts=2 sw=2 aw ai sm:
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/me8100_test_int/test.c	Wed Jan 16 15:54:58 2002 +0100
@@ -0,0 +1,141 @@
+/*
+ * Source File : me8100_test_int.c                                            
+ * Destination : me8100_test_int.out                                              
+ * Author      : GG (Guenter Gebhardt)                                 
+ *    
+ *                                                                     
+ * File History: Version   Date       Editor   Action                  
+ *---------------------------------------------------------------------
+ *               1.00.00   01.07.12   GG       first release           
+ *                                                                     
+ *---------------------------------------------------------------------
+ *                                                                     
+ * Description:
+ *   This program shows the usage of the driver and the interrupt
+ *   facility of the me8100. First the board is configured, in order to
+ *   generate an interrupt when a bit pattern of 0x0001 on port a and a bit
+ *   pattern of 0x0100 an port b is pending. Then the board is configured, 
+ *   in order to generate an interrupt with a bit mask of 0x0001 on port a 
+ *   and a bit mask of 0x0100 on port b. 
+ *   We install a signal handler, which is informed by the interrupt routine 
+ *   by signalling of the driver, when a interrupt occures.
+ */
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <stdlib.h>
+#include "me8100.h"
+
+
+/* Prototypes */
+static void signal_handler(int);
+
+/* Counts the interrupts */
+static me8100_int_occur_type intcounts;
+
+/* Count of signal handler execution */
+static int i = 0;
+
+/* Path to the ME8100 board */
+static int file_handle = -1;
+
+int main(void){
+  int err = 0;
+  int oflags = 0;
+
+  unsigned short mask_a;
+  unsigned short ctrl_a;
+
+  unsigned char icsr;
+
+  printf("IRQ Test %d\n", getpid());
+
+  file_handle = open("/dev/me8100_0", O_RDWR, 0);
+
+  if(file_handle < 0){
+    printf("Cannot open path !\n");
+    return 1;
+  }
+
+  /*---------------------- general setup ------------------------------------*/
+
+  /* install the signal handler */
+  signal(SIGIO, signal_handler);
+
+  /* set current process as owner of the path */
+  fcntl(file_handle, F_SETOWN, getpid());
+
+  /* read the flags of the path */
+  oflags = fcntl(file_handle, F_GETFL);
+
+  /* Inform the driver to put the current process on the fasync queue */
+  fcntl(file_handle, F_SETFL, oflags | FASYNC); 
+
+  /* enable both interrupts on the plx, set interrupts to high active */
+  icsr =
+    LOCAL_INT1_EN |
+    LOCAL_INT1_POL |
+    PCI_INT_EN;
+
+  err = ioctl(file_handle, ME8100_SETUP_ICSR, &icsr);
+  if(err){
+    printf("Cannot setup PLX\n");
+    return 1;
+  }
+
+  /*-------------------- Interrupt caused by bit mask -----------------*/
+
+  /* Set the proper bit mask for port a */
+  mask_a = 0xffff;
+  err = ioctl(file_handle, ME8100_WRITE_MASK_A, &mask_a);
+  if(err){
+    printf("Cannot write mask a\n");
+    return 1;
+  }
+
+  /* Enable interrupt signalling by bit mask for port a */
+  ctrl_a = ME8100_CTL_ENIO | ME8100_CTL_SOURCE | ME8100_CTL_IRQ_MASK;
+  err = ioctl(file_handle, ME8100_WRITE_CTRL_A, &ctrl_a);
+  if(err){
+    printf("Cannot write ctrl a\n");
+    return 1;
+  }
+
+  printf("<<<--- WAITING FOR INTERRUPTS BY BIT MASK --->>>\n\n");
+
+  i = 0;
+  while(i < 10) {
+    select(0, NULL, NULL, NULL, NULL);
+  }
+
+  printf("Close path to me8100_0\n");
+  err = close(file_handle);
+  if(err){
+    printf("Kann Pfad nicht schliessen\n");
+    return 1;
+  }
+
+  return 1;
+}
+
+
+
+void signal_handler(int sig){
+  int err = 0;
+  i++;
+  err = ioctl(file_handle, ME8100_GET_INT_COUNT, &intcounts);
+  if(err)
+    return;
+
+  fprintf(stderr, "<<<--- ME8100 SIGNAL HANDLER CALLED --->>>\n"
+	 "Execution   = %04d\n"
+	 "int_count_1 = %04d\n"
+	 "int_count_2 = %04d\n\n", i, intcounts.int1, intcounts.int2);
+  return;
+}
+
+/*
+	vim:sts=2 sw=2 aw ai sm:
+*/