use the common kernel list.h implementation for the lists in mISDN
This commit is contained in:
parent
818a365de2
commit
918caa4018
|
@ -130,8 +130,7 @@ typedef struct hdlc_hw {
|
|||
|
||||
|
||||
typedef struct _fritzpnppci {
|
||||
struct _fritzpnppci *prev;
|
||||
struct _fritzpnppci *next;
|
||||
struct list_head list;
|
||||
void *pdev;
|
||||
u_int type;
|
||||
u_int irq;
|
||||
|
@ -410,7 +409,8 @@ hdlc_empty_fifo(bchannel_t *bch, int count)
|
|||
mISDN_debugprint(&bch->inst, "hdlc_empty_fifo: incoming packet too large");
|
||||
return;
|
||||
}
|
||||
ptr = (u_int *) p = bch->rx_buf + bch->rx_idx;
|
||||
p = bch->rx_buf + bch->rx_idx;
|
||||
ptr = (u_int *)p;
|
||||
bch->rx_idx += count;
|
||||
if (fc->type == AVM_FRITZ_PCIV2) {
|
||||
while (cnt < count) {
|
||||
|
@ -1110,7 +1110,7 @@ release_card(fritzpnppci *card)
|
|||
mISDN_free_dch(&card->dch);
|
||||
fritz.ctrl(card->dch.inst.up.peer, MGR_DISCONNECT | REQUEST, &card->dch.inst.up);
|
||||
fritz.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
|
||||
REMOVE_FROM_LISTBASE(card, ((fritzpnppci *)fritz.ilist));
|
||||
list_del(&card->list);
|
||||
unlock_dev(card);
|
||||
if (card->type == AVM_FRITZ_PNP) {
|
||||
pnp_disable_dev(card->pdev);
|
||||
|
@ -1124,7 +1124,7 @@ release_card(fritzpnppci *card)
|
|||
|
||||
static int
|
||||
fritz_manager(void *data, u_int prim, void *arg) {
|
||||
fritzpnppci *card = fritz.ilist;
|
||||
fritzpnppci *card;
|
||||
mISDNinstance_t *inst = data;
|
||||
struct sk_buff *skb;
|
||||
int channel = -1;
|
||||
|
@ -1138,7 +1138,7 @@ fritz_manager(void *data, u_int prim, void *arg) {
|
|||
__FUNCTION__, prim, arg);
|
||||
return(-EINVAL);
|
||||
}
|
||||
while(card) {
|
||||
list_for_each_entry(card, &fritz.ilist, list) {
|
||||
if (&card->dch.inst == inst) {
|
||||
channel = 2;
|
||||
break;
|
||||
|
@ -1151,7 +1151,6 @@ fritz_manager(void *data, u_int prim, void *arg) {
|
|||
channel = 1;
|
||||
break;
|
||||
}
|
||||
card = card->next;
|
||||
}
|
||||
if (channel<0) {
|
||||
printk(KERN_WARNING "%s: no channel data %p prim %x arg %p\n",
|
||||
|
@ -1245,7 +1244,7 @@ static int __devinit setup_instance(fritzpnppci *card)
|
|||
int i, err;
|
||||
mISDN_pid_t pid;
|
||||
|
||||
APPEND_TO_LIST(card, ((fritzpnppci *)fritz.ilist));
|
||||
list_add_tail(&card->list, &fritz.ilist);
|
||||
card->dch.debug = debug;
|
||||
lock_HW_init(&card->lock);
|
||||
card->dch.inst.lock = lock_dev;
|
||||
|
@ -1274,7 +1273,7 @@ static int __devinit setup_instance(fritzpnppci *card)
|
|||
mISDN_free_dch(&card->dch);
|
||||
mISDN_free_bch(&card->bch[1]);
|
||||
mISDN_free_bch(&card->bch[0]);
|
||||
REMOVE_FROM_LISTBASE(card, ((fritzpnppci *)fritz.ilist));
|
||||
list_del(&card->list);
|
||||
kfree(card);
|
||||
return(err);
|
||||
}
|
||||
|
@ -1460,18 +1459,16 @@ static int __init Fritz_init(void)
|
|||
int err, pci_nr_found;
|
||||
|
||||
printk(KERN_INFO "AVM Fritz PCI/PnP driver Rev. %s\n", mISDN_getrev(avm_fritz_rev));
|
||||
|
||||
#ifdef MODULE
|
||||
fritz.owner = THIS_MODULE;
|
||||
#endif
|
||||
INIT_LIST_HEAD(&fritz.ilist);
|
||||
fritz.name = FritzName;
|
||||
fritz.own_ctrl = fritz_manager;
|
||||
fritz.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0;
|
||||
fritz.BPROTO.protocol[1] = ISDN_PID_L1_B_64TRANS |
|
||||
ISDN_PID_L1_B_64HDLC;
|
||||
fritz.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANS;
|
||||
fritz.prev = NULL;
|
||||
fritz.next = NULL;
|
||||
if ((err = mISDN_register(&fritz))) {
|
||||
printk(KERN_ERR "Can't register Fritz PCI error(%d)\n", err);
|
||||
return(err);
|
||||
|
@ -1507,14 +1504,16 @@ static int __init Fritz_init(void)
|
|||
|
||||
static void __exit Fritz_cleanup(void)
|
||||
{
|
||||
fritzpnppci *card, *next;
|
||||
int err;
|
||||
|
||||
if ((err = mISDN_unregister(&fritz))) {
|
||||
printk(KERN_ERR "Can't unregister Fritz PCI error(%d)\n", err);
|
||||
}
|
||||
while(fritz.ilist) {
|
||||
list_for_each_entry_safe(card, next, &fritz.ilist, list) {
|
||||
printk(KERN_ERR "Fritz PCI card struct not empty refs %d\n",
|
||||
fritz.refcnt);
|
||||
release_card(fritz.ilist);
|
||||
release_card(card);
|
||||
}
|
||||
#if defined(CONFIG_PNP)
|
||||
pnp_unregister_driver(&fcpnp_driver);
|
||||
|
|
|
@ -193,7 +193,7 @@ free_garbage(void)
|
|||
kmem_cache_free(mISDN_AppPlci_cp, item);
|
||||
break;
|
||||
case KM_DBG_TYP_NI:
|
||||
printk(KERN_DEBUG "Ncci: NCCI(%x) state(%x) m.state(%x) aplci(%p)\n",
|
||||
printk(KERN_DEBUG "Ncci: NCCI(%x) state(%lx) m.state(%x) aplci(%p)\n",
|
||||
kda->a.ni.addr,
|
||||
kda->a.ni.state,
|
||||
kda->a.ni.ncci_m.state,
|
||||
|
@ -310,30 +310,29 @@ capi20_manager(void *data, u_int prim, void *arg) {
|
|||
mISDNinstance_t *inst = data;
|
||||
int found=0;
|
||||
PLInst_t *plink = NULL;
|
||||
Controller_t *ctrl = (Controller_t *)capi_obj.ilist;
|
||||
Controller_t *ctrl;
|
||||
|
||||
if (CAPI_DBG_INFO & debug)
|
||||
printk(KERN_DEBUG "capi20_manager data:%p prim:%x arg:%p\n", data, prim, arg);
|
||||
if (!data)
|
||||
return(-EINVAL);
|
||||
while(ctrl) {
|
||||
list_for_each_entry(ctrl, &capi_obj.ilist, list) {
|
||||
if (&ctrl->inst == inst) {
|
||||
found++;
|
||||
break;
|
||||
}
|
||||
plink = ctrl->linklist;
|
||||
while(plink) {
|
||||
list_for_each_entry(plink, &ctrl->linklist, list) {
|
||||
if (&plink->inst == inst) {
|
||||
found++;
|
||||
break;
|
||||
}
|
||||
plink = plink->next;
|
||||
}
|
||||
if (found)
|
||||
break;
|
||||
plink = NULL;
|
||||
ctrl = ctrl->next;
|
||||
}
|
||||
if (&ctrl->list == &capi_obj.ilist)
|
||||
ctrl = NULL;
|
||||
if (prim == (MGR_NEWLAYER | REQUEST)) {
|
||||
int ret = ControllerConstr(&ctrl, data, arg, &capi_obj);
|
||||
if (!ret)
|
||||
|
@ -398,9 +397,7 @@ int Capi20Init(void)
|
|||
capi_obj.BPROTO.protocol[4] = ISDN_PID_L4_B_CAPI20;
|
||||
capi_obj.BPROTO.protocol[3] = ISDN_PID_L3_B_TRANS;
|
||||
capi_obj.own_ctrl = capi20_manager;
|
||||
capi_obj.prev = NULL;
|
||||
capi_obj.next = NULL;
|
||||
capi_obj.ilist = NULL;
|
||||
INIT_LIST_HEAD(&capi_obj.ilist);
|
||||
if ((err = CapiNew()))
|
||||
return(err);
|
||||
if ((err = mISDN_register(&capi_obj))) {
|
||||
|
@ -421,14 +418,14 @@ int Capi20Init(void)
|
|||
static void Capi20cleanup(void)
|
||||
{
|
||||
int err;
|
||||
Controller_t *contr;
|
||||
Controller_t *contr, *next;
|
||||
|
||||
if ((err = mISDN_unregister(&capi_obj))) {
|
||||
printk(KERN_ERR "Can't unregister CAPI20 error(%d)\n", err);
|
||||
}
|
||||
if (capi_obj.ilist) {
|
||||
if (!list_empty(&capi_obj.ilist)) {
|
||||
printk(KERN_WARNING "mISDN controller list not empty\n");
|
||||
while((contr = capi_obj.ilist))
|
||||
list_for_each_entry_safe(contr, next, &capi_obj.ilist, list)
|
||||
ControllerDestr(contr);
|
||||
}
|
||||
#ifdef OLDCAPI_DRIVER_INTERFACE
|
||||
|
|
|
@ -20,7 +20,7 @@ ControllerDestr(Controller_t *contr)
|
|||
|
||||
spin_lock_irqsave(&contr->list_lock, flags);
|
||||
list_for_each_safe(item, next, &contr->Applications) {
|
||||
ApplicationDestr((Application_t *)item, 3);
|
||||
ApplicationDestr(list_entry(item, Application_t, head), 3);
|
||||
}
|
||||
if (contr->plcis) {
|
||||
Plci_t *plci = contr->plcis;
|
||||
|
@ -46,7 +46,7 @@ ControllerDestr(Controller_t *contr)
|
|||
contr->plcis = NULL;
|
||||
}
|
||||
list_for_each_safe(item, next, &contr->SSProcesse) {
|
||||
SSProcessDestr((SSProcess_t *)item);
|
||||
SSProcessDestr(list_entry(item, SSProcess_t, head));
|
||||
}
|
||||
#ifdef OLDCAPI_DRIVER_INTERFACE
|
||||
if (contr->ctrl)
|
||||
|
@ -66,15 +66,15 @@ ControllerDestr(Controller_t *contr)
|
|||
inst->down.peer->obj->ctrl(inst->down.peer,
|
||||
MGR_DISCONNECT | REQUEST, &inst->down);
|
||||
}
|
||||
while (contr->linklist) {
|
||||
PLInst_t *plink = contr->linklist;
|
||||
REMOVE_FROM_LISTBASE(plink, contr->linklist);
|
||||
list_for_each_safe(item, next, &contr->linklist) {
|
||||
PLInst_t *plink = list_entry(item, PLInst_t, list);
|
||||
list_del(&plink->list);
|
||||
kfree(plink);
|
||||
}
|
||||
if (contr->entity != MISDN_ENTITY_NONE)
|
||||
inst->obj->ctrl(inst, MGR_DELENTITY | REQUEST, (void *)contr->entity);
|
||||
inst->obj->ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
|
||||
REMOVE_FROM_LISTBASE(contr, ((Controller_t *)inst->obj->ilist));
|
||||
list_del(&contr->list);
|
||||
spin_unlock_irqrestore(&contr->list_lock, flags);
|
||||
kfree(contr);
|
||||
}
|
||||
|
@ -116,8 +116,13 @@ ControllerRun(Controller_t *contr)
|
|||
pidmask.protocol[1] = 0x03ff;
|
||||
pidmask.protocol[2] = 0x1fff;
|
||||
pidmask.protocol[3] = 0x00ff;
|
||||
plink = contr->linklist;
|
||||
ret = plink->inst.obj->ctrl(plink->st, MGR_EVALSTACK | REQUEST, &pidmask);
|
||||
if (list_empty(&contr->linklist)) {
|
||||
int_error();
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
plink = list_entry(contr->linklist.next, PLInst_t, list);
|
||||
ret = plink->inst.obj->ctrl(plink->st, MGR_EVALSTACK | REQUEST, &pidmask);
|
||||
}
|
||||
if (ret) {
|
||||
/* Fallback on error, minimum set */
|
||||
int_error();
|
||||
|
@ -510,13 +515,25 @@ ControllerPutStatus(Controller_t *contr, char *msg)
|
|||
int
|
||||
ControllerConstr(Controller_t **contr_p, mISDNstack_t *st, mISDN_pid_t *pid, mISDNobject_t *ocapi)
|
||||
{
|
||||
Controller_t *contr;
|
||||
int retval;
|
||||
mISDNstack_t *cst;
|
||||
PLInst_t *plink;
|
||||
struct list_head *head;
|
||||
Controller_t *contr;
|
||||
int retval;
|
||||
mISDNstack_t *cst;
|
||||
PLInst_t *plink;
|
||||
|
||||
if (!st)
|
||||
return(-EINVAL);
|
||||
if (list_empty(&st->childlist)) {
|
||||
if ((st->id & FLG_CLONE_STACK) &&
|
||||
(st->childlist.prev != &st->childlist)) {
|
||||
head = st->childlist.prev;
|
||||
} else {
|
||||
printk(KERN_ERR "%s: invalid empty childlist (no clone) stid(%x) childlist(%p<-%p->%p)\n",
|
||||
__FUNCTION__, st->id, st->childlist.prev, &st->childlist, st->childlist.next);
|
||||
return(-EINVAL);
|
||||
}
|
||||
} else
|
||||
head = &st->childlist;
|
||||
if (!pid)
|
||||
return(-EINVAL);
|
||||
contr = kmalloc(sizeof(Controller_t), GFP_KERNEL);
|
||||
|
@ -525,6 +542,7 @@ ControllerConstr(Controller_t **contr_p, mISDNstack_t *st, mISDN_pid_t *pid, mIS
|
|||
memset(contr, 0, sizeof(Controller_t));
|
||||
INIT_LIST_HEAD(&contr->Applications);
|
||||
INIT_LIST_HEAD(&contr->SSProcesse);
|
||||
INIT_LIST_HEAD(&contr->linklist);
|
||||
spin_lock_init(&contr->list_lock);
|
||||
spin_lock_init(&contr->id_lock);
|
||||
contr->next_id = 1;
|
||||
|
@ -538,11 +556,8 @@ ControllerConstr(Controller_t **contr_p, mISDNstack_t *st, mISDN_pid_t *pid, mIS
|
|||
}
|
||||
memset(contr->ctrl, 0, sizeof(struct capi_ctr));
|
||||
#endif
|
||||
cst = st->child;
|
||||
while(cst) {
|
||||
list_for_each_entry(cst, head, list)
|
||||
contr->nr_bc++;
|
||||
cst = cst->next;
|
||||
}
|
||||
if (!contr->nr_bc) {
|
||||
printk(KERN_ERR "no bchannels\n");
|
||||
ControllerDestr(contr);
|
||||
|
@ -571,8 +586,7 @@ ControllerConstr(Controller_t **contr_p, mISDNstack_t *st, mISDN_pid_t *pid, mIS
|
|||
ControllerDestr(contr);
|
||||
return(-ENOPROTOOPT);
|
||||
}
|
||||
cst = st->child;
|
||||
while(cst) {
|
||||
list_for_each_entry(cst, head, list) {
|
||||
if (!(plink = kmalloc(sizeof(PLInst_t), GFP_KERNEL))) {
|
||||
printk(KERN_ERR "no mem for PLinst\n");
|
||||
int_error();
|
||||
|
@ -585,10 +599,9 @@ ControllerConstr(Controller_t **contr_p, mISDNstack_t *st, mISDN_pid_t *pid, mIS
|
|||
mISDN_init_instance(&plink->inst, ocapi, plink);
|
||||
plink->inst.pid.layermask |= ISDN_LAYER(4);
|
||||
plink->inst.down.stat = IF_NOACTIV;
|
||||
APPEND_TO_LIST(plink, contr->linklist);
|
||||
cst = cst->next;
|
||||
list_add_tail(&plink->list, &contr->linklist);
|
||||
}
|
||||
APPEND_TO_LIST(contr, ocapi->ilist);
|
||||
list_add_tail(&contr->list, &ocapi->ilist);
|
||||
contr->entity = MISDN_ENTITY_NONE;
|
||||
retval = ocapi->ctrl(&contr->inst, MGR_NEWENTITY | REQUEST, NULL);
|
||||
if (retval) {
|
||||
|
@ -639,26 +652,23 @@ ControllerSelChannel(Controller_t *contr, u_int channel)
|
|||
channel_info_t ci;
|
||||
int ret;
|
||||
|
||||
if (!contr->linklist) {
|
||||
if (list_empty(&contr->linklist)) {
|
||||
int_errtxt("no linklist for controller(%x)", contr->addr);
|
||||
return(NULL);
|
||||
}
|
||||
ci.channel = channel;
|
||||
ci.st.p = NULL;
|
||||
ret = contr->inst.obj->ctrl(contr->inst.st, MGR_SELCHANNEL | REQUEST,
|
||||
&ci);
|
||||
ret = contr->inst.obj->ctrl(contr->inst.st, MGR_SELCHANNEL | REQUEST, &ci);
|
||||
if (ret) {
|
||||
int_errtxt("MGR_SELCHANNEL ret(%d)", ret);
|
||||
return(NULL);
|
||||
}
|
||||
cst = ci.st.p;
|
||||
plink = contr->linklist;
|
||||
while(plink) {
|
||||
list_for_each_entry(plink, &contr->linklist, list) {
|
||||
if (cst == plink->st)
|
||||
break;
|
||||
plink = plink->next;
|
||||
return(plink);
|
||||
}
|
||||
return(plink);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -19,10 +19,11 @@
|
|||
#include <linux/smp_lock.h>
|
||||
#endif
|
||||
|
||||
static char *mISDN_core_revision = "$Revision$";
|
||||
static char *mISDN_core_revision = "$Revision$";
|
||||
|
||||
LIST_HEAD(mISDN_objectlist);
|
||||
rwlock_t mISDN_objects_lock = RW_LOCK_UNLOCKED;
|
||||
|
||||
mISDNobject_t *mISDN_objects = NULL;
|
||||
rwlock_t mISDN_objects_lock = RW_LOCK_UNLOCKED;
|
||||
int core_debug;
|
||||
|
||||
static u_char entityarray[MISDN_MAX_ENTITY/8];
|
||||
|
@ -153,14 +154,13 @@ get_object(int id) {
|
|||
mISDNobject_t *obj;
|
||||
|
||||
read_lock(&mISDN_objects_lock);
|
||||
obj = mISDN_objects;
|
||||
while(obj) {
|
||||
if (obj->id == id)
|
||||
break;
|
||||
obj = obj->next;
|
||||
}
|
||||
list_for_each_entry(obj, &mISDN_objectlist, list)
|
||||
if (obj->id == id) {
|
||||
read_unlock(&mISDN_objects_lock);
|
||||
return(obj);
|
||||
}
|
||||
read_unlock(&mISDN_objects_lock);
|
||||
return(obj);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
static mISDNobject_t *
|
||||
|
@ -169,17 +169,17 @@ find_object(int protocol) {
|
|||
int err;
|
||||
|
||||
read_lock(&mISDN_objects_lock);
|
||||
obj = mISDN_objects;
|
||||
while (obj) {
|
||||
list_for_each_entry(obj, &mISDN_objectlist, list) {
|
||||
err = obj->own_ctrl(NULL, MGR_HASPROTOCOL | REQUEST, &protocol);
|
||||
if (!err)
|
||||
break;
|
||||
goto unlock;
|
||||
if (err != -ENOPROTOOPT) {
|
||||
if (0 == mISDN_HasProtocol(obj, protocol))
|
||||
break;
|
||||
goto unlock;
|
||||
}
|
||||
obj = obj->next;
|
||||
}
|
||||
obj = NULL;
|
||||
unlock:
|
||||
read_unlock(&mISDN_objects_lock);
|
||||
return(obj);
|
||||
}
|
||||
|
@ -220,26 +220,16 @@ find_object_module(int protocol) {
|
|||
|
||||
static void
|
||||
remove_object(mISDNobject_t *obj) {
|
||||
mISDNstack_t *st = mISDN_stacklist;
|
||||
mISDNlayer_t *layer;
|
||||
mISDNinstance_t *inst, *tmp;
|
||||
mISDNstack_t *st, *nst;
|
||||
mISDNlayer_t *layer, *nl;
|
||||
mISDNinstance_t *inst;
|
||||
|
||||
while (st) {
|
||||
layer = st->lstack;
|
||||
while(layer) {
|
||||
list_for_each_entry_safe(st, nst, &mISDN_stacklist, list) {
|
||||
list_for_each_entry_safe(layer, nl, &st->layerlist, list) {
|
||||
inst = layer->inst;
|
||||
while (inst) {
|
||||
if (inst->obj == obj) {
|
||||
tmp = inst->next;
|
||||
inst->obj->own_ctrl(st, MGR_RELEASE
|
||||
| INDICATION, inst);
|
||||
inst = tmp;
|
||||
} else
|
||||
inst = inst->next;
|
||||
}
|
||||
layer = layer->next;
|
||||
if (inst && inst->obj == obj)
|
||||
inst->obj->own_ctrl(st, MGR_RELEASE | INDICATION, inst);
|
||||
}
|
||||
st = st->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -296,7 +286,7 @@ get_next_instance(mISDNstack_t *st, mISDN_pid_t *pid)
|
|||
static int
|
||||
sel_channel(mISDNstack_t *st, channel_info_t *ci)
|
||||
{
|
||||
int err = -EINVAL;
|
||||
int err = -EINVAL;
|
||||
|
||||
if (!ci)
|
||||
return(err);
|
||||
|
@ -314,20 +304,30 @@ sel_channel(mISDNstack_t *st, channel_info_t *ci)
|
|||
printk(KERN_WARNING "%s: no mgr st(%p)\n", __FUNCTION__, st);
|
||||
}
|
||||
if (err) {
|
||||
mISDNstack_t *cst = st->child;
|
||||
mISDNstack_t *cst;
|
||||
u_int nr = 0;
|
||||
|
||||
ci->st.p = NULL;
|
||||
if (!(ci->channel & (~CHANNEL_NUMBER))) {
|
||||
/* only number is set */
|
||||
while(cst) {
|
||||
struct list_head *head;
|
||||
if (list_empty(&st->childlist)) {
|
||||
if ((st->id & FLG_CLONE_STACK) &&
|
||||
(st->childlist.prev != &st->childlist)) {
|
||||
head = st->childlist.prev;
|
||||
} else {
|
||||
printk(KERN_WARNING "%s: invalid empty childlist (no clone) stid(%x) childlist(%p<-%p->%p)\n",
|
||||
__FUNCTION__, st->id, st->childlist.prev, &st->childlist, st->childlist.next);
|
||||
return(err);
|
||||
}
|
||||
} else
|
||||
head = &st->childlist;
|
||||
list_for_each_entry(cst, head, list) {
|
||||
nr++;
|
||||
if (nr == (ci->channel & 3)) {
|
||||
ci->st.p = cst;
|
||||
err = 0;
|
||||
break;
|
||||
return(0);
|
||||
}
|
||||
cst = cst->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -363,7 +363,10 @@ add_if(mISDNinstance_t *inst, u_int prim, mISDNif_t *hif) {
|
|||
myif = &inst->up;
|
||||
} else
|
||||
return(-EINVAL);
|
||||
APPEND_TO_LIST(hif, myif);
|
||||
while(myif->clone)
|
||||
myif = myif->clone;
|
||||
myif->clone = hif;
|
||||
hif->predecessor = myif;
|
||||
inst->obj->own_ctrl(inst, prim, hif);
|
||||
return(0);
|
||||
}
|
||||
|
@ -567,7 +570,7 @@ int mISDN_register(mISDNobject_t *obj) {
|
|||
return(-EINVAL);
|
||||
write_lock_irqsave(&mISDN_objects_lock, flags);
|
||||
obj->id = obj_id++;
|
||||
APPEND_TO_LIST(obj, mISDN_objects);
|
||||
list_add_tail(&obj->list, &mISDN_objectlist);
|
||||
write_unlock_irqrestore(&mISDN_objects_lock, flags);
|
||||
obj->ctrl = central_manager;
|
||||
// register_prop
|
||||
|
@ -592,10 +595,11 @@ int mISDN_unregister(mISDNobject_t *obj) {
|
|||
else
|
||||
remove_object(obj);
|
||||
write_lock_irqsave(&mISDN_objects_lock, flags);
|
||||
REMOVE_FROM_LISTBASE(obj, mISDN_objects);
|
||||
list_del(&obj->list);
|
||||
write_unlock_irqrestore(&mISDN_objects_lock, flags);
|
||||
if (core_debug & DEBUG_CORE_FUNC)
|
||||
printk(KERN_DEBUG "mISDN_unregister: mISDN_objects(%p)\n", mISDN_objects);
|
||||
printk(KERN_DEBUG "mISDN_unregister: mISDN_objectlist(%p<-%p->%p)\n",
|
||||
mISDN_objectlist.prev, &mISDN_objectlist, mISDN_objectlist.next);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -628,23 +632,21 @@ mISDNInit(void)
|
|||
|
||||
void mISDN_cleanup(void) {
|
||||
DECLARE_MUTEX_LOCKED(sem);
|
||||
mISDNstack_t *st;
|
||||
mISDNstack_t *st, *nst;
|
||||
|
||||
free_mISDNdev();
|
||||
if (mISDN_objects) {
|
||||
if (!list_empty(&mISDN_objectlist)) {
|
||||
printk(KERN_WARNING "mISDNcore mISDN_objects not empty\n");
|
||||
}
|
||||
if (mISDN_stacklist) {
|
||||
if (!list_empty(&mISDN_stacklist)) {
|
||||
printk(KERN_WARNING "mISDNcore mISDN_stacklist not empty\n");
|
||||
st = mISDN_stacklist;
|
||||
while (st) {
|
||||
printk(KERN_WARNING "mISDNcore st %x in list\n",
|
||||
list_for_each_entry_safe(st, nst, &mISDN_stacklist, list) {
|
||||
printk(KERN_WARNING "mISDNcore st %x still in list\n",
|
||||
st->id);
|
||||
if (st == st->next) {
|
||||
if (list_empty(&st->list)) {
|
||||
printk(KERN_WARNING "mISDNcore st == next\n");
|
||||
break;
|
||||
}
|
||||
st = st->next;
|
||||
}
|
||||
}
|
||||
if (mISDN_thread.thread) {
|
||||
|
|
|
@ -37,8 +37,8 @@ extern int free_device(mISDNdevice_t *dev);
|
|||
|
||||
/* from mISDN_stack.c */
|
||||
|
||||
extern mISDNstack_t *mISDN_stacklist;
|
||||
extern mISDNinstance_t *mISDN_instlist;
|
||||
extern struct list_head mISDN_stacklist;
|
||||
extern struct list_head mISDN_instlist;
|
||||
|
||||
extern void get_stack_info(iframe_t *);
|
||||
extern int get_stack_cnt(void);
|
||||
|
@ -57,7 +57,7 @@ extern mISDNinstance_t *get_instance(mISDNstack_t *, int, int);
|
|||
|
||||
/* from mISDN_core.c */
|
||||
|
||||
extern mISDNobject_t *mISDN_objects;
|
||||
extern struct list_head mISDN_objectlist;
|
||||
extern int core_debug;
|
||||
|
||||
extern int register_layer(mISDNstack_t *, mISDNinstance_t *);
|
||||
|
|
|
@ -78,24 +78,22 @@ extern u8 silence;
|
|||
/* all members within a conference (this is linked 1:1 with the dsp) */
|
||||
struct _dsp;
|
||||
typedef struct _conf_member {
|
||||
struct _conf_member *prev;
|
||||
struct _conf_member *next;
|
||||
struct _dsp *dsp;
|
||||
struct list_head list;
|
||||
struct _dsp *dsp;
|
||||
} conf_member_t;
|
||||
|
||||
/* the list of all conferences */
|
||||
typedef struct _conference {
|
||||
struct _conference *prev;
|
||||
struct _conference *next;
|
||||
u32 id; /* all cmx stacks with the same ID are connected */
|
||||
conf_member_t *mlist;
|
||||
int software; /* conf is processed by software */
|
||||
int hardware; /* conf is processed by hardware */
|
||||
struct list_head list;
|
||||
u32 id; /* all cmx stacks with the same ID are connected */
|
||||
struct list_head mlist;
|
||||
int software; /* conf is processed by software */
|
||||
int hardware; /* conf is processed by hardware */
|
||||
//#ifndef AUTOJITTER
|
||||
int largest; /* largest frame received in conf's life. */
|
||||
int largest; /* largest frame received in conf's life. */
|
||||
//#endif
|
||||
int W_min, W_max; /* min/maximum rx-write pointer of members */
|
||||
s32 conf_buff[CMX_BUFF_SIZE];
|
||||
int W_min, W_max; /* min/maximum rx-write pointer of members */
|
||||
s32 conf_buff[CMX_BUFF_SIZE];
|
||||
} conference_t;
|
||||
|
||||
extern mISDNobject_t dsp_obj;
|
||||
|
@ -148,8 +146,7 @@ struct dsp_features {
|
|||
};
|
||||
|
||||
typedef struct _dsp {
|
||||
struct _dsp *prev;
|
||||
struct _dsp *next;
|
||||
struct list_head list;
|
||||
mISDNinstance_t inst;
|
||||
int b_active;
|
||||
int echo; /* echo is done by software */
|
||||
|
@ -205,7 +202,7 @@ typedef struct _dsp {
|
|||
|
||||
extern void dsp_change_volume(struct sk_buff *skb, int volume);
|
||||
|
||||
extern conference_t *Conf_list;
|
||||
extern struct list_head Conf_list;
|
||||
extern void dsp_cmx_debug(dsp_t *dsp);
|
||||
extern void dsp_cmx_hardware(conference_t *conf, dsp_t *dsp);
|
||||
extern int dsp_cmx_conf(dsp_t *dsp, u32 conf_id);
|
||||
|
|
|
@ -149,7 +149,7 @@
|
|||
//#define CMX_DEBUG /* massive read/write pointer output */
|
||||
|
||||
extern mISDN_HWlock_t dsp_lock;
|
||||
conference_t *Conf_list = NULL;
|
||||
LIST_HEAD(Conf_list);
|
||||
|
||||
/*
|
||||
* debug cmx memory structure
|
||||
|
@ -162,8 +162,7 @@ dsp_cmx_debug(dsp_t *dsp)
|
|||
dsp_t *odsp;
|
||||
|
||||
printk(KERN_DEBUG "-----Current DSP\n");
|
||||
odsp = (dsp_t *)dsp_obj.ilist;
|
||||
while(odsp)
|
||||
list_for_each_entry(odsp, &dsp_obj.ilist, list)
|
||||
{
|
||||
printk(KERN_DEBUG "* %s echo=%d txmix=%d", odsp->inst.name, odsp->echo, odsp->tx_mix);
|
||||
if (odsp->conf)
|
||||
|
@ -171,21 +170,16 @@ dsp_cmx_debug(dsp_t *dsp)
|
|||
if (dsp == odsp)
|
||||
printk(" *this*");
|
||||
printk("\n");
|
||||
odsp = odsp->next;
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG "-----Current Conf:\n");
|
||||
conf = Conf_list;
|
||||
while(conf)
|
||||
list_for_each_entry(conf, &Conf_list, list)
|
||||
{
|
||||
printk(KERN_DEBUG "* Conf %d (0x%x)\n", conf->id, (u32)conf);
|
||||
member = conf->mlist;
|
||||
while(member)
|
||||
list_for_each_entry(member, &conf->mlist, list)
|
||||
{
|
||||
printk(KERN_DEBUG " - member = %s (slot_tx %d, bank_tx %d, slot_rx %d, bank_rx %d hfc_conf %d)%s\n", member->dsp->inst.name, member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx, member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx, member->dsp->hfc_conf, (member->dsp==dsp)?" *this*":"");
|
||||
member = member->next;
|
||||
}
|
||||
conf = conf->next;
|
||||
}
|
||||
printk(KERN_DEBUG "-----end\n");
|
||||
}
|
||||
|
@ -205,12 +199,9 @@ static conference_t
|
|||
}
|
||||
|
||||
/* search conference */
|
||||
conf = Conf_list;
|
||||
while(conf) {
|
||||
list_for_each_entry(conf, &Conf_list, list)
|
||||
if (conf->id == id)
|
||||
return(conf);
|
||||
conf = conf->next;
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
@ -254,10 +245,10 @@ dsp_cmx_add_conf_member(dsp_t *dsp, conference_t *conf)
|
|||
dsp->W_rx = conf->W_max;
|
||||
dsp->R_rx = conf->W_max;
|
||||
|
||||
APPEND_TO_LIST(member, ((conf_member_t *)conf->mlist));
|
||||
list_add_tail(&member->list, &conf->mlist);
|
||||
|
||||
/* zero conf-buffer if we change from 2 to 3 members */
|
||||
if (conf->mlist->next) if (!conf->mlist->next->next)
|
||||
if (3 == count_list_member(&conf->mlist))
|
||||
memset(conf->conf_buff, 0, sizeof(conf->conf_buff));
|
||||
|
||||
dsp->conf = conf;
|
||||
|
@ -287,33 +278,28 @@ dsp_cmx_del_conf_member(dsp_t *dsp)
|
|||
return(-EINVAL);
|
||||
}
|
||||
|
||||
member = dsp->conf->mlist;
|
||||
if (!member) {
|
||||
if (list_empty(&dsp->conf->mlist)) {
|
||||
printk(KERN_WARNING "%s: dsp has linked an empty conf.\n",
|
||||
__FUNCTION__);
|
||||
return(-EINVAL);
|
||||
}
|
||||
|
||||
/* find us in conf */
|
||||
while(member) {
|
||||
if (member->dsp == dsp)
|
||||
break;
|
||||
member = member->next;
|
||||
}
|
||||
if (!member) {
|
||||
printk(KERN_WARNING "%s: dsp is not present in its own conf_meber list.\n",
|
||||
__FUNCTION__);
|
||||
return(-EINVAL);
|
||||
list_for_each_entry(member, &dsp->conf->mlist, list) {
|
||||
if (member->dsp == dsp) {
|
||||
list_del(&member->list);
|
||||
dsp->conf = NULL;
|
||||
dsp->member = NULL;
|
||||
unlock_HW(&dsp_lock);
|
||||
vfree(member);
|
||||
lock_HW(&dsp_lock, 0);
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
printk(KERN_WARNING "%s: dsp is not present in its own conf_meber list.\n",
|
||||
__FUNCTION__);
|
||||
|
||||
REMOVE_FROM_LISTBASE(member, ((conf_member_t *)dsp->conf->mlist));
|
||||
dsp->conf = NULL;
|
||||
dsp->member = NULL;
|
||||
unlock_HW(&dsp_lock);
|
||||
vfree(member);
|
||||
lock_HW(&dsp_lock, 0);
|
||||
|
||||
return(0);
|
||||
return(-EINVAL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -339,9 +325,10 @@ static conference_t
|
|||
}
|
||||
lock_HW(&dsp_lock, 0);
|
||||
memset(conf, 0, sizeof(conference_t));
|
||||
INIT_LIST_HEAD(&conf->mlist);
|
||||
conf->id = id;
|
||||
|
||||
APPEND_TO_LIST(conf, ((conference_t *)Conf_list));
|
||||
list_add_tail(&conf->list, &Conf_list);
|
||||
|
||||
return(conf);
|
||||
}
|
||||
|
@ -359,13 +346,12 @@ dsp_cmx_del_conf(conference_t *conf)
|
|||
return(-EINVAL);
|
||||
}
|
||||
|
||||
if (conf->mlist) {
|
||||
if (!list_empty(&conf->mlist)) {
|
||||
printk(KERN_WARNING "%s: conf not empty.\n",
|
||||
__FUNCTION__);
|
||||
return(-EINVAL);
|
||||
}
|
||||
|
||||
REMOVE_FROM_LISTBASE(conf, ((conference_t *)Conf_list));
|
||||
list_del(&conf->list);
|
||||
unlock_HW(&dsp_lock);
|
||||
vfree(conf);
|
||||
lock_HW(&dsp_lock, 0);
|
||||
|
@ -409,11 +395,11 @@ dsp_cmx_hw_message(dsp_t *dsp, u32 message, u32 param1, u32 param2, u32 param3,
|
|||
void
|
||||
dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
||||
{
|
||||
conf_member_t *member;
|
||||
conf_member_t *member, *nextm;
|
||||
int memb = 0, i, ii, i1, i2;
|
||||
int freeunits[8];
|
||||
u_char freeslots[256];
|
||||
int same_hfc = -1, current_conf = -1, all_conf = 1;
|
||||
int same_hfc = -1, same_pcm = -1, current_conf = -1, all_conf = 1;
|
||||
|
||||
/* dsp gets updated (no conf) */
|
||||
//printk("-----1\n");
|
||||
|
@ -451,18 +437,22 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
|||
if (dsp_debug & DEBUG_DSP_CMX)
|
||||
printk(KERN_DEBUG "%s checking conference %d\n", __FUNCTION__, conf->id);
|
||||
//printk("-----5\n");
|
||||
|
||||
member = conf->mlist;
|
||||
|
||||
if (list_empty(&conf->mlist)) {
|
||||
printk(KERN_ERR "%s: conference whithout members\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
member = list_entry(conf->mlist.next, conf_member_t, list);
|
||||
same_hfc = member->dsp->features.hfc_id;
|
||||
same_pcm = member->dsp->features.pcm_id;
|
||||
/* check all members in our conference */
|
||||
while (member) {
|
||||
list_for_each_entry(member, &conf->mlist, list) {
|
||||
/* check if member uses mixing */
|
||||
if (member->dsp->tx_mix) {
|
||||
if (dsp_debug & DEBUG_DSP_CMX)
|
||||
printk(KERN_DEBUG "%s dsp %s cannot form a conf, because tx_mix is turned on\n", __FUNCTION__, member->dsp->inst.name);
|
||||
conf_software:
|
||||
member = conf->mlist;
|
||||
while (member) {
|
||||
list_for_each_entry(member, &conf->mlist, list) {
|
||||
dsp = member->dsp;
|
||||
/* remove HFC conference if enabled */
|
||||
if (dsp->hfc_conf >= 0) {
|
||||
|
@ -481,7 +471,6 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
|||
dsp->pcm_slot_rx = -1;
|
||||
dsp->pcm_bank_rx = -1;
|
||||
}
|
||||
member = member->next;
|
||||
}
|
||||
conf->hardware = 0;
|
||||
conf->software = 1;
|
||||
|
@ -517,9 +506,10 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
|||
goto conf_software;
|
||||
}
|
||||
/* check if relations are on the same PCM bus */
|
||||
if (member->dsp->features.pcm_id != conf->mlist->dsp->features.pcm_id) {
|
||||
if (member->dsp->features.pcm_id != same_pcm) {
|
||||
if (dsp_debug & DEBUG_DSP_CMX)
|
||||
printk(KERN_DEBUG "%s dsp %s cannot form a conf, because dsp is on a different PCM bus than the first dsp\n", __FUNCTION__, member->dsp->inst.name);
|
||||
printk(KERN_DEBUG "%s dsp %s cannot form a conf, because dsp is on a different PCM bus than the first dsp\n",
|
||||
__FUNCTION__, member->dsp->inst.name);
|
||||
goto conf_software;
|
||||
}
|
||||
/* determine if members are on the same hfc chip */
|
||||
|
@ -532,7 +522,6 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
|||
if (member->dsp->hfc_conf < 0)
|
||||
all_conf = 0;
|
||||
|
||||
member = member->next;
|
||||
memb++;
|
||||
}
|
||||
|
||||
|
@ -546,7 +535,8 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
|||
printk(KERN_DEBUG "%s conf %d cannot form a HW conference, because dsp is alone\n", __FUNCTION__, conf->id);
|
||||
conf->hardware = 0;
|
||||
conf->software = 1;
|
||||
dsp = conf->mlist->dsp;
|
||||
member = list_entry(conf->mlist.next, conf_member_t, list);
|
||||
dsp = member->dsp;
|
||||
goto one_member;
|
||||
}
|
||||
|
||||
|
@ -557,7 +547,8 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
|||
|
||||
/* if we have only two members */
|
||||
if (memb == 2) {
|
||||
member = conf->mlist;
|
||||
member = list_entry(conf->mlist.next, conf_member_t, list);
|
||||
nextm = list_entry(member->list.next, conf_member_t, list);
|
||||
/* remove HFC conference if enabled */
|
||||
if (member->dsp->hfc_conf >= 0) {
|
||||
if (dsp_debug & DEBUG_DSP_CMX)
|
||||
|
@ -565,39 +556,40 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
|||
dsp_cmx_hw_message(member->dsp, HW_CONF_SPLIT, 0, 0, 0, 0);
|
||||
member->dsp->hfc_conf = -1;
|
||||
}
|
||||
if (member->next->dsp->hfc_conf >= 0) {
|
||||
if (nextm->dsp->hfc_conf >= 0) {
|
||||
if (dsp_debug & DEBUG_DSP_CMX)
|
||||
printk(KERN_DEBUG "%s removing %s from HFC conf %d because two parties require only a PCM slot\n", __FUNCTION__, member->next->dsp->inst.name, member->next->dsp->hfc_conf);
|
||||
dsp_cmx_hw_message(member->next->dsp, HW_CONF_SPLIT, 0, 0, 0, 0);
|
||||
member->next->dsp->hfc_conf = -1;
|
||||
printk(KERN_DEBUG "%s removing %s from HFC conf %d because two parties require only a PCM slot\n", __FUNCTION__, nextm->dsp->inst.name, nextm->dsp->hfc_conf);
|
||||
dsp_cmx_hw_message(nextm->dsp, HW_CONF_SPLIT, 0, 0, 0, 0);
|
||||
nextm->dsp->hfc_conf = -1;
|
||||
}
|
||||
/* if members have two banks (and not on the same chip) */
|
||||
if (member->dsp->features.pcm_banks>1
|
||||
&& member->next->dsp->features.pcm_banks>1
|
||||
&& member->dsp->features.pcm_id!=member->next->dsp->features.pcm_id) {
|
||||
&& nextm->dsp->features.pcm_banks>1
|
||||
&& member->dsp->features.pcm_id!=nextm->dsp->features.pcm_id) {
|
||||
/* if both members have same slots with crossed banks */
|
||||
if (member->dsp->pcm_slot_tx>=0
|
||||
&& member->dsp->pcm_slot_rx>=0
|
||||
&& member->next->dsp->pcm_slot_tx>=0
|
||||
&& member->next->dsp->pcm_slot_rx>=0
|
||||
&& member->next->dsp->pcm_slot_tx==member->dsp->pcm_slot_rx
|
||||
&& member->next->dsp->pcm_slot_rx==member->dsp->pcm_slot_tx
|
||||
&& member->next->dsp->pcm_slot_tx==member->dsp->pcm_slot_tx
|
||||
&& nextm->dsp->pcm_slot_tx>=0
|
||||
&& nextm->dsp->pcm_slot_rx>=0
|
||||
&& nextm->dsp->pcm_slot_tx==member->dsp->pcm_slot_rx
|
||||
&& nextm->dsp->pcm_slot_rx==member->dsp->pcm_slot_tx
|
||||
&& nextm->dsp->pcm_slot_tx==member->dsp->pcm_slot_tx
|
||||
&& member->dsp->pcm_bank_tx!=member->dsp->pcm_bank_rx
|
||||
&& member->next->dsp->pcm_bank_tx!=member->next->dsp->pcm_bank_rx) {
|
||||
&& nextm->dsp->pcm_bank_tx!=nextm->dsp->pcm_bank_rx) {
|
||||
/* all members have same slot */
|
||||
if (dsp_debug & DEBUG_DSP_CMX)
|
||||
printk(KERN_DEBUG "%s dsp %s & %s stay joined on PCM slot %d bank %d (TX) bank %d (RX) (on different chips)\n", __FUNCTION__, member->dsp->inst.name, member->next->dsp->inst.name, member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx, member->dsp->pcm_bank_rx);
|
||||
printk(KERN_DEBUG "%s dsp %s & %s stay joined on PCM slot %d bank %d (TX) bank %d (RX) (on different chips)\n", __FUNCTION__,
|
||||
member->dsp->inst.name, nextm->dsp->inst.name,
|
||||
member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx, member->dsp->pcm_bank_rx);
|
||||
conf->hardware = 0;
|
||||
conf->software = 1;
|
||||
return;
|
||||
}
|
||||
/* find a new slot */
|
||||
memset(freeslots, 1, sizeof(freeslots));
|
||||
dsp = (dsp_t *)dsp_obj.ilist;
|
||||
while(dsp) {
|
||||
list_for_each_entry(dsp, &dsp_obj.ilist, list) {
|
||||
if (dsp!=member->dsp
|
||||
&& dsp!=member->next->dsp
|
||||
&& dsp!=nextm->dsp
|
||||
&& member->dsp->features.pcm_id==dsp->features.pcm_id) {
|
||||
if (dsp->pcm_slot_rx>=0
|
||||
&& dsp->pcm_slot_rx<sizeof(freeslots))
|
||||
|
@ -606,7 +598,6 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
|||
&& dsp->pcm_slot_tx<sizeof(freeslots))
|
||||
freeslots[dsp->pcm_slot_rx] = 0;
|
||||
}
|
||||
dsp = dsp->next;
|
||||
}
|
||||
i = 0;
|
||||
ii = member->dsp->features.pcm_slots;
|
||||
|
@ -617,23 +608,27 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
|||
}
|
||||
if (i == ii) {
|
||||
if (dsp_debug & DEBUG_DSP_CMX)
|
||||
printk(KERN_DEBUG "%s no slot available for %s & %s\n", __FUNCTION__, member->dsp->inst.name, member->next->dsp->inst.name);
|
||||
printk(KERN_DEBUG "%s no slot available for %s & %s\n", __FUNCTION__,
|
||||
member->dsp->inst.name, nextm->dsp->inst.name);
|
||||
/* no more slots available */
|
||||
goto conf_software;
|
||||
}
|
||||
/* assign free slot */
|
||||
member->dsp->pcm_slot_tx = i;
|
||||
member->dsp->pcm_slot_rx = i;
|
||||
member->next->dsp->pcm_slot_tx = i;
|
||||
member->next->dsp->pcm_slot_rx = i;
|
||||
nextm->dsp->pcm_slot_tx = i;
|
||||
nextm->dsp->pcm_slot_rx = i;
|
||||
member->dsp->pcm_bank_rx = 0;
|
||||
member->dsp->pcm_bank_tx = 1;
|
||||
member->next->dsp->pcm_bank_rx = 1;
|
||||
member->next->dsp->pcm_bank_tx = 0;
|
||||
nextm->dsp->pcm_bank_rx = 1;
|
||||
nextm->dsp->pcm_bank_tx = 0;
|
||||
if (dsp_debug & DEBUG_DSP_CMX)
|
||||
printk(KERN_DEBUG "%s adding %s & %s to new PCM slot %d (TX and RX on different chips) because both members have not same slots\n", __FUNCTION__, member->dsp->inst.name, member->next->dsp->inst.name, member->dsp->pcm_slot_tx);
|
||||
dsp_cmx_hw_message(member->dsp, HW_PCM_CONN, member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx, member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx);
|
||||
dsp_cmx_hw_message(member->next->dsp, HW_PCM_CONN, member->next->dsp->pcm_slot_tx, member->next->dsp->pcm_bank_tx, member->next->dsp->pcm_slot_rx, member->next->dsp->pcm_bank_rx);
|
||||
printk(KERN_DEBUG "%s adding %s & %s to new PCM slot %d (TX and RX on different chips) because both members have not same slots\n", __FUNCTION__,
|
||||
member->dsp->inst.name, nextm->dsp->inst.name, member->dsp->pcm_slot_tx);
|
||||
dsp_cmx_hw_message(member->dsp, HW_PCM_CONN, member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx,
|
||||
member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx);
|
||||
dsp_cmx_hw_message(nextm->dsp, HW_PCM_CONN, nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx,
|
||||
nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
|
||||
conf->hardware = 1;
|
||||
conf->software = 0;
|
||||
return;
|
||||
|
@ -642,28 +637,28 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
|||
/* if both members have different crossed slots */
|
||||
if (member->dsp->pcm_slot_tx>=0
|
||||
&& member->dsp->pcm_slot_rx>=0
|
||||
&& member->next->dsp->pcm_slot_tx>=0
|
||||
&& member->next->dsp->pcm_slot_rx>=0
|
||||
&& member->next->dsp->pcm_slot_tx==member->dsp->pcm_slot_rx
|
||||
&& member->next->dsp->pcm_slot_rx==member->dsp->pcm_slot_tx
|
||||
&& nextm->dsp->pcm_slot_tx>=0
|
||||
&& nextm->dsp->pcm_slot_rx>=0
|
||||
&& nextm->dsp->pcm_slot_tx==member->dsp->pcm_slot_rx
|
||||
&& nextm->dsp->pcm_slot_rx==member->dsp->pcm_slot_tx
|
||||
&& member->dsp->pcm_slot_tx!=member->dsp->pcm_slot_rx
|
||||
&& member->dsp->pcm_bank_tx==0
|
||||
&& member->dsp->pcm_bank_rx==0
|
||||
&& member->next->dsp->pcm_bank_tx==0
|
||||
&& member->next->dsp->pcm_bank_rx==0) {
|
||||
&& nextm->dsp->pcm_bank_tx==0
|
||||
&& nextm->dsp->pcm_bank_rx==0) {
|
||||
/* all members have same slot */
|
||||
if (dsp_debug & DEBUG_DSP_CMX)
|
||||
printk(KERN_DEBUG "%s dsp %s & %s stay joined on PCM slot %d (TX) %d (RX) on same chip or one bank PCM)\n", __FUNCTION__, member->dsp->inst.name, member->next->dsp->inst.name, member->dsp->pcm_slot_tx, member->dsp->pcm_slot_rx);
|
||||
printk(KERN_DEBUG "%s dsp %s & %s stay joined on PCM slot %d (TX) %d (RX) on same chip or one bank PCM)\n", __FUNCTION__,
|
||||
member->dsp->inst.name, nextm->dsp->inst.name, member->dsp->pcm_slot_tx, member->dsp->pcm_slot_rx);
|
||||
conf->hardware = 0;
|
||||
conf->software = 1;
|
||||
return;
|
||||
}
|
||||
/* find two new slot */
|
||||
memset(freeslots, 1, sizeof(freeslots));
|
||||
dsp = (dsp_t *)dsp_obj.ilist;
|
||||
while(dsp) {
|
||||
list_for_each_entry(dsp, &dsp_obj.ilist, list) {
|
||||
if (dsp!=member->dsp
|
||||
&& dsp!=member->next->dsp
|
||||
&& dsp!=nextm->dsp
|
||||
&& member->dsp->features.pcm_id==dsp->features.pcm_id) {
|
||||
if (dsp->pcm_slot_rx>=0
|
||||
&& dsp->pcm_slot_rx<sizeof(freeslots))
|
||||
|
@ -672,7 +667,6 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
|||
&& dsp->pcm_slot_tx<sizeof(freeslots))
|
||||
freeslots[dsp->pcm_slot_rx] = 0;
|
||||
}
|
||||
dsp = dsp->next;
|
||||
}
|
||||
i1 = 0;
|
||||
ii = member->dsp->features.pcm_slots;
|
||||
|
@ -683,7 +677,8 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
|||
}
|
||||
if (i1 == ii) {
|
||||
if (dsp_debug & DEBUG_DSP_CMX)
|
||||
printk(KERN_DEBUG "%s no slot available for %s & %s\n", __FUNCTION__, member->dsp->inst.name, member->next->dsp->inst.name);
|
||||
printk(KERN_DEBUG "%s no slot available for %s & %s\n", __FUNCTION__,
|
||||
member->dsp->inst.name, nextm->dsp->inst.name);
|
||||
/* no more slots available */
|
||||
goto conf_software;
|
||||
}
|
||||
|
@ -695,23 +690,26 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
|||
}
|
||||
if (i2 == ii) {
|
||||
if (dsp_debug & DEBUG_DSP_CMX)
|
||||
printk(KERN_DEBUG "%s no slot available for %s & %s\n", __FUNCTION__, member->dsp->inst.name, member->next->dsp->inst.name);
|
||||
printk(KERN_DEBUG "%s no slot available for %s & %s\n", __FUNCTION__,
|
||||
member->dsp->inst.name, nextm->dsp->inst.name);
|
||||
/* no more slots available */
|
||||
goto conf_software;
|
||||
}
|
||||
/* assign free slots */
|
||||
member->dsp->pcm_slot_tx = i1;
|
||||
member->dsp->pcm_slot_rx = i2;
|
||||
member->next->dsp->pcm_slot_tx = i2;
|
||||
member->next->dsp->pcm_slot_rx = i1;
|
||||
nextm->dsp->pcm_slot_tx = i2;
|
||||
nextm->dsp->pcm_slot_rx = i1;
|
||||
member->dsp->pcm_bank_rx = 0;
|
||||
member->dsp->pcm_bank_tx = 0;
|
||||
member->next->dsp->pcm_bank_rx = 0;
|
||||
member->next->dsp->pcm_bank_tx = 0;
|
||||
nextm->dsp->pcm_bank_rx = 0;
|
||||
nextm->dsp->pcm_bank_tx = 0;
|
||||
if (dsp_debug & DEBUG_DSP_CMX)
|
||||
printk(KERN_DEBUG "%s adding %s & %s to new PCM slot %d (TX) %d (RX) on same chip or one bank PCM) because both members have not crossed slots\n", __FUNCTION__, member->dsp->inst.name, member->next->dsp->inst.name, member->dsp->pcm_slot_tx, member->dsp->pcm_slot_rx);
|
||||
printk(KERN_DEBUG "%s adding %s & %s to new PCM slot %d (TX) %d (RX) on same chip or one bank PCM) because both members have not crossed slots\n", __FUNCTION__,
|
||||
member->dsp->inst.name, nextm->dsp->inst.name, member->dsp->pcm_slot_tx,
|
||||
member->dsp->pcm_slot_rx);
|
||||
dsp_cmx_hw_message(member->dsp, HW_PCM_CONN, member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx, member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx);
|
||||
dsp_cmx_hw_message(member->next->dsp, HW_PCM_CONN, member->next->dsp->pcm_slot_tx, member->next->dsp->pcm_bank_tx, member->next->dsp->pcm_slot_rx, member->next->dsp->pcm_bank_rx);
|
||||
dsp_cmx_hw_message(nextm->dsp, HW_PCM_CONN, nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx, nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
|
||||
conf->hardware = 1;
|
||||
conf->software = 0;
|
||||
return;
|
||||
|
@ -725,7 +723,8 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
|||
/* if not the same HFC chip */
|
||||
if (same_hfc < 0) {
|
||||
if (dsp_debug & DEBUG_DSP_CMX)
|
||||
printk(KERN_DEBUG "%s conference %d cannot be formed, because members are on different chips or not on HFC chip\n", __FUNCTION__, conf->id);
|
||||
printk(KERN_DEBUG "%s conference %d cannot be formed, because members are on different chips or not on HFC chip\n",
|
||||
__FUNCTION__, conf->id);
|
||||
goto conf_software;
|
||||
}
|
||||
|
||||
|
@ -737,17 +736,14 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
|||
*/
|
||||
if (current_conf >= 0) {
|
||||
join_members:
|
||||
member = conf->mlist;
|
||||
while (member) {
|
||||
list_for_each_entry(member, &conf->mlist, list) {
|
||||
/* join to current conference */
|
||||
if (member->dsp->hfc_conf == current_conf) {
|
||||
member = member->next;
|
||||
continue;
|
||||
}
|
||||
/* get a free timeslot first */
|
||||
memset(freeslots, 1, sizeof(freeslots));
|
||||
dsp = (dsp_t *)dsp_obj.ilist;
|
||||
while(dsp) {
|
||||
list_for_each_entry(dsp, &dsp_obj.ilist, list) {
|
||||
/* not checking current member, because
|
||||
* slot will be overwritten.
|
||||
*/
|
||||
|
@ -762,7 +758,6 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
|||
&& dsp->pcm_slot_rx<sizeof(freeslots))
|
||||
freeslots[dsp->pcm_slot_rx] = 0;
|
||||
}
|
||||
dsp = dsp->next;
|
||||
}
|
||||
i = 0;
|
||||
ii = member->dsp->features.pcm_slots;
|
||||
|
@ -787,7 +782,6 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
|||
member->dsp->hfc_conf = current_conf;
|
||||
dsp_cmx_hw_message(member->dsp, HW_PCM_CONN, i, 2, i, 2);
|
||||
dsp_cmx_hw_message(member->dsp, HW_CONF_JOIN, current_conf, 0, 0, 0);
|
||||
member = member->next;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -795,8 +789,7 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
|||
/* no member is in a conference yet, so we find a free one
|
||||
*/
|
||||
memset(freeunits, 1, sizeof(freeunits));
|
||||
dsp = (dsp_t *)dsp_obj.ilist;
|
||||
while(dsp) {
|
||||
list_for_each_entry(dsp, &dsp_obj.ilist, list) {
|
||||
/* dsp must be on the same chip */
|
||||
if (dsp->features.hfc_id==same_hfc
|
||||
/* dsp must have joined a HW conference */
|
||||
|
@ -804,7 +797,6 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
|
|||
/* slot must be within range */
|
||||
&& dsp->hfc_conf<8)
|
||||
freeunits[dsp->hfc_conf] = 0;
|
||||
dsp = dsp->next;
|
||||
}
|
||||
i = 0;
|
||||
ii = 8;
|
||||
|
@ -855,7 +847,7 @@ dsp_cmx_conf(dsp_t *dsp, u32 conf_id)
|
|||
dsp_cmx_hardware(NULL, dsp);
|
||||
|
||||
/* conf now empty? */
|
||||
if (!conf->mlist) {
|
||||
if (list_empty(&conf->mlist)) {
|
||||
if (dsp_debug & DEBUG_DSP_CMX)
|
||||
printk(KERN_DEBUG "conference is empty, so we remove it.\n");
|
||||
err = dsp_cmx_del_conf(conf);
|
||||
|
@ -891,7 +883,7 @@ dsp_cmx_conf(dsp_t *dsp, u32 conf_id)
|
|||
dsp->conf_id = conf_id;
|
||||
|
||||
/* if we are alone, we do nothing! */
|
||||
if (!conf->mlist) {
|
||||
if (list_empty(&conf->mlist)) {
|
||||
if (dsp_debug & DEBUG_DSP_CMX)
|
||||
printk(KERN_DEBUG "we are alone in this conference, so exit.\n");
|
||||
/* update hardware */
|
||||
|
@ -954,8 +946,7 @@ dsp_cmx_receive(dsp_t *dsp, struct sk_buff *skb)
|
|||
else if (conf->largest > dsp->largest)
|
||||
dsp->largest = conf->largest;
|
||||
|
||||
member = conf->mlist;
|
||||
while(member) {
|
||||
list_for_each_entry(member, &conf->mlist, list) {
|
||||
if (member != dsp->member) {
|
||||
/* if W_rx is lower */
|
||||
if (((member->dsp->W_rx - W_min) & CMX_BUFF_MASK) >= CMX_BUFF_HALF)
|
||||
|
@ -964,7 +955,6 @@ dsp_cmx_receive(dsp_t *dsp, struct sk_buff *skb)
|
|||
if (((W_max - member->dsp->W_rx) & CMX_BUFF_MASK) >= CMX_BUFF_HALF)
|
||||
W_max = member->dsp->W_rx;
|
||||
}
|
||||
member = member->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -990,9 +980,9 @@ dsp_cmx_receive(dsp_t *dsp, struct sk_buff *skb)
|
|||
if (conf) {
|
||||
#ifdef CMX_CONF_DEBUG
|
||||
#warning CMX_CONF_DEBUG is enabled, it causes performance loss with normal 2-party crossconnects
|
||||
if (conf->mlist) if (conf->mlist->next) {
|
||||
if (2 <= count_list_member(&conf->mlist)) {
|
||||
#else
|
||||
if (conf->mlist) if (conf->mlist->next) if (conf->mlist->next->next) {
|
||||
if (3 <= count_list_member(&conf->mlist)) {
|
||||
#endif
|
||||
//printk(KERN_DEBUG "cmxing dsp:%s dsp->W_rx=%04x conf->W_max=%04x\n", dsp->inst.name, dsp->W_rx, conf->W_max);
|
||||
/* -> received data is added to conf-buffer
|
||||
|
@ -1158,19 +1148,19 @@ struct sk_buff
|
|||
dsp->R_tx = t;
|
||||
return(nskb);
|
||||
}
|
||||
if (!conf->mlist->next) {
|
||||
if (1 == count_list_member(&conf->mlist)) {
|
||||
goto single;
|
||||
}
|
||||
/* STEP 2.2: PROCESS DATA (two members) */
|
||||
#ifdef CMX_CONF_DEBUG
|
||||
if (0) {
|
||||
#else
|
||||
if (!conf->mlist->next->next) {
|
||||
if (2 == count_list_member(&conf->mlist)) {
|
||||
#endif
|
||||
/* "other" becomes other party */
|
||||
other = conf->mlist->dsp;
|
||||
other = (list_entry(conf->mlist.next, conf_member_t, list))->dsp;
|
||||
if (other == member)
|
||||
other = conf->mlist->next->dsp;
|
||||
other = (list_entry(conf->mlist.prev, conf_member_t, list))->dsp;
|
||||
o = other->rx_buff; /* received data */
|
||||
/* -> if echo is NOT enabled */
|
||||
if (!dsp->echo) {
|
||||
|
|
|
@ -677,7 +677,7 @@ release_dsp(dsp_t *dsp)
|
|||
conf = dsp->conf;
|
||||
if (conf) {
|
||||
dsp_cmx_del_conf_member(dsp);
|
||||
if (!conf->mlist) {
|
||||
if (!list_empty(&conf->mlist)) {
|
||||
dsp_cmx_del_conf(conf);
|
||||
}
|
||||
}
|
||||
|
@ -695,7 +695,7 @@ release_dsp(dsp_t *dsp)
|
|||
|
||||
if (dsp_debug & DEBUG_DSP_MGR)
|
||||
printk(KERN_DEBUG "%s: remove & destroy object %s\n", __FUNCTION__, dsp->inst.name);
|
||||
REMOVE_FROM_LISTBASE(dsp, ((dsp_t *)dsp_obj.ilist));
|
||||
list_del(&dsp->list);
|
||||
dsp_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
|
||||
unlock_HW(&dsp_lock);
|
||||
vfree(dsp);
|
||||
|
@ -757,11 +757,11 @@ new_dsp(mISDNstack_t *st, mISDN_pid_t *pid)
|
|||
INIT_WORK(&ndsp->sendwork, (void *)(void *)sendevent, ndsp);
|
||||
lock_HW(&dsp_lock, 0);
|
||||
/* append and register */
|
||||
APPEND_TO_LIST(ndsp, ((dsp_t *)dsp_obj.ilist));
|
||||
list_add_tail(&ndsp->list, &dsp_obj.ilist);
|
||||
err = dsp_obj.ctrl(st, MGR_REGLAYER | INDICATION, &ndsp->inst);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: failed to register layer %s\n", __FUNCTION__, ndsp->inst.name);
|
||||
REMOVE_FROM_LISTBASE(ndsp, ((dsp_t *)dsp_obj.ilist));
|
||||
list_del(&ndsp->list);
|
||||
unlock_HW(&dsp_lock);
|
||||
goto free_mem;
|
||||
}
|
||||
|
@ -811,17 +811,22 @@ dsp_feat(dsp_t *dsp)
|
|||
static int
|
||||
dsp_manager(void *data, u_int prim, void *arg) {
|
||||
mISDNinstance_t *inst = data;
|
||||
dsp_t *dspl = (dsp_t *)dsp_obj.ilist;
|
||||
int ret = 0;
|
||||
dsp_t *dspl;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (dsp_debug & DEBUG_DSP_MGR)
|
||||
printk(KERN_DEBUG "%s: data:%p prim:%x arg:%p\n", __FUNCTION__, data, prim, arg);
|
||||
if (!data)
|
||||
return(-EINVAL);
|
||||
while(dspl) {
|
||||
if (&dspl->inst == inst)
|
||||
return(ret);
|
||||
list_for_each_entry(dspl, &dsp_obj.ilist, list) {
|
||||
if (&dspl->inst == inst) {
|
||||
ret = 0;
|
||||
break;
|
||||
dspl = dspl->next;
|
||||
}
|
||||
}
|
||||
if (ret && (prim != (MGR_NEWLAYER | REQUEST))) {
|
||||
printk(KERN_WARNING "%s: given instance(%p) not in ilist.\n", __FUNCTION__, data);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
switch(prim) {
|
||||
|
@ -829,39 +834,19 @@ dsp_manager(void *data, u_int prim, void *arg) {
|
|||
ret = new_dsp(data, arg);
|
||||
break;
|
||||
case MGR_CONNECT | REQUEST:
|
||||
if (!dspl) {
|
||||
printk(KERN_WARNING "%s: given instance(%p) not in ilist.\n", __FUNCTION__, data);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ret = mISDN_ConnectIF(inst, arg);
|
||||
dsp_feat(dspl);
|
||||
break;
|
||||
case MGR_SETIF | REQUEST:
|
||||
case MGR_SETIF | INDICATION:
|
||||
if (!dspl) {
|
||||
printk(KERN_WARNING "%s: given instance(%p) not in ilist.\n", __FUNCTION__, data);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ret = mISDN_SetIF(inst, arg, prim, dsp_from_up, dsp_from_down, dspl);
|
||||
break;
|
||||
case MGR_DISCONNECT | REQUEST:
|
||||
case MGR_DISCONNECT | INDICATION:
|
||||
if (!dspl) {
|
||||
printk(KERN_WARNING "%s: given instance(%p) not in ilist.\n", __FUNCTION__, data);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ret = mISDN_DisConnectIF(inst, arg);
|
||||
break;
|
||||
case MGR_UNREGLAYER | REQUEST:
|
||||
case MGR_RELEASE | INDICATION:
|
||||
if (!dspl) {
|
||||
printk(KERN_WARNING "%s: given instance(%p) not in ilist.\n", __FUNCTION__, data);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if (dsp_debug & DEBUG_DSP_MGR)
|
||||
printk(KERN_DEBUG "%s: release_dsp id %x\n", __FUNCTION__, dspl->inst.st->id);
|
||||
|
||||
|
@ -922,9 +907,7 @@ static int dsp_init(void)
|
|||
dsp_obj.name = DSPName;
|
||||
dsp_obj.BPROTO.protocol[3] = ISDN_PID_L3_B_DSP;
|
||||
dsp_obj.own_ctrl = dsp_manager;
|
||||
dsp_obj.prev = NULL;
|
||||
dsp_obj.next = NULL;
|
||||
dsp_obj.ilist = NULL;
|
||||
INIT_LIST_HEAD(&dsp_obj.ilist);
|
||||
|
||||
/* initialize audio tables */
|
||||
silence = (dsp_options&DSP_OPT_ULAW)?0xff:0x2a;
|
||||
|
@ -954,7 +937,8 @@ static int dsp_init(void)
|
|||
*/
|
||||
static void dsp_cleanup(void)
|
||||
{
|
||||
int err;
|
||||
dsp_t *dspl, *nd;
|
||||
int err;
|
||||
|
||||
if (dsp_debug & DEBUG_DSP_MGR)
|
||||
printk(KERN_DEBUG "%s: removing module\n", __FUNCTION__);
|
||||
|
@ -963,12 +947,12 @@ static void dsp_cleanup(void)
|
|||
printk(KERN_ERR "mISDN_dsp: Can't unregister Audio DSP error(%d)\n",
|
||||
err);
|
||||
}
|
||||
if(dsp_obj.ilist) {
|
||||
if (!list_empty(&dsp_obj.ilist)) {
|
||||
printk(KERN_WARNING "mISDN_dsp: Audio DSP object inst list not empty.\n");
|
||||
while(dsp_obj.ilist)
|
||||
release_dsp(dsp_obj.ilist);
|
||||
list_for_each_entry_safe(dspl, nd, &dsp_obj.ilist, list)
|
||||
release_dsp(dspl);
|
||||
}
|
||||
if (Conf_list) {
|
||||
if (!list_empty(&Conf_list)) {
|
||||
printk(KERN_ERR "mISDN_dsp: Conference list not empty. Not all memory freed.\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,14 +24,13 @@
|
|||
#define DTMF_NPOINTS 205 /* Number of samples for DTMF recognition */
|
||||
|
||||
typedef struct _dtmf {
|
||||
struct _dtmf *prev;
|
||||
struct _dtmf *next;
|
||||
u_long Flags;
|
||||
int debug;
|
||||
char last;
|
||||
int idx;
|
||||
int buf[DTMF_NPOINTS];
|
||||
mISDNinstance_t inst;
|
||||
struct list_head list;
|
||||
u_long Flags;
|
||||
int debug;
|
||||
char last;
|
||||
int idx;
|
||||
int buf[DTMF_NPOINTS];
|
||||
mISDNinstance_t inst;
|
||||
} dtmf_t;
|
||||
|
||||
#define FLG_DTMF_ULAW 1
|
||||
|
@ -490,7 +489,7 @@ release_dtmf(dtmf_t *dtmf) {
|
|||
inst->down.peer->obj->ctrl(inst->down.peer,
|
||||
MGR_DISCONNECT | REQUEST, &inst->down);
|
||||
}
|
||||
REMOVE_FROM_LISTBASE(dtmf, ((dtmf_t *)dtmf_obj.ilist));
|
||||
list_del(&dtmf->list);
|
||||
dtmf_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
|
||||
kfree(dtmf);
|
||||
}
|
||||
|
@ -515,10 +514,10 @@ new_dtmf(mISDNstack_t *st, mISDN_pid_t *pid) {
|
|||
return(-ENOPROTOOPT);
|
||||
}
|
||||
n_dtmf->debug = debug;
|
||||
APPEND_TO_LIST(n_dtmf, ((dtmf_t *)dtmf_obj.ilist));
|
||||
list_add_tail(&n_dtmf->list, &dtmf_obj.ilist);
|
||||
err = dtmf_obj.ctrl(st, MGR_REGLAYER | INDICATION, &n_dtmf->inst);
|
||||
if (err) {
|
||||
REMOVE_FROM_LISTBASE(n_dtmf, ((dtmf_t *)dtmf_obj.ilist));
|
||||
list_del(&n_dtmf->list);
|
||||
kfree(n_dtmf);
|
||||
}
|
||||
return(err);
|
||||
|
@ -559,23 +558,25 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
static int
|
||||
dtmf_manager(void *data, u_int prim, void *arg) {
|
||||
mISDNinstance_t *inst = data;
|
||||
dtmf_t *dtmf_l = dtmf_obj.ilist;
|
||||
mISDNinstance_t *inst = data;
|
||||
dtmf_t *dtmf_l;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (debug & DEBUG_DTMF_MGR)
|
||||
printk(KERN_DEBUG "dtmf_manager data:%p prim:%x arg:%p\n", data, prim, arg);
|
||||
if (!data)
|
||||
return(-EINVAL);
|
||||
while(dtmf_l) {
|
||||
if (&dtmf_l->inst == inst)
|
||||
return(ret);
|
||||
list_for_each_entry(dtmf_l, &dtmf_obj.ilist, list) {
|
||||
if (&dtmf_l->inst == inst) {
|
||||
ret = 0;
|
||||
break;
|
||||
dtmf_l = dtmf_l->next;
|
||||
}
|
||||
}
|
||||
if (prim == (MGR_NEWLAYER | REQUEST))
|
||||
return(new_dtmf(data, arg));
|
||||
if (!dtmf_l) {
|
||||
if (ret) {
|
||||
printk(KERN_WARNING "dtmf_manager prim(%x) no instance\n", prim);
|
||||
return(-EINVAL);
|
||||
return(ret);
|
||||
}
|
||||
switch(prim) {
|
||||
case MGR_CLRSTPARA | INDICATION:
|
||||
|
@ -616,9 +617,7 @@ static int dtmf_init(void)
|
|||
dtmf_obj.name = MName;
|
||||
dtmf_obj.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANSDTMF;
|
||||
dtmf_obj.own_ctrl = dtmf_manager;
|
||||
dtmf_obj.prev = NULL;
|
||||
dtmf_obj.next = NULL;
|
||||
dtmf_obj.ilist = NULL;
|
||||
INIT_LIST_HEAD(&dtmf_obj.ilist);
|
||||
if ((err = mISDN_register(&dtmf_obj))) {
|
||||
printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
|
||||
}
|
||||
|
@ -627,15 +626,16 @@ static int dtmf_init(void)
|
|||
|
||||
static void dtmf_cleanup(void)
|
||||
{
|
||||
int err;
|
||||
int err;
|
||||
dtmf_t *dtmf, *nd;
|
||||
|
||||
if ((err = mISDN_unregister(&dtmf_obj))) {
|
||||
printk(KERN_ERR "Can't unregister DTMF error(%d)\n", err);
|
||||
}
|
||||
if(dtmf_obj.ilist) {
|
||||
if (!list_empty(&dtmf_obj.ilist)) {
|
||||
printk(KERN_WARNING "dtmf inst list not empty\n");
|
||||
while(dtmf_obj.ilist)
|
||||
release_dtmf(dtmf_obj.ilist);
|
||||
list_for_each_entry_safe(dtmf, nd, &dtmf_obj.ilist, list)
|
||||
release_dtmf(dtmf);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,7 @@
|
|||
static int ttt=180;
|
||||
|
||||
typedef struct _faxl3 {
|
||||
struct _faxl3 *prev;
|
||||
struct _faxl3 *next;
|
||||
struct list_head list;
|
||||
spinlock_t lock;
|
||||
u_long state;
|
||||
int debug;
|
||||
|
@ -1953,7 +1952,7 @@ release_faxl3(faxl3_t *faxl3) {
|
|||
inst->down.peer->obj->ctrl(inst->down.peer,
|
||||
MGR_DISCONNECT | REQUEST, &inst->down);
|
||||
}
|
||||
REMOVE_FROM_LISTBASE(faxl3, ((faxl3_t *)faxl3_obj.ilist));
|
||||
list_del(&faxl3->list);
|
||||
discard_queue(&faxl3->downq);
|
||||
discard_queue(&faxl3->dataq);
|
||||
discard_queue(&faxl3->pageq);
|
||||
|
@ -2048,7 +2047,7 @@ new_faxl3(mISDNstack_t *st, mISDN_pid_t *pid) {
|
|||
skb_queue_head_init(&n_faxl3->pageq);
|
||||
skb_queue_head_init(&n_faxl3->saveq);
|
||||
|
||||
APPEND_TO_LIST(n_faxl3, ((faxl3_t *)faxl3_obj.ilist));
|
||||
list_add_tail(&n_faxl3->list, &faxl3_obj.ilist);
|
||||
n_faxl3->entity = MISDN_ENTITY_NONE;
|
||||
err = faxl3_obj.ctrl(&n_faxl3->inst, MGR_NEWENTITY | REQUEST, NULL);
|
||||
if (err) {
|
||||
|
@ -2057,7 +2056,7 @@ new_faxl3(mISDNstack_t *st, mISDN_pid_t *pid) {
|
|||
}
|
||||
err = faxl3_obj.ctrl(st, MGR_REGLAYER | INDICATION, &n_faxl3->inst);
|
||||
if (err) {
|
||||
REMOVE_FROM_LISTBASE(n_faxl3, ((faxl3_t *)faxl3_obj.ilist));
|
||||
list_del(&n_faxl3->list);
|
||||
kfree(n_faxl3);
|
||||
} else {
|
||||
if (st->para.maxdatalen)
|
||||
|
@ -2075,23 +2074,25 @@ new_faxl3(mISDNstack_t *st, mISDN_pid_t *pid) {
|
|||
|
||||
static int
|
||||
faxl3_manager(void *data, u_int prim, void *arg) {
|
||||
mISDNinstance_t *inst = data;
|
||||
faxl3_t *faxl3_l = faxl3_obj.ilist;
|
||||
mISDNinstance_t *inst = data;
|
||||
faxl3_t *faxl3_l;
|
||||
int err = -EINVAL;
|
||||
|
||||
if (debug & DEBUG_FAXL3_MGR)
|
||||
printk(KERN_DEBUG "faxl3_manager data:%p prim:%x arg:%p\n", data, prim, arg);
|
||||
if (!data)
|
||||
return(-EINVAL);
|
||||
while(faxl3_l) {
|
||||
if (&faxl3_l->inst == inst)
|
||||
return(err);
|
||||
list_for_each_entry(faxl3_l, &faxl3_obj.ilist, list) {
|
||||
if (&faxl3_l->inst == inst) {
|
||||
err = 0;
|
||||
break;
|
||||
faxl3_l = faxl3_l->next;
|
||||
}
|
||||
}
|
||||
if (prim == (MGR_NEWLAYER | REQUEST))
|
||||
return(new_faxl3(data, arg));
|
||||
if (!faxl3_l) {
|
||||
if (err) {
|
||||
printk(KERN_WARNING "faxl3_manager prim(%x) no instance\n", prim);
|
||||
return(-EINVAL);
|
||||
return(err);
|
||||
}
|
||||
switch(prim) {
|
||||
case MGR_CLRSTPARA | INDICATION:
|
||||
|
@ -2145,9 +2146,7 @@ static int faxl3_init(void)
|
|||
faxl3_obj.name = MName;
|
||||
faxl3_obj.BPROTO.protocol[3] = ISDN_PID_L3_B_T30;
|
||||
faxl3_obj.own_ctrl = faxl3_manager;
|
||||
faxl3_obj.prev = NULL;
|
||||
faxl3_obj.next = NULL;
|
||||
faxl3_obj.ilist = NULL;
|
||||
INIT_LIST_HEAD(&faxl3_obj.ilist);
|
||||
if ((err = mISDN_register(&faxl3_obj))) {
|
||||
printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
|
||||
return(err);
|
||||
|
@ -2167,15 +2166,16 @@ static int faxl3_init(void)
|
|||
|
||||
static void faxl3_cleanup(void)
|
||||
{
|
||||
int err;
|
||||
faxl3_t *l3, *nl3;
|
||||
int err;
|
||||
|
||||
if ((err = mISDN_unregister(&faxl3_obj))) {
|
||||
printk(KERN_ERR "Can't unregister DTMF error(%d)\n", err);
|
||||
}
|
||||
if(faxl3_obj.ilist) {
|
||||
if(!list_empty(&faxl3_obj.ilist)) {
|
||||
printk(KERN_WARNING "faxl3 inst list not empty\n");
|
||||
while(faxl3_obj.ilist)
|
||||
release_faxl3(faxl3_obj.ilist);
|
||||
list_for_each_entry_safe(l3, nl3, &faxl3_obj.ilist, list)
|
||||
release_faxl3(l3);
|
||||
}
|
||||
mISDN_FsmFree(&faxl3fsm);
|
||||
mISDN_FsmFree(&modfsm);
|
||||
|
|
|
@ -321,9 +321,10 @@ mISDN_ConnectIF(mISDNinstance_t *owner, mISDNinstance_t *peer)
|
|||
int
|
||||
mISDN_DisConnectIF(mISDNinstance_t *inst, mISDNif_t *hif) {
|
||||
if (hif) {
|
||||
if (hif->next && hif->next->owner) {
|
||||
hif->next->owner->obj->ctrl(hif->next->owner,
|
||||
MGR_DISCONNECT | REQUEST, hif->next);
|
||||
if (hif->clone) {
|
||||
if (hif->clone->owner)
|
||||
hif->clone->owner->obj->ctrl(hif->clone->owner,
|
||||
MGR_DISCONNECT | REQUEST, hif->clone);
|
||||
}
|
||||
if (inst->up.peer) {
|
||||
if (inst->up.peer == hif->owner)
|
||||
|
@ -354,6 +355,10 @@ mISDN_init_instance(mISDNinstance_t *inst, mISDNobject_t *obj, void *data)
|
|||
inst->data = data;
|
||||
inst->up.owner = inst;
|
||||
inst->down.owner = inst;
|
||||
inst->up.clone = NULL;
|
||||
inst->up.predecessor = NULL;
|
||||
inst->down.clone = NULL;
|
||||
inst->down.predecessor = NULL;
|
||||
obj->ctrl(NULL, MGR_DISCONNECT | REQUEST, &inst->down);
|
||||
obj->ctrl(NULL, MGR_DISCONNECT | REQUEST, &inst->up);
|
||||
}
|
||||
|
|
|
@ -20,42 +20,6 @@
|
|||
printk(KERN_ERR "mISDN: INTERNAL ERROR in %s:%d " fmt "\n", \
|
||||
__FILE__, __LINE__, ## arg)
|
||||
|
||||
#define APPEND_TO_LIST(item,base) \
|
||||
if (item->prev || item->next) \
|
||||
int_errtxt("APPEND not clean %p<-%p->%p", \
|
||||
item->prev, item, item->next); \
|
||||
item->next = NULL; \
|
||||
item->prev = base; \
|
||||
while (item->prev && item->prev->next) \
|
||||
item->prev = item->prev->next; \
|
||||
if (item->prev == item) { \
|
||||
int_errtxt("APPEND DUP %p", item); \
|
||||
} else \
|
||||
if (base) { \
|
||||
item->prev->next = item; \
|
||||
} else \
|
||||
base = item
|
||||
|
||||
#define INSERT_INTO_LIST(newi,nexti,base) \
|
||||
newi->next = nexti; \
|
||||
newi->prev = nexti->prev; \
|
||||
if (newi->prev) \
|
||||
newi->prev->next = newi; \
|
||||
nexti->prev = newi; \
|
||||
if (base == nexti) \
|
||||
base = newi
|
||||
|
||||
#define REMOVE_FROM_LIST(item) \
|
||||
if (item->prev) \
|
||||
item->prev->next = item->next; \
|
||||
if (item->next) \
|
||||
item->next->prev = item->prev
|
||||
|
||||
#define REMOVE_FROM_LISTBASE(item,base) \
|
||||
REMOVE_FROM_LIST(item); \
|
||||
if (item == base) \
|
||||
base = item->next
|
||||
|
||||
static inline int
|
||||
discard_queue(struct sk_buff_head *q)
|
||||
{
|
||||
|
@ -103,6 +67,17 @@ extern int mISDN_SetHandledPID(mISDNobject_t *, mISDN_pid_t *);
|
|||
extern void mISDN_RemoveUsedPID(mISDN_pid_t *, mISDN_pid_t *);
|
||||
extern void mISDN_init_instance(mISDNinstance_t *, mISDNobject_t *, void *);
|
||||
|
||||
static inline int
|
||||
count_list_member(struct list_head *head)
|
||||
{
|
||||
int cnt = 0;
|
||||
struct list_head *m;
|
||||
|
||||
list_for_each(m, head)
|
||||
cnt++;
|
||||
return(cnt);
|
||||
}
|
||||
|
||||
static inline int
|
||||
mISDN_HasProtocolP(mISDNobject_t *obj, int *PP)
|
||||
{
|
||||
|
|
|
@ -2191,7 +2191,7 @@ hfcmulti_dch_bh(dchannel_t *dch)
|
|||
if (hc->created[hc->chan[ch].port]) {
|
||||
while(upif) {
|
||||
if_link(upif, prim, para, 0, NULL, 0);
|
||||
upif = upif->next;
|
||||
upif = upif->clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2479,11 +2479,12 @@ init_card(hfc_multi_t *hc)
|
|||
static int
|
||||
SelFreeBChannel(hfc_multi_t *hc, int ch, channel_info_t *ci)
|
||||
{
|
||||
bchannel_t *bch;
|
||||
hfc_multi_t *hfc;
|
||||
mISDNstack_t *bst;
|
||||
int cnr;
|
||||
int port = hc->chan[ch].port;
|
||||
bchannel_t *bch;
|
||||
hfc_multi_t *hfc;
|
||||
mISDNstack_t *bst;
|
||||
struct list_head *head;
|
||||
int cnr;
|
||||
int port = hc->chan[ch].port;
|
||||
|
||||
if (port < 0 || port>=hc->type) {
|
||||
printk(KERN_WARNING "%s: port(%d) out of range", __FUNCTION__, port);
|
||||
|
@ -2493,9 +2494,20 @@ SelFreeBChannel(hfc_multi_t *hc, int ch, channel_info_t *ci)
|
|||
if (!ci)
|
||||
return(-EINVAL);
|
||||
ci->st.p = NULL;
|
||||
bst = hc->chan[ch].dch->inst.st->child;
|
||||
cnr=0;
|
||||
while(bst) {
|
||||
bst = hc->chan[ch].dch->inst.st;
|
||||
if (list_empty(&bst->childlist)) {
|
||||
if ((bst->id & FLG_CLONE_STACK) &&
|
||||
(bst->childlist.prev != &bst->childlist)) {
|
||||
head = bst->childlist.prev;
|
||||
} else {
|
||||
printk(KERN_ERR "%s: invalid empty childlist (no clone) stid(%x) childlist(%p<-%p->%p)\n",
|
||||
__FUNCTION__, bst->id, bst->childlist.prev, &bst->childlist, bst->childlist.next);
|
||||
return(-EINVAL);
|
||||
}
|
||||
} else
|
||||
head = &bst->childlist;
|
||||
list_for_each_entry(bst, head, list) {
|
||||
if (cnr == ((hc->type==1)?30:2)) /* 30 or 2 B-channels */ {
|
||||
printk(KERN_WARNING "%s: fatal error: more b-stacks than ports", __FUNCTION__);
|
||||
return(-EINVAL);
|
||||
|
@ -2529,7 +2541,6 @@ SelFreeBChannel(hfc_multi_t *hc, int ch, channel_info_t *ci)
|
|||
}
|
||||
}
|
||||
cnr++;
|
||||
bst = bst->next;
|
||||
}
|
||||
return(-EBUSY);
|
||||
}
|
||||
|
@ -2783,7 +2794,7 @@ release_port(hfc_multi_t *hc, int port)
|
|||
|
||||
if (debug & DEBUG_HFCMULTI_INIT)
|
||||
printk(KERN_DEBUG "%s: removing object from listbase\n", __FUNCTION__);
|
||||
REMOVE_FROM_LISTBASE(hc, ((hfc_multi_t *)HFCM_obj.ilist));
|
||||
list_del(&hc->list);
|
||||
kfree(hc);
|
||||
}
|
||||
|
||||
|
@ -2793,7 +2804,7 @@ release_port(hfc_multi_t *hc, int port)
|
|||
static int
|
||||
HFC_manager(void *data, u_int prim, void *arg)
|
||||
{
|
||||
hfc_multi_t *hc = HFCM_obj.ilist;
|
||||
hfc_multi_t *hc;
|
||||
mISDNinstance_t *inst = data;
|
||||
struct sk_buff *skb;
|
||||
dchannel_t *dch = NULL;
|
||||
|
@ -2808,7 +2819,7 @@ HFC_manager(void *data, u_int prim, void *arg)
|
|||
}
|
||||
|
||||
/* find channel and card */
|
||||
while(hc) {
|
||||
list_for_each_entry(hc, &HFCM_obj.ilist, list) {
|
||||
i = 0;
|
||||
while(i < 32) {
|
||||
//printk(KERN_DEBUG "comparing (D-channel) card=%08x inst=%08x with inst=%08x\n", hc, &hc->dch[i].inst, inst);
|
||||
|
@ -2828,8 +2839,6 @@ HFC_manager(void *data, u_int prim, void *arg)
|
|||
}
|
||||
if (ch >= 0)
|
||||
break;
|
||||
|
||||
hc = hc->next;
|
||||
}
|
||||
if (ch < 0) {
|
||||
printk(KERN_ERR "%s: no card/channel found data %p prim %x arg %p\n", __FUNCTION__, data, prim, arg);
|
||||
|
@ -2955,7 +2964,7 @@ static int __init
|
|||
HFCmulti_init(void)
|
||||
{
|
||||
int err, err2, i;
|
||||
hfc_multi_t *hc;
|
||||
hfc_multi_t *hc,*next;
|
||||
mISDN_pid_t pid, pids[MAX_CARDS];
|
||||
mISDNstack_t *dst = NULL; /* make gcc happy */
|
||||
int port_cnt;
|
||||
|
@ -3004,6 +3013,7 @@ HFCmulti_init(void)
|
|||
#ifdef MODULE
|
||||
HFCM_obj.owner = THIS_MODULE;
|
||||
#endif
|
||||
INIT_LIST_HEAD(&HFCM_obj.ilist);
|
||||
HFCM_obj.name = HFCName;
|
||||
HFCM_obj.own_ctrl = HFC_manager;
|
||||
HFCM_obj.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0 | ISDN_PID_L0_NT_S0
|
||||
|
@ -3087,7 +3097,7 @@ HFCmulti_init(void)
|
|||
|
||||
if (debug & DEBUG_HFCMULTI_INIT)
|
||||
printk(KERN_DEBUG "%s: (after APPEND_TO_LIST)\n", __FUNCTION__);
|
||||
APPEND_TO_LIST(hc, ((hfc_multi_t *)HFCM_obj.ilist));
|
||||
list_add_tail(&hc->list, &HFCM_obj.ilist);
|
||||
if (debug & DEBUG_HFCMULTI_INIT)
|
||||
printk(KERN_DEBUG "%s: (after APPEND_TO_LIST)\n", __FUNCTION__);
|
||||
|
||||
|
@ -3415,7 +3425,7 @@ HFCmulti_init(void)
|
|||
}
|
||||
if (debug & DEBUG_HFCMULTI_INIT)
|
||||
printk(KERN_DEBUG "%s: before REMOVE_FROM_LIST (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
|
||||
REMOVE_FROM_LISTBASE(hc, ((hfc_multi_t *)HFCM_obj.ilist));
|
||||
list_del(&hc->list);
|
||||
if (debug & DEBUG_HFCMULTI_INIT)
|
||||
printk(KERN_DEBUG "%s: after REMOVE_FROM_LIST (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
|
||||
kfree(hc);
|
||||
|
@ -3426,9 +3436,9 @@ HFCmulti_init(void)
|
|||
if ((err2 = mISDN_unregister(&HFCM_obj))) {
|
||||
printk(KERN_ERR "Can't unregister HFC-Multi cards error(%d)\n", err);
|
||||
}
|
||||
while(HFCM_obj.ilist) {
|
||||
list_for_each_entry_safe(hc, next, &HFCM_obj.ilist, list) {
|
||||
printk(KERN_ERR "HFC PCI card struct not empty refs %d\n", HFCM_obj.refcnt);
|
||||
release_port(HFCM_obj.ilist, -1); /* all ports */
|
||||
release_port(hc, -1); /* all ports */
|
||||
}
|
||||
if (debug & DEBUG_HFCMULTI_INIT)
|
||||
printk(KERN_DEBUG "%s: after mISDN_unregister (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
|
||||
|
@ -3443,6 +3453,7 @@ HFCmulti_init(void)
|
|||
static void __exit
|
||||
HFCmulti_cleanup(void)
|
||||
{
|
||||
hfc_multi_t *hc,*next;
|
||||
int err;
|
||||
|
||||
if (debug & DEBUG_HFCMULTI_INIT)
|
||||
|
@ -3452,9 +3463,10 @@ HFCmulti_cleanup(void)
|
|||
}
|
||||
if (debug & DEBUG_HFCMULTI_INIT)
|
||||
printk(KERN_DEBUG "%s: now checking ilist (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
|
||||
while(HFCM_obj.ilist) {
|
||||
|
||||
list_for_each_entry_safe(hc, next, &HFCM_obj.ilist, list) {
|
||||
printk(KERN_ERR "HFC PCI card struct not empty refs %d\n", HFCM_obj.refcnt);
|
||||
release_port(HFCM_obj.ilist, -1); /* all ports */
|
||||
release_port(hc, -1); /* all ports */
|
||||
}
|
||||
if (debug & DEBUG_HFCMULTI_INIT)
|
||||
printk(KERN_DEBUG "%s: done (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
|
||||
|
|
|
@ -86,9 +86,7 @@ typedef struct hfcmulti_hw hfcmulti_hw_t;
|
|||
#define HFC_CHIP_CLOCK2 6 /* double clock mode */
|
||||
|
||||
struct hfc_multi {
|
||||
struct hfc_multi *prev;
|
||||
struct hfc_multi *next;
|
||||
|
||||
struct list_head list;
|
||||
char name[32];
|
||||
int id; /* chip number starting with 1 */
|
||||
int pcm; /* id of pcm bus */
|
||||
|
|
|
@ -158,17 +158,16 @@ typedef struct hfcPCI_hw hfcPCI_hw_t;
|
|||
#define HFC_CFG_SW_DD_DU 7
|
||||
|
||||
typedef struct _hfc_pci {
|
||||
struct _hfc_pci *prev;
|
||||
struct _hfc_pci *next;
|
||||
u_char subtyp;
|
||||
u_char chanlimit;
|
||||
u_long cfg;
|
||||
u_int irq;
|
||||
u_int irqcnt;
|
||||
hfcPCI_hw_t hw;
|
||||
mISDN_HWlock_t lock;
|
||||
dchannel_t dch;
|
||||
bchannel_t bch[2];
|
||||
struct list_head list;
|
||||
u_char subtyp;
|
||||
u_char chanlimit;
|
||||
u_long cfg;
|
||||
u_int irq;
|
||||
u_int irqcnt;
|
||||
hfcPCI_hw_t hw;
|
||||
mISDN_HWlock_t lock;
|
||||
dchannel_t dch;
|
||||
bchannel_t bch[2];
|
||||
} hfc_pci_t;
|
||||
|
||||
|
||||
|
@ -1915,7 +1914,7 @@ HW_hfcD_bh(dchannel_t *dch)
|
|||
}
|
||||
while(upif) {
|
||||
if_link(upif, prim, para, 0, NULL, 0);
|
||||
upif = upif->next;
|
||||
upif = upif->clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2034,17 +2033,29 @@ static int init_card(hfc_pci_t *hc)
|
|||
static int
|
||||
SelFreeBChannel(hfc_pci_t *hc, channel_info_t *ci)
|
||||
{
|
||||
bchannel_t *bch;
|
||||
hfc_pci_t *hfc;
|
||||
mISDNstack_t *bst;
|
||||
u_int cnr;
|
||||
bchannel_t *bch;
|
||||
hfc_pci_t *hfc;
|
||||
mISDNstack_t *bst;
|
||||
u_int cnr;
|
||||
struct list_head *head;
|
||||
|
||||
if (!ci)
|
||||
return(-EINVAL);
|
||||
ci->st.p = NULL;
|
||||
bst = hc->dch.inst.st->child;
|
||||
cnr=0;
|
||||
while(bst) {
|
||||
bst = hc->dch.inst.st;
|
||||
if (list_empty(&bst->childlist)) {
|
||||
if ((bst->id & FLG_CLONE_STACK) &&
|
||||
(bst->childlist.prev != &bst->childlist)) {
|
||||
head = bst->childlist.prev;
|
||||
} else {
|
||||
printk(KERN_ERR "%s: invalid empty childlist (no clone) stid(%x) childlist(%p<-%p->%p)\n",
|
||||
__FUNCTION__, bst->id, bst->childlist.prev, &bst->childlist, bst->childlist.next);
|
||||
return(-EINVAL);
|
||||
}
|
||||
} else
|
||||
head = &bst->childlist;
|
||||
list_for_each_entry(bst, head, list) {
|
||||
if(!bst->mgr) {
|
||||
int_errtxt("no mgr st(%p)", bst);
|
||||
return(-EINVAL);
|
||||
|
@ -2076,7 +2087,6 @@ SelFreeBChannel(hfc_pci_t *hc, channel_info_t *ci)
|
|||
}
|
||||
}
|
||||
cnr++;
|
||||
bst = bst->next;
|
||||
}
|
||||
return(-EBUSY);
|
||||
}
|
||||
|
@ -2178,12 +2188,12 @@ setup_hfcpci(hfc_pci_t *hc)
|
|||
/* Allocate memory for FIFOS */
|
||||
/* Because the HFC-PCI needs a 32K physical alignment, we */
|
||||
/* need to allocate the double mem and align the address */
|
||||
if (!((void *) hc->hw.share_start = kmalloc(65536, GFP_KERNEL))) {
|
||||
if (!(hc->hw.share_start = kmalloc(65536, GFP_KERNEL))) {
|
||||
printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
|
||||
return 1;
|
||||
}
|
||||
(ulong) hc->hw.fifos =
|
||||
(((ulong) hc->hw.share_start) & ~0x7FFF) + 0x8000;
|
||||
hc->hw.fifos = (void *)
|
||||
((((ulong) hc->hw.share_start) & ~0x7FFF) + 0x8000);
|
||||
pci_write_config_dword(hc->hw.dev, 0x80, (u_int) virt_to_bus(hc->hw.fifos));
|
||||
hc->hw.pci_io = ioremap((ulong) hc->hw.pci_io, 256);
|
||||
printk(KERN_INFO
|
||||
|
@ -2234,14 +2244,14 @@ release_card(hfc_pci_t *hc) {
|
|||
mISDN_free_dch(&hc->dch);
|
||||
HFC_obj.ctrl(hc->dch.inst.up.peer, MGR_DISCONNECT | REQUEST, &hc->dch.inst.up);
|
||||
HFC_obj.ctrl(&hc->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
|
||||
REMOVE_FROM_LISTBASE(hc, ((hfc_pci_t *)HFC_obj.ilist));
|
||||
list_del(&hc->list);
|
||||
unlock_dev(hc);
|
||||
kfree(hc);
|
||||
}
|
||||
|
||||
static int
|
||||
HFC_manager(void *data, u_int prim, void *arg) {
|
||||
hfc_pci_t *card = HFC_obj.ilist;
|
||||
hfc_pci_t *card;
|
||||
mISDNinstance_t *inst = data;
|
||||
struct sk_buff *skb;
|
||||
int channel = -1;
|
||||
|
@ -2252,7 +2262,7 @@ HFC_manager(void *data, u_int prim, void *arg) {
|
|||
__FUNCTION__, prim, arg);
|
||||
return(-EINVAL);
|
||||
}
|
||||
while(card) {
|
||||
list_for_each_entry(card, &HFC_obj.ilist, list) {
|
||||
if (&card->dch.inst == inst) {
|
||||
channel = 2;
|
||||
break;
|
||||
|
@ -2266,7 +2276,6 @@ HFC_manager(void *data, u_int prim, void *arg) {
|
|||
channel = 1;
|
||||
break;
|
||||
}
|
||||
card = card->next;
|
||||
}
|
||||
if (channel<0) {
|
||||
printk(KERN_ERR "%s: no channel data %p prim %x arg %p\n",
|
||||
|
@ -2371,6 +2380,7 @@ static int __init HFC_init(void)
|
|||
#ifdef MODULE
|
||||
HFC_obj.owner = THIS_MODULE;
|
||||
#endif
|
||||
INIT_LIST_HEAD(&HFC_obj.ilist);
|
||||
HFC_obj.name = HFCName;
|
||||
HFC_obj.own_ctrl = HFC_manager;
|
||||
HFC_obj.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0 |
|
||||
|
@ -2380,8 +2390,6 @@ static int __init HFC_init(void)
|
|||
ISDN_PID_L1_B_64HDLC;
|
||||
HFC_obj.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANS |
|
||||
ISDN_PID_L2_B_RAWDEV;
|
||||
HFC_obj.prev = NULL;
|
||||
HFC_obj.next = NULL;
|
||||
if ((err = mISDN_register(&HFC_obj))) {
|
||||
printk(KERN_ERR "Can't register HFC PCI error(%d)\n", err);
|
||||
return(err);
|
||||
|
@ -2393,7 +2401,7 @@ static int __init HFC_init(void)
|
|||
return(-ENOMEM);
|
||||
}
|
||||
memset(card, 0, sizeof(hfc_pci_t));
|
||||
APPEND_TO_LIST(card, ((hfc_pci_t *)HFC_obj.ilist));
|
||||
list_add_tail(&card->list, &HFC_obj.ilist);
|
||||
card->dch.debug = debug;
|
||||
lock_HW_init(&card->lock);
|
||||
card->dch.inst.lock = lock_dev;
|
||||
|
@ -2420,7 +2428,10 @@ static int __init HFC_init(void)
|
|||
}
|
||||
}
|
||||
if (protocol[HFC_cnt] == 0x100) {
|
||||
prev = card->prev;
|
||||
if (card->list.prev == &HFC_obj.ilist)
|
||||
prev = NULL;
|
||||
else
|
||||
prev = list_entry(card->list.prev, hfc_pci_t, list);
|
||||
|
||||
if (!prev) {
|
||||
int_errtxt("card(%d) no previous HFC",
|
||||
|
@ -2475,7 +2486,7 @@ static int __init HFC_init(void)
|
|||
mISDN_free_dch(&card->dch);
|
||||
mISDN_free_bch(&card->bch[1]);
|
||||
mISDN_free_bch(&card->bch[0]);
|
||||
REMOVE_FROM_LISTBASE(card, ((hfc_pci_t *)HFC_obj.ilist));
|
||||
list_del(&card->list);
|
||||
kfree(card);
|
||||
if (!HFC_cnt) {
|
||||
mISDN_unregister(&HFC_obj);
|
||||
|
@ -2545,14 +2556,16 @@ static int __init HFC_init(void)
|
|||
#ifdef MODULE
|
||||
static void __exit HFC_cleanup(void)
|
||||
{
|
||||
int err;
|
||||
hfc_pci_t *card, *next;
|
||||
int err;
|
||||
|
||||
if ((err = mISDN_unregister(&HFC_obj))) {
|
||||
printk(KERN_ERR "Can't unregister HFC PCI error(%d)\n", err);
|
||||
}
|
||||
while(HFC_obj.ilist) {
|
||||
list_for_each_entry_safe(card, next, &HFC_obj.ilist, list) {
|
||||
printk(KERN_ERR "HFC PCI card struct not empty refs %d\n",
|
||||
HFC_obj.refcnt);
|
||||
release_card(HFC_obj.ilist);
|
||||
release_card(card);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ isac_new_ph(dchannel_t *dch)
|
|||
}
|
||||
while(upif) {
|
||||
if_link(upif, prim, para, 0, NULL, 0);
|
||||
upif = upif->next;
|
||||
upif = upif->clone;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1516,7 +1516,7 @@ l3dss1_global_restart(l3_process_t *pc, u_char pr, void *arg)
|
|||
u_char *p, ri, ch = 0, chan = 0;
|
||||
struct sk_buff *skb = arg;
|
||||
Q931_info_t *qi = (Q931_info_t *)skb->data;
|
||||
l3_process_t *up;
|
||||
l3_process_t *up, *n;
|
||||
|
||||
// newl3state(pc, 2);
|
||||
L3DelTimer(&pc->timer);
|
||||
|
@ -1539,13 +1539,11 @@ l3dss1_global_restart(l3_process_t *pc, u_char pr, void *arg)
|
|||
if (pc->l3->debug)
|
||||
l3_debug(pc->l3, "Restart for channel %d", chan);
|
||||
}
|
||||
up = pc->l3->proc;
|
||||
while (up) {
|
||||
list_for_each_entry_safe(up, n, &pc->l3->plist, list) {
|
||||
if ((ri & 7) == 7)
|
||||
dss1man(up, CC_RESTART | REQUEST, NULL);
|
||||
else if (up->bc == chan)
|
||||
mISDN_l3up(up, CC_RESTART | REQUEST, NULL);
|
||||
up = up->next;
|
||||
}
|
||||
dev_kfree_skb(skb);
|
||||
skb = MsgStart(pc, MT_RESTART_ACKNOWLEDGE, chan ? 6 : 3);
|
||||
|
@ -2221,7 +2219,7 @@ release_udss1(layer3_t *l3)
|
|||
inst->down.peer->obj->ctrl(inst->down.peer,
|
||||
MGR_DISCONNECT | REQUEST, &inst->down);
|
||||
}
|
||||
REMOVE_FROM_LISTBASE(l3, ((layer3_t *)u_dss1.ilist));
|
||||
list_del(&l3->list);
|
||||
u_dss1.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
|
||||
if (l3->entity != MISDN_ENTITY_NONE)
|
||||
u_dss1.ctrl(inst, MGR_DELENTITY | REQUEST, (void *)l3->entity);
|
||||
|
@ -2270,7 +2268,7 @@ new_udss1(mISDNstack_t *st, mISDN_pid_t *pid)
|
|||
nl3->global->state = 0;
|
||||
nl3->global->callref = 0;
|
||||
nl3->global->id = MISDN_ID_GLOBAL;
|
||||
nl3->global->next = NULL;
|
||||
INIT_LIST_HEAD(&nl3->global->list);
|
||||
nl3->global->n303 = N303;
|
||||
nl3->global->l3 = nl3;
|
||||
nl3->global->t303skb = NULL;
|
||||
|
@ -2284,14 +2282,14 @@ new_udss1(mISDNstack_t *st, mISDN_pid_t *pid)
|
|||
nl3->dummy->state = 0;
|
||||
nl3->dummy->callref = -1;
|
||||
nl3->dummy->id = MISDN_ID_DUMMY;
|
||||
nl3->dummy->next = NULL;
|
||||
INIT_LIST_HEAD(&nl3->dummy->list);
|
||||
nl3->dummy->n303 = N303;
|
||||
nl3->dummy->l3 = nl3;
|
||||
nl3->dummy->t303skb = NULL;
|
||||
L3InitTimer(nl3->dummy, &nl3->dummy->timer);
|
||||
sprintf(nl3->inst.name, "DSS1 %d", st->id);
|
||||
nl3->p_mgr = dss1man;
|
||||
APPEND_TO_LIST(nl3, ((layer3_t *)u_dss1.ilist));
|
||||
list_add_tail(&nl3->list, &u_dss1.ilist);
|
||||
err = u_dss1.ctrl(&nl3->inst, MGR_NEWENTITY | REQUEST, NULL);
|
||||
if (err) {
|
||||
printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%x)\n",
|
||||
|
@ -2300,7 +2298,7 @@ new_udss1(mISDNstack_t *st, mISDN_pid_t *pid)
|
|||
err = u_dss1.ctrl(st, MGR_REGLAYER | INDICATION, &nl3->inst);
|
||||
if (err) {
|
||||
release_l3(nl3);
|
||||
REMOVE_FROM_LISTBASE(nl3, ((layer3_t *)u_dss1.ilist));
|
||||
list_del(&nl3->list);
|
||||
kfree(nl3);
|
||||
} else {
|
||||
mISDN_stPara_t stp;
|
||||
|
@ -2328,17 +2326,18 @@ MODULE_PARM(debug, "1i");
|
|||
static int
|
||||
udss1_manager(void *data, u_int prim, void *arg) {
|
||||
mISDNinstance_t *inst = data;
|
||||
layer3_t *l3l = u_dss1.ilist;
|
||||
layer3_t *l3l;
|
||||
|
||||
if (debug & 0x1000)
|
||||
printk(KERN_DEBUG "udss1_manager data:%p prim:%x arg:%p\n", data, prim, arg);
|
||||
if (!data)
|
||||
return(-EINVAL);
|
||||
while(l3l) {
|
||||
list_for_each_entry(l3l, &u_dss1.ilist, list) {
|
||||
if (&l3l->inst == inst)
|
||||
break;
|
||||
l3l = l3l->next;
|
||||
}
|
||||
if (&l3l->list == &u_dss1.ilist)
|
||||
l3l = NULL;
|
||||
if (prim == (MGR_NEWLAYER | REQUEST))
|
||||
return(new_udss1(data, arg));
|
||||
if (!l3l) {
|
||||
|
@ -2387,14 +2386,13 @@ int UDSS1Init(void)
|
|||
#ifdef MODULE
|
||||
u_dss1.owner = THIS_MODULE;
|
||||
#endif
|
||||
INIT_LIST_HEAD(&u_dss1.ilist);
|
||||
u_dss1.name = MName;
|
||||
u_dss1.DPROTO.protocol[3] = ISDN_PID_L3_DSS1USER |
|
||||
ISDN_PID_L3_DF_PTP |
|
||||
ISDN_PID_L3_DF_EXTCID |
|
||||
ISDN_PID_L3_DF_CRLEN2;
|
||||
u_dss1.own_ctrl = udss1_manager;
|
||||
u_dss1.prev = NULL;
|
||||
u_dss1.next = NULL;
|
||||
mISDNl3New();
|
||||
if ((err = mISDN_register(&u_dss1))) {
|
||||
printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
|
||||
|
@ -2407,14 +2405,15 @@ int UDSS1Init(void)
|
|||
void UDSS1_cleanup(void)
|
||||
{
|
||||
int err;
|
||||
layer3_t *l3, *next;
|
||||
|
||||
if ((err = mISDN_unregister(&u_dss1))) {
|
||||
printk(KERN_ERR "Can't unregister User DSS1 error(%d)\n", err);
|
||||
}
|
||||
if (u_dss1.ilist) {
|
||||
if (!list_empty(&u_dss1.ilist)) {
|
||||
printk(KERN_WARNING "mISDNl3 u_dss1 list not empty\n");
|
||||
while(u_dss1.ilist)
|
||||
release_udss1(u_dss1.ilist);
|
||||
list_for_each_entry_safe(l3, next, &u_dss1.ilist, list)
|
||||
release_udss1(l3);
|
||||
}
|
||||
mISDNl3Free();
|
||||
}
|
||||
|
|
|
@ -19,14 +19,13 @@ static char *l1_revision = "$Revision$";
|
|||
#include "debug.h"
|
||||
|
||||
typedef struct _layer1 {
|
||||
struct _layer1 *prev;
|
||||
struct _layer1 *next;
|
||||
u_long Flags;
|
||||
struct FsmInst l1m;
|
||||
struct FsmTimer timer;
|
||||
int debug;
|
||||
int delay;
|
||||
mISDNinstance_t inst;
|
||||
struct list_head list;
|
||||
u_long Flags;
|
||||
struct FsmInst l1m;
|
||||
struct FsmTimer timer;
|
||||
int debug;
|
||||
int delay;
|
||||
mISDNinstance_t inst;
|
||||
} layer1_t;
|
||||
|
||||
/* l1 status_info */
|
||||
|
@ -614,7 +613,7 @@ release_l1(layer1_t *l1) {
|
|||
inst->down.peer->obj->ctrl(inst->down.peer,
|
||||
MGR_DISCONNECT | REQUEST, &inst->down);
|
||||
}
|
||||
REMOVE_FROM_LISTBASE(l1, ((layer1_t *)isdnl1.ilist));
|
||||
list_del(&l1->list);
|
||||
isdnl1.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
|
||||
kfree(l1);
|
||||
}
|
||||
|
@ -656,11 +655,11 @@ new_l1(mISDNstack_t *st, mISDN_pid_t *pid) {
|
|||
nl1->l1m.userint = 0;
|
||||
nl1->l1m.printdebug = l1m_debug;
|
||||
mISDN_FsmInitTimer(&nl1->l1m, &nl1->timer);
|
||||
APPEND_TO_LIST(nl1, ((layer1_t *)isdnl1.ilist));
|
||||
list_add_tail(&nl1->list, &isdnl1.ilist);
|
||||
err = isdnl1.ctrl(st, MGR_REGLAYER | INDICATION, &nl1->inst);
|
||||
if (err) {
|
||||
mISDN_FsmDelTimer(&nl1->timer, 0);
|
||||
REMOVE_FROM_LISTBASE(nl1, ((layer1_t *)isdnl1.ilist));
|
||||
list_del(&nl1->list);
|
||||
kfree(nl1);
|
||||
}
|
||||
return(err);
|
||||
|
@ -699,66 +698,57 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
static int
|
||||
l1_manager(void *data, u_int prim, void *arg) {
|
||||
mISDNinstance_t *inst = data;
|
||||
layer1_t *l1l = isdnl1.ilist;
|
||||
mISDNinstance_t *inst = data;
|
||||
layer1_t *l1l;
|
||||
int err = -EINVAL;
|
||||
|
||||
if (debug & 0x10000)
|
||||
printk(KERN_DEBUG "%s: data(%p) prim(%x) arg(%p)\n",
|
||||
__FUNCTION__, data, prim, arg);
|
||||
if (!data)
|
||||
return(-EINVAL);
|
||||
while(l1l) {
|
||||
if (&l1l->inst == inst)
|
||||
return(err);
|
||||
list_for_each_entry(l1l, &isdnl1.ilist, list) {
|
||||
if (&l1l->inst == inst) {
|
||||
err = 0;
|
||||
break;
|
||||
l1l = l1l->next;
|
||||
}
|
||||
}
|
||||
if (err && (prim != (MGR_NEWLAYER | REQUEST))) {
|
||||
printk(KERN_WARNING "l1_manager connect no instance\n");
|
||||
return(err);
|
||||
}
|
||||
|
||||
switch(prim) {
|
||||
case MGR_NEWLAYER | REQUEST:
|
||||
return(new_l1(data, arg));
|
||||
err = new_l1(data, arg);
|
||||
break;
|
||||
case MGR_CONNECT | REQUEST:
|
||||
if (!l1l) {
|
||||
printk(KERN_WARNING "l1_manager connect no instance\n");
|
||||
return(-EINVAL);
|
||||
}
|
||||
return(mISDN_ConnectIF(inst, arg));
|
||||
err = mISDN_ConnectIF(inst, arg);
|
||||
break;
|
||||
case MGR_SETIF | REQUEST:
|
||||
case MGR_SETIF | INDICATION:
|
||||
if (!l1l) {
|
||||
printk(KERN_WARNING "l1_manager setif no instance\n");
|
||||
return(-EINVAL);
|
||||
}
|
||||
return(mISDN_SetIF(inst, arg, prim, l1from_up, l1from_down, l1l));
|
||||
err = mISDN_SetIF(inst, arg, prim, l1from_up, l1from_down, l1l);
|
||||
break;
|
||||
case MGR_DISCONNECT | REQUEST:
|
||||
case MGR_DISCONNECT | INDICATION:
|
||||
if (!l1l) {
|
||||
printk(KERN_WARNING "l1_manager disconnect no instance\n");
|
||||
return(-EINVAL);
|
||||
}
|
||||
return(mISDN_DisConnectIF(inst, arg));
|
||||
err = mISDN_DisConnectIF(inst, arg);
|
||||
break;
|
||||
case MGR_UNREGLAYER | REQUEST:
|
||||
case MGR_RELEASE | INDICATION:
|
||||
if (l1l) {
|
||||
printk(KERN_DEBUG "release_l1 id %x\n", l1l->inst.st->id);
|
||||
release_l1(l1l);
|
||||
} else
|
||||
printk(KERN_WARNING "l1_manager release no instance\n");
|
||||
break;
|
||||
printk(KERN_DEBUG "release_l1 id %x\n", l1l->inst.st->id);
|
||||
release_l1(l1l);
|
||||
break;
|
||||
case MGR_STATUS | REQUEST:
|
||||
if (!l1l) {
|
||||
printk(KERN_WARNING "l1_manager status l1 no instance\n");
|
||||
return(-EINVAL);
|
||||
}
|
||||
return(l1_status(l1l, arg));
|
||||
err = l1_status(l1l, arg);
|
||||
break;
|
||||
PRIM_NOT_HANDLED(MGR_CTRLREADY|INDICATION);
|
||||
PRIM_NOT_HANDLED(MGR_ADDSTPARA|INDICATION);
|
||||
default:
|
||||
printk(KERN_WARNING "l1_manager prim %x not handled\n", prim);
|
||||
return(-EINVAL);
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return(0);
|
||||
return(err);
|
||||
}
|
||||
|
||||
int Isdnl1Init(void)
|
||||
|
@ -772,9 +762,7 @@ int Isdnl1Init(void)
|
|||
isdnl1.name = MName;
|
||||
isdnl1.DPROTO.protocol[1] = ISDN_PID_L1_TE_S0;
|
||||
isdnl1.own_ctrl = l1_manager;
|
||||
isdnl1.prev = NULL;
|
||||
isdnl1.next = NULL;
|
||||
isdnl1.ilist = NULL;
|
||||
INIT_LIST_HEAD(&isdnl1.ilist);
|
||||
#ifdef mISDN_UINTERFACE
|
||||
isdnl1.DPROTO.protocol[1] |= ISDN_PID_L1_TE_U;
|
||||
l1fsm_u.state_count = L1U_STATE_COUNT;
|
||||
|
@ -807,15 +795,16 @@ int Isdnl1Init(void)
|
|||
#ifdef MODULE
|
||||
void cleanup_module(void)
|
||||
{
|
||||
int err;
|
||||
int err;
|
||||
layer1_t *l1, *nl1;
|
||||
|
||||
if ((err = mISDN_unregister(&isdnl1))) {
|
||||
printk(KERN_ERR "Can't unregister ISDN layer 1 error(%d)\n", err);
|
||||
}
|
||||
if(isdnl1.ilist) {
|
||||
if(!list_empty(&isdnl1.ilist)) {
|
||||
printk(KERN_WARNING "mISDNl1 inst list not empty\n");
|
||||
while(isdnl1.ilist)
|
||||
release_l1(isdnl1.ilist);
|
||||
list_for_each_entry_safe(l1, nl1, &isdnl1.ilist, list)
|
||||
release_l1(l1);
|
||||
}
|
||||
#ifdef mISDN_UINTERFACE
|
||||
mISDN_FsmFree(&l1fsm_u);
|
||||
|
|
|
@ -200,7 +200,7 @@ static int
|
|||
ph_data_confirm(mISDNif_t *up, mISDN_head_t *hh, struct sk_buff *skb) {
|
||||
layer2_t *l2 = up->fdata;
|
||||
struct sk_buff *nskb = skb;
|
||||
mISDNif_t *next = up->next;
|
||||
mISDNif_t *next = up->clone;
|
||||
int ret = -EAGAIN;
|
||||
|
||||
if (test_bit(FLG_L1_BUSY, &l2->flag)) {
|
||||
|
@ -1885,16 +1885,18 @@ l2from_down(mISDNif_t *hif, struct sk_buff *askb)
|
|||
layer2_t *l2;
|
||||
int ret = -EINVAL;
|
||||
struct sk_buff *cskb = askb;
|
||||
mISDNif_t *next;
|
||||
mISDN_head_t *hh, sh;
|
||||
|
||||
if (!hif || !askb)
|
||||
return(-EINVAL);
|
||||
l2 = hif->fdata;
|
||||
hh = mISDN_HEAD_P(askb);
|
||||
next = hif->clone;
|
||||
// printk(KERN_DEBUG "%s: prim(%x)\n", __FUNCTION__, hh->prim);
|
||||
if (!l2) {
|
||||
if (hif->next && hif->next->func)
|
||||
ret = hif->next->func(hif->next, askb);
|
||||
if (next && next->func)
|
||||
ret = next->func(next, askb);
|
||||
return(ret);
|
||||
}
|
||||
if (hh->prim == (PH_DATA | CONFIRM))
|
||||
|
@ -1912,14 +1914,14 @@ l2from_down(mISDNif_t *hif, struct sk_buff *askb)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (hif->next && hif->next->func)
|
||||
ret = hif->next->func(hif->next, askb);
|
||||
if (next && next->func)
|
||||
ret = next->func(next, askb);
|
||||
return(ret);
|
||||
}
|
||||
if (hif->next) {
|
||||
if (hif->next->func) {
|
||||
if (next) {
|
||||
if (next->func) {
|
||||
if (!(cskb = skb_clone(askb, GFP_ATOMIC)))
|
||||
return(hif->next->func(hif->next, askb));
|
||||
return(next->func(next, askb));
|
||||
else
|
||||
sh = *hh;
|
||||
}
|
||||
|
@ -1960,9 +1962,9 @@ l2from_down(mISDNif_t *hif, struct sk_buff *askb)
|
|||
dev_kfree_skb(cskb);
|
||||
ret = 0;
|
||||
}
|
||||
if (hif->next && hif->next->func) {
|
||||
if (next && next->func) {
|
||||
*hh = sh;
|
||||
ret = hif->next->func(hif->next, askb);
|
||||
ret = next->func(next, askb);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
@ -2096,14 +2098,17 @@ release_l2(layer2_t *l2)
|
|||
if (l2->cloneif) {
|
||||
printk(KERN_DEBUG "%s: cloneif(%p) owner(%p) peer(%p)\n",
|
||||
__FUNCTION__, l2->cloneif, l2->cloneif->owner, l2->cloneif->peer);
|
||||
REMOVE_FROM_LIST(l2->cloneif);
|
||||
if (l2->cloneif->predecessor)
|
||||
l2->cloneif->predecessor->clone = l2->cloneif->clone;
|
||||
if (l2->cloneif->clone)
|
||||
l2->cloneif->clone->predecessor = l2->cloneif->predecessor;
|
||||
if (l2->cloneif->owner &&
|
||||
(l2->cloneif->owner->up.next == l2->cloneif))
|
||||
l2->cloneif->owner->up.next = l2->cloneif->next;
|
||||
(l2->cloneif->owner->up.clone == l2->cloneif))
|
||||
l2->cloneif->owner->up.clone = l2->cloneif->clone;
|
||||
kfree(l2->cloneif);
|
||||
l2->cloneif = NULL;
|
||||
}
|
||||
REMOVE_FROM_LISTBASE(l2, ((layer2_t *)isdnl2.ilist));
|
||||
list_del(&l2->list);
|
||||
isdnl2.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
|
||||
if (l2->entity != MISDN_ENTITY_NONE)
|
||||
isdnl2.ctrl(inst, MGR_DELENTITY | REQUEST, (void *)l2->entity);
|
||||
|
@ -2225,7 +2230,7 @@ new_l2(mISDNstack_t *st, mISDN_pid_t *pid, layer2_t **newl2) {
|
|||
|
||||
mISDN_FsmInitTimer(&nl2->l2m, &nl2->t200);
|
||||
mISDN_FsmInitTimer(&nl2->l2m, &nl2->t203);
|
||||
APPEND_TO_LIST(nl2, ((layer2_t *)isdnl2.ilist));
|
||||
list_add_tail(&nl2->list, &isdnl2.ilist);
|
||||
err = isdnl2.ctrl(&nl2->inst, MGR_NEWENTITY | REQUEST, NULL);
|
||||
if (err) {
|
||||
printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%x)\n",
|
||||
|
@ -2235,7 +2240,7 @@ new_l2(mISDNstack_t *st, mISDN_pid_t *pid, layer2_t **newl2) {
|
|||
if (err) {
|
||||
mISDN_FsmDelTimer(&nl2->t200, 0);
|
||||
mISDN_FsmDelTimer(&nl2->t203, 0);
|
||||
REMOVE_FROM_LISTBASE(nl2, ((layer2_t *)isdnl2.ilist));
|
||||
list_del(&nl2->list);
|
||||
kfree(nl2);
|
||||
nl2 = NULL;
|
||||
} else {
|
||||
|
@ -2286,7 +2291,10 @@ clone_l2(layer2_t *l2, mISDNinstance_t **new_ip) {
|
|||
nif->owner = l2->inst.down.peer;
|
||||
nif->peer = &nl2->inst;
|
||||
nif->stat = IF_DOWN;
|
||||
APPEND_TO_LIST(nif, nif->owner->up.next);
|
||||
nif->predecessor = &nif->owner->up;
|
||||
while(nif->predecessor->clone)
|
||||
nif->predecessor = nif->predecessor->clone;
|
||||
nif->predecessor->clone = nif;
|
||||
nl2->inst.down.owner = &nl2->inst;
|
||||
nl2->inst.down.peer = &l2->inst;
|
||||
nl2->inst.down.func = l2_chain_down;
|
||||
|
@ -2347,25 +2355,27 @@ MODULE_PARM(debug, "1i");
|
|||
|
||||
static int
|
||||
l2_manager(void *data, u_int prim, void *arg) {
|
||||
mISDNinstance_t *inst = data;
|
||||
layer2_t *l2l = isdnl2.ilist;;
|
||||
mISDNinstance_t *inst = data;
|
||||
layer2_t *l2l;
|
||||
int err = -EINVAL;
|
||||
|
||||
if (debug & 0x1000)
|
||||
printk(KERN_DEBUG "%s: data:%p prim:%x arg:%p\n", __FUNCTION__,
|
||||
data, prim, arg);
|
||||
if (!data)
|
||||
return(-EINVAL);
|
||||
while(l2l) {
|
||||
if (&l2l->inst == inst)
|
||||
return(err);
|
||||
list_for_each_entry(l2l, &isdnl2.ilist, list) {
|
||||
if (&l2l->inst == inst) {
|
||||
err = 0;
|
||||
break;
|
||||
l2l = l2l->next;
|
||||
}
|
||||
}
|
||||
if (prim == (MGR_NEWLAYER | REQUEST))
|
||||
return(new_l2(data, arg, NULL));
|
||||
if (!l2l) {
|
||||
if (err) {
|
||||
if (debug & 0x1)
|
||||
printk(KERN_WARNING "l2_manager prim(%x) l2 no instance\n", prim);
|
||||
return(-EINVAL);
|
||||
return(err);
|
||||
}
|
||||
switch(prim) {
|
||||
case MGR_NEWENTITY | CONFIRM:
|
||||
|
@ -2423,8 +2433,7 @@ int Isdnl2_Init(void)
|
|||
ISDN_PID_L2_DF_PTP;
|
||||
isdnl2.BPROTO.protocol[2] = ISDN_PID_L2_B_X75SLP;
|
||||
isdnl2.own_ctrl = l2_manager;
|
||||
isdnl2.prev = NULL;
|
||||
isdnl2.next = NULL;
|
||||
INIT_LIST_HEAD(&isdnl2.ilist);
|
||||
l2fsm.state_count = L2_STATE_COUNT;
|
||||
l2fsm.event_count = L2_EVENT_COUNT;
|
||||
l2fsm.strEvent = strL2Event;
|
||||
|
@ -2440,15 +2449,16 @@ int Isdnl2_Init(void)
|
|||
|
||||
void Isdnl2_cleanup(void)
|
||||
{
|
||||
int err;
|
||||
int err;
|
||||
layer2_t *l2, *nl2;
|
||||
|
||||
if ((err = mISDN_unregister(&isdnl2))) {
|
||||
printk(KERN_ERR "Can't unregister ISDN layer 2 error(%d)\n", err);
|
||||
}
|
||||
if(isdnl2.ilist) {
|
||||
if(!list_empty(&isdnl2.ilist)) {
|
||||
printk(KERN_WARNING "mISDNl2 l2 list not empty\n");
|
||||
while(isdnl2.ilist)
|
||||
release_l2(isdnl2.ilist);
|
||||
list_for_each_entry_safe(l2, nl2, &isdnl2.ilist, list)
|
||||
release_l2(l2);
|
||||
}
|
||||
TEIFree();
|
||||
mISDN_FsmFree(&l2fsm);
|
||||
|
|
|
@ -30,8 +30,7 @@ typedef struct _laddr {
|
|||
} laddr_t;
|
||||
|
||||
typedef struct _layer2 {
|
||||
struct _layer2 *prev;
|
||||
struct _layer2 *next;
|
||||
struct list_head list;
|
||||
int sapi;
|
||||
int tei;
|
||||
laddr_t addr;
|
||||
|
|
|
@ -254,26 +254,22 @@ no_l3_proto_spec(struct PStack *st, isdn_ctrl *ic)
|
|||
l3_process_t
|
||||
*getl3proc(layer3_t *l3, int cr)
|
||||
{
|
||||
l3_process_t *p = l3->proc;
|
||||
|
||||
while (p)
|
||||
l3_process_t *p;
|
||||
|
||||
list_for_each_entry(p, &l3->plist, list)
|
||||
if (p->callref == cr)
|
||||
return (p);
|
||||
else
|
||||
p = p->next;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
l3_process_t
|
||||
*getl3proc4id(layer3_t *l3, u_int id)
|
||||
{
|
||||
l3_process_t *p = l3->proc;
|
||||
l3_process_t *p;
|
||||
|
||||
while (p)
|
||||
list_for_each_entry(p, &l3->plist, list)
|
||||
if (p->id == id)
|
||||
return (p);
|
||||
else
|
||||
p = p->next;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
@ -324,7 +320,7 @@ l3_process_t
|
|||
p->callref = cr;
|
||||
p->n303 = n303;
|
||||
L3InitTimer(p, &p->timer);
|
||||
APPEND_TO_LIST(p, l3->proc);
|
||||
list_add_tail(&p->list, &l3->plist);
|
||||
return (p);
|
||||
};
|
||||
|
||||
|
@ -337,10 +333,10 @@ release_l3_process(l3_process_t *p)
|
|||
return;
|
||||
l3 = p->l3;
|
||||
mISDN_l3up(p, CC_RELEASE_CR | INDICATION, NULL);
|
||||
REMOVE_FROM_LISTBASE(p, l3->proc);
|
||||
list_del(&p->list);
|
||||
StopAllL3Timer(p);
|
||||
kfree(p);
|
||||
if (!l3->proc && !test_bit(FLG_PTP, &l3->Flag)) {
|
||||
if (list_empty(&l3->plist) && !test_bit(FLG_PTP, &l3->Flag)) {
|
||||
if (l3->debug)
|
||||
l3_debug(l3, "release_l3_process: last process");
|
||||
if (!skb_queue_len(&l3->squeue)) {
|
||||
|
@ -357,15 +353,10 @@ release_l3_process(l3_process_t *p)
|
|||
static void
|
||||
l3ml3p(layer3_t *l3, int pr)
|
||||
{
|
||||
l3_process_t *p = l3->proc;
|
||||
l3_process_t *np;
|
||||
l3_process_t *p, *np;
|
||||
|
||||
while (p) {
|
||||
/* p might be kfreed under us, so we need to save where we want to go on */
|
||||
np = p->next;
|
||||
list_for_each_entry_safe(p, np, &l3->plist, list)
|
||||
l3->p_mgr(p, pr, NULL);
|
||||
p = np;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -419,7 +410,7 @@ lc_connect(struct FsmInst *fi, int event, void *arg)
|
|||
dev_kfree_skb(skb);
|
||||
dequeued++;
|
||||
}
|
||||
if ((!l3->proc) && dequeued) {
|
||||
if (list_empty(&l3->plist) && dequeued) {
|
||||
if (l3->debug)
|
||||
l3m_debug(fi, "lc_connect: release link");
|
||||
mISDN_FsmEvent(&l3->l3m, EV_RELEASE_REQ, NULL);
|
||||
|
@ -441,7 +432,7 @@ lc_connected(struct FsmInst *fi, int event, void *arg)
|
|||
dev_kfree_skb(skb);
|
||||
dequeued++;
|
||||
}
|
||||
if ((!l3->proc) && dequeued) {
|
||||
if (list_empty(&l3->plist) && dequeued) {
|
||||
if (l3->debug)
|
||||
l3m_debug(fi, "lc_connected: release link");
|
||||
mISDN_FsmEvent(&l3->l3m, EV_RELEASE_REQ, NULL);
|
||||
|
@ -558,7 +549,7 @@ l3_msg(layer3_t *l3, u_int pr, int dinfo, int len, void *arg)
|
|||
void
|
||||
init_l3(layer3_t *l3)
|
||||
{
|
||||
l3->proc = NULL;
|
||||
INIT_LIST_HEAD(&l3->plist);
|
||||
l3->global = NULL;
|
||||
l3->dummy = NULL;
|
||||
l3->entity = MISDN_ENTITY_NONE;
|
||||
|
@ -578,11 +569,13 @@ init_l3(layer3_t *l3)
|
|||
void
|
||||
release_l3(layer3_t *l3)
|
||||
{
|
||||
l3_process_t *p, *np;
|
||||
|
||||
if (l3->l3m.debug)
|
||||
printk(KERN_DEBUG "release_l3(%p) proc(%p) global(%p) dummy(%p)\n",
|
||||
l3, l3->proc, l3->global, l3->dummy);
|
||||
while (l3->proc)
|
||||
release_l3_process(l3->proc);
|
||||
printk(KERN_DEBUG "release_l3(%p) plist(%s) global(%p) dummy(%p)\n",
|
||||
l3, list_empty(&l3->plist) ? "no" : "yes", l3->global, l3->dummy);
|
||||
list_for_each_entry_safe(p, np, &l3->plist, list)
|
||||
release_l3_process(p);
|
||||
if (l3->global) {
|
||||
StopAllL3Timer(l3->global);
|
||||
kfree(l3->global);
|
||||
|
|
|
@ -35,8 +35,7 @@ typedef struct _L3Timer {
|
|||
} L3Timer_t;
|
||||
|
||||
typedef struct _l3_process {
|
||||
struct _l3_process *prev;
|
||||
struct _l3_process *next;
|
||||
struct list_head list;
|
||||
struct _layer3 *l3;
|
||||
int callref;
|
||||
int state;
|
||||
|
@ -49,14 +48,13 @@ typedef struct _l3_process {
|
|||
} l3_process_t;
|
||||
|
||||
typedef struct _layer3 {
|
||||
struct _layer3 *prev;
|
||||
struct _layer3 *next;
|
||||
struct list_head list;
|
||||
struct FsmInst l3m;
|
||||
struct FsmTimer l3m_timer;
|
||||
int entity;
|
||||
int pid_cnt;
|
||||
int next_id;
|
||||
l3_process_t *proc;
|
||||
struct list_head plist;
|
||||
l3_process_t *global;
|
||||
l3_process_t *dummy;
|
||||
int (*p_mgr)(l3_process_t *, u_int, void *);
|
||||
|
|
|
@ -148,11 +148,10 @@ typedef struct FacConfParm FacConfParm_t;
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
struct _PLInst {
|
||||
PLInst_t *prev;
|
||||
PLInst_t *next;
|
||||
u_int state;
|
||||
mISDNstack_t *st;
|
||||
mISDNinstance_t inst;
|
||||
struct list_head list;
|
||||
u_int state;
|
||||
mISDNstack_t *st;
|
||||
mISDNinstance_t inst;
|
||||
};
|
||||
|
||||
struct _ConfQueue {
|
||||
|
@ -175,11 +174,10 @@ struct Bprotocol {
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
struct _Controller {
|
||||
struct _Controller *prev;
|
||||
struct _Controller *next;
|
||||
struct list_head list;
|
||||
mISDNinstance_t inst;
|
||||
int nr_bc;
|
||||
PLInst_t *linklist;
|
||||
struct list_head linklist;
|
||||
struct capi_ctr *ctrl;
|
||||
__u32 addr;
|
||||
int entity;
|
||||
|
|
|
@ -109,8 +109,7 @@ const char *Sedlbauer_Types[] =
|
|||
/* data struct */
|
||||
|
||||
typedef struct _sedl_fax {
|
||||
struct _sedl_fax *prev;
|
||||
struct _sedl_fax *next;
|
||||
struct list_head list;
|
||||
void *pdev;
|
||||
u_int subtyp;
|
||||
u_int irq;
|
||||
|
@ -582,7 +581,7 @@ release_card(sedl_fax *card) {
|
|||
mISDN_free_dch(&card->dch);
|
||||
speedfax.ctrl(card->dch.inst.up.peer, MGR_DISCONNECT | REQUEST, &card->dch.inst.up);
|
||||
speedfax.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
|
||||
REMOVE_FROM_LISTBASE(card, ((sedl_fax *)speedfax.ilist));
|
||||
list_del(&card->list);
|
||||
unlock_dev(card);
|
||||
if (card->subtyp == SEDL_SPEEDFAX_ISA) {
|
||||
pnp_disable_dev(card->pdev);
|
||||
|
@ -597,7 +596,7 @@ release_card(sedl_fax *card) {
|
|||
|
||||
static int
|
||||
speedfax_manager(void *data, u_int prim, void *arg) {
|
||||
sedl_fax *card = speedfax.ilist;
|
||||
sedl_fax *card;
|
||||
mISDNinstance_t *inst=data;
|
||||
int channel = -1;
|
||||
struct sk_buff *skb;
|
||||
|
@ -610,7 +609,7 @@ speedfax_manager(void *data, u_int prim, void *arg) {
|
|||
prim, arg);
|
||||
return(-EINVAL);
|
||||
}
|
||||
while(card) {
|
||||
list_for_each_entry(card, &speedfax.ilist, list) {
|
||||
if (&card->dch.inst == inst) {
|
||||
channel = 2;
|
||||
break;
|
||||
|
@ -623,7 +622,6 @@ speedfax_manager(void *data, u_int prim, void *arg) {
|
|||
channel = 1;
|
||||
break;
|
||||
}
|
||||
card = card->next;
|
||||
}
|
||||
if (channel<0) {
|
||||
printk(KERN_ERR "speedfax_manager no channel data %p prim %x arg %p\n",
|
||||
|
@ -731,7 +729,7 @@ static int __devinit setup_instance(sedl_fax *card)
|
|||
kfree(card);
|
||||
return(-EINVAL);
|
||||
}
|
||||
APPEND_TO_LIST(card, ((sedl_fax *)speedfax.ilist));
|
||||
list_add_tail(&card->list, &speedfax.ilist);
|
||||
card->dch.debug = debug;
|
||||
lock_HW_init(&card->lock);
|
||||
card->dch.inst.lock = lock_dev;
|
||||
|
@ -759,7 +757,7 @@ static int __devinit setup_instance(sedl_fax *card)
|
|||
mISDN_free_dch(&card->dch);
|
||||
mISDN_free_bch(&card->bch[1]);
|
||||
mISDN_free_bch(&card->bch[0]);
|
||||
REMOVE_FROM_LISTBASE(card, ((sedl_fax *)speedfax.ilist));
|
||||
list_del(&card->list);
|
||||
kfree(card);
|
||||
return(err);
|
||||
}
|
||||
|
@ -825,6 +823,7 @@ static int __devinit sedlpci_probe(struct pci_dev *pdev, const struct pci_device
|
|||
return(err);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PNP)
|
||||
#ifdef NEW_ISAPNP
|
||||
static int __devinit sedlpnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
|
||||
#else
|
||||
|
@ -864,6 +863,7 @@ static int __devinit sedlpnp_probe(struct pci_dev *pdev, const struct isapnp_dev
|
|||
pnp_set_drvdata(pdev, NULL);
|
||||
return(err);
|
||||
}
|
||||
#endif /* CONFIG_PNP */
|
||||
|
||||
static void __devexit sedl_remove_pci(struct pci_dev *pdev)
|
||||
{
|
||||
|
@ -875,6 +875,7 @@ static void __devexit sedl_remove_pci(struct pci_dev *pdev)
|
|||
printk(KERN_WARNING "%s: drvdata allready removed\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PNP)
|
||||
#ifdef NEW_ISAPNP
|
||||
static void __devexit sedl_remove_pnp(struct pnp_dev *pdev)
|
||||
#else
|
||||
|
@ -888,6 +889,7 @@ static void __devexit sedl_remove_pnp(struct pci_dev *pdev)
|
|||
else
|
||||
printk(KERN_WARNING "%s: drvdata allready removed\n", __FUNCTION__);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct pci_device_id sedlpci_ids[] __devinitdata = {
|
||||
{ PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100, PCI_SUBVENDOR_SPEEDFAX_PYRAMID, PCI_SUB_ID_SEDLBAUER,
|
||||
|
@ -905,6 +907,7 @@ static struct pci_driver sedlpci_driver = {
|
|||
id_table: sedlpci_ids,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_PNP)
|
||||
#ifdef NEW_ISAPNP
|
||||
static struct pnp_device_id sedlpnp_ids[] __devinitdata = {
|
||||
{
|
||||
|
@ -930,6 +933,7 @@ static struct isapnp_driver sedlpnp_driver = {
|
|||
remove: __devexit_p(sedl_remove_pnp),
|
||||
id_table: sedlpnp_ids,
|
||||
};
|
||||
#endif /* CONFIG_PNP */
|
||||
|
||||
static int __init Speedfax_init(void)
|
||||
{
|
||||
|
@ -938,6 +942,7 @@ static int __init Speedfax_init(void)
|
|||
#ifdef MODULE
|
||||
speedfax.owner = THIS_MODULE;
|
||||
#endif
|
||||
INIT_LIST_HEAD(&speedfax.ilist);
|
||||
speedfax.name = SpeedfaxName;
|
||||
speedfax.own_ctrl = speedfax_manager;
|
||||
speedfax.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0;
|
||||
|
@ -948,9 +953,6 @@ static int __init Speedfax_init(void)
|
|||
speedfax.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANS |
|
||||
ISDN_PID_L2_B_T30;
|
||||
|
||||
speedfax.prev = NULL;
|
||||
speedfax.next = NULL;
|
||||
|
||||
if ((err = mISDN_register(&speedfax))) {
|
||||
printk(KERN_ERR "Can't register Speedfax error(%d)\n", err);
|
||||
return(err);
|
||||
|
@ -959,11 +961,11 @@ static int __init Speedfax_init(void)
|
|||
if (err < 0)
|
||||
goto out;
|
||||
pci_nr_found = err;
|
||||
|
||||
#if defined(CONFIG_PNP)
|
||||
err = pnp_register_driver(&sedlpnp_driver);
|
||||
if (err < 0)
|
||||
goto out_unregister_pci;
|
||||
|
||||
#endif
|
||||
#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
|
||||
if (pci_nr_found + err == 0) {
|
||||
err = -ENODEV;
|
||||
|
@ -974,7 +976,9 @@ static int __init Speedfax_init(void)
|
|||
|
||||
#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
|
||||
out_unregister_isapnp:
|
||||
#if defined(CONFIG_PNP)
|
||||
pnp_unregister_driver(&sedlpnp_driver);
|
||||
#endif
|
||||
#endif
|
||||
out_unregister_pci:
|
||||
pci_unregister_driver(&sedlpci_driver);
|
||||
|
@ -984,16 +988,20 @@ static int __init Speedfax_init(void)
|
|||
|
||||
static void __exit Speedfax_cleanup(void)
|
||||
{
|
||||
int err;
|
||||
int err;
|
||||
sedl_fax *card, *next;
|
||||
|
||||
if ((err = mISDN_unregister(&speedfax))) {
|
||||
printk(KERN_ERR "Can't unregister Speedfax PCI error(%d)\n", err);
|
||||
}
|
||||
while(speedfax.ilist) {
|
||||
list_for_each_entry_safe(card, next, &speedfax.ilist, list) {
|
||||
printk(KERN_ERR "Speedfax PCI card struct not empty refs %d\n",
|
||||
speedfax.refcnt);
|
||||
release_card(speedfax.ilist);
|
||||
release_card(card);
|
||||
}
|
||||
#if defined(CONFIG_PNP)
|
||||
pnp_unregister_driver(&sedlpnp_driver);
|
||||
#endif
|
||||
pci_unregister_driver(&sedlpci_driver);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,18 +8,16 @@
|
|||
|
||||
#include "core.h"
|
||||
|
||||
mISDNstack_t *mISDN_stacklist = NULL;
|
||||
mISDNinstance_t *mISDN_instlist = NULL;
|
||||
LIST_HEAD(mISDN_stacklist);
|
||||
LIST_HEAD(mISDN_instlist);
|
||||
|
||||
int
|
||||
get_stack_cnt(void) {
|
||||
int cnt = 0;
|
||||
mISDNstack_t *st = mISDN_stacklist;
|
||||
mISDNstack_t *st;
|
||||
|
||||
while(st) {
|
||||
list_for_each_entry(st, &mISDN_stacklist, list)
|
||||
cnt++;
|
||||
st = st->next;
|
||||
}
|
||||
return(cnt);
|
||||
}
|
||||
|
||||
|
@ -44,20 +42,16 @@ get_stack_info(iframe_t *frm) {
|
|||
memcpy(&si->pid, &st->pid, sizeof(mISDN_pid_t));
|
||||
memcpy(&si->para, &st->para, sizeof(mISDN_stPara_t));
|
||||
si->instcnt = 0;
|
||||
lay = st->lstack;
|
||||
while(lay) {
|
||||
list_for_each_entry(lay, &st->layerlist, list) {
|
||||
if (lay->inst) {
|
||||
si->inst[si->instcnt] = lay->inst->id;
|
||||
si->instcnt++;
|
||||
}
|
||||
lay = lay->next;
|
||||
}
|
||||
si->childcnt = 0;
|
||||
cst = st->child;
|
||||
while(cst) {
|
||||
list_for_each_entry(cst, &st->childlist, list) {
|
||||
si->child[si->childcnt] = cst->id;
|
||||
si->childcnt++;
|
||||
cst = cst->next;
|
||||
}
|
||||
frm->len = sizeof(stack_info_t);
|
||||
if (si->childcnt>2)
|
||||
|
@ -67,18 +61,19 @@ get_stack_info(iframe_t *frm) {
|
|||
|
||||
static int
|
||||
get_free_stackid(mISDNstack_t *mst, int flag) {
|
||||
u_int id=1;
|
||||
u_int id=1, found;
|
||||
mISDNstack_t *st;
|
||||
|
||||
if (!mst) {
|
||||
while(id<127) {
|
||||
st = mISDN_stacklist;
|
||||
while (st) {
|
||||
if (st->id == id)
|
||||
found = 0;
|
||||
list_for_each_entry(st, &mISDN_stacklist, list) {
|
||||
if (st->id == id) {
|
||||
found++;
|
||||
break;
|
||||
st = st->next;
|
||||
}
|
||||
}
|
||||
if (st)
|
||||
if (found)
|
||||
id++;
|
||||
else
|
||||
return(id);
|
||||
|
@ -86,27 +81,29 @@ get_free_stackid(mISDNstack_t *mst, int flag) {
|
|||
} else if (flag & FLG_CLONE_STACK) {
|
||||
id = mst->id | FLG_CLONE_STACK;
|
||||
while(id < CLONE_ID_MAX) {
|
||||
found = 0;
|
||||
id += CLONE_ID_INC;
|
||||
st = mISDN_stacklist;
|
||||
while (st) {
|
||||
if (st->id == id)
|
||||
list_for_each_entry(st, &mISDN_stacklist, list) {
|
||||
if (st->id == id) {
|
||||
found++;
|
||||
break;
|
||||
st = st->next;
|
||||
}
|
||||
}
|
||||
if (!st)
|
||||
if (!found)
|
||||
return(id);
|
||||
}
|
||||
} else if (flag & FLG_CHILD_STACK) {
|
||||
id = mst->id | FLG_CHILD_STACK;
|
||||
while(id < CHILD_ID_MAX) {
|
||||
id += CHILD_ID_INC;
|
||||
st = mst->child;
|
||||
while (st) {
|
||||
if (st->id == id)
|
||||
found = 0;
|
||||
list_for_each_entry(st, &mst->childlist, list) {
|
||||
if (st->id == id) {
|
||||
found++;
|
||||
break;
|
||||
st = st->next;
|
||||
}
|
||||
}
|
||||
if (!st)
|
||||
if (!found)
|
||||
return(id);
|
||||
}
|
||||
}
|
||||
|
@ -116,22 +113,19 @@ get_free_stackid(mISDNstack_t *mst, int flag) {
|
|||
mISDNstack_t *
|
||||
get_stack4id(u_int id)
|
||||
{
|
||||
mISDNstack_t *cst, *st = mISDN_stacklist;
|
||||
mISDNstack_t *cst, *st;
|
||||
|
||||
if (core_debug & DEBUG_CORE_FUNC)
|
||||
printk(KERN_DEBUG "get_stack4id(%x)\n", id);
|
||||
if (!id) /* 0 isn't a valid id */
|
||||
return(NULL);
|
||||
while(st) {
|
||||
list_for_each_entry(st, &mISDN_stacklist, list) {
|
||||
if (id == st->id)
|
||||
return(st);
|
||||
cst = st->child;
|
||||
while (cst) {
|
||||
list_for_each_entry(cst, &st->childlist, list) {
|
||||
if (cst->id == id)
|
||||
return(cst);
|
||||
cst = cst->next;
|
||||
}
|
||||
st = st->next;
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
@ -146,14 +140,12 @@ getlayer4lay(mISDNstack_t *st, int layermask)
|
|||
int_error();
|
||||
return(NULL);
|
||||
}
|
||||
layer = st->lstack;
|
||||
while(layer) {
|
||||
list_for_each_entry(layer, &st->layerlist, list) {
|
||||
inst = layer->inst;
|
||||
if(inst && (inst->pid.layermask & layermask))
|
||||
break;
|
||||
layer = layer->next;
|
||||
return(layer);
|
||||
}
|
||||
return(layer);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
mISDNinstance_t *
|
||||
|
@ -173,8 +165,7 @@ get_instance(mISDNstack_t *st, int layer_nr, int protocol)
|
|||
int_errtxt("lnr %d", layer_nr);
|
||||
return(NULL);
|
||||
}
|
||||
layer = st->lstack;
|
||||
while(layer) {
|
||||
list_for_each_entry(layer, &st->layerlist, list) {
|
||||
inst = layer->inst;
|
||||
if (inst) {
|
||||
if (core_debug & DEBUG_CORE_FUNC)
|
||||
|
@ -186,11 +177,10 @@ get_instance(mISDNstack_t *st, int layer_nr, int protocol)
|
|||
goto out;
|
||||
inst = NULL;
|
||||
}
|
||||
if (layer == layer->next) {
|
||||
if (list_empty(&layer->list)) {
|
||||
int_errtxt("deadloop layer %p", layer);
|
||||
return(NULL);
|
||||
}
|
||||
layer = layer->next;
|
||||
}
|
||||
out:
|
||||
return(inst);
|
||||
|
@ -199,13 +189,11 @@ out:
|
|||
mISDNinstance_t *
|
||||
get_instance4id(u_int id)
|
||||
{
|
||||
mISDNinstance_t *inst = mISDN_instlist;
|
||||
mISDNinstance_t *inst;
|
||||
|
||||
while(inst) {
|
||||
list_for_each_entry(inst, &mISDN_instlist, list)
|
||||
if (inst->id == id)
|
||||
return(inst);
|
||||
inst = inst->next;
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
@ -231,22 +219,16 @@ insertlayer(mISDNstack_t *st, mISDNlayer_t *layer, int layermask)
|
|||
int_error();
|
||||
return(-EINVAL);
|
||||
}
|
||||
item = st->lstack;
|
||||
if (!item) {
|
||||
st->lstack = layer;
|
||||
if (list_empty(&st->layerlist)) {
|
||||
list_add(&layer->list, &st->layerlist);
|
||||
} else {
|
||||
while(item) {
|
||||
list_for_each_entry(item, &st->layerlist, list) {
|
||||
if (layermask < get_layermask(item)) {
|
||||
INSERT_INTO_LIST(layer, item, st->lstack);
|
||||
list_add_tail(&layer->list, &item->list);
|
||||
return(0);
|
||||
} else {
|
||||
if (!item->next)
|
||||
break;
|
||||
}
|
||||
item = item->next;
|
||||
}
|
||||
item->next = layer;
|
||||
layer->prev = item;
|
||||
list_add_tail(&layer->list, &st->layerlist);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
@ -264,6 +246,8 @@ new_stack(mISDNstack_t *master, mISDNinstance_t *inst)
|
|||
return(NULL);
|
||||
}
|
||||
memset(newst, 0, sizeof(mISDNstack_t));
|
||||
INIT_LIST_HEAD(&newst->layerlist);
|
||||
INIT_LIST_HEAD(&newst->childlist);
|
||||
if (!master) {
|
||||
if (inst && inst->st) {
|
||||
newst->id = get_free_stackid(inst->st, FLG_CLONE_STACK);
|
||||
|
@ -275,9 +259,9 @@ new_stack(mISDNstack_t *master, mISDNinstance_t *inst)
|
|||
}
|
||||
newst->mgr = inst;
|
||||
if (master) {
|
||||
APPEND_TO_LIST(newst, master->child);
|
||||
list_add_tail(&newst->list, &master->childlist);
|
||||
} else {
|
||||
APPEND_TO_LIST(newst, mISDN_stacklist);
|
||||
list_add_tail(&newst->list, &mISDN_stacklist);
|
||||
}
|
||||
if (core_debug & DEBUG_CORE_FUNC)
|
||||
printk(KERN_DEBUG "Stack id %x added\n", newst->id);
|
||||
|
@ -291,10 +275,10 @@ static int
|
|||
release_layers(mISDNstack_t *st, u_int prim)
|
||||
{
|
||||
mISDNinstance_t *inst;
|
||||
mISDNlayer_t *layer;
|
||||
mISDNlayer_t *layer, *nl;
|
||||
int cnt = 0;
|
||||
|
||||
while((layer = st->lstack)) {
|
||||
list_for_each_entry_safe(layer, nl, &st->layerlist, list) {
|
||||
inst = layer->inst;
|
||||
if (inst) {
|
||||
if (core_debug & DEBUG_CORE_FUNC)
|
||||
|
@ -303,10 +287,10 @@ release_layers(mISDNstack_t *st, u_int prim)
|
|||
inst->name, inst->pid.layermask);
|
||||
inst->obj->own_ctrl(inst, prim, NULL);
|
||||
}
|
||||
REMOVE_FROM_LISTBASE(layer, st->lstack);
|
||||
list_del(&layer->list);
|
||||
kfree(layer);
|
||||
if (cnt++ > 1000) {
|
||||
int_errtxt("release_layers st(%p)", st);
|
||||
int_errtxt("release_layers endless loop st(%p)", st);
|
||||
return(-EINVAL);
|
||||
}
|
||||
}
|
||||
|
@ -317,17 +301,15 @@ int
|
|||
do_for_all_layers(mISDNstack_t *st, u_int prim, void *arg)
|
||||
{
|
||||
mISDNinstance_t *inst;
|
||||
mISDNlayer_t *layer;
|
||||
mISDNlayer_t *layer, *nl;
|
||||
int cnt = 0;
|
||||
|
||||
if (!st) {
|
||||
int_error();
|
||||
return(-EINVAL);
|
||||
}
|
||||
layer = st->lstack;
|
||||
while(layer) {
|
||||
list_for_each_entry_safe(layer, nl, &st->layerlist, list) {
|
||||
inst = layer->inst;
|
||||
layer = layer->next;
|
||||
if (inst) {
|
||||
if (core_debug & DEBUG_CORE_FUNC)
|
||||
printk(KERN_DEBUG "%s: st(%p) inst(%p):%x %s prim(%x) arg(%p)\n",
|
||||
|
@ -335,7 +317,7 @@ do_for_all_layers(mISDNstack_t *st, u_int prim, void *arg)
|
|||
inst->obj->own_ctrl(inst, prim, arg);
|
||||
}
|
||||
if (cnt++ > 1000) {
|
||||
int_errtxt("release_layers st(%p)", st);
|
||||
int_errtxt("do_for_all_layers endless loop st(%p)", st);
|
||||
return(-EINVAL);
|
||||
}
|
||||
}
|
||||
|
@ -382,66 +364,55 @@ change_stack_para(mISDNstack_t *st, u_int prim, mISDN_stPara_t *stpara)
|
|||
int
|
||||
release_stack(mISDNstack_t *st) {
|
||||
int err;
|
||||
mISDNstack_t *cst;
|
||||
mISDNstack_t *cst, *nst;
|
||||
|
||||
if (core_debug & DEBUG_CORE_FUNC)
|
||||
printk(KERN_DEBUG "%s: st(%p)\n", __FUNCTION__, st);
|
||||
while (st->child) {
|
||||
cst = st->child;
|
||||
list_for_each_entry_safe(cst, nst, &st->childlist, list) {
|
||||
if (core_debug & DEBUG_CORE_FUNC)
|
||||
printk(KERN_DEBUG "%s: cst(%p)\n", __FUNCTION__, cst);
|
||||
if ((err = release_layers(cst, MGR_RELEASE | INDICATION))) {
|
||||
printk(KERN_WARNING "release_stack child err(%d)\n", err);
|
||||
return(err);
|
||||
}
|
||||
REMOVE_FROM_LISTBASE(cst, st->child);
|
||||
list_del(&cst->list);
|
||||
kfree(cst);
|
||||
}
|
||||
if ((err = release_layers(st, MGR_RELEASE | INDICATION))) {
|
||||
printk(KERN_WARNING "release_stack err(%d)\n", err);
|
||||
return(err);
|
||||
}
|
||||
REMOVE_FROM_LISTBASE(st, mISDN_stacklist);
|
||||
list_del(&st->list);
|
||||
kfree(st);
|
||||
if (core_debug & DEBUG_CORE_FUNC)
|
||||
printk(KERN_DEBUG "%s: mISDN_stacklist(%p)\n", __FUNCTION__, mISDN_stacklist);
|
||||
printk(KERN_DEBUG "%s: mISDN_stacklist(%p<-%p->%p)\n", __FUNCTION__,
|
||||
mISDN_stacklist.prev, &mISDN_stacklist, mISDN_stacklist.next);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void
|
||||
release_stacks(mISDNobject_t *obj) {
|
||||
mISDNstack_t *st, *tmp;
|
||||
mISDNlayer_t *layer;
|
||||
mISDNinstance_t *inst;
|
||||
mISDNlayer_t *layer, *ltmp;
|
||||
int rel;
|
||||
|
||||
st = mISDN_stacklist;
|
||||
if (core_debug & DEBUG_CORE_FUNC)
|
||||
printk(KERN_DEBUG "%s: obj(%p) %s\n",
|
||||
__FUNCTION__, obj, obj->name);
|
||||
while (st) {
|
||||
list_for_each_entry_safe(st, tmp, &mISDN_stacklist, list) {
|
||||
rel = 0;
|
||||
layer = st->lstack;
|
||||
if (core_debug & DEBUG_CORE_FUNC)
|
||||
printk(KERN_DEBUG "%s: st(%p) l(%p)\n",
|
||||
__FUNCTION__, st, layer);
|
||||
while(layer) {
|
||||
inst = layer->inst;
|
||||
if (inst) {
|
||||
if (core_debug & DEBUG_CORE_FUNC)
|
||||
printk(KERN_DEBUG "%s: inst(%p)\n",
|
||||
__FUNCTION__, inst);
|
||||
if (inst->obj == obj)
|
||||
rel++;
|
||||
}
|
||||
layer = layer->next;
|
||||
printk(KERN_DEBUG "%s: st(%p)\n",
|
||||
__FUNCTION__, st);
|
||||
list_for_each_entry_safe(layer, ltmp, &st->layerlist, list) {
|
||||
if (core_debug & DEBUG_CORE_FUNC)
|
||||
printk(KERN_DEBUG "%s: layer(%p) inst(%p)\n",
|
||||
__FUNCTION__, layer, layer->inst);
|
||||
if (layer->inst && layer->inst->obj == obj)
|
||||
rel++;
|
||||
}
|
||||
if (rel) {
|
||||
tmp = st->next;
|
||||
if (rel)
|
||||
release_stack(st);
|
||||
st = tmp;
|
||||
} else
|
||||
st = st->next;
|
||||
}
|
||||
if (obj->refcnt)
|
||||
printk(KERN_WARNING "release_stacks obj %s refcnt is %d\n",
|
||||
|
@ -451,24 +422,22 @@ release_stacks(mISDNobject_t *obj) {
|
|||
|
||||
static void
|
||||
get_free_instid(mISDNstack_t *st, mISDNinstance_t *inst) {
|
||||
mISDNinstance_t *il = mISDN_instlist;
|
||||
mISDNinstance_t *il;
|
||||
|
||||
inst->id = mISDN_get_lowlayer(inst->pid.layermask)<<20;
|
||||
inst->id |= FLG_INSTANCE;
|
||||
if (st) {
|
||||
inst->id |= st->id;
|
||||
} else {
|
||||
while(il) {
|
||||
list_for_each_entry(il, &mISDN_instlist, list) {
|
||||
if (il->id == inst->id) {
|
||||
if ((inst->id & IF_INSTMASK) >= INST_ID_MAX) {
|
||||
inst->id = 0;
|
||||
return;
|
||||
}
|
||||
inst->id += INST_ID_INC;
|
||||
il = mISDN_instlist;
|
||||
continue;
|
||||
il = list_entry(mISDN_instlist.next, mISDNinstance_t, list);
|
||||
}
|
||||
il = il->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -515,7 +484,7 @@ register_layer(mISDNstack_t *st, mISDNinstance_t *inst) {
|
|||
if (!inst->id) {
|
||||
int_errtxt("no free inst->id for layer %x", inst->pid.layermask);
|
||||
if (st && layer) {
|
||||
REMOVE_FROM_LISTBASE(layer, st->lstack);
|
||||
list_del(&layer->list);
|
||||
kfree(layer);
|
||||
}
|
||||
return(-EINVAL);
|
||||
|
@ -523,7 +492,7 @@ register_layer(mISDNstack_t *st, mISDNinstance_t *inst) {
|
|||
inst->st = st;
|
||||
if (refinc)
|
||||
inst->obj->refcnt++;
|
||||
APPEND_TO_LIST(inst, mISDN_instlist);
|
||||
list_add_tail(&inst->list, &mISDN_instlist);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -550,12 +519,12 @@ unregister_instance(mISDNinstance_t *inst) {
|
|||
if (inst->st && (inst->st->mgr != inst))
|
||||
inst->st = NULL;
|
||||
}
|
||||
REMOVE_FROM_LISTBASE(inst, mISDN_instlist);
|
||||
inst->prev = inst->next = NULL;
|
||||
list_del_init(&inst->list);
|
||||
inst->id = 0;
|
||||
inst->obj->refcnt--;
|
||||
if (core_debug & DEBUG_CORE_FUNC)
|
||||
printk(KERN_DEBUG "%s: mISDN_instlist(%p)\n", __FUNCTION__, mISDN_instlist);
|
||||
printk(KERN_DEBUG "%s: mISDN_instlist(%p<-%p->%p)\n", __FUNCTION__,
|
||||
mISDN_instlist.prev, &mISDN_instlist, mISDN_instlist.next);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -588,7 +557,7 @@ set_stack(mISDNstack_t *st, mISDN_pid_t *pid)
|
|||
int err;
|
||||
u_char *pbuf = NULL;
|
||||
mISDNinstance_t *inst;
|
||||
mISDNlayer_t *hl;
|
||||
mISDNlayer_t *hl, *hln;
|
||||
|
||||
if (!st || !pid) {
|
||||
int_error();
|
||||
|
@ -624,8 +593,10 @@ set_stack(mISDNstack_t *st, mISDN_pid_t *pid)
|
|||
}
|
||||
mISDN_RemoveUsedPID(pid, &inst->pid);
|
||||
}
|
||||
hl = st->lstack;
|
||||
while(hl && hl->next) {
|
||||
|
||||
list_for_each_entry_safe(hl, hln, &st->layerlist, list) {
|
||||
if (hl->list.next == &st->layerlist)
|
||||
break;
|
||||
if (!hl->inst) {
|
||||
int_error();
|
||||
return(-EINVAL);
|
||||
|
@ -639,8 +610,7 @@ set_stack(mISDNstack_t *st, mISDN_pid_t *pid)
|
|||
return(-EINVAL);
|
||||
}
|
||||
hl->inst->obj->own_ctrl(hl->inst, MGR_CONNECT | REQUEST,
|
||||
hl->next->inst);
|
||||
hl = hl->next;
|
||||
hln->inst);
|
||||
}
|
||||
st->mgr->obj->own_ctrl(st->mgr, MGR_SETSTACK |CONFIRM, NULL);
|
||||
return(0);
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <linux/vmalloc.h>
|
||||
#include <linux/config.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/list.h>
|
||||
#include "core.h"
|
||||
|
||||
#define MAX_HEADER_LEN 4
|
||||
|
@ -23,8 +22,7 @@
|
|||
|
||||
|
||||
typedef struct _devicelayer {
|
||||
struct _devicelayer *prev;
|
||||
struct _devicelayer *next;
|
||||
struct list_head list;
|
||||
mISDNdevice_t *dev;
|
||||
mISDNinstance_t inst;
|
||||
mISDNinstance_t *slave;
|
||||
|
@ -36,16 +34,14 @@ typedef struct _devicelayer {
|
|||
} devicelayer_t;
|
||||
|
||||
typedef struct _devicestack {
|
||||
struct _devicestack *prev;
|
||||
struct _devicestack *next;
|
||||
struct list_head list;
|
||||
mISDNdevice_t *dev;
|
||||
mISDNstack_t *st;
|
||||
int extentions;
|
||||
} devicestack_t;
|
||||
|
||||
typedef struct _mISDNtimer {
|
||||
struct _mISDNtimer *prev;
|
||||
struct _mISDNtimer *next;
|
||||
struct list_head list;
|
||||
struct _mISDNdevice *dev;
|
||||
struct timer_list tl;
|
||||
int id;
|
||||
|
@ -57,7 +53,7 @@ typedef struct entity_item {
|
|||
int entity;
|
||||
} entity_item_t;
|
||||
|
||||
static mISDNdevice_t *mISDN_devicelist = NULL;
|
||||
static LIST_HEAD(mISDN_devicelist);
|
||||
static rwlock_t mISDN_device_lock = RW_LOCK_UNLOCKED;
|
||||
|
||||
static mISDNobject_t udev_obj;
|
||||
|
@ -76,14 +72,17 @@ static int mISDN_wdata(mISDNdevice_t *dev);
|
|||
static mISDNdevice_t *
|
||||
get_mISDNdevice4minor(int minor)
|
||||
{
|
||||
mISDNdevice_t *dev = mISDN_devicelist;
|
||||
mISDNdevice_t *dev;
|
||||
|
||||
while(dev) {
|
||||
if (dev->minor == minor)
|
||||
break;
|
||||
dev = dev->next;
|
||||
read_lock(&mISDN_device_lock);
|
||||
list_for_each_entry(dev, &mISDN_devicelist, list) {
|
||||
if (dev->minor == minor) {
|
||||
read_unlock(&mISDN_device_lock);
|
||||
return(dev);
|
||||
}
|
||||
}
|
||||
return(dev);
|
||||
read_unlock(&mISDN_device_lock);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
|
@ -252,69 +251,65 @@ mISDN_rdata(mISDNdevice_t *dev, iframe_t *iff, int use_value) {
|
|||
}
|
||||
|
||||
static devicelayer_t
|
||||
*get_devlayer(mISDNdevice_t *dev, int addr) {
|
||||
devicelayer_t *dl = dev->layer;
|
||||
*get_devlayer(mISDNdevice_t *dev, int addr) {
|
||||
devicelayer_t *dl;
|
||||
|
||||
if (device_debug & DEBUG_MGR_FUNC)
|
||||
printk(KERN_DEBUG "%s: addr:%x\n", __FUNCTION__, addr);
|
||||
while(dl) {
|
||||
list_for_each_entry(dl, &dev->layerlist, list) {
|
||||
// if (device_debug & DEBUG_MGR_FUNC)
|
||||
// printk(KERN_DEBUG "%s: dl(%p) iaddr:%x\n",
|
||||
// __FUNCTION__, dl, dl->iaddr);
|
||||
if ((u_int)dl->iaddr == (IF_IADDRMASK & addr))
|
||||
break;
|
||||
dl = dl->next;
|
||||
return(dl);
|
||||
}
|
||||
return(dl);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
static devicestack_t
|
||||
*get_devstack(mISDNdevice_t *dev, int addr)
|
||||
{
|
||||
devicestack_t *ds = dev->stack;
|
||||
devicestack_t *ds;
|
||||
|
||||
if (device_debug & DEBUG_MGR_FUNC)
|
||||
printk(KERN_DEBUG "%s: addr:%x\n", __FUNCTION__, addr);
|
||||
while(ds) {
|
||||
list_for_each_entry(ds, &dev->stacklist, list) {
|
||||
if (ds->st && (ds->st->id == (u_int)addr))
|
||||
break;
|
||||
ds = ds->next;
|
||||
return(ds);
|
||||
}
|
||||
return(ds);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
static mISDNtimer_t
|
||||
*get_devtimer(mISDNdevice_t *dev, int id)
|
||||
*get_devtimer(mISDNdevice_t *dev, int id)
|
||||
{
|
||||
mISDNtimer_t *ht = dev->timer;
|
||||
mISDNtimer_t *ht;
|
||||
|
||||
if (device_debug & DEBUG_DEV_TIMER)
|
||||
printk(KERN_DEBUG "%s: dev:%p id:%x\n", __FUNCTION__, dev, id);
|
||||
while(ht) {
|
||||
list_for_each_entry(ht, &dev->timerlist, list) {
|
||||
if (ht->id == id)
|
||||
break;
|
||||
ht = ht->next;
|
||||
return(ht);
|
||||
}
|
||||
return(ht);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
stack_inst_flg(mISDNdevice_t *dev, mISDNstack_t *st, int bit, int clear)
|
||||
{
|
||||
int ret = -1;
|
||||
devicelayer_t *dl = dev->layer;
|
||||
int ret;
|
||||
devicelayer_t *dl;
|
||||
|
||||
while(dl) {
|
||||
list_for_each_entry(dl, &dev->layerlist, list) {
|
||||
if (dl->inst.st == st) {
|
||||
if (clear)
|
||||
ret = test_and_clear_bit(bit, &dl->Flags);
|
||||
else
|
||||
ret = test_and_set_bit(bit, &dl->Flags);
|
||||
break;
|
||||
return(ret);
|
||||
}
|
||||
dl = dl->next;
|
||||
}
|
||||
return(ret);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -349,7 +344,8 @@ new_devstack(mISDNdevice_t *dev, stack_info_t *si)
|
|||
nds->dev = dev;
|
||||
if (si->extentions & EXT_STACK_CLONE) {
|
||||
// memcpy(&inst.st->pid, &st->pid, sizeof(mISDN_pid_t));
|
||||
inst.st->child = st->child;
|
||||
// FIXME that is a ugly idea, but I don't have a better one
|
||||
inst.st->childlist.prev = &st->childlist;
|
||||
} else {
|
||||
memcpy(&inst.st->pid, &si->pid, sizeof(mISDN_pid_t));
|
||||
}
|
||||
|
@ -357,7 +353,7 @@ new_devstack(mISDNdevice_t *dev, stack_info_t *si)
|
|||
inst.st->extentions |= si->extentions;
|
||||
inst.st->mgr = get_instance4id(si->mgr);
|
||||
nds->st = inst.st;
|
||||
APPEND_TO_LIST(nds, dev->stack);
|
||||
list_add_tail(&nds->list, &dev->stacklist);
|
||||
return(inst.st->id);
|
||||
}
|
||||
|
||||
|
@ -453,7 +449,7 @@ create_layer(mISDNdevice_t *dev, layer_info_t *linfo, int *adr)
|
|||
nl->inst.up.owner = &nl->inst;
|
||||
nl->inst.obj = &udev_obj;
|
||||
nl->inst.data = nl;
|
||||
APPEND_TO_LIST(nl, dev->layer);
|
||||
list_add_tail(&nl->list, &dev->layerlist);
|
||||
nl->inst.obj->ctrl(st, MGR_REGLAYER | INDICATION, &nl->inst);
|
||||
nl->iaddr = nl->inst.id;
|
||||
*adr++ = nl->iaddr;
|
||||
|
@ -492,7 +488,10 @@ remove_if(devicelayer_t *dl, int stat) {
|
|||
memcpy(phif, shif, sizeof(mISDNif_t));
|
||||
memset(shif, 0, sizeof(mISDNif_t));
|
||||
}
|
||||
REMOVE_FROM_LIST(hif);
|
||||
if (hif->predecessor)
|
||||
hif->predecessor->clone = hif->clone;
|
||||
if (hif->clone)
|
||||
hif->clone->predecessor = hif->predecessor;
|
||||
return(err);
|
||||
}
|
||||
|
||||
|
@ -514,10 +513,10 @@ del_stack(devicestack_t *ds)
|
|||
return(-EINVAL);
|
||||
if (ds->st) {
|
||||
if (ds->extentions & EXT_STACK_CLONE)
|
||||
ds->st->child = NULL;
|
||||
INIT_LIST_HEAD(&ds->st->childlist);
|
||||
udev_obj.ctrl(ds->st, MGR_DELSTACK | REQUEST, NULL);
|
||||
}
|
||||
REMOVE_FROM_LISTBASE(ds, dev->stack);
|
||||
list_del(&ds->list);
|
||||
kfree(ds);
|
||||
return(0);
|
||||
}
|
||||
|
@ -529,8 +528,8 @@ del_layer(devicelayer_t *dl) {
|
|||
int i;
|
||||
|
||||
if (device_debug & DEBUG_MGR_FUNC) {
|
||||
printk(KERN_DEBUG "%s: dl(%p) inst(%p) LM(%x) dev(%p) nexti(%p)\n",
|
||||
__FUNCTION__, dl, inst, inst->pid.layermask, dev, inst->next);
|
||||
printk(KERN_DEBUG "%s: dl(%p) inst(%p) LM(%x) dev(%p)\n",
|
||||
__FUNCTION__, dl, inst, inst->pid.layermask, dev);
|
||||
printk(KERN_DEBUG "%s: iaddr %x inst %s slave %p\n",
|
||||
__FUNCTION__, dl->iaddr, inst->name, dl->slave);
|
||||
}
|
||||
|
@ -566,7 +565,7 @@ del_layer(devicelayer_t *dl) {
|
|||
MGR_DISCONNECT | REQUEST, &inst->down);
|
||||
}
|
||||
dl->iaddr = 0;
|
||||
REMOVE_FROM_LISTBASE(dl, dev->layer);
|
||||
list_del(&dl->list);
|
||||
udev_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
|
||||
if (test_and_clear_bit(FLG_MGR_OWNSTACK, &dl->Flags)) {
|
||||
if (dl->inst.st) {
|
||||
|
@ -859,14 +858,12 @@ dev_init_timer(mISDNdevice_t *dev, iframe_t *iff)
|
|||
ht = kmalloc(sizeof(mISDNtimer_t), GFP_ATOMIC);
|
||||
if (!ht)
|
||||
return(-ENOMEM);
|
||||
ht->prev = NULL;
|
||||
ht->next = NULL;
|
||||
ht->dev = dev;
|
||||
ht->id = iff->addr;
|
||||
ht->tl.data = (long) ht;
|
||||
ht->tl.function = (void *) dev_expire_timer;
|
||||
init_timer(&ht->tl);
|
||||
APPEND_TO_LIST(ht, dev->timer);
|
||||
list_add_tail(&ht->list, &dev->timerlist);
|
||||
if (device_debug & DEBUG_DEV_TIMER)
|
||||
printk(KERN_DEBUG "%s: new(%x)\n", __FUNCTION__, ht->id);
|
||||
} else if (device_debug & DEBUG_DEV_TIMER)
|
||||
|
@ -933,6 +930,16 @@ dev_del_timer(mISDNdevice_t *dev, iframe_t *iff)
|
|||
return(0);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_free_timer(mISDNtimer_t *ht)
|
||||
{
|
||||
if (device_debug & DEBUG_DEV_TIMER)
|
||||
printk(KERN_DEBUG "%s: timer(%x)\n", __FUNCTION__, ht->id);
|
||||
del_timer(&ht->tl);
|
||||
list_del(&ht->list);
|
||||
kfree(ht);
|
||||
}
|
||||
|
||||
static int
|
||||
dev_remove_timer(mISDNdevice_t *dev, int id)
|
||||
{
|
||||
|
@ -943,11 +950,7 @@ dev_remove_timer(mISDNdevice_t *dev, int id)
|
|||
printk(KERN_WARNING "%s: no timer(%x)\n", __FUNCTION__, id);
|
||||
return(-ENODEV);
|
||||
}
|
||||
if (device_debug & DEBUG_DEV_TIMER)
|
||||
printk(KERN_DEBUG "%s: timer(%x)\n", __FUNCTION__, ht->id);
|
||||
del_timer(&ht->tl);
|
||||
REMOVE_FROM_LISTBASE(ht, dev->timer);
|
||||
kfree(ht);
|
||||
dev_free_timer(ht);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -1532,9 +1535,12 @@ init_device(u_int minor) {
|
|||
init_waitqueue_head(&dev->rport.procq);
|
||||
init_waitqueue_head(&dev->wport.procq);
|
||||
init_MUTEX(&dev->io_sema);
|
||||
INIT_LIST_HEAD(&dev->layerlist);
|
||||
INIT_LIST_HEAD(&dev->stacklist);
|
||||
INIT_LIST_HEAD(&dev->timerlist);
|
||||
INIT_LIST_HEAD(&dev->entitylist);
|
||||
write_lock_irqsave(&mISDN_device_lock, flags);
|
||||
APPEND_TO_LIST(dev, mISDN_devicelist);
|
||||
list_add_tail(&dev->list, &mISDN_devicelist);
|
||||
write_unlock_irqrestore(&mISDN_device_lock, flags);
|
||||
}
|
||||
return(dev);
|
||||
|
@ -1568,6 +1574,7 @@ get_free_rawdevice(void)
|
|||
int
|
||||
free_device(mISDNdevice_t *dev)
|
||||
{
|
||||
struct list_head *item, *ni;
|
||||
u_long flags;
|
||||
|
||||
if (!dev)
|
||||
|
@ -1575,25 +1582,24 @@ free_device(mISDNdevice_t *dev)
|
|||
if (device_debug & DEBUG_MGR_FUNC)
|
||||
printk(KERN_DEBUG "%s: dev(%d)\n", __FUNCTION__, dev->minor);
|
||||
/* release related stuff */
|
||||
while(dev->layer)
|
||||
del_layer(dev->layer);
|
||||
while(dev->stack)
|
||||
del_stack(dev->stack);
|
||||
while(dev->timer)
|
||||
dev_remove_timer(dev, dev->timer->id);
|
||||
list_for_each_safe(item, ni, &dev->layerlist)
|
||||
del_layer(list_entry(item, devicelayer_t, list));
|
||||
list_for_each_safe(item, ni, &dev->stacklist)
|
||||
del_stack(list_entry(item, devicestack_t, list));
|
||||
list_for_each_safe(item, ni, &dev->timerlist)
|
||||
dev_free_timer(list_entry(item, mISDNtimer_t, list));
|
||||
if (dev->rport.buf)
|
||||
vfree(dev->rport.buf);
|
||||
if (dev->wport.buf)
|
||||
vfree(dev->wport.buf);
|
||||
write_lock_irqsave(&mISDN_device_lock, flags);
|
||||
REMOVE_FROM_LISTBASE(dev, mISDN_devicelist);
|
||||
list_del(&dev->list);
|
||||
write_unlock_irqrestore(&mISDN_device_lock, flags);
|
||||
if (!list_empty(&dev->entitylist)) {
|
||||
printk(KERN_WARNING "MISDN %s: entitylist not empty\n", __FUNCTION__);
|
||||
while(!list_empty(&dev->entitylist)) {
|
||||
struct entity_item *ei;
|
||||
ei = (struct entity_item *)dev->entitylist.next;
|
||||
list_del((struct list_head *)ei);
|
||||
list_for_each_safe(item, ni, &dev->entitylist) {
|
||||
struct entity_item *ei = list_entry(item, struct entity_item, head);
|
||||
list_del(item);
|
||||
mISDN_delete_entity(ei->entity);
|
||||
kfree(ei);
|
||||
}
|
||||
|
@ -1631,7 +1637,7 @@ mISDN_open(struct inode *ino, struct file *filep)
|
|||
if (!dev->rport.buf) {
|
||||
if (isnew) {
|
||||
write_lock_irqsave(&mISDN_device_lock, flags);
|
||||
REMOVE_FROM_LISTBASE(dev, mISDN_devicelist);
|
||||
list_del(&dev->list);
|
||||
write_unlock_irqrestore(&mISDN_device_lock, flags);
|
||||
kfree(dev);
|
||||
}
|
||||
|
@ -1652,7 +1658,7 @@ mISDN_open(struct inode *ino, struct file *filep)
|
|||
if (dev->rport.buf)
|
||||
vfree(dev->rport.buf);
|
||||
write_lock_irqsave(&mISDN_device_lock, flags);
|
||||
REMOVE_FROM_LISTBASE(dev, mISDN_devicelist);
|
||||
list_del(&dev->list);
|
||||
write_unlock_irqrestore(&mISDN_device_lock, flags);
|
||||
kfree(dev);
|
||||
}
|
||||
|
@ -1674,12 +1680,12 @@ mISDN_open(struct inode *ino, struct file *filep)
|
|||
static int
|
||||
mISDN_close(struct inode *ino, struct file *filep)
|
||||
{
|
||||
mISDNdevice_t *dev = mISDN_devicelist;
|
||||
mISDNdevice_t *dev, *nd;
|
||||
|
||||
if (device_debug & DEBUG_DEV_OP)
|
||||
printk(KERN_DEBUG "mISDN: mISDN_close %p %p\n", filep, filep->private_data);
|
||||
read_lock(&mISDN_device_lock);
|
||||
while (dev) {
|
||||
list_for_each_entry_safe(dev, nd, &mISDN_devicelist, list) {
|
||||
if (dev == filep->private_data) {
|
||||
if (device_debug & DEBUG_DEV_OP)
|
||||
printk(KERN_DEBUG "mISDN: dev(%d) %p mode %x/%x\n",
|
||||
|
@ -1699,7 +1705,6 @@ mISDN_close(struct inode *ino, struct file *filep)
|
|||
free_device(dev);
|
||||
return 0;
|
||||
}
|
||||
dev = dev->next;
|
||||
}
|
||||
read_unlock(&mISDN_device_lock);
|
||||
printk(KERN_WARNING "mISDN: No private data while closing device\n");
|
||||
|
@ -1941,9 +1946,9 @@ set_if(devicelayer_t *dl, u_int prim, mISDNif_t *hif)
|
|||
static int
|
||||
udev_manager(void *data, u_int prim, void *arg) {
|
||||
mISDNinstance_t *inst = data;
|
||||
mISDNdevice_t *dev = mISDN_devicelist;
|
||||
devicelayer_t *dl = NULL;
|
||||
int err = -EINVAL;
|
||||
mISDNdevice_t *dev;
|
||||
devicelayer_t *dl;
|
||||
int err = -EINVAL;
|
||||
|
||||
if (device_debug & DEBUG_MGR_FUNC)
|
||||
printk(KERN_DEBUG "udev_manager data:%p prim:%x arg:%p\n",
|
||||
|
@ -1951,18 +1956,17 @@ udev_manager(void *data, u_int prim, void *arg) {
|
|||
if (!data)
|
||||
return(-EINVAL);
|
||||
read_lock(&mISDN_device_lock);
|
||||
while(dev) {
|
||||
dl = dev->layer;
|
||||
while(dl) {
|
||||
if (&dl->inst == inst)
|
||||
list_for_each_entry(dev, &mISDN_devicelist, list) {
|
||||
list_for_each_entry(dl, &dev->layerlist, list) {
|
||||
if (&dl->inst == inst) {
|
||||
err = 0;
|
||||
break;
|
||||
dl = dl->next;
|
||||
}
|
||||
}
|
||||
if (dl)
|
||||
if (!err)
|
||||
break;
|
||||
dev = dev->next;
|
||||
}
|
||||
if (!dl) {
|
||||
if (err) {
|
||||
printk(KERN_WARNING "dev_manager prim %x without device layer\n", prim);
|
||||
goto out;
|
||||
}
|
||||
|
@ -1987,6 +1991,7 @@ udev_manager(void *data, u_int prim, void *arg) {
|
|||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "dev_manager prim %x not handled\n", prim);
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
out:
|
||||
|
@ -2002,9 +2007,8 @@ int init_mISDNdev (int debug) {
|
|||
udev_obj.DPROTO.protocol[i] = ISDN_PID_ANY;
|
||||
udev_obj.BPROTO.protocol[i] = ISDN_PID_ANY;
|
||||
}
|
||||
INIT_LIST_HEAD(&udev_obj.ilist);
|
||||
udev_obj.own_ctrl = udev_manager;
|
||||
udev_obj.prev = NULL;
|
||||
udev_obj.next = NULL;
|
||||
device_debug = debug;
|
||||
if (register_chrdev(mISDN_MAJOR, "mISDN", &mISDN_fops)) {
|
||||
printk(KERN_WARNING "mISDN: Could not register devices\n");
|
||||
|
@ -2018,13 +2022,12 @@ int init_mISDNdev (int debug) {
|
|||
|
||||
int free_mISDNdev(void) {
|
||||
int err = 0;
|
||||
mISDNdevice_t *dev = mISDN_devicelist;
|
||||
mISDNdevice_t *dev, *nd;
|
||||
|
||||
if (mISDN_devicelist) {
|
||||
if (!list_empty(&mISDN_devicelist)) {
|
||||
printk(KERN_WARNING "mISDN: devices open on remove\n");
|
||||
while (dev) {
|
||||
list_for_each_entry_safe(dev, nd, &mISDN_devicelist, list) {
|
||||
free_device(dev);
|
||||
dev = mISDN_devicelist;
|
||||
}
|
||||
err = -EBUSY;
|
||||
}
|
||||
|
|
|
@ -51,8 +51,7 @@ typedef struct _w6692_bc {
|
|||
} w6692_bc;
|
||||
|
||||
typedef struct _w6692pci {
|
||||
struct _w6692pci *prev;
|
||||
struct _w6692pci *next;
|
||||
struct list_head list;
|
||||
void *pdev;
|
||||
u_int irq;
|
||||
u_int irqcnt;
|
||||
|
@ -165,7 +164,7 @@ W6692_new_ph(dchannel_t *dch)
|
|||
para = HW_RESET;
|
||||
while(upif) {
|
||||
if_link(upif, prim, para, 0, NULL, 0);
|
||||
upif = upif->next;
|
||||
upif = upif->clone;
|
||||
}
|
||||
upif = &dch->inst.up;
|
||||
/* fall trough */
|
||||
|
@ -198,7 +197,7 @@ W6692_new_ph(dchannel_t *dch)
|
|||
}
|
||||
while(upif) {
|
||||
if_link(upif, prim, para, 0, NULL, 0);
|
||||
upif = upif->next;
|
||||
upif = upif->clone;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1278,7 +1277,7 @@ release_card(w6692pci *card)
|
|||
mISDN_free_dch(&card->dch);
|
||||
w6692.ctrl(card->dch.inst.up.peer, MGR_DISCONNECT | REQUEST, &card->dch.inst.up);
|
||||
w6692.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
|
||||
REMOVE_FROM_LISTBASE(card, ((w6692pci *)w6692.ilist));
|
||||
list_del(&card->list);
|
||||
unlock_dev(card);
|
||||
pci_disable_device(card->pdev);
|
||||
pci_set_drvdata(card->pdev, NULL);
|
||||
|
@ -1287,7 +1286,7 @@ release_card(w6692pci *card)
|
|||
|
||||
static int
|
||||
w6692_manager(void *data, u_int prim, void *arg) {
|
||||
w6692pci *card = w6692.ilist;
|
||||
w6692pci *card;
|
||||
mISDNinstance_t *inst = data;
|
||||
struct sk_buff *skb;
|
||||
int channel = -1;
|
||||
|
@ -1301,7 +1300,7 @@ w6692_manager(void *data, u_int prim, void *arg) {
|
|||
__FUNCTION__, prim, arg);
|
||||
return(-EINVAL);
|
||||
}
|
||||
while(card) {
|
||||
list_for_each_entry(card, &w6692.ilist, list) {
|
||||
if (&card->dch.inst == inst) {
|
||||
channel = 2;
|
||||
break;
|
||||
|
@ -1314,7 +1313,6 @@ w6692_manager(void *data, u_int prim, void *arg) {
|
|||
channel = 1;
|
||||
break;
|
||||
}
|
||||
card = card->next;
|
||||
}
|
||||
if (channel<0) {
|
||||
printk(KERN_WARNING "%s: no channel data %p prim %x arg %p\n",
|
||||
|
@ -1420,7 +1418,7 @@ static int __devinit setup_instance(w6692pci *card)
|
|||
int i, err;
|
||||
mISDN_pid_t pid;
|
||||
|
||||
APPEND_TO_LIST(card, ((w6692pci *)w6692.ilist));
|
||||
list_add_tail(&card->list, &w6692.ilist);
|
||||
card->dch.debug = debug;
|
||||
lock_HW_init(&card->lock);
|
||||
card->dch.inst.lock = lock_dev;
|
||||
|
@ -1451,7 +1449,7 @@ static int __devinit setup_instance(w6692pci *card)
|
|||
mISDN_free_dch(&card->dch);
|
||||
mISDN_free_bch(&card->bch[1]);
|
||||
mISDN_free_bch(&card->bch[0]);
|
||||
REMOVE_FROM_LISTBASE(card, ((w6692pci *)w6692.ilist));
|
||||
list_del(&card->list);
|
||||
kfree(card);
|
||||
return(err);
|
||||
}
|
||||
|
@ -1567,14 +1565,13 @@ static int __init w6692_init(void)
|
|||
#ifdef MODULE
|
||||
w6692.owner = THIS_MODULE;
|
||||
#endif
|
||||
INIT_LIST_HEAD(&w6692.ilist);
|
||||
w6692.name = W6692Name;
|
||||
w6692.own_ctrl = w6692_manager;
|
||||
w6692.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0;
|
||||
w6692.BPROTO.protocol[1] = ISDN_PID_L1_B_64TRANS |
|
||||
ISDN_PID_L1_B_64HDLC;
|
||||
w6692.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANS;
|
||||
w6692.prev = NULL;
|
||||
w6692.next = NULL;
|
||||
if ((err = mISDN_register(&w6692))) {
|
||||
printk(KERN_ERR "Can't register Winbond W6692 PCI error(%d)\n", err);
|
||||
return(err);
|
||||
|
@ -1597,15 +1594,16 @@ static int __init w6692_init(void)
|
|||
|
||||
static void __exit w6692_cleanup(void)
|
||||
{
|
||||
int err;
|
||||
int err;
|
||||
w6692pci *card, *next;
|
||||
|
||||
if ((err = mISDN_unregister(&w6692))) {
|
||||
printk(KERN_ERR "Can't unregister Winbond W6692 PCI error(%d)\n", err);
|
||||
}
|
||||
while(w6692.ilist) {
|
||||
list_for_each_entry_safe(card, next, &w6692.ilist, list) {
|
||||
printk(KERN_ERR "Winbond W6692 PCI card struct not empty refs %d\n",
|
||||
w6692.refcnt);
|
||||
release_card(w6692.ilist);
|
||||
release_card(card);
|
||||
}
|
||||
pci_unregister_driver(&w6692_driver);
|
||||
}
|
||||
|
|
|
@ -1248,22 +1248,24 @@ MODULE_LICENSE("GPL");
|
|||
static int
|
||||
dte_manager(void *data, u_int prim, void *arg) {
|
||||
mISDNinstance_t *inst = data;
|
||||
x25_l3_t *l3_l = x25dte_obj.ilist;
|
||||
x25_l3_t *l3_l;
|
||||
int err = -EINVAL;
|
||||
|
||||
if (debug & DEBUG_L3X25_MGR)
|
||||
printk(KERN_DEBUG "l3x25_manager data:%p prim:%x arg:%p\n", data, prim, arg);
|
||||
if (!data)
|
||||
return(-EINVAL);
|
||||
while(l3_l) {
|
||||
if (&l3_l->inst == inst)
|
||||
return(err);
|
||||
list_for_each_entry(l3_l, &x25dte_obj.ilist, list) {
|
||||
if (&l3_l->inst == inst) {
|
||||
err = 0;
|
||||
break;
|
||||
l3_l = l3_l->next;
|
||||
}
|
||||
}
|
||||
if (prim == (MGR_NEWLAYER | REQUEST))
|
||||
return(new_l3(data, arg));
|
||||
if (!l3_l) {
|
||||
if (err) {
|
||||
printk(KERN_WARNING "l3x25_manager prim(%x) no instance\n", prim);
|
||||
return(-EINVAL);
|
||||
return(err);
|
||||
}
|
||||
switch(prim) {
|
||||
case MGR_NEWENTITY | CONFIRM:
|
||||
|
@ -1320,9 +1322,7 @@ x25_dte_init(void)
|
|||
x25dte_obj.name = MName;
|
||||
x25dte_obj.BPROTO.protocol[3] = ISDN_PID_L3_B_X25DTE;
|
||||
x25dte_obj.own_ctrl = dte_manager;
|
||||
x25dte_obj.prev = NULL;
|
||||
x25dte_obj.next = NULL;
|
||||
x25dte_obj.ilist = NULL;
|
||||
INIT_LIST_HEAD(&x25dte_obj.ilist);
|
||||
if ((err = mISDN_register(&x25dte_obj))) {
|
||||
printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
|
||||
} else {
|
||||
|
@ -1349,15 +1349,16 @@ x25_dte_init(void)
|
|||
static void
|
||||
x25_dte_cleanup(void)
|
||||
{
|
||||
int err;
|
||||
x25_l3_t *l3, *nl3;
|
||||
int err;
|
||||
|
||||
if ((err = mISDN_unregister(&x25dte_obj))) {
|
||||
printk(KERN_ERR "Can't unregister l3x25 error(%d)\n", err);
|
||||
}
|
||||
if(x25dte_obj.ilist) {
|
||||
if(!list_empty(&x25dte_obj.ilist)) {
|
||||
printk(KERN_WARNING "l3x25 inst list not empty\n");
|
||||
while(x25dte_obj.ilist)
|
||||
X25_release_l3(x25dte_obj.ilist);
|
||||
list_for_each_entry_safe(l3, nl3, &x25dte_obj.ilist, list)
|
||||
X25_release_l3(l3);
|
||||
}
|
||||
X25_l3_cleanup();
|
||||
mISDN_FsmFree(&dte_rfsm);
|
||||
|
|
|
@ -273,13 +273,12 @@ X25_reset_channel(x25_channel_t *l3c, struct sk_buff *skb)
|
|||
int
|
||||
X25_restart(x25_l3_t *l3)
|
||||
{
|
||||
x25_channel_t *l3c = l3->channels;
|
||||
x25_channel_t *l3c;
|
||||
|
||||
while(l3c) {
|
||||
list_for_each_entry(l3c, &l3->channellist, list) {
|
||||
memcpy(l3c->cause, l3->cause, 2);
|
||||
X25_reset_channel(l3c, NULL);
|
||||
mISDN_FsmEvent(&l3c->x25p, EV_L3_READY, NULL);
|
||||
l3c = l3c->next;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
@ -539,9 +538,7 @@ X25_get_and_test_ps(x25_channel_t *chan, u_char ptype, struct sk_buff *skb)
|
|||
void
|
||||
X25_release_channel(x25_channel_t *l3c)
|
||||
{
|
||||
x25_l3_t *l3 = l3c->l3;
|
||||
|
||||
REMOVE_FROM_LISTBASE(l3c, l3->channels);
|
||||
list_del(&l3c->list);
|
||||
if (l3c->ncpi_data)
|
||||
kfree(l3c->ncpi_data);
|
||||
l3c->ncpi_data = NULL;
|
||||
|
@ -561,6 +558,7 @@ X25_release_channel(x25_channel_t *l3c)
|
|||
void
|
||||
X25_release_l3(x25_l3_t *l3) {
|
||||
mISDNinstance_t *inst = &l3->inst;
|
||||
x25_channel_t *ch, *nch;
|
||||
|
||||
if (inst->up.peer) {
|
||||
inst->up.peer->obj->ctrl(inst->up.peer,
|
||||
|
@ -571,11 +569,11 @@ X25_release_l3(x25_l3_t *l3) {
|
|||
MGR_DISCONNECT | REQUEST, &inst->down);
|
||||
}
|
||||
if (inst->obj) {
|
||||
REMOVE_FROM_LISTBASE(l3, ((x25_l3_t *)inst->obj->ilist));
|
||||
list_del_init(&l3->list);
|
||||
}
|
||||
discard_queue(&l3->downq);
|
||||
while(l3->channels)
|
||||
X25_release_channel(l3->channels);
|
||||
list_for_each_entry_safe(ch, nch, &l3->channellist, list)
|
||||
X25_release_channel(ch);
|
||||
mISDN_FsmDelTimer(&l3->TR, 3);
|
||||
if (inst->obj) {
|
||||
if (l3->entity != MISDN_ENTITY_NONE)
|
||||
|
@ -654,7 +652,7 @@ new_x25_channel(x25_l3_t *l3, x25_channel_t **ch_p, __u16 ch, int dlen, u_char *
|
|||
mISDN_FsmInitTimer(&l3c->x25d, &l3c->TD);
|
||||
skb_queue_head_init(&l3c->dataq);
|
||||
|
||||
APPEND_TO_LIST(l3c, l3->channels);
|
||||
list_add_tail(&l3c->list, &l3->channellist);
|
||||
*ch_p = l3c;
|
||||
return(0);
|
||||
}
|
||||
|
@ -671,6 +669,7 @@ new_x25_l3(x25_l3_t **l3_p, mISDNstack_t *st, mISDN_pid_t *pid, mISDNobject_t *o
|
|||
return(-ENOMEM);
|
||||
}
|
||||
memset(n_l3, 0, sizeof(x25_l3_t));
|
||||
INIT_LIST_HEAD(&n_l3->channellist);
|
||||
n_l3->entity = MISDN_ENTITY_NONE;
|
||||
n_l3->next_id = 1;
|
||||
spin_lock_init(&n_l3->lock);
|
||||
|
@ -706,7 +705,7 @@ new_x25_l3(x25_l3_t **l3_p, mISDNstack_t *st, mISDN_pid_t *pid, mISDNobject_t *o
|
|||
mISDN_FsmInitTimer(&n_l3->x25r, &n_l3->TR);
|
||||
skb_queue_head_init(&n_l3->downq);
|
||||
|
||||
APPEND_TO_LIST(n_l3, ((x25_l3_t *)obj->ilist));
|
||||
list_add_tail(&n_l3->list, &obj->ilist);
|
||||
err = obj->ctrl(&n_l3->inst, MGR_NEWENTITY | REQUEST, NULL);
|
||||
if (err) {
|
||||
printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%x)\n",
|
||||
|
@ -714,7 +713,7 @@ new_x25_l3(x25_l3_t **l3_p, mISDNstack_t *st, mISDN_pid_t *pid, mISDNobject_t *o
|
|||
}
|
||||
err = obj->ctrl(st, MGR_REGLAYER | INDICATION, &n_l3->inst);
|
||||
if (err) {
|
||||
REMOVE_FROM_LISTBASE(n_l3, ((x25_l3_t *)obj->ilist));
|
||||
list_del(&n_l3->list);
|
||||
kfree(n_l3);
|
||||
n_l3 = NULL;
|
||||
} else {
|
||||
|
@ -923,27 +922,25 @@ X25_send_diagnostic(x25_l3_t *l3, struct sk_buff *skb, int err, int channel)
|
|||
x25_channel_t *
|
||||
X25_get_channel(x25_l3_t *l3, __u16 ch)
|
||||
{
|
||||
x25_channel_t *l3c = l3->channels;
|
||||
x25_channel_t *l3c;
|
||||
|
||||
while(l3c) {
|
||||
list_for_each_entry(l3c, &l3->channellist, list) {
|
||||
if (l3c->lchan == ch)
|
||||
break;
|
||||
l3c = l3c->next;
|
||||
return(l3c);
|
||||
}
|
||||
return(l3c);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
x25_channel_t *
|
||||
X25_get_channel4NCCI(x25_l3_t *l3, __u32 addr)
|
||||
{
|
||||
x25_channel_t *l3c = l3->channels;
|
||||
x25_channel_t *l3c;
|
||||
|
||||
while(l3c) {
|
||||
list_for_each_entry(l3c, &l3->channellist, list) {
|
||||
if ((l3c->ncci & 0xffff0000) == (addr & 0xffff0000))
|
||||
break;
|
||||
l3c = l3c->next;
|
||||
return(l3c);
|
||||
}
|
||||
return(l3c);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -47,10 +47,9 @@ struct _x25_ConfQueue {
|
|||
};
|
||||
|
||||
struct _x25_l3 {
|
||||
x25_l3_t *prev;
|
||||
x25_l3_t *next;
|
||||
struct list_head list;
|
||||
mISDNinstance_t inst;
|
||||
x25_channel_t *channels;
|
||||
struct list_head channellist;
|
||||
struct FsmInst l2l3m;
|
||||
struct FsmInst x25r;
|
||||
struct FsmTimer TR;
|
||||
|
@ -70,8 +69,7 @@ struct _x25_l3 {
|
|||
};
|
||||
|
||||
struct _x25_channel {
|
||||
x25_channel_t *prev;
|
||||
x25_channel_t *next;
|
||||
struct list_head list;
|
||||
x25_l3_t *l3;
|
||||
struct FsmInst x25p;
|
||||
struct FsmInst x25d;
|
||||
|
|
|
@ -596,6 +596,7 @@ typedef struct _Q931_info {
|
|||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/isdn_compat.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
typedef struct _mISDNobject mISDNobject_t;
|
||||
|
@ -635,8 +636,7 @@ typedef struct _mISDN_headext {
|
|||
|
||||
/* Basic struct of a mISDN component */
|
||||
struct _mISDNobject {
|
||||
mISDNobject_t *prev;
|
||||
mISDNobject_t *next;
|
||||
struct list_head list;
|
||||
char *name;
|
||||
int id;
|
||||
int refcnt;
|
||||
|
@ -644,27 +644,26 @@ struct _mISDNobject {
|
|||
mISDN_pid_t BPROTO;
|
||||
ctrl_func_t *own_ctrl;
|
||||
ctrl_func_t *ctrl;
|
||||
void *ilist;
|
||||
struct list_head ilist;
|
||||
struct module *owner;
|
||||
};
|
||||
|
||||
/* the interface between two mISDNinstances */
|
||||
struct _mISDNif {
|
||||
mISDNif_t *prev;
|
||||
mISDNif_t *next;
|
||||
if_func_t *func;
|
||||
void *fdata;
|
||||
mISDNif_t *clone;
|
||||
mISDNif_t *predecessor;
|
||||
int extentions;
|
||||
int stat;
|
||||
mISDNstack_t *st;
|
||||
mISDNinstance_t *owner;
|
||||
mISDNinstance_t *peer;
|
||||
if_func_t *func;
|
||||
void *fdata;
|
||||
};
|
||||
|
||||
/* a instance of a mISDNobject */
|
||||
struct _mISDNinstance {
|
||||
mISDNinstance_t *prev;
|
||||
mISDNinstance_t *next;
|
||||
struct list_head list;
|
||||
char name[mISDN_MAX_IDLEN];
|
||||
int extentions;
|
||||
u_int id;
|
||||
|
@ -682,23 +681,21 @@ struct _mISDNinstance {
|
|||
* normally here is only one instance per layer only if the information
|
||||
* will be splitted here are more instances */
|
||||
struct _mISDNlayer {
|
||||
mISDNlayer_t *prev;
|
||||
mISDNlayer_t *next;
|
||||
struct list_head list;
|
||||
mISDNinstance_t *inst;
|
||||
};
|
||||
|
||||
/* the STACK; a (vertical) chain of layers */
|
||||
|
||||
struct _mISDNstack {
|
||||
mISDNstack_t *prev;
|
||||
mISDNstack_t *next;
|
||||
struct list_head list;
|
||||
u_int id;
|
||||
u_int extentions;
|
||||
mISDN_pid_t pid;
|
||||
mISDN_stPara_t para;
|
||||
mISDNlayer_t *lstack;
|
||||
struct list_head layerlist;
|
||||
mISDNinstance_t *mgr;
|
||||
mISDNstack_t *child;
|
||||
struct list_head childlist;
|
||||
};
|
||||
|
||||
/* lowlevel read/write struct for the mISDNdevice */
|
||||
|
@ -716,16 +713,15 @@ struct _mISDNport {
|
|||
|
||||
/* the user interface to handle /dev/mISDN */
|
||||
struct _mISDNdevice {
|
||||
mISDNdevice_t *prev;
|
||||
mISDNdevice_t *next;
|
||||
struct list_head list;
|
||||
int minor;
|
||||
struct semaphore io_sema;
|
||||
int open_mode;
|
||||
mISDNport_t rport;
|
||||
mISDNport_t wport;
|
||||
struct _devicelayer *layer;
|
||||
struct _devicestack *stack;
|
||||
struct _mISDNtimer *timer;
|
||||
struct list_head layerlist;
|
||||
struct list_head stacklist;
|
||||
struct list_head timerlist;
|
||||
struct list_head entitylist;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue