patch-2.3.99-pre3 linux/drivers/isdn/avmb1/capidrv.c
Next file: linux/drivers/isdn/avmb1/capifs.c
Previous file: linux/drivers/isdn/avmb1/capidev.h
Back to the patch index
Back to the overall index
- Lines: 278
- Date:
Thu Mar 23 08:38:57 2000
- Orig file:
v2.3.99-pre2/linux/drivers/isdn/avmb1/capidrv.c
- Orig date:
Wed Feb 16 17:03:52 2000
diff -u --recursive --new-file v2.3.99-pre2/linux/drivers/isdn/avmb1/capidrv.c linux/drivers/isdn/avmb1/capidrv.c
@@ -1,11 +1,22 @@
/*
- * $Id: capidrv.c,v 1.29 1999/12/06 17:13:06 calle Exp $
+ * $Id: capidrv.c,v 1.30 2000/03/03 15:50:42 calle Exp $
*
* ISDN4Linux Driver, using capi20 interface (kernelcapi)
*
* Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: capidrv.c,v $
+ * Revision 1.30 2000/03/03 15:50:42 calle
+ * - kernel CAPI:
+ * - Changed parameter "param" in capi_signal from __u32 to void *.
+ * - rewrote notifier handling in kcapi.c
+ * - new notifier NCCI_UP and NCCI_DOWN
+ * - User CAPI:
+ * - /dev/capi20 is now a cloning device.
+ * - middleware extentions prepared.
+ * - capidrv.c
+ * - locking of list operations and module count updates.
+ *
* Revision 1.29 1999/12/06 17:13:06 calle
* Added controller watchdog.
*
@@ -171,7 +182,7 @@
#include "capicmd.h"
#include "capidrv.h"
-static char *revision = "$Revision: 1.29 $";
+static char *revision = "$Revision: 1.30 $";
int debugmode = 0;
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
@@ -440,25 +451,33 @@
static inline capidrv_contr *findcontrbydriverid(int driverid)
{
capidrv_contr *p = global.contr_list;
+ long flags;
+ save_flags(flags);
+ cli();
while (p) {
if (p->myid == driverid)
- return p;
+ break;
p = p->next;
}
- return (capidrv_contr *) 0;
+ restore_flags(flags);
+ return p;
}
static capidrv_contr *findcontrbynumber(__u32 contr)
{
capidrv_contr *p = global.contr_list;
+ long flags;
+ save_flags(flags);
+ cli();
while (p) {
if (p->contrnr == contr)
- return p;
+ break;
p = p->next;
}
- return (capidrv_contr *) 0;
+ restore_flags(flags);
+ return p;
}
@@ -1501,7 +1520,7 @@
static _cmsg s_cmsg;
-static void capidrv_signal(__u16 applid, __u32 dummy)
+static void capidrv_signal(__u16 applid, void *dummy)
{
struct sk_buff *skb = 0;
@@ -2218,14 +2237,18 @@
static int capidrv_addcontr(__u16 contr, struct capi_profile *profp)
{
capidrv_contr *card;
+ long flags;
isdn_ctrl cmd;
char id[20];
int i;
+ MOD_INC_USE_COUNT;
+
sprintf(id, "capidrv-%d", contr);
if (!(card = (capidrv_contr *) kmalloc(sizeof(capidrv_contr), GFP_ATOMIC))) {
printk(KERN_WARNING
"capidrv: (%s) Could not allocate contr-struct.\n", id);
+ MOD_DEC_USE_COUNT;
return -1;
}
memset(card, 0, sizeof(capidrv_contr));
@@ -2238,6 +2261,7 @@
printk(KERN_WARNING
"capidrv: (%s) Could not allocate bchan-structs.\n", id);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -1;
}
card->interface.channels = profp->nbchannel;
@@ -2258,29 +2282,35 @@
ISDN_FEATURE_P_UNKNOWN;
card->interface.hl_hdrlen = 22; /* len of DATA_B3_REQ */
strncpy(card->interface.id, id, sizeof(card->interface.id) - 1);
- card->next = global.contr_list;
- global.contr_list = card;
- global.ncontr++;
+
+
card->q931_read = card->q931_buf;
card->q931_write = card->q931_buf;
card->q931_end = card->q931_buf + sizeof(card->q931_buf) - 1;
if (!register_isdn(&card->interface)) {
- global.contr_list = global.contr_list->next;
printk(KERN_ERR "capidrv: Unable to register contr %s\n", id);
kfree(card->bchans);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -1;
}
card->myid = card->interface.channels;
+ save_flags(flags);
+ cli();
+ card->next = global.contr_list;
+ global.contr_list = card;
+ global.ncontr++;
+ restore_flags(flags);
+
memset(card->bchans, 0, sizeof(capidrv_bchan) * card->nbchan);
for (i = 0; i < card->nbchan; i++) {
card->bchans[i].contr = card;
}
- cmd.driver = card->myid;
cmd.command = ISDN_STAT_RUN;
+ cmd.driver = card->myid;
card->interface.statcallb(&cmd);
card->cipmask = 0x1FFF03FF; /* any */
@@ -2304,30 +2334,41 @@
{
capidrv_contr **pp, *card;
isdn_ctrl cmd;
+ long flags;
int i;
+ save_flags(flags);
+ cli();
for (pp = &global.contr_list; *pp; pp = &(*pp)->next) {
if ((*pp)->contrnr == contr)
break;
}
if (!*pp) {
+ restore_flags(flags);
printk(KERN_ERR "capidrv: delcontr: no contr %u\n", contr);
return -1;
}
card = *pp;
+ *pp = (*pp)->next;
+ global.ncontr--;
+ restore_flags(flags);
if (debugmode)
printk(KERN_DEBUG "capidrv-%d: id=%d unloading\n",
card->contrnr, card->myid);
- cmd.command = ISDN_STAT_UNLOAD;
+ cmd.command = ISDN_STAT_STOP;
cmd.driver = card->myid;
card->interface.statcallb(&cmd);
- *pp = (*pp)->next;
- global.ncontr--;
-
for (i = 0; i < card->nbchan; i++) {
+
+ cmd.command = ISDN_STAT_DISCH;
+ cmd.driver = card->myid;
+ cmd.arg = i;
+ cmd.parm.num[0] = 0;
+ card->interface.statcallb(&cmd);
+
if (card->bchans[i].nccip)
free_ncci(card, card->bchans[i].nccip);
if (card->bchans[i].plcip)
@@ -2338,10 +2379,16 @@
kfree(card->bchans);
del_timer(&card->listentimer);
- printk(KERN_INFO "%s: now down.\n", card->name);
+ cmd.command = ISDN_STAT_UNLOAD;
+ cmd.driver = card->myid;
+ card->interface.statcallb(&cmd);
kfree(card);
+ printk(KERN_INFO "%s: now down.\n", card->name);
+
+ MOD_DEC_USE_COUNT;
+
return 0;
}
@@ -2438,10 +2485,14 @@
__u32 ncontr, contr;
__u16 errcode;
+ MOD_INC_USE_COUNT;
+
capifuncs = attach_capi_interface(&cuser);
- if (!capifuncs)
+ if (!capifuncs) {
+ MOD_DEC_USE_COUNT;
return -EIO;
+ }
if ((p = strchr(revision, ':'))) {
strcpy(rev, p + 1);
@@ -2456,6 +2507,7 @@
errcode = (*capifuncs->capi_register) (&rparam, &global.appid);
if (errcode) {
detach_capi_interface(&cuser);
+ MOD_DEC_USE_COUNT;
return -EIO;
}
@@ -2463,6 +2515,7 @@
if (errcode != CAPI_NOERROR) {
(void) (*capifuncs->capi_release) (global.appid);
detach_capi_interface(&cuser);
+ MOD_DEC_USE_COUNT;
return -EIO;
}
@@ -2477,6 +2530,9 @@
}
proc_init();
+ printk(KERN_NOTICE "capidrv: Rev%s: loaded\n", rev);
+ MOD_DEC_USE_COUNT;
+
return 0;
}
@@ -2484,6 +2540,7 @@
void cleanup_module(void)
{
capidrv_contr *card, *next;
+ long flags;
char rev[10];
char *p;
@@ -2498,8 +2555,15 @@
for (card = global.contr_list; card; card = next) {
next = card->next;
disable_dchannel_trace(card);
+ }
+
+ save_flags(flags);
+ cli();
+ for (card = global.contr_list; card; card = next) {
+ next = card->next;
capidrv_delcontr(card->contrnr);
}
+ restore_flags(flags);
(void) (*capifuncs->capi_release) (global.appid);
detach_capi_interface(&cuser);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)