me8100.c
changeset 3 fc24e3b47731
parent 0 c9b8efdb5369
child 4 a90b94337569
--- 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: 
+ */
+