Nun mit meinen ersten Änderungen.
--- /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:
+*/