mISDN/drivers/isdn/hardware/mISDN/contr.c

638 lines
14 KiB
C
Raw Normal View History

2001-02-21 19:22:35 +00:00
/* $Id$
*
*/
2003-07-28 12:05:47 +00:00
#include <linux/vmalloc.h>
#include <asm/uaccess.h>
2003-07-21 12:44:46 +00:00
#include "capi.h"
2001-02-21 19:22:35 +00:00
#include "helper.h"
#include "debug.h"
#define contrDebug(contr, lev, fmt, args...) \
if (contr->debug & lev) capidebug(lev, fmt, ## args)
2001-02-21 19:22:35 +00:00
2003-07-28 12:05:47 +00:00
void
contrDestr(Contr_t *contr)
2001-02-21 19:22:35 +00:00
{
int i;
2003-07-21 12:00:05 +00:00
mISDNinstance_t *inst = &contr->inst;
2001-02-21 19:22:35 +00:00
for (i = 0; i < CAPI_MAXAPPL; i++) {
if (contr->appls[i]) {
applDestr(contr->appls[i]);
kfree(contr->appls[i]);
2001-02-27 17:45:44 +00:00
contr->appls[i] = NULL;
2001-02-21 19:22:35 +00:00
}
}
for (i = 0; i < CAPI_MAXPLCI; i++) {
if (contr->plcis[i]) {
plciDestr(contr->plcis[i]);
kfree(contr->plcis[i]);
2001-02-27 17:45:44 +00:00
contr->plcis[i] = NULL;
2001-02-21 19:22:35 +00:00
}
}
for (i = 0; i < CAPI_MAXDUMMYPCS; i++) {
if (contr->dummy_pcs[i]) {
dummyPcDestr(contr->dummy_pcs[i]);
kfree(contr->dummy_pcs[i]);
2001-02-27 17:45:44 +00:00
contr->dummy_pcs[i] = NULL;
2001-02-21 19:22:35 +00:00
}
}
2003-07-28 12:05:47 +00:00
#ifdef OLDCAPI_DRIVER_INTERFACE
2001-02-22 05:54:40 +00:00
if (contr->ctrl)
cdrv_if->detach_ctr(contr->ctrl);
2003-07-28 12:05:47 +00:00
#else
detach_capi_ctr(contr->ctrl);
kfree(contr->ctrl);
contr->ctrl = NULL;
#endif
2001-02-27 17:45:44 +00:00
while (contr->binst) {
BInst_t *binst = contr->binst;
REMOVE_FROM_LISTBASE(binst, contr->binst);
kfree(binst);
2001-02-22 05:54:40 +00:00
}
2001-03-26 11:40:02 +00:00
if (inst->up.peer) {
inst->up.peer->obj->ctrl(inst->up.peer,
MGR_DISCONNECT | REQUEST, &inst->up);
}
if (inst->down.peer) {
inst->down.peer->obj->ctrl(inst->down.peer,
MGR_DISCONNECT | REQUEST, &inst->down);
}
inst->obj->ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
REMOVE_FROM_LISTBASE(contr, ((Contr_t *)inst->obj->ilist));
2001-02-21 19:22:35 +00:00
}
2003-07-28 12:05:47 +00:00
void
contrRun(Contr_t *contr)
2001-02-21 19:22:35 +00:00
{
BInst_t *binst;
int nb, ret;
2001-11-14 10:41:26 +00:00
nb = 0;
binst = contr->binst;
while(binst) {
nb++;
binst = binst->next;
}
if (contr->inst.st && contr->inst.st->mgr)
sprintf(contr->ctrl->manu, "mISDN CAPI controller %s", contr->inst.st->mgr->name);
else
sprintf(contr->ctrl->manu, "mISDN CAPI");
2003-07-28 12:05:47 +00:00
strncpy(contr->ctrl->serial, "0002", CAPI_SERIAL_LEN);
contr->ctrl->version.majorversion = 2;
2003-07-28 12:05:47 +00:00
contr->ctrl->version.minorversion = 0;
contr->ctrl->version.majormanuversion = 1;
contr->ctrl->version.minormanuversion = 0;
2003-07-28 12:05:47 +00:00
memset(&contr->ctrl->profile, 0, sizeof(struct capi_profile));
contr->ctrl->profile.ncontroller = 1;
contr->ctrl->profile.nbchannel = nb;
contrDebug(contr, CAPI_DBG_INFO, "%s: %s version(%s)",
__FUNCTION__, contr->ctrl->manu, contr->ctrl->serial);
// FIXME
contr->ctrl->profile.goptions = 0x19; // internal controller, supplementary services, DTMF
if (nb) {
mISDN_pid_t pidmask;
memset(&pidmask, 0, sizeof(mISDN_pid_t));
pidmask.protocol[1] = 0x03ff;
pidmask.protocol[2] = 0x1fff;
pidmask.protocol[3] = 0x00ff;
binst = contr->binst;
ret = binst->inst.obj->ctrl(binst->bst, MGR_EVALSTACK | REQUEST, &pidmask);
if (ret) {
/* Fallback on error, minimum set */
int_error();
contr->ctrl->profile.support1 = 3; // HDLC, TRANS
contr->ctrl->profile.support2 = 3; // X75SLP, TRANS
contr->ctrl->profile.support3 = 1; // TRANS
} else {
contr->ctrl->profile.support1 = pidmask.protocol[1];
contr->ctrl->profile.support2 = pidmask.protocol[2];
contr->ctrl->profile.support3 = pidmask.protocol[3];
}
}
contrDebug(contr, CAPI_DBG_INFO, "%s: GLOBAL(%08X) B1(%08X) B2(%08X) B3(%08X)",
__FUNCTION__, contr->ctrl->profile.goptions, contr->ctrl->profile.support1,
contr->ctrl->profile.support2, contr->ctrl->profile.support2);
2003-07-28 12:05:47 +00:00
#ifdef OLDCAPI_DRIVER_INTERFACE
contr->ctrl->ready(contr->ctrl);
#else
capi_ctr_ready(contr->ctrl);
#endif
2001-02-21 19:22:35 +00:00
}
2003-07-28 12:05:47 +00:00
Appl_t
*contrId2appl(Contr_t *contr, __u16 ApplId)
2001-02-21 19:22:35 +00:00
{
if ((ApplId < 1) || (ApplId > CAPI_MAXAPPL)) {
int_error();
return 0;
}
return contr->appls[ApplId - 1];
}
2003-07-28 12:05:47 +00:00
Plci_t
*contrAdr2plci(Contr_t *contr, __u32 adr)
2001-02-21 19:22:35 +00:00
{
int i = (adr >> 8);
if ((i < 1) || (i > CAPI_MAXPLCI)) {
int_error();
return 0;
}
return contr->plcis[i - 1];
}
2003-07-28 12:05:47 +00:00
static void
RegisterAppl(struct capi_ctr *ctrl, __u16 ApplId, capi_register_params *rp)
{
Contr_t *contr = ctrl->driverdata;
Appl_t *appl;
2001-02-21 19:22:35 +00:00
2003-07-28 12:05:47 +00:00
contrDebug(contr, CAPI_DBG_APPL, "%s: ApplId(%x)", __FUNCTION__, ApplId);
2001-02-21 19:22:35 +00:00
appl = contrId2appl(contr, ApplId);
if (appl) {
int_error();
return;
}
appl = kmalloc(sizeof(Appl_t), GFP_ATOMIC);
2001-02-21 19:22:35 +00:00
if (!appl) {
int_error();
return;
}
contr->appls[ApplId - 1] = appl;
applConstr(appl, contr, ApplId, rp);
2003-07-28 12:05:47 +00:00
#ifdef OLDCAPI_DRIVER_INTERFACE
2001-02-21 19:22:35 +00:00
contr->ctrl->appl_registered(contr->ctrl, ApplId);
2003-07-28 12:05:47 +00:00
#endif
2001-02-21 19:22:35 +00:00
}
2003-07-28 12:05:47 +00:00
static void
ReleaseAppl(struct capi_ctr *ctrl, __u16 ApplId)
{
Contr_t *contr = ctrl->driverdata;
Appl_t *appl;
2001-02-21 19:22:35 +00:00
2003-07-21 11:13:02 +00:00
contrDebug(contr, CAPI_DBG_APPL, "%s: ApplId(%x)", __FUNCTION__, ApplId);
2001-02-21 19:22:35 +00:00
appl = contrId2appl(contr, ApplId);
if (!appl) {
int_error();
return;
}
applDestr(appl);
kfree(appl);
2001-02-27 17:45:44 +00:00
contr->appls[ApplId - 1] = NULL;
2003-07-28 12:05:47 +00:00
#ifdef OLDCAPI_DRIVER_INTERFACE
2001-02-21 19:22:35 +00:00
contr->ctrl->appl_released(contr->ctrl, ApplId);
2003-07-28 12:05:47 +00:00
#endif
2001-02-21 19:22:35 +00:00
}
2003-07-28 12:05:47 +00:00
#ifdef OLDCAPI_DRIVER_INTERFACE
static void
#else
static u16
#endif
SendMessage(struct capi_ctr *ctrl, struct sk_buff *skb)
{
Contr_t *contr = ctrl->driverdata;
Appl_t *appl;
int ApplId;
int err = CAPI_NOERROR;
2001-02-21 19:22:35 +00:00
ApplId = CAPIMSG_APPID(skb->data);
appl = contrId2appl(contr, ApplId);
if (!appl) {
int_error();
2003-07-28 12:05:47 +00:00
err = CAPI_ILLAPPNR;
} else
applSendMessage(appl, skb);
#ifndef OLDCAPI_DRIVER_INTERFACE
return(err);
#endif
2001-02-21 19:22:35 +00:00
}
2003-07-28 12:05:47 +00:00
static int
LoadFirmware(struct capi_ctr *ctrl, capiloaddata *data)
2001-02-21 19:22:35 +00:00
{
2003-07-28 12:05:47 +00:00
Contr_t *contr = ctrl->driverdata;
2001-03-03 18:17:16 +00:00
struct firm {
int len;
void *data;
} firm;
2003-07-28 12:05:47 +00:00
int retval;
2001-02-27 17:45:44 +00:00
2003-07-28 12:05:47 +00:00
firm.len = data->firmware.len;
if (data->firmware.user) {
firm.data = vmalloc(data->firmware.len);
if (!firm.data)
return(-ENOMEM);
retval = copy_from_user(firm.data, data->firmware.data, data->firmware.len);
if (retval) {
vfree(firm.data);
return(retval);
}
} else
firm.data = data;
2001-03-03 18:17:16 +00:00
contr->inst.obj->ctrl(contr->inst.st, MGR_LOADFIRM | REQUEST, &firm);
2003-07-28 12:05:47 +00:00
if (data->firmware.user)
vfree(firm.data);
return(0);
}
static char *
procinfo(struct capi_ctr *ctrl)
{
Contr_t *contr = ctrl->driverdata;
if (CAPI_DBG_INFO & contr->debug)
printk(KERN_DEBUG "%s\n", __FUNCTION__);
if (!contr)
return "";
sprintf(contr->infobuf, "-");
return contr->infobuf;
2001-02-21 19:22:35 +00:00
}
2003-07-28 12:05:47 +00:00
static int
read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl)
{
int len = 0;
len += sprintf(page+len, "mISDN_read_proc\n");
if (off+count >= len)
*eof = 1;
if (len < off)
return 0;
*start = page + off;
return ((count < len-off) ? count : len-off);
};
static void
ResetContr(struct capi_ctr *ctrl)
2001-02-21 19:22:35 +00:00
{
2003-07-28 12:05:47 +00:00
Contr_t *contr = ctrl->driverdata;
int ApplId;
Appl_t *appl;
2001-02-21 19:22:35 +00:00
for (ApplId = 1; ApplId <= CAPI_MAXAPPL; ApplId++) {
appl = contrId2appl(contr, ApplId);
2003-07-28 12:05:47 +00:00
if (appl) {
2001-02-21 19:22:35 +00:00
applDestr(appl);
2003-07-28 12:05:47 +00:00
kfree(appl);
}
2001-02-21 19:22:35 +00:00
contr->appls[ApplId - 1] = NULL;
}
2003-07-28 12:05:47 +00:00
#ifdef OLDCAPI_DRIVER_INTERFACE
2001-02-21 19:22:35 +00:00
contr->ctrl->reseted(contr->ctrl);
2003-07-28 12:05:47 +00:00
#else
capi_ctr_reseted(contr->ctrl);
#endif
2001-02-21 19:22:35 +00:00
}
2003-07-28 12:05:47 +00:00
#ifdef OLDCAPI_DRIVER_INTERFACE
static void
Remove_Contr(struct capi_ctr *ctrl)
2001-02-21 19:22:35 +00:00
{
2003-07-28 12:05:47 +00:00
Contr_t *contr = ctrl->driverdata;
if (CAPI_DBG_INFO & contr->debug)
printk(KERN_DEBUG "%s\n", __FUNCTION__);
}
struct capi_driver mISDN_driver = {
"mISDN",
"0.01",
LoadFirmware,
ResetContr,
Remove_Contr,
RegisterAppl,
ReleaseAppl,
SendMessage,
procinfo,
read_proc,
0,
0,
};
#endif
void
contrD2Trace(Contr_t *contr, u_char *buf, int len)
{
Appl_t *appl;
__u16 applId;
2001-02-21 19:22:35 +00:00
for (applId = 1; applId <= CAPI_MAXAPPL; applId++) {
appl = contrId2appl(contr, applId);
if (appl) {
applD2Trace(appl, buf, len);
}
}
}
2003-07-28 12:05:47 +00:00
void
contrRecvCmsg(Contr_t *contr, _cmsg *cmsg)
2001-02-21 19:22:35 +00:00
{
2003-07-28 12:05:47 +00:00
struct sk_buff *skb;
int len;
2001-02-21 19:22:35 +00:00
capi_cmsg2message(cmsg, contr->msgbuf);
len = CAPIMSG_LEN(contr->msgbuf);
contrDebug(contr, CAPI_DBG_CONTR_MSG, "%s: len(%d) applid(%x) %s msgnr(%d) addr(%08x",
__FUNCTION__, len, cmsg->ApplId, capi_cmd2str(cmsg->Command, cmsg->Subcommand),
cmsg->Messagenumber, cmsg->adr.adrController);
2001-02-21 19:22:35 +00:00
if (!(skb = alloc_skb(len, GFP_ATOMIC))) {
printk(KERN_ERR "%s: no mem for %d bytes\n", __FUNCTION__, len);
2001-02-21 19:22:35 +00:00
int_error();
return;
}
memcpy(skb_put(skb, len), contr->msgbuf, len);
2003-07-28 12:05:47 +00:00
#ifdef OLDCAPI_DRIVER_INTERFACE
2001-02-21 19:22:35 +00:00
contr->ctrl->handle_capimsg(contr->ctrl, cmsg->ApplId, skb);
2003-07-28 12:05:47 +00:00
#else
capi_ctr_handle_message(contr->ctrl, cmsg->ApplId, skb);
#endif
2001-02-21 19:22:35 +00:00
}
2003-07-28 12:05:47 +00:00
void
contrAnswerCmsg(Contr_t *contr, _cmsg *cmsg, __u16 Info)
2001-02-21 19:22:35 +00:00
{
capi_cmsg_answer(cmsg);
cmsg->Info = Info;
contrRecvCmsg(contr, cmsg);
}
2003-07-28 12:05:47 +00:00
void
contrAnswerMessage(Contr_t *contr, struct sk_buff *skb, __u16 Info)
2001-02-21 19:22:35 +00:00
{
2003-07-28 12:05:47 +00:00
_cmsg cmsg;
2001-02-21 19:22:35 +00:00
capi_message2cmsg(&cmsg, skb->data);
contrAnswerCmsg(contr, &cmsg, Info);
}
2003-07-28 12:05:47 +00:00
Plci_t *
contrNewPlci(Contr_t *contr)
2001-02-21 19:22:35 +00:00
{
2003-07-28 12:05:47 +00:00
Plci_t *plci;
int i;
2001-02-21 19:22:35 +00:00
for (i = 0; i < CAPI_MAXPLCI; i++) {
if (!contr->plcis[i])
break;
}
if (i == CAPI_MAXPLCI) {
return 0;
}
plci = kmalloc(sizeof(Plci_t), GFP_ATOMIC);
if (!plci) {
int_error();
return 0;
}
contr->plcis[i] = plci;
plciConstr(plci, contr, (i+1) << 8 | contr->adrController);
contrDebug(contr, CAPI_DBG_PLCI, "%s: PLCI(%x) plci(%p,%d)", __FUNCTION__, plci->adrPLCI, plci, sizeof(*plci));
2001-02-21 19:22:35 +00:00
return plci;
}
2003-07-28 12:05:47 +00:00
void
contrDelPlci(Contr_t *contr, Plci_t *plci)
2001-02-21 19:22:35 +00:00
{
2003-07-28 12:05:47 +00:00
int i = plci->adrPLCI >> 8;
2001-02-21 19:22:35 +00:00
contrDebug(contr, CAPI_DBG_PLCI, "%s: PLCI(%x) plci(%p)", __FUNCTION__, plci->adrPLCI, plci);
2001-02-21 19:22:35 +00:00
if ((i < 1) || (i > CAPI_MAXPLCI)) {
int_error();
return;
}
if (contr->plcis[i-1] != plci) {
int_error();
return;
}
plciDestr(plci);
kfree(plci);
2001-02-27 17:45:44 +00:00
contr->plcis[i-1] = NULL;
2001-02-21 19:22:35 +00:00
}
2003-07-28 12:05:47 +00:00
static Plci_t *
contrGetPLCI4addr(Contr_t *contr, u_int addr)
2001-02-21 19:22:35 +00:00
{
2003-07-28 12:05:47 +00:00
int i;
2001-02-21 19:22:35 +00:00
for (i = 0; i < CAPI_MAXPLCI; i++) {
if (!contr->plcis[i])
continue;
if (contr->plcis[i]->adrPLCI == addr)
return(contr->plcis[i]);
}
return(NULL);
}
2001-02-22 05:54:40 +00:00
int
2003-07-21 12:00:05 +00:00
contrL3L4(mISDNif_t *hif, struct sk_buff *skb)
2001-02-21 19:22:35 +00:00
{
2001-08-02 14:51:56 +00:00
Contr_t *contr;
Plci_t *plci;
__u32 *id;
int ret = -EINVAL;
2003-07-21 12:00:05 +00:00
mISDN_head_t *hh;
2001-08-02 14:51:56 +00:00
if (!hif || !skb)
return(ret);
2003-07-21 12:00:05 +00:00
hh = mISDN_HEAD_P(skb);
2001-02-21 19:22:35 +00:00
contr = hif->fdata;
contrDebug(contr, CAPI_DBG_CONTR_INFO, "%s: prim(%x) id(%x)",
__FUNCTION__, hh->prim, hh->dinfo);
2001-08-02 14:51:56 +00:00
if (hh->prim == (CC_NEW_CR | INDICATION)) {
2001-02-21 19:22:35 +00:00
plci = contrNewPlci(contr);
if (!plci)
return(-EBUSY);
2001-08-02 14:51:56 +00:00
if (skb->len >= sizeof(void)) {
2001-10-31 23:04:42 +00:00
id = *((__u32 **)skb->data);
2001-08-02 14:51:56 +00:00
*id = plci->adrPLCI;
dev_kfree_skb(skb);
ret = 0;
}
} else if ((hh->dinfo & ~CONTROLER_MASK) == DUMMY_CR_FLAG) {
ret = contrDummyInd(contr, hh->prim, skb);
2001-02-21 19:22:35 +00:00
} else {
2001-08-02 14:51:56 +00:00
if (!(plci = contrGetPLCI4addr(contr, hh->dinfo))) {
2003-07-21 11:13:02 +00:00
contrDebug(contr, CAPI_DBG_WARN, "%s: unknown plci prim(%x) id(%x)",
2002-09-16 23:49:38 +00:00
__FUNCTION__, hh->prim, hh->dinfo);
2001-02-21 19:22:35 +00:00
return(-ENODEV);
}
contrDebug(contr, CAPI_DBG_PLCI, "%s: PLCI(%x) plci(%p)", __FUNCTION__, plci->adrPLCI, plci);
2001-08-02 14:51:56 +00:00
ret = plci_l3l4(plci, hh->prim, skb);
2001-02-21 19:22:35 +00:00
}
2001-08-02 14:51:56 +00:00
return(ret);
2001-02-21 19:22:35 +00:00
}
2003-07-28 12:05:47 +00:00
int
contrL4L3(Contr_t *contr, u_int prim, int dinfo, struct sk_buff *skb)
2001-08-02 14:51:56 +00:00
{
return(if_newhead(&contr->inst.down, prim, dinfo, skb));
2001-02-22 05:54:40 +00:00
}
2003-07-28 12:05:47 +00:00
void
contrPutStatus(Contr_t *contr, char *msg)
2001-02-21 19:22:35 +00:00
{
2003-07-21 11:13:02 +00:00
contrDebug(contr, CAPI_DBG_CONTR, "%s: %s", __FUNCTION__, msg);
2001-02-21 19:22:35 +00:00
}
2003-07-28 12:05:47 +00:00
static int
contrConstr(Contr_t *contr, mISDNstack_t *st, mISDN_pid_t *pid, mISDNobject_t *ocapi)
{
int retval;
mISDNstack_t *cst = st->child;
BInst_t *binst;
memset(contr, 0, sizeof(Contr_t));
memcpy(&contr->inst.pid, pid, sizeof(mISDN_pid_t));
#ifndef OLDCAPI_DRIVER_INTERFACE
if (!(contr->ctrl = kmalloc(sizeof(struct capi_ctr), GFP_ATOMIC))) {
printk(KERN_ERR "no mem for contr->ctrl\n");
int_error();
return -ENOMEM;
}
memset(contr->ctrl, 0, sizeof(struct capi_ctr));
#endif
contr->adrController = st->id;
sprintf(contr->inst.name, "CAPI %d", st->id);
init_mISDNinstance(&contr->inst, ocapi, contr);
2003-07-28 12:05:47 +00:00
if (!SetHandledPID(ocapi, &contr->inst.pid)) {
int_error();
return(-ENOPROTOOPT);
}
while(cst) {
if (!(binst = kmalloc(sizeof(BInst_t), GFP_ATOMIC))) {
printk(KERN_ERR "no mem for Binst\n");
int_error();
return -ENOMEM;
}
memset(binst, 0, sizeof(BInst_t));
binst->bst = cst;
binst->inst.st = cst;
init_mISDNinstance(&binst->inst, ocapi, binst);
2003-07-28 12:05:47 +00:00
binst->inst.pid.layermask |= ISDN_LAYER(4);
binst->inst.down.stat = IF_NOACTIV;
APPEND_TO_LIST(binst, contr->binst);
cst = cst->next;
}
APPEND_TO_LIST(contr, ocapi->ilist);
retval = 0;
#ifdef OLDCAPI_DRIVER_INTERFACE
{
char tmp[10];
sprintf(tmp, "mISDN%d", st->id);
contr->ctrl = cdrv_if->attach_ctr(&mISDN_driver, tmp, contr);
if (!contr->ctrl)
retval = -ENODEV;
}
#else
contr->ctrl->owner = THIS_MODULE;
sprintf(contr->ctrl->name, "mISDN%d", st->id);
contr->ctrl->driver_name = "mISDN";
contr->ctrl->driverdata = contr;
contr->ctrl->register_appl = RegisterAppl;
contr->ctrl->release_appl = ReleaseAppl;
contr->ctrl->send_message = SendMessage;
contr->ctrl->load_firmware = LoadFirmware;
contr->ctrl->reset_ctr = ResetContr;
contr->ctrl->procinfo = procinfo;
contr->ctrl->ctr_read_proc = read_proc;
retval = attach_capi_ctr(contr->ctrl);
#endif
if (!retval) {
contr->adrController = contr->ctrl->cnr;
ocapi->ctrl(st, MGR_REGLAYER | INDICATION, &contr->inst);
contr->inst.up.stat = IF_DOWN;
}
return retval;
}
Contr_t *
newContr(mISDNobject_t *ocapi, mISDNstack_t *st, mISDN_pid_t *pid)
2001-02-21 19:22:35 +00:00
{
Contr_t *contr;
2001-03-26 11:40:02 +00:00
if (!pid)
2001-02-21 19:22:35 +00:00
return(NULL);
if (!st) {
printk(KERN_ERR "newContr no stack\n");
return(NULL);
}
contr = kmalloc(sizeof(Contr_t), GFP_KERNEL);
if (!contr)
return(NULL);
2001-03-26 11:40:02 +00:00
if (contrConstr(contr, st, pid, ocapi) != 0) {
2001-02-22 05:54:40 +00:00
contrDestr(contr);
2001-02-21 19:22:35 +00:00
kfree(contr);
return(NULL);
}
return contr;
}
2003-07-28 12:05:47 +00:00
BInst_t *
contrSelChannel(Contr_t *contr, u_int channel)
2001-02-27 17:45:44 +00:00
{
2003-07-21 12:00:05 +00:00
mISDNstack_t *cst;
2001-11-14 10:41:26 +00:00
BInst_t *binst;
channel_info_t ci;
int ret;
2001-02-27 17:45:44 +00:00
if (!contr->binst) {
cst = contr->inst.st->child;
if (!cst)
return(NULL);
while(cst) {
if (!(binst = kmalloc(sizeof(BInst_t), GFP_ATOMIC))) {
2001-02-27 17:45:44 +00:00
printk(KERN_ERR "no mem for Binst\n");
int_error();
return(NULL);
}
memset(binst, 0, sizeof(BInst_t));
2001-10-31 23:04:42 +00:00
binst->bst = cst;
2001-02-27 17:45:44 +00:00
binst->inst.st = cst;
binst->inst.data = binst;
binst->inst.obj = contr->inst.obj;
2001-03-26 11:40:02 +00:00
binst->inst.pid.layermask = ISDN_LAYER(4);
2001-02-27 17:45:44 +00:00
binst->inst.down.stat = IF_NOACTIV;
APPEND_TO_LIST(binst, contr->binst);
cst = cst->next;
}
}
2001-11-14 10:41:26 +00:00
ci.channel = channel;
ci.st.p = NULL;
ret = contr->inst.obj->ctrl(contr->inst.st, MGR_SELCHANNEL | REQUEST,
&ci);
if (ret) {
2003-07-21 11:13:02 +00:00
int_errtxt("MGR_SELCHANNEL ret(%d)", ret);
2001-11-14 10:41:26 +00:00
return(NULL);
}
cst = ci.st.p;
binst = contr->binst;
while(binst) {
if (cst == binst->bst)
break;
binst = binst->next;
}
2001-02-27 17:45:44 +00:00
return(binst);
}
2001-02-21 19:22:35 +00:00
#if 0
2003-07-28 12:05:47 +00:00
static void
d2_listener(struct IsdnCardState *cs, u_char *buf, int len)
2001-02-21 19:22:35 +00:00
{
Contr_t *contr = cs->contr;
if (!contr) {
int_error();
return;
}
contrD2Trace(contr, buf, len);
}
#endif