Commit bb257be4 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ISDN udpate

From: Karsten Keil <kkeil@suse.de>

- new port of 2.4 I4L core to 2.6

- new port of 2.4 I4L HiSax to 2.6

- fixes for I4L CAPI subsystem to make it stable in 2.6

- fix parameter handling of AVM ISA cards (calle)

- cleanup ISDN config variables

- SMP in act2000 and pcbit driver

- remove check_region in act2000

- mark hysdn, isdnloop and divert as BROKEN_ON_SMP
parent f7d6fe84
......@@ -45,7 +45,7 @@ obj-$(CONFIG_I2C) += i2c/
obj-$(CONFIG_PHONE) += telephony/
obj-$(CONFIG_MD) += md/
obj-$(CONFIG_BT) += bluetooth/
obj-$(CONFIG_ISDN_BOOL) += isdn/
obj-$(CONFIG_ISDN) += isdn/
obj-$(CONFIG_MCA) += mca/
obj-$(CONFIG_EISA) += eisa/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
......@@ -4,8 +4,8 @@
menu "ISDN subsystem"
config ISDN_BOOL
bool "ISDN support"
config ISDN
tristate "ISDN support"
depends on NET
---help---
ISDN ("Integrated Services Digital Networks", called RNIS in France)
......@@ -22,9 +22,9 @@ config ISDN_BOOL
menu "Old ISDN4Linux"
depends on NET && ISDN_BOOL && BROKEN_ON_SMP
depends on NET && ISDN
config ISDN
config ISDN_I4L
tristate "Old ISDN4Linux (obsolete)"
---help---
This driver allows you to use an ISDN-card for networking
......@@ -41,18 +41,18 @@ config ISDN
Therefore the old ISDN4Linux layer is becoming obsolete. It is
still usable, though, if you select this option.
if ISDN
if ISDN_I4L
source "drivers/isdn/i4l/Kconfig"
endif
endmenu
comment "CAPI subsystem"
depends on NET && ISDN_BOOL
depends on NET && ISDN
config ISDN_CAPI
tristate "CAPI2.0 support"
depends on ISDN_BOOL
depends on ISDN
help
This provides the CAPI (Common ISDN Application Programming
Interface, a standard making it easy for programs to access ISDN
......
......@@ -2,7 +2,7 @@
# Object files in subdirectories
obj-$(CONFIG_ISDN) += i4l/
obj-$(CONFIG_ISDN_I4L) += i4l/
obj-$(CONFIG_ISDN_CAPI) += capi/
obj-$(CONFIG_ISDN_CAPI) += hardware/
obj-$(CONFIG_ISDN_DIVERSION) += divert/
......
......@@ -3,7 +3,7 @@
#
config ISDN_DRV_ACT2000
tristate "IBM Active 2000 support"
depends on ISDN && ISA
depends on ISDN_I4L && ISA
help
Say Y here if you have an IBM Active 2000 ISDN card. In order to use
this card, additional firmware is necessary, which has to be loaded
......
......@@ -147,34 +147,36 @@ typedef union irq_data {
* Per card driver data
*/
typedef struct act2000_card {
unsigned short port; /* Base-port-address */
unsigned short irq; /* Interrupt */
u_char ptype; /* Protocol type (1TR6 or Euro) */
u_char bus; /* Cardtype (ISA, MCA, PCMCIA) */
struct act2000_card *next; /* Pointer to next device struct */
int myid; /* Driver-Nr. assigned by linklevel */
unsigned long flags; /* Statusflags */
unsigned long ilock; /* Semaphores for IRQ-Routines */
struct sk_buff_head rcvq; /* Receive-Message queue */
struct sk_buff_head sndq; /* Send-Message queue */
struct sk_buff_head ackq; /* Data-Ack-Message queue */
u_char *ack_msg; /* Ptr to User Data in User skb */
__u16 need_b3ack; /* Flag: Need ACK for current skb */
struct sk_buff *sbuf; /* skb which is currently sent */
struct timer_list ptimer; /* Poll timer */
struct work_struct snd_tq; /* Task struct for xmit bh */
struct work_struct rcv_tq; /* Task struct for rcv bh */
struct work_struct poll_tq; /* Task struct for polled rcv bh */
unsigned short port; /* Base-port-address */
unsigned short irq; /* Interrupt */
u_char ptype; /* Protocol type (1TR6 or Euro) */
u_char bus; /* Cardtype (ISA, MCA, PCMCIA) */
struct act2000_card *next; /* Pointer to next device struct */
spinlock_t lock; /* protect critical operations */
int myid; /* Driver-Nr. assigned by linklevel */
unsigned long flags; /* Statusflags */
unsigned long ilock; /* Semaphores for IRQ-Routines */
struct sk_buff_head rcvq; /* Receive-Message queue */
struct sk_buff_head sndq; /* Send-Message queue */
struct sk_buff_head ackq; /* Data-Ack-Message queue */
u_char *ack_msg; /* Ptr to User Data in User skb */
__u16 need_b3ack; /* Flag: Need ACK for current skb */
struct sk_buff *sbuf; /* skb which is currently sent */
struct timer_list ptimer; /* Poll timer */
struct work_struct snd_tq; /* Task struct for xmit bh */
struct work_struct rcv_tq; /* Task struct for rcv bh */
struct work_struct poll_tq; /* Task struct for polled rcv bh */
msn_entry *msn_list;
unsigned short msgnum; /* Message number fur sending */
act2000_chan bch[ACT2000_BCH]; /* B-Channel status/control */
char status_buf[256]; /* Buffer for status messages */
unsigned short msgnum; /* Message number for sending */
spinlock_t mnlock; /* lock for msgnum */
act2000_chan bch[ACT2000_BCH]; /* B-Channel status/control */
char status_buf[256]; /* Buffer for status messages */
char *status_buf_read;
char *status_buf_write;
char *status_buf_end;
irq_data idat; /* Data used for IRQ handler */
isdn_if interface; /* Interface to upper layer */
char regname[35]; /* Name used for request_region */
irq_data idat; /* Data used for IRQ handler */
isdn_if interface; /* Interface to upper layer */
char regname[35]; /* Name used for request_region */
} act2000_card;
extern __inline__ void act2000_schedule_tx(act2000_card *card)
......
......@@ -21,10 +21,8 @@ static act2000_card *irq2card_map[16];
static void
act2000_isa_delay(long t)
{
sti();
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(t);
sti();
}
/*
......@@ -64,8 +62,10 @@ act2000_isa_detect(unsigned short portbase)
{
int ret = 0;
if (!check_region(portbase, ISA_REGION))
if (request_region(portbase, ACT2000_PORTLEN, "act2000isa")) {
ret = act2000_isa_reset(portbase);
release_region(portbase, ISA_REGION);
}
return ret;
}
......@@ -177,14 +177,13 @@ act2000_isa_config_port(act2000_card * card, unsigned short portbase)
release_region(card->port, ISA_REGION);
card->flags &= ~ACT2000_FLAGS_PVALID;
}
if (!check_region(portbase, ISA_REGION)) {
if (request_region(portbase, ACT2000_PORTLEN, card->regname) == NULL)
return -EIO;
if (request_region(portbase, ACT2000_PORTLEN, card->regname) == NULL)
return -EBUSY;
else {
card->port = portbase;
card->flags |= ACT2000_FLAGS_PVALID;
return 0;
}
return -EBUSY;
}
/*
......@@ -195,8 +194,7 @@ act2000_isa_release(act2000_card * card)
{
unsigned long flags;
save_flags(flags);
cli();
spin_lock_irqsave(&card->lock, flags);
if (card->flags & ACT2000_FLAGS_IVALID) {
free_irq(card->irq, NULL);
irq2card_map[card->irq] = NULL;
......@@ -205,7 +203,7 @@ act2000_isa_release(act2000_card * card)
if (card->flags & ACT2000_FLAGS_PVALID)
release_region(card->port, ISA_REGION);
card->flags &= ~ACT2000_FLAGS_PVALID;
restore_flags(flags);
spin_unlock_irqrestore(&card->lock, flags);
}
static int
......@@ -316,8 +314,7 @@ act2000_isa_send(act2000_card * card)
if (test_and_set_bit(ACT2000_LOCK_TX, (void *) &card->ilock) != 0)
return;
while (1) {
save_flags(flags);
cli();
spin_lock_irqsave(&card->lock, flags);
if (!(card->sbuf)) {
if ((card->sbuf = skb_dequeue(&card->sndq))) {
card->ack_msg = card->sbuf->data;
......@@ -330,7 +327,7 @@ act2000_isa_send(act2000_card * card)
}
}
}
restore_flags(flags);
spin_unlock_irqrestore(&card->lock, flags);
if (!(card->sbuf)) {
/* No more data to send */
test_and_clear_bit(ACT2000_LOCK_TX, (void *) &card->ilock);
......
......@@ -591,10 +591,9 @@ handle_ack(act2000_card *card, act2000_chan *chan, __u8 blocknr) {
struct actcapi_msg *m;
int ret = 0;
save_flags(flags);
cli();
spin_lock_irqsave(&card->lock, flags);
skb = skb_peek(&card->ackq);
restore_flags(flags);
spin_unlock_irqrestore(&card->lock, flags);
if (!skb) {
printk(KERN_WARNING "act2000: handle_ack nothing found!\n");
return 0;
......@@ -614,10 +613,9 @@ handle_ack(act2000_card *card, act2000_chan *chan, __u8 blocknr) {
chan->queued = 0;
return ret;
}
save_flags(flags);
cli();
spin_lock_irqsave(&card->lock, flags);
tmp = skb_peek((struct sk_buff_head *)tmp);
restore_flags(flags);
spin_unlock_irqrestore(&card->lock, flags);
if ((tmp == skb) || (tmp == NULL)) {
/* reached end of queue */
printk(KERN_WARNING "act2000: handle_ack nothing found!\n");
......
......@@ -336,12 +336,11 @@ actcapi_nextsmsg(act2000_card *card)
unsigned long flags;
unsigned short n;
save_flags(flags);
cli();
spin_lock_irqsave(&card->mnlock, flags);
n = card->msgnum;
card->msgnum++;
card->msgnum &= 0x7fff;
restore_flags(flags);
spin_unlock_irqrestore(&card->mnlock, flags);
return n;
}
#define DEBUG_MSG
......
......@@ -62,19 +62,18 @@ find_channel(act2000_card *card, int channel)
static void
act2000_clear_msn(act2000_card *card)
{
struct msn_entry *p = card->msn_list;
struct msn_entry *q;
struct msn_entry *p = card->msn_list;
struct msn_entry *q;
unsigned long flags;
save_flags(flags);
cli();
card->msn_list = NULL;
restore_flags(flags);
while (p) {
q = p->next;
kfree(p);
p = q;
}
spin_lock_irqsave(&card->lock, flags);
card->msn_list = NULL;
spin_unlock_irqrestore(&card->lock, flags);
while (p) {
q = p->next;
kfree(p);
p = q;
}
}
/*
......@@ -143,13 +142,12 @@ act2000_set_msn(act2000_card *card, char *eazmsn)
/* Delete a single MSN */
while (p) {
if (p->eaz == eazmsn[0]) {
save_flags(flags);
cli();
spin_lock_irqsave(&card->lock, flags);
if (q)
q->next = p->next;
else
card->msn_list = p->next;
restore_flags(flags);
spin_unlock_irqrestore(&card->lock, flags);
kfree(p);
printk(KERN_DEBUG
"Mapping for EAZ %c deleted\n",
......@@ -165,10 +163,9 @@ act2000_set_msn(act2000_card *card, char *eazmsn)
while (p) {
/* Found in list, replace MSN */
if (p->eaz == eazmsn[0]) {
save_flags(flags);
cli();
spin_lock_irqsave(&card->lock, flags);
strcpy(p->msn, &eazmsn[1]);
restore_flags(flags);
spin_unlock_irqrestore(&card->lock, flags);
printk(KERN_DEBUG
"Mapping for EAZ %c changed to %s\n",
eazmsn[0],
......@@ -184,10 +181,9 @@ act2000_set_msn(act2000_card *card, char *eazmsn)
p->eaz = eazmsn[0];
strcpy(p->msn, &eazmsn[1]);
p->next = card->msn_list;
save_flags(flags);
cli();
spin_lock_irqsave(&card->lock, flags);
card->msn_list = p;
restore_flags(flags);
spin_unlock_irqrestore(&card->lock, flags);
printk(KERN_DEBUG
"Mapping %c -> %s added\n",
eazmsn[0],
......@@ -232,10 +228,9 @@ act2000_poll(unsigned long data)
unsigned long flags;
act2000_receive(card);
save_flags(flags);
cli();
mod_timer(&card->ptimer, jiffies+3);
restore_flags(flags);
spin_lock_irqsave(&card->lock, flags);
mod_timer(&card->ptimer, jiffies+3);
spin_unlock_irqrestore(&card->lock, flags);
}
static int
......@@ -311,10 +306,9 @@ act2000_command(act2000_card * card, isdn_ctrl * c)
return -ENODEV;
if (!(chan = find_channel(card, c->arg & 0x0f)))
break;
save_flags(flags);
cli();
spin_lock_irqsave(&card->lock, flags);
if (chan->fsm_state != ACT2000_STATE_NULL) {
restore_flags(flags);
spin_unlock_irqrestore(&card->lock, flags);
printk(KERN_WARNING "Dial on channel with state %d\n",
chan->fsm_state);
return -EBUSY;
......@@ -325,7 +319,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c)
tmp[0] = c->parm.setup.eazmsn[0];
chan->fsm_state = ACT2000_STATE_OCALL;
chan->callref = 0xffff;
restore_flags(flags);
spin_unlock_irqrestore(&card->lock, flags);
ret = actcapi_connect_req(card, chan, c->parm.setup.phone,
tmp[0], c->parm.setup.si1,
c->parm.setup.si2);
......@@ -580,6 +574,8 @@ act2000_alloccard(int bus, int port, int irq, char *id)
return;
}
memset((char *) card, 0, sizeof(act2000_card));
spin_lock_init(&card->lock);
spin_lock_init(&card->mnlock);
skb_queue_head_init(&card->sndq);
skb_queue_head_init(&card->rcvq);
skb_queue_head_init(&card->ackq);
......
......@@ -44,7 +44,7 @@ config ISDN_CAPI_CAPIFS
config ISDN_CAPI_CAPIDRV
tristate "CAPI2.0 capidrv interface support"
depends on ISDN_CAPI && ISDN
depends on ISDN_CAPI && ISDN_I4L
help
This option provides the glue code to hook up CAPI driven cards to
the legacy isdn4linux link layer. If you have a card which is
......
/* $Id: capi.c,v 1.1.4.1.2.2 2001/12/21 15:00:17 kai Exp $
/* $Id: capi.c,v 1.1.2.3 2004/01/16 21:09:26 keil Exp $
*
* CAPI 2.0 Interface for Linux
*
......@@ -44,7 +44,7 @@
#include "capifs.h"
#endif
static char *revision = "$Revision: 1.1.4.1.2.2 $";
static char *revision = "$Revision: 1.1.2.3 $";
MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface");
MODULE_AUTHOR("Carsten Paeth");
......@@ -203,7 +203,7 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
struct list_head *l;
unsigned int minor = 0;
unsigned long flags;
mp = kmalloc(sizeof(*mp), GFP_ATOMIC);
if (!mp) {
printk(KERN_ERR "capi: can't alloc capiminor\n");
......@@ -220,19 +220,24 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
skb_queue_head_init(&mp->outqueue);
write_lock_irqsave(&capiminor_list_lock, flags);
list_for_each(l, &capiminor_list) {
p = list_entry(l, struct capiminor, list);
if (p->minor > minor) {
mp->minor = minor;
list_add_tail(&mp->list, &p->list);
break;
if (list_empty(&capiminor_list)) {
list_add(&mp->list, &capiminor_list);
write_unlock_irqrestore(&capiminor_list_lock, flags);
} else {
list_for_each(l, &capiminor_list) {
p = list_entry(l, struct capiminor, list);
if (p->minor > minor) {
mp->minor = minor;
list_add_tail(&mp->list, &p->list);
break;
}
minor++;
}
write_unlock_irqrestore(&capiminor_list_lock, flags);
if (l == &capiminor_list) {
kfree(mp);
return NULL;
}
minor++;
}
write_unlock_irqrestore(&capiminor_list_lock, flags);
if (l == &capiminor_list) {
kfree(mp);
return NULL;
}
return mp;
}
......@@ -297,7 +302,7 @@ static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci)
printk(KERN_DEBUG "set mp->nccip\n");
#endif
#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
capifs_new_ncci(0, mp->minor, MKDEV(capi_ttymajor, mp->minor));
capifs_new_ncci(mp->minor, MKDEV(capi_ttymajor, mp->minor));
#endif
}
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
......@@ -322,8 +327,7 @@ static void capincci_free(struct capidev *cdev, u32 ncci)
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
if ((mp = np->minorp) != 0) {
#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
capifs_free_ncci('r', mp->minor);
capifs_free_ncci(0, mp->minor);
capifs_free_ncci(mp->minor);
#endif
if (mp->tty) {
mp->nccip = 0;
......
/* $Id: capidrv.c,v 1.39.6.7 2001/09/23 22:24:33 kai Exp $
/* $Id: capidrv.c,v 1.1.2.2 2004/01/12 23:17:24 keil Exp $
*
* ISDN4Linux Driver, using capi20 interface (kernelcapi)
*
......@@ -34,7 +34,7 @@
#include <linux/isdn/capicmd.h>
#include "capidrv.h"
static char *revision = "$Revision: 1.39.6.7 $";
static char *revision = "$Revision: 1.1.2.2 $";
static int debugmode = 0;
MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux");
......@@ -1263,6 +1263,10 @@ static void handle_ncci(_cmsg * cmsg)
goto ignored;
case CAPI_DATA_B3_CONF: /* ncci */
if (cmsg->Info) {
printk(KERN_WARNING "CAPI_DATA_B3_CONF: Info %x - %s\n",
cmsg->Info, capi_info2str(cmsg->Info));
}
if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
goto notfound;
......@@ -1368,7 +1372,7 @@ static _cmsg s_cmsg;
static void capidrv_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
{
capi_message2cmsg(&s_cmsg, skb->data);
if (debugmode > 2)
if (debugmode > 3)
printk(KERN_DEBUG "capidrv_signal: applid=%d %s\n",
ap->applid, capi_cmsg2str(&s_cmsg));
......@@ -1825,7 +1829,7 @@ static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb)
id);
return 0;
}
if (debugmode > 1)
if (debugmode > 4)
printk(KERN_DEBUG "capidrv-%d: sendbuf len=%d skb=%p doack=%d\n",
card->contrnr, len, skb, doack);
bchan = &card->bchans[channel % card->nbchan];
......@@ -1866,6 +1870,9 @@ static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb)
nccip->datahandle++;
return len;
}
if (debugmode > 3)
printk(KERN_DEBUG "capidrv-%d: sendbuf putmsg ret(%x) - %s\n",
card->contrnr, errcode, capi_info2str(errcode));
(void)capidrv_del_ack(nccip, datahandle);
dev_kfree_skb(nskb);
return errcode == CAPI_SENDQUEUEFULL ? 0 : -1;
......@@ -1876,6 +1883,9 @@ static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb)
nccip->datahandle++;
return len;
}
if (debugmode > 3)
printk(KERN_DEBUG "capidrv-%d: sendbuf putmsg ret(%x) - %s\n",
card->contrnr, errcode, capi_info2str(errcode));
skb_pull(skb, msglen);
(void)capidrv_del_ack(nccip, datahandle);
return errcode == CAPI_SENDQUEUEFULL ? 0 : -1;
......
/* $Id: capifs.c,v 1.14.6.8 2001/09/23 22:24:33 kai Exp $
/* $Id: capifs.c,v 1.1.2.3 2004/01/16 21:09:26 keil Exp $
*
* Copyright 2000 by Carsten Paeth <calle@calle.de>
*
......@@ -20,99 +20,75 @@ MODULE_DESCRIPTION("CAPI4Linux: /dev/capi/ filesystem");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
static char *revision = "$Revision: 1.14.6.8 $";
/* ------------------------------------------------------------------ */
static char *revision = "$Revision: 1.1.2.3 $";
/* ------------------------------------------------------------------ */
struct options {
#define CAPIFS_SUPER_MAGIC (('C'<<8)|'N')
static struct vfsmount *capifs_mnt;
static struct dentry *capifs_root;
static struct {
int setuid;
int setgid;
uid_t uid;
gid_t gid;
umode_t mode;
};
static struct options options = {.mode = 0600};
#define CAPIFS_SUPER_MAGIC (('C'<<8)|'N')
} config = {.mode = 0600};
/* ------------------------------------------------------------------ */
static int capifs_parse_options(char *s, struct options *p)
static int capifs_remount(struct super_block *s, int *flags, char *data)
{
int setuid = 0;
int setgid = 0;
uid_t uid = 0;
gid_t gid = 0;
umode_t mode = 0600;
char *this_char, *value;
char *this_char;
if (!s)
return 0;
while ((this_char = strsep(&s, ",")) != NULL) {
this_char = NULL;
while ((this_char = strsep(&data, ",")) != NULL) {
int n;
char dummy;
if (!*this_char)
continue;
if ((value = strchr(this_char,'=')) != NULL)
*value++ = 0;
if (!strcmp(this_char,"uid")) {
if (!value || !*value)
return 1;
uid = simple_strtoul(value,&value,0);
if (*value)
return 1;
if (sscanf(this_char, "uid=%i%c", &n, &dummy) == 1) {
setuid = 1;
}
else if (!strcmp(this_char,"gid")) {
if (!value || !*value)
return 1;
gid = simple_strtoul(value,&value,0);
if (*value)
return 1;
uid = n;
} else if (sscanf(this_char, "gid=%i%c", &n, &dummy) == 1) {
setgid = 1;
gid = n;
} else if (sscanf(this_char, "mode=%o%c", &n, &dummy) == 1)
mode = n & ~S_IFMT;
else {
printk("capifs: called with bogus options\n");
return -EINVAL;
}
else if (!strcmp(this_char,"mode")) {
if (!value || !*value)
return 1;
mode = simple_strtoul(value,&value,8);
if (*value)
return 1;
}
}
p->setuid = setuid;
p->setgid = setgid;
p->uid = uid;
p->gid = gid;
p->mode = mode & ~S_IFMT;
return 0;
}
static int capifs_remount(struct super_block *s, int *flags, char *data)
{
struct options new;
if (capifs_parse_options(data, &new)) {
printk("capifs: called with bogus options\n");
return -EINVAL;
}
options = new;
config.setuid = setuid;
config.setgid = setgid;
config.uid = uid;
config.gid = gid;
config.mode = mode;
return 0;
}
static struct super_operations capifs_sops =
{
.statfs = simple_statfs,
.remount_fs = capifs_remount,
};
static int capifs_fill_super(struct super_block *s, void *data, int silent)
static int
capifs_fill_super(struct super_block *s, void *data, int silent)
{
struct inode * inode;
if (capifs_parse_options(data, &options)) {
printk("capifs: called with bogus options\n");
return -EINVAL;
}
s->s_blocksize = 1024;
s->s_blocksize_bits = 10;
s->s_magic = CAPIFS_SUPER_MAGIC;
......@@ -120,24 +96,25 @@ static int capifs_fill_super(struct super_block *s, void *data, int silent)
inode = new_inode(s);
if (!inode)
return -ENOMEM;
goto fail;
inode->i_ino = 1;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_blocks = 0;
inode->i_blksize = 1024;
inode->i_uid = inode->i_gid = 0;
inode->i_ino = 1;
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
inode->i_nlink = 2;
s->s_root = d_alloc_root(inode);
if (!s->s_root) {
printk("capifs: get root dentry failed\n");
iput(inode);
return -ENOMEM;
}
return 0;
capifs_root = s->s_root = d_alloc_root(inode);
if (s->s_root)
return 0;
printk("capifs: get root dentry failed\n");
iput(inode);
fail:
return -ENOMEM;
}
static struct super_block *capifs_get_sb(struct file_system_type *fs_type,
......@@ -153,78 +130,48 @@ static struct file_system_type capifs_fs_type = {
.kill_sb = kill_anon_super,
};
static struct vfsmount *capifs_mnt;
static int entry_count;
static int grab_instance(void)
{
return simple_pin_fs("capifs", &capifs_mnt, &entry_count);
}
static void drop_instance(void)
{
return simple_release_fs(&capifs_mnt, &entry_count);
}
static struct dentry *get_node(int type, int num)
static struct dentry *get_node(int num)
{
char s[10];
int len;
struct dentry *root = capifs_mnt->mnt_root;
if (type)
len = sprintf(s, "%d", num);
else
len = sprintf(s, "%c%d", type, num);
struct dentry *root = capifs_root;
down(&root->d_inode->i_sem);
return lookup_one_len(s, root, len);
return lookup_one_len(s, root, sprintf(s, "%d", num));
}
void capifs_new_ncci(char type, unsigned int num, dev_t device)
void capifs_new_ncci(unsigned int number, dev_t device)
{
struct super_block *sb;
struct dentry *dentry;
struct inode *inode;
if (grab_instance() < 0)
struct inode *inode = new_inode(capifs_mnt->mnt_sb);
if (!inode)
return;
sb = capifs_mnt->mnt_sb;
inode = new_inode(sb);
if (inode) {
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_blocks = 0;
inode->i_blksize = 1024;
inode->i_uid = options.setuid ? options.uid : current->fsuid;
inode->i_gid = options.setgid ? options.gid : current->fsgid;
inode->i_nlink = 1;
init_special_inode(inode, S_IFCHR | options.mode, device);
dentry = get_node(type, num);
if (!IS_ERR(dentry) && !dentry->d_inode) {
grab_instance();
d_instantiate(dentry, inode);
} else
iput(inode);
up(&sb->s_root->d_inode->i_sem);
}
drop_instance();
inode->i_ino = number+2;
inode->i_blksize = 1024;
inode->i_uid = config.setuid ? config.uid : current->fsuid;
inode->i_gid = config.setgid ? config.gid : current->fsgid;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
init_special_inode(inode, S_IFCHR|config.mode, device);
//inode->i_op = &capifs_file_inode_operations;
dentry = get_node(number);
if (!IS_ERR(dentry) && !dentry->d_inode)
d_instantiate(dentry, inode);
up(&capifs_root->d_inode->i_sem);
}
void capifs_free_ncci(char type, unsigned int num)
void capifs_free_ncci(unsigned int number)
{
if (grab_instance() == 0) {
struct dentry *dentry = get_node(type, num);
if (!IS_ERR(dentry)) {
struct inode *inode = dentry->d_inode;
if (inode) {
inode->i_nlink--;
d_delete(dentry);
dput(dentry);
drop_instance();
}
struct dentry *dentry = get_node(number);
if (!IS_ERR(dentry)) {
struct inode *inode = dentry->d_inode;
if (inode) {
inode->i_nlink--;
d_delete(dentry);
dput(dentry);
}
up(&capifs_mnt->mnt_root->d_inode->i_sem);
drop_instance();
dput(dentry);
}
up(&capifs_root->d_inode->i_sem);
}
static int __init capifs_init(void)
......@@ -241,14 +188,20 @@ static int __init capifs_init(void)
strcpy(rev, "1.0");
err = register_filesystem(&capifs_fs_type);
if (!err) {
capifs_mnt = kern_mount(&capifs_fs_type);
if (IS_ERR(capifs_mnt))
err = PTR_ERR(capifs_mnt);
}
if (!err)
printk(KERN_NOTICE "capifs: Rev %s\n", rev);
return 0;
return err;
}
static void __exit capifs_exit(void)
{
unregister_filesystem(&capifs_fs_type);
mntput(capifs_mnt);
}
EXPORT_SYMBOL(capifs_new_ncci);
......
/* $Id: capifs.h,v 1.2.6.2 2001/09/23 22:24:33 kai Exp $
/* $Id: capifs.h,v 1.1.2.2 2004/01/16 21:09:26 keil Exp $
*
* Copyright 2000 by Carsten Paeth <calle@calle.de>
*
......@@ -7,5 +7,5 @@
*
*/
void capifs_new_ncci(char type, unsigned int num, dev_t device);
void capifs_free_ncci(char type, unsigned int num);
void capifs_new_ncci(unsigned int num, dev_t device);
void capifs_free_ncci(unsigned int num);
/* $Id: kcapi.c,v 1.21.6.8 2001/09/23 22:24:33 kai Exp $
/* $Id: kcapi.c,v 1.1.2.4 2004/02/10 01:07:11 keil Exp $
*
* Kernel CAPI 2.0 Module
*
......@@ -31,7 +31,7 @@
#include <linux/b1lli.h>
#endif
static char *revision = "$Revision: 1.21.6.8 $";
static char *revision = "$Revision: 1.1.2.4 $";
/* ------------------------------------------------------------- */
......@@ -61,7 +61,7 @@ static char capi_manufakturer[64] = "AVM Berlin";
#define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f)
LIST_HEAD(capi_drivers);
spinlock_t capi_drivers_lock = SPIN_LOCK_UNLOCKED;
rwlock_t capi_drivers_list_lock = RW_LOCK_UNLOCKED;
struct capi20_appl *capi_applications[CAPI_MAXAPPL];
struct capi_ctr *capi_cards[CAPI_MAXCONTR];
......@@ -309,12 +309,10 @@ static void recv_handler(void *dummy)
continue;
}
if ( CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
&& CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {
if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_IND)
ap->nrecvdatapkt++;
} else {
else
ap->nrecvctlpkt++;
}
ap->recv_message(ap, skb);
}
}
......@@ -498,6 +496,28 @@ int detach_capi_ctr(struct capi_ctr *card)
EXPORT_SYMBOL(detach_capi_ctr);
void register_capi_driver(struct capi_driver *driver)
{
unsigned long flags;
write_lock_irqsave(&capi_drivers_list_lock, flags);
list_add_tail(&driver->list, &capi_drivers);
write_unlock_irqrestore(&capi_drivers_list_lock, flags);
}
EXPORT_SYMBOL(register_capi_driver);
void unregister_capi_driver(struct capi_driver *driver)
{
unsigned long flags;
write_lock_irqsave(&capi_drivers_list_lock, flags);
list_del(&driver->list);
write_unlock_irqrestore(&capi_drivers_list_lock, flags);
}
EXPORT_SYMBOL(unregister_capi_driver);
/* ------------------------------------------------------------- */
/* -------- CAPI2.0 Interface ---------------------------------- */
/* ------------------------------------------------------------- */
......@@ -704,12 +724,68 @@ EXPORT_SYMBOL(capi20_get_profile);
static int old_capi_manufacturer(unsigned int cmd, void *data)
{
avmb1_loadandconfigdef ldef;
avmb1_extcarddef cdef;
avmb1_resetdef rdef;
capicardparams cparams;
struct capi_ctr *card;
struct capi_driver *driver = 0;
capiloaddata ldata;
struct list_head *l;
unsigned long flags;
int retval;
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;
read_lock_irqsave(&capi_drivers_list_lock, flags);
switch (cdef.cardtype) {
case AVM_CARDTYPE_B1:
list_for_each(l, &capi_drivers) {
driver = list_entry(l, struct capi_driver, list);
if (strcmp(driver->name, "b1isa") == 0)
break;
}
break;
case AVM_CARDTYPE_T1:
list_for_each(l, &capi_drivers) {
driver = list_entry(l, struct capi_driver, list);
if (strcmp(driver->name, "t1isa") == 0)
break;
}
break;
default:
driver = 0;
break;
}
if (!driver) {
read_unlock_irqrestore(&capi_drivers_list_lock, flags);
printk(KERN_ERR "kcapi: driver not loaded.\n");
return -EIO;
}
if (!driver->add_card) {
read_unlock_irqrestore(&capi_drivers_list_lock, flags);
printk(KERN_ERR "kcapi: driver has no add card function.\n");
return -EIO;
}
retval = driver->add_card(driver, &cparams);
read_unlock_irqrestore(&capi_drivers_list_lock, flags);
return retval;
case AVMB1_LOAD:
case AVMB1_LOAD_AND_CONFIG:
......@@ -832,6 +908,43 @@ int capi20_manufacturer(unsigned int cmd, void *data)
card->cnr, card->traceflag);
return 0;
}
case KCAPI_CMD_ADDCARD:
{
struct list_head *l;
struct capi_driver *driver = 0;
capicardparams cparams;
kcapi_carddef cdef;
int retval;
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;
list_for_each(l, &capi_drivers) {
driver = list_entry(l, struct capi_driver, list);
if (strcmp(driver->name, cdef.driver) == 0)
break;
}
if (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:
printk(KERN_ERR "kcapi: manufacturer command %d unknown.\n",
......
......@@ -15,10 +15,13 @@
#include <linux/list.h>
#include <linux/isdn/capilli.h>
#ifdef KCAPI_DEBUG
#define DBG(format, arg...) do { \
printk(KERN_DEBUG "%s: " format "\n" , __FUNCTION__ , ## arg); \
} while (0)
#else
#define DBG(format, arg...) /* */
#endif
enum {
CARD_DETECTED = 1,
......@@ -27,7 +30,7 @@ enum {
};
extern struct list_head capi_drivers;
extern spinlock_t capi_drivers_lock;
extern rwlock_t capi_drivers_list_lock;
extern struct capi20_appl *capi_applications[CAPI_MAXAPPL];
extern struct capi_ctr *capi_cards[CAPI_MAXCONTR];
......
......@@ -243,16 +243,84 @@ create_seq_entry(char *name, mode_t mode, struct file_operations *f)
// ---------------------------------------------------------------------------
static __inline__ struct capi_driver *capi_driver_get_idx(loff_t pos)
{
struct capi_driver *drv = 0;
struct list_head *l;
loff_t i;
i = 0;
list_for_each(l, &capi_drivers) {
drv = list_entry(l, struct capi_driver, list);
if (i++ == pos)
return drv;
}
return 0;
}
static void *capi_driver_start(struct seq_file *seq, loff_t *pos)
{
struct capi_driver *drv;
read_lock(&capi_drivers_list_lock);
drv = capi_driver_get_idx(*pos);
return drv;
}
static void *capi_driver_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct capi_driver *drv = (struct capi_driver *)v;
++*pos;
if (drv->list.next == &capi_drivers) return 0;
return list_entry(drv->list.next, struct capi_driver, list);
}
static void capi_driver_stop(struct seq_file *seq, void *v)
{
read_unlock(&capi_drivers_list_lock);
}
static int capi_driver_show(struct seq_file *seq, void *v)
{
struct capi_driver *drv = (struct capi_driver *)v;
seq_printf(seq, "%-32s %s\n", drv->name, drv->revision);
return 0;
}
struct seq_operations seq_capi_driver_ops = {
.start = capi_driver_start,
.next = capi_driver_next,
.stop = capi_driver_stop,
.show = capi_driver_show,
};
static int
seq_capi_driver_open(struct inode *inode, struct file *file)
{
int err;
err = seq_open(file, &seq_capi_driver_ops);
return err;
}
static struct file_operations proc_driver_ops = {
.open = seq_capi_driver_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
// ---------------------------------------------------------------------------
void __init
kcapi_proc_init(void)
{
proc_mkdir("capi", NULL);
proc_mkdir("capi/controllers", NULL);
proc_mkdir("capi/drivers", NULL);
create_seq_entry("capi/controller", 0, &proc_controller_ops);
create_seq_entry("capi/contrstats", 0, &proc_contrstats_ops);
create_seq_entry("capi/applications", 0, &proc_applications_ops);
create_seq_entry("capi/applstats", 0, &proc_applstats_ops);
create_seq_entry("capi/driver", 0, &proc_driver_ops);
}
void __exit
......@@ -263,7 +331,6 @@ kcapi_proc_exit(void)
remove_proc_entry("capi/contrstats", NULL);
remove_proc_entry("capi/applications", NULL);
remove_proc_entry("capi/applstats", NULL);
remove_proc_entry("capi/drivers", NULL);
remove_proc_entry("capi/controllers", NULL);
remove_proc_entry("capi", NULL);
}
......@@ -2,32 +2,9 @@
# ISDN hardware drivers
#
comment "CAPI hardware drivers"
depends on NET && ISDN_BOOL && ISDN_CAPI
depends on NET && ISDN && ISDN_CAPI
source "drivers/isdn/hardware/avm/Kconfig"
source "drivers/isdn/hardware/eicon/Kconfig"
comment "ISDN4Linux hardware drivers"
depends on NET && ISDN_BOOL && ISDN
source "drivers/isdn/hisax/Kconfig"
menu "Active cards"
depends on NET && ISDN_BOOL && ISDN!=n
source "drivers/isdn/icn/Kconfig"
source "drivers/isdn/pcbit/Kconfig"
source "drivers/isdn/sc/Kconfig"
source "drivers/isdn/act2000/Kconfig"
source "drivers/isdn/tpam/Kconfig"
source "drivers/isdn/hysdn/Kconfig"
endmenu
......@@ -3,7 +3,7 @@
#
menu "Active AVM cards"
depends on NET && ISDN_BOOL && ISDN_CAPI!=n
depends on NET && ISDN && ISDN_CAPI!=n
config CAPI_AVM
bool "Support AVM cards"
......
/* $Id: b1.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
/* $Id: b1.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
*
* Common module for AVM B1 cards.
*
......@@ -28,7 +28,7 @@
#include <linux/isdn/capicmd.h>
#include <linux/isdn/capiutil.h>
static char *revision = "$Revision: 1.1.4.1.2.1 $";
static char *revision = "$Revision: 1.1.2.2 $";
/* ------------------------------------------------------------- */
......@@ -76,7 +76,7 @@ avmcard *b1_alloc_card(int nr_controllers)
kfree(card);
return 0;
}
memset(cinfo, 0, sizeof(*cinfo));
memset(cinfo, 0, sizeof(*cinfo) * nr_controllers);
card->ctrlinfo = cinfo;
for (i = 0; i < nr_controllers; i++) {
......@@ -308,14 +308,13 @@ int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
return -EIO;
}
save_flags(flags);
cli();
spin_lock_irqsave(&card->lock, flags);
b1_setinterrupt(port, card->irq, card->cardtype);
b1_put_byte(port, SEND_INIT);
b1_put_word(port, CAPI_MAXAPPL);
b1_put_word(port, AVM_NCCI_PER_CHANNEL*2);
b1_put_word(port, ctrl->cnr - 1);
restore_flags(flags);
spin_unlock_irqrestore(&card->lock, flags);
return 0;
}
......@@ -348,15 +347,14 @@ void b1_register_appl(struct capi_ctr *ctrl,
else nconn = ctrl->profile.nbchannel * -want;
if (nconn == 0) nconn = ctrl->profile.nbchannel;
save_flags(flags);
cli();
spin_lock_irqsave(&card->lock, flags);
b1_put_byte(port, SEND_REGISTER);
b1_put_word(port, appl);
b1_put_word(port, 1024 * (nconn+1));
b1_put_word(port, nconn);
b1_put_word(port, rp->datablkcnt);
b1_put_word(port, rp->datablklen);
restore_flags(flags);
spin_unlock_irqrestore(&card->lock, flags);
}
void b1_release_appl(struct capi_ctr *ctrl, u16 appl)
......@@ -368,11 +366,10 @@ void b1_release_appl(struct capi_ctr *ctrl, u16 appl)
capilib_release_appl(&cinfo->ncci_head, appl);
save_flags(flags);
cli();
spin_lock_irqsave(&card->lock, flags);
b1_put_byte(port, SEND_RELEASE);
b1_put_word(port, appl);
restore_flags(flags);
spin_unlock_irqrestore(&card->lock, flags);
}
u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
......@@ -396,20 +393,18 @@ u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
dlen = CAPIMSG_DATALEN(skb->data);
save_flags(flags);
cli();
spin_lock_irqsave(&card->lock, flags);
b1_put_byte(port, SEND_DATA_B3_REQ);
b1_put_slice(port, skb->data, len);
b1_put_slice(port, skb->data + len, dlen);
restore_flags(flags);
spin_unlock_irqrestore(&card->lock, flags);
} else {
retval = CAPI_NOERROR;
save_flags(flags);
cli();
spin_lock_irqsave(&card->lock, flags);
b1_put_byte(port, SEND_MESSAGE);
b1_put_slice(port, skb->data, len);
restore_flags(flags);
spin_unlock_irqrestore(&card->lock, flags);
}
out:
dev_kfree_skb_any(skb);
......@@ -505,9 +500,14 @@ irqreturn_t b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
unsigned DataB3Len;
unsigned NCCI;
unsigned WindowSize;
unsigned long flags;
spin_lock_irqsave(&card->lock, flags);
if (!b1_rx_full(card->port))
return IRQ_NONE;
if (!b1_rx_full(card->port)) {
spin_unlock_irqrestore(&card->lock, flags);
return IRQ_NONE;
}
b1cmd = b1_get_byte(card->port);
......@@ -518,6 +518,7 @@ irqreturn_t b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
ApplId = (unsigned) b1_get_word(card->port);
MsgLen = b1_get_slice(card->port, card->msgbuf);
DataB3Len = b1_get_slice(card->port, card->databuf);
spin_unlock_irqrestore(&card->lock, flags);
if (MsgLen < 30) { /* not CAPI 64Bit */
memset(card->msgbuf+MsgLen, 0, 30-MsgLen);
......@@ -538,6 +539,7 @@ irqreturn_t b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
ApplId = (unsigned) b1_get_word(card->port);
MsgLen = b1_get_slice(card->port, card->msgbuf);
spin_unlock_irqrestore(&card->lock, flags);
if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
printk(KERN_ERR "%s: incoming packet dropped\n",
card->name);
......@@ -557,6 +559,7 @@ irqreturn_t b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
ApplId = b1_get_word(card->port);
NCCI = b1_get_word(card->port);
WindowSize = b1_get_word(card->port);
spin_unlock_irqrestore(&card->lock, flags);
capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
......@@ -566,6 +569,7 @@ irqreturn_t b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
ApplId = b1_get_word(card->port);
NCCI = b1_get_word(card->port);
spin_unlock_irqrestore(&card->lock, flags);
if (NCCI != 0xffffffff)
capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
......@@ -574,16 +578,19 @@ irqreturn_t b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
case RECEIVE_START:
/* b1_put_byte(card->port, SEND_POLLACK); */
spin_unlock_irqrestore(&card->lock, flags);
capi_ctr_resume_output(ctrl);
break;
case RECEIVE_STOP:
spin_unlock_irqrestore(&card->lock, flags);
capi_ctr_suspend_output(ctrl);
break;
case RECEIVE_INIT:
cinfo->versionlen = b1_get_slice(card->port, cinfo->versionbuf);
spin_unlock_irqrestore(&card->lock, flags);
b1_parse_version(cinfo);
printk(KERN_INFO "%s: %s-card (%s) now active\n",
card->name,
......@@ -595,6 +602,7 @@ irqreturn_t b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
case RECEIVE_TASK_READY:
ApplId = (unsigned) b1_get_word(card->port);
MsgLen = b1_get_slice(card->port, card->msgbuf);
spin_unlock_irqrestore(&card->lock, flags);
card->msgbuf[MsgLen] = 0;
while ( MsgLen > 0
&& ( card->msgbuf[MsgLen-1] == '\n'
......@@ -608,6 +616,7 @@ irqreturn_t b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
case RECEIVE_DEBUGMSG:
MsgLen = b1_get_slice(card->port, card->msgbuf);
spin_unlock_irqrestore(&card->lock, flags);
card->msgbuf[MsgLen] = 0;
while ( MsgLen > 0
&& ( card->msgbuf[MsgLen-1] == '\n'
......@@ -619,9 +628,11 @@ irqreturn_t b1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
break;
case 0xff:
spin_unlock_irqrestore(&card->lock, flags);
printk(KERN_ERR "%s: card removed ?\n", card->name);
return IRQ_NONE;
default:
spin_unlock_irqrestore(&card->lock, flags);
printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n",
card->name, b1cmd);
return IRQ_HANDLED;
......
/* $Id: b1dma.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
/* $Id: b1dma.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $
*
* Common module for AVM B1 cards that support dma with AMCC
*
......@@ -28,11 +28,9 @@
#include <linux/isdn/capicmd.h>
#include <linux/isdn/capiutil.h>
#if BITS_PER_LONG != 32
#error FIXME: driver requires 32-bit platform
#endif
static char *revision = "$Revision: 1.1.2.3 $";
static char *revision = "$Revision: 1.1.4.1.2.1 $";
#undef CONFIG_B1DMA_DEBUG
/* ------------------------------------------------------------- */
......@@ -239,7 +237,7 @@ void b1dma_reset(avmcard *card)
/* ------------------------------------------------------------- */
int b1dma_detect(avmcard *card)
static int b1dma_detect(avmcard *card)
{
b1dma_writel(card, 0, AMCC_MCSR);
mdelay(10);
......@@ -578,11 +576,16 @@ static void b1dma_handle_rx(avmcard *card)
static void b1dma_handle_interrupt(avmcard *card)
{
u32 status = b1dma_readl(card, AMCC_INTCSR);
u32 status;
u32 newcsr;
if ((status & ANY_S5933_INT) == 0)
spin_lock(&card->lock);
status = b1dma_readl(card, AMCC_INTCSR);
if ((status & ANY_S5933_INT) == 0) {
spin_unlock(&card->lock);
return;
}
newcsr = card->csr | (status & ALL_INT);
if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT;
......@@ -593,20 +596,28 @@ static void b1dma_handle_interrupt(avmcard *card)
struct avmcard_dmainfo *dma = card->dma;
u32 rxlen;
if (card->dma->recvlen == 0) {
dma->recvlen = *((u32 *)dma->recvbuf.dmabuf);
rxlen = (dma->recvlen + 3) & ~3;
b1dma_writel(card, dma->recvbuf.dmaaddr+4, AMCC_RXPTR);
b1dma_writel(card, rxlen, AMCC_RXLEN);
rxlen = b1dma_readl(card, AMCC_RXLEN);
if (rxlen == 0) {
dma->recvlen = *((u32 *)dma->recvbuf.dmabuf);
rxlen = (dma->recvlen + 3) & ~3;
b1dma_writel(card, dma->recvbuf.dmaaddr+4, AMCC_RXPTR);
b1dma_writel(card, rxlen, AMCC_RXLEN);
#ifdef CONFIG_B1DMA_DEBUG
} else {
printk(KERN_ERR "%s: rx not complete (%d).\n",
card->name, rxlen);
#endif
}
} else {
spin_unlock(&card->lock);
b1dma_handle_rx(card);
dma->recvlen = 0;
spin_lock(&card->lock);
b1dma_writel(card, dma->recvbuf.dmaaddr, AMCC_RXPTR);
b1dma_writel(card, 4, AMCC_RXLEN);
}
}
spin_lock(&card->lock);
if ((status & TX_TC_INT) != 0) {
if (skb_queue_empty(&card->dma->send_queue))
card->csr &= ~EN_TX_TC_INT;
......@@ -736,18 +747,19 @@ void b1dma_reset_ctr(struct capi_ctr *ctrl)
{
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
avmcard *card = cinfo->card;
unsigned long flags;
spin_lock_irqsave(&card->lock, flags);
b1dma_reset(card);
spin_unlock_irqrestore(&card->lock, flags);
memset(cinfo->version, 0, sizeof(cinfo->version));
capilib_release(&cinfo->ncci_head);
capi_ctr_reseted(ctrl);
}
/* ------------------------------------------------------------- */
void b1dma_register_appl(struct capi_ctr *ctrl,
u16 appl,
capi_register_params *rp)
......@@ -844,6 +856,7 @@ int b1dmactl_read_proc(char *page, char **start, off_t off,
int len = 0;
char *s;
u32 txoff, txlen, rxoff, rxlen, csr;
unsigned long flags;
len += sprintf(page+len, "%-16s %s\n", "name", card->name);
len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
......@@ -896,6 +909,9 @@ int b1dmactl_read_proc(char *page, char **start, off_t off,
}
len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname);
spin_lock_irqsave(&card->lock, flags);
txoff = (dma_addr_t)b1dma_readl(card, AMCC_TXPTR)-card->dma->sendbuf.dmaaddr;
txlen = b1dma_readl(card, AMCC_TXLEN);
......@@ -904,6 +920,8 @@ int b1dmactl_read_proc(char *page, char **start, off_t off,
csr = b1dma_readl(card, AMCC_INTCSR);
spin_unlock_irqrestore(&card->lock, flags);
len += sprintf(page+len, "%-16s 0x%lx\n",
"csr (cached)", (unsigned long)card->csr);
len += sprintf(page+len, "%-16s 0x%lx\n",
......
/* $Id: b1isa.c,v 1.10.6.6 2001/09/23 22:24:33 kai Exp $
/* $Id: b1isa.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $
*
* Module for AVM B1 ISA-card.
*
......@@ -27,6 +27,10 @@
/* ------------------------------------------------------------- */
static char *revision = "$Revision: 1.1.2.3 $";
/* ------------------------------------------------------------- */
MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 ISA card");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
......@@ -56,7 +60,7 @@ static void b1isa_remove(struct pci_dev *pdev)
static char *b1isa_procinfo(struct capi_ctr *ctrl);
static int __init b1isa_probe(struct pci_dev *pdev)
static int b1isa_probe(struct pci_dev *pdev)
{
avmctrl_info *cinfo;
avmcard *card;
......@@ -108,6 +112,7 @@ static int __init b1isa_probe(struct pci_dev *pdev)
b1_reset(card->port);
b1_getrevision(card);
cinfo->capi_ctrl.owner = THIS_MODULE;
cinfo->capi_ctrl.driver_name = "b1isa";
cinfo->capi_ctrl.driverdata = cinfo;
cinfo->capi_ctrl.register_appl = b1_register_appl;
......@@ -118,7 +123,6 @@ static int __init b1isa_probe(struct pci_dev *pdev)
cinfo->capi_ctrl.procinfo = b1isa_procinfo;
cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc;
strcpy(cinfo->capi_ctrl.name, card->name);
cinfo->capi_ctrl.owner = THIS_MODULE;
retval = attach_capi_ctr(&cinfo->capi_ctrl);
if (retval) {
......@@ -170,23 +174,56 @@ 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 b1isa_add_card(struct capi_driver *driver, capicardparams *data)
{
int i;
for (i = 0; i < MAX_CARDS; i++) {
if (isa_dev[i].resource[0].start)
continue;
isa_dev[i].resource[0].start = data->port;
isa_dev[i].irq = data->irq;
if (b1isa_probe(&isa_dev[i]) == 0)
return 0;
}
return -ENODEV;
}
static struct capi_driver capi_driver_b1isa = {
.name = "b1isa",
.revision = "1.0",
.add_card = b1isa_add_card,
};
static int __init b1isa_init(void)
{
char *p;
char rev[32];
int i;
int found = 0;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strlcpy(rev, p + 2, 32);
if ((p = strchr(rev, '$')) != 0 && p > rev)
*(p-1) = 0;
} else
strcpy(rev, "1.0");
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];
isa_dev[i].irq = irq[i];
if (b1isa_probe(&isa_dev[i]) == 0)
found++;
if (b1isa_probe(&isa_dev[i]) != 0)
return -ENODEV;
}
if (found == 0)
return -ENODEV;
strlcpy(capi_driver_b1isa.revision, rev, 32);
register_capi_driver(&capi_driver_b1isa);
printk(KERN_INFO "b1isa: revision %s\n", rev);
return 0;
}
......@@ -201,6 +238,7 @@ static void __exit b1isa_exit(void)
b1isa_remove(&isa_dev[i]);
}
unregister_capi_driver(&capi_driver_b1isa);
}
module_init(b1isa_init);
......
/* $Id: b1pci.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
/* $Id: b1pci.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
*
* Module for AVM B1 PCI-card.
*
......@@ -28,6 +28,10 @@
/* ------------------------------------------------------------- */
static char *revision = "$Revision: 1.1.2.2 $";
/* ------------------------------------------------------------- */
static struct pci_device_id b1pci_pci_tbl[] = {
{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, PCI_ANY_ID, PCI_ANY_ID },
{ } /* Terminating entry */
......@@ -362,13 +366,50 @@ static struct pci_driver b1pci_pci_driver = {
.remove = __devexit_p(b1pci_pci_remove),
};
static struct capi_driver capi_driver_b1pci = {
.name = "b1pci",
.revision = "1.0",
};
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
static struct capi_driver capi_driver_b1pciv4 = {
.name = "b1pciv4",
.revision = "1.0",
};
#endif
static int __init b1pci_init(void)
{
return pci_module_init(&b1pci_pci_driver);
char *p;
char rev[32];
int err;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strlcpy(rev, p + 2, 32);
if ((p = strchr(rev, '$')) != 0 && p > rev)
*(p-1) = 0;
} else
strcpy(rev, "1.0");
err = pci_module_init(&b1pci_pci_driver);
if (!err) {
strlcpy(capi_driver_b1pci.revision, rev, 32);
register_capi_driver(&capi_driver_b1pci);
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
strlcpy(capi_driver_b1pciv4.revision, rev, 32);
register_capi_driver(&capi_driver_b1pciv4);
#endif
printk(KERN_INFO "b1pci: revision %s\n", rev);
}
return err;
}
static void __exit b1pci_exit(void)
{
unregister_capi_driver(&capi_driver_b1pci);
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
unregister_capi_driver(&capi_driver_b1pciv4);
#endif
pci_unregister_driver(&b1pci_pci_driver);
}
......
/* $Id: b1pcmcia.c,v 1.12.6.5 2001/09/23 22:24:33 kai Exp $
/* $Id: b1pcmcia.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
*
* Module for AVM B1/M1/M2 PCMCIA-card.
*
......@@ -27,6 +27,10 @@
/* ------------------------------------------------------------- */
static char *revision = "$Revision: 1.1.2.2 $";
/* ------------------------------------------------------------- */
MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM PCMCIA cards");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
......@@ -186,3 +190,36 @@ EXPORT_SYMBOL(b1pcmcia_addcard_b1);
EXPORT_SYMBOL(b1pcmcia_addcard_m1);
EXPORT_SYMBOL(b1pcmcia_addcard_m2);
EXPORT_SYMBOL(b1pcmcia_delcard);
static struct capi_driver capi_driver_b1pcmcia = {
.name = "b1pcmcia",
.revision = "1.0",
};
static int __init b1pcmcia_init(void)
{
char *p;
char rev[32];
int err;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strlcpy(rev, p + 2, 32);
if ((p = strchr(rev, '$')) != 0 && p > rev)
*(p-1) = 0;
} else
strcpy(rev, "1.0");
strlcpy(capi_driver_b1pcmcia.revision, rev, 32);
register_capi_driver(&capi_driver_b1pcmcia);
printk(KERN_INFO "b1pci: revision %s\n", rev);
return 0;
}
static void __exit b1pcmcia_exit(void)
{
unregister_capi_driver(&capi_driver_b1pcmcia);
}
module_init(b1pcmcia_init);
module_exit(b1pcmcia_exit);
/* $Id: c4.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
/* $Id: c4.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
*
* Module for AVM C4 & C2 card.
*
......@@ -34,6 +34,10 @@
/* ------------------------------------------------------------- */
static char *revision = "$Revision: 1.1.2.2 $";
/* ------------------------------------------------------------- */
static int suppress_pollack;
static struct pci_device_id c4_pci_tbl[] = {
......@@ -404,18 +408,14 @@ static int c4_detect(avmcard *card)
static void c4_dispatch_tx(avmcard *card)
{
avmcard_dmainfo *dma = card->dma;
unsigned long flags;
struct sk_buff *skb;
u8 cmd, subcmd;
u16 len;
u32 txlen;
void *p;
save_flags(flags);
cli();
if (card->csr & DBELL_DOWN_ARM) { /* tx busy */
restore_flags(flags);
return;
}
......@@ -424,7 +424,6 @@ static void c4_dispatch_tx(avmcard *card)
#ifdef CONFIG_C4_DEBUG
printk(KERN_DEBUG "%s: tx underrun\n", card->name);
#endif
restore_flags(flags);
return;
}
......@@ -470,7 +469,6 @@ static void c4_dispatch_tx(avmcard *card)
c4outmeml(card->mbase+DOORBELL, DBELL_DOWN_ARM);
restore_flags(flags);
dev_kfree_skb_any(skb);
}
......@@ -664,11 +662,15 @@ static void c4_handle_rx(avmcard *card)
static irqreturn_t c4_handle_interrupt(avmcard *card)
{
u32 status = c4inmeml(card->mbase+DOORBELL);
u32 status;
spin_lock(&card->lock);
status = c4inmeml(card->mbase+DOORBELL);
if (status & DBELL_RESET_HOST) {
u_int i;
c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c);
spin_unlock(&card->lock);
if (card->nlogcontr == 0)
return IRQ_HANDLED;
printk(KERN_ERR "%s: unexpected reset\n", card->name);
......@@ -683,8 +685,10 @@ static irqreturn_t c4_handle_interrupt(avmcard *card)
}
status &= (DBELL_UP_HOST | DBELL_DOWN_HOST);
if (!status)
if (!status) {
spin_unlock(&card->lock);
return IRQ_HANDLED;
}
c4outmeml(card->mbase+DOORBELL, status);
if ((status & DBELL_UP_HOST) != 0) {
......@@ -705,6 +709,7 @@ static irqreturn_t c4_handle_interrupt(avmcard *card)
c4_dispatch_tx(card);
}
}
spin_unlock(&card->lock);
return IRQ_HANDLED;
}
......@@ -767,6 +772,7 @@ static int queue_sendconfigword(avmcard *card, u32 val)
static int queue_sendconfig(avmcard *card, char cval[4])
{
struct sk_buff *skb;
unsigned long flags;
void *p;
skb = alloc_skb(3+4, GFP_ATOMIC);
......@@ -786,7 +792,10 @@ static int queue_sendconfig(avmcard *card, char cval[4])
skb_put(skb, (u8 *)p - (u8 *)skb->data);
skb_queue_tail(&card->dma->send_queue, skb);
spin_lock_irqsave(&card->lock, flags);
c4_dispatch_tx(card);
spin_unlock_irqrestore(&card->lock, flags);
return 0;
}
......@@ -835,7 +844,6 @@ static int c4_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
{
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
avmcard *card = cinfo->card;
unsigned long flags;
int retval;
if ((retval = c4_load_t4file(card, &data->firmware))) {
......@@ -845,9 +853,6 @@ static int c4_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
return retval;
}
save_flags(flags);
cli();
card->csr = 0;
c4outmeml(card->mbase+MBOX_UP_LEN, 0);
c4outmeml(card->mbase+MBOX_DOWN_LEN, 0);
......@@ -862,7 +867,6 @@ static int c4_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
c4outmeml(card->mbase+MBOX_UP_ADDR, card->dma->recvbuf.dmaaddr);
c4outmeml(card->mbase+MBOX_UP_LEN, card->dma->recvbuf.size);
c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM);
restore_flags(flags);
if (data->configuration.len > 0 && data->configuration.data) {
retval = c4_send_config(card, &data->configuration);
......@@ -885,9 +889,14 @@ void c4_reset_ctr(struct capi_ctr *ctrl)
avmcard *card = ((avmctrl_info *)(ctrl->driverdata))->card;
avmctrl_info *cinfo;
u_int i;
unsigned long flags;
spin_lock_irqsave(&card->lock, flags);
c4_reset(card);
spin_unlock_irqrestore(&card->lock, flags);
for (i=0; i < card->nr_controllers; i++) {
cinfo = &card->ctrlinfo[i];
memset(cinfo->version, 0, sizeof(cinfo->version));
......@@ -931,6 +940,7 @@ void c4_register_appl(struct capi_ctr *ctrl,
avmcard *card = cinfo->card;
struct sk_buff *skb;
int want = rp->level3cnt;
unsigned long flags;
int nconn;
void *p;
......@@ -958,7 +968,10 @@ void c4_register_appl(struct capi_ctr *ctrl,
skb_put(skb, (u8 *)p - (u8 *)skb->data);
skb_queue_tail(&card->dma->send_queue, skb);
spin_lock_irqsave(&card->lock, flags);
c4_dispatch_tx(card);
spin_unlock_irqrestore(&card->lock, flags);
}
}
......@@ -968,6 +981,7 @@ void c4_release_appl(struct capi_ctr *ctrl, u16 appl)
{
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
avmcard *card = cinfo->card;
unsigned long flags;
struct sk_buff *skb;
void *p;
......@@ -988,7 +1002,9 @@ void c4_release_appl(struct capi_ctr *ctrl, u16 appl)
skb_put(skb, (u8 *)p - (u8 *)skb->data);
skb_queue_tail(&card->dma->send_queue, skb);
spin_lock_irqsave(&card->lock, flags);
c4_dispatch_tx(card);
spin_unlock_irqrestore(&card->lock, flags);
}
}
......@@ -1000,6 +1016,7 @@ static u16 c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
avmcard *card = cinfo->card;
u16 retval = CAPI_NOERROR;
unsigned long flags;
if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
retval = capilib_data_b3_req(&cinfo->ncci_head,
......@@ -1009,7 +1026,9 @@ static u16 c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
}
if (retval == CAPI_NOERROR) {
skb_queue_tail(&card->dma->send_queue, skb);
spin_lock_irqsave(&card->lock, flags);
c4_dispatch_tx(card);
spin_unlock_irqrestore(&card->lock, flags);
} else {
dev_kfree_skb_any(skb);
}
......@@ -1164,6 +1183,7 @@ static int c4_add_card(struct capicardparams *p, struct pci_dev *dev,
for (i=0; i < nr_controllers ; i++) {
cinfo = &card->ctrlinfo[i];
cinfo->capi_ctrl.owner = THIS_MODULE;
cinfo->capi_ctrl.driver_name = "c4";
cinfo->capi_ctrl.driverdata = cinfo;
cinfo->capi_ctrl.register_appl = c4_register_appl;
......@@ -1174,7 +1194,6 @@ static int c4_add_card(struct capicardparams *p, struct pci_dev *dev,
cinfo->capi_ctrl.procinfo = c4_procinfo;
cinfo->capi_ctrl.ctr_read_proc = c4_read_proc;
strcpy(cinfo->capi_ctrl.name, card->name);
cinfo->capi_ctrl.owner = THIS_MODULE;
retval = attach_capi_ctr(&cinfo->capi_ctrl);
if (retval) {
......@@ -1247,13 +1266,44 @@ static struct pci_driver c4_pci_driver = {
.remove = c4_remove,
};
static struct capi_driver capi_driver_c2 = {
.name = "c2",
.revision = "1.0",
};
static struct capi_driver capi_driver_c4 = {
.name = "c4",
.revision = "1.0",
};
static int __init c4_init(void)
{
return pci_module_init(&c4_pci_driver);
char *p;
char rev[32];
int err;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strlcpy(rev, p + 2, 32);
if ((p = strchr(rev, '$')) != 0 && p > rev)
*(p-1) = 0;
} else
strcpy(rev, "1.0");
err = pci_module_init(&c4_pci_driver);
if (!err) {
strlcpy(capi_driver_c2.revision, rev, 32);
register_capi_driver(&capi_driver_c2);
strlcpy(capi_driver_c4.revision, rev, 32);
register_capi_driver(&capi_driver_c4);
printk(KERN_INFO "c4: revision %s\n", rev);
}
return err;
}
static void __exit c4_exit(void)
{
unregister_capi_driver(&capi_driver_c2);
unregister_capi_driver(&capi_driver_c4);
pci_unregister_driver(&c4_pci_driver);
}
......
/* $Id: t1isa.c,v 1.16.6.7 2001/09/23 22:24:34 kai Exp $
/* $Id: t1isa.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $
*
* Module for AVM T1 HEMA-card.
*
......@@ -29,6 +29,10 @@
/* ------------------------------------------------------------- */
static char *revision = "$Revision: 1.1.2.3 $";
/* ------------------------------------------------------------- */
MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 HEMA ISA card");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
......@@ -58,7 +62,6 @@ static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr)
{
unsigned char cregs[8];
unsigned char reverse_cardnr;
unsigned long flags;
unsigned char dummy;
int i;
......@@ -73,8 +76,12 @@ static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr)
cregs[6] = 0;
cregs[7] = 0;
save_flags(flags);
cli();
/*
* no one else should use the ISA bus in this moment,
* but no function there to prevent this :-(
* save_flags(flags); cli();
*/
/* board reset */
t1outp(base, T1_RESETBOARD, 0xf);
mdelay(100);
......@@ -87,7 +94,7 @@ static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr)
t1outp(base, HEMA_PAL_ID >> 4, cregs[0]);
for(i=1;i<7;i++) t1outp(base, 0, cregs[i]);
t1outp(base, ((base >> 4)) & 0x3, cregs[7]);
restore_flags(flags);
/* restore_flags(flags); */
mdelay(100);
t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
......@@ -137,6 +144,9 @@ static irqreturn_t t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *
unsigned DataB3Len;
unsigned NCCI;
unsigned WindowSize;
unsigned long flags;
spin_lock_irqsave(&card->lock, flags);
while (b1_rx_full(card->port)) {
......@@ -149,6 +159,7 @@ static irqreturn_t t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *
ApplId = (unsigned) b1_get_word(card->port);
MsgLen = t1_get_slice(card->port, card->msgbuf);
DataB3Len = t1_get_slice(card->port, card->databuf);
spin_unlock_irqrestore(&card->lock, flags);
if (MsgLen < 30) { /* not CAPI 64Bit */
memset(card->msgbuf+MsgLen, 0, 30-MsgLen);
......@@ -169,6 +180,7 @@ static irqreturn_t t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *
ApplId = (unsigned) b1_get_word(card->port);
MsgLen = t1_get_slice(card->port, card->msgbuf);
spin_unlock_irqrestore(&card->lock, flags);
if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
printk(KERN_ERR "%s: incoming packet dropped\n",
card->name);
......@@ -188,6 +200,7 @@ static irqreturn_t t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *
ApplId = b1_get_word(card->port);
NCCI = b1_get_word(card->port);
WindowSize = b1_get_word(card->port);
spin_unlock_irqrestore(&card->lock, flags);
capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize);
......@@ -197,6 +210,7 @@ static irqreturn_t t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *
ApplId = b1_get_word(card->port);
NCCI = b1_get_word(card->port);
spin_unlock_irqrestore(&card->lock, flags);
if (NCCI != 0xffffffff)
capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI);
......@@ -205,16 +219,19 @@ static irqreturn_t t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *
case RECEIVE_START:
b1_put_byte(card->port, SEND_POLLACK);
spin_unlock_irqrestore(&card->lock, flags);
capi_ctr_resume_output(ctrl);
break;
case RECEIVE_STOP:
spin_unlock_irqrestore(&card->lock, flags);
capi_ctr_suspend_output(ctrl);
break;
case RECEIVE_INIT:
cinfo->versionlen = t1_get_slice(card->port, cinfo->versionbuf);
spin_unlock_irqrestore(&card->lock, flags);
b1_parse_version(cinfo);
printk(KERN_INFO "%s: %s-card (%s) now active\n",
card->name,
......@@ -226,6 +243,7 @@ static irqreturn_t t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *
case RECEIVE_TASK_READY:
ApplId = (unsigned) b1_get_word(card->port);
MsgLen = t1_get_slice(card->port, card->msgbuf);
spin_unlock_irqrestore(&card->lock, flags);
card->msgbuf[MsgLen] = 0;
while ( MsgLen > 0
&& ( card->msgbuf[MsgLen-1] == '\n'
......@@ -239,6 +257,7 @@ static irqreturn_t t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *
case RECEIVE_DEBUGMSG:
MsgLen = t1_get_slice(card->port, card->msgbuf);
spin_unlock_irqrestore(&card->lock, flags);
card->msgbuf[MsgLen] = 0;
while ( MsgLen > 0
&& ( card->msgbuf[MsgLen-1] == '\n'
......@@ -251,9 +270,11 @@ static irqreturn_t t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *
case 0xff:
spin_unlock_irqrestore(&card->lock, flags);
printk(KERN_ERR "%s: card reseted ?\n", card->name);
return IRQ_HANDLED;
default:
spin_unlock_irqrestore(&card->lock, flags);
printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n",
card->name, b1cmd);
return IRQ_NONE;
......@@ -296,14 +317,13 @@ static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
return -EIO;
}
save_flags(flags);
cli();
spin_lock_irqsave(&card->lock, flags);
b1_setinterrupt(port, card->irq, card->cardtype);
b1_put_byte(port, SEND_INIT);
b1_put_word(port, CAPI_MAXAPPL);
b1_put_word(port, AVM_NCCI_PER_CHANNEL*30);
b1_put_word(port, ctrl->cnr - 1);
restore_flags(flags);
spin_unlock_irqrestore(&card->lock, flags);
return 0;
}
......@@ -349,7 +369,7 @@ static void t1isa_remove(struct pci_dev *pdev)
static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
static char *t1isa_procinfo(struct capi_ctr *ctrl);
static int __init t1isa_probe(struct pci_dev *pdev, int cardnr)
static int t1isa_probe(struct pci_dev *pdev, int cardnr)
{
avmctrl_info *cinfo;
avmcard *card;
......@@ -401,6 +421,7 @@ static int __init t1isa_probe(struct pci_dev *pdev, int cardnr)
t1_disable_irq(card->port);
b1_reset(card->port);
cinfo->capi_ctrl.owner = THIS_MODULE;
cinfo->capi_ctrl.driver_name = "t1isa";
cinfo->capi_ctrl.driverdata = cinfo;
cinfo->capi_ctrl.register_appl = b1_register_appl;
......@@ -411,7 +432,6 @@ static int __init t1isa_probe(struct pci_dev *pdev, int cardnr)
cinfo->capi_ctrl.procinfo = t1isa_procinfo;
cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc;
strcpy(cinfo->capi_ctrl.name, card->name);
cinfo->capi_ctrl.owner = THIS_MODULE;
retval = attach_capi_ctr(&cinfo->capi_ctrl);
if (retval) {
......@@ -456,20 +476,18 @@ static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
dlen = CAPIMSG_DATALEN(skb->data);
save_flags(flags);
cli();
spin_lock_irqsave(&card->lock, flags);
b1_put_byte(port, SEND_DATA_B3_REQ);
t1_put_slice(port, skb->data, len);
t1_put_slice(port, skb->data + len, dlen);
restore_flags(flags);
spin_unlock_irqrestore(&card->lock, flags);
} else {
retval = CAPI_NOERROR;
save_flags(flags);
cli();
spin_lock_irqsave(&card->lock, flags);
b1_put_byte(port, SEND_MESSAGE);
t1_put_slice(port, skb->data, len);
restore_flags(flags);
spin_unlock_irqrestore(&card->lock, flags);
}
out:
dev_kfree_skb_any(skb);
......@@ -509,23 +527,56 @@ MODULE_PARM_DESC(io, "I/O base address(es)");
MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
MODULE_PARM_DESC(cardnr, "Card number(s) (as jumpered)");
static int t1isa_add_card(struct capi_driver *driver, capicardparams *data)
{
int i;
for (i = 0; i < MAX_CARDS; i++) {
if (isa_dev[i].resource[0].start)
continue;
isa_dev[i].resource[0].start = data->port;
isa_dev[i].irq = data->irq;
if (t1isa_probe(&isa_dev[i], data->cardnr) == 0)
return 0;
}
return -ENODEV;
}
static struct capi_driver capi_driver_t1isa = {
.name = "t1isa",
.revision = "1.0",
.add_card = t1isa_add_card,
};
static int __init t1isa_init(void)
{
char rev[32];
char *p;
int i;
int found = 0;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strlcpy(rev, p + 2, 32);
if ((p = strchr(rev, '$')) != 0 && p > rev)
*(p-1) = 0;
} else
strcpy(rev, "1.0");
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];
isa_dev[i].irq = irq[i];
if (t1isa_probe(&isa_dev[i], cardnr[i]) == 0)
found++;
if (t1isa_probe(&isa_dev[i], cardnr[i]) != 0)
return -ENODEV;
}
if (found == 0)
return -ENODEV;
strlcpy(capi_driver_t1isa.revision, rev, 32);
register_capi_driver(&capi_driver_t1isa);
printk(KERN_INFO "t1isa: revision %s\n", rev);
return 0;
}
......
/* $Id: t1pci.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
/* $Id: t1pci.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
*
* Module for AVM T1 PCI-card.
*
......@@ -29,6 +29,8 @@
#undef CONFIG_T1PCI_DEBUG
#undef CONFIG_T1PCI_POLLDEBUG
/* ------------------------------------------------------------- */
static char *revision = "$Revision: 1.1.2.2 $";
/* ------------------------------------------------------------- */
static struct pci_device_id t1pci_pci_tbl[] = {
......@@ -221,13 +223,36 @@ static struct pci_driver t1pci_pci_driver = {
.remove = t1pci_remove,
};
static struct capi_driver capi_driver_t1pci = {
.name = "t1pci",
.revision = "1.0",
};
static int __init t1pci_init(void)
{
return pci_module_init(&t1pci_pci_driver);
char *p;
char rev[32];
int err;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strlcpy(rev, p + 2, 32);
if ((p = strchr(rev, '$')) != 0 && p > rev)
*(p-1) = 0;
} else
strcpy(rev, "1.0");
err = pci_module_init(&t1pci_pci_driver);
if (!err) {
strlcpy(capi_driver_t1pci.revision, rev, 32);
register_capi_driver(&capi_driver_t1pci);
printk(KERN_INFO "t1pci: revision %s\n", rev);
}
return err;
}
static void __exit t1pci_exit(void)
{
unregister_capi_driver(&capi_driver_t1pci);
pci_unregister_driver(&t1pci_pci_driver);
}
......
......@@ -3,7 +3,7 @@
#
menu "Active Eicon DIVA Server cards"
depends on NET && ISDN_BOOL && ISDN_CAPI!=n
depends on NET && ISDN && ISDN_CAPI!=n
config CAPI_EICON
bool "Support Eicon cards"
......
menu "Passive cards"
depends on ISDN
depends on ISDN_I4L
config ISDN_DRV_HISAX
tristate "HiSax SiemensChipSet driver support"
......@@ -341,8 +341,8 @@ config HISAX_HFC_SX
# bool ' TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
config HISAX_ENTERNOW_PCI
bool "Formula-n enter:now PCI card (EXPERIMENTAL)"
depends on PCI && EXPERIMENTAL
bool "Formula-n enter:now PCI card"
depends on PCI
help
This enables HiSax support for the Formula-n enter:now PCI
ISDN card.
......@@ -365,6 +365,8 @@ config HISAX_DEBUG
the ST5481 USB driver currently.
If in doubt, say yes.
comment "HiSax PCMCIA card service modules"
config HISAX_SEDLBAUER_CS
tristate "Sedlbauer PCMCIA cards"
depends on PCMCIA && HISAX_SEDLBAUER
......@@ -374,18 +376,26 @@ config HISAX_SEDLBAUER_CS
config HISAX_ELSA_CS
tristate "ELSA PCMCIA MicroLink cards"
depends on PCMCIA
depends on PCMCIA && HISAX_ELSA
help
This enables the PCMCIA client driver for the Elsa PCMCIA MicroLink
card.
config HISAX_AVM_A1_CS
tristate "AVM A1 PCMCIA cards"
depends on PCMCIA
depends on PCMCIA && ISDN_DRV_HISAX
help
This enables the PCMCIA client driver for the AVM A1 / Fritz!Card
PCMCIA cards.
config HISAX_TELES_CS
tristate "TELES PCMCIA cards"
depends on PCMCIA && HISAX_16_3
help
This enables the PCMCIA client driver for the Teles PCMCIA cards.
comment "HiSax sub driver modules"
config HISAX_ST5481
tristate "ST5481 USB ISDN modem (EXPERIMENTAL)"
depends on USB && EXPERIMENTAL
......@@ -393,6 +403,12 @@ config HISAX_ST5481
This enables the driver for ST5481 based USB ISDN adapters,
e.g. the BeWan Gazel 128 USB
config HISAX_HFCUSB
tristate "HFC USB based ISDN modems (EXPERIMENTAL)"
depends on USB && EXPERIMENTAL
help
This enables the driver for HFC USB based ISDN modems.
config HISAX_FRITZ_PCIPNP
tristate "AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)"
depends on EXPERIMENTAL
......@@ -402,18 +418,15 @@ config HISAX_FRITZ_PCIPNP
(the latter also needs you to select "ISA Plug and Play support"
from the menu "Plug and Play configuration")
config HISAX_FRITZ_CLASSIC
tristate "AVM Fritz!Card classic support (EXPERIMENTAL)"
depends on ISA && EXPERIMENTAL
help
This enables the driver for the AVM Fritz!Card classic, formerly
known as AVM A1.
config HISAX_HDLC
bool
depends on HISAX_ST5481
default y
config HISAX_HFCPCI
tristate "HFC PCI support (EXPERIMENTAL)"
depends on PCI && EXPERIMENTAL
help
This enables the driver for CCD HFC PCI based cards.
config HISAX_AVM_A1_PCMCIA
bool
depends on HISAX_AVM_A1_CS
default y
endif
......
# Makefile for the hisax ISDN device driver
# The target object and module list name.
# Define maximum number of cards
EXTRA_CFLAGS += -DHISAX_MAX_CARDS=$(CONFIG_HISAX_MAX_CARDS)
# Each configuration option enables a list of files.
obj-$(CONFIG_ISDN_DRV_HISAX) += hisax.o
obj-$(CONFIG_HISAX_SEDLBAUER_CS) += sedlbauer_cs.o
obj-$(CONFIG_HISAX_ELSA_CS) += elsa_cs.o
obj-$(CONFIG_HISAX_AVM_A1_CS) += avma1_cs.o
obj-$(CONFIG_HISAX_TELES_CS) += teles_cs.o
obj-$(CONFIG_HISAX_ST5481) += hisax_st5481.o
obj-$(CONFIG_HISAX_HFCUSB) += hfc_usb.o
obj-$(CONFIG_HISAX_FRITZ_PCIPNP) += hisax_isac.o hisax_fcpcipnp.o
obj-$(CONFIG_HISAX_FRITZ_CLASSIC) += hisax_isac.o hisax_hscx.o hisax_fcclassic.o
obj-$(CONFIG_HISAX_FRITZ_PCIPNP) += hisax_hfcpci.o
ifdef CONFIG_HISAX_HDLC
obj-$(CONFIG_ISDN_DRV_HISAX) += isdnhdlc.o
endif
# Multipart objects.
......@@ -21,7 +25,7 @@ hisax_st5481-y := st5481_init.o st5481_usb.o st5481_d.o \
st5481_b.o st5481_hdlc.o
hisax-y := config.o isdnl1.o tei.o isdnl2.o isdnl3.o \
lmgr.o q931.o callc.o fsm.o cert.o
lmgr.o q931.o callc.o fsm.o
hisax-$(CONFIG_HISAX_EURO) += l3dss1.o
hisax-$(CONFIG_HISAX_NI1) += l3ni1.o
hisax-$(CONFIG_HISAX_1TR6) += l3_1tr6.o
......@@ -33,12 +37,12 @@ hisax-$(CONFIG_HISAX_S0BOX) += s0box.o isac.o arcofi.o hscx.o
hisax-$(CONFIG_HISAX_AVM_A1) += avm_a1.o isac.o arcofi.o hscx.o
hisax-$(CONFIG_HISAX_AVM_A1_PCMCIA) += avm_a1p.o isac.o arcofi.o hscx.o
hisax-$(CONFIG_HISAX_FRITZPCI) += avm_pci.o isac.o arcofi.o
hisax-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o ipac.o
hisax-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o
hisax-$(CONFIG_HISAX_IX1MICROR2) += ix1_micro.o isac.o arcofi.o hscx.o
hisax-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o ipac.o ipacx.o
hisax-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o ipac.o
hisax-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o ipacx.o
hisax-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o
hisax-$(CONFIG_HISAX_TELEINT) += teleint.o isac.o arcofi.o hfc_2bs0.o
hisax-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o ipac.o \
hisax-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o \
isar.o
hisax-$(CONFIG_HISAX_SPORTSTER) += sportster.o isac.o arcofi.o hscx.o
hisax-$(CONFIG_HISAX_MIC) += mic.o isac.o arcofi.o hscx.o
......@@ -51,11 +55,9 @@ hisax-$(CONFIG_HISAX_NICCY) += niccy.o isac.o arcofi.o hscx.o
hisax-$(CONFIG_HISAX_ISURF) += isurf.o isac.o arcofi.o isar.o
hisax-$(CONFIG_HISAX_HSTSAPHIR) += saphir.o isac.o arcofi.o hscx.o
hisax-$(CONFIG_HISAX_BKM_A4T) += bkm_a4t.o isac.o arcofi.o jade.o
hisax-$(CONFIG_HISAX_SCT_QUADRO) += bkm_a8.o isac.o arcofi.o hscx.o ipac.o
hisax-$(CONFIG_HISAX_GAZEL) += gazel.o isac.o arcofi.o hscx.o ipac.o
hisax-$(CONFIG_HISAX_SCT_QUADRO) += bkm_a8.o isac.o arcofi.o hscx.o
hisax-$(CONFIG_HISAX_GAZEL) += gazel.o isac.o arcofi.o hscx.o
hisax-$(CONFIG_HISAX_W6692) += w6692.o
hisax-$(CONFIG_HISAX_ENTERNOW_PCI) += enternow_pci.o amd7930_fn.o
#hisax-$(CONFIG_HISAX_TESTEMU) += testemu.o
CERT = $(shell cd $(src); md5sum -c md5sums.asc > /dev/null 2> /dev/null ;echo $$?)
CFLAGS_cert.o = -DCERTIFICATION=$(CERT)
This diff is collapsed.
......@@ -12,13 +12,26 @@
*/
#define BYTE unsigned char
#define WORD unsigned int
#define rByteAMD(cs, reg) cs->readisac(cs, reg)
#define wByteAMD(cs, reg, val) cs->writeisac(cs, reg, val)
#define rWordAMD(cs, reg) ReadWordAmd7930(cs, reg)
#define wWordAMD(cs, reg, val) WriteWordAmd7930(cs, reg, val)
#define HIBYTE(w) ((unsigned char)((w & 0xff00) / 256))
#define LOBYTE(w) ((unsigned char)(w & 0x00ff))
#define AmdIrqOff(cs) cs->dc.amd7930.setIrqMask(cs, 0)
#define AmdIrqOn(cs) cs->dc.amd7930.setIrqMask(cs, 1)
#define AMD_CR 0x00
#define AMD_DR 0x01
#define DBUSY_TIMER_VALUE 80
void Amd7930_interrupt(struct IsdnCardState *cs, unsigned char irflags);
void Amd7930_init(struct IsdnCardState *cs);
int amd7930_setup(struct IsdnCardState *cs, struct dc_hw_ops *amd7930_ops,
void (*set_irq_mask)(struct IsdnCardState *, u8 val));
extern void Amd7930_interrupt(struct IsdnCardState *, unsigned char);
extern void Amd7930_init(struct IsdnCardState *);
extern void setup_Amd7930(struct IsdnCardState *);
/* $Id: arcofi.c,v 1.12.6.2 2001/09/23 22:24:46 kai Exp $
/* $Id: arcofi.c,v 1.14.2.3 2004/01/13 14:31:24 keil Exp $
*
* Ansteuerung ARCOFI 2165
*
......@@ -17,19 +17,6 @@
#define ARCOFI_TIMER_VALUE 20
static inline u8
isac_read(struct IsdnCardState *cs, u8 addr)
{
return cs->dc_hw_ops->read_reg(cs, addr);
}
static inline void
isac_write(struct IsdnCardState *cs, u8 addr, u8 val)
{
cs->dc_hw_ops->write_reg(cs, addr, val);
}
static void
add_arcofi_timer(struct IsdnCardState *cs) {
if (test_and_set_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
......@@ -42,7 +29,7 @@ add_arcofi_timer(struct IsdnCardState *cs) {
static void
send_arcofi(struct IsdnCardState *cs) {
u8 val;
u_char val;
add_arcofi_timer(cs);
cs->dc.isac.mon_txp = 0;
......@@ -56,11 +43,11 @@ send_arcofi(struct IsdnCardState *cs) {
}
cs->dc.isac.mocr &= 0x0f;
cs->dc.isac.mocr |= 0xa0;
isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
val = isac_read(cs, ISAC_MOSR);
isac_write(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
val = cs->readisac(cs, ISAC_MOSR);
cs->writeisac(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
cs->dc.isac.mocr |= 0x10;
isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr);
cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
}
int
......
This diff is collapsed.
This diff is collapsed.
/* $Id: avm_a1p.c,v 2.7.6.2 2001/09/23 22:24:46 kai Exp $
/* $Id: avm_a1p.c,v 2.9.2.5 2004/01/24 20:47:19 keil Exp $
*
* low level stuff for the following AVM cards:
* A1 PCMCIA
......@@ -56,176 +56,182 @@
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
static const char *avm_revision = "$Revision: 2.7.6.2 $";
static spinlock_t avm_a1p_lock = SPIN_LOCK_UNLOCKED;
static const char *avm_revision = "$Revision: 2.9.2.5 $";
static inline u8
readreg(struct IsdnCardState *cs, int offset, u8 adr)
static inline u_char
ReadISAC(struct IsdnCardState *cs, u_char offset)
{
unsigned long flags;
u8 ret;
u_char ret;
spin_lock_irqsave(&avm_a1p_lock, flags);
byteout(cs->hw.avm.cfg_reg + ADDRREG_OFFSET, offset + adr - 0x20);
ret = bytein(cs->hw.avm.cfg_reg + DATAREG_OFFSET);
spin_unlock_irqrestore(&avm_a1p_lock, flags);
offset -= 0x20;
byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset);
ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET);
return ret;
}
static inline void
writereg(struct IsdnCardState *cs, int offset, u8 adr, u8 value)
WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
{
unsigned long flags;
spin_lock_irqsave(&avm_a1p_lock, flags);
byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, offset + adr - 0x20);
offset -= 0x20;
byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset);
byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value);
spin_unlock_irqrestore(&avm_a1p_lock, flags);
}
static inline void
readfifo(struct IsdnCardState *cs, int offset, u8 *data, int size)
ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
{
byteout(cs->hw.avm.cfg_reg + ADDRREG_OFFSET, offset);
insb(cs->hw.avm.cfg_reg + DATAREG_OFFSET, data, size);
byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET);
insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
}
static inline void
writefifo(struct IsdnCardState *cs, int offset, u8 *data, int size)
WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
{
byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, offset);
byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET);
outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
}
static u8
isac_read(struct IsdnCardState *cs, u8 adr)
static inline u_char
ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
{
return readreg(cs, ISAC_REG_OFFSET, adr);
}
u_char ret;
static void
isac_write(struct IsdnCardState *cs, u8 adr, u8 value)
{
writereg(cs, ISAC_REG_OFFSET, adr, value);
}
static void
isac_read_fifo(struct IsdnCardState *cs, u8 *data, int size)
{
readfifo(cs, ISAC_FIFO_OFFSET, data, size);
offset -= 0x20;
byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset);
ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET);
return ret;
}
static void
isac_write_fifo(struct IsdnCardState *cs, u8 *data, int size)
static inline void
WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
{
writefifo(cs, ISAC_FIFO_OFFSET, data, size);
offset -= 0x20;
byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset);
byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value);
}
static struct dc_hw_ops isac_ops = {
.read_reg = isac_read,
.write_reg = isac_write,
.read_fifo = isac_read_fifo,
.write_fifo = isac_write_fifo,
};
static u8
hscx_read(struct IsdnCardState *cs, int hscx, u8 adr)
static inline void
ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
{
return readreg(cs, HSCX_REG_OFFSET + hscx*HSCX_CH_DIFF, adr);
byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF);
insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
}
static void
hscx_write(struct IsdnCardState *cs, int hscx, u8 adr, u8 value)
static inline void
WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
{
writereg(cs, HSCX_REG_OFFSET + hscx*HSCX_CH_DIFF, adr, value);
byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF);
outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
}
static void
hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
{
return readfifo(cs, HSCX_FIFO_OFFSET + hscx*HSCX_CH_DIFF, data, size);
}
/*
* fast interrupt HSCX stuff goes here
*/
static void
hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)
{
writefifo(cs, HSCX_FIFO_OFFSET + hscx*HSCX_CH_DIFF, data, size);
}
#define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg)
#define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data)
#define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt)
#define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt)
static struct bc_hw_ops hscx_ops = {
.read_reg = hscx_read,
.write_reg = hscx_write,
.read_fifo = hscx_read_fifo,
.write_fifo = hscx_write_fifo,
};
#include "hscx_irq.c"
static irqreturn_t
avm_a1p_interrupt(int intno, void *dev_id, struct pt_regs *regs)
{
struct IsdnCardState *cs = dev_id;
u8 val, sval;
u_char val, sval;
u_long flags;
spin_lock(&cs->lock);
spin_lock_irqsave(&cs->lock, flags);
while ((sval = (~bytein(cs->hw.avm.cfg_reg+ASL0_OFFSET) & ASL0_R_IRQPENDING))) {
if (cs->debug & L1_DEB_INTSTAT)
debugl1(cs, "avm IntStatus %x", sval);
if (sval & ASL0_R_HSCX) {
val = hscx_read(cs, 1, HSCX_ISTA);
val = ReadHSCX(cs, 1, HSCX_ISTA);
if (val)
hscx_int_main(cs, val);
}
if (sval & ASL0_R_ISAC) {
val = isac_read(cs, ISAC_ISTA);
val = ReadISAC(cs, ISAC_ISTA);
if (val)
isac_interrupt(cs, val);
}
}
hscx_write(cs, 0, HSCX_MASK, 0xFF);
hscx_write(cs, 1, HSCX_MASK, 0xFF);
isac_write(cs, ISAC_MASK, 0xFF);
isac_write(cs, ISAC_MASK, 0x0);
hscx_write(cs, 0, HSCX_MASK, 0x0);
hscx_write(cs, 1, HSCX_MASK, 0x0);
spin_unlock(&cs->lock);
WriteHSCX(cs, 0, HSCX_MASK, 0xff);
WriteHSCX(cs, 1, HSCX_MASK, 0xff);
WriteISAC(cs, ISAC_MASK, 0xff);
WriteISAC(cs, ISAC_MASK, 0x00);
WriteHSCX(cs, 0, HSCX_MASK, 0x00);
WriteHSCX(cs, 1, HSCX_MASK, 0x00);
spin_unlock_irqrestore(&cs->lock, flags);
return IRQ_HANDLED;
}
static void
avm_a1p_init(struct IsdnCardState *cs)
{
byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,
ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE);
inithscxisac(cs);
}
static int
avm_a1p_reset(struct IsdnCardState *cs)
AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
{
byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
HZDELAY(HZ / 5 + 1);
byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
HZDELAY(HZ / 5 + 1);
byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
u_long flags;
switch (mt) {
case CARD_RESET:
spin_lock_irqsave(&cs->lock, flags);
byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
HZDELAY(HZ / 5 + 1);
byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
HZDELAY(HZ / 5 + 1);
byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
spin_unlock_irqrestore(&cs->lock, flags);
return 0;
case CARD_RELEASE:
/* free_irq is done in HiSax_closecard(). */
/* free_irq(cs->irq, cs); */
return 0;
case CARD_INIT:
spin_lock_irqsave(&cs->lock, flags);
byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE);
clear_pending_isac_ints(cs);
clear_pending_hscx_ints(cs);
inithscxisac(cs, 1);
inithscxisac(cs, 2);
spin_unlock_irqrestore(&cs->lock, flags);
return 0;
case CARD_TEST:
/* we really don't need it for the PCMCIA Version */
return 0;
default:
/* all card drivers ignore others, so we do the same */
return 0;
}
return 0;
}
static struct card_ops avm_a1p_ops = {
.init = avm_a1p_init,
.reset = avm_a1p_reset,
.irq_func = avm_a1p_interrupt,
};
static int __init
avm_a1p_probe(struct IsdnCardState *cs, struct IsdnCard *card)
int
setup_avm_a1_pcmcia(struct IsdnCard *card)
{
u8 model, vers;
u_char model, vers;
struct IsdnCardState *cs = card->cs;
char tmp[64];
strcpy(tmp, avm_revision);
printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n",
HiSax_getrev(tmp));
if (cs->typ != ISDN_CTYPE_A1_PCMCIA)
return (0);
cs->irq = card->para[0];
cs->hw.avm.cfg_reg = card->para[1];
cs->irq = card->para[0];
outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0);
outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0);
byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
HZDELAY(HZ / 5 + 1);
byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
......@@ -238,26 +244,25 @@ avm_a1p_probe(struct IsdnCardState *cs, struct IsdnCard *card)
vers = bytein(cs->hw.avm.cfg_reg+VERREG_OFFSET);
printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %d\n",
cs->hw.avm.cfg_reg, cs->irq, model, vers);
cs->card_ops = &avm_a1p_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
int __devinit
setup_avm_a1_pcmcia(struct IsdnCard *card)
{
char tmp[64];
strcpy(tmp, avm_revision);
printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n",
HiSax_getrev(tmp));
if (avm_a1p_probe(card->cs, card))
return 0;
return 1;
cs->hw.avm.cfg_reg, cs->irq, model, vers);
setup_isac(cs);
cs->readisac = &ReadISAC;
cs->writeisac = &WriteISAC;
cs->readisacfifo = &ReadISACfifo;
cs->writeisacfifo = &WriteISACfifo;
cs->BC_Read_Reg = &ReadHSCX;
cs->BC_Write_Reg = &WriteHSCX;
cs->BC_Send_Data = &hscx_fill_fifo;
cs->cardmsg = &AVM_card_msg;
cs->irq_flags = SA_SHIRQ;
cs->irq_func = &avm_a1p_interrupt;
ISACVersion(cs, "AVM A1 PCMCIA:");
if (HscxVersion(cs, "AVM A1 PCMCIA:")) {
printk(KERN_WARNING
"AVM A1 PCMCIA: wrong HSCX versions check IO address\n");
return (0);
}
return (1);
}
This diff is collapsed.
......@@ -26,15 +26,12 @@
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include "hisax_cfg.h"
MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for AVM A1/Fritz!PCMCIA cards");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot);
void HiSax_closecard(int cardnr);
/*
All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
you do not define PCMCIA_DEBUG at all, all the debug code will be
......@@ -156,6 +153,15 @@ static dev_link_t *avma1cs_attach(void)
return NULL;
memset(link, 0, sizeof(struct dev_link_t));
/* Allocate space for private device-specific data */
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) {
kfree(link);
return NULL;
}
memset(local, 0, sizeof(local_info_t));
link->priv = local;
/* The io structure describes IO port mapping */
link->io.NumPorts1 = 16;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
......@@ -183,15 +189,6 @@ static dev_link_t *avma1cs_attach(void)
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
/* Allocate space for private device-specific data */
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) {
kfree(link);
return NULL;
}
memset(local, 0, sizeof(local_info_t));
link->priv = local;
/* Register with Card Services */
link->next = dev_list;
dev_list = link;
......@@ -252,7 +249,7 @@ static void avma1cs_detach(dev_link_t *link)
/* Break the link with Card Services */
if (link->handle)
pcmcia_deregister_client(link->handle);
pcmcia_deregister_client(link->handle);
/* Unlink device structure, free pieces */
*linkp = link->next;
......@@ -303,8 +300,9 @@ static void avma1cs_config(dev_link_t *link)
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
local_info_t *dev;
int i;
u8 buf[64];
u_char buf[64];
char devname[128];
IsdnCard_t icard;
int busy = 0;
handle = link->handle;
......@@ -365,9 +363,9 @@ static void avma1cs_config(dev_link_t *link)
link->io.BasePort1 = cf->io.win[0].base;
link->io.NumPorts1 = cf->io.win[0].len;
link->io.NumPorts2 = 0;
printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
link->io.BasePort1,
link->io.BasePort1+link->io.NumPorts1 - 1);
link->io.BasePort1+link->io.NumPorts1 - 1);
i = pcmcia_request_io(link->handle, &link->io);
if (i == CS_SUCCESS) goto found_port;
}
......@@ -391,8 +389,8 @@ static void avma1cs_config(dev_link_t *link)
}
/*
* configure the PCMCIA socket
*/
* configure the PCMCIA socket
*/
i = pcmcia_request_configuration(link->handle, &link->conf);
if (i != CS_SUCCESS) {
cs_error(link->handle, RequestConfiguration, i);
......@@ -421,15 +419,17 @@ static void avma1cs_config(dev_link_t *link)
printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n",
link->io.BasePort1, link->irq.AssignedIRQ);
if (avm_a1_init_pcmcia((void *)(int)link->io.BasePort1,
link->irq.AssignedIRQ,
&busy, isdnprot) != 0) {
printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1);
return;
icard.para[0] = link->irq.AssignedIRQ;
icard.para[1] = link->io.BasePort1;
icard.protocol = isdnprot;
icard.typ = ISDN_CTYPE_A1_PCMCIA;
i = hisax_init_pcmcia(link, &busy, &icard);
if (i < 0) {
printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1);
avma1cs_release(link);
return;
}
i = 0; /* no returncode for cardnr :-( */
dev->node.minor = i;
} /* avma1cs_config */
......@@ -486,29 +486,28 @@ static int avma1cs_event(event_t event, int priority,
DEBUG(1, "avma1cs_event(0x%06x)\n", event);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG)
case CS_EVENT_CARD_REMOVAL:
if (link->state & DEV_CONFIG)
avma1cs_release(link);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
avma1cs_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG)
pcmcia_request_configuration(link->handle, &link->conf);
break;
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
avma1cs_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG)
pcmcia_request_configuration(link->handle, &link->conf);
break;
}
return 0;
} /* avma1cs_event */
......@@ -521,10 +520,12 @@ static struct pcmcia_driver avma1cs_driver = {
.attach = avma1cs_attach,
.detach = avma1cs_detach,
};
/*====================================================================*/
static int __init init_avma1_cs(void)
{
return pcmcia_register_driver(&avma1cs_driver);
return(pcmcia_register_driver(&avma1cs_driver));
}
static void __exit exit_avma1_cs(void)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* $Id: cert.c,v 2.3.6.3 2001/09/23 22:24:47 kai Exp $
*
* Author Karsten Keil
* Copyright by Karsten Keil <keil@isdn4linux.de>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* For changes and modifications please read
* ../../../Documentation/isdn/HiSax.cert
*
*/
#include <linux/kernel.h>
int
certification_check(int output) {
#ifdef CERTIFICATION
#if CERTIFICATION == 0
if (output) {
printk(KERN_INFO "HiSax: Approval certification valid\n");
printk(KERN_INFO "HiSax: Approved with ELSA Microlink PCI cards\n");
printk(KERN_INFO "HiSax: Approved with Eicon Technology Diva 2.01 PCI cards\n");
printk(KERN_INFO "HiSax: Approved with Sedlbauer Speedfax + cards\n");
printk(KERN_INFO "HiSax: Approved with HFC-S PCI A based cards\n");
}
return(0);
#endif
#if CERTIFICATION == 1
if (output) {
printk(KERN_INFO "HiSax: Approval certification failed because of\n");
printk(KERN_INFO "HiSax: unauthorized source code changes\n");
}
return(1);
#endif
#if CERTIFICATION == 127
if (output) {
printk(KERN_INFO "HiSax: Approval certification not possible\n");
printk(KERN_INFO "HiSax: because \"md5sum\" is not available\n");
}
return(2);
#endif
#else
if (output) {
printk(KERN_INFO "HiSax: Certification not verified\n");
}
return(3);
#endif
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -40,3 +40,12 @@
* den TigerJet i/o-Raum gemappt
* -> 0x01 des AMD bei hw.njet.base + 0C4 */
#define TJ_AMD_PORT 0xC0
/* ***************************************************************************************** *
* *************************************** Prototypen ************************************** *
* ***************************************************************************************** */
BYTE ReadByteAmd7930(struct IsdnCardState *cs, BYTE offset);
void WriteByteAmd7930(struct IsdnCardState *cs, BYTE offset, BYTE value);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* $Id: hfc_2bds0.h,v 1.4.6.2 2001/09/23 22:24:47 kai Exp $
/* $Id: hfc_2bds0.h,v 1.6.2.2 2004/01/12 22:52:26 keil Exp $
*
* specific defines for CCD's HFC 2BDS0
*
......@@ -124,5 +124,5 @@
extern void main_irq_2bds0(struct BCState *bcs);
extern void init2bds0(struct IsdnCardState *cs);
extern void release2bds0(struct IsdnCardState *cs);
extern void hfc2bds0_interrupt(struct IsdnCardState *cs, u8 val);
extern void hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val);
extern void set_cs_func(struct IsdnCardState *cs);
This diff is collapsed.
/* $Id: hfc_2bs0.h,v 1.3.6.2 2001/09/23 22:24:47 kai Exp $
/* $Id: hfc_2bs0.h,v 1.5.2.2 2004/01/12 22:52:26 keil Exp $
*
* specific defines for CCD's HFC 2BS0
*
......@@ -58,4 +58,3 @@
extern void main_irq_hfc(struct BCState *bcs);
extern void inithfc(struct IsdnCardState *cs);
extern void releasehfc(struct IsdnCardState *cs);
extern int hfc_setup(struct IsdnCardState *cs, struct bc_hw_ops *hfc_ops);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -39,7 +39,7 @@ printk(KERN_DEBUG "%s: " format "\n" , __FUNCTION__ , ## arg); \
static void __attribute__((unused))
dump_packet(const char *name,const u8 *data,int pkt_len)
dump_packet(const char *name,const u_char *data,int pkt_len)
{
#define DUMP_HDR_SIZE 20
#define DUMP_TLR_SIZE 8
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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