Interrupt fires when module is unloaded

Eric Fowler eric.fowler at gmail.com
Mon Jan 6 19:32:41 EST 2014


It's a mess, but you are welcome to it :-)

//-------------------------------cut here---------------------
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
//#include <linux/proc_fs.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <linux/seq_file.h>
#include <linux/interrupt.h>

MODULE_LICENSE("GPL");

#define NUM_DEVICES (1)
#define DEVNAME "foobar"
#define DEVPROCNAME "foobar_mem"
#define FOOBAR_MAJOR (248)
#define FOOBAR_MINOR (0)

int foobar_init(void);
void foobar_exit(void);
int foobar_release(struct inode *, struct file*);
ssize_t foobar_read(struct file *, char __user *, size_t, loff_t *);
ssize_t foobar_write(struct file *, const char __user *, size_t, loff_t *);
int foobar_read_procmem(char * buf, char **start, off_t offset, int count,
int * eof, void * data);
int foobar_open(struct inode * inode, struct file * file);
void set_port_and_irq(void);
static irqreturn_t irqhandler(int irq, void * data);
int foobar_set_irq(void);

int port_address = -1;
module_param(port_address, int, 0);

unsigned int irq = 0;
module_param(irq, uint, 0);

int irqavail = -1;

static struct file_operations foobar_i_fops =
  {
    .owner = THIS_MODULE,
    .read =  foobar_read,
    .write = foobar_write,
    .open = foobar_open,
    .release = foobar_release,
  };


static dev_t g_dev;
unsigned dev_id = (unsigned)&foobar_i_fops;

int foobar_init(void)
{
  int result = 0;

  result = register_chrdev(0, DEVNAME, &foobar_i_fops);
  g_dev = MKDEV(result, FOOBAR_MINOR);
  if(result < 0)
  {
      printk(KERN_WARNING "foobar: can't get device number, returning %d",
result);
      return result;
  }

  printk(KERN_WARNING "foobar: Module %s got device number %d, minor is %d,
result is %d\n", THIS_MODULE->name, MAJOR(g_dev), MINOR(g_dev), result);
  g_dev = MKDEV(MAJOR(g_dev), FOOBAR_MINOR + NUM_DEVICES);

  set_port_and_irq();
  printk(KERN_WARNING "Port address is 0x%x, IRQ is %d\n", port_address,
irq);
  return 0;
}

void set_port_and_irq(void)
{
  if(irq < 0)
      switch(port_address)
{
case 0x378:
  irq = 7;
  break;

case 0x278:
  irq = 2;
  break;
}

    switch(irq)
      {
      case 2:
port_address = 0x278;
break;

      case 7:
port_address = 0x378;
break;

     }
}

void foobar_exit(void)
{
  int major = MAJOR(g_dev);

  if(irqavail == 0)
    {
      printk(KERN_WARNING "Freeing irq %d, dev_id is 0x%x\n", irq, dev_id);
      free_irq(irq, (void*)dev_id);
    }

  printk(KERN_WARNING "unregister_chrdev(%d) called for %s, dev # is %d\n",
major, DEVNAME, g_dev);

  unregister_chrdev(major, DEVNAME);
}

int foobar_set_irq(void)
{
  irqavail = request_irq(irq, irqhandler, IRQF_SHARED, DEVNAME,
(void*)dev_id);
  printk(KERN_WARNING "IRQ:%d\tPort Address:0x%x\tAvailable:%s\n", irq,
port_address, irqavail == 0 ? "true" : "false");

  return irqavail;
}

static irqreturn_t irqhandler(int irq, void * data)
{
  printk(KERN_WARNING "Interrupt is fired, IRQ is %d, data is 0x%p\n", irq,
data);
  return IRQ_HANDLED;
}

int foobar_open(struct inode * inode, struct file * file)
{
  return foobar_set_irq();
}


int foobar_release(struct inode * inode, struct file * filp)
{
  printk(KERN_WARNING "foobar_release() is called, fil is 0x%p, inode is
0x%p\n", filp, inode);
  return 0;
}

ssize_t foobar_read(struct file * filp, char __user * buf, size_t count,
loff_t * f_pos)
{
  printk(KERN_WARNING "Read is called\n");
  return 0;
}

ssize_t foobar_write(struct file * filp, const char __user * buf, size_t
count, loff_t *f_pos)
{
  unsigned long address = (unsigned long)port_address;
  printk(KERN_WARNING "Write is called, address is 0x%lx\n", address);
  outb_p(0x10, address + 2);
  outb_p(0x00, address);
  outb_p(0xff, address);
  udelay(5);
  outb_p(0x00, address + 2);
  if(f_pos)
    * f_pos = 0;
  return count;
}

module_init(foobar_init);
module_exit(foobar_exit);





On Mon, Jan 6, 2014 at 4:27 PM, Rajat Sharma <fs.rajat at gmail.com> wrote:

> It would be nice to post the code when asking for debugging help. Looks
> like your interrupts are in masked state but when you unload the driver
> they are getting unmasked and hence you are receiving them on unload.
>
> -Rajat
>
>
> On Mon, Jan 6, 2014 at 4:09 PM, Eric Fowler <eric.fowler at gmail.com> wrote:
>
>> I am trying to figure out interrupts by writing a shadow of Rubini's
>> 'short' program. Recall that Rubini tells us to enable parallel port
>> interrupts by wiring pins 9&10 together, then writing binary data to the
>> parallel port's address.
>>
>> I am doing that, but:
>> - I don't see interrupts when I write to the port
>> - I do see one interrupt when I unload the driver (in the fop's .release
>> method)
>> - This happens whether or not the pins are wired up.
>>
>> What is going on here?
>>
>>
>>
>> _______________________________________________
>> Kernelnewbies mailing list
>> Kernelnewbies at kernelnewbies.org
>> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
>>
>>
>


-- 
cc:NSA
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20140106/a44f0319/attachment-0001.html 


More information about the Kernelnewbies mailing list