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