patch-2.2.19 linux/drivers/isdn/eicon/eicon_mod.c
Next file: linux/drivers/isdn/eicon/eicon_pci.c
Previous file: linux/drivers/isdn/eicon/eicon_isa.h
Back to the patch index
Back to the overall index
- Lines: 1071
- Date:
Sun Mar 25 11:37:32 2001
- Orig file:
v2.2.18/drivers/isdn/eicon/eicon_mod.c
- Orig date:
Sun Mar 25 11:13:08 2001
diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.18/drivers/isdn/eicon/eicon_mod.c linux/drivers/isdn/eicon/eicon_mod.c
@@ -1,4 +1,4 @@
-/* $Id: eicon_mod.c,v 1.25 2000/02/22 16:26:40 armin Exp $
+/* $Id: eicon_mod.c,v 1.37.6.4 2001/02/16 09:09:50 armin Exp $
*
* ISDN lowlevel-module for Eicon active cards.
*
@@ -6,11 +6,9 @@
* Copyright 1998-2000 by Armin Schindler (mac@melware.de)
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
*
- * Thanks to Eicon Technology GmbH & Co. oHG for
+ * Thanks to Eicon Networks for
* documents, informations and hardware.
*
- * Deutsche Telekom AG for S2M support.
- *
* Deutsche Mailbox Saar-Lor-Lux GmbH
* for sponsoring and testing fax
* capabilities with Diva Server cards.
@@ -30,105 +28,12 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Log: eicon_mod.c,v $
- * Revision 1.25 2000/02/22 16:26:40 armin
- * Fixed membase error message.
- * Fixed missing log buffer struct.
- *
- * Revision 1.24 2000/01/23 21:21:23 armin
- * Added new trace capability and some updates.
- * DIVA Server BRI now supports data for ISDNLOG.
- *
- * Revision 1.23 2000/01/20 19:55:34 keil
- * Add FAX Class 1 support
- *
- * Revision 1.22 1999/11/27 12:56:19 armin
- * Forgot some iomem changes for last ioremap compat.
- *
- * Revision 1.21 1999/11/25 11:35:10 armin
- * Microchannel fix from Erik Weber (exrz73@ibm.net).
- * Minor cleanup.
- *
- * Revision 1.20 1999/11/18 21:14:30 armin
- * New ISA memory mapped IO
- *
- * Revision 1.19 1999/11/12 13:21:44 armin
- * Bugfix of undefined reference with CONFIG_MCA
- *
- * Revision 1.18 1999/10/11 18:13:25 armin
- * Added fax capabilities for Eicon Diva Server cards.
- *
- * Revision 1.17 1999/10/08 22:09:34 armin
- * Some fixes of cards interface handling.
- * Bugfix of NULL pointer occurence.
- * Changed a few log outputs.
- *
- * Revision 1.16 1999/09/26 14:17:53 armin
- * Improved debug and log via readstat()
- *
- * Revision 1.15 1999/09/08 20:17:31 armin
- * Added microchannel patch from Erik Weber (exrz73@ibm.net).
- *
- * Revision 1.14 1999/09/06 07:29:35 fritz
- * Changed my mail-address.
- *
- * Revision 1.13 1999/09/04 17:37:59 armin
- * Removed not used define, did not work and caused error
- * in 2.3.16
- *
- * Revision 1.12 1999/08/31 11:20:14 paul
- * various spelling corrections (new checksums may be needed, Karsten!)
- *
- * Revision 1.11 1999/08/29 17:23:45 armin
- * New setup compat.
- * Bugfix if compile as not module.
- *
- * Revision 1.10 1999/08/28 21:32:53 armin
- * Prepared for fax related functions.
- * Now compilable without errors/warnings.
- *
- * Revision 1.9 1999/08/18 20:17:02 armin
- * Added XLOG function for all cards.
- * Bugfix of alloc_skb NULL pointer.
- *
- * Revision 1.8 1999/07/25 15:12:08 armin
- * fix of some debug logs.
- * enabled ISA-cards option.
- *
- * Revision 1.7 1999/07/11 17:16:27 armin
- * Bugfixes in queue handling.
- * Added DSP-DTMF decoder functions.
- * Reorganized ack_handler.
- *
- * Revision 1.6 1999/06/09 19:31:26 armin
- * Wrong PLX size for request_region() corrected.
- * Added first MCA code from Erik Weber.
- *
- * Revision 1.5 1999/04/01 12:48:35 armin
- * Changed some log outputs.
- *
- * Revision 1.4 1999/03/29 11:19:47 armin
- * I/O stuff now in seperate file (eicon_io.c)
- * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
- *
- * Revision 1.3 1999/03/02 12:37:47 armin
- * Added some important checks.
- * Analog Modem with DSP.
- * Channels will be added to Link-Level after loading firmware.
- *
- * Revision 1.2 1999/01/24 20:14:21 armin
- * Changed and added debug stuff.
- * Better data sending. (still problems with tty's flip buffer)
- *
- * Revision 1.1 1999/01/01 18:09:44 armin
- * First checkin of new eicon driver.
- * DIVA-Server BRI/PCI and PRI/PCI are supported.
- * Old diehl code is obsolete.
- *
- *
*/
-#define DRIVERPATCH ""
+#define DRIVERNAME "Eicon active ISDN driver"
+#define DRIVERRELEASE "2.0"
+#define DRIVERPATCH ".16"
+
#include <linux/config.h>
#include <linux/module.h>
@@ -139,17 +44,27 @@
#include "eicon.h"
+#include "../avmb1/capicmd.h" /* this should be moved in a common place */
+
+#undef N_DATA
+#include "adapter.h"
+#include "uxio.h"
+
#define INCLUDE_INLINE_FUNCS
static eicon_card *cards = (eicon_card *) NULL; /* glob. var , contains
start of card-list */
-static char *eicon_revision = "$Revision: 1.25 $";
+static char *eicon_revision = "$Revision: 1.37.6.4 $";
extern char *eicon_pci_revision;
extern char *eicon_isa_revision;
extern char *eicon_idi_revision;
+extern int do_ioctl(struct inode *pDivasInode, struct file *pDivasFile,
+ unsigned int command, unsigned long arg);
+extern void eicon_pci_init_conf(eicon_card *card);
+
#ifdef MODULE
#define MOD_USE_COUNT (GET_USE_COUNT (&__this_module))
#endif
@@ -158,6 +73,10 @@
ulong DebugVar;
+spinlock_t eicon_lock;
+
+DESCRIPTOR idi_d[32];
+
/* Parameters to be set by insmod */
#ifdef CONFIG_ISDN_DRV_EICON_ISA
static int membase = -1;
@@ -189,23 +108,6 @@
"DIVA Server PRI/PCI"
};
-static int
-getrel(char *p)
-{
- int v = 0;
- char *tmp = 0;
-
- if ((tmp = strchr(p, '.')))
- p = tmp + 1;
- while (p[0] >= '0' && p[0] <= '9') {
- v = ((v < 0) ? 0 : (v * 10)) + (int) (p[0] - '0');
- p++;
- }
- return v;
-
-
-}
-
static char *
eicon_getrev(const char *revision)
{
@@ -229,68 +131,26 @@
return NULL;
}
+#ifdef CONFIG_PCI
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
/*
- * Free MSN list
+ * Find pcicard with given card number
*/
-static void
-eicon_clear_msn(eicon_card *card)
+static inline eicon_card *
+eicon_findnpcicard(int driverid)
{
- struct msn_entry *p = card->msn_list;
- struct msn_entry *q;
- unsigned long flags;
+ eicon_card *p = cards;
- save_flags(flags);
- cli();
- card->msn_list = NULL;
- restore_flags(flags);
while (p) {
- q = p->next;
- kfree(p);
- p = q;
+ if ((p->regname[strlen(p->regname)-1] == (driverid + '0')) &&
+ (p->bus == EICON_BUS_PCI))
+ return p;
+ p = p->next;
}
+ return (eicon_card *) 0;
}
-
-/*
- * Find an MSN entry in the list.
- * If ia5 != 0, return IA5-encoded EAZ, else
- * return a bitmask with corresponding bit set.
- */
-static __u16
-eicon_find_msn(eicon_card *card, char *msn, int ia5)
-{
- struct msn_entry *p = card->msn_list;
- __u8 eaz = '0';
-
- while (p) {
- if (!strcmp(p->msn, msn)) {
- eaz = p->eaz;
- break;
- }
- p = p->next;
- }
- if (!ia5)
- return (1 << (eaz - '0'));
- else
- return eaz;
-}
-
-/*
- * Find an EAZ entry in the list.
- * return a string with corresponding msn.
- */
-char *
-eicon_find_eaz(eicon_card *card, char eaz)
-{
- struct msn_entry *p = card->msn_list;
-
- while (p) {
- if (p->eaz == eaz)
- return(p->msn);
- p = p->next;
- }
- return("\0");
-}
-
+#endif
+#endif /* CONFIG_PCI */
static void
eicon_rcv_dispatch(struct eicon_card *card)
@@ -337,39 +197,19 @@
}
}
-static int eicon_xlog(eicon_card *card, xlogreq_t *xlogreq)
-{
- xlogreq_t *xlr;
- int ret_val;
-
- if (!(xlr = kmalloc(sizeof(xlogreq_t), GFP_KERNEL))) {
- eicon_log(card, 1, "idi_err: alloc_xlogreq_t failed\n");
- return -ENOMEM;
- }
- if (copy_from_user(xlr, xlogreq, sizeof(xlogreq_t))) {
- kfree(xlr);
- return -EFAULT;
- }
-
- ret_val = eicon_get_xlog(card, xlr);
-
- if (copy_to_user(xlogreq, xlr, sizeof(xlogreq_t))) {
- kfree(xlr);
- return -EFAULT;
- }
- kfree(xlr);
-
- return ret_val;
-}
-
static int
eicon_command(eicon_card * card, isdn_ctrl * c)
{
ulong a;
eicon_chan *chan;
eicon_cdef cdef;
+#ifdef CONFIG_PCI
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
+ dia_start_t dstart;
+ int idi_length = 0;
+#endif
+#endif
isdn_ctrl cmd;
- char tmp[17];
int ret = 0;
unsigned long flags;
@@ -383,16 +223,15 @@
case EICON_IOCTL_GETVER:
return(EICON_CTRL_VERSION);
case EICON_IOCTL_GETTYPE:
+ if (card->bus == EICON_BUS_PCI) {
+ copy_to_user((char *)a, &card->hwif.pci.master, sizeof(int));
+ }
return(card->type);
case EICON_IOCTL_GETMMIO:
switch (card->bus) {
case EICON_BUS_ISA:
case EICON_BUS_MCA:
return (int)card->hwif.isa.shmem;
-#if CONFIG_PCI
- case EICON_BUS_PCI:
- return card->hwif.pci.PCIram;
-#endif
default:
eicon_log(card, 1,
"eicon: Illegal BUS type %d\n",
@@ -433,10 +272,6 @@
case EICON_BUS_ISA:
case EICON_BUS_MCA:
return card->hwif.isa.irq;
-#if CONFIG_PCI
- case EICON_BUS_PCI:
- return card->hwif.pci.irq;
-#endif
default:
eicon_log(card, 1,
"eicon: Illegal BUS type %d\n",
@@ -514,7 +349,9 @@
case EICON_IOCTL_MANIF:
if (!card->flags & EICON_FLAGS_RUNNING)
return -ENODEV;
- if (!card->Feature & PROTCAP_MANIF)
+ if (!card->d)
+ return -ENODEV;
+ if (!card->d->features & DI_MANAGE)
return -ENODEV;
ret = eicon_idi_manage(
card,
@@ -522,49 +359,12 @@
return ret;
case EICON_IOCTL_GETXLOG:
- if (!card->flags & EICON_FLAGS_RUNNING)
- return XLOG_ERR_CARD_STATE;
- ret = eicon_xlog(card, (xlogreq_t *)a);
- return ret;
-#if CONFIG_PCI
- case EICON_IOCTL_LOADPCI:
- if (card->flags & EICON_FLAGS_RUNNING)
- return -EBUSY;
- if (card->bus == EICON_BUS_PCI) {
- switch(card->type) {
- case EICON_CTYPE_MAESTRA:
- ret = eicon_pci_load_bri(
- &(card->hwif.pci),
- &(((eicon_codebuf *)a)->pci));
- break;
-
- case EICON_CTYPE_MAESTRAP:
- ret = eicon_pci_load_pri(
- &(card->hwif.pci),
- &(((eicon_codebuf *)a)->pci));
- break;
- }
- if (!ret) {
- card->flags |= EICON_FLAGS_LOADED;
- card->flags |= EICON_FLAGS_RUNNING;
- if (card->hwif.pci.channels > 1) {
- cmd.command = ISDN_STAT_ADDCH;
- cmd.driver = card->myid;
- cmd.arg = card->hwif.pci.channels - 1;
- card->interface.statcallb(&cmd);
- }
- cmd.command = ISDN_STAT_RUN;
- cmd.driver = card->myid;
- cmd.arg = 0;
- card->interface.statcallb(&cmd);
- }
- return ret;
- } else return -ENODEV;
-#endif
+ return -ENODEV;
+
case EICON_IOCTL_ADDCARD:
if ((ret = copy_from_user(&cdef, (char *)a, sizeof(cdef))))
return -EFAULT;
- if (!(eicon_addcard(0, cdef.membase, cdef.irq, cdef.id)))
+ if (!(eicon_addcard(0, cdef.membase, cdef.irq, cdef.id, 0)))
return -EIO;
return 0;
case EICON_IOCTL_DEBUGVAR:
@@ -577,8 +377,87 @@
MOD_INC_USE_COUNT;
return 0;
#endif
- default:
+ case EICON_IOCTL_LOADPCI:
+ eicon_log(card, 1, "Eicon: Wrong version of load-utility,\n");
+ eicon_log(card, 1, "Eicon: re-compile eiconctrl !\n");
+ eicon_log(card, 1, "Eicon: Maybe update of utility is necessary !\n");
return -EINVAL;
+ default:
+#ifdef CONFIG_PCI
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
+ if (c->arg < EICON_IOCTL_DIA_OFFSET)
+ return -EINVAL;
+ if (copy_from_user(&dstart, (char *)a, sizeof(dstart)))
+ return -1;
+ if (!(card = eicon_findnpcicard(dstart.card_id)))
+ return -EINVAL;
+ ret = do_ioctl(NULL, NULL,
+ c->arg - EICON_IOCTL_DIA_OFFSET,
+ (unsigned long) a);
+ if (((c->arg - EICON_IOCTL_DIA_OFFSET)==DIA_IOCTL_START) && (!ret)) {
+ if (card->type != EICON_CTYPE_MAESTRAQ) {
+ DIVA_DIDD_Read(idi_d, sizeof(idi_d));
+ for(idi_length = 0; idi_length < 32; idi_length++) {
+ if (idi_d[idi_length].type == 0) break;
+ }
+ if ((idi_length < 1) || (idi_length >= 32)) {
+ eicon_log(card, 1, "eicon: invalid idi table length.\n");
+ break;
+ }
+ card->d = &idi_d[idi_length - 1];
+ card->flags |= EICON_FLAGS_LOADED;
+ card->flags |= EICON_FLAGS_RUNNING;
+ eicon_pci_init_conf(card);
+ if (card->d->channels > 1) {
+ cmd.command = ISDN_STAT_ADDCH;
+ cmd.driver = card->myid;
+ cmd.arg = card->d->channels - 1;
+ card->interface.statcallb(&cmd);
+ }
+ cmd.command = ISDN_STAT_RUN;
+ cmd.driver = card->myid;
+ cmd.arg = 0;
+ card->interface.statcallb(&cmd);
+ eicon_log(card, 1, "Eicon: %s started, %d channels (feat. 0x%x)\n",
+ (card->type == EICON_CTYPE_MAESTRA) ? "BRI" : "PRI",
+ card->d->channels, card->d->features);
+ } else {
+ int i;
+ DIVA_DIDD_Read(idi_d, sizeof(idi_d));
+ for(idi_length = 0; idi_length < 32; idi_length++)
+ if (idi_d[idi_length].type == 0) break;
+ if ((idi_length < 1) || (idi_length >= 32)) {
+ eicon_log(card, 1, "eicon: invalid idi table length.\n");
+ break;
+ }
+ for(i = 3; i >= 0; i--) {
+ if (!(card = eicon_findnpcicard(dstart.card_id - i)))
+ return -EINVAL;
+
+ card->flags |= EICON_FLAGS_LOADED;
+ card->flags |= EICON_FLAGS_RUNNING;
+ card->d = &idi_d[idi_length - (i+1)];
+ eicon_pci_init_conf(card);
+ if (card->d->channels > 1) {
+ cmd.command = ISDN_STAT_ADDCH;
+ cmd.driver = card->myid;
+ cmd.arg = card->d->channels - 1;
+ card->interface.statcallb(&cmd);
+ }
+ cmd.command = ISDN_STAT_RUN;
+ cmd.driver = card->myid;
+ cmd.arg = 0;
+ card->interface.statcallb(&cmd);
+ eicon_log(card, 1, "Eicon: %d/4BRI started, %d channels (feat. 0x%x)\n",
+ 4-i, card->d->channels, card->d->features);
+ }
+ }
+ }
+ return ret;
+#else
+ return -EINVAL;
+#endif
+#endif /* CONFIG_PCI */
}
break;
case ISDN_CMD_DIAL:
@@ -586,20 +465,15 @@
return -ENODEV;
if (!(chan = find_channel(card, c->arg & 0x1f)))
break;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&eicon_lock, flags);
if ((chan->fsm_state != EICON_STATE_NULL) && (chan->fsm_state != EICON_STATE_LISTEN)) {
- restore_flags(flags);
+ spin_unlock_irqrestore(&eicon_lock, flags);
eicon_log(card, 1, "Dial on channel %d with state %d\n",
chan->No, chan->fsm_state);
return -EBUSY;
}
- if (card->ptype == ISDN_PTYPE_EURO)
- tmp[0] = eicon_find_msn(card, c->parm.setup.eazmsn, 1);
- else
- tmp[0] = c->parm.setup.eazmsn[0];
chan->fsm_state = EICON_STATE_OCALL;
- restore_flags(flags);
+ spin_unlock_irqrestore(&eicon_lock, flags);
ret = idi_connect_req(card, chan, c->parm.setup.phone,
c->parm.setup.eazmsn,
@@ -637,19 +511,7 @@
return -ENODEV;
if (!(chan = find_channel(card, c->arg & 0x1f)))
break;
- if (strlen(c->parm.num)) {
- if (card->ptype == ISDN_PTYPE_EURO) {
- chan->eazmask = eicon_find_msn(card, c->parm.num, 0);
- }
- if (card->ptype == ISDN_PTYPE_1TR6) {
- int i;
- chan->eazmask = 0;
- for (i = 0; i < strlen(c->parm.num); i++)
- if (isdigit(c->parm.num[i]))
- chan->eazmask |= (1 << (c->parm.num[i] - '0'));
- }
- } else
- chan->eazmask = 0x3ff;
+ chan->eazmask = 0x3ff;
eicon_idi_listen_req(card, chan);
return 0;
case ISDN_CMD_CLREAZ:
@@ -680,8 +542,10 @@
break;
chan->l3prot = (c->arg >> 8);
#ifdef CONFIG_ISDN_TTY_FAX
- if (chan->l3prot == ISDN_PROTO_L3_FCLASS2)
+ if (chan->l3prot == ISDN_PROTO_L3_FCLASS2) {
chan->fax = c->parm.fax;
+ eicon_log(card, 128, "idi_cmd: Ch%d: SETL3 struct fax=0x%x\n",chan->No, chan->fax);
+ }
#endif
return 0;
case ISDN_CMD_GETL3:
@@ -729,6 +593,23 @@
break;
idi_audio_cmd(card, chan, c->arg >> 8, c->parm.num);
return 0;
+ case CAPI_PUT_MESSAGE:
+ if (!card->flags & EICON_FLAGS_RUNNING)
+ return -ENODEV;
+ if (!(chan = find_channel(card, c->arg & 0x1f)))
+ break;
+ if (c->parm.cmsg.Length < 8)
+ break;
+ switch(c->parm.cmsg.Command) {
+ case CAPI_FACILITY:
+ if (c->parm.cmsg.Subcommand == CAPI_REQ)
+ return(capipmsg(card, chan, &c->parm.cmsg));
+ break;
+ case CAPI_MANUFACTURER:
+ default:
+ break;
+ }
+ return 0;
}
return -EINVAL;
@@ -787,8 +668,7 @@
if (!card->flags & EICON_FLAGS_RUNNING)
return -ENODEV;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&eicon_lock, flags);
while((skb = skb_dequeue(&card->statq))) {
if ((skb->len + count) > len)
@@ -811,12 +691,12 @@
} else {
skb_pull(skb, cnt);
skb_queue_head(&card->statq, skb);
- restore_flags(flags);
+ spin_unlock_irqrestore(&eicon_lock, flags);
return count;
}
}
card->statq_entries = 0;
- restore_flags(flags);
+ spin_unlock_irqrestore(&eicon_lock, flags);
return count;
}
printk(KERN_ERR
@@ -848,7 +728,7 @@
}
else
#endif
- ret = idi_send_data(card, chan, ack, skb, 1);
+ ret = idi_send_data(card, chan, ack, skb, 1, 1);
return (ret);
} else {
return -ENODEV;
@@ -895,12 +775,11 @@
return;
}
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&eicon_lock, flags);
count = strlen(buf);
skb = alloc_skb(count, GFP_ATOMIC);
if (!skb) {
- restore_flags(flags);
+ spin_unlock_irqrestore(&eicon_lock, flags);
printk(KERN_ERR "eicon: could not alloc skb in putstatus\n");
return;
}
@@ -918,7 +797,7 @@
} else
card->statq_entries++;
- restore_flags(flags);
+ spin_unlock_irqrestore(&eicon_lock, flags);
if (count) {
cmd.command = ISDN_STAT_STAVAIL;
cmd.driver = card->myid;
@@ -967,7 +846,7 @@
* link it into cards-list.
*/
static void
-eicon_alloccard(int Type, int membase, int irq, char *id)
+eicon_alloccard(int Type, int membase, int irq, char *id, int card_id)
{
int i;
int j;
@@ -976,9 +855,6 @@
char qid[5];
#endif
eicon_card *card;
-#if CONFIG_PCI
- eicon_pci_card *pcic;
-#endif
qloop = (Type == EICON_CTYPE_QUADRO)?2:0;
for (i = 0; i <= qloop; i++) {
@@ -1088,9 +964,9 @@
card->interface.channels = 1;
break;
#endif
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
case EICON_CTYPE_MAESTRA:
- (eicon_pci_card *)pcic = (eicon_pci_card *)membase;
card->bus = EICON_BUS_PCI;
card->interface.features |=
ISDN_FEATURE_L2_V11096 |
@@ -1101,11 +977,26 @@
ISDN_FEATURE_L3_TRANSDSP |
ISDN_FEATURE_L3_FCLASS2;
card->hwif.pci.card = (void *)card;
- card->hwif.pci.PCIreg = pcic->PCIreg;
- card->hwif.pci.PCIcfg = pcic->PCIcfg;
- card->hwif.pci.master = 1;
- card->hwif.pci.mvalid = pcic->mvalid;
- card->hwif.pci.ivalid = 0;
+ card->hwif.pci.master = card_id;
+ card->hwif.pci.irq = irq;
+ card->hwif.pci.type = Type;
+ card->flags = 0;
+ card->nchannels = 2;
+ card->interface.channels = 1;
+ break;
+
+ case EICON_CTYPE_MAESTRAQ:
+ card->bus = EICON_BUS_PCI;
+ card->interface.features |=
+ ISDN_FEATURE_L2_V11096 |
+ ISDN_FEATURE_L2_V11019 |
+ ISDN_FEATURE_L2_V11038 |
+ ISDN_FEATURE_L2_MODEM |
+ ISDN_FEATURE_L2_FAX |
+ ISDN_FEATURE_L3_TRANSDSP |
+ ISDN_FEATURE_L3_FCLASS2;
+ card->hwif.pci.card = (void *)card;
+ card->hwif.pci.master = card_id;
card->hwif.pci.irq = irq;
card->hwif.pci.type = Type;
card->flags = 0;
@@ -1114,7 +1005,6 @@
break;
case EICON_CTYPE_MAESTRAP:
- (eicon_pci_card *)pcic = (eicon_pci_card *)membase;
card->bus = EICON_BUS_PCI;
card->interface.features |=
ISDN_FEATURE_L2_V11096 |
@@ -1125,13 +1015,7 @@
ISDN_FEATURE_L3_TRANSDSP |
ISDN_FEATURE_L3_FCLASS2;
card->hwif.pci.card = (void *)card;
- card->hwif.pci.shmem = (eicon_pci_shmem *)pcic->shmem;
- card->hwif.pci.PCIreg = pcic->PCIreg;
- card->hwif.pci.PCIram = pcic->PCIram;
- card->hwif.pci.PCIcfg = pcic->PCIcfg;
- card->hwif.pci.master = 1;
- card->hwif.pci.mvalid = pcic->mvalid;
- card->hwif.pci.ivalid = 0;
+ card->hwif.pci.master = card_id;
card->hwif.pci.irq = irq;
card->hwif.pci.type = Type;
card->flags = 0;
@@ -1139,6 +1023,7 @@
card->interface.channels = 1;
break;
#endif
+#endif
#ifdef CONFIG_ISDN_DRV_EICON_ISA
case EICON_CTYPE_ISABRI:
if (membase == -1)
@@ -1197,6 +1082,53 @@
skb_queue_head_init(&card->bch[j].e.X);
skb_queue_head_init(&card->bch[j].e.R);
}
+
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
+ /* *** Diva Server *** */
+ if (!(card->dbuf = (DBUFFER *) kmalloc((sizeof(DBUFFER) * (card->nchannels + 1))*2
+ , GFP_KERNEL))) {
+ eicon_log(card, 1,
+ "eicon: (%s) Could not allocate DBUFFER-struct.\n", id);
+ kfree(card);
+ kfree(card->bch);
+ return;
+ }
+ if (!(card->sbuf = (BUFFERS *) kmalloc((sizeof(BUFFERS) * (card->nchannels + 1)) * 2, GFP_KERNEL))) {
+ eicon_log(card, 1,
+ "eicon: (%s) Could not allocate BUFFERS-struct.\n", id);
+ kfree(card);
+ kfree(card->bch);
+ kfree(card->dbuf);
+ return;
+ }
+ if (!(card->sbufp = (char *) kmalloc((270 * (card->nchannels + 1)) * 2, GFP_KERNEL))) {
+ eicon_log(card, 1,
+ "eicon: (%s) Could not allocate BUFFERSP-struct.\n", id);
+ kfree(card);
+ kfree(card->bch);
+ kfree(card->dbuf);
+ kfree(card->sbuf);
+ return;
+ }
+ for (j=0; j< (card->nchannels + 1); j++) {
+ memset((char *)&card->dbuf[j], 0, sizeof(DBUFFER));
+ card->bch[j].de.RBuffer = (DBUFFER *)&card->dbuf[j];
+ memset((char *)&card->dbuf[j+(card->nchannels+1)], 0, sizeof(BUFFERS));
+ card->bch[j].be.RBuffer = (DBUFFER *)&card->dbuf[j+(card->nchannels+1)];
+
+ memset((char *)&card->sbuf[j], 0, sizeof(BUFFERS));
+ card->bch[j].de.X = (BUFFERS *)&card->sbuf[j];
+ memset((char *)&card->sbuf[j+(card->nchannels+1)], 0, sizeof(BUFFERS));
+ card->bch[j].be.X = (BUFFERS *)&card->sbuf[j+(card->nchannels+1)];
+
+ memset((char *)&card->sbufp[j], 0, 270);
+ card->bch[j].de.X->P = (char *)&card->sbufp[j * 270];
+ memset((char *)&card->sbufp[j+(card->nchannels+1)], 0, 270);
+ card->bch[j].be.X->P = (char *)&card->sbufp[(j+(card->nchannels+1)) * 270];
+ }
+ /* *** */
+#endif /* CONFIG_ISDN_DRV_EICON_PCI */
+
card->next = cards;
cards = card;
}
@@ -1220,10 +1152,7 @@
#endif /* CONFIG_MCA */
#endif
case EICON_BUS_PCI:
-#if CONFIG_PCI
- eicon_pci_printpar(&card->hwif.pci);
break;
-#endif
default:
eicon_log(card, 1,
"eicon_registercard: Illegal BUS type %d\n",
@@ -1241,8 +1170,7 @@
return 0;
}
-#ifdef MODULE
-static void
+static void
unregister_card(eicon_card * card)
{
isdn_ctrl cmd;
@@ -1260,10 +1188,7 @@
break;
#endif
case EICON_BUS_PCI:
-#if CONFIG_PCI
- eicon_pci_release(&card->hwif.pci);
break;
-#endif
default:
eicon_log(card, 1,
"eicon: Invalid BUS type %d\n",
@@ -1271,7 +1196,6 @@
break;
}
}
-#endif /* MODULE */
static void
eicon_freecard(eicon_card *card) {
@@ -1295,13 +1219,17 @@
while((skb = skb_dequeue(&card->statq)))
dev_kfree_skb(skb);
- eicon_clear_msn(card);
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
+ kfree(card->sbufp);
+ kfree(card->sbuf);
+ kfree(card->dbuf);
+#endif
kfree(card->bch);
kfree(card);
}
int
-eicon_addcard(int Type, int membase, int irq, char *id)
+eicon_addcard(int Type, int membase, int irq, char *id, int card_id)
{
eicon_card *p;
eicon_card *q = NULL;
@@ -1314,7 +1242,7 @@
if ((Type = eicon_isa_find_card(membase, irq, id)) < 0)
return 0;
#endif
- eicon_alloccard(Type, membase, irq, id);
+ eicon_alloccard(Type, membase, irq, id, card_id);
p = cards;
while (p) {
registered = 0;
@@ -1333,12 +1261,14 @@
break;
#endif
case EICON_BUS_PCI:
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
if (eicon_registercard(p))
break;
registered = 1;
break;
#endif
+#endif
default:
printk(KERN_ERR
"eicon: addcard: Invalid BUS type %d\n",
@@ -1371,46 +1301,35 @@
return (added - failed);
}
-#define DRIVERNAME "Eicon active ISDN driver"
-#define DRIVERRELEASE "1"
-#ifdef MODULE
-#define eicon_init init_module
-#endif
-
-int
+static int __init
eicon_init(void)
{
int card_count = 0;
- int release = 0;
char tmprev[50];
DebugVar = 1;
+ eicon_lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
printk(KERN_INFO "%s Rev: ", DRIVERNAME);
strcpy(tmprev, eicon_revision);
printk("%s/", eicon_getrev(tmprev));
- release += getrel(tmprev);
strcpy(tmprev, eicon_pci_revision);
-#if CONFIG_PCI
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
printk("%s/", eicon_getrev(tmprev));
#else
printk("---/");
#endif
- release += getrel(tmprev);
strcpy(tmprev, eicon_isa_revision);
#ifdef CONFIG_ISDN_DRV_EICON_ISA
printk("%s/", eicon_getrev(tmprev));
#else
printk("---/");
#endif
- release += getrel(tmprev);
strcpy(tmprev, eicon_idi_revision);
printk("%s\n", eicon_getrev(tmprev));
- release += getrel(tmprev);
- sprintf(tmprev,"%d", release);
- printk(KERN_INFO "%s Release: %s.%s%s\n", DRIVERNAME,
- DRIVERRELEASE, tmprev, DRIVERPATCH);
+ printk(KERN_INFO "%s Release: %s%s\n", DRIVERNAME,
+ DRIVERRELEASE, DRIVERPATCH);
#ifdef CONFIG_ISDN_DRV_EICON_ISA
#ifdef CONFIG_MCA
@@ -1427,18 +1346,23 @@
card_count++;
};
#else
- card_count = eicon_addcard(0, membase, irq, id);
+ card_count = eicon_addcard(0, membase, irq, id, 0);
#endif /* CONFIG_MCA */
#endif /* CONFIG_ISDN_DRV_EICON_ISA */
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
+ DivasCardsDiscover();
card_count += eicon_pci_find_card(id);
#endif
+#endif
+
if (!cards) {
#ifdef MODULE
-#ifndef CONFIG_PCI
+#ifndef CONFIG_ISDN_DRV_EICON_PCI
#ifndef CONFIG_ISDN_DRV_EICON_ISA
printk(KERN_INFO "Eicon: Driver is neither ISA nor PCI compiled !\n");
+ printk(KERN_INFO "Eicon: Driver not loaded !\n");
#else
printk(KERN_INFO "Eicon: No cards defined, driver not loaded !\n");
#endif
@@ -1451,17 +1375,34 @@
} else
printk(KERN_INFO "Eicon: %d card%s added\n", card_count,
(card_count>1)?"s":"");
- /* No symbols to export, hide all symbols */
- EXPORT_NO_SYMBOLS;
return 0;
}
-#ifdef MODULE
-void
-cleanup_module(void)
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
+void DIVA_DIDD_Write(DESCRIPTOR *, int);
+EXPORT_SYMBOL_NOVERS(DIVA_DIDD_Read);
+EXPORT_SYMBOL_NOVERS(DIVA_DIDD_Write);
+EXPORT_SYMBOL_NOVERS(DivasPrintf);
+#else
+int DivasCardNext;
+card_t DivasCards[1];
+#endif
+
+static void
+eicon_exit(void)
{
+#if CONFIG_PCI
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
+ card_t *pCard;
+ word wCardIndex;
+ extern int Divas_major;
+ int iTmp = 0;
+#endif
+#endif
+
eicon_card *card = cards;
eicon_card *last;
+
while (card) {
#ifdef CONFIG_ISDN_DRV_EICON_ISA
#ifdef CONFIG_MCA
@@ -1481,10 +1422,58 @@
card = card->next;
eicon_freecard(last);
}
+
+#if CONFIG_PCI
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
+ pCard = DivasCards;
+ for (wCardIndex = 0; wCardIndex < MAX_CARDS; wCardIndex++)
+ {
+ if ((pCard->hw) && (pCard->hw->in_use))
+ {
+ (*pCard->card_reset)(pCard);
+
+ UxIsrRemove(pCard->hw, pCard);
+ UxCardHandleFree(pCard->hw);
+
+ if(pCard->e_tbl != NULL)
+ {
+ kfree(pCard->e_tbl);
+ }
+
+ if(pCard->hw->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
+ {
+ release_region(pCard->hw->io_base,0x20);
+ release_region(pCard->hw->reset_base,0x80);
+ }
+
+ // If this is a 4BRI ...
+ if (pCard->hw->card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
+ {
+ // Skip over the next 3 virtual adapters
+ wCardIndex += 3;
+
+ // But free their handles
+ for (iTmp = 0; iTmp < 3; iTmp++)
+ {
+ pCard++;
+ UxCardHandleFree(pCard->hw);
+
+ if(pCard->e_tbl != NULL)
+ {
+ kfree(pCard->e_tbl);
+ }
+ }
+ }
+ }
+ pCard++;
+ }
+ unregister_chrdev(Divas_major, "Divas");
+#endif
+#endif /* CONFIG_PCI */
printk(KERN_INFO "%s unloaded\n", DRIVERNAME);
}
-#else /* no module */
+#ifndef MODULE
void
eicon_setup(char *str, int *ints)
@@ -1669,7 +1658,7 @@
return ENODEV;
};
/* matching membase & irq */
- if ( 1 == eicon_addcard(type, membase, irq, id)) {
+ if ( 1 == eicon_addcard(type, membase, irq, id, 0)) {
mca_set_adapter_name(slot, eicon_mca_adapters[a_idx].name);
mca_set_adapter_procfn(slot, (MCA_ProcFn) eicon_info, cards);
@@ -1691,3 +1680,5 @@
#endif /* CONFIG_MCA */
#endif /* CONFIG_ISDN_DRV_EICON_ISA */
+module_init(eicon_init);
+module_exit(eicon_exit);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)