me8100.c
changeset 14 c3f6d5e9713a
parent 13 f7fb771d7842
child 15 b9baa645576a
--- 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);