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
- Lines: 290
- Date:
Mon Aug 9 12:04:39 1999
- Orig file:
v2.2.10/linux/drivers/isdn/avmb1/capi.c
- Orig date:
Mon Aug 24 13:02:44 1998
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)