115 lines
2.4 KiB
C
115 lines
2.4 KiB
C
/* $Id$
|
|
*
|
|
* Author Karsten Keil (keil@isdn4linux.de)
|
|
*
|
|
* This file is (c) under GNU PUBLIC LICENSE
|
|
*
|
|
*/
|
|
|
|
#define __NO_VERSION__
|
|
#include <linux/mISDNif.h>
|
|
#include "layer1.h"
|
|
#include "helper.h"
|
|
#include "dchannel.h"
|
|
|
|
static void
|
|
dchannel_bh(dchannel_t *dch)
|
|
{
|
|
struct sk_buff *skb;
|
|
int err;
|
|
mISDN_head_t *hh;
|
|
|
|
if (!dch)
|
|
return;
|
|
if (dch->debug)
|
|
printk(KERN_DEBUG "%s: event %lx\n", __FUNCTION__, dch->event);
|
|
#if 0
|
|
if (test_and_clear_bit(D_CLEARBUSY, &dch->event)) {
|
|
if (dch->debug)
|
|
debugprint(&dch->inst, "D-Channel Busy cleared");
|
|
stptr = dch->stlist;
|
|
while (stptr != NULL) {
|
|
stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
|
|
stptr = stptr->next;
|
|
}
|
|
}
|
|
#endif
|
|
if (test_and_clear_bit(D_XMTBUFREADY, &dch->event)) {
|
|
if ((skb = dch->next_skb)) {
|
|
hh = mISDN_HEAD_P(skb);
|
|
dch->next_skb = NULL;
|
|
skb_trim(skb, 0);
|
|
if (if_newhead(&dch->inst.up, PH_DATA_CNF, hh->dinfo, skb))
|
|
dev_kfree_skb(skb);
|
|
}
|
|
}
|
|
|
|
if (test_and_clear_bit(D_RCVBUFREADY, &dch->event)) {
|
|
while ((skb = skb_dequeue(&dch->rqueue))) {
|
|
err = if_newhead(&dch->inst.up, PH_DATA_IND, DINFO_SKB, skb);
|
|
if (err < 0) {
|
|
printk(KERN_WARNING "%s: deliver err %d\n", __FUNCTION__, err);
|
|
dev_kfree_skb(skb);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dch->hw_bh)
|
|
dch->hw_bh(dch);
|
|
}
|
|
|
|
int
|
|
init_dchannel(dchannel_t *dch) {
|
|
if (!(dch->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
|
|
printk(KERN_WARNING
|
|
"mISDN: No memory for dlog\n");
|
|
return(-ENOMEM);
|
|
}
|
|
if (!(dch->tx_buf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
|
|
printk(KERN_WARNING
|
|
"mISDN: No memory for dchannel tx_buf\n");
|
|
kfree(dch->dlog);
|
|
dch->dlog = NULL;
|
|
return(-ENOMEM);
|
|
}
|
|
dch->hw = NULL;
|
|
dch->rx_skb = NULL;
|
|
dch->tx_idx = 0;
|
|
dch->next_skb = NULL;
|
|
dch->event = 0;
|
|
INIT_WORK(&dch->work, (void *)(void *)dchannel_bh, dch);
|
|
dch->hw_bh = NULL;
|
|
skb_queue_head_init(&dch->rqueue);
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
free_dchannel(dchannel_t *dch) {
|
|
#ifdef HAS_WORKQUEUE
|
|
if (dch->work.pending)
|
|
printk(KERN_ERR "free_dchannel work:(%lx)\n", dch->work.pending);
|
|
#else
|
|
if (dch->work.sync)
|
|
printk(KERN_ERR "free_dchannel work:(%lx)\n", dch->work.sync);
|
|
#endif
|
|
discard_queue(&dch->rqueue);
|
|
if (dch->rx_skb) {
|
|
dev_kfree_skb(dch->rx_skb);
|
|
dch->rx_skb = NULL;
|
|
}
|
|
if (dch->tx_buf) {
|
|
kfree(dch->tx_buf);
|
|
dch->tx_buf = NULL;
|
|
}
|
|
if (dch->next_skb) {
|
|
dev_kfree_skb(dch->next_skb);
|
|
dch->next_skb = NULL;
|
|
}
|
|
if (dch->dlog) {
|
|
kfree(dch->dlog);
|
|
dch->dlog = NULL;
|
|
}
|
|
return(0);
|
|
}
|
|
|