Bitweise Negation ist "~", nicht "!".
--- 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);
--- a/me8100.h Mon Jan 21 20:14:51 2002 +0100
+++ b/me8100.h Mon Jan 21 21:52:00 2002 +0100
@@ -134,10 +134,14 @@
#define ME8100_CTRL_IRQ_PATTERN 0x40
#define ME8100_CTRL_IRQ_MASK 0x60
-#define ME8100_CTRL_REG 0x00 //( ,w)
-#define ME8100_MASK_REG 0x02 //(r, )
-#define ME8100_DI_REG 0x04 //(r, )
-#define ME8100_DO_REG 0x06 //( ,w)
+#define ME8100_ID_REG 0x00 //(r, )
+#define ME8100_CTRL_REG 0x00 //( ,w)
+#define ME8100_RES_INT_REG 0x02 //(r, )
+#define ME8100_DI_REG 0x04 //(r, )
+#define ME8100_DO_REG 0x06 //( ,w)
+#define ME8100_PATTERN_REG 0x08 //( ,w)
+#define ME8100_MASK_REG 0x0A //( ,w)
+#define ME8100_INT_DI_REG 0x0A //(r, )
/* ME8100 Register Set A */
#define ME8100_ID_REG_A 0x00 //(r, )
@@ -216,6 +220,7 @@
int int_seen;
int int_count;
+ unsigned short int_di; /* value that raised the interrupt */
struct fasync_struct *fasync_ptr;
wait_queue_head_t readq;