--- a/me8100.c Fri Jan 25 21:31:37 2002 +0100
+++ b/me8100.c Sat Jan 26 17:57:25 2002 +0100
@@ -87,6 +87,7 @@
#include <linux/ioport.h>
#include <linux/fs.h>
+#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
@@ -173,6 +174,7 @@
static int me8100_read_icsr(unsigned char *, me8100_info_t *);
static int me8100_get_board_info(me8100_info_t *, me8100_info_t *);
static int me8100_get_int_count(me8100_int_occur_type *, me8100_info_t *);
+static int me8100_read_proc(char*, char**, off_t, int, int*, void*);
static inline int DEVICE(int i) { return i & 0x0f; }
static inline int SUBDEVICE(int i) { return (i >> 4) - 1; }
@@ -221,8 +223,8 @@
* Author: GG
* Modification:
*/
+int init_module(void){
#ifdef CONFIG_PCI
-int init_module(void){
int result;
unsigned short board_count = 0;
unsigned short sort_count;
@@ -233,7 +235,7 @@
/* Set the board context to 0 */
memset(&info_vec, 0, sizeof(info_vec));
- if (pci_present()){
+ if (pci_present()) {
/* Search for ME8100_A boards */
for(sort_count = 0;
sort_count < ME8100_MAX_DEVICES;
@@ -293,10 +295,12 @@
if (result < 0){
printk(KERN_ERR"ME8100:init_module():Can't get major no\n");
return result;
- }
- else{
+ } else {
+ /* Finally successful. */
major = result;
PDEBUG("init_module():Major = %d\n", major);
+
+ create_proc_read_entry("me8100", 0, NULL, me8100_read_proc, NULL);
}
}
else{
@@ -304,10 +308,10 @@
return -ENODEV;
}
return 0;
+#else
+ return -ENODEV
+#endif
}
-#else
-return -ENODEV
-#endif
@@ -2133,13 +2137,21 @@
PDEBUG("==> Interrupt for subdevice %d\n", i);
+ /* Remember the the time the interrupt was seen. This is used
+ * later from read() to decide if it has to wait for further
+ * bytes on the input port. */
subinfo->int_seen = jiffies;
++subinfo->int_count;
+ /* Read the word and store it for later read(). Then
+ * perform a "dummy" read to re-enable the IRQ line */
subinfo->int_di = inw(subinfo->regbase + ME8100_INT_DI_REG);
- inw(subinfo->regbase + ME8100_RES_INT_REG); // dummy read
+ inw(subinfo->regbase + ME8100_RES_INT_REG);
PDEBUG("==> read: 0x%04x\n", subinfo->int_di);
+
+ /* Now wake up all sleeping processes and send the
+ * interrupt (SIGIO) signal to all asked for. */
wake_up_interruptible(&subinfo->readq);
if (subinfo->fasync_ptr) kill_fasync(&subinfo->fasync_ptr, SIGIO, POLL_IN);
}
@@ -2186,6 +2198,8 @@
if(err)
printk(KERN_WARNING"ME8100:cleanup_module():cannot unregister major\n");
}
+
+ remove_proc_entry("me8100", NULL);
}
/* Reading: we do only read (at most) one word (an usigned short) and return immediatly,
@@ -2214,7 +2228,7 @@
if (len < 0) return -EINVAL; /* do we really need this check? */
/* If the time we did the last read operation is more recent than the
- * last interupt, we have to go to sleep (or return -EAGAIN in non blockin
+ * last interupt, we have to go to sleep (or return -EAGAIN in non blocking
* mode). Then, if we're awoken, we return the value that triggered the
* interrupt. (If awoken from a signal, we return -ERESTARTSYS.)
*
@@ -2232,9 +2246,7 @@
return -ERESTARTSYS;
val = subinfo->int_di;
- } else val = inw(subinfo->regbase + ME8100_DI_REG);
-
- PDEBUG("me8100_read: val=0x%04x\n", val);
+ } else val = subinfo->int_di = inw(subinfo->regbase + ME8100_DI_REG);
/* Remember the time of the last interrupt we've seen. (It might be
* 0 if there was no interrupt yet. This doesn't hurt, since the next
@@ -2242,6 +2254,9 @@
*/
priv->last_read = subinfo->int_seen;
+
+ PDEBUG("me8100_read: val=0x%04x\n", val);
+
/* Return at most 2 byte, but check if the read want's them both! */
if (len >= sizeof(val)) {
err = put_user(val, (unsigned short*) buffer);
@@ -2302,6 +2317,14 @@
}
+int me8100_read_proc(char *buffer, char **start, off_t offset, int count, int *eof, void *data)
+{
+ int len = 0;
+ len += sprintf(buffer + len, "Version: $Id$\n");
+ *eof = 1;
+ return len;
+}
+
/*
vim:sts=2 sw=2 aw ai sm:
*/