me8100.c
changeset 3 fc24e3b47731
parent 0 c9b8efdb5369
child 4 a90b94337569
equal deleted inserted replaced
2:3345048104fc 3:fc24e3b47731
    87 
    87 
    88 #include <linux/fs.h>
    88 #include <linux/fs.h>
    89 #include <linux/sched.h>
    89 #include <linux/sched.h>
    90 #include <linux/interrupt.h>
    90 #include <linux/interrupt.h>
    91 #include <linux/pci.h>
    91 #include <linux/pci.h>
    92 #include <linux/malloc.h>
    92 #include <linux/slab.h>
    93 #include <asm/io.h>
    93 #include <asm/io.h>
    94 #include <asm/system.h>
    94 #include <asm/system.h>
    95 #include <asm/uaccess.h>
    95 #include <asm/uaccess.h>
    96 #include <linux/errno.h>
    96 #include <linux/errno.h>
    97 #include <linux/delay.h>
    97 #include <linux/delay.h>
   131 static int me8100_release(struct inode *, struct file *);
   131 static int me8100_release(struct inode *, struct file *);
   132 static int me8100_ioctl(struct inode *, struct file *, 
   132 static int me8100_ioctl(struct inode *, struct file *, 
   133 			unsigned int , unsigned long ); 
   133 			unsigned int , unsigned long ); 
   134 static int me8100_fasync(int, struct file *, int);
   134 static int me8100_fasync(int, struct file *, int);
   135 static void me8100_isr(int, void *, struct pt_regs *);
   135 static void me8100_isr(int, void *, struct pt_regs *);
       
   136 static ssize_t me8100_read(struct file *, char *, size_t, loff_t *);
   136 
   137 
   137 static int me8100_init_board(me8100_info_type *, struct pci_dev *);
   138 static int me8100_init_board(me8100_info_type *, struct pci_dev *);
   138 static int me8100_reset_board(me8100_info_type *);
   139 static int me8100_reset_board(me8100_info_type *);
   139 
   140 
   140 static int me8100_read_id_a(unsigned short *, me8100_info_type *);
   141 static int me8100_read_id_a(unsigned short *, me8100_info_type *);
   169 static int me8100_setup_icsr(unsigned char *, me8100_info_type *);
   170 static int me8100_setup_icsr(unsigned char *, me8100_info_type *);
   170 static int me8100_read_icsr(unsigned char *, me8100_info_type *);
   171 static int me8100_read_icsr(unsigned char *, me8100_info_type *);
   171 static int me8100_get_board_info(me8100_info_type *, me8100_info_type *);
   172 static int me8100_get_board_info(me8100_info_type *, me8100_info_type *);
   172 static int me8100_get_int_count(me8100_int_occur_type *, me8100_info_type *);
   173 static int me8100_get_int_count(me8100_int_occur_type *, me8100_info_type *);
   173 
   174 
       
   175 static inline int DEVICE(int i) { return MINOR(i) & 0x0f; }
       
   176 static inline int SUBDEVICE(int i) { return MINOR(i) >> 4; }
       
   177 
   174 
   178 
   175 /* File operations provided by the driver */
   179 /* File operations provided by the driver */
   176 static struct file_operations me8100_file_operations = {
   180 static struct file_operations me8100_file_operations = {
   177 #ifdef LINUX_24
   181 #ifdef LINUX_24
   178   THIS_MODULE,	        /* owner               */
   182   owner:    THIS_MODULE,        /* owner               */
   179 #endif
   183 #endif
   180   NULL,		        /* lseek()             */
   184   llseek:   NULL,	        /* lseek()             */
   181   NULL,   		/* read()              */
   185   read:	    me8100_read, 	/* read()              */
   182   NULL,    		/* write()             */
   186   write:    NULL,    		/* write()             */
   183   NULL,		        /* readdir()           */
   187   readdir:  NULL,	        /* readdir()           */
   184   NULL,		        /* poll()              */
   188   poll:	    NULL,	        /* poll()              */
   185   me8100_ioctl,         /* ioctl()             */
   189   ioctl:    me8100_ioctl,       /* ioctl()             */
   186   NULL,   		/* mmap()              */
   190   mmap:	    NULL,   		/* mmap()              */
   187   me8100_open,          /* open()              */
   191   open:	    me8100_open,        /* open()              */
   188   NULL,                 /* flush()             */
   192   flush:    NULL,               /* flush()             */
   189   me8100_release,       /* release()           */
   193   release:  me8100_release,     /* release()           */
   190   NULL,		        /* fsync()             */
   194   fsync:    NULL,		/* fsync()             */
   191   me8100_fasync,        /* fasync()            */
   195   fasync:   me8100_fasync,      /* fasync()            */
   192   NULL,		        /* check_media_change()*/
   196   lock:	    NULL                /* lock()              */
   193   NULL,		        /* revalidate()        */
       
   194   NULL                  /* lock()              */
       
   195 };
   197 };
   196 
       
   197 
   198 
   198 
   199 
   199 /*
   200 /*
   200  * Routine:                                                                 
   201  * Routine:                                                                 
   201  *   init_module                                                               
   202  *   init_module                                                               
   204  *   This function is executed from the system, when the driver is loaded.
   205  *   This function is executed from the system, when the driver is loaded.
   205  *   Actions performed:
   206  *   Actions performed:
   206  *     - Searches for PCI hardware.
   207  *     - Searches for PCI hardware.
   207  *     - Initializes detected ME8100 boards with me8100_init_board().
   208  *     - Initializes detected ME8100 boards with me8100_init_board().
   208  *     - Installs the driver in the system with register_chrdev().
   209  *     - Installs the driver in the system with register_chrdev().
       
   210  *     - Installs the me8100_isr(). //.hs
   209  *                                                                          
   211  *                                                                          
   210  * Parameter list:                                                          
   212  * Parameter list:                                                          
   211  *   Name           Type          Access             Description            
   213  *   Name           Type          Access             Description            
   212  *--------------------------------------------------------------------------
   214  *--------------------------------------------------------------------------
   213  *
   215  *
   472   info->int_count_1 = 0;
   474   info->int_count_1 = 0;
   473   info->int_count_2 = 0;
   475   info->int_count_2 = 0;
   474   info->int1 = 0;
   476   info->int1 = 0;
   475   info->int2 = 0;
   477   info->int2 = 0;
   476   info->file_ptr = NULL;
   478   info->file_ptr = NULL;
       
   479   info->fasync_ptr = NULL;
   477   info->board_in_use = 0;
   480   info->board_in_use = 0;
   478   spin_lock_init(&info->use_lock);
   481   spin_lock_init(&info->use_lock);
   479 
   482 
   480   
   483   
   481   /*--------------------------- Reset the board -----------------------------*/
   484   /*--------------------------- Reset the board -----------------------------*/
   484   if(result){
   487   if(result){
   485     printk(KERN_ERR"ME8100:me8100_init_board():Can't reset board\n");
   488     printk(KERN_ERR"ME8100:me8100_init_board():Can't reset board\n");
   486     return result;
   489     return result;
   487   }
   490   }
   488 
   491 
       
   492   result = request_irq(info->int_line,
       
   493       me8100_isr, SA_INTERRUPT | SA_SHIRQ,
       
   494       ME8100_NAME, (void *) info);
       
   495   if(result){
       
   496     printk(KERN_ERR"ME8100:me8100_open():Can't get interrupt line");
       
   497     return result;
       
   498   }
   489   return 0;
   499   return 0;
   490 }
   500 }
   491 
   501 
   492 
   502 
   493 
   503 
   541  *                                                                          
   551  *                                                                          
   542  * Description:                                                             
   552  * Description:                                                             
   543  *   Function, which is executed, when a userprogramm makes the syscall     
   553  *   Function, which is executed, when a userprogramm makes the syscall     
   544  *   open. 
   554  *   open. 
   545  *   Actions performed:
   555  *   Actions performed:
   546  *     - It installs the drivers interrupt service routine 
       
   547  *       me8100_isr in the system.
       
   548  *     - It remarks the board as used in the global data structure.
   556  *     - It remarks the board as used in the global data structure.
   549  *                                                                          
   557  *                                                                          
   550  * Parameter list:
   558  * Parameter list:
   551  *   Name       Type             Access    Description
   559  *   Name       Type             Access    Description
   552  *--------------------------------------------------------------------------
   560  *--------------------------------------------------------------------------
   563  *   01.10.04  Guard board_in_use with spin_lock, cause of race condition
   571  *   01.10.04  Guard board_in_use with spin_lock, cause of race condition
   564  *             when compiling for SMP.
   572  *             when compiling for SMP.
   565  */
   573  */
   566 static int me8100_open(struct inode *inode_ptr, struct file *file_ptr){
   574 static int me8100_open(struct inode *inode_ptr, struct file *file_ptr){
   567   int minor = 0;
   575   int minor = 0;
   568   int err = 0;
   576   me8100_info_type *info;
   569 
   577 
   570   PDEBUG("me8100_open() is executed\n");
   578   PDEBUG("*** me8100_open() is executed for pid: %d\n", file_ptr->f_owner.pid);
   571 
   579 
   572   minor = MINOR(inode_ptr->i_rdev);
   580   minor = DEVICE(inode_ptr->i_rdev);
       
   581 
       
   582   PDEBUG("*** device: %d, subdevice %d\n", DEVICE(inode_ptr->i_rdev),
       
   583       SUBDEVICE(inode_ptr->i_rdev));
   573 
   584 
   574   if(minor >= me8100_board_count){
   585   if(minor >= me8100_board_count){
   575     printk(KERN_ERR"ME8100:me8100_open():Board %d doesn't exist\n", minor);
   586     printk(KERN_ERR"ME8100:me8100_open():Board %d doesn't exist\n", minor);
   576     return -ENODEV;
   587     return -ENODEV;
   577   }
   588   }
   578 
   589   info = &info_vec[minor];
   579   spin_lock(&info_vec[minor].use_lock);
   590 
   580   if(info_vec[minor].board_in_use){
   591   spin_lock(&info->use_lock);
   581     printk(KERN_ERR"ME8100:me8100_open():Board %d already in use\n", minor);
   592   if(info->board_in_use){
   582     spin_unlock(&info_vec[minor].use_lock);
   593     printk(KERN_ERR "WARNING: ME8100:me8100_open():Board %d already in use\n", minor);
   583     return -EBUSY;
   594   }
   584   }
   595   ++info->board_in_use;
   585   info_vec[minor].board_in_use = 1;
   596   spin_unlock(&info->use_lock);
   586   spin_unlock(&info_vec[minor].use_lock);
   597 
   587 
   598   /* info->file_ptr = file_ptr; */  /* müssen wir uns nicht hier merken! */
   588   info_vec[minor].file_ptr = file_ptr;
       
   589 
       
   590   err = request_irq(info_vec[minor].int_line,
       
   591 		    me8100_isr,
       
   592 		    SA_INTERRUPT | SA_SHIRQ,
       
   593 		    ME8100_NAME,
       
   594 		    (void *)&info_vec[minor]);
       
   595   if(err){
       
   596     printk(KERN_ERR"ME8100:me8100_open():Can't get interrupt line");
       
   597     return err;
       
   598   }
       
   599 
   599 
   600   MOD_INC_USE_COUNT;
   600   MOD_INC_USE_COUNT;
   601 
   601 
   602   return 0;
   602   return 0;
   603 }
   603 }
   629  *--------------------------------------------------------------------------
   629  *--------------------------------------------------------------------------
   630  * Author: GG                                                               
   630  * Author: GG                                                               
   631  * Modification:                                                            
   631  * Modification:                                                            
   632  */
   632  */
   633 static int me8100_release(struct inode *inode_ptr, struct file *file_ptr){
   633 static int me8100_release(struct inode *inode_ptr, struct file *file_ptr){
   634   int minor = 0;
   634   int minor;
   635   int err   = 0;
   635   int err;
       
   636   me8100_info_type *info;
       
   637 
   636   
   638   
   637   PDEBUG("me8100_release() is executed\n");
   639   PDEBUG("me8100_release() is executed\n");
   638 
   640 
   639   minor = MINOR(inode_ptr->i_rdev);
   641   minor = DEVICE(inode_ptr->i_rdev);
   640 
   642   info = &info_vec[minor];
   641   err = me8100_reset_board(&info_vec[minor]);
   643 
   642   if(err){
   644   /* resetting the board on last close */
   643     printk(KERN_ERR"ME8100:me8100_release():Can't reset");
   645 
   644     return err;
   646   if (--info->board_in_use == 0) {
   645   }
   647     err = me8100_reset_board(info);
   646 
   648     if(err){
   647   free_irq(info_vec[minor].int_line, (void *) &info_vec[minor]);
   649       printk(KERN_ERR"ME8100:me8100_release():Can't reset");
   648 
   650       return err;
   649   /* Delete the fasync structure and free memory */
   651     }
   650   me8100_fasync(0, file_ptr, 0);
   652   }
   651 
   653   me8100_fasync(-1, file_ptr, 0);
   652   info_vec[minor].board_in_use = 0;
       
   653 
   654 
   654   MOD_DEC_USE_COUNT;
   655   MOD_DEC_USE_COUNT;
   655   PDEBUG("me8100_release() is leaved\n");
   656   PDEBUG("me8100_release() is leaved\n");
   656   return 0;
   657   return 0;
   657 }
   658 }
   695 
   696 
   696   int minor = 0;
   697   int minor = 0;
   697 
   698 
   698   PDEBUG("me8100_ioctl() is executed\n");
   699   PDEBUG("me8100_ioctl() is executed\n");
   699 
   700 
   700   minor = MINOR(inode_ptr->i_rdev);      
   701   minor = DEVICE(inode_ptr->i_rdev);      
   701 
   702 
   702   if(_IOC_TYPE(service) != ME8100_MAGIC){
   703   if(_IOC_TYPE(service) != ME8100_MAGIC){
   703     printk(KERN_ERR"ME8100:Invalid ME8100_MAGIC\n");
   704     printk(KERN_ERR"ME8100:Invalid ME8100_MAGIC\n");
   704     return -EINVAL;
   705     return -EINVAL;
   705   }
   706   }
   803  *--------------------------------------------------------------------------
   804  *--------------------------------------------------------------------------
   804  * Author: GG                                                               
   805  * Author: GG                                                               
   805  * Modufication:                                                            
   806  * Modufication:                                                            
   806  */
   807  */
   807 static int me8100_fasync(int fd, struct file *file_ptr, int mode){
   808 static int me8100_fasync(int fd, struct file *file_ptr, int mode){
   808   int val = 0;
   809   int val;
   809   struct fasync_struct *fasync_ptr;
   810   int minor;
   810 
   811   me8100_info_type *info;
   811   fasync_ptr = file_ptr->private_data;
   812 
       
   813   minor = DEVICE(file_ptr->f_dentry->d_inode->i_rdev);
       
   814   info = &info_vec[minor];
   812 
   815 
   813   PDEBUG("me8100_fasync() is executed\n");
   816   PDEBUG("me8100_fasync() is executed\n");
   814  
   817   PDEBUG("** fasync_ptr: %p\n", info->fasync_ptr);
   815   val = fasync_helper(fd, file_ptr, mode, &fasync_ptr);
   818   val = fasync_helper(fd, file_ptr, mode, &info->fasync_ptr);
   816   file_ptr->private_data = fasync_ptr;
   819   PDEBUG("** fasync_ptr: %p\n", info->fasync_ptr);
   817   return val;
   820   return val;
   818 }
   821 }
   819 
       
   820 
   822 
   821 
   823 
   822 
   824 
   823 /*
   825 /*
   824  * Routine:                                                                 
   826  * Routine:                                                                 
  1997  *--------------------------------------------------------------------------
  1999  *--------------------------------------------------------------------------
  1998  * Author: GG                                                               
  2000  * Author: GG                                                               
  1999  * Modification:                                                            
  2001  * Modification:                                                            
  2000  */
  2002  */
  2001 static void me8100_isr(int irq, void *dev_id, struct pt_regs *regs){
  2003 static void me8100_isr(int irq, void *dev_id, struct pt_regs *regs){
  2002   unsigned char icsr = 0;
  2004   unsigned char icsr;
  2003   unsigned short dummy = 0;
  2005   unsigned short dummy;
  2004   me8100_info_type *board_context;
  2006   me8100_info_type *info;
  2005   struct fasync_struct *fasync_ptr;
       
  2006 
  2007 
  2007   PDEBUG("me8100_isr() is executed\n");
  2008   PDEBUG("me8100_isr() is executed\n");
  2008 
  2009 
  2009   board_context = (me8100_info_type *) dev_id;
  2010   info = (me8100_info_type *) dev_id;
  2010 
  2011 
  2011   fasync_ptr = board_context->file_ptr->private_data;
  2012   if(irq != info->int_line){
  2012 
       
  2013   if(irq != board_context->int_line){
       
  2014     PDEBUG("me8100_isr():incorrect interrupt num: %d\n", irq);
  2013     PDEBUG("me8100_isr():incorrect interrupt num: %d\n", irq);
  2015     return;
  2014     return;
  2016   }
  2015   }
  2017 
  2016 
  2018   board_context->int1 = 0;
  2017   info->int1 = 0;
  2019   board_context->int2 = 0;
  2018   info->int2 = 0;
  2020 
  2019 
  2021   icsr = inb(board_context->plx_regbase + PLX_ICSR);
  2020   icsr = inb(info->plx_regbase + PLX_ICSR);
  2022 
  2021 
  2023   if((icsr & 0x04)&&(icsr & 0x40)&&(icsr & 0x01)){
  2022   if((icsr & 0x04)&&(icsr & 0x40)&&(icsr & 0x01)){
  2024     PDEBUG("me8100_isr():Int1 occured\n");
  2023     PDEBUG("me8100_isr():Int1 occured\n");
  2025     board_context->int1 = 1;
  2024     info->int1 = 1;
  2026     board_context->int_count_1++;
  2025     info->int_count_1++;
  2027     dummy = inw(board_context->me8100_regbase + ME8100_RES_INT_REG_A); 
  2026     dummy = inw(info->me8100_regbase + ME8100_RES_INT_REG_A); 
  2028   }
  2027   }
  2029 
  2028 
  2030   if((icsr & 0x20)&&(icsr & 0x40)&&(icsr & 0x08)){
  2029   if((icsr & 0x20)&&(icsr & 0x40)&&(icsr & 0x08)){
  2031     PDEBUG("me8100_isr():Int2 occured\n");
  2030     PDEBUG("me8100_isr():Int2 occured\n");
  2032     board_context->int2 = 1;
  2031     info->int2 = 1;
  2033     board_context->int_count_2++;
  2032     info->int_count_2++;
  2034     dummy = inw(board_context->me8100_regbase + ME8100_RES_INT_REG_B); 
  2033     dummy = inw(info->me8100_regbase + ME8100_RES_INT_REG_B); 
  2035   }
  2034   }
  2036 
  2035 
  2037   if(!(board_context->int1 || board_context->int2)){
  2036   if(!(info->int1 || info->int2)){
  2038     PDEBUG("me8100_isr():Not this Board\n");
  2037     PDEBUG("me8100_isr():Not this Board\n");
  2039     return;
  2038     return;
  2040   }
  2039   }
  2041 
  2040 
  2042   if(fasync_ptr){
  2041   if(info->fasync_ptr){
  2043     PDEBUG("me8100_isr():send signal to process\n");
  2042     PDEBUG("*** me8100_isr():send signal to process %p->%d\n", 
  2044     kill_fasync(&fasync_ptr, SIGIO, POLL_IN);
  2043       info->fasync_ptr, info->fasync_ptr->fa_file->f_owner.pid);
       
  2044     kill_fasync(&info->fasync_ptr, SIGIO, POLL_IN);
  2045   }
  2045   }
  2046 } 
  2046 } 
  2047 
  2047 
  2048 
  2048 
  2049 
  2049 
  2065  * Author: GG                                                               
  2065  * Author: GG                                                               
  2066  * Modification:                                                            
  2066  * Modification:                                                            
  2067  */
  2067  */
  2068 void cleanup_module(void){
  2068 void cleanup_module(void){
  2069   extern unsigned int major;
  2069   extern unsigned int major;
       
  2070   int minor;
  2070   int err;
  2071   int err;
  2071 
  2072 
       
  2073 
  2072   PDEBUG("cleanup_module() is executed\n");
  2074   PDEBUG("cleanup_module() is executed\n");
       
  2075 
       
  2076   for (minor = me8100_board_count - 1; minor > -1; --minor) {
       
  2077     free_irq(info_vec[minor].int_line, (void *) &info_vec[minor]);
       
  2078   }
  2073   
  2079   
  2074   if(major){
  2080   if(major){
  2075     err = unregister_chrdev(major, ME8100_NAME);
  2081     err = unregister_chrdev(major, ME8100_NAME);
  2076     if(err)
  2082     if(err)
  2077       printk(KERN_WARNING"ME8100:cleanup_module():cannot unregister major\n");
  2083       printk(KERN_WARNING"ME8100:cleanup_module():cannot unregister major\n");
  2078   }
  2084   }
  2079 }
  2085 }
       
  2086 
       
  2087 ssize_t me8100_read(struct file * file_ptr, char *buffer, size_t len, loff_t *offset) {
       
  2088   PDEBUG("me8100_read() called\n");
       
  2089   return -EINVAL;
       
  2090 }
       
  2091 
       
  2092 /* 
       
  2093   vim:sts=2 sw=2 aw ai sm: 
       
  2094  */
       
  2095