]> git.hungrycats.org Git - linux/commitdiff
ISDN: maintain outstanding CAPI messages in the drivers
authorKai Germaschewski <kai@tp1.ruhr-uni-bochum.de>
Tue, 7 May 2002 10:21:08 +0000 (05:21 -0500)
committerKai Germaschewski <kai@tp1.ruhr-uni-bochum.de>
Tue, 7 May 2002 10:21:08 +0000 (05:21 -0500)
It's up to the drivers to maintain their list of buffered messages
themselves. As most drivers can share common code, provide it
in capilib.o, inside of the module kernelcapi.o

12 files changed:
drivers/isdn/capi/Makefile
drivers/isdn/capi/capilib.c [new file with mode: 0644]
drivers/isdn/capi/kcapi.c
drivers/isdn/hardware/avm/avmcard.h
drivers/isdn/hardware/avm/b1.c
drivers/isdn/hardware/avm/b1dma.c
drivers/isdn/hardware/avm/c4.c
drivers/isdn/hardware/avm/t1isa.c
drivers/isdn/hysdn/hycapi.c
drivers/isdn/hysdn/hysdn_defs.h
include/linux/isdn/capilli.h
include/linux/kernelcapi.h

index 6534e419c1b1bf302c849681dc0a5de660e1cd17..90a1fbc52048d300981a7ea1d1416484fd6406d9 100644 (file)
@@ -6,11 +6,11 @@ O_TARGET      := vmlinux-obj.o
 
 # Objects that export symbols.
 
-export-objs    := kcapi.o capiutil.o capifs.o
+export-objs    := kcapi.o capiutil.o capilib.o capifs.o
 
 # Multipart objects.
 
-kernelcapi-objs        := kcapi.o capiutil.o
+kernelcapi-objs        := kcapi.o capiutil.o capilib.o
 
 # Ordering constraints: kernelcapi.o first
 
diff --git a/drivers/isdn/capi/capilib.c b/drivers/isdn/capi/capilib.c
new file mode 100644 (file)
index 0000000..36018c7
--- /dev/null
@@ -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 __FUNCTION__ ": " format "\n" , ## 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)
+{
+       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 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 = 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 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 = 0;
+                       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);
index 362abc241de95c1f03e6c19beace806de0826d1d..e243b28185414d9d887feb6a09494bf6479f6912 100644 (file)
@@ -55,23 +55,6 @@ 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;
@@ -245,45 +228,6 @@ endloop:
        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=1; i <= CAPI_MAXAPPL; i++) {
-               ap = get_capi_appl_by_nr(i);
-               if (!ap) 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
@@ -477,7 +421,6 @@ static struct procfsentries {
 } 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 },
@@ -525,26 +468,9 @@ static void register_appl(struct capi_ctr *card, u16 applid, capi_register_param
 
 static void release_appl(struct capi_ctr *card, u16 applid)
 {
-       struct capi_appl *ap = get_capi_appl_by_nr(applid);
-       struct capi_ncci **pp, **nextpp;
-       
-       DBG("");
+       DBG("applid %#x", applid);
        
-       for (pp = &ap->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", applid, np->ncci);
-                       kfree(np);
-                       ap->nncci--;
-                       nextpp = pp;
-               } else {
-                       nextpp = &(*pp)->next;
-               }
-       }
-
        card->driver->release_appl(card, applid);
-
        capi_ctr_put(card);
 }
 
@@ -679,130 +605,12 @@ static void notify_handler(void *dummy)
        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;
-}
-
-/*
- * ncci management
- */
-
-static void controllercb_new_ncci(struct capi_ctr * card,
-                                       u16 appl, u32 ncci, u32 winsize)
-{
-       struct capi_ncci *np;
-       struct capi_appl *ap = get_capi_appl_by_nr(appl);
-
-       if (!ap) {
-               printk(KERN_ERR "avmb1_handle_new_ncci: illegal appl %d\n", 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%x\n", ncci);
-               return;
-       }
-       if (winsize > CAPI_MAXDATAWINDOW) {
-               printk(KERN_ERR "capi_new_ncci: winsize %d too big, set to %d\n",
-                      winsize, CAPI_MAXDATAWINDOW);
-               winsize = CAPI_MAXDATAWINDOW;
-       }
-       np->applid = appl;
-       np->ncci = ncci;
-       np->winsize = winsize;
-       mq_init(np);
-       np->next = ap->nccilist;
-       ap->nccilist = np;
-       ap->nncci++;
-       printk(KERN_INFO "kcapi: appl %d ncci 0x%x up\n", appl, ncci);
-}
-
-static void controllercb_free_ncci(struct capi_ctr * card,
-                               u16 appl, u32 ncci)
-{
-       struct capi_ncci **pp;
-       struct capi_appl *ap = get_capi_appl_by_nr(appl);
-       if (!ap) {
-               printk(KERN_ERR "free_ncci: illegal appl %d\n", appl);
-               return;
-       }
-       for (pp = &ap->nccilist; *pp; pp = &(*pp)->next) {
-               if ((*pp)->ncci == ncci) {
-                       struct capi_ncci *np = *pp;
-                       *pp = np->next;
-                       kfree(np);
-                       ap->nncci--;
-                       printk(KERN_INFO "kcapi: appl %d ncci 0x%x down\n", appl, ncci);
-                       return;
-               }
-       }
-       printk(KERN_ERR "free_ncci: ncci 0x%x not found\n", 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;
        struct capi_appl *ap;
-       struct capi_ncci *np;
 
        while ((skb = skb_dequeue(&recv_queue)) != 0) {
                ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data));
@@ -818,13 +626,6 @@ static void recv_handler(void *dummy)
                        kfree_skb(skb);
                        continue;
                }
-               if (   CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
-                   && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF
-                   && (np = find_ncci(ap, CAPIMSG_NCCI(skb->data))) != 0
-                   && mq_dequeue(np, CAPIMSG_MSGID(skb->data)) == 0) {
-                       printk(KERN_ERR "kcapi: msgid %hu ncci 0x%x not on queue\n",
-                               CAPIMSG_MSGID(skb->data), np->ncci);
-               }
                if (   CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
                    && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {
                        ap->nrecvdatapkt++;
@@ -917,22 +718,9 @@ static void controllercb_reseted(struct capi_ctr * card)
 
        for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
                struct capi_appl *ap = get_capi_appl_by_nr(appl);
-               struct capi_ncci **pp, **nextpp;
-
                if (!ap)
                        continue;
 
-               for (pp = &ap->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);
-                               kfree(np);
-                               nextpp = pp;
-                       } else {
-                               nextpp = &(*pp)->next;
-                       }
-               }
                capi_ctr_put(card);
        }
 
@@ -993,8 +781,6 @@ attach_capi_ctr(struct capi_driver *driver, char *name, void *driverdata)
         card->suspend_output = controllercb_suspend_output;
         card->resume_output = controllercb_resume_output;
         card->handle_capimsg = controllercb_handle_capimsg;
-        card->new_ncci = controllercb_new_ncci;
-        card->free_ncci = controllercb_free_ncci;
 
        list_add_tail(&card->driver_list, &driver->contr_head);
        driver->ncontroller++;
@@ -1185,7 +971,6 @@ static u16 capi_put_message(u16 applid, struct sk_buff *skb)
 {
        struct capi_ctr *card;
        struct capi_appl *ap;
-       struct capi_ncci *np;
        int showctl = 0;
        u8 cmd, subcmd;
 
@@ -1213,9 +998,6 @@ static u16 capi_put_message(u16 applid, struct sk_buff *skb)
         subcmd = CAPIMSG_SUBCOMMAND(skb->data);
 
        if (cmd == CAPI_DATA_B3 && subcmd== CAPI_REQ) {
-               if ((np = find_ncci(ap, CAPIMSG_NCCI(skb->data))) != 0
-                   && mq_enqueue(np, CAPIMSG_MSGID(skb->data)) == 0)
-                       return CAPI_SENDQUEUEFULL;
                card->nsentdatapkt++;
                ap->nsentdatapkt++;
                if (card->traceflag > 2) showctl |= 2;
@@ -1239,8 +1021,7 @@ static u16 capi_put_message(u16 applid, struct sk_buff *skb)
                }
 
        }
-       card->driver->send_message(card, skb);
-       return CAPI_NOERROR;
+       return card->driver->send_message(card, skb);
 }
 
 static u16 capi_get_message(u16 applid, struct sk_buff **msgp)
index 984b19db1d16f5ea357423a5c2eb182295deccfd..e20442093c64d7ee631a399a6ab4b597a1e16e09 100644 (file)
@@ -69,6 +69,7 @@ typedef       struct avmctrl_info {
        struct avmcard  *card;
        struct capi_ctr *capi_ctrl;
        
+       struct list_head ncci_head;
 } avmctrl_info;
 
 typedef struct avmcard {
@@ -549,7 +550,7 @@ void b1_reset_ctr(struct capi_ctr *ctrl);
 void b1_register_appl(struct capi_ctr *ctrl, u16 appl,
                                capi_register_params *rp);
 void b1_release_appl(struct capi_ctr *ctrl, u16 appl);
-void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
+u16  b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
 void b1_parse_version(avmctrl_info *card);
 void b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs);
 
@@ -574,7 +575,7 @@ void b1dma_register_appl(struct capi_ctr *ctrl,
                                u16 appl,
                                capi_register_params *rp);
 void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl);
-void b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
+u16  b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
 int b1dmactl_read_proc(char *page, char **start, off_t off,
                        int count, int *eof, struct capi_ctr *ctrl);
 
index ffdfeac7510a2d4cf5d72632f008253573c93503..060dcb96901dca9b3906a438fefd7976857d4cc1 100644 (file)
@@ -80,6 +80,7 @@ avmcard *b1_alloc_card(int nr_controllers)
 
        card->ctrlinfo = cinfo;
        for (i = 0; i < nr_controllers; i++) {
+               INIT_LIST_HEAD(&cinfo[i].ncci_head);
                cinfo[i].card = card;
        }
        spin_lock_init(&card->lock);
@@ -331,6 +332,7 @@ void b1_reset_ctr(struct capi_ctr *ctrl)
        b1_reset(port);
 
        memset(cinfo->version, 0, sizeof(cinfo->version));
+       capilib_release(&cinfo->ncci_head);
        ctrl->reseted(ctrl);
 }
 
@@ -366,6 +368,8 @@ void b1_release_appl(struct capi_ctr *ctrl, u16 appl)
        unsigned int port = card->port;
        unsigned long flags;
 
+       capilib_release_appl(&cinfo->ncci_head, appl);
+
        save_flags(flags);
        cli();
        b1_put_byte(port, SEND_RELEASE);
@@ -373,7 +377,7 @@ void b1_release_appl(struct capi_ctr *ctrl, u16 appl)
        restore_flags(flags);
 }
 
-void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
+u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
 {
        avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
        avmcard *card = cinfo->card;
@@ -382,20 +386,36 @@ void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
        u16 len = CAPIMSG_LEN(skb->data);
        u8 cmd = CAPIMSG_COMMAND(skb->data);
        u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
+       u16 dlen, retval;
 
-       save_flags(flags);
-       cli();
        if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
-               u16 dlen = CAPIMSG_DATALEN(skb->data);
+               retval = capilib_data_b3_req(&cinfo->ncci_head,
+                                            CAPIMSG_APPID(skb->data),
+                                            CAPIMSG_NCCI(skb->data),
+                                            CAPIMSG_MSGID(skb->data));
+               if (retval != CAPI_NOERROR) 
+                       goto out;
+
+               dlen = CAPIMSG_DATALEN(skb->data);
+
+               save_flags(flags);
+               cli();
                b1_put_byte(port, SEND_DATA_B3_REQ);
                b1_put_slice(port, skb->data, len);
                b1_put_slice(port, skb->data + len, dlen);
+               restore_flags(flags);
        } else {
+               retval = CAPI_NOERROR;
+
+               save_flags(flags);
+               cli();
                b1_put_byte(port, SEND_MESSAGE);
                b1_put_slice(port, skb->data, len);
+               restore_flags(flags);
        }
-       restore_flags(flags);
+ out:
        dev_kfree_skb_any(skb);
+       return retval;
 }
 
 /* ------------------------------------------------------------- */
@@ -525,6 +545,11 @@ void b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
                                        card->name);
                } else {
                        memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
+                       if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF)
+                               capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
+                                                    CAPIMSG_NCCI(skb->data),
+                                                    CAPIMSG_MSGID(skb->data));
+
                        ctrl->handle_capimsg(ctrl, ApplId, skb);
                }
                break;
@@ -535,7 +560,7 @@ void b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
                NCCI = b1_get_word(card->port);
                WindowSize = b1_get_word(card->port);
 
-               ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
+               capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
 
                break;
 
@@ -545,8 +570,8 @@ void b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
                NCCI = b1_get_word(card->port);
 
                if (NCCI != 0xffffffff)
-                       ctrl->free_ncci(ctrl, ApplId, NCCI);
-
+                       capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
+              
                break;
 
        case RECEIVE_START:
index f67266fe897f55235a79d1f6ed70cb0a39a63f98..aceec474e52afdef78ae47a4e486eef68da0de49 100644 (file)
@@ -488,6 +488,11 @@ static void b1dma_handle_rx(avmcard *card)
                                        card->name);
                } else {
                        memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
+                       if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF)
+                               capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
+                                                    CAPIMSG_NCCI(skb->data),
+                                                    CAPIMSG_MSGID(skb->data));
+
                        ctrl->handle_capimsg(ctrl, ApplId, skb);
                }
                break;
@@ -498,7 +503,7 @@ static void b1dma_handle_rx(avmcard *card)
                NCCI = _get_word(&p);
                WindowSize = _get_word(&p);
 
-               ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
+               capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
 
                break;
 
@@ -508,7 +513,7 @@ static void b1dma_handle_rx(avmcard *card)
                NCCI = _get_word(&p);
 
                if (NCCI != 0xffffffff)
-                       ctrl->free_ncci(ctrl, ApplId, NCCI);
+                       capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
 
                break;
 
@@ -734,6 +739,7 @@ void b1dma_reset_ctr(struct capi_ctr *ctrl)
        b1dma_reset(card);
 
        memset(cinfo->version, 0, sizeof(cinfo->version));
+       capilib_release(&cinfo->ncci_head);
        ctrl->reseted(ctrl);
 }
 
@@ -785,6 +791,8 @@ void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl)
        struct sk_buff *skb;
        void *p;
 
+       capilib_release_appl(&cinfo->ncci_head, appl);
+
        skb = alloc_skb(7, GFP_ATOMIC);
        if (!skb) {
                printk(KERN_CRIT "%s: no memory, lost release appl.\n",
@@ -804,12 +812,24 @@ void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl)
 
 /* ------------------------------------------------------------- */
 
-void b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
+u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
 {
        avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
        avmcard *card = cinfo->card;
+       u16 retval = CAPI_NOERROR;
 
-       b1dma_queue_tx(card, skb);
+       if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
+               retval = capilib_data_b3_req(&cinfo->ncci_head,
+                                            CAPIMSG_APPID(skb->data),
+                                            CAPIMSG_NCCI(skb->data),
+                                            CAPIMSG_MSGID(skb->data));
+       }
+       if (retval == CAPI_NOERROR) 
+               b1dma_queue_tx(card, skb);
+       else
+               dev_kfree_skb_any(skb);
+
+       return retval;
 }
 
 /* ------------------------------------------------------------- */
index 8a0bb60dcb936de7a1c2d1e8c1d9c248c5071834..5da88d71011ab43688aea8c875ccd7303c736ac6 100644 (file)
@@ -548,6 +548,7 @@ static void c4_handle_rx(avmcard *card)
                MsgLen = _get_slice(&p, card->msgbuf);
                cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr;
                if (cidx >= card->nlogcontr) cidx = 0;
+               cinfo = &card->ctrlinfo[cidx];
                ctrl = card->ctrlinfo[cidx].capi_ctrl;
 
                if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
@@ -555,6 +556,11 @@ static void c4_handle_rx(avmcard *card)
                                        card->name);
                } else {
                        memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
+                       if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF)
+                               capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
+                                                    CAPIMSG_NCCI(skb->data),
+                                                    CAPIMSG_MSGID(skb->data));
+
                        ctrl->handle_capimsg(ctrl, ApplId, skb);
                }
                break;
@@ -566,9 +572,8 @@ static void c4_handle_rx(avmcard *card)
                WindowSize = _get_word(&p);
                cidx = (NCCI&0x7f) - card->cardnr;
                if (cidx >= card->nlogcontr) cidx = 0;
-               ctrl = card->ctrlinfo[cidx].capi_ctrl;
 
-               ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
+               capilib_new_ncci(&card->ctrlinfo[cidx].ncci_head, ApplId, NCCI, WindowSize);
 
                break;
 
@@ -580,9 +585,7 @@ static void c4_handle_rx(avmcard *card)
                if (NCCI != 0xffffffff) {
                        cidx = (NCCI&0x7f) - card->cardnr;
                        if (cidx >= card->nlogcontr) cidx = 0;
-                       ctrl = card->ctrlinfo[cidx].capi_ctrl;
-                       if (ctrl)
-                               ctrl->free_ncci(ctrl, ApplId, NCCI);
+                       capilib_free_ncci(&card->ctrlinfo[cidx].ncci_head, ApplId, NCCI);
                }
                break;
 
@@ -675,6 +678,7 @@ static void c4_handle_interrupt(avmcard *card)
                 for (i=0; i < 4; i++) {
                        avmctrl_info *cinfo = &card->ctrlinfo[i];
                        memset(cinfo->version, 0, sizeof(cinfo->version));
+                       capilib_release(&cinfo->ncci_head);
                        if (cinfo->capi_ctrl)
                                cinfo->capi_ctrl->reseted(cinfo->capi_ctrl);
                }
@@ -974,6 +978,8 @@ void c4_release_appl(struct capi_ctr *ctrl, u16 appl)
        struct sk_buff *skb;
        void *p;
 
+       capilib_release_appl(&cinfo->ncci_head, appl);
+
        if (ctrl->cnr == card->cardnr) {
                skb = alloc_skb(7, GFP_ATOMIC);
                if (!skb) {
@@ -996,12 +1002,25 @@ void c4_release_appl(struct capi_ctr *ctrl, u16 appl)
 /* ------------------------------------------------------------- */
 
 
-static void c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
+static u16 c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
 {
        avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
        avmcard *card = cinfo->card;
-       skb_queue_tail(&card->dma->send_queue, skb);
-       c4_dispatch_tx(card);
+       u16 retval = CAPI_NOERROR;
+
+       if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
+               retval = capilib_data_b3_req(&cinfo->ncci_head,
+                                            CAPIMSG_APPID(skb->data),
+                                            CAPIMSG_NCCI(skb->data),
+                                            CAPIMSG_MSGID(skb->data));
+       }
+       if (retval == CAPI_NOERROR) {
+               skb_queue_tail(&card->dma->send_queue, skb);
+               c4_dispatch_tx(card);
+       } else {
+               dev_kfree_skb_any(skb);
+       }
+       return retval;
 }
 
 /* ------------------------------------------------------------- */
index ff9c65f5321e2105809930111ef60d5f8012168e..7e631b710a20e5d8e66ecfcc60549865986f9413 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/capi.h>
+#include <linux/netdevice.h>
 #include <linux/kernelcapi.h>
 #include <linux/init.h>
 #include <asm/io.h>
@@ -174,6 +175,11 @@ static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
                                                card->name);
                        } else {
                                memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
+                               if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3)
+                                       capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
+                                                            CAPIMSG_NCCI(skb->data),
+                                                            CAPIMSG_MSGID(skb->data));
+
                                ctrl->handle_capimsg(ctrl, ApplId, skb);
                        }
                        break;
@@ -184,7 +190,7 @@ static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
                        NCCI = b1_get_word(card->port);
                        WindowSize = b1_get_word(card->port);
 
-                       ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
+                       capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
 
                        break;
 
@@ -194,7 +200,7 @@ static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
                        NCCI = b1_get_word(card->port);
 
                        if (NCCI != 0xffffffff)
-                               ctrl->free_ncci(ctrl, ApplId, NCCI);
+                               capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
 
                        break;
 
@@ -313,6 +319,7 @@ void t1isa_reset_ctr(struct capi_ctr *ctrl)
        b1_reset(port);
 
        memset(cinfo->version, 0, sizeof(cinfo->version));
+       capilib_release(&cinfo->ncci_head);
        ctrl->reseted(ctrl);
 }
 
@@ -433,7 +440,7 @@ static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
        return retval;
 }
 
-static void t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
+static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
 {
        avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
        avmcard *card = cinfo->card;
@@ -442,20 +449,36 @@ static void t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
        u16 len = CAPIMSG_LEN(skb->data);
        u8 cmd = CAPIMSG_COMMAND(skb->data);
        u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
+       u16 dlen, retval;
 
-       save_flags(flags);
-       cli();
        if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
-               u16 dlen = CAPIMSG_DATALEN(skb->data);
+               retval = capilib_data_b3_req(&cinfo->ncci_head,
+                                            CAPIMSG_APPID(skb->data),
+                                            CAPIMSG_NCCI(skb->data),
+                                            CAPIMSG_MSGID(skb->data));
+               if (retval != CAPI_NOERROR) 
+                       goto out;
+
+               dlen = CAPIMSG_DATALEN(skb->data);
+
+               save_flags(flags);
+               cli();
                b1_put_byte(port, SEND_DATA_B3_REQ);
                t1_put_slice(port, skb->data, len);
                t1_put_slice(port, skb->data + len, dlen);
+               restore_flags(flags);
        } else {
+               retval = CAPI_NOERROR;
+
+               save_flags(flags);
+               cli();
                b1_put_byte(port, SEND_MESSAGE);
                t1_put_slice(port, skb->data, len);
+               restore_flags(flags);
        }
-       restore_flags(flags);
-       dev_kfree_skb(skb);
+ out:
+       dev_kfree_skb_any(skb);
+       return retval;
 }
 /* ------------------------------------------------------------- */
 
index bf46091138879a1540f16b77d68ab9e5009954bf..aef7d8c3b68c3ba21c3b5e9edd12cbb66093449a 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/signal.h>
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
-
+#include <linux/netdevice.h>
 
 #define        VER_DRIVER      0
 #define        VER_CARDTYPE    1
@@ -62,9 +62,12 @@ Kernel-Capi callback reset_ctr
 void 
 hycapi_reset_ctr(struct capi_ctr *ctrl)
 {
+       hycapictrl_info *cinfo = ctrl->driverdata;
+
 #ifdef HYCAPI_PRINTFNAMES
        printk(KERN_NOTICE "HYCAPI hycapi_reset_ctr\n");
 #endif
+       capilib_release(&cinfo->ncci_head);
        ctrl->reseted(ctrl);
 }
 
@@ -269,6 +272,9 @@ static void hycapi_release_internal(struct capi_ctr *ctrl, __u16 appl)
        __u16 len;
        __u8 _command = 0xa1, _subcommand = 0x80;
        __u16 MessageNumber = 0x0000;
+
+       capilib_release_appl(&cinfo->ncci_head, appl);
+
 #ifdef HYCAPI_PRINTFNAMES
        printk(KERN_NOTICE "hycapi_release_appl\n");
 #endif
@@ -373,12 +379,14 @@ firmware-releases that do not check the MsgLen-Indication!
 
 ***************************************************************/
 
-void hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
+u16 hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
 {
        __u16 appl_id;
        int _len, _len2;
        __u8 msghead[64];
-       
+       hycapictrl_info *cinfo = ctrl->driverdata;
+       u16 retval = CAPI_NOERROR;
+
        appl_id = CAPIMSG_APPID(skb->data);
        switch(_hycapi_appCheck(appl_id, ctrl->cnr))
        {
@@ -392,12 +400,13 @@ void hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
                        break;
                default:
                        printk(KERN_ERR "HYCAPI: Controller mixup!\n");
-                       return;
+                       retval = CAPI_ILLAPPNR;
+                       goto out;
        }
        switch(CAPIMSG_CMD(skb->data)) {                
                case CAPI_DISCONNECT_B3_RESP:
-                       ctrl->free_ncci(ctrl, appl_id, 
-                                       CAPIMSG_NCCI(skb->data));
+                       capilib_free_ncci(&cinfo->ncci_head, appl_id, 
+                                         CAPIMSG_NCCI(skb->data));
                        break;
                case CAPI_DATA_B3_REQ:
                        _len = CAPIMSG_LEN(skb->data);
@@ -407,6 +416,10 @@ void hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
                                memcpy(skb->data + _len2, msghead, 22);
                                skb_pull(skb, _len2);
                                CAPIMSG_SETLEN(skb->data, 22);
+                               retval = capilib_data_b3_req(&cinfo->ncci_head,
+                                                            CAPIMSG_APPID(skb->data),
+                                                            CAPIMSG_NCCI(skb->data),
+                                                            CAPIMSG_MSGID(skb->data));
                        }
                        break;
                case CAPI_LISTEN_REQ:
@@ -423,7 +436,13 @@ void hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
                default:
                        break;
        }
-       hycapi_sendmsg_internal(ctrl, skb);
+ out:
+       if (retval == CAPI_NOERROR)
+               hycapi_sendmsg_internal(ctrl, skb);
+       else 
+               dev_kfree_skb_any(skb);
+
+       return retval;
 }
 
 /*********************************************************************
@@ -575,8 +594,8 @@ hycapi_rx_capipkt(hysdn_card * card, uchar * buf, word len)
                        switch(info)
                        {
                                case 0:
-                                       ctrl->new_ncci(ctrl, ApplId, CAPIMSG_NCCI(skb->data), 
-                                                      hycapi_applications[ApplId-1].rp.datablkcnt); 
+                                       capilib_new_ncci(&cinfo->ncci_head, ApplId, CAPIMSG_NCCI(skb->data), 
+                                                        hycapi_applications[ApplId-1].rp.datablkcnt); 
                                        
                                        break;
                                case 0x0001:
@@ -604,9 +623,14 @@ hycapi_rx_capipkt(hysdn_card * card, uchar * buf, word len)
                        }
                        break;
                case CAPI_CONNECT_B3_IND:
-                       ctrl->new_ncci(ctrl, ApplId, 
-                                      CAPIMSG_NCCI(skb->data), 
-                                      hycapi_applications[ApplId-1].rp.datablkcnt);
+                       capilib_new_ncci(&cinfo->ncci_head, ApplId, 
+                                        CAPIMSG_NCCI(skb->data), 
+                                        hycapi_applications[ApplId-1].rp.datablkcnt);
+                       break;
+               case CAPI_DATA_B3_CONF:
+                       capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
+                                            CAPIMSG_NCCI(skb->data),
+                                            CAPIMSG_MSGID(skb->data));
                        break;
                default:
                        break;
@@ -786,6 +810,7 @@ hycapi_capi_create(hysdn_card *card)
                card->hyctrlinfo = cinfo;
                cinfo->card = card;
                spin_lock_init(&cinfo->lock);
+               INIT_LIST_HEAD(&cinfo->ncci_head);
 
                switch (card->brdtype) {
                        case BD_PCCARD:  strcpy(cinfo->cardname,"HYSDN Hycard"); break;
index 1e5ba9f983559cc40356b4d4a3e57ec185607a93..9bc6c030a827475e85cb60d5f9c943bd36669848 100644 (file)
@@ -213,6 +213,8 @@ typedef struct HYSDN_CARD {
                int in_idx, out_idx;    /* indexes to buffer ring */
                int sk_count;           /* number of buffers currently in ring */
                struct sk_buff *tx_skb; /* buffer for tx operation */
+         
+               struct list_head ncci_head;
        } *hyctrlinfo;
 #endif /* CONFIG_HYSDN_CAPI */
 } hysdn_card;
@@ -284,7 +286,7 @@ extern void hycapi_remove_ctr(struct capi_ctr *);
 extern void hycapi_register_appl(struct capi_ctr *, __u16 appl,
                                 capi_register_params *);
 extern void hycapi_release_appl(struct capi_ctr *, __u16 appl);
-extern void hycapi_send_message(struct capi_ctr *, struct sk_buff *skb);
+extern u16  hycapi_send_message(struct capi_ctr *, struct sk_buff *skb);
 extern char *hycapi_procinfo(struct capi_ctr *);
 extern int hycapi_read_proc(char *page, char **start, off_t off,
                            int count, int *eof, struct capi_ctr *card);
index 76eb4e1d2fad5e922359770e180dea24eee035d3..2d34c7384ec2e0ff09deca2639f02484b7d8c6dc 100644 (file)
 #ifndef __CAPILLI_H__
 #define __CAPILLI_H__
 
+#include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/capi.h>
+#include <linux/kernelcapi.h>
 
 typedef struct capiloaddatapart {
        int user;               /* data in userspace ? */
@@ -60,10 +63,6 @@ struct capi_ctr {
         void (*handle_capimsg)(struct capi_ctr * card,
                                __u16 appl, struct sk_buff *skb);
 
-        void (*new_ncci)(struct capi_ctr * card,
-                               __u16 appl, __u32 ncci, __u32 winsize);
-        void (*free_ncci)(struct capi_ctr * card, __u16 appl, __u32 ncci);
-
        /* management information for kcapi */
 
        unsigned long nrecvctlpkt;
@@ -85,7 +84,7 @@ struct capi_driver {
        void (*register_appl)(struct capi_ctr *, __u16 appl,
                              capi_register_params *);
        void (*release_appl)(struct capi_ctr *, __u16 appl);
-       void (*send_message)(struct capi_ctr *, struct sk_buff *skb);
+       u16  (*send_message)(struct capi_ctr *, struct sk_buff *skb);
        
        char *(*procinfo)(struct capi_ctr *);
        int (*ctr_read_proc)(char *page, char **start, off_t off,
@@ -109,4 +108,16 @@ void detach_capi_driver(struct capi_driver *driver);
 struct capi_ctr *attach_capi_ctr(struct capi_driver *driver, char *name, void *data);
 int detach_capi_ctr(struct capi_ctr *);
 
+
+
+// ---------------------------------------------------------------------------
+// library functions for use by hardware controller drivers
+
+void capilib_new_ncci(struct list_head *head, u16 applid, u32 ncci, u32 winsize);
+void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci);
+void capilib_release_appl(struct list_head *head, u16 applid);
+void capilib_release(struct list_head *head);
+void capilib_data_b3_conf(struct list_head *head, u16 applid, u32 ncci, u16 msgid);
+u16  capilib_data_b3_req(struct list_head *head, u16 applid, u32 ncci, u16 msgid);
+
 #endif                         /* __CAPILLI_H__ */
index c162ff96f53b0668ad7b2fd3c0ebea3e452e10b2..2c7264b4326ec2eeeb523617ba812bbdab242fbd 100644 (file)
@@ -47,6 +47,8 @@ typedef struct kcapi_carddef {
 
 #ifdef __KERNEL__
 
+#include <linux/skbuff.h>
+
 struct capi_interface {
        __u16 (*capi_isinstalled) (void);