# 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
--- /dev/null
+
+#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);
/* ------------------------------------------------------------- */
-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;
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
} 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 },
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);
}
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));
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++;
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);
}
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++;
{
struct capi_ctr *card;
struct capi_appl *ap;
- struct capi_ncci *np;
int showctl = 0;
u8 cmd, subcmd;
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;
}
}
- 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)
struct avmcard *card;
struct capi_ctr *capi_ctrl;
+ struct list_head ncci_head;
} avmctrl_info;
typedef struct avmcard {
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);
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);
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);
b1_reset(port);
memset(cinfo->version, 0, sizeof(cinfo->version));
+ capilib_release(&cinfo->ncci_head);
ctrl->reseted(ctrl);
}
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);
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;
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;
}
/* ------------------------------------------------------------- */
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;
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;
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:
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;
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;
NCCI = _get_word(&p);
if (NCCI != 0xffffffff)
- ctrl->free_ncci(ctrl, ApplId, NCCI);
+ capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
break;
b1dma_reset(card);
memset(cinfo->version, 0, sizeof(cinfo->version));
+ capilib_release(&cinfo->ncci_head);
ctrl->reseted(ctrl);
}
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",
/* ------------------------------------------------------------- */
-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;
}
/* ------------------------------------------------------------- */
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))) {
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;
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;
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;
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);
}
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) {
/* ------------------------------------------------------------- */
-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;
}
/* ------------------------------------------------------------- */
#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>
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;
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;
NCCI = b1_get_word(card->port);
if (NCCI != 0xffffffff)
- ctrl->free_ncci(ctrl, ApplId, NCCI);
+ capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
break;
b1_reset(port);
memset(cinfo->version, 0, sizeof(cinfo->version));
+ capilib_release(&cinfo->ncci_head);
ctrl->reseted(ctrl);
}
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;
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;
}
/* ------------------------------------------------------------- */
#include <linux/signal.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
-
+#include <linux/netdevice.h>
#define VER_DRIVER 0
#define VER_CARDTYPE 1
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);
}
__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
***************************************************************/
-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))
{
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);
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:
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;
}
/*********************************************************************
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:
}
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;
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;
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;
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);
#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 ? */
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;
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,
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__ */
#ifdef __KERNEL__
+#include <linux/skbuff.h>
+
struct capi_interface {
__u16 (*capi_isinstalled) (void);