--- 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;