Creation of Cybook 2416 (actually Gen4) repository
This commit is contained in:
65
drivers/isdn/capi/Kconfig
Normal file
65
drivers/isdn/capi/Kconfig
Normal file
@@ -0,0 +1,65 @@
|
||||
#
|
||||
# Config.in for the CAPI subsystem
|
||||
#
|
||||
config ISDN_DRV_AVMB1_VERBOSE_REASON
|
||||
bool "Verbose reason code reporting"
|
||||
depends on ISDN_CAPI
|
||||
default y
|
||||
help
|
||||
If you say Y here, the CAPI drivers will give verbose reasons for
|
||||
disconnecting. This will increase the size of the kernel by 7 KB. If
|
||||
unsure, say Y.
|
||||
|
||||
config CAPI_TRACE
|
||||
bool "CAPI trace support"
|
||||
depends on ISDN_CAPI
|
||||
default y
|
||||
help
|
||||
If you say Y here, the kernelcapi driver can make verbose traces
|
||||
of CAPI messages. This feature can be enabled/disabled via IOCTL for
|
||||
every controler (default disabled).
|
||||
This will increase the size of the kernelcapi module by 20 KB.
|
||||
If unsure, say Y.
|
||||
|
||||
config ISDN_CAPI_MIDDLEWARE
|
||||
bool "CAPI2.0 Middleware support (EXPERIMENTAL)"
|
||||
depends on ISDN_CAPI && EXPERIMENTAL
|
||||
help
|
||||
This option will enhance the capabilities of the /dev/capi20
|
||||
interface. It will provide a means of moving a data connection,
|
||||
established via the usual /dev/capi20 interface to a special tty
|
||||
device. If you want to use pppd with pppdcapiplugin to dial up to
|
||||
your ISP, say Y here.
|
||||
|
||||
config ISDN_CAPI_CAPI20
|
||||
tristate "CAPI2.0 /dev/capi support"
|
||||
depends on ISDN_CAPI
|
||||
help
|
||||
This option will provide the CAPI 2.0 interface to userspace
|
||||
applications via /dev/capi20. Applications should use the
|
||||
standardized libcapi20 to access this functionality. You should say
|
||||
Y/M here.
|
||||
|
||||
config ISDN_CAPI_CAPIFS_BOOL
|
||||
bool "CAPI2.0 filesystem support"
|
||||
depends on ISDN_CAPI_MIDDLEWARE && ISDN_CAPI_CAPI20
|
||||
|
||||
config ISDN_CAPI_CAPIFS
|
||||
tristate
|
||||
depends on ISDN_CAPI_CAPIFS_BOOL
|
||||
default ISDN_CAPI_CAPI20
|
||||
help
|
||||
This option provides a special file system, similar to /dev/pts with
|
||||
device nodes for the special ttys established by using the
|
||||
middleware extension above. If you want to use pppd with
|
||||
pppdcapiplugin to dial up to your ISP, say Y here.
|
||||
|
||||
config ISDN_CAPI_CAPIDRV
|
||||
tristate "CAPI2.0 capidrv interface support"
|
||||
depends on ISDN_CAPI && ISDN_I4L
|
||||
help
|
||||
This option provides the glue code to hook up CAPI driven cards to
|
||||
the legacy isdn4linux link layer. If you have a card which is
|
||||
supported by a CAPI driver, but still want to use old features like
|
||||
ippp interfaces or ttyI emulation, say Y/M here.
|
||||
|
||||
15
drivers/isdn/capi/Makefile
Normal file
15
drivers/isdn/capi/Makefile
Normal file
@@ -0,0 +1,15 @@
|
||||
# Makefile for the CAPI subsystem.
|
||||
|
||||
# Ordering constraints: kernelcapi.o first
|
||||
|
||||
# Each configuration option enables a list of files.
|
||||
|
||||
obj-$(CONFIG_ISDN_CAPI) += kernelcapi.o
|
||||
obj-$(CONFIG_ISDN_CAPI_CAPI20) += capi.o
|
||||
obj-$(CONFIG_ISDN_CAPI_CAPIDRV) += capidrv.o
|
||||
obj-$(CONFIG_ISDN_CAPI_CAPIFS) += capifs.o
|
||||
|
||||
# Multipart objects.
|
||||
|
||||
kernelcapi-y := kcapi.o capiutil.o capilib.o
|
||||
kernelcapi-$(CONFIG_PROC_FS) += kcapi_proc.o
|
||||
1590
drivers/isdn/capi/capi.c
Normal file
1590
drivers/isdn/capi/capi.c
Normal file
File diff suppressed because it is too large
Load Diff
2328
drivers/isdn/capi/capidrv.c
Normal file
2328
drivers/isdn/capi/capidrv.c
Normal file
File diff suppressed because it is too large
Load Diff
140
drivers/isdn/capi/capidrv.h
Normal file
140
drivers/isdn/capi/capidrv.h
Normal file
@@ -0,0 +1,140 @@
|
||||
/* $Id: capidrv.h,v 1.1.1.1 2007/06/12 07:27:09 eyryu Exp $
|
||||
*
|
||||
* ISDN4Linux Driver, using capi20 interface (kernelcapi)
|
||||
*
|
||||
* Copyright 1997 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CAPIDRV_H__
|
||||
#define __CAPIDRV_H__
|
||||
|
||||
/*
|
||||
* LISTEN state machine
|
||||
*/
|
||||
#define ST_LISTEN_NONE 0 /* L-0 */
|
||||
#define ST_LISTEN_WAIT_CONF 1 /* L-0.1 */
|
||||
#define ST_LISTEN_ACTIVE 2 /* L-1 */
|
||||
#define ST_LISTEN_ACTIVE_WAIT_CONF 3 /* L-1.1 */
|
||||
|
||||
|
||||
#define EV_LISTEN_REQ 1 /* L-0 -> L-0.1
|
||||
L-1 -> L-1.1 */
|
||||
#define EV_LISTEN_CONF_ERROR 2 /* L-0.1 -> L-0
|
||||
L-1.1 -> L-1 */
|
||||
#define EV_LISTEN_CONF_EMPTY 3 /* L-0.1 -> L-0
|
||||
L-1.1 -> L-0 */
|
||||
#define EV_LISTEN_CONF_OK 4 /* L-0.1 -> L-1
|
||||
L-1.1 -> L.1 */
|
||||
|
||||
/*
|
||||
* per plci state machine
|
||||
*/
|
||||
#define ST_PLCI_NONE 0 /* P-0 */
|
||||
#define ST_PLCI_OUTGOING 1 /* P-0.1 */
|
||||
#define ST_PLCI_ALLOCATED 2 /* P-1 */
|
||||
#define ST_PLCI_ACTIVE 3 /* P-ACT */
|
||||
#define ST_PLCI_INCOMING 4 /* P-2 */
|
||||
#define ST_PLCI_FACILITY_IND 5 /* P-3 */
|
||||
#define ST_PLCI_ACCEPTING 6 /* P-4 */
|
||||
#define ST_PLCI_DISCONNECTING 7 /* P-5 */
|
||||
#define ST_PLCI_DISCONNECTED 8 /* P-6 */
|
||||
#define ST_PLCI_RESUMEING 9 /* P-0.Res */
|
||||
#define ST_PLCI_RESUME 10 /* P-Res */
|
||||
#define ST_PLCI_HELD 11 /* P-HELD */
|
||||
|
||||
#define EV_PLCI_CONNECT_REQ 1 /* P-0 -> P-0.1
|
||||
*/
|
||||
#define EV_PLCI_CONNECT_CONF_ERROR 2 /* P-0.1 -> P-0
|
||||
*/
|
||||
#define EV_PLCI_CONNECT_CONF_OK 3 /* P-0.1 -> P-1
|
||||
*/
|
||||
#define EV_PLCI_FACILITY_IND_UP 4 /* P-0 -> P-1
|
||||
*/
|
||||
#define EV_PLCI_CONNECT_IND 5 /* P-0 -> P-2
|
||||
*/
|
||||
#define EV_PLCI_CONNECT_ACTIVE_IND 6 /* P-1 -> P-ACT
|
||||
*/
|
||||
#define EV_PLCI_CONNECT_REJECT 7 /* P-2 -> P-5
|
||||
P-3 -> P-5
|
||||
*/
|
||||
#define EV_PLCI_DISCONNECT_REQ 8 /* P-1 -> P-5
|
||||
P-2 -> P-5
|
||||
P-3 -> P-5
|
||||
P-4 -> P-5
|
||||
P-ACT -> P-5
|
||||
P-Res -> P-5 (*)
|
||||
P-HELD -> P-5 (*)
|
||||
*/
|
||||
#define EV_PLCI_DISCONNECT_IND 9 /* P-1 -> P-6
|
||||
P-2 -> P-6
|
||||
P-3 -> P-6
|
||||
P-4 -> P-6
|
||||
P-5 -> P-6
|
||||
P-ACT -> P-6
|
||||
P-Res -> P-6 (*)
|
||||
P-HELD -> P-6 (*)
|
||||
*/
|
||||
#define EV_PLCI_FACILITY_IND_DOWN 10 /* P-0.1 -> P-5
|
||||
P-1 -> P-5
|
||||
P-ACT -> P-5
|
||||
P-2 -> P-5
|
||||
P-3 -> P-5
|
||||
P-4 -> P-5
|
||||
*/
|
||||
#define EV_PLCI_DISCONNECT_RESP 11 /* P-6 -> P-0
|
||||
*/
|
||||
#define EV_PLCI_CONNECT_RESP 12 /* P-6 -> P-0
|
||||
*/
|
||||
|
||||
#define EV_PLCI_RESUME_REQ 13 /* P-0 -> P-0.Res
|
||||
*/
|
||||
#define EV_PLCI_RESUME_CONF_OK 14 /* P-0.Res -> P-Res
|
||||
*/
|
||||
#define EV_PLCI_RESUME_CONF_ERROR 15 /* P-0.Res -> P-0
|
||||
*/
|
||||
#define EV_PLCI_RESUME_IND 16 /* P-Res -> P-ACT
|
||||
*/
|
||||
#define EV_PLCI_HOLD_IND 17 /* P-ACT -> P-HELD
|
||||
*/
|
||||
#define EV_PLCI_RETRIEVE_IND 18 /* P-HELD -> P-ACT
|
||||
*/
|
||||
#define EV_PLCI_SUSPEND_IND 19 /* P-ACT -> P-5
|
||||
*/
|
||||
#define EV_PLCI_CD_IND 20 /* P-2 -> P-5
|
||||
*/
|
||||
|
||||
/*
|
||||
* per ncci state machine
|
||||
*/
|
||||
#define ST_NCCI_PREVIOUS -1
|
||||
#define ST_NCCI_NONE 0 /* N-0 */
|
||||
#define ST_NCCI_OUTGOING 1 /* N-0.1 */
|
||||
#define ST_NCCI_INCOMING 2 /* N-1 */
|
||||
#define ST_NCCI_ALLOCATED 3 /* N-2 */
|
||||
#define ST_NCCI_ACTIVE 4 /* N-ACT */
|
||||
#define ST_NCCI_RESETING 5 /* N-3 */
|
||||
#define ST_NCCI_DISCONNECTING 6 /* N-4 */
|
||||
#define ST_NCCI_DISCONNECTED 7 /* N-5 */
|
||||
|
||||
#define EV_NCCI_CONNECT_B3_REQ 1 /* N-0 -> N-0.1 */
|
||||
#define EV_NCCI_CONNECT_B3_IND 2 /* N-0 -> N.1 */
|
||||
#define EV_NCCI_CONNECT_B3_CONF_OK 3 /* N-0.1 -> N.2 */
|
||||
#define EV_NCCI_CONNECT_B3_CONF_ERROR 4 /* N-0.1 -> N.0 */
|
||||
#define EV_NCCI_CONNECT_B3_REJECT 5 /* N-1 -> N-4 */
|
||||
#define EV_NCCI_CONNECT_B3_RESP 6 /* N-1 -> N-2 */
|
||||
#define EV_NCCI_CONNECT_B3_ACTIVE_IND 7 /* N-2 -> N-ACT */
|
||||
#define EV_NCCI_RESET_B3_REQ 8 /* N-ACT -> N-3 */
|
||||
#define EV_NCCI_RESET_B3_IND 9 /* N-3 -> N-ACT */
|
||||
#define EV_NCCI_DISCONNECT_B3_IND 10 /* N-4 -> N.5 */
|
||||
#define EV_NCCI_DISCONNECT_B3_CONF_ERROR 11 /* N-4 -> previous */
|
||||
#define EV_NCCI_DISCONNECT_B3_REQ 12 /* N-1 -> N-4
|
||||
N-2 -> N-4
|
||||
N-3 -> N-4
|
||||
N-ACT -> N-4 */
|
||||
#define EV_NCCI_DISCONNECT_B3_RESP 13 /* N-5 -> N-0 */
|
||||
|
||||
#endif /* __CAPIDRV_H__ */
|
||||
215
drivers/isdn/capi/capifs.c
Normal file
215
drivers/isdn/capi/capifs.c
Normal file
@@ -0,0 +1,215 @@
|
||||
/* $Id: capifs.c,v 1.1.1.1 2007/06/12 07:27:09 eyryu Exp $
|
||||
*
|
||||
* Copyright 2000 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* Heavily based on devpts filesystem from H. Peter Anvin
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/namei.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/sched.h> /* current */
|
||||
|
||||
#include "capifs.h"
|
||||
|
||||
MODULE_DESCRIPTION("CAPI4Linux: /dev/capi/ filesystem");
|
||||
MODULE_AUTHOR("Carsten Paeth");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static char *revision = "$Revision: 1.1.1.1 $";
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
#define CAPIFS_SUPER_MAGIC (('C'<<8)|'N')
|
||||
|
||||
static struct vfsmount *capifs_mnt;
|
||||
static struct dentry *capifs_root;
|
||||
|
||||
static struct {
|
||||
int setuid;
|
||||
int setgid;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
umode_t mode;
|
||||
} config = {.mode = 0600};
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static int capifs_remount(struct super_block *s, int *flags, char *data)
|
||||
{
|
||||
int setuid = 0;
|
||||
int setgid = 0;
|
||||
uid_t uid = 0;
|
||||
gid_t gid = 0;
|
||||
umode_t mode = 0600;
|
||||
char *this_char;
|
||||
|
||||
this_char = NULL;
|
||||
while ((this_char = strsep(&data, ",")) != NULL) {
|
||||
int n;
|
||||
char dummy;
|
||||
if (!*this_char)
|
||||
continue;
|
||||
if (sscanf(this_char, "uid=%i%c", &n, &dummy) == 1) {
|
||||
setuid = 1;
|
||||
uid = n;
|
||||
} else if (sscanf(this_char, "gid=%i%c", &n, &dummy) == 1) {
|
||||
setgid = 1;
|
||||
gid = n;
|
||||
} else if (sscanf(this_char, "mode=%o%c", &n, &dummy) == 1)
|
||||
mode = n & ~S_IFMT;
|
||||
else {
|
||||
printk("capifs: called with bogus options\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
config.setuid = setuid;
|
||||
config.setgid = setgid;
|
||||
config.uid = uid;
|
||||
config.gid = gid;
|
||||
config.mode = mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct super_operations capifs_sops =
|
||||
{
|
||||
.statfs = simple_statfs,
|
||||
.remount_fs = capifs_remount,
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
capifs_fill_super(struct super_block *s, void *data, int silent)
|
||||
{
|
||||
struct inode * inode;
|
||||
|
||||
s->s_blocksize = 1024;
|
||||
s->s_blocksize_bits = 10;
|
||||
s->s_magic = CAPIFS_SUPER_MAGIC;
|
||||
s->s_op = &capifs_sops;
|
||||
s->s_time_gran = 1;
|
||||
|
||||
inode = new_inode(s);
|
||||
if (!inode)
|
||||
goto fail;
|
||||
inode->i_ino = 1;
|
||||
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
|
||||
inode->i_blocks = 0;
|
||||
inode->i_uid = inode->i_gid = 0;
|
||||
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
|
||||
inode->i_op = &simple_dir_inode_operations;
|
||||
inode->i_fop = &simple_dir_operations;
|
||||
inode->i_nlink = 2;
|
||||
|
||||
capifs_root = s->s_root = d_alloc_root(inode);
|
||||
if (s->s_root)
|
||||
return 0;
|
||||
|
||||
printk("capifs: get root dentry failed\n");
|
||||
iput(inode);
|
||||
fail:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int capifs_get_sb(struct file_system_type *fs_type,
|
||||
int flags, const char *dev_name, void *data, struct vfsmount *mnt)
|
||||
{
|
||||
return get_sb_single(fs_type, flags, data, capifs_fill_super, mnt);
|
||||
}
|
||||
|
||||
static struct file_system_type capifs_fs_type = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "capifs",
|
||||
.get_sb = capifs_get_sb,
|
||||
.kill_sb = kill_anon_super,
|
||||
};
|
||||
|
||||
static struct dentry *get_node(int num)
|
||||
{
|
||||
char s[10];
|
||||
struct dentry *root = capifs_root;
|
||||
mutex_lock(&root->d_inode->i_mutex);
|
||||
return lookup_one_len(s, root, sprintf(s, "%d", num));
|
||||
}
|
||||
|
||||
void capifs_new_ncci(unsigned int number, dev_t device)
|
||||
{
|
||||
struct dentry *dentry;
|
||||
struct inode *inode = new_inode(capifs_mnt->mnt_sb);
|
||||
if (!inode)
|
||||
return;
|
||||
inode->i_ino = number+2;
|
||||
inode->i_uid = config.setuid ? config.uid : current->fsuid;
|
||||
inode->i_gid = config.setgid ? config.gid : current->fsgid;
|
||||
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
|
||||
init_special_inode(inode, S_IFCHR|config.mode, device);
|
||||
//inode->i_op = &capifs_file_inode_operations;
|
||||
|
||||
dentry = get_node(number);
|
||||
if (!IS_ERR(dentry) && !dentry->d_inode)
|
||||
d_instantiate(dentry, inode);
|
||||
mutex_unlock(&capifs_root->d_inode->i_mutex);
|
||||
}
|
||||
|
||||
void capifs_free_ncci(unsigned int number)
|
||||
{
|
||||
struct dentry *dentry = get_node(number);
|
||||
|
||||
if (!IS_ERR(dentry)) {
|
||||
struct inode *inode = dentry->d_inode;
|
||||
if (inode) {
|
||||
inode->i_nlink--;
|
||||
d_delete(dentry);
|
||||
dput(dentry);
|
||||
}
|
||||
dput(dentry);
|
||||
}
|
||||
mutex_unlock(&capifs_root->d_inode->i_mutex);
|
||||
}
|
||||
|
||||
static int __init capifs_init(void)
|
||||
{
|
||||
char rev[32];
|
||||
char *p;
|
||||
int err;
|
||||
|
||||
if ((p = strchr(revision, ':')) != 0 && p[1]) {
|
||||
strlcpy(rev, p + 2, sizeof(rev));
|
||||
if ((p = strchr(rev, '$')) != 0 && p > rev)
|
||||
*(p-1) = 0;
|
||||
} else
|
||||
strcpy(rev, "1.0");
|
||||
|
||||
err = register_filesystem(&capifs_fs_type);
|
||||
if (!err) {
|
||||
capifs_mnt = kern_mount(&capifs_fs_type);
|
||||
if (IS_ERR(capifs_mnt)) {
|
||||
err = PTR_ERR(capifs_mnt);
|
||||
unregister_filesystem(&capifs_fs_type);
|
||||
}
|
||||
}
|
||||
if (!err)
|
||||
printk(KERN_NOTICE "capifs: Rev %s\n", rev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit capifs_exit(void)
|
||||
{
|
||||
unregister_filesystem(&capifs_fs_type);
|
||||
mntput(capifs_mnt);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(capifs_new_ncci);
|
||||
EXPORT_SYMBOL(capifs_free_ncci);
|
||||
|
||||
module_init(capifs_init);
|
||||
module_exit(capifs_exit);
|
||||
11
drivers/isdn/capi/capifs.h
Normal file
11
drivers/isdn/capi/capifs.h
Normal file
@@ -0,0 +1,11 @@
|
||||
/* $Id: capifs.h,v 1.1.1.1 2007/06/12 07:27:09 eyryu Exp $
|
||||
*
|
||||
* Copyright 2000 by Carsten Paeth <calle@calle.de>
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
void capifs_new_ncci(unsigned int num, dev_t device);
|
||||
void capifs_free_ncci(unsigned int num);
|
||||
200
drivers/isdn/capi/capilib.c
Normal file
200
drivers/isdn/capi/capilib.c
Normal file
@@ -0,0 +1,200 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/isdn/capilli.h>
|
||||
|
||||
#define DBG(format, arg...) do { \
|
||||
printk(KERN_DEBUG "%s: " format "\n" , __FUNCTION__ , ## arg); \
|
||||
} while (0)
|
||||
|
||||
struct capilib_msgidqueue {
|
||||
struct capilib_msgidqueue *next;
|
||||
u16 msgid;
|
||||
};
|
||||
|
||||
struct capilib_ncci {
|
||||
struct list_head list;
|
||||
u16 applid;
|
||||
u32 ncci;
|
||||
u32 winsize;
|
||||
int nmsg;
|
||||
struct capilib_msgidqueue *msgidqueue;
|
||||
struct capilib_msgidqueue *msgidlast;
|
||||
struct capilib_msgidqueue *msgidfree;
|
||||
struct capilib_msgidqueue msgidpool[CAPI_MAXDATAWINDOW];
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// NCCI Handling
|
||||
|
||||
static inline void mq_init(struct capilib_ncci * np)
|
||||
{
|
||||
u_int i;
|
||||
np->msgidqueue = NULL;
|
||||
np->msgidlast = NULL;
|
||||
np->nmsg = 0;
|
||||
memset(np->msgidpool, 0, sizeof(np->msgidpool));
|
||||
np->msgidfree = &np->msgidpool[0];
|
||||
for (i = 1; i < np->winsize; i++) {
|
||||
np->msgidpool[i].next = np->msgidfree;
|
||||
np->msgidfree = &np->msgidpool[i];
|
||||
}
|
||||
}
|
||||
|
||||
static inline int mq_enqueue(struct capilib_ncci * np, u16 msgid)
|
||||
{
|
||||
struct capilib_msgidqueue *mq;
|
||||
if ((mq = np->msgidfree) == 0)
|
||||
return 0;
|
||||
np->msgidfree = mq->next;
|
||||
mq->msgid = msgid;
|
||||
mq->next = NULL;
|
||||
if (np->msgidlast)
|
||||
np->msgidlast->next = mq;
|
||||
np->msgidlast = mq;
|
||||
if (!np->msgidqueue)
|
||||
np->msgidqueue = mq;
|
||||
np->nmsg++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int mq_dequeue(struct capilib_ncci * np, u16 msgid)
|
||||
{
|
||||
struct capilib_msgidqueue **pp;
|
||||
for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) {
|
||||
if ((*pp)->msgid == msgid) {
|
||||
struct capilib_msgidqueue *mq = *pp;
|
||||
*pp = mq->next;
|
||||
if (mq == np->msgidlast)
|
||||
np->msgidlast = NULL;
|
||||
mq->next = np->msgidfree;
|
||||
np->msgidfree = mq;
|
||||
np->nmsg--;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void capilib_new_ncci(struct list_head *head, u16 applid, u32 ncci, u32 winsize)
|
||||
{
|
||||
struct capilib_ncci *np;
|
||||
|
||||
np = kmalloc(sizeof(*np), GFP_ATOMIC);
|
||||
if (!np) {
|
||||
printk(KERN_WARNING "capilib_new_ncci: no memory.\n");
|
||||
return;
|
||||
}
|
||||
if (winsize > CAPI_MAXDATAWINDOW) {
|
||||
printk(KERN_ERR "capi_new_ncci: winsize %d too big\n",
|
||||
winsize);
|
||||
winsize = CAPI_MAXDATAWINDOW;
|
||||
}
|
||||
np->applid = applid;
|
||||
np->ncci = ncci;
|
||||
np->winsize = winsize;
|
||||
mq_init(np);
|
||||
list_add_tail(&np->list, head);
|
||||
DBG("kcapi: appl %d ncci 0x%x up", applid, ncci);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(capilib_new_ncci);
|
||||
|
||||
void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci)
|
||||
{
|
||||
struct list_head *l;
|
||||
struct capilib_ncci *np;
|
||||
|
||||
list_for_each(l, head) {
|
||||
np = list_entry(l, struct capilib_ncci, list);
|
||||
if (np->applid != applid)
|
||||
continue;
|
||||
if (np->ncci != ncci)
|
||||
continue;
|
||||
printk(KERN_INFO "kcapi: appl %d ncci 0x%x down\n", applid, ncci);
|
||||
list_del(&np->list);
|
||||
kfree(np);
|
||||
return;
|
||||
}
|
||||
printk(KERN_ERR "capilib_free_ncci: ncci 0x%x not found\n", ncci);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(capilib_free_ncci);
|
||||
|
||||
void capilib_release_appl(struct list_head *head, u16 applid)
|
||||
{
|
||||
struct list_head *l, *n;
|
||||
struct capilib_ncci *np;
|
||||
|
||||
list_for_each_safe(l, n, head) {
|
||||
np = list_entry(l, struct capilib_ncci, list);
|
||||
if (np->applid != applid)
|
||||
continue;
|
||||
printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down\n", applid, np->ncci);
|
||||
list_del(&np->list);
|
||||
kfree(np);
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(capilib_release_appl);
|
||||
|
||||
void capilib_release(struct list_head *head)
|
||||
{
|
||||
struct list_head *l, *n;
|
||||
struct capilib_ncci *np;
|
||||
|
||||
list_for_each_safe(l, n, head) {
|
||||
np = list_entry(l, struct capilib_ncci, list);
|
||||
printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down\n", np->applid, np->ncci);
|
||||
list_del(&np->list);
|
||||
kfree(np);
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(capilib_release);
|
||||
|
||||
u16 capilib_data_b3_req(struct list_head *head, u16 applid, u32 ncci, u16 msgid)
|
||||
{
|
||||
struct list_head *l;
|
||||
struct capilib_ncci *np;
|
||||
|
||||
list_for_each(l, head) {
|
||||
np = list_entry(l, struct capilib_ncci, list);
|
||||
if (np->applid != applid)
|
||||
continue;
|
||||
if (np->ncci != ncci)
|
||||
continue;
|
||||
|
||||
if (mq_enqueue(np, msgid) == 0)
|
||||
return CAPI_SENDQUEUEFULL;
|
||||
|
||||
return CAPI_NOERROR;
|
||||
}
|
||||
printk(KERN_ERR "capilib_data_b3_req: ncci 0x%x not found\n", ncci);
|
||||
return CAPI_NOERROR;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(capilib_data_b3_req);
|
||||
|
||||
void capilib_data_b3_conf(struct list_head *head, u16 applid, u32 ncci, u16 msgid)
|
||||
{
|
||||
struct list_head *l;
|
||||
struct capilib_ncci *np;
|
||||
|
||||
list_for_each(l, head) {
|
||||
np = list_entry(l, struct capilib_ncci, list);
|
||||
if (np->applid != applid)
|
||||
continue;
|
||||
if (np->ncci != ncci)
|
||||
continue;
|
||||
|
||||
if (mq_dequeue(np, msgid) == 0) {
|
||||
printk(KERN_ERR "kcapi: msgid %hu ncci 0x%x not on queue\n",
|
||||
msgid, ncci);
|
||||
}
|
||||
return;
|
||||
}
|
||||
printk(KERN_ERR "capilib_data_b3_conf: ncci 0x%x not found\n", ncci);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(capilib_data_b3_conf);
|
||||
1020
drivers/isdn/capi/capiutil.c
Normal file
1020
drivers/isdn/capi/capiutil.c
Normal file
File diff suppressed because it is too large
Load Diff
1027
drivers/isdn/capi/kcapi.c
Normal file
1027
drivers/isdn/capi/kcapi.c
Normal file
File diff suppressed because it is too large
Load Diff
49
drivers/isdn/capi/kcapi.h
Normal file
49
drivers/isdn/capi/kcapi.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Kernel CAPI 2.0 Module
|
||||
*
|
||||
* Copyright 1999 by Carsten Paeth <calle@calle.de>
|
||||
* Copyright 2002 by Kai Germaschewski <kai@germaschewski.name>
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/isdn/capilli.h>
|
||||
|
||||
#ifdef KCAPI_DEBUG
|
||||
#define DBG(format, arg...) do { \
|
||||
printk(KERN_DEBUG "%s: " format "\n" , __FUNCTION__ , ## arg); \
|
||||
} while (0)
|
||||
#else
|
||||
#define DBG(format, arg...) /* */
|
||||
#endif
|
||||
|
||||
enum {
|
||||
CARD_DETECTED = 1,
|
||||
CARD_LOADING = 2,
|
||||
CARD_RUNNING = 3,
|
||||
};
|
||||
|
||||
extern struct list_head capi_drivers;
|
||||
extern rwlock_t capi_drivers_list_lock;
|
||||
|
||||
extern struct capi20_appl *capi_applications[CAPI_MAXAPPL];
|
||||
extern struct capi_ctr *capi_cards[CAPI_MAXCONTR];
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
||||
void kcapi_proc_init(void);
|
||||
void kcapi_proc_exit(void);
|
||||
|
||||
#else
|
||||
|
||||
static inline void kcapi_proc_init(void) { };
|
||||
static inline void kcapi_proc_exit(void) { };
|
||||
|
||||
#endif
|
||||
|
||||
336
drivers/isdn/capi/kcapi_proc.c
Normal file
336
drivers/isdn/capi/kcapi_proc.c
Normal file
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Kernel CAPI 2.0 Module - /proc/capi handling
|
||||
*
|
||||
* Copyright 1999 by Carsten Paeth <calle@calle.de>
|
||||
* Copyright 2002 by Kai Germaschewski <kai@germaschewski.name>
|
||||
*
|
||||
* This software may be used and distributed according to the terms
|
||||
* of the GNU General Public License, incorporated herein by reference.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "kcapi.h"
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
static char *
|
||||
cardstate2str(unsigned short cardstate)
|
||||
{
|
||||
switch (cardstate) {
|
||||
case CARD_DETECTED: return "detected";
|
||||
case CARD_LOADING: return "loading";
|
||||
case CARD_RUNNING: return "running";
|
||||
default: return "???";
|
||||
}
|
||||
}
|
||||
|
||||
// /proc/capi
|
||||
// ===========================================================================
|
||||
|
||||
// /proc/capi/controller:
|
||||
// cnr driver cardstate name driverinfo
|
||||
// /proc/capi/contrstats:
|
||||
// cnr nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static void *controller_start(struct seq_file *seq, loff_t *pos)
|
||||
{
|
||||
if (*pos < CAPI_MAXCONTR)
|
||||
return &capi_cards[*pos];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *controller_next(struct seq_file *seq, void *v, loff_t *pos)
|
||||
{
|
||||
++*pos;
|
||||
if (*pos < CAPI_MAXCONTR)
|
||||
return &capi_cards[*pos];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void controller_stop(struct seq_file *seq, void *v)
|
||||
{
|
||||
}
|
||||
|
||||
static int controller_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct capi_ctr *ctr = *(struct capi_ctr **) v;
|
||||
|
||||
if (!ctr)
|
||||
return 0;
|
||||
|
||||
seq_printf(seq, "%d %-10s %-8s %-16s %s\n",
|
||||
ctr->cnr, ctr->driver_name,
|
||||
cardstate2str(ctr->cardstate),
|
||||
ctr->name,
|
||||
ctr->procinfo ? ctr->procinfo(ctr) : "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int contrstats_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct capi_ctr *ctr = *(struct capi_ctr **) v;
|
||||
|
||||
if (!ctr)
|
||||
return 0;
|
||||
|
||||
seq_printf(seq, "%d %lu %lu %lu %lu\n",
|
||||
ctr->cnr,
|
||||
ctr->nrecvctlpkt,
|
||||
ctr->nrecvdatapkt,
|
||||
ctr->nsentctlpkt,
|
||||
ctr->nsentdatapkt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct seq_operations seq_controller_ops = {
|
||||
.start = controller_start,
|
||||
.next = controller_next,
|
||||
.stop = controller_stop,
|
||||
.show = controller_show,
|
||||
};
|
||||
|
||||
static struct seq_operations seq_contrstats_ops = {
|
||||
.start = controller_start,
|
||||
.next = controller_next,
|
||||
.stop = controller_stop,
|
||||
.show = contrstats_show,
|
||||
};
|
||||
|
||||
static int seq_controller_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open(file, &seq_controller_ops);
|
||||
}
|
||||
|
||||
static int seq_contrstats_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open(file, &seq_contrstats_ops);
|
||||
}
|
||||
|
||||
static const struct file_operations proc_controller_ops = {
|
||||
.open = seq_controller_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
};
|
||||
|
||||
static const struct file_operations proc_contrstats_ops = {
|
||||
.open = seq_contrstats_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
};
|
||||
|
||||
// /proc/capi/applications:
|
||||
// applid l3cnt dblkcnt dblklen #ncci recvqueuelen
|
||||
// /proc/capi/applstats:
|
||||
// applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static void *
|
||||
applications_start(struct seq_file *seq, loff_t *pos)
|
||||
{
|
||||
if (*pos < CAPI_MAXAPPL)
|
||||
return &capi_applications[*pos];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
applications_next(struct seq_file *seq, void *v, loff_t *pos)
|
||||
{
|
||||
++*pos;
|
||||
if (*pos < CAPI_MAXAPPL)
|
||||
return &capi_applications[*pos];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
applications_stop(struct seq_file *seq, void *v)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
applications_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct capi20_appl *ap = *(struct capi20_appl **) v;
|
||||
|
||||
if (!ap)
|
||||
return 0;
|
||||
|
||||
seq_printf(seq, "%u %d %d %d\n",
|
||||
ap->applid,
|
||||
ap->rparam.level3cnt,
|
||||
ap->rparam.datablkcnt,
|
||||
ap->rparam.datablklen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
applstats_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct capi20_appl *ap = *(struct capi20_appl **) v;
|
||||
|
||||
if (!ap)
|
||||
return 0;
|
||||
|
||||
seq_printf(seq, "%u %lu %lu %lu %lu\n",
|
||||
ap->applid,
|
||||
ap->nrecvctlpkt,
|
||||
ap->nrecvdatapkt,
|
||||
ap->nsentctlpkt,
|
||||
ap->nsentdatapkt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct seq_operations seq_applications_ops = {
|
||||
.start = applications_start,
|
||||
.next = applications_next,
|
||||
.stop = applications_stop,
|
||||
.show = applications_show,
|
||||
};
|
||||
|
||||
static struct seq_operations seq_applstats_ops = {
|
||||
.start = applications_start,
|
||||
.next = applications_next,
|
||||
.stop = applications_stop,
|
||||
.show = applstats_show,
|
||||
};
|
||||
|
||||
static int
|
||||
seq_applications_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open(file, &seq_applications_ops);
|
||||
}
|
||||
|
||||
static int
|
||||
seq_applstats_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open(file, &seq_applstats_ops);
|
||||
}
|
||||
|
||||
static const struct file_operations proc_applications_ops = {
|
||||
.open = seq_applications_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
};
|
||||
|
||||
static const struct file_operations proc_applstats_ops = {
|
||||
.open = seq_applstats_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
};
|
||||
|
||||
static void
|
||||
create_seq_entry(char *name, mode_t mode, const struct file_operations *f)
|
||||
{
|
||||
struct proc_dir_entry *entry;
|
||||
entry = create_proc_entry(name, mode, NULL);
|
||||
if (entry)
|
||||
entry->proc_fops = f;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
static __inline__ struct capi_driver *capi_driver_get_idx(loff_t pos)
|
||||
{
|
||||
struct capi_driver *drv = NULL;
|
||||
struct list_head *l;
|
||||
loff_t i;
|
||||
|
||||
i = 0;
|
||||
list_for_each(l, &capi_drivers) {
|
||||
drv = list_entry(l, struct capi_driver, list);
|
||||
if (i++ == pos)
|
||||
return drv;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *capi_driver_start(struct seq_file *seq, loff_t *pos)
|
||||
{
|
||||
struct capi_driver *drv;
|
||||
read_lock(&capi_drivers_list_lock);
|
||||
drv = capi_driver_get_idx(*pos);
|
||||
return drv;
|
||||
}
|
||||
|
||||
static void *capi_driver_next(struct seq_file *seq, void *v, loff_t *pos)
|
||||
{
|
||||
struct capi_driver *drv = (struct capi_driver *)v;
|
||||
++*pos;
|
||||
if (drv->list.next == &capi_drivers) return NULL;
|
||||
return list_entry(drv->list.next, struct capi_driver, list);
|
||||
}
|
||||
|
||||
static void capi_driver_stop(struct seq_file *seq, void *v)
|
||||
{
|
||||
read_unlock(&capi_drivers_list_lock);
|
||||
}
|
||||
|
||||
static int capi_driver_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct capi_driver *drv = (struct capi_driver *)v;
|
||||
seq_printf(seq, "%-32s %s\n", drv->name, drv->revision);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct seq_operations seq_capi_driver_ops = {
|
||||
.start = capi_driver_start,
|
||||
.next = capi_driver_next,
|
||||
.stop = capi_driver_stop,
|
||||
.show = capi_driver_show,
|
||||
};
|
||||
|
||||
static int
|
||||
seq_capi_driver_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int err;
|
||||
err = seq_open(file, &seq_capi_driver_ops);
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct file_operations proc_driver_ops = {
|
||||
.open = seq_capi_driver_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void __init
|
||||
kcapi_proc_init(void)
|
||||
{
|
||||
proc_mkdir("capi", NULL);
|
||||
proc_mkdir("capi/controllers", NULL);
|
||||
create_seq_entry("capi/controller", 0, &proc_controller_ops);
|
||||
create_seq_entry("capi/contrstats", 0, &proc_contrstats_ops);
|
||||
create_seq_entry("capi/applications", 0, &proc_applications_ops);
|
||||
create_seq_entry("capi/applstats", 0, &proc_applstats_ops);
|
||||
create_seq_entry("capi/driver", 0, &proc_driver_ops);
|
||||
}
|
||||
|
||||
void __exit
|
||||
kcapi_proc_exit(void)
|
||||
{
|
||||
remove_proc_entry("capi/driver", NULL);
|
||||
remove_proc_entry("capi/controller", NULL);
|
||||
remove_proc_entry("capi/contrstats", NULL);
|
||||
remove_proc_entry("capi/applications", NULL);
|
||||
remove_proc_entry("capi/applstats", NULL);
|
||||
remove_proc_entry("capi/controllers", NULL);
|
||||
remove_proc_entry("capi", NULL);
|
||||
}
|
||||
Reference in New Issue
Block a user