2001-02-11 22:46:19 +00:00
|
|
|
/* $Id$
|
|
|
|
*
|
|
|
|
* Author Karsten Keil (keil@isdn4linux.de)
|
|
|
|
*
|
|
|
|
* This file is (c) under GNU PUBLIC LICENSE
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/types.h>
|
|
|
|
#include <linux/stddef.h>
|
|
|
|
#include <linux/config.h>
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include "hisax_core.h"
|
|
|
|
#ifdef CONFIG_KMOD
|
|
|
|
#include <linux/kmod.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
hisaxobject_t *hisax_objects = NULL;
|
2001-02-22 10:14:16 +00:00
|
|
|
int core_debug;
|
|
|
|
|
2001-03-11 21:23:39 +00:00
|
|
|
static int debug;
|
|
|
|
static int obj_id;
|
2001-02-11 22:46:19 +00:00
|
|
|
|
|
|
|
#ifdef MODULE
|
|
|
|
MODULE_AUTHOR("Karsten Keil");
|
|
|
|
MODULE_PARM(debug, "1i");
|
|
|
|
EXPORT_SYMBOL(HiSax_register);
|
|
|
|
EXPORT_SYMBOL(HiSax_unregister);
|
|
|
|
#define HiSaxInit init_module
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static moditem_t modlist[] = {
|
2001-03-04 17:08:33 +00:00
|
|
|
{"hisaxl1", ISDN_PID_L1_TE_S0},
|
|
|
|
{"hisaxl2", ISDN_PID_L2_LAPD},
|
|
|
|
{"hisaxl2", ISDN_PID_L2_B_X75SLP},
|
|
|
|
{NULL, ISDN_PID_NONE}
|
2001-02-11 22:46:19 +00:00
|
|
|
};
|
|
|
|
|
2001-04-08 16:45:56 +00:00
|
|
|
hisaxobject_t *
|
|
|
|
get_object(int id) {
|
|
|
|
hisaxobject_t *obj = hisax_objects;
|
|
|
|
|
|
|
|
while(obj) {
|
|
|
|
if (obj->id == id)
|
|
|
|
return(obj);
|
|
|
|
obj = obj->next;
|
|
|
|
}
|
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
|
2001-02-11 22:46:19 +00:00
|
|
|
static hisaxobject_t *
|
2001-03-04 17:08:33 +00:00
|
|
|
find_object(int protocol) {
|
2001-02-11 22:46:19 +00:00
|
|
|
hisaxobject_t *obj = hisax_objects;
|
2001-03-04 17:08:33 +00:00
|
|
|
int err;
|
2001-02-11 22:46:19 +00:00
|
|
|
|
|
|
|
while (obj) {
|
2001-03-04 17:08:33 +00:00
|
|
|
err = obj->own_ctrl(NULL, MGR_HASPROTOCOL | REQUEST, &protocol);
|
|
|
|
if (!err)
|
|
|
|
return(obj);
|
|
|
|
if (err != -ENOPROTOOPT) {
|
|
|
|
if (HasProtocol(obj, protocol))
|
|
|
|
return(obj);
|
|
|
|
}
|
2001-02-11 22:46:19 +00:00
|
|
|
obj = obj->next;
|
|
|
|
}
|
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static hisaxobject_t *
|
2001-03-04 17:08:33 +00:00
|
|
|
find_object_module(int protocol) {
|
2001-02-11 22:46:19 +00:00
|
|
|
moditem_t *m = modlist;
|
|
|
|
hisaxobject_t *obj;
|
|
|
|
|
|
|
|
while (m->name != NULL) {
|
2001-03-04 17:08:33 +00:00
|
|
|
if (m->protocol == protocol) {
|
2001-02-11 22:46:19 +00:00
|
|
|
#ifdef CONFIG_KMOD
|
2001-03-04 17:08:33 +00:00
|
|
|
if (debug)
|
|
|
|
printk(KERN_DEBUG
|
|
|
|
"find_object_module %s - trying to load\n",
|
2001-02-11 22:46:19 +00:00
|
|
|
m->name);
|
2001-03-04 17:08:33 +00:00
|
|
|
request_module(m->name);
|
|
|
|
#else
|
|
|
|
printk(KERN_WARNING "not possible to autoload %s please try to load manually\n",
|
|
|
|
m->name);
|
2001-02-11 22:46:19 +00:00
|
|
|
#endif
|
2001-03-04 17:08:33 +00:00
|
|
|
if ((obj = find_object(protocol)))
|
|
|
|
return(obj);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
m++;
|
|
|
|
}
|
|
|
|
if (debug)
|
2001-03-04 17:08:33 +00:00
|
|
|
printk(KERN_DEBUG __FUNCTION__": no module for protocol %x found\n",
|
|
|
|
protocol);
|
2001-02-11 22:46:19 +00:00
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
remove_object(hisaxobject_t *obj) {
|
|
|
|
hisaxstack_t *st = hisax_stacklist;
|
2001-03-03 08:07:30 +00:00
|
|
|
hisaxlayer_t *layer;
|
2001-02-11 22:46:19 +00:00
|
|
|
hisaxinstance_t *inst, *tmp;
|
|
|
|
|
|
|
|
while (st) {
|
2001-03-03 08:07:30 +00:00
|
|
|
layer = st->lstack;
|
|
|
|
while(layer) {
|
|
|
|
inst = layer->inst;
|
2001-02-11 22:46:19 +00:00
|
|
|
while (inst) {
|
|
|
|
if (inst->obj == obj) {
|
|
|
|
tmp = inst->next;
|
|
|
|
inst->obj->own_ctrl(st, MGR_RELEASE
|
|
|
|
| INDICATION, inst);
|
|
|
|
inst = tmp;
|
|
|
|
} else
|
|
|
|
inst = inst->next;
|
|
|
|
}
|
2001-03-03 08:07:30 +00:00
|
|
|
layer = layer->next;
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
st = st->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2001-03-03 18:17:16 +00:00
|
|
|
dummy_if(hisaxif_t *hif, u_int prim, int dinfo, int len, void *arg) {
|
2001-02-11 22:46:19 +00:00
|
|
|
if (debug & DEBUG_DUMMY_FUNC)
|
2001-03-03 18:17:16 +00:00
|
|
|
printk(KERN_DEBUG __FUNCTION__": prim:%x hif:%p dinfo:%x len:%d arg:%p\n",
|
|
|
|
prim, hif, dinfo, len, arg);
|
2001-02-11 22:46:19 +00:00
|
|
|
return(-EINVAL);
|
|
|
|
}
|
|
|
|
|
2001-03-26 11:40:02 +00:00
|
|
|
hisaxinstance_t *
|
|
|
|
get_next_instance(hisaxstack_t *st, hisax_pid_t *pid)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
hisaxinstance_t *next;
|
|
|
|
int layer, proto;
|
|
|
|
hisaxobject_t *obj;
|
|
|
|
|
|
|
|
layer = get_lowlayer(pid->layermask);
|
|
|
|
proto = pid->protocol[layer];
|
|
|
|
next = get_instance(st, layer, proto);
|
|
|
|
if (!next) {
|
|
|
|
obj = find_object(proto);
|
|
|
|
if (!obj)
|
|
|
|
obj = find_object_module(proto);
|
|
|
|
if (!obj) {
|
|
|
|
printk(KERN_WARNING __FUNCTION__": no object found\n");
|
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
err = obj->own_ctrl(st, MGR_NEWLAYER | REQUEST, pid);
|
|
|
|
if (err) {
|
|
|
|
printk(KERN_WARNING __FUNCTION__": newlayer err(%d)\n",
|
|
|
|
err);
|
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
next = get_instance(st, layer, proto);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
2001-03-26 11:40:02 +00:00
|
|
|
return(next);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2001-03-26 11:40:02 +00:00
|
|
|
disconnect_if(hisaxinstance_t *inst, u_int prim, hisaxif_t *hif) {
|
|
|
|
int err = 0;
|
2001-02-11 22:46:19 +00:00
|
|
|
|
2001-03-26 11:40:02 +00:00
|
|
|
if (hif) {
|
|
|
|
hif->stat = IF_NOACTIV;
|
|
|
|
hif->func = dummy_if;
|
|
|
|
hif->peer = NULL;
|
|
|
|
hif->fdata = NULL;
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
2001-03-26 11:40:02 +00:00
|
|
|
if (inst)
|
|
|
|
err = inst->obj->own_ctrl(inst, prim, hif);
|
|
|
|
return(err);
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
|
2001-04-11 10:21:10 +00:00
|
|
|
static int
|
|
|
|
add_if(hisaxinstance_t *inst, u_int prim, hisaxif_t *hif) {
|
|
|
|
hisaxif_t *myif;
|
|
|
|
|
|
|
|
if (!inst)
|
|
|
|
return(-EINVAL);
|
|
|
|
if (!hif)
|
|
|
|
return(-EINVAL);
|
|
|
|
if (hif->stat & IF_UP) {
|
|
|
|
myif = &inst->down;
|
|
|
|
} else if (hif->stat & IF_DOWN) {
|
|
|
|
myif = &inst->up;
|
|
|
|
} else
|
|
|
|
return(-EINVAL);
|
|
|
|
APPEND_TO_LIST(hif, myif);
|
|
|
|
inst->obj->own_ctrl(inst, prim, hif);
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
2001-02-11 22:46:19 +00:00
|
|
|
static char tmpbuf[4096];
|
|
|
|
static int
|
|
|
|
debugout(hisaxinstance_t *inst, logdata_t *log)
|
|
|
|
{
|
|
|
|
char *p = tmpbuf;
|
|
|
|
|
|
|
|
if (log->head && *log->head)
|
|
|
|
p += sprintf(p,"%s ", log->head);
|
|
|
|
else
|
|
|
|
p += sprintf(p,"%s ", inst->obj->name);
|
|
|
|
p += vsprintf(p, log->fmt, log->args);
|
|
|
|
printk(KERN_DEBUG "%s\n", tmpbuf);
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int central_manager(void *data, u_int prim, void *arg) {
|
|
|
|
hisaxstack_t *st = data;
|
|
|
|
|
2001-03-26 11:40:02 +00:00
|
|
|
if ((prim != (MGR_NEWSTACK | REQUEST)) &&
|
|
|
|
(prim != (MGR_DISCONNECT | REQUEST)) && !data)
|
2001-02-11 22:46:19 +00:00
|
|
|
return(-EINVAL);
|
|
|
|
switch(prim) {
|
2001-03-26 11:40:02 +00:00
|
|
|
case MGR_NEWSTACK | REQUEST:
|
|
|
|
if (!(st = new_stack(data, arg)))
|
2001-02-27 17:45:44 +00:00
|
|
|
return(-EINVAL);
|
|
|
|
return(0);
|
|
|
|
case MGR_SETSTACK | REQUEST:
|
|
|
|
return(set_stack(st, arg));
|
|
|
|
case MGR_CLEARSTACK | REQUEST:
|
|
|
|
return(clear_stack(st));
|
2001-03-03 08:07:30 +00:00
|
|
|
case MGR_DELSTACK | REQUEST:
|
|
|
|
return(release_stack(st));
|
2001-03-26 11:40:02 +00:00
|
|
|
case MGR_REGLAYER | INDICATION:
|
2001-03-03 08:07:30 +00:00
|
|
|
return(register_layer(st, arg));
|
2001-03-26 11:40:02 +00:00
|
|
|
case MGR_REGLAYER | REQUEST:
|
2001-03-03 08:07:30 +00:00
|
|
|
if (!register_layer(st, arg)) {
|
2001-02-27 17:45:44 +00:00
|
|
|
hisaxinstance_t *inst = arg;
|
2001-03-26 11:40:02 +00:00
|
|
|
return(inst->obj->own_ctrl(arg, MGR_REGLAYER | CONFIRM, NULL));
|
2001-02-27 17:45:44 +00:00
|
|
|
}
|
2001-03-26 11:40:02 +00:00
|
|
|
return(-EINVAL);
|
|
|
|
case MGR_UNREGLAYER | REQUEST:
|
2001-03-27 15:34:20 +00:00
|
|
|
return(unregister_instance(data));
|
2001-03-26 11:40:02 +00:00
|
|
|
case MGR_DISCONNECT | REQUEST:
|
|
|
|
case MGR_DISCONNECT | INDICATION:
|
|
|
|
return(disconnect_if(data, prim, arg));
|
2001-04-11 10:21:10 +00:00
|
|
|
case MGR_ADDIF | REQUEST:
|
|
|
|
return(add_if(data, prim, arg));
|
2001-03-27 15:34:20 +00:00
|
|
|
case MGR_CONNECT | REQUEST:
|
|
|
|
return(ConnectIF(data, arg));
|
2001-02-27 17:45:44 +00:00
|
|
|
case MGR_LOADFIRM | REQUEST:
|
|
|
|
if (st->mgr && st->mgr->obj && st->mgr->obj->own_ctrl)
|
2001-03-26 11:40:02 +00:00
|
|
|
return(st->mgr->obj->own_ctrl(st->mgr, prim, arg));
|
2001-02-27 17:45:44 +00:00
|
|
|
break;
|
2001-02-11 22:46:19 +00:00
|
|
|
case MGR_DEBUGDATA | REQUEST:
|
|
|
|
return(debugout(data, arg));
|
|
|
|
default:
|
|
|
|
printk(KERN_WARNING "manager prim %x not handled\n", prim);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return(-EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
hisaxlock_core(void) {
|
|
|
|
#ifdef MODULE
|
|
|
|
MOD_INC_USE_COUNT;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
hisaxunlock_core(void) {
|
|
|
|
#ifdef MODULE
|
|
|
|
MOD_DEC_USE_COUNT;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
int HiSax_register(hisaxobject_t *obj) {
|
|
|
|
|
|
|
|
if (!obj)
|
|
|
|
return(-EINVAL);
|
2001-03-11 21:23:39 +00:00
|
|
|
obj->id = obj_id++;
|
2001-02-11 22:46:19 +00:00
|
|
|
APPEND_TO_LIST(obj, hisax_objects);
|
|
|
|
obj->ctrl = central_manager;
|
|
|
|
// register_prop
|
|
|
|
if (debug)
|
2001-03-11 21:23:39 +00:00
|
|
|
printk(KERN_DEBUG "HiSax_register %s id %x\n", obj->name,
|
|
|
|
obj->id);
|
2001-02-11 22:46:19 +00:00
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int HiSax_unregister(hisaxobject_t *obj) {
|
|
|
|
|
|
|
|
if (!obj)
|
|
|
|
return(-EINVAL);
|
|
|
|
if (debug)
|
|
|
|
printk(KERN_DEBUG "HiSax_unregister %s %d refs\n",
|
|
|
|
obj->name, obj->refcnt);
|
2001-03-04 17:08:33 +00:00
|
|
|
if (obj->DPROTO.protocol[0])
|
2001-02-11 22:46:19 +00:00
|
|
|
release_stacks(obj);
|
|
|
|
else
|
|
|
|
remove_object(obj);
|
|
|
|
REMOVE_FROM_LISTBASE(obj, hisax_objects);
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
HiSaxInit(void)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
2001-02-22 10:14:16 +00:00
|
|
|
core_debug = debug;
|
2001-02-11 22:46:19 +00:00
|
|
|
err = init_hisaxdev(debug);
|
|
|
|
return(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef MODULE
|
|
|
|
void cleanup_module(void) {
|
2001-03-03 08:07:30 +00:00
|
|
|
hisaxstack_t *st;
|
2001-02-11 22:46:19 +00:00
|
|
|
|
|
|
|
free_hisaxdev();
|
|
|
|
if (hisax_objects) {
|
|
|
|
printk(KERN_WARNING "hisaxcore hisax_objects not empty\n");
|
|
|
|
}
|
|
|
|
if (hisax_stacklist) {
|
|
|
|
printk(KERN_WARNING "hisaxcore hisax_stacklist not empty\n");
|
2001-03-03 08:07:30 +00:00
|
|
|
st = hisax_stacklist;
|
|
|
|
while (st) {
|
|
|
|
printk(KERN_WARNING "hisaxcore st %x in list\n",
|
|
|
|
st->id);
|
|
|
|
if (st == st->next) {
|
|
|
|
printk(KERN_WARNING "hisaxcore st == next\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
st = st->next;
|
|
|
|
}
|
2001-02-11 22:46:19 +00:00
|
|
|
}
|
|
|
|
printk(KERN_DEBUG "hisaxcore unloaded\n");
|
|
|
|
}
|
|
|
|
#endif
|