diff -r f7fb771d7842 -r c3f6d5e9713a me8100.c --- a/me8100.c Mon Jan 21 20:14:51 2002 +0100 +++ b/me8100.c Mon Jan 21 21:52:00 2002 +0100 @@ -478,7 +478,7 @@ info->subinfo[1].regbase = info->me8100_regbase + 0x0C; for (i = 0; i <= 1; ++i) { - info->subinfo[i].int_seen = 0; + info->subinfo[i].int_seen = jiffies; /* suppose we got just the first irq */ info->subinfo[i].int_count = 0; info->subinfo[i].fasync_ptr = NULL; init_waitqueue_head(&info->subinfo[i].readq); @@ -719,7 +719,7 @@ PDEBUG("*** last writer...\n"); /* PDEBUG("*** resetting ENIO mode ctrl: 0x%x\n", subinfo->ctrl_reg); - subinfo->ctrl_reg &= !subinfo->ctrl_wflags; + subinfo->ctrl_reg &= ~subinfo->ctrl_wflags; subinfo->ctrl_wflags = 0; outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG); */ @@ -730,7 +730,7 @@ PDEBUG("*** reader close\n"); if (0 == --subinfo->num_reader) { PDEBUG("*** last reader...\n"); - subinfo->ctrl_reg &= !subinfo->ctrl_rflags; + subinfo->ctrl_reg &= ~subinfo->ctrl_rflags; subinfo->ctrl_rflags = 0; PDEBUG("*** resetting IRQ mode ctrl: 0x%x\n", subinfo->ctrl_reg); outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG); @@ -2105,53 +2105,49 @@ * Modification: */ static void me8100_isr(int irq, void *dev_id, struct pt_regs *regs){ + int i; unsigned char icsr; - unsigned short dummy; me8100_info_type *info; - //unsigned short icsr_mask[] = { 0x45, 0x68 }; + /* A: 0x04 & 0x40 & 0x01 */ + /* B: 0x20 & 0x40 & 0x08 */ + unsigned short icsr_mask[] = { 0x45, 0x68 }; + + info = (me8100_info_type *) dev_id; PDEBUG("=====> me8100_isr() is executed\n"); - info = (me8100_info_type *) dev_id; if(irq != info->int_line){ PDEBUG("me8100_isr():incorrect interrupt num: %d\n", irq); return; } - info->subinfo[0].int_seen = 0; - info->subinfo[1].int_seen = 0; icsr = inb(info->plx_regbase + PLX_ICSR); PDEBUG("== ICSR: 0x%04x\n", icsr); - - /* A: 0x04 & 0x40 & 0x01 */ - /* B: 0x20 & 0x40 & 0x08 */ - if((icsr & 0x45) == 0x45) { - struct me8100_subinfo *subinfo = &info->subinfo[0]; - PDEBUG("me8100_isr():Int1 occured\n"); - 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); + /* We got an interrupt. Now try each possible subdevice in turn. + * (There is the possibility that all subdevices raised an intterupt + * at the same time. I don't know how this is resolved by the board. + * So we've to try each subdevice in turn.) */ + for (i = 0; i <= 1; ++i) { + if ((icsr & icsr_mask[i]) == icsr_mask[i]) { - } else if((icsr & 0x68) == 0x68) { - struct me8100_subinfo *subinfo = &info->subinfo[1]; - PDEBUG("me8100_isr():Int2 occured\n"); - 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); + struct me8100_subinfo *subinfo = &info->subinfo[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 - } else { - PDEBUG("me8100_isr():Not this Board\n"); - return; + 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); + } } + return; } @@ -2202,8 +2198,8 @@ * * If a a reader (identified by the file_ptr) calls this functions the first time, * the current input is returned. Every succsessive read is then put to sleep until - * the status of the input changed. (Unless the IRQ behaviour if the device is changed by - * some ioctl()s.) + * the status of the input changed. (Signalled by an interrupt.) If awoken from + * interrupt, the value that caused the interrupt ist read. */ ssize_t me8100_read(struct file * file_ptr, char *buffer, size_t len, loff_t *offset) { @@ -2220,14 +2216,20 @@ if (len == 0) return 0; /* do we really need this check? */ if (len < 0) return -EINVAL; /* do we really need this check? */ - if (priv->last_read > subinfo->last_change) { + + if (priv->last_read >= subinfo->int_seen) { /* alread seen, sleep */ PDEBUG("*** going to sleep\n"); - interruptible_sleep_on(&subinfo->readq); + if (wait_event_interruptible(subinfo->readq, (priv->last_read != subinfo->int_seen))) { + PDEBUG("** awoken on signal?\n"); + return -ERESTARTSYS; + } + val = subinfo->int_di; /* the value that caused the interrupt */ + } else { /* not yet seen ... */ + val = inw(subinfo->regbase + ME8100_DI_REG); + PDEBUG("me8100_read: val=0x%04x\n", val); } - priv->last_read = jiffies; - val = inw(subinfo->regbase + ME8100_DI_REG); - PDEBUG("me8100_read: val=0x%04x\n", val); + priv->last_read = subinfo->int_seen; if (len >= sizeof(val)) { err = put_user(val, (unsigned short*) buffer);