me8100.c
changeset 13 f7fb771d7842
parent 12 67e56b4bce81
child 14 c3f6d5e9713a
--- a/me8100.c	Mon Jan 21 19:35:53 2002 +0100
+++ b/me8100.c	Mon Jan 21 20:14:51 2002 +0100
@@ -125,11 +125,6 @@
 /* Major Device Number. 0 means to get it automatically from the System */
 static unsigned int major = 0;
 
-/* The queue all the readers are on. */
-DECLARE_WAIT_QUEUE_HEAD(me8100_readq);
-
-
-
 /* Prototypes */
 static int me8100_open(struct inode *, struct file *);
 static int me8100_release(struct inode *, struct file *);
@@ -486,6 +481,7 @@
     info->subinfo[i].int_seen = 0;
     info->subinfo[i].int_count = 0;
     info->subinfo[i].fasync_ptr = NULL;
+    init_waitqueue_head(&info->subinfo[i].readq);
   }
   
   
@@ -630,42 +626,44 @@
 
     PDEBUG("*** open for reading\n");
 
+    /* Allocate memory for the private data.  If allocating fails,
+     * call m8100_release() (which in turn decrements the mod-in-use-count)
+     * and return IO error. */
+    if (NULL == (priv = kmalloc(sizeof(*priv), GFP_KERNEL))) {	  
+      printk(KERN_ERR"ME8100:me8100_open: kmalloc() failed.\n");
+      me8100_release(inode_ptr, file_ptr);  
+      return -EIO;
+    }
+
+    priv->last_read = 0;
+    file_ptr->private_data = priv;
+
     /* The first reader should setup the IRQs (enabling IRQ handling
      * with the full bit mask.  It might be modified later. */
     if (0 == subinfo->num_reader++) {
-      int mask = 0xffff;
-      unsigned short icsr = PCI_INT_EN
-	| ((LOCAL_INT_EN | LOCAL_INT_POL) << (3 * subdevice));
-      PDEBUG("*** first reader...\n");
-      subinfo->ctrl_rflags = 0;
+      int mask;
+      unsigned short icsr;
 
-      /* Allocate memory for the private data.  If allocating fails,
-       * call m8100_release() (which in turn decrements the mod-in-use-count)
-       * and return IO error. */
-      if (NULL == (priv = kmalloc(sizeof(*priv), GFP_KERNEL))) {	  
-	printk(KERN_ERR"ME8100:me8100_open: kmalloc() failed.\n");
-	me8100_release(inode_ptr, file_ptr);  
-	return -EIO;
-      }
+      mask = 0xffff;
+      icsr = PCI_INT_EN | ((LOCAL_INT_EN | LOCAL_INT_POL) << (3 * subdevice));
 
-      priv->last_read = 0;
-      file_ptr->private_data = priv;
+      PDEBUG("*** first reader on subdevice %d\n", subdevice);
 
       /* 1) setup the PLX register */
       PDEBUG("*** plx = 0x%0x\n", icsr);
       outb(icsr, info->plx_regbase + PLX_ICSR);
 
-      /* 2) setup the irq flags in regbase */
+      /* 2) setup the interrupt mask */
+      PDEBUG("*** irqmask = 0x%04x\n", mask);
+      outw(mask, subinfo->regbase + ME8100_MASK_REG);
+
+      /* 3) setup the irq flags in regbase */
       subinfo->ctrl_rflags = ME8100_CTRL_IRQ_MASK;
       subinfo->ctrl_reg |= subinfo->ctrl_rflags;
       PDEBUG("*** adding 0x%0x to ctrl => 0x%04x\n", 
 	subinfo->ctrl_rflags, subinfo->ctrl_reg);
       outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG);
 
-      /* 3) setup the interrupt mask */
-      PDEBUG("*** irqmask = 0x%04x\n", mask);
-      outw(mask, subinfo->regbase + ME8100_MASK_REG);
-
     } /* first reader */
   } /* reader */    
 
@@ -718,6 +716,7 @@
   if (file_ptr->f_mode & FMODE_WRITE) {
     PDEBUG("*** writer closes\n");
     if (0 == --subinfo->num_writer) {
+	PDEBUG("*** last writer...\n");
 	/*
 	PDEBUG("*** resetting ENIO mode ctrl: 0x%x\n", subinfo->ctrl_reg);
 	subinfo->ctrl_reg &= !subinfo->ctrl_wflags;
@@ -2109,6 +2108,8 @@
   unsigned char icsr;
   unsigned short dummy;
   me8100_info_type *info;
+  //unsigned short icsr_mask[] = { 0x45, 0x68 };
+
 
   PDEBUG("=====> me8100_isr() is executed\n");
 
@@ -2134,6 +2135,7 @@
     subinfo->int_seen = 1;
     subinfo->int_count++;
     dummy = inw(info->me8100_regbase + ME8100_RES_INT_REG_A); 
+    wake_up_interruptible(&subinfo->readq);
     if (subinfo->fasync_ptr) kill_fasync(&subinfo->fasync_ptr, SIGIO, POLL_IN);
 
   } else if((icsr & 0x68) == 0x68) {
@@ -2142,6 +2144,7 @@
     subinfo->int_seen = 1;
     subinfo->int_count++;
     dummy = inw(info->me8100_regbase + ME8100_RES_INT_REG_B); 
+    wake_up_interruptible(&subinfo->readq);
     if (subinfo->fasync_ptr) kill_fasync(&subinfo->fasync_ptr, SIGIO, POLL_IN);
 
   } else {
@@ -2149,9 +2152,8 @@
     return;
   }
 
-  PDEBUG("*** wake up sleeper\n");
-  /* should be splitted too (one queue for each channel) */
-  wake_up_interruptible(&me8100_readq);
+  return;
+
 } 
 
 
@@ -2220,7 +2222,7 @@
   if (len < 0) return -EINVAL;	/* do we really need this check? */
   if (priv->last_read > subinfo->last_change) {
     PDEBUG("*** going to sleep\n");
-    interruptible_sleep_on(&me8100_readq);
+    interruptible_sleep_on(&subinfo->readq);
   }
   priv->last_read = jiffies;