mISDN/drivers/isdn/hardware/mISDN/capi.c

302 lines
6.5 KiB
C
Raw Normal View History

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;
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