2001-02-21 19:22:35 +00:00
|
|
|
/* $Id$
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/module.h>
|
2001-02-27 17:45:44 +00:00
|
|
|
#include <linux/vmalloc.h>
|
|
|
|
#include <asm/uaccess.h>
|
2001-02-21 19:22:35 +00:00
|
|
|
#include "hisax_capi.h"
|
|
|
|
#include "helper.h"
|
|
|
|
#include "debug.h"
|
|
|
|
|
|
|
|
const char *capi_revision = "$Revision$";
|
|
|
|
|
|
|
|
static int debug = 0;
|
|
|
|
static hisaxobject_t capi_obj;
|
|
|
|
|
|
|
|
|
|
|
|
static char MName[] = "HiSax Capi 2.0";
|
|
|
|
|
|
|
|
#ifdef MODULE
|
|
|
|
MODULE_AUTHOR("Karsten Keil");
|
2002-09-16 23:49:38 +00:00
|
|
|
#ifdef MODULE_LICENSE
|
|
|
|
MODULE_LICENSE("GPL");
|
|
|
|
#endif
|
2001-02-21 19:22:35 +00:00
|
|
|
MODULE_PARM(debug, "1i");
|
|
|
|
#define Capi20Init init_module
|
|
|
|
#endif
|
|
|
|
|
2001-02-22 05:54:40 +00:00
|
|
|
static char deb_buf[256];
|
|
|
|
|
|
|
|
void capidebug(int level, char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
|
|
|
|
if (debug & level) {
|
|
|
|
va_start(args, fmt);
|
|
|
|
vsprintf(deb_buf, fmt, args);
|
|
|
|
printk(KERN_DEBUG "%s\n", deb_buf);
|
|
|
|
va_end(args);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-02-21 19:22:35 +00:00
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// registration to kernelcapi
|
|
|
|
|
|
|
|
int hisax_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
|
|
|
|
{
|
|
|
|
Contr_t *contr = ctrl->driverdata;
|
2001-02-27 17:45:44 +00:00
|
|
|
u_char *tmp;
|
|
|
|
int retval;
|
|
|
|
|
2002-09-16 23:49:38 +00:00
|
|
|
printk(KERN_INFO "%s: firm user(%d) len(%d)\n", __FUNCTION__,
|
2001-02-27 17:45:44 +00:00
|
|
|
data->firmware.user, data->firmware.len);
|
2002-09-16 23:49:38 +00:00
|
|
|
printk(KERN_INFO "%s: cfg user(%d) len(%d)\n", __FUNCTION__,
|
2001-02-27 17:45:44 +00:00
|
|
|
data->configuration.user, data->configuration.len);
|
|
|
|
if (data->firmware.user) {
|
|
|
|
tmp = vmalloc(data->firmware.len);
|
|
|
|
if (!tmp)
|
|
|
|
return(-ENOMEM);
|
|
|
|
retval = copy_from_user(tmp, data->firmware.data,
|
|
|
|
data->firmware.len);
|
|
|
|
if (retval)
|
|
|
|
return(retval);
|
|
|
|
} else
|
|
|
|
tmp = data->firmware.data;
|
|
|
|
contrLoadFirmware(contr, data->firmware.len, tmp);
|
|
|
|
if (data->firmware.user)
|
|
|
|
vfree(tmp);
|
2001-02-21 19:22:35 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void hisax_reset_ctr(struct capi_ctr *ctrl)
|
|
|
|
{
|
|
|
|
Contr_t *contr = ctrl->driverdata;
|
|
|
|
|
2002-09-16 23:49:38 +00:00
|
|
|
printk(KERN_DEBUG "%s\n", __FUNCTION__);
|
2001-02-21 19:22:35 +00:00
|
|
|
contrReset(contr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hisax_remove_ctr(struct capi_ctr *ctrl)
|
|
|
|
{
|
2002-09-16 23:49:38 +00:00
|
|
|
printk(KERN_DEBUG "%s\n", __FUNCTION__);
|
2001-02-27 17:45:44 +00:00
|
|
|
// int_error();
|
2001-02-21 19:22:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *hisax_procinfo(struct capi_ctr *ctrl)
|
|
|
|
{
|
|
|
|
Contr_t *contr = (ctrl->driverdata);
|
|
|
|
|
2002-09-16 23:49:38 +00:00
|
|
|
printk(KERN_DEBUG "%s\n", __FUNCTION__);
|
2001-02-21 19:22:35 +00:00
|
|
|
if (!contr)
|
|
|
|
return "";
|
|
|
|
sprintf(contr->infobuf, "-");
|
|
|
|
return contr->infobuf;
|
|
|
|
}
|
|
|
|
|
|
|
|
void hisax_register_appl(struct capi_ctr *ctrl,
|
|
|
|
__u16 ApplId, capi_register_params *rp)
|
|
|
|
{
|
|
|
|
Contr_t *contr = ctrl->driverdata;
|
|
|
|
|
2002-09-16 23:49:38 +00:00
|
|
|
printk(KERN_DEBUG "%s\n", __FUNCTION__);
|
2001-02-21 19:22:35 +00:00
|
|
|
contrRegisterAppl(contr, ApplId, rp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hisax_release_appl(struct capi_ctr *ctrl, __u16 ApplId)
|
|
|
|
{
|
|
|
|
Contr_t *contr = ctrl->driverdata;
|
|
|
|
|
2002-09-16 23:49:38 +00:00
|
|
|
printk(KERN_DEBUG "%s\n", __FUNCTION__);
|
2001-02-21 19:22:35 +00:00
|
|
|
contrReleaseAppl(contr, ApplId);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hisax_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
Contr_t *contr = ctrl->driverdata;
|
|
|
|
|
|
|
|
contrSendMessage(contr, skb);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int hisax_read_proc(char *page, char **start, off_t off,
|
|
|
|
int count, int *eof, struct capi_ctr *ctrl)
|
|
|
|
{
|
|
|
|
int len = 0;
|
|
|
|
|
|
|
|
len += sprintf(page+len, "hisax_read_proc\n");
|
|
|
|
if (off+count >= len)
|
|
|
|
*eof = 1;
|
|
|
|
if (len < off)
|
|
|
|
return 0;
|
|
|
|
*start = page + off;
|
|
|
|
return ((count < len-off) ? count : len-off);
|
|
|
|
};
|
|
|
|
|
|
|
|
struct capi_driver_interface *cdrv_if;
|
|
|
|
|
|
|
|
struct capi_driver hisax_driver = {
|
|
|
|
"hisax",
|
|
|
|
"0.01",
|
|
|
|
hisax_load_firmware,
|
|
|
|
hisax_reset_ctr,
|
|
|
|
hisax_remove_ctr,
|
|
|
|
hisax_register_appl,
|
|
|
|
hisax_release_appl,
|
|
|
|
hisax_send_message,
|
|
|
|
hisax_procinfo,
|
|
|
|
hisax_read_proc,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
|
|
|
int CapiNew(void)
|
|
|
|
{
|
|
|
|
char tmp[64];
|
|
|
|
|
|
|
|
strcpy(tmp, capi_revision);
|
|
|
|
printk(KERN_INFO "HiSax: CAPI Revision %s\n", HiSax_getrev(tmp));
|
|
|
|
|
|
|
|
cdrv_if = attach_capi_driver(&hisax_driver);
|
|
|
|
|
|
|
|
if (!cdrv_if) {
|
|
|
|
printk(KERN_ERR "hisax: failed to attach capi_driver\n");
|
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
init_listen();
|
|
|
|
init_cplci();
|
|
|
|
init_ncci();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
capi20_manager(void *data, u_int prim, void *arg) {
|
2001-03-26 11:40:02 +00:00
|
|
|
hisaxinstance_t *inst = data;
|
|
|
|
int found=0;
|
2001-10-31 23:04:42 +00:00
|
|
|
BInst_t *binst = NULL;
|
2001-02-21 19:22:35 +00:00
|
|
|
Contr_t *ctrl = (Contr_t *)capi_obj.ilist;
|
|
|
|
|
2001-02-27 17:45:44 +00:00
|
|
|
printk(KERN_DEBUG "capi20_manager data:%p prim:%x arg:%p\n", data, prim, arg);
|
2001-02-21 19:22:35 +00:00
|
|
|
if (!data)
|
|
|
|
return(-EINVAL);
|
|
|
|
while(ctrl) {
|
2001-03-26 11:40:02 +00:00
|
|
|
if (&ctrl->inst == inst) {
|
|
|
|
found++;
|
2001-02-27 17:45:44 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
binst = ctrl->binst;
|
|
|
|
while(binst) {
|
2001-03-26 11:40:02 +00:00
|
|
|
if (&binst->inst == inst) {
|
|
|
|
found++;
|
2001-02-27 17:45:44 +00:00
|
|
|
break;
|
|
|
|
}
|
2001-03-05 01:48:27 +00:00
|
|
|
binst = binst->next;
|
2001-02-27 17:45:44 +00:00
|
|
|
}
|
2001-03-26 11:40:02 +00:00
|
|
|
if (found)
|
2001-02-21 19:22:35 +00:00
|
|
|
break;
|
|
|
|
ctrl = ctrl->next;
|
|
|
|
}
|
|
|
|
switch(prim) {
|
2001-03-26 11:40:02 +00:00
|
|
|
case MGR_NEWLAYER | REQUEST:
|
|
|
|
if (!(ctrl = newContr(&capi_obj, data, arg)))
|
|
|
|
return(-EINVAL);
|
|
|
|
break;
|
|
|
|
case MGR_CONNECT | REQUEST:
|
2001-02-21 19:22:35 +00:00
|
|
|
if (!ctrl) {
|
2001-03-26 11:40:02 +00:00
|
|
|
printk(KERN_WARNING "capi20_manager connect no instance\n");
|
|
|
|
return(-EINVAL);
|
2001-02-21 19:22:35 +00:00
|
|
|
}
|
2001-03-26 11:40:02 +00:00
|
|
|
return(ConnectIF(inst, arg));
|
2001-02-21 19:22:35 +00:00
|
|
|
break;
|
2001-03-26 11:40:02 +00:00
|
|
|
case MGR_SETIF | INDICATION:
|
|
|
|
case MGR_SETIF | REQUEST:
|
2001-02-21 19:22:35 +00:00
|
|
|
if (!ctrl) {
|
2001-03-26 11:40:02 +00:00
|
|
|
printk(KERN_WARNING "capi20_manager setif no instance\n");
|
2001-02-21 19:22:35 +00:00
|
|
|
return(-EINVAL);
|
|
|
|
}
|
2001-03-26 11:40:02 +00:00
|
|
|
if (&ctrl->inst == inst)
|
|
|
|
return(SetIF(inst, arg, prim, NULL, contrL3L4, ctrl));
|
|
|
|
else
|
|
|
|
return(SetIF(inst, arg, prim, NULL, ncci_l3l4, inst->data));
|
2001-02-21 19:22:35 +00:00
|
|
|
break;
|
2001-03-26 11:40:02 +00:00
|
|
|
case MGR_DISCONNECT | REQUEST:
|
|
|
|
case MGR_DISCONNECT | INDICATION:
|
|
|
|
if (!ctrl) {
|
|
|
|
printk(KERN_WARNING "capi20_manager disconnect no instance\n");
|
2001-03-03 08:07:30 +00:00
|
|
|
return(-EINVAL);
|
|
|
|
}
|
2001-03-26 11:40:02 +00:00
|
|
|
return(DisConnectIF(inst, arg));
|
2001-03-03 08:07:30 +00:00
|
|
|
break;
|
2001-02-21 19:22:35 +00:00
|
|
|
case MGR_RELEASE | INDICATION:
|
|
|
|
if (ctrl) {
|
|
|
|
printk(KERN_DEBUG "release_capi20 id %x\n", ctrl->inst.st->id);
|
2001-03-03 18:17:16 +00:00
|
|
|
contrDestr(ctrl);
|
|
|
|
kfree(ctrl);
|
2001-02-21 19:22:35 +00:00
|
|
|
} else
|
|
|
|
printk(KERN_WARNING "capi20_manager release no instance\n");
|
|
|
|
break;
|
2001-10-31 23:04:42 +00:00
|
|
|
case MGR_UNREGLAYER | REQUEST:
|
|
|
|
if (!ctrl) {
|
|
|
|
printk(KERN_WARNING "capi20_manager unreglayer no instance\n");
|
|
|
|
return(-EINVAL);
|
|
|
|
}
|
|
|
|
if (binst) {
|
|
|
|
capi_obj.ctrl(binst->inst.down.peer, MGR_DISCONNECT | REQUEST,
|
|
|
|
&binst->inst.down);
|
|
|
|
capi_obj.ctrl(&binst->inst, MGR_UNREGLAYER | REQUEST, NULL);
|
|
|
|
}
|
|
|
|
break;
|
2001-02-21 19:22:35 +00:00
|
|
|
default:
|
|
|
|
printk(KERN_WARNING "capi20_manager prim %x not handled\n", prim);
|
|
|
|
return(-EINVAL);
|
|
|
|
}
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int Capi20Init(void)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
2003-06-24 21:58:53 +00:00
|
|
|
SET_MODULE_OWNER(&capi_obj);
|
2001-02-21 19:22:35 +00:00
|
|
|
capi_obj.name = MName;
|
2001-03-04 17:08:33 +00:00
|
|
|
capi_obj.DPROTO.protocol[4] = ISDN_PID_L4_CAPI20;
|
|
|
|
capi_obj.BPROTO.protocol[4] = ISDN_PID_L4_B_CAPI20;
|
|
|
|
capi_obj.BPROTO.protocol[3] = ISDN_PID_L3_B_TRANS;
|
2001-02-21 19:22:35 +00:00
|
|
|
capi_obj.own_ctrl = capi20_manager;
|
|
|
|
capi_obj.prev = NULL;
|
|
|
|
capi_obj.next = NULL;
|
|
|
|
capi_obj.ilist = NULL;
|
|
|
|
if ((err = CapiNew()))
|
|
|
|
return(err);
|
|
|
|
if ((err = HiSax_register(&capi_obj))) {
|
|
|
|
printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
|
|
|
|
detach_capi_driver(&hisax_driver);
|
|
|
|
free_listen();
|
|
|
|
free_cplci();
|
|
|
|
free_ncci();
|
|
|
|
}
|
|
|
|
return(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef MODULE
|
|
|
|
void cleanup_module(void)
|
|
|
|
{
|
|
|
|
int err;
|
2001-03-03 18:17:16 +00:00
|
|
|
Contr_t *contr;
|
2001-02-21 19:22:35 +00:00
|
|
|
|
|
|
|
if ((err = HiSax_unregister(&capi_obj))) {
|
|
|
|
printk(KERN_ERR "Can't unregister User DSS1 error(%d)\n", err);
|
|
|
|
}
|
2001-03-03 18:17:16 +00:00
|
|
|
if (capi_obj.ilist) {
|
2001-02-21 19:22:35 +00:00
|
|
|
printk(KERN_WARNING "hisaxl3 contrlist not empty\n");
|
2001-03-03 18:17:16 +00:00
|
|
|
while((contr = capi_obj.ilist)) {
|
|
|
|
contrDestr(contr);
|
|
|
|
kfree(contr);
|
|
|
|
}
|
2001-02-21 19:22:35 +00:00
|
|
|
}
|
|
|
|
detach_capi_driver(&hisax_driver);
|
|
|
|
free_listen();
|
|
|
|
free_cplci();
|
|
|
|
free_ncci();
|
|
|
|
}
|
|
|
|
#endif
|