--- a/me8100.c Fri Jan 25 20:26:01 2002 +0100
+++ b/me8100.c Fri Jan 25 20:26:39 2002 +0100
@@ -600,14 +600,12 @@
printk(KERN_ERR "ME8100: me8100_open(): kmalloc() failed\n");
return -EIO;
}
+
file_ptr->private_data = priv;
-
memset(priv, 0, sizeof(*priv));
- info = &info_vec[device];
- subinfo = &info->subinfo[subdevice];
- priv->info = info;
- priv->subinfo = subinfo;
+ priv->info = info = &info_vec[device];
+ priv->subinfo = subinfo = &info->subinfo[subdevice];
MOD_INC_USE_COUNT;
@@ -633,35 +631,40 @@
* (might be done by some ioctl()s. The file_ptr get a private data
* pointer passed. We need this to keep track of timestamps for
* read data. */
+ unsigned short icsr;
PDEBUG("*** open for reading\n");
- /* The first reader should setup the IRQs (enabling IRQ handling
- * with the full bit mask. It might be modified later. */
+ /* The first reader on the board will enable IRQs at all.
+ * Every next reader shouldn't care. */
+ if (0 == info->num_reader++) icsr = PCI_INT_EN;
+ else icsr = inw(info->plx_regbase + PLX_ICSR);
+
+ /* The first reader per subdevice should enable IRQs for
+ * this subdevice, but not change the settings found already
+ * in the ICSR. */
if (0 == subinfo->num_reader++) {
- int mask;
- unsigned short icsr;
-
- mask = 0xffff;
- icsr = PCI_INT_EN | ((LOCAL_INT_EN | LOCAL_INT_POL) << (3 * subdevice));
+ int mask = 0xffff;
PDEBUG("*** first reader on subdevice %d\n", subdevice);
- /* 1) setup the PLX register */
+ subinfo->icsr_flags = (LOCAL_INT_EN | LOCAL_INT_POL) << (3 * subdevice);
+ icsr |= subinfo->icsr_flags;
+
+ /* Setup the interrupt mask */
+ PDEBUG("*** irqmask = 0x%04x\n", mask);
+ outw(mask, subinfo->regbase + ME8100_MASK_REG);
+
+ /* Setup the PLX register */
PDEBUG("*** plx = 0x%0x\n", icsr);
outb(icsr, info->plx_regbase + PLX_ICSR);
- /* 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 */
+ /* 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);
-
} /* first reader */
} /* reader */
@@ -730,6 +733,14 @@
PDEBUG("*** resetting IRQ mode ctrl: 0x%x\n", subinfo->ctrl_reg);
outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG);
}
+
+ if (0 == --info->num_reader) {
+ unsigned short icsr;
+ icsr = inw(info->plx_regbase + PLX_ICSR);
+ icsr &= ~(PCI_INT_EN | SOFT_INT);
+ outw(icsr, info->plx_regbase + PLX_ICSR);
+ PDEBUG("** reset icsr to 0x%0X\n", icsr);
+ }
}
@@ -2081,7 +2092,7 @@
* Name Type Access Description
*--------------------------------------------------------------------------
* irq int read number of interrupt occured
- * dev_id void* read pointer to board specific
+ * dev void* read pointer to board specific
* informations
* regs struct pt_regs * read pointer to cpu register
*
@@ -2090,7 +2101,7 @@
* Author: GG
* Modification:
*/
-static void me8100_isr(int irq, void *dev_id, struct pt_regs *regs){
+static void me8100_isr(int irq, void *dev, struct pt_regs *regs){
int i;
unsigned char icsr;
me8100_info_t *info;
@@ -2099,9 +2110,9 @@
/* B: 0x20 & 0x40 & 0x08 for irq at port B */
unsigned short icsr_mask[] = { 0x45, 0x68 };
- info = (me8100_info_t *) dev_id;
+ info = dev;
- PDEBUG("INT: me8100_isr()\n");
+ PDEBUG("==> me8100_isr()\n");
if(irq != info->int_line){
PDEBUG("me8100_isr():incorrect interrupt num: %d\n", irq);
@@ -2110,7 +2121,7 @@
icsr = inb(info->plx_regbase + PLX_ICSR);
- PDEBUG("ICSR: 0x%04x\n", icsr);
+ PDEBUG("==> ICSR: 0x%04x\n", icsr);
/* We got an interrupt. Now try each possible subdevice in turn.
* (There is the possibility that all subdevices raised an interupt
@@ -2118,15 +2129,17 @@
* So we've to try each subdevice in turn.) */
for (i = 0; i < MAX_SUBDEVICES; ++i) {
if ((icsr & icsr_mask[i]) == icsr_mask[i]) {
+ me8100_subinfo_t *subinfo = &info->subinfo[i];
- me8100_subinfo_t *subinfo = &info->subinfo[i];
+ PDEBUG("==> Interrupt for subdevice %d\n", i);
+
subinfo->int_seen = jiffies;
++subinfo->int_count;
subinfo->int_di = inw(subinfo->regbase + ME8100_INT_DI_REG);
inw(subinfo->regbase + ME8100_RES_INT_REG); // dummy read
- PDEBUG("===> read: 0x%04x\n", subinfo->int_di);
+ PDEBUG("==> read: 0x%04x\n", subinfo->int_di);
wake_up_interruptible(&subinfo->readq);
if (subinfo->fasync_ptr) kill_fasync(&subinfo->fasync_ptr, SIGIO, POLL_IN);
}
@@ -2134,7 +2147,6 @@
return;
-
}