kcapi.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:41k
- /* $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>
- #endif
- static 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 %dn",
- 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 %dn",
- 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 %sn",
- 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, "%sn", 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 %sn",
- 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 %lun",
- 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 %lun",
- 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 = ¬ifier_list;
- unsigned long flags;
- spin_lock_irqsave(¬ifier_lock, flags);
- if (q->tail) {
- q->tail->next = np;
- q->tail = np;
- } else {
- q->head = q->tail = np;
- }
- spin_unlock_irqrestore(¬ifier_lock, flags);
- }
- static inline struct capi_notifier *notify_dequeue(void)
- {
- struct capi_notifier_list *q = ¬ifier_list;
- struct capi_notifier *np = 0;
- unsigned long flags;
- spin_lock_irqsave(¬ifier_lock, flags);
- if (q->head) {
- np = q->head;
- if ((q->head = np->next) == 0)
- q->tail = 0;
- np->next = 0;
- }
- spin_unlock_irqrestore(¬ifier_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 %dn", 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 %dn", contr);
- spin_lock(&capi_users_lock);
- for (p = capi_users; p; p = p->next) {
- if (!p->callback) continue;
- (*p->callback) (KCI_CONTRDOWN, contr, 0);
- }
- spin_unlock(&capi_users_lock);
- }
- /* -------- KCI_NCCIUP ---------------------------------------- */
- static void notify_ncciup(__u32 contr, __u16 applid, __u32 ncci)
- {
- struct capi_interface_user *p;
- struct capi_ncciinfo n;
- n.applid = applid;
- n.ncci = ncci;
- /*printk(KERN_NOTICE "kcapi: notify up contr %dn", contr);*/
- spin_lock(&capi_users_lock);
- for (p = capi_users; p; p = p->next) {
- if (!p->callback) continue;
- (*p->callback) (KCI_NCCIUP, contr, &n);
- }
- spin_unlock(&capi_users_lock);
- };
- /* -------- KCI_NCCIDOWN -------------------------------------- */
- static void notify_nccidown(__u32 contr, __u16 applid, __u32 ncci)
- {
- struct capi_interface_user *p;
- struct capi_ncciinfo n;
- n.applid = applid;
- n.ncci = ncci;
- /*printk(KERN_NOTICE "kcapi: notify down contr %dn", contr);*/
- spin_lock(&capi_users_lock);
- for (p = capi_users; p; p = p->next) {
- if (!p->callback) continue;
- (*p->callback) (KCI_NCCIDOWN, contr, &n);
- }
- spin_unlock(&capi_users_lock);
- };
- /* ------------------------------------------------------------ */
- static void inline notify_doit(struct capi_notifier *np)
- {
- switch (np->cmd) {
- case KCI_CONTRUP:
- notify_up(np->controller);
- break;
- case KCI_CONTRDOWN:
- notify_down(np->controller);
- break;
- case KCI_NCCIUP:
- notify_ncciup(np->controller, np->applid, np->ncci);
- break;
- case KCI_NCCIDOWN:
- notify_nccidown(np->controller, np->applid, np->ncci);
- break;
- }
- }
- static void notify_handler(void *dummy)
- {
- struct capi_notifier *np;
- while ((np = notify_dequeue()) != 0) {
- notify_doit(np);
- kfree(np);
- MOD_DEC_USE_COUNT;
- }
- MOD_DEC_USE_COUNT;
- }
-
- /* -------- NCCI Handling ------------------------------------- */
- static inline void mq_init(struct capi_ncci * np)
- {
- int i;
- np->msgidqueue = 0;
- np->msgidlast = 0;
- 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 capi_ncci * np, __u16 msgid)
- {
- struct msgidqueue *mq;
- if ((mq = np->msgidfree) == 0)
- return 0;
- np->msgidfree = mq->next;
- mq->msgid = msgid;
- mq->next = 0;
- 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 capi_ncci * np, __u16 msgid)
- {
- struct msgidqueue **pp;
- for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) {
- if ((*pp)->msgid == msgid) {
- struct msgidqueue *mq = *pp;
- *pp = mq->next;
- if (mq == np->msgidlast)
- np->msgidlast = 0;
- mq->next = np->msgidfree;
- np->msgidfree = mq;
- np->nmsg--;
- return 1;
- }
- }
- return 0;
- }
- static void controllercb_appl_registered(struct capi_ctr * card, __u16 appl)
- {
- }
- static void controllercb_appl_released(struct capi_ctr * card, __u16 appl)
- {
- struct capi_ncci **pp, **nextpp;
- for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) {
- if (NCCI2CTRL((*pp)->ncci) == card->cnr) {
- struct capi_ncci *np = *pp;
- *pp = np->next;
- printk(KERN_INFO "kcapi: appl %d ncci 0x%x down!n", appl, np->ncci);
- kfree(np);
- APPL(appl)->nncci--;
- nextpp = pp;
- } else {
- nextpp = &(*pp)->next;
- }
- }
- APPL(appl)->releasing--;
- if (APPL(appl)->releasing <= 0) {
- APPL(appl)->signal = 0;
- APPL_MARK_FREE(appl);
- printk(KERN_INFO "kcapi: appl %d downn", appl);
- }
- }
- /*
- * ncci management
- */
- static void controllercb_new_ncci(struct capi_ctr * card,
- __u16 appl, __u32 ncci, __u32 winsize)
- {
- struct capi_ncci *np;
- if (!VALID_APPLID(appl)) {
- printk(KERN_ERR "avmb1_handle_new_ncci: illegal appl %dn", appl);
- return;
- }
- if ((np = (struct capi_ncci *) kmalloc(sizeof(struct capi_ncci), GFP_ATOMIC)) == 0) {
- printk(KERN_ERR "capi_new_ncci: alloc failed ncci 0x%xn", ncci);
- return;
- }
- if (winsize > CAPI_MAXDATAWINDOW) {
- printk(KERN_ERR "capi_new_ncci: winsize %d too big, set to %dn",
- winsize, CAPI_MAXDATAWINDOW);
- winsize = CAPI_MAXDATAWINDOW;
- }
- np->applid = appl;
- np->ncci = ncci;
- np->winsize = winsize;
- mq_init(np);
- np->next = APPL(appl)->nccilist;
- APPL(appl)->nccilist = np;
- APPL(appl)->nncci++;
- printk(KERN_INFO "kcapi: appl %d ncci 0x%x upn", appl, ncci);
- notify_push(KCI_NCCIUP, CARDNR(card), appl, ncci);
- }
- static void controllercb_free_ncci(struct capi_ctr * card,
- __u16 appl, __u32 ncci)
- {
- struct capi_ncci **pp;
- if (!VALID_APPLID(appl)) {
- printk(KERN_ERR "free_ncci: illegal appl %dn", appl);
- return;
- }
- for (pp = &APPL(appl)->nccilist; *pp; pp = &(*pp)->next) {
- if ((*pp)->ncci == ncci) {
- struct capi_ncci *np = *pp;
- *pp = np->next;
- kfree(np);
- APPL(appl)->nncci--;
- printk(KERN_INFO "kcapi: appl %d ncci 0x%x downn", appl, ncci);
- notify_push(KCI_NCCIDOWN, CARDNR(card), appl, ncci);
- return;
- }
- }
- printk(KERN_ERR "free_ncci: ncci 0x%x not foundn", ncci);
- }
- static struct capi_ncci *find_ncci(struct capi_appl * app, __u32 ncci)
- {
- struct capi_ncci *np;
- for (np = app->nccilist; np; np = np->next) {
- if (np->ncci == ncci)
- return np;
- }
- return 0;
- }
- /* -------- Receiver ------------------------------------------ */
- static void recv_handler(void *dummy)
- {
- struct sk_buff *skb;
- while ((skb = skb_dequeue(&recv_queue)) != 0) {
- __u16 appl = CAPIMSG_APPID(skb->data);
- struct capi_ncci *np;
- if (!VALID_APPLID(appl)) {
- printk(KERN_ERR "kcapi: recv_handler: applid %d ? (%s)n",
- appl, capi_message2str(skb->data));
- kfree_skb(skb);
- continue;
- }
- if (APPL(appl)->signal == 0) {
- printk(KERN_ERR "kcapi: recv_handler: applid %d has no signal functionn",
- appl);
- kfree_skb(skb);
- continue;
- }
- if ( CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
- && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF
- && (np = find_ncci(APPL(appl), CAPIMSG_NCCI(skb->data))) != 0
- && mq_dequeue(np, CAPIMSG_MSGID(skb->data)) == 0) {
- printk(KERN_ERR "kcapi: msgid %hu ncci 0x%x not on queuen",
- CAPIMSG_MSGID(skb->data), np->ncci);
- }
- if ( CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
- && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {
- APPL(appl)->nrecvdatapkt++;
- } else {
- APPL(appl)->nrecvctlpkt++;
- }
- skb_queue_tail(&APPL(appl)->recv_queue, skb);
- (APPL(appl)->signal) (APPL(appl)->applid, APPL(appl)->param);
- }
- }
- static void controllercb_handle_capimsg(struct capi_ctr * card,
- __u16 appl, struct sk_buff *skb)
- {
- int showctl = 0;
- __u8 cmd, subcmd;
- if (card->cardstate != CARD_RUNNING) {
- printk(KERN_INFO "kcapi: controller %d not active, got: %s",
- card->cnr, capi_message2str(skb->data));
- goto error;
- }
- cmd = CAPIMSG_COMMAND(skb->data);
- subcmd = CAPIMSG_SUBCOMMAND(skb->data);
- if (cmd == CAPI_DATA_B3 && subcmd == CAPI_IND) {
- card->nrecvdatapkt++;
- if (card->traceflag > 2) showctl |= 2;
- } else {
- card->nrecvctlpkt++;
- if (card->traceflag) showctl |= 2;
- }
- showctl |= (card->traceflag & 1);
- if (showctl & 2) {
- if (showctl & 1) {
- printk(KERN_DEBUG "kcapi: got [0x%lx] id#%d %s len=%un",
- (unsigned long) card->cnr,
- CAPIMSG_APPID(skb->data),
- capi_cmd2str(cmd, subcmd),
- CAPIMSG_LEN(skb->data));
- } else {
- printk(KERN_DEBUG "kcapi: got [0x%lx] %sn",
- (unsigned long) card->cnr,
- capi_message2str(skb->data));
- }
- }
- skb_queue_tail(&recv_queue, skb);
- queue_task(&tq_recv_notify, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
- return;
- error:
- kfree_skb(skb);
- }
- static void controllercb_ready(struct capi_ctr * card)
- {
- __u16 appl;
- card->cardstate = CARD_RUNNING;
- for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
- if (!VALID_APPLID(appl)) continue;
- if (APPL(appl)->releasing) continue;
- card->driver->register_appl(card, appl, &APPL(appl)->rparam);
- }
- printk(KERN_NOTICE "kcapi: card %d "%s" ready.n",
- CARDNR(card), card->name);
- notify_push(KCI_CONTRUP, CARDNR(card), 0, 0);
- }
- static void controllercb_reseted(struct capi_ctr * card)
- {
- __u16 appl;
- if (card->cardstate == CARD_FREE)
- return;
- if (card->cardstate == CARD_DETECTED)
- return;
- card->cardstate = CARD_DETECTED;
- memset(card->manu, 0, sizeof(card->manu));
- memset(&card->version, 0, sizeof(card->version));
- memset(&card->profile, 0, sizeof(card->profile));
- memset(card->serial, 0, sizeof(card->serial));
- for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
- struct capi_ncci **pp, **nextpp;
- for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) {
- if (NCCI2CTRL((*pp)->ncci) == card->cnr) {
- struct capi_ncci *np = *pp;
- *pp = np->next;
- printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down!n", appl, np->ncci);
- notify_push(KCI_NCCIDOWN, CARDNR(card), appl, np->ncci);
- kfree(np);
- nextpp = pp;
- } else {
- nextpp = &(*pp)->next;
- }
- }
- }
- printk(KERN_NOTICE "kcapi: card %d down.n", CARDNR(card));
- notify_push(KCI_CONTRDOWN, CARDNR(card), 0, 0);
- }
- static void controllercb_suspend_output(struct capi_ctr *card)
- {
- if (!card->blocked) {
- printk(KERN_DEBUG "kcapi: card %d suspendn", CARDNR(card));
- card->blocked = 1;
- }
- }
- static void controllercb_resume_output(struct capi_ctr *card)
- {
- if (card->blocked) {
- printk(KERN_DEBUG "kcapi: card %d resumen", CARDNR(card));
- card->blocked = 0;
- }
- }
- /* ------------------------------------------------------------- */
- struct capi_ctr *
- drivercb_attach_ctr(struct capi_driver *driver, char *name, void *driverdata)
- {
- struct capi_ctr *card, **pp;
- int i;
- for (i=0; i < CAPI_MAXCONTR && cards[i].cardstate != CARD_FREE; i++) ;
-
- if (i == CAPI_MAXCONTR) {
- printk(KERN_ERR "kcapi: out of controller slotsn");
- return 0;
- }
- card = &cards[i];
- memset(card, 0, sizeof(struct capi_ctr));
- card->driver = driver;
- card->cnr = CARDNR(card);
- strncpy(card->name, name, sizeof(card->name));
- card->cardstate = CARD_DETECTED;
- card->blocked = 0;
- card->driverdata = driverdata;
- card->traceflag = showcapimsgs;
- card->ready = controllercb_ready;
- card->reseted = controllercb_reseted;
- card->suspend_output = controllercb_suspend_output;
- card->resume_output = controllercb_resume_output;
- card->handle_capimsg = controllercb_handle_capimsg;
- card->appl_registered = controllercb_appl_registered;
- card->appl_released = controllercb_appl_released;
- card->new_ncci = controllercb_new_ncci;
- card->free_ncci = controllercb_free_ncci;
- for (pp = &driver->controller; *pp; pp = &(*pp)->next) ;
- card->next = 0;
- *pp = card;
- driver->ncontroller++;
- sprintf(card->procfn, "capi/controllers/%d", card->cnr);
- card->procent = create_proc_entry(card->procfn, 0, 0);
- if (card->procent) {
- card->procent->read_proc =
- (int (*)(char *,char **,off_t,int,int *,void *))
- driver->ctr_read_proc;
- card->procent->data = card;
- }
- ncards++;
- printk(KERN_NOTICE "kcapi: Controller %d: %s attachedn",
- card->cnr, card->name);
- return card;
- }
- static int drivercb_detach_ctr(struct capi_ctr *card)
- {
- struct capi_driver *driver = card->driver;
- struct capi_ctr **pp;
- if (card->cardstate == CARD_FREE)
- return 0;
- if (card->cardstate != CARD_DETECTED)
- controllercb_reseted(card);
- for (pp = &driver->controller; *pp ; pp = &(*pp)->next) {
- if (*pp == card) {
- *pp = card->next;
- driver->ncontroller--;
- ncards--;
- break;
- }
- }
- if (card->procent) {
- remove_proc_entry(card->procfn, 0);
- card->procent = 0;
- }
- card->cardstate = CARD_FREE;
- printk(KERN_NOTICE "kcapi: Controller %d: %s unregisteredn",
- card->cnr, card->name);
- return 0;
- }
- /* ------------------------------------------------------------- */
- /* fallback if no driver read_proc function defined by driver */
- static int driver_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
- {
- struct capi_driver *driver = (struct capi_driver *)data;
- int len = 0;
- len += sprintf(page+len, "%-16s %sn", "name", driver->name);
- len += sprintf(page+len, "%-16s %sn", "revision", driver->revision);
- if (len < off)
- return 0;
- *eof = 1;
- *start = page + off;
- return ((count < len-off) ? count : len-off);
- }
- /* ------------------------------------------------------------- */
- static struct capi_driver_interface di = {
- drivercb_attach_ctr,
- drivercb_detach_ctr,
- };
- struct capi_driver_interface *attach_capi_driver(struct capi_driver *driver)
- {
- struct capi_driver **pp;
- MOD_INC_USE_COUNT;
- spin_lock(&drivers_lock);
- for (pp = &drivers; *pp; pp = &(*pp)->next) ;
- driver->next = 0;
- *pp = driver;
- spin_unlock(&drivers_lock);
- printk(KERN_NOTICE "kcapi: driver %s attachedn", driver->name);
- sprintf(driver->procfn, "capi/drivers/%s", driver->name);
- driver->procent = create_proc_entry(driver->procfn, 0, 0);
- if (driver->procent) {
- if (driver->driver_read_proc) {
- driver->procent->read_proc =
- (int (*)(char *,char **,off_t,int,int *,void *))
- driver->driver_read_proc;
- } else {
- driver->procent->read_proc = driver_read_proc;
- }
- driver->procent->data = driver;
- }
- return &di;
- }
- void detach_capi_driver(struct capi_driver *driver)
- {
- struct capi_driver **pp;
- spin_lock(&drivers_lock);
- for (pp = &drivers; *pp && *pp != driver; pp = &(*pp)->next) ;
- if (*pp) {
- *pp = (*pp)->next;
- printk(KERN_NOTICE "kcapi: driver %s detachedn", driver->name);
- } else {
- printk(KERN_ERR "kcapi: driver %s double detach ?n", driver->name);
- }
- spin_unlock(&drivers_lock);
- if (driver->procent) {
- remove_proc_entry(driver->procfn, 0);
- driver->procent = 0;
- }
- MOD_DEC_USE_COUNT;
- }
- /* ------------------------------------------------------------- */
- /* -------- CAPI2.0 Interface ---------------------------------- */
- /* ------------------------------------------------------------- */
- static __u16 capi_isinstalled(void)
- {
- int i;
- for (i = 0; i < CAPI_MAXCONTR; i++) {
- if (cards[i].cardstate == CARD_RUNNING)
- return CAPI_NOERROR;
- }
- return CAPI_REGNOTINSTALLED;
- }
- static __u16 capi_register(capi_register_params * rparam, __u16 * applidp)
- {
- int appl;
- int i;
- if (rparam->datablklen < 128)
- return CAPI_LOGBLKSIZETOSMALL;
- for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
- if (APPL_IS_FREE(appl))
- break;
- }
- if (appl > CAPI_MAXAPPL)
- return CAPI_TOOMANYAPPLS;
- APPL_MARK_USED(appl);
- skb_queue_head_init(&APPL(appl)->recv_queue);
- APPL(appl)->nncci = 0;
- memcpy(&APPL(appl)->rparam, rparam, sizeof(capi_register_params));
- for (i = 0; i < CAPI_MAXCONTR; i++) {
- if (cards[i].cardstate != CARD_RUNNING)
- continue;
- cards[i].driver->register_appl(&cards[i], appl,
- &APPL(appl)->rparam);
- }
- *applidp = appl;
- printk(KERN_INFO "kcapi: appl %d upn", appl);
- return CAPI_NOERROR;
- }
- static __u16 capi_release(__u16 applid)
- {
- int i;
- if (!VALID_APPLID(applid) || APPL(applid)->releasing)
- return CAPI_ILLAPPNR;
- APPL(applid)->releasing++;
- skb_queue_purge(&APPL(applid)->recv_queue);
- for (i = 0; i < CAPI_MAXCONTR; i++) {
- if (cards[i].cardstate != CARD_RUNNING)
- continue;
- APPL(applid)->releasing++;
- cards[i].driver->release_appl(&cards[i], applid);
- }
- APPL(applid)->releasing--;
- if (APPL(applid)->releasing <= 0) {
- APPL(applid)->signal = 0;
- APPL_MARK_FREE(applid);
- printk(KERN_INFO "kcapi: appl %d downn", applid);
- }
- return CAPI_NOERROR;
- }
- static __u16 capi_put_message(__u16 applid, struct sk_buff *skb)
- {
- struct capi_ncci *np;
- __u32 contr;
- int showctl = 0;
- __u8 cmd, subcmd;
- if (ncards == 0)
- return CAPI_REGNOTINSTALLED;
- if (!VALID_APPLID(applid))
- return CAPI_ILLAPPNR;
- if (skb->len < 12
- || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data))
- || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data)))
- return CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
- contr = CAPIMSG_CONTROLLER(skb->data);
- if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) {
- contr = 1;
- if (CARD(contr)->cardstate != CARD_RUNNING)
- return CAPI_REGNOTINSTALLED;
- }
- if (CARD(contr)->blocked)
- return CAPI_SENDQUEUEFULL;
- cmd = CAPIMSG_COMMAND(skb->data);
- subcmd = CAPIMSG_SUBCOMMAND(skb->data);
- if (cmd == CAPI_DATA_B3 && subcmd== CAPI_REQ) {
- if ((np = find_ncci(APPL(applid), CAPIMSG_NCCI(skb->data))) != 0
- && mq_enqueue(np, CAPIMSG_MSGID(skb->data)) == 0)
- return CAPI_SENDQUEUEFULL;
- CARD(contr)->nsentdatapkt++;
- APPL(applid)->nsentdatapkt++;
- if (CARD(contr)->traceflag > 2) showctl |= 2;
- } else {
- CARD(contr)->nsentctlpkt++;
- APPL(applid)->nsentctlpkt++;
- if (CARD(contr)->traceflag) showctl |= 2;
- }
- showctl |= (CARD(contr)->traceflag & 1);
- if (showctl & 2) {
- if (showctl & 1) {
- printk(KERN_DEBUG "kcapi: put [0x%lx] id#%d %s len=%un",
- (unsigned long) contr,
- CAPIMSG_APPID(skb->data),
- capi_cmd2str(cmd, subcmd),
- CAPIMSG_LEN(skb->data));
- } else {
- printk(KERN_DEBUG "kcapi: put [0x%lx] %sn",
- (unsigned long) contr,
- capi_message2str(skb->data));
- }
- }
- CARD(contr)->driver->send_message(CARD(contr), skb);
- return CAPI_NOERROR;
- }
- static __u16 capi_get_message(__u16 applid, struct sk_buff **msgp)
- {
- struct sk_buff *skb;
- if (!VALID_APPLID(applid))
- return CAPI_ILLAPPNR;
- if ((skb = skb_dequeue(&APPL(applid)->recv_queue)) == 0)
- return CAPI_RECEIVEQUEUEEMPTY;
- *msgp = skb;
- return CAPI_NOERROR;
- }
- static __u16 capi_set_signal(__u16 applid,
- void (*signal) (__u16 applid, void *param),
- void *param)
- {
- if (!VALID_APPLID(applid))
- return CAPI_ILLAPPNR;
- APPL(applid)->signal = signal;
- APPL(applid)->param = param;
- return CAPI_NOERROR;
- }
- static __u16 capi_get_manufacturer(__u32 contr, __u8 buf[CAPI_MANUFACTURER_LEN])
- {
- if (contr == 0) {
- strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
- return CAPI_NOERROR;
- }
- if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING)
- return CAPI_REGNOTINSTALLED;
- strncpy(buf, CARD(contr)->manu, CAPI_MANUFACTURER_LEN);
- return CAPI_NOERROR;
- }
- static __u16 capi_get_version(__u32 contr, struct capi_version *verp)
- {
- if (contr == 0) {
- *verp = driver_version;
- return CAPI_NOERROR;
- }
- if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING)
- return CAPI_REGNOTINSTALLED;
- memcpy((void *) verp, &CARD(contr)->version, sizeof(capi_version));
- return CAPI_NOERROR;
- }
- static __u16 capi_get_serial(__u32 contr, __u8 serial[CAPI_SERIAL_LEN])
- {
- if (contr == 0) {
- strncpy(serial, driver_serial, CAPI_SERIAL_LEN);
- return CAPI_NOERROR;
- }
- if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING)
- return CAPI_REGNOTINSTALLED;
- strncpy((void *) serial, CARD(contr)->serial, CAPI_SERIAL_LEN);
- return CAPI_NOERROR;
- }
- static __u16 capi_get_profile(__u32 contr, struct capi_profile *profp)
- {
- if (contr == 0) {
- profp->ncontroller = ncards;
- return CAPI_NOERROR;
- }
- if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING)
- return CAPI_REGNOTINSTALLED;
- memcpy((void *) profp, &CARD(contr)->profile,
- sizeof(struct capi_profile));
- return CAPI_NOERROR;
- }
- static struct capi_driver *find_driver(char *name)
- {
- struct capi_driver *dp;
- spin_lock(&drivers_lock);
- for (dp = drivers; dp; dp = dp->next)
- if (strcmp(dp->name, name) == 0)
- break;
- spin_unlock(&drivers_lock);
- return dp;
- }
- #ifdef CONFIG_AVMB1_COMPAT
- static int old_capi_manufacturer(unsigned int cmd, void *data)
- {
- avmb1_loadandconfigdef ldef;
- avmb1_extcarddef cdef;
- avmb1_resetdef rdef;
- avmb1_getdef gdef;
- struct capi_driver *driver;
- struct capi_ctr *card;
- capicardparams cparams;
- capiloaddata ldata;
- int retval;
- switch (cmd) {
- case AVMB1_ADDCARD:
- case AVMB1_ADDCARD_WITH_TYPE:
- if (cmd == AVMB1_ADDCARD) {
- if ((retval = copy_from_user((void *) &cdef, data,
- sizeof(avmb1_carddef))))
- return retval;
- cdef.cardtype = AVM_CARDTYPE_B1;
- } else {
- if ((retval = copy_from_user((void *) &cdef, data,
- sizeof(avmb1_extcarddef))))
- return retval;
- }
- cparams.port = cdef.port;
- cparams.irq = cdef.irq;
- cparams.cardnr = cdef.cardnr;
- switch (cdef.cardtype) {
- case AVM_CARDTYPE_B1:
- driver = find_driver("b1isa");
- break;
- case AVM_CARDTYPE_T1:
- driver = find_driver("t1isa");
- break;
- default:
- driver = 0;
- break;
- }
- if (!driver) {
- printk(KERN_ERR "kcapi: driver not loaded.n");
- return -EIO;
- }
- if (!driver->add_card) {
- printk(KERN_ERR "kcapi: driver has no add card function.n");
- return -EIO;
- }
- return driver->add_card(driver, &cparams);
- case AVMB1_LOAD:
- case AVMB1_LOAD_AND_CONFIG:
- if (cmd == AVMB1_LOAD) {
- if ((retval = copy_from_user((void *) &ldef, data,
- sizeof(avmb1_loaddef))))
- return retval;
- ldef.t4config.len = 0;
- ldef.t4config.data = 0;
- } else {
- if ((retval = copy_from_user((void *) &ldef, data,
- sizeof(avmb1_loadandconfigdef))))
- return retval;
- }
- if (!VALID_CARD(ldef.contr))
- return -ESRCH;
- card = CARD(ldef.contr);
- if (card->cardstate == CARD_FREE)
- return -ESRCH;
- if (card->driver->load_firmware == 0) {
- printk(KERN_DEBUG "kcapi: load: driver %s" has no load functionn", card->driver->name);
- return -ESRCH;
- }
- if (ldef.t4file.len <= 0) {
- printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?n", ldef.t4file.len);
- return -EINVAL;
- }
- if (ldef.t4file.data == 0) {
- printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0n");
- return -EINVAL;
- }
- ldata.firmware.user = 1;
- ldata.firmware.data = ldef.t4file.data;
- ldata.firmware.len = ldef.t4file.len;
- ldata.configuration.user = 1;
- ldata.configuration.data = ldef.t4config.data;
- ldata.configuration.len = ldef.t4config.len;
- if (card->cardstate != CARD_DETECTED) {
- printk(KERN_INFO "kcapi: load: contr=%d not in detect staten", ldef.contr);
- return -EBUSY;
- }
- card->cardstate = CARD_LOADING;
- retval = card->driver->load_firmware(card, &ldata);
- if (retval) {
- card->cardstate = CARD_DETECTED;
- return retval;
- }
- while (card->cardstate != CARD_RUNNING) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ/10); /* 0.1 sec */
- if (signal_pending(current))
- return -EINTR;
- }
- return 0;
- case AVMB1_RESETCARD:
- if ((retval = copy_from_user((void *) &rdef, data,
- sizeof(avmb1_resetdef))))
- return retval;
- if (!VALID_CARD(rdef.contr))
- return -ESRCH;
- card = CARD(rdef.contr);
- if (card->cardstate == CARD_FREE)
- return -ESRCH;
- if (card->cardstate == CARD_DETECTED)
- return 0;
- card->driver->reset_ctr(card);
- while (card->cardstate > CARD_DETECTED) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ/10); /* 0.1 sec */
- if (signal_pending(current))
- return -EINTR;
- }
- return 0;
- case AVMB1_GET_CARDINFO:
- if ((retval = copy_from_user((void *) &gdef, data,
- sizeof(avmb1_getdef))))
- return retval;
- if (!VALID_CARD(gdef.contr))
- return -ESRCH;
- card = CARD(gdef.contr);
- if (card->cardstate == CARD_FREE)
- return -ESRCH;
- gdef.cardstate = card->cardstate;
- if (card->driver == find_driver("t1isa"))
- gdef.cardtype = AVM_CARDTYPE_T1;
- else gdef.cardtype = AVM_CARDTYPE_B1;
- if ((retval = copy_to_user(data, (void *) &gdef,
- sizeof(avmb1_getdef))))
- return retval;
- return 0;
- case AVMB1_REMOVECARD:
- if ((retval = copy_from_user((void *) &rdef, data,
- sizeof(avmb1_resetdef))))
- return retval;
- if (!VALID_CARD(rdef.contr))
- return -ESRCH;
- card = CARD(rdef.contr);
- if (card->cardstate == CARD_FREE)
- return -ESRCH;
- if (card->cardstate != CARD_DETECTED)
- return -EBUSY;
- card->driver->remove_ctr(card);
- while (card->cardstate != CARD_FREE) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ/10); /* 0.1 sec */
- if (signal_pending(current))
- return -EINTR;
- }
- return 0;
- }
- return -EINVAL;
- }
- #endif
- static int capi_manufacturer(unsigned int cmd, void *data)
- {
- struct capi_ctr *card;
- int retval;
- switch (cmd) {
- #ifdef CONFIG_AVMB1_COMPAT
- case AVMB1_ADDCARD:
- case AVMB1_ADDCARD_WITH_TYPE:
- case AVMB1_LOAD:
- case AVMB1_LOAD_AND_CONFIG:
- case AVMB1_RESETCARD:
- case AVMB1_GET_CARDINFO:
- case AVMB1_REMOVECARD:
- return old_capi_manufacturer(cmd, data);
- #endif
- case KCAPI_CMD_TRACE:
- {
- kcapi_flagdef fdef;
- if ((retval = copy_from_user((void *) &fdef, data,
- sizeof(kcapi_flagdef))))
- return retval;
- if (!VALID_CARD(fdef.contr))
- return -ESRCH;
- card = CARD(fdef.contr);
- if (card->cardstate == CARD_FREE)
- return -ESRCH;
- card->traceflag = fdef.flag;
- printk(KERN_INFO "kcapi: contr %d set trace=%dn",
- card->cnr, card->traceflag);
- return 0;
- }
- case KCAPI_CMD_ADDCARD:
- {
- struct capi_driver *driver;
- capicardparams cparams;
- kcapi_carddef cdef;
- if ((retval = copy_from_user((void *) &cdef, data,
- sizeof(cdef))))
- return retval;
- cparams.port = cdef.port;
- cparams.irq = cdef.irq;
- cparams.membase = cdef.membase;
- cparams.cardnr = cdef.cardnr;
- cparams.cardtype = 0;
- cdef.driver[sizeof(cdef.driver)-1] = 0;
- if ((driver = find_driver(cdef.driver)) == 0) {
- printk(KERN_ERR "kcapi: driver "%s" not loaded.n",
- cdef.driver);
- return -ESRCH;
- }
- if (!driver->add_card) {
- printk(KERN_ERR "kcapi: driver "%s" has no add card function.n", cdef.driver);
- return -EIO;
- }
- return driver->add_card(driver, &cparams);
- }
- default:
- printk(KERN_ERR "kcapi: manufacturer command %d unknown.n",
- cmd);
- break;
- }
- return -EINVAL;
- }
- struct capi_interface avmb1_interface =
- {
- capi_isinstalled,
- capi_register,
- capi_release,
- capi_put_message,
- capi_get_message,
- capi_set_signal,
- capi_get_manufacturer,
- capi_get_version,
- capi_get_serial,
- capi_get_profile,
- capi_manufacturer
- };
- /* ------------------------------------------------------------- */
- /* -------- Exported Functions --------------------------------- */
- /* ------------------------------------------------------------- */
- struct capi_interface *attach_capi_interface(struct capi_interface_user *userp)
- {
- struct capi_interface_user *p;
- MOD_INC_USE_COUNT;
- spin_lock(&capi_users_lock);
- for (p = capi_users; p; p = p->next) {
- if (p == userp) {
- spin_unlock(&capi_users_lock);
- printk(KERN_ERR "kcapi: double attach from %sn",
- userp->name);
- MOD_DEC_USE_COUNT;
- return 0;
- }
- }
- userp->next = capi_users;
- capi_users = userp;
- spin_unlock(&capi_users_lock);
- printk(KERN_NOTICE "kcapi: %s attachedn", userp->name);
- return &avmb1_interface;
- }
- int detach_capi_interface(struct capi_interface_user *userp)
- {
- struct capi_interface_user **pp;
- spin_lock(&capi_users_lock);
- for (pp = &capi_users; *pp; pp = &(*pp)->next) {
- if (*pp == userp) {
- *pp = userp->next;
- spin_unlock(&capi_users_lock);
- userp->next = 0;
- printk(KERN_NOTICE "kcapi: %s detachedn", userp->name);
- MOD_DEC_USE_COUNT;
- return 0;
- }
- }
- spin_unlock(&capi_users_lock);
- printk(KERN_ERR "kcapi: double detach from %sn", userp->name);
- return -1;
- }
- /* ------------------------------------------------------------- */
- /* -------- Init & Cleanup ------------------------------------- */
- /* ------------------------------------------------------------- */
- EXPORT_SYMBOL(attach_capi_interface);
- EXPORT_SYMBOL(detach_capi_interface);
- EXPORT_SYMBOL(attach_capi_driver);
- EXPORT_SYMBOL(detach_capi_driver);
- /*
- * init / exit functions
- */
- static int __init kcapi_init(void)
- {
- char *p;
- char rev[32];
- MOD_INC_USE_COUNT;
- skb_queue_head_init(&recv_queue);
- tq_state_notify.routine = notify_handler;
- tq_state_notify.data = 0;
- tq_recv_notify.routine = recv_handler;
- tq_recv_notify.data = 0;
- proc_capi_init();
- if ((p = strchr(revision, ':')) != 0 && p[1]) {
- strncpy(rev, p + 2, sizeof(rev));
- rev[sizeof(rev)-1] = 0;
- if ((p = strchr(rev, '$')) != 0 && p > rev)
- *(p-1) = 0;
- } else
- strcpy(rev, "1.0");
- #ifdef MODULE
- printk(KERN_NOTICE "CAPI-driver Rev %s: loadedn", rev);
- #else
- printk(KERN_NOTICE "CAPI-driver Rev %s: startedn", rev);
- #endif
- MOD_DEC_USE_COUNT;
- return 0;
- }
- static void __exit kcapi_exit(void)
- {
- char rev[10];
- char *p;
- if ((p = strchr(revision, ':'))) {
- strcpy(rev, p + 1);
- p = strchr(rev, '$');
- *p = 0;
- } else {
- strcpy(rev, "1.0");
- }
- proc_capi_exit();
- printk(KERN_NOTICE "CAPI-driver Rev%s: unloadedn", rev);
- }
- module_init(kcapi_init);
- module_exit(kcapi_exit);