⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kcapi.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $Id: kcapi.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $ *  * Kernel CAPI 2.0 Module *  * Copyright 1999 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. * */#define CONFIG_AVMB1_COMPAT#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/interrupt.h>#include <linux/ioport.h>#include <asm/segment.h>#include <linux/proc_fs.h>#include <linux/skbuff.h>#include <linux/tqueue.h>#include <linux/capi.h>#include <linux/kernelcapi.h>#include <linux/locks.h>#include <linux/init.h>#include <asm/uaccess.h>#include "capicmd.h"#include "capiutil.h"#include "capilli.h"#ifdef CONFIG_AVMB1_COMPAT#include <linux/b1lli.h>#endifstatic char *revision = "$Revision: 1.1.4.1 $";/* ------------------------------------------------------------- */#define CARD_FREE	0#define CARD_DETECTED	1#define CARD_LOADING	2#define CARD_RUNNING	3/* ------------------------------------------------------------- */static int showcapimsgs = 0;MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer");MODULE_AUTHOR("Carsten Paeth");MODULE_LICENSE("GPL");MODULE_PARM(showcapimsgs, "i");/* ------------------------------------------------------------- */struct msgidqueue {	struct msgidqueue *next;	__u16 msgid;};struct capi_ncci {	struct capi_ncci *next;	__u16 applid;	__u32 ncci;	__u32 winsize;	int   nmsg;	struct msgidqueue *msgidqueue;	struct msgidqueue *msgidlast;	struct msgidqueue *msgidfree;	struct msgidqueue msgidpool[CAPI_MAXDATAWINDOW];};struct capi_appl {	__u16 applid;	capi_register_params rparam;	int releasing;	void *param;	void (*signal) (__u16 applid, void *param);	struct sk_buff_head recv_queue;	int nncci;	struct capi_ncci *nccilist;	unsigned long nrecvctlpkt;	unsigned long nrecvdatapkt;	unsigned long nsentctlpkt;	unsigned long nsentdatapkt;};struct capi_notifier {	struct capi_notifier *next;	unsigned int cmd;	__u32 controller;	__u16 applid;	__u32 ncci;};/* ------------------------------------------------------------- */static struct capi_version driver_version = {2, 0, 1, 1<<4};static char driver_serial[CAPI_SERIAL_LEN] = "0004711";static char capi_manufakturer[64] = "AVM Berlin";#define APPL(a)		   (&applications[(a)-1])#define	VALID_APPLID(a)	   ((a) && (a) <= CAPI_MAXAPPL && APPL(a)->applid == a)#define APPL_IS_FREE(a)    (APPL(a)->applid == 0)#define APPL_MARK_FREE(a)  do{ APPL(a)->applid=0; MOD_DEC_USE_COUNT; }while(0);#define APPL_MARK_USED(a)  do{ APPL(a)->applid=(a); MOD_INC_USE_COUNT; }while(0);#define NCCI2CTRL(ncci)    (((ncci) >> 24) & 0x7f)#define VALID_CARD(c)	   ((c) > 0 && (c) <= CAPI_MAXCONTR)#define CARD(c)		   (&cards[(c)-1])#define CARDNR(cp)	   (((cp)-cards)+1)static struct capi_appl applications[CAPI_MAXAPPL];static struct capi_ctr cards[CAPI_MAXCONTR];static int ncards = 0;static struct sk_buff_head recv_queue;static struct capi_interface_user *capi_users = 0;static spinlock_t capi_users_lock = SPIN_LOCK_UNLOCKED;static struct capi_driver *drivers;static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED;static struct tq_struct tq_state_notify;static struct tq_struct tq_recv_notify;/* -------- util functions ------------------------------------ */static char *cardstate2str(unsigned short cardstate){	switch (cardstate) {        	default:		case CARD_FREE:		return "free";		case CARD_DETECTED:	return "detected";		case CARD_LOADING:	return "loading";		case CARD_RUNNING:	return "running";	}}static inline int capi_cmd_valid(__u8 cmd){	switch (cmd) {	case CAPI_ALERT:	case CAPI_CONNECT:	case CAPI_CONNECT_ACTIVE:	case CAPI_CONNECT_B3_ACTIVE:	case CAPI_CONNECT_B3:	case CAPI_CONNECT_B3_T90_ACTIVE:	case CAPI_DATA_B3:	case CAPI_DISCONNECT_B3:	case CAPI_DISCONNECT:	case CAPI_FACILITY:	case CAPI_INFO:	case CAPI_LISTEN:	case CAPI_MANUFACTURER:	case CAPI_RESET_B3:	case CAPI_SELECT_B_PROTOCOL:		return 1;	}	return 0;}static inline int capi_subcmd_valid(__u8 subcmd){	switch (subcmd) {	case CAPI_REQ:	case CAPI_CONF:	case CAPI_IND:	case CAPI_RESP:		return 1;	}	return 0;}/* -------- /proc functions ----------------------------------- *//* * /proc/capi/applications: *      applid l3cnt dblkcnt dblklen #ncci recvqueuelen */static int proc_applications_read_proc(char *page, char **start, off_t off,                                       int count, int *eof, void *data){	struct capi_appl *ap;	int i;	int len = 0;	for (i=0; i < CAPI_MAXAPPL; i++) {		ap = &applications[i];		if (ap->applid == 0) continue;		len += sprintf(page+len, "%u %d %d %d %d %d\n",			ap->applid,			ap->rparam.level3cnt,			ap->rparam.datablkcnt,			ap->rparam.datablklen,			ap->nncci,                        skb_queue_len(&ap->recv_queue));		if (len <= off) {			off -= len;			len = 0;		} else {			if (len-off > count)				goto endloop;		}	}endloop:	*start = page+off;	if (len < count)		*eof = 1;	if (len>count) len = count;	if (len<0) len = 0;	return len;}/* * /proc/capi/ncci: *	applid ncci winsize nblk */static int proc_ncci_read_proc(char *page, char **start, off_t off,                                       int count, int *eof, void *data){	struct capi_appl *ap;	struct capi_ncci *np;	int i;	int len = 0;	for (i=0; i < CAPI_MAXAPPL; i++) {		ap = &applications[i];		if (ap->applid == 0) continue;		for (np = ap->nccilist; np; np = np->next) {			len += sprintf(page+len, "%d 0x%x %d %d\n",				np->applid,				np->ncci,				np->winsize,				np->nmsg);			if (len <= off) {				off -= len;				len = 0;			} else {				if (len-off > count)					goto endloop;			}		}	}endloop:	*start = page+off;	if (len < count)		*eof = 1;	if (len>count) len = count;	if (len<0) len = 0;	return len;}/* * /proc/capi/driver: *	driver ncontroller */static int proc_driver_read_proc(char *page, char **start, off_t off,                                       int count, int *eof, void *data){	struct capi_driver *driver;	int len = 0;	spin_lock(&drivers_lock);	for (driver = drivers; driver; driver = driver->next) {		len += sprintf(page+len, "%-32s %d %s\n",					driver->name,					driver->ncontroller,					driver->revision);		if (len <= off) {			off -= len;			len = 0;		} else {			if (len-off > count)				goto endloop;		}	}endloop:	spin_unlock(&drivers_lock);	*start = page+off;	if (len < count)		*eof = 1;	if (len>count) len = count;	if (len<0) len = 0;	return len;}/* * /proc/capi/users: *	name */static int proc_users_read_proc(char *page, char **start, off_t off,                                       int count, int *eof, void *data){        struct capi_interface_user *cp;	int len = 0;	spin_lock(&capi_users_lock);        for (cp = capi_users; cp ; cp = cp->next) {		len += sprintf(page+len, "%s\n", cp->name);		if (len <= off) {			off -= len;			len = 0;		} else {			if (len-off > count)				goto endloop;		}	}endloop:	spin_unlock(&capi_users_lock);	*start = page+off;	if (len < count)		*eof = 1;	if (len>count) len = count;	if (len<0) len = 0;	return len;}/* * /proc/capi/controller: *	cnr driver cardstate name driverinfo */static int proc_controller_read_proc(char *page, char **start, off_t off,                                       int count, int *eof, void *data){	struct capi_ctr *cp;	int i;	int len = 0;	for (i=0; i < CAPI_MAXCONTR; i++) {		cp = &cards[i];		if (cp->cardstate == CARD_FREE) continue;		len += sprintf(page+len, "%d %-10s %-8s %-16s %s\n",			cp->cnr, cp->driver->name, 			cardstate2str(cp->cardstate),			cp->name,			cp->driver->procinfo ?  cp->driver->procinfo(cp) : ""			);		if (len <= off) {			off -= len;			len = 0;		} else {			if (len-off > count)				goto endloop;		}	}endloop:	*start = page+off;	if (len < count)		*eof = 1;	if (len>count) len = count;	if (len<0) len = 0;	return len;}/* * /proc/capi/applstats: *	applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt */static int proc_applstats_read_proc(char *page, char **start, off_t off,                                       int count, int *eof, void *data){	struct capi_appl *ap;	int i;	int len = 0;	for (i=0; i < CAPI_MAXAPPL; i++) {		ap = &applications[i];		if (ap->applid == 0) continue;		len += sprintf(page+len, "%u %lu %lu %lu %lu\n",			ap->applid,			ap->nrecvctlpkt,			ap->nrecvdatapkt,			ap->nsentctlpkt,			ap->nsentdatapkt);		if (len <= off) {			off -= len;			len = 0;		} else {			if (len-off > count)				goto endloop;		}	}endloop:	*start = page+off;	if (len < count)		*eof = 1;	if (len>count) len = count;	if (len<0) len = 0;	return len;}/* * /proc/capi/contrstats: *	cnr nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt */static int proc_contrstats_read_proc(char *page, char **start, off_t off,                                       int count, int *eof, void *data){	struct capi_ctr *cp;	int i;	int len = 0;	for (i=0; i < CAPI_MAXCONTR; i++) {		cp = &cards[i];		if (cp->cardstate == CARD_FREE) continue;		len += sprintf(page+len, "%d %lu %lu %lu %lu\n",			cp->cnr, 			cp->nrecvctlpkt,			cp->nrecvdatapkt,			cp->nsentctlpkt,			cp->nsentdatapkt);		if (len <= off) {			off -= len;			len = 0;		} else {			if (len-off > count)				goto endloop;		}	}endloop:	*start = page+off;	if (len < count)		*eof = 1;	if (len>count) len = count;	if (len<0) len = 0;	return len;}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/applications", 0	 , proc_applications_read_proc },   { "capi/ncci", 	  0	 , proc_ncci_read_proc },   { "capi/driver",       0	 , proc_driver_read_proc },   { "capi/users", 	  0	 , proc_users_read_proc },   { "capi/controller",   0	 , proc_controller_read_proc },   { "capi/applstats",    0	 , proc_applstats_read_proc },   { "capi/contrstats",   0	 , proc_contrstats_read_proc },   { "capi/drivers",	  S_IFDIR, 0 },   { "capi/controllers",  S_IFDIR, 0 },};static void proc_capi_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_capi_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;	}    }}/* -------- Notifier handling --------------------------------- */static struct capi_notifier_list{	struct capi_notifier *head;	struct capi_notifier *tail;} notifier_list;static spinlock_t notifier_lock = SPIN_LOCK_UNLOCKED;static inline void notify_enqueue(struct capi_notifier *np){	struct capi_notifier_list *q = &notifier_list;	unsigned long flags;	spin_lock_irqsave(&notifier_lock, flags);	if (q->tail) {		q->tail->next = np;		q->tail = np;	} else {		q->head = q->tail = np;	}	spin_unlock_irqrestore(&notifier_lock, flags);}static inline struct capi_notifier *notify_dequeue(void){	struct capi_notifier_list *q = &notifier_list;	struct capi_notifier *np = 0;	unsigned long flags;	spin_lock_irqsave(&notifier_lock, flags);	if (q->head) {		np = q->head;		if ((q->head = np->next) == 0) 			q->tail = 0;		np->next = 0;	}	spin_unlock_irqrestore(&notifier_lock, flags);	return np;}static int notify_push(unsigned int cmd, __u32 controller,				__u16 applid, __u32 ncci){	struct capi_notifier *np;	MOD_INC_USE_COUNT;	np = (struct capi_notifier *)kmalloc(sizeof(struct capi_notifier), GFP_ATOMIC);	if (!np) {		MOD_DEC_USE_COUNT;		return -1;	}	memset(np, 0, sizeof(struct capi_notifier));	np->cmd = cmd;	np->controller = controller;	np->applid = applid;	np->ncci = ncci;	notify_enqueue(np);	/*	 * The notifier will result in adding/deleteing	 * of devices. Devices can only removed in	 * user process, not in bh.	 */	MOD_INC_USE_COUNT;	if (schedule_task(&tq_state_notify) == 0)		MOD_DEC_USE_COUNT;	return 0;}/* -------- KCI_CONTRUP --------------------------------------- */static void notify_up(__u32 contr){	struct capi_interface_user *p;        printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr);	spin_lock(&capi_users_lock);	for (p = capi_users; p; p = p->next) {		if (!p->callback) continue;		(*p->callback) (KCI_CONTRUP, contr, &CARD(contr)->profile);	}	spin_unlock(&capi_users_lock);}/* -------- KCI_CONTRDOWN ------------------------------------- */static void notify_down(__u32 contr){	struct capi_interface_user *p;        printk(KERN_NOTICE "kcapi: notify down contr %d\n", contr);	spin_lock(&capi_users_lock);	for (p = capi_users; p; p = p->next) {		if (!p->callback) continue;		(*p->callback) (KCI_CONTRDOWN, contr, 0);	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -