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: + */ +