patch-2.2.11 linux/drivers/isdn/avmb1/capi.c

Next file: linux/drivers/isdn/avmb1/capidev.h
Previous file: linux/drivers/isdn/avmb1/b1pcmcia.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.10/linux/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c
@@ -1,11 +1,55 @@
 /*
- * $Id: capi.c,v 1.10 1998/02/13 07:09:13 calle Exp $
+ * $Id: capi.c,v 1.19 1999/07/09 15:05:42 keil Exp $
  *
  * CAPI 2.0 Interface for Linux
  *
  * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: capi.c,v $
+ * Revision 1.19  1999/07/09 15:05:42  keil
+ * compat.h is now isdn_compat.h
+ *
+ * Revision 1.18  1999/07/06 07:42:01  calle
+ * - changes in /proc interface
+ * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb.
+ *
+ * Revision 1.17  1999/07/01 15:26:30  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ * Revision 1.16  1999/07/01 08:22:57  keil
+ * compatibility macros now in <linux/isdn_compat.h>
+ *
+ * Revision 1.15  1999/06/21 15:24:11  calle
+ * extend information in /proc.
+ *
+ * Revision 1.14  1999/06/10 16:51:03  calle
+ * Bugfix: open/release of control device was not handled correct.
+ *
+ * Revision 1.13  1998/08/28 04:32:25  calle
+ * Added patch send by Michael.Mueller4@post.rwth-aachen.de, to get AVM B1
+ * driver running with 2.1.118.
+ *
+ * Revision 1.12  1998/05/26 22:39:34  he
+ * sync'ed with 2.1.102 where appropriate (CAPABILITY changes)
+ * concap typo
+ * cleared dev.tbusy in isdn_net BCONN status callback
+ *
+ * Revision 1.11  1998/03/09 17:46:37  he
+ * merged in 2.1.89 changes
+ *
  * Revision 1.10  1998/02/13 07:09:13  calle
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -68,11 +112,12 @@
 #include <linux/timer.h>
 #include <linux/wait.h>
 #include <linux/skbuff.h>
+#include <linux/proc_fs.h>
 #include <linux/poll.h>
 #include <linux/capi.h>
 #include <linux/kernelcapi.h>
 
-#include "compat.h"
+#include <linux/isdn_compat.h>
 #include "capiutil.h"
 #include "capicmd.h"
 #include "capidev.h"
@@ -166,7 +211,10 @@
 	}
 	copied = skb->len;
 
-
+	if (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
+	    && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND)
+		cdev->nrecvdatapkt++;
+        else cdev->nrecvctlpkt++;
 	kfree_skb(skb);
 
 	return copied;
@@ -195,7 +243,7 @@
 	skb = alloc_skb(count, GFP_USER);
 
 	if ((retval = copy_from_user(skb_put(skb, count), buf, count))) {
-		dev_kfree_skb(skb);
+		kfree_skb(skb);
 		return retval;
 	}
 	cmd = CAPIMSG_COMMAND(skb->data);
@@ -204,11 +252,11 @@
 	if (cmd == CAPI_DATA_B3 && subcmd == CAPI_REQ) {
 		__u16 dlen = CAPIMSG_DATALEN(skb->data);
 		if (mlen + dlen != count) {
-			dev_kfree_skb(skb);
+			kfree_skb(skb);
 			return -EINVAL;
 		}
 	} else if (mlen != count) {
-		dev_kfree_skb(skb);
+		kfree_skb(skb);
 		return -EINVAL;
 	}
 	CAPIMSG_SETAPPID(skb->data, cdev->applid);
@@ -216,9 +264,12 @@
 	cdev->errcode = (*capifuncs->capi_put_message) (cdev->applid, skb);
 
 	if (cdev->errcode) {
-		dev_kfree_skb(skb);
+		kfree_skb(skb);
 		return -EIO;
 	}
+	if (cmd == CAPI_DATA_B3 && subcmd == CAPI_REQ)
+		cdev->nsentdatapkt++;
+	else cdev->nsentctlpkt++;
 	return count;
 }
 
@@ -237,6 +288,9 @@
 		return POLLERR;
 
 	cdev = &capidevs[minor];
+#if (LINUX_VERSION_CODE < 0x020159) /* 2.1.89 */
+#define poll_wait(f,wq,w) poll_wait((wq),(w))
+#endif
 	poll_wait(file, &(cdev->recv_wait), wait);
 	mask = POLLOUT | POLLWRNORM;
 	if (!skb_queue_empty(&cdev->recv_queue))
@@ -411,16 +465,13 @@
 		capidevs[minor].is_open = 1;
 		skb_queue_head_init(&capidevs[minor].recv_queue);
 		MOD_INC_USE_COUNT;
+		capidevs[minor].nopen++;
 
 	} else {
-
-		if (!capidevs[minor].is_open) {
-			capidevs[minor].is_open = 1;
-			MOD_INC_USE_COUNT;
-		}
+		capidevs[minor].is_open++;
+		MOD_INC_USE_COUNT;
 	}
 
-
 	return 0;
 }
 
@@ -445,10 +496,13 @@
 		cdev->is_registered = 0;
 		cdev->applid = 0;
 
-		while ((skb = skb_dequeue(&cdev->recv_queue)) != 0)
+		while ((skb = skb_dequeue(&cdev->recv_queue)) != 0) {
 			kfree_skb(skb);
+		}
+		cdev->is_open = 0;
+	} else {
+		cdev->is_open--;
 	}
-	cdev->is_open = 0;
 
 	MOD_DEC_USE_COUNT;
 	return 0;
@@ -464,13 +518,90 @@
 	capi_ioctl,
 	NULL,			/* capi_mmap */
 	capi_open,
-	NULL,			/* flush */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,118)
+        NULL,                   /* capi_flush */
+#endif
 	capi_release,
 	NULL,			/* capi_fsync */
 	NULL,			/* capi_fasync */
 };
 
+/* -------- /proc functions ----------------------------------- */
 
+/*
+ * /proc/capi/capi20:
+ *  minor opencount nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
+ */
+static int proc_capidev_read_proc(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+        struct capidev *cp;
+	int i;
+	int len = 0;
+	off_t begin = 0;
+
+	for (i=0; i < CAPI_MAXMINOR; i++) {
+		cp = &capidevs[i+1];
+		if (cp->nopen == 0) continue;
+		len += sprintf(page+len, "%d %lu %lu %lu %lu %lu\n",
+			i+1,
+			cp->nopen,
+			cp->nrecvctlpkt,
+			cp->nrecvdatapkt,
+			cp->nsentctlpkt,
+			cp->nsentdatapkt);
+		if (len+begin > off+count)
+			goto endloop;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+endloop:
+	if (i >= CAPI_MAXMINOR)
+		*eof = 1;
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+static struct procfsentries {
+  char *name;
+  mode_t mode;
+  int (*read_proc)(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data);
+  struct proc_dir_entry *procent;
+} procfsentries[] = {
+   /* { "capi",		  S_IFDIR, 0 }, */
+   { "capi/capi20", 	  0	 , proc_capidev_read_proc },
+};
+
+static void proc_init(void)
+{
+    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int i;
+
+    for (i=0; i < nelem; i++) {
+        struct procfsentries *p = procfsentries + i;
+	p->procent = create_proc_entry(p->name, p->mode, 0);
+	if (p->procent) p->procent->read_proc = p->read_proc;
+    }
+}
+
+static void proc_exit(void)
+{
+    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int i;
+
+    for (i=nelem-1; i >= 0; i--) {
+        struct procfsentries *p = procfsentries + i;
+	if (p->procent) {
+	   remove_proc_entry(p->name, 0);
+	   p->procent = 0;
+	}
+    }
+}
 /* -------- init function and module interface ---------------------- */
 
 #ifdef MODULE
@@ -484,7 +615,16 @@
 
 int capi_init(void)
 {
+#ifdef COMPAT_HAS_NEW_WAITQ
+	int j;
+#endif
+	
 	memset(capidevs, 0, sizeof(capidevs));
+#ifdef COMPAT_HAS_NEW_WAITQ
+	for ( j = 0; j < CAPI_MAXMINOR+1; j++ ) {
+		init_waitqueue_head(&capidevs[j].recv_wait);
+	}
+#endif
 
 	if (register_chrdev(capi_major, "capi20", &capi_fops)) {
 		printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);
@@ -496,12 +636,14 @@
 		unregister_chrdev(capi_major, "capi20");
 		return -EIO;
 	}
+	(void)proc_init();
 	return 0;
 }
 
 #ifdef MODULE
 void cleanup_module(void)
 {
+	(void)proc_exit();
 	unregister_chrdev(capi_major, "capi20");
 	(void) detach_capi_interface(&cuser);
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)