Commit 2658bb8b authored by Kai Germaschewski's avatar Kai Germaschewski

Merge tp1.ruhr-uni-bochum.de:/home/kai/kernel/v2.5/linux-2.5

into tp1.ruhr-uni-bochum.de:/home/kai/kernel/v2.5/linux-2.5.isdn
parents bdff23c1 960dc036
...@@ -6,11 +6,11 @@ O_TARGET := vmlinux-obj.o ...@@ -6,11 +6,11 @@ O_TARGET := vmlinux-obj.o
# Objects that export symbols. # Objects that export symbols.
export-objs := kcapi.o capiutil.o capifs.o export-objs := kcapi.o capiutil.o capilib.o capifs.o
# Multipart objects. # Multipart objects.
kernelcapi-objs := kcapi.o capiutil.o kernelcapi-objs := kcapi.o capiutil.o capilib.o
# Ordering constraints: kernelcapi.o first # Ordering constraints: kernelcapi.o first
......
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/isdn/capilli.h>
#define DBG(format, arg...) do { \
printk(KERN_DEBUG __FUNCTION__ ": " format "\n" , ## arg); \
} while (0)
struct capilib_msgidqueue {
struct capilib_msgidqueue *next;
u16 msgid;
};
struct capilib_ncci {
struct list_head list;
u16 applid;
u32 ncci;
u32 winsize;
int nmsg;
struct capilib_msgidqueue *msgidqueue;
struct capilib_msgidqueue *msgidlast;
struct capilib_msgidqueue *msgidfree;
struct capilib_msgidqueue msgidpool[CAPI_MAXDATAWINDOW];
};
// ---------------------------------------------------------------------------
// NCCI Handling
static inline void mq_init(struct capilib_ncci * np)
{
int i;
np->msgidqueue = 0;
np->msgidlast = 0;
np->nmsg = 0;
memset(np->msgidpool, 0, sizeof(np->msgidpool));
np->msgidfree = &np->msgidpool[0];
for (i = 1; i < np->winsize; i++) {
np->msgidpool[i].next = np->msgidfree;
np->msgidfree = &np->msgidpool[i];
}
}
static inline int mq_enqueue(struct capilib_ncci * np, u16 msgid)
{
struct capilib_msgidqueue *mq;
if ((mq = np->msgidfree) == 0)
return 0;
np->msgidfree = mq->next;
mq->msgid = msgid;
mq->next = 0;
if (np->msgidlast)
np->msgidlast->next = mq;
np->msgidlast = mq;
if (!np->msgidqueue)
np->msgidqueue = mq;
np->nmsg++;
return 1;
}
static inline int mq_dequeue(struct capilib_ncci * np, u16 msgid)
{
struct capilib_msgidqueue **pp;
for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) {
if ((*pp)->msgid == msgid) {
struct capilib_msgidqueue *mq = *pp;
*pp = mq->next;
if (mq == np->msgidlast)
np->msgidlast = 0;
mq->next = np->msgidfree;
np->msgidfree = mq;
np->nmsg--;
return 1;
}
}
return 0;
}
void capilib_new_ncci(struct list_head *head, u16 applid, u32 ncci, u32 winsize)
{
struct capilib_ncci *np;
np = kmalloc(sizeof(*np), GFP_ATOMIC);
if (!np) {
printk(KERN_WARNING "capilib_new_ncci: no memory.\n");
return;
}
if (winsize > CAPI_MAXDATAWINDOW) {
printk(KERN_ERR "capi_new_ncci: winsize %d too big\n",
winsize);
winsize = CAPI_MAXDATAWINDOW;
}
np->applid = applid;
np->ncci = ncci;
np->winsize = winsize;
mq_init(np);
list_add_tail(&np->list, head);
DBG("kcapi: appl %d ncci 0x%x up", applid, ncci);
}
EXPORT_SYMBOL(capilib_new_ncci);
void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci)
{
struct list_head *l;
struct capilib_ncci *np;
list_for_each(l, head) {
np = list_entry(l, struct capilib_ncci, list);
if (np->applid != applid)
continue;
if (np->ncci != ncci)
continue;
printk(KERN_INFO "kcapi: appl %d ncci 0x%x down\n", applid, ncci);
list_del(&np->list);
kfree(np);
return;
}
printk(KERN_ERR "capilib_free_ncci: ncci 0x%x not found\n", ncci);
}
EXPORT_SYMBOL(capilib_free_ncci);
void capilib_release_appl(struct list_head *head, u16 applid)
{
struct list_head *l, *n;
struct capilib_ncci *np;
list_for_each_safe(l, n, head) {
np = list_entry(l, struct capilib_ncci, list);
if (np->applid != applid)
continue;
printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down\n", applid, np->ncci);
list_del(&np->list);
kfree(np);
}
}
EXPORT_SYMBOL(capilib_release_appl);
void capilib_release(struct list_head *head)
{
struct list_head *l, *n;
struct capilib_ncci *np;
list_for_each_safe(l, n, head) {
np = list_entry(l, struct capilib_ncci, list);
printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down\n", np->applid, np->ncci);
list_del(&np->list);
kfree(np);
}
}
EXPORT_SYMBOL(capilib_release);
u16 capilib_data_b3_req(struct list_head *head, u16 applid, u32 ncci, u16 msgid)
{
struct list_head *l;
struct capilib_ncci *np;
list_for_each(l, head) {
np = list_entry(l, struct capilib_ncci, list);
if (np->applid != applid)
continue;
if (np->ncci != ncci)
continue;
if (mq_enqueue(np, msgid) == 0)
return CAPI_SENDQUEUEFULL;
return CAPI_NOERROR;
}
printk(KERN_ERR "capilib_data_b3_req: ncci 0x%x not found\n", ncci);
return CAPI_NOERROR;
}
EXPORT_SYMBOL(capilib_data_b3_req);
void capilib_data_b3_conf(struct list_head *head, u16 applid, u32 ncci, u16 msgid)
{
struct list_head *l;
struct capilib_ncci *np;
list_for_each(l, head) {
np = list_entry(l, struct capilib_ncci, list);
if (np->applid != applid)
continue;
if (np->ncci != ncci)
continue;
if (mq_dequeue(np, msgid) == 0) {
printk(KERN_ERR "kcapi: msgid %hu ncci 0x%x not on queue\n",
msgid, ncci);
}
return;
}
printk(KERN_ERR "capilib_data_b3_conf: ncci 0x%x not found\n", ncci);
}
EXPORT_SYMBOL(capilib_data_b3_conf);
...@@ -55,23 +55,6 @@ MODULE_PARM(showcapimsgs, "i"); ...@@ -55,23 +55,6 @@ MODULE_PARM(showcapimsgs, "i");
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
struct msgidqueue {
struct msgidqueue *next;
u16 msgid;
};
struct capi_ncci {
struct capi_ncci *next;
u16 applid;
u32 ncci;
u32 winsize;
int nmsg;
struct msgidqueue *msgidqueue;
struct msgidqueue *msgidlast;
struct msgidqueue *msgidfree;
struct msgidqueue msgidpool[CAPI_MAXDATAWINDOW];
};
struct capi_appl { struct capi_appl {
u16 applid; u16 applid;
capi_register_params rparam; capi_register_params rparam;
...@@ -245,45 +228,6 @@ static int proc_applications_read_proc(char *page, char **start, off_t off, ...@@ -245,45 +228,6 @@ static int proc_applications_read_proc(char *page, char **start, off_t off,
return len; return len;
} }
/*
* /proc/capi/ncci:
* applid ncci winsize nblk
*/
static int proc_ncci_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
struct capi_appl *ap;
struct capi_ncci *np;
int i;
int len = 0;
for (i=1; i <= CAPI_MAXAPPL; i++) {
ap = get_capi_appl_by_nr(i);
if (!ap) continue;
for (np = ap->nccilist; np; np = np->next) {
len += sprintf(page+len, "%d 0x%x %d %d\n",
np->applid,
np->ncci,
np->winsize,
np->nmsg);
if (len <= off) {
off -= len;
len = 0;
} else {
if (len-off > count)
goto endloop;
}
}
}
endloop:
*start = page+off;
if (len < count)
*eof = 1;
if (len>count) len = count;
if (len<0) len = 0;
return len;
}
/* /*
* /proc/capi/driver: * /proc/capi/driver:
* driver ncontroller * driver ncontroller
...@@ -477,7 +421,6 @@ static struct procfsentries { ...@@ -477,7 +421,6 @@ static struct procfsentries {
} procfsentries[] = { } procfsentries[] = {
{ "capi", S_IFDIR, 0 }, { "capi", S_IFDIR, 0 },
{ "capi/applications", 0 , proc_applications_read_proc }, { "capi/applications", 0 , proc_applications_read_proc },
{ "capi/ncci", 0 , proc_ncci_read_proc },
{ "capi/driver", 0 , proc_driver_read_proc }, { "capi/driver", 0 , proc_driver_read_proc },
{ "capi/users", 0 , proc_users_read_proc }, { "capi/users", 0 , proc_users_read_proc },
{ "capi/controller", 0 , proc_controller_read_proc }, { "capi/controller", 0 , proc_controller_read_proc },
...@@ -525,26 +468,9 @@ static void register_appl(struct capi_ctr *card, u16 applid, capi_register_param ...@@ -525,26 +468,9 @@ static void register_appl(struct capi_ctr *card, u16 applid, capi_register_param
static void release_appl(struct capi_ctr *card, u16 applid) static void release_appl(struct capi_ctr *card, u16 applid)
{ {
struct capi_appl *ap = get_capi_appl_by_nr(applid); DBG("applid %#x", applid);
struct capi_ncci **pp, **nextpp;
DBG("");
for (pp = &ap->nccilist; *pp; pp = nextpp) {
if (NCCI2CTRL((*pp)->ncci) == card->cnr) {
struct capi_ncci *np = *pp;
*pp = np->next;
printk(KERN_INFO "kcapi: appl %d ncci 0x%x down!\n", applid, np->ncci);
kfree(np);
ap->nncci--;
nextpp = pp;
} else {
nextpp = &(*pp)->next;
}
}
card->driver->release_appl(card, applid); card->driver->release_appl(card, applid);
capi_ctr_put(card); capi_ctr_put(card);
} }
...@@ -679,130 +605,12 @@ static void notify_handler(void *dummy) ...@@ -679,130 +605,12 @@ static void notify_handler(void *dummy)
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
} }
/* -------- NCCI Handling ------------------------------------- */
static inline void mq_init(struct capi_ncci * np)
{
int i;
np->msgidqueue = 0;
np->msgidlast = 0;
np->nmsg = 0;
memset(np->msgidpool, 0, sizeof(np->msgidpool));
np->msgidfree = &np->msgidpool[0];
for (i = 1; i < np->winsize; i++) {
np->msgidpool[i].next = np->msgidfree;
np->msgidfree = &np->msgidpool[i];
}
}
static inline int mq_enqueue(struct capi_ncci * np, u16 msgid)
{
struct msgidqueue *mq;
if ((mq = np->msgidfree) == 0)
return 0;
np->msgidfree = mq->next;
mq->msgid = msgid;
mq->next = 0;
if (np->msgidlast)
np->msgidlast->next = mq;
np->msgidlast = mq;
if (!np->msgidqueue)
np->msgidqueue = mq;
np->nmsg++;
return 1;
}
static inline int mq_dequeue(struct capi_ncci * np, u16 msgid)
{
struct msgidqueue **pp;
for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) {
if ((*pp)->msgid == msgid) {
struct msgidqueue *mq = *pp;
*pp = mq->next;
if (mq == np->msgidlast)
np->msgidlast = 0;
mq->next = np->msgidfree;
np->msgidfree = mq;
np->nmsg--;
return 1;
}
}
return 0;
}
/*
* ncci management
*/
static void controllercb_new_ncci(struct capi_ctr * card,
u16 appl, u32 ncci, u32 winsize)
{
struct capi_ncci *np;
struct capi_appl *ap = get_capi_appl_by_nr(appl);
if (!ap) {
printk(KERN_ERR "avmb1_handle_new_ncci: illegal appl %d\n", appl);
return;
}
if ((np = (struct capi_ncci *) kmalloc(sizeof(struct capi_ncci), GFP_ATOMIC)) == 0) {
printk(KERN_ERR "capi_new_ncci: alloc failed ncci 0x%x\n", ncci);
return;
}
if (winsize > CAPI_MAXDATAWINDOW) {
printk(KERN_ERR "capi_new_ncci: winsize %d too big, set to %d\n",
winsize, CAPI_MAXDATAWINDOW);
winsize = CAPI_MAXDATAWINDOW;
}
np->applid = appl;
np->ncci = ncci;
np->winsize = winsize;
mq_init(np);
np->next = ap->nccilist;
ap->nccilist = np;
ap->nncci++;
printk(KERN_INFO "kcapi: appl %d ncci 0x%x up\n", appl, ncci);
}
static void controllercb_free_ncci(struct capi_ctr * card,
u16 appl, u32 ncci)
{
struct capi_ncci **pp;
struct capi_appl *ap = get_capi_appl_by_nr(appl);
if (!ap) {
printk(KERN_ERR "free_ncci: illegal appl %d\n", appl);
return;
}
for (pp = &ap->nccilist; *pp; pp = &(*pp)->next) {
if ((*pp)->ncci == ncci) {
struct capi_ncci *np = *pp;
*pp = np->next;
kfree(np);
ap->nncci--;
printk(KERN_INFO "kcapi: appl %d ncci 0x%x down\n", appl, ncci);
return;
}
}
printk(KERN_ERR "free_ncci: ncci 0x%x not found\n", ncci);
}
static struct capi_ncci *find_ncci(struct capi_appl * app, u32 ncci)
{
struct capi_ncci *np;
for (np = app->nccilist; np; np = np->next) {
if (np->ncci == ncci)
return np;
}
return 0;
}
/* -------- Receiver ------------------------------------------ */ /* -------- Receiver ------------------------------------------ */
static void recv_handler(void *dummy) static void recv_handler(void *dummy)
{ {
struct sk_buff *skb; struct sk_buff *skb;
struct capi_appl *ap; struct capi_appl *ap;
struct capi_ncci *np;
while ((skb = skb_dequeue(&recv_queue)) != 0) { while ((skb = skb_dequeue(&recv_queue)) != 0) {
ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data)); ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data));
...@@ -818,13 +626,6 @@ static void recv_handler(void *dummy) ...@@ -818,13 +626,6 @@ static void recv_handler(void *dummy)
kfree_skb(skb); kfree_skb(skb);
continue; continue;
} }
if ( CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
&& CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF
&& (np = find_ncci(ap, CAPIMSG_NCCI(skb->data))) != 0
&& mq_dequeue(np, CAPIMSG_MSGID(skb->data)) == 0) {
printk(KERN_ERR "kcapi: msgid %hu ncci 0x%x not on queue\n",
CAPIMSG_MSGID(skb->data), np->ncci);
}
if ( CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3 if ( CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
&& CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) { && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {
ap->nrecvdatapkt++; ap->nrecvdatapkt++;
...@@ -917,22 +718,9 @@ static void controllercb_reseted(struct capi_ctr * card) ...@@ -917,22 +718,9 @@ static void controllercb_reseted(struct capi_ctr * card)
for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
struct capi_appl *ap = get_capi_appl_by_nr(appl); struct capi_appl *ap = get_capi_appl_by_nr(appl);
struct capi_ncci **pp, **nextpp;
if (!ap) if (!ap)
continue; continue;
for (pp = &ap->nccilist; *pp; pp = nextpp) {
if (NCCI2CTRL((*pp)->ncci) == card->cnr) {
struct capi_ncci *np = *pp;
*pp = np->next;
printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down!\n", appl, np->ncci);
kfree(np);
nextpp = pp;
} else {
nextpp = &(*pp)->next;
}
}
capi_ctr_put(card); capi_ctr_put(card);
} }
...@@ -993,8 +781,6 @@ attach_capi_ctr(struct capi_driver *driver, char *name, void *driverdata) ...@@ -993,8 +781,6 @@ attach_capi_ctr(struct capi_driver *driver, char *name, void *driverdata)
card->suspend_output = controllercb_suspend_output; card->suspend_output = controllercb_suspend_output;
card->resume_output = controllercb_resume_output; card->resume_output = controllercb_resume_output;
card->handle_capimsg = controllercb_handle_capimsg; card->handle_capimsg = controllercb_handle_capimsg;
card->new_ncci = controllercb_new_ncci;
card->free_ncci = controllercb_free_ncci;
list_add_tail(&card->driver_list, &driver->contr_head); list_add_tail(&card->driver_list, &driver->contr_head);
driver->ncontroller++; driver->ncontroller++;
...@@ -1185,7 +971,6 @@ static u16 capi_put_message(u16 applid, struct sk_buff *skb) ...@@ -1185,7 +971,6 @@ static u16 capi_put_message(u16 applid, struct sk_buff *skb)
{ {
struct capi_ctr *card; struct capi_ctr *card;
struct capi_appl *ap; struct capi_appl *ap;
struct capi_ncci *np;
int showctl = 0; int showctl = 0;
u8 cmd, subcmd; u8 cmd, subcmd;
...@@ -1213,9 +998,6 @@ static u16 capi_put_message(u16 applid, struct sk_buff *skb) ...@@ -1213,9 +998,6 @@ static u16 capi_put_message(u16 applid, struct sk_buff *skb)
subcmd = CAPIMSG_SUBCOMMAND(skb->data); subcmd = CAPIMSG_SUBCOMMAND(skb->data);
if (cmd == CAPI_DATA_B3 && subcmd== CAPI_REQ) { if (cmd == CAPI_DATA_B3 && subcmd== CAPI_REQ) {
if ((np = find_ncci(ap, CAPIMSG_NCCI(skb->data))) != 0
&& mq_enqueue(np, CAPIMSG_MSGID(skb->data)) == 0)
return CAPI_SENDQUEUEFULL;
card->nsentdatapkt++; card->nsentdatapkt++;
ap->nsentdatapkt++; ap->nsentdatapkt++;
if (card->traceflag > 2) showctl |= 2; if (card->traceflag > 2) showctl |= 2;
...@@ -1239,8 +1021,7 @@ static u16 capi_put_message(u16 applid, struct sk_buff *skb) ...@@ -1239,8 +1021,7 @@ static u16 capi_put_message(u16 applid, struct sk_buff *skb)
} }
} }
card->driver->send_message(card, skb); return card->driver->send_message(card, skb);
return CAPI_NOERROR;
} }
static u16 capi_get_message(u16 applid, struct sk_buff **msgp) static u16 capi_get_message(u16 applid, struct sk_buff **msgp)
...@@ -1354,54 +1135,13 @@ static struct capi_driver *find_driver(char *name) ...@@ -1354,54 +1135,13 @@ static struct capi_driver *find_driver(char *name)
static int old_capi_manufacturer(unsigned int cmd, void *data) static int old_capi_manufacturer(unsigned int cmd, void *data)
{ {
avmb1_loadandconfigdef ldef; avmb1_loadandconfigdef ldef;
avmb1_extcarddef cdef;
avmb1_resetdef rdef; avmb1_resetdef rdef;
avmb1_getdef gdef; avmb1_getdef gdef;
struct capi_driver *driver;
struct capi_ctr *card; struct capi_ctr *card;
capicardparams cparams;
capiloaddata ldata; capiloaddata ldata;
int retval; int retval;
switch (cmd) { switch (cmd) {
case AVMB1_ADDCARD:
case AVMB1_ADDCARD_WITH_TYPE:
if (cmd == AVMB1_ADDCARD) {
if ((retval = copy_from_user((void *) &cdef, data,
sizeof(avmb1_carddef))))
return retval;
cdef.cardtype = AVM_CARDTYPE_B1;
} else {
if ((retval = copy_from_user((void *) &cdef, data,
sizeof(avmb1_extcarddef))))
return retval;
}
cparams.port = cdef.port;
cparams.irq = cdef.irq;
cparams.cardnr = cdef.cardnr;
switch (cdef.cardtype) {
case AVM_CARDTYPE_B1:
driver = find_driver("b1isa");
break;
case AVM_CARDTYPE_T1:
driver = find_driver("t1isa");
break;
default:
driver = 0;
break;
}
if (!driver) {
printk(KERN_ERR "kcapi: driver not loaded.\n");
return -EIO;
}
if (!driver->add_card) {
printk(KERN_ERR "kcapi: driver has no add card function.\n");
return -EIO;
}
return driver->add_card(driver, &cparams);
case AVMB1_LOAD: case AVMB1_LOAD:
case AVMB1_LOAD_AND_CONFIG: case AVMB1_LOAD_AND_CONFIG:
...@@ -1417,6 +1157,7 @@ static int old_capi_manufacturer(unsigned int cmd, void *data) ...@@ -1417,6 +1157,7 @@ static int old_capi_manufacturer(unsigned int cmd, void *data)
return retval; return retval;
} }
card = get_capi_ctr_by_nr(ldef.contr); card = get_capi_ctr_by_nr(ldef.contr);
card = capi_ctr_get(card);
if (!card) if (!card)
return -ESRCH; return -ESRCH;
if (card->driver->load_firmware == 0) { if (card->driver->load_firmware == 0) {
...@@ -1450,6 +1191,7 @@ static int old_capi_manufacturer(unsigned int cmd, void *data) ...@@ -1450,6 +1191,7 @@ static int old_capi_manufacturer(unsigned int cmd, void *data)
if (retval) { if (retval) {
card->cardstate = CARD_DETECTED; card->cardstate = CARD_DETECTED;
capi_ctr_put(card);
return retval; return retval;
} }
...@@ -1458,9 +1200,12 @@ static int old_capi_manufacturer(unsigned int cmd, void *data) ...@@ -1458,9 +1200,12 @@ static int old_capi_manufacturer(unsigned int cmd, void *data)
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ/10); /* 0.1 sec */ schedule_timeout(HZ/10); /* 0.1 sec */
if (signal_pending(current)) if (signal_pending(current)) {
capi_ctr_put(card);
return -EINTR; return -EINTR;
}
} }
capi_ctr_put(card);
return 0; return 0;
case AVMB1_RESETCARD: case AVMB1_RESETCARD:
...@@ -1505,30 +1250,6 @@ static int old_capi_manufacturer(unsigned int cmd, void *data) ...@@ -1505,30 +1250,6 @@ static int old_capi_manufacturer(unsigned int cmd, void *data)
return retval; return retval;
return 0; return 0;
case AVMB1_REMOVECARD:
if ((retval = copy_from_user((void *) &rdef, data,
sizeof(avmb1_resetdef))))
return retval;
card = get_capi_ctr_by_nr(rdef.contr);
if (!card)
return -ESRCH;
if (card->cardstate != CARD_DETECTED)
return -EBUSY;
card->driver->remove_ctr(card);
while (cards[rdef.contr]) {
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ/10); /* 0.1 sec */
if (signal_pending(current))
return -EINTR;
}
return 0;
} }
return -EINVAL; return -EINVAL;
} }
...@@ -1541,8 +1262,6 @@ static int capi_manufacturer(unsigned int cmd, void *data) ...@@ -1541,8 +1262,6 @@ static int capi_manufacturer(unsigned int cmd, void *data)
switch (cmd) { switch (cmd) {
#ifdef CONFIG_AVMB1_COMPAT #ifdef CONFIG_AVMB1_COMPAT
case AVMB1_ADDCARD:
case AVMB1_ADDCARD_WITH_TYPE:
case AVMB1_LOAD: case AVMB1_LOAD:
case AVMB1_LOAD_AND_CONFIG: case AVMB1_LOAD_AND_CONFIG:
case AVMB1_RESETCARD: case AVMB1_RESETCARD:
...@@ -1568,37 +1287,6 @@ static int capi_manufacturer(unsigned int cmd, void *data) ...@@ -1568,37 +1287,6 @@ static int capi_manufacturer(unsigned int cmd, void *data)
return 0; return 0;
} }
case KCAPI_CMD_ADDCARD:
{
struct capi_driver *driver;
capicardparams cparams;
kcapi_carddef cdef;
if ((retval = copy_from_user((void *) &cdef, data,
sizeof(cdef))))
return retval;
cparams.port = cdef.port;
cparams.irq = cdef.irq;
cparams.membase = cdef.membase;
cparams.cardnr = cdef.cardnr;
cparams.cardtype = 0;
cdef.driver[sizeof(cdef.driver)-1] = 0;
if ((driver = find_driver(cdef.driver)) == 0) {
printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n",
cdef.driver);
return -ESRCH;
}
if (!driver->add_card) {
printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver);
return -EIO;
}
return driver->add_card(driver, &cparams);
}
default: default:
printk(KERN_ERR "kcapi: manufacturer command %d unknown.\n", printk(KERN_ERR "kcapi: manufacturer command %d unknown.\n",
cmd); cmd);
......
...@@ -69,6 +69,7 @@ typedef struct avmctrl_info { ...@@ -69,6 +69,7 @@ typedef struct avmctrl_info {
struct avmcard *card; struct avmcard *card;
struct capi_ctr *capi_ctrl; struct capi_ctr *capi_ctrl;
struct list_head ncci_head;
} avmctrl_info; } avmctrl_info;
typedef struct avmcard { typedef struct avmcard {
...@@ -536,6 +537,7 @@ static inline void b1_setinterrupt(unsigned int base, unsigned irq, ...@@ -536,6 +537,7 @@ static inline void b1_setinterrupt(unsigned int base, unsigned irq,
} }
/* b1.c */ /* b1.c */
void b1_set_revision(struct capi_driver *driver, char *rev);
avmcard *b1_alloc_card(int nr_controllers); avmcard *b1_alloc_card(int nr_controllers);
void b1_free_card(avmcard *card); void b1_free_card(avmcard *card);
int b1_detect(unsigned int base, enum avmcardtype cardtype); int b1_detect(unsigned int base, enum avmcardtype cardtype);
...@@ -549,7 +551,7 @@ void b1_reset_ctr(struct capi_ctr *ctrl); ...@@ -549,7 +551,7 @@ void b1_reset_ctr(struct capi_ctr *ctrl);
void b1_register_appl(struct capi_ctr *ctrl, u16 appl, void b1_register_appl(struct capi_ctr *ctrl, u16 appl,
capi_register_params *rp); capi_register_params *rp);
void b1_release_appl(struct capi_ctr *ctrl, u16 appl); void b1_release_appl(struct capi_ctr *ctrl, u16 appl);
void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
void b1_parse_version(avmctrl_info *card); void b1_parse_version(avmctrl_info *card);
void b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs); void b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs);
...@@ -560,7 +562,6 @@ avmcard_dmainfo *avmcard_dma_alloc(char *name, struct pci_dev *, ...@@ -560,7 +562,6 @@ avmcard_dmainfo *avmcard_dma_alloc(char *name, struct pci_dev *,
long rsize, long ssize); long rsize, long ssize);
void avmcard_dma_free(avmcard_dmainfo *); void avmcard_dma_free(avmcard_dmainfo *);
/* b1dma.c */ /* b1dma.c */
int b1pciv4_detect(avmcard *card); int b1pciv4_detect(avmcard *card);
int t1pci_detect(avmcard *card); int t1pci_detect(avmcard *card);
...@@ -574,7 +575,7 @@ void b1dma_register_appl(struct capi_ctr *ctrl, ...@@ -574,7 +575,7 @@ void b1dma_register_appl(struct capi_ctr *ctrl,
u16 appl, u16 appl,
capi_register_params *rp); capi_register_params *rp);
void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl); void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl);
void b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
int b1dmactl_read_proc(char *page, char **start, off_t off, int b1dmactl_read_proc(char *page, char **start, off_t off,
int count, int *eof, struct capi_ctr *ctrl); int count, int *eof, struct capi_ctr *ctrl);
......
...@@ -59,6 +59,21 @@ int b1_irq_table[16] = ...@@ -59,6 +59,21 @@ int b1_irq_table[16] =
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
void b1_set_revision(struct capi_driver *driver, char *rev)
{
char *p;
if ((p = strchr(rev, ':')) != 0 && p[1]) {
strncpy(driver->revision, p + 2, sizeof(driver->revision));
driver->revision[sizeof(driver->revision)-1] = 0;
if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
*(p-1) = 0;
}
printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
}
/* ------------------------------------------------------------- */
avmcard *b1_alloc_card(int nr_controllers) avmcard *b1_alloc_card(int nr_controllers)
{ {
avmcard *card; avmcard *card;
...@@ -80,6 +95,7 @@ avmcard *b1_alloc_card(int nr_controllers) ...@@ -80,6 +95,7 @@ avmcard *b1_alloc_card(int nr_controllers)
card->ctrlinfo = cinfo; card->ctrlinfo = cinfo;
for (i = 0; i < nr_controllers; i++) { for (i = 0; i < nr_controllers; i++) {
INIT_LIST_HEAD(&cinfo[i].ncci_head);
cinfo[i].card = card; cinfo[i].card = card;
} }
spin_lock_init(&card->lock); spin_lock_init(&card->lock);
...@@ -331,6 +347,7 @@ void b1_reset_ctr(struct capi_ctr *ctrl) ...@@ -331,6 +347,7 @@ void b1_reset_ctr(struct capi_ctr *ctrl)
b1_reset(port); b1_reset(port);
memset(cinfo->version, 0, sizeof(cinfo->version)); memset(cinfo->version, 0, sizeof(cinfo->version));
capilib_release(&cinfo->ncci_head);
ctrl->reseted(ctrl); ctrl->reseted(ctrl);
} }
...@@ -366,6 +383,8 @@ void b1_release_appl(struct capi_ctr *ctrl, u16 appl) ...@@ -366,6 +383,8 @@ void b1_release_appl(struct capi_ctr *ctrl, u16 appl)
unsigned int port = card->port; unsigned int port = card->port;
unsigned long flags; unsigned long flags;
capilib_release_appl(&cinfo->ncci_head, appl);
save_flags(flags); save_flags(flags);
cli(); cli();
b1_put_byte(port, SEND_RELEASE); b1_put_byte(port, SEND_RELEASE);
...@@ -373,7 +392,7 @@ void b1_release_appl(struct capi_ctr *ctrl, u16 appl) ...@@ -373,7 +392,7 @@ void b1_release_appl(struct capi_ctr *ctrl, u16 appl)
restore_flags(flags); restore_flags(flags);
} }
void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
{ {
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
avmcard *card = cinfo->card; avmcard *card = cinfo->card;
...@@ -382,20 +401,36 @@ void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) ...@@ -382,20 +401,36 @@ void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
u16 len = CAPIMSG_LEN(skb->data); u16 len = CAPIMSG_LEN(skb->data);
u8 cmd = CAPIMSG_COMMAND(skb->data); u8 cmd = CAPIMSG_COMMAND(skb->data);
u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data); u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
u16 dlen, retval;
save_flags(flags);
cli();
if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
u16 dlen = CAPIMSG_DATALEN(skb->data); retval = capilib_data_b3_req(&cinfo->ncci_head,
CAPIMSG_APPID(skb->data),
CAPIMSG_NCCI(skb->data),
CAPIMSG_MSGID(skb->data));
if (retval != CAPI_NOERROR)
goto out;
dlen = CAPIMSG_DATALEN(skb->data);
save_flags(flags);
cli();
b1_put_byte(port, SEND_DATA_B3_REQ); b1_put_byte(port, SEND_DATA_B3_REQ);
b1_put_slice(port, skb->data, len); b1_put_slice(port, skb->data, len);
b1_put_slice(port, skb->data + len, dlen); b1_put_slice(port, skb->data + len, dlen);
restore_flags(flags);
} else { } else {
retval = CAPI_NOERROR;
save_flags(flags);
cli();
b1_put_byte(port, SEND_MESSAGE); b1_put_byte(port, SEND_MESSAGE);
b1_put_slice(port, skb->data, len); b1_put_slice(port, skb->data, len);
restore_flags(flags);
} }
restore_flags(flags); out:
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return retval;
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
...@@ -525,6 +560,11 @@ void b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs) ...@@ -525,6 +560,11 @@ void b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
card->name); card->name);
} else { } else {
memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF)
capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
CAPIMSG_NCCI(skb->data),
CAPIMSG_MSGID(skb->data));
ctrl->handle_capimsg(ctrl, ApplId, skb); ctrl->handle_capimsg(ctrl, ApplId, skb);
} }
break; break;
...@@ -535,7 +575,7 @@ void b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs) ...@@ -535,7 +575,7 @@ void b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
NCCI = b1_get_word(card->port); NCCI = b1_get_word(card->port);
WindowSize = b1_get_word(card->port); WindowSize = b1_get_word(card->port);
ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize); capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
break; break;
...@@ -545,8 +585,8 @@ void b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs) ...@@ -545,8 +585,8 @@ void b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
NCCI = b1_get_word(card->port); NCCI = b1_get_word(card->port);
if (NCCI != 0xffffffff) if (NCCI != 0xffffffff)
ctrl->free_ncci(ctrl, ApplId, NCCI); capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
break; break;
case RECEIVE_START: case RECEIVE_START:
...@@ -738,6 +778,7 @@ EXPORT_SYMBOL(avmcard_dma_free); ...@@ -738,6 +778,7 @@ EXPORT_SYMBOL(avmcard_dma_free);
EXPORT_SYMBOL(b1_irq_table); EXPORT_SYMBOL(b1_irq_table);
EXPORT_SYMBOL(b1_set_revision);
EXPORT_SYMBOL(b1_alloc_card); EXPORT_SYMBOL(b1_alloc_card);
EXPORT_SYMBOL(b1_free_card); EXPORT_SYMBOL(b1_free_card);
EXPORT_SYMBOL(b1_detect); EXPORT_SYMBOL(b1_detect);
......
...@@ -488,6 +488,11 @@ static void b1dma_handle_rx(avmcard *card) ...@@ -488,6 +488,11 @@ static void b1dma_handle_rx(avmcard *card)
card->name); card->name);
} else { } else {
memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF)
capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
CAPIMSG_NCCI(skb->data),
CAPIMSG_MSGID(skb->data));
ctrl->handle_capimsg(ctrl, ApplId, skb); ctrl->handle_capimsg(ctrl, ApplId, skb);
} }
break; break;
...@@ -498,7 +503,7 @@ static void b1dma_handle_rx(avmcard *card) ...@@ -498,7 +503,7 @@ static void b1dma_handle_rx(avmcard *card)
NCCI = _get_word(&p); NCCI = _get_word(&p);
WindowSize = _get_word(&p); WindowSize = _get_word(&p);
ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize); capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
break; break;
...@@ -508,7 +513,7 @@ static void b1dma_handle_rx(avmcard *card) ...@@ -508,7 +513,7 @@ static void b1dma_handle_rx(avmcard *card)
NCCI = _get_word(&p); NCCI = _get_word(&p);
if (NCCI != 0xffffffff) if (NCCI != 0xffffffff)
ctrl->free_ncci(ctrl, ApplId, NCCI); capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
break; break;
...@@ -734,6 +739,7 @@ void b1dma_reset_ctr(struct capi_ctr *ctrl) ...@@ -734,6 +739,7 @@ void b1dma_reset_ctr(struct capi_ctr *ctrl)
b1dma_reset(card); b1dma_reset(card);
memset(cinfo->version, 0, sizeof(cinfo->version)); memset(cinfo->version, 0, sizeof(cinfo->version));
capilib_release(&cinfo->ncci_head);
ctrl->reseted(ctrl); ctrl->reseted(ctrl);
} }
...@@ -785,6 +791,8 @@ void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl) ...@@ -785,6 +791,8 @@ void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl)
struct sk_buff *skb; struct sk_buff *skb;
void *p; void *p;
capilib_release_appl(&cinfo->ncci_head, appl);
skb = alloc_skb(7, GFP_ATOMIC); skb = alloc_skb(7, GFP_ATOMIC);
if (!skb) { if (!skb) {
printk(KERN_CRIT "%s: no memory, lost release appl.\n", printk(KERN_CRIT "%s: no memory, lost release appl.\n",
...@@ -804,12 +812,24 @@ void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl) ...@@ -804,12 +812,24 @@ void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl)
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
void b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
{ {
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
avmcard *card = cinfo->card; avmcard *card = cinfo->card;
u16 retval = CAPI_NOERROR;
b1dma_queue_tx(card, skb); if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
retval = capilib_data_b3_req(&cinfo->ncci_head,
CAPIMSG_APPID(skb->data),
CAPIMSG_NCCI(skb->data),
CAPIMSG_MSGID(skb->data));
}
if (retval == CAPI_NOERROR)
b1dma_queue_tx(card, skb);
else
dev_kfree_skb_any(skb);
return retval;
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/capi.h> #include <linux/capi.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/pci.h>
#include <asm/io.h> #include <asm/io.h>
#include <linux/isdn/capicmd.h> #include <linux/isdn/capicmd.h>
#include <linux/isdn/capiutil.h> #include <linux/isdn/capiutil.h>
...@@ -34,33 +35,31 @@ MODULE_LICENSE("GPL"); ...@@ -34,33 +35,31 @@ MODULE_LICENSE("GPL");
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
static void b1isa_remove_ctr(struct capi_ctr *ctrl) static struct capi_driver b1isa_driver;
static void b1isa_remove(struct pci_dev *pdev)
{ {
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmctrl_info *cinfo = pci_get_drvdata(pdev);
avmcard *card = cinfo->card; avmcard *card = cinfo->card;
unsigned int port = card->port; unsigned int port = cinfo->card->port;
b1_reset(port); b1_reset(port);
b1_reset(port); b1_reset(port);
detach_capi_ctr(ctrl); detach_capi_ctr(cinfo->capi_ctrl);
free_irq(card->irq, card); free_irq(card->irq, card);
release_region(card->port, AVMB1_PORTLEN); release_region(card->port, AVMB1_PORTLEN);
b1_free_card(card); b1_free_card(card);
MOD_DEC_USE_COUNT;
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) static int __init b1isa_probe(struct pci_dev *pdev)
{ {
avmctrl_info *cinfo; avmctrl_info *cinfo;
avmcard *card; avmcard *card;
int retval; int retval;
MOD_INC_USE_COUNT;
card = b1_alloc_card(1); card = b1_alloc_card(1);
if (!card) { if (!card) {
printk(KERN_WARNING "b1isa: no memory.\n"); printk(KERN_WARNING "b1isa: no memory.\n");
...@@ -70,10 +69,10 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) ...@@ -70,10 +69,10 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
cinfo = card->ctrlinfo; cinfo = card->ctrlinfo;
sprintf(card->name, "b1isa-%x", p->port); card->port = pci_resource_start(pdev, 0);
card->port = p->port; card->irq = pdev->irq;
card->irq = p->irq;
card->cardtype = avm_b1isa; card->cardtype = avm_b1isa;
sprintf(card->name, "b1isa-%x", card->port);
if ( card->port != 0x150 && card->port != 0x250 if ( card->port != 0x150 && card->port != 0x250
&& card->port != 0x300 && card->port != 0x340) { && card->port != 0x300 && card->port != 0x340) {
...@@ -107,7 +106,7 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) ...@@ -107,7 +106,7 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
b1_reset(card->port); b1_reset(card->port);
b1_getrevision(card); b1_getrevision(card);
cinfo->capi_ctrl = attach_capi_ctr(driver, card->name, cinfo); cinfo->capi_ctrl = attach_capi_ctr(&b1isa_driver, card->name, cinfo);
if (!cinfo->capi_ctrl) { if (!cinfo->capi_ctrl) {
printk(KERN_ERR "b1isa: attach controller failed.\n"); printk(KERN_ERR "b1isa: attach controller failed.\n");
retval = -EBUSY; retval = -EBUSY;
...@@ -116,8 +115,9 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) ...@@ -116,8 +115,9 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
printk(KERN_INFO printk(KERN_INFO
"%s: AVM B1 ISA at i/o %#x, irq %d, revision %d\n", "%s: AVM B1 ISA at i/o %#x, irq %d, revision %d\n",
driver->name, card->port, card->irq, card->revision); b1isa_driver.name, card->port, card->irq, card->revision);
pci_set_drvdata(pdev, cinfo);
return 0; return 0;
err_free_irq: err_free_irq:
...@@ -127,7 +127,6 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) ...@@ -127,7 +127,6 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
err_free: err_free:
b1_free_card(card); b1_free_card(card);
err: err:
MOD_DEC_USE_COUNT;
return retval; return retval;
} }
...@@ -155,7 +154,6 @@ static struct capi_driver b1isa_driver = { ...@@ -155,7 +154,6 @@ static struct capi_driver b1isa_driver = {
revision: "0.0", revision: "0.0",
load_firmware: b1_load_firmware, load_firmware: b1_load_firmware,
reset_ctr: b1_reset_ctr, reset_ctr: b1_reset_ctr,
remove_ctr: b1isa_remove_ctr,
register_appl: b1_register_appl, register_appl: b1_register_appl,
release_appl: b1_release_appl, release_appl: b1_release_appl,
send_message: b1_send_message, send_message: b1_send_message,
...@@ -163,34 +161,63 @@ static struct capi_driver b1isa_driver = { ...@@ -163,34 +161,63 @@ static struct capi_driver b1isa_driver = {
procinfo: b1isa_procinfo, procinfo: b1isa_procinfo,
ctr_read_proc: b1ctl_read_proc, ctr_read_proc: b1ctl_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */ driver_read_proc: 0, /* use standard driver_read_proc */
add_card: b1isa_add_card,
}; };
#define MAX_CARDS 4
static struct pci_dev isa_dev[MAX_CARDS];
static int io[MAX_CARDS];
static int irq[MAX_CARDS];
MODULE_PARM(io, "1-" __MODULE_STRING(MAX_CARDS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i");
MODULE_PARM_DESC(io, "I/O base address(es)");
MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
static int __init b1isa_init(void) static int __init b1isa_init(void)
{ {
struct capi_driver *driver = &b1isa_driver; int i, retval;
char *p; int found = 0;
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
if ((p = strchr(revision, ':')) != 0 && p[1]) { b1_set_revision(&b1isa_driver, revision);
strncpy(driver->revision, p + 2, sizeof(driver->revision)); attach_capi_driver(&b1isa_driver);
driver->revision[sizeof(driver->revision)-1] = 0;
if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision) for (i = 0; i < MAX_CARDS; i++) {
*(p-1) = 0; if (!io[i])
} break;
printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision); isa_dev[i].resource[0].start = io[i];
isa_dev[i].irq_resource[0].start = irq[i];
attach_capi_driver(driver); if (b1isa_probe(&isa_dev[i]) == 0)
found++;
}
if (found == 0) {
retval = -ENODEV;
goto err;
}
retval = 0;
goto out;
err:
detach_capi_driver(&b1isa_driver);
out:
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
return 0; return retval;
} }
static void __exit b1isa_exit(void) static void __exit b1isa_exit(void)
{ {
detach_capi_driver(&b1isa_driver); int i;
for (i = 0; i < MAX_CARDS; i++) {
if (!io[i])
break;
b1isa_remove(&isa_dev[i]);
}
detach_capi_driver(&b1isa_driver);
} }
module_init(b1isa_init); module_init(b1isa_init);
......
...@@ -60,16 +60,14 @@ static char *b1pci_procinfo(struct capi_ctr *ctrl) ...@@ -60,16 +60,14 @@ static char *b1pci_procinfo(struct capi_ctr *ctrl)
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
static int b1pci_add_card(struct capi_driver *driver, static int b1pci_probe(struct capi_driver *driver,
struct capicardparams *p, struct capicardparams *p,
struct pci_dev *dev) struct pci_dev *pdev)
{ {
avmcard *card; avmcard *card;
avmctrl_info *cinfo; avmctrl_info *cinfo;
int retval; int retval;
MOD_INC_USE_COUNT;
card = b1_alloc_card(1); card = b1_alloc_card(1);
if (!card) { if (!card) {
printk(KERN_WARNING "%s: no memory.\n", driver->name); printk(KERN_WARNING "%s: no memory.\n", driver->name);
...@@ -127,6 +125,7 @@ static int b1pci_add_card(struct capi_driver *driver, ...@@ -127,6 +125,7 @@ static int b1pci_add_card(struct capi_driver *driver,
driver->name, card->port, card->irq, card->revision); driver->name, card->port, card->irq, card->revision);
} }
pci_set_drvdata(pdev, card);
return 0; return 0;
err_free_irq: err_free_irq:
...@@ -136,26 +135,22 @@ static int b1pci_add_card(struct capi_driver *driver, ...@@ -136,26 +135,22 @@ static int b1pci_add_card(struct capi_driver *driver,
err_free: err_free:
b1_free_card(card); b1_free_card(card);
err: err:
MOD_DEC_USE_COUNT;
return retval; return retval;
} }
static void b1pci_remove_ctr(struct capi_ctr *ctrl) static void b1pci_remove(struct pci_dev *pdev)
{ {
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmcard *card = pci_get_drvdata(pdev);
avmcard *card = cinfo->card; avmctrl_info *cinfo = card->ctrlinfo;
unsigned int port = card->port; unsigned int port = card->port;
b1_reset(port); b1_reset(port);
b1_reset(port); b1_reset(port);
detach_capi_ctr(ctrl); detach_capi_ctr(cinfo->capi_ctrl);
free_irq(card->irq, card); free_irq(card->irq, card);
release_region(card->port, AVMB1_PORTLEN); release_region(card->port, AVMB1_PORTLEN);
ctrl->driverdata = 0;
b1_free_card(card); b1_free_card(card);
MOD_DEC_USE_COUNT;
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
...@@ -166,7 +161,6 @@ static struct capi_driver b1pci_driver = { ...@@ -166,7 +161,6 @@ static struct capi_driver b1pci_driver = {
revision: "0.0", revision: "0.0",
load_firmware: b1_load_firmware, load_firmware: b1_load_firmware,
reset_ctr: b1_reset_ctr, reset_ctr: b1_reset_ctr,
remove_ctr: b1pci_remove_ctr,
register_appl: b1_register_appl, register_appl: b1_register_appl,
release_appl: b1_release_appl, release_appl: b1_release_appl,
send_message: b1_send_message, send_message: b1_send_message,
...@@ -174,8 +168,6 @@ static struct capi_driver b1pci_driver = { ...@@ -174,8 +168,6 @@ static struct capi_driver b1pci_driver = {
procinfo: b1pci_procinfo, procinfo: b1pci_procinfo,
ctr_read_proc: b1ctl_read_proc, ctr_read_proc: b1ctl_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */ driver_read_proc: 0, /* use standard driver_read_proc */
add_card: 0, /* no add_card function */
}; };
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
...@@ -200,16 +192,14 @@ static char *b1pciv4_procinfo(struct capi_ctr *ctrl) ...@@ -200,16 +192,14 @@ static char *b1pciv4_procinfo(struct capi_ctr *ctrl)
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
static int b1pciv4_add_card(struct capi_driver *driver, static int b1pciv4_probe(struct capi_driver *driver,
struct capicardparams *p, struct capicardparams *p,
struct pci_dev *dev) struct pci_dev *pdev)
{ {
avmcard *card; avmcard *card;
avmctrl_info *cinfo; avmctrl_info *cinfo;
int retval; int retval;
MOD_INC_USE_COUNT;
card = b1_alloc_card(1); card = b1_alloc_card(1);
if (!card) { if (!card) {
printk(KERN_WARNING "%s: no memory.\n", driver->name); printk(KERN_WARNING "%s: no memory.\n", driver->name);
...@@ -217,7 +207,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, ...@@ -217,7 +207,7 @@ static int b1pciv4_add_card(struct capi_driver *driver,
goto err; goto err;
} }
card->dma = avmcard_dma_alloc(driver->name, dev, 2048+128, 2048+128); card->dma = avmcard_dma_alloc(driver->name, pdev, 2048+128, 2048+128);
if (!card->dma) { if (!card->dma) {
printk(KERN_WARNING "%s: dma alloc.\n", driver->name); printk(KERN_WARNING "%s: dma alloc.\n", driver->name);
retval = -ENOMEM; retval = -ENOMEM;
...@@ -280,6 +270,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, ...@@ -280,6 +270,7 @@ static int b1pciv4_add_card(struct capi_driver *driver,
driver->name, card->port, card->irq, driver->name, card->port, card->irq,
card->membase, card->revision); card->membase, card->revision);
pci_set_drvdata(pdev, card);
return 0; return 0;
err_free_irq: err_free_irq:
...@@ -293,27 +284,23 @@ static int b1pciv4_add_card(struct capi_driver *driver, ...@@ -293,27 +284,23 @@ static int b1pciv4_add_card(struct capi_driver *driver,
err_free: err_free:
b1_free_card(card); b1_free_card(card);
err: err:
MOD_DEC_USE_COUNT;
return retval; return retval;
} }
static void b1pciv4_remove_ctr(struct capi_ctr *ctrl) static void b1pciv4_remove(struct pci_dev *pdev)
{ {
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmcard *card = pci_get_drvdata(pdev);
avmcard *card = cinfo->card; avmctrl_info *cinfo = card->ctrlinfo;
b1dma_reset(card); b1dma_reset(card);
detach_capi_ctr(ctrl); detach_capi_ctr(cinfo->capi_ctrl);
free_irq(card->irq, card); free_irq(card->irq, card);
iounmap(card->mbase); iounmap(card->mbase);
release_region(card->port, AVMB1_PORTLEN); release_region(card->port, AVMB1_PORTLEN);
ctrl->driverdata = 0;
avmcard_dma_free(card->dma); avmcard_dma_free(card->dma);
b1_free_card(card); b1_free_card(card);
MOD_DEC_USE_COUNT;
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
...@@ -325,7 +312,6 @@ static struct capi_driver b1pciv4_driver = { ...@@ -325,7 +312,6 @@ static struct capi_driver b1pciv4_driver = {
revision: "0.0", revision: "0.0",
load_firmware: b1dma_load_firmware, load_firmware: b1dma_load_firmware,
reset_ctr: b1dma_reset_ctr, reset_ctr: b1dma_reset_ctr,
remove_ctr: b1pciv4_remove_ctr,
register_appl: b1dma_register_appl, register_appl: b1dma_register_appl,
release_appl: b1dma_release_appl, release_appl: b1dma_release_appl,
send_message: b1dma_send_message, send_message: b1dma_send_message,
...@@ -333,42 +319,40 @@ static struct capi_driver b1pciv4_driver = { ...@@ -333,42 +319,40 @@ static struct capi_driver b1pciv4_driver = {
procinfo: b1pciv4_procinfo, procinfo: b1pciv4_procinfo,
ctr_read_proc: b1dmactl_read_proc, ctr_read_proc: b1dmactl_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */ driver_read_proc: 0, /* use standard driver_read_proc */
add_card: 0, /* no add_card function */
}; };
#endif /* CONFIG_ISDN_DRV_AVMB1_B1PCIV4 */ #endif /* CONFIG_ISDN_DRV_AVMB1_B1PCIV4 */
static int __devinit b1pci_probe(struct pci_dev *dev, static int __devinit b1pci_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
struct capi_driver *driver = &b1pci_driver; struct capi_driver *driver = &b1pci_driver;
struct capicardparams param; struct capicardparams param;
int retval; int retval;
if (pci_enable_device(dev) < 0) { if (pci_enable_device(pdev) < 0) {
printk(KERN_ERR "%s: failed to enable AVM-B1\n", printk(KERN_ERR "%s: failed to enable AVM-B1\n",
driver->name); driver->name);
return -ENODEV; return -ENODEV;
} }
param.irq = dev->irq; param.irq = pdev->irq;
if (pci_resource_start(dev, 2)) { /* B1 PCI V4 */ if (pci_resource_start(pdev, 2)) { /* B1 PCI V4 */
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
driver = &b1pciv4_driver; driver = &b1pciv4_driver;
pci_set_master(dev); pci_set_master(pdev);
#endif #endif
param.membase = pci_resource_start(dev, 0); param.membase = pci_resource_start(pdev, 0);
param.port = pci_resource_start(dev, 2); param.port = pci_resource_start(pdev, 2);
printk(KERN_INFO printk(KERN_INFO
"%s: PCI BIOS reports AVM-B1 V4 at i/o %#x, irq %d, mem %#x\n", "%s: PCI BIOS reports AVM-B1 V4 at i/o %#x, irq %d, mem %#x\n",
driver->name, param.port, param.irq, param.membase); driver->name, param.port, param.irq, param.membase);
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
retval = b1pciv4_add_card(driver, &param, dev); retval = b1pciv4_probe(driver, &param, pdev);
#else #else
retval = b1pci_add_card(driver, &param, dev); retval = b1pci_probe(driver, &param, pdev);
#endif #endif
if (retval != 0) { if (retval != 0) {
printk(KERN_ERR printk(KERN_ERR
...@@ -377,12 +361,12 @@ static int __devinit b1pci_probe(struct pci_dev *dev, ...@@ -377,12 +361,12 @@ static int __devinit b1pci_probe(struct pci_dev *dev,
} }
} else { } else {
param.membase = 0; param.membase = 0;
param.port = pci_resource_start(dev, 1); param.port = pci_resource_start(pdev, 1);
printk(KERN_INFO printk(KERN_INFO
"%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n", "%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
driver->name, param.port, param.irq); driver->name, param.port, param.irq);
retval = b1pci_add_card(driver, &param, dev); retval = b1pci_probe(driver, &param, pdev);
if (retval != 0) { if (retval != 0) {
printk(KERN_ERR printk(KERN_ERR
"%s: no AVM-B1 at i/o %#x, irq %d detected\n", "%s: no AVM-B1 at i/o %#x, irq %d detected\n",
...@@ -392,68 +376,60 @@ static int __devinit b1pci_probe(struct pci_dev *dev, ...@@ -392,68 +376,60 @@ static int __devinit b1pci_probe(struct pci_dev *dev,
return retval; return retval;
} }
static void __devexit b1pci_pci_remove(struct pci_dev *pdev)
{
avmcard *card = pci_get_drvdata(pdev);
if (card->dma)
b1pciv4_remove(pdev);
else
b1pci_remove(pdev);
}
static struct pci_driver b1pci_pci_driver = { static struct pci_driver b1pci_pci_driver = {
name: "b1pci", name: "b1pci",
id_table: b1pci_pci_tbl, id_table: b1pci_pci_tbl,
probe: b1pci_probe, probe: b1pci_pci_probe,
remove: __devexit_p(b1pci_pci_remove),
}; };
static int __init b1pci_init(void) static int __init b1pci_init(void)
{ {
struct capi_driver *driver = &b1pci_driver; int retval;
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
struct capi_driver *driverv4 = &b1pciv4_driver;
#endif
char *p;
int ncards;
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
if ((p = strchr(revision, ':')) != 0 && p[1]) { b1_set_revision(&b1pci_driver, revision);
strncpy(driver->revision, p + 2, sizeof(driver->revision)); attach_capi_driver(&b1pci_driver);
driver->revision[sizeof(driver->revision)-1] = 0;
if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
*(p-1) = 0;
}
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
if ((p = strchr(revision, ':')) != 0 && p[1]) { b1_set_revision(&b1pciv4_driver, revision);
strncpy(driverv4->revision, p + 2, sizeof(driverv4->revision)); attach_capi_driver(&b1pciv4_driver);
driverv4->revision[sizeof(driverv4->revision)-1] = 0;
if ((p = strchr(driverv4->revision, '$')) != 0 && p > driverv4->revision)
*(p-1) = 0;
}
#endif #endif
printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision); retval = pci_module_init(&b1pci_pci_driver);
if (retval < 0)
attach_capi_driver(driver); goto err;
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
printk(KERN_INFO "%s: revision %s\n", driverv4->name, driverv4->revision);
attach_capi_driver(driverv4); printk(KERN_INFO "%s: %d B1-PCI card(s) detected\n",
#endif b1pci_driver.name, retval);
retval = 0;
goto out;
ncards = pci_register_driver(&b1pci_pci_driver); err:
if (ncards) { detach_capi_driver(&b1pci_driver);
printk(KERN_INFO "%s: %d B1-PCI card(s) detected\n",
driver->name, ncards);
MOD_DEC_USE_COUNT;
return 0;
}
printk(KERN_ERR "%s: NO B1-PCI card detected\n", driver->name);
pci_unregister_driver(&b1pci_pci_driver);
detach_capi_driver(driver);
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
detach_capi_driver(driverv4); detach_capi_driver(&b1pciv4_driver);
#endif #endif
out:
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
return -ENODEV; return retval;
} }
static void __exit b1pci_exit(void) static void __exit b1pci_exit(void)
{ {
pci_unregister_driver(&b1pci_pci_driver); pci_unregister_driver(&b1pci_pci_driver);
detach_capi_driver(&b1pci_driver); detach_capi_driver(&b1pci_driver);
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
detach_capi_driver(&b1pciv4_driver); detach_capi_driver(&b1pciv4_driver);
......
...@@ -47,8 +47,6 @@ static void b1pcmcia_remove_ctr(struct capi_ctr *ctrl) ...@@ -47,8 +47,6 @@ static void b1pcmcia_remove_ctr(struct capi_ctr *ctrl)
detach_capi_ctr(ctrl); detach_capi_ctr(ctrl);
free_irq(card->irq, card); free_irq(card->irq, card);
b1_free_card(card); b1_free_card(card);
MOD_DEC_USE_COUNT;
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
...@@ -63,8 +61,6 @@ static int b1pcmcia_add_card(struct capi_driver *driver, ...@@ -63,8 +61,6 @@ static int b1pcmcia_add_card(struct capi_driver *driver,
char *cardname; char *cardname;
int retval; int retval;
MOD_INC_USE_COUNT;
card = b1_alloc_card(1); card = b1_alloc_card(1);
if (!card) { if (!card) {
printk(KERN_WARNING "%s: no memory.\n", driver->name); printk(KERN_WARNING "%s: no memory.\n", driver->name);
...@@ -123,7 +119,6 @@ static int b1pcmcia_add_card(struct capi_driver *driver, ...@@ -123,7 +119,6 @@ static int b1pcmcia_add_card(struct capi_driver *driver,
err_free: err_free:
b1_free_card(card); b1_free_card(card);
err: err:
MOD_DEC_USE_COUNT;
return retval; return retval;
} }
...@@ -153,7 +148,6 @@ static struct capi_driver b1pcmcia_driver = { ...@@ -153,7 +148,6 @@ static struct capi_driver b1pcmcia_driver = {
revision: "0.0", revision: "0.0",
load_firmware: b1_load_firmware, load_firmware: b1_load_firmware,
reset_ctr: b1_reset_ctr, reset_ctr: b1_reset_ctr,
remove_ctr: b1pcmcia_remove_ctr,
register_appl: b1_register_appl, register_appl: b1_register_appl,
release_appl: b1_release_appl, release_appl: b1_release_appl,
send_message: b1_send_message, send_message: b1_send_message,
...@@ -161,8 +155,6 @@ static struct capi_driver b1pcmcia_driver = { ...@@ -161,8 +155,6 @@ static struct capi_driver b1pcmcia_driver = {
procinfo: b1pcmcia_procinfo, procinfo: b1pcmcia_procinfo,
ctr_read_proc: b1ctl_read_proc, ctr_read_proc: b1ctl_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */ driver_read_proc: 0, /* use standard driver_read_proc */
add_card: 0,
}; };
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
...@@ -208,30 +200,18 @@ EXPORT_SYMBOL(b1pcmcia_delcard); ...@@ -208,30 +200,18 @@ EXPORT_SYMBOL(b1pcmcia_delcard);
static int __init b1pcmcia_init(void) static int __init b1pcmcia_init(void)
{ {
struct capi_driver *driver = &b1pcmcia_driver;
char *p;
int retval = 0;
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
if ((p = strchr(revision, ':')) != 0 && p[1]) { b1_set_revision(&b1pcmcia_driver, revision);
strncpy(driver->revision, p + 2, sizeof(driver->revision)); attach_capi_driver(&b1pcmcia_driver);
driver->revision[sizeof(driver->revision)-1] = 0;
if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
*(p-1) = 0;
}
printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
attach_capi_driver(driver);
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
return retval; return 0;
} }
static void __exit b1pcmcia_exit(void) static void __exit b1pcmcia_exit(void)
{ {
detach_capi_driver(&b1pcmcia_driver); detach_capi_driver(&b1pcmcia_driver);
} }
module_init(b1pcmcia_init); module_init(b1pcmcia_init);
......
...@@ -548,6 +548,7 @@ static void c4_handle_rx(avmcard *card) ...@@ -548,6 +548,7 @@ static void c4_handle_rx(avmcard *card)
MsgLen = _get_slice(&p, card->msgbuf); MsgLen = _get_slice(&p, card->msgbuf);
cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr; cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr;
if (cidx >= card->nlogcontr) cidx = 0; if (cidx >= card->nlogcontr) cidx = 0;
cinfo = &card->ctrlinfo[cidx];
ctrl = card->ctrlinfo[cidx].capi_ctrl; ctrl = card->ctrlinfo[cidx].capi_ctrl;
if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
...@@ -555,6 +556,11 @@ static void c4_handle_rx(avmcard *card) ...@@ -555,6 +556,11 @@ static void c4_handle_rx(avmcard *card)
card->name); card->name);
} else { } else {
memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF)
capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
CAPIMSG_NCCI(skb->data),
CAPIMSG_MSGID(skb->data));
ctrl->handle_capimsg(ctrl, ApplId, skb); ctrl->handle_capimsg(ctrl, ApplId, skb);
} }
break; break;
...@@ -566,9 +572,8 @@ static void c4_handle_rx(avmcard *card) ...@@ -566,9 +572,8 @@ static void c4_handle_rx(avmcard *card)
WindowSize = _get_word(&p); WindowSize = _get_word(&p);
cidx = (NCCI&0x7f) - card->cardnr; cidx = (NCCI&0x7f) - card->cardnr;
if (cidx >= card->nlogcontr) cidx = 0; if (cidx >= card->nlogcontr) cidx = 0;
ctrl = card->ctrlinfo[cidx].capi_ctrl;
ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize); capilib_new_ncci(&card->ctrlinfo[cidx].ncci_head, ApplId, NCCI, WindowSize);
break; break;
...@@ -580,9 +585,7 @@ static void c4_handle_rx(avmcard *card) ...@@ -580,9 +585,7 @@ static void c4_handle_rx(avmcard *card)
if (NCCI != 0xffffffff) { if (NCCI != 0xffffffff) {
cidx = (NCCI&0x7f) - card->cardnr; cidx = (NCCI&0x7f) - card->cardnr;
if (cidx >= card->nlogcontr) cidx = 0; if (cidx >= card->nlogcontr) cidx = 0;
ctrl = card->ctrlinfo[cidx].capi_ctrl; capilib_free_ncci(&card->ctrlinfo[cidx].ncci_head, ApplId, NCCI);
if (ctrl)
ctrl->free_ncci(ctrl, ApplId, NCCI);
} }
break; break;
...@@ -675,6 +678,7 @@ static void c4_handle_interrupt(avmcard *card) ...@@ -675,6 +678,7 @@ static void c4_handle_interrupt(avmcard *card)
for (i=0; i < 4; i++) { for (i=0; i < 4; i++) {
avmctrl_info *cinfo = &card->ctrlinfo[i]; avmctrl_info *cinfo = &card->ctrlinfo[i];
memset(cinfo->version, 0, sizeof(cinfo->version)); memset(cinfo->version, 0, sizeof(cinfo->version));
capilib_release(&cinfo->ncci_head);
if (cinfo->capi_ctrl) if (cinfo->capi_ctrl)
cinfo->capi_ctrl->reseted(cinfo->capi_ctrl); cinfo->capi_ctrl->reseted(cinfo->capi_ctrl);
} }
...@@ -897,9 +901,9 @@ void c4_reset_ctr(struct capi_ctr *ctrl) ...@@ -897,9 +901,9 @@ void c4_reset_ctr(struct capi_ctr *ctrl)
card->nlogcontr = 0; card->nlogcontr = 0;
} }
static void c4_remove_ctr(struct capi_ctr *ctrl) static void c4_remove(struct pci_dev *pdev)
{ {
avmcard *card = ((avmctrl_info *)(ctrl->driverdata))->card; avmcard *card = pci_get_drvdata(pdev);
avmctrl_info *cinfo; avmctrl_info *cinfo;
int i; int i;
...@@ -916,11 +920,8 @@ static void c4_remove_ctr(struct capi_ctr *ctrl) ...@@ -916,11 +920,8 @@ static void c4_remove_ctr(struct capi_ctr *ctrl)
free_irq(card->irq, card); free_irq(card->irq, card);
iounmap(card->mbase); iounmap(card->mbase);
release_region(card->port, AVMB1_PORTLEN); release_region(card->port, AVMB1_PORTLEN);
ctrl->driverdata = 0;
avmcard_dma_free(card->dma); avmcard_dma_free(card->dma);
b1_free_card(card); b1_free_card(card);
MOD_DEC_USE_COUNT;
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
...@@ -974,6 +975,8 @@ void c4_release_appl(struct capi_ctr *ctrl, u16 appl) ...@@ -974,6 +975,8 @@ void c4_release_appl(struct capi_ctr *ctrl, u16 appl)
struct sk_buff *skb; struct sk_buff *skb;
void *p; void *p;
capilib_release_appl(&cinfo->ncci_head, appl);
if (ctrl->cnr == card->cardnr) { if (ctrl->cnr == card->cardnr) {
skb = alloc_skb(7, GFP_ATOMIC); skb = alloc_skb(7, GFP_ATOMIC);
if (!skb) { if (!skb) {
...@@ -996,12 +999,25 @@ void c4_release_appl(struct capi_ctr *ctrl, u16 appl) ...@@ -996,12 +999,25 @@ void c4_release_appl(struct capi_ctr *ctrl, u16 appl)
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
static void c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) static u16 c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
{ {
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
avmcard *card = cinfo->card; avmcard *card = cinfo->card;
skb_queue_tail(&card->dma->send_queue, skb); u16 retval = CAPI_NOERROR;
c4_dispatch_tx(card);
if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
retval = capilib_data_b3_req(&cinfo->ncci_head,
CAPIMSG_APPID(skb->data),
CAPIMSG_NCCI(skb->data),
CAPIMSG_MSGID(skb->data));
}
if (retval == CAPI_NOERROR) {
skb_queue_tail(&card->dma->send_queue, skb);
c4_dispatch_tx(card);
} else {
dev_kfree_skb_any(skb);
}
return retval;
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
...@@ -1102,8 +1118,6 @@ static int c4_add_card(struct capi_driver *driver, ...@@ -1102,8 +1118,6 @@ static int c4_add_card(struct capi_driver *driver,
int retval; int retval;
int i; int i;
MOD_INC_USE_COUNT;
card = b1_alloc_card(nr_controllers); card = b1_alloc_card(nr_controllers);
if (!card) { if (!card) {
printk(KERN_WARNING "%s: no memory.\n", driver->name); printk(KERN_WARNING "%s: no memory.\n", driver->name);
...@@ -1189,7 +1203,6 @@ static int c4_add_card(struct capi_driver *driver, ...@@ -1189,7 +1203,6 @@ static int c4_add_card(struct capi_driver *driver,
err_free: err_free:
b1_free_card(card); b1_free_card(card);
err: err:
MOD_DEC_USE_COUNT;
return retval; return retval;
} }
...@@ -1201,7 +1214,6 @@ static struct capi_driver c2_driver = { ...@@ -1201,7 +1214,6 @@ static struct capi_driver c2_driver = {
revision: "0.0", revision: "0.0",
load_firmware: c4_load_firmware, load_firmware: c4_load_firmware,
reset_ctr: c4_reset_ctr, reset_ctr: c4_reset_ctr,
remove_ctr: c4_remove_ctr,
register_appl: c4_register_appl, register_appl: c4_register_appl,
release_appl: c4_release_appl, release_appl: c4_release_appl,
send_message: c4_send_message, send_message: c4_send_message,
...@@ -1209,8 +1221,6 @@ static struct capi_driver c2_driver = { ...@@ -1209,8 +1221,6 @@ static struct capi_driver c2_driver = {
procinfo: c4_procinfo, procinfo: c4_procinfo,
ctr_read_proc: c4_read_proc, ctr_read_proc: c4_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */ driver_read_proc: 0, /* use standard driver_read_proc */
add_card: 0, /* no add_card function */
}; };
static struct capi_driver c4_driver = { static struct capi_driver c4_driver = {
...@@ -1219,7 +1229,6 @@ static struct capi_driver c4_driver = { ...@@ -1219,7 +1229,6 @@ static struct capi_driver c4_driver = {
revision: "0.0", revision: "0.0",
load_firmware: c4_load_firmware, load_firmware: c4_load_firmware,
reset_ctr: c4_reset_ctr, reset_ctr: c4_reset_ctr,
remove_ctr: c4_remove_ctr,
register_appl: c4_register_appl, register_appl: c4_register_appl,
release_appl: c4_release_appl, release_appl: c4_release_appl,
send_message: c4_send_message, send_message: c4_send_message,
...@@ -1227,26 +1236,8 @@ static struct capi_driver c4_driver = { ...@@ -1227,26 +1236,8 @@ static struct capi_driver c4_driver = {
procinfo: c4_procinfo, procinfo: c4_procinfo,
ctr_read_proc: c4_read_proc, ctr_read_proc: c4_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */ driver_read_proc: 0, /* use standard driver_read_proc */
add_card: 0, /* no add_card function */
}; };
static int c4_attach_driver (struct capi_driver * driver)
{
char *p;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strncpy(driver->revision, p + 2, sizeof(driver->revision));
driver->revision[sizeof(driver->revision)-1] = 0;
if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
*(p-1) = 0;
}
printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
attach_capi_driver(driver);
return 0;
}
static int __devinit c4_probe(struct pci_dev *dev, static int __devinit c4_probe(struct pci_dev *dev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
...@@ -1284,40 +1275,37 @@ static struct pci_driver c4_pci_driver = { ...@@ -1284,40 +1275,37 @@ static struct pci_driver c4_pci_driver = {
name: "c4", name: "c4",
id_table: c4_pci_tbl, id_table: c4_pci_tbl,
probe: c4_probe, probe: c4_probe,
remove: c4_remove,
}; };
static int __init c4_init(void) static int __init c4_init(void)
{ {
int retval; int retval;
int ncards;
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
retval = c4_attach_driver (&c4_driver); b1_set_revision(&c2_driver, revision);
if (retval) { attach_capi_driver(&c2_driver);
MOD_DEC_USE_COUNT;
return retval;
}
retval = c4_attach_driver (&c2_driver); b1_set_revision(&c4_driver, revision);
if (retval) { attach_capi_driver(&c4_driver);
MOD_DEC_USE_COUNT;
return retval;
}
ncards = pci_register_driver(&c4_pci_driver); retval = pci_module_init(&c4_pci_driver);
if (ncards) { if (retval < 0)
printk(KERN_INFO "%s: %d C4/C2 card(s) detected\n", goto err;
c4_driver.name, ncards);
MOD_DEC_USE_COUNT; printk(KERN_INFO "%s: %d C4/C2 card(s) detected\n",
return 0; c4_driver.name, retval);
}
printk(KERN_ERR "%s: NO C4/C2 card detected\n", c4_driver.name); retval = 0;
pci_unregister_driver(&c4_pci_driver); goto out;
detach_capi_driver(&c4_driver);
err:
detach_capi_driver(&c2_driver); detach_capi_driver(&c2_driver);
detach_capi_driver(&c4_driver);
out:
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
return -ENODEV; return retval;
} }
static void __exit c4_exit(void) static void __exit c4_exit(void)
......
...@@ -17,8 +17,10 @@ ...@@ -17,8 +17,10 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/capi.h> #include <linux/capi.h>
#include <linux/netdevice.h>
#include <linux/kernelcapi.h> #include <linux/kernelcapi.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/pci.h>
#include <asm/io.h> #include <asm/io.h>
#include <linux/isdn/capicmd.h> #include <linux/isdn/capicmd.h>
#include <linux/isdn/capiutil.h> #include <linux/isdn/capiutil.h>
...@@ -35,6 +37,8 @@ MODULE_LICENSE("GPL"); ...@@ -35,6 +37,8 @@ MODULE_LICENSE("GPL");
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
static struct capi_driver t1isa_driver;
static int hema_irq_table[16] = static int hema_irq_table[16] =
{0, {0,
0, 0,
...@@ -174,6 +178,11 @@ static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs) ...@@ -174,6 +178,11 @@ static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
card->name); card->name);
} else { } else {
memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3)
capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
CAPIMSG_NCCI(skb->data),
CAPIMSG_MSGID(skb->data));
ctrl->handle_capimsg(ctrl, ApplId, skb); ctrl->handle_capimsg(ctrl, ApplId, skb);
} }
break; break;
...@@ -184,7 +193,7 @@ static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs) ...@@ -184,7 +193,7 @@ static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
NCCI = b1_get_word(card->port); NCCI = b1_get_word(card->port);
WindowSize = b1_get_word(card->port); WindowSize = b1_get_word(card->port);
ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize); capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
break; break;
...@@ -194,7 +203,7 @@ static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs) ...@@ -194,7 +203,7 @@ static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
NCCI = b1_get_word(card->port); NCCI = b1_get_word(card->port);
if (NCCI != 0xffffffff) if (NCCI != 0xffffffff)
ctrl->free_ncci(ctrl, ApplId, NCCI); capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
break; break;
...@@ -313,12 +322,13 @@ void t1isa_reset_ctr(struct capi_ctr *ctrl) ...@@ -313,12 +322,13 @@ void t1isa_reset_ctr(struct capi_ctr *ctrl)
b1_reset(port); b1_reset(port);
memset(cinfo->version, 0, sizeof(cinfo->version)); memset(cinfo->version, 0, sizeof(cinfo->version));
capilib_release(&cinfo->ncci_head);
ctrl->reseted(ctrl); ctrl->reseted(ctrl);
} }
static void t1isa_remove_ctr(struct capi_ctr *ctrl) static void t1isa_remove(struct pci_dev *pdev)
{ {
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmctrl_info *cinfo = pci_get_drvdata(pdev);
avmcard *card = cinfo->card; avmcard *card = cinfo->card;
unsigned int port = card->port; unsigned int port = card->port;
...@@ -327,99 +337,82 @@ static void t1isa_remove_ctr(struct capi_ctr *ctrl) ...@@ -327,99 +337,82 @@ static void t1isa_remove_ctr(struct capi_ctr *ctrl)
b1_reset(port); b1_reset(port);
t1_reset(port); t1_reset(port);
detach_capi_ctr(ctrl); detach_capi_ctr(cinfo->capi_ctrl);
free_irq(card->irq, card); free_irq(card->irq, card);
release_region(card->port, AVMB1_PORTLEN); release_region(card->port, AVMB1_PORTLEN);
b1_free_card(card); b1_free_card(card);
MOD_DEC_USE_COUNT;
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p) static int __init t1isa_probe(struct pci_dev *pdev)
{ {
struct capi_ctr *ctrl;
struct list_head *l;
avmctrl_info *cinfo; avmctrl_info *cinfo;
avmcard *card; avmcard *card;
int retval; int retval;
static int cardnr = 1;
MOD_INC_USE_COUNT;
card = b1_alloc_card(1); card = b1_alloc_card(1);
if (!card) { if (!card) {
printk(KERN_WARNING "%s: no memory.\n", driver->name); printk(KERN_WARNING "%s: no memory.\n", t1isa_driver.name);
retval = -ENOMEM; retval = -ENOMEM;
goto err; goto err;
} }
cinfo = card->ctrlinfo; cinfo = card->ctrlinfo;
sprintf(card->name, "t1isa-%x", p->port); card->port = pci_resource_start(pdev, 0);
card->port = p->port; card->irq = pdev->irq;
card->irq = p->irq;
card->cardtype = avm_t1isa; card->cardtype = avm_t1isa;
card->cardnr = p->cardnr; card->cardnr = cardnr++;
sprintf(card->name, "t1isa-%x", card->port);
if (!(((card->port & 0x7) == 0) && ((card->port & 0x30) != 0x30))) { if (!(((card->port & 0x7) == 0) && ((card->port & 0x30) != 0x30))) {
printk(KERN_WARNING "%s: illegal port 0x%x.\n", printk(KERN_WARNING "%s: illegal port 0x%x.\n",
driver->name, card->port); t1isa_driver.name, card->port);
retval = -EINVAL; retval = -EINVAL;
goto err_free; goto err_free;
} }
if (hema_irq_table[card->irq & 0xf] == 0) { if (hema_irq_table[card->irq & 0xf] == 0) {
printk(KERN_WARNING "%s: irq %d not valid.\n", printk(KERN_WARNING "%s: irq %d not valid.\n",
driver->name, card->irq); t1isa_driver.name, card->irq);
retval = -EINVAL; retval = -EINVAL;
goto err_free; goto err_free;
} }
list_for_each(l, &driver->contr_head) {
avmcard *cardp;
ctrl = list_entry(l, struct capi_ctr, driver_list);
cardp = ((avmctrl_info *)(ctrl->driverdata))->card;
if (cardp->cardnr == card->cardnr) {
printk(KERN_WARNING "%s: card with number %d already installed at 0x%x.\n",
driver->name, card->cardnr, cardp->port);
retval = -EINVAL;
goto err_free;
}
}
if (!request_region(card->port, AVMB1_PORTLEN, card->name)) { if (!request_region(card->port, AVMB1_PORTLEN, card->name)) {
printk(KERN_WARNING "%s: ports 0x%03x-0x%03x in use.\n", printk(KERN_INFO "%s: ports 0x%03x-0x%03x in use.\n",
driver->name, card->port, card->port + AVMB1_PORTLEN); t1isa_driver.name, card->port, card->port + AVMB1_PORTLEN);
retval = -EBUSY; retval = -EBUSY;
goto err_free; goto err_free;
} }
retval = request_irq(card->irq, t1isa_interrupt, 0, card->name, card); retval = request_irq(card->irq, t1isa_interrupt, 0, card->name, card);
if (retval) { if (retval) {
printk(KERN_ERR "%s: unable to get IRQ %d.\n", printk(KERN_INFO "%s: unable to get IRQ %d.\n",
driver->name, card->irq); t1isa_driver.name, card->irq);
retval = -EBUSY; retval = -EBUSY;
goto err_release_region; goto err_release_region;
} }
if ((retval = t1_detectandinit(card->port, card->irq, card->cardnr)) != 0) { if ((retval = t1_detectandinit(card->port, card->irq, card->cardnr)) != 0) {
printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n", printk(KERN_INFO "%s: NO card at 0x%x (%d)\n",
driver->name, card->port, retval); t1isa_driver.name, card->port, retval);
retval = -ENODEV; retval = -ENODEV;
goto err_free_irq; goto err_free_irq;
} }
t1_disable_irq(card->port); t1_disable_irq(card->port);
b1_reset(card->port); b1_reset(card->port);
cinfo->capi_ctrl = attach_capi_ctr(driver, card->name, cinfo); cinfo->capi_ctrl = attach_capi_ctr(&t1isa_driver, card->name, cinfo);
if (!cinfo->capi_ctrl) { if (!cinfo->capi_ctrl) {
printk(KERN_ERR "%s: attach controller failed.\n", printk(KERN_INFO "%s: attach controller failed.\n",
driver->name); t1isa_driver.name);
retval = -EBUSY; retval = -EBUSY;
goto err_free_irq; goto err_free_irq;
} }
printk(KERN_INFO printk(KERN_INFO "%s: AVM T1 ISA at i/o %#x, irq %d, card %d\n",
"%s: AVM T1 ISA at i/o %#x, irq %d, card %d\n", t1isa_driver.name, card->port, card->irq, card->cardnr);
driver->name, card->port, card->irq, card->cardnr);
pci_set_drvdata(pdev, cinfo);
return 0; return 0;
err_free_irq: err_free_irq:
...@@ -429,11 +422,10 @@ static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p) ...@@ -429,11 +422,10 @@ static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
err_free: err_free:
b1_free_card(card); b1_free_card(card);
err: err:
MOD_DEC_USE_COUNT;
return retval; return retval;
} }
static void t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
{ {
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
avmcard *card = cinfo->card; avmcard *card = cinfo->card;
...@@ -442,20 +434,36 @@ static void t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) ...@@ -442,20 +434,36 @@ static void t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
u16 len = CAPIMSG_LEN(skb->data); u16 len = CAPIMSG_LEN(skb->data);
u8 cmd = CAPIMSG_COMMAND(skb->data); u8 cmd = CAPIMSG_COMMAND(skb->data);
u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data); u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
u16 dlen, retval;
save_flags(flags);
cli();
if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
u16 dlen = CAPIMSG_DATALEN(skb->data); retval = capilib_data_b3_req(&cinfo->ncci_head,
CAPIMSG_APPID(skb->data),
CAPIMSG_NCCI(skb->data),
CAPIMSG_MSGID(skb->data));
if (retval != CAPI_NOERROR)
goto out;
dlen = CAPIMSG_DATALEN(skb->data);
save_flags(flags);
cli();
b1_put_byte(port, SEND_DATA_B3_REQ); b1_put_byte(port, SEND_DATA_B3_REQ);
t1_put_slice(port, skb->data, len); t1_put_slice(port, skb->data, len);
t1_put_slice(port, skb->data + len, dlen); t1_put_slice(port, skb->data + len, dlen);
restore_flags(flags);
} else { } else {
retval = CAPI_NOERROR;
save_flags(flags);
cli();
b1_put_byte(port, SEND_MESSAGE); b1_put_byte(port, SEND_MESSAGE);
t1_put_slice(port, skb->data, len); t1_put_slice(port, skb->data, len);
restore_flags(flags);
} }
restore_flags(flags); out:
dev_kfree_skb(skb); dev_kfree_skb_any(skb);
return retval;
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
...@@ -484,7 +492,6 @@ static struct capi_driver t1isa_driver = { ...@@ -484,7 +492,6 @@ static struct capi_driver t1isa_driver = {
revision: "0.0", revision: "0.0",
load_firmware: t1isa_load_firmware, load_firmware: t1isa_load_firmware,
reset_ctr: t1isa_reset_ctr, reset_ctr: t1isa_reset_ctr,
remove_ctr: t1isa_remove_ctr,
register_appl: b1_register_appl, register_appl: b1_register_appl,
release_appl: b1_release_appl, release_appl: b1_release_appl,
send_message: t1isa_send_message, send_message: t1isa_send_message,
...@@ -492,36 +499,63 @@ static struct capi_driver t1isa_driver = { ...@@ -492,36 +499,63 @@ static struct capi_driver t1isa_driver = {
procinfo: t1isa_procinfo, procinfo: t1isa_procinfo,
ctr_read_proc: b1ctl_read_proc, ctr_read_proc: b1ctl_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */ driver_read_proc: 0, /* use standard driver_read_proc */
add_card: t1isa_add_card,
}; };
#define MAX_CARDS 4
static struct pci_dev isa_dev[MAX_CARDS];
static int io[MAX_CARDS];
static int irq[MAX_CARDS];
MODULE_PARM(io, "1-" __MODULE_STRING(MAX_CARDS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i");
MODULE_PARM_DESC(io, "I/O base address(es)");
MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
static int __init t1isa_init(void) static int __init t1isa_init(void)
{ {
struct capi_driver *driver = &t1isa_driver; int i, retval;
char *p; int found = 0;
int retval = 0;
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
if ((p = strchr(revision, ':')) != 0 && p[1]) { b1_set_revision(&t1isa_driver, revision);
strncpy(driver->revision, p + 2, sizeof(driver->revision)); attach_capi_driver(&t1isa_driver);
driver->revision[sizeof(driver->revision)-1] = 0;
if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
*(p-1) = 0;
}
printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision); for (i = 0; i < MAX_CARDS; i++) {
if (!io[i])
break;
isa_dev[i].resource[0].start = io[i];
isa_dev[i].irq_resource[0].start = irq[i];
attach_capi_driver(driver); if (t1isa_probe(&isa_dev[i]) == 0)
found++;
}
if (found == 0) {
retval = -ENODEV;
goto err;
}
retval = 0;
goto out;
err:
detach_capi_driver(&t1isa_driver);
out:
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
return retval; return retval;
} }
static void __exit t1isa_exit(void) static void __exit t1isa_exit(void)
{ {
detach_capi_driver(&t1isa_driver); int i;
for (i = 0; i < MAX_CARDS; i++) {
if (!io[i])
break;
t1isa_remove(&isa_dev[i]);
}
detach_capi_driver(&t1isa_driver);
} }
module_init(t1isa_init); module_init(t1isa_init);
......
...@@ -47,14 +47,12 @@ MODULE_LICENSE("GPL"); ...@@ -47,14 +47,12 @@ MODULE_LICENSE("GPL");
static int t1pci_add_card(struct capi_driver *driver, static int t1pci_add_card(struct capi_driver *driver,
struct capicardparams *p, struct capicardparams *p,
struct pci_dev *dev) struct pci_dev *pdev)
{ {
avmcard *card; avmcard *card;
avmctrl_info *cinfo; avmctrl_info *cinfo;
int retval; int retval;
MOD_INC_USE_COUNT;
card = b1_alloc_card(1); card = b1_alloc_card(1);
if (!card) { if (!card) {
printk(KERN_WARNING "%s: no memory.\n", driver->name); printk(KERN_WARNING "%s: no memory.\n", driver->name);
...@@ -62,7 +60,7 @@ static int t1pci_add_card(struct capi_driver *driver, ...@@ -62,7 +60,7 @@ static int t1pci_add_card(struct capi_driver *driver,
goto err; goto err;
} }
card->dma = avmcard_dma_alloc(driver->name, dev, 2048+128, 2048+128); card->dma = avmcard_dma_alloc(driver->name, pdev, 2048+128, 2048+128);
if (!card->dma) { if (!card->dma) {
printk(KERN_WARNING "%s: no memory.\n", driver->name); printk(KERN_WARNING "%s: no memory.\n", driver->name);
retval = -ENOMEM; retval = -ENOMEM;
...@@ -127,6 +125,7 @@ static int t1pci_add_card(struct capi_driver *driver, ...@@ -127,6 +125,7 @@ static int t1pci_add_card(struct capi_driver *driver,
"%s: AVM T1 PCI at i/o %#x, irq %d, mem %#lx\n", "%s: AVM T1 PCI at i/o %#x, irq %d, mem %#lx\n",
driver->name, card->port, card->irq, card->membase); driver->name, card->port, card->irq, card->membase);
pci_set_drvdata(pdev, card);
return 0; return 0;
err_free_irq: err_free_irq:
...@@ -140,28 +139,24 @@ static int t1pci_add_card(struct capi_driver *driver, ...@@ -140,28 +139,24 @@ static int t1pci_add_card(struct capi_driver *driver,
err_free: err_free:
b1_free_card(card); b1_free_card(card);
err: err:
MOD_DEC_USE_COUNT;
return retval; return retval;
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
static void t1pci_remove_ctr(struct capi_ctr *ctrl) static void t1pci_remove(struct pci_dev *pdev)
{ {
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmcard *card = pci_get_drvdata(pdev);
avmcard *card = cinfo->card; avmctrl_info *cinfo = card->ctrlinfo;
b1dma_reset(card); b1dma_reset(card);
detach_capi_ctr(ctrl); detach_capi_ctr(cinfo->capi_ctrl);
free_irq(card->irq, card); free_irq(card->irq, card);
iounmap(card->mbase); iounmap(card->mbase);
release_region(card->port, AVMB1_PORTLEN); release_region(card->port, AVMB1_PORTLEN);
ctrl->driverdata = 0;
avmcard_dma_free(card->dma); avmcard_dma_free(card->dma);
b1_free_card(card); b1_free_card(card);
MOD_DEC_USE_COUNT;
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
...@@ -190,7 +185,6 @@ static struct capi_driver t1pci_driver = { ...@@ -190,7 +185,6 @@ static struct capi_driver t1pci_driver = {
revision: "0.0", revision: "0.0",
load_firmware: b1dma_load_firmware, load_firmware: b1dma_load_firmware,
reset_ctr: b1dma_reset_ctr, reset_ctr: b1dma_reset_ctr,
remove_ctr: t1pci_remove_ctr,
register_appl: b1dma_register_appl, register_appl: b1dma_register_appl,
release_appl: b1dma_release_appl, release_appl: b1dma_release_appl,
send_message: b1dma_send_message, send_message: b1dma_send_message,
...@@ -198,8 +192,6 @@ static struct capi_driver t1pci_driver = { ...@@ -198,8 +192,6 @@ static struct capi_driver t1pci_driver = {
procinfo: t1pci_procinfo, procinfo: t1pci_procinfo,
ctr_read_proc: b1dmactl_read_proc, ctr_read_proc: b1dmactl_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */ driver_read_proc: 0, /* use standard driver_read_proc */
add_card: 0, /* no add_card function */
}; };
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
...@@ -240,38 +232,32 @@ static struct pci_driver t1pci_pci_driver = { ...@@ -240,38 +232,32 @@ static struct pci_driver t1pci_pci_driver = {
name: "t1pci", name: "t1pci",
id_table: t1pci_pci_tbl, id_table: t1pci_pci_tbl,
probe: t1pci_probe, probe: t1pci_probe,
remove: t1pci_remove,
}; };
static int __init t1pci_init(void) static int __init t1pci_init(void)
{ {
struct capi_driver *driver = &t1pci_driver; int retval;
char *p;
int ncards;
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
if ((p = strchr(revision, ':')) != 0 && p[1]) { b1_set_revision(&t1pci_driver, revision);
strncpy(driver->revision, p + 2, sizeof(driver->revision) - 1); attach_capi_driver(&t1pci_driver);
if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
*(p-1) = 0;
}
printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision); retval = pci_register_driver(&t1pci_pci_driver);
if (retval < 0)
goto err;
attach_capi_driver(&t1pci_driver); printk(KERN_INFO "%s: %d T1-PCI card(s) detected\n",
t1pci_driver.name, retval);
retval = 0;
goto out;
ncards = pci_register_driver(&t1pci_pci_driver); err:
if (ncards) {
printk(KERN_INFO "%s: %d T1-PCI card(s) detected\n",
driver->name, ncards);
MOD_DEC_USE_COUNT;
return 0;
}
printk(KERN_ERR "%s: NO T1-PCI card detected\n", driver->name);
pci_unregister_driver(&t1pci_pci_driver);
detach_capi_driver(&t1pci_driver); detach_capi_driver(&t1pci_driver);
out:
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
return -ENODEV; return retval;
} }
static void __exit t1pci_exit(void) static void __exit t1pci_exit(void)
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/netdevice.h>
#define VER_DRIVER 0 #define VER_DRIVER 0
#define VER_CARDTYPE 1 #define VER_CARDTYPE 1
...@@ -62,9 +62,12 @@ Kernel-Capi callback reset_ctr ...@@ -62,9 +62,12 @@ Kernel-Capi callback reset_ctr
void void
hycapi_reset_ctr(struct capi_ctr *ctrl) hycapi_reset_ctr(struct capi_ctr *ctrl)
{ {
hycapictrl_info *cinfo = ctrl->driverdata;
#ifdef HYCAPI_PRINTFNAMES #ifdef HYCAPI_PRINTFNAMES
printk(KERN_NOTICE "HYCAPI hycapi_reset_ctr\n"); printk(KERN_NOTICE "HYCAPI hycapi_reset_ctr\n");
#endif #endif
capilib_release(&cinfo->ncci_head);
ctrl->reseted(ctrl); ctrl->reseted(ctrl);
} }
...@@ -269,6 +272,9 @@ static void hycapi_release_internal(struct capi_ctr *ctrl, __u16 appl) ...@@ -269,6 +272,9 @@ static void hycapi_release_internal(struct capi_ctr *ctrl, __u16 appl)
__u16 len; __u16 len;
__u8 _command = 0xa1, _subcommand = 0x80; __u8 _command = 0xa1, _subcommand = 0x80;
__u16 MessageNumber = 0x0000; __u16 MessageNumber = 0x0000;
capilib_release_appl(&cinfo->ncci_head, appl);
#ifdef HYCAPI_PRINTFNAMES #ifdef HYCAPI_PRINTFNAMES
printk(KERN_NOTICE "hycapi_release_appl\n"); printk(KERN_NOTICE "hycapi_release_appl\n");
#endif #endif
...@@ -373,12 +379,14 @@ firmware-releases that do not check the MsgLen-Indication! ...@@ -373,12 +379,14 @@ firmware-releases that do not check the MsgLen-Indication!
***************************************************************/ ***************************************************************/
void hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) u16 hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
{ {
__u16 appl_id; __u16 appl_id;
int _len, _len2; int _len, _len2;
__u8 msghead[64]; __u8 msghead[64];
hycapictrl_info *cinfo = ctrl->driverdata;
u16 retval = CAPI_NOERROR;
appl_id = CAPIMSG_APPID(skb->data); appl_id = CAPIMSG_APPID(skb->data);
switch(_hycapi_appCheck(appl_id, ctrl->cnr)) switch(_hycapi_appCheck(appl_id, ctrl->cnr))
{ {
...@@ -392,12 +400,13 @@ void hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) ...@@ -392,12 +400,13 @@ void hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
break; break;
default: default:
printk(KERN_ERR "HYCAPI: Controller mixup!\n"); printk(KERN_ERR "HYCAPI: Controller mixup!\n");
return; retval = CAPI_ILLAPPNR;
goto out;
} }
switch(CAPIMSG_CMD(skb->data)) { switch(CAPIMSG_CMD(skb->data)) {
case CAPI_DISCONNECT_B3_RESP: case CAPI_DISCONNECT_B3_RESP:
ctrl->free_ncci(ctrl, appl_id, capilib_free_ncci(&cinfo->ncci_head, appl_id,
CAPIMSG_NCCI(skb->data)); CAPIMSG_NCCI(skb->data));
break; break;
case CAPI_DATA_B3_REQ: case CAPI_DATA_B3_REQ:
_len = CAPIMSG_LEN(skb->data); _len = CAPIMSG_LEN(skb->data);
...@@ -407,6 +416,10 @@ void hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) ...@@ -407,6 +416,10 @@ void hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
memcpy(skb->data + _len2, msghead, 22); memcpy(skb->data + _len2, msghead, 22);
skb_pull(skb, _len2); skb_pull(skb, _len2);
CAPIMSG_SETLEN(skb->data, 22); CAPIMSG_SETLEN(skb->data, 22);
retval = capilib_data_b3_req(&cinfo->ncci_head,
CAPIMSG_APPID(skb->data),
CAPIMSG_NCCI(skb->data),
CAPIMSG_MSGID(skb->data));
} }
break; break;
case CAPI_LISTEN_REQ: case CAPI_LISTEN_REQ:
...@@ -423,7 +436,13 @@ void hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) ...@@ -423,7 +436,13 @@ void hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
default: default:
break; break;
} }
hycapi_sendmsg_internal(ctrl, skb); out:
if (retval == CAPI_NOERROR)
hycapi_sendmsg_internal(ctrl, skb);
else
dev_kfree_skb_any(skb);
return retval;
} }
/********************************************************************* /*********************************************************************
...@@ -575,8 +594,8 @@ hycapi_rx_capipkt(hysdn_card * card, uchar * buf, word len) ...@@ -575,8 +594,8 @@ hycapi_rx_capipkt(hysdn_card * card, uchar * buf, word len)
switch(info) switch(info)
{ {
case 0: case 0:
ctrl->new_ncci(ctrl, ApplId, CAPIMSG_NCCI(skb->data), capilib_new_ncci(&cinfo->ncci_head, ApplId, CAPIMSG_NCCI(skb->data),
hycapi_applications[ApplId-1].rp.datablkcnt); hycapi_applications[ApplId-1].rp.datablkcnt);
break; break;
case 0x0001: case 0x0001:
...@@ -604,9 +623,14 @@ hycapi_rx_capipkt(hysdn_card * card, uchar * buf, word len) ...@@ -604,9 +623,14 @@ hycapi_rx_capipkt(hysdn_card * card, uchar * buf, word len)
} }
break; break;
case CAPI_CONNECT_B3_IND: case CAPI_CONNECT_B3_IND:
ctrl->new_ncci(ctrl, ApplId, capilib_new_ncci(&cinfo->ncci_head, ApplId,
CAPIMSG_NCCI(skb->data), CAPIMSG_NCCI(skb->data),
hycapi_applications[ApplId-1].rp.datablkcnt); hycapi_applications[ApplId-1].rp.datablkcnt);
break;
case CAPI_DATA_B3_CONF:
capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
CAPIMSG_NCCI(skb->data),
CAPIMSG_MSGID(skb->data));
break; break;
default: default:
break; break;
...@@ -669,7 +693,6 @@ static struct capi_driver hycapi_driver = { ...@@ -669,7 +693,6 @@ static struct capi_driver hycapi_driver = {
revision: "0.0", revision: "0.0",
load_firmware: hycapi_load_firmware, load_firmware: hycapi_load_firmware,
reset_ctr: hycapi_reset_ctr, reset_ctr: hycapi_reset_ctr,
remove_ctr: hycapi_remove_ctr,
register_appl: hycapi_register_appl, register_appl: hycapi_register_appl,
release_appl: hycapi_release_appl, release_appl: hycapi_release_appl,
send_message: hycapi_send_message, send_message: hycapi_send_message,
...@@ -677,8 +700,6 @@ static struct capi_driver hycapi_driver = { ...@@ -677,8 +700,6 @@ static struct capi_driver hycapi_driver = {
procinfo: hycapi_procinfo, procinfo: hycapi_procinfo,
ctr_read_proc: hycapi_read_proc, ctr_read_proc: hycapi_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */ driver_read_proc: 0, /* use standard driver_read_proc */
add_card: 0, /* no add_card function */
}; };
...@@ -786,6 +807,7 @@ hycapi_capi_create(hysdn_card *card) ...@@ -786,6 +807,7 @@ hycapi_capi_create(hysdn_card *card)
card->hyctrlinfo = cinfo; card->hyctrlinfo = cinfo;
cinfo->card = card; cinfo->card = card;
spin_lock_init(&cinfo->lock); spin_lock_init(&cinfo->lock);
INIT_LIST_HEAD(&cinfo->ncci_head);
switch (card->brdtype) { switch (card->brdtype) {
case BD_PCCARD: strcpy(cinfo->cardname,"HYSDN Hycard"); break; case BD_PCCARD: strcpy(cinfo->cardname,"HYSDN Hycard"); break;
......
...@@ -213,6 +213,8 @@ typedef struct HYSDN_CARD { ...@@ -213,6 +213,8 @@ typedef struct HYSDN_CARD {
int in_idx, out_idx; /* indexes to buffer ring */ int in_idx, out_idx; /* indexes to buffer ring */
int sk_count; /* number of buffers currently in ring */ int sk_count; /* number of buffers currently in ring */
struct sk_buff *tx_skb; /* buffer for tx operation */ struct sk_buff *tx_skb; /* buffer for tx operation */
struct list_head ncci_head;
} *hyctrlinfo; } *hyctrlinfo;
#endif /* CONFIG_HYSDN_CAPI */ #endif /* CONFIG_HYSDN_CAPI */
} hysdn_card; } hysdn_card;
...@@ -284,7 +286,7 @@ extern void hycapi_remove_ctr(struct capi_ctr *); ...@@ -284,7 +286,7 @@ extern void hycapi_remove_ctr(struct capi_ctr *);
extern void hycapi_register_appl(struct capi_ctr *, __u16 appl, extern void hycapi_register_appl(struct capi_ctr *, __u16 appl,
capi_register_params *); capi_register_params *);
extern void hycapi_release_appl(struct capi_ctr *, __u16 appl); extern void hycapi_release_appl(struct capi_ctr *, __u16 appl);
extern void hycapi_send_message(struct capi_ctr *, struct sk_buff *skb); extern u16 hycapi_send_message(struct capi_ctr *, struct sk_buff *skb);
extern char *hycapi_procinfo(struct capi_ctr *); extern char *hycapi_procinfo(struct capi_ctr *);
extern int hycapi_read_proc(char *page, char **start, off_t off, extern int hycapi_read_proc(char *page, char **start, off_t off,
int count, int *eof, struct capi_ctr *card); int count, int *eof, struct capi_ctr *card);
......
...@@ -61,12 +61,12 @@ typedef struct avmb1_extcarddef { ...@@ -61,12 +61,12 @@ typedef struct avmb1_extcarddef {
} avmb1_extcarddef; } avmb1_extcarddef;
#define AVMB1_LOAD 0 /* load image to card */ #define AVMB1_LOAD 0 /* load image to card */
#define AVMB1_ADDCARD 1 /* add a new card */ #define AVMB1_ADDCARD 1 /* add a new card - OBSOLETE */
#define AVMB1_RESETCARD 2 /* reset a card */ #define AVMB1_RESETCARD 2 /* reset a card */
#define AVMB1_LOAD_AND_CONFIG 3 /* load image and config to card */ #define AVMB1_LOAD_AND_CONFIG 3 /* load image and config to card */
#define AVMB1_ADDCARD_WITH_TYPE 4 /* add a new card, with cardtype */ #define AVMB1_ADDCARD_WITH_TYPE 4 /* add a new card, with cardtype */
#define AVMB1_GET_CARDINFO 5 /* get cardtype */ #define AVMB1_GET_CARDINFO 5 /* get cardtype */
#define AVMB1_REMOVECARD 6 /* remove a card (useful for T1) */ #define AVMB1_REMOVECARD 6 /* remove a card - OBSOLETE */
#define AVMB1_REGISTERCARD_IS_OBSOLETE #define AVMB1_REGISTERCARD_IS_OBSOLETE
......
...@@ -12,7 +12,10 @@ ...@@ -12,7 +12,10 @@
#ifndef __CAPILLI_H__ #ifndef __CAPILLI_H__
#define __CAPILLI_H__ #define __CAPILLI_H__
#include <linux/kernel.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/capi.h>
#include <linux/kernelcapi.h>
typedef struct capiloaddatapart { typedef struct capiloaddatapart {
int user; /* data in userspace ? */ int user; /* data in userspace ? */
...@@ -60,10 +63,6 @@ struct capi_ctr { ...@@ -60,10 +63,6 @@ struct capi_ctr {
void (*handle_capimsg)(struct capi_ctr * card, void (*handle_capimsg)(struct capi_ctr * card,
__u16 appl, struct sk_buff *skb); __u16 appl, struct sk_buff *skb);
void (*new_ncci)(struct capi_ctr * card,
__u16 appl, __u32 ncci, __u32 winsize);
void (*free_ncci)(struct capi_ctr * card, __u16 appl, __u32 ncci);
/* management information for kcapi */ /* management information for kcapi */
unsigned long nrecvctlpkt; unsigned long nrecvctlpkt;
...@@ -81,11 +80,10 @@ struct capi_driver { ...@@ -81,11 +80,10 @@ struct capi_driver {
char revision[32]; char revision[32];
int (*load_firmware)(struct capi_ctr *, capiloaddata *); int (*load_firmware)(struct capi_ctr *, capiloaddata *);
void (*reset_ctr)(struct capi_ctr *); void (*reset_ctr)(struct capi_ctr *);
void (*remove_ctr)(struct capi_ctr *);
void (*register_appl)(struct capi_ctr *, __u16 appl, void (*register_appl)(struct capi_ctr *, __u16 appl,
capi_register_params *); capi_register_params *);
void (*release_appl)(struct capi_ctr *, __u16 appl); void (*release_appl)(struct capi_ctr *, __u16 appl);
void (*send_message)(struct capi_ctr *, struct sk_buff *skb); u16 (*send_message)(struct capi_ctr *, struct sk_buff *skb);
char *(*procinfo)(struct capi_ctr *); char *(*procinfo)(struct capi_ctr *);
int (*ctr_read_proc)(char *page, char **start, off_t off, int (*ctr_read_proc)(char *page, char **start, off_t off,
...@@ -93,8 +91,6 @@ struct capi_driver { ...@@ -93,8 +91,6 @@ struct capi_driver {
int (*driver_read_proc)(char *page, char **start, off_t off, int (*driver_read_proc)(char *page, char **start, off_t off,
int count, int *eof, struct capi_driver *driver); int count, int *eof, struct capi_driver *driver);
int (*add_card)(struct capi_driver *driver, capicardparams *data);
/* intitialized by kcapi */ /* intitialized by kcapi */
struct list_head contr_head; /* list of controllers */ struct list_head contr_head; /* list of controllers */
struct list_head driver_list; struct list_head driver_list;
...@@ -109,4 +105,16 @@ void detach_capi_driver(struct capi_driver *driver); ...@@ -109,4 +105,16 @@ void detach_capi_driver(struct capi_driver *driver);
struct capi_ctr *attach_capi_ctr(struct capi_driver *driver, char *name, void *data); struct capi_ctr *attach_capi_ctr(struct capi_driver *driver, char *name, void *data);
int detach_capi_ctr(struct capi_ctr *); int detach_capi_ctr(struct capi_ctr *);
// ---------------------------------------------------------------------------
// library functions for use by hardware controller drivers
void capilib_new_ncci(struct list_head *head, u16 applid, u32 ncci, u32 winsize);
void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci);
void capilib_release_appl(struct list_head *head, u16 applid);
void capilib_release(struct list_head *head);
void capilib_data_b3_conf(struct list_head *head, u16 applid, u32 ncci, u16 msgid);
u16 capilib_data_b3_req(struct list_head *head, u16 applid, u32 ncci, u16 msgid);
#endif /* __CAPILLI_H__ */ #endif /* __CAPILLI_H__ */
...@@ -32,7 +32,7 @@ typedef struct kcapi_carddef { ...@@ -32,7 +32,7 @@ typedef struct kcapi_carddef {
/* new ioctls >= 10 */ /* new ioctls >= 10 */
#define KCAPI_CMD_TRACE 10 #define KCAPI_CMD_TRACE 10
#define KCAPI_CMD_ADDCARD 11 /* add card to named driver */ #define KCAPI_CMD_ADDCARD 11 /* OBSOLETE */
/* /*
* flag > 2 => trace also data * flag > 2 => trace also data
...@@ -47,6 +47,8 @@ typedef struct kcapi_carddef { ...@@ -47,6 +47,8 @@ typedef struct kcapi_carddef {
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/skbuff.h>
struct capi_interface { struct capi_interface {
__u16 (*capi_isinstalled) (void); __u16 (*capi_isinstalled) (void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment