# HG changeset patch # User heiko # Date 1011192898 -3600 # Node ID fc24e3b4773175316bcddfc68a703ab3ecaeafeb # Parent 3345048104fc01d06fded9cc11757e7c7bd3f3a0 Nun mit meinen ersten Änderungen. diff -r 3345048104fc -r fc24e3b47731 .cvsignore --- /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 diff -r 3345048104fc -r fc24e3b47731 .cvsrc --- 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 diff -r 3345048104fc -r fc24e3b47731 Makefile --- 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 diff -r 3345048104fc -r fc24e3b47731 README.hs --- /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... (?) diff -r 3345048104fc -r fc24e3b47731 me8100-driver --- 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} diff -r 3345048104fc -r fc24e3b47731 me8100.c --- 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 #include #include -#include +#include #include #include #include @@ -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: + */ + diff -r 3345048104fc -r fc24e3b47731 me8100.h --- 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) + diff -r 3345048104fc -r fc24e3b47731 me8100_test_dio/Makefile --- 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) diff -r 3345048104fc -r fc24e3b47731 me8100_test_dio/me8100_test_dio.c --- 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"); diff -r 3345048104fc -r fc24e3b47731 me8100_test_dio/rtest.c --- /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 +#include +#include +#include +#include + +#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: +*/ diff -r 3345048104fc -r fc24e3b47731 me8100_test_dio/wtest.c --- /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 +#include +#include +#include +#include + +#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: +*/ diff -r 3345048104fc -r fc24e3b47731 me8100_test_int/Makefile --- 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) diff -r 3345048104fc -r fc24e3b47731 me8100_test_int/me8100_test_int.c --- 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 #include -#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: + */ diff -r 3345048104fc -r fc24e3b47731 me8100_test_int/test.c --- /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 +#include +#include +#include +#include +#include +#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: +*/