diff -r 8675c3e5d914 -r 24a49943680f me8100.c --- 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; - }