summaryrefslogtreecommitdiffstats
path: root/drivers/isdn
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/isdn')
-rw-r--r--drivers/isdn/Config.in15
-rw-r--r--drivers/isdn/Makefile13
-rw-r--r--drivers/isdn/act2000/act2000.h12
-rw-r--r--drivers/isdn/act2000/act2000_isa.c15
-rw-r--r--drivers/isdn/act2000/act2000_isa.h7
-rw-r--r--drivers/isdn/act2000/capi.c7
-rw-r--r--drivers/isdn/act2000/capi.h7
-rw-r--r--drivers/isdn/act2000/module.c34
-rw-r--r--drivers/isdn/avmb1/b1capi.c184
-rw-r--r--drivers/isdn/avmb1/b1lli.c429
-rw-r--r--drivers/isdn/avmb1/b1pci.c27
-rw-r--r--drivers/isdn/avmb1/capi.c31
-rw-r--r--drivers/isdn/avmb1/capidev.h4
-rw-r--r--drivers/isdn/avmb1/capidrv.c382
-rw-r--r--drivers/isdn/avmb1/capidrv.h73
-rw-r--r--drivers/isdn/avmb1/compat.h6
-rw-r--r--drivers/isdn/hisax/Makefile48
-rw-r--r--drivers/isdn/hisax/arcofi.c49
-rw-r--r--drivers/isdn/hisax/arcofi.h11
-rw-r--r--drivers/isdn/hisax/asuscom.c180
-rw-r--r--drivers/isdn/hisax/avm_a1.c31
-rw-r--r--drivers/isdn/hisax/callc.c1426
-rw-r--r--drivers/isdn/hisax/config.c1038
-rw-r--r--drivers/isdn/hisax/diva.c316
-rw-r--r--drivers/isdn/hisax/elsa.c423
-rw-r--r--drivers/isdn/hisax/fsm.c115
-rw-r--r--drivers/isdn/hisax/hfc_2bds0.c354
-rw-r--r--drivers/isdn/hisax/hfc_2bs0.c178
-rw-r--r--drivers/isdn/hisax/hisax.h512
-rw-r--r--drivers/isdn/hisax/hscx.c205
-rw-r--r--drivers/isdn/hisax/hscx.h6
-rw-r--r--drivers/isdn/hisax/hscx_irq.c134
-rw-r--r--drivers/isdn/hisax/ipac.h6
-rw-r--r--drivers/isdn/hisax/isac.c307
-rw-r--r--drivers/isdn/hisax/isac.h12
-rw-r--r--drivers/isdn/hisax/isdnl1.c1094
-rw-r--r--drivers/isdn/hisax/isdnl1.h34
-rw-r--r--drivers/isdn/hisax/isdnl2.c472
-rw-r--r--drivers/isdn/hisax/isdnl3.c244
-rw-r--r--drivers/isdn/hisax/isdnl3.h19
-rw-r--r--drivers/isdn/hisax/ix1_micro.c12
-rw-r--r--drivers/isdn/hisax/l3_1tr6.c332
-rw-r--r--drivers/isdn/hisax/l3_1tr6.h6
-rw-r--r--drivers/isdn/hisax/l3dss1.c1319
-rw-r--r--drivers/isdn/hisax/l3dss1.h9
-rw-r--r--drivers/isdn/hisax/lmgr.c30
-rw-r--r--drivers/isdn/hisax/mic.c12
-rw-r--r--drivers/isdn/hisax/netjet.c421
-rw-r--r--drivers/isdn/hisax/niccy.c121
-rw-r--r--drivers/isdn/hisax/q931.c134
-rw-r--r--drivers/isdn/hisax/rawhdlc.c2
-rw-r--r--drivers/isdn/hisax/sedlbauer.c546
-rw-r--r--drivers/isdn/hisax/sportster.c16
-rw-r--r--drivers/isdn/hisax/tei.c206
-rw-r--r--drivers/isdn/hisax/teleint.c67
-rw-r--r--drivers/isdn/hisax/teles0.c41
-rw-r--r--drivers/isdn/hisax/teles3.c40
-rw-r--r--drivers/isdn/hisax/teles3c.c30
-rw-r--r--drivers/isdn/icn/icn.c72
-rw-r--r--drivers/isdn/icn/icn.h4
-rw-r--r--drivers/isdn/isdn_audio.c107
-rw-r--r--drivers/isdn/isdn_audio.h18
-rw-r--r--drivers/isdn/isdn_cards.c17
-rw-r--r--drivers/isdn/isdn_cards.h7
-rw-r--r--drivers/isdn/isdn_common.c762
-rw-r--r--drivers/isdn/isdn_common.h43
-rw-r--r--drivers/isdn/isdn_concap.c24
-rw-r--r--drivers/isdn/isdn_net.c553
-rw-r--r--drivers/isdn/isdn_net.h16
-rw-r--r--drivers/isdn/isdn_ppp.c1081
-rw-r--r--drivers/isdn/isdn_ppp.h8
-rw-r--r--drivers/isdn/isdn_tty.c676
-rw-r--r--drivers/isdn/isdn_tty.h24
-rw-r--r--drivers/isdn/isdn_x25iface.c20
-rw-r--r--drivers/isdn/isdnloop/isdnloop.c20
-rw-r--r--drivers/isdn/isdnloop/isdnloop.h5
-rw-r--r--drivers/isdn/pcbit/callbacks.c27
-rw-r--r--drivers/isdn/pcbit/drv.c3
-rw-r--r--drivers/isdn/pcbit/pcbit.h4
-rw-r--r--drivers/isdn/sc/message.c2
80 files changed, 9901 insertions, 5396 deletions
diff --git a/drivers/isdn/Config.in b/drivers/isdn/Config.in
index df610b5b5..52e3acbdb 100644
--- a/drivers/isdn/Config.in
+++ b/drivers/isdn/Config.in
@@ -19,34 +19,39 @@ dep_tristate 'HiSax SiemensChipSet driver support' CONFIG_ISDN_DRV_HISAX $CONFIG
if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
bool 'HiSax Support for EURO/DSS1' CONFIG_HISAX_EURO
if [ "$CONFIG_HISAX_EURO" != "n" ]; then
- bool 'Support for german tarifinfo' CONFIG_DE_AOC
- bool 'Support for australian Microlink service (not for std. EURO)' CONFIG_HISAX_ML
+ bool 'Support for german chargeinfo' CONFIG_DE_AOC
+ bool 'Disable sending complete' CONFIG_HISAX_NO_SENDCOMPLETE
+ bool 'Disable sending low layer compatibility' CONFIG_HISAX_NO_LLC
fi
bool 'HiSax Support for german 1TR6' CONFIG_HISAX_1TR6
bool 'HiSax Support for Teles 16.0/8.0' CONFIG_HISAX_16_0
bool 'HiSax Support for Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
bool 'HiSax Support for Teles 16.3c' CONFIG_HISAX_TELES3C
+ bool 'HiSax Support for Teles PCI' CONFIG_HISAX_TELESPCI
+ bool 'HiSax Support for Teles S0Box' CONFIG_HISAX_S0BOX
bool 'HiSax Support for AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1
+ bool 'HiSax Support for AVM PnP/PCI (Fritz!PnP/PCI)' CONFIG_HISAX_FRITZPCI
+ bool 'HiSax Support for AVM A1 PCMCIA (Fritz)' CONFIG_HISAX_AVM_A1_PCMCIA
bool 'HiSax Support for Elsa cards' CONFIG_HISAX_ELSA
bool 'HiSax Support for ITK ix1-micro Revision 2' CONFIG_HISAX_IX1MICROR2
bool 'HiSax Support for Eicon.Diehl Diva cards' CONFIG_HISAX_DIEHLDIVA
bool 'HiSax Support for ASUSCOM cards' CONFIG_HISAX_ASUSCOM
bool 'HiSax Support for TELEINT cards' CONFIG_HISAX_TELEINT
- bool 'HiSax Support for Sedlbauer speed card/win/star' CONFIG_HISAX_SEDLBAUER
+ bool 'HiSax Support for Sedlbauer speed card/win/star/fax' CONFIG_HISAX_SEDLBAUER
bool 'HiSax Support for USR Sportster internal TA' CONFIG_HISAX_SPORTSTER
bool 'HiSax Support for MIC card' CONFIG_HISAX_MIC
bool 'HiSax Support for NETjet card' CONFIG_HISAX_NETJET
bool 'HiSax Support for Niccy PnP/PCI card' CONFIG_HISAX_NICCY
if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
- bool 'HiSax Support for SPARC Am7930' CONFIG_HISAX_AMD7930
- bool 'HiSax Support for SPARC DBRI' CONFIG_HISAX_DBRI
+ bool 'HiSax Support for Am7930' CONFIG_HISAX_AMD7930
fi
fi
fi
if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
dep_tristate 'Spellcaster support (EXPERIMENTAL)' CONFIG_ISDN_DRV_SC $CONFIG_ISDN
dep_tristate 'IBM Active 2000 support (EXPERIMENTAL)' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN
+ dep_tristate 'Eicon.Diehl active card support (EXPERIMENTAL)' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN
fi
dep_tristate 'AVM-B1 with CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN
if [ "$CONFIG_ISDN_DRV_AVMB1" != "n" ]; then
diff --git a/drivers/isdn/Makefile b/drivers/isdn/Makefile
index 35d56d142..36a1f5bb7 100644
--- a/drivers/isdn/Makefile
+++ b/drivers/isdn/Makefile
@@ -1,6 +1,6 @@
SUB_DIRS :=
MOD_SUB_DIRS :=
-ALL_SUB_DIRS := icn pcbit hisax avmb1 act2000
+ALL_SUB_DIRS := icn pcbit hisax avmb1 act2000 eicon
L_OBJS :=
LX_OBJS :=
@@ -33,6 +33,7 @@ else
OX_OBJS += isdn_common.o
ifdef CONFIG_ISDN_PPP
O_OBJS += isdn_ppp.o
+ M_OBJS += isdn_bsdcomp.o
endif
ifdef CONFIG_ISDN_X25
O_OBJS += isdn_x25iface.o
@@ -114,5 +115,15 @@ else
endif
endif
+ifeq ($(CONFIG_ISDN_DRV_EICON),y)
+ L_OBJS += eicon/eicon.o
+ SUB_DIRS += eicon
+ MOD_SUB_DIRS += eicon
+else
+ ifeq ($(CONFIG_ISDN_DRV_EICON),m)
+ MOD_SUB_DIRS += eicon
+ endif
+endif
+
include $(TOPDIR)/Rules.make
diff --git a/drivers/isdn/act2000/act2000.h b/drivers/isdn/act2000/act2000.h
index 129888258..5d35a12ec 100644
--- a/drivers/isdn/act2000/act2000.h
+++ b/drivers/isdn/act2000/act2000.h
@@ -1,8 +1,8 @@
-/* $Id: act2000.h,v 1.5 1997/10/09 22:22:59 fritz Exp $
+/* $Id: act2000.h,v 1.7 1999/04/12 13:13:54 fritz Exp $
*
* ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
*
- * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
* Thanks to Friedemann Baitinger and IBM Germany
*
* This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,12 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: act2000.h,v $
+ * Revision 1.7 1999/04/12 13:13:54 fritz
+ * Made cards pointer static to avoid name-clash.
+ *
+ * Revision 1.6 1998/11/05 22:12:38 fritz
+ * Changed mail-address.
+ *
* Revision 1.5 1997/10/09 22:22:59 fritz
* New HL<->LL interface:
* New BSENT callback with nr. of bytes included.
@@ -213,8 +219,6 @@ typedef struct act2000_card {
char regname[35]; /* Name used for request_region */
} act2000_card;
-extern act2000_card *actcards;
-
extern __inline__ void act2000_schedule_tx(act2000_card *card)
{
queue_task(&card->snd_tq, &tq_immediate);
diff --git a/drivers/isdn/act2000/act2000_isa.c b/drivers/isdn/act2000/act2000_isa.c
index d19ff99e4..80f06b080 100644
--- a/drivers/isdn/act2000/act2000_isa.c
+++ b/drivers/isdn/act2000/act2000_isa.c
@@ -1,8 +1,8 @@
-/* $Id: act2000_isa.c,v 1.5 1998/02/12 23:06:47 keil Exp $
+/* $Id: act2000_isa.c,v 1.8 1999/01/05 18:29:25 he Exp $
*
* ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
*
- * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
* Thanks to Friedemann Baitinger and IBM Germany
*
* This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,17 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: act2000_isa.c,v $
+ * Revision 1.8 1999/01/05 18:29:25 he
+ * merged remaining schedule_timeout() changes from 2.1.127
+ *
+ * Revision 1.7 1998/11/05 22:12:41 fritz
+ * Changed mail-address.
+ *
+ * Revision 1.6 1998/06/17 19:51:09 he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
* Revision 1.5 1998/02/12 23:06:47 keil
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
diff --git a/drivers/isdn/act2000/act2000_isa.h b/drivers/isdn/act2000/act2000_isa.h
index b7c01ee2b..35a68e7d2 100644
--- a/drivers/isdn/act2000/act2000_isa.h
+++ b/drivers/isdn/act2000/act2000_isa.h
@@ -1,8 +1,8 @@
-/* $Id: act2000_isa.h,v 1.1 1997/09/23 18:00:07 fritz Exp $
+/* $Id: act2000_isa.h,v 1.2 1998/11/05 22:12:43 fritz Exp $
*
* ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
*
- * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
* Thanks to Friedemann Baitinger and IBM Germany
*
* This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: act2000_isa.h,v $
+ * Revision 1.2 1998/11/05 22:12:43 fritz
+ * Changed mail-address.
+ *
* Revision 1.1 1997/09/23 18:00:07 fritz
* New driver for IBM Active 2000.
*
diff --git a/drivers/isdn/act2000/capi.c b/drivers/isdn/act2000/capi.c
index d0310bcc0..df2fd68d3 100644
--- a/drivers/isdn/act2000/capi.c
+++ b/drivers/isdn/act2000/capi.c
@@ -1,9 +1,9 @@
-/* $Id: capi.c,v 1.7 1998/02/23 23:35:41 fritz Exp $
+/* $Id: capi.c,v 1.8 1998/11/05 22:12:46 fritz Exp $
*
* ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
* CAPI encoder/decoder
*
- * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
* Thanks to Friedemann Baitinger and IBM Germany
*
* This program is free software; you can redistribute it and/or modify
@@ -21,6 +21,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: capi.c,v $
+ * Revision 1.8 1998/11/05 22:12:46 fritz
+ * Changed mail-address.
+ *
* Revision 1.7 1998/02/23 23:35:41 fritz
* Eliminated some compiler warnings.
*
diff --git a/drivers/isdn/act2000/capi.h b/drivers/isdn/act2000/capi.h
index 901f15ed4..69a104100 100644
--- a/drivers/isdn/act2000/capi.h
+++ b/drivers/isdn/act2000/capi.h
@@ -1,8 +1,8 @@
-/* $Id: capi.h,v 1.4 1997/10/01 09:21:04 fritz Exp $
+/* $Id: capi.h,v 1.5 1998/11/05 22:12:48 fritz Exp $
*
* ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
*
- * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
* Thanks to Friedemann Baitinger and IBM Germany
*
* This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: capi.h,v $
+ * Revision 1.5 1998/11/05 22:12:48 fritz
+ * Changed mail-address.
+ *
* Revision 1.4 1997/10/01 09:21:04 fritz
* Removed old compatibility stuff for 2.0.X kernels.
* From now on, this code is for 2.1.X ONLY!
diff --git a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c
index 34a3be1d7..2ec5e2fd4 100644
--- a/drivers/isdn/act2000/module.c
+++ b/drivers/isdn/act2000/module.c
@@ -1,8 +1,8 @@
-/* $Id: module.c,v 1.7 1998/02/12 23:06:52 keil Exp $
+/* $Id: module.c,v 1.9 1999/04/12 13:13:56 fritz Exp $
*
* ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
*
- * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
* Thanks to Friedemann Baitinger and IBM Germany
*
* This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,12 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: module.c,v $
+ * Revision 1.9 1999/04/12 13:13:56 fritz
+ * Made cards pointer static to avoid name-clash.
+ *
+ * Revision 1.8 1998/11/05 22:12:51 fritz
+ * Changed mail-address.
+ *
* Revision 1.7 1998/02/12 23:06:52 keil
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
@@ -57,7 +63,7 @@ static unsigned short isa_ports[] =
};
#define ISA_NRPORTS (sizeof(isa_ports)/sizeof(unsigned short))
-act2000_card *actcards = (act2000_card *) NULL;
+static act2000_card *cards = (act2000_card *) NULL;
/* Parameters to be set by insmod */
static int act_bus = 0;
@@ -589,7 +595,7 @@ act2000_logstat(struct act2000_card *card, char *str)
static inline act2000_card *
act2000_findcard(int driverid)
{
- act2000_card *p = actcards;
+ act2000_card *p = cards;
while (p) {
if (p->myid == driverid)
@@ -714,8 +720,8 @@ act2000_alloccard(int bus, int port, int irq, char *id)
card->bus = bus;
card->port = port;
card->irq = irq;
- card->next = actcards;
- actcards = card;
+ card->next = cards;
+ cards = card;
}
/*
@@ -805,9 +811,9 @@ act2000_addcard(int bus, int port, int irq, char *id)
bus);
}
}
- if (!actcards)
+ if (!cards)
return 1;
- p = actcards;
+ p = cards;
while (p) {
initialized = 0;
if (!p->interface.statcallb) {
@@ -870,9 +876,9 @@ act2000_addcard(int bus, int port, int irq, char *id)
kfree(p);
p = q->next;
} else {
- actcards = p->next;
+ cards = p->next;
kfree(p);
- p = actcards;
+ p = cards;
}
failed++;
}
@@ -890,9 +896,9 @@ int
act2000_init(void)
{
printk(KERN_INFO "%s\n", DRIVERNAME);
- if (!actcards)
+ if (!cards)
act2000_addcard(act_bus, act_port, act_irq, act_id);
- if (!actcards)
+ if (!cards)
printk(KERN_INFO "act2000: No cards defined yet\n");
/* No symbols to export, hide all symbols */
EXPORT_NO_SYMBOLS;
@@ -903,14 +909,14 @@ act2000_init(void)
void
cleanup_module(void)
{
- act2000_card *card = actcards;
+ act2000_card *card = cards;
act2000_card *last;
while (card) {
unregister_card(card);
del_timer(&card->ptimer);
card = card->next;
}
- card = actcards;
+ card = cards;
while (card) {
last = card;
card = card->next;
diff --git a/drivers/isdn/avmb1/b1capi.c b/drivers/isdn/avmb1/b1capi.c
index dbf3606f4..ea4aeb369 100644
--- a/drivers/isdn/avmb1/b1capi.c
+++ b/drivers/isdn/avmb1/b1capi.c
@@ -1,11 +1,49 @@
/*
- * $Id: b1capi.c,v 1.10 1998/02/13 07:09:10 calle Exp $
+ * $Id: b1capi.c,v 1.14 1999/04/15 19:49:29 calle Exp $
*
* CAPI 2.0 Module for AVM B1-card.
*
* (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: b1capi.c,v $
+ * Revision 1.14 1999/04/15 19:49:29 calle
+ * fix fuer die B1-PCI. Jetzt geht z.B. auch IRQ 17 ...
+ *
+ * Revision 1.13 1999/01/05 18:29:31 he
+ * merged remaining schedule_timeout() changes from 2.1.127
+ *
+ * Revision 1.12 1998/10/25 14:38:58 fritz
+ * Backported from MIPS (Cobalt).
+ *
+ * Revision 1.11 1998/03/29 16:05:58 calle
+ * changes from 2.0 tree merged.
+ *
+ * Revision 1.4.2.18 1998/03/20 20:34:37 calle
+ * port valid check now only for T1, because of the PCI and PCMCIA cards.
+ *
+ * Revision 1.4.2.17 1998/03/20 14:38:17 calle
+ * capidrv: prepared state machines for suspend/resume/hold
+ * capidrv: fix bug in state machine if B1/T1 is out of nccis
+ * b1capi: changed some errno returns.
+ * b1capi: detect if you try to add same T1 to different io address.
+ * b1capi: change number of nccis depending on number of channels.
+ * b1lli: cosmetics
+ *
+ * Revision 1.4.2.16 1998/03/20 09:01:08 calle
+ * Changes capi_register handling to get full support for 30 bchannels.
+ *
+ * Revision 1.4.2.15 1998/03/18 17:43:26 calle
+ * T1 with fastlink, bugfix for multicontroller support in capidrv.c
+ *
+ * Revision 1.4.2.14 1998/03/04 17:33:47 calle
+ * Changes for T1.
+ *
+ * Revision 1.4.2.13 1998/02/27 15:40:41 calle
+ * T1 running with slow link. bugfix in capi_release.
+ *
+ * Revision 1.4.2.12 1998/02/24 17:58:25 calle
+ * changes for T1.
+ *
* Revision 1.10 1998/02/13 07:09:10 calle
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
@@ -76,7 +114,7 @@
#include "capicmd.h"
#include "capiutil.h"
-static char *revision = "$Revision: 1.10 $";
+static char *revision = "$Revision: 1.14 $";
/* ------------------------------------------------------------- */
@@ -84,7 +122,7 @@ int showcapimsgs = 0; /* used in lli.c */
int loaddebug = 0;
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
-MODULE_PARM(showcapimsgs, "0-3i");
+MODULE_PARM(showcapimsgs, "0-5i");
MODULE_PARM(loaddebug, "0-1i");
/* ------------------------------------------------------------- */
@@ -150,10 +188,11 @@ static char *cardtype2str(int cardtype)
{
switch (cardtype) {
default:
- case AVM_CARDTYPE_B1: return "B1";
- case AVM_CARDTYPE_M1: return "M1";
- case AVM_CARDTYPE_M2: return "M2";
- case AVM_CARDTYPE_T1: return "T1";
+ case AVM_CARDTYPE_B1: return "B1-ISA";
+ case AVM_CARDTYPE_B1PCI: return "B1-PCI";
+ case AVM_CARDTYPE_M1: return "M1";
+ case AVM_CARDTYPE_M2: return "M2";
+ case AVM_CARDTYPE_T1: return "T1";
}
}
@@ -300,7 +339,7 @@ void avmb1_handle_free_ncci(avmb1_card * card,
}
}
APPL(appl)->releasing--;
- if (APPL(appl)->releasing == 0) {
+ if (APPL(appl)->releasing <= 0) {
APPL(appl)->signal = 0;
APPL_MARK_FREE(appl);
printk(KERN_INFO "b1capi: appl %d down\n", appl);
@@ -433,6 +472,7 @@ static void notify_handler(void *dummy)
/* -------- card ready callback ------------------------------- */
+
void avmb1_card_ready(avmb1_card * card)
{
struct capi_profile *profp =
@@ -441,6 +481,7 @@ void avmb1_card_ready(avmb1_card * card)
__u16 appl;
char *cardname, cname[20];
__u32 flag;
+ int nbchan = profp->nbchannel;
card->cversion.majorversion = 2;
card->cversion.minorversion = 0;
@@ -453,9 +494,14 @@ void avmb1_card_ready(avmb1_card * card)
for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
if (VALID_APPLID(appl) && !APPL(appl)->releasing) {
+ int nconn, want = APPL(appl)->rparam.level3cnt;
+
+ if (want > 0) nconn = want;
+ else nconn = nbchan * -want;
+ if (nconn == 0) nconn = nbchan;
+
B1_send_register(card->port, appl,
- 1024 * (APPL(appl)->rparam.level3cnt+1),
- APPL(appl)->rparam.level3cnt,
+ 1024 * (nconn+1), nconn,
APPL(appl)->rparam.datablkcnt,
APPL(appl)->rparam.datablklen);
}
@@ -553,8 +599,8 @@ int avmb1_registercard(int port, int irq, int cardtype, int allocio)
SA_SHIRQ, card->name, card)) != 0) {
printk(KERN_ERR "b1capi: unable to get IRQ %d (irqval=%d).\n",
irq, irqval);
- release_region((unsigned short) port, AVMB1_PORTLEN);
- return -EIO;
+ release_region(port, AVMB1_PORTLEN);
+ return -EBUSY;
}
card->cardstate = CARD_DETECTED;
@@ -578,8 +624,14 @@ int avmb1_detectcard(int port, int irq, int cardtype)
if (!B1_valid_irq(irq, cardtype)) {
printk(KERN_WARNING "b1capi: irq %d not valid for %s-card.\n",
irq, cardtype2str(cardtype));
- return -EIO;
+ return -EINVAL;
+ }
+ if (!B1_valid_port(port, cardtype)) {
+ printk(KERN_WARNING "b1capi: port 0x%x not valid for %s-card.\n",
+ port, cardtype2str(cardtype));
+ return -EINVAL;
}
+ B1_reset(port);
if ((rc = B1_detect(port, cardtype)) != 0) {
printk(KERN_NOTICE "b1capi: NO %s-card at 0x%x (%d)\n",
cardtype2str(cardtype), port, rc);
@@ -591,10 +643,10 @@ int avmb1_detectcard(int port, int irq, int cardtype)
case AVM_CARDTYPE_M1:
case AVM_CARDTYPE_M2:
case AVM_CARDTYPE_B1:
+ case AVM_CARDTYPE_B1PCI:
printk(KERN_NOTICE "b1capi: AVM-%s-Controller detected at 0x%x\n", cardtype2str(cardtype), port);
break;
case AVM_CARDTYPE_T1:
- printk(KERN_NOTICE "b1capi: AVM-%s-Controller may be at 0x%x\n", cardtype2str(cardtype), port);
break;
}
@@ -603,11 +655,11 @@ int avmb1_detectcard(int port, int irq, int cardtype)
int avmb1_probecard(int port, int irq, int cardtype)
{
- if (check_region((unsigned short) port, AVMB1_PORTLEN)) {
+ if (check_region(port, AVMB1_PORTLEN)) {
printk(KERN_WARNING
"b1capi: ports 0x%03x-0x%03x in use.\n",
port, port + AVMB1_PORTLEN);
- return -EIO;
+ return -EBUSY;
}
return avmb1_detectcard(port, irq, cardtype);
}
@@ -618,11 +670,16 @@ int avmb1_unregistercard(int cnr, int freeio)
if (!VALID_CARD(cnr))
return -ESRCH;
card = CARD(cnr);
+
if (card->cardstate == CARD_FREE)
return -ESRCH;
if (card->cardstate == CARD_RUNNING)
avmb1_card_down(card, freeio);
+ if (card->cardstate != CARD_FREE)
+ if (card->cardtype == AVM_CARDTYPE_T1)
+ T1_reset(card->port);
+
free_irq(card->irq, card);
if (freeio)
release_region(card->port, AVMB1_PORTLEN);
@@ -667,6 +724,7 @@ static int capi_installed(void)
static __u16 capi_register(capi_register_params * rparam, __u16 * applidp)
{
+ int nconn, want = rparam->level3cnt;
int i;
int appl;
@@ -686,13 +744,20 @@ static __u16 capi_register(capi_register_params * rparam, __u16 * applidp)
memcpy(&APPL(appl)->rparam, rparam, sizeof(capi_register_params));
for (i = 0; i < CAPI_MAXCONTR; i++) {
+ struct capi_profile *profp =
+ (struct capi_profile *)cards[i].version[VER_PROFILE];
+
if (cards[i].cardstate != CARD_RUNNING)
continue;
+
+ if (want > 0) nconn = want;
+ else nconn = profp->nbchannel * -want;
+ if (nconn == 0) nconn = profp->nbchannel;
+
B1_send_register(cards[i].port, appl,
- 1024 * (APPL(appl)->rparam.level3cnt + 1),
- APPL(appl)->rparam.level3cnt,
- APPL(appl)->rparam.datablkcnt,
- APPL(appl)->rparam.datablklen);
+ 1024 * (nconn+1), nconn,
+ APPL(appl)->rparam.datablkcnt,
+ APPL(appl)->rparam.datablklen);
}
*applidp = appl;
printk(KERN_INFO "b1capi: appl %d up\n", appl);
@@ -705,8 +770,6 @@ static __u16 capi_release(__u16 applid)
struct sk_buff *skb;
int i;
- if (ncards == 0)
- return CAPI_REGNOTINSTALLED;
if (!VALID_APPLID(applid) || APPL(applid)->releasing)
return CAPI_ILLAPPNR;
while ((skb = skb_dequeue(&APPL(applid)->recv_queue)) != 0)
@@ -718,7 +781,7 @@ static __u16 capi_release(__u16 applid)
APPL(applid)->releasing++;
B1_send_release(cards[i].port, applid);
}
- if (APPL(applid)->releasing == 0) {
+ if (APPL(applid)->releasing <= 0) {
APPL(applid)->signal = 0;
APPL_MARK_FREE(applid);
printk(KERN_INFO "b1capi: appl %d down\n", applid);
@@ -863,7 +926,43 @@ static int capi_manufacturer(unsigned int cmd, void *data)
if ((rc = avmb1_probecard(cdef.port, cdef.irq, cdef.cardtype)) != 0)
return rc;
- return avmb1_addcard(cdef.port, cdef.irq, cdef.cardtype);
+ if (cdef.cardtype == AVM_CARDTYPE_T1) {
+ int i;
+ for (i=0; i < CAPI_MAXCONTR; i++) {
+ if ( cards[i].cardstate != CARD_FREE
+ && cards[i].cardtype == AVM_CARDTYPE_T1
+ && cards[i].cardnr == cdef.cardnr) {
+ printk(KERN_ERR
+ "b1capi: T1-HEMA-card-%d already at 0x%x\n",
+ cdef.cardnr, cards[i].port);
+ return -EBUSY;
+ }
+ }
+ rc = T1_detectandinit(cdef.port,cdef.irq,cdef.cardnr);
+ if (rc) {
+ printk(KERN_NOTICE "b1capi: NO T1-HEMA-card-%d at 0x%x (%d)\n",
+ cdef.cardnr, cdef.port, rc);
+ return -EIO;
+ }
+ printk(KERN_NOTICE "b1capi: T1-HEMA-card-%d at 0x%x\n",
+ cdef.cardnr, cdef.port);
+ }
+
+ rc = avmb1_addcard(cdef.port, cdef.irq, cdef.cardtype);
+ if (rc < 0)
+ return rc;
+ /* don't want to change interface t
+ addcard/probecard/registercard */
+ if (cdef.cardtype == AVM_CARDTYPE_T1) {
+ int i;
+ for (i=0; i < CAPI_MAXCONTR; i++) {
+ if (cards[i].cnr == rc) {
+ cards[i].cardnr = cdef.cardnr;
+ break;
+ }
+ }
+ }
+ return rc;
case AVMB1_LOAD:
case AVMB1_LOAD_AND_CONFIG:
@@ -883,8 +982,7 @@ static int capi_manufacturer(unsigned int cmd, void *data)
return -ESRCH;
if (ldef.t4file.len <= 0) {
- if (loaddebug)
- printk(KERN_DEBUG "b1capi: load: invalid parameter length of t4file is %d ?\n", ldef.t4file.len);
+ printk(KERN_DEBUG "b1capi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len);
return -EINVAL;
}
@@ -906,12 +1004,19 @@ static int capi_manufacturer(unsigned int cmd, void *data)
}
B1_reset(card->port);
+
+ if (loaddebug) {
+ printk(KERN_DEBUG "b1capi: loading contr %d\n",
+ ldef.contr);
+ }
+
if ((rc = B1_load_t4file(card->port, &ldef.t4file))) {
B1_reset(card->port);
printk(KERN_ERR "b1capi: failed to load t4file!!\n");
card->cardstate = CARD_DETECTED;
return rc;
}
+
B1_disable_irq(card->port);
if (ldef.t4config.len > 0) { /* load config */
@@ -944,8 +1049,7 @@ static int capi_manufacturer(unsigned int cmd, void *data)
card->cardstate = CARD_INITSTATE;
save_flags(flags);
cli();
- B1_assign_irq(card->port, card->irq, card->cardtype);
- B1_enable_irq(card->port);
+ B1_setinterrupt(card->port, card->irq, card->cardtype);
restore_flags(flags);
if (loaddebug) {
@@ -956,7 +1060,14 @@ static int capi_manufacturer(unsigned int cmd, void *data)
/*
* init card
*/
- B1_send_init(card->port, AVM_NAPPS, AVM_NNCCI, card->cnr - 1);
+ if (card->cardtype == AVM_CARDTYPE_T1)
+ B1_send_init(card->port, AVM_NAPPS,
+ AVM_NNCCI_PER_CHANNEL*30,
+ card->cnr - 1);
+ else
+ B1_send_init(card->port, AVM_NAPPS,
+ AVM_NNCCI_PER_CHANNEL*2,
+ card->cnr - 1);
if (loaddebug) {
printk(KERN_DEBUG "b1capi: load: waiting for init reply contr %d\n",
@@ -998,6 +1109,19 @@ static int capi_manufacturer(unsigned int cmd, void *data)
return rc;
return 0;
+ case AVMB1_REMOVECARD:
+ if ((rc = copy_from_user((void *) &rdef, data,
+ sizeof(avmb1_resetdef))))
+ return rc;
+ if (!VALID_CARD(rdef.contr))
+ return -ESRCH;
+
+ card = CARD(rdef.contr);
+
+ if (card->cardstate != CARD_DETECTED)
+ return -EBUSY;
+
+ return avmb1_unregistercard(rdef.contr, 1);
}
return -EINVAL;
}
@@ -1035,6 +1159,7 @@ struct capi_interface *attach_capi_interface(struct capi_interface_user *userp)
userp->next = capi_users;
capi_users = userp;
MOD_INC_USE_COUNT;
+ printk(KERN_NOTICE "b1capi: %s attached\n", userp->name);
return &avmb1_interface;
}
@@ -1048,6 +1173,7 @@ int detach_capi_interface(struct capi_interface_user *userp)
*pp = userp->next;
userp->next = 0;
MOD_DEC_USE_COUNT;
+ printk(KERN_NOTICE "b1capi: %s detached\n", userp->name);
return 0;
}
}
diff --git a/drivers/isdn/avmb1/b1lli.c b/drivers/isdn/avmb1/b1lli.c
index db6fe1453..4d9fd647c 100644
--- a/drivers/isdn/avmb1/b1lli.c
+++ b/drivers/isdn/avmb1/b1lli.c
@@ -1,11 +1,46 @@
/*
- * $Id: b1lli.c,v 1.6 1998/02/13 07:09:11 calle Exp $
+ * $Id: b1lli.c,v 1.10 1999/04/15 19:49:31 calle Exp $
*
* ISDN lowlevel-module for AVM B1-card.
*
* (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: b1lli.c,v $
+ * Revision 1.10 1999/04/15 19:49:31 calle
+ * fix fuer die B1-PCI. Jetzt geht z.B. auch IRQ 17 ...
+ *
+ * Revision 1.9 1999/01/05 18:33:23 he
+ * merged remaining 2.2pre{1,2} changes (jiffies and Config)
+ *
+ * Revision 1.8 1998/10/25 14:39:00 fritz
+ * Backported from MIPS (Cobalt).
+ *
+ * Revision 1.7 1998/03/29 16:06:00 calle
+ * changes from 2.0 tree merged.
+ *
+ * Revision 1.1.2.10 1998/03/20 20:34:41 calle
+ * port valid check now only for T1, because of the PCI and PCMCIA cards.
+ *
+ * Revision 1.1.2.9 1998/03/20 14:38:20 calle
+ * capidrv: prepared state machines for suspend/resume/hold
+ * capidrv: fix bug in state machine if B1/T1 is out of nccis
+ * b1capi: changed some errno returns.
+ * b1capi: detect if you try to add same T1 to different io address.
+ * b1capi: change number of nccis depending on number of channels.
+ * b1lli: cosmetics
+ *
+ * Revision 1.1.2.8 1998/03/18 17:43:29 calle
+ * T1 with fastlink, bugfix for multicontroller support in capidrv.c
+ *
+ * Revision 1.1.2.7 1998/03/04 17:33:50 calle
+ * Changes for T1.
+ *
+ * Revision 1.1.2.6 1998/02/27 15:40:44 calle
+ * T1 running with slow link. bugfix in capi_release.
+ *
+ * Revision 1.1.2.5 1998/02/13 16:28:28 calle
+ * first step for T1
+ *
* Revision 1.6 1998/02/13 07:09:11 calle
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
@@ -41,6 +76,7 @@
*
*
*/
+/* #define FASTLINK_DEBUG */
#include <linux/kernel.h>
#include <linux/skbuff.h>
@@ -55,6 +91,8 @@
#include "capicmd.h"
#include "capiutil.h"
+extern int showcapimsgs;
+
/*
* LLI Messages to the ISDN-ControllerISDN Controller
*/
@@ -93,6 +131,8 @@
#define SEND_CONFIG 0x21 /*
*/
+#define SEND_POLLACK 0x73 /* T1 Watchdog */
+
/*
* LLI Messages from the ISDN-ControllerISDN Controller
*/
@@ -136,6 +176,10 @@
#define RECEIVE_RELEASE 0x26 /*
* int32 AppllID int32 0xffffffff
*/
+#define RECEIVE_TASK_READY 0x31 /*
+ * int32 tasknr
+ * int32 Length Taskname ...
+ */
#define WRITE_REGISTER 0x00
#define READ_REGISTER 0x01
@@ -150,14 +194,48 @@
#define B1_OUTSTAT 0x03
#define B1_RESET 0x10
#define B1_ANALYSE 0x04
-#define B1_IDENT 0x17 /* Hema card T1 */
-#define B1_IRQ_MASTER 0x12 /* Hema card T1 */
+
+/* Hema card T1 */
+
+#define T1_FASTLINK 0x00
+#define T1_SLOWLINK 0x08
+
+#define T1_READ B1_READ
+#define T1_WRITE B1_WRITE
+#define T1_INSTAT B1_INSTAT
+#define T1_OUTSTAT B1_OUTSTAT
+#define T1_IRQENABLE 0x05
+#define T1_FIFOSTAT 0x06
+#define T1_RESETLINK 0x10
+#define T1_ANALYSE 0x11
+#define T1_IRQMASTER 0x12
+#define T1_IDENT 0x17
+#define T1_RESETBOARD 0x1f
+
+#define T1F_IREADY 0x01
+#define T1F_IHALF 0x02
+#define T1F_IFULL 0x04
+#define T1F_IEMPTY 0x08
+#define T1F_IFLAGS 0xF0
+
+#define T1F_OREADY 0x10
+#define T1F_OHALF 0x20
+#define T1F_OEMPTY 0x40
+#define T1F_OFULL 0x80
+#define T1F_OFLAGS 0xF0
+
+/* there are HEMA cards with 1k and 4k FIFO out */
+#define FIFO_OUTBSIZE 256
+#define FIFO_INPBSIZE 512
+
+#define HEMA_VERSION_ID 0
+#define HEMA_PAL_ID 0
#define B1_STAT0(cardtype) ((cardtype) == AVM_CARDTYPE_M1 ? 0x81200000l : 0x80A00000l)
#define B1_STAT1(cardtype) (0x80E00000l)
-static inline unsigned char b1outp(unsigned short base,
+static inline unsigned char b1outp(unsigned int base,
unsigned short offset,
unsigned char value)
{
@@ -165,22 +243,44 @@ static inline unsigned char b1outp(unsigned short base,
return inb(base + B1_ANALYSE);
}
-static inline int B1_rx_full(unsigned short base)
+static inline void t1outp(unsigned int base,
+ unsigned short offset,
+ unsigned char value)
+{
+ outb(value, base + offset);
+}
+
+static inline unsigned char t1inp(unsigned int base,
+ unsigned short offset)
+{
+ return inb(base + offset);
+}
+
+static inline int B1_isfastlink(unsigned int base)
+{
+ return (inb(base + T1_IDENT) & ~0x82) == 1;
+}
+static inline unsigned char B1_fifostatus(unsigned int base)
+{
+ return inb(base + T1_FIFOSTAT);
+}
+
+static inline int B1_rx_full(unsigned int base)
{
return inb(base + B1_INSTAT) & 0x1;
}
-static inline unsigned char B1_get_byte(unsigned short base)
+static inline unsigned char B1_get_byte(unsigned int base)
{
- unsigned long i = jiffies + 5 * HZ; /* maximum wait time 5 sec */
+ unsigned long i = jiffies + 1 * HZ; /* maximum wait time 1 sec */
while (!B1_rx_full(base) && time_before(jiffies, i));
if (B1_rx_full(base))
return inb(base + B1_READ);
- printk(KERN_CRIT "b1lli: rx not full after 5 second\n");
+ printk(KERN_CRIT "b1lli(0x%x): rx not full after 1 second\n", base);
return 0;
}
-static inline unsigned int B1_get_word(unsigned short base)
+static inline unsigned int B1_get_word(unsigned int base)
{
unsigned int val = 0;
val |= B1_get_byte(base);
@@ -190,18 +290,18 @@ static inline unsigned int B1_get_word(unsigned short base)
return val;
}
-static inline int B1_tx_empty(unsigned short base)
+static inline int B1_tx_empty(unsigned int base)
{
return inb(base + B1_OUTSTAT) & 0x1;
}
-static inline void B1_put_byte(unsigned short base, unsigned char val)
+static inline void B1_put_byte(unsigned int base, unsigned char val)
{
while (!B1_tx_empty(base));
b1outp(base, B1_WRITE, val);
}
-static inline void B1_put_word(unsigned short base, unsigned int val)
+static inline void B1_put_word(unsigned int base, unsigned int val)
{
B1_put_byte(base, val & 0xff);
B1_put_byte(base, (val >> 8) & 0xff);
@@ -209,26 +309,95 @@ static inline void B1_put_word(unsigned short base, unsigned int val)
B1_put_byte(base, (val >> 24) & 0xff);
}
-static inline unsigned int B1_get_slice(unsigned short base,
+static inline unsigned int B1_get_slice(unsigned int base,
unsigned char *dp)
{
unsigned int len, i;
+#ifdef FASTLINK_DEBUG
+ unsigned wcnt = 0, bcnt = 0;
+#endif
len = i = B1_get_word(base);
- while (i-- > 0)
- *dp++ = B1_get_byte(base);
+ if (B1_isfastlink(base)) {
+ int status;
+ while (i > 0) {
+ status = B1_fifostatus(base) & (T1F_IREADY|T1F_IHALF);
+ if (i >= FIFO_INPBSIZE) status |= T1F_IFULL;
+
+ switch (status) {
+ case T1F_IREADY|T1F_IHALF|T1F_IFULL:
+ insb(base+B1_READ, dp, FIFO_INPBSIZE);
+ dp += FIFO_INPBSIZE;
+ i -= FIFO_INPBSIZE;
+#ifdef FASTLINK_DEBUG
+ wcnt += FIFO_INPBSIZE;
+#endif
+ break;
+ case T1F_IREADY|T1F_IHALF:
+ insb(base+B1_READ,dp, i);
+#ifdef FASTLINK_DEBUG
+ wcnt += i;
+#endif
+ dp += i;
+ i = 0;
+ if (i == 0)
+ break;
+ /* fall through */
+ default:
+ *dp++ = B1_get_byte(base);
+ i--;
+#ifdef FASTLINK_DEBUG
+ bcnt++;
+#endif
+ break;
+ }
+ }
+#ifdef FASTLINK_DEBUG
+ if (wcnt)
+ printk(KERN_DEBUG "b1lli(0x%x): get_slice l=%d w=%d b=%d\n",
+ base, len, wcnt, bcnt);
+#endif
+ } else {
+ while (i-- > 0)
+ *dp++ = B1_get_byte(base);
+ }
return len;
}
-static inline void B1_put_slice(unsigned short base,
+static inline void B1_put_slice(unsigned int base,
unsigned char *dp, unsigned int len)
{
- B1_put_word(base, len);
- while (len-- > 0)
- B1_put_byte(base, *dp++);
+ unsigned i = len;
+ B1_put_word(base, i);
+ if (B1_isfastlink(base)) {
+ int status;
+ while (i > 0) {
+ status = B1_fifostatus(base) & (T1F_OREADY|T1F_OHALF);
+ if (i >= FIFO_OUTBSIZE) status |= T1F_OEMPTY;
+ switch (status) {
+ case T1F_OREADY|T1F_OHALF|T1F_OEMPTY:
+ outsb(base+B1_WRITE, dp, FIFO_OUTBSIZE);
+ dp += FIFO_OUTBSIZE;
+ i -= FIFO_OUTBSIZE;
+ break;
+ case T1F_OREADY|T1F_OHALF:
+ outsb(base+B1_WRITE, dp, i);
+ dp += i;
+ i = 0;
+ break;
+ default:
+ B1_put_byte(base, *dp++);
+ i--;
+ break;
+ }
+ }
+ } else {
+ while (i-- > 0)
+ B1_put_byte(base, *dp++);
+ }
}
-static void b1_wr_reg(unsigned short base,
+static void b1_wr_reg(unsigned int base,
unsigned int reg,
unsigned int value)
{
@@ -237,7 +406,7 @@ static void b1_wr_reg(unsigned short base,
B1_put_word(base, value);
}
-static inline unsigned int b1_rd_reg(unsigned short base,
+static inline unsigned int b1_rd_reg(unsigned int base,
unsigned int reg)
{
B1_put_byte(base, READ_REGISTER);
@@ -246,14 +415,14 @@ static inline unsigned int b1_rd_reg(unsigned short base,
}
-static inline void b1_set_test_bit(unsigned short base,
+static inline void b1_set_test_bit(unsigned int base,
int cardtype,
int onoff)
{
b1_wr_reg(base, B1_STAT0(cardtype), onoff ? 0x21 : 0x20);
}
-static inline int b1_get_test_bit(unsigned short base,
+static inline int b1_get_test_bit(unsigned int base,
int cardtype)
{
return (b1_rd_reg(base, B1_STAT0(cardtype)) & 0x01) != 0;
@@ -278,6 +447,26 @@ static int irq_table[16] =
112, /* irq 15 */
};
+static int hema_irq_table[16] =
+{0,
+ 0,
+ 0,
+ 0x80, /* irq 3 */
+ 0,
+ 0x90, /* irq 5 */
+ 0,
+ 0xA0, /* irq 7 */
+ 0,
+ 0xB0, /* irq 9 */
+ 0xC0, /* irq 10 */
+ 0xD0, /* irq 11 */
+ 0xE0, /* irq 12 */
+ 0,
+ 0,
+ 0xF0, /* irq 15 */
+};
+
+
int B1_valid_irq(unsigned irq, int cardtype)
{
switch (cardtype) {
@@ -285,36 +474,76 @@ int B1_valid_irq(unsigned irq, int cardtype)
case AVM_CARDTYPE_M1:
case AVM_CARDTYPE_M2:
case AVM_CARDTYPE_B1:
- return irq_table[irq] != 0;
+ return irq_table[irq & 0xf] != 0;
case AVM_CARDTYPE_T1:
- return irq == 5;
+ return hema_irq_table[irq & 0xf] != 0;
+ case AVM_CARDTYPE_B1PCI:
+ return 1;
}
}
-unsigned char B1_assign_irq(unsigned short base, unsigned irq, int cardtype)
+int B1_valid_port(unsigned port, int cardtype)
+{
+ switch (cardtype) {
+ default:
+ case AVM_CARDTYPE_M1:
+ case AVM_CARDTYPE_M2:
+ case AVM_CARDTYPE_B1:
+#if 0 /* problem with PCMCIA and PCI cards */
+ switch (port) {
+ case 0x150:
+ case 0x250:
+ case 0x300:
+ case 0x340:
+ return 1;
+ }
+ return 0;
+#else
+ return 1;
+#endif
+ case AVM_CARDTYPE_B1PCI:
+ return 1;
+ case AVM_CARDTYPE_T1:
+ return ((port & 0x7) == 0) && ((port & 0x30) != 0x30);
+ }
+}
+
+void B1_setinterrupt(unsigned int base,
+ unsigned irq, int cardtype)
{
switch (cardtype) {
case AVM_CARDTYPE_T1:
- return b1outp(base, B1_IRQ_MASTER, 0x08);
+ t1outp(base, B1_INSTAT, 0x00);
+ t1outp(base, B1_INSTAT, 0x02);
+ t1outp(base, T1_IRQMASTER, 0x08);
+ break;
default:
case AVM_CARDTYPE_M1:
case AVM_CARDTYPE_M2:
case AVM_CARDTYPE_B1:
- return b1outp(base, B1_RESET, irq_table[irq]);
+ b1outp(base, B1_INSTAT, 0x00);
+ b1outp(base, B1_RESET, irq_table[irq]);
+ b1outp(base, B1_INSTAT, 0x02);
+ break;
+ case AVM_CARDTYPE_B1PCI:
+ b1outp(base, B1_INSTAT, 0x00);
+ b1outp(base, B1_RESET, 0xf0);
+ b1outp(base, B1_INSTAT, 0x02);
+ break;
}
}
-unsigned char B1_enable_irq(unsigned short base)
+unsigned char B1_disable_irq(unsigned int base)
{
- return b1outp(base, B1_INSTAT, 0x02);
+ return b1outp(base, B1_INSTAT, 0x00);
}
-unsigned char B1_disable_irq(unsigned short base)
+void T1_disable_irq(unsigned int base)
{
- return b1outp(base, B1_INSTAT, 0x00);
+ t1outp(base, T1_IRQMASTER, 0x00);
}
-void B1_reset(unsigned short base)
+void B1_reset(unsigned int base)
{
b1outp(base, B1_RESET, 0);
udelay(55 * 2 * 1000); /* 2 TIC's */
@@ -326,7 +555,19 @@ void B1_reset(unsigned short base)
udelay(55 * 2 * 1000); /* 2 TIC's */
}
-int B1_detect(unsigned short base, int cardtype)
+void T1_reset(unsigned int base)
+{
+ /* reset T1 Controller */
+ B1_reset(base);
+ /* disable irq on HEMA */
+ t1outp(base, B1_INSTAT, 0x00);
+ t1outp(base, B1_OUTSTAT, 0x00);
+ t1outp(base, T1_IRQMASTER, 0x00);
+ /* reset HEMA board configuration */
+ t1outp(base, T1_RESETBOARD, 0xf);
+}
+
+int B1_detect(unsigned int base, int cardtype)
{
int onoff, i;
@@ -372,10 +613,79 @@ int B1_detect(unsigned short base, int cardtype)
return 0;
}
+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;
+
+ reverse_cardnr = ((cardnr & 0x01) << 3) | ((cardnr & 0x02) << 1)
+ | ((cardnr & 0x04) >> 1) | ((cardnr & 0x08) >> 3);
+ cregs[0] = (HEMA_VERSION_ID << 4) | (reverse_cardnr & 0xf);
+ cregs[1] = 0x00; /* fast & slow link connected to CON1 */
+ cregs[2] = 0x05; /* fast link 20MBit, slow link 20 MBit */
+ cregs[3] = 0;
+ cregs[4] = 0x11; /* zero wait state */
+ cregs[5] = hema_irq_table[irq & 0xf];
+ cregs[6] = 0;
+ cregs[7] = 0;
+
+ save_flags(flags);
+ cli();
+ /* board reset */
+ t1outp(base, T1_RESETBOARD, 0xf);
+ udelay(100 * 1000);
+ dummy = t1inp(base, T1_FASTLINK+T1_OUTSTAT); /* first read */
+
+ /* write config */
+ dummy = (base >> 4) & 0xff;
+ for (i=1;i<=0xf;i++) t1outp(base, i, dummy);
+ t1outp(base, HEMA_PAL_ID & 0xf, dummy);
+ 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);
+
+ udelay(100 * 1000);
+ t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
+ t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
+ udelay(10 * 1000);
+ t1outp(base, T1_FASTLINK+T1_RESETLINK, 1);
+ t1outp(base, T1_SLOWLINK+T1_RESETLINK, 1);
+ udelay(100 * 1000);
+ t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
+ t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
+ udelay(10 * 1000);
+ t1outp(base, T1_FASTLINK+T1_ANALYSE, 0);
+ udelay(5 * 1000);
+ t1outp(base, T1_SLOWLINK+T1_ANALYSE, 0);
+
+ if (t1inp(base, T1_FASTLINK+T1_OUTSTAT) != 0x1) /* tx empty */
+ return 1;
+ if (t1inp(base, T1_FASTLINK+T1_INSTAT) != 0x0) /* rx empty */
+ return 2;
+ if (t1inp(base, T1_FASTLINK+T1_IRQENABLE) != 0x0)
+ return 3;
+ if ((t1inp(base, T1_FASTLINK+T1_FIFOSTAT) & 0xf0) != 0x70)
+ return 4;
+ if ((t1inp(base, T1_FASTLINK+T1_IRQMASTER) & 0x0e) != 0)
+ return 5;
+ if ((t1inp(base, T1_FASTLINK+T1_IDENT) & 0x7d) != 1)
+ return 6;
+ if (t1inp(base, T1_SLOWLINK+T1_OUTSTAT) != 0x1) /* tx empty */
+ return 7;
+ if ((t1inp(base, T1_SLOWLINK+T1_IRQMASTER) & 0x0e) != 0)
+ return 8;
+ if ((t1inp(base, T1_SLOWLINK+T1_IDENT) & 0x7d) != 0)
+ return 9;
+ return 0;
+}
extern int loaddebug;
-int B1_load_t4file(unsigned short base, avmb1_t4file * t4file)
+int B1_load_t4file(unsigned int base, avmb1_t4file * t4file)
{
/*
* Data is in user space !!!
@@ -414,7 +724,7 @@ int B1_load_t4file(unsigned short base, avmb1_t4file * t4file)
return 0;
}
-int B1_load_config(unsigned short base, avmb1_t4file * config)
+int B1_load_config(unsigned int base, avmb1_t4file * config)
{
/*
* Data is in user space !!!
@@ -470,7 +780,7 @@ int B1_load_config(unsigned short base, avmb1_t4file * config)
return 0;
}
-int B1_loaded(unsigned short base)
+int B1_loaded(unsigned int base)
{
int i;
unsigned char ans;
@@ -482,7 +792,7 @@ int B1_loaded(unsigned short base)
break;
}
if (!B1_tx_empty(base)) {
- printk(KERN_ERR "b1lli: B1_loaded: timeout tx\n");
+ printk(KERN_ERR "b1lli(0x%x): B1_loaded: timeout tx\n", base);
return 0;
}
B1_put_byte(base, SEND_POLL);
@@ -494,11 +804,12 @@ int B1_loaded(unsigned short base)
printk(KERN_DEBUG "b1capi: loaded: ok\n");
return 1;
}
- printk(KERN_ERR "b1lli: B1_loaded: got 0x%x ???\n", ans);
+ printk(KERN_ERR "b1lli(0x%x): B1_loaded: got 0x%x ???\n",
+ base, ans);
return 0;
}
}
- printk(KERN_ERR "b1lli: B1_loaded: timeout rx\n");
+ printk(KERN_ERR "b1lli(0x%x): B1_loaded: timeout rx\n", base);
return 0;
}
@@ -519,7 +830,7 @@ static inline void parse_version(avmb1_card * card)
* -------------------------------------------------------------------
*/
-void B1_send_init(unsigned short port,
+void B1_send_init(unsigned int port,
unsigned int napps, unsigned int nncci, unsigned int cardnr)
{
unsigned long flags;
@@ -533,7 +844,7 @@ void B1_send_init(unsigned short port,
restore_flags(flags);
}
-void B1_send_register(unsigned short port,
+void B1_send_register(unsigned int port,
__u16 appid, __u32 nmsg,
__u32 nb3conn, __u32 nb3blocks, __u32 b3bsize)
{
@@ -550,7 +861,7 @@ void B1_send_register(unsigned short port,
restore_flags(flags);
}
-void B1_send_release(unsigned short port,
+void B1_send_release(unsigned int port,
__u16 appid)
{
unsigned long flags;
@@ -562,9 +873,7 @@ void B1_send_release(unsigned short port,
restore_flags(flags);
}
-extern int showcapimsgs;
-
-void B1_send_message(unsigned short port, struct sk_buff *skb)
+void B1_send_message(unsigned int port, struct sk_buff *skb)
{
unsigned long flags;
__u16 len = CAPIMSG_LEN(skb->data);
@@ -630,6 +939,7 @@ void B1_handle_interrupt(avmb1_card * card)
unsigned NCCI;
unsigned WindowSize;
+t1retry:
if (!B1_rx_full(card->port))
return;
@@ -704,7 +1014,7 @@ void B1_handle_interrupt(avmb1_card * card)
WindowSize = B1_get_word(card->port);
if (showcapimsgs)
- printk(KERN_DEBUG "b1lli: NEW_NCCI app %u ncci 0x%x\n", ApplId, NCCI);
+ printk(KERN_DEBUG "b1lli(0x%x): NEW_NCCI app %u ncci 0x%x\n", card->port, ApplId, NCCI);
avmb1_handle_new_ncci(card, ApplId, NCCI, WindowSize);
@@ -716,19 +1026,23 @@ void B1_handle_interrupt(avmb1_card * card)
NCCI = B1_get_word(card->port);
if (showcapimsgs)
- printk(KERN_DEBUG "b1lli: FREE_NCCI app %u ncci 0x%x\n", ApplId, NCCI);
+ printk(KERN_DEBUG "b1lli(0x%x): FREE_NCCI app %u ncci 0x%x\n", card->port, ApplId, NCCI);
avmb1_handle_free_ncci(card, ApplId, NCCI);
break;
case RECEIVE_START:
+ if (card->cardtype == AVM_CARDTYPE_T1) {
+ B1_put_byte(card->port, SEND_POLLACK);
+ /* printk(KERN_DEBUG "b1lli: T1 watchdog\n"); */
+ }
if (card->blocked)
- printk(KERN_DEBUG "b1lli: RESTART\n");
+ printk(KERN_DEBUG "b1lli(0x%x): RESTART\n", card->port);
card->blocked = 0;
break;
case RECEIVE_STOP:
- printk(KERN_DEBUG "b1lli: STOP\n");
+ printk(KERN_DEBUG "b1lli(0x%x): STOP\n", card->port);
card->blocked = 1;
break;
@@ -737,13 +1051,24 @@ void B1_handle_interrupt(avmb1_card * card)
card->versionlen = B1_get_slice(card->port, card->versionbuf);
card->cardstate = CARD_ACTIVE;
parse_version(card);
- printk(KERN_INFO "b1lli: %s-card (%s) now active\n",
+ printk(KERN_INFO "b1lli(0x%x): %s-card (%s) now active\n",
+ card->port,
card->version[VER_CARDTYPE],
card->version[VER_DRIVER]);
avmb1_card_ready(card);
break;
+ case RECEIVE_TASK_READY:
+ ApplId = (unsigned) B1_get_word(card->port);
+ MsgLen = B1_get_slice(card->port, card->msgbuf);
+ card->msgbuf[MsgLen] = 0;
+ printk(KERN_INFO "b1lli(0x%x): Task %d \"%s\" ready.\n",
+ card->port, ApplId, card->msgbuf);
+ break;
default:
- printk(KERN_ERR "b1lli: B1_handle_interrupt: 0x%x ???\n", b1cmd);
+ printk(KERN_ERR "b1lli(0x%x): B1_handle_interrupt: 0x%x ???\n",
+ card->port, b1cmd);
break;
}
+ if (card->cardtype == AVM_CARDTYPE_T1)
+ goto t1retry;
}
diff --git a/drivers/isdn/avmb1/b1pci.c b/drivers/isdn/avmb1/b1pci.c
index b5c45acfd..112ddbb81 100644
--- a/drivers/isdn/avmb1/b1pci.c
+++ b/drivers/isdn/avmb1/b1pci.c
@@ -1,11 +1,29 @@
/*
- * $Id: b1pci.c,v 1.5 1998/01/31 11:14:43 calle Exp $
+ * $Id: b1pci.c,v 1.9 1999/04/15 19:49:32 calle Exp $
*
* Module for AVM B1 PCI-card.
*
* (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: b1pci.c,v $
+ * Revision 1.9 1999/04/15 19:49:32 calle
+ * fix fuer die B1-PCI. Jetzt geht z.B. auch IRQ 17 ...
+ *
+ * Revision 1.8 1998/06/17 19:51:16 he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.7 1998/03/29 16:06:02 calle
+ * changes from 2.0 tree merged.
+ *
+ * Revision 1.2.2.2 1998/01/23 16:49:30 calle
+ * added functions for pcmcia cards,
+ * avmb1_addcard returns now the controller number.
+ *
+ * Revision 1.6 1998/02/25 09:15:36 fritz
+ * apply Martin's pci driver patch to isdn drivers (vgerCVS)
+ *
* Revision 1.5 1998/01/31 11:14:43 calle
* merged changes to 2.0 tree, prepare 2.1.82 to work.
*
@@ -28,6 +46,7 @@
*/
#include <linux/config.h>
+#include <linux/string.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
@@ -44,7 +63,7 @@
#define PCI_DEVICE_ID_AVM_B1 0x700
#endif
-static char *revision = "$Revision: 1.5 $";
+static char *revision = "$Revision: 1.9 $";
/* ------------------------------------------------------------- */
@@ -93,13 +112,13 @@ int b1pci_init(void)
printk(KERN_INFO
"b1pci: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
ioaddr, irq);
- if ((rc = avmb1_probecard(ioaddr, irq, AVM_CARDTYPE_B1)) != 0) {
+ if ((rc = avmb1_probecard(ioaddr, irq, AVM_CARDTYPE_B1PCI)) != 0) {
printk(KERN_ERR
"b1pci: no AVM-B1 at i/o %#x, irq %d detected\n",
ioaddr, irq);
return rc;
}
- if ((rc = avmb1_addcard(ioaddr, irq, AVM_CARDTYPE_B1)) < 0)
+ if ((rc = avmb1_addcard(ioaddr, irq, AVM_CARDTYPE_B1PCI)) < 0)
return rc;
}
return 0;
diff --git a/drivers/isdn/avmb1/capi.c b/drivers/isdn/avmb1/capi.c
index f4f5c7039..69ed317f3 100644
--- a/drivers/isdn/avmb1/capi.c
+++ b/drivers/isdn/avmb1/capi.c
@@ -1,11 +1,23 @@
/*
- * $Id: capi.c,v 1.10 1998/02/13 07:09:13 calle Exp $
+ * $Id: capi.c,v 1.13 1998/08/28 04:32:25 calle Exp $
*
* CAPI 2.0 Interface for Linux
*
* Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: capi.c,v $
+ * Revision 1.13 1998/08/28 04:32:25 calle
+ * Added patch send by Michael.Mueller4@post.rwth-aachen.de, to get AVM B1
+ * driver running with 2.1.118.
+ *
+ * Revision 1.12 1998/05/26 22:39:34 he
+ * sync'ed with 2.1.102 where appropriate (CAPABILITY changes)
+ * concap typo
+ * cleared dev.tbusy in isdn_net BCONN status callback
+ *
+ * Revision 1.11 1998/03/09 17:46:37 he
+ * merged in 2.1.89 changes
+ *
* Revision 1.10 1998/02/13 07:09:13 calle
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
@@ -237,6 +249,9 @@ capi_poll(struct file *file, poll_table * wait)
return POLLERR;
cdev = &capidevs[minor];
+#if (LINUX_VERSION_CODE < 0x020159) /* 2.1.89 */
+#define poll_wait(f,wq,w) poll_wait((wq),(w))
+#endif
poll_wait(file, &(cdev->recv_wait), wait);
mask = POLLOUT | POLLWRNORM;
if (!skb_queue_empty(&cdev->recv_queue))
@@ -464,7 +479,9 @@ static struct file_operations capi_fops =
capi_ioctl,
NULL, /* capi_mmap */
capi_open,
- NULL, /* flush */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,118)
+ NULL, /* capi_flush */
+#endif
capi_release,
NULL, /* capi_fsync */
NULL, /* capi_fasync */
@@ -484,7 +501,16 @@ static struct capi_interface_user cuser = {
int capi_init(void)
{
+#if LINUX_VERSION_CODE >= 131841
+ int j;
+#endif
+
memset(capidevs, 0, sizeof(capidevs));
+#if LINUX_VERSION_CODE >= 131841
+ for ( j = 0; j < CAPI_MAXMINOR+1; j++ ) {
+ init_waitqueue_head(&capidevs[j].recv_wait);
+ }
+#endif
if (register_chrdev(capi_major, "capi20", &capi_fops)) {
printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);
@@ -496,6 +522,7 @@ int capi_init(void)
unregister_chrdev(capi_major, "capi20");
return -EIO;
}
+
return 0;
}
diff --git a/drivers/isdn/avmb1/capidev.h b/drivers/isdn/avmb1/capidev.h
index f2e0d6d2d..bd57255b6 100644
--- a/drivers/isdn/avmb1/capidev.h
+++ b/drivers/isdn/avmb1/capidev.h
@@ -22,7 +22,11 @@ struct capidev {
int is_registered;
__u16 applid;
struct sk_buff_head recv_queue;
+#if LINUX_VERSION_CODE < 131841
struct wait_queue *recv_wait;
+#else
+ wait_queue_head_t recv_wait;
+#endif
__u16 errcode;
};
diff --git a/drivers/isdn/avmb1/capidrv.c b/drivers/isdn/avmb1/capidrv.c
index 1d4a7c2e8..7eb0c33cf 100644
--- a/drivers/isdn/avmb1/capidrv.c
+++ b/drivers/isdn/avmb1/capidrv.c
@@ -1,11 +1,36 @@
/*
- * $Id: capidrv.c,v 1.11 1998/02/13 07:09:15 calle Exp $
+ * $Id: capidrv.c,v 1.13 1998/06/26 15:12:55 fritz Exp $
*
* ISDN4Linux Driver, using capi20 interface (kernelcapi)
*
* Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: capidrv.c,v $
+ * Revision 1.13 1998/06/26 15:12:55 fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 1.12 1998/03/29 16:06:03 calle
+ * changes from 2.0 tree merged.
+ *
+ * Revision 1.3.2.10 1998/03/20 14:38:24 calle
+ * capidrv: prepared state machines for suspend/resume/hold
+ * capidrv: fix bug in state machine if B1/T1 is out of nccis
+ * b1capi: changed some errno returns.
+ * b1capi: detect if you try to add same T1 to different io address.
+ * b1capi: change number of nccis depending on number of channels.
+ * b1lli: cosmetics
+ *
+ * Revision 1.3.2.9 1998/03/20 09:01:12 calle
+ * Changes capi_register handling to get full support for 30 bchannels.
+ *
+ * Revision 1.3.2.8 1998/03/18 17:51:28 calle
+ * added controller number to error messages
+ *
+ * Revision 1.3.2.7 1998/02/27 15:40:47 calle
+ * T1 running with slow link. bugfix in capi_release.
+ *
* Revision 1.11 1998/02/13 07:09:15 calle
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
@@ -79,7 +104,7 @@
#include "capicmd.h"
#include "capidrv.h"
-static char *revision = "$Revision: 1.11 $";
+static char *revision = "$Revision: 1.13 $";
int debugmode = 0;
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
@@ -378,8 +403,8 @@ static void free_plci(capidrv_contr * card, capidrv_plci * plcip)
return;
}
}
- printk(KERN_ERR "capidrv: free_plci %p (0x%x) not found, Huh?\n",
- plcip, plcip->plci);
+ printk(KERN_ERR "capidrv-%d: free_plci %p (0x%x) not found, Huh?\n",
+ card->contrnr, plcip, plcip->plci);
}
/* -------- ncci management ------------------------------------------ */
@@ -512,15 +537,15 @@ struct listenstatechange {
static struct listenstatechange listentable[] =
{
- {ST_LISTEN_NONE, ST_LISTEN_WAIT_CONF, EV_LISTEN_REQ},
- {ST_LISTEN_ACTIVE, ST_LISTEN_ACTIVE_WAIT_CONF, EV_LISTEN_REQ},
- {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_ERROR},
- {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_ERROR},
- {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
- {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
- {ST_LISTEN_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
- {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
- {},
+ {ST_LISTEN_NONE, ST_LISTEN_WAIT_CONF, EV_LISTEN_REQ},
+ {ST_LISTEN_ACTIVE, ST_LISTEN_ACTIVE_WAIT_CONF, EV_LISTEN_REQ},
+ {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_ERROR},
+ {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_ERROR},
+ {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
+ {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
+ {ST_LISTEN_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
+ {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
+ {},
};
static void listen_change_state(capidrv_contr * card, int event)
@@ -529,15 +554,15 @@ static void listen_change_state(capidrv_contr * card, int event)
while (p->event) {
if (card->state == p->actstate && p->event == event) {
if (debugmode)
- printk(KERN_DEBUG "capidrv: listen_change_state %d -> %d\n",
- card->state, p->nextstate);
+ printk(KERN_DEBUG "capidrv-%d: listen_change_state %d -> %d\n",
+ card->contrnr, card->state, p->nextstate);
card->state = p->nextstate;
return;
}
p++;
}
- printk(KERN_ERR "capidrv: listen_change_state state=%d event=%d ????\n",
- card->state, event);
+ printk(KERN_ERR "capidrv-%d: listen_change_state state=%d event=%d ????\n",
+ card->contrnr, card->state, event);
}
@@ -567,46 +592,57 @@ struct plcistatechange {
static struct plcistatechange plcitable[] =
{
/* P-0 */
- {ST_PLCI_NONE, ST_PLCI_OUTGOING, EV_PLCI_CONNECT_REQ, 0},
- {ST_PLCI_NONE, ST_PLCI_ALLOCATED, EV_PLCI_FACILITY_IND_UP, 0},
- {ST_PLCI_NONE, ST_PLCI_INCOMING, EV_PLCI_CONNECT_IND, 0},
+ {ST_PLCI_NONE, ST_PLCI_OUTGOING, EV_PLCI_CONNECT_REQ, 0},
+ {ST_PLCI_NONE, ST_PLCI_ALLOCATED, EV_PLCI_FACILITY_IND_UP, 0},
+ {ST_PLCI_NONE, ST_PLCI_INCOMING, EV_PLCI_CONNECT_IND, 0},
+ {ST_PLCI_NONE, ST_PLCI_RESUMEING, EV_PLCI_RESUME_REQ, 0},
/* P-0.1 */
- {ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0},
- {ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, 0},
- {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
- {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
+ {ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0},
+ {ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, 0},
+ {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
+ {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
/* P-1 */
- {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},
- {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
-{ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
- {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+ {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},
+ {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
+ {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
+ {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
/* P-ACT */
- {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
- {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
- {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+ {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
+ {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
+ {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+ {ST_PLCI_ACTIVE, ST_PLCI_HELD, EV_PLCI_HOLD_IND, 0},
+ {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_SUSPEND_IND, 0},
/* P-2 */
- {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},
- {ST_PLCI_INCOMING, ST_PLCI_FACILITY_IND, EV_PLCI_FACILITY_IND_UP, 0},
- {ST_PLCI_INCOMING, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_RESP, 0},
- {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
- {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
- {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+ {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},
+ {ST_PLCI_INCOMING, ST_PLCI_FACILITY_IND, EV_PLCI_FACILITY_IND_UP, 0},
+ {ST_PLCI_INCOMING, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_RESP, 0},
+ {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
+ {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
+ {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+ {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CD_IND, 0},
/* P-3 */
-{ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},
-{ST_PLCI_FACILITY_IND, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_ACTIVE_IND, 0},
-{ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
- {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
- {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+ {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},
+ {ST_PLCI_FACILITY_IND, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_ACTIVE_IND, 0},
+ {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
+ {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
+ {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
/* P-4 */
- {ST_PLCI_ACCEPTING, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},
- {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
-{ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
- {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+ {ST_PLCI_ACCEPTING, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},
+ {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
+ {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
+ {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
/* P-5 */
-{ST_PLCI_DISCONNECTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+ {ST_PLCI_DISCONNECTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
/* P-6 */
- {ST_PLCI_DISCONNECTED, ST_PLCI_NONE, EV_PLCI_DISCONNECT_RESP, p0},
- {},
+ {ST_PLCI_DISCONNECTED, ST_PLCI_NONE, EV_PLCI_DISCONNECT_RESP, p0},
+ /* P-0.Res */
+ {ST_PLCI_RESUMEING, ST_PLCI_NONE, EV_PLCI_RESUME_CONF_ERROR, p0},
+ {ST_PLCI_RESUMEING, ST_PLCI_RESUME, EV_PLCI_RESUME_CONF_OK, 0},
+ /* P-RES */
+ {ST_PLCI_RESUME, ST_PLCI_ACTIVE, EV_PLCI_RESUME_IND, 0},
+ /* P-HELD */
+ {ST_PLCI_HELD, ST_PLCI_ACTIVE, EV_PLCI_RETRIEVE_IND, 0},
+ {},
};
static void plci_change_state(capidrv_contr * card, capidrv_plci * plci, int event)
@@ -615,8 +651,8 @@ static void plci_change_state(capidrv_contr * card, capidrv_plci * plci, int eve
while (p->event) {
if (plci->state == p->actstate && p->event == event) {
if (debugmode)
- printk(KERN_DEBUG "capidrv: plci_change_state:0x%x %d -> %d\n",
- plci->plci, plci->state, p->nextstate);
+ printk(KERN_DEBUG "capidrv-%d: plci_change_state:0x%x %d -> %d\n",
+ card->contrnr, plci->plci, plci->state, p->nextstate);
plci->state = p->nextstate;
if (p->changefunc)
p->changefunc(card, plci);
@@ -624,8 +660,8 @@ static void plci_change_state(capidrv_contr * card, capidrv_plci * plci, int eve
}
p++;
}
- printk(KERN_ERR "capidrv: plci_change_state:0x%x state=%d event=%d ????\n",
- plci->plci, plci->state, event);
+ printk(KERN_ERR "capidrv-%d: plci_change_state:0x%x state=%d event=%d ????\n",
+ card->contrnr, plci->plci, plci->state, event);
}
/* ------------------------------------------------------------------ */
@@ -642,7 +678,7 @@ static void n0(capidrv_contr * card, capidrv_ncci * ncci)
ncci->plcip->plci,
0, /* BChannelinformation */
0, /* Keypadfacility */
- 0, /* Useruserdata */
+ 0, /* Useruserdata */ /* $$$$ */
0 /* Facilitydataarray */
);
send_message(card, &cmsg);
@@ -667,34 +703,35 @@ struct nccistatechange {
static struct nccistatechange nccitable[] =
{
/* N-0 */
- {ST_NCCI_NONE, ST_NCCI_OUTGOING, EV_NCCI_CONNECT_B3_REQ, 0},
- {ST_NCCI_NONE, ST_NCCI_INCOMING, EV_NCCI_CONNECT_B3_IND, 0},
+ {ST_NCCI_NONE, ST_NCCI_OUTGOING, EV_NCCI_CONNECT_B3_REQ, 0},
+ {ST_NCCI_NONE, ST_NCCI_INCOMING, EV_NCCI_CONNECT_B3_IND, 0},
/* N-0.1 */
- {ST_NCCI_OUTGOING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_CONF_OK, 0},
- {ST_NCCI_OUTGOING, ST_NCCI_NONE, EV_NCCI_CONNECT_B3_CONF_ERROR, 0},
+ {ST_NCCI_OUTGOING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_CONF_OK, 0},
+ {ST_NCCI_OUTGOING, ST_NCCI_NONE, EV_NCCI_CONNECT_B3_CONF_ERROR, n0},
/* N-1 */
- {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_CONNECT_B3_REJECT, 0},
- {ST_NCCI_INCOMING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_RESP, 0},
+ {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_CONNECT_B3_REJECT, 0},
+ {ST_NCCI_INCOMING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_RESP, 0},
{ST_NCCI_INCOMING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
- {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
+ {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
/* N-2 */
- {ST_NCCI_ALLOCATED, ST_NCCI_ACTIVE, EV_NCCI_CONNECT_B3_ACTIVE_IND, 0},
- {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
-{ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
+ {ST_NCCI_ALLOCATED, ST_NCCI_ACTIVE, EV_NCCI_CONNECT_B3_ACTIVE_IND, 0},
+ {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
+ {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
/* N-ACT */
- {ST_NCCI_ACTIVE, ST_NCCI_RESETING, EV_NCCI_RESET_B3_REQ, 0},
- {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
- {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
+ {ST_NCCI_ACTIVE, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0},
+ {ST_NCCI_ACTIVE, ST_NCCI_RESETING, EV_NCCI_RESET_B3_REQ, 0},
+ {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
+ {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
/* N-3 */
- {ST_NCCI_RESETING, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0},
+ {ST_NCCI_RESETING, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0},
{ST_NCCI_RESETING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
- {ST_NCCI_RESETING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
+ {ST_NCCI_RESETING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
/* N-4 */
- {ST_NCCI_DISCONNECTING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
- {ST_NCCI_DISCONNECTING, ST_NCCI_PREVIOUS, EV_NCCI_DISCONNECT_B3_CONF_ERROR, 0},
+ {ST_NCCI_DISCONNECTING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
+ {ST_NCCI_DISCONNECTING, ST_NCCI_PREVIOUS, EV_NCCI_DISCONNECT_B3_CONF_ERROR,0},
/* N-5 */
- {ST_NCCI_DISCONNECTED, ST_NCCI_NONE, EV_NCCI_DISCONNECT_B3_RESP, n0},
- {},
+ {ST_NCCI_DISCONNECTED, ST_NCCI_NONE, EV_NCCI_DISCONNECT_B3_RESP, n0},
+ {},
};
static void ncci_change_state(capidrv_contr * card, capidrv_ncci * ncci, int event)
@@ -703,8 +740,8 @@ static void ncci_change_state(capidrv_contr * card, capidrv_ncci * ncci, int eve
while (p->event) {
if (ncci->state == p->actstate && p->event == event) {
if (debugmode)
- printk(KERN_DEBUG "capidrv: ncci_change_state:0x%x %d -> %d\n",
- ncci->ncci, ncci->state, p->nextstate);
+ printk(KERN_DEBUG "capidrv-%d: ncci_change_state:0x%x %d -> %d\n",
+ card->contrnr, ncci->ncci, ncci->state, p->nextstate);
if (p->nextstate == ST_NCCI_PREVIOUS) {
ncci->state = ncci->oldstate;
ncci->oldstate = p->actstate;
@@ -718,8 +755,8 @@ static void ncci_change_state(capidrv_contr * card, capidrv_ncci * ncci, int eve
}
p++;
}
- printk(KERN_ERR "capidrv: ncci_change_state:0x%x state=%d event=%d ????\n",
- ncci->ncci, ncci->state, event);
+ printk(KERN_ERR "capidrv-%d: ncci_change_state:0x%x state=%d event=%d ????\n",
+ card->contrnr, ncci->ncci, ncci->state, event);
}
/* ------------------------------------------------------------------- */
@@ -752,8 +789,8 @@ static void handle_controller(_cmsg * cmsg)
case CAPI_LISTEN_CONF: /* Controller */
if (debugmode)
- printk(KERN_DEBUG "capidrv: listenconf Info=0x%4x (%s) cipmask=0x%x\n",
- cmsg->Info, capi_info2str(cmsg->Info), card->cipmask);
+ printk(KERN_DEBUG "capidrv-%d: listenconf Info=0x%4x (%s) cipmask=0x%x\n",
+ card->contrnr, cmsg->Info, capi_info2str(cmsg->Info), card->cipmask);
if (cmsg->Info) {
listen_change_state(card, EV_LISTEN_CONF_ERROR);
} else if (card->cipmask == 0) {
@@ -789,7 +826,8 @@ static void handle_controller(_cmsg * cmsg)
handle_dtrace_data(card, direction, 0, data, len);
break;
}
- printk(KERN_INFO "capidrv: %s from controller 0x%x layer 0x%x, ignored\n",
+ printk(KERN_INFO "capidrv-%d: %s from controller 0x%x layer 0x%x, ignored\n",
+ card->contrnr,
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
cmsg->adr.adrController, layer);
break;
@@ -805,7 +843,8 @@ static void handle_controller(_cmsg * cmsg)
default: s = "unkown error"; break;
}
if (s)
- printk(KERN_INFO "capidrv: %s from controller 0x%x function %d: %s\n",
+ printk(KERN_INFO "capidrv-%d: %s from controller 0x%x function %d: %s\n",
+ card->contrnr,
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
cmsg->adr.adrController,
cmsg->Function, s);
@@ -822,14 +861,16 @@ static void handle_controller(_cmsg * cmsg)
goto ignored;
default:
- printk(KERN_ERR "capidrv: got %s from controller 0x%x ???",
+ printk(KERN_ERR "capidrv-%d: got %s from controller 0x%x ???",
+ card->contrnr,
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
cmsg->adr.adrController);
}
return;
ignored:
- printk(KERN_INFO "capidrv: %s from controller 0x%x ignored\n",
+ printk(KERN_INFO "capidrv-%d: %s from controller 0x%x ignored\n",
+ card->contrnr,
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
cmsg->adr.adrController);
}
@@ -842,12 +883,12 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
int chan;
if ((chan = new_bchan(card)) == -1) {
- printk(KERN_ERR "capidrv: incoming call on not existing bchan ?\n");
+ printk(KERN_ERR "capidrv-%d: incoming call on not existing bchan ?\n", card->contrnr);
return;
}
bchan = &card->bchans[chan];
if ((plcip = new_plci(card, chan)) == 0) {
- printk(KERN_ERR "capidrv: incoming call: no memory, sorry.\n");
+ printk(KERN_ERR "capidrv-%d: incoming call: no memory, sorry.\n", card->contrnr);
return;
}
bchan->incoming = 1;
@@ -869,7 +910,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
cmd.parm.setup.plan = cmsg->CallingPartyNumber[1];
cmd.parm.setup.screen = cmsg->CallingPartyNumber[2];
- printk(KERN_INFO "capidrv: incoming call %s,%d,%d,%s\n",
+ printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s\n",
+ card->contrnr,
cmd.parm.setup.phone,
cmd.parm.setup.si1,
cmd.parm.setup.si2,
@@ -877,6 +919,7 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
switch (card->interface.statcallb(&cmd)) {
case 0:
+ case 3:
/* No device matching this call.
* and isdn_common.c has send a HANGUP command
* which is ignored in state ST_PLCI_INCOMING,
@@ -886,7 +929,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
cmsg->Reject = 1; /* ignore */
send_message(card, cmsg);
plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
- printk(KERN_INFO "capidrv: incoming call %s,%d,%d,%s ignored\n",
+ printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s ignored\n",
+ card->contrnr,
cmd.parm.setup.phone,
cmd.parm.setup.si1,
cmd.parm.setup.si2,
@@ -903,7 +947,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
* and CONNECT_RESP already sent.
*/
if (plcip->state == ST_PLCI_INCOMING) {
- printk(KERN_INFO "capidrv: incoming call %s,%d,%d,%s tty alerting\n",
+ printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s tty alerting\n",
+ card->contrnr,
cmd.parm.setup.phone,
cmd.parm.setup.si1,
cmd.parm.setup.si2,
@@ -920,7 +965,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
plcip->msgid = cmsg->Messagenumber;
send_message(card, cmsg);
} else {
- printk(KERN_INFO "capidrv: incoming call %s,%d,%d,%s on netdev\n",
+ printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s on netdev\n",
+ card->contrnr,
cmd.parm.setup.phone,
cmd.parm.setup.si1,
cmd.parm.setup.si2,
@@ -963,7 +1009,8 @@ static void handle_plci(_cmsg * cmsg)
case CAPI_DISCONNECT_IND: /* plci */
if (cmsg->Reason) {
- printk(KERN_INFO "capidrv: %s reason 0x%x (%s) for plci 0x%x\n",
+ printk(KERN_INFO "capidrv-%d: %s reason 0x%x (%s) for plci 0x%x\n",
+ card->contrnr,
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
cmsg->Reason, capi_info2str(cmsg->Reason), cmsg->adr.adrPLCI);
}
@@ -981,7 +1028,8 @@ static void handle_plci(_cmsg * cmsg)
case CAPI_DISCONNECT_CONF: /* plci */
if (cmsg->Info) {
- printk(KERN_INFO "capidrv: %s info 0x%x (%s) for plci 0x%x\n",
+ printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
+ card->contrnr,
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
cmsg->Info, capi_info2str(cmsg->Info),
cmsg->adr.adrPLCI);
@@ -994,7 +1042,8 @@ static void handle_plci(_cmsg * cmsg)
case CAPI_ALERT_CONF: /* plci */
if (cmsg->Info) {
- printk(KERN_INFO "capidrv: %s info 0x%x (%s) for plci 0x%x\n",
+ printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
+ card->contrnr,
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
cmsg->Info, capi_info2str(cmsg->Info),
cmsg->adr.adrPLCI);
@@ -1007,7 +1056,8 @@ static void handle_plci(_cmsg * cmsg)
case CAPI_CONNECT_CONF: /* plci */
if (cmsg->Info) {
- printk(KERN_INFO "capidrv: %s info 0x%x (%s) for plci 0x%x\n",
+ printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
+ card->contrnr,
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
cmsg->Info, capi_info2str(cmsg->Info),
cmsg->adr.adrPLCI);
@@ -1040,7 +1090,7 @@ static void handle_plci(_cmsg * cmsg)
nccip = new_ncci(card, plcip, cmsg->adr.adrPLCI);
if (!nccip) {
- printk(KERN_ERR "capidrv: no mem for ncci, sorry\n");
+ printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr);
break; /* $$$$ */
}
capi_fill_CONNECT_B3_REQ(cmsg,
@@ -1080,7 +1130,8 @@ static void handle_plci(_cmsg * cmsg)
break;
}
}
- printk(KERN_ERR "capidrv: %s\n", capi_cmsg2str(cmsg));
+ printk(KERN_ERR "capidrv-%d: %s\n",
+ card->contrnr, capi_cmsg2str(cmsg));
break;
case CAPI_CONNECT_ACTIVE_CONF: /* plci */
@@ -1096,18 +1147,21 @@ static void handle_plci(_cmsg * cmsg)
goto ignored;
default:
- printk(KERN_ERR "capidrv: got %s for plci 0x%x ???",
+ printk(KERN_ERR "capidrv-%d: got %s for plci 0x%x ???",
+ card->contrnr,
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
cmsg->adr.adrPLCI);
}
return;
ignored:
- printk(KERN_INFO "capidrv: %s for plci 0x%x ignored\n",
+ printk(KERN_INFO "capidrv-%d: %s for plci 0x%x ignored\n",
+ card->contrnr,
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
cmsg->adr.adrPLCI);
return;
notfound:
- printk(KERN_ERR "capidrv: %s: plci 0x%x not found\n",
+ printk(KERN_ERR "capidrv-%d: %s: plci 0x%x not found\n",
+ card->contrnr,
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
cmsg->adr.adrPLCI);
return;
@@ -1142,8 +1196,8 @@ static void handle_ncci(_cmsg * cmsg)
cmd.arg = nccip->chan;
card->interface.statcallb(&cmd);
- printk(KERN_INFO "capidrv: chan %d up with ncci 0x%x\n",
- nccip->chan, nccip->ncci);
+ printk(KERN_INFO "capidrv-%d: chan %d up with ncci 0x%x\n",
+ card->contrnr, nccip->chan, nccip->ncci);
break;
case CAPI_CONNECT_B3_ACTIVE_CONF: /* ncci */
@@ -1167,9 +1221,10 @@ static void handle_ncci(_cmsg * cmsg)
ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP);
break;
}
- printk(KERN_ERR "capidrv: no mem for ncci, sorry\n");
+ printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr);
} else {
- printk(KERN_ERR "capidrv: %s: plci for ncci 0x%x not found\n",
+ printk(KERN_ERR "capidrv-%d: %s: plci for ncci 0x%x not found\n",
+ card->contrnr,
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
cmsg->adr.adrNCCI);
}
@@ -1192,7 +1247,8 @@ static void handle_ncci(_cmsg * cmsg)
nccip->ncci = cmsg->adr.adrNCCI;
if (cmsg->Info) {
- printk(KERN_INFO "capidrv: %s info 0x%x (%s) for ncci 0x%x\n",
+ printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
+ card->contrnr,
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
cmsg->Info, capi_info2str(cmsg->Info),
cmsg->adr.adrNCCI);
@@ -1242,7 +1298,8 @@ static void handle_ncci(_cmsg * cmsg)
if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
goto notfound;
if (cmsg->Info) {
- printk(KERN_INFO "capidrv: %s info 0x%x (%s) for ncci 0x%x\n",
+ printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
+ card->contrnr,
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
cmsg->Info, capi_info2str(cmsg->Info),
cmsg->adr.adrNCCI);
@@ -1251,6 +1308,9 @@ static void handle_ncci(_cmsg * cmsg)
break;
case CAPI_RESET_B3_IND: /* ncci */
+ if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
+ goto notfound;
+ ncci_change_state(card, nccip, EV_NCCI_RESET_B3_IND);
capi_cmsg_answer(cmsg);
send_message(card, cmsg);
break;
@@ -1264,18 +1324,21 @@ static void handle_ncci(_cmsg * cmsg)
goto ignored;
default:
- printk(KERN_ERR "capidrv: got %s for ncci 0x%x ???",
+ printk(KERN_ERR "capidrv-%d: got %s for ncci 0x%x ???",
+ card->contrnr,
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
cmsg->adr.adrNCCI);
}
return;
ignored:
- printk(KERN_INFO "capidrv: %s for ncci 0x%x ignored\n",
+ printk(KERN_INFO "capidrv-%d: %s for ncci 0x%x ignored\n",
+ card->contrnr,
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
cmsg->adr.adrNCCI);
return;
notfound:
- printk(KERN_ERR "capidrv: %s: ncci 0x%x not found\n",
+ printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n",
+ card->contrnr,
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
cmsg->adr.adrNCCI);
}
@@ -1293,7 +1356,8 @@ static void handle_data(_cmsg * cmsg, struct sk_buff *skb)
return;
}
if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) {
- printk(KERN_ERR "capidrv: %s: ncci 0x%x not found\n",
+ printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n",
+ card->contrnr,
capi_cmd2str(cmsg->Command, cmsg->Subcommand),
cmsg->adr.adrNCCI);
kfree_skb(skb);
@@ -1314,7 +1378,8 @@ static void capidrv_signal(__u16 applid, __u32 dummy)
while ((*capifuncs->capi_get_message) (global.appid, &skb) == CAPI_NOERROR) {
capi_message2cmsg(&s_cmsg, skb->data);
if (debugmode > 1)
- printk(KERN_DEBUG "capidrv_signal: %s\n", capi_cmsg2str(&s_cmsg));
+ printk(KERN_DEBUG "capidrv_signal: applid=%d %s\n",
+ applid, capi_cmsg2str(&s_cmsg));
if (s_cmsg.Command == CAPI_DATA_B3
&& s_cmsg.Subcommand == CAPI_IND) {
@@ -1348,7 +1413,8 @@ static void handle_dtrace_data(capidrv_contr *card,
isdn_ctrl cmd;
if (!len) {
- printk(KERN_DEBUG "avmb1_q931_data: len == %d\n", len);
+ printk(KERN_DEBUG "capidrv-%d: avmb1_q931_data: len == %d\n",
+ card->contrnr, len);
return;
}
@@ -1393,7 +1459,8 @@ static int capidrv_ioctl(isdn_ctrl * c, capidrv_contr * card)
{
switch (c->arg) {
default:
- printk(KERN_DEBUG "capidrv: capidrv_ioctl(%ld) called ??\n", c->arg);
+ printk(KERN_DEBUG "capidrv-%d: capidrv_ioctl(%ld) called ??\n",
+ card->contrnr, c->arg);
return -EINVAL;
}
return -EINVAL;
@@ -1414,7 +1481,8 @@ static int capidrv_command(isdn_ctrl * c, capidrv_contr * card)
__u8 called[ISDN_MSNLEN + 2];
if (debugmode)
- printk(KERN_DEBUG "capidrv: ISDN_CMD_DIAL(ch=%ld,\"%s,%d,%d,%s\")\n",
+ printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_DIAL(ch=%ld,\"%s,%d,%d,%s\")\n",
+ card->contrnr,
c->arg,
c->parm.setup.phone,
c->parm.setup.si1,
@@ -1424,7 +1492,8 @@ static int capidrv_command(isdn_ctrl * c, capidrv_contr * card)
bchan = &card->bchans[c->arg % card->nbchan];
if (bchan->plcip) {
- printk(KERN_ERR "capidrv: dail ch=%ld,\"%s,%d,%d,%s\" in use (plci=0x%x)\n",
+ printk(KERN_ERR "capidrv-%d: dail ch=%ld,\"%s,%d,%d,%s\" in use (plci=0x%x)\n",
+ card->contrnr,
c->arg,
c->parm.setup.phone,
c->parm.setup.si1,
@@ -1486,10 +1555,11 @@ static int capidrv_command(isdn_ctrl * c, capidrv_contr * card)
case ISDN_CMD_ACCEPTD:
- if (debugmode)
- printk(KERN_DEBUG "capidrv: ISDN_CMD_ACCEPTD(ch=%ld)\n",
- c->arg);
bchan = &card->bchans[c->arg % card->nbchan];
+ if (debugmode)
+ printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTD(ch=%ld) l2=%d l3=%d\n",
+ card->contrnr,
+ c->arg, bchan->l2, bchan->l3);
capi_fill_CONNECT_RESP(&cmdcmsg,
global.appid,
@@ -1517,19 +1587,22 @@ static int capidrv_command(isdn_ctrl * c, capidrv_contr * card)
case ISDN_CMD_ACCEPTB:
if (debugmode)
- printk(KERN_DEBUG "capidrv: ISDN_CMD_ACCEPTB(ch=%ld)\n",
+ printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTB(ch=%ld)\n",
+ card->contrnr,
c->arg);
return -ENOSYS;
case ISDN_CMD_HANGUP:
if (debugmode)
- printk(KERN_DEBUG "capidrv: ISDN_CMD_HANGUP(ch=%ld)\n",
+ printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_HANGUP(ch=%ld)\n",
+ card->contrnr,
c->arg);
bchan = &card->bchans[c->arg % card->nbchan];
if (bchan->disconnecting) {
if (debugmode)
- printk(KERN_DEBUG "capidrv: chan %ld already disconnecting ...\n",
+ printk(KERN_DEBUG "capidrv-%d: chan %ld already disconnecting ...\n",
+ card->contrnr,
c->arg);
return 0;
}
@@ -1568,23 +1641,26 @@ static int capidrv_command(isdn_ctrl * c, capidrv_contr * card)
case ISDN_CMD_SETL2:
if (debugmode)
- printk(KERN_DEBUG "capidrv: set L2 on chan %ld to %ld\n",
+ printk(KERN_DEBUG "capidrv-%d: set L2 on chan %ld to %ld\n",
+ card->contrnr,
(c->arg & 0xff), (c->arg >> 8));
- bchan = &card->bchans[c->arg % card->nbchan];
+ bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];
bchan->l2 = (c->arg >> 8);
return 0;
case ISDN_CMD_SETL3:
if (debugmode)
- printk(KERN_DEBUG "capidrv: set L3 on chan %ld to %ld\n",
+ printk(KERN_DEBUG "capidrv-%d: set L3 on chan %ld to %ld\n",
+ card->contrnr,
(c->arg & 0xff), (c->arg >> 8));
- bchan = &card->bchans[c->arg % card->nbchan];
+ bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];
bchan->l3 = (c->arg >> 8);
return 0;
case ISDN_CMD_SETEAZ:
if (debugmode)
- printk(KERN_DEBUG "capidrv: set EAZ \"%s\" on chan %ld\n",
+ printk(KERN_DEBUG "capidrv-%d: set EAZ \"%s\" on chan %ld\n",
+ card->contrnr,
c->parm.num, c->arg);
bchan = &card->bchans[c->arg % card->nbchan];
strncpy(bchan->msn, c->parm.num, ISDN_MSNLEN);
@@ -1592,46 +1668,54 @@ static int capidrv_command(isdn_ctrl * c, capidrv_contr * card)
case ISDN_CMD_CLREAZ:
if (debugmode)
- printk(KERN_DEBUG "capidrv: clearing EAZ on chan %ld\n", c->arg);
+ printk(KERN_DEBUG "capidrv-%d: clearing EAZ on chan %ld\n",
+ card->contrnr, c->arg);
bchan = &card->bchans[c->arg % card->nbchan];
bchan->msn[0] = 0;
return 0;
case ISDN_CMD_LOCK:
if (debugmode > 1)
- printk(KERN_DEBUG "capidrv: ISDN_CMD_LOCK (%ld)\n", c->arg);
+ printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_LOCK (%ld)\n", card->contrnr, c->arg);
MOD_INC_USE_COUNT;
break;
case ISDN_CMD_UNLOCK:
if (debugmode > 1)
- printk(KERN_DEBUG "capidrv: ISDN_CMD_UNLOCK (%ld)\n", c->arg);
+ printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_UNLOCK (%ld)\n",
+ card->contrnr, c->arg);
MOD_DEC_USE_COUNT;
break;
/* never called */
case ISDN_CMD_GETL2:
if (debugmode)
- printk(KERN_DEBUG "capidrv: ISDN_CMD_GETL2\n");
+ printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL2\n",
+ card->contrnr);
return -ENODEV;
case ISDN_CMD_GETL3:
if (debugmode)
- printk(KERN_DEBUG "capidrv: ISDN_CMD_GETL3\n");
+ printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL3\n",
+ card->contrnr);
return -ENODEV;
case ISDN_CMD_GETEAZ:
if (debugmode)
- printk(KERN_DEBUG "capidrv: ISDN_CMD_GETEAZ\n");
+ printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETEAZ\n",
+ card->contrnr);
return -ENODEV;
case ISDN_CMD_SETSIL:
if (debugmode)
- printk(KERN_DEBUG "capidrv: ISDN_CMD_SETSIL\n");
+ printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_SETSIL\n",
+ card->contrnr);
return -ENODEV;
case ISDN_CMD_GETSIL:
if (debugmode)
- printk(KERN_DEBUG "capidrv: ISDN_CMD_GETSIL\n");
+ printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETSIL\n",
+ card->contrnr);
return -ENODEV;
default:
- printk(KERN_ERR "capidrv: ISDN_CMD_%d, Huh?\n", c->command);
+ printk(KERN_ERR "capidrv-%d: ISDN_CMD_%d, Huh?\n",
+ card->contrnr, c->command);
return -EINVAL;
}
return 0;
@@ -1645,8 +1729,8 @@ static int if_command(isdn_ctrl * c)
return capidrv_command(c, card);
printk(KERN_ERR
- "capidrv: if_command %d called with invalid driverId %d!\n",
- c->command, c->driver);
+ "capidrv-%d: if_command %d called with invalid driverId %d!\n",
+ card->contrnr, c->command, c->driver);
return -ENODEV;
}
@@ -1663,15 +1747,15 @@ static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb)
__u16 datahandle;
if (!card) {
- printk(KERN_ERR "capidrv: if_sendbuf called with invalid driverId %d!\n",
- id);
+ printk(KERN_ERR "capidrv-%d: if_sendbuf called with invalid driverId %d!\n",
+ card->contrnr, id);
return 0;
}
bchan = &card->bchans[channel % card->nbchan];
nccip = bchan->nccip;
if (!nccip || nccip->state != ST_NCCI_ACTIVE) {
- printk(KERN_ERR "capidrv: if_sendbuf: %s:%d: chan not up!\n",
- card->name, channel);
+ printk(KERN_ERR "capidrv-%d: if_sendbuf: %s:%d: chan not up!\n",
+ card->contrnr, card->name, channel);
return 0;
}
datahandle = nccip->datahandle;
@@ -1691,13 +1775,14 @@ static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb)
if (skb_headroom(skb) < msglen) {
struct sk_buff *nskb = dev_alloc_skb(msglen + skb->len);
if (!nskb) {
- printk(KERN_ERR "capidrv: if_sendbuf: no memory\n");
+ printk(KERN_ERR "capidrv-%d: if_sendbuf: no memory\n",
+ card->contrnr);
(void)capidrv_del_ack(nccip, datahandle);
return 0;
}
#if 0
- printk(KERN_DEBUG "capidrv: only %d bytes headroom\n",
- skb_headroom(skb));
+ printk(KERN_DEBUG "capidrv-%d: only %d bytes headroom\n",
+ card->contrnr, skb_headroom(skb));
#endif
memcpy(skb_put(nskb, msglen), sendcmsg.buf, msglen);
memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
@@ -1729,8 +1814,8 @@ static int if_readstat(__u8 *buf, int len, int user, int id, int channel)
__u8 *p;
if (!card) {
- printk(KERN_ERR "capidrv: if_readstat called with invalid driverId %d!\n",
- id);
+ printk(KERN_ERR "capidrv-%d: if_readstat called with invalid driverId %d!\n",
+ card->contrnr, id);
return -ENODEV;
}
@@ -1776,7 +1861,7 @@ static void enable_dchannel_trace(capidrv_contr *card)
avmversion[1] |= (version.minormanuversion >> 4) & 0x0f;
avmversion[2] |= version.minormanuversion & 0x0f;
- if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 5)) {
+ if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 6)) {
printk(KERN_INFO "%s: D2 trace enabled\n", card->name);
capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid,
card->msgid++,
@@ -1878,7 +1963,8 @@ static int capidrv_addcontr(__u16 contr, struct capi_profile *profp)
printk(KERN_INFO "%s: now up (%d B channels)\n",
card->name, card->nbchan);
- enable_dchannel_trace(card);
+ if (card->nbchan == 2) /* no T1 */
+ enable_dchannel_trace(card);
return 0;
}
@@ -1965,8 +2051,8 @@ int capidrv_init(void)
} else
strcpy(rev, " ??? ");
- rparam.level3cnt = 2;
- rparam.datablkcnt = 8;
+ rparam.level3cnt = -2; /* number of bchannels twice */
+ rparam.datablkcnt = 16;
rparam.datablklen = 2048;
errcode = (*capifuncs->capi_register) (&rparam, &global.appid);
if (errcode) {
diff --git a/drivers/isdn/avmb1/capidrv.h b/drivers/isdn/avmb1/capidrv.h
index f30c3f4dd..2e5abf04b 100644
--- a/drivers/isdn/avmb1/capidrv.h
+++ b/drivers/isdn/avmb1/capidrv.h
@@ -1,11 +1,22 @@
/*
- * $Id: capidrv.h,v 1.1 1997/03/04 21:50:33 calle Exp $
+ * $Id: capidrv.h,v 1.2 1998/03/29 16:06:06 calle Exp $
*
* ISDN4Linux Driver, using capi20 interface (kernelcapi)
*
* Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: capidrv.h,v $
+ * Revision 1.2 1998/03/29 16:06:06 calle
+ * changes from 2.0 tree merged.
+ *
+ * Revision 1.1.2.1 1998/03/20 14:38:28 calle
+ * capidrv: prepared state machines for suspend/resume/hold
+ * capidrv: fix bug in state machine if B1/T1 is out of nccis
+ * b1capi: changed some errno returns.
+ * b1capi: detect if you try to add same T1 to different io address.
+ * b1capi: change number of nccis depending on number of channels.
+ * b1lli: cosmetics
+ *
* Revision 1.1 1997/03/04 21:50:33 calle
* Frirst version in isdn4linux
*
@@ -49,34 +60,70 @@
#define ST_PLCI_ACCEPTING 6 /* P-4 */
#define ST_PLCI_DISCONNECTING 7 /* P-5 */
#define ST_PLCI_DISCONNECTED 8 /* P-6 */
+#define ST_PLCI_RESUMEING 9 /* P-0.Res */
+#define ST_PLCI_RESUME 10 /* P-Res */
+#define ST_PLCI_HELD 11 /* P-HELD */
-#define EV_PLCI_CONNECT_REQ 1 /* P-0 -> P-0.1 */
-#define EV_PLCI_CONNECT_CONF_ERROR 2 /* P-0.1 -> P-0 */
-#define EV_PLCI_CONNECT_CONF_OK 3 /* P-0.1 -> P-1 */
-#define EV_PLCI_FACILITY_IND_UP 4 /* P-0 -> P-1 */
-#define EV_PLCI_CONNECT_IND 5 /* P-0 -> P-2 */
-#define EV_PLCI_CONNECT_ACTIVE_IND 6 /* P-1 -> P-ACT */
+#define EV_PLCI_CONNECT_REQ 1 /* P-0 -> P-0.1
+ */
+#define EV_PLCI_CONNECT_CONF_ERROR 2 /* P-0.1 -> P-0
+ */
+#define EV_PLCI_CONNECT_CONF_OK 3 /* P-0.1 -> P-1
+ */
+#define EV_PLCI_FACILITY_IND_UP 4 /* P-0 -> P-1
+ */
+#define EV_PLCI_CONNECT_IND 5 /* P-0 -> P-2
+ */
+#define EV_PLCI_CONNECT_ACTIVE_IND 6 /* P-1 -> P-ACT
+ */
#define EV_PLCI_CONNECT_REJECT 7 /* P-2 -> P-5
- P-3 -> P-5 */
+ P-3 -> P-5
+ */
#define EV_PLCI_DISCONNECT_REQ 8 /* P-1 -> P-5
P-2 -> P-5
P-3 -> P-5
P-4 -> P-5
- P-ACT -> P-5 */
+ P-ACT -> P-5
+ P-Res -> P-5 (*)
+ P-HELD -> P-5 (*)
+ */
#define EV_PLCI_DISCONNECT_IND 9 /* P-1 -> P-6
P-2 -> P-6
P-3 -> P-6
P-4 -> P-6
P-5 -> P-6
- P-ACT -> P-6 */
+ P-ACT -> P-6
+ P-Res -> P-6 (*)
+ P-HELD -> P-6 (*)
+ */
#define EV_PLCI_FACILITY_IND_DOWN 10 /* P-0.1 -> P-5
P-1 -> P-5
P-ACT -> P-5
P-2 -> P-5
P-3 -> P-5
- P-4 -> P-5 */
-#define EV_PLCI_DISCONNECT_RESP 11 /* P-6 -> P-0 */
-#define EV_PLCI_CONNECT_RESP 12 /* P-6 -> P-0 */
+ P-4 -> P-5
+ */
+#define EV_PLCI_DISCONNECT_RESP 11 /* P-6 -> P-0
+ */
+#define EV_PLCI_CONNECT_RESP 12 /* P-6 -> P-0
+ */
+
+#define EV_PLCI_RESUME_REQ 13 /* P-0 -> P-0.Res
+ */
+#define EV_PLCI_RESUME_CONF_OK 14 /* P-0.Res -> P-Res
+ */
+#define EV_PLCI_RESUME_CONF_ERROR 15 /* P-0.Res -> P-0
+ */
+#define EV_PLCI_RESUME_IND 16 /* P-Res -> P-ACT
+ */
+#define EV_PLCI_HOLD_IND 17 /* P-ACT -> P-HELD
+ */
+#define EV_PLCI_RETRIEVE_IND 18 /* P-HELD -> P-ACT
+ */
+#define EV_PLCI_SUSPEND_IND 19 /* P-ACT -> P-5
+ */
+#define EV_PLCI_CD_IND 20 /* P-2 -> P-5
+ */
/*
* per ncci state machine
diff --git a/drivers/isdn/avmb1/compat.h b/drivers/isdn/avmb1/compat.h
index 41ad2b626..15f471559 100644
--- a/drivers/isdn/avmb1/compat.h
+++ b/drivers/isdn/avmb1/compat.h
@@ -1,11 +1,14 @@
/*
- * $Id: compat.h,v 1.3 1997/11/04 06:12:15 calle Exp $
+ * $Id: compat.h,v 1.4 1998/10/25 14:39:02 fritz Exp $
*
* Headerfile for Compartibility between different kernel versions
*
* (c) Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: compat.h,v $
+ * Revision 1.4 1998/10/25 14:39:02 fritz
+ * Backported from MIPS (Cobalt).
+ *
* Revision 1.3 1997/11/04 06:12:15 calle
* capi.c: new read/write in file_ops since 2.1.60
* capidrv.c: prepared isdnlog interface for d2-trace in newer firmware.
@@ -32,6 +35,7 @@
#define __COMPAT_H__
#include <linux/version.h>
+#include <asm/segment.h>
#include <linux/isdnif.h>
#ifndef LinuxVersionCode
diff --git a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile
index da07e7b8c..9e7cb7773 100644
--- a/drivers/isdn/hisax/Makefile
+++ b/drivers/isdn/hisax/Makefile
@@ -8,7 +8,7 @@ L_TARGET :=
O_TARGET :=
O_OBJS := isdnl1.o tei.o isdnl2.o isdnl3.o \
- lmgr.o q931.o callc.o fsm.o
+ lmgr.o q931.o callc.o fsm.o cert.o
# EXTRA_CFLAGS += -S
@@ -27,6 +27,7 @@ endif
ISAC_OBJ :=
ARCOFI_OBJ :=
HSCX_OBJ :=
+ISAR_OBJ :=
HFC_OBJ :=
HFC_2BDS0 :=
RAWHDLC_OBJ :=
@@ -43,12 +44,36 @@ ifeq ($(CONFIG_HISAX_16_3),y)
HSCX_OBJ := hscx.o
endif
+ifeq ($(CONFIG_HISAX_TELESPCI),y)
+ O_OBJS += telespci.o
+ ISAC_OBJ := isac.o
+ HSCX_OBJ := hscx.o
+endif
+
+ifeq ($(CONFIG_HISAX_S0BOX),y)
+ O_OBJS += s0box.o
+ ISAC_OBJ := isac.o
+ HSCX_OBJ := hscx.o
+endif
+
ifeq ($(CONFIG_HISAX_AVM_A1),y)
O_OBJS += avm_a1.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
endif
+ifeq ($(CONFIG_HISAX_AVM_A1_PCMCIA),y)
+ O_OBJS += avm_a1p.o
+ ISAC_OBJ := isac.o
+ HSCX_OBJ := hscx.o
+endif
+
+ifeq ($(CONFIG_HISAX_FRITZPCI),y)
+ O_OBJS += avm_pci.o
+ ISAC_OBJ := isac.o
+endif
+
+
ifeq ($(CONFIG_HISAX_ELSA),y)
O_OBJS += elsa.o
ISAC_OBJ := isac.o
@@ -84,6 +109,7 @@ ifeq ($(CONFIG_HISAX_SEDLBAUER),y)
O_OBJS += sedlbauer.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
+ ISAR_OBJ := isar.o
endif
ifeq ($(CONFIG_HISAX_SPORTSTER),y)
@@ -101,6 +127,7 @@ endif
ifeq ($(CONFIG_HISAX_NETJET),y)
O_OBJS += netjet.o
ISAC_OBJ := isac.o
+# RAWHDLC_OBJ := rawhdlc.o
endif
ifeq ($(CONFIG_HISAX_TELES3C),y)
@@ -108,10 +135,8 @@ ifeq ($(CONFIG_HISAX_TELES3C),y)
HFC_2BDS0 := hfc_2bds0.o
endif
ifeq ($(CONFIG_HISAX_AMD7930),y)
- RAWHDLC_OBJ := foreign.o rawhdlc.o
-endif
-ifeq ($(CONFIG_HISAX_DBRI),y)
- RAWHDLC_OBJ := foreign.o rawhdlc.o
+ O_OBJS += amd7930.o
+ RAWHDLC_OBJ := rawhdlc.o
endif
ifeq ($(CONFIG_HISAX_NICCY),y)
@@ -120,7 +145,8 @@ ifeq ($(CONFIG_HISAX_NICCY),y)
HSCX_OBJ := hscx.o
endif
-O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(HFC_OBJ) $(ARCOFI_OBJ) $(HFC_2BDS0) $(RAWHDLC_OBJ)
+O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(ISAR_OBJ) $(ARCOFI_OBJ)
+O_OBJS += $(HFC_OBJ) $(HFC_2BDS0) $(RAWHDLC_OBJ)
OX_OBJS += config.o
O_TARGET :=
@@ -134,4 +160,14 @@ else
endif
endif
+
include $(TOPDIR)/Rules.make
+
+MD5FILES += isac.c isdnl1.c isdnl2.c isdnl3.c \
+ tei.c callc.c cert.c l3dss1.c l3_1tr6.c elsa.c
+
+CERT = $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?)
+
+cert.o: $(MD5FILES) md5sums.asc
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -D CERTIFICATION=$(CERT) -c -o cert.o cert.c
+
diff --git a/drivers/isdn/hisax/arcofi.c b/drivers/isdn/hisax/arcofi.c
index 1717b3a27..a7c091321 100644
--- a/drivers/isdn/hisax/arcofi.c
+++ b/drivers/isdn/hisax/arcofi.c
@@ -1,12 +1,28 @@
-/* $Id: arcofi.c,v 1.1 1997/10/29 18:51:20 keil Exp $
+/* $Id: arcofi.c,v 1.6 1998/09/30 22:21:56 keil Exp $
- * arcofi.h Ansteuerung ARCOFI 2165
+ * arcofi.c Ansteuerung ARCOFI 2165
*
* Author Karsten Keil (keil@temic-ech.spacenet.de)
*
*
*
* $Log: arcofi.c,v $
+ * Revision 1.6 1998/09/30 22:21:56 keil
+ * cosmetics
+ *
+ * Revision 1.5 1998/09/27 12:52:57 keil
+ * cosmetics
+ *
+ * Revision 1.4 1998/08/20 13:50:24 keil
+ * More support for hybrid modem (not working yet)
+ *
+ * Revision 1.3 1998/05/25 12:57:38 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.2 1998/04/15 16:47:16 keil
+ * new interface
+ *
* Revision 1.1 1997/10/29 18:51:20 keil
* New files
*
@@ -18,18 +34,25 @@
#include "isac.h"
int
-send_arcofi(struct IsdnCardState *cs, const u_char *msg) {
+send_arcofi(struct IsdnCardState *cs, const u_char *msg, int bc, int receive) {
u_char val;
- char tmp[32];
long flags;
- int cnt=2;
+ int cnt=30;
cs->mon_txp = 0;
cs->mon_txc = msg[0];
memcpy(cs->mon_tx, &msg[1], cs->mon_txc);
+ switch(bc) {
+ case 0: break;
+ case 1: cs->mon_tx[1] |= 0x40;
+ break;
+ default: break;
+ }
cs->mocr &= 0x0f;
cs->mocr |= 0xa0;
test_and_clear_bit(HW_MON1_TX_END, &cs->HW_Flags);
+ if (receive)
+ test_and_clear_bit(HW_MON1_RX_END, &cs->HW_Flags);
cs->writeisac(cs, ISAC_MOCR, cs->mocr);
val = cs->readisac(cs, ISAC_MOSR);
cs->writeisac(cs, ISAC_MOX1, cs->mon_tx[cs->mon_txp++]);
@@ -39,12 +62,18 @@ send_arcofi(struct IsdnCardState *cs, const u_char *msg) {
sti();
while (cnt && !test_bit(HW_MON1_TX_END, &cs->HW_Flags)) {
cnt--;
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
+ udelay(500);
+ }
+ if (receive) {
+ while (cnt && !test_bit(HW_MON1_RX_END, &cs->HW_Flags)) {
+ cnt--;
+ udelay(500);
+ }
}
restore_flags(flags);
- sprintf(tmp, "arcofi tout %d", cnt);
- debugl1(cs, tmp);
+ if (cnt <= 0) {
+ printk(KERN_WARNING"HiSax arcofi monitor timed out\n");
+ debugl1(cs, "HiSax arcofi monitor timed out");
+ }
return(cnt);
}
-
diff --git a/drivers/isdn/hisax/arcofi.h b/drivers/isdn/hisax/arcofi.h
index 5e1bb9e99..be1097d15 100644
--- a/drivers/isdn/hisax/arcofi.h
+++ b/drivers/isdn/hisax/arcofi.h
@@ -1,4 +1,4 @@
-/* $Id: arcofi.h,v 1.1 1997/10/29 18:51:20 keil Exp $
+/* $Id: arcofi.h,v 1.3 1998/05/25 12:57:39 keil Exp $
* arcofi.h Ansteuerung ARCOFI 2165
*
@@ -7,6 +7,13 @@
*
*
* $Log: arcofi.h,v $
+ * Revision 1.3 1998/05/25 12:57:39 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.2 1998/04/15 16:47:17 keil
+ * new interface
+ *
* Revision 1.1 1997/10/29 18:51:20 keil
* New files
*
@@ -14,4 +21,4 @@
#define ARCOFI_USE 1
-extern int send_arcofi(struct IsdnCardState *cs, const u_char *msg);
+extern int send_arcofi(struct IsdnCardState *cs, const u_char *msg, int bc, int receive);
diff --git a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c
index 6980a2888..4990f9eb8 100644
--- a/drivers/isdn/hisax/asuscom.c
+++ b/drivers/isdn/hisax/asuscom.c
@@ -1,13 +1,22 @@
-/* $Id: asuscom.c,v 1.2 1998/02/02 13:27:06 keil Exp $
+/* $Id: asuscom.c,v 1.5 1998/11/15 23:54:19 keil Exp $
* asuscom.c low level stuff for ASUSCOM NETWORK INC. ISDNLink cards
*
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
*
* Thanks to ASUSCOM NETWORK INC. Taiwan and Dynalink NL for informations
*
*
* $Log: asuscom.c,v $
+ * Revision 1.5 1998/11/15 23:54:19 keil
+ * changes from 2.0
+ *
+ * Revision 1.4 1998/06/18 23:18:20 keil
+ * Support for new IPAC card
+ *
+ * Revision 1.3 1998/04/15 16:46:53 keil
+ * new init code
+ *
* Revision 1.2 1998/02/02 13:27:06 keil
* New
*
@@ -17,12 +26,13 @@
#define __NO_VERSION__
#include "hisax.h"
#include "isac.h"
+#include "ipac.h"
#include "hscx.h"
#include "isdnl1.h"
extern const char *CardType[];
-const char *Asuscom_revision = "$Revision: 1.2 $";
+const char *Asuscom_revision = "$Revision: 1.5 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -33,6 +43,12 @@ const char *Asuscom_revision = "$Revision: 1.2 $";
#define ASUS_CTRL_U7 3
#define ASUS_CTRL_POTS 5
+#define ASUS_IPAC_ALE 0
+#define ASUS_IPAC_DATA 1
+
+#define ASUS_ISACHSCX 1
+#define ASUS_IPAC 2
+
/* CARD_ADR (Write) */
#define ASUS_RESET 0x80 /* Bit 7 Reset-Leitung */
@@ -107,6 +123,30 @@ WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
}
static u_char
+ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
+{
+ return (readreg(cs->hw.asus.adr, cs->hw.asus.isac, offset|0x80));
+}
+
+static void
+WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+ writereg(cs->hw.asus.adr, cs->hw.asus.isac, offset|0x80, value);
+}
+
+static void
+ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+ readfifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size);
+}
+
+static void
+WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+ writefifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size);
+}
+
+static u_char
ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
{
return (readreg(cs->hw.asus.adr,
@@ -183,6 +223,52 @@ asuscom_interrupt(int intno, void *dev_id, struct pt_regs *regs)
}
}
+static void
+asuscom_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+{
+ struct IsdnCardState *cs = dev_id;
+ u_char ista, val, icnt = 20;
+
+ if (!cs) {
+ printk(KERN_WARNING "ISDNLink: Spurious interrupt!\n");
+ return;
+ }
+ ista = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA);
+Start_IPAC:
+ if (cs->debug & L1_DEB_IPAC)
+ debugl1(cs, "IPAC ISTA %02X", ista);
+ if (ista & 0x0f) {
+ val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
+ if (ista & 0x01)
+ val |= 0x01;
+ if (ista & 0x04)
+ val |= 0x02;
+ if (ista & 0x08)
+ val |= 0x04;
+ if (val)
+ hscx_int_main(cs, val);
+ }
+ if (ista & 0x20) {
+ val = 0xfe & readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA | 0x80);
+ if (val) {
+ isac_interrupt(cs, val);
+ }
+ }
+ if (ista & 0x10) {
+ val = 0x01;
+ isac_interrupt(cs, val);
+ }
+ ista = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA);
+ if ((ista & 0x3f) && icnt) {
+ icnt--;
+ goto Start_IPAC;
+ }
+ if (!icnt)
+ printk(KERN_WARNING "ASUS IRQ LOOP\n");
+ writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xFF);
+ writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xC0);
+}
+
void
release_io_asuscom(struct IsdnCardState *cs)
{
@@ -197,14 +283,27 @@ reset_asuscom(struct IsdnCardState *cs)
{
long flags;
- byteout(cs->hw.asus.adr, ASUS_RESET); /* Reset On */
+ if (cs->subtyp == ASUS_IPAC)
+ writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x20);
+ else
+ byteout(cs->hw.asus.adr, ASUS_RESET); /* Reset On */
save_flags(flags);
sti();
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(1);
- byteout(cs->hw.asus.adr, 0); /* Reset Off */
+ if (cs->subtyp == ASUS_IPAC)
+ writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x0);
+ else
+ byteout(cs->hw.asus.adr, 0); /* Reset Off */
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(1);
+ if (cs->subtyp == ASUS_IPAC) {
+ writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_CONF, 0x0);
+ writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ACFG, 0xff);
+ writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_AOE, 0x0);
+ writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xc0);
+ writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_PCFG, 0x12);
+ }
restore_flags(flags);
}
@@ -219,13 +318,15 @@ Asus_card_msg(struct IsdnCardState *cs, int mt, void *arg)
release_io_asuscom(cs);
return(0);
case CARD_SETIRQ:
- return(request_irq(cs->irq, &asuscom_interrupt,
+ if (cs->subtyp == ASUS_IPAC)
+ return(request_irq(cs->irq, &asuscom_interrupt_ipac,
+ I4L_IRQ_FLAG, "HiSax", cs));
+ else
+ return(request_irq(cs->irq, &asuscom_interrupt,
I4L_IRQ_FLAG, "HiSax", cs));
case CARD_INIT:
- clear_pending_isac_ints(cs);
- clear_pending_hscx_ints(cs);
- initisac(cs);
- inithscx(cs);
+ cs->debug |= L1_DEB_IPAC;
+ inithscxisac(cs, 3);
return(0);
case CARD_TEST:
return(0);
@@ -238,6 +339,7 @@ setup_asuscom(struct IsdnCard *card))
{
int bytecnt;
struct IsdnCardState *cs = card->cs;
+ u_char val;
char tmp[64];
strcpy(tmp, Asuscom_revision);
@@ -248,12 +350,6 @@ setup_asuscom(struct IsdnCard *card))
bytecnt = 8;
cs->hw.asus.cfg_reg = card->para[1];
cs->irq = card->para[0];
- cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR;
- cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC;
- cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX;
- cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7;
- cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS;
-
if (check_region((cs->hw.asus.cfg_reg), bytecnt)) {
printk(KERN_WARNING
"HiSax: %s config port %x-%x already in use\n",
@@ -264,27 +360,45 @@ setup_asuscom(struct IsdnCard *card))
} else {
request_region(cs->hw.asus.cfg_reg, bytecnt, "asuscom isdn");
}
-
- printk(KERN_INFO
- "ISDNLink: defined at 0x%x IRQ %d\n",
- cs->hw.asus.cfg_reg,
- cs->irq);
- printk(KERN_INFO "ISDNLink: resetting card\n");
- reset_asuscom(cs);
- cs->readisac = &ReadISAC;
- cs->writeisac = &WriteISAC;
- cs->readisacfifo = &ReadISACfifo;
- cs->writeisacfifo = &WriteISACfifo;
+ printk(KERN_INFO "ISDNLink: defined at 0x%x IRQ %d\n",
+ cs->hw.asus.cfg_reg, cs->irq);
cs->BC_Read_Reg = &ReadHSCX;
cs->BC_Write_Reg = &WriteHSCX;
cs->BC_Send_Data = &hscx_fill_fifo;
cs->cardmsg = &Asus_card_msg;
- ISACVersion(cs, "ISDNLink:");
- if (HscxVersion(cs, "ISDNLink:")) {
- printk(KERN_WARNING
- "ISDNLink: wrong HSCX versions check IO address\n");
- release_io_asuscom(cs);
- return (0);
+ val = readreg(cs->hw.asus.cfg_reg + ASUS_IPAC_ALE,
+ cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID);
+ if (val == 1) {
+ cs->subtyp = ASUS_IPAC;
+ cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE;
+ cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
+ cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
+ test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+ cs->readisac = &ReadISAC_IPAC;
+ cs->writeisac = &WriteISAC_IPAC;
+ cs->readisacfifo = &ReadISACfifo_IPAC;
+ cs->writeisacfifo = &WriteISACfifo_IPAC;
+ printk(KERN_INFO "Asus: IPAC version %x\n", val);
+ } else {
+ cs->subtyp = ASUS_ISACHSCX;
+ cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR;
+ cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC;
+ cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX;
+ cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7;
+ cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS;
+ cs->readisac = &ReadISAC;
+ cs->writeisac = &WriteISAC;
+ cs->readisacfifo = &ReadISACfifo;
+ cs->writeisacfifo = &WriteISACfifo;
+ ISACVersion(cs, "ISDNLink:");
+ if (HscxVersion(cs, "ISDNLink:")) {
+ printk(KERN_WARNING
+ "ISDNLink: wrong HSCX versions check IO address\n");
+ release_io_asuscom(cs);
+ return (0);
+ }
}
+ printk(KERN_INFO "ISDNLink: resetting card\n");
+ reset_asuscom(cs);
return (1);
}
diff --git a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c
index 464bc33fd..5c5f944d4 100644
--- a/drivers/isdn/hisax/avm_a1.c
+++ b/drivers/isdn/hisax/avm_a1.c
@@ -1,11 +1,20 @@
-/* $Id: avm_a1.c,v 2.7 1998/02/02 13:29:37 keil Exp $
+/* $Id: avm_a1.c,v 2.10 1998/11/15 23:54:21 keil Exp $
* avm_a1.c low level stuff for AVM A1 (Fritz) isdn cards
*
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
*
*
* $Log: avm_a1.c,v $
+ * Revision 2.10 1998/11/15 23:54:21 keil
+ * changes from 2.0
+ *
+ * Revision 2.9 1998/08/13 23:36:12 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.8 1998/04/15 16:44:27 keil
+ * new init code
+ *
* Revision 2.7 1998/02/02 13:29:37 keil
* fast io
*
@@ -57,7 +66,7 @@
#include "isdnl1.h"
extern const char *CardType[];
-const char *avm_revision = "$Revision: 2.7 $";
+static const char *avm_revision = "$Revision: 2.10 $";
#define AVM_A1_STAT_ISAC 0x01
#define AVM_A1_STAT_HSCX 0x02
@@ -145,7 +154,6 @@ avm_a1_interrupt(int intno, void *dev_id, struct pt_regs *regs)
{
struct IsdnCardState *cs = dev_id;
u_char val, sval, stat = 0;
- char tmp[32];
if (!cs) {
printk(KERN_WARNING "AVM A1: Spurious interrupt!\n");
@@ -155,10 +163,8 @@ avm_a1_interrupt(int intno, void *dev_id, struct pt_regs *regs)
if (!(sval & AVM_A1_STAT_TIMER)) {
byteout(cs->hw.avm.cfg_reg, 0x1E);
sval = bytein(cs->hw.avm.cfg_reg);
- } else if (cs->debug & L1_DEB_INTSTAT) {
- sprintf(tmp, "avm IntStatus %x", sval);
- debugl1(cs, tmp);
- }
+ } else if (cs->debug & L1_DEB_INTSTAT)
+ debugl1(cs, "avm IntStatus %x", sval);
if (!(sval & AVM_A1_STAT_HSCX)) {
val = readreg(cs->hw.avm.hscx[1], HSCX_ISTA);
if (val) {
@@ -217,10 +223,10 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(request_irq(cs->irq, &avm_a1_interrupt,
I4L_IRQ_FLAG, "HiSax", cs));
case CARD_INIT:
- clear_pending_isac_ints(cs);
- clear_pending_hscx_ints(cs);
- initisac(cs);
- inithscx(cs);
+ inithscxisac(cs, 1);
+ byteout(cs->hw.avm.cfg_reg, 0x16);
+ byteout(cs->hw.avm.cfg_reg, 0x1E);
+ inithscxisac(cs, 2);
return(0);
case CARD_TEST:
return(0);
@@ -348,7 +354,6 @@ setup_avm_a1(struct IsdnCard *card))
val = bytein(cs->hw.avm.cfg_reg + 2);
printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
cs->hw.avm.cfg_reg + 2, val);
- byteout(cs->hw.avm.cfg_reg, 0x1E);
val = bytein(cs->hw.avm.cfg_reg);
printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
cs->hw.avm.cfg_reg, val);
diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c
index bcd305058..bf09acd20 100644
--- a/drivers/isdn/hisax/callc.c
+++ b/drivers/isdn/hisax/callc.c
@@ -1,12 +1,61 @@
-/* $Id: callc.c,v 2.13 1998/02/12 23:07:16 keil Exp $
+/* $Id: callc.c,v 2.25 1999/01/02 11:17:20 keil Exp $
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
* based on the teles driver from Jan den Ouden
*
+ * This file is (c) under GNU PUBLIC LICENSE
+ * For changes and modifications please read
+ * ../../../Documentation/isdn/HiSax.cert
+ *
* Thanks to Jan den Ouden
* Fritz Elfert
*
* $Log: callc.c,v $
+ * Revision 2.25 1999/01/02 11:17:20 keil
+ * Changes for 2.2
+ *
+ * Revision 2.24 1998/11/15 23:54:24 keil
+ * changes from 2.0
+ *
+ * Revision 2.23 1998/09/30 22:21:57 keil
+ * cosmetics
+ *
+ * Revision 2.22 1998/08/20 13:50:29 keil
+ * More support for hybrid modem (not working yet)
+ *
+ * Revision 2.21 1998/08/13 23:36:15 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.20 1998/06/26 15:13:05 fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 2.19 1998/05/25 14:08:06 keil
+ * HiSax 3.0
+ * fixed X.75 and leased line to work again
+ * Point2Point and fixed TEI are runtime options now:
+ * hisaxctrl <id> 7 1 set PTP
+ * hisaxctrl <id> 8 <TEIVALUE *2 >
+ * set fixed TEI to TEIVALUE (0-63)
+ *
+ * Revision 2.18 1998/05/25 12:57:40 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.17 1998/04/15 16:46:06 keil
+ * RESUME support
+ *
+ * Revision 2.16 1998/04/10 10:35:17 paul
+ * fixed (silly?) warnings from egcs on Alpha.
+ *
+ * Revision 2.15 1998/03/19 13:18:37 keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
+ * Revision 2.14 1998/03/07 22:56:54 tsbogend
+ * made HiSax working on Linux/Alpha
+ *
* Revision 2.13 1998/02/12 23:07:16 keil
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
@@ -60,12 +109,13 @@
#define __NO_VERSION__
#include "hisax.h"
+#include "../avmb1/capicmd.h" /* this should be moved in a common place */
#ifdef MODULE
#define MOD_USE_COUNT ( GET_USE_COUNT (&__this_module))
#endif /* MODULE */
-const char *lli_revision = "$Revision: 2.13 $";
+const char *lli_revision = "$Revision: 2.25 $";
extern struct IsdnCard cards[];
extern int nrcards;
@@ -77,20 +127,18 @@ static void release_b_st(struct Channel *chanp);
static struct Fsm callcfsm =
{NULL, 0, 0, NULL, NULL};
-static struct Fsm lcfsm =
-{NULL, 0, 0, NULL, NULL};
static int chancount = 0;
-/* experimental REJECT after ALERTING for CALLBACK to beat the 4s delay */
-#define ALERT_REJECT 1
+/* experimental REJECT after ALERTING for CALLBACK to beat the 4s delay */
+#define ALERT_REJECT 0
/* Value to delay the sending of the first B-channel paket after CONNECT
* here is no value given by ITU, but experience shows that 300 ms will
* work on many networks, if you or your other side is behind local exchanges
* a greater value may be recommented. If the delay is to short the first paket
* will be lost and autodetect on many comercial routers goes wrong !
- * You can adjust this value on runtime with
+ * You can adjust this value on runtime with
* hisaxctrl <id> 2 <value>
* value is in milliseconds
*/
@@ -114,11 +162,12 @@ static int chancount = 0;
#define FLG_DO_HANGUP 13
#define FLG_DO_CONNECT 14
#define FLG_DO_ESTAB 15
+#define FLG_RESUME 16
/*
* Because of callback it's a good idea to delay the shutdown of the d-channel
*/
-#define DREL_TIMER_VALUE 10000
+#define DREL_TIMER_VALUE 40000
/*
* Find card with given driverId
@@ -136,15 +185,30 @@ hisax_findcard(int driverid)
return (struct IsdnCardState *) 0;
}
+int
+discard_queue(struct sk_buff_head *q)
+{
+ struct sk_buff *skb;
+ int ret=0;
+
+ while ((skb = skb_dequeue(q))) {
+ dev_kfree_skb(skb);
+ ret++;
+ }
+ return(ret);
+}
+
static void
-link_debug(struct Channel *chanp, char *s, int direction)
+link_debug(struct Channel *chanp, int direction, char *fmt, ...)
{
- char tmp[100], tm[32];
+ va_list args;
+ char tmp[16];
- jiftime(tm, jiffies);
- sprintf(tmp, "%s Channel %d %s %s\n", tm, chanp->chan,
- direction ? "LL->HL" : "HL->LL", s);
- HiSax_putstatus(chanp->cs, tmp);
+ va_start(args, fmt);
+ sprintf(tmp, "Ch%d %s ", chanp->chan,
+ direction ? "LL->HL" : "HL->LL");
+ VHiSax_putstatus(chanp->cs, tmp, fmt, args);
+ va_end(args);
}
@@ -244,72 +308,21 @@ static char *strEvent[] =
"EV_RELEASE_ERR",
};
-enum {
- ST_LC_NULL,
- ST_LC_ACTIVATE_WAIT,
- ST_LC_DELAY,
- ST_LC_ESTABLISH_WAIT,
- ST_LC_CONNECTED,
- ST_LC_FLUSH_WAIT,
- ST_LC_RELEASE_WAIT,
-};
-
-#define LC_STATE_COUNT (ST_LC_RELEASE_WAIT+1)
-
-static char *strLcState[] =
-{
- "ST_LC_NULL",
- "ST_LC_ACTIVATE_WAIT",
- "ST_LC_DELAY",
- "ST_LC_ESTABLISH_WAIT",
- "ST_LC_CONNECTED",
- "ST_LC_FLUSH_WAIT",
- "ST_LC_RELEASE_WAIT",
-};
-
-enum {
- EV_LC_ESTABLISH,
- EV_LC_PH_ACTIVATE,
- EV_LC_PH_DEACTIVATE,
- EV_LC_DL_ESTABLISH,
- EV_LC_TIMER,
- EV_LC_DL_RELEASE,
- EV_LC_RELEASE,
-};
-
-#define LC_EVENT_COUNT (EV_LC_RELEASE+1)
-
-static char *strLcEvent[] =
-{
- "EV_LC_ESTABLISH",
- "EV_LC_PH_ACTIVATE",
- "EV_LC_PH_DEACTIVATE",
- "EV_LC_DL_ESTABLISH",
- "EV_LC_TIMER",
- "EV_LC_DL_RELEASE",
- "EV_LC_RELEASE",
-};
-
-#define LC_D 0
-#define LC_B 1
-
static inline void
-lli_deliver_cause(struct Channel *chanp)
+lli_deliver_cause(struct Channel *chanp, isdn_ctrl *ic)
{
- isdn_ctrl ic;
-
if (chanp->proc->para.cause < 0)
return;
- ic.driver = chanp->cs->myid;
- ic.command = ISDN_STAT_CAUSE;
- ic.arg = chanp->chan;
+ ic->driver = chanp->cs->myid;
+ ic->command = ISDN_STAT_CAUSE;
+ ic->arg = chanp->chan;
if (chanp->cs->protocol == ISDN_PTYPE_EURO)
- sprintf(ic.parm.num, "E%02X%02X", chanp->proc->para.loc & 0x7f,
+ sprintf(ic->parm.num, "E%02X%02X", chanp->proc->para.loc & 0x7f,
chanp->proc->para.cause & 0x7f);
else
- sprintf(ic.parm.num, "%02X%02X", chanp->proc->para.loc & 0x7f,
+ sprintf(ic->parm.num, "%02X%02X", chanp->proc->para.loc & 0x7f,
chanp->proc->para.cause & 0x7f);
- chanp->cs->iif.statcallb(&ic);
+ chanp->cs->iif.statcallb(ic);
}
static void
@@ -321,13 +334,12 @@ lli_d_established(struct FsmInst *fi, int event, void *arg)
if (chanp->leased) {
isdn_ctrl ic;
int ret;
- char txt[32];
- chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) chanp->chan);
+ chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
FsmChangeState(fi, ST_IN_WAIT_LL);
test_and_set_bit(FLG_CALL_REC, &chanp->Flags);
if (chanp->debug & 1)
- link_debug(chanp, "STAT_ICALL_LEASED", 0);
+ link_debug(chanp, 0, "STAT_ICALL_LEASED");
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_ICALL;
ic.arg = chanp->chan;
@@ -335,15 +347,13 @@ lli_d_established(struct FsmInst *fi, int event, void *arg)
ic.parm.setup.si2 = 0;
ic.parm.setup.plan = 0;
ic.parm.setup.screen = 0;
- sprintf(ic.parm.setup.eazmsn,"%d", chanp->chan + 1);
+ sprintf(ic.parm.setup.eazmsn,"%d", chanp->chan + 1);
sprintf(ic.parm.setup.phone,"LEASED%d", chanp->cs->myid);
ret = chanp->cs->iif.statcallb(&ic);
- if (chanp->debug & 1) {
- sprintf(txt, "statcallb ret=%d", ret);
- link_debug(chanp, txt, 1);
- }
+ if (chanp->debug & 1)
+ link_debug(chanp, 1, "statcallb ret=%d", ret);
if (!ret) {
- chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) chanp->chan);
+ chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
FsmChangeState(fi, ST_NULL);
}
} else if (fi->state == ST_WAIT_DSHUTDOWN)
@@ -371,28 +381,14 @@ lli_prep_dialout(struct FsmInst *fi, int event, void *arg)
FsmDelTimer(&chanp->dial_timer, 73);
chanp->l2_active_protocol = chanp->l2_protocol;
chanp->incoming = 0;
- chanp->lc_b->l2_start = !0;
- switch (chanp->l2_active_protocol) {
- case (ISDN_PROTO_L2_X75I):
- chanp->lc_b->l2_establish = !0;
- break;
- case (ISDN_PROTO_L2_HDLC):
- case (ISDN_PROTO_L2_TRANS):
- chanp->lc_b->l2_establish = 0;
- break;
- default:
- printk(KERN_WARNING "lli_prep_dialout unknown protocol\n");
- break;
- }
if (test_bit(FLG_ESTAB_D, &chanp->Flags)) {
FsmEvent(fi, EV_DLEST, NULL);
} else {
chanp->Flags = 0;
+ if (EV_RESUME == event)
+ test_and_set_bit(FLG_RESUME, &chanp->Flags);
test_and_set_bit(FLG_START_D, &chanp->Flags);
- if (chanp->leased) {
- chanp->lc_d->l2_establish = 0;
- }
- FsmEvent(&chanp->lc_d->lcfi, EV_LC_ESTABLISH, NULL);
+ chanp->d_st->lli.l4l3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL);
}
}
@@ -400,14 +396,19 @@ static void
lli_do_dialout(struct FsmInst *fi, int event, void *arg)
{
struct Channel *chanp = fi->userdata;
+ int ev;
FsmChangeState(fi, ST_OUT_DIAL);
- chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) chanp->chan);
+ chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
+ if (test_and_clear_bit(FLG_RESUME, &chanp->Flags))
+ ev = CC_RESUME | REQUEST;
+ else
+ ev = CC_SETUP | REQUEST;
if (chanp->leased) {
FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL);
} else {
test_and_set_bit(FLG_ESTAB_D, &chanp->Flags);
- chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP_REQ, chanp);
+ chanp->d_st->lli.l4l3(chanp->d_st, ev, chanp);
test_and_set_bit(FLG_CALL_SEND, &chanp->Flags);
}
}
@@ -421,14 +422,14 @@ lli_init_bchan_out(struct FsmInst *fi, int event, void *arg)
FsmChangeState(fi, ST_WAIT_BCONN);
test_and_set_bit(FLG_LL_DCONN, &chanp->Flags);
if (chanp->debug & 1)
- link_debug(chanp, "STAT_DCONN", 0);
+ link_debug(chanp, 0, "STAT_DCONN");
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_DCONN;
ic.arg = chanp->chan;
chanp->cs->iif.statcallb(&ic);
init_b_st(chanp, 0);
test_and_set_bit(FLG_START_B, &chanp->Flags);
- FsmEvent(&chanp->lc_b->lcfi, EV_LC_ESTABLISH, NULL);
+ chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL);
}
static void
@@ -441,15 +442,19 @@ lli_go_active(struct FsmInst *fi, int event, void *arg)
chanp->data_open = !0;
test_and_set_bit(FLG_CONNECT_B, &chanp->Flags);
if (chanp->debug & 1)
- link_debug(chanp, "STAT_BCONN", 0);
+ link_debug(chanp, 0, "STAT_BCONN");
test_and_set_bit(FLG_LL_BCONN, &chanp->Flags);
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_BCONN;
ic.arg = chanp->chan;
chanp->cs->iif.statcallb(&ic);
- chanp->cs->cardmsg(chanp->cs, MDL_INFO_CONN, (void *) chanp->chan);
+ chanp->cs->cardmsg(chanp->cs, MDL_INFO_CONN, (void *) (long)chanp->chan);
}
+/*
+ * RESUME
+ */
+
/* incomming call */
static void
@@ -463,14 +468,14 @@ lli_start_dchan(struct FsmInst *fi, int event, void *arg)
test_and_set_bit(FLG_DO_CONNECT, &chanp->Flags);
else if (event == EV_HANGUP) {
test_and_set_bit(FLG_DO_HANGUP, &chanp->Flags);
-#ifdef ALERT_REJECT
+#ifdef ALERT_REJECT
test_and_set_bit(FLG_DO_ALERT, &chanp->Flags);
#endif
- }
+ }
if (test_bit(FLG_ESTAB_D, &chanp->Flags)) {
FsmEvent(fi, EV_DLEST, NULL);
} else if (!test_and_set_bit(FLG_START_D, &chanp->Flags))
- FsmEvent(&chanp->lc_d->lcfi, EV_LC_ESTABLISH, NULL);
+ chanp->d_st->lli.l4l3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL);
}
static void
@@ -479,9 +484,8 @@ lli_deliver_call(struct FsmInst *fi, int event, void *arg)
struct Channel *chanp = fi->userdata;
isdn_ctrl ic;
int ret;
- char txt[32];
- chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) chanp->chan);
+ chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
/*
* Report incoming calls only once to linklevel, use CallFlags
* which is set to 3 with each broadcast message in isdnl1.c
@@ -491,7 +495,7 @@ lli_deliver_call(struct FsmInst *fi, int event, void *arg)
FsmChangeState(fi, ST_IN_WAIT_LL);
test_and_set_bit(FLG_CALL_REC, &chanp->Flags);
if (chanp->debug & 1)
- link_debug(chanp, "STAT_ICALL", 0);
+ link_debug(chanp, 0, "STAT_ICALL");
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_ICALL;
ic.arg = chanp->chan;
@@ -501,22 +505,21 @@ lli_deliver_call(struct FsmInst *fi, int event, void *arg)
*/
ic.parm.setup = chanp->proc->para.setup;
ret = chanp->cs->iif.statcallb(&ic);
- if (chanp->debug & 1) {
- sprintf(txt, "statcallb ret=%d", ret);
- link_debug(chanp, txt, 1);
- }
+ if (chanp->debug & 1)
+ link_debug(chanp, 1, "statcallb ret=%d", ret);
switch (ret) {
case 1: /* OK, anybody likes this call */
FsmDelTimer(&chanp->drel_timer, 61);
if (test_bit(FLG_ESTAB_D, &chanp->Flags)) {
FsmChangeState(fi, ST_IN_ALERT_SEND);
test_and_set_bit(FLG_CALL_ALERT, &chanp->Flags);
- chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING_REQ, chanp->proc);
+ chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
} else {
test_and_set_bit(FLG_DO_ALERT, &chanp->Flags);
FsmChangeState(fi, ST_IN_WAIT_D);
test_and_set_bit(FLG_START_D, &chanp->Flags);
- FsmEvent(&chanp->lc_d->lcfi, EV_LC_ESTABLISH, NULL);
+ chanp->d_st->lli.l4l3(chanp->d_st,
+ DL_ESTABLISH | REQUEST, NULL);
}
break;
case 2: /* Rejecting Call */
@@ -524,38 +527,36 @@ lli_deliver_call(struct FsmInst *fi, int event, void *arg)
break;
case 0: /* OK, nobody likes this call */
default: /* statcallb problems */
- chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE, chanp->proc);
- chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) chanp->chan);
+ chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc);
+ chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
FsmChangeState(fi, ST_NULL);
-#ifndef LAYER2_WATCHING
- if (test_bit(FLG_ESTAB_D, &chanp->Flags))
+ if (test_bit(FLG_ESTAB_D, &chanp->Flags) &&
+ !test_bit(FLG_PTP, &chanp->d_st->l2.flag))
FsmRestartTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 61);
-#endif
break;
}
} else {
- chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE, chanp->proc);
- chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) chanp->chan);
+ chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc);
+ chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
FsmChangeState(fi, ST_NULL);
-#ifndef LAYER2_WATCHING
- if (test_bit(FLG_ESTAB_D, &chanp->Flags))
+ if (test_bit(FLG_ESTAB_D, &chanp->Flags) &&
+ !test_bit(FLG_PTP, &chanp->d_st->l2.flag))
FsmRestartTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 62);
-#endif
}
}
static void
lli_establish_d(struct FsmInst *fi, int event, void *arg)
{
- /* This establish the D-channel for pending L3 messages
- * without blocking th channel
+ /* This establish the D-channel for pending L3 messages
+ * without blocking the channel
*/
struct Channel *chanp = fi->userdata;
test_and_set_bit(FLG_DO_ESTAB, &chanp->Flags);
FsmChangeState(fi, ST_IN_WAIT_D);
test_and_set_bit(FLG_START_D, &chanp->Flags);
- FsmEvent(&chanp->lc_d->lcfi, EV_LC_ESTABLISH, NULL);
+ chanp->d_st->lli.l4l3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL);
}
static void
@@ -573,27 +574,18 @@ lli_do_action(struct FsmInst *fi, int event, void *arg)
!test_bit(FLG_DO_HANGUP, &chanp->Flags)) {
FsmChangeState(fi, ST_IN_WAIT_CONN_ACK);
test_and_clear_bit(FLG_DO_ALERT, &chanp->Flags);
- chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP_RSP, chanp->proc);
+ chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc);
} else if (test_and_clear_bit(FLG_DO_ALERT, &chanp->Flags)) {
if (test_bit(FLG_DO_HANGUP, &chanp->Flags))
FsmRestartTimer(&chanp->drel_timer, 40, EV_HANGUP, NULL, 63);
FsmChangeState(fi, ST_IN_ALERT_SEND);
test_and_set_bit(FLG_CALL_ALERT, &chanp->Flags);
- chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING_REQ, chanp->proc);
+ chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
} else if (test_and_clear_bit(FLG_DO_HANGUP, &chanp->Flags)) {
FsmChangeState(fi, ST_WAIT_DRELEASE);
chanp->proc->para.cause = 0x15; /* Call Rejected */
- chanp->d_st->lli.l4l3(chanp->d_st, CC_REJECT_REQ, chanp->proc);
+ chanp->d_st->lli.l4l3(chanp->d_st, CC_REJECT | REQUEST, chanp->proc);
test_and_set_bit(FLG_DISC_SEND, &chanp->Flags);
- } else if (test_and_clear_bit(FLG_DO_ESTAB, &chanp->Flags)) {
- FsmChangeState(fi, ST_NULL);
- chanp->Flags = 0;
- test_and_set_bit(FLG_ESTAB_D, &chanp->Flags);
- chanp->d_st->lli.l4l3(chanp->d_st, CC_ESTABLISH, chanp->proc);
- chanp->proc = NULL;
-#ifndef LAYER2_WATCHING
- FsmAddTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 60);
-#endif
}
}
@@ -603,7 +595,7 @@ lli_send_dconnect(struct FsmInst *fi, int event, void *arg)
struct Channel *chanp = fi->userdata;
FsmChangeState(fi, ST_IN_WAIT_CONN_ACK);
- chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP_RSP, chanp->proc);
+ chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc);
}
static void
@@ -615,29 +607,26 @@ lli_init_bchan_in(struct FsmInst *fi, int event, void *arg)
FsmChangeState(fi, ST_WAIT_BCONN);
test_and_set_bit(FLG_LL_DCONN, &chanp->Flags);
if (chanp->debug & 1)
- link_debug(chanp, "STAT_DCONN", 0);
+ link_debug(chanp, 0, "STAT_DCONN");
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_DCONN;
ic.arg = chanp->chan;
chanp->cs->iif.statcallb(&ic);
chanp->l2_active_protocol = chanp->l2_protocol;
chanp->incoming = !0;
- chanp->lc_b->l2_start = 0;
- switch (chanp->l2_active_protocol) {
- case (ISDN_PROTO_L2_X75I):
- chanp->lc_b->l2_establish = !0;
- break;
- case (ISDN_PROTO_L2_HDLC):
- case (ISDN_PROTO_L2_TRANS):
- chanp->lc_b->l2_establish = 0;
- break;
- default:
- printk(KERN_WARNING "bchannel unknown protocol\n");
- break;
- }
init_b_st(chanp, !0);
test_and_set_bit(FLG_START_B, &chanp->Flags);
- FsmEvent(&chanp->lc_b->lcfi, EV_LC_ESTABLISH, NULL);
+ chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL);
+}
+
+/* Call suspend */
+
+static void
+lli_suspend(struct FsmInst *fi, int event, void *arg)
+{
+ struct Channel *chanp = fi->userdata;
+
+ chanp->d_st->lli.l4l3(chanp->d_st, CC_SUSPEND | REQUEST, chanp->proc);
}
/* Call clearing */
@@ -651,7 +640,7 @@ lli_cancel_call(struct FsmInst *fi, int event, void *arg)
FsmChangeState(fi, ST_WAIT_DRELEASE);
if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
if (chanp->debug & 1)
- link_debug(chanp, "STAT_BHUP", 0);
+ link_debug(chanp, 0, "STAT_BHUP");
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_BHUP;
ic.arg = chanp->chan;
@@ -660,7 +649,7 @@ lli_cancel_call(struct FsmInst *fi, int event, void *arg)
if (test_and_clear_bit(FLG_START_B, &chanp->Flags))
release_b_st(chanp);
chanp->proc->para.cause = 0x10; /* Normal Call Clearing */
- chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT_REQ, chanp->proc);
+ chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST, chanp->proc);
test_and_set_bit(FLG_DISC_SEND, &chanp->Flags);
}
@@ -670,22 +659,22 @@ lli_shutdown_d(struct FsmInst *fi, int event, void *arg)
struct Channel *chanp = fi->userdata;
FsmDelTimer(&chanp->drel_timer, 62);
-#ifdef LAYER2_WATCHING
- FsmChangeState(fi, ST_NULL);
-#else
- if (!test_bit(FLG_TWO_DCHAN, &chanp->cs->HW_Flags)) {
- if (chanp->chan) {
- if (chanp->cs->channel[0].fi.state != ST_NULL)
- return;
- } else {
- if (chanp->cs->channel[1].fi.state != ST_NULL)
- return;
+ if (test_bit(FLG_PTP, &chanp->d_st->l2.flag)) {
+ FsmChangeState(fi, ST_NULL);
+ } else {
+ if (!test_bit(FLG_TWO_DCHAN, &chanp->cs->HW_Flags)) {
+ if (chanp->chan) {
+ if (chanp->cs->channel[0].fi.state != ST_NULL)
+ return;
+ } else {
+ if (chanp->cs->channel[1].fi.state != ST_NULL)
+ return;
+ }
}
+ FsmChangeState(fi, ST_WAIT_DSHUTDOWN);
+ test_and_clear_bit(FLG_ESTAB_D, &chanp->Flags);
+ chanp->d_st->lli.l4l3(chanp->d_st, DL_RELEASE | REQUEST, NULL);
}
- FsmChangeState(fi, ST_WAIT_DSHUTDOWN);
- test_and_clear_bit(FLG_ESTAB_D, &chanp->Flags);
- FsmEvent(&chanp->lc_d->lcfi, EV_LC_RELEASE, NULL);
-#endif
}
static void
@@ -694,22 +683,20 @@ lli_timeout_d(struct FsmInst *fi, int event, void *arg)
struct Channel *chanp = fi->userdata;
isdn_ctrl ic;
- if (test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags)) {
- if (chanp->debug & 1)
- link_debug(chanp, "STAT_DHUP", 0);
- lli_deliver_cause(chanp);
- ic.driver = chanp->cs->myid;
- ic.command = ISDN_STAT_DHUP;
- ic.arg = chanp->chan;
- chanp->cs->iif.statcallb(&ic);
- }
+ test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags);
+ if (chanp->debug & 1)
+ link_debug(chanp, 0, "STAT_DHUP");
+ lli_deliver_cause(chanp, &ic);
+ ic.driver = chanp->cs->myid;
+ ic.command = ISDN_STAT_DHUP;
+ ic.arg = chanp->chan;
+ chanp->cs->iif.statcallb(&ic);
FsmChangeState(fi, ST_NULL);
chanp->Flags = 0;
test_and_set_bit(FLG_ESTAB_D, &chanp->Flags);
-#ifndef LAYER2_WATCHING
- FsmAddTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 60);
-#endif
- chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) chanp->chan);
+ if (!test_bit(FLG_PTP, &chanp->d_st->l2.flag))
+ FsmAddTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 60);
+ chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
}
static void
@@ -720,7 +707,7 @@ lli_go_null(struct FsmInst *fi, int event, void *arg)
FsmChangeState(fi, ST_NULL);
chanp->Flags = 0;
FsmDelTimer(&chanp->drel_timer, 63);
- chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) chanp->chan);
+ chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
}
static void
@@ -731,7 +718,7 @@ lli_disconn_bchan(struct FsmInst *fi, int event, void *arg)
chanp->data_open = 0;
FsmChangeState(fi, ST_WAIT_BRELEASE);
test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags);
- FsmEvent(&chanp->lc_b->lcfi, EV_LC_RELEASE, NULL);
+ chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
}
static void
@@ -746,7 +733,7 @@ lli_send_d_disc(struct FsmInst *fi, int event, void *arg)
FsmChangeState(fi, ST_WAIT_DRELEASE);
if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
if (chanp->debug & 1)
- link_debug(chanp, "STAT_BHUP", 0);
+ link_debug(chanp, 0, "STAT_BHUP");
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_BHUP;
ic.arg = chanp->chan;
@@ -760,20 +747,20 @@ lli_send_d_disc(struct FsmInst *fi, int event, void *arg)
sprintf(ic.parm.num, "L0010");
chanp->cs->iif.statcallb(&ic);
if (chanp->debug & 1)
- link_debug(chanp, "STAT_DHUP", 0);
+ link_debug(chanp, 0, "STAT_DHUP");
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_DHUP;
ic.arg = chanp->chan;
chanp->cs->iif.statcallb(&ic);
FsmChangeState(fi, ST_WAIT_DSHUTDOWN);
test_and_clear_bit(FLG_ESTAB_D, &chanp->Flags);
- FsmEvent(&chanp->lc_d->lcfi, EV_LC_RELEASE, NULL);
+ chanp->d_st->lli.l4l3(chanp->d_st, DL_RELEASE | REQUEST, NULL);
} else {
if (test_and_clear_bit(FLG_DO_HANGUP, &chanp->Flags))
chanp->proc->para.cause = 0x15; /* Call Reject */
else
chanp->proc->para.cause = 0x10; /* Normal Call Clearing */
- chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT_REQ, chanp->proc);
+ chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST, chanp->proc);
test_and_set_bit(FLG_DISC_SEND, &chanp->Flags);
}
}
@@ -788,7 +775,7 @@ lli_released_bchan(struct FsmInst *fi, int event, void *arg)
chanp->data_open = 0;
if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
if (chanp->debug & 1)
- link_debug(chanp, "STAT_BHUP", 0);
+ link_debug(chanp, 0, "STAT_BHUP");
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_BHUP;
ic.arg = chanp->chan;
@@ -808,7 +795,7 @@ lli_release_bchan(struct FsmInst *fi, int event, void *arg)
test_and_set_bit(FLG_DISC_REC, &chanp->Flags);
FsmChangeState(fi, ST_WAIT_BREL_DISC);
test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags);
- FsmEvent(&chanp->lc_b->lcfi, EV_LC_RELEASE, NULL);
+ chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
}
static void
@@ -821,12 +808,11 @@ lli_received_d_rel(struct FsmInst *fi, int event, void *arg)
FsmChangeState(fi, ST_NULL);
test_and_set_bit(FLG_REL_REC, &chanp->Flags);
if (test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags)) {
- chanp->lc_b->l2_establish = 0; /* direct reset in lc_b->lcfi */
- FsmEvent(&chanp->lc_b->lcfi, EV_LC_RELEASE, NULL);
+ chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
}
if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
if (chanp->debug & 1)
- link_debug(chanp, "STAT_BHUP", 0);
+ link_debug(chanp, 0, "STAT_BHUP");
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_BHUP;
ic.arg = chanp->chan;
@@ -834,17 +820,13 @@ lli_received_d_rel(struct FsmInst *fi, int event, void *arg)
}
if (test_and_clear_bit(FLG_START_B, &chanp->Flags))
release_b_st(chanp);
- if (test_bit(FLG_LL_DCONN, &chanp->Flags) ||
- test_bit(FLG_CALL_SEND, &chanp->Flags) ||
- test_bit(FLG_CALL_ALERT, &chanp->Flags)) {
- if (chanp->debug & 1)
- link_debug(chanp, "STAT_DHUP", 0);
- lli_deliver_cause(chanp);
- ic.driver = chanp->cs->myid;
- ic.command = ISDN_STAT_DHUP;
- ic.arg = chanp->chan;
- chanp->cs->iif.statcallb(&ic);
- }
+ if (chanp->debug & 1)
+ link_debug(chanp, 0, "STAT_DHUP");
+ lli_deliver_cause(chanp, &ic);
+ ic.driver = chanp->cs->myid;
+ ic.command = ISDN_STAT_DHUP;
+ ic.arg = chanp->chan;
+ chanp->cs->iif.statcallb(&ic);
test_and_clear_bit(FLG_DISC_SEND, &chanp->Flags);
test_and_clear_bit(FLG_CALL_REC, &chanp->Flags);
test_and_clear_bit(FLG_CALL_ALERT, &chanp->Flags);
@@ -862,12 +844,11 @@ lli_received_d_relcnf(struct FsmInst *fi, int event, void *arg)
chanp->data_open = 0;
FsmChangeState(fi, ST_NULL);
if (test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags)) {
- chanp->lc_b->l2_establish = 0; /* direct reset in lc_b->lcfi */
- FsmEvent(&chanp->lc_b->lcfi, EV_LC_RELEASE, NULL);
+ chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
}
if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
if (chanp->debug & 1)
- link_debug(chanp, "STAT_BHUP", 0);
+ link_debug(chanp, 0, "STAT_BHUP");
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_BHUP;
ic.arg = chanp->chan;
@@ -875,17 +856,13 @@ lli_received_d_relcnf(struct FsmInst *fi, int event, void *arg)
}
if (test_and_clear_bit(FLG_START_B, &chanp->Flags))
release_b_st(chanp);
- if (test_bit(FLG_LL_DCONN, &chanp->Flags) ||
- test_bit(FLG_CALL_SEND, &chanp->Flags) ||
- test_bit(FLG_CALL_ALERT, &chanp->Flags)) {
- if (chanp->debug & 1)
- link_debug(chanp, "STAT_DHUP", 0);
- lli_deliver_cause(chanp);
- ic.driver = chanp->cs->myid;
- ic.command = ISDN_STAT_DHUP;
- ic.arg = chanp->chan;
- chanp->cs->iif.statcallb(&ic);
- }
+ if (chanp->debug & 1)
+ link_debug(chanp, 0, "STAT_DHUP");
+ lli_deliver_cause(chanp, &ic);
+ ic.driver = chanp->cs->myid;
+ ic.command = ISDN_STAT_DHUP;
+ ic.arg = chanp->chan;
+ chanp->cs->iif.statcallb(&ic);
test_and_clear_bit(FLG_DISC_SEND, &chanp->Flags);
test_and_clear_bit(FLG_CALL_REC, &chanp->Flags);
test_and_clear_bit(FLG_CALL_ALERT, &chanp->Flags);
@@ -905,7 +882,7 @@ lli_received_d_disc(struct FsmInst *fi, int event, void *arg)
test_and_set_bit(FLG_DISC_REC, &chanp->Flags);
if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
if (chanp->debug & 1)
- link_debug(chanp, "STAT_BHUP", 0);
+ link_debug(chanp, 0, "STAT_BHUP");
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_BHUP;
ic.arg = chanp->chan;
@@ -913,21 +890,17 @@ lli_received_d_disc(struct FsmInst *fi, int event, void *arg)
}
if (test_and_clear_bit(FLG_START_B, &chanp->Flags))
release_b_st(chanp);
- if (test_bit(FLG_LL_DCONN, &chanp->Flags) ||
- test_bit(FLG_CALL_SEND, &chanp->Flags) ||
- test_bit(FLG_CALL_ALERT, &chanp->Flags)) {
- if (chanp->debug & 1)
- link_debug(chanp, "STAT_DHUP", 0);
- lli_deliver_cause(chanp);
- ic.driver = chanp->cs->myid;
- ic.command = ISDN_STAT_DHUP;
- ic.arg = chanp->chan;
- chanp->cs->iif.statcallb(&ic);
- }
+ if (chanp->debug & 1)
+ link_debug(chanp, 0, "STAT_DHUP");
+ lli_deliver_cause(chanp, &ic);
+ ic.driver = chanp->cs->myid;
+ ic.command = ISDN_STAT_DHUP;
+ ic.arg = chanp->chan;
+ chanp->cs->iif.statcallb(&ic);
test_and_clear_bit(FLG_CALL_ALERT, &chanp->Flags);
test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags);
test_and_clear_bit(FLG_CALL_SEND, &chanp->Flags);
- chanp->d_st->lli.l4l3(chanp->d_st, CC_RELEASE_REQ, chanp->proc);
+ chanp->d_st->lli.l4l3(chanp->d_st, CC_RELEASE | REQUEST, chanp->proc);
}
/* processing charge info */
@@ -953,14 +926,14 @@ lli_no_dchan(struct FsmInst *fi, int event, void *arg)
isdn_ctrl ic;
if (chanp->debug & 1)
- link_debug(chanp, "STAT_NODCH", 0);
+ link_debug(chanp, 0, "STAT_NODCH");
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_NODCH;
ic.arg = chanp->chan;
chanp->cs->iif.statcallb(&ic);
chanp->Flags = 0;
FsmChangeState(fi, ST_NULL);
- FsmEvent(&chanp->lc_d->lcfi, EV_LC_RELEASE, NULL);
+ chanp->d_st->lli.l4l3(chanp->d_st, DL_RELEASE | REQUEST, NULL);
}
static void
@@ -970,7 +943,7 @@ lli_no_dchan_ready(struct FsmInst *fi, int event, void *arg)
isdn_ctrl ic;
if (chanp->debug & 1)
- link_debug(chanp, "STAT_DHUP", 0);
+ link_debug(chanp, 0, "STAT_DHUP");
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_DHUP;
ic.arg = chanp->chan;
@@ -984,15 +957,15 @@ lli_no_dchan_in(struct FsmInst *fi, int event, void *arg)
isdn_ctrl ic;
if (chanp->debug & 1)
- link_debug(chanp, "STAT_DHUP", 0);
+ link_debug(chanp, 0, "STAT_DHUP");
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_DHUP;
ic.arg = chanp->chan;
chanp->cs->iif.statcallb(&ic);
- chanp->d_st->lli.l4l3(chanp->d_st, CC_DLRL, chanp->proc);
+ chanp->d_st->lli.l4l3(chanp->d_st, CC_DLRL | REQUEST, chanp->proc);
chanp->Flags = 0;
FsmChangeState(fi, ST_NULL);
- FsmEvent(&chanp->lc_d->lcfi, EV_LC_RELEASE, NULL);
+ chanp->d_st->lli.l4l3(chanp->d_st, DL_RELEASE | REQUEST, NULL);
}
static void
@@ -1004,7 +977,7 @@ lli_no_setup_rsp(struct FsmInst *fi, int event, void *arg)
FsmChangeState(fi, ST_NULL);
test_and_clear_bit(FLG_CALL_SEND, &chanp->Flags);
if (chanp->debug & 1)
- link_debug(chanp, "STAT_DHUP", 0);
+ link_debug(chanp, 0, "STAT_DHUP");
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_DHUP;
ic.arg = chanp->chan;
@@ -1019,15 +992,14 @@ lli_setup_err(struct FsmInst *fi, int event, void *arg)
isdn_ctrl ic;
FsmChangeState(fi, ST_WAIT_DRELEASE);
- if (test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags)) {
- if (chanp->debug & 1)
- link_debug(chanp, "STAT_DHUP", 0);
- lli_deliver_cause(chanp);
- ic.driver = chanp->cs->myid;
- ic.command = ISDN_STAT_DHUP;
- ic.arg = chanp->chan;
- chanp->cs->iif.statcallb(&ic);
- }
+ test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags);
+ if (chanp->debug & 1)
+ link_debug(chanp, 0, "STAT_DHUP");
+ lli_deliver_cause(chanp, &ic);
+ ic.driver = chanp->cs->myid;
+ ic.command = ISDN_STAT_DHUP;
+ ic.arg = chanp->chan;
+ chanp->cs->iif.statcallb(&ic);
test_and_set_bit(FLG_DISC_SEND, &chanp->Flags); /* DISCONN was sent from L3 */
}
@@ -1038,15 +1010,14 @@ lli_connect_err(struct FsmInst *fi, int event, void *arg)
isdn_ctrl ic;
FsmChangeState(fi, ST_WAIT_DRELEASE);
- if (test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags)) {
- if (chanp->debug & 1)
- link_debug(chanp, "STAT_DHUP", 0);
- lli_deliver_cause(chanp);
- ic.driver = chanp->cs->myid;
- ic.command = ISDN_STAT_DHUP;
- ic.arg = chanp->chan;
- chanp->cs->iif.statcallb(&ic);
- }
+ test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags);
+ if (chanp->debug & 1)
+ link_debug(chanp, 0, "STAT_DHUP");
+ lli_deliver_cause(chanp, &ic);
+ ic.driver = chanp->cs->myid;
+ ic.command = ISDN_STAT_DHUP;
+ ic.arg = chanp->chan;
+ chanp->cs->iif.statcallb(&ic);
test_and_set_bit(FLG_DISC_SEND, &chanp->Flags); /* DISCONN was sent from L3 */
}
@@ -1059,12 +1030,11 @@ lli_got_dlrl(struct FsmInst *fi, int event, void *arg)
chanp->data_open = 0;
FsmChangeState(fi, ST_NULL);
if (test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags)) {
- chanp->lc_b->l2_establish = 0; /* direct reset in lc_b->lcfi */
- FsmEvent(&chanp->lc_b->lcfi, EV_LC_RELEASE, NULL);
+ chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
}
if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
if (chanp->debug & 1)
- link_debug(chanp, "STAT_BHUP", 0);
+ link_debug(chanp, 0, "STAT_BHUP");
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_BHUP;
ic.arg = chanp->chan;
@@ -1084,33 +1054,33 @@ lli_got_dlrl(struct FsmInst *fi, int event, void *arg)
chanp->cs->iif.statcallb(&ic);
chanp->Flags = 0;
} else {
- if (test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags)) {
- if (chanp->debug & 1)
- link_debug(chanp, "STAT_DHUP", 0);
- if (chanp->cs->protocol == ISDN_PTYPE_EURO) {
- chanp->proc->para.cause = 0x2f;
- chanp->proc->para.loc = 0;
- } else {
- chanp->proc->para.cause = 0x70;
- chanp->proc->para.loc = 0;
- }
- lli_deliver_cause(chanp);
- ic.driver = chanp->cs->myid;
- ic.command = ISDN_STAT_DHUP;
- ic.arg = chanp->chan;
- chanp->cs->iif.statcallb(&ic);
+ test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags);
+ if (chanp->debug & 1)
+ link_debug(chanp, 0, "STAT_DHUP");
+ if (chanp->cs->protocol == ISDN_PTYPE_EURO) {
+ chanp->proc->para.cause = 0x2f;
+ chanp->proc->para.loc = 0;
+ } else {
+ chanp->proc->para.cause = 0x70;
+ chanp->proc->para.loc = 0;
}
- chanp->d_st->lli.l4l3(chanp->d_st, CC_DLRL, chanp->proc);
+ lli_deliver_cause(chanp, &ic);
+ ic.driver = chanp->cs->myid;
+ ic.command = ISDN_STAT_DHUP;
+ ic.arg = chanp->chan;
+ chanp->cs->iif.statcallb(&ic);
+ chanp->d_st->lli.l4l3(chanp->d_st, CC_DLRL | REQUEST, chanp->proc);
chanp->Flags = 0;
- FsmEvent(&chanp->lc_d->lcfi, EV_LC_RELEASE, NULL);
+ chanp->d_st->lli.l4l3(chanp->d_st, DL_RELEASE | REQUEST, NULL);
}
- chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) chanp->chan);
+ chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
}
/* *INDENT-OFF* */
static struct FsmNode fnlist[] HISAX_INITDATA =
{
{ST_NULL, EV_DIAL, lli_prep_dialout},
+ {ST_NULL, EV_RESUME, lli_prep_dialout},
{ST_NULL, EV_SETUP_IND, lli_deliver_call},
{ST_NULL, EV_SHUTDOWN_D, lli_shutdown_d},
{ST_NULL, EV_DLRL, lli_go_null},
@@ -1162,6 +1132,7 @@ static struct FsmNode fnlist[] HISAX_INITDATA =
{ST_WAIT_BCONN, EV_CINF, lli_charge_info},
{ST_ACTIVE, EV_CINF, lli_charge_info},
{ST_ACTIVE, EV_BC_REL, lli_released_bchan},
+ {ST_ACTIVE, EV_SUSPEND, lli_suspend},
{ST_ACTIVE, EV_HANGUP, lli_disconn_bchan},
{ST_ACTIVE, EV_DISCONNECT_IND, lli_release_bchan},
{ST_ACTIVE, EV_RELEASE_CNF, lli_received_d_relcnf},
@@ -1195,6 +1166,7 @@ static struct FsmNode fnlist[] HISAX_INITDATA =
{ST_WAIT_DSHUTDOWN, EV_DLRL, lli_go_null},
{ST_WAIT_DSHUTDOWN, EV_DLEST, lli_d_established},
{ST_WAIT_DSHUTDOWN, EV_DIAL, lli_prep_dialout},
+ {ST_WAIT_DSHUTDOWN, EV_RESUME, lli_prep_dialout},
{ST_WAIT_DSHUTDOWN, EV_SETUP_IND, lli_deliver_call},
};
/* *INDENT-ON* */
@@ -1202,153 +1174,6 @@ static struct FsmNode fnlist[] HISAX_INITDATA =
#define FNCOUNT (sizeof(fnlist)/sizeof(struct FsmNode))
-static void
-lc_activate_l1(struct FsmInst *fi, int event, void *arg)
-{
- struct LcFsm *lf = fi->userdata;
-
- FsmDelTimer(&lf->act_timer, 50);
- FsmChangeState(fi, ST_LC_ACTIVATE_WAIT);
- /* This timeout is to avoid a hang if no L1 activation is possible */
- FsmAddTimer(&lf->act_timer, 30000, EV_LC_TIMER, NULL, 50);
- lf->st->ma.manl1(lf->st, PH_ACTIVATE_REQ, NULL);
-}
-
-static void
-lc_activated_from_l1(struct FsmInst *fi, int event, void *arg)
-{
- struct LcFsm *lf = fi->userdata;
-
- if (lf->l2_establish)
- FsmChangeState(fi, ST_LC_DELAY);
- else {
- FsmChangeState(fi, ST_LC_CONNECTED);
- lf->lccall(lf, LC_ESTABLISH, NULL);
- }
-}
-
-static void
-lc_l1_activated(struct FsmInst *fi, int event, void *arg)
-{
- struct LcFsm *lf = fi->userdata;
-
- FsmDelTimer(&lf->act_timer, 50);
- FsmChangeState(fi, ST_LC_DELAY);
- /* This timer is needed for delay the first paket on a channel
- to be shure that the other side is ready too */
- if (lf->delay)
- FsmAddTimer(&lf->act_timer, lf->delay, EV_LC_TIMER, NULL, 51);
- else
- FsmEvent(fi, EV_LC_TIMER, NULL);
-}
-
-static void
-lc_start_l2(struct FsmInst *fi, int event, void *arg)
-{
- struct LcFsm *lf = fi->userdata;
-
-/* if (!lf->st->l1.act_state)
- lf->st->l1.act_state = 2;
-*/ if (lf->l2_establish) {
- FsmChangeState(fi, ST_LC_ESTABLISH_WAIT);
- if (lf->l2_start)
- lf->st->ma.manl2(lf->st, DL_ESTABLISH, NULL);
- } else {
- FsmChangeState(fi, ST_LC_CONNECTED);
- lf->lccall(lf, LC_ESTABLISH, NULL);
- }
-}
-
-static void
-lc_connected(struct FsmInst *fi, int event, void *arg)
-{
- struct LcFsm *lf = fi->userdata;
-
- FsmDelTimer(&lf->act_timer, 50);
- FsmChangeState(fi, ST_LC_CONNECTED);
- lf->lccall(lf, LC_ESTABLISH, NULL);
-}
-
-static void
-lc_release_l2(struct FsmInst *fi, int event, void *arg)
-{
- struct LcFsm *lf = fi->userdata;
-
- if (lf->l2_establish) {
- FsmChangeState(fi, ST_LC_RELEASE_WAIT);
- lf->st->ma.manl2(lf->st, DL_RELEASE, NULL);
- } else {
- FsmChangeState(fi, ST_LC_NULL);
- lf->st->ma.manl1(lf->st, PH_DEACTIVATE_REQ, NULL);
- lf->lccall(lf, LC_RELEASE, NULL);
- }
-}
-
-static void
-lc_l2_released(struct FsmInst *fi, int event, void *arg)
-{
- struct LcFsm *lf = fi->userdata;
-
- FsmChangeState(fi, ST_LC_RELEASE_WAIT);
- FsmDelTimer(&lf->act_timer, 51);
- /* This delay is needed for send out the UA frame before
- * PH_DEACTIVATE the interface
- */
- FsmAddTimer(&lf->act_timer, 20, EV_LC_TIMER, NULL, 54);
-}
-
-static void
-lc_release_l1(struct FsmInst *fi, int event, void *arg)
-{
- struct LcFsm *lf = fi->userdata;
-
- FsmDelTimer(&lf->act_timer, 54);
- FsmChangeState(fi, ST_LC_NULL);
- lf->st->ma.manl1(lf->st, PH_DEACTIVATE_REQ, NULL);
- lf->lccall(lf, LC_RELEASE, NULL);
-}
-
-static void
-lc_l1_deactivated(struct FsmInst *fi, int event, void *arg)
-{
- struct LcFsm *lf = fi->userdata;
-
- FsmDelTimer(&lf->act_timer, 54);
- FsmChangeState(fi, ST_LC_NULL);
- lf->lccall(lf, LC_RELEASE, NULL);
-}
-/* *INDENT-OFF* */
-static struct FsmNode LcFnList[] HISAX_INITDATA =
-{
- {ST_LC_NULL, EV_LC_ESTABLISH, lc_activate_l1},
- {ST_LC_NULL, EV_LC_PH_ACTIVATE, lc_activated_from_l1},
- {ST_LC_NULL, EV_LC_DL_ESTABLISH, lc_connected},
- {ST_LC_ACTIVATE_WAIT, EV_LC_PH_ACTIVATE, lc_l1_activated},
- {ST_LC_ACTIVATE_WAIT, EV_LC_TIMER, lc_release_l1},
- {ST_LC_ACTIVATE_WAIT, EV_LC_PH_DEACTIVATE, lc_l1_deactivated},
- {ST_LC_DELAY, EV_LC_ESTABLISH, lc_start_l2},
- {ST_LC_DELAY, EV_LC_TIMER, lc_start_l2},
- {ST_LC_DELAY, EV_LC_DL_ESTABLISH, lc_connected},
- {ST_LC_DELAY, EV_LC_PH_DEACTIVATE, lc_l1_deactivated},
- {ST_LC_ESTABLISH_WAIT, EV_LC_DL_ESTABLISH, lc_connected},
- {ST_LC_ESTABLISH_WAIT, EV_LC_RELEASE, lc_release_l1},
- {ST_LC_ESTABLISH_WAIT, EV_LC_DL_RELEASE, lc_release_l1},
- {ST_LC_ESTABLISH_WAIT, EV_LC_PH_DEACTIVATE, lc_l1_deactivated},
- {ST_LC_CONNECTED, EV_LC_ESTABLISH, lc_connected},
- {ST_LC_CONNECTED, EV_LC_RELEASE, lc_release_l2},
- {ST_LC_CONNECTED, EV_LC_DL_RELEASE, lc_l2_released},
- {ST_LC_CONNECTED, EV_LC_PH_DEACTIVATE, lc_l1_deactivated},
- {ST_LC_FLUSH_WAIT, EV_LC_TIMER, lc_release_l2},
- {ST_LC_FLUSH_WAIT, EV_LC_PH_DEACTIVATE, lc_l1_deactivated},
- {ST_LC_RELEASE_WAIT, EV_LC_DL_RELEASE, lc_release_l1},
- {ST_LC_RELEASE_WAIT, EV_LC_TIMER, lc_release_l1},
- {ST_LC_FLUSH_WAIT, EV_LC_PH_DEACTIVATE, lc_l1_deactivated},
-};
-/* *INDENT-ON* */
-
-
-#define LC_FN_COUNT (sizeof(LcFnList)/sizeof(struct FsmNode))
-
HISAX_INITFUNC(void
CallcNew(void))
{
@@ -1357,18 +1182,11 @@ CallcNew(void))
callcfsm.strEvent = strEvent;
callcfsm.strState = strState;
FsmNew(&callcfsm, fnlist, FNCOUNT);
-
- lcfsm.state_count = LC_STATE_COUNT;
- lcfsm.event_count = LC_EVENT_COUNT;
- lcfsm.strEvent = strLcEvent;
- lcfsm.strState = strLcState;
- FsmNew(&lcfsm, LcFnList, LC_FN_COUNT);
}
void
CallcFree(void)
{
- FsmFree(&lcfsm);
FsmFree(&callcfsm);
}
@@ -1384,75 +1202,10 @@ release_b_st(struct Channel *chanp)
break;
case (ISDN_PROTO_L2_HDLC):
case (ISDN_PROTO_L2_TRANS):
+// case (ISDN_PROTO_L2_MODEM):
releasestack_transl2(st);
break;
}
- /* Reset B-Channel Statemachine */
- FsmDelTimer(&chanp->lc_b->act_timer, 79);
- FsmChangeState(&chanp->lc_b->lcfi, ST_LC_NULL);
-}
-
-static void
-dc_l1man(struct PStack *st, int pr, void *arg)
-{
- struct Channel *chanp;
-
- chanp = (struct Channel *) st->lli.userdata;
- switch (pr) {
- case (PH_ACTIVATE_CNF):
- case (PH_ACTIVATE_IND):
- FsmEvent(&chanp->lc_d->lcfi, EV_LC_PH_ACTIVATE, NULL);
- break;
- case (PH_DEACTIVATE_IND):
- FsmEvent(&chanp->lc_d->lcfi, EV_LC_PH_DEACTIVATE, NULL);
- break;
- }
-}
-
-static void
-dc_l2man(struct PStack *st, int pr, void *arg)
-{
- struct Channel *chanp = (struct Channel *) st->lli.userdata;
-
- switch (pr) {
- case (DL_ESTABLISH):
- FsmEvent(&chanp->lc_d->lcfi, EV_LC_DL_ESTABLISH, NULL);
- break;
- case (DL_RELEASE):
- FsmEvent(&chanp->lc_d->lcfi, EV_LC_DL_RELEASE, NULL);
- break;
- }
-}
-
-static void
-bc_l1man(struct PStack *st, int pr, void *arg)
-{
- struct Channel *chanp = (struct Channel *) st->lli.userdata;
-
- switch (pr) {
- case (PH_ACTIVATE_IND):
- case (PH_ACTIVATE_CNF):
- FsmEvent(&chanp->lc_b->lcfi, EV_LC_PH_ACTIVATE, NULL);
- break;
- case (PH_DEACTIVATE_IND):
- FsmEvent(&chanp->lc_b->lcfi, EV_LC_PH_DEACTIVATE, NULL);
- break;
- }
-}
-
-static void
-bc_l2man(struct PStack *st, int pr, void *arg)
-{
- struct Channel *chanp = (struct Channel *) st->lli.userdata;
-
- switch (pr) {
- case (DL_ESTABLISH):
- FsmEvent(&chanp->lc_b->lcfi, EV_LC_DL_ESTABLISH, NULL);
- break;
- case (DL_RELEASE):
- FsmEvent(&chanp->lc_b->lcfi, EV_LC_DL_RELEASE, NULL);
- break;
- }
}
struct Channel
@@ -1471,7 +1224,7 @@ struct Channel
return (chanp);
chanp++;
i++;
- }
+ }
return (NULL);
}
@@ -1491,62 +1244,85 @@ is_activ(struct PStack *st)
return (1);
chanp++;
i++;
- }
+ }
return (0);
}
static void
-ll_handler(struct l3_process *pc, int pr, void *arg)
+dchan_l3l4(struct PStack *st, int pr, void *arg)
{
+ struct l3_process *pc = arg;
+ struct IsdnCardState *cs = st->l1.hardware;
struct Channel *chanp;
- char tmp[64], tm[32];
+ int event;
+
+ switch (pr) {
+ case (DL_ESTABLISH | INDICATION):
+ event = EV_DLEST;
+ break;
+ case (DL_RELEASE | INDICATION):
+ event = EV_DLRL;
+ break;
+ default:
+ event = -1;
+ break;
+ }
+ if (event >= 0) {
+ int i;
- if (pr == CC_SETUP_IND) {
+ chanp = st->lli.userdata;
+ if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags))
+ i = 1;
+ else
+ i = 0;
+ while (i < 2) {
+ FsmEvent(&chanp->fi, event, NULL);
+ chanp++;
+ i++;
+ }
+ return;
+ } else if (pr == (CC_SETUP | INDICATION)) {
if (!(chanp = selectfreechannel(pc->st))) {
- pc->st->lli.l4l3(pc->st, CC_DLRL, pc);
- return;
+ pc->st->lli.l4l3(pc->st, CC_DLRL | REQUEST, pc);
} else {
chanp->proc = pc;
pc->chan = chanp;
FsmEvent(&chanp->fi, EV_SETUP_IND, NULL);
- return;
}
- } else if (pr == CC_ESTABLISH) {
- if (is_activ(pc->st)) {
- pc->st->lli.l4l3(pc->st, CC_ESTABLISH, pc);
- return;
- } else if (!(chanp = selectfreechannel(pc->st))) {
- pc->st->lli.l4l3(pc->st, CC_DLRL, pc);
- return;
- } else {
- chanp->proc = pc;
- FsmEvent(&chanp->fi, EV_ESTABLISH, NULL);
- return;
- }
-
-
+ return;
}
- chanp = pc->chan;
+ if (!(chanp = pc->chan))
+ return;
+
switch (pr) {
- case (CC_DISCONNECT_IND):
+ case (CC_DISCONNECT | INDICATION):
FsmEvent(&chanp->fi, EV_DISCONNECT_IND, NULL);
break;
- case (CC_RELEASE_CNF):
+ case (CC_RELEASE | CONFIRM):
+ FsmEvent(&chanp->fi, EV_RELEASE_CNF, NULL);
+ break;
+ case (CC_SUSPEND | CONFIRM):
FsmEvent(&chanp->fi, EV_RELEASE_CNF, NULL);
break;
- case (CC_RELEASE_IND):
+ case (CC_RESUME | CONFIRM):
+ FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL);
+ break;
+ case (CC_RESUME_ERR):
+ FsmEvent(&chanp->fi, EV_RELEASE_CNF, NULL);
+ break;
+ case (CC_RELEASE | INDICATION):
FsmEvent(&chanp->fi, EV_RELEASE_IND, NULL);
break;
- case (CC_SETUP_COMPLETE_IND):
+ case (CC_SETUP_COMPL | INDICATION):
FsmEvent(&chanp->fi, EV_SETUP_CMPL_IND, NULL);
break;
- case (CC_SETUP_CNF):
+ case (CC_SETUP | CONFIRM):
FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL);
break;
- case (CC_INFO_CHARGE):
+ case (CC_CHARGE | INDICATION):
FsmEvent(&chanp->fi, EV_CINF, NULL);
break;
- case (CC_NOSETUP_RSP_ERR):
+ case (CC_NOSETUP_RSP):
FsmEvent(&chanp->fi, EV_NOSETUP_RSP, NULL);
break;
case (CC_SETUP_ERR):
@@ -1558,15 +1334,14 @@ ll_handler(struct l3_process *pc, int pr, void *arg)
case (CC_RELEASE_ERR):
FsmEvent(&chanp->fi, EV_RELEASE_ERR, NULL);
break;
- case (CC_PROCEEDING_IND):
- case (CC_ALERTING_IND):
+ case (CC_PROCEEDING | INDICATION):
+ case (CC_ALERTING | INDICATION):
break;
default:
if (chanp->debug & 0x800) {
- jiftime(tm, jiffies);
- sprintf(tmp, "%s Channel %d L3->L4 unknown primitiv %d\n",
- tm, chanp->chan, pr);
- HiSax_putstatus(chanp->cs, tmp);
+ HiSax_putstatus(chanp->cs, "Ch",
+ "%d L3->L4 unknown primitiv %x",
+ chanp->chan, pr);
}
}
}
@@ -1576,7 +1351,7 @@ init_d_st(struct Channel *chanp)
{
struct PStack *st = chanp->d_st;
struct IsdnCardState *cs = chanp->cs;
- char tmp[128];
+ char tmp[16];
HiSax_addlist(cs, st);
setstack_HiSax(st, cs);
@@ -1590,95 +1365,50 @@ init_d_st(struct Channel *chanp)
st->l2.window = 1;
st->l2.T200 = 1000; /* 1000 milliseconds */
st->l2.N200 = 3; /* try 3 times */
- if (st->protocol == ISDN_PTYPE_1TR6)
- st->l2.T203 = 10000; /* 10000 milliseconds */
+ st->l2.T203 = 10000; /* 10000 milliseconds */
+ if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags))
+ sprintf(tmp, "DCh%d Q.921 ", chanp->chan);
else
- st->l2.T203 = 10000; /* 5000 milliseconds */
-
- sprintf(tmp, "Channel %d q.921", chanp->chan);
+ sprintf(tmp, "DCh Q.921 ");
setstack_isdnl2(st, tmp);
- setstack_isdnl3(st, chanp);
+ setstack_l3dc(st, chanp);
st->lli.userdata = chanp;
st->lli.l2writewakeup = NULL;
- st->l3.l3l4 = ll_handler;
- st->l1.l1man = dc_l1man;
- st->l2.l2man = dc_l2man;
+ st->l3.l3l4 = dchan_l3l4;
}
static void
-callc_debug(struct FsmInst *fi, char *s)
+callc_debug(struct FsmInst *fi, char *fmt, ...)
{
- char str[80], tm[32];
+ va_list args;
struct Channel *chanp = fi->userdata;
+ char tmp[16];
- jiftime(tm, jiffies);
- sprintf(str, "%s Channel %d callc %s\n", tm, chanp->chan, s);
- HiSax_putstatus(chanp->cs, str);
-}
-
-static void
-lc_debug(struct FsmInst *fi, char *s)
-{
- char str[256], tm[32];
- struct LcFsm *lf = fi->userdata;
-
- jiftime(tm, jiffies);
- sprintf(str, "%s Channel %d dc %s\n", tm, lf->ch->chan, s);
- HiSax_putstatus(lf->ch->cs, str);
-}
-
-static void
-dlc_debug(struct FsmInst *fi, char *s)
-{
- char str[256], tm[32];
- struct LcFsm *lf = fi->userdata;
-
- jiftime(tm, jiffies);
- sprintf(str, "%s Channel %d bc %s\n", tm, lf->ch->chan, s);
- HiSax_putstatus(lf->ch->cs, str);
+ va_start(args, fmt);
+ sprintf(tmp, "Ch%d callc ", chanp->chan);
+ VHiSax_putstatus(chanp->cs, tmp, fmt, args);
+ va_end(args);
}
static void
-lccall_d(struct LcFsm *lf, int pr, void *arg)
-{
- struct IsdnCardState *cs = lf->st->l1.hardware;
- struct Channel *chanp;
- int i;
-
- if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags)) {
- chanp = lf->ch;
- i = 1;
- } else {
- chanp = cs->channel;
- i = 0;
- }
- while (i < 2) {
- switch (pr) {
- case (LC_ESTABLISH):
- FsmEvent(&chanp->fi, EV_DLEST, NULL);
- break;
- case (LC_RELEASE):
- FsmEvent(&chanp->fi, EV_DLRL, NULL);
- break;
- }
- chanp++;
- i++;
- }
+dummy_pstack(struct PStack *st, int pr, void *arg) {
+ printk(KERN_WARNING"call to dummy_pstack pr=%04x arg %lx\n", pr, (long)arg);
}
static void
-lccall_b(struct LcFsm *lf, int pr, void *arg)
-{
- struct Channel *chanp = lf->ch;
-
- switch (pr) {
- case (LC_ESTABLISH):
- FsmEvent(&chanp->fi, EV_BC_EST, NULL);
- break;
- case (LC_RELEASE):
- FsmEvent(&chanp->fi, EV_BC_REL, NULL);
- break;
- }
+init_PStack(struct PStack **stp) {
+ *stp = kmalloc(sizeof(struct PStack), GFP_ATOMIC);
+ (*stp)->next = NULL;
+ (*stp)->l1.l1l2 = dummy_pstack;
+ (*stp)->l1.l1hw = dummy_pstack;
+ (*stp)->l1.l1tei = dummy_pstack;
+ (*stp)->l2.l2tei = dummy_pstack;
+ (*stp)->l2.l2l1 = dummy_pstack;
+ (*stp)->l2.l2l3 = dummy_pstack;
+ (*stp)->l3.l3l2 = dummy_pstack;
+ (*stp)->l3.l3l4 = dummy_pstack;
+ (*stp)->lli.l4l3 = dummy_pstack;
+ (*stp)->ma.layer = dummy_pstack;
}
static void
@@ -1693,9 +1423,8 @@ init_chan(int chan, struct IsdnCardState *csta)
chanp->debug = 0;
chanp->Flags = 0;
chanp->leased = 0;
- chanp->b_st = kmalloc(sizeof(struct PStack), GFP_ATOMIC);
- chanp->b_st->next = NULL;
-
+ init_PStack(&chanp->b_st);
+ chanp->b_st->l1.delay = DEFAULT_B_DELAY;
chanp->fi.fsm = &callcfsm;
chanp->fi.state = ST_NULL;
chanp->fi.debug = 0;
@@ -1704,41 +1433,14 @@ init_chan(int chan, struct IsdnCardState *csta)
FsmInitTimer(&chanp->fi, &chanp->dial_timer);
FsmInitTimer(&chanp->fi, &chanp->drel_timer);
if (!chan || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) {
- chanp->d_st = kmalloc(sizeof(struct PStack), GFP_ATOMIC);
+ init_PStack(&chanp->d_st);
+ if (chan)
+ csta->channel->d_st->next = chanp->d_st;
chanp->d_st->next = NULL;
init_d_st(chanp);
- chanp->lc_d = kmalloc(sizeof(struct LcFsm), GFP_ATOMIC);
- chanp->lc_d->lcfi.fsm = &lcfsm;
- chanp->lc_d->lcfi.state = ST_LC_NULL;
- chanp->lc_d->lcfi.debug = 0;
- chanp->lc_d->lcfi.userdata = chanp->lc_d;
- chanp->lc_d->lcfi.printdebug = lc_debug;
- chanp->lc_d->type = LC_D;
- chanp->lc_d->delay = 0;
- chanp->lc_d->ch = chanp;
- chanp->lc_d->st = chanp->d_st;
- chanp->lc_d->l2_establish = !0;
- chanp->lc_d->l2_start = !0;
- chanp->lc_d->lccall = lccall_d;
- FsmInitTimer(&chanp->lc_d->lcfi, &chanp->lc_d->act_timer);
} else {
chanp->d_st = csta->channel->d_st;
- chanp->lc_d = csta->channel->lc_d;
}
- chanp->lc_b = kmalloc(sizeof(struct LcFsm), GFP_ATOMIC);
- chanp->lc_b->lcfi.fsm = &lcfsm;
- chanp->lc_b->lcfi.state = ST_LC_NULL;
- chanp->lc_b->lcfi.debug = 0;
- chanp->lc_b->lcfi.userdata = chanp->lc_b;
- chanp->lc_b->lcfi.printdebug = dlc_debug;
- chanp->lc_b->type = LC_B;
- chanp->lc_b->delay = DEFAULT_B_DELAY;
- chanp->lc_b->ch = chanp;
- chanp->lc_b->st = chanp->b_st;
- chanp->lc_b->l2_establish = !0;
- chanp->lc_b->l2_start = !0;
- chanp->lc_b->lccall = lccall_b;
- FsmInitTimer(&chanp->lc_b->lcfi, &chanp->lc_b->act_timer);
chanp->data_open = 0;
}
@@ -1749,11 +1451,12 @@ CallcNewChan(struct IsdnCardState *csta)
init_chan(0, csta);
init_chan(1, csta);
printk(KERN_INFO "HiSax: 2 channels added\n");
-#ifdef LAYER2_WATCHING
- printk(KERN_INFO "LAYER2 ESTABLISH\n");
- test_and_set_bit(FLG_START_D, &csta->channel->Flags);
- FsmEvent(&csta->channel->lc_d->lcfi, EV_LC_ESTABLISH, NULL);
-#endif
+ if (test_bit(FLG_PTP, &csta->channel->d_st->l2.flag)) {
+ printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n");
+ test_and_set_bit(FLG_START_D, &csta->channel->Flags);
+ csta->channel->d_st->lli.l4l3(csta->channel->d_st,
+ DL_ESTABLISH | REQUEST, NULL);
+ }
return (2);
}
@@ -1779,8 +1482,6 @@ CallcFreeChan(struct IsdnCardState *csta)
for (i = 0; i < 2; i++) {
FsmDelTimer(&csta->channel[i].drel_timer, 74);
FsmDelTimer(&csta->channel[i].dial_timer, 75);
- FsmDelTimer(&csta->channel[i].lc_d->act_timer, 77);
- FsmDelTimer(&csta->channel[i].lc_b->act_timer, 76);
if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags))
release_d_st(csta->channel + i);
if (csta->channel[i].b_st) {
@@ -1790,18 +1491,8 @@ CallcFreeChan(struct IsdnCardState *csta)
csta->channel[i].b_st = NULL;
} else
printk(KERN_WARNING "CallcFreeChan b_st ch%d allready freed\n", i);
- if (csta->channel[i].lc_b) {
- kfree(csta->channel[i].lc_b);
- csta->channel[i].b_st = NULL;
- }
if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) {
release_d_st(csta->channel + i);
- FsmDelTimer(&csta->channel[i].lc_d->act_timer, 77);
- if (csta->channel[i].lc_d) {
- kfree(csta->channel[i].lc_d);
- csta->channel[i].d_st = NULL;
- } else
- printk(KERN_WARNING "CallcFreeChan lc_d ch%d allready freed\n", i);
} else
csta->channel[i].d_st = NULL;
}
@@ -1814,15 +1505,23 @@ lldata_handler(struct PStack *st, int pr, void *arg)
struct sk_buff *skb = arg;
switch (pr) {
- case (DL_DATA):
+ case (DL_DATA | INDICATION):
if (chanp->data_open)
chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb);
else {
dev_kfree_skb(skb);
}
break;
+ case (DL_ESTABLISH | INDICATION):
+ case (DL_ESTABLISH | CONFIRM):
+ FsmEvent(&chanp->fi, EV_BC_EST, NULL);
+ break;
+ case (DL_RELEASE | INDICATION):
+ case (DL_RELEASE | CONFIRM):
+ FsmEvent(&chanp->fi, EV_BC_REL, NULL);
+ break;
default:
- printk(KERN_WARNING "lldata_handler unknown primitive %d\n",
+ printk(KERN_WARNING "lldata_handler unknown primitive %x\n",
pr);
break;
}
@@ -1835,22 +1534,24 @@ lltrans_handler(struct PStack *st, int pr, void *arg)
struct sk_buff *skb = arg;
switch (pr) {
- case (PH_DATA_IND):
+ case (PH_DATA | INDICATION):
if (chanp->data_open)
chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb);
else {
- if (chanp->lc_b->lcfi.state == ST_LC_DELAY)
- FsmEvent(&chanp->lc_b->lcfi, EV_LC_DL_ESTABLISH, NULL);
- if (chanp->data_open) {
- link_debug(chanp, "channel now open", 0);
- chanp->cs->iif.rcvcallb_skb(chanp->cs->myid,
- chanp->chan, skb);
- } else
- dev_kfree_skb(skb);
+ link_debug(chanp, 0, "channel not open");
+ dev_kfree_skb(skb);
}
break;
+ case (PH_ACTIVATE | INDICATION):
+ case (PH_ACTIVATE | CONFIRM):
+ FsmEvent(&chanp->fi, EV_BC_EST, NULL);
+ break;
+ case (PH_DEACTIVATE | INDICATION):
+ case (PH_DEACTIVATE | CONFIRM):
+ FsmEvent(&chanp->fi, EV_BC_REL, NULL);
+ break;
default:
- printk(KERN_WARNING "lltrans_handler unknown primitive %d\n",
+ printk(KERN_WARNING "lltrans_handler unknown primitive %x\n",
pr);
break;
}
@@ -1865,7 +1566,7 @@ ll_writewakeup(struct PStack *st, int len)
ic.driver = chanp->cs->myid;
ic.command = ISDN_STAT_BSENT;
ic.arg = chanp->chan;
- ic.parm.length = len;
+// ic.parm.length = len;
chanp->cs->iif.statcallb(&ic);
}
@@ -1874,10 +1575,27 @@ init_b_st(struct Channel *chanp, int incoming)
{
struct PStack *st = chanp->b_st;
struct IsdnCardState *cs = chanp->cs;
- char tmp[128];
+ char tmp[16];
st->l1.hardware = cs;
- chanp->bcs->mode = 2;
+ if (chanp->leased)
+ st->l1.bc = chanp->chan & 1;
+ else
+ st->l1.bc = chanp->proc->para.bchannel - 1;
+ switch (chanp->l2_active_protocol) {
+ case (ISDN_PROTO_L2_X75I):
+ case (ISDN_PROTO_L2_HDLC):
+ st->l1.mode = L1_MODE_HDLC;
+ break;
+ case (ISDN_PROTO_L2_TRANS):
+ st->l1.mode = L1_MODE_TRANS;
+ break;
+#if 0
+ case (ISDN_PROTO_L2_MODEM):
+ st->l1.mode = L1_MODE_MODEM;
+ break;
+#endif
+ }
if (chanp->bcs->BC_SetStack(st, chanp->bcs))
return (-1);
st->l2.flag = 0;
@@ -1892,50 +1610,87 @@ init_b_st(struct Channel *chanp, int incoming)
st->l3.debug = 0;
switch (chanp->l2_active_protocol) {
case (ISDN_PROTO_L2_X75I):
- sprintf(tmp, "Channel %d x.75", chanp->chan);
+ sprintf(tmp, "Ch%d X.75", chanp->chan);
setstack_isdnl2(st, tmp);
+ setstack_l3bc(st, chanp);
st->l2.l2l3 = lldata_handler;
- st->l1.l1man = bc_l1man;
- st->l2.l2man = bc_l2man;
st->lli.userdata = chanp;
st->lli.l1writewakeup = NULL;
st->lli.l2writewakeup = ll_writewakeup;
st->l2.l2m.debug = chanp->debug & 16;
st->l2.debug = chanp->debug & 64;
- st->ma.manl2(st, MDL_NOTEIPROC, NULL);
- st->l1.mode = L1_MODE_HDLC;
- if (chanp->leased)
- st->l1.bc = chanp->chan & 1;
- else
- st->l1.bc = chanp->proc->para.bchannel - 1;
break;
case (ISDN_PROTO_L2_HDLC):
- st->l1.l1l2 = lltrans_handler;
- st->l1.l1man = bc_l1man;
- st->lli.userdata = chanp;
- st->lli.l1writewakeup = ll_writewakeup;
- st->l1.mode = L1_MODE_HDLC;
- if (chanp->leased)
- st->l1.bc = chanp->chan & 1;
- else
- st->l1.bc = chanp->proc->para.bchannel - 1;
- break;
case (ISDN_PROTO_L2_TRANS):
+// case (ISDN_PROTO_L2_MODEM):
st->l1.l1l2 = lltrans_handler;
- st->l1.l1man = bc_l1man;
st->lli.userdata = chanp;
st->lli.l1writewakeup = ll_writewakeup;
- st->l1.mode = L1_MODE_TRANS;
- if (chanp->leased)
- st->l1.bc = chanp->chan & 1;
- else
- st->l1.bc = chanp->proc->para.bchannel - 1;
+ setstack_transl2(st);
+ setstack_l3bc(st, chanp);
break;
}
return (0);
}
static void
+leased_l4l3(struct PStack *st, int pr, void *arg)
+{
+ struct Channel *chanp = (struct Channel *) st->lli.userdata;
+ struct sk_buff *skb = arg;
+
+ switch (pr) {
+ case (DL_DATA | REQUEST):
+ link_debug(chanp, 0, "leased line d-channel DATA");
+ dev_kfree_skb(skb);
+ break;
+ case (DL_ESTABLISH | REQUEST):
+ st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL);
+ break;
+ case (DL_RELEASE | REQUEST):
+ break;
+ default:
+ printk(KERN_WARNING "transd_l4l3 unknown primitive %x\n",
+ pr);
+ break;
+ }
+}
+
+static void
+leased_l1l2(struct PStack *st, int pr, void *arg)
+{
+ struct Channel *chanp = (struct Channel *) st->lli.userdata;
+ struct sk_buff *skb = arg;
+ int i,event = EV_DLRL;
+
+ switch (pr) {
+ case (PH_DATA | INDICATION):
+ link_debug(chanp, 0, "leased line d-channel DATA");
+ dev_kfree_skb(skb);
+ break;
+ case (PH_ACTIVATE | INDICATION):
+ case (PH_ACTIVATE | CONFIRM):
+ event = EV_DLEST;
+ case (PH_DEACTIVATE | INDICATION):
+ case (PH_DEACTIVATE | CONFIRM):
+ if (test_bit(FLG_TWO_DCHAN, &chanp->cs->HW_Flags))
+ i = 1;
+ else
+ i = 0;
+ while (i < 2) {
+ FsmEvent(&chanp->fi, event, NULL);
+ chanp++;
+ i++;
+ }
+ break;
+ default:
+ printk(KERN_WARNING
+ "transd_l1l2 unknown primitive %x\n", pr);
+ break;
+ }
+}
+
+static void
channel_report(struct Channel *chanp)
{
}
@@ -1953,13 +1708,70 @@ distr_debug(struct IsdnCardState *csta, int debugflags)
chanp[i].b_st->l2.l2m.debug = debugflags & 0x10;
chanp[i].d_st->l2.debug = debugflags & 0x20;
chanp[i].b_st->l2.debug = debugflags & 0x40;
- chanp[i].lc_d->lcfi.debug = debugflags & 0x80;
- chanp[i].lc_b->lcfi.debug = debugflags & 0x100;
+ chanp[i].d_st->l3.l3m.debug = debugflags & 0x80;
+ chanp[i].b_st->l3.l3m.debug = debugflags & 0x100;
chanp[i].b_st->ma.tei_m.debug = debugflags & 0x200;
chanp[i].b_st->ma.debug = debugflags & 0x200;
chanp[i].d_st->l1.l1m.debug = debugflags & 0x1000;
+ chanp[i].b_st->l1.l1m.debug = debugflags & 0x2000;
+ }
+ if (debugflags & 4)
+ csta->debug |= DEB_DLOG_HEX;
+ else
+ csta->debug &= ~DEB_DLOG_HEX;
+}
+
+static char tmpbuf[256];
+
+static void
+capi_debug(struct Channel *chanp, capi_msg *cm)
+{
+ char *t = tmpbuf;
+
+ t += sprintf(tmpbuf, "%d CAPIMSG", chanp->chan);
+ t += QuickHex(t, (u_char *)cm, (cm->Length>50)? 50: cm->Length);
+ t--;
+ *t= 0;
+ HiSax_putstatus(chanp->cs, "Ch", "%d CAPIMSG %s", chanp->chan, tmpbuf);
+}
+
+void
+lli_got_fac_req(struct Channel *chanp, capi_msg *cm) {
+ if ((cm->para[0] != 3) || (cm->para[1] != 0))
+ return;
+ if (cm->para[2]<3)
+ return;
+ if (cm->para[4] != 0)
+ return;
+ switch(cm->para[3]) {
+ case 4: /* Suspend */
+ if (cm->para[5]) {
+ strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1);
+ FsmEvent(&chanp->fi, EV_SUSPEND, cm);
+ }
+ break;
+ case 5: /* Resume */
+ if (cm->para[5]) {
+ strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1);
+ if (chanp->fi.state == ST_NULL) {
+ FsmEvent(&chanp->fi, EV_RESUME, cm);
+ } else {
+ FsmDelTimer(&chanp->dial_timer, 72);
+ FsmAddTimer(&chanp->dial_timer, 80, EV_RESUME, cm, 73);
+ }
+ }
+ break;
+ }
+}
+
+void
+lli_got_manufacturer(struct Channel *chanp, struct IsdnCardState *cs, capi_msg *cm) {
+ if ((cs->typ == ISDN_CTYPE_ELSA) || (cs->typ == ISDN_CTYPE_ELSA_PNP) ||
+ (cs->typ == ISDN_CTYPE_ELSA_PCI)) {
+ if (cs->hw.elsa.MFlag) {
+ cs->cardmsg(cs, CARD_AUX_IND, cm->para);
+ }
}
- csta->dlogflag = debugflags & 4;
}
int
@@ -1967,9 +1779,9 @@ HiSax_command(isdn_ctrl * ic)
{
struct IsdnCardState *csta = hisax_findcard(ic->driver);
struct Channel *chanp;
- char tmp[128];
int i;
- unsigned int num;
+ u_int num;
+ u_long adr;
if (!csta) {
printk(KERN_ERR
@@ -1977,32 +1789,32 @@ HiSax_command(isdn_ctrl * ic)
ic->command, ic->driver);
return -ENODEV;
}
+
switch (ic->command) {
case (ISDN_CMD_SETEAZ):
chanp = csta->channel + ic->arg;
- if (chanp->debug & 1) {
- sprintf(tmp, "SETEAZ card %d %s", csta->cardnr + 1,
- ic->parm.num);
- link_debug(chanp, tmp, 1);
- }
break;
+
case (ISDN_CMD_SETL2):
chanp = csta->channel + (ic->arg & 0xff);
- if (chanp->debug & 1) {
- sprintf(tmp, "SETL2 card %d %ld", csta->cardnr + 1,
- ic->arg >> 8);
- link_debug(chanp, tmp, 1);
- }
+ if (chanp->debug & 1)
+ link_debug(chanp, 1, "SETL2 card %d %ld",
+ csta->cardnr + 1, ic->arg >> 8);
chanp->l2_protocol = ic->arg >> 8;
break;
+ case (ISDN_CMD_SETL3):
+ chanp = csta->channel + (ic->arg & 0xff);
+ if (chanp->debug & 1)
+ link_debug(chanp, 1, "SETL3 card %d %ld",
+ csta->cardnr + 1, ic->arg >> 8);
+ chanp->l3_protocol = ic->arg >> 8;
+ break;
case (ISDN_CMD_DIAL):
chanp = csta->channel + (ic->arg & 0xff);
- if (chanp->debug & 1) {
- sprintf(tmp, "DIAL %s -> %s (%d,%d)",
+ if (chanp->debug & 1)
+ link_debug(chanp, 1, "DIAL %s -> %s (%d,%d)",
ic->parm.setup.eazmsn, ic->parm.setup.phone,
- ic->parm.setup.si1, ic->parm.setup.si2);
- link_debug(chanp, tmp, 1);
- }
+ ic->parm.setup.si1, ic->parm.setup.si2);
chanp->setup = ic->parm.setup;
if (!strcmp(chanp->setup.eazmsn, "0"))
chanp->setup.eazmsn[0] = '\0';
@@ -2018,57 +1830,54 @@ HiSax_command(isdn_ctrl * ic)
case (ISDN_CMD_ACCEPTB):
chanp = csta->channel + ic->arg;
if (chanp->debug & 1)
- link_debug(chanp, "ACCEPTB", 1);
+ link_debug(chanp, 1, "ACCEPTB");
FsmEvent(&chanp->fi, EV_ACCEPTB, NULL);
break;
case (ISDN_CMD_ACCEPTD):
chanp = csta->channel + ic->arg;
if (chanp->debug & 1)
- link_debug(chanp, "ACCEPTD", 1);
+ link_debug(chanp, 1, "ACCEPTD");
FsmEvent(&chanp->fi, EV_ACCEPTD, NULL);
break;
case (ISDN_CMD_HANGUP):
chanp = csta->channel + ic->arg;
if (chanp->debug & 1)
- link_debug(chanp, "HANGUP", 1);
+ link_debug(chanp, 1, "HANGUP");
FsmEvent(&chanp->fi, EV_HANGUP, NULL);
break;
- case (ISDN_CMD_SUSPEND):
- chanp = csta->channel + ic->arg;
- if (chanp->debug & 1) {
- sprintf(tmp, "SUSPEND %s", ic->parm.num);
- link_debug(chanp, tmp, 1);
- }
- FsmEvent(&chanp->fi, EV_SUSPEND, ic);
- break;
- case (ISDN_CMD_RESUME):
+ case (CAPI_PUT_MESSAGE):
chanp = csta->channel + ic->arg;
- if (chanp->debug & 1) {
- sprintf(tmp, "RESUME %s", ic->parm.num);
- link_debug(chanp, tmp, 1);
+ if (chanp->debug & 1)
+ capi_debug(chanp, &ic->parm.cmsg);
+ if (ic->parm.cmsg.Length < 8)
+ break;
+ switch(ic->parm.cmsg.Command) {
+ case CAPI_FACILITY:
+ if (ic->parm.cmsg.Subcommand == CAPI_REQ)
+ lli_got_fac_req(chanp, &ic->parm.cmsg);
+ break;
+ case CAPI_MANUFACTURER:
+ if (ic->parm.cmsg.Subcommand == CAPI_REQ)
+ lli_got_manufacturer(chanp, csta, &ic->parm.cmsg);
+ break;
+ default:
+ break;
}
- FsmEvent(&chanp->fi, EV_RESUME, ic);
break;
case (ISDN_CMD_LOCK):
HiSax_mod_inc_use_count();
#ifdef MODULE
- if (csta->channel[0].debug & 0x400) {
- jiftime(tmp, jiffies);
- i = strlen(tmp);
- sprintf(tmp + i, " LOCK modcnt %d\n", MOD_USE_COUNT);
- HiSax_putstatus(csta, tmp);
- }
+ if (csta->channel[0].debug & 0x400)
+ HiSax_putstatus(csta, " LOCK ", "modcnt %x",
+ MOD_USE_COUNT);
#endif /* MODULE */
break;
case (ISDN_CMD_UNLOCK):
HiSax_mod_dec_use_count();
#ifdef MODULE
- if (csta->channel[0].debug & 0x400) {
- jiftime(tmp, jiffies);
- i = strlen(tmp);
- sprintf(tmp + i, " UNLOCK modcnt %d\n", MOD_USE_COUNT);
- HiSax_putstatus(csta, tmp);
- }
+ if (csta->channel[0].debug & 0x400)
+ HiSax_putstatus(csta, " UNLOCK ", "modcnt %x",
+ MOD_USE_COUNT);
#endif /* MODULE */
break;
case (ISDN_CMD_IOCTL):
@@ -2081,19 +1890,19 @@ HiSax_command(isdn_ctrl * ic)
case (1):
num = *(unsigned int *) ic->parm.num;
distr_debug(csta, num);
- sprintf(tmp, "debugging flags card %d set to %x\n",
+ printk(KERN_DEBUG "HiSax: debugging flags card %d set to %x\n",
csta->cardnr + 1, num);
- HiSax_putstatus(csta, tmp);
- printk(KERN_DEBUG "HiSax: %s", tmp);
+ HiSax_putstatus(csta, "debugging flags ",
+ "card %d set to %x", csta->cardnr + 1, num);
break;
case (2):
- num = *(unsigned int *) ic->parm.num;
- csta->channel[0].lc_b->delay = num;
- csta->channel[1].lc_b->delay = num;
- sprintf(tmp, "delay card %d set to %d ms\n",
+ num = *(unsigned int *) ic->parm.num;
+ csta->channel[0].b_st->l1.delay = num;
+ csta->channel[1].b_st->l1.delay = num;
+ HiSax_putstatus(csta, "delay ", "card %d set to %d ms",
+ csta->cardnr + 1, num);
+ printk(KERN_DEBUG "HiSax: delay card %d set to %d ms\n",
csta->cardnr + 1, num);
- HiSax_putstatus(csta, tmp);
- printk(KERN_DEBUG "HiSax: %s", tmp);
break;
case (3):
for (i = 0; i < *(unsigned int *) ic->parm.num; i++)
@@ -2106,47 +1915,91 @@ HiSax_command(isdn_ctrl * ic)
case (5): /* set card in leased mode */
num = *(unsigned int *) ic->parm.num;
if ((num <1) || (num > 2)) {
- sprintf(tmp, "Set LEASED wrong channel %d\n",
+ HiSax_putstatus(csta, "Set LEASED ",
+ "wrong channel %d", num);
+ printk(KERN_WARNING "HiSax: Set LEASED wrong channel %d\n",
num);
- HiSax_putstatus(csta, tmp);
- printk(KERN_WARNING "HiSax: %s", tmp);
} else {
num--;
- csta->channel[num].leased = 1;
- csta->channel[num].lc_d->l2_establish = 0;
- sprintf(tmp, "card %d channel %d set leased mode\n",
+ chanp = csta->channel +num;
+ chanp->leased = 1;
+ HiSax_putstatus(csta, "Card",
+ "%d channel %d set leased mode\n",
csta->cardnr + 1, num + 1);
- HiSax_putstatus(csta, tmp);
- FsmEvent(&csta->channel[num].lc_d->lcfi, EV_LC_ESTABLISH, NULL);
+ chanp->d_st->l1.l1l2 = leased_l1l2;
+ chanp->d_st->lli.l4l3 = leased_l4l3;
+ chanp->d_st->lli.l4l3(chanp->d_st,
+ DL_ESTABLISH | REQUEST, NULL);
}
break;
case (6): /* set B-channel test loop */
num = *(unsigned int *) ic->parm.num;
if (csta->stlist)
- csta->stlist->ma.manl1(csta->stlist,
- PH_TESTLOOP_REQ, (void *) num);
+ csta->stlist->l2.l2l1(csta->stlist,
+ PH_TESTLOOP | REQUEST, (void *) (long)num);
+ break;
+ case (7): /* set card in PTP mode */
+ num = *(unsigned int *) ic->parm.num;
+ if (test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) {
+ printk(KERN_ERR "HiSax PTP mode only with one TEI possible\n");
+ } else if (num) {
+ test_and_set_bit(FLG_PTP, &csta->channel[0].d_st->l2.flag);
+ test_and_set_bit(FLG_FIXED_TEI, &csta->channel[0].d_st->l2.flag);
+ csta->channel[0].d_st->l2.tei = 0;
+ HiSax_putstatus(csta, "set card ", "in PTP mode");
+ printk(KERN_DEBUG "HiSax: set card in PTP mode\n");
+ printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n");
+ test_and_set_bit(FLG_START_D, &csta->channel[0].Flags);
+ test_and_set_bit(FLG_START_D, &csta->channel[1].Flags);
+ csta->channel[0].d_st->lli.l4l3(csta->channel[0].d_st,
+ DL_ESTABLISH | REQUEST, NULL);
+ } else {
+ test_and_clear_bit(FLG_PTP, &csta->channel[0].d_st->l2.flag);
+ test_and_clear_bit(FLG_FIXED_TEI, &csta->channel[0].d_st->l2.flag);
+ HiSax_putstatus(csta, "set card ", "in PTMP mode");
+ printk(KERN_DEBUG "HiSax: set card in PTMP mode\n");
+ }
+ break;
+ case (8): /* set card in FIXED TEI mode */
+ num = *(unsigned int *) ic->parm.num;
+ chanp = csta->channel + (num & 1);
+ num = num >>1;
+ test_and_set_bit(FLG_FIXED_TEI, &chanp->d_st->l2.flag);
+ chanp->d_st->l2.tei = num;
+ HiSax_putstatus(csta, "set card ", "in FIXED TEI (%d) mode", num);
+ printk(KERN_DEBUG "HiSax: set card in FIXED TEI (%d) mode\n",
+ num);
+ break;
+ case (9): /* load firmware */
+ memcpy(&adr, ic->parm.num, sizeof(ulong));
+ csta->cardmsg(csta, CARD_LOAD_FIRM,
+ (void *) adr);
break;
#ifdef MODULE
case (55):
while ( MOD_USE_COUNT > 0)
- MOD_DEC_USE_COUNT;
+ MOD_DEC_USE_COUNT;
HiSax_mod_inc_use_count();
break;
#endif /* MODULE */
case (11):
+ num = csta->debug & DEB_DLOG_HEX;
csta->debug = *(unsigned int *) ic->parm.num;
- sprintf(tmp, "l1 debugging flags card %d set to %x\n",
+ csta->debug |= num;
+ HiSax_putstatus(cards[0].cs, "l1 debugging ",
+ "flags card %d set to %x",
+ csta->cardnr + 1, csta->debug);
+ printk(KERN_DEBUG "HiSax: l1 debugging flags card %d set to %x\n",
csta->cardnr + 1, csta->debug);
- HiSax_putstatus(cards[0].cs, tmp);
- printk(KERN_DEBUG "HiSax: %s", tmp);
break;
case (13):
csta->channel[0].d_st->l3.debug = *(unsigned int *) ic->parm.num;
csta->channel[1].d_st->l3.debug = *(unsigned int *) ic->parm.num;
- sprintf(tmp, "l3 debugging flags card %d set to %x\n",
+ HiSax_putstatus(cards[0].cs, "l3 debugging ",
+ "flags card %d set to %x\n", csta->cardnr + 1,
+ *(unsigned int *) ic->parm.num);
+ printk(KERN_DEBUG "HiSax: l3 debugging flags card %d set to %x\n",
csta->cardnr + 1, *(unsigned int *) ic->parm.num);
- HiSax_putstatus(cards[0].cs, tmp);
- printk(KERN_DEBUG "HiSax: %s", tmp);
break;
default:
printk(KERN_DEBUG "HiSax: invalid ioclt %d\n",
@@ -2170,7 +2023,6 @@ HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb)
int len = skb->len;
unsigned long flags;
struct sk_buff *nskb;
- char tmp[64];
if (!csta) {
printk(KERN_ERR
@@ -2180,13 +2032,13 @@ HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb)
chanp = csta->channel + chan;
st = chanp->b_st;
if (!chanp->data_open) {
- link_debug(chanp, "writebuf: channel not open", 1);
+ link_debug(chanp, 1, "writebuf: channel not open");
return -EIO;
}
if (len > MAX_DATA_SIZE) {
- sprintf(tmp, "writebuf: packet too large (%d bytes)", len);
- printk(KERN_WARNING "HiSax_%s !\n", tmp);
- link_debug(chanp, tmp, 1);
+ link_debug(chanp, 1, "writebuf: packet too large (%d bytes)", len);
+ printk(KERN_WARNING "HiSax_writebuf: packet too large (%d bytes) !\n",
+ len);
return -EINVAL;
}
if (len) {
@@ -2194,10 +2046,8 @@ HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb)
/* Must return 0 here, since this is not an error
* but a temporary lack of resources.
*/
- if (chanp->debug & 0x800) {
- sprintf(tmp, "writebuf: no buffers for %d bytes", len);
- link_debug(chanp, tmp, 1);
- }
+ if (chanp->debug & 0x800)
+ link_debug(chanp, 1, "writebuf: no buffers for %d bytes", len);
return 0;
}
save_flags(flags);
@@ -2206,11 +2056,11 @@ HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb)
if (nskb) {
if (!ack)
nskb->pkt_type = PACKET_NOACK;
- if (chanp->lc_b->l2_establish)
- st->l3.l3l2(st, DL_DATA, nskb);
+ if (chanp->l2_active_protocol == ISDN_PROTO_L2_X75I)
+ st->l3.l3l2(st, DL_DATA | REQUEST, nskb);
else {
chanp->bcs->tx_cnt += len;
- st->l2.l2l1(st, PH_DATA_REQ, nskb);
+ st->l2.l2l1(st, PH_DATA | REQUEST, nskb);
}
dev_kfree_skb(skb);
} else
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index 3b98a3a30..7ca2de9e4 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -1,10 +1,50 @@
-/* $Id: config.c,v 2.12 1998/02/11 17:28:02 keil Exp $
+/* $Id: config.c,v 2.23 1999/02/17 10:53:02 cpetig Exp $
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
* based on the teles driver from Jan den Ouden
*
*
* $Log: config.c,v $
+ * Revision 2.23 1999/02/17 10:53:02 cpetig
+ * Added Hisax_closecard to exported symbols.
+ * As indicated by Oliver Schoett <os@sdm.de>.
+ *
+ * If anyone is annoyed by exporting symbols deep inside the code, please
+ * contact me.
+ *
+ * Revision 2.22 1999/02/04 21:41:53 keil
+ * Fix printk msg
+ *
+ * Revision 2.21 1999/02/04 10:48:52 keil
+ * Fix readstat bug
+ *
+ * Revision 2.20 1998/11/15 23:54:28 keil
+ * changes from 2.0
+ *
+ * Revision 2.19 1998/08/13 23:36:18 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.18 1998/07/30 21:01:37 niemann
+ * Fixed Sedlbauer Speed Fax PCMCIA missing isdnl3new
+ *
+ * Revision 2.17 1998/07/15 15:01:26 calle
+ * Support for AVM passive PCMCIA cards:
+ * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0
+ *
+ * Revision 2.16 1998/05/25 14:10:03 keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.15 1998/05/25 12:57:43 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.14 1998/04/15 16:38:25 keil
+ * Add S0Box and Teles PCI support
+ *
+ * Revision 2.13 1998/03/09 23:19:23 keil
+ * Changes for PCMCIA
+ *
* Revision 2.12 1998/02/11 17:28:02 keil
* Niccy PnP/PCI support
*
@@ -55,6 +95,12 @@
#include <linux/timer.h>
#include <linux/config.h>
#include "hisax.h"
+#include <linux/module.h>
+#include <linux/kernel_stat.h>
+#include <linux/tqueue.h>
+#include <linux/interrupt.h>
+#define HISAX_STATUS_BUFSIZE 4096
+#define INCLUDE_INLINE_FUNCS
/*
* This structure array contains one entry per card. An entry looks
@@ -78,42 +124,78 @@
* 13 Teleint p0=irq p1=iobase
* 14 Teles 16.3c p0=irq p1=iobase
* 15 Sedlbauer speed p0=irq p1=iobase
+ * 15 Sedlbauer PC/104 p0=irq p1=iobase
+ * 15 Sedlbauer speed pci no parameter
* 16 USR Sportster internal p0=irq p1=iobase
* 17 MIC card p0=irq p1=iobase
* 18 ELSA Quickstep 1000PCI no parameter
* 19 Compaq ISDN S0 ISA card p0=irq p1=IO0 (HSCX) p2=IO1 (ISAC) p3=IO2
* 20 Travers Technologies NETjet PCI card
- * 21 reserved TELES PCI
+ * 21 TELES PCI no parameter
* 22 Sedlbauer Speed Star p0=irq p1=iobase
* 23 reserved
* 24 Dr Neuhaus Niccy PnP/PCI card p0=irq p1=IO0 p2=IO1 (PnP only)
- *
+ * 25 Teles S0Box p0=irq p1=iobase (from isapnp setup)
+ * 26 AVM A1 PCMCIA (Fritz) p0=irq p1=iobase
+ * 27 AVM PnP/PCI p0=irq p1=iobase (PCI no parameter)
+ * 28 Sedlbauer Speed Fax+ p0=irq p1=iobase (from isapnp setup)
*
* protocol can be either ISDN_PTYPE_EURO or ISDN_PTYPE_1TR6 or ISDN_PTYPE_NI1
*
*
*/
+const char *CardType[] =
+{"No Card", "Teles 16.0", "Teles 8.0", "Teles 16.3", "Creatix/Teles PnP",
+ "AVM A1", "Elsa ML", "Elsa Quickstep", "Teles PCMCIA", "ITK ix1-micro Rev.2",
+ "Elsa PCMCIA", "Eicon.Diehl Diva", "ISDNLink", "TeleInt", "Teles 16.3c",
+ "Sedlbauer Speed Card", "USR Sportster", "ith mic Linux", "Elsa PCI",
+ "Compaq ISA", "NETjet", "Teles PCI", "Sedlbauer Speed Star (PCMCIA)",
+ "AMD 7930", "NICCY", "S0Box", "AVM A1 (PCMCIA)", "AVM Fritz PnP/PCI",
+ "Sedlbauer Speed Fax +"
+};
+
#ifdef CONFIG_HISAX_ELSA
#define DEFAULT_CARD ISDN_CTYPE_ELSA
#define DEFAULT_CFG {0,0,0,0}
-#ifdef MODULE
int elsa_init_pcmcia(void*, int, int*, int);
EXPORT_SYMBOL(elsa_init_pcmcia);
#endif
-#endif
#ifdef CONFIG_HISAX_AVM_A1
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_A1
#define DEFAULT_CFG {10,0x340,0,0}
#endif
+
+#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_A1_PCMCIA
+#define DEFAULT_CFG {11,0x170,0,0}
+int avm_a1_init_pcmcia(void*, int, int*, int);
+EXPORT_SYMBOL(avm_a1_init_pcmcia);
+#endif
+
+#ifdef CONFIG_HISAX_FRITZPCI
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_FRITZPCI
+#define DEFAULT_CFG {0,0,0,0}
+#endif
+
#ifdef CONFIG_HISAX_16_3
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_16_3
#define DEFAULT_CFG {15,0x180,0,0}
#endif
+#ifdef CONFIG_HISAX_S0BOX
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_S0BOX
+#define DEFAULT_CFG {7,0x378,0,0}
+#endif
#ifdef CONFIG_HISAX_16_0
#undef DEFAULT_CARD
#undef DEFAULT_CFG
@@ -121,6 +203,13 @@ EXPORT_SYMBOL(elsa_init_pcmcia);
#define DEFAULT_CFG {15,0xd0000,0xd80,0}
#endif
+#ifdef CONFIG_HISAX_TELESPCI
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_TELESPCI
+#define DEFAULT_CFG {0,0,0,0}
+#endif
+
#ifdef CONFIG_HISAX_IX1MICROR2
#undef DEFAULT_CARD
#undef DEFAULT_CFG
@@ -193,13 +282,6 @@ EXPORT_SYMBOL(sedl_init_pcmcia);
#define DEFAULT_CFG {12,0x3e0,0,0}
#endif
-#ifdef CONFIG_HISAX_DBRI
-#undef DEFAULT_CARD
-#undef DEFAULT_CFG
-#define DEFAULT_CARD ISDN_CTYPE_DBRI
-#define DEFAULT_CFG {0,0x0,0,0}
-#endif
-
#ifdef CONFIG_HISAX_NICCY
#undef DEFAULT_CARD
#undef DEFAULT_CFG
@@ -232,10 +314,10 @@ EXPORT_SYMBOL(sedl_init_pcmcia);
#endif
#define FIRST_CARD { \
- DEFAULT_CARD, \
- DEFAULT_PROTO, \
- DEFAULT_CFG, \
- NULL, \
+ DEFAULT_CARD, \
+ DEFAULT_PROTO, \
+ DEFAULT_CFG, \
+ NULL, \
}
#define EMPTY_CARD {0, DEFAULT_PROTO, {0, 0, 0, 0}, NULL}
@@ -250,29 +332,20 @@ struct IsdnCard cards[] =
EMPTY_CARD,
EMPTY_CARD,
EMPTY_CARD,
- EMPTY_CARD,
- EMPTY_CARD,
- EMPTY_CARD,
- EMPTY_CARD,
- EMPTY_CARD,
- EMPTY_CARD,
- EMPTY_CARD,
- EMPTY_CARD,
};
-static char HiSaxID[96] HISAX_INITDATA = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" \
-"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" \
+static char HiSaxID[64] HISAX_INITDATA = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" \
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" \
-"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
char *HiSax_id HISAX_INITDATA = HiSaxID;
#ifdef MODULE
/* Variables for insmod */
static int type[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+{0, 0, 0, 0, 0, 0, 0, 0};
static int protocol[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+{0, 0, 0, 0, 0, 0, 0, 0};
static int io[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+{0, 0, 0, 0, 0, 0, 0, 0};
#undef IO0_IO1
#ifdef CONFIG_HISAX_16_3
#define IO0_IO1
@@ -283,29 +356,29 @@ static int io[] HISAX_INITDATA =
#endif
#ifdef IO0_IO1
static int io0[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+{0, 0, 0, 0, 0, 0, 0, 0};
static int io1[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+{0, 0, 0, 0, 0, 0, 0, 0};
#endif
static int irq[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+{0, 0, 0, 0, 0, 0, 0, 0};
static int mem[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+{0, 0, 0, 0, 0, 0, 0, 0};
static char *id HISAX_INITDATA = HiSaxID;
MODULE_AUTHOR("Karsten Keil");
-MODULE_PARM(type, "1-3i");
-MODULE_PARM(protocol, "1-2i");
+MODULE_PARM(type, "1-8i");
+MODULE_PARM(protocol, "1-8i");
MODULE_PARM(io, "1-8i");
-MODULE_PARM(irq, "1-2i");
-MODULE_PARM(mem, "1-12i");
+MODULE_PARM(irq, "1-8i");
+MODULE_PARM(mem, "1-8i");
MODULE_PARM(id, "s");
#ifdef CONFIG_HISAX_16_3 /* For Creatix/Teles PnP */
MODULE_PARM(io0, "1-8i");
MODULE_PARM(io1, "1-8i");
-#endif
+#endif /* CONFIG_HISAX_16_3 */
-#endif
+#endif /* MODULE */
int nrcards;
@@ -333,23 +406,25 @@ HiSax_getrev(const char *revision))
HISAX_INITFUNC(void
HiSaxVersion(void))
{
- char tmp[64], rev[64];
- char *r = rev;
+ char tmp[64];
+ printk(KERN_INFO "HiSax: Linux Driver for passive ISDN cards\n");
+#ifdef MODULE
+ printk(KERN_INFO "HiSax: Version 3.1a (module)\n");
+#else
+ printk(KERN_INFO "HiSax: Version 3.1a (kernel)\n");
+#endif
strcpy(tmp, l1_revision);
- r += sprintf(r, "%s/", HiSax_getrev(tmp));
+ printk(KERN_INFO "HiSax: Layer1 Revision %s\n", HiSax_getrev(tmp));
strcpy(tmp, l2_revision);
- r += sprintf(r, "%s/", HiSax_getrev(tmp));
+ printk(KERN_INFO "HiSax: Layer2 Revision %s\n", HiSax_getrev(tmp));
+ strcpy(tmp, tei_revision);
+ printk(KERN_INFO "HiSax: TeiMgr Revision %s\n", HiSax_getrev(tmp));
strcpy(tmp, l3_revision);
- r += sprintf(r, "%s/", HiSax_getrev(tmp));
+ printk(KERN_INFO "HiSax: Layer3 Revision %s\n", HiSax_getrev(tmp));
strcpy(tmp, lli_revision);
- r += sprintf(r, "%s/", HiSax_getrev(tmp));
- strcpy(tmp, tei_revision);
- r += sprintf(r, "%s", HiSax_getrev(tmp));
-
- printk(KERN_INFO "HiSax: Driver for Siemens chip set ISDN cards\n");
- printk(KERN_INFO "HiSax: Version 2.8\n");
- printk(KERN_INFO "HiSax: Revisions %s\n", rev);
+ printk(KERN_INFO "HiSax: LinkLayer Revision %s\n", HiSax_getrev(tmp));
+ certification_check(1);
}
void
@@ -375,7 +450,7 @@ HiSax_setup(char *str, int *ints))
argc = ints[0];
i = 0;
j = 1;
- while (argc && (i < 16)) {
+ while (argc && (i < HISAX_MAX_CARDS)) {
if (argc) {
cards[i].typ = ints[j];
j++;
@@ -413,11 +488,759 @@ HiSax_setup(char *str, int *ints))
}
#endif
+#if CARD_TELES0
+extern int setup_teles0(struct IsdnCard *card);
+#endif
+
+#if CARD_TELES3
+extern int setup_teles3(struct IsdnCard *card);
+#endif
+
+#if CARD_S0BOX
+extern int setup_s0box(struct IsdnCard *card);
+#endif
+
+#if CARD_TELESPCI
+extern int setup_telespci(struct IsdnCard *card);
+#endif
+
+#if CARD_AVM_A1
+extern int setup_avm_a1(struct IsdnCard *card);
+#endif
+
+#if CARD_AVM_A1_PCMCIA
+extern int setup_avm_a1_pcmcia(struct IsdnCard *card);
+#endif
+
+#if CARD_FRITZPCI
+extern int setup_avm_pcipnp(struct IsdnCard *card);
+#endif
+
+#if CARD_ELSA
+extern int setup_elsa(struct IsdnCard *card);
+#endif
+
+#if CARD_IX1MICROR2
+extern int setup_ix1micro(struct IsdnCard *card);
+#endif
+
+#if CARD_DIEHLDIVA
+extern int setup_diva(struct IsdnCard *card);
+#endif
+
+#if CARD_ASUSCOM
+extern int setup_asuscom(struct IsdnCard *card);
+#endif
+
+#if CARD_TELEINT
+extern int setup_TeleInt(struct IsdnCard *card);
+#endif
+
+#if CARD_SEDLBAUER
+extern int setup_sedlbauer(struct IsdnCard *card);
+#endif
+
+#if CARD_SPORTSTER
+extern int setup_sportster(struct IsdnCard *card);
+#endif
+
+#if CARD_MIC
+extern int setup_mic(struct IsdnCard *card);
+#endif
+
+#if CARD_NETJET
+extern int setup_netjet(struct IsdnCard *card);
+#endif
+
+#if CARD_TELES3C
+extern int setup_t163c(struct IsdnCard *card);
+#endif
+
+#if CARD_AMD7930
+extern int setup_amd7930(struct IsdnCard *card);
+#endif
+
+#if CARD_NICCY
+extern int setup_niccy(struct IsdnCard *card);
+#endif
+
+/*
+ * Find card with given driverId
+ */
+static inline struct IsdnCardState
+*hisax_findcard(int driverid)
+{
+ int i;
+
+ for (i = 0; i < nrcards; i++)
+ if (cards[i].cs)
+ if (cards[i].cs->myid == driverid)
+ return (cards[i].cs);
+ return (NULL);
+}
+
+int
+HiSax_readstatus(u_char * buf, int len, int user, int id, int channel)
+{
+ int count,cnt;
+ u_char *p = buf;
+ struct IsdnCardState *cs = hisax_findcard(id);
+
+ if (cs) {
+ if (len > HISAX_STATUS_BUFSIZE) {
+ printk(KERN_WARNING "HiSax: status overflow readstat %d/%d\n",
+ len, HISAX_STATUS_BUFSIZE);
+ }
+ count = cs->status_end - cs->status_read +1;
+ if (count >= len)
+ count = len;
+ if (user)
+ copy_to_user(p, cs->status_read, count);
+ else
+ memcpy(p, cs->status_read, count);
+ cs->status_read += count;
+ if (cs->status_read > cs->status_end)
+ cs->status_read = cs->status_buf;
+ p += count;
+ count = len - count;
+ while (count) {
+ if (count > HISAX_STATUS_BUFSIZE)
+ cnt = HISAX_STATUS_BUFSIZE;
+ else
+ cnt = count;
+ if (user)
+ copy_to_user(p, cs->status_read, cnt);
+ else
+ memcpy(p, cs->status_read, cnt);
+ p += cnt;
+ cs->status_read += cnt % HISAX_STATUS_BUFSIZE;
+ count -= cnt;
+ }
+ return len;
+ } else {
+ printk(KERN_ERR
+ "HiSax: if_readstatus called with invalid driverId!\n");
+ return -ENODEV;
+ }
+}
+
+inline int
+jiftime(char *s, long mark)
+{
+ s += 8;
+
+ *s-- = '\0';
+ *s-- = mark % 10 + '0';
+ mark /= 10;
+ *s-- = mark % 10 + '0';
+ mark /= 10;
+ *s-- = '.';
+ *s-- = mark % 10 + '0';
+ mark /= 10;
+ *s-- = mark % 6 + '0';
+ mark /= 6;
+ *s-- = ':';
+ *s-- = mark % 10 + '0';
+ mark /= 10;
+ *s-- = mark % 10 + '0';
+ return(8);
+}
+
+static u_char tmpbuf[HISAX_STATUS_BUFSIZE];
+
+void
+VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args)
+{
+/* if head == NULL the fmt contains the full info */
+
+ long flags;
+ int count, i;
+ u_char *p;
+ isdn_ctrl ic;
+ int len;
+
+ save_flags(flags);
+ cli();
+ p = tmpbuf;
+ if (head) {
+ p += jiftime(p, jiffies);
+ p += sprintf(p, " %s", head);
+ p += vsprintf(p, fmt, args);
+ *p++ = '\n';
+ *p = 0;
+ len = p - tmpbuf;
+ p = tmpbuf;
+ } else {
+ p = fmt;
+ len = strlen(fmt);
+ }
+ if (!cs) {
+ printk(KERN_WARNING "HiSax: No CardStatus for message %s", p);
+ restore_flags(flags);
+ return;
+ }
+ if (len > HISAX_STATUS_BUFSIZE) {
+ printk(KERN_WARNING "HiSax: status overflow %d/%d\n",
+ len, HISAX_STATUS_BUFSIZE);
+ restore_flags(flags);
+ return;
+ }
+ count = len;
+ i = cs->status_end - cs->status_write +1;
+ if (i >= len)
+ i = len;
+ len -= i;
+ memcpy(cs->status_write, p, i);
+ cs->status_write += i;
+ if (cs->status_write > cs->status_end)
+ cs->status_write = cs->status_buf;
+ p += i;
+ if (len) {
+ memcpy(cs->status_write, p, len);
+ cs->status_write += len;
+ }
+#ifdef KERNELSTACK_DEBUG
+ i = (ulong)&len - current->kernel_stack_page;
+ sprintf(tmpbuf, "kstack %s %lx use %ld\n", current->comm,
+ current->kernel_stack_page, i);
+ len = strlen(tmpbuf);
+ for (p = tmpbuf, i = len; i > 0; i--, p++) {
+ *cs->status_write++ = *p;
+ if (cs->status_write > cs->status_end)
+ cs->status_write = cs->status_buf;
+ count++;
+ }
+#endif
+ restore_flags(flags);
+ if (count) {
+ ic.command = ISDN_STAT_STAVAIL;
+ ic.driver = cs->myid;
+ ic.arg = count;
+ cs->iif.statcallb(&ic);
+ }
+}
+
+void
+HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ VHiSax_putstatus(cs, head, fmt, args);
+ va_end(args);
+}
+
+int
+ll_run(struct IsdnCardState *cs)
+{
+ long flags;
+ isdn_ctrl ic;
+
+ save_flags(flags);
+ cli();
+ ic.driver = cs->myid;
+ ic.command = ISDN_STAT_RUN;
+ cs->iif.statcallb(&ic);
+ restore_flags(flags);
+ return 0;
+}
+
+void
+ll_stop(struct IsdnCardState *cs)
+{
+ isdn_ctrl ic;
+
+ ic.command = ISDN_STAT_STOP;
+ ic.driver = cs->myid;
+ cs->iif.statcallb(&ic);
+ CallcFreeChan(cs);
+}
+
+static void
+ll_unload(struct IsdnCardState *cs)
+{
+ isdn_ctrl ic;
+
+ ic.command = ISDN_STAT_UNLOAD;
+ ic.driver = cs->myid;
+ cs->iif.statcallb(&ic);
+ if (cs->status_buf)
+ kfree(cs->status_buf);
+ cs->status_read = NULL;
+ cs->status_write = NULL;
+ cs->status_end = NULL;
+ kfree(cs->dlog);
+}
+
+static void
+closecard(int cardnr)
+{
+ struct IsdnCardState *csta = cards[cardnr].cs;
+
+ if (csta->bcs->BC_Close != NULL) {
+ csta->bcs->BC_Close(csta->bcs + 1);
+ csta->bcs->BC_Close(csta->bcs);
+ }
+
+ if (csta->rcvbuf) {
+ kfree(csta->rcvbuf);
+ csta->rcvbuf = NULL;
+ }
+ discard_queue(&csta->rq);
+ discard_queue(&csta->sq);
+ if (csta->tx_skb) {
+ dev_kfree_skb(csta->tx_skb);
+ csta->tx_skb = NULL;
+ }
+ if (csta->mon_rx) {
+ kfree(csta->mon_rx);
+ csta->mon_rx = NULL;
+ }
+ if (csta->mon_tx) {
+ kfree(csta->mon_tx);
+ csta->mon_tx = NULL;
+ }
+ csta->cardmsg(csta, CARD_RELEASE, NULL);
+ if (csta->dbusytimer.function != NULL)
+ del_timer(&csta->dbusytimer);
+ ll_unload(csta);
+}
+
+HISAX_INITFUNC(static int init_card(struct IsdnCardState *cs))
+{
+ int irq_cnt, cnt = 3;
+ long flags;
+
+ save_flags(flags);
+ cli();
+ irq_cnt = kstat_irqs(cs->irq);
+ printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ], cs->irq,
+ irq_cnt);
+ if (cs->cardmsg(cs, CARD_SETIRQ, NULL)) {
+ printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n",
+ cs->irq);
+ restore_flags(flags);
+ return(1);
+ }
+ while (cnt) {
+ cs->cardmsg(cs, CARD_INIT, NULL);
+ sti();
+ current->state = TASK_INTERRUPTIBLE;
+ /* Timeout 10ms */
+ schedule_timeout((10 * HZ) / 1000);
+ restore_flags(flags);
+ printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ],
+ cs->irq, kstat_irqs(cs->irq));
+ if (kstat_irqs(cs->irq) == irq_cnt) {
+ printk(KERN_WARNING
+ "%s: IRQ(%d) getting no interrupts during init %d\n",
+ CardType[cs->typ], cs->irq, 4 - cnt);
+ if (cnt == 1) {
+ free_irq(cs->irq, cs);
+ return (2);
+ } else {
+ cs->cardmsg(cs, CARD_RESET, NULL);
+ cnt--;
+ }
+ } else {
+ cs->cardmsg(cs, CARD_TEST, NULL);
+ return(0);
+ }
+ }
+ restore_flags(flags);
+ return(3);
+}
+
+HISAX_INITFUNC(static int
+checkcard(int cardnr, char *id, int *busy_flag))
+{
+ long flags;
+ int ret = 0;
+ struct IsdnCard *card = cards + cardnr;
+ struct IsdnCardState *cs;
+
+ save_flags(flags);
+ cli();
+ if (!(cs = (struct IsdnCardState *)
+ kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC))) {
+ printk(KERN_WARNING
+ "HiSax: No memory for IsdnCardState(card %d)\n",
+ cardnr + 1);
+ restore_flags(flags);
+ return (0);
+ }
+ memset(cs, 0, sizeof(struct IsdnCardState));
+ card->cs = cs;
+ cs->cardnr = cardnr;
+ cs->debug = L1_DEB_WARN;
+ cs->HW_Flags = 0;
+ cs->busy_flag = busy_flag;
+#if TEI_PER_CARD
+#else
+ test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
+#endif
+ cs->protocol = card->protocol;
+
+ if ((card->typ > 0) && (card->typ < 31)) {
+ if (!((1 << card->typ) & SUPORTED_CARDS)) {
+ printk(KERN_WARNING
+ "HiSax: Support for %s Card not selected\n",
+ CardType[card->typ]);
+ restore_flags(flags);
+ return (0);
+ }
+ } else {
+ printk(KERN_WARNING
+ "HiSax: Card Type %d out of range\n",
+ card->typ);
+ restore_flags(flags);
+ return (0);
+ }
+ if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
+ printk(KERN_WARNING
+ "HiSax: No memory for dlog(card %d)\n",
+ cardnr + 1);
+ restore_flags(flags);
+ return (0);
+ }
+ if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) {
+ printk(KERN_WARNING
+ "HiSax: No memory for status_buf(card %d)\n",
+ cardnr + 1);
+ kfree(cs->dlog);
+ restore_flags(flags);
+ return (0);
+ }
+ cs->stlist = NULL;
+ cs->mon_tx = NULL;
+ cs->mon_rx = NULL;
+ cs->status_read = cs->status_buf;
+ cs->status_write = cs->status_buf;
+ cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
+ cs->typ = card->typ;
+ strcpy(cs->iif.id, id);
+ cs->iif.channels = 2;
+ cs->iif.maxbufsize = MAX_DATA_SIZE;
+ cs->iif.hl_hdrlen = MAX_HEADER_LEN;
+ cs->iif.features =
+ ISDN_FEATURE_L2_X75I |
+ ISDN_FEATURE_L2_HDLC |
+ ISDN_FEATURE_L2_MODEM |
+ ISDN_FEATURE_L2_TRANS |
+ ISDN_FEATURE_L3_TRANS |
+#ifdef CONFIG_HISAX_1TR6
+ ISDN_FEATURE_P_1TR6 |
+#endif
+#ifdef CONFIG_HISAX_EURO
+ ISDN_FEATURE_P_EURO |
+#endif
+#ifdef CONFIG_HISAX_NI1
+ ISDN_FEATURE_P_NI1 |
+#endif
+ 0;
+
+ cs->iif.command = HiSax_command;
+ cs->iif.writecmd = NULL;
+ cs->iif.writebuf_skb = HiSax_writebuf_skb;
+ cs->iif.readstat = HiSax_readstatus;
+ register_isdn(&cs->iif);
+ cs->myid = cs->iif.channels;
+ printk(KERN_INFO
+ "HiSax: Card %d Protocol %s Id=%s (%d)\n", cardnr + 1,
+ (card->protocol == ISDN_PTYPE_1TR6) ? "1TR6" :
+ (card->protocol == ISDN_PTYPE_EURO) ? "EDSS1" :
+ (card->protocol == ISDN_PTYPE_LEASED) ? "LEASED" :
+ (card->protocol == ISDN_PTYPE_NI1) ? "NI1" :
+ "NONE", cs->iif.id, cs->myid);
+ switch (card->typ) {
+#if CARD_TELES0
+ case ISDN_CTYPE_16_0:
+ case ISDN_CTYPE_8_0:
+ ret = setup_teles0(card);
+ break;
+#endif
+#if CARD_TELES3
+ case ISDN_CTYPE_16_3:
+ case ISDN_CTYPE_PNP:
+ case ISDN_CTYPE_TELESPCMCIA:
+ case ISDN_CTYPE_COMPAQ_ISA:
+ ret = setup_teles3(card);
+ break;
+#endif
+#if CARD_S0BOX
+ case ISDN_CTYPE_S0BOX:
+ ret = setup_s0box(card);
+ break;
+#endif
+#if CARD_TELESPCI
+ case ISDN_CTYPE_TELESPCI:
+ ret = setup_telespci(card);
+ break;
+#endif
+#if CARD_AVM_A1
+ case ISDN_CTYPE_A1:
+ ret = setup_avm_a1(card);
+ break;
+#endif
+#if CARD_AVM_A1_PCMCIA
+ case ISDN_CTYPE_A1_PCMCIA:
+ ret = setup_avm_a1_pcmcia(card);
+ break;
+#endif
+#if CARD_FRITZPCI
+ case ISDN_CTYPE_FRITZPCI:
+ ret = setup_avm_pcipnp(card);
+ break;
+#endif
+#if CARD_ELSA
+ case ISDN_CTYPE_ELSA:
+ case ISDN_CTYPE_ELSA_PNP:
+ case ISDN_CTYPE_ELSA_PCMCIA:
+ case ISDN_CTYPE_ELSA_PCI:
+ ret = setup_elsa(card);
+ break;
+#endif
+#if CARD_IX1MICROR2
+ case ISDN_CTYPE_IX1MICROR2:
+ ret = setup_ix1micro(card);
+ break;
+#endif
+#if CARD_DIEHLDIVA
+ case ISDN_CTYPE_DIEHLDIVA:
+ ret = setup_diva(card);
+ break;
+#endif
+#if CARD_ASUSCOM
+ case ISDN_CTYPE_ASUSCOM:
+ ret = setup_asuscom(card);
+ break;
+#endif
+#if CARD_TELEINT
+ case ISDN_CTYPE_TELEINT:
+ ret = setup_TeleInt(card);
+ break;
+#endif
+#if CARD_SEDLBAUER
+ case ISDN_CTYPE_SEDLBAUER:
+ case ISDN_CTYPE_SEDLBAUER_PCMCIA:
+ case ISDN_CTYPE_SEDLBAUER_FAX:
+ ret = setup_sedlbauer(card);
+ break;
+#endif
+#if CARD_SPORTSTER
+ case ISDN_CTYPE_SPORTSTER:
+ ret = setup_sportster(card);
+ break;
+#endif
+#if CARD_MIC
+ case ISDN_CTYPE_MIC:
+ ret = setup_mic(card);
+ break;
+#endif
+#if CARD_NETJET
+ case ISDN_CTYPE_NETJET:
+ ret = setup_netjet(card);
+ break;
+#endif
+#if CARD_TELES3C
+ case ISDN_CTYPE_TELES3C:
+ ret = setup_t163c(card);
+ break;
+#endif
+#if CARD_NICCY
+ case ISDN_CTYPE_NICCY:
+ ret = setup_niccy(card);
+ break;
+#endif
+#if CARD_AMD7930
+ case ISDN_CTYPE_AMD7930:
+ ret = setup_amd7930(card);
+ break;
+#endif
+ default:
+ printk(KERN_WARNING "HiSax: Unknown Card Typ %d\n",
+ card->typ);
+ ll_unload(cs);
+ restore_flags(flags);
+ return (0);
+ }
+ if (!ret) {
+ ll_unload(cs);
+ restore_flags(flags);
+ return (0);
+ }
+ if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
+ printk(KERN_WARNING
+ "HiSax: No memory for isac rcvbuf\n");
+ return (1);
+ }
+ cs->rcvidx = 0;
+ cs->tx_skb = NULL;
+ cs->tx_cnt = 0;
+ cs->event = 0;
+ cs->tqueue.next = 0;
+ cs->tqueue.sync = 0;
+ cs->tqueue.data = cs;
+
+ skb_queue_head_init(&cs->rq);
+ skb_queue_head_init(&cs->sq);
+
+ init_bcstate(cs, 0);
+ init_bcstate(cs, 1);
+ ret = init_card(cs);
+ if (ret) {
+ closecard(cardnr);
+ restore_flags(flags);
+ return (0);
+ }
+ init_tei(cs, cs->protocol);
+ CallcNewChan(cs);
+ /* ISAR needs firmware download first */
+ if (!test_bit(HW_ISAR, &cs->HW_Flags))
+ ll_run(cs);
+ restore_flags(flags);
+ return (1);
+}
+
+HISAX_INITFUNC(void
+HiSax_shiftcards(int idx))
+{
+ int i;
+
+ for (i = idx; i < (HISAX_MAX_CARDS - 1); i++)
+ memcpy(&cards[i], &cards[i + 1], sizeof(cards[i]));
+}
+
+HISAX_INITFUNC(int
+HiSax_inithardware(int *busy_flag))
+{
+ int foundcards = 0;
+ int i = 0;
+ int t = ',';
+ int flg = 0;
+ char *id;
+ char *next_id = HiSax_id;
+ char ids[20];
+
+ if (strchr(HiSax_id, ','))
+ t = ',';
+ else if (strchr(HiSax_id, '%'))
+ t = '%';
+
+ while (i < nrcards) {
+ if (cards[i].typ < 1)
+ break;
+ id = next_id;
+ if ((next_id = strchr(id, t))) {
+ *next_id++ = 0;
+ strcpy(ids, id);
+ flg = i + 1;
+ } else {
+ next_id = id;
+ if (flg >= i)
+ strcpy(ids, id);
+ else
+ sprintf(ids, "%s%d", id, i);
+ }
+ if (checkcard(i, ids, busy_flag)) {
+ foundcards++;
+ i++;
+ } else {
+ printk(KERN_WARNING "HiSax: Card %s not installed !\n",
+ CardType[cards[i].typ]);
+ if (cards[i].cs)
+ kfree((void *) cards[i].cs);
+ cards[i].cs = NULL;
+ HiSax_shiftcards(i);
+ }
+ }
+ return foundcards;
+}
+
+void
+HiSax_closecard(int cardnr)
+{
+ int i,last=nrcards - 1;
+
+ if (cardnr>last)
+ return;
+ if (cards[cardnr].cs) {
+ ll_stop(cards[cardnr].cs);
+ release_tei(cards[cardnr].cs);
+ closecard(cardnr);
+ free_irq(cards[cardnr].cs->irq, cards[cardnr].cs);
+ kfree((void *) cards[cardnr].cs);
+ cards[cardnr].cs = NULL;
+ }
+ i = cardnr;
+ while (i!=last) {
+ cards[i] = cards[i+1];
+ i++;
+ }
+ nrcards--;
+}
+
+EXPORT_SYMBOL(HiSax_closecard);
+
+void
+HiSax_reportcard(int cardnr)
+{
+ struct IsdnCardState *cs = cards[cardnr].cs;
+ struct PStack *stptr;
+ struct l3_process *pc;
+ int j, i = 1;
+
+ printk(KERN_DEBUG "HiSax: reportcard No %d\n", cardnr + 1);
+ printk(KERN_DEBUG "HiSax: Type %s\n", CardType[cs->typ]);
+ printk(KERN_DEBUG "HiSax: debuglevel %x\n", cs->debug);
+ printk(KERN_DEBUG "HiSax: HiSax_reportcard address 0x%lX\n",
+ (ulong) & HiSax_reportcard);
+ printk(KERN_DEBUG "HiSax: cs 0x%lX\n", (ulong) cs);
+ printk(KERN_DEBUG "HiSax: HW_Flags %x bc0 flg %x bc0 flg %x\n",
+ cs->HW_Flags, cs->bcs[0].Flag, cs->bcs[1].Flag);
+ printk(KERN_DEBUG "HiSax: bcs 0 mode %d ch%d\n",
+ cs->bcs[0].mode, cs->bcs[0].channel);
+ printk(KERN_DEBUG "HiSax: bcs 1 mode %d ch%d\n",
+ cs->bcs[1].mode, cs->bcs[1].channel);
+ printk(KERN_DEBUG "HiSax: cs stl 0x%lX\n", (ulong) & (cs->stlist));
+ stptr = cs->stlist;
+ while (stptr != NULL) {
+ printk(KERN_DEBUG "HiSax: dst%d 0x%lX\n", i, (ulong) stptr);
+ printk(KERN_DEBUG "HiSax: dst%d stp 0x%lX\n", i, (ulong) stptr->l1.stlistp);
+ printk(KERN_DEBUG "HiSax: tei %d sapi %d\n",
+ stptr->l2.tei, stptr->l2.sap);
+ printk(KERN_DEBUG "HiSax: man 0x%lX\n", (ulong) stptr->ma.layer);
+ pc = stptr->l3.proc;
+ while (pc) {
+ printk(KERN_DEBUG "HiSax: l3proc %x 0x%lX\n", pc->callref,
+ (ulong) pc);
+ printk(KERN_DEBUG "HiSax: state %d st 0x%lX chan 0x%lX\n",
+ pc->state, (ulong) pc->st, (ulong) pc->chan);
+ pc = pc->next;
+ }
+ stptr = stptr->next;
+ i++;
+ }
+ for (j = 0; j < 2; j++) {
+ printk(KERN_DEBUG "HiSax: ch%d 0x%lX\n", j,
+ (ulong) & cs->channel[j]);
+ stptr = cs->channel[j].b_st;
+ i = 1;
+ while (stptr != NULL) {
+ printk(KERN_DEBUG "HiSax: b_st%d 0x%lX\n", i, (ulong) stptr);
+ printk(KERN_DEBUG "HiSax: man 0x%lX\n", (ulong) stptr->ma.layer);
+ stptr = stptr->next;
+ i++;
+ }
+ }
+}
+
+
__initfunc(int
HiSax_init(void))
{
int i;
-
+
#ifdef MODULE
int nzproto = 0;
#ifdef CONFIG_HISAX_ELSA
@@ -432,13 +1255,19 @@ HiSax_init(void))
return 0;
}
#endif
+#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
+ if (type[0] == ISDN_CTYPE_A1_PCMCIA) {
+ /* we have to export and return in this case */
+ return 0;
+ }
+#endif
#endif
- HiSaxVersion();
nrcards = 0;
+ HiSaxVersion();
#ifdef MODULE
if (id) /* If id= string used */
HiSax_id = id;
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < HISAX_MAX_CARDS; i++) {
cards[i].typ = type[i];
if (protocol[i]) {
cards[i].protocol = protocol[i];
@@ -476,6 +1305,7 @@ HiSax_init(void))
case ISDN_CTYPE_16_3:
case ISDN_CTYPE_TELESPCMCIA:
case ISDN_CTYPE_A1:
+ case ISDN_CTYPE_A1_PCMCIA:
case ISDN_CTYPE_ELSA_PNP:
case ISDN_CTYPE_ELSA_PCMCIA:
case ISDN_CTYPE_IX1MICROR2:
@@ -484,16 +1314,19 @@ HiSax_init(void))
case ISDN_CTYPE_TELEINT:
case ISDN_CTYPE_SEDLBAUER:
case ISDN_CTYPE_SEDLBAUER_PCMCIA:
+ case ISDN_CTYPE_SEDLBAUER_FAX:
case ISDN_CTYPE_SPORTSTER:
case ISDN_CTYPE_MIC:
case ISDN_CTYPE_TELES3C:
+ case ISDN_CTYPE_S0BOX:
+ case ISDN_CTYPE_FRITZPCI:
cards[i].para[0] = irq[i];
cards[i].para[1] = io[i];
break;
case ISDN_CTYPE_ELSA_PCI:
case ISDN_CTYPE_NETJET:
case ISDN_CTYPE_AMD7930:
- case ISDN_CTYPE_DBRI:
+ case ISDN_CTYPE_TELESPCI:
break;
}
}
@@ -507,13 +1340,14 @@ HiSax_init(void))
HiSax_id = HiSaxID;
if (!HiSaxID[0])
strcpy(HiSaxID, "HiSax");
- for (i = 0; i < 16; i++)
+ for (i = 0; i < HISAX_MAX_CARDS; i++)
if (cards[i].typ > 0)
nrcards++;
printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
nrcards, (nrcards > 1) ? "s" : "");
CallcNew();
+ Isdnl3New();
Isdnl2New();
TeiNew();
Isdnl1New();
@@ -522,7 +1356,6 @@ HiSax_init(void))
/* No symbols to export, hide all symbols */
#ifdef MODULE
- EXPORT_NO_SYMBOLS;
printk(KERN_INFO "HiSax: module installed\n");
#endif
return (0);
@@ -530,6 +1363,7 @@ HiSax_init(void))
Isdnl1Free();
TeiFree();
Isdnl2Free();
+ Isdnl3Free();
CallcFree();
return -EIO;
}
@@ -539,13 +1373,27 @@ HiSax_init(void))
void
cleanup_module(void)
{
- HiSax_closehardware();
+ int cardnr = nrcards -1;
+ long flags;
+
+ save_flags(flags);
+ cli();
+ while(cardnr>=0)
+ HiSax_closecard(cardnr--);
+ Isdnl1Free();
+ TeiFree();
+ Isdnl2Free();
+ Isdnl3Free();
+ CallcFree();
+ restore_flags(flags);
printk(KERN_INFO "HiSax module removed\n");
}
+#endif
#ifdef CONFIG_HISAX_ELSA
int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
{
+#ifdef MODULE
int i;
int nzproto = 0;
@@ -553,10 +1401,10 @@ int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
HiSaxVersion();
if (id) /* If id= string used */
HiSax_id = id;
- /* Initialize all 16 structs, even though we only accept
+ /* Initialize all 8 structs, even though we only accept
two pcmcia cards
*/
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < HISAX_MAX_CARDS; i++) {
cards[i].para[0] = irq[i];
cards[i].para[1] = io[i];
cards[i].typ = type[i];
@@ -575,7 +1423,7 @@ int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
HiSax_id = HiSaxID;
if (!HiSaxID[0])
strcpy(HiSaxID, "HiSax");
- for (i = 0; i < 16; i++)
+ for (i = 0; i < HISAX_MAX_CARDS; i++)
if (cards[i].typ > 0)
nrcards++;
printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
@@ -583,16 +1431,71 @@ int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
Isdnl1New();
CallcNew();
+ Isdnl3New();
Isdnl2New();
TeiNew();
HiSax_inithardware(busy_flag);
printk(KERN_NOTICE "HiSax: module installed\n");
+#endif
return (0);
}
#endif
+
#ifdef CONFIG_HISAX_SEDLBAUER
int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
{
+#ifdef MODULE
+ int i;
+ int nzproto = 0;
+
+ nrcards = 0;
+ HiSaxVersion();
+ if (id) /* If id= string used */
+ HiSax_id = id;
+ /* Initialize all 8 structs, even though we only accept
+ two pcmcia cards
+ */
+ for (i = 0; i < HISAX_MAX_CARDS; i++) {
+ cards[i].para[0] = irq[i];
+ cards[i].para[1] = io[i];
+ cards[i].typ = type[i];
+ if (protocol[i]) {
+ cards[i].protocol = protocol[i];
+ nzproto++;
+ }
+ }
+ cards[0].para[0] = pcm_irq;
+ cards[0].para[1] = (int)pcm_iob;
+ cards[0].protocol = prot;
+ cards[0].typ = ISDN_CTYPE_SEDLBAUER_PCMCIA;
+ nzproto = 1;
+
+ if (!HiSax_id)
+ HiSax_id = HiSaxID;
+ if (!HiSaxID[0])
+ strcpy(HiSaxID, "HiSax");
+ for (i = 0; i < HISAX_MAX_CARDS; i++)
+ if (cards[i].typ > 0)
+ nrcards++;
+ printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
+ nrcards, (nrcards > 1) ? "s" : "");
+
+ CallcNew();
+ Isdnl3New();
+ Isdnl2New();
+ Isdnl1New();
+ TeiNew();
+ HiSax_inithardware(busy_flag);
+ printk(KERN_NOTICE "HiSax: module installed\n");
+#endif
+ return (0);
+}
+#endif
+
+#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
+int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
+{
+#ifdef MODULE
int i;
int nzproto = 0;
@@ -615,14 +1518,14 @@ int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
cards[0].para[0] = pcm_irq;
cards[0].para[1] = (int)pcm_iob;
cards[0].protocol = prot;
- cards[0].typ = ISDN_CTYPE_SEDLBAUER_PCMCIA;
+ cards[0].typ = ISDN_CTYPE_A1_PCMCIA;
nzproto = 1;
if (!HiSax_id)
HiSax_id = HiSaxID;
if (!HiSaxID[0])
strcpy(HiSaxID, "HiSax");
- for (i = 0; i < 16; i++)
+ for (i = 0; i < HISAX_MAX_CARDS; i++)
if (cards[i].typ > 0)
nrcards++;
printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
@@ -630,11 +1533,12 @@ int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
Isdnl1New();
CallcNew();
+ Isdnl3New();
Isdnl2New();
TeiNew();
HiSax_inithardware(busy_flag);
printk(KERN_NOTICE "HiSax: module installed\n");
+#endif
return (0);
}
#endif
-#endif
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
index a533272c8..4baf740b1 100644
--- a/drivers/isdn/hisax/diva.c
+++ b/drivers/isdn/hisax/diva.c
@@ -1,13 +1,30 @@
-/* $Id: diva.c,v 1.5 1998/02/02 13:29:38 keil Exp $
+/* $Id: diva.c,v 1.10 1998/11/15 23:54:31 keil Exp $
* diva.c low level stuff for Eicon.Diehl Diva Family ISDN cards
*
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
*
* Thanks to Eicon Technology Diehl GmbH & Co. oHG for documents and informations
*
*
* $Log: diva.c,v $
+ * Revision 1.10 1998/11/15 23:54:31 keil
+ * changes from 2.0
+ *
+ * Revision 1.9 1998/06/27 22:52:03 keil
+ * support for Diva 2.01
+ *
+ * Revision 1.8 1998/05/25 12:57:46 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.7 1998/04/15 16:42:36 keil
+ * new init code
+ * new PCI init (2.1.94)
+ *
+ * Revision 1.6 1998/03/07 22:56:57 tsbogend
+ * made HiSax working on Linux/Alpha
+ *
* Revision 1.5 1998/02/02 13:29:38 keil
* fast io
*
@@ -31,13 +48,13 @@
#include "hisax.h"
#include "isac.h"
#include "hscx.h"
+#include "ipac.h"
#include "isdnl1.h"
#include <linux/pci.h>
-#include <linux/bios32.h>
extern const char *CardType[];
-const char *Diva_revision = "$Revision: 1.5 $";
+const char *Diva_revision = "$Revision: 1.10 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -47,6 +64,8 @@ const char *Diva_revision = "$Revision: 1.5 $";
#define DIVA_ISA_ISAC_DATA 2
#define DIVA_ISA_ISAC_ADR 6
#define DIVA_ISA_CTRL 7
+#define DIVA_IPAC_ADR 0
+#define DIVA_IPAC_DATA 1
#define DIVA_PCI_ISAC_DATA 8
#define DIVA_PCI_ISAC_ADR 0xc
@@ -55,6 +74,7 @@ const char *Diva_revision = "$Revision: 1.5 $";
/* SUB Types */
#define DIVA_ISA 1
#define DIVA_PCI 2
+#define DIVA_IPAC_ISA 3
/* PCI stuff */
#define PCI_VENDOR_EICON_DIEHL 0x1133
@@ -140,13 +160,37 @@ ReadISACfifo(struct IsdnCardState *cs, u_char *data, int size)
readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0, data, size);
}
-static void
+static void
WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size)
{
writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0, data, size);
}
static u_char
+ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
+{
+ return (readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset+0x80));
+}
+
+static void
+WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+ writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset|0x80, value);
+}
+
+static void
+ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+ readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size);
+}
+
+static void
+WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+ writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size);
+}
+
+static u_char
ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
{
return(readreg(cs->hw.diva.hscx_adr,
@@ -168,13 +212,13 @@ WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
cs->hw.diva.hscx, reg + (nr ? 0x40 : 0))
#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.diva.hscx_adr, \
cs->hw.diva.hscx, reg + (nr ? 0x40 : 0), data)
-
+
#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.diva.hscx_adr, \
cs->hw.diva.hscx, (nr ? 0x40 : 0), ptr, cnt)
-
+
#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.diva.hscx_adr, \
cs->hw.diva.hscx, (nr ? 0x40 : 0), ptr, cnt)
-
+
#include "hscx_irq.c"
static void
@@ -215,18 +259,69 @@ diva_interrupt(int intno, void *dev_id, struct pt_regs *regs)
}
}
+static void
+diva_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+{
+ struct IsdnCardState *cs = dev_id;
+ u_char ista,val;
+ int icnt=20;
+
+ if (!cs) {
+ printk(KERN_WARNING "Diva: Spurious interrupt!\n");
+ return;
+ }
+ ista = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA);
+Start_IPAC:
+ if (cs->debug & L1_DEB_IPAC)
+ debugl1(cs, "IPAC ISTA %02X", ista);
+ if (ista & 0x0f) {
+ val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, HSCX_ISTA + 0x40);
+ if (ista & 0x01)
+ val |= 0x01;
+ if (ista & 0x04)
+ val |= 0x02;
+ if (ista & 0x08)
+ val |= 0x04;
+ if (val)
+ hscx_int_main(cs, val);
+ }
+ if (ista & 0x20) {
+ val = 0xfe & readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA + 0x80);
+ if (val) {
+ isac_interrupt(cs, val);
+ }
+ }
+ if (ista & 0x10) {
+ val = 0x01;
+ isac_interrupt(cs, val);
+ }
+ ista = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA);
+ if ((ista & 0x3f) && icnt) {
+ icnt--;
+ goto Start_IPAC;
+ }
+ if (!icnt)
+ printk(KERN_WARNING "DIVA IPAC IRQ LOOP\n");
+ writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xFF);
+ writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xC0);
+}
+
+
void
release_io_diva(struct IsdnCardState *cs)
{
int bytecnt;
-
- del_timer(&cs->hw.diva.tl);
- if (cs->subtyp == DIVA_ISA)
+
+ if (cs->subtyp != DIVA_IPAC_ISA) {
+ del_timer(&cs->hw.diva.tl);
+ if (cs->hw.diva.cfg_reg)
+ byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */
+ }
+ if ((cs->subtyp == DIVA_ISA) || (cs->subtyp == DIVA_IPAC_ISA))
bytecnt = 8;
else
bytecnt = 32;
if (cs->hw.diva.cfg_reg) {
- byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */
release_region(cs->hw.diva.cfg_reg, bytecnt);
}
}
@@ -238,19 +333,30 @@ reset_diva(struct IsdnCardState *cs)
save_flags(flags);
sti();
- cs->hw.diva.ctrl_reg = 0; /* Reset On */
- byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
- cs->hw.diva.ctrl_reg |= DIVA_RESET; /* Reset Off */
- byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
- if (cs->subtyp == DIVA_ISA)
- cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A;
- else
- cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A;
- byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
+ if (cs->subtyp == DIVA_IPAC_ISA) {
+ writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
+ writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
+ writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0);
+ } else {
+ cs->hw.diva.ctrl_reg = 0; /* Reset On */
+ byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
+ cs->hw.diva.ctrl_reg |= DIVA_RESET; /* Reset Off */
+ byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
+ if (cs->subtyp == DIVA_ISA)
+ cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A;
+ else
+ cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A;
+ byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
+ }
+ restore_flags(flags);
}
#define DIVA_ASSIGN 1
@@ -260,6 +366,8 @@ diva_led_handler(struct IsdnCardState *cs)
{
int blink = 0;
+ if (cs->subtyp == DIVA_IPAC_ISA)
+ return;
del_timer(&cs->hw.diva.tl);
if (cs->hw.diva.status & DIVA_ASSIGN)
cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ?
@@ -272,14 +380,14 @@ diva_led_handler(struct IsdnCardState *cs)
if (cs->hw.diva.status & 0xf000)
cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ?
DIVA_ISA_LED_B : DIVA_PCI_LED_B;
- else if (cs->hw.diva.status & 0x0f00) {
+ else if (cs->hw.diva.status & 0x0f00) {
cs->hw.diva.ctrl_reg ^= (DIVA_ISA == cs->subtyp) ?
DIVA_ISA_LED_B : DIVA_PCI_LED_B;
blink = 500;
} else
cs->hw.diva.ctrl_reg &= ~((DIVA_ISA == cs->subtyp) ?
DIVA_ISA_LED_B : DIVA_PCI_LED_B);
-
+
byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
if (blink) {
init_timer(&cs->hw.diva.tl);
@@ -291,6 +399,8 @@ diva_led_handler(struct IsdnCardState *cs)
static int
Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg)
{
+ u_int irq_flag = I4L_IRQ_FLAG;
+
switch (mt) {
case CARD_RESET:
reset_diva(cs);
@@ -299,36 +409,40 @@ Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg)
release_io_diva(cs);
return(0);
case CARD_SETIRQ:
- return(request_irq(cs->irq, &diva_interrupt,
- I4L_IRQ_FLAG, "HiSax", cs));
+ if (cs->subtyp == DIVA_PCI)
+ irq_flag |= SA_SHIRQ;
+ if (cs->subtyp == DIVA_IPAC_ISA) {
+ return(request_irq(cs->irq, &diva_interrupt_ipac,
+ irq_flag, "HiSax", cs));
+ } else {
+ return(request_irq(cs->irq, &diva_interrupt,
+ irq_flag, "HiSax", cs));
+ }
case CARD_INIT:
- clear_pending_isac_ints(cs);
- clear_pending_hscx_ints(cs);
- initisac(cs);
- inithscx(cs);
+ inithscxisac(cs, 3);
return(0);
case CARD_TEST:
return(0);
- case MDL_REMOVE_REQ:
+ case (MDL_REMOVE | REQUEST):
cs->hw.diva.status = 0;
break;
- case MDL_ASSIGN_REQ:
+ case (MDL_ASSIGN | REQUEST):
cs->hw.diva.status |= DIVA_ASSIGN;
break;
case MDL_INFO_SETUP:
- if ((int)arg)
+ if ((long)arg)
cs->hw.diva.status |= 0x0200;
else
cs->hw.diva.status |= 0x0100;
break;
case MDL_INFO_CONN:
- if ((int)arg)
+ if ((long)arg)
cs->hw.diva.status |= 0x2000;
else
cs->hw.diva.status |= 0x1000;
break;
case MDL_INFO_REL:
- if ((int)arg) {
+ if ((long)arg) {
cs->hw.diva.status &= ~0x2000;
cs->hw.diva.status &= ~0x0200;
} else {
@@ -337,18 +451,19 @@ Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg)
}
break;
}
- diva_led_handler(cs);
+ if (cs->subtyp != DIVA_IPAC_ISA)
+ diva_led_handler(cs);
return(0);
}
-
-
-static int pci_index __initdata = 0;
+static struct pci_dev *dev_diva __initdata = NULL;
+static struct pci_dev *dev_diva_u __initdata = NULL;
__initfunc(int
setup_diva(struct IsdnCard *card))
{
int bytecnt;
+ u_char val;
struct IsdnCardState *cs = card->cs;
char tmp[64];
@@ -358,64 +473,72 @@ setup_diva(struct IsdnCard *card))
return(0);
cs->hw.diva.status = 0;
if (card->para[1]) {
- cs->subtyp = DIVA_ISA;
cs->hw.diva.ctrl_reg = 0;
cs->hw.diva.cfg_reg = card->para[1];
- cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL;
- cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA;
- cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA;
- cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR;
- cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
+ val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR,
+ cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID);
+ printk(KERN_INFO "Diva: IPAC version %x\n", val);
+ if (val == 1) {
+ cs->subtyp = DIVA_IPAC_ISA;
+ cs->hw.diva.ctrl = 0;
+ cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA;
+ cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA;
+ cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR;
+ cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR;
+ test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+ } else {
+ cs->subtyp = DIVA_ISA;
+ cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL;
+ cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA;
+ cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA;
+ cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR;
+ cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
+ }
cs->irq = card->para[0];
bytecnt = 8;
} else {
#if CONFIG_PCI
- u_char pci_bus, pci_device_fn, pci_irq;
- u_int pci_ioaddr;
+ if (!pci_present()) {
+ printk(KERN_ERR "Diva: no PCI bus present\n");
+ return(0);
+ }
cs->subtyp = 0;
- for (; pci_index < 0xff; pci_index++) {
- if (pcibios_find_device(PCI_VENDOR_EICON_DIEHL,
- PCI_DIVA20_ID, pci_index, &pci_bus, &pci_device_fn)
- == PCIBIOS_SUCCESSFUL)
+ if ((dev_diva = pci_find_device(PCI_VENDOR_EICON_DIEHL,
+ PCI_DIVA20_ID, dev_diva))) {
cs->subtyp = DIVA_PCI;
- else if (pcibios_find_device(PCI_VENDOR_EICON_DIEHL,
- PCI_DIVA20_ID, pci_index, &pci_bus, &pci_device_fn)
- == PCIBIOS_SUCCESSFUL)
+ /* get IRQ */
+ cs->irq = dev_diva->irq;
+ /* get IO address */
+ cs->hw.diva.cfg_reg = dev_diva->base_address[2]
+ & PCI_BASE_ADDRESS_IO_MASK;
+ } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_EICON_DIEHL,
+ PCI_DIVA20_U_ID, dev_diva_u))) {
cs->subtyp = DIVA_PCI;
- else
- break;
/* get IRQ */
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_INTERRUPT_LINE, &pci_irq);
-
+ cs->irq = dev_diva_u->irq;
/* get IO address */
- pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_2, &pci_ioaddr);
- if (cs->subtyp)
- break;
- }
- if (!cs->subtyp) {
+ cs->hw.diva.cfg_reg = dev_diva_u->base_address[2]
+ & PCI_BASE_ADDRESS_IO_MASK;
+ } else {
printk(KERN_WARNING "Diva: No PCI card found\n");
return(0);
}
- if (!pci_irq) {
+
+ if (!cs->irq) {
printk(KERN_WARNING "Diva: No IRQ for PCI card found\n");
return(0);
}
- if (!pci_ioaddr) {
+ if (!cs->hw.diva.cfg_reg) {
printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n");
return(0);
}
- pci_ioaddr &= ~3; /* remove io/mem flag */
- cs->hw.diva.cfg_reg = pci_ioaddr;
- cs->hw.diva.ctrl = pci_ioaddr + DIVA_PCI_CTRL;
- cs->hw.diva.isac = pci_ioaddr + DIVA_PCI_ISAC_DATA;
- cs->hw.diva.hscx = pci_ioaddr + DIVA_HSCX_DATA;
- cs->hw.diva.isac_adr = pci_ioaddr + DIVA_PCI_ISAC_ADR;
- cs->hw.diva.hscx_adr = pci_ioaddr + DIVA_HSCX_ADR;
- cs->irq = pci_irq;
+ cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;
+ cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA;
+ cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA;
+ cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR;
+ cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR;
bytecnt = 32;
#else
printk(KERN_WARNING "Diva: cfgreg 0 and NO_PCI_BIOS\n");
@@ -426,7 +549,8 @@ setup_diva(struct IsdnCard *card))
printk(KERN_INFO
"Diva: %s card configured at 0x%x IRQ %d\n",
- (cs->subtyp == DIVA_ISA) ? "ISA" : "PCI",
+ (cs->subtyp == DIVA_PCI) ? "PCI" :
+ (cs->subtyp == DIVA_ISA) ? "ISA" : "IPAC",
cs->hw.diva.cfg_reg, cs->irq);
if (check_region(cs->hw.diva.cfg_reg, bytecnt)) {
printk(KERN_WARNING
@@ -440,24 +564,32 @@ setup_diva(struct IsdnCard *card))
}
reset_diva(cs);
- cs->hw.diva.tl.function = (void *) diva_led_handler;
- cs->hw.diva.tl.data = (long) cs;
- init_timer(&cs->hw.diva.tl);
- 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 = &Diva_card_msg;
-
- ISACVersion(cs, "Diva:");
- if (HscxVersion(cs, "Diva:")) {
- printk(KERN_WARNING
+ if (cs->subtyp == DIVA_IPAC_ISA) {
+ cs->readisac = &ReadISAC_IPAC;
+ cs->writeisac = &WriteISAC_IPAC;
+ cs->readisacfifo = &ReadISACfifo_IPAC;
+ cs->writeisacfifo = &WriteISACfifo_IPAC;
+ val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ID);
+ printk(KERN_INFO "Diva: IPAC version %x\n", val);
+ } else {
+ cs->hw.diva.tl.function = (void *) diva_led_handler;
+ cs->hw.diva.tl.data = (long) cs;
+ init_timer(&cs->hw.diva.tl);
+ cs->readisac = &ReadISAC;
+ cs->writeisac = &WriteISAC;
+ cs->readisacfifo = &ReadISACfifo;
+ cs->writeisacfifo = &WriteISACfifo;
+ ISACVersion(cs, "Diva:");
+ if (HscxVersion(cs, "Diva:")) {
+ printk(KERN_WARNING
"Diva: wrong HSCX versions check IO address\n");
- release_io_diva(cs);
- return (0);
+ release_io_diva(cs);
+ return (0);
+ }
}
return (1);
}
diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
index 008178065..50f9df9c0 100644
--- a/drivers/isdn/hisax/elsa.c
+++ b/drivers/isdn/hisax/elsa.c
@@ -1,13 +1,41 @@
-/* $Id: elsa.c,v 2.6 1998/02/02 13:29:40 keil Exp $
+/* $Id: elsa.c,v 2.12 1998/11/15 23:54:35 keil Exp $
* elsa.c low level stuff for Elsa isdn cards
*
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
+ *
+ * This file is (c) under GNU PUBLIC LICENSE
+ * For changes and modifications please read
+ * ../../../Documentation/isdn/HiSax.cert
*
* Thanks to Elsa GmbH for documents and informations
*
+ * Klaus Lichtenwalder (Klaus.Lichtenwalder@WebForum.DE)
+ * for ELSA PCMCIA support
+ *
*
* $Log: elsa.c,v $
+ * Revision 2.12 1998/11/15 23:54:35 keil
+ * changes from 2.0
+ *
+ * Revision 2.11 1998/08/20 13:50:34 keil
+ * More support for hybrid modem (not working yet)
+ *
+ * Revision 2.10 1998/08/13 23:36:22 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.9 1998/05/25 12:57:48 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.8 1998/04/15 16:41:42 keil
+ * QS3000 PCI support
+ * new init code
+ * new PCI init (2.1.94)
+ *
+ * Revision 2.7 1998/03/07 22:56:58 tsbogend
+ * made HiSax working on Linux/Alpha
+ *
* Revision 2.6 1998/02/02 13:29:40 keil
* fast io
*
@@ -29,15 +57,6 @@
* Revision 2.0 1997/06/26 11:02:40 keil
* New Layer and card interface
*
- * Revision 1.14 1997/04/13 19:53:25 keil
- * Fixed QS1000 init, change in IRQ check delay for SMP
- *
- * Revision 1.13 1997/04/07 22:58:07 keil
- * need include config.h
- *
- * Revision 1.12 1997/04/06 22:54:14 keil
- * Using SKB's
- *
* old changes removed KKe
*
*/
@@ -51,14 +70,16 @@
#include "hscx.h"
#include "isdnl1.h"
#include <linux/pci.h>
-#include <linux/bios32.h>
+
+//#define KDEBUG_DEF
+//#include "../kdebug.h"
extern const char *CardType[];
-const char *Elsa_revision = "$Revision: 2.6 $";
+static const char *Elsa_revision = "$Revision: 2.12 $";
const char *Elsa_Types[] =
{"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro",
- "PCMCIA", "QS 1000", "QS 3000", "QS 1000 PCI"};
+ "PCMCIA", "QS 1000", "QS 3000", "QS 1000 PCI", "QS 3000 PCI"};
const char *ITACVer[] =
{"?0?", "?1?", "?2?", "?3?", "?4?", "V2.2",
@@ -87,11 +108,13 @@ const char *ITACVer[] =
#define ELSA_QS1000 7
#define ELSA_QS3000 8
#define ELSA_QS1000PCI 9
+#define ELSA_QS3000PCI 10
/* PCI stuff */
#define PCI_VENDOR_ELSA 0x1048
#define PCI_QS1000_ID 0x1000
-
+#define PCI_QS3000_ID 0x3000
+#define ELSA_PCI_IRQ_MASK 0x04
/* ITAC Registeradressen (only Microlink PC) */
#define ITAC_SYS 0x34
@@ -128,6 +151,30 @@ const char *ITACVer[] =
#define ELSA_BAD_PWR 2
#define ELSA_ASSIGN 4
+#define RS_ISR_PASS_LIMIT 256
+#define _INLINE_ inline
+#define FLG_MODEM_ACTIVE 1
+/* IPAC AUX */
+#define ELSA_IPAC_LINE_LED 0x40 /* Bit 6 Gelbe LED */
+#define ELSA_IPAC_STAT_LED 0x80 /* Bit 7 Gruene LED */
+
+const u_char ARCOFI_VERSION[] = {2,0xa0,0};
+const u_char ARCOFI_COP_5[] = {4,0xa1,0x25,0xbb,0x4a}; /* GTX */
+const u_char ARCOFI_COP_6[] = {6,0xa1,0x26,0,0,0x82,0x7c}; /* GRL GRH */
+const u_char ARCOFI_COP_7[] = {4,0xa1,0x27,0x80,0x80}; /* GZ */
+const u_char ARCOFI_COP_8[] = {10,0xa1,0x28,0x49,0x31,0x8,0x13,0x6e,0x88,0x2a,0x61}; /* TX */
+const u_char ARCOFI_COP_9[] = {10,0xa1,0x29,0x80,0xcb,0xe9,0x88,0x00,0xc8,0xd8,0x80}; /* RX */
+const u_char ARCOFI_XOP_0[] = {2,0xa1,0x30}; /* PWR Down */
+const u_char ARCOFI_XOP_1[] = {2,0xa1,0x31}; /* PWR UP */
+const u_char ARCOFI_XOP_F[] = {2,0xa1,0x3f}; /* Normal OP */
+const u_char ARCOFI_SOP_F[] = {10,0xa1,0x1f,0x00,0x50,0x10,0x00,0x00,0x80,0x02,0x12};
+
+static void set_arcofi(struct IsdnCardState *cs, int bc);
+
+#if ARCOFI_USE
+#include "elsa_ser.c"
+#endif
+
static inline u_char
readreg(unsigned int ale, unsigned int adr, u_char off)
{
@@ -302,6 +349,21 @@ elsa_interrupt(int intno, void *dev_id, struct pt_regs *regs)
printk(KERN_WARNING "Elsa: Spurious interrupt!\n");
return;
}
+ if ((cs->typ == ISDN_CTYPE_ELSA_PCMCIA) && (*cs->busy_flag == 1)) {
+ /* The card tends to generate interrupts while being removed
+ causing us to just crash the kernel. bad. */
+ printk(KERN_WARNING "Elsa: card not available!\n");
+ return;
+ }
+#if ARCOFI_USE
+ if (cs->hw.elsa.MFlag) {
+ val = serial_inp(cs, UART_IIR);
+ if (!(val & UART_IIR_NO_INT)) {
+ debugl1(cs,"IIR %02x", val);
+ rs_interrupt_elsa(intno, cs);
+ }
+ }
+#endif
val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40);
Start_HSCX:
if (val) {
@@ -338,6 +400,14 @@ elsa_interrupt(int intno, void *dev_id, struct pt_regs *regs)
cs->hw.elsa.counter++;
}
}
+ if (cs->hw.elsa.MFlag) {
+ val = serial_inp(cs, UART_MCR);
+ val ^= 0x8;
+ serial_outp(cs, UART_MCR, val);
+ val = serial_inp(cs, UART_MCR);
+ val ^= 0x8;
+ serial_outp(cs, UART_MCR, val);
+ }
if (cs->hw.elsa.trig)
byteout(cs->hw.elsa.trig, 0x00);
writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0x0);
@@ -350,25 +420,28 @@ elsa_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
{
struct IsdnCardState *cs = dev_id;
u_char ista,val;
- char tmp[64];
int icnt=20;
if (!cs) {
printk(KERN_WARNING "Elsa: Spurious interrupt!\n");
return;
}
- if ((cs->typ == ISDN_CTYPE_ELSA_PCMCIA) && (*cs->busy_flag == 1)) {
- /* The card tends to generate interrupts while being removed
- causing us to just crash the kernel. bad. */
- printk(KERN_WARNING "Elsa: card not available!\n");
- return;
+ val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */
+ if (!(val & ELSA_PCI_IRQ_MASK))
+ return;
+#if ARCOFI_USE
+ if (cs->hw.elsa.MFlag) {
+ val = serial_inp(cs, UART_IIR);
+ if (!(val & UART_IIR_NO_INT)) {
+ debugl1(cs,"IIR %02x", val);
+ rs_interrupt_elsa(intno, cs);
+ }
}
+#endif
ista = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA);
Start_IPAC:
- if (cs->debug & L1_DEB_IPAC) {
- sprintf(tmp, "IPAC ISTA %02X", ista);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_IPAC)
+ debugl1(cs, "IPAC ISTA %02X", ista);
if (ista & 0x0f) {
val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40);
if (ista & 0x01)
@@ -409,15 +482,24 @@ release_io_elsa(struct IsdnCardState *cs)
del_timer(&cs->hw.elsa.tl);
if (cs->hw.elsa.ctrl)
byteout(cs->hw.elsa.ctrl, 0); /* LEDs Out */
- if ((cs->subtyp == ELSA_PCFPRO) ||
- (cs->subtyp == ELSA_QS3000) ||
- (cs->subtyp == ELSA_PCF))
- bytecnt = 16;
if (cs->subtyp == ELSA_QS1000PCI) {
byteout(cs->hw.elsa.cfg + 0x4c, 0x01); /* disable IRQ */
+ writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);
bytecnt = 2;
release_region(cs->hw.elsa.cfg, 0x80);
}
+ if (cs->subtyp == ELSA_QS3000PCI) {
+ byteout(cs->hw.elsa.cfg + 0x4c, 0x03); /* disable ELSA PCI IRQ */
+ writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);
+ release_region(cs->hw.elsa.cfg, 0x80);
+ }
+ if ((cs->subtyp == ELSA_PCFPRO) ||
+ (cs->subtyp == ELSA_QS3000) ||
+ (cs->subtyp == ELSA_PCF) ||
+ (cs->subtyp == ELSA_QS3000PCI)) {
+ bytecnt = 16;
+ release_modem(cs);
+ }
if (cs->hw.elsa.base)
release_region(cs->hw.elsa.base, bytecnt);
}
@@ -445,7 +527,7 @@ reset_elsa(struct IsdnCardState *cs)
if (cs->hw.elsa.trig)
byteout(cs->hw.elsa.trig, 0xff);
}
- if (cs->subtyp == ELSA_QS1000PCI) {
+ if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) {
save_flags(flags);
sti();
writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x20);
@@ -455,35 +537,55 @@ reset_elsa(struct IsdnCardState *cs)
current->state = TASK_INTERRUPTIBLE;
schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xc0);
- schedule();
restore_flags(flags);
- byteout(cs->hw.elsa.cfg + 0x4c, 0x41); /* enable ELSA PCI IRQ */
+ writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x0);
+ writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0x3c);
+ writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);
+ if (cs->subtyp == ELSA_QS1000PCI)
+ byteout(cs->hw.elsa.cfg + 0x4c, 0x41); /* enable ELSA PCI IRQ */
+ else if (cs->subtyp == ELSA_QS3000PCI)
+ byteout(cs->hw.elsa.cfg + 0x4c, 0x43); /* enable ELSA PCI IRQ */
}
}
-const u_char ARCOFI_VERSION[] = {2,0xa0,0};
-const u_char ARCOFI_COP_5[] = {4,0xa1,0x25,0xbb,0x4a}; /* GTX */
-const u_char ARCOFI_COP_6[] = {6,0xa1,0x26,0,0,0x82,0x7c}; /* GRL GRH */
-const u_char ARCOFI_COP_7[] = {4,0xa1,0x27,0x80,0x80}; /* GZ */
-const u_char ARCOFI_COP_8[] = {10,0xa1,0x28,0x49,0x31,0x8,0x13,0x6e,0x88,0x2a,0x61}; /* TX */
-const u_char ARCOFI_COP_9[] = {10,0xa1,0x29,0x80,0xcb,0x9e,0x88,0x00,0xc8,0xd8,0x80}; /* RX */
-const u_char ARCOFI_XOP_0[] = {2,0xa1,0x30}; /* PWR Down */
-const u_char ARCOFI_XOP_1[] = {2,0xa1,0x31}; /* PWR Down */
-const u_char ARCOFI_XOP_F[] = {2,0xa1,0x3f}; /* PWR Down */
-const u_char ARCOFI_SOP_F[] = {10,0xa1,0x1f,0x00,0x50,0x10,0x00,0x00,0x80,0x02,0x12};
-
static void
init_arcofi(struct IsdnCardState *cs) {
- send_arcofi(cs, ARCOFI_COP_5);
- send_arcofi(cs, ARCOFI_COP_6);
- send_arcofi(cs, ARCOFI_COP_7);
- send_arcofi(cs, ARCOFI_COP_8);
- send_arcofi(cs, ARCOFI_COP_9);
- send_arcofi(cs, ARCOFI_SOP_F);
- send_arcofi(cs, ARCOFI_XOP_F);
+ send_arcofi(cs, ARCOFI_XOP_0, 1, 0);
+/* send_arcofi(cs, ARCOFI_XOP_F, 1);
+*/
}
+#define ARCDEL 500
+
static void
+set_arcofi(struct IsdnCardState *cs, int bc) {
+ long flags;
+
+ debugl1(cs,"set_arcofi bc=%d", bc);
+ save_flags(flags);
+ sti();
+ send_arcofi(cs, ARCOFI_XOP_0, bc, 0);
+ udelay(ARCDEL);
+ send_arcofi(cs, ARCOFI_COP_5, bc, 0);
+ udelay(ARCDEL);
+ send_arcofi(cs, ARCOFI_COP_6, bc, 0);
+ udelay(ARCDEL);
+ send_arcofi(cs, ARCOFI_COP_7, bc, 0);
+ udelay(ARCDEL);
+ send_arcofi(cs, ARCOFI_COP_8, bc, 0);
+ udelay(ARCDEL);
+ send_arcofi(cs, ARCOFI_COP_9, bc, 0);
+ udelay(ARCDEL);
+ send_arcofi(cs, ARCOFI_SOP_F, bc, 0);
+ udelay(ARCDEL);
+ send_arcofi(cs, ARCOFI_XOP_1, bc, 0);
+ udelay(ARCDEL);
+ send_arcofi(cs, ARCOFI_XOP_F, bc, 0);
+ restore_flags(flags);
+ debugl1(cs,"end set_arcofi bc=%d", bc);
+}
+
+static int
check_arcofi(struct IsdnCardState *cs)
{
#if ARCOFI_USE
@@ -496,13 +598,12 @@ check_arcofi(struct IsdnCardState *cs)
if (!(cs->mon_tx=kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "ISAC MON TX out of buffers!");
- return;
+ return(0);
}
- send_arcofi(cs, ARCOFI_VERSION);
+ send_arcofi(cs, ARCOFI_VERSION, 0, 1);
if (test_and_clear_bit(HW_MON1_TX_END, &cs->HW_Flags)) {
if (test_and_clear_bit(HW_MON1_RX_END, &cs->HW_Flags)) {
- sprintf(tmp, "Arcofi response received %d bytes", cs->mon_rxp);
- debugl1(cs, tmp);
+ debugl1(cs, "Arcofi response received %d bytes", cs->mon_rxp);
p = cs->mon_rx;
t = tmp;
t += sprintf(tmp, "Arcofi data");
@@ -531,8 +632,7 @@ check_arcofi(struct IsdnCardState *cs)
cs->mon_rxp = 0;
}
} else if (cs->mon_tx) {
- sprintf(tmp, "Arcofi not detected");
- debugl1(cs, tmp);
+ debugl1(cs, "Arcofi not detected");
}
if (arcofi_present) {
if (cs->subtyp==ELSA_QS1000) {
@@ -573,8 +673,10 @@ check_arcofi(struct IsdnCardState *cs)
Elsa_Types[cs->subtyp],
cs->hw.elsa.base+8);
init_arcofi(cs);
+ return(1);
}
#endif
+ return(0);
}
static void
@@ -582,8 +684,7 @@ elsa_led_handler(struct IsdnCardState *cs)
{
int blink = 0;
- if ((cs->subtyp == ELSA_PCMCIA) &&
- (cs->subtyp == ELSA_QS1000PCI))
+ if (cs->subtyp == ELSA_PCMCIA)
return;
del_timer(&cs->hw.elsa.tl);
if (cs->hw.elsa.status & ELSA_ASSIGN)
@@ -602,7 +703,16 @@ elsa_led_handler(struct IsdnCardState *cs)
} else
cs->hw.elsa.ctrl_reg &= ~ELSA_LINE_LED;
- byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
+ if ((cs->subtyp == ELSA_QS1000PCI) ||
+ (cs->subtyp == ELSA_QS3000PCI)) {
+ u_char led = 0xff;
+ if (cs->hw.elsa.ctrl_reg & ELSA_LINE_LED)
+ led ^= ELSA_IPAC_LINE_LED;
+ if (cs->hw.elsa.ctrl_reg & ELSA_STAT_LED)
+ led ^= ELSA_IPAC_STAT_LED;
+ writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, led);
+ } else
+ byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
if (blink) {
init_timer(&cs->hw.elsa.tl);
cs->hw.elsa.tl.expires = jiffies + ((blink * HZ) / 1000);
@@ -613,8 +723,9 @@ elsa_led_handler(struct IsdnCardState *cs)
static int
Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg)
{
- int pwr, ret = 0;
- long flags;
+ int len, ret = 0;
+ u_char *msg;
+ long flags;
switch (mt) {
case CARD_RESET:
@@ -624,28 +735,33 @@ Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg)
release_io_elsa(cs);
return(0);
case CARD_SETIRQ:
- if (cs->subtyp == ELSA_QS1000PCI)
+ if ((cs->subtyp == ELSA_QS1000PCI) ||
+ (cs->subtyp == ELSA_QS3000PCI))
ret = request_irq(cs->irq, &elsa_interrupt_ipac,
- I4L_IRQ_FLAG, "HiSax", cs);
+ I4L_IRQ_FLAG | SA_SHIRQ, "HiSax", cs);
else
ret = request_irq(cs->irq, &elsa_interrupt,
I4L_IRQ_FLAG, "HiSax", cs);
return(ret);
case CARD_INIT:
- if (cs->hw.elsa.trig)
- byteout(cs->hw.elsa.trig, 0xff);
- clear_pending_isac_ints(cs);
- clear_pending_hscx_ints(cs);
- initisac(cs);
- inithscx(cs);
- if (cs->subtyp == ELSA_QS1000) {
+ cs->debug |= L1_DEB_IPAC;
+ inithscxisac(cs, 1);
+ if ((cs->subtyp == ELSA_QS1000) ||
+ (cs->subtyp == ELSA_QS3000))
+ {
byteout(cs->hw.elsa.timer, 0);
- byteout(cs->hw.elsa.trig, 0xff);
}
+ if (cs->hw.elsa.trig)
+ byteout(cs->hw.elsa.trig, 0xff);
+ inithscxisac(cs, 2);
return(0);
case CARD_TEST:
- if ((cs->subtyp != ELSA_PCMCIA) &&
- (cs->subtyp != ELSA_QS1000PCI)) {
+ if ((cs->subtyp == ELSA_PCMCIA) ||
+ (cs->subtyp == ELSA_QS1000PCI)) {
+ return(0);
+ } else if (cs->subtyp == ELSA_QS3000PCI) {
+ ret = 0;
+ } else {
save_flags(flags);
cs->hw.elsa.counter = 0;
sti();
@@ -653,48 +769,52 @@ Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg)
cs->hw.elsa.status |= ELSA_TIMER_AKTIV;
byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
byteout(cs->hw.elsa.timer, 0);
- } else
- return(0);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout((110*HZ)/1000); /* Timeout 110ms */
- restore_flags(flags);
- cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT;
- byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
- cs->hw.elsa.status &= ~ELSA_TIMER_AKTIV;
- printk(KERN_INFO "Elsa: %d timer tics in 110 msek\n",
- cs->hw.elsa.counter);
- if (abs(cs->hw.elsa.counter - 13) < 3) {
- printk(KERN_INFO "Elsa: timer and irq OK\n");
- ret = 0;
- } else {
- printk(KERN_WARNING
- "Elsa: timer tic problem (%d/12) maybe an IRQ(%d) conflict\n",
- cs->hw.elsa.counter, cs->irq);
- ret = 1;
+ current->state = TASK_INTERRUPTIBLE;
+ /* Timeout 110ms */
+ schedule_timeout((110*HZ)/1000);
+ restore_flags(flags);
+ cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT;
+ byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
+ cs->hw.elsa.status &= ~ELSA_TIMER_AKTIV;
+ printk(KERN_INFO "Elsa: %d timer tics in 110 msek\n",
+ cs->hw.elsa.counter);
+ if (abs(cs->hw.elsa.counter - 13) < 3) {
+ printk(KERN_INFO "Elsa: timer and irq OK\n");
+ ret = 0;
+ } else {
+ printk(KERN_WARNING
+ "Elsa: timer tic problem (%d/12) maybe an IRQ(%d) conflict\n",
+ cs->hw.elsa.counter, cs->irq);
+ ret = 1;
+ }
}
- check_arcofi(cs);
+#if ARCOFI_USE
+ if (check_arcofi(cs)) {
+ init_modem(cs);
+ }
+#endif
elsa_led_handler(cs);
return(ret);
- case MDL_REMOVE_REQ:
+ case (MDL_REMOVE | REQUEST):
cs->hw.elsa.status &= 0;
break;
- case MDL_ASSIGN_REQ:
+ case (MDL_ASSIGN | REQUEST):
cs->hw.elsa.status |= ELSA_ASSIGN;
break;
case MDL_INFO_SETUP:
- if ((int) arg)
+ if ((long) arg)
cs->hw.elsa.status |= 0x0200;
else
cs->hw.elsa.status |= 0x0100;
break;
case MDL_INFO_CONN:
- if ((int) arg)
+ if ((long) arg)
cs->hw.elsa.status |= 0x2000;
else
cs->hw.elsa.status |= 0x1000;
break;
case MDL_INFO_REL:
- if ((int) arg) {
+ if ((long) arg) {
cs->hw.elsa.status &= ~0x2000;
cs->hw.elsa.status &= ~0x0200;
} else {
@@ -703,13 +823,23 @@ Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg)
}
break;
case CARD_AUX_IND:
+ if (cs->hw.elsa.MFlag) {
+ if (!arg)
+ return(0);
+ msg = arg;
+ len = *msg;
+ msg++;
+ modem_write_cmd(cs, msg, len);
+ }
break;
}
- pwr = bytein(cs->hw.elsa.ale);
- if (pwr & 0x08)
- cs->hw.elsa.status |= ELSA_BAD_PWR;
- else
- cs->hw.elsa.status &= ~ELSA_BAD_PWR;
+ if (cs->typ == ISDN_CTYPE_ELSA) {
+ int pwr = bytein(cs->hw.elsa.ale);
+ if (pwr & 0x08)
+ cs->hw.elsa.status |= ELSA_BAD_PWR;
+ else
+ cs->hw.elsa.status &= ~ELSA_BAD_PWR;
+ }
elsa_led_handler(cs);
return(ret);
}
@@ -778,7 +908,8 @@ probe_elsa(struct IsdnCardState *cs)
return (CARD_portlist[i]);
}
-static int pci_index __initdata = 0;
+static struct pci_dev *dev_qs1000 __initdata = NULL;
+static struct pci_dev *dev_qs3000 __initdata = NULL;
int
setup_elsa(struct IsdnCard *card)
@@ -793,6 +924,7 @@ setup_elsa(struct IsdnCard *card)
printk(KERN_INFO "HiSax: Elsa driver Rev. %s\n", HiSax_getrev(tmp));
cs->hw.elsa.ctrl_reg = 0;
cs->hw.elsa.status = 0;
+ cs->hw.elsa.MFlag = 0;
if (cs->typ == ISDN_CTYPE_ELSA) {
cs->hw.elsa.base = card->para[0];
printk(KERN_INFO "Elsa: Microlink IO probing\n");
@@ -886,59 +1018,62 @@ setup_elsa(struct IsdnCard *card)
cs->irq);
} else if (cs->typ == ISDN_CTYPE_ELSA_PCI) {
#if CONFIG_PCI
- u_char pci_bus, pci_device_fn, pci_irq;
- u_int pci_ioaddr;
-
+ if (!pci_present()) {
+ printk(KERN_ERR "Elsa: no PCI bus present\n");
+ return(0);
+ }
cs->subtyp = 0;
- for (; pci_index < 0xff; pci_index++) {
- if (pcibios_find_device(PCI_VENDOR_ELSA,
- PCI_QS1000_ID, pci_index, &pci_bus, &pci_device_fn)
- == PCIBIOS_SUCCESSFUL)
+ if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ELSA, PCI_QS1000_ID,
+ dev_qs1000))) {
cs->subtyp = ELSA_QS1000PCI;
- else
- break;
- /* get IRQ */
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_INTERRUPT_LINE, &pci_irq);
-
- /* get IO address */
- pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_1, &pci_ioaddr);
- pci_ioaddr &= ~3; /* remove io/mem flag */
- cs->hw.elsa.cfg = pci_ioaddr;
- pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_3, &pci_ioaddr);
- if (cs->subtyp)
- break;
- }
- if (!cs->subtyp) {
+ cs->irq = dev_qs1000->irq;
+ cs->hw.elsa.cfg = dev_qs1000->base_address[1] &
+ PCI_BASE_ADDRESS_IO_MASK;
+ cs->hw.elsa.base = dev_qs1000->base_address[3] &
+ PCI_BASE_ADDRESS_IO_MASK;
+ } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ELSA,
+ PCI_QS3000_ID, dev_qs3000))) {
+ cs->subtyp = ELSA_QS3000PCI;
+ cs->irq = dev_qs3000->irq;
+ cs->hw.elsa.cfg = dev_qs3000->base_address[1] &
+ PCI_BASE_ADDRESS_IO_MASK;
+ cs->hw.elsa.base = dev_qs3000->base_address[3] &
+ PCI_BASE_ADDRESS_IO_MASK;
+ } else {
printk(KERN_WARNING "Elsa: No PCI card found\n");
return(0);
}
- if (!pci_irq) {
+ if (!cs->irq) {
printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n");
return(0);
}
- if (!pci_ioaddr) {
+ if (!(cs->hw.elsa.base && cs->hw.elsa.cfg)) {
printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n");
return(0);
}
- pci_ioaddr &= ~3; /* remove io/mem flag */
- cs->hw.elsa.base = pci_ioaddr;
- cs->hw.elsa.ale = pci_ioaddr;
- cs->hw.elsa.isac = pci_ioaddr +1;
- cs->hw.elsa.hscx = pci_ioaddr +1;
- cs->irq = pci_irq;
+ cs->hw.elsa.ale = cs->hw.elsa.base;
+ cs->hw.elsa.isac = cs->hw.elsa.base +1;
+ cs->hw.elsa.hscx = cs->hw.elsa.base +1;
test_and_set_bit(HW_IPAC, &cs->HW_Flags);
cs->hw.elsa.timer = 0;
cs->hw.elsa.trig = 0;
printk(KERN_INFO
- "Elsa: %s defined at 0x%x/0x%x IRQ %d\n",
- Elsa_Types[cs->subtyp],
- cs->hw.elsa.base,
- cs->hw.elsa.cfg,
- cs->irq);
+ "Elsa: %s defined at 0x%x/0x%x IRQ %d\n",
+ Elsa_Types[cs->subtyp],
+ cs->hw.elsa.base,
+ cs->hw.elsa.cfg,
+ cs->irq);
+ if ((cs->hw.elsa.cfg & 0xff) || (cs->hw.elsa.base & 0xf)) {
+ printk(KERN_WARNING "Elsa: You may have a wrong PCI bios\n");
+ printk(KERN_WARNING "Elsa: If your system hangs now, read\n");
+ printk(KERN_WARNING "Elsa: Documentation/isdn/README.HiSax\n");
+ printk(KERN_WARNING "Elsa: Waiting 5 sec to sync discs\n");
+ save_flags(flags);
+ sti();
+ HZDELAY(500); /* wait 500*10 ms */
+ restore_flags(flags);
+ }
#else
printk(KERN_WARNING "Elsa: Elsa PCI and NO_PCI_BIOS\n");
printk(KERN_WARNING "Elsa: unable to config Elsa PCI\n");
@@ -957,6 +1092,7 @@ setup_elsa(struct IsdnCard *card)
break;
case ELSA_PCFPRO:
case ELSA_PCF:
+ case ELSA_QS3000PCI:
bytecnt = 16;
break;
case ELSA_QS1000PCI:
@@ -980,7 +1116,7 @@ setup_elsa(struct IsdnCard *card)
} else {
request_region(cs->hw.elsa.base, bytecnt, "elsa isdn");
}
- if (cs->subtyp == ELSA_QS1000PCI) {
+ if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) {
if (check_region(cs->hw.elsa.cfg, 0x80)) {
printk(KERN_WARNING
"HiSax: %s pci port %x-%x already in use\n",
@@ -1020,12 +1156,12 @@ setup_elsa(struct IsdnCard *card)
}
printk(KERN_INFO "Elsa: timer OK; resetting card\n");
}
- reset_elsa(cs);
cs->BC_Read_Reg = &ReadHSCX;
cs->BC_Write_Reg = &WriteHSCX;
cs->BC_Send_Data = &hscx_fill_fifo;
cs->cardmsg = &Elsa_card_msg;
- if (cs->subtyp == ELSA_QS1000PCI) {
+ reset_elsa(cs);
+ if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) {
cs->readisac = &ReadISAC_IPAC;
cs->writeisac = &WriteISAC_IPAC;
cs->readisacfifo = &ReadISACfifo_IPAC;
@@ -1056,4 +1192,3 @@ setup_elsa(struct IsdnCard *card)
}
return (1);
}
-
diff --git a/drivers/isdn/hisax/fsm.c b/drivers/isdn/hisax/fsm.c
index ae0662f3f..aa0ff4adb 100644
--- a/drivers/isdn/hisax/fsm.c
+++ b/drivers/isdn/hisax/fsm.c
@@ -1,4 +1,4 @@
-/* $Id: fsm.c,v 1.7 1997/11/06 17:09:13 keil Exp $
+/* $Id: fsm.c,v 1.10 1998/11/15 23:54:39 keil Exp $
* Author Karsten Keil (keil@temic-ech.spacenet.de)
* based on the teles driver from Jan den Ouden
@@ -7,6 +7,18 @@
* Fritz Elfert
*
* $Log: fsm.c,v $
+ * Revision 1.10 1998/11/15 23:54:39 keil
+ * changes from 2.0
+ *
+ * Revision 1.9 1998/03/26 07:10:02 paul
+ * The jumpmatrix table in struct Fsm was an array of "int". This is not
+ * large enough for pointers to functions on Linux/Alpha (instant crash
+ * on "insmod hisax). Now there is a typedef for the pointer to function.
+ * This also prevents warnings about "incompatible pointer types".
+ *
+ * Revision 1.8 1998/03/07 22:56:59 tsbogend
+ * made HiSax working on Linux/Alpha
+ *
* Revision 1.7 1997/11/06 17:09:13 keil
* New 2.1 init code
*
@@ -41,18 +53,18 @@ FsmNew(struct Fsm *fsm,
{
int i;
- fsm->jumpmatrix = (int *)
- kmalloc(4L * fsm->state_count * fsm->event_count, GFP_KERNEL);
- memset(fsm->jumpmatrix, 0, 4L * fsm->state_count * fsm->event_count);
+ fsm->jumpmatrix = (FSMFNPTR *)
+ kmalloc(sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL);
+ memset(fsm->jumpmatrix, 0, sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count);
for (i = 0; i < fncount; i++)
if ((fnlist[i].state>=fsm->state_count) || (fnlist[i].event>=fsm->event_count)) {
- printk(KERN_ERR "FsmNew Error line %d st(%d/%d) ev(%d/%d)\n",
- i,fnlist[i].state,fsm->state_count,
- fnlist[i].event,fsm->event_count);
+ printk(KERN_ERR "FsmNew Error line %d st(%ld/%ld) ev(%ld/%ld)\n",
+ i,(long)fnlist[i].state,(long)fsm->state_count,
+ (long)fnlist[i].event,(long)fsm->event_count);
} else
fsm->jumpmatrix[fsm->state_count * fnlist[i].event +
- fnlist[i].state] = (int) fnlist[i].routine;
+ fnlist[i].state] = (FSMFNPTR) fnlist[i].routine;
}
void
@@ -64,31 +76,26 @@ FsmFree(struct Fsm *fsm)
int
FsmEvent(struct FsmInst *fi, int event, void *arg)
{
- void (*r) (struct FsmInst *, int, void *);
- char str[80];
+ FSMFNPTR r;
if ((fi->state>=fi->fsm->state_count) || (event >= fi->fsm->event_count)) {
- printk(KERN_ERR "FsmEvent Error st(%d/%d) ev(%d/%d)\n",
- fi->state,fi->fsm->state_count,event,fi->fsm->event_count);
+ printk(KERN_ERR "FsmEvent Error st(%ld/%ld) ev(%d/%ld)\n",
+ (long)fi->state,(long)fi->fsm->state_count,event,(long)fi->fsm->event_count);
return(1);
}
- r = (void (*)) fi->fsm->jumpmatrix[fi->fsm->state_count * event + fi->state];
+ r = fi->fsm->jumpmatrix[fi->fsm->state_count * event + fi->state];
if (r) {
- if (fi->debug) {
- sprintf(str, "State %s Event %s",
+ if (fi->debug)
+ fi->printdebug(fi, "State %s Event %s",
fi->fsm->strState[fi->state],
fi->fsm->strEvent[event]);
- fi->printdebug(fi, str);
- }
r(fi, event, arg);
return (0);
} else {
- if (fi->debug) {
- sprintf(str, "State %s Event %s no routine",
+ if (fi->debug)
+ fi->printdebug(fi, "State %s Event %s no routine",
fi->fsm->strState[fi->state],
fi->fsm->strEvent[event]);
- fi->printdebug(fi, str);
- }
return (!0);
}
}
@@ -96,25 +103,18 @@ FsmEvent(struct FsmInst *fi, int event, void *arg)
void
FsmChangeState(struct FsmInst *fi, int newstate)
{
- char str[80];
-
fi->state = newstate;
- if (fi->debug) {
- sprintf(str, "ChangeState %s",
+ if (fi->debug)
+ fi->printdebug(fi, "ChangeState %s",
fi->fsm->strState[newstate]);
- fi->printdebug(fi, str);
- }
}
static void
FsmExpireTimer(struct FsmTimer *ft)
{
#if FSM_TIMER_DEBUG
- if (ft->fi->debug) {
- char str[40];
- sprintf(str, "FsmExpireTimer %lx", (long) ft);
- ft->fi->printdebug(ft->fi, str);
- }
+ if (ft->fi->debug)
+ ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft);
#endif
FsmEvent(ft->fi, ft->event, ft->arg);
}
@@ -126,11 +126,8 @@ FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft)
ft->tl.function = (void *) FsmExpireTimer;
ft->tl.data = (long) ft;
#if FSM_TIMER_DEBUG
- if (ft->fi->debug) {
- char str[40];
- sprintf(str, "FsmInitTimer %lx", (long) ft);
- ft->fi->printdebug(ft->fi, str);
- }
+ if (ft->fi->debug)
+ ft->fi->printdebug(ft->fi, "FsmInitTimer %lx", (long) ft);
#endif
init_timer(&ft->tl);
}
@@ -139,11 +136,8 @@ void
FsmDelTimer(struct FsmTimer *ft, int where)
{
#if FSM_TIMER_DEBUG
- if (ft->fi->debug) {
- char str[40];
- sprintf(str, "FsmDelTimer %lx %d", (long) ft, where);
- ft->fi->printdebug(ft->fi, str);
- }
+ if (ft->fi->debug)
+ ft->fi->printdebug(ft->fi, "FsmDelTimer %lx %d", (long) ft, where);
#endif
del_timer(&ft->tl);
}
@@ -154,11 +148,9 @@ FsmAddTimer(struct FsmTimer *ft,
{
#if FSM_TIMER_DEBUG
- if (ft->fi->debug) {
- char str[40];
- sprintf(str, "FsmAddTimer %lx %d %d", (long) ft, millisec, where);
- ft->fi->printdebug(ft->fi, str);
- }
+ if (ft->fi->debug)
+ ft->fi->printdebug(ft->fi, "FsmAddTimer %lx %d %d",
+ (long) ft, millisec, where);
#endif
if (ft->tl.next || ft->tl.prev) {
@@ -180,11 +172,9 @@ FsmRestartTimer(struct FsmTimer *ft,
{
#if FSM_TIMER_DEBUG
- if (ft->fi->debug) {
- char str[40];
- sprintf(str, "FsmRestartTimer %lx %d %d", (long) ft, millisec, where);
- ft->fi->printdebug(ft->fi, str);
- }
+ if (ft->fi->debug)
+ ft->fi->printdebug(ft->fi, "FsmRestartTimer %lx %d %d",
+ (long) ft, millisec, where);
#endif
if (ft->tl.next || ft->tl.prev)
@@ -195,24 +185,3 @@ FsmRestartTimer(struct FsmTimer *ft,
ft->tl.expires = jiffies + (millisec * HZ) / 1000;
add_timer(&ft->tl);
}
-
-void
-jiftime(char *s, long mark)
-{
- s += 8;
-
- *s-- = '\0';
- *s-- = mark % 10 + '0';
- mark /= 10;
- *s-- = mark % 10 + '0';
- mark /= 10;
- *s-- = '.';
- *s-- = mark % 10 + '0';
- mark /= 10;
- *s-- = mark % 6 + '0';
- mark /= 6;
- *s-- = ':';
- *s-- = mark % 10 + '0';
- mark /= 10;
- *s-- = mark % 10 + '0';
-}
diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c
index c42a2bb56..b649c55f4 100644
--- a/drivers/isdn/hisax/hfc_2bds0.c
+++ b/drivers/isdn/hisax/hfc_2bds0.c
@@ -1,4 +1,4 @@
-/* $Id: hfc_2bds0.c,v 1.3 1998/02/12 23:07:22 keil Exp $
+/* $Id: hfc_2bds0.c,v 1.8 1998/11/15 23:54:40 keil Exp $
*
* specific routines for CCD's HFC 2BDS0
*
@@ -6,6 +6,22 @@
*
*
* $Log: hfc_2bds0.c,v $
+ * Revision 1.8 1998/11/15 23:54:40 keil
+ * changes from 2.0
+ *
+ * Revision 1.7 1998/09/30 22:24:45 keil
+ * Fix missing line in setstack*
+ *
+ * Revision 1.6 1998/08/13 23:36:26 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 1.5 1998/06/27 22:52:58 keil
+ * make 16.3c working with 3.0
+ *
+ * Revision 1.4 1998/05/25 12:57:52 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
* Revision 1.3 1998/02/12 23:07:22 keil
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
@@ -46,11 +62,8 @@ ReadReg(struct IsdnCardState *cs, int data, u_char reg)
}
ret = bytein(cs->hw.hfcD.addr);
#if HFC_REG_DEBUG
- if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2)) {
- char tmp[32];
- sprintf(tmp, "t3c RD %02x %02x", reg, ret);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2))
+ debugl1(cs, "t3c RD %02x %02x", reg, ret);
#endif
} else
ret = bytein(cs->hw.hfcD.addr | 1);
@@ -67,11 +80,8 @@ WriteReg(struct IsdnCardState *cs, int data, u_char reg, u_char value)
if (data)
byteout(cs->hw.hfcD.addr, value);
#if HFC_REG_DEBUG
- if (cs->debug & L1_DEB_HSCX_FIFO && (data != HFCD_DATA_NODEB)) {
- char tmp[16];
- sprintf(tmp, "t3c W%c %02x %02x", data ? 'D' : 'C', reg, value);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_HSCX_FIFO && (data != HFCD_DATA_NODEB))
+ debugl1(cs, "t3c W%c %02x %02x", data ? 'D' : 'C', reg, value);
#endif
}
@@ -227,7 +237,6 @@ static struct sk_buff
int chksum;
long flags;
u_char stat, cip;
- char tmp[64];
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
debugl1(cs, "hfc_empty_fifo");
@@ -283,11 +292,9 @@ static struct sk_buff
WaitNoBusy(cs);
stat = ReadReg(cs, HFCD_DATA, cip);
sti();
- if (cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "hfc_empty_fifo %d chksum %x stat %x",
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x",
bcs->channel, chksum, stat);
- debugl1(cs, tmp);
- }
if (stat) {
debugl1(cs, "FIFO CRC error");
dev_kfree_skb(skb);
@@ -315,14 +322,11 @@ hfc_fill_fifo(struct BCState *bcs)
int idx, fcnt;
int count;
u_char cip;
- char tmp[64];
-
- if (!bcs->hw.hfc.tx_skb)
+ if (!bcs->tx_skb)
return;
- if (bcs->hw.hfc.tx_skb->len <= 0)
+ if (bcs->tx_skb->len <= 0)
return;
-
save_flags(flags);
cli();
SelFiFo(cs, HFCB_SEND | HFCB_CHANNEL(bcs->channel));
@@ -335,12 +339,10 @@ hfc_fill_fifo(struct BCState *bcs)
bcs->hw.hfc.f2 = ReadReg(cs, HFCD_DATA, cip);
bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_CHANNEL(bcs->channel));
sti();
- if (cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)",
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)",
bcs->channel, bcs->hw.hfc.f1, bcs->hw.hfc.f2,
bcs->hw.hfc.send[bcs->hw.hfc.f1]);
- debugl1(cs, tmp);
- }
fcnt = bcs->hw.hfc.f1 - bcs->hw.hfc.f2;
if (fcnt < 0)
fcnt += 32;
@@ -351,13 +353,11 @@ hfc_fill_fifo(struct BCState *bcs)
return;
}
count = GetFreeFifoBytes_B(bcs);
- if (cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "hfc_fill_fifo %d count(%d/%d),%lx",
- bcs->channel, bcs->hw.hfc.tx_skb->len,
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "hfc_fill_fifo %d count(%ld/%d),%lx",
+ bcs->channel, bcs->tx_skb->len,
count, current->state);
- debugl1(cs, tmp);
- }
- if (count < bcs->hw.hfc.tx_skb->len) {
+ if (count < bcs->tx_skb->len) {
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfc_fill_fifo no fifo mem");
restore_flags(flags);
@@ -368,26 +368,26 @@ hfc_fill_fifo(struct BCState *bcs)
cli();
WaitForBusy(cs);
WaitNoBusy(cs);
- WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->hw.hfc.tx_skb->data[idx++]);
- while (idx < bcs->hw.hfc.tx_skb->len) {
+ WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx++]);
+ while (idx < bcs->tx_skb->len) {
cli();
if (!WaitNoBusy(cs))
break;
- WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->hw.hfc.tx_skb->data[idx]);
+ WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx]);
sti();
idx++;
}
- if (idx != bcs->hw.hfc.tx_skb->len) {
+ if (idx != bcs->tx_skb->len) {
sti();
debugl1(cs, "FIFO Send BUSY error");
printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel);
} else {
- bcs->tx_cnt -= bcs->hw.hfc.tx_skb->len;
+ bcs->tx_cnt -= bcs->tx_skb->len;
if (bcs->st->lli.l1writewakeup &&
- (PACKET_NOACK != bcs->hw.hfc.tx_skb->pkt_type))
- bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hfc.tx_skb->len);
- dev_kfree_skb(bcs->hw.hfc.tx_skb);
- bcs->hw.hfc.tx_skb = NULL;
+ (PACKET_NOACK != bcs->tx_skb->pkt_type))
+ bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
+ dev_kfree_skb(bcs->tx_skb);
+ bcs->tx_skb = NULL;
}
WaitForBusy(cs);
cli();
@@ -404,15 +404,12 @@ static void
hfc_send_data(struct BCState *bcs)
{
struct IsdnCardState *cs = bcs->cs;
- char tmp[32];
if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
hfc_fill_fifo(bcs);
test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
- } else {
- sprintf(tmp,"send_data %d blocked", bcs->channel);
- debugl1(cs, tmp);
- }
+ } else
+ debugl1(cs,"send_data %d blocked", bcs->channel);
}
void
@@ -424,15 +421,13 @@ main_rec_2bds0(struct BCState *bcs)
u_char f1, f2, cip;
int receive, count = 5;
struct sk_buff *skb;
- char tmp[64];
save_flags(flags);
Begin:
count--;
cli();
if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
- sprintf(tmp,"rec_data %d blocked", bcs->channel);
- debugl1(cs, tmp);
+ debugl1(cs,"rec_data %d blocked", bcs->channel);
restore_flags(flags);
return;
}
@@ -445,11 +440,9 @@ main_rec_2bds0(struct BCState *bcs)
f2 = ReadReg(cs, HFCD_DATA, cip);
sti();
if (f1 != f2) {
- if (cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "hfc rec %d f1(%d) f2(%d)",
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "hfc rec %d f1(%d) f2(%d)",
bcs->channel, f1, f2);
- debugl1(cs, tmp);
- }
cli();
z1 = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_REC | HFCB_CHANNEL(bcs->channel));
z2 = ReadZReg(cs, HFCB_FIFO | HFCB_Z2 | HFCB_REC | HFCB_CHANNEL(bcs->channel));
@@ -458,11 +451,9 @@ main_rec_2bds0(struct BCState *bcs)
if (rcnt < 0)
rcnt += cs->hw.hfcD.bfifosize;
rcnt++;
- if (cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
bcs->channel, z1, z2, rcnt);
- debugl1(cs, tmp);
- }
if ((skb = hfc_empty_fifo(bcs, rcnt))) {
cli();
skb_queue_tail(&bcs->rqueue, skb);
@@ -490,12 +481,9 @@ mode_2bs0(struct BCState *bcs, int mode, int bc)
{
struct IsdnCardState *cs = bcs->cs;
- if (cs->debug & L1_DEB_HSCX) {
- char tmp[40];
- sprintf(tmp, "HFCD bchannel mode %d bchan %d/%d",
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "HFCD bchannel mode %d bchan %d/%d",
mode, bc, bcs->channel);
- debugl1(cs, tmp);
- }
bcs->mode = mode;
bcs->channel = bc;
switch (mode) {
@@ -543,122 +531,99 @@ hfc_l2l1(struct PStack *st, int pr, void *arg)
long flags;
switch (pr) {
- case (PH_DATA_REQ):
+ case (PH_DATA | REQUEST):
save_flags(flags);
cli();
- if (st->l1.bcs->hw.hfc.tx_skb) {
+ if (st->l1.bcs->tx_skb) {
skb_queue_tail(&st->l1.bcs->squeue, skb);
restore_flags(flags);
} else {
- st->l1.bcs->hw.hfc.tx_skb = skb;
+ st->l1.bcs->tx_skb = skb;
/* test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
*/ st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
restore_flags(flags);
}
break;
- case (PH_PULL_IND):
- if (st->l1.bcs->hw.hfc.tx_skb) {
+ case (PH_PULL | INDICATION):
+ if (st->l1.bcs->tx_skb) {
printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
break;
}
save_flags(flags);
cli();
/* test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-*/ st->l1.bcs->hw.hfc.tx_skb = skb;
+*/ st->l1.bcs->tx_skb = skb;
st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
restore_flags(flags);
break;
- case (PH_PULL_REQ):
- if (!st->l1.bcs->hw.hfc.tx_skb) {
+ case (PH_PULL | REQUEST):
+ if (!st->l1.bcs->tx_skb) {
test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
- st->l1.l1l2(st, PH_PULL_CNF, NULL);
+ st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
} else
test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
break;
+ case (PH_ACTIVATE | REQUEST):
+ test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+ mode_2bs0(st->l1.bcs, st->l1.mode, st->l1.bc);
+ l1_msg_b(st, pr, arg);
+ break;
+ case (PH_DEACTIVATE | REQUEST):
+ l1_msg_b(st, pr, arg);
+ break;
+ case (PH_DEACTIVATE | CONFIRM):
+ test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+ test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ mode_2bs0(st->l1.bcs, 0, st->l1.bc);
+ st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+ break;
}
}
void
close_2bs0(struct BCState *bcs)
{
- struct sk_buff *skb;
-
- mode_2bs0(bcs, 0, 0);
+ mode_2bs0(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
- while ((skb = skb_dequeue(&bcs->rqueue))) {
- dev_kfree_skb(skb);
- }
- while ((skb = skb_dequeue(&bcs->squeue))) {
- dev_kfree_skb(skb);
- }
- if (bcs->hw.hfc.tx_skb) {
- dev_kfree_skb(bcs->hw.hfc.tx_skb);
- bcs->hw.hfc.tx_skb = NULL;
+ discard_queue(&bcs->rqueue);
+ discard_queue(&bcs->squeue);
+ if (bcs->tx_skb) {
+ dev_kfree_skb(bcs->tx_skb);
+ bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
}
}
}
static int
-open_hfcstate(struct IsdnCardState *cs,
- int bc)
+open_hfcstate(struct IsdnCardState *cs, struct BCState *bcs)
{
- struct BCState *bcs = cs->bcs + bc;
-
if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
skb_queue_head_init(&bcs->rqueue);
skb_queue_head_init(&bcs->squeue);
}
- bcs->hw.hfc.tx_skb = NULL;
+ bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->event = 0;
bcs->tx_cnt = 0;
return (0);
}
-static void
-hfc_manl1(struct PStack *st, int pr,
- void *arg)
-{
- switch (pr) {
- case (PH_ACTIVATE_REQ):
- test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
- mode_2bs0(st->l1.bcs, st->l1.mode, st->l1.bc);
- st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
- break;
- case (PH_DEACTIVATE_REQ):
- if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
- mode_2bs0(st->l1.bcs, 0, 0);
- test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
- break;
- }
-}
-
int
setstack_2b(struct PStack *st, struct BCState *bcs)
{
- if (open_hfcstate(st->l1.hardware, bcs->channel))
+ bcs->channel = st->l1.bc;
+ if (open_hfcstate(st->l1.hardware, bcs))
return (-1);
st->l1.bcs = bcs;
st->l2.l2l1 = hfc_l2l1;
- st->ma.manl1 = hfc_manl1;
setstack_manager(st);
bcs->st = st;
+ setstack_l1_B(st);
return (0);
}
static void
-manl1_msg(struct IsdnCardState *cs, int msg, void *arg) {
- struct PStack *st;
-
- st = cs->stlist;
- while (st) {
- st->ma.manl1(st, msg, arg);
- st = st->next;
- }
-}
-
-static void
hfcd_bh(struct IsdnCardState *cs)
{
/* struct PStack *stptr;
@@ -671,7 +636,7 @@ hfcd_bh(struct IsdnCardState *cs)
debugl1(cs, "D-Channel Busy cleared");
stptr = cs->stlist;
while (stptr != NULL) {
- stptr->l1.l1l2(stptr, PH_PAUSE_CNF, NULL);
+ stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
stptr = stptr->next;
}
}
@@ -679,19 +644,19 @@ hfcd_bh(struct IsdnCardState *cs)
if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
switch (cs->ph_state) {
case (0):
- manl1_msg(cs, PH_RESET_IND, NULL);
+ l1_msg(cs, HW_RESET | INDICATION, NULL);
break;
case (3):
- manl1_msg(cs, PH_DEACT_IND, NULL);
+ l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
break;
case (8):
- manl1_msg(cs, PH_RSYNC_IND, NULL);
+ l1_msg(cs, HW_RSYNC | INDICATION, NULL);
break;
case (6):
- manl1_msg(cs, PH_INFO2_IND, NULL);
+ l1_msg(cs, HW_INFO2 | INDICATION, NULL);
break;
case (7):
- manl1_msg(cs, PH_I4_P8_IND, NULL);
+ l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
break;
default:
break;
@@ -722,7 +687,6 @@ int receive_dmsg(struct IsdnCardState *cs)
int chksum;
int count=5;
u_char *ptr;
- char tmp[64];
save_flags(flags);
cli();
@@ -745,11 +709,9 @@ int receive_dmsg(struct IsdnCardState *cs)
if (rcnt < 0)
rcnt += cs->hw.hfcD.dfifosize;
rcnt++;
- if (cs->debug & L1_DEB_ISAC) {
- sprintf(tmp, "hfcd recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)",
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "hfcd recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)",
f1, f2, z1, z2, rcnt);
- debugl1(cs, tmp);
- }
sti();
idx = 0;
cip = HFCD_FIFO | HFCD_FIFO_OUT | HFCD_REC;
@@ -796,11 +758,9 @@ int receive_dmsg(struct IsdnCardState *cs)
WaitNoBusy(cs);
stat = ReadReg(cs, HFCD_DATA, cip);
sti();
- if (cs->debug & L1_DEB_ISAC) {
- sprintf(tmp, "empty_dfifo chksum %x stat %x",
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "empty_dfifo chksum %x stat %x",
chksum, stat);
- debugl1(cs, tmp);
- }
if (stat) {
debugl1(cs, "FIFO CRC error");
dev_kfree_skb(skb);
@@ -837,7 +797,6 @@ hfc_fill_dfifo(struct IsdnCardState *cs)
int idx, fcnt;
int count;
u_char cip;
- char tmp[64];
if (!cs->tx_skb)
return;
@@ -855,12 +814,10 @@ hfc_fill_dfifo(struct IsdnCardState *cs)
cs->hw.hfcD.f2 = ReadReg(cs, HFCD_DATA, cip) & 0xf;
cs->hw.hfcD.send[cs->hw.hfcD.f1] = ReadZReg(cs, HFCD_FIFO | HFCD_Z1 | HFCD_SEND);
sti();
- if (cs->debug & L1_DEB_ISAC) {
- sprintf(tmp, "hfc_fill_Dfifo f1(%d) f2(%d) z1(%x)",
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "hfc_fill_Dfifo f1(%d) f2(%d) z1(%x)",
cs->hw.hfcD.f1, cs->hw.hfcD.f2,
cs->hw.hfcD.send[cs->hw.hfcD.f1]);
- debugl1(cs, tmp);
- }
fcnt = cs->hw.hfcD.f1 - cs->hw.hfcD.f2;
if (fcnt < 0)
fcnt += 16;
@@ -871,11 +828,9 @@ hfc_fill_dfifo(struct IsdnCardState *cs)
return;
}
count = GetFreeFifoBytes_D(cs);
- if (cs->debug & L1_DEB_ISAC) {
- sprintf(tmp, "hfc_fill_Dfifo count(%d/%d)",
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "hfc_fill_Dfifo count(%ld/%d)",
cs->tx_skb->len, count);
- debugl1(cs, tmp);
- }
if (count < cs->tx_skb->len) {
if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "hfc_fill_Dfifo no fifo mem");
@@ -929,24 +884,19 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val)
{
u_char exval;
struct BCState *bcs;
- char tmp[32];
int count=15;
long flags;
- if (cs->debug & L1_DEB_ISAC) {
- sprintf(tmp, "HFCD irq %x %s", val,
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "HFCD irq %x %s", val,
test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
"locked" : "unlocked");
- debugl1(cs, tmp);
- }
val &= cs->hw.hfcD.int_m1;
if (val & 0x40) { /* TE state machine irq */
exval = cs->readisac(cs, HFCD_STATES) & 0xf;
- if (cs->debug & L1_DEB_ISAC) {
- sprintf(tmp, "ph_state chg %d->%d", cs->ph_state,
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "ph_state chg %d->%d", cs->ph_state,
exval);
- debugl1(cs, tmp);
- }
cs->ph_state = exval;
sched_event_D(cs, D_L1STATECHANGE);
val &= ~0x40;
@@ -983,23 +933,19 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val)
if (cs->debug)
debugl1(cs, "hfcd spurious 0x01 IRQ");
} else {
- if (bcs->hw.hfc.tx_skb) {
+ if (bcs->tx_skb) {
if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
hfc_fill_fifo(bcs);
test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
- } else {
- sprintf(tmp,"fill_data %d blocked", bcs->channel);
- debugl1(cs, tmp);
- }
+ } else
+ debugl1(cs,"fill_data %d blocked", bcs->channel);
} else {
- if ((bcs->hw.hfc.tx_skb = skb_dequeue(&bcs->squeue))) {
+ if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
hfc_fill_fifo(bcs);
test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
- } else {
- sprintf(tmp,"fill_data %d blocked", bcs->channel);
- debugl1(cs, tmp);
- }
+ } else
+ debugl1(cs,"fill_data %d blocked", bcs->channel);
} else {
hfc_sched_event(bcs, B_XMTBUFREADY);
}
@@ -1011,23 +957,19 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val)
if (cs->debug)
debugl1(cs, "hfcd spurious 0x02 IRQ");
} else {
- if (bcs->hw.hfc.tx_skb) {
+ if (bcs->tx_skb) {
if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
hfc_fill_fifo(bcs);
test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
- } else {
- sprintf(tmp,"fill_data %d blocked", bcs->channel);
- debugl1(cs, tmp);
- }
+ } else
+ debugl1(cs,"fill_data %d blocked", bcs->channel);
} else {
- if ((bcs->hw.hfc.tx_skb = skb_dequeue(&bcs->squeue))) {
+ if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
hfc_fill_fifo(bcs);
test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
- } else {
- sprintf(tmp,"fill_data %d blocked", bcs->channel);
- debugl1(cs, tmp);
- }
+ } else
+ debugl1(cs,"fill_data %d blocked", bcs->channel);
} else {
hfc_sched_event(bcs, B_XMTBUFREADY);
}
@@ -1042,7 +984,7 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val)
del_timer(&cs->dbusytimer);
if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
sched_event_D(cs, D_CLEARBUSY);
- if (cs->tx_skb) {
+ if (cs->tx_skb)
if (cs->tx_skb->len) {
if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
hfc_fill_dfifo(cs);
@@ -1056,7 +998,6 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val)
cs->tx_cnt = 0;
cs->tx_skb = NULL;
}
- }
if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
cs->tx_cnt = 0;
if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
@@ -1072,10 +1013,8 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val)
if (cs->hw.hfcD.int_s1 && count--) {
val = cs->hw.hfcD.int_s1;
cs->hw.hfcD.int_s1 = 0;
- if (cs->debug & L1_DEB_ISAC) {
- sprintf(tmp, "HFCD irq %x loop %d", val, 15-count);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "HFCD irq %x loop %d", val, 15-count);
} else
val = 0;
restore_flags(flags);
@@ -1083,13 +1022,17 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val)
}
static void
-HFCD_l2l1(struct PStack *st, int pr, void *arg)
+HFCD_l1hw(struct PStack *st, int pr, void *arg)
{
struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
struct sk_buff *skb = arg;
- char str[64];
+
switch (pr) {
- case (PH_DATA_REQ):
+ case (PH_DATA | REQUEST):
+ if (cs->debug & DEB_DLOG_HEX)
+ LogFrame(cs, skb->data, skb->len);
+ if (cs->debug & DEB_DLOG_VERBOSE)
+ dlogframe(cs, skb, 0);
if (cs->tx_skb) {
skb_queue_tail(&cs->sq, skb);
#ifdef L2FRAME_DEBUG /* psa */
@@ -1097,12 +1040,6 @@ HFCD_l2l1(struct PStack *st, int pr, void *arg)
Logl2Frame(cs, skb, "PH_DATA Queued", 0);
#endif
} else {
- if ((cs->dlogflag) && (!(skb->data[2] & 1))) { /* I-FRAME */
- LogFrame(cs, skb->data, skb->len);
- sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
- dlogframe(cs, skb->data + 4, skb->len - 4,
- str);
- }
cs->tx_skb = skb;
cs->tx_cnt = 0;
#ifdef L2FRAME_DEBUG /* psa */
@@ -1117,19 +1054,17 @@ HFCD_l2l1(struct PStack *st, int pr, void *arg)
}
break;
- case (PH_PULL_IND):
+ case (PH_PULL | INDICATION):
if (cs->tx_skb) {
if (cs->debug & L1_DEB_WARN)
debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
skb_queue_tail(&cs->sq, skb);
break;
}
- if ((cs->dlogflag) && (!(skb->data[2] & 1))) { /* I-FRAME */
+ if (cs->debug & DEB_DLOG_HEX)
LogFrame(cs, skb->data, skb->len);
- sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
- dlogframe(cs, skb->data + 4, skb->len - 4,
- str);
- }
+ if (cs->debug & DEB_DLOG_VERBOSE)
+ dlogframe(cs, skb, 0);
cs->tx_skb = skb;
cs->tx_cnt = 0;
#ifdef L2FRAME_DEBUG /* psa */
@@ -1142,47 +1077,39 @@ HFCD_l2l1(struct PStack *st, int pr, void *arg)
} else
debugl1(cs, "hfc_fill_dfifo blocked");
break;
- case (PH_PULL_REQ):
+ case (PH_PULL | REQUEST):
#ifdef L2FRAME_DEBUG /* psa */
if (cs->debug & L1_DEB_LAPD)
debugl1(cs, "-> PH_REQUEST_PULL");
#endif
if (!cs->tx_skb) {
test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
- st->l1.l1l2(st, PH_PULL_CNF, NULL);
+ st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
} else
test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
break;
- }
-}
-
-void
-hfcd_l1cmd(struct IsdnCardState *cs, int msg, void *arg)
-{
- char tmp[32];
- switch(msg) {
- case PH_RESET_REQ:
+ case (HW_RESET | REQUEST):
cs->writeisac(cs, HFCD_STATES, HFCD_LOAD_STATE | 3); /* HFC ST 3 */
udelay(6);
cs->writeisac(cs, HFCD_STATES, 3); /* HFC ST 2 */
cs->hw.hfcD.mst_m |= HFCD_MASTER;
cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION);
- manl1_msg(cs, PH_POWERUP_CNF, NULL);
+ l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
break;
- case PH_ENABLE_REQ:
+ case (HW_ENABLE | REQUEST):
cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION);
break;
- case PH_DEACT_ACK:
+ case (HW_DEACTIVATE | REQUEST):
cs->hw.hfcD.mst_m &= ~HFCD_MASTER;
cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
break;
- case PH_INFO3_REQ:
+ case (HW_INFO3 | REQUEST):
cs->hw.hfcD.mst_m |= HFCD_MASTER;
cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
break;
#if 0
- case PH_TESTLOOP_REQ:
+ case (HW_TESTLOOP | REQUEST):
u_char val = 0;
if (1 & (int) arg)
val |= 0x0c;
@@ -1208,10 +1135,8 @@ hfcd_l1cmd(struct IsdnCardState *cs, int msg, void *arg)
break;
#endif
default:
- if (cs->debug & L1_DEB_WARN) {
- sprintf(tmp, "hfcd_l1cmd unknown %4x", msg);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "hfcd_l1hw unknown pr %4x", pr);
break;
}
}
@@ -1219,7 +1144,7 @@ hfcd_l1cmd(struct IsdnCardState *cs, int msg, void *arg)
void
setstack_hfcd(struct PStack *st, struct IsdnCardState *cs)
{
- st->l2.l2l1 = HFCD_l2l1;
+ st->l1.l1hw = HFCD_l1hw;
}
static void
@@ -1234,7 +1159,7 @@ hfc_dbusy_timer(struct IsdnCardState *cs)
stptr = cs->stlist;
while (stptr != NULL) {
- stptr->l1.l1l2(stptr, PH_PAUSE_IND, NULL);
+ stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
stptr = stptr->next;
}
}
@@ -1260,7 +1185,6 @@ __initfunc(void
init2bds0(struct IsdnCardState *cs))
{
cs->setstack_d = setstack_hfcd;
- cs->l1cmd = hfcd_l1cmd;
cs->dbusytimer.function = (void *) hfc_dbusy_timer;
cs->dbusytimer.data = (long) cs;
init_timer(&cs->dbusytimer);
diff --git a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c
index 2d9ce5bd5..26d47b936 100644
--- a/drivers/isdn/hisax/hfc_2bs0.c
+++ b/drivers/isdn/hisax/hfc_2bs0.c
@@ -1,11 +1,24 @@
-/* $Id: hfc_2bs0.c,v 1.4 1998/02/12 23:07:29 keil Exp $
+/* $Id: hfc_2bs0.c,v 1.8 1998/11/15 23:54:43 keil Exp $
* specific routines for CCD's HFC 2BS0
*
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
*
*
* $Log: hfc_2bs0.c,v $
+ * Revision 1.8 1998/11/15 23:54:43 keil
+ * changes from 2.0
+ *
+ * Revision 1.7 1998/09/30 22:24:46 keil
+ * Fix missing line in setstack*
+ *
+ * Revision 1.6 1998/08/13 23:36:28 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 1.5 1998/05/25 12:57:54 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
* Revision 1.4 1998/02/12 23:07:29 keil
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
@@ -109,7 +122,6 @@ hfc_clear_fifo(struct BCState *bcs)
int idx, cnt;
int rcnt, z1, z2;
u_char cip, f1, f2;
- char tmp[64];
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
debugl1(cs, "hfc_clear_fifo");
@@ -129,21 +141,17 @@ hfc_clear_fifo(struct BCState *bcs)
z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
cnt = 32;
while (((f1 != f2) || (z1 != z2)) && cnt--) {
- if (cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "hfc clear %d f1(%d) f2(%d)",
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "hfc clear %d f1(%d) f2(%d)",
bcs->channel, f1, f2);
- debugl1(cs, tmp);
- }
rcnt = z1 - z2;
if (rcnt < 0)
rcnt += cs->hw.hfc.fifosize;
if (rcnt)
rcnt++;
- if (cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "hfc clear %d z1(%x) z2(%x) cnt(%d)",
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "hfc clear %d z1(%x) z2(%x) cnt(%d)",
bcs->channel, z1, z2, rcnt);
- debugl1(cs, tmp);
- }
cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
idx = 0;
while ((idx < rcnt) && WaitNoBusy(cs)) {
@@ -180,7 +188,6 @@ hfc_empty_fifo(struct BCState *bcs, int count)
int idx;
int chksum;
u_char stat, cip;
- char tmp[64];
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
debugl1(cs, "hfc_empty_fifo");
@@ -235,11 +242,9 @@ hfc_empty_fifo(struct BCState *bcs, int count)
chksum += cs->BC_Read_Reg(cs, HFC_DATA, cip);
WaitNoBusy(cs);
stat = cs->BC_Read_Reg(cs, HFC_DATA, cip);
- if (cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "hfc_empty_fifo %d chksum %x stat %x",
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x",
bcs->channel, chksum, stat);
- debugl1(cs, tmp);
- }
if (stat) {
debugl1(cs, "FIFO CRC error");
dev_kfree_skb(skb);
@@ -261,11 +266,10 @@ hfc_fill_fifo(struct BCState *bcs)
int idx, fcnt;
int count;
u_char cip;
- char tmp[64];
- if (!bcs->hw.hfc.tx_skb)
+ if (!bcs->tx_skb)
return;
- if (bcs->hw.hfc.tx_skb->len <= 0)
+ if (bcs->tx_skb->len <= 0)
return;
save_flags(flags);
@@ -281,12 +285,10 @@ hfc_fill_fifo(struct BCState *bcs)
WaitNoBusy(cs);
bcs->hw.hfc.f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(bcs, HFC_Z1 | HFC_SEND | HFC_CHANNEL(bcs->channel));
- if (cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)",
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)",
bcs->channel, bcs->hw.hfc.f1, bcs->hw.hfc.f2,
bcs->hw.hfc.send[bcs->hw.hfc.f1]);
- debugl1(cs, tmp);
- }
fcnt = bcs->hw.hfc.f1 - bcs->hw.hfc.f2;
if (fcnt < 0)
fcnt += 32;
@@ -297,13 +299,11 @@ hfc_fill_fifo(struct BCState *bcs)
return;
}
count = GetFreeFifoBytes(bcs);
- if (cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "hfc_fill_fifo %d count(%d/%d)",
- bcs->channel, bcs->hw.hfc.tx_skb->len,
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "hfc_fill_fifo %d count(%ld/%d)",
+ bcs->channel, bcs->tx_skb->len,
count);
- debugl1(cs, tmp);
- }
- if (count < bcs->hw.hfc.tx_skb->len) {
+ if (count < bcs->tx_skb->len) {
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfc_fill_fifo no fifo mem");
restore_flags(flags);
@@ -311,18 +311,18 @@ hfc_fill_fifo(struct BCState *bcs)
}
cip = HFC_CIP | HFC_FIFO_IN | HFC_SEND | HFC_CHANNEL(bcs->channel);
idx = 0;
- while ((idx < bcs->hw.hfc.tx_skb->len) && WaitNoBusy(cs))
- cs->BC_Write_Reg(cs, HFC_DATA_NODEB, cip, bcs->hw.hfc.tx_skb->data[idx++]);
- if (idx != bcs->hw.hfc.tx_skb->len) {
+ while ((idx < bcs->tx_skb->len) && WaitNoBusy(cs))
+ cs->BC_Write_Reg(cs, HFC_DATA_NODEB, cip, bcs->tx_skb->data[idx++]);
+ if (idx != bcs->tx_skb->len) {
debugl1(cs, "FIFO Send BUSY error");
printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel);
} else {
- count = bcs->hw.hfc.tx_skb->len;
+ count = bcs->tx_skb->len;
bcs->tx_cnt -= count;
- if (PACKET_NOACK == bcs->hw.hfc.tx_skb->pkt_type)
+ if (PACKET_NOACK == bcs->tx_skb->pkt_type)
count = -1;
- dev_kfree_skb(bcs->hw.hfc.tx_skb);
- bcs->hw.hfc.tx_skb = NULL;
+ dev_kfree_skb(bcs->tx_skb);
+ bcs->tx_skb = NULL;
WaitForBusy(cs);
WaitNoBusy(cs);
cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F1_INC | HFC_SEND | HFC_CHANNEL(bcs->channel));
@@ -343,7 +343,6 @@ main_irq_hfc(struct BCState *bcs)
u_char f1, f2, cip;
int receive, transmit, count = 5;
struct sk_buff *skb;
- char tmp[64];
save_flags(flags);
Begin:
@@ -360,11 +359,9 @@ main_irq_hfc(struct BCState *bcs)
WaitNoBusy(cs);
f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
if (f1 != f2) {
- if (cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "hfc rec %d f1(%d) f2(%d)",
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "hfc rec %d f1(%d) f2(%d)",
bcs->channel, f1, f2);
- debugl1(cs, tmp);
- }
WaitForBusy(cs);
z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
@@ -372,11 +369,9 @@ main_irq_hfc(struct BCState *bcs)
if (rcnt < 0)
rcnt += cs->hw.hfc.fifosize;
rcnt++;
- if (cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
bcs->channel, z1, z2, rcnt);
- debugl1(cs, tmp);
- }
/* sti(); */
if ((skb = hfc_empty_fifo(bcs, rcnt))) {
skb_queue_tail(&bcs->rqueue, skb);
@@ -388,14 +383,14 @@ main_irq_hfc(struct BCState *bcs)
restore_flags(flags);
udelay(1);
cli();
- if (bcs->hw.hfc.tx_skb) {
+ if (bcs->tx_skb) {
transmit = 1;
test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
hfc_fill_fifo(bcs);
if (test_bit(BC_FLG_BUSY, &bcs->Flag))
transmit = 0;
} else {
- if ((bcs->hw.hfc.tx_skb = skb_dequeue(&bcs->squeue))) {
+ if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
transmit = 1;
test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
hfc_fill_fifo(bcs);
@@ -417,13 +412,11 @@ mode_hfc(struct BCState *bcs, int mode, int bc)
{
struct IsdnCardState *cs = bcs->cs;
- if (cs->debug & L1_DEB_HSCX) {
- char tmp[40];
- sprintf(tmp, "HFC 2BS0 mode %d bchan %d/%d",
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "HFC 2BS0 mode %d bchan %d/%d",
mode, bc, bcs->channel);
- debugl1(cs, tmp);
- }
bcs->mode = mode;
+ bcs->channel = bc;
switch (mode) {
case (L1_MODE_NULL):
@@ -468,57 +461,66 @@ hfc_l2l1(struct PStack *st, int pr, void *arg)
long flags;
switch (pr) {
- case (PH_DATA_REQ):
+ case (PH_DATA | REQUEST):
save_flags(flags);
cli();
- if (st->l1.bcs->hw.hfc.tx_skb) {
+ if (st->l1.bcs->tx_skb) {
skb_queue_tail(&st->l1.bcs->squeue, skb);
restore_flags(flags);
} else {
- st->l1.bcs->hw.hfc.tx_skb = skb;
+ st->l1.bcs->tx_skb = skb;
test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
restore_flags(flags);
}
break;
- case (PH_PULL_IND):
- if (st->l1.bcs->hw.hfc.tx_skb) {
+ case (PH_PULL | INDICATION):
+ if (st->l1.bcs->tx_skb) {
printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
break;
}
save_flags(flags);
cli();
test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
- st->l1.bcs->hw.hfc.tx_skb = skb;
+ st->l1.bcs->tx_skb = skb;
st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
restore_flags(flags);
break;
- case (PH_PULL_REQ):
- if (!st->l1.bcs->hw.hfc.tx_skb) {
+ case (PH_PULL | REQUEST):
+ if (!st->l1.bcs->tx_skb) {
test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
- st->l1.l1l2(st, PH_PULL_CNF, NULL);
+ st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
} else
test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
break;
+ case (PH_ACTIVATE | REQUEST):
+ test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+ mode_hfc(st->l1.bcs, st->l1.mode, st->l1.bc);
+ l1_msg_b(st, pr, arg);
+ break;
+ case (PH_DEACTIVATE | REQUEST):
+ l1_msg_b(st, pr, arg);
+ break;
+ case (PH_DEACTIVATE | CONFIRM):
+ test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+ test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ mode_hfc(st->l1.bcs, 0, st->l1.bc);
+ st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+ break;
}
}
+
void
close_hfcstate(struct BCState *bcs)
{
- struct sk_buff *skb;
-
- mode_hfc(bcs, 0, 0);
+ mode_hfc(bcs, 0, bcs->channel);
if (test_bit(BC_FLG_INIT, &bcs->Flag)) {
- while ((skb = skb_dequeue(&bcs->rqueue))) {
- dev_kfree_skb(skb);
- }
- while ((skb = skb_dequeue(&bcs->squeue))) {
- dev_kfree_skb(skb);
- }
- if (bcs->hw.hfc.tx_skb) {
- dev_kfree_skb(bcs->hw.hfc.tx_skb);
- bcs->hw.hfc.tx_skb = NULL;
+ discard_queue(&bcs->rqueue);
+ discard_queue(&bcs->squeue);
+ if (bcs->tx_skb) {
+ dev_kfree_skb(bcs->tx_skb);
+ bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
}
}
@@ -526,50 +528,30 @@ close_hfcstate(struct BCState *bcs)
}
static int
-open_hfcstate(struct IsdnCardState *cs,
- int bc)
+open_hfcstate(struct IsdnCardState *cs, struct BCState *bcs)
{
- struct BCState *bcs = cs->bcs + bc;
-
if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
skb_queue_head_init(&bcs->rqueue);
skb_queue_head_init(&bcs->squeue);
}
- bcs->hw.hfc.tx_skb = NULL;
+ bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->event = 0;
bcs->tx_cnt = 0;
return (0);
}
-static void
-hfc_manl1(struct PStack *st, int pr,
- void *arg)
-{
- switch (pr) {
- case (PH_ACTIVATE_REQ):
- test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
- mode_hfc(st->l1.bcs, st->l1.mode, st->l1.bc);
- st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
- break;
- case (PH_DEACTIVATE_REQ):
- if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
- mode_hfc(st->l1.bcs, 0, 0);
- test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
- break;
- }
-}
-
int
setstack_hfc(struct PStack *st, struct BCState *bcs)
{
- if (open_hfcstate(st->l1.hardware, bcs->channel))
+ bcs->channel = st->l1.bc;
+ if (open_hfcstate(st->l1.hardware, bcs))
return (-1);
st->l1.bcs = bcs;
st->l2.l2l1 = hfc_l2l1;
- st->ma.manl1 = hfc_manl1;
setstack_manager(st);
bcs->st = st;
+ setstack_l1_B(st);
return (0);
}
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 4795ada08..36cd82ee1 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -1,8 +1,48 @@
-/* $Id: hisax.h,v 2.14 1998/02/11 17:28:04 keil Exp $
+/* $Id: hisax.h,v 2.26 1998/11/15 23:54:45 keil Exp $
* Basic declarations, defines and prototypes
*
* $Log: hisax.h,v $
+ * Revision 2.26 1998/11/15 23:54:45 keil
+ * changes from 2.0
+ *
+ * Revision 2.25 1998/09/30 22:28:42 keil
+ * More work for ISAR support
+ *
+ * Revision 2.24 1998/08/20 13:50:39 keil
+ * More support for hybrid modem (not working yet)
+ *
+ * Revision 2.23 1998/08/13 23:36:31 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.22 1998/07/15 15:01:28 calle
+ * Support for AVM passive PCMCIA cards:
+ * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0
+ *
+ * Revision 2.21 1998/05/25 14:10:05 keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.20 1998/05/25 12:57:57 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.19 1998/04/15 16:39:15 keil
+ * Add S0Box and Teles PCI support
+ *
+ * Revision 2.18 1998/03/26 07:10:04 paul
+ * The jumpmatrix table in struct Fsm was an array of "int". This is not
+ * large enough for pointers to functions on Linux/Alpha (instant crash
+ * on "insmod hisax). Now there is a typedef for the pointer to function.
+ * This also prevents warnings about "incompatible pointer types".
+ *
+ * Revision 2.17 1998/03/19 13:18:43 keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
+ * Revision 2.16 1998/03/09 23:19:25 keil
+ * Changes for PCMCIA
+ *
* Revision 2.14 1998/02/11 17:28:04 keil
* Niccy PnP/PCI support
*
@@ -72,120 +112,90 @@
#include <linux/isdnif.h>
#include <linux/tty.h>
#include <linux/init.h>
+#include <linux/serialP.h>
+
+#define REQUEST 0
+#define CONFIRM 1
+#define INDICATION 2
+#define RESPONSE 3
+
+#define HW_ENABLE 0x0000
+#define HW_RESET 0x0004
+#define HW_POWERUP 0x0008
+#define HW_ACTIVATE 0x0010
+#define HW_DEACTIVATE 0x0018
+#define HW_INFO2 0x0020
+#define HW_INFO3 0x0030
+#define HW_INFO4_P8 0x0040
+#define HW_INFO4_P10 0x0048
+#define HW_RSYNC 0x0060
+#define HW_TESTLOOP 0x0070
+#define CARD_RESET 0x00F0
+#define CARD_SETIRQ 0x00F1
+#define CARD_INIT 0x00F2
+#define CARD_RELEASE 0x00F3
+#define CARD_TEST 0x00F4
+#define CARD_AUX_IND 0x00F5
+#define CARD_LOAD_FIRM 0x00F6
+
+#define PH_ACTIVATE 0x0100
+#define PH_DEACTIVATE 0x0110
+#define PH_DATA 0x0120
+#define PH_PULL 0x0130
+#define PH_TESTLOOP 0x0140
+#define PH_PAUSE 0x0150
+#define MPH_ACTIVATE 0x0180
+#define MPH_DEACTIVATE 0x0190
+#define MPH_INFORMATION 0x01A0
+
+#define DL_ESTABLISH 0x0200
+#define DL_RELEASE 0x0210
+#define DL_DATA 0x0220
+#define DL_FLUSH 0x0224
+#define DL_UNIT_DATA 0x0230
+#define MDL_ASSIGN 0x0280
+#define MDL_REMOVE 0x0284
+#define MDL_ERROR 0x0288
+#define MDL_INFO_SETUP 0x02E0
+#define MDL_INFO_CONN 0x02E4
+#define MDL_INFO_REL 0x02E8
+
+#define CC_SETUP 0x0300
+#define CC_RESUME 0x0304
+#define CC_MORE_INFO 0x0310
+#define CC_IGNORE 0x0320
+#define CC_REJECT 0x0324
+#define CC_SETUP_COMPL 0x0330
+#define CC_PROCEEDING 0x0340
+#define CC_ALERTING 0x0344
+#define CC_CONNECT 0x0350
+#define CC_CHARGE 0x0354
+#define CC_DISCONNECT 0x0360
+#define CC_RELEASE 0x0368
+#define CC_SUSPEND 0x0370
+#define CC_T303 0x0383
+#define CC_T304 0x0384
+#define CC_T305 0x0385
+#define CC_T308_1 0x0388
+#define CC_T308_2 0x0389
+#define CC_T310 0x0390
+#define CC_T313 0x0393
+#define CC_T318 0x0398
+#define CC_T319 0x0399
+#define CC_NOSETUP_RSP 0x03E0
+#define CC_SETUP_ERR 0x03E1
+#define CC_SUSPEND_ERR 0x03E2
+#define CC_RESUME_ERR 0x03E3
+#define CC_CONNECT_ERR 0x03E4
+#define CC_RELEASE_ERR 0x03E5
+#define CC_DLRL 0x03F0
+#define CC_RESTART 0x03F4
-#define PH_ACTIVATE_REQ 0x0010
-#define PH_ACTIVATE_CNF 0x0011
-#define PH_ACTIVATE_IND 0x0012
-#define PH_DEACTIVATE_REQ 0x0020
-#define PH_DEACTIVATE_CNF 0x0021
-#define PH_DEACTIVATE_IND 0x0022
-#define PH_DEACT_REQ 0x0024
-#define PH_DEACT_CNF 0x0025
-#define PH_DEACT_IND 0x0026
-#define PH_DEACT_ACK 0x0027
-#define PH_TESTLOOP_REQ 0x0030
-#define PH_PAUSE_CNF 0x0035
-#define PH_PAUSE_IND 0x0036
-#define PH_PULL_REQ 0x0038
-#define PH_PULL_CNF 0x0039
-#define PH_PULL_IND 0x003A
-#define PH_DATA_REQ 0x0040
-#define PH_DATA_IND 0x0042
-
-#define PH_INFO3_REQ 0x0008
-#define PH_INFO2_IND 0x000A
-#define PH_ENABLE_REQ 0x0004
-#define PH_RSYNC_IND 0x0006
-#define PH_RESET_REQ 0x0000
-#define PH_RESET_IND 0x0002
-#define PH_POWERUP_CNF 0x0003
-#define PH_ACTIV_REQ 0x000C
-#define PH_I4_P8_IND 0x000D
-#define PH_I4_P10_IND 0x000F
-
-#define MDL_ASSIGN_REQ 0x0050
-#define MDL_ASSIGN_IND 0x0052
-#define MDL_REMOVE_REQ 0x0054
-#define MDL_ERROR_REQ 0x0058
-#define MDL_ERROR_IND 0x005A
-#define CARD_AUX_IND 0x005E
-
-#define DL_UNIT_DATA 6
-#define CC_ESTABLISH 7
-#define DL_ESTABLISH 8
-#define DL_DATA 9
-
-#define CC_CONNECT 15
-#define DL_RELEASE 20
-#define DL_FLUSH 21
-
-#define CC_REJECT 23
-
-#define CC_SETUP_REQ 24
-#define CC_SETUP_CNF 25
-#define CC_SETUP_IND 26
-#define CC_SETUP_RSP 27
-#define CC_SETUP_COMPLETE_IND 28
-
-#define CC_DISCONNECT_REQ 29
-#define CC_DISCONNECT_IND 30
-
-#define CC_RELEASE_CNF 31
-#define CC_RELEASE_IND 32
-#define CC_RELEASE_REQ 33
-
-#define CC_REJECT_REQ 34
-
-#define CC_PROCEEDING_IND 35
-
-#define CC_DLRL 36
-#define CC_DLEST 37
-
-#define CC_ALERTING_REQ 38
-#define CC_ALERTING_IND 39
-
-#define DL_STOP 40
-#define DL_START 41
-
-#define MDL_INFO_SETUP 42
-#define MDL_INFO_CONN 43
-#define MDL_INFO_REL 44
-#define MDL_NOTEIPROC 46
-
-#define LC_ESTABLISH 47
-#define LC_RELEASE 48
-
-#define CC_INFO_CHARGE 52
-
-#define CC_MORE_INFO 53
-#define CC_IGNORE 54
-#define CC_RESTART 55
-
-
-#define CC_T303 60
-#define CC_T304 61
-#define CC_T305 62
-#define CC_T308_1 64
-#define CC_T308_2 65
-#define CC_T310 66
-#define CC_T313 67
-#define CC_T318 68
-#define CC_T319 69
-
-#define CC_NOSETUP_RSP_ERR 70
-#define CC_SETUP_ERR 71
-#define CC_CONNECT_ERR 72
-#define CC_RELEASE_ERR 73
-
-#define CARD_RESET 0x1001
-#define CARD_SETIRQ 0x1002
-#define CARD_INIT 0x1003
-#define CARD_RELEASE 0x1004
-#define CARD_TEST 0x1005
#ifdef __KERNEL__
#define MAX_DFRAME_LEN 260
+#define MAX_DFRAME_LEN_L1 300
#define HSCX_BUFMAX 4096
#define MAX_DATA_SIZE (HSCX_BUFMAX - 4)
#define MAX_DATA_MEM (HSCX_BUFMAX + 64)
@@ -193,6 +203,8 @@
#define MAX_HEADER_LEN 4
#define MAX_WINDOW 8
#define MAX_MON_FRAME 32
+#define MAX_DLOG_SPACE 2048
+#define MAX_BLOG_SPACE 256
/* #define I4L_IRQ_FLAG SA_INTERRUPT */
#define I4L_IRQ_FLAG 0
@@ -201,8 +213,12 @@
* Statemachine
*/
+struct FsmInst;
+
+typedef void (* FSMFNPTR)(struct FsmInst *, int, void *);
+
struct Fsm {
- int *jumpmatrix;
+ FSMFNPTR *jumpmatrix;
int state_count, event_count;
char **strEvent, **strState;
};
@@ -213,7 +229,7 @@ struct FsmInst {
int debug;
void *userdata;
int userint;
- void (*printdebug) (struct FsmInst *, char *);
+ void (*printdebug) (struct FsmInst *, char *, ...);
};
struct FsmNode {
@@ -249,9 +265,10 @@ struct Layer1 {
struct FsmInst l1m;
struct FsmTimer timer;
void (*l1l2) (struct PStack *, int, void *);
- void (*l1man) (struct PStack *, int, void *);
+ void (*l1hw) (struct PStack *, int, void *);
void (*l1tei) (struct PStack *, int, void *);
int mode, bc;
+ int delay;
};
#define GROUP_TEI 127
@@ -266,17 +283,20 @@ struct Layer1 {
#define FLG_ORIG 2
#define FLG_MOD128 3
#define FLG_PEND_REL 4
-#define FLG_L3_INIT 5
-#define FLG_T200_RUN 6
+#define FLG_L3_INIT 5
+#define FLG_T200_RUN 6
#define FLG_ACK_PEND 7
#define FLG_REJEXC 8
#define FLG_OWN_BUSY 9
#define FLG_PEER_BUSY 10
#define FLG_DCHAN_BUSY 11
+#define FLG_L1_ACTIV 12
+#define FLG_ESTAB_PEND 13
+#define FLG_PTP 14
+#define FLG_FIXED_TEI 15
struct Layer2 {
int tei;
- int tei_wanted;
int sap;
int maxlen;
unsigned int flag;
@@ -288,23 +308,25 @@ struct Layer2 {
struct sk_buff_head i_queue;
struct sk_buff_head ui_queue;
void (*l2l1) (struct PStack *, int, void *);
- void (*l2man) (struct PStack *, int, void *);
void (*l2l3) (struct PStack *, int, void *);
void (*l2tei) (struct PStack *, int, void *);
struct FsmInst l2m;
struct FsmTimer t200, t203;
int T200, N200, T203;
int debug;
- char debug_id[32];
+ char debug_id[16];
};
struct Layer3 {
- void (*l3l4) (struct l3_process *, int, void *);
+ void (*l3l4) (struct PStack *, int, void *);
void (*l3l2) (struct PStack *, int, void *);
+ struct FsmInst l3m;
+ struct sk_buff_head squeue;
struct l3_process *proc;
struct l3_process *global;
int N303;
int debug;
+ char debug_id[8];
};
struct LLInterface {
@@ -321,8 +343,6 @@ struct Management {
struct FsmTimer t202;
int T202, N202, debug;
void (*layer) (struct PStack *, int, void *);
- void (*manl1) (struct PStack *, int, void *);
- void (*manl2) (struct PStack *, int, void *);
};
@@ -343,7 +363,7 @@ struct PStack {
struct Layer1 l1;
struct Layer2 l2;
struct Layer3 l3;
- struct LLInterface lli;
+ struct LLInterface lli;
struct Management ma;
int protocol; /* EDSS1 or 1TR6 */
};
@@ -361,21 +381,55 @@ struct l3_process {
};
struct hscx_hw {
+ int hscx;
+ int rcvidx;
+ int count; /* Current skb sent count */
+ u_char *rcvbuf; /* B-Channel receive Buffer */
+};
+
+struct isar_reg {
+ unsigned int Flags;
+ volatile u_char bstat;
+ volatile u_char iis;
+ volatile u_char cmsb;
+ volatile u_char clsb;
+ volatile u_char par[8];
+};
+
+struct isar_hw {
+ int dpath;
+ int rcvidx;
+ int txcnt;
+ int mml;
+ u_char *rcvbuf; /* B-Channel receive Buffer */
+ struct isar_reg *reg;
+};
+
+struct hdlc_stat_reg {
+ u_char cmd __attribute__((packed));
+ u_char xml __attribute__((packed));
+ u_char mode __attribute__((packed));
+ u_char fill __attribute__((packed));
+};
+
+struct hdlc_hw {
+ union {
+ u_int ctrl;
+ struct hdlc_stat_reg sr;
+ } ctrl;
+ u_int stat;
int rcvidx;
int count; /* Current skb sent count */
u_char *rcvbuf; /* B-Channel receive Buffer */
- struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
};
struct hfcB_hw {
unsigned int *send;
int f1;
int f2;
- struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
};
struct tiger_hw {
- struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
u_int *send;
u_int *s_irq;
u_int *s_end;
@@ -397,8 +451,7 @@ struct tiger_hw {
u_char s_state;
};
-struct foreign_hw {
- int doHDLCprocessing;
+struct amd7930_hw {
u_char *tx_buff;
u_char *rv_buff;
int rv_buff_in;
@@ -407,9 +460,9 @@ struct foreign_hw {
struct hdlc_state *hdlc_state;
struct tq_struct tq_rcv;
struct tq_struct tq_xmt;
- struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
};
+
#define BC_FLG_INIT 1
#define BC_FLG_ACTIV 2
#define BC_FLG_BUSY 3
@@ -420,6 +473,7 @@ struct foreign_hw {
#define L1_MODE_NULL 0
#define L1_MODE_TRANS 1
#define L1_MODE_HDLC 2
+#define L1_MODE_MODEM 7
struct BCState {
int channel;
@@ -427,34 +481,26 @@ struct BCState {
int Flag;
struct IsdnCardState *cs;
int tx_cnt; /* B-Channel transmit counter */
+ struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
struct sk_buff_head rqueue; /* B-Channel receive Queue */
struct sk_buff_head squeue; /* B-Channel send Queue */
struct PStack *st;
+ u_char *blog;
+ struct timer_list transbusy;
struct tq_struct tqueue;
int event;
int (*BC_SetStack) (struct PStack *, struct BCState *);
void (*BC_Close) (struct BCState *);
union {
struct hscx_hw hscx;
+ struct hdlc_hw hdlc;
+ struct isar_hw isar;
struct hfcB_hw hfc;
struct tiger_hw tiger;
- struct foreign_hw foreign;
+ struct amd7930_hw amd7930;
} hw;
};
-struct LcFsm {
- int type;
- int delay;
- struct FsmInst lcfi;
- struct Channel *ch;
- void (*lccall) (struct LcFsm *, int, void *);
- struct PStack *st;
- int l2_establish;
- int l2_start;
- struct FsmTimer act_timer;
- char debug_id[32];
-};
-
struct Channel {
struct PStack *b_st, *d_st;
struct IsdnCardState *cs;
@@ -462,11 +508,10 @@ struct Channel {
int chan;
int incoming;
struct FsmInst fi;
- struct LcFsm *lc_d;
- struct LcFsm *lc_b;
struct FsmTimer drel_timer, dial_timer;
int debug;
int l2_protocol, l2_active_protocol;
+ int l3_protocol;
int data_open;
struct l3_process *proc;
setup_parm setup; /* from isdnif.h numbers and Serviceindicator */
@@ -487,21 +532,33 @@ struct elsa_hw {
unsigned int counter;
unsigned int status;
struct timer_list tl;
+ unsigned int MFlag;
+ struct BCState *bcs;
+ u_char *transbuf;
+ u_char *rcvbuf;
+ unsigned int transp;
+ unsigned int rcvp;
+ unsigned int transcnt;
+ unsigned int rcvcnt;
+ u_char IER;
+ u_char FCR;
+ u_char LCR;
+ u_char MCR;
u_char ctrl_reg;
-};
+};
struct teles3_hw {
unsigned int cfg_reg;
- unsigned int isac;
- unsigned int hscx[2];
- unsigned int isacfifo;
- unsigned int hscxfifo[2];
-};
+ signed int isac;
+ signed int hscx[2];
+ signed int isacfifo;
+ signed int hscxfifo[2];
+};
struct teles0_hw {
unsigned int cfg_reg;
unsigned int membase;
-};
+};
struct avm_hw {
unsigned int cfg_reg;
@@ -510,7 +567,7 @@ struct avm_hw {
unsigned int isacfifo;
unsigned int hscxfifo[2];
unsigned int counter;
-};
+};
struct ix1_hw {
unsigned int cfg_reg;
@@ -530,7 +587,7 @@ struct diva_hw {
unsigned int status;
struct timer_list tl;
u_char ctrl_reg;
-};
+};
struct asus_hw {
unsigned int cfg_reg;
@@ -559,6 +616,9 @@ struct sedl_hw {
unsigned int hscx;
unsigned int reset_on;
unsigned int reset_off;
+ struct isar_reg isar;
+ unsigned int chip;
+ unsigned int bus;
};
struct spt_hw {
@@ -566,7 +626,7 @@ struct spt_hw {
unsigned int isac;
unsigned int hscx[2];
unsigned char res_irq;
-};
+};
struct mic_hw {
unsigned int cfg_reg;
@@ -610,6 +670,7 @@ struct hfcD_hw {
#define HW_IOM1 0
#define HW_IPAC 1
+#define HW_ISAR 2
#define FLG_TWO_DCHAN 4
#define FLG_L1_DBUSY 5
#define FLG_DBUSY_TIMER 6
@@ -624,7 +685,7 @@ struct IsdnCardState {
unsigned char subtyp;
int protocol;
unsigned int irq;
- int HW_Flags;
+ int HW_Flags;
int *busy_flag;
union {
struct elsa_hw elsa;
@@ -641,7 +702,6 @@ struct IsdnCardState {
struct njet_hw njet;
struct hfcD_hw hfcD;
struct ix1_hw niccy;
- struct foreign_interface *foreign;
} hw;
int myid;
isdn_if iif;
@@ -657,7 +717,6 @@ struct IsdnCardState {
void (*BC_Write_Reg) (struct IsdnCardState *, int, u_char, u_char);
void (*BC_Send_Data) (struct BCState *);
int (*cardmsg) (struct IsdnCardState *, int, void *);
- void (*l1cmd) (struct IsdnCardState *, int, void *);
struct Channel channel[2];
struct BCState bcs[2];
struct PStack *stlist;
@@ -671,8 +730,7 @@ struct IsdnCardState {
struct sk_buff_head rq, sq; /* D-channel queues */
int ph_state;
int cardnr;
- int dlogflag;
- char *dlogspace;
+ char *dlog;
int debug;
u_char *mon_tx;
u_char *mon_rx;
@@ -688,6 +746,8 @@ struct IsdnCardState {
#define MON0_TX 4
#define MON1_TX 8
+#define HISAX_MAX_CARDS 8
+
#define ISDN_CTYPE_16_0 1
#define ISDN_CTYPE_8_0 2
#define ISDN_CTYPE_16_3 3
@@ -712,9 +772,12 @@ struct IsdnCardState {
#define ISDN_CTYPE_SEDLBAUER_PCMCIA 22
#define ISDN_CTYPE_AMD7930 23
#define ISDN_CTYPE_NICCY 24
-#define ISDN_CTYPE_DBRI 25
+#define ISDN_CTYPE_S0BOX 25
+#define ISDN_CTYPE_A1_PCMCIA 26
+#define ISDN_CTYPE_FRITZPCI 27
+#define ISDN_CTYPE_SEDLBAUER_FAX 28
-#define ISDN_CTYPE_COUNT 25
+#define ISDN_CTYPE_COUNT 28
#ifdef ISDN_CHIP_ISAC
#undef ISDN_CHIP_ISAC
@@ -742,15 +805,42 @@ struct IsdnCardState {
#define CARD_TELES3 0
#endif
+#ifdef CONFIG_HISAX_TELESPCI
+#define CARD_TELESPCI (1<< ISDN_CTYPE_TELESPCI)
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_TELESPCI 0
+#endif
+
#ifdef CONFIG_HISAX_AVM_A1
#define CARD_AVM_A1 (1<< ISDN_CTYPE_A1)
-#ifndef ISDN_CHIP_ISAC
+#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_AVM_A1 0
#endif
+#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
+#define CARD_AVM_A1_PCMCIA (1<< ISDN_CTYPE_A1_PCMCIA)
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_AVM_A1_PCMCIA 0
+#endif
+
+#ifdef CONFIG_HISAX_FRITZPCI
+#define CARD_FRITZPCI (1<< ISDN_CTYPE_FRITZPCI)
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_FRITZPCI 0
+#endif
+
#ifdef CONFIG_HISAX_ELSA
#define CARD_ELSA (1<< ISDN_CTYPE_ELSA) | (1<< ISDN_CTYPE_ELSA_PNP) | \
(1<< ISDN_CTYPE_ELSA_PCMCIA) | (1<< ISDN_CTYPE_ELSA_PCI)
@@ -803,7 +893,7 @@ struct IsdnCardState {
#endif
#ifdef CONFIG_HISAX_SEDLBAUER
-#define CARD_SEDLBAUER (1 << ISDN_CTYPE_SEDLBAUER) | (1 << ISDN_CTYPE_SEDLBAUER_PCMCIA)
+#define CARD_SEDLBAUER (1 << ISDN_CTYPE_SEDLBAUER) | (1 << ISDN_CTYPE_SEDLBAUER_PCMCIA) | ( 1 << ISDN_CTYPE_SEDLBAUER_FAX)
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
@@ -859,18 +949,21 @@ struct IsdnCardState {
#define CARD_NICCY 0
#endif
-#ifdef CONFIG_HISAX_DBRI
-#define CARD_DBRI (1 << ISDN_CTYPE_DBRI)
+#ifdef CONFIG_HISAX_S0BOX
+#define CARD_S0BOX (1 << ISDN_CTYPE_S0BOX)
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
#else
-#define CARD_DBRI 0
+#define CARD_S0BOX 0
#endif
-
#define SUPORTED_CARDS (CARD_TELES0 | CARD_TELES3 | CARD_AVM_A1 | CARD_ELSA \
| CARD_IX1MICROR2 | CARD_DIEHLDIVA | CARD_ASUSCOM \
| CARD_TELEINT | CARD_SEDLBAUER | CARD_SPORTSTER \
| CARD_MIC | CARD_NETJET | CARD_TELES3C | CARD_AMD7930 \
- | CARD_NICCY | CARD_DBRI)
+ | CARD_AVM_A1_PCMCIA | CARD_FRITZPCI\
+ | CARD_NICCY | CARD_S0BOX | CARD_TELESPCI)
#define TEI_PER_CARD 0
@@ -883,25 +976,38 @@ struct IsdnCardState {
#undef TEI_PER_CARD
#define TEI_PER_CARD 1
#define HISAX_EURO_SENDCOMPLETE 1
-#ifdef CONFIG_HISAX_ML
+#define EXT_BEARER_CAPS 1
+#define HISAX_SEND_STD_LLC_IE 1
+#ifdef CONFIG_HISAX_NO_SENDCOMPLETE
#undef HISAX_EURO_SENDCOMPLETE
#endif
+#ifdef CONFIG_HISAX_NO_LLC
+#undef HISAX_SEND_STD_LLC_IE
+#endif
#undef HISAX_DE_AOC
#ifdef CONFIG_DE_AOC
#define HISAX_DE_AOC 1
#endif
#endif
-#if TEI_PER_CARD
-#undef TEI_FIXED
-#endif
-
-#undef PTP_DATA_LINK
-
-#ifdef PTP_DATA_LINK
-#undef TEI_FIXED
-#define TEI_FIXED 0
-#define LAYER2_WATCHING
+/* L1 Debug */
+#define L1_DEB_WARN 0x01
+#define L1_DEB_INTSTAT 0x02
+#define L1_DEB_ISAC 0x04
+#define L1_DEB_ISAC_FIFO 0x08
+#define L1_DEB_HSCX 0x10
+#define L1_DEB_HSCX_FIFO 0x20
+#define L1_DEB_LAPD 0x40
+#define L1_DEB_IPAC 0x80
+#define L1_DEB_RECEIVE_FRAME 0x100
+#define L1_DEB_MONITOR 0x200
+#define DEB_DLOG_HEX 0x400
+#define DEB_DLOG_VERBOSE 0x800
+
+#define L2FRAME_DEBUG
+
+#ifdef L2FRAME_DEBUG
+extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir);
#endif
struct IsdnCard {
@@ -911,17 +1017,26 @@ struct IsdnCard {
struct IsdnCardState *cs;
};
-void setstack_isdnl2(struct PStack *st, char *debug_id);
-int HiSax_inithardware(int *);
-void HiSax_closehardware(void);
+void init_bcstate(struct IsdnCardState *cs, int bc);
void setstack_HiSax(struct PStack *st, struct IsdnCardState *cs);
unsigned int random_ri(void);
-void setstack_isdnl3(struct PStack *st, struct Channel *chanp);
void HiSax_addlist(struct IsdnCardState *sp, struct PStack *st);
+void HiSax_rmlist(struct IsdnCardState *sp, struct PStack *st);
+
+void setstack_l1_B(struct PStack *st);
+
+void setstack_tei(struct PStack *st);
+void setstack_manager(struct PStack *st);
+
+void setstack_isdnl2(struct PStack *st, char *debug_id);
void releasestack_isdnl2(struct PStack *st);
+void setstack_transl2(struct PStack *st);
+void releasestack_transl2(struct PStack *st);
+
+void setstack_l3dc(struct PStack *st, struct Channel *chanp);
+void setstack_l3bc(struct PStack *st, struct Channel *chanp);
void releasestack_isdnl3(struct PStack *st);
-void HiSax_rmlist(struct IsdnCardState *sp, struct PStack *st);
u_char *findie(u_char * p, int size, u_char ie, int wanted_set);
int getcallref(u_char * p);
@@ -937,20 +1052,18 @@ int FsmAddTimer(struct FsmTimer *ft, int millisec, int event,
void FsmRestartTimer(struct FsmTimer *ft, int millisec, int event,
void *arg, int where);
void FsmDelTimer(struct FsmTimer *ft, int where);
-void jiftime(char *s, long mark);
+int jiftime(char *s, long mark);
int HiSax_command(isdn_ctrl * ic);
int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
-void HiSax_putstatus(struct IsdnCardState *csta, char *buf);
+void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args);
void HiSax_reportcard(int cardnr);
int QuickHex(char *txt, u_char * p, int cnt);
-void LogFrame(struct IsdnCardState *sp, u_char * p, int size);
-void dlogframe(struct IsdnCardState *sp, u_char * p, int size, char *comment);
+void LogFrame(struct IsdnCardState *cs, u_char * p, int size);
+void dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir);
void iecpy(u_char * dest, u_char * iestart, int ieoffset);
-void setstack_transl2(struct PStack *st);
-void releasestack_transl2(struct PStack *st);
-void setstack_tei(struct PStack *st);
-void setstack_manager(struct PStack *st);
+int discard_queue(struct sk_buff_head *q);
#ifdef ISDN_CHIP_ISAC
void setstack_isac(struct PStack *st, struct IsdnCardState *cs);
#endif /* ISDN_CHIP_ISAC */
@@ -958,18 +1071,21 @@ void setstack_isac(struct PStack *st, struct IsdnCardState *cs);
#define HZDELAY(jiffs) {int tout = jiffs; while (tout--) udelay(1000000/HZ);}
-int ll_run(struct IsdnCardState *csta);
-void ll_stop(struct IsdnCardState *csta);
+int ll_run(struct IsdnCardState *cs);
+void ll_stop(struct IsdnCardState *cs);
void CallcNew(void);
void CallcFree(void);
-int CallcNewChan(struct IsdnCardState *csta);
-void CallcFreeChan(struct IsdnCardState *csta);
+int CallcNewChan(struct IsdnCardState *cs);
+void CallcFreeChan(struct IsdnCardState *cs);
void Isdnl1New(void);
void Isdnl1Free(void);
void Isdnl2New(void);
void Isdnl2Free(void);
-void init_tei(struct IsdnCardState *sp, int protocol);
-void release_tei(struct IsdnCardState *sp);
+void Isdnl3New(void);
+void Isdnl3Free(void);
+void init_tei(struct IsdnCardState *cs, int protocol);
+void release_tei(struct IsdnCardState *cs);
char *HiSax_getrev(const char *revision);
void TeiNew(void);
void TeiFree(void);
+int certification_check(int output);
diff --git a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c
index c44cc54df..980dc76e8 100644
--- a/drivers/isdn/hisax/hscx.c
+++ b/drivers/isdn/hisax/hscx.c
@@ -1,11 +1,40 @@
-/* $Id: hscx.c,v 1.7 1998/02/12 23:07:36 keil Exp $
+/* $Id: hscx.c,v 1.16 1998/11/15 23:54:48 keil Exp $
* hscx.c HSCX specific routines
*
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
*
*
* $Log: hscx.c,v $
+ * Revision 1.16 1998/11/15 23:54:48 keil
+ * changes from 2.0
+ *
+ * Revision 1.15 1998/08/20 13:50:42 keil
+ * More support for hybrid modem (not working yet)
+ *
+ * Revision 1.14 1998/08/13 23:36:33 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 1.13 1998/06/26 22:03:28 keil
+ * send flags between hdlc frames
+ *
+ * Revision 1.12 1998/06/09 18:26:01 keil
+ * PH_DEACTIVATE B-channel every time signaled to higher layer
+ *
+ * Revision 1.11 1998/05/25 14:10:07 keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 1.10 1998/05/25 12:57:59 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.9 1998/04/15 16:45:33 keil
+ * new init code
+ *
+ * Revision 1.8 1998/03/19 13:16:24 keil
+ * fix the correct release of the hscx
+ *
* Revision 1.7 1998/02/12 23:07:36 keil
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
@@ -30,6 +59,7 @@
#define __NO_VERSION__
#include "hisax.h"
#include "hscx.h"
+#include "isac.h"
#include "isdnl1.h"
#include <linux/interrupt.h>
@@ -56,21 +86,20 @@ void
modehscx(struct BCState *bcs, int mode, int bc)
{
struct IsdnCardState *cs = bcs->cs;
- int hscx = bcs->channel;
+ int hscx = bcs->hw.hscx.hscx;
- if (cs->debug & L1_DEB_HSCX) {
- char tmp[40];
- sprintf(tmp, "hscx %c mode %d ichan %d",
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "hscx %c mode %d ichan %d",
'A' + hscx, mode, bc);
- debugl1(cs, tmp);
- }
bcs->mode = mode;
- cs->BC_Write_Reg(cs, hscx, HSCX_CCR1, 0x85);
+ bcs->channel = bc;
cs->BC_Write_Reg(cs, hscx, HSCX_XAD1, 0xFF);
cs->BC_Write_Reg(cs, hscx, HSCX_XAD2, 0xFF);
cs->BC_Write_Reg(cs, hscx, HSCX_RAH2, 0xFF);
cs->BC_Write_Reg(cs, hscx, HSCX_XBCH, 0x0);
cs->BC_Write_Reg(cs, hscx, HSCX_RLCR, 0x0);
+ cs->BC_Write_Reg(cs, hscx, HSCX_CCR1,
+ test_bit(HW_IPAC, &cs->HW_Flags) ? 0x82 : 0x85);
cs->BC_Write_Reg(cs, hscx, HSCX_CCR2, 0x30);
cs->BC_Write_Reg(cs, hscx, HSCX_XCCR, 7);
cs->BC_Write_Reg(cs, hscx, HSCX_RCCR, 7);
@@ -90,14 +119,16 @@ modehscx(struct BCState *bcs, int mode, int bc)
}
switch (mode) {
case (L1_MODE_NULL):
- cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0xff);
- cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0xff);
+ cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0x1f);
+ cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0x1f);
cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x84);
break;
case (L1_MODE_TRANS):
cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0xe4);
break;
case (L1_MODE_HDLC):
+ cs->BC_Write_Reg(cs, hscx, HSCX_CCR1,
+ test_bit(HW_IPAC, &cs->HW_Flags) ? 0x8a : 0x8d);
cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x8c);
break;
}
@@ -114,89 +145,106 @@ hscx_sched_event(struct BCState *bcs, int event)
mark_bh(IMMEDIATE_BH);
}
-static void
+void
hscx_l2l1(struct PStack *st, int pr, void *arg)
{
struct sk_buff *skb = arg;
long flags;
switch (pr) {
- case (PH_DATA_REQ):
+ case (PH_DATA | REQUEST):
save_flags(flags);
cli();
- if (st->l1.bcs->hw.hscx.tx_skb) {
+ if (st->l1.bcs->tx_skb) {
skb_queue_tail(&st->l1.bcs->squeue, skb);
restore_flags(flags);
} else {
- st->l1.bcs->hw.hscx.tx_skb = skb;
+ st->l1.bcs->tx_skb = skb;
test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
st->l1.bcs->hw.hscx.count = 0;
restore_flags(flags);
st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
}
break;
- case (PH_PULL_IND):
- if (st->l1.bcs->hw.hscx.tx_skb) {
+ case (PH_PULL | INDICATION):
+ if (st->l1.bcs->tx_skb) {
printk(KERN_WARNING "hscx_l2l1: this shouldn't happen\n");
break;
}
test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
- st->l1.bcs->hw.hscx.tx_skb = skb;
+ st->l1.bcs->tx_skb = skb;
st->l1.bcs->hw.hscx.count = 0;
st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
break;
- case (PH_PULL_REQ):
- if (!st->l1.bcs->hw.hscx.tx_skb) {
+ case (PH_PULL | REQUEST):
+ if (!st->l1.bcs->tx_skb) {
test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
- st->l1.l1l2(st, PH_PULL_CNF, NULL);
+ st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
} else
test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
break;
+ case (PH_ACTIVATE | REQUEST):
+ test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+ modehscx(st->l1.bcs, st->l1.mode, st->l1.bc);
+ l1_msg_b(st, pr, arg);
+ break;
+ case (PH_DEACTIVATE | REQUEST):
+ l1_msg_b(st, pr, arg);
+ break;
+ case (PH_DEACTIVATE | CONFIRM):
+ test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+ test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ modehscx(st->l1.bcs, 0, st->l1.bc);
+ st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+ break;
}
-
}
void
close_hscxstate(struct BCState *bcs)
{
- struct sk_buff *skb;
-
- modehscx(bcs, 0, 0);
+ modehscx(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
if (bcs->hw.hscx.rcvbuf) {
kfree(bcs->hw.hscx.rcvbuf);
bcs->hw.hscx.rcvbuf = NULL;
}
- while ((skb = skb_dequeue(&bcs->rqueue))) {
- dev_kfree_skb(skb);
- }
- while ((skb = skb_dequeue(&bcs->squeue))) {
- dev_kfree_skb(skb);
+ if (bcs->blog) {
+ kfree(bcs->blog);
+ bcs->blog = NULL;
}
- if (bcs->hw.hscx.tx_skb) {
- dev_kfree_skb(bcs->hw.hscx.tx_skb);
- bcs->hw.hscx.tx_skb = NULL;
+ discard_queue(&bcs->rqueue);
+ discard_queue(&bcs->squeue);
+ if (bcs->tx_skb) {
+ dev_kfree_skb(bcs->tx_skb);
+ bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
}
}
}
-static int
-open_hscxstate(struct IsdnCardState *cs,
- int bc)
+int
+open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs)
{
- struct BCState *bcs = cs->bcs + bc;
-
if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
printk(KERN_WARNING
- "HiSax: No memory for hscx.rcvbuf\n");
+ "HiSax: No memory for hscx.rcvbuf\n");
+ test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
return (1);
}
+ if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
+ printk(KERN_WARNING
+ "HiSax: No memory for bcs->blog\n");
+ test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
+ kfree(bcs->hw.hscx.rcvbuf);
+ bcs->hw.hscx.rcvbuf = NULL;
+ return (2);
+ }
skb_queue_head_init(&bcs->rqueue);
skb_queue_head_init(&bcs->squeue);
}
- bcs->hw.hscx.tx_skb = NULL;
+ bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->event = 0;
bcs->hw.hscx.rcvidx = 0;
@@ -204,77 +252,74 @@ open_hscxstate(struct IsdnCardState *cs,
return (0);
}
-static void
-hscx_manl1(struct PStack *st, int pr,
- void *arg)
-{
- switch (pr) {
- case (PH_ACTIVATE_REQ):
- test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
- modehscx(st->l1.bcs, st->l1.mode, st->l1.bc);
- st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
- break;
- case (PH_DEACTIVATE_REQ):
- if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
- modehscx(st->l1.bcs, 0, 0);
- test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
- break;
- }
-}
-
int
setstack_hscx(struct PStack *st, struct BCState *bcs)
{
- if (open_hscxstate(st->l1.hardware, bcs->channel))
+ bcs->channel = st->l1.bc;
+ if (open_hscxstate(st->l1.hardware, bcs))
return (-1);
st->l1.bcs = bcs;
st->l2.l2l1 = hscx_l2l1;
- st->ma.manl1 = hscx_manl1;
setstack_manager(st);
bcs->st = st;
+ setstack_l1_B(st);
return (0);
}
HISAX_INITFUNC(void
clear_pending_hscx_ints(struct IsdnCardState *cs))
{
- int val;
- char tmp[64];
+ int val, eval;
val = cs->BC_Read_Reg(cs, 1, HSCX_ISTA);
- sprintf(tmp, "HSCX B ISTA %x", val);
- debugl1(cs, tmp);
+ debugl1(cs, "HSCX B ISTA %x", val);
if (val & 0x01) {
- val = cs->BC_Read_Reg(cs, 1, HSCX_EXIR);
- sprintf(tmp, "HSCX B EXIR %x", val);
- debugl1(cs, tmp);
- } else if (val & 0x02) {
- val = cs->BC_Read_Reg(cs, 0, HSCX_EXIR);
- sprintf(tmp, "HSCX A EXIR %x", val);
- debugl1(cs, tmp);
+ eval = cs->BC_Read_Reg(cs, 1, HSCX_EXIR);
+ debugl1(cs, "HSCX B EXIR %x", eval);
+ }
+ if (val & 0x02) {
+ eval = cs->BC_Read_Reg(cs, 0, HSCX_EXIR);
+ debugl1(cs, "HSCX A EXIR %x", eval);
}
val = cs->BC_Read_Reg(cs, 0, HSCX_ISTA);
- sprintf(tmp, "HSCX A ISTA %x", val);
- debugl1(cs, tmp);
+ debugl1(cs, "HSCX A ISTA %x", val);
val = cs->BC_Read_Reg(cs, 1, HSCX_STAR);
- sprintf(tmp, "HSCX B STAR %x", val);
- debugl1(cs, tmp);
+ debugl1(cs, "HSCX B STAR %x", val);
val = cs->BC_Read_Reg(cs, 0, HSCX_STAR);
- sprintf(tmp, "HSCX A STAR %x", val);
- debugl1(cs, tmp);
+ debugl1(cs, "HSCX A STAR %x", val);
+ /* disable all IRQ */
cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0xFF);
cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0xFF);
- cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0);
- cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0);
}
-HISAX_INITFUNC(void
+HISAX_INITFUNC(void
inithscx(struct IsdnCardState *cs))
{
cs->bcs[0].BC_SetStack = setstack_hscx;
cs->bcs[1].BC_SetStack = setstack_hscx;
cs->bcs[0].BC_Close = close_hscxstate;
cs->bcs[1].BC_Close = close_hscxstate;
+ cs->bcs[0].hw.hscx.hscx = 0;
+ cs->bcs[1].hw.hscx.hscx = 1;
modehscx(cs->bcs, 0, 0);
modehscx(cs->bcs + 1, 0, 0);
}
+
+HISAX_INITFUNC(void
+inithscxisac(struct IsdnCardState *cs, int part))
+{
+ if (part & 1) {
+ clear_pending_isac_ints(cs);
+ clear_pending_hscx_ints(cs);
+ initisac(cs);
+ inithscx(cs);
+ }
+ if (part & 2) {
+ /* Reenable all IRQ */
+ cs->writeisac(cs, ISAC_MASK, 0);
+ cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0);
+ cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0);
+ /* RESET Receiver and Transmitter */
+ cs->writeisac(cs, ISAC_CMDR, 0x41);
+ }
+}
diff --git a/drivers/isdn/hisax/hscx.h b/drivers/isdn/hisax/hscx.h
index ac2d38086..08801bc73 100644
--- a/drivers/isdn/hisax/hscx.h
+++ b/drivers/isdn/hisax/hscx.h
@@ -1,4 +1,4 @@
-/* $Id: hscx.h,v 1.3 1997/07/27 21:38:35 keil Exp $
+/* $Id: hscx.h,v 1.4 1998/04/15 16:45:34 keil Exp $
* hscx.h HSCX specific defines
*
@@ -6,6 +6,9 @@
*
*
* $Log: hscx.h,v $
+ * Revision 1.4 1998/04/15 16:45:34 keil
+ * new init code
+ *
* Revision 1.3 1997/07/27 21:38:35 keil
* new B-channel interface
*
@@ -44,3 +47,4 @@ extern void hscx_sched_event(struct BCState *bcs, int event);
extern void modehscx(struct BCState *bcs, int mode, int bc);
extern void clear_pending_hscx_ints(struct IsdnCardState *cs);
extern void inithscx(struct IsdnCardState *cs);
+extern void inithscxisac(struct IsdnCardState *cs, int part);
diff --git a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c
index 992ec813b..217d241c3 100644
--- a/drivers/isdn/hisax/hscx_irq.c
+++ b/drivers/isdn/hisax/hscx_irq.c
@@ -1,12 +1,24 @@
-/* $Id: hscx_irq.c,v 1.7 1998/02/12 23:07:37 keil Exp $
+/* $Id: hscx_irq.c,v 1.11 1998/11/15 23:54:49 keil Exp $
* hscx_irq.c low level b-channel stuff for Siemens HSCX
*
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
*
* This is an include file for fast inline IRQ stuff
*
* $Log: hscx_irq.c,v $
+ * Revision 1.11 1998/11/15 23:54:49 keil
+ * changes from 2.0
+ *
+ * Revision 1.10 1998/08/13 23:36:35 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 1.9 1998/06/24 14:44:51 keil
+ * Fix recovery of TX IRQ loss
+ *
+ * Revision 1.8 1998/04/10 10:35:22 paul
+ * fixed (silly?) warnings from egcs on Alpha.
+ *
* Revision 1.7 1998/02/12 23:07:37 keil
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
@@ -30,6 +42,8 @@
*
*/
+#include <linux/string.h>
+
static inline void
waitforCEC(struct IsdnCardState *cs, int hscx)
@@ -85,7 +99,7 @@ hscx_empty_fifo(struct BCState *bcs, int count)
if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "hscx_empty_fifo: incoming packet too large");
- WriteHSCXCMDR(cs, bcs->channel, 0x80);
+ WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
bcs->hw.hscx.rcvidx = 0;
return;
}
@@ -93,17 +107,16 @@ hscx_empty_fifo(struct BCState *bcs, int count)
bcs->hw.hscx.rcvidx += count;
save_flags(flags);
cli();
- READHSCXFIFO(cs, bcs->channel, ptr, count);
- WriteHSCXCMDR(cs, bcs->channel, 0x80);
+ READHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
+ WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
restore_flags(flags);
if (cs->debug & L1_DEB_HSCX_FIFO) {
- char tmp[256];
- char *t = tmp;
+ char *t = bcs->blog;
t += sprintf(t, "hscx_empty_fifo %c cnt %d",
- bcs->channel ? 'B' : 'A', count);
+ bcs->hw.hscx.hscx ? 'B' : 'A', count);
QuickHex(t, ptr, count);
- debugl1(cs, tmp);
+ debugl1(cs, bcs->blog);
}
}
@@ -120,36 +133,35 @@ hscx_fill_fifo(struct BCState *bcs)
if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
debugl1(cs, "hscx_fill_fifo");
- if (!bcs->hw.hscx.tx_skb)
+ if (!bcs->tx_skb)
return;
- if (bcs->hw.hscx.tx_skb->len <= 0)
+ if (bcs->tx_skb->len <= 0)
return;
more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
- if (bcs->hw.hscx.tx_skb->len > fifo_size) {
+ if (bcs->tx_skb->len > fifo_size) {
more = !0;
count = fifo_size;
} else
- count = bcs->hw.hscx.tx_skb->len;
+ count = bcs->tx_skb->len;
- waitforXFW(cs, bcs->channel);
+ waitforXFW(cs, bcs->hw.hscx.hscx);
save_flags(flags);
cli();
- ptr = bcs->hw.hscx.tx_skb->data;
- skb_pull(bcs->hw.hscx.tx_skb, count);
+ ptr = bcs->tx_skb->data;
+ skb_pull(bcs->tx_skb, count);
bcs->tx_cnt -= count;
bcs->hw.hscx.count += count;
- WRITEHSCXFIFO(cs, bcs->channel, ptr, count);
- WriteHSCXCMDR(cs, bcs->channel, more ? 0x8 : 0xa);
+ WRITEHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
+ WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa);
restore_flags(flags);
if (cs->debug & L1_DEB_HSCX_FIFO) {
- char tmp[256];
- char *t = tmp;
+ char *t = bcs->blog;
t += sprintf(t, "hscx_fill_fifo %c cnt %d",
- bcs->channel ? 'B' : 'A', count);
+ bcs->hw.hscx.hscx ? 'B' : 'A', count);
QuickHex(t, ptr, count);
- debugl1(cs, tmp);
+ debugl1(cs, bcs->blog);
}
}
@@ -161,7 +173,6 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
struct sk_buff *skb;
int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
int count;
- char tmp[32];
if (!test_bit(BC_FLG_INIT, &bcs->Flag))
return;
@@ -173,11 +184,9 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "HSCX invalid frame");
if ((r & 0x40) && bcs->mode)
- if (cs->debug & L1_DEB_WARN) {
- sprintf(tmp, "HSCX RDO mode=%d",
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "HSCX RDO mode=%d",
bcs->mode);
- debugl1(cs, tmp);
- }
if (!(r & 0x20))
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "HSCX CRC error");
@@ -189,10 +198,8 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
count = fifo_size;
hscx_empty_fifo(bcs, count);
if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
- if (cs->debug & L1_DEB_HSCX_FIFO) {
- sprintf(tmp, "HX Frame %d", count);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_HSCX_FIFO)
+ debugl1(cs, "HX Frame %d", count);
if (!(skb = dev_alloc_skb(count)))
printk(KERN_WARNING "HSCX: receive out of memory\n");
else {
@@ -219,20 +226,20 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
}
}
if (val & 0x10) { /* XPR */
- if (bcs->hw.hscx.tx_skb) {
- if (bcs->hw.hscx.tx_skb->len) {
+ if (bcs->tx_skb) {
+ if (bcs->tx_skb->len) {
hscx_fill_fifo(bcs);
return;
} else {
if (bcs->st->lli.l1writewakeup &&
- (PACKET_NOACK != bcs->hw.hscx.tx_skb->pkt_type))
+ (PACKET_NOACK != bcs->tx_skb->pkt_type))
bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count);
- dev_kfree_skb(bcs->hw.hscx.tx_skb);
+ dev_kfree_skb(bcs->tx_skb);
bcs->hw.hscx.count = 0;
- bcs->hw.hscx.tx_skb = NULL;
+ bcs->tx_skb = NULL;
}
}
- if ((bcs->hw.hscx.tx_skb = skb_dequeue(&bcs->squeue))) {
+ if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
bcs->hw.hscx.count = 0;
test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
hscx_fill_fifo(bcs);
@@ -249,73 +256,60 @@ hscx_int_main(struct IsdnCardState *cs, u_char val)
u_char exval;
struct BCState *bcs;
- char tmp[32];
if (val & 0x01) {
bcs = cs->bcs + 1;
exval = READHSCX(cs, 1, HSCX_EXIR);
- if (exval == 0x40) {
+ if (exval & 0x40) {
if (bcs->mode == 1)
hscx_fill_fifo(bcs);
else {
/* Here we lost an TX interrupt, so
* restart transmitting the whole frame.
*/
- if (bcs->hw.hscx.tx_skb) {
- skb_push(bcs->hw.hscx.tx_skb, bcs->hw.hscx.count);
+ if (bcs->tx_skb) {
+ skb_push(bcs->tx_skb, bcs->hw.hscx.count);
bcs->tx_cnt += bcs->hw.hscx.count;
bcs->hw.hscx.count = 0;
}
- WriteHSCXCMDR(cs, bcs->channel, 0x01);
- if (cs->debug & L1_DEB_WARN) {
- sprintf(tmp, "HSCX B EXIR %x Lost TX", exval);
- debugl1(cs, tmp);
- }
+ WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "HSCX B EXIR %x Lost TX", exval);
}
- } else if (cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "HSCX B EXIR %x", exval);
- debugl1(cs, tmp);
- }
+ } else if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "HSCX B EXIR %x", exval);
}
if (val & 0xf8) {
- if (cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "HSCX B interrupt %x", val);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "HSCX B interrupt %x", val);
hscx_interrupt(cs, val, 1);
}
if (val & 0x02) {
bcs = cs->bcs;
exval = READHSCX(cs, 0, HSCX_EXIR);
- if (exval == 0x40) {
+ if (exval & 0x40) {
if (bcs->mode == L1_MODE_TRANS)
hscx_fill_fifo(bcs);
else {
/* Here we lost an TX interrupt, so
* restart transmitting the whole frame.
*/
- if (bcs->hw.hscx.tx_skb) {
- skb_push(bcs->hw.hscx.tx_skb, bcs->hw.hscx.count);
+ if (bcs->tx_skb) {
+ skb_push(bcs->tx_skb, bcs->hw.hscx.count);
bcs->tx_cnt += bcs->hw.hscx.count;
bcs->hw.hscx.count = 0;
}
- WriteHSCXCMDR(cs, bcs->channel, 0x01);
- if (cs->debug & L1_DEB_WARN) {
- sprintf(tmp, "HSCX A EXIR %x Lost TX", exval);
- debugl1(cs, tmp);
- }
+ WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "HSCX A EXIR %x Lost TX", exval);
}
- } else if (cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "HSCX A EXIR %x", exval);
- debugl1(cs, tmp);
- }
+ } else if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "HSCX A EXIR %x", exval);
}
if (val & 0x04) {
exval = READHSCX(cs, 0, HSCX_ISTA);
- if (cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "HSCX A interrupt %x", exval);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "HSCX A interrupt %x", exval);
hscx_interrupt(cs, exval, 0);
}
}
diff --git a/drivers/isdn/hisax/ipac.h b/drivers/isdn/hisax/ipac.h
index 6d856ec6c..82c5fa8f8 100644
--- a/drivers/isdn/hisax/ipac.h
+++ b/drivers/isdn/hisax/ipac.h
@@ -1,4 +1,4 @@
-/* $Id: ipac.h,v 1.2 1997/10/29 18:51:21 keil Exp $
+/* $Id: ipac.h,v 1.3 1998/04/15 16:48:09 keil Exp $
* ipac.h IPAC specific defines
*
@@ -6,6 +6,9 @@
*
*
* $Log: ipac.h,v $
+ * Revision 1.3 1998/04/15 16:48:09 keil
+ * IPAC_ATX added
+ *
* Revision 1.2 1997/10/29 18:51:21 keil
* New files
*
@@ -26,6 +29,7 @@
#define IPAC_ACFG 0xC3
#define IPAC_AOE 0xC4
#define IPAC_ARX 0xC5
+#define IPAC_ATX 0xC5
#define IPAC_PITA1 0xC6
#define IPAC_PITA2 0xC7
#define IPAC_POTA1 0xC8
diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c
index f8458364c..a239fdfad 100644
--- a/drivers/isdn/hisax/isac.c
+++ b/drivers/isdn/hisax/isac.c
@@ -1,11 +1,33 @@
-/* $Id: isac.c,v 1.12 1998/02/12 23:07:40 keil Exp $
+/* $Id: isac.c,v 1.18 1998/11/15 23:54:51 keil Exp $
* isac.c ISAC specific routines
*
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
*
+ * This file is (c) under GNU PUBLIC LICENSE
+ * For changes and modifications please read
+ * ../../../Documentation/isdn/HiSax.cert
*
* $Log: isac.c,v $
+ * Revision 1.18 1998/11/15 23:54:51 keil
+ * changes from 2.0
+ *
+ * Revision 1.17 1998/08/13 23:36:37 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 1.16 1998/05/25 12:58:01 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.15 1998/04/15 16:45:32 keil
+ * new init code
+ *
+ * Revision 1.14 1998/04/10 10:35:26 paul
+ * fixed (silly?) warnings from egcs on Alpha.
+ *
+ * Revision 1.13 1998/03/07 22:57:01 tsbogend
+ * made HiSax working on Linux/Alpha
+ *
* Revision 1.12 1998/02/12 23:07:40 keil
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
@@ -63,30 +85,17 @@ ISACVersion(struct IsdnCardState *cs, char *s)
int val;
val = cs->readisac(cs, ISAC_RBCH);
- printk(KERN_INFO "%s ISAC version : %s\n", s, ISACVer[(val >> 5) & 3]);
+ printk(KERN_INFO "%s ISAC version (%x): %s\n", s, val, ISACVer[(val >> 5) & 3]);
}
static void
ph_command(struct IsdnCardState *cs, unsigned int command)
{
- if (cs->debug & L1_DEB_ISAC) {
- char tmp[32];
- sprintf(tmp, "ph_command %x", command);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "ph_command %x", command);
cs->writeisac(cs, ISAC_CIX0, (command << 2) | 3);
}
-static void
-manl1_msg(struct IsdnCardState *cs, int msg, void *arg) {
- struct PStack *st;
-
- st = cs->stlist;
- while (st) {
- st->ma.manl1(st, msg, arg);
- st = st->next;
- }
-}
static void
isac_new_ph(struct IsdnCardState *cs)
@@ -95,28 +104,28 @@ isac_new_ph(struct IsdnCardState *cs)
case (ISAC_IND_RS):
case (ISAC_IND_EI):
ph_command(cs, ISAC_CMD_DUI);
- manl1_msg(cs, PH_RESET_IND, NULL);
+ l1_msg(cs, HW_RESET | INDICATION, NULL);
break;
case (ISAC_IND_DID):
- manl1_msg(cs, PH_DEACT_CNF, NULL);
+ l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL);
break;
case (ISAC_IND_DR):
- manl1_msg(cs, PH_DEACT_IND, NULL);
+ l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
break;
case (ISAC_IND_PU):
- manl1_msg(cs, PH_POWERUP_CNF, NULL);
+ l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
break;
case (ISAC_IND_RSY):
- manl1_msg(cs, PH_RSYNC_IND, NULL);
+ l1_msg(cs, HW_RSYNC | INDICATION, NULL);
break;
case (ISAC_IND_ARD):
- manl1_msg(cs, PH_INFO2_IND, NULL);
+ l1_msg(cs, HW_INFO2 | INDICATION, NULL);
break;
case (ISAC_IND_AI8):
- manl1_msg(cs, PH_I4_P8_IND, NULL);
+ l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
break;
case (ISAC_IND_AI10):
- manl1_msg(cs, PH_I4_P10_IND, NULL);
+ l1_msg(cs, HW_INFO4_P10 | INDICATION, NULL);
break;
default:
break;
@@ -130,13 +139,12 @@ isac_bh(struct IsdnCardState *cs)
if (!cs)
return;
-
if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
if (cs->debug)
debugl1(cs, "D-Channel Busy cleared");
stptr = cs->stlist;
while (stptr != NULL) {
- stptr->l1.l1l2(stptr, PH_PAUSE_CNF, NULL);
+ stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
stptr = stptr->next;
}
}
@@ -147,13 +155,13 @@ isac_bh(struct IsdnCardState *cs)
if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
DChannel_proc_xmt(cs);
if (test_and_clear_bit(D_RX_MON0, &cs->event))
- test_and_set_bit(HW_MON0_TX_END, &cs->HW_Flags);
+ test_and_set_bit(HW_MON0_RX_END, &cs->HW_Flags);
if (test_and_clear_bit(D_RX_MON1, &cs->event))
- test_and_set_bit(HW_MON1_TX_END, &cs->HW_Flags);
+ test_and_set_bit(HW_MON1_RX_END, &cs->HW_Flags);
if (test_and_clear_bit(D_TX_MON0, &cs->event))
- test_and_set_bit(HW_MON0_RX_END, &cs->HW_Flags);
+ test_and_set_bit(HW_MON0_TX_END, &cs->HW_Flags);
if (test_and_clear_bit(D_TX_MON1, &cs->event))
- test_and_set_bit(HW_MON1_RX_END, &cs->HW_Flags);
+ test_and_set_bit(HW_MON1_TX_END, &cs->HW_Flags);
}
void
@@ -165,13 +173,10 @@ isac_empty_fifo(struct IsdnCardState *cs, int count)
if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
debugl1(cs, "isac_empty_fifo");
- if ((cs->rcvidx + count) >= MAX_DFRAME_LEN) {
- if (cs->debug & L1_DEB_WARN) {
- char tmp[40];
- sprintf(tmp, "isac_empty_fifo overrun %d",
+ if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "isac_empty_fifo overrun %d",
cs->rcvidx + count);
- debugl1(cs, tmp);
- }
cs->writeisac(cs, ISAC_CMDR, 0x80);
cs->rcvidx = 0;
return;
@@ -184,12 +189,11 @@ isac_empty_fifo(struct IsdnCardState *cs, int count)
cs->writeisac(cs, ISAC_CMDR, 0x80);
restore_flags(flags);
if (cs->debug & L1_DEB_ISAC_FIFO) {
- char tmp[128];
- char *t = tmp;
+ char *t = cs->dlog;
t += sprintf(t, "isac_empty_fifo cnt %d", count);
QuickHex(t, ptr, count);
- debugl1(cs, tmp);
+ debugl1(cs, cs->dlog);
}
}
@@ -231,12 +235,11 @@ isac_fill_fifo(struct IsdnCardState *cs)
cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
add_timer(&cs->dbusytimer);
if (cs->debug & L1_DEB_ISAC_FIFO) {
- char tmp[128];
- char *t = tmp;
+ char *t = cs->dlog;
t += sprintf(t, "isac_fill_fifo cnt %d", count);
QuickHex(t, ptr, count);
- debugl1(cs, tmp);
+ debugl1(cs, cs->dlog);
}
}
@@ -255,12 +258,9 @@ isac_interrupt(struct IsdnCardState *cs, u_char val)
struct sk_buff *skb;
unsigned int count;
long flags;
- char tmp[32];
- if (cs->debug & L1_DEB_ISAC) {
- sprintf(tmp, "ISAC interrupt %x", val);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "ISAC interrupt %x", val);
if (val & 0x80) { /* RME */
exval = cs->readisac(cs, ISAC_RSTA);
if ((exval & 0x70) != 0x20) {
@@ -323,12 +323,20 @@ isac_interrupt(struct IsdnCardState *cs, u_char val)
}
afterXPR:
if (val & 0x04) { /* CISQ */
- cs->ph_state = (cs->readisac(cs, ISAC_CIX0) >> 2) & 0xf;
- if (cs->debug & L1_DEB_ISAC) {
- sprintf(tmp, "ph_state change %x", cs->ph_state);
- debugl1(cs, tmp);
+ exval = cs->readisac(cs, ISAC_CIR0);
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "ISAC CIR0 %02X", exval );
+ if (exval & 2) {
+ cs->ph_state = (exval >> 2) & 0xf;
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "ph_state change %x", cs->ph_state);
+ isac_sched_event(cs, D_L1STATECHANGE);
+ }
+ if (exval & 1) {
+ exval = cs->readisac(cs, ISAC_CIR1);
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "ISAC CIR1 %02X", exval );
}
- isac_sched_event(cs, D_L1STATECHANGE);
}
if (val & 0x02) { /* SIN */
/* never */
@@ -337,16 +345,12 @@ isac_interrupt(struct IsdnCardState *cs, u_char val)
}
if (val & 0x01) { /* EXI */
exval = cs->readisac(cs, ISAC_EXIR);
- if (cs->debug & L1_DEB_WARN) {
- sprintf(tmp, "ISAC EXIR %02x", exval);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "ISAC EXIR %02x", exval);
if (exval & 0x04) {
v1 = cs->readisac(cs, ISAC_MOSR);
- if (cs->debug & L1_DEB_WARN) {
- sprintf(tmp, "ISAC MOSR %02x", v1);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_MONITOR)
+ debugl1(cs, "ISAC MOSR %02x", v1);
#if ARCOFI_USE
if (v1 & 0x08) {
if (!cs->mon_rx) {
@@ -370,10 +374,8 @@ isac_interrupt(struct IsdnCardState *cs, u_char val)
goto afterMONR0;
}
cs->mon_rx[cs->mon_rxp++] = cs->readisac(cs, ISAC_MOR0);
- if (cs->debug & L1_DEB_WARN) {
- sprintf(tmp, "ISAC MOR0 %02x", cs->mon_rx[cs->mon_rxp -1]);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_MONITOR)
+ debugl1(cs, "ISAC MOR0 %02x", cs->mon_rx[cs->mon_rxp -1]);
if (cs->mon_rxp == 1) {
cs->mocr |= 0x04;
cs->writeisac(cs, ISAC_MOCR, cs->mocr);
@@ -402,66 +404,70 @@ isac_interrupt(struct IsdnCardState *cs, u_char val)
goto afterMONR1;
}
cs->mon_rx[cs->mon_rxp++] = cs->readisac(cs, ISAC_MOR1);
- if (cs->debug & L1_DEB_WARN) {
- sprintf(tmp, "ISAC MOR1 %02x", cs->mon_rx[cs->mon_rxp -1]);
- debugl1(cs, tmp);
- }
- if (cs->mon_rxp == 1) {
- cs->mocr |= 0x40;
- cs->writeisac(cs, ISAC_MOCR, cs->mocr);
- }
+ if (cs->debug & L1_DEB_MONITOR)
+ debugl1(cs, "ISAC MOR1 %02x", cs->mon_rx[cs->mon_rxp -1]);
+ cs->mocr |= 0x40;
+ cs->writeisac(cs, ISAC_MOCR, cs->mocr);
}
afterMONR1:
if (v1 & 0x04) {
cs->mocr &= 0xf0;
+ cs->writeisac(cs, ISAC_MOCR, cs->mocr);
cs->mocr |= 0x0a;
cs->writeisac(cs, ISAC_MOCR, cs->mocr);
- isac_sched_event(cs, D_RX_MON0);
+ test_and_set_bit(HW_MON0_RX_END, &cs->HW_Flags);
}
if (v1 & 0x40) {
cs->mocr &= 0x0f;
+ cs->writeisac(cs, ISAC_MOCR, cs->mocr);
cs->mocr |= 0xa0;
cs->writeisac(cs, ISAC_MOCR, cs->mocr);
- isac_sched_event(cs, D_RX_MON1);
+ test_and_set_bit(HW_MON1_RX_END, &cs->HW_Flags);
}
if (v1 & 0x02) {
- if (!cs->mon_tx) {
+ if ((!cs->mon_tx) || (cs->mon_txc &&
+ (cs->mon_txp >= cs->mon_txc) &&
+ !(v1 & 0x08))) {
cs->mocr &= 0xf0;
+ cs->writeisac(cs, ISAC_MOCR, cs->mocr);
cs->mocr |= 0x0a;
cs->writeisac(cs, ISAC_MOCR, cs->mocr);
+ if (cs->mon_txc &&
+ (cs->mon_txp >= cs->mon_txc))
+ test_and_set_bit(HW_MON0_TX_END, &cs->HW_Flags);
goto AfterMOX0;
}
- if (cs->mon_txp >= cs->mon_txc) {
- if (cs->mon_txc)
- isac_sched_event(cs, D_TX_MON0);
+ if (cs->mon_txc && (cs->mon_txp >= cs->mon_txc)) {
+ test_and_set_bit(HW_MON0_TX_END, &cs->HW_Flags);
goto AfterMOX0;
}
cs->writeisac(cs, ISAC_MOX0,
cs->mon_tx[cs->mon_txp++]);
- if (cs->debug & L1_DEB_WARN) {
- sprintf(tmp, "ISAC %02x -> MOX0", cs->mon_tx[cs->mon_txp -1]);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_MONITOR)
+ debugl1(cs, "ISAC %02x -> MOX0", cs->mon_tx[cs->mon_txp -1]);
}
AfterMOX0:
if (v1 & 0x20) {
- if (!cs->mon_tx) {
+ if ((!cs->mon_tx) || (cs->mon_txc &&
+ (cs->mon_txp >= cs->mon_txc) &&
+ !(v1 & 0x80))) {
cs->mocr &= 0x0f;
+ cs->writeisac(cs, ISAC_MOCR, cs->mocr);
cs->mocr |= 0xa0;
cs->writeisac(cs, ISAC_MOCR, cs->mocr);
+ if (cs->mon_txc &&
+ (cs->mon_txp >= cs->mon_txc))
+ test_and_set_bit(HW_MON1_TX_END, &cs->HW_Flags);
goto AfterMOX1;
}
- if (cs->mon_txp >= cs->mon_txc) {
- if (cs->mon_txc)
- isac_sched_event(cs, D_TX_MON1);
+ if (cs->mon_txc && (cs->mon_txp >= cs->mon_txc)) {
+ test_and_set_bit(HW_MON1_TX_END, &cs->HW_Flags);
goto AfterMOX1;
}
cs->writeisac(cs, ISAC_MOX1,
cs->mon_tx[cs->mon_txp++]);
- if (cs->debug & L1_DEB_WARN) {
- sprintf(tmp, "ISAC %02x -> MOX1", cs->mon_tx[cs->mon_txp -1]);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_MONITOR)
+ debugl1(cs, "ISAC %02x -> MOX1", cs->mon_tx[cs->mon_txp -1]);
}
AfterMOX1:
#endif
@@ -470,14 +476,18 @@ isac_interrupt(struct IsdnCardState *cs, u_char val)
}
static void
-ISAC_l2l1(struct PStack *st, int pr, void *arg)
+ISAC_l1hw(struct PStack *st, int pr, void *arg)
{
struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
struct sk_buff *skb = arg;
- char str[64];
+ int val;
switch (pr) {
- case (PH_DATA_REQ):
+ case (PH_DATA |REQUEST):
+ if (cs->debug & DEB_DLOG_HEX)
+ LogFrame(cs, skb->data, skb->len);
+ if (cs->debug & DEB_DLOG_VERBOSE)
+ dlogframe(cs, skb, 0);
if (cs->tx_skb) {
skb_queue_tail(&cs->sq, skb);
#ifdef L2FRAME_DEBUG /* psa */
@@ -485,12 +495,6 @@ ISAC_l2l1(struct PStack *st, int pr, void *arg)
Logl2Frame(cs, skb, "PH_DATA Queued", 0);
#endif
} else {
- if ((cs->dlogflag) && (!(skb->data[2] & 1))) { /* I-FRAME */
- LogFrame(cs, skb->data, skb->len);
- sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
- dlogframe(cs, skb->data + 4, skb->len - 4,
- str);
- }
cs->tx_skb = skb;
cs->tx_cnt = 0;
#ifdef L2FRAME_DEBUG /* psa */
@@ -500,19 +504,17 @@ ISAC_l2l1(struct PStack *st, int pr, void *arg)
isac_fill_fifo(cs);
}
break;
- case (PH_PULL_IND):
+ case (PH_PULL |INDICATION):
if (cs->tx_skb) {
if (cs->debug & L1_DEB_WARN)
debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
skb_queue_tail(&cs->sq, skb);
break;
}
- if ((cs->dlogflag) && (!(skb->data[2] & 1))) { /* I-FRAME */
+ if (cs->debug & DEB_DLOG_HEX)
LogFrame(cs, skb->data, skb->len);
- sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
- dlogframe(cs, skb->data + 4, skb->len - 4,
- str);
- }
+ if (cs->debug & DEB_DLOG_VERBOSE)
+ dlogframe(cs, skb, 0);
cs->tx_skb = skb;
cs->tx_cnt = 0;
#ifdef L2FRAME_DEBUG /* psa */
@@ -521,28 +523,18 @@ ISAC_l2l1(struct PStack *st, int pr, void *arg)
#endif
isac_fill_fifo(cs);
break;
- case (PH_PULL_REQ):
+ case (PH_PULL | REQUEST):
#ifdef L2FRAME_DEBUG /* psa */
if (cs->debug & L1_DEB_LAPD)
debugl1(cs, "-> PH_REQUEST_PULL");
#endif
if (!cs->tx_skb) {
test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
- st->l1.l1l2(st, PH_PULL_CNF, NULL);
+ st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
} else
test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
break;
- }
-}
-
-void
-isac_l1cmd(struct IsdnCardState *cs, int msg, void *arg)
-{
- u_char val;
- char tmp[32];
-
- switch(msg) {
- case PH_RESET_REQ:
+ case (HW_RESET | REQUEST):
if ((cs->ph_state == ISAC_IND_EI) ||
(cs->ph_state == ISAC_IND_DR) ||
(cs->ph_state == ISAC_IND_RS))
@@ -550,17 +542,17 @@ isac_l1cmd(struct IsdnCardState *cs, int msg, void *arg)
else
ph_command(cs, ISAC_CMD_RS);
break;
- case PH_ENABLE_REQ:
+ case (HW_ENABLE | REQUEST):
ph_command(cs, ISAC_CMD_TIM);
break;
- case PH_INFO3_REQ:
+ case (HW_INFO3 | REQUEST):
ph_command(cs, ISAC_CMD_AR8);
break;
- case PH_TESTLOOP_REQ:
+ case (HW_TESTLOOP | REQUEST):
val = 0;
- if (1 & (int) arg)
+ if (1 & (long) arg)
val |= 0x0c;
- if (2 & (int) arg)
+ if (2 & (long) arg)
val |= 0x3;
if (test_bit(HW_IOM1, &cs->HW_Flags)) {
/* IOM 1 Mode */
@@ -580,11 +572,21 @@ isac_l1cmd(struct IsdnCardState *cs, int msg, void *arg)
cs->writeisac(cs, ISAC_ADF1, 0x0);
}
break;
- default:
- if (cs->debug & L1_DEB_WARN) {
- sprintf(tmp, "isac_l1cmd unknown %4x", msg);
- debugl1(cs, tmp);
+ case (HW_DEACTIVATE | RESPONSE):
+ discard_queue(&cs->rq);
+ discard_queue(&cs->sq);
+ if (cs->tx_skb) {
+ dev_kfree_skb(cs->tx_skb);
+ cs->tx_skb = NULL;
}
+ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+ del_timer(&cs->dbusytimer);
+ if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+ isac_sched_event(cs, D_CLEARBUSY);
+ break;
+ default:
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "isac_l1hw unknown %04x", pr);
break;
}
}
@@ -592,22 +594,29 @@ isac_l1cmd(struct IsdnCardState *cs, int msg, void *arg)
void
setstack_isac(struct PStack *st, struct IsdnCardState *cs)
{
- st->l2.l2l1 = ISAC_l2l1;
+ st->l1.l1hw = ISAC_l1hw;
}
static void
dbusy_timer_handler(struct IsdnCardState *cs)
{
struct PStack *stptr;
+ int val;
if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
- if (cs->debug)
+ if (cs->debug) {
debugl1(cs, "D-Channel Busy");
+ val = cs->readisac(cs, ISAC_RBCH);
+ if (val & ISAC_RBCH_XAC)
+ debugl1(cs, "ISAC XAC");
+ else
+ debugl1(cs, "ISAC No XAC");
+ }
test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
stptr = cs->stlist;
while (stptr != NULL) {
- stptr->l1.l1l2(stptr, PH_PAUSE_IND, NULL);
+ stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
stptr = stptr->next;
}
}
@@ -617,7 +626,6 @@ HISAX_INITFUNC(void
initisac(struct IsdnCardState *cs))
{
cs->tqueue.routine = (void *) (void *) isac_bh;
- cs->l1cmd = isac_l1cmd;
cs->setstack_d = setstack_isac;
cs->dbusytimer.function = (void *) dbusy_timer_handler;
cs->dbusytimer.data = (long) cs;
@@ -648,35 +656,24 @@ initisac(struct IsdnCardState *cs))
HISAX_INITFUNC(void
clear_pending_isac_ints(struct IsdnCardState *cs))
{
- int val;
- char tmp[64];
+ int val, eval;
val = cs->readisac(cs, ISAC_STAR);
- sprintf(tmp, "ISAC STAR %x", val);
- debugl1(cs, tmp);
+ debugl1(cs, "ISAC STAR %x", val);
val = cs->readisac(cs, ISAC_MODE);
- sprintf(tmp, "ISAC MODE %x", val);
- debugl1(cs, tmp);
+ debugl1(cs, "ISAC MODE %x", val);
val = cs->readisac(cs, ISAC_ADF2);
- sprintf(tmp, "ISAC ADF2 %x", val);
- debugl1(cs, tmp);
+ debugl1(cs, "ISAC ADF2 %x", val);
val = cs->readisac(cs, ISAC_ISTA);
- sprintf(tmp, "ISAC ISTA %x", val);
- debugl1(cs, tmp);
+ debugl1(cs, "ISAC ISTA %x", val);
if (val & 0x01) {
- val = cs->readisac(cs, ISAC_EXIR);
- sprintf(tmp, "ISAC EXIR %x", val);
- debugl1(cs, tmp);
- } else if (val & 0x04) {
- val = cs->readisac(cs, ISAC_CIR0);
- sprintf(tmp, "ISAC CIR0 %x", val);
- debugl1(cs, tmp);
- cs->ph_state = (val >> 2) & 0xf;
- } else {
- cs->ph_state = (cs->readisac(cs, ISAC_CIX0) >> 2) & 0xf;
+ eval = cs->readisac(cs, ISAC_EXIR);
+ debugl1(cs, "ISAC EXIR %x", eval);
}
+ val = cs->readisac(cs, ISAC_CIR0);
+ debugl1(cs, "ISAC CIR0 %x", val);
+ cs->ph_state = (val >> 2) & 0xf;
isac_sched_event(cs, D_L1STATECHANGE);
+ /* Disable all IRQ */
cs->writeisac(cs, ISAC_MASK, 0xFF);
- cs->writeisac(cs, ISAC_MASK, 0);
- cs->writeisac(cs, ISAC_CMDR, 0x41);
}
diff --git a/drivers/isdn/hisax/isac.h b/drivers/isdn/hisax/isac.h
index ac4d55647..bed887d4f 100644
--- a/drivers/isdn/hisax/isac.h
+++ b/drivers/isdn/hisax/isac.h
@@ -1,4 +1,4 @@
-/* $Id: isac.h,v 1.4 1997/10/29 19:09:34 keil Exp $
+/* $Id: isac.h,v 1.5 1998/05/25 12:58:03 keil Exp $
* isac.h ISAC specific defines
*
@@ -6,6 +6,10 @@
*
*
* $Log: isac.h,v $
+ * Revision 1.5 1998/05/25 12:58:03 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
* Revision 1.4 1997/10/29 19:09:34 keil
* new L1
*
@@ -26,16 +30,18 @@
#define ISAC_STAR 0x21
#define ISAC_CMDR 0x21
#define ISAC_EXIR 0x24
-#define ISAC_RBCH 0x2a
#define ISAC_ADF2 0x39
#define ISAC_SPCR 0x30
#define ISAC_ADF1 0x38
#define ISAC_CIR0 0x31
#define ISAC_CIX0 0x31
+#define ISAC_CIR1 0x33
+#define ISAC_CIX1 0x33
#define ISAC_STCR 0x37
#define ISAC_MODE 0x22
#define ISAC_RSTA 0x27
#define ISAC_RBCL 0x25
+#define ISAC_RBCH 0x2A
#define ISAC_TIMR 0x23
#define ISAC_SQXR 0x3b
#define ISAC_MOSR 0x3a
@@ -45,6 +51,8 @@
#define ISAC_MOR1 0x34
#define ISAC_MOX1 0x34
+#define ISAC_RBCH_XAC 0x80
+
#define ISAC_CMD_TIM 0x0
#define ISAC_CMD_RS 0x1
#define ISAC_CMD_SCZ 0x4
diff --git a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c
index b249b2c47..c8f88a162 100644
--- a/drivers/isdn/hisax/isdnl1.c
+++ b/drivers/isdn/hisax/isdnl1.c
@@ -1,9 +1,13 @@
-/* $Id: isdnl1.c,v 2.18 1998/02/12 23:07:42 keil Exp $
+/* $Id: isdnl1.c,v 2.31 1998/11/15 23:54:56 keil Exp $
* isdnl1.c common low level stuff for Siemens Chipsetbased isdn cards
* based on the teles driver from Jan den Ouden
*
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
+ *
+ * This file is (c) under GNU PUBLIC LICENSE
+ * For changes and modifications please read
+ * ../../../Documentation/isdn/HiSax.cert
*
* Thanks to Jan den Ouden
* Fritz Elfert
@@ -11,6 +15,43 @@
*
*
* $Log: isdnl1.c,v $
+ * Revision 2.31 1998/11/15 23:54:56 keil
+ * changes from 2.0
+ *
+ * Revision 2.30 1998/09/30 22:27:00 keil
+ * Add init of l1.Flags
+ *
+ * Revision 2.29 1998/09/27 23:54:43 keil
+ * cosmetics
+ *
+ * Revision 2.28 1998/09/27 12:52:23 keil
+ * Fix against segfault, if the driver cannot allocate an IRQ channel
+ *
+ * Revision 2.27 1998/08/13 23:36:39 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.26 1998/07/15 15:01:31 calle
+ * Support for AVM passive PCMCIA cards:
+ * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0
+ *
+ * Revision 2.25 1998/05/25 14:10:09 keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.24 1998/05/25 12:58:04 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.22 1998/04/15 16:40:13 keil
+ * Add S0Box and Teles PCI support
+ * Fix cardnr overwrite bug
+ *
+ * Revision 2.21 1998/04/10 10:35:28 paul
+ * fixed (silly?) warnings from egcs on Alpha.
+ *
+ * Revision 2.20 1998/03/09 23:19:27 keil
+ * Changes for PCMCIA
+ *
* Revision 2.18 1998/02/12 23:07:42 keil
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
@@ -79,102 +120,20 @@
*
*/
-const char *l1_revision = "$Revision: 2.18 $";
+const char *l1_revision = "$Revision: 2.31 $";
#define __NO_VERSION__
-#include <linux/config.h>
#include "hisax.h"
#include "isdnl1.h"
-#include <linux/kernel_stat.h>
-#if (LINUX_VERSION_CODE < 0x020150) /* 2.1.80 */
-#define kstat_irqs( PAR ) kstat.interrupts( (PAR) )
-#endif
-
-
-
-#if CARD_TELES0
-extern int setup_teles0(struct IsdnCard *card);
-#endif
-
-#if CARD_TELES3
-extern int setup_teles3(struct IsdnCard *card);
-#endif
-
-#if CARD_AVM_A1
-extern int setup_avm_a1(struct IsdnCard *card);
-#endif
-
-#if CARD_ELSA
-extern int setup_elsa(struct IsdnCard *card);
-#endif
-
-#if CARD_IX1MICROR2
-extern int setup_ix1micro(struct IsdnCard *card);
-#endif
-
-#if CARD_DIEHLDIVA
-extern int setup_diva(struct IsdnCard *card);
-#endif
-
-#if CARD_ASUSCOM
-extern int setup_asuscom(struct IsdnCard *card);
-#endif
-
-#if CARD_TELEINT
-extern int setup_TeleInt(struct IsdnCard *card);
-#endif
-
-#if CARD_SEDLBAUER
-extern int setup_sedlbauer(struct IsdnCard *card);
-#endif
-
-#if CARD_SPORTSTER
-extern int setup_sportster(struct IsdnCard *card);
-#endif
-
-#if CARD_MIC
-extern int setup_mic(struct IsdnCard *card);
-#endif
-
-#if CARD_NETJET
-extern int setup_netjet(struct IsdnCard *card);
-#endif
-
-#if CARD_TELES3C
-extern int setup_t163c(struct IsdnCard *card);
-#endif
-#if CARD_AMD7930 || CARD_DBRI
-extern int setup_foreign(struct IsdnCard *card);
-#endif
-
-#if CARD_NICCY
-extern int setup_niccy(struct IsdnCard *card);
-#endif
-
-#define HISAX_STATUS_BUFSIZE 4096
-#define ISDN_CTRL_DEBUG 1
-#define INCLUDE_INLINE_FUNCS
-#include <linux/tqueue.h>
-#include <linux/interrupt.h>
-const char *CardType[] =
-{"No Card", "Teles 16.0", "Teles 8.0", "Teles 16.3", "Creatix/Teles PnP",
- "AVM A1", "Elsa ML", "Elsa Quickstep", "Teles PCMCIA", "ITK ix1-micro Rev.2",
- "Elsa PCMCIA", "Eicon.Diehl Diva", "ISDNLink", "TeleInt", "Teles 16.3c",
- "Sedlbauer Speed Card", "USR Sportster", "ith mic Linux", "Elsa PCI",
- "Compaq ISA", "NETjet", "Teles PCI", "Sedlbauer Speed Star (PCMCIA)",
- "AMD 7930", "NICCY", "DBRI"
-};
+#define TIMER3_VALUE 7000
-extern struct IsdnCard cards[];
-extern int nrcards;
-extern char *HiSax_id;
-extern struct IsdnBuffers *tracebuf;
-
-#define TIMER3_VALUE 7
+static
+struct Fsm l1fsm_b =
+{NULL, 0, 0, NULL, NULL};
static
-struct Fsm l1fsm =
+struct Fsm l1fsm_d =
{NULL, 0, 0, NULL, NULL};
enum {
@@ -187,9 +146,9 @@ enum {
ST_L1_F8,
};
-#define L1_STATE_COUNT (ST_L1_F8+1)
+#define L1D_STATE_COUNT (ST_L1_F8+1)
-static char *strL1State[] =
+static char *strL1DState[] =
{
"ST_L1_F2",
"ST_L1_F3",
@@ -201,7 +160,25 @@ static char *strL1State[] =
};
enum {
+ ST_L1_NULL,
+ ST_L1_WAIT_ACT,
+ ST_L1_WAIT_DEACT,
+ ST_L1_ACTIV,
+};
+
+#define L1B_STATE_COUNT (ST_L1_ACTIV+1)
+
+static char *strL1BState[] =
+{
+ "ST_L1_NULL",
+ "ST_L1_WAIT_ACT",
+ "ST_L1_WAIT_DEACT",
+ "ST_L1_ACTIV",
+};
+
+enum {
EV_PH_ACTIVATE,
+ EV_PH_DEACTIVATE,
EV_RESET_IND,
EV_DEACT_CNF,
EV_DEACT_IND,
@@ -219,6 +196,7 @@ enum {
static char *strL1Event[] =
{
"EV_PH_ACTIVATE",
+ "EV_PH_DEACTIVATE",
"EV_RESET_IND",
"EV_DEACT_CNF",
"EV_DEACT_IND",
@@ -231,154 +209,30 @@ static char *strL1Event[] =
"EV_TIMER3",
};
-/*
- * Find card with given driverId
- */
-static inline struct IsdnCardState
-*hisax_findcard(int driverid)
-{
- int i;
-
- for (i = 0; i < nrcards; i++)
- if (cards[i].cs)
- if (cards[i].cs->myid == driverid)
- return (cards[i].cs);
- return (NULL);
-}
-
-int
-HiSax_readstatus(u_char * buf, int len, int user, int id, int channel)
-{
- int count;
- u_char *p;
- struct IsdnCardState *csta = hisax_findcard(id);
-
- if (csta) {
- for (p = buf, count = 0; count < len; p++, count++) {
- if (user)
- put_user(*csta->status_read++, p);
- else
- *p++ = *csta->status_read++;
- if (csta->status_read > csta->status_end)
- csta->status_read = csta->status_buf;
- }
- return count;
- } else {
- printk(KERN_ERR
- "HiSax: if_readstatus called with invalid driverId!\n");
- return -ENODEV;
- }
-}
-
-#if ISDN_CTRL_DEBUG
-void
-HiSax_putstatus(struct IsdnCardState *csta, char *buf)
-{
- long flags;
- int len, count, i;
- u_char *p;
- isdn_ctrl ic;
-
- save_flags(flags);
- cli();
- count = 0;
- len = strlen(buf);
-
- if (!csta) {
- printk(KERN_WARNING "HiSax: No CardStatus for message %s", buf);
- restore_flags(flags);
- return;
- }
- for (p = buf, i = len; i > 0; i--, p++) {
- *csta->status_write++ = *p;
- if (csta->status_write > csta->status_end)
- csta->status_write = csta->status_buf;
- count++;
- }
- restore_flags(flags);
- if (count) {
- ic.command = ISDN_STAT_STAVAIL;
- ic.driver = csta->myid;
- ic.arg = count;
- csta->iif.statcallb(&ic);
- }
-}
-#else
-#define KDEBUG_DEF
-#include "../kdebug.h"
-
-static int DbgLineNr=0,DbgSequenzNr=1;
-
void
-HiSax_putstatus(struct IsdnCardState *csta, char *buf)
+debugl1(struct IsdnCardState *cs, char *fmt, ...)
{
- char tmp[512];
+ va_list args;
+ char tmp[8];
- if (DbgLineNr==23)
- DbgLineNr=0;
- sprintf(tmp, "%5d %s",DbgSequenzNr++,buf);
- gput_str(tmp,0,DbgLineNr++);
-}
-#endif
-
-int
-ll_run(struct IsdnCardState *csta)
-{
- long flags;
- isdn_ctrl ic;
-
- save_flags(flags);
- cli();
- ic.driver = csta->myid;
- ic.command = ISDN_STAT_RUN;
- csta->iif.statcallb(&ic);
- restore_flags(flags);
- return 0;
-}
-
-void
-ll_stop(struct IsdnCardState *csta)
-{
- isdn_ctrl ic;
-
- ic.command = ISDN_STAT_STOP;
- ic.driver = csta->myid;
- csta->iif.statcallb(&ic);
- CallcFreeChan(csta);
+ va_start(args, fmt);
+ sprintf(tmp, "Card%d ", cs->cardnr + 1);
+ VHiSax_putstatus(cs, tmp, fmt, args);
+ va_end(args);
}
static void
-ll_unload(struct IsdnCardState *csta)
-{
- isdn_ctrl ic;
-
- ic.command = ISDN_STAT_UNLOAD;
- ic.driver = csta->myid;
- csta->iif.statcallb(&ic);
- if (csta->status_buf)
- kfree(csta->status_buf);
- csta->status_read = NULL;
- csta->status_write = NULL;
- csta->status_end = NULL;
- kfree(csta->dlogspace);
-}
-
-void
-debugl1(struct IsdnCardState *cs, char *msg)
-{
- char tmp[1024], tm[32];
-
- jiftime(tm, jiffies);
- sprintf(tmp, "%s Card %d %s\n", tm, cs->cardnr + 1, msg);
- HiSax_putstatus(cs, tmp);
-}
-
-static void
-l1m_debug(struct FsmInst *fi, char *s)
+l1m_debug(struct FsmInst *fi, char *fmt, ...)
{
+ va_list args;
struct PStack *st = fi->userdata;
+ struct IsdnCardState *cs = st->l1.hardware;
+ char tmp[8];
- debugl1(st->l1.hardware, s);
+ va_start(args, fmt);
+ sprintf(tmp, "Card%d ", cs->cardnr + 1);
+ VHiSax_putstatus(cs, tmp, fmt, args);
+ va_end(args);
}
void
@@ -389,9 +243,9 @@ L1activated(struct IsdnCardState *cs)
st = cs->stlist;
while (st) {
if (test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags))
- st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
+ st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
else
- st->l1.l1man(st, PH_ACTIVATE_IND, NULL);
+ st->l1.l1l2(st, PH_ACTIVATE | INDICATION, NULL);
st = st->next;
}
}
@@ -404,8 +258,8 @@ L1deactivated(struct IsdnCardState *cs)
st = cs->stlist;
while (st) {
if (test_bit(FLG_L1_DBUSY, &cs->HW_Flags))
- st->l1.l1l2(st, PH_PAUSE_CNF, NULL);
- st->l1.l1man(st, PH_DEACTIVATE_IND, NULL);
+ st->l1.l1l2(st, PH_PAUSE | CONFIRM, NULL);
+ st->l1.l1l2(st, PH_DEACTIVATE | INDICATION, NULL);
st = st->next;
}
test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags);
@@ -422,7 +276,7 @@ DChannel_proc_xmt(struct IsdnCardState *cs)
stptr = cs->stlist;
while (stptr != NULL)
if (test_and_clear_bit(FLG_L1_PULL_REQ, &stptr->l1.Flags)) {
- stptr->l1.l1l2(stptr, PH_PULL_CNF, NULL);
+ stptr->l1.l1l2(stptr, PH_PULL | CONFIRM, NULL);
break;
} else
stptr = stptr->next;
@@ -434,7 +288,6 @@ DChannel_proc_rcv(struct IsdnCardState *cs)
struct sk_buff *skb, *nskb;
struct PStack *stptr = cs->stlist;
int found, tei, sapi;
- char tmp[64];
if (stptr)
if (test_bit(FLG_L1_ACTTIMER, &stptr->l1.Flags))
@@ -448,16 +301,15 @@ DChannel_proc_rcv(struct IsdnCardState *cs)
sapi = skb->data[0] >> 2;
tei = skb->data[1] >> 1;
+ if (cs->debug & DEB_DLOG_HEX)
+ LogFrame(cs, skb->data, skb->len);
+ if (cs->debug & DEB_DLOG_VERBOSE)
+ dlogframe(cs, skb, 1);
if (tei == GROUP_TEI) {
- if (sapi == CTRL_SAPI) { /* sapi 0 */
- if (cs->dlogflag) {
- LogFrame(cs, skb->data, skb->len);
- dlogframe(cs, skb->data + 3, skb->len - 3,
- "Q.931 frame network->user broadcast");
- }
+ if (sapi == CTRL_SAPI) { /* sapi 0 */
while (stptr != NULL) {
if ((nskb = skb_clone(skb, GFP_ATOMIC)))
- stptr->l1.l1l2(stptr, PH_DATA_IND, nskb);
+ stptr->l1.l1l2(stptr, PH_DATA | INDICATION, nskb);
else
printk(KERN_WARNING "HiSax: isdn broadcast buffer shortage\n");
stptr = stptr->next;
@@ -465,37 +317,24 @@ DChannel_proc_rcv(struct IsdnCardState *cs)
} else if (sapi == TEI_SAPI) {
while (stptr != NULL) {
if ((nskb = skb_clone(skb, GFP_ATOMIC)))
- stptr->l1.l1tei(stptr, PH_DATA_IND, nskb);
+ stptr->l1.l1tei(stptr, PH_DATA | INDICATION, nskb);
else
printk(KERN_WARNING "HiSax: tei broadcast buffer shortage\n");
stptr = stptr->next;
}
}
dev_kfree_skb(skb);
- } else if (sapi == CTRL_SAPI) {
+ } else if (sapi == CTRL_SAPI) { /* sapi 0 */
found = 0;
while (stptr != NULL)
if (tei == stptr->l2.tei) {
- stptr->l1.l1l2(stptr, PH_DATA_IND, skb);
+ stptr->l1.l1l2(stptr, PH_DATA | INDICATION, skb);
found = !0;
break;
} else
stptr = stptr->next;
- if (!found) {
- /* BD 10.10.95
- * Print out D-Channel msg not processed
- * by isdn4linux
- */
-
- if ((!(skb->data[0] >> 2)) && (!(skb->data[2] & 0x01))) {
- sprintf(tmp,
- "Q.931 frame network->user with tei %d (not for us)",
- skb->data[1] >> 1);
- LogFrame(cs, skb->data, skb->len);
- dlogframe(cs, skb->data + 4, skb->len - 4, tmp);
- }
+ if (!found)
dev_kfree_skb(skb);
- }
}
}
}
@@ -505,14 +344,18 @@ BChannel_proc_xmt(struct BCState *bcs)
{
struct PStack *st = bcs->st;
- if (test_bit(BC_FLG_BUSY, &bcs->Flag))
+ if (test_bit(BC_FLG_BUSY, &bcs->Flag)) {
+ debugl1(bcs->cs, "BC_BUSY Error");
return;
+ }
if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags))
- st->l1.l1l2(st, PH_PULL_CNF, NULL);
- if (!test_bit(BC_FLG_ACTIV, &bcs->Flag))
- if (!test_bit(BC_FLG_BUSY, &bcs->Flag) && (!skb_queue_len(&bcs->squeue)))
- st->ma.manl1(st, PH_DEACTIVATE_CNF, 0);
+ st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+ if (!test_bit(BC_FLG_ACTIV, &bcs->Flag)) {
+ if (!test_bit(BC_FLG_BUSY, &bcs->Flag) && (!skb_queue_len(&bcs->squeue))) {
+ st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL);
+ }
+ }
}
static void
@@ -520,8 +363,12 @@ BChannel_proc_rcv(struct BCState *bcs)
{
struct sk_buff *skb;
+ if (bcs->st->l1.l1m.state == ST_L1_WAIT_ACT) {
+ FsmDelTimer(&bcs->st->l1.timer, 4);
+ FsmEvent(&bcs->st->l1.l1m, EV_TIMER_ACT, NULL);
+ }
while ((skb = skb_dequeue(&bcs->rqueue))) {
- bcs->st->l1.l1l2(bcs->st, PH_DATA_IND, skb);
+ bcs->st->l1.l1l2(bcs->st, PH_DATA | INDICATION, skb);
}
}
@@ -581,443 +428,6 @@ init_bcstate(struct IsdnCardState *cs,
bcs->Flag = 0;
}
-static void
-closecard(int cardnr)
-{
- struct IsdnCardState *csta = cards[cardnr].cs;
- struct sk_buff *skb;
-
- if (csta->bcs->BC_Close != NULL) {
- csta->bcs->BC_Close(csta->bcs + 1);
- csta->bcs->BC_Close(csta->bcs);
- }
-
- if (csta->rcvbuf) {
- kfree(csta->rcvbuf);
- csta->rcvbuf = NULL;
- }
- while ((skb = skb_dequeue(&csta->rq))) {
- dev_kfree_skb(skb);
- }
- while ((skb = skb_dequeue(&csta->sq))) {
- dev_kfree_skb(skb);
- }
- if (csta->tx_skb) {
- dev_kfree_skb(csta->tx_skb);
- csta->tx_skb = NULL;
- }
- if (csta->mon_rx) {
- kfree(csta->mon_rx);
- csta->mon_rx = NULL;
- }
- if (csta->mon_tx) {
- kfree(csta->mon_tx);
- csta->mon_tx = NULL;
- }
- csta->cardmsg(csta, CARD_RELEASE, NULL);
- del_timer(&csta->dbusytimer);
- ll_unload(csta);
-}
-
-HISAX_INITFUNC(static int init_card(struct IsdnCardState *cs))
-{
- int irq_cnt, cnt = 3;
- long flags;
-
- save_flags(flags);
- cli();
- irq_cnt = kstat_irqs(cs->irq);
- printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ], cs->irq,
- irq_cnt);
- if (cs->cardmsg(cs, CARD_SETIRQ, NULL)) {
- printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n",
- cs->irq);
- return(1);
- }
- while (cnt) {
- cs->cardmsg(cs, CARD_INIT, NULL);
- sti();
- current->state = TASK_INTERRUPTIBLE;
- /* Timeout 10ms */
- schedule_timeout((10 * HZ) / 1000);
- restore_flags(flags);
- printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ],
- cs->irq, kstat_irqs(cs->irq));
- if (kstat_irqs(cs->irq) == irq_cnt) {
- printk(KERN_WARNING
- "%s: IRQ(%d) getting no interrupts during init %d\n",
- CardType[cs->typ], cs->irq, 4 - cnt);
- if (cnt == 1) {
- free_irq(cs->irq, cs);
- return (2);
- } else {
- cs->cardmsg(cs, CARD_RESET, NULL);
- cnt--;
- }
- } else {
- cs->cardmsg(cs, CARD_TEST, NULL);
- return(0);
- }
- }
- restore_flags(flags);
- return(3);
-}
-
-HISAX_INITFUNC(static int
-checkcard(int cardnr, char *id, int *busy_flag))
-{
- long flags;
- int ret = 0;
- struct IsdnCard *card = cards + cardnr;
- struct IsdnCardState *cs;
-
- save_flags(flags);
- cli();
- if (!(cs = (struct IsdnCardState *)
- kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC))) {
- printk(KERN_WARNING
- "HiSax: No memory for IsdnCardState(card %d)\n",
- cardnr + 1);
- restore_flags(flags);
- return (0);
- }
- card->cs = cs;
- cs->cardnr = cardnr;
- cs->debug = L1_DEB_WARN;
- cs->HW_Flags = 0;
- cs->busy_flag = busy_flag;
-#if TEI_PER_CARD
-#else
- test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
-#endif
- cs->protocol = card->protocol;
-
- if ((card->typ > 0) && (card->typ < 31)) {
- if (!((1 << card->typ) & SUPORTED_CARDS)) {
- printk(KERN_WARNING
- "HiSax: Support for %s Card not selected\n",
- CardType[card->typ]);
- restore_flags(flags);
- return (0);
- }
- } else {
- printk(KERN_WARNING
- "HiSax: Card Type %d out of range\n",
- card->typ);
- restore_flags(flags);
- return (0);
- }
- if (!(cs->dlogspace = kmalloc(4096, GFP_ATOMIC))) {
- printk(KERN_WARNING
- "HiSax: No memory for dlogspace(card %d)\n",
- cardnr + 1);
- restore_flags(flags);
- return (0);
- }
- if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) {
- printk(KERN_WARNING
- "HiSax: No memory for status_buf(card %d)\n",
- cardnr + 1);
- kfree(cs->dlogspace);
- restore_flags(flags);
- return (0);
- }
- cs->stlist = NULL;
- cs->dlogflag = 0;
- cs->mon_tx = NULL;
- cs->mon_rx = NULL;
- cs->status_read = cs->status_buf;
- cs->status_write = cs->status_buf;
- cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
- cs->typ = card->typ;
- strcpy(cs->iif.id, id);
- cs->iif.channels = 2;
- cs->iif.maxbufsize = MAX_DATA_SIZE;
- cs->iif.hl_hdrlen = MAX_HEADER_LEN;
- cs->iif.features =
- ISDN_FEATURE_L2_X75I |
- ISDN_FEATURE_L2_HDLC |
- ISDN_FEATURE_L2_TRANS |
- ISDN_FEATURE_L3_TRANS |
-#ifdef CONFIG_HISAX_1TR6
- ISDN_FEATURE_P_1TR6 |
-#endif
-#ifdef CONFIG_HISAX_EURO
- ISDN_FEATURE_P_EURO |
-#endif
-#ifdef CONFIG_HISAX_NI1
- ISDN_FEATURE_P_NI1 |
-#endif
- 0;
-
- cs->iif.command = HiSax_command;
- cs->iif.writecmd = NULL;
- cs->iif.writebuf_skb = HiSax_writebuf_skb;
- cs->iif.readstat = HiSax_readstatus;
- register_isdn(&cs->iif);
- cs->myid = cs->iif.channels;
- printk(KERN_INFO
- "HiSax: Card %d Protocol %s Id=%s (%d)\n", cardnr + 1,
- (card->protocol == ISDN_PTYPE_1TR6) ? "1TR6" :
- (card->protocol == ISDN_PTYPE_EURO) ? "EDSS1" :
- (card->protocol == ISDN_PTYPE_LEASED) ? "LEASED" :
- (card->protocol == ISDN_PTYPE_NI1) ? "NI1" :
- "NONE", cs->iif.id, cs->myid);
- switch (card->typ) {
-#if CARD_TELES0
- case ISDN_CTYPE_16_0:
- case ISDN_CTYPE_8_0:
- ret = setup_teles0(card);
- break;
-#endif
-#if CARD_TELES3
- case ISDN_CTYPE_16_3:
- case ISDN_CTYPE_PNP:
- case ISDN_CTYPE_TELESPCMCIA:
- case ISDN_CTYPE_COMPAQ_ISA:
- ret = setup_teles3(card);
- break;
-#endif
-#if CARD_AVM_A1
- case ISDN_CTYPE_A1:
- ret = setup_avm_a1(card);
- break;
-#endif
-#if CARD_ELSA
- case ISDN_CTYPE_ELSA:
- case ISDN_CTYPE_ELSA_PNP:
- case ISDN_CTYPE_ELSA_PCMCIA:
- case ISDN_CTYPE_ELSA_PCI:
- ret = setup_elsa(card);
- break;
-#endif
-#if CARD_IX1MICROR2
- case ISDN_CTYPE_IX1MICROR2:
- ret = setup_ix1micro(card);
- break;
-#endif
-#if CARD_DIEHLDIVA
- case ISDN_CTYPE_DIEHLDIVA:
- ret = setup_diva(card);
- break;
-#endif
-#if CARD_ASUSCOM
- case ISDN_CTYPE_ASUSCOM:
- ret = setup_asuscom(card);
- break;
-#endif
-#if CARD_TELEINT
- case ISDN_CTYPE_TELEINT:
- ret = setup_TeleInt(card);
- break;
-#endif
-#if CARD_SEDLBAUER
- case ISDN_CTYPE_SEDLBAUER:
- case ISDN_CTYPE_SEDLBAUER_PCMCIA:
- ret = setup_sedlbauer(card);
- break;
-#endif
-#if CARD_SPORTSTER
- case ISDN_CTYPE_SPORTSTER:
- ret = setup_sportster(card);
- break;
-#endif
-#if CARD_MIC
- case ISDN_CTYPE_MIC:
- ret = setup_mic(card);
- break;
-#endif
-#if CARD_NETJET
- case ISDN_CTYPE_NETJET:
- ret = setup_netjet(card);
- break;
-#endif
-#if CARD_TELES3C
- case ISDN_CTYPE_TELES3C:
- ret = setup_t163c(card);
- break;
-#endif
-#if CARD_NICCY
- case ISDN_CTYPE_NICCY:
- ret = setup_niccy(card);
- break;
-#endif
-#if CARD_AMD7930 || CARD_DBRI
- case ISDN_CTYPE_AMD7930:
- case ISDN_CTYPE_DBRI:
- ret = setup_foreign(card);
- break;
-#endif
- default:
- printk(KERN_WARNING "HiSax: Unknown Card Typ %d\n",
- card->typ);
- ll_unload(cs);
- restore_flags(flags);
- return (0);
- }
- if (!ret) {
- ll_unload(cs);
- restore_flags(flags);
- return (0);
- }
- if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN, GFP_ATOMIC))) {
- printk(KERN_WARNING
- "HiSax: No memory for isac rcvbuf\n");
- return (1);
- }
- cs->rcvidx = 0;
- cs->tx_skb = NULL;
- cs->tx_cnt = 0;
- cs->event = 0;
- cs->tqueue.next = 0;
- cs->tqueue.sync = 0;
- cs->tqueue.data = cs;
-
- skb_queue_head_init(&cs->rq);
- skb_queue_head_init(&cs->sq);
-
- init_bcstate(cs, 0);
- init_bcstate(cs, 1);
- ret = init_card(cs);
- if (ret) {
- closecard(cardnr);
- restore_flags(flags);
- return (0);
- }
- init_tei(cs, cs->protocol);
- CallcNewChan(cs);
- ll_run(cs);
- cs->l1cmd(cs, PH_RESET_REQ, NULL);
- restore_flags(flags);
- return (1);
-}
-
-HISAX_INITFUNC(void
-HiSax_shiftcards(int idx))
-{
- int i;
-
- for (i = idx; i < 15; i++)
- memcpy(&cards[i], &cards[i + 1], sizeof(cards[i]));
-}
-
-HISAX_INITFUNC(int
-HiSax_inithardware(int *busy_flag))
-{
- int foundcards = 0;
- int i = 0;
- int t = ',';
- int flg = 0;
- char *id;
- char *next_id = HiSax_id;
- char ids[20];
-
- if (strchr(HiSax_id, ','))
- t = ',';
- else if (strchr(HiSax_id, '%'))
- t = '%';
-
- while (i < nrcards) {
- if (cards[i].typ < 1)
- break;
- id = next_id;
- if ((next_id = strchr(id, t))) {
- *next_id++ = 0;
- strcpy(ids, id);
- flg = i + 1;
- } else {
- next_id = id;
- if (flg >= i)
- strcpy(ids, id);
- else
- sprintf(ids, "%s%d", id, i);
- }
- if (checkcard(i, ids, busy_flag)) {
- foundcards++;
- i++;
- } else {
- printk(KERN_WARNING "HiSax: Card %s not installed !\n",
- CardType[cards[i].typ]);
- if (cards[i].cs)
- kfree((void *) cards[i].cs);
- cards[i].cs = NULL;
- HiSax_shiftcards(i);
- }
- }
- return foundcards;
-}
-
-void
-HiSax_closehardware(void)
-{
- int i;
- long flags;
-
- save_flags(flags);
- cli();
- for (i = 0; i < nrcards; i++)
- if (cards[i].cs) {
- ll_stop(cards[i].cs);
- release_tei(cards[i].cs);
- closecard(i);
- free_irq(cards[i].cs->irq, cards[i].cs);
- kfree((void *) cards[i].cs);
- cards[i].cs = NULL;
- }
- Isdnl1Free();
- TeiFree();
- Isdnl2Free();
- CallcFree();
- restore_flags(flags);
-}
-
-void
-HiSax_reportcard(int cardnr)
-{
- struct IsdnCardState *cs = cards[cardnr].cs;
- struct PStack *stptr;
- struct l3_process *pc;
- int j, i = 1;
-
- printk(KERN_DEBUG "HiSax: reportcard No %d\n", cardnr + 1);
- printk(KERN_DEBUG "HiSax: Type %s\n", CardType[cs->typ]);
- printk(KERN_DEBUG "HiSax: debuglevel %x\n", cs->debug);
- printk(KERN_DEBUG "HiSax: HiSax_reportcard address 0x%lX\n",
- (ulong) & HiSax_reportcard);
- printk(KERN_DEBUG "HiSax: cs 0x%lX\n", (ulong) cs);
- printk(KERN_DEBUG "HiSax: cs stl 0x%lX\n", (ulong) & (cs->stlist));
- stptr = cs->stlist;
- while (stptr != NULL) {
- printk(KERN_DEBUG "HiSax: dst%d 0x%lX\n", i, (ulong) stptr);
- printk(KERN_DEBUG "HiSax: dst%d stp 0x%lX\n", i, (ulong) stptr->l1.stlistp);
- printk(KERN_DEBUG "HiSax: tei %d sapi %d\n",
- stptr->l2.tei, stptr->l2.sap);
- printk(KERN_DEBUG "HiSax: man 0x%lX\n", (ulong) stptr->ma.layer);
- pc = stptr->l3.proc;
- while (pc) {
- printk(KERN_DEBUG "HiSax: l3proc %x 0x%lX\n", pc->callref,
- (ulong) pc);
- printk(KERN_DEBUG "HiSax: state %d st 0x%lX chan 0x%lX\n",
- pc->state, (ulong) pc->st, (ulong) pc->chan);
- pc = pc->next;
- }
- stptr = stptr->next;
- i++;
- }
- for (j = 0; j < 2; j++) {
- printk(KERN_DEBUG "HiSax: ch%d 0x%lX\n", j,
- (ulong) & cs->channel[j]);
- stptr = cs->channel[j].b_st;
- i = 1;
- while (stptr != NULL) {
- printk(KERN_DEBUG "HiSax: b_st%d 0x%lX\n", i, (ulong) stptr);
- printk(KERN_DEBUG "HiSax: man 0x%lX\n", (ulong) stptr->ma.layer);
- stptr = stptr->next;
- i++;
- }
- }
-}
-
#ifdef L2FRAME_DEBUG /* psa */
char *
@@ -1052,7 +462,7 @@ l2cmd(u_char cmd)
}
}
-static char tmp[20];
+static char tmpdeb[32];
char *
l2frames(u_char * ptr)
@@ -1061,7 +471,7 @@ l2frames(u_char * ptr)
case 1:
case 5:
case 9:
- sprintf(tmp, "%s[%d](nr %d)", l2cmd(ptr[2]), ptr[3] & 1, ptr[3] >> 1);
+ sprintf(tmpdeb, "%s[%d](nr %d)", l2cmd(ptr[2]), ptr[3] & 1, ptr[3] >> 1);
break;
case 0x6f:
case 0x0f:
@@ -1070,36 +480,33 @@ l2frames(u_char * ptr)
case 0x63:
case 0x87:
case 0xaf:
- sprintf(tmp, "%s[%d]", l2cmd(ptr[2]), (ptr[2] & 0x10) >> 4);
+ sprintf(tmpdeb, "%s[%d]", l2cmd(ptr[2]), (ptr[2] & 0x10) >> 4);
break;
default:
if (!(ptr[2] & 1)) {
- sprintf(tmp, "I[%d](ns %d, nr %d)", ptr[3] & 1, ptr[2] >> 1, ptr[3] >> 1);
+ sprintf(tmpdeb, "I[%d](ns %d, nr %d)", ptr[3] & 1, ptr[2] >> 1, ptr[3] >> 1);
break;
} else
return "invalid command";
}
- return tmp;
+ return tmpdeb;
}
void
Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir)
{
- char tmp[132];
u_char *ptr;
ptr = skb->data;
if (ptr[0] & 1 || !(ptr[1] & 1))
- debugl1(cs, "Addres not LAPD");
- else {
- sprintf(tmp, "%s %s: %s%c (sapi %d, tei %d)",
+ debugl1(cs, "Address not LAPD");
+ else
+ debugl1(cs, "%s %s: %s%c (sapi %d, tei %d)",
(dir ? "<-" : "->"), buf, l2frames(ptr),
((ptr[0] & 2) >> 1) == dir ? 'C' : 'R', ptr[0] >> 2, ptr[1] >> 1);
- debugl1(cs, tmp);
- }
}
#endif
@@ -1113,11 +520,10 @@ static void
l1_deact_cnf(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
- struct IsdnCardState *cs = st->l1.hardware;
FsmChangeState(fi, ST_L1_F3);
if (test_bit(FLG_L1_ACTIVATING, &st->l1.Flags))
- cs->l1cmd(cs, PH_ENABLE_REQ, NULL);
+ st->l1.l1hw(st, HW_ENABLE | REQUEST, NULL);
}
static void
@@ -1126,24 +532,23 @@ l1_deact_req(struct FsmInst *fi, int event, void *arg)
struct PStack *st = fi->userdata;
FsmChangeState(fi, ST_L1_F3);
- if (!test_bit(FLG_L1_T3RUN, &st->l1.Flags)) {
+// if (!test_bit(FLG_L1_T3RUN, &st->l1.Flags)) {
FsmDelTimer(&st->l1.timer, 1);
FsmAddTimer(&st->l1.timer, 550, EV_TIMER_DEACT, NULL, 2);
test_and_set_bit(FLG_L1_DEACTTIMER, &st->l1.Flags);
- }
+// }
}
static void
l1_power_up(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
- struct IsdnCardState *cs = st->l1.hardware;
if (test_bit(FLG_L1_ACTIVATING, &st->l1.Flags)) {
FsmChangeState(fi, ST_L1_F4);
- cs->l1cmd(cs, PH_INFO3_REQ, NULL);
+ st->l1.l1hw(st, HW_INFO3 | REQUEST, NULL);
FsmDelTimer(&st->l1.timer, 1);
- FsmAddTimer(&st->l1.timer, TIMER3_VALUE * HZ, EV_TIMER3, NULL, 2);
+ FsmAddTimer(&st->l1.timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
test_and_set_bit(FLG_L1_T3RUN, &st->l1.Flags);
} else
FsmChangeState(fi, ST_L1_F3);
@@ -1165,20 +570,18 @@ static void
l1_info2_ind(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
- struct IsdnCardState *cs = st->l1.hardware;
FsmChangeState(fi, ST_L1_F6);
- cs->l1cmd(cs, PH_INFO3_REQ, NULL);
+ st->l1.l1hw(st, HW_INFO3 | REQUEST, NULL);
}
static void
l1_info4_ind(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
- struct IsdnCardState *cs = st->l1.hardware;
FsmChangeState(fi, ST_L1_F7);
- cs->l1cmd(cs, PH_INFO3_REQ, NULL);
+ st->l1.l1hw(st, HW_INFO3 | REQUEST, NULL);
if (test_and_clear_bit(FLG_L1_DEACTTIMER, &st->l1.Flags))
FsmDelTimer(&st->l1.timer, 4);
if (!test_bit(FLG_L1_ACTIVATED, &st->l1.Flags)) {
@@ -1193,50 +596,61 @@ static void
l1_timer3(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
- struct IsdnCardState *cs = st->l1.hardware;
-
+
test_and_clear_bit(FLG_L1_T3RUN, &st->l1.Flags);
- if (test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags))
- L1deactivated(cs);
- if (st->l1.l1m.state != ST_L1_F6)
- FsmChangeState(fi, ST_L1_F3);
+ if (test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags))
+ L1deactivated(st->l1.hardware);
+ if (st->l1.l1m.state != ST_L1_F6) {
+ FsmChangeState(fi, ST_L1_F3);
+ st->l1.l1hw(st, HW_ENABLE | REQUEST, NULL);
+ }
}
static void
l1_timer_act(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
- struct IsdnCardState *cs = st->l1.hardware;
test_and_clear_bit(FLG_L1_ACTTIMER, &st->l1.Flags);
test_and_set_bit(FLG_L1_ACTIVATED, &st->l1.Flags);
- L1activated(cs);
+ L1activated(st->l1.hardware);
}
static void
l1_timer_deact(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
- struct IsdnCardState *cs = st->l1.hardware;
test_and_clear_bit(FLG_L1_DEACTTIMER, &st->l1.Flags);
test_and_clear_bit(FLG_L1_ACTIVATED, &st->l1.Flags);
- L1deactivated(cs);
- cs->l1cmd(cs, PH_DEACT_ACK, NULL);
+ L1deactivated(st->l1.hardware);
+ st->l1.l1hw(st, HW_DEACTIVATE | RESPONSE, NULL);
}
static void
l1_activate(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
- struct IsdnCardState *cs = st->l1.hardware;
- cs->l1cmd(cs, PH_RESET_REQ, NULL);
+ st->l1.l1hw(st, HW_RESET | REQUEST, NULL);
}
-static struct FsmNode L1FnList[] HISAX_INITDATA =
+static void
+l1_activate_no(struct FsmInst *fi, int event, void *arg)
+{
+ struct PStack *st = fi->userdata;
+
+ if ((!test_bit(FLG_L1_DEACTTIMER, &st->l1.Flags)) && (!test_bit(FLG_L1_T3RUN, &st->l1.Flags))) {
+ test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags);
+ L1deactivated(st->l1.hardware);
+ }
+}
+
+static struct FsmNode L1DFnList[] HISAX_INITDATA =
{
{ST_L1_F3, EV_PH_ACTIVATE, l1_activate},
+ {ST_L1_F6, EV_PH_ACTIVATE, l1_activate_no},
+ {ST_L1_F8, EV_PH_ACTIVATE, l1_activate_no},
{ST_L1_F3, EV_RESET_IND, l1_reset},
{ST_L1_F4, EV_RESET_IND, l1_reset},
{ST_L1_F5, EV_RESET_IND, l1_reset},
@@ -1280,86 +694,159 @@ static struct FsmNode L1FnList[] HISAX_INITDATA =
{ST_L1_F8, EV_TIMER_DEACT, l1_timer_deact},
};
-#define L1_FN_COUNT (sizeof(L1FnList)/sizeof(struct FsmNode))
+#define L1D_FN_COUNT (sizeof(L1DFnList)/sizeof(struct FsmNode))
+
+static void
+l1b_activate(struct FsmInst *fi, int event, void *arg)
+{
+ struct PStack *st = fi->userdata;
+
+ FsmChangeState(fi, ST_L1_WAIT_ACT);
+ FsmAddTimer(&st->l1.timer, st->l1.delay, EV_TIMER_ACT, NULL, 2);
+}
+
+static void
+l1b_deactivate(struct FsmInst *fi, int event, void *arg)
+{
+ struct PStack *st = fi->userdata;
+
+ FsmChangeState(fi, ST_L1_WAIT_DEACT);
+ FsmAddTimer(&st->l1.timer, 10, EV_TIMER_DEACT, NULL, 2);
+}
+
+static void
+l1b_timer_act(struct FsmInst *fi, int event, void *arg)
+{
+ struct PStack *st = fi->userdata;
+
+ FsmChangeState(fi, ST_L1_ACTIV);
+ st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
+}
+
+static void
+l1b_timer_deact(struct FsmInst *fi, int event, void *arg)
+{
+ struct PStack *st = fi->userdata;
+
+ FsmChangeState(fi, ST_L1_NULL);
+ st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL);
+}
+
+static struct FsmNode L1BFnList[] HISAX_INITDATA =
+{
+ {ST_L1_NULL, EV_PH_ACTIVATE, l1b_activate},
+ {ST_L1_WAIT_ACT, EV_TIMER_ACT, l1b_timer_act},
+ {ST_L1_ACTIV, EV_PH_DEACTIVATE, l1b_deactivate},
+ {ST_L1_WAIT_DEACT, EV_TIMER_DEACT, l1b_timer_deact},
+};
+
+#define L1B_FN_COUNT (sizeof(L1BFnList)/sizeof(struct FsmNode))
HISAX_INITFUNC(void Isdnl1New(void))
{
- l1fsm.state_count = L1_STATE_COUNT;
- l1fsm.event_count = L1_EVENT_COUNT;
- l1fsm.strEvent = strL1Event;
- l1fsm.strState = strL1State;
- FsmNew(&l1fsm, L1FnList, L1_FN_COUNT);
+ l1fsm_d.state_count = L1D_STATE_COUNT;
+ l1fsm_d.event_count = L1_EVENT_COUNT;
+ l1fsm_d.strEvent = strL1Event;
+ l1fsm_d.strState = strL1DState;
+ FsmNew(&l1fsm_d, L1DFnList, L1D_FN_COUNT);
+ l1fsm_b.state_count = L1B_STATE_COUNT;
+ l1fsm_b.event_count = L1_EVENT_COUNT;
+ l1fsm_b.strEvent = strL1Event;
+ l1fsm_b.strState = strL1BState;
+ FsmNew(&l1fsm_b, L1BFnList, L1B_FN_COUNT);
}
void Isdnl1Free(void)
{
- FsmFree(&l1fsm);
+ FsmFree(&l1fsm_d);
+ FsmFree(&l1fsm_b);
}
static void
-dch_manl1(struct PStack *st, int pr,
- void *arg)
+dch_l2l1(struct PStack *st, int pr, void *arg)
{
struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
- char tmp[32];
switch (pr) {
- case PH_ACTIVATE_REQ:
- if (cs->debug) {
- sprintf(tmp, "PH_ACTIVATE_REQ %s",
- strL1State[st->l1.l1m.state]);
- debugl1(cs, tmp);
- }
+ case (PH_DATA | REQUEST):
+ case (PH_PULL | REQUEST):
+ case (PH_PULL |INDICATION):
+ st->l1.l1hw(st, pr, arg);
+ break;
+ case (PH_ACTIVATE | REQUEST):
+ if (cs->debug)
+ debugl1(cs, "PH_ACTIVATE_REQ %s",
+ strL1DState[st->l1.l1m.state]);
if (test_bit(FLG_L1_ACTIVATED, &st->l1.Flags))
- st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
+ st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
else {
test_and_set_bit(FLG_L1_ACTIVATING, &st->l1.Flags);
FsmEvent(&st->l1.l1m, EV_PH_ACTIVATE, arg);
}
break;
- case PH_DEACTIVATE_REQ:
- if (cs->debug) {
- sprintf(tmp, "PH_DEACTIVATE_REQ %s",
- strL1State[st->l1.l1m.state]);
- debugl1(cs, tmp);
- }
- break;
- case PH_TESTLOOP_REQ:
- if (1 & (int) arg)
+ case (PH_TESTLOOP | REQUEST):
+ if (1 & (long) arg)
debugl1(cs, "PH_TEST_LOOP B1");
- if (2 & (int) arg)
+ if (2 & (long) arg)
debugl1(cs, "PH_TEST_LOOP B2");
- if (!(3 & (int) arg))
+ if (!(3 & (long) arg))
debugl1(cs, "PH_TEST_LOOP DISABLED");
- cs->l1cmd(cs, PH_TESTLOOP_REQ, arg);
- break;
- case PH_RESET_IND:
- FsmEvent(&st->l1.l1m, EV_RESET_IND, arg);
- break;
- case PH_DEACT_CNF:
- FsmEvent(&st->l1.l1m, EV_DEACT_CNF, arg);
- break;
- case PH_DEACT_IND:
- FsmEvent(&st->l1.l1m, EV_DEACT_IND, arg);
+ st->l1.l1hw(st, HW_TESTLOOP | REQUEST, arg);
break;
- case PH_POWERUP_CNF:
- FsmEvent(&st->l1.l1m, EV_POWER_UP, arg);
- break;
- case PH_RSYNC_IND:
- FsmEvent(&st->l1.l1m, EV_RSYNC_IND, arg);
- break;
- case PH_INFO2_IND:
- FsmEvent(&st->l1.l1m, EV_INFO2_IND, arg);
+ default:
+ if (cs->debug)
+ debugl1(cs, "dch_l2l1 msg %04X unhandled", pr);
break;
- case PH_I4_P8_IND:
- case PH_I4_P10_IND:
- FsmEvent(&st->l1.l1m, EV_INFO4_IND, arg);
+ }
+}
+
+void
+l1_msg(struct IsdnCardState *cs, int pr, void *arg) {
+ struct PStack *st;
+
+ st = cs->stlist;
+
+ while (st) {
+ switch(pr) {
+ case (HW_RESET | INDICATION):
+ FsmEvent(&st->l1.l1m, EV_RESET_IND, arg);
+ break;
+ case (HW_DEACTIVATE | CONFIRM):
+ FsmEvent(&st->l1.l1m, EV_DEACT_CNF, arg);
+ break;
+ case (HW_DEACTIVATE | INDICATION):
+ FsmEvent(&st->l1.l1m, EV_DEACT_IND, arg);
+ break;
+ case (HW_POWERUP | CONFIRM):
+ FsmEvent(&st->l1.l1m, EV_POWER_UP, arg);
+ break;
+ case (HW_RSYNC | INDICATION):
+ FsmEvent(&st->l1.l1m, EV_RSYNC_IND, arg);
+ break;
+ case (HW_INFO2 | INDICATION):
+ FsmEvent(&st->l1.l1m, EV_INFO2_IND, arg);
+ break;
+ case (HW_INFO4_P8 | INDICATION):
+ case (HW_INFO4_P10 | INDICATION):
+ FsmEvent(&st->l1.l1m, EV_INFO4_IND, arg);
+ break;
+ default:
+ if (cs->debug)
+ debugl1(cs, "l1msg %04X unhandled", pr);
+ break;
+ }
+ st = st->next;
+ }
+}
+
+void
+l1_msg_b(struct PStack *st, int pr, void *arg) {
+ switch(pr) {
+ case (PH_ACTIVATE | REQUEST):
+ FsmEvent(&st->l1.l1m, EV_PH_ACTIVATE, NULL);
break;
- default:
- if (cs->debug) {
- sprintf(tmp, "dch_manl1 msg %04X unhandled", pr);
- debugl1(cs, tmp);
- }
+ case (PH_DEACTIVATE | REQUEST):
+ FsmEvent(&st->l1.l1m, EV_PH_DEACTIVATE, NULL);
break;
}
}
@@ -1369,7 +856,7 @@ setstack_HiSax(struct PStack *st, struct IsdnCardState *cs)
{
st->l1.hardware = cs;
st->protocol = cs->protocol;
- st->l1.l1m.fsm = &l1fsm;
+ st->l1.l1m.fsm = &l1fsm_d;
st->l1.l1m.state = ST_L1_F3;
st->l1.l1m.debug = cs->debug;
st->l1.l1m.userdata = st;
@@ -1379,7 +866,22 @@ setstack_HiSax(struct PStack *st, struct IsdnCardState *cs)
setstack_tei(st);
setstack_manager(st);
st->l1.stlistp = &(cs->stlist);
- st->ma.manl1 = dch_manl1;
+ st->l2.l2l1 = dch_l2l1;
st->l1.Flags = 0;
cs->setstack_d(st, cs);
}
+
+void
+setstack_l1_B(struct PStack *st)
+{
+ struct IsdnCardState *cs = st->l1.hardware;
+
+ st->l1.l1m.fsm = &l1fsm_b;
+ st->l1.l1m.state = ST_L1_NULL;
+ st->l1.l1m.debug = cs->debug;
+ st->l1.l1m.userdata = st;
+ st->l1.l1m.userint = 0;
+ st->l1.l1m.printdebug = l1m_debug;
+ st->l1.Flags = 0;
+ FsmInitTimer(&st->l1.l1m, &st->l1.timer);
+}
diff --git a/drivers/isdn/hisax/isdnl1.h b/drivers/isdn/hisax/isdnl1.h
index 71f081a07..01a96b7dd 100644
--- a/drivers/isdn/hisax/isdnl1.h
+++ b/drivers/isdn/hisax/isdnl1.h
@@ -1,6 +1,16 @@
-/* $Id: isdnl1.h,v 2.5 1998/02/02 13:36:58 keil Exp $
+/* $Id: isdnl1.h,v 2.8 1998/11/15 23:54:59 keil Exp $
* $Log: isdnl1.h,v $
+ * Revision 2.8 1998/11/15 23:54:59 keil
+ * changes from 2.0
+ *
+ * Revision 2.7 1998/09/30 22:21:55 keil
+ * cosmetics
+ *
+ * Revision 2.6 1998/05/25 12:58:06 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
* Revision 2.5 1998/02/02 13:36:58 keil
* more debug
*
@@ -22,21 +32,6 @@
*
*/
-
-#define L2FRAME_DEBUG
-
-/* DEBUG Level */
-
-#define L1_DEB_WARN 0x01
-#define L1_DEB_INTSTAT 0x02
-#define L1_DEB_ISAC 0x04
-#define L1_DEB_ISAC_FIFO 0x08
-#define L1_DEB_HSCX 0x10
-#define L1_DEB_HSCX_FIFO 0x20
-#define L1_DEB_LAPD 0x40
-#define L1_DEB_IPAC 0x80
-#define L1_DEB_RECEIVE_FRAME 0x100
-
#define D_RCVBUFREADY 0
#define D_XMTBUFREADY 1
#define D_L1STATECHANGE 2
@@ -49,11 +44,12 @@
#define B_RCVBUFREADY 0
#define B_XMTBUFREADY 1
-extern void debugl1(struct IsdnCardState *sp, char *msg);
+extern void debugl1(struct IsdnCardState *cs, char *fmt, ...);
extern void DChannel_proc_xmt(struct IsdnCardState *cs);
extern void DChannel_proc_rcv(struct IsdnCardState *cs);
-
+extern void l1_msg(struct IsdnCardState *cs, int pr, void *arg);
+extern void l1_msg_b(struct PStack *st, int pr, void *arg);
#ifdef L2FRAME_DEBUG
-extern void Logl2Frame(struct IsdnCardState *sp, struct sk_buff *skb, char *buf, int dir);
+extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir);
#endif
diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c
index 824ba16c3..ccef2682e 100644
--- a/drivers/isdn/hisax/isdnl2.c
+++ b/drivers/isdn/hisax/isdnl2.c
@@ -1,12 +1,42 @@
-/* $Id: isdnl2.c,v 2.7 1998/02/12 23:07:47 keil Exp $
+/* $Id: isdnl2.c,v 2.16 1998/11/15 23:55:01 keil Exp $
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
* based on the teles driver from Jan den Ouden
*
+ * This file is (c) under GNU PUBLIC LICENSE
+ * For changes and modifications please read
+ * ../../../Documentation/isdn/HiSax.cert
+ *
* Thanks to Jan den Ouden
* Fritz Elfert
*
* $Log: isdnl2.c,v $
+ * Revision 2.16 1998/11/15 23:55:01 keil
+ * changes from 2.0
+ *
+ * Revision 2.15 1998/08/13 23:36:42 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.14 1998/06/19 15:19:18 keil
+ * fix LAPB tx_cnt for none I-frames
+ *
+ * Revision 2.13 1998/06/18 23:17:20 keil
+ * LAPB bugfix
+ *
+ * Revision 2.12 1998/05/25 14:10:12 keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.11 1998/05/25 12:58:08 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.9 1998/04/10 10:35:30 paul
+ * fixed (silly?) warnings from egcs on Alpha.
+ *
+ * Revision 2.8 1998/03/07 22:57:04 tsbogend
+ * made HiSax working on Linux/Alpha
+ *
* Revision 2.7 1998/02/12 23:07:47 keil
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
@@ -25,7 +55,7 @@
* Old stuff is still in the separate branch.
*
* Revision 2.2 1997/07/31 11:49:05 keil
- * Eroor handling for no TEI assign
+ * Error handling for no TEI assign
*
* Revision 2.1 1997/07/27 21:34:38 keil
* cosmetics
@@ -41,9 +71,9 @@
#include "hisax.h"
#include "isdnl2.h"
-const char *l2_revision = "$Revision: 2.7 $";
+const char *l2_revision = "$Revision: 2.16 $";
-static void l2m_debug(struct FsmInst *fi, char *s);
+static void l2m_debug(struct FsmInst *fi, char *fmt, ...);
static
struct Fsm l2fsm =
@@ -91,7 +121,6 @@ enum {
EV_L2_MDL_ASSIGN,
EV_L2_MDL_REMOVE,
EV_L2_MDL_ERROR,
- EV_L2_MDL_NOTEIPROC,
EV_L1_DEACTIVATE,
EV_L2_T200,
EV_L2_T203,
@@ -117,7 +146,6 @@ static char *strL2Event[] =
"EV_L2_MDL_ASSIGN",
"EV_L2_MDL_REMOVE",
"EV_L2_MDL_ERROR",
- "EV_L2_MDL_NOTEIPROC",
"EV_L1_DEACTIVATE",
"EV_L2_T200",
"EV_L2_T203",
@@ -161,26 +189,6 @@ cansend(struct PStack *st)
return ((p1 < st->l2.window) && !test_bit(FLG_PEER_BUSY, &st->l2.flag));
}
-static void
-discard_i_queue(struct PStack *st)
-{
- struct sk_buff *skb;
-
- while ((skb = skb_dequeue(&st->l2.i_queue))) {
- dev_kfree_skb(skb);
- }
-}
-
-static void
-discard_ui_queue(struct PStack *st)
-{
- struct sk_buff *skb;
-
- while ((skb = skb_dequeue(&st->l2.ui_queue))) {
- dev_kfree_skb(skb);
- }
-}
-
inline void
clear_exception(struct Layer2 *l2)
{
@@ -224,20 +232,17 @@ sethdraddr(struct Layer2 *l2, u_char * header, int rsp)
}
}
-static void
-enqueue_ui(struct PStack *st,
- struct sk_buff *skb)
-{
- st->l2.l2l1(st, PH_DATA_REQ, skb);
-}
-
-static void
+inline static void
enqueue_super(struct PStack *st,
struct sk_buff *skb)
{
- st->l2.l2l1(st, PH_DATA_REQ, skb);
+ if (test_bit(FLG_LAPB, &st->l2.flag))
+ st->l1.bcs->tx_cnt += skb->len;
+ st->l2.l2l1(st, PH_DATA | REQUEST, skb);
}
+#define enqueue_ui(a, b) enqueue_super(a, b)
+
inline int
IsUI(u_char * data, int ext)
{
@@ -272,6 +277,16 @@ IsRR(u_char * data, int ext)
}
inline int
+IsSFrame(u_char * data, int ext)
+{
+ register u_char d = *data;
+
+ if (!ext)
+ d &= 0xf;
+ return(((d & 0xf3) == 1) && ((d & 0x0c) != 0x0c));
+}
+
+inline int
IsSABMX(u_char * data, int ext)
{
u_char d = data[0] & ~0x10;
@@ -393,15 +408,15 @@ l2_mdl_error(struct FsmInst *fi, int event, void *arg)
switch (event) {
case EV_L2_UA:
if (get_PollFlagFree(st, skb))
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'C');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'C');
else
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'D');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'D');
break;
case EV_L2_DM:
if (get_PollFlagFree(st, skb))
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'B');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'B');
else {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'E');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'E');
establishlink(fi);
test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
}
@@ -415,9 +430,16 @@ l2_dl_establish(struct FsmInst *fi, int event, void *arg)
struct PStack *st = fi->userdata;
int state = fi->state;
- FsmChangeState(fi, ST_L2_3);
- if (state == ST_L2_1)
- st->l2.l2tei(st, MDL_ASSIGN_IND, NULL);
+
+ if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
+ FsmChangeState(fi, ST_L2_4);
+ establishlink(fi);
+ test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
+ } else {
+ FsmChangeState(fi, ST_L2_3);
+ if (state == ST_L2_1)
+ st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL);
+ }
}
static void
@@ -444,7 +466,7 @@ l2_put_ui(struct FsmInst *fi, int event, void *arg)
skb_queue_tail(&st->l2.ui_queue, skb);
if (fi->state == ST_L2_1) {
FsmChangeState(fi, ST_L2_2);
- st->l2.l2tei(st, MDL_ASSIGN_IND, NULL);
+ st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL);
}
if (fi->state > ST_L2_3)
l2_send_ui(st);
@@ -458,10 +480,10 @@ l2_got_ui(struct FsmInst *fi, int event, void *arg)
skb_pull(skb, l2headersize(&st->l2, 1));
if (skb->len > st->l2.maxlen) {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'O');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'O');
FreeSkb(skb);
} else
- st->l2.l2l3(st, DL_UNIT_DATA, skb);
+ st->l2.l2l3(st, DL_UNIT_DATA | INDICATION, skb);
}
static void
@@ -470,7 +492,7 @@ l2_establish(struct FsmInst *fi, int event, void *arg)
struct PStack *st = fi->userdata;
if (fi->state != ST_L2_4)
- discard_i_queue(st);
+ discard_queue(&st->l2.i_queue);
if (fi->state != ST_L2_5)
establishlink(fi);
test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
@@ -482,13 +504,13 @@ l2_dl_release(struct FsmInst *fi, int event, void *arg)
struct PStack *st = fi->userdata;
if (fi->state == ST_L2_4) {
- st->l2.l2man(st, DL_RELEASE, NULL);
+ st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
return;
} else if (fi->state == ST_L2_5) {
test_and_set_bit(FLG_PEND_REL, &st->l2.flag);
return;
}
- discard_i_queue(st);
+ discard_queue(&st->l2.i_queue);
FsmChangeState(fi, ST_L2_6);
st->l2.rc = 0;
send_uframe(st, DISC | 0x10, CMD);
@@ -510,14 +532,14 @@ l2_got_SABMX(struct FsmInst *fi, int event, void *arg)
if (test_bit(FLG_ORIG, &st->l2.flag))
rsp = !rsp;
if (rsp) {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'L');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'L');
FreeSkb(skb);
if ((state == ST_L2_7) || (state == ST_L2_8))
establishlink(fi);
return;
}
if (skb->len != (l2addrsize(&st->l2) + 1)) {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
FreeSkb(skb);
if ((state == ST_L2_7) || (state == ST_L2_8))
establishlink(fi);
@@ -532,9 +554,9 @@ l2_got_SABMX(struct FsmInst *fi, int event, void *arg)
if (ST_L2_5 == state)
return;
if (ST_L2_4 != state) {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'F');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'F');
if (st->l2.vs != st->l2.va) {
- discard_i_queue(st);
+ discard_queue(&st->l2.i_queue);
est = 1;
} else
est = 0;
@@ -547,14 +569,14 @@ l2_got_SABMX(struct FsmInst *fi, int event, void *arg)
FsmChangeState(fi, ST_L2_7);
if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
FsmDelTimer(&st->l2.t200, 2);
- FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3);
+ FsmRestartTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3);
if (est)
- st->l2.l2man(st, DL_ESTABLISH, NULL);
+ st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL);
if (ST_L2_8 == state)
if (skb_queue_len(&st->l2.i_queue) && cansend(st))
- st->l2.l2l1(st, PH_PULL_REQ, NULL);
+ st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
}
static void
@@ -571,14 +593,14 @@ l2_got_disconn(struct FsmInst *fi, int event, void *arg)
rsp = !rsp;
if (rsp) {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'L');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'L');
FreeSkb(skb);
if ((state == ST_L2_7) || (state == ST_L2_8))
establishlink(fi);
return;
}
if (skb->len != (l2addrsize(&st->l2) + 1)) {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
FreeSkb(skb);
if ((state == ST_L2_7) || (state == ST_L2_8))
establishlink(fi);
@@ -600,8 +622,11 @@ l2_got_disconn(struct FsmInst *fi, int event, void *arg)
FsmDelTimer(&st->l2.t200, 2);
}
send_uframe(st, cmd | PollFlag, RSP);
- if (rel)
- st->l2.l2man(st, DL_RELEASE, NULL);
+ if (rel) {
+ if (test_bit(FLG_LAPB, &st->l2.flag))
+ st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+ st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
+ }
}
@@ -610,7 +635,8 @@ l2_got_ua(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
struct sk_buff *skb = arg;
- u_char PollFlag, est = 1;
+ int pr=-1;
+ u_char PollFlag;
int state,rsp;
state = fi->state;
@@ -619,14 +645,14 @@ l2_got_ua(struct FsmInst *fi, int event, void *arg)
rsp = !rsp;
if (!rsp) {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'L');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'L');
FreeSkb(skb);
if ((state == ST_L2_7) || (state == ST_L2_8))
establishlink(fi);
return;
}
if (skb->len != (l2addrsize(&st->l2) + 1)) {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
FreeSkb(skb);
if ((fi->state == ST_L2_7) || (fi->state == ST_L2_8))
establishlink(fi);
@@ -643,30 +669,31 @@ l2_got_ua(struct FsmInst *fi, int event, void *arg)
FsmDelTimer(&st->l2.t200, 2);
if (fi->state == ST_L2_5) {
if (test_and_clear_bit(FLG_PEND_REL, &st->l2.flag)) {
- discard_i_queue(st);
+ discard_queue(&st->l2.i_queue);
st->l2.rc = 0;
send_uframe(st, DISC | 0x10, CMD);
FsmChangeState(fi, ST_L2_6);
FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 4);
test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
} else {
- if (!test_and_clear_bit(FLG_L3_INIT, &st->l2.flag)) {
- if (st->l2.vs != st->l2.va)
- discard_i_queue(st);
- else
- est = 0;
+ if (test_and_clear_bit(FLG_L3_INIT, &st->l2.flag)) {
+ pr = DL_ESTABLISH | CONFIRM;
+ } else if (st->l2.vs != st->l2.va) {
+ discard_queue(&st->l2.i_queue);
+ pr = DL_ESTABLISH | INDICATION;
}
st->l2.vs = 0;
st->l2.va = 0;
st->l2.vr = 0;
st->l2.sow = 0;
FsmChangeState(fi, ST_L2_7);
- FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 4);
- if (est)
- st->l2.l2man(st, DL_ESTABLISH, NULL);
+ if (pr > -1)
+ st->l2.l2l3(st, pr, NULL);
}
} else { /* ST_L2_6 */
- st->l2.l2man(st, DL_RELEASE, NULL);
+ if (test_bit(FLG_LAPB, &st->l2.flag))
+ st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+ st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
FsmChangeState(fi, ST_L2_4);
}
}
@@ -685,14 +712,14 @@ l2_got_dm(struct FsmInst *fi, int event, void *arg)
rsp = !rsp;
if (!rsp) {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'L');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'L');
FreeSkb(skb);
if ((state == ST_L2_7) || (state == ST_L2_8))
establishlink(fi);
return;
}
if (skb->len != (l2addrsize(&st->l2) + 1)) {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
FreeSkb(skb);
if ((fi->state == ST_L2_7) || (fi->state == ST_L2_8))
establishlink(fi);
@@ -700,15 +727,41 @@ l2_got_dm(struct FsmInst *fi, int event, void *arg)
}
PollFlag = get_PollFlagFree(st, skb);
if (!PollFlag) {
- establishlink(fi);
- test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
+ if (fi->state == ST_L2_4) {
+ establishlink(fi);
+ test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
+ FsmChangeState(fi, ST_L2_5);
+ } else if ((fi->state == ST_L2_7) || (fi->state == ST_L2_8)) {
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'E');
+ establishlink(fi);
+ }
} else {
- if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
- FsmDelTimer(&st->l2.t200, 2);
- if (fi->state == ST_L2_5 && !test_bit(FLG_L3_INIT, &st->l2.flag))
- discard_i_queue(st);
- st->l2.l2man(st, DL_RELEASE, NULL);
- FsmChangeState(fi, ST_L2_4);
+ switch (fi->state) {
+ case ST_L2_8:
+ establishlink(fi);
+ case ST_L2_7:
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'B');
+ break;
+ case ST_L2_4:
+ break;
+ case ST_L2_5:
+ if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
+ FsmDelTimer(&st->l2.t200, 2);
+ discard_queue(&st->l2.i_queue);
+ if (test_bit(FLG_LAPB, &st->l2.flag))
+ st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+ st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
+ FsmChangeState(fi, ST_L2_4);
+ break;
+ case ST_L2_6:
+ if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
+ FsmDelTimer(&st->l2.t200, 2);
+ if (test_bit(FLG_LAPB, &st->l2.flag))
+ st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+ st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
+ FsmChangeState(fi, ST_L2_4);
+ break;
+ }
}
}
@@ -763,7 +816,7 @@ nrerrorrecovery(struct FsmInst *fi)
{
struct PStack *st = fi->userdata;
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'J');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'J');
establishlink(fi);
}
@@ -785,11 +838,13 @@ invoke_retransmission(struct PStack *st, int nr)
if (p1 < 0)
p1 += (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8);
p1 = (p1 + l2->sow) % l2->window;
+ if (test_bit(FLG_LAPB, &l2->flag))
+ st->l1.bcs->tx_cnt += l2->windowar[p1]->len + l2headersize(l2, 0);
skb_queue_head(&l2->i_queue, l2->windowar[p1]);
l2->windowar[p1] = NULL;
}
restore_flags(flags);
- st->l2.l2l1(st, PH_PULL_REQ, NULL);
+ st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
}
}
@@ -818,9 +873,11 @@ l2_got_st7_super(struct FsmInst *fi, int event, void *arg)
PollFlag = (skb->data[1] & 0x1) == 0x1;
nr = skb->data[1] >> 1;
} else {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+ if (skb->len >2) {
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
+ establishlink(fi);
+ }
FreeSkb(skb);
- establishlink(fi);
return;
}
} else {
@@ -828,7 +885,7 @@ l2_got_st7_super(struct FsmInst *fi, int event, void *arg)
PollFlag = (skb->data[0] & 0x10);
nr = (skb->data[0] >> 5) & 0x7;
} else {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
FreeSkb(skb);
establishlink(fi);
return;
@@ -839,7 +896,7 @@ l2_got_st7_super(struct FsmInst *fi, int event, void *arg)
if ((!rsp) && PollFlag)
enquiry_response(st);
if (rsp && PollFlag)
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'A');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'A');
if (legalnr(st, nr)) {
if (typ == REJ) {
setva(st, nr);
@@ -862,13 +919,13 @@ l2_got_st7_super(struct FsmInst *fi, int event, void *arg)
test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
}
if (skb_queue_len(&st->l2.i_queue) && (typ == RR))
- st->l2.l2l1(st, PH_PULL_REQ, NULL);
+ st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
} else
nrerrorrecovery(fi);
if ((fi->userint & LC_FLUSH_WAIT) && rsp && !(skb_queue_len(&st->l2.i_queue))) {
fi->userint &= ~LC_FLUSH_WAIT;
- st->l2.l2man(st, DL_FLUSH, NULL);
+ st->l2.l2l3(st, DL_FLUSH | INDICATION, NULL);
}
}
@@ -883,7 +940,7 @@ l2_feed_iqueue(struct FsmInst *fi, int event, void *arg)
if (!((fi->state == ST_L2_5) && test_bit(FLG_L3_INIT, &st->l2.flag)))
skb_queue_tail(&st->l2.i_queue, skb);
if (fi->state == ST_L2_7)
- st->l2.l2l1(st, PH_PULL_REQ, NULL);
+ st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
}
static void
@@ -891,17 +948,15 @@ l2_got_iframe(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
struct sk_buff *skb = arg;
- struct IsdnCardState *sp = st->l1.hardware;
struct Layer2 *l2 = &(st->l2);
- int PollFlag, ns, nr, i, hs, rsp;
- char str[64];
+ int PollFlag, ns, nr, i, rsp;
rsp = *skb->data & 0x2;
if (test_bit(FLG_ORIG, &l2->flag))
rsp = !rsp;
if (rsp) {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'L');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'L');
FreeSkb(skb);
establishlink(fi);
return;
@@ -909,12 +964,10 @@ l2_got_iframe(struct FsmInst *fi, int event, void *arg)
i = l2addrsize(l2);
if (test_bit(FLG_MOD128, &l2->flag)) {
if (skb->len <= (i + 1)) {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
FreeSkb(skb);
- establishlink(fi);
return;
} else if ((skb->len - i - 1) > l2->maxlen) {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'O');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'O');
FreeSkb(skb);
establishlink(fi);
return;
@@ -924,12 +977,12 @@ l2_got_iframe(struct FsmInst *fi, int event, void *arg)
nr = (skb->data[i + 1] >> 1) & 0x7f;
} else {
if (skb->len <= i) {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
FreeSkb(skb);
establishlink(fi);
return;
} else if ((skb->len - i) > l2->maxlen) {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'O');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'O');
FreeSkb(skb);
establishlink(fi);
return;
@@ -944,20 +997,12 @@ l2_got_iframe(struct FsmInst *fi, int event, void *arg)
} else if (l2->vr == ns) {
l2->vr = (l2->vr + 1) % (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8);
test_and_clear_bit(FLG_REJEXC, &l2->flag);
- if (test_bit(FLG_LAPD, &l2->flag))
- if (sp->dlogflag) {
- hs = l2headersize(l2, 0);
- LogFrame(st->l1.hardware, skb->data, skb->len);
- sprintf(str, "Q.931 frame network->user tei %d", st->l2.tei);
- dlogframe(st->l1.hardware, skb->data + hs,
- skb->len - hs, str);
- }
if (PollFlag)
enquiry_response(st);
else
test_and_set_bit(FLG_ACK_PEND, &l2->flag);
skb_pull(skb, l2headersize(l2, 0));
- st->l2.l2l3(st, DL_DATA, skb);
+ st->l2.l2l3(st, DL_DATA | INDICATION, skb);
} else {
/* n(s)!=v(r) */
FreeSkb(skb);
@@ -990,7 +1035,7 @@ l2_got_iframe(struct FsmInst *fi, int event, void *arg)
}
if (skb_queue_len(&st->l2.i_queue) && (fi->state == ST_L2_7))
- st->l2.l2l1(st, PH_PULL_REQ, NULL);
+ st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
if (test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag))
enquiry_cr(st, RR, RSP, 0);
}
@@ -1000,7 +1045,7 @@ l2_got_tei(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
- st->l2.tei = (int) arg;
+ st->l2.tei = (long) arg;
if (fi->state == ST_L2_3) {
establishlink(fi);
@@ -1012,12 +1057,6 @@ l2_got_tei(struct FsmInst *fi, int event, void *arg)
}
static void
-l2_no_tei(struct FsmInst *fi, int event, void *arg)
-{
- FsmChangeState(fi, ST_L2_4);
-}
-
-static void
l2_st5_tout_200(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
@@ -1028,9 +1067,11 @@ l2_st5_tout_200(struct FsmInst *fi, int event, void *arg)
} else if (st->l2.rc == st->l2.N200) {
FsmChangeState(fi, ST_L2_4);
test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
- discard_i_queue(st);
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'G');
- st->l2.l2man(st, DL_RELEASE, NULL);
+ discard_queue(&st->l2.i_queue);
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'G');
+ if (test_bit(FLG_LAPB, &st->l2.flag))
+ st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+ st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
} else {
st->l2.rc++;
FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
@@ -1049,8 +1090,10 @@ l2_st6_tout_200(struct FsmInst *fi, int event, void *arg)
FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
} else if (st->l2.rc == st->l2.N200) {
FsmChangeState(fi, ST_L2_4);
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'H');
- st->l2.l2man(st, DL_RELEASE, NULL);
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'H');
+ if (test_bit(FLG_LAPB, &st->l2.flag))
+ st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+ st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
} else {
st->l2.rc++;
FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200,
@@ -1146,14 +1189,14 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
memcpy(skb_put(skb, oskb->len), oskb->data, oskb->len);
FreeSkb(oskb);
}
- st->l2.l2l1(st, PH_PULL_IND, skb);
+ st->l2.l2l1(st, PH_PULL | INDICATION, skb);
test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
if (!test_and_set_bit(FLG_T200_RUN, &st->l2.flag)) {
FsmDelTimer(&st->l2.t203, 13);
FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 11);
}
if (skb_queue_len(&l2->i_queue) && cansend(st))
- st->l2.l2l1(st, PH_PULL_REQ, NULL);
+ st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
}
static void
@@ -1179,7 +1222,7 @@ l2_got_st8_super(struct FsmInst *fi, int event, void *arg)
PollFlag = (skb->data[1] & 0x1) == 0x1;
nr = skb->data[1] >> 1;
} else {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
FreeSkb(skb);
establishlink(fi);
return;
@@ -1189,7 +1232,7 @@ l2_got_st8_super(struct FsmInst *fi, int event, void *arg)
PollFlag = (skb->data[0] & 0x10);
nr = (skb->data[0] >> 5) & 0x7;
} else {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
FreeSkb(skb);
establishlink(fi);
return;
@@ -1213,10 +1256,10 @@ l2_got_st8_super(struct FsmInst *fi, int event, void *arg)
invoke_retransmission(st, nr);
FsmChangeState(fi, ST_L2_7);
if (skb_queue_len(&l2->i_queue) && cansend(st))
- st->l2.l2l1(st, PH_PULL_REQ, NULL);
+ st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
else if (fi->userint & LC_FLUSH_WAIT) {
fi->userint &= ~LC_FLUSH_WAIT;
- st->l2.l2man(st, DL_FLUSH, NULL);
+ st->l2.l2l3(st, DL_FLUSH | INDICATION, NULL);
}
}
} else {
@@ -1233,30 +1276,25 @@ l2_got_FRMR(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
struct sk_buff *skb = arg;
- char tmp[64];
skb_pull(skb, l2addrsize(&st->l2) + 1);
if (test_bit(FLG_MOD128, &st->l2.flag)) {
if (skb->len < 5)
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
- else {
- sprintf(tmp, "FRMR information %2x %2x %2x %2x %2x",
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
+ else
+ l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x %2x %2x",
skb->data[0], skb->data[1], skb->data[2],
skb->data[3], skb->data[4]);
- l2m_debug(&st->l2.l2m, tmp);
- }
} else {
if (skb->len < 3)
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
- else {
- sprintf(tmp, "FRMR information %2x %2x %2x",
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
+ else
+ l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x",
skb->data[0], skb->data[1], skb->data[2]);
- l2m_debug(&st->l2.l2m, tmp);
- }
}
if (!(skb->data[0] & 1) || ((skb->data[0] & 3) == 1) || /* I or S */
(IsUA(skb->data, 0) && (fi->state == ST_L2_7))) {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'K');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'K');
establishlink(fi);
test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
}
@@ -1268,14 +1306,14 @@ l2_tei_remove(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
- discard_i_queue(st);
- discard_ui_queue(st);
+ discard_queue(&st->l2.i_queue);
+ discard_queue(&st->l2.ui_queue);
st->l2.tei = -1;
if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
FsmDelTimer(&st->l2.t200, 18);
FsmDelTimer(&st->l2.t203, 19);
if (fi->state != ST_L2_4)
- st->l2.l2man(st, DL_RELEASE, NULL);
+ st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
FsmChangeState(fi, ST_L2_1);
}
@@ -1283,33 +1321,45 @@ static void
l2_persistant_da(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
+ int rel = DL_RELEASE | INDICATION;
+
- discard_i_queue(st);
- discard_ui_queue(st);
+ discard_queue(&st->l2.i_queue);
+ discard_queue(&st->l2.ui_queue);
if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
FsmDelTimer(&st->l2.t200, 18);
FsmDelTimer(&st->l2.t203, 19);
- test_and_clear_bit(FLG_PEND_REL, &st->l2.flag);
clear_exception(&st->l2);
switch (fi->state) {
+ case ST_L2_1:
+ if (!test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag))
+ break;
case ST_L2_3:
- st->l2.l2man(st, DL_RELEASE, NULL);
+ st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
case ST_L2_2:
FsmChangeState(fi, ST_L2_1);
break;
- case ST_L2_5:
case ST_L2_6:
+ rel = DL_RELEASE | CONFIRM;
+ case ST_L2_5:
+ if (test_and_clear_bit(FLG_PEND_REL, &st->l2.flag))
+ rel = DL_RELEASE | CONFIRM;
case ST_L2_7:
case ST_L2_8:
- st->l2.l2man(st, DL_RELEASE, NULL);
+ st->l2.l2l3(st, rel, NULL);
FsmChangeState(fi, ST_L2_4);
break;
+ case ST_L2_4:
+ if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag))
+ st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
+ break;
}
+ test_and_clear_bit(FLG_PEND_REL, &st->l2.flag);
+ test_and_clear_bit(FLG_L1_ACTIV, &st->l2.flag);
}
static struct FsmNode L2FnList[] HISAX_INITDATA =
{
- {ST_L2_1, EV_L2_MDL_NOTEIPROC, l2_no_tei},
{ST_L2_1, EV_L2_DL_ESTABLISH, l2_dl_establish},
{ST_L2_2, EV_L2_DL_ESTABLISH, l2_dl_establish},
{ST_L2_4, EV_L2_DL_ESTABLISH, l2_establish},
@@ -1359,8 +1409,8 @@ static struct FsmNode L2FnList[] HISAX_INITDATA =
{ST_L2_4, EV_L2_DM, l2_got_dm},
{ST_L2_5, EV_L2_DM, l2_got_dm},
{ST_L2_6, EV_L2_DM, l2_got_dm},
- {ST_L2_7, EV_L2_DM, l2_mdl_error},
- {ST_L2_8, EV_L2_DM, l2_mdl_error},
+ {ST_L2_7, EV_L2_DM, l2_got_dm},
+ {ST_L2_8, EV_L2_DM, l2_got_dm},
{ST_L2_1, EV_L2_UI, l2_got_ui},
{ST_L2_2, EV_L2_UI, l2_got_ui},
{ST_L2_3, EV_L2_UI, l2_got_ui},
@@ -1381,6 +1431,7 @@ static struct FsmNode L2FnList[] HISAX_INITDATA =
{ST_L2_8, EV_L2_T200, l2_st78_tout_200},
{ST_L2_7, EV_L2_T203, l2_st7_tout_203},
{ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue},
+ {ST_L2_1, EV_L1_DEACTIVATE, l2_persistant_da},
{ST_L2_2, EV_L1_DEACTIVATE, l2_persistant_da},
{ST_L2_3, EV_L1_DEACTIVATE, l2_persistant_da},
{ST_L2_4, EV_L1_DEACTIVATE, l2_persistant_da},
@@ -1400,19 +1451,19 @@ isdnl2_l1l2(struct PStack *st, int pr, void *arg)
int ret = 1, len;
switch (pr) {
- case (PH_DATA_IND):
+ case (PH_DATA | INDICATION):
datap = skb->data;
len = l2addrsize(&st->l2);
if (skb->len > len)
datap += len;
else {
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
FreeSkb(skb);
return;
}
if (!(*datap & 1)) /* I-Frame */
ret = FsmEvent(&st->l2.l2m, EV_L2_I, skb);
- else if ((*datap & 3) == 1) /* S-Frame */
+ else if (IsSFrame(datap, test_bit(FLG_MOD128, &st->l2.flag)))
ret = FsmEvent(&st->l2.l2m, EV_L2_SUPER, skb);
else if (IsUI(datap, test_bit(FLG_MOD128, &st->l2.flag)))
ret = FsmEvent(&st->l2.l2m, EV_L2_UI, skb);
@@ -1427,23 +1478,39 @@ isdnl2_l1l2(struct PStack *st, int pr, void *arg)
else if (IsFRMR(datap, test_bit(FLG_MOD128, &st->l2.flag)))
ret = FsmEvent(&st->l2.l2m, EV_L2_FRMR, skb);
else {
- ret = 0;
- st->ma.layer(st, MDL_ERROR_IND, (void *) 'L');
- FreeSkb(skb);
+ ret = 1;
+ if ((st->l2.l2m.state == ST_L2_7) ||
+ (st->l2.l2m.state == ST_L2_8))
+ establishlink(&st->l2.l2m);
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'L');
}
if (ret) {
FreeSkb(skb);
}
break;
- case (PH_PULL_CNF):
+ case (PH_PULL | CONFIRM):
FsmEvent(&st->l2.l2m, EV_L2_ACK_PULL, arg);
break;
- case (PH_PAUSE_IND):
+ case (PH_PAUSE | INDICATION):
test_and_set_bit(FLG_DCHAN_BUSY, &st->l2.flag);
break;
- case (PH_PAUSE_CNF):
+ case (PH_PAUSE | CONFIRM):
test_and_clear_bit(FLG_DCHAN_BUSY, &st->l2.flag);
break;
+ case (PH_ACTIVATE | CONFIRM):
+ case (PH_ACTIVATE | INDICATION):
+ test_and_set_bit(FLG_L1_ACTIV, &st->l2.flag);
+ if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag))
+ FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH, arg);
+ break;
+ case (PH_DEACTIVATE | INDICATION):
+ case (PH_DEACTIVATE | CONFIRM):
+ test_and_clear_bit(FLG_L1_ACTIV, &st->l2.flag);
+ FsmEvent(&st->l2.l2m, EV_L1_DEACTIVATE, arg);
+ break;
+ default:
+ l2m_debug(&st->l2.l2m, "l2 unknown pr %04x", pr);
+ break;
}
}
@@ -1451,45 +1518,46 @@ static void
isdnl2_l3l2(struct PStack *st, int pr, void *arg)
{
switch (pr) {
- case (DL_DATA):
+ case (DL_DATA | REQUEST):
if (FsmEvent(&st->l2.l2m, EV_L2_DL_DATA, arg)) {
dev_kfree_skb((struct sk_buff *) arg);
}
break;
- case (DL_UNIT_DATA):
+ case (DL_UNIT_DATA | REQUEST):
if (FsmEvent(&st->l2.l2m, EV_L2_DL_UNIT_DATA, arg)) {
dev_kfree_skb((struct sk_buff *) arg);
}
break;
- }
-}
-
-static void
-isdnl2_manl2(struct PStack *st, int pr, void *arg)
-{
- switch (pr) {
- case (DL_ESTABLISH):
- FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH, arg);
+ case (DL_ESTABLISH | REQUEST):
+ if (test_bit(FLG_L1_ACTIV, &st->l2.flag)) {
+ if (test_bit(FLG_LAPD, &st->l2.flag) ||
+ test_bit(FLG_ORIG, &st->l2.flag)) {
+ FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH, arg);
+ }
+ } else {
+ if (test_bit(FLG_LAPD, &st->l2.flag) ||
+ test_bit(FLG_ORIG, &st->l2.flag)) {
+ test_and_set_bit(FLG_ESTAB_PEND, &st->l2.flag);
+ }
+ st->l2.l2l1(st, PH_ACTIVATE, NULL);
+ }
break;
- case (DL_RELEASE):
+ case (DL_RELEASE | REQUEST):
+ if (test_bit(FLG_LAPB, &st->l2.flag)) {
+ st->l2.l2l1(st, PH_DEACTIVATE, NULL);
+ }
FsmEvent(&st->l2.l2m, EV_L2_DL_RELEASE, arg);
break;
- case (MDL_NOTEIPROC):
- FsmEvent(&st->l2.l2m, EV_L2_MDL_NOTEIPROC, NULL);
- break;
- case (DL_FLUSH):
+ case (DL_FLUSH | REQUEST):
(&st->l2.l2m)->userint |= LC_FLUSH_WAIT;
break;
- case (PH_DEACTIVATE_IND):
- FsmEvent(&st->l2.l2m, EV_L1_DEACTIVATE, arg);
- break;
- case (MDL_ASSIGN_REQ):
+ case (MDL_ASSIGN | REQUEST):
FsmEvent(&st->l2.l2m, EV_L2_MDL_ASSIGN, arg);
break;
- case (MDL_REMOVE_REQ):
+ case (MDL_REMOVE | REQUEST):
FsmEvent(&st->l2.l2m, EV_L2_MDL_REMOVE, arg);
break;
- case (MDL_ERROR_REQ):
+ case (MDL_ERROR | RESPONSE):
FsmEvent(&st->l2.l2m, EV_L2_MDL_ERROR, arg);
break;
}
@@ -1500,20 +1568,20 @@ releasestack_isdnl2(struct PStack *st)
{
FsmDelTimer(&st->l2.t200, 15);
FsmDelTimer(&st->l2.t203, 16);
- discard_i_queue(st);
- discard_ui_queue(st);
+ discard_queue(&st->l2.i_queue);
+ discard_queue(&st->l2.ui_queue);
ReleaseWin(&st->l2);
}
static void
-l2m_debug(struct FsmInst *fi, char *s)
+l2m_debug(struct FsmInst *fi, char *fmt, ...)
{
+ va_list args;
struct PStack *st = fi->userdata;
- char tm[32], str[256];
- jiftime(tm, jiffies);
- sprintf(str, "%s %s %s\n", tm, st->l2.debug_id, s);
- HiSax_putstatus(st->l1.hardware, str);
+ va_start(args, fmt);
+ VHiSax_putstatus(st->l1.hardware, st->l2.debug_id, fmt, args);
+ va_end(args);
}
void
@@ -1521,7 +1589,6 @@ setstack_isdnl2(struct PStack *st, char *debug_id)
{
st->l1.l1l2 = isdnl2_l1l2;
st->l3.l3l2 = isdnl2_l3l2;
- st->ma.manl2 = isdnl2_manl2;
skb_queue_head_init(&st->l2.i_queue);
skb_queue_head_init(&st->l2.ui_queue);
@@ -1529,6 +1596,9 @@ setstack_isdnl2(struct PStack *st, char *debug_id)
st->l2.debug = 0;
st->l2.l2m.fsm = &l2fsm;
+ if (test_bit(FLG_LAPB, &st->l2.flag))
+ st->l2.l2m.state = ST_L2_4;
+ else
st->l2.l2m.state = ST_L2_1;
st->l2.l2m.debug = 0;
st->l2.l2m.userdata = st;
@@ -1540,9 +1610,27 @@ setstack_isdnl2(struct PStack *st, char *debug_id)
FsmInitTimer(&st->l2.l2m, &st->l2.t203);
}
+static void
+transl2_l3l2(struct PStack *st, int pr, void *arg)
+{
+ switch (pr) {
+ case (DL_DATA | REQUEST):
+ case (DL_UNIT_DATA | REQUEST):
+ st->l2.l2l1(st, PH_DATA | REQUEST, arg);
+ break;
+ case (DL_ESTABLISH | REQUEST):
+ st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL);
+ break;
+ case (DL_RELEASE | REQUEST):
+ st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+ break;
+ }
+}
+
void
setstack_transl2(struct PStack *st)
{
+ st->l3.l3l2 = transl2_l3l2;
}
void
diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c
index 026d8eb76..4511251e7 100644
--- a/drivers/isdn/hisax/isdnl3.c
+++ b/drivers/isdn/hisax/isdnl3.c
@@ -1,12 +1,27 @@
-/* $Id: isdnl3.c,v 2.5 1998/02/12 23:07:52 keil Exp $
+/* $Id: isdnl3.c,v 2.8 1998/11/15 23:55:04 keil Exp $
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
* based on the teles driver from Jan den Ouden
*
+ * This file is (c) under GNU PUBLIC LICENSE
+ * For changes and modifications please read
+ * ../../../Documentation/isdn/HiSax.cert
+ *
* Thanks to Jan den Ouden
* Fritz Elfert
*
* $Log: isdnl3.c,v $
+ * Revision 2.8 1998/11/15 23:55:04 keil
+ * changes from 2.0
+ *
+ * Revision 2.7 1998/05/25 14:10:15 keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.6 1998/05/25 12:58:11 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
* Revision 2.5 1998/02/12 23:07:52 keil
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
@@ -47,7 +62,60 @@
#include "isdnl3.h"
#include <linux/config.h>
-const char *l3_revision = "$Revision: 2.5 $";
+const char *l3_revision = "$Revision: 2.8 $";
+
+static
+struct Fsm l3fsm =
+{NULL, 0, 0, NULL, NULL};
+
+enum {
+ ST_L3_LC_REL,
+ ST_L3_LC_ESTAB_WAIT,
+ ST_L3_LC_REL_WAIT,
+ ST_L3_LC_ESTAB,
+};
+
+#define L3_STATE_COUNT (ST_L3_LC_ESTAB+1)
+
+static char *strL3State[] =
+{
+ "ST_L3_LC_REL",
+ "ST_L3_LC_ESTAB_WAIT",
+ "ST_L3_LC_REL_WAIT",
+ "ST_L3_LC_ESTAB",
+};
+
+enum {
+ EV_ESTABLISH_REQ,
+ EV_ESTABLISH_IND,
+ EV_ESTABLISH_CNF,
+ EV_RELEASE_REQ,
+ EV_RELEASE_CNF,
+ EV_RELEASE_IND,
+};
+
+#define L3_EVENT_COUNT (EV_RELEASE_IND+1)
+
+static char *strL3Event[] =
+{
+ "EV_ESTABLISH_REQ",
+ "EV_ESTABLISH_IND",
+ "EV_ESTABLISH_CNF",
+ "EV_RELEASE_REQ",
+ "EV_RELEASE_CNF",
+ "EV_RELEASE_IND",
+};
+
+static void
+l3m_debug(struct FsmInst *fi, char *fmt, ...)
+{
+ va_list args;
+ struct PStack *st = fi->userdata;
+
+ va_start(args, fmt);
+ VHiSax_putstatus(st->l1.hardware, st->l3.debug_id, fmt, args);
+ va_end(args);
+}
u_char *
findie(u_char * p, int size, u_char ie, int wanted_set)
@@ -115,25 +183,11 @@ newcallref(void)
}
void
-l3_debug(struct PStack *st, char *s)
-{
- char str[256], tm[32];
-
- jiftime(tm, jiffies);
- sprintf(str, "%s l3 %s\n", tm, s);
- HiSax_putstatus(st->l1.hardware, str);
-}
-
-void
newl3state(struct l3_process *pc, int state)
{
- char tmp[80];
-
- if (pc->debug & L3_DEB_STATE) {
- sprintf(tmp, "newstate cr %d %d --> %d", pc->callref,
+ if (pc->debug & L3_DEB_STATE)
+ l3_debug(pc->st, "newstate cr %d %d --> %d", pc->callref,
pc->state, state);
- l3_debug(pc->st, tmp);
- }
pc->state = state;
}
@@ -197,7 +251,7 @@ no_l3_proto(struct PStack *st, int pr, void *arg)
{
struct sk_buff *skb = arg;
- HiSax_putstatus(st->l1.hardware, "L3 no D protocol\n");
+ HiSax_putstatus(st->l1.hardware, "L3", "no D protocol");
if (skb) {
dev_kfree_skb(skb);
}
@@ -277,16 +331,25 @@ release_l3_process(struct l3_process *p)
pp = np;
np = np->next;
}
- printk(KERN_ERR "HiSax internal L3 error CR not in list\n");
+ printk(KERN_ERR "HiSax internal L3 error CR(%d) not in list\n", p->callref);
+ l3_debug(p->st, "HiSax internal L3 error CR(%d) not in list", p->callref);
};
void
-setstack_isdnl3(struct PStack *st, struct Channel *chanp)
+setstack_l3dc(struct PStack *st, struct Channel *chanp)
{
char tmp[64];
st->l3.proc = NULL;
st->l3.global = NULL;
+ skb_queue_head_init(&st->l3.squeue);
+ st->l3.l3m.fsm = &l3fsm;
+ st->l3.l3m.state = ST_L3_LC_REL;
+ st->l3.l3m.debug = 1;
+ st->l3.l3m.userdata = st;
+ st->l3.l3m.userint = 0;
+ st->l3.l3m.printdebug = l3m_debug;
+ strcpy(st->l3.debug_id, "L3DC ");
#ifdef CONFIG_HISAX_EURO
if (st->protocol == ISDN_PTYPE_EURO) {
@@ -321,6 +384,11 @@ setstack_isdnl3(struct PStack *st, struct Channel *chanp)
}
void
+isdnl3_trans(struct PStack *st, int pr, void *arg) {
+ st->l3.l3l2(st, pr, arg);
+}
+
+void
releasestack_isdnl3(struct PStack *st)
{
while (st->l3.proc)
@@ -330,4 +398,136 @@ releasestack_isdnl3(struct PStack *st)
kfree(st->l3.global);
st->l3.global = NULL;
}
+ discard_queue(&st->l3.squeue);
+}
+
+void
+setstack_l3bc(struct PStack *st, struct Channel *chanp)
+{
+
+ st->l3.proc = NULL;
+ st->l3.global = NULL;
+ skb_queue_head_init(&st->l3.squeue);
+ st->l3.l3m.fsm = &l3fsm;
+ st->l3.l3m.state = ST_L3_LC_REL;
+ st->l3.l3m.debug = 1;
+ st->l3.l3m.userdata = st;
+ st->l3.l3m.userint = 0;
+ st->l3.l3m.printdebug = l3m_debug;
+ strcpy(st->l3.debug_id, "L3BC ");
+ st->lli.l4l3 = isdnl3_trans;
+}
+
+static void
+lc_activate(struct FsmInst *fi, int event, void *arg)
+{
+ struct PStack *st = fi->userdata;
+
+ FsmChangeState(fi, ST_L3_LC_ESTAB_WAIT);
+ st->l3.l3l2(st, DL_ESTABLISH | REQUEST, NULL);
+}
+
+static void
+lc_connect(struct FsmInst *fi, int event, void *arg)
+{
+ struct PStack *st = fi->userdata;
+ struct sk_buff *skb = arg;
+
+ FsmChangeState(fi, ST_L3_LC_ESTAB);
+ while ((skb = skb_dequeue(&st->l3.squeue))) {
+ st->l3.l3l2(st, DL_DATA | REQUEST, skb);
+ }
+ st->l3.l3l4(st, DL_ESTABLISH | INDICATION, NULL);
+}
+
+static void
+lc_release_req(struct FsmInst *fi, int event, void *arg)
+{
+ struct PStack *st = fi->userdata;
+
+ if (fi->state == ST_L3_LC_ESTAB_WAIT)
+ FsmChangeState(fi, ST_L3_LC_REL);
+ else
+ FsmChangeState(fi, ST_L3_LC_REL_WAIT);
+ st->l3.l3l2(st, DL_RELEASE | REQUEST, NULL);
+}
+
+static void
+lc_release_ind(struct FsmInst *fi, int event, void *arg)
+{
+ struct PStack *st = fi->userdata;
+
+ FsmChangeState(fi, ST_L3_LC_REL);
+ discard_queue(&st->l3.squeue);
+ st->l3.l3l4(st, DL_RELEASE | INDICATION, NULL);
+}
+
+/* *INDENT-OFF* */
+static struct FsmNode L3FnList[] HISAX_INITDATA =
+{
+ {ST_L3_LC_REL, EV_ESTABLISH_REQ, lc_activate},
+ {ST_L3_LC_REL, EV_ESTABLISH_IND, lc_connect},
+ {ST_L3_LC_REL, EV_ESTABLISH_CNF, lc_connect},
+ {ST_L3_LC_ESTAB_WAIT, EV_ESTABLISH_CNF, lc_connect},
+ {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_REQ, lc_release_req},
+ {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_IND, lc_release_ind},
+ {ST_L3_LC_ESTAB, EV_RELEASE_IND, lc_release_ind},
+ {ST_L3_LC_ESTAB, EV_RELEASE_REQ, lc_release_req},
+ {ST_L3_LC_REL_WAIT, EV_RELEASE_CNF, lc_release_ind},
+ {ST_L3_LC_REL_WAIT, EV_ESTABLISH_REQ, lc_activate},
+};
+/* *INDENT-ON* */
+
+#define L3_FN_COUNT (sizeof(L3FnList)/sizeof(struct FsmNode))
+
+void
+l3_msg(struct PStack *st, int pr, void *arg)
+{
+
+ switch (pr) {
+ case (DL_DATA | REQUEST):
+ if (st->l3.l3m.state == ST_L3_LC_ESTAB) {
+ st->l3.l3l2(st, pr, arg);
+ } else {
+ struct sk_buff *skb = arg;
+
+ skb_queue_head(&st->l3.squeue, skb);
+ FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL);
+ }
+ break;
+ case (DL_ESTABLISH | REQUEST):
+ FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL);
+ break;
+ case (DL_ESTABLISH | CONFIRM):
+ FsmEvent(&st->l3.l3m, EV_ESTABLISH_CNF, NULL);
+ break;
+ case (DL_ESTABLISH | INDICATION):
+ FsmEvent(&st->l3.l3m, EV_ESTABLISH_IND, NULL);
+ break;
+ case (DL_RELEASE | INDICATION):
+ FsmEvent(&st->l3.l3m, EV_RELEASE_IND, NULL);
+ break;
+ case (DL_RELEASE | CONFIRM):
+ FsmEvent(&st->l3.l3m, EV_RELEASE_CNF, NULL);
+ break;
+ case (DL_RELEASE | REQUEST):
+ FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL);
+ break;
+ }
+}
+
+HISAX_INITFUNC(void
+Isdnl3New(void))
+{
+ l3fsm.state_count = L3_STATE_COUNT;
+ l3fsm.event_count = L3_EVENT_COUNT;
+ l3fsm.strEvent = strL3Event;
+ l3fsm.strState = strL3State;
+ FsmNew(&l3fsm, L3FnList, L3_FN_COUNT);
+}
+
+void
+Isdnl3Free(void)
+{
+ FsmFree(&l3fsm);
}
diff --git a/drivers/isdn/hisax/isdnl3.h b/drivers/isdn/hisax/isdnl3.h
index 2ff582b4a..a0e518f8c 100644
--- a/drivers/isdn/hisax/isdnl3.h
+++ b/drivers/isdn/hisax/isdnl3.h
@@ -1,6 +1,17 @@
-/* $Id: isdnl3.h,v 2.0 1997/07/27 21:15:42 keil Exp $
+/* $Id: isdnl3.h,v 2.3 1998/11/15 23:55:06 keil Exp $
* $Log: isdnl3.h,v $
+ * Revision 2.3 1998/11/15 23:55:06 keil
+ * changes from 2.0
+ *
+ * Revision 2.2 1998/05/25 14:10:17 keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.1 1998/05/25 12:58:13 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
* Revision 2.0 1997/07/27 21:15:42 keil
* New Callref based layer3
*
@@ -31,11 +42,12 @@
struct stateentry {
int state;
- u_char primitive;
+ int primitive;
void (*rout) (struct l3_process *, u_char, void *);
};
-extern void l3_debug(struct PStack *st, char *s);
+#define l3_debug(st, fmt, args...) HiSax_putstatus(st->l1.hardware, "l3 ", fmt, ## args)
+
extern void newl3state(struct l3_process *pc, int state);
extern void L3InitTimer(struct l3_process *pc, struct L3Timer *t);
extern void L3DelTimer(struct L3Timer *t);
@@ -45,3 +57,4 @@ extern struct sk_buff *l3_alloc_skb(int len);
extern struct l3_process *new_l3_process(struct PStack *st, int cr);
extern void release_l3_process(struct l3_process *p);
extern struct l3_process *getl3proc(struct PStack *st, int cr);
+extern void l3_msg(struct PStack *st, int pr, void *arg);
diff --git a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c
index 0c075546b..009783b6d 100644
--- a/drivers/isdn/hisax/ix1_micro.c
+++ b/drivers/isdn/hisax/ix1_micro.c
@@ -1,4 +1,4 @@
-/* $Id: ix1_micro.c,v 2.6 1998/02/11 17:28:09 keil Exp $
+/* $Id: ix1_micro.c,v 2.7 1998/04/15 16:44:31 keil Exp $
* ix1_micro.c low level stuff for ITK ix1-micro Rev.2 isdn cards
* derived from the original file teles3.c from Karsten Keil
@@ -11,6 +11,9 @@
* Beat Doebeli
*
* $Log: ix1_micro.c,v $
+ * Revision 2.7 1998/04/15 16:44:31 keil
+ * new init code
+ *
* Revision 2.6 1998/02/11 17:28:09 keil
* Niccy PnP/PCI support
*
@@ -81,7 +84,7 @@
#include "isdnl1.h"
extern const char *CardType[];
-const char *ix1_revision = "$Revision: 2.6 $";
+const char *ix1_revision = "$Revision: 2.7 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -277,10 +280,7 @@ ix1_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(request_irq(cs->irq, &ix1micro_interrupt,
I4L_IRQ_FLAG, "HiSax", cs));
case CARD_INIT:
- clear_pending_isac_ints(cs);
- clear_pending_hscx_ints(cs);
- initisac(cs);
- inithscx(cs);
+ inithscxisac(cs, 3);
return(0);
case CARD_TEST:
return(0);
diff --git a/drivers/isdn/hisax/l3_1tr6.c b/drivers/isdn/hisax/l3_1tr6.c
index d60a5da66..db6ceca76 100644
--- a/drivers/isdn/hisax/l3_1tr6.c
+++ b/drivers/isdn/hisax/l3_1tr6.c
@@ -1,11 +1,29 @@
-/* $Id: l3_1tr6.c,v 2.4 1998/02/12 23:07:57 keil Exp $
+/* $Id: l3_1tr6.c,v 2.8 1998/11/15 23:55:08 keil Exp $
* German 1TR6 D-channel protocol
*
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
+ *
+ * This file is (c) under GNU PUBLIC LICENSE
+ * For changes and modifications please read
+ * ../../../Documentation/isdn/HiSax.cert
*
*
* $Log: l3_1tr6.c,v $
+ * Revision 2.8 1998/11/15 23:55:08 keil
+ * changes from 2.0
+ *
+ * Revision 2.7 1998/08/13 23:36:45 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.6 1998/05/25 14:10:18 keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.5 1998/05/25 12:58:14 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
* Revision 2.4 1998/02/12 23:07:57 keil
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
@@ -38,7 +56,7 @@
#include <linux/ctype.h>
extern char *HiSax_getrev(const char *revision);
-const char *l3_1tr6_revision = "$Revision: 2.4 $";
+const char *l3_1tr6_revision = "$Revision: 2.8 $";
#define MsgHead(ptr, cref, mty, dis) \
*ptr++ = dis; \
@@ -56,66 +74,34 @@ l3_1TR6_message(struct l3_process *pc, u_char mt, u_char pd)
return;
p = skb_put(skb, 4);
MsgHead(p, pc->callref, mt, pd);
- pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
}
-static int
-l31tr6_check_messagetype_validity(int mt, int pd) {
-/* verify if a message type exists */
-
- if (pd == PROTO_DIS_N0)
- switch(mt) {
- case MT_N0_REG_IND:
- case MT_N0_CANC_IND:
- case MT_N0_FAC_STA:
- case MT_N0_STA_ACK:
- case MT_N0_STA_REJ:
- case MT_N0_FAC_INF:
- case MT_N0_INF_ACK:
- case MT_N0_INF_REJ:
- case MT_N0_CLOSE:
- case MT_N0_CLO_ACK:
- return(1);
- default:
- return(0);
- }
- else if (pd == PROTO_DIS_N1)
- switch(mt) {
- case MT_N1_ESC:
- case MT_N1_ALERT:
- case MT_N1_CALL_SENT:
- case MT_N1_CONN:
- case MT_N1_CONN_ACK:
- case MT_N1_SETUP:
- case MT_N1_SETUP_ACK:
- case MT_N1_RES:
- case MT_N1_RES_ACK:
- case MT_N1_RES_REJ:
- case MT_N1_SUSP:
- case MT_N1_SUSP_ACK:
- case MT_N1_SUSP_REJ:
- case MT_N1_USER_INFO:
- case MT_N1_DET:
- case MT_N1_DISC:
- case MT_N1_REL:
- case MT_N1_REL_ACK:
- case MT_N1_CANC_ACK:
- case MT_N1_CANC_REJ:
- case MT_N1_CON_CON:
- case MT_N1_FAC:
- case MT_N1_FAC_ACK:
- case MT_N1_FAC_CAN:
- case MT_N1_FAC_REG:
- case MT_N1_FAC_REJ:
- case MT_N1_INFO:
- case MT_N1_REG_ACK:
- case MT_N1_REG_REJ:
- case MT_N1_STAT:
- return (1);
- default:
- return(0);
- }
- return(0);
+static void
+l3_1tr6_release_req(struct l3_process *pc, u_char pr, void *arg)
+{
+ StopAllL3Timer(pc);
+ newl3state(pc, 19);
+ l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1);
+ L3AddTimer(&pc->timer, T308, CC_T308_1);
+}
+
+static void
+l3_1tr6_invalid(struct l3_process *pc, u_char pr, void *arg)
+{
+ struct sk_buff *skb = arg;
+
+ dev_kfree_skb(skb);
+ l3_1tr6_release_req(pc, 0, NULL);
+}
+
+static void
+l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb)
+{
+ dev_kfree_skb(skb);
+ if (pc->st->l3.debug & L3_DEB_WARN)
+ l3_debug(pc->st, msg);
+ l3_1tr6_release_req(pc, 0, NULL);
}
static void
@@ -204,7 +190,7 @@ l3_1tr6_setup_req(struct l3_process *pc, u_char pr, void *arg)
L3DelTimer(&pc->timer);
L3AddTimer(&pc->timer, T303, CC_T303);
newl3state(pc, 1);
- pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
}
static void
@@ -220,17 +206,29 @@ l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg)
/* Channel Identification */
p = skb->data;
if ((p = findie(p, skb->len, WE0_chanID, 0))) {
- pc->para.bchannel = p[2] & 0x3;
- bcfound++;
- } else if (pc->st->l3.debug & L3_DEB_WARN)
- l3_debug(pc->st, "setup without bchannel");
+ if (p[1] != 1) {
+ l3_1tr6_error(pc, "setup wrong chanID len", skb);
+ return;
+ }
+ if ((p[2] & 0xf4) != 0x80) {
+ l3_1tr6_error(pc, "setup wrong WE0_chanID", skb);
+ return;
+ }
+ if ((pc->para.bchannel = p[2] & 0x3))
+ bcfound++;
+ } else {
+ l3_1tr6_error(pc, "missing setup chanID", skb);
+ return;
+ }
p = skb->data;
if ((p = findie(p, skb->len, WE6_serviceInd, 6))) {
pc->para.setup.si1 = p[2];
pc->para.setup.si2 = p[3];
- } else if (pc->st->l3.debug & L3_DEB_WARN)
- l3_debug(pc->st, "setup without service indicator");
+ } else {
+ l3_1tr6_error(pc, "missing setup SI", skb);
+ return;
+ }
p = skb->data;
if ((p = findie(p, skb->len, WE0_destAddr, 0)))
@@ -261,7 +259,7 @@ l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg)
l3_debug(pc->st, tmp);
}
newl3state(pc, 6);
- pc->st->l3.l3l4(pc, CC_SETUP_IND, NULL);
+ pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
} else
release_l3_process(pc);
}
@@ -276,12 +274,22 @@ l3_1tr6_setup_ack(struct l3_process *pc, u_char pr, void *arg)
p = skb->data;
newl3state(pc, 2);
if ((p = findie(p, skb->len, WE0_chanID, 0))) {
+ if (p[1] != 1) {
+ l3_1tr6_error(pc, "setup_ack wrong chanID len", skb);
+ return;
+ }
+ if ((p[2] & 0xf4) != 0x80) {
+ l3_1tr6_error(pc, "setup_ack wrong WE0_chanID", skb);
+ return;
+ }
pc->para.bchannel = p[2] & 0x3;
- } else if (pc->st->l3.debug & L3_DEB_WARN)
- l3_debug(pc->st, "setup answer without bchannel");
+ } else {
+ l3_1tr6_error(pc, "missing setup_ack WE0_chanID", skb);
+ return;
+ }
dev_kfree_skb(skb);
L3AddTimer(&pc->timer, T304, CC_T304);
- pc->st->l3.l3l4(pc, CC_MORE_INFO, NULL);
+ pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
}
static void
@@ -293,13 +301,27 @@ l3_1tr6_call_sent(struct l3_process *pc, u_char pr, void *arg)
L3DelTimer(&pc->timer);
p = skb->data;
if ((p = findie(p, skb->len, WE0_chanID, 0))) {
+ if (p[1] != 1) {
+ l3_1tr6_error(pc, "call sent wrong chanID len", skb);
+ return;
+ }
+ if ((p[2] & 0xf4) != 0x80) {
+ l3_1tr6_error(pc, "call sent wrong WE0_chanID", skb);
+ return;
+ }
+ if ((pc->state == 2) && (pc->para.bchannel != (p[2] & 0x3))) {
+ l3_1tr6_error(pc, "call sent wrong chanID value", skb);
+ return;
+ }
pc->para.bchannel = p[2] & 0x3;
- } else if (pc->st->l3.debug & L3_DEB_WARN)
- l3_debug(pc->st, "setup answer without bchannel");
+ } else {
+ l3_1tr6_error(pc, "missing call sent WE0_chanID", skb);
+ return;
+ }
dev_kfree_skb(skb);
L3AddTimer(&pc->timer, T310, CC_T310);
newl3state(pc, 3);
- pc->st->l3.l3l4(pc, CC_PROCEEDING_IND, NULL);
+ pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
}
static void
@@ -310,7 +332,7 @@ l3_1tr6_alert(struct l3_process *pc, u_char pr, void *arg)
dev_kfree_skb(skb);
L3DelTimer(&pc->timer); /* T304 */
newl3state(pc, 4);
- pc->st->l3.l3l4(pc, CC_ALERTING_IND, NULL);
+ pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
}
static void
@@ -330,7 +352,7 @@ l3_1tr6_info(struct l3_process *pc, u_char pr, void *arg)
}
if (tmpcharge > pc->para.chargeinfo) {
pc->para.chargeinfo = tmpcharge;
- pc->st->l3.l3l4(pc, CC_INFO_CHARGE, NULL);
+ pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
}
if (pc->st->l3.debug & L3_DEB_CHARGE) {
sprintf(tmp, "charging info %d", pc->para.chargeinfo);
@@ -356,10 +378,14 @@ l3_1tr6_connect(struct l3_process *pc, u_char pr, void *arg)
struct sk_buff *skb = arg;
L3DelTimer(&pc->timer); /* T310 */
+ if (!findie(skb->data, skb->len, WE6_date, 6)) {
+ l3_1tr6_error(pc, "missing connect date", skb);
+ return;
+ }
newl3state(pc, 10);
dev_kfree_skb(skb);
pc->para.chargeinfo = 0;
- pc->st->l3.l3l4(pc, CC_SETUP_CNF, NULL);
+ pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
}
static void
@@ -380,13 +406,16 @@ l3_1tr6_rel(struct l3_process *pc, u_char pr, void *arg)
pc->para.cause = 0;
pc->para.loc = 0;
}
- } else
+ } else {
pc->para.cause = -1;
+ l3_1tr6_error(pc, "missing REL cause", skb);
+ return;
+ }
dev_kfree_skb(skb);
StopAllL3Timer(pc);
newl3state(pc, 0);
l3_1TR6_message(pc, MT_N1_REL_ACK, PROTO_DIS_N1);
- pc->st->l3.l3l4(pc, CC_RELEASE_IND, NULL);
+ pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
release_l3_process(pc);
}
@@ -399,7 +428,7 @@ l3_1tr6_rel_ack(struct l3_process *pc, u_char pr, void *arg)
StopAllL3Timer(pc);
newl3state(pc, 0);
pc->para.cause = -1;
- pc->st->l3.l3l4(pc, CC_RELEASE_CNF, NULL);
+ pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
release_l3_process(pc);
}
@@ -421,7 +450,7 @@ l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg)
}
if (tmpcharge > pc->para.chargeinfo) {
pc->para.chargeinfo = tmpcharge;
- pc->st->l3.l3l4(pc, CC_INFO_CHARGE, NULL);
+ pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
}
if (pc->st->l3.debug & L3_DEB_CHARGE) {
sprintf(tmp, "charging info %d", pc->para.chargeinfo);
@@ -448,9 +477,13 @@ l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg)
l3_debug(pc->st, "cause not found");
pc->para.cause = -1;
}
+ if (!findie(skb->data, skb->len, WE6_date, 6)) {
+ l3_1tr6_error(pc, "missing connack date", skb);
+ return;
+ }
dev_kfree_skb(skb);
newl3state(pc, 12);
- pc->st->l3.l3l4(pc, CC_DISCONNECT_IND, NULL);
+ pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
}
@@ -459,11 +492,15 @@ l3_1tr6_connect_ack(struct l3_process *pc, u_char pr, void *arg)
{
struct sk_buff *skb = arg;
+ if (!findie(skb->data, skb->len, WE6_date, 6)) {
+ l3_1tr6_error(pc, "missing connack date", skb);
+ return;
+ }
dev_kfree_skb(skb);
newl3state(pc, 10);
pc->para.chargeinfo = 0;
L3DelTimer(&pc->timer);
- pc->st->l3.l3l4(pc, CC_SETUP_COMPLETE_IND, NULL);
+ pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
}
static void
@@ -502,7 +539,7 @@ l3_1tr6_setup_rsp(struct l3_process *pc, u_char pr, void *arg)
if (!(skb = l3_alloc_skb(l)))
return;
memcpy(skb_put(skb, l), tmp, l);
- pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
L3DelTimer(&pc->timer);
L3AddTimer(&pc->timer, T313, CC_T313);
}
@@ -545,20 +582,11 @@ l3_1tr6_disconnect_req(struct l3_process *pc, u_char pr, void *arg)
if (!(skb = l3_alloc_skb(l)))
return;
memcpy(skb_put(skb, l), tmp, l);
- pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
L3AddTimer(&pc->timer, T305, CC_T305);
}
static void
-l3_1tr6_release_req(struct l3_process *pc, u_char pr, void *arg)
-{
- StopAllL3Timer(pc);
- newl3state(pc, 19);
- l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1);
- L3AddTimer(&pc->timer, T308, CC_T308_1);
-}
-
-static void
l3_1tr6_t303(struct l3_process *pc, u_char pr, void *arg)
{
if (pc->N303 > 0) {
@@ -567,8 +595,8 @@ l3_1tr6_t303(struct l3_process *pc, u_char pr, void *arg)
l3_1tr6_setup_req(pc, pr, arg);
} else {
L3DelTimer(&pc->timer);
- pc->st->l3.l3l4(pc, CC_NOSETUP_RSP_ERR, NULL);
- release_l3_process(pc);
+ pc->para.cause = 0;
+ l3_1tr6_disconnect_req(pc, 0, NULL);
}
}
@@ -578,7 +606,7 @@ l3_1tr6_t304(struct l3_process *pc, u_char pr, void *arg)
L3DelTimer(&pc->timer);
pc->para.cause = 0xE6;
l3_1tr6_disconnect_req(pc, pr, NULL);
- pc->st->l3.l3l4(pc, CC_SETUP_ERR, NULL);
+ pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
}
static void
@@ -613,7 +641,7 @@ l3_1tr6_t305(struct l3_process *pc, u_char pr, void *arg)
if (!(skb = l3_alloc_skb(l)))
return;
memcpy(skb_put(skb, l), tmp, l);
- pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
L3AddTimer(&pc->timer, T308, CC_T308_1);
}
@@ -623,7 +651,7 @@ l3_1tr6_t310(struct l3_process *pc, u_char pr, void *arg)
L3DelTimer(&pc->timer);
pc->para.cause = 0xE6;
l3_1tr6_disconnect_req(pc, pr, NULL);
- pc->st->l3.l3l4(pc, CC_SETUP_ERR, NULL);
+ pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
}
static void
@@ -632,7 +660,7 @@ l3_1tr6_t313(struct l3_process *pc, u_char pr, void *arg)
L3DelTimer(&pc->timer);
pc->para.cause = 0xE6;
l3_1tr6_disconnect_req(pc, pr, NULL);
- pc->st->l3.l3l4(pc, CC_CONNECT_ERR, NULL);
+ pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
}
static void
@@ -648,29 +676,29 @@ static void
l3_1tr6_t308_2(struct l3_process *pc, u_char pr, void *arg)
{
L3DelTimer(&pc->timer);
- pc->st->l3.l3l4(pc, CC_RELEASE_ERR, NULL);
+ pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
release_l3_process(pc);
}
/* *INDENT-OFF* */
static struct stateentry downstl[] =
{
{SBIT(0),
- CC_SETUP_REQ, l3_1tr6_setup_req},
+ CC_SETUP | REQUEST, l3_1tr6_setup_req},
{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) |
SBIT(10),
- CC_DISCONNECT_REQ, l3_1tr6_disconnect_req},
+ CC_DISCONNECT | REQUEST, l3_1tr6_disconnect_req},
{SBIT(12),
- CC_RELEASE_REQ, l3_1tr6_release_req},
+ CC_RELEASE | REQUEST, l3_1tr6_release_req},
{ALL_STATES,
- CC_DLRL, l3_1tr6_reset},
+ CC_DLRL | REQUEST, l3_1tr6_reset},
{SBIT(6),
- CC_IGNORE, l3_1tr6_reset},
+ CC_IGNORE | REQUEST, l3_1tr6_reset},
{SBIT(6),
- CC_REJECT_REQ, l3_1tr6_disconnect_req},
+ CC_REJECT | REQUEST, l3_1tr6_disconnect_req},
{SBIT(6),
- CC_ALERTING_REQ, l3_1tr6_alert_req},
+ CC_ALERTING | REQUEST, l3_1tr6_alert_req},
{SBIT(6) | SBIT(7),
- CC_SETUP_RSP, l3_1tr6_setup_rsp},
+ CC_SETUP | RESPONSE, l3_1tr6_setup_rsp},
{SBIT(1),
CC_T303, l3_1tr6_t303},
{SBIT(2),
@@ -687,12 +715,14 @@ static struct stateentry downstl[] =
CC_T308_2, l3_1tr6_t308_2},
};
-static int downstl_len = sizeof(downstl) /
-sizeof(struct stateentry);
+#define DOWNSTL_LEN \
+ (sizeof(downstl) / sizeof(struct stateentry))
static struct stateentry datastln1[] =
{
{SBIT(0),
+ MT_N1_INVALID, l3_1tr6_invalid},
+ {SBIT(0),
MT_N1_SETUP, l3_1tr6_setup},
{SBIT(1),
MT_N1_SETUP_ACK, l3_1tr6_setup_ack},
@@ -711,18 +741,20 @@ static struct stateentry datastln1[] =
{SBIT(10),
MT_N1_INFO, l3_1tr6_info},
{SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) |
- SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19),
+ SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17),
MT_N1_REL, l3_1tr6_rel},
{SBIT(19),
+ MT_N1_REL, l3_1tr6_rel_ack},
+ {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) |
+ SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17),
+ MT_N1_REL_ACK, l3_1tr6_invalid},
+ {SBIT(19),
MT_N1_REL_ACK, l3_1tr6_rel_ack}
};
/* *INDENT-ON* */
-
-
-
-static int datastln1_len = sizeof(datastln1) /
-sizeof(struct stateentry);
+#define DATASTLN1_LEN \
+ (sizeof(datastln1) / sizeof(struct stateentry))
static void
up1tr6(struct PStack *st, int pr, void *arg)
@@ -732,9 +764,21 @@ up1tr6(struct PStack *st, int pr, void *arg)
struct sk_buff *skb = arg;
char tmp[80];
+ switch (pr) {
+ case (DL_DATA | INDICATION):
+ case (DL_UNIT_DATA | INDICATION):
+ break;
+ case (DL_ESTABLISH | CONFIRM):
+ case (DL_ESTABLISH | INDICATION):
+ case (DL_RELEASE | INDICATION):
+ case (DL_RELEASE | CONFIRM):
+ l3_msg(st, pr, arg);
+ return;
+ break;
+ }
if (skb->len < 4) {
if (st->l3.debug & L3_DEB_PROTERR) {
- sprintf(tmp, "up1tr6 len only %d", skb->len);
+ sprintf(tmp, "up1tr6 len only %ld", skb->len);
l3_debug(st, tmp);
}
dev_kfree_skb(skb);
@@ -742,8 +786,8 @@ up1tr6(struct PStack *st, int pr, void *arg)
}
if ((skb->data[0] & 0xfe) != PROTO_DIS_N0) {
if (st->l3.debug & L3_DEB_PROTERR) {
- sprintf(tmp, "up1tr6%sunexpected discriminator %x message len %d",
- (pr == DL_DATA) ? " " : "(broadcast) ",
+ sprintf(tmp, "up1tr6%sunexpected discriminator %x message len %ld",
+ (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
skb->data[0], skb->len);
l3_debug(st, tmp);
}
@@ -764,12 +808,33 @@ up1tr6(struct PStack *st, int pr, void *arg)
dev_kfree_skb(skb);
if (st->l3.debug & L3_DEB_STATE) {
sprintf(tmp, "up1tr6%s N0 mt %x unhandled",
- (pr == DL_DATA) ? " " : "(broadcast) ", mt);
+ (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", mt);
l3_debug(st, tmp);
}
} else if (skb->data[0] == PROTO_DIS_N1) {
if (!(proc = getl3proc(st, cr))) {
- if ((mt == MT_N1_SETUP) && (cr < 128)) {
+ if (mt == MT_N1_SETUP) {
+ if (cr < 128) {
+ if (!(proc = new_l3_process(st, cr))) {
+ if (st->l3.debug & L3_DEB_PROTERR) {
+ sprintf(tmp, "up1tr6 no roc mem");
+ l3_debug(st, tmp);
+ }
+ dev_kfree_skb(skb);
+ return;
+ }
+ } else {
+ dev_kfree_skb(skb);
+ return;
+ }
+ } else if ((mt == MT_N1_REL) || (mt == MT_N1_REL_ACK) ||
+ (mt == MT_N1_CANC_ACK) || (mt == MT_N1_CANC_REJ) ||
+ (mt == MT_N1_REG_ACK) || (mt == MT_N1_REG_REJ) ||
+ (mt == MT_N1_SUSP_ACK) || (mt == MT_N1_RES_REJ) ||
+ (mt == MT_N1_INFO)) {
+ dev_kfree_skb(skb);
+ return;
+ } else {
if (!(proc = new_l3_process(st, cr))) {
if (st->l3.debug & L3_DEB_PROTERR) {
sprintf(tmp, "up1tr6 no roc mem");
@@ -778,20 +843,18 @@ up1tr6(struct PStack *st, int pr, void *arg)
dev_kfree_skb(skb);
return;
}
- } else {
- dev_kfree_skb(skb);
- return;
+ mt = MT_N1_INVALID;
}
}
- for (i = 0; i < datastln1_len; i++)
+ for (i = 0; i < DATASTLN1_LEN; i++)
if ((mt == datastln1[i].primitive) &&
((1 << proc->state) & datastln1[i].state))
break;
- if (i == datastln1_len) {
+ if (i == DATASTLN1_LEN) {
dev_kfree_skb(skb);
if (st->l3.debug & L3_DEB_STATE) {
sprintf(tmp, "up1tr6%sstate %d mt %x unhandled",
- (pr == DL_DATA) ? " " : "(broadcast) ",
+ (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
proc->state, mt);
l3_debug(st, tmp);
}
@@ -799,7 +862,7 @@ up1tr6(struct PStack *st, int pr, void *arg)
} else {
if (st->l3.debug & L3_DEB_STATE) {
sprintf(tmp, "up1tr6%sstate %d mt %x",
- (pr == DL_DATA) ? " " : "(broadcast) ",
+ (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
proc->state, mt);
l3_debug(st, tmp);
}
@@ -816,7 +879,10 @@ down1tr6(struct PStack *st, int pr, void *arg)
struct Channel *chan;
char tmp[80];
- if (CC_SETUP_REQ == pr) {
+ if (((DL_ESTABLISH | REQUEST)== pr) || ((DL_RELEASE | REQUEST)== pr)) {
+ l3_msg(st, pr, NULL);
+ return;
+ } else if ((CC_SETUP | REQUEST) == pr) {
chan = arg;
cr = newcallref();
cr |= 0x80;
@@ -832,11 +898,11 @@ down1tr6(struct PStack *st, int pr, void *arg)
proc = arg;
}
- for (i = 0; i < downstl_len; i++)
+ for (i = 0; i < DOWNSTL_LEN; i++)
if ((pr == downstl[i].primitive) &&
((1 << proc->state) & downstl[i].state))
break;
- if (i == downstl_len) {
+ if (i == DOWNSTL_LEN) {
if (st->l3.debug & L3_DEB_STATE) {
sprintf(tmp, "down1tr6 state %d prim %d unhandled",
proc->state, pr);
diff --git a/drivers/isdn/hisax/l3_1tr6.h b/drivers/isdn/hisax/l3_1tr6.h
index 90d08793e..7c0ba56b2 100644
--- a/drivers/isdn/hisax/l3_1tr6.h
+++ b/drivers/isdn/hisax/l3_1tr6.h
@@ -1,8 +1,11 @@
-/* $Id: l3_1tr6.h,v 2.0 1997/07/27 21:15:47 keil Exp $
+/* $Id: l3_1tr6.h,v 2.1 1998/08/13 23:36:48 keil Exp $
*
* German 1TR6 D-channel protocol defines
*
* $Log: l3_1tr6.h,v $
+ * Revision 2.1 1998/08/13 23:36:48 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
* Revision 2.0 1997/07/27 21:15:47 keil
* New Callref based layer3
*
@@ -64,6 +67,7 @@
#define MT_N1_REG_ACK 0x6C
#define MT_N1_REG_REJ 0x6F
#define MT_N1_STAT 0x63
+#define MT_N1_INVALID 0
/*
* W Elemente
diff --git a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c
index f8b97fd73..0808d32a0 100644
--- a/drivers/isdn/hisax/l3dss1.c
+++ b/drivers/isdn/hisax/l3dss1.c
@@ -1,14 +1,36 @@
-/* $Id: l3dss1.c,v 2.7 1998/02/12 23:08:01 keil Exp $
+/* $Id: l3dss1.c,v 2.12 1998/11/15 23:55:10 keil Exp $
* EURO/DSS1 D-channel protocol
*
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
* based on the teles driver from Jan den Ouden
*
+ * This file is (c) under GNU PUBLIC LICENSE
+ * For changes and modifications please read
+ * ../../../Documentation/isdn/HiSax.cert
+ *
* Thanks to Jan den Ouden
* Fritz Elfert
*
* $Log: l3dss1.c,v $
+ * Revision 2.12 1998/11/15 23:55:10 keil
+ * changes from 2.0
+ *
+ * Revision 2.11 1998/08/13 23:36:51 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.10 1998/05/25 14:10:20 keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.9 1998/05/25 12:58:17 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.8 1998/03/19 13:18:47 keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
* Revision 2.7 1998/02/12 23:08:01 keil
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
@@ -50,9 +72,7 @@
#include <linux/ctype.h>
extern char *HiSax_getrev(const char *revision);
-const char *dss1_revision = "$Revision: 2.7 $";
-
-#define EXT_BEARER_CAPS 1
+const char *dss1_revision = "$Revision: 2.12 $";
#define MsgHead(ptr, cref, mty) \
*ptr++ = 0x8; \
@@ -61,12 +81,11 @@ const char *dss1_revision = "$Revision: 2.7 $";
*ptr++ = mty
-#ifdef HISAX_DE_AOC
+#if HISAX_DE_AOC
static void
-l3dss1_parse_facility(struct l3_process *pc, u_char *p)
+l3dss1_parse_facility(struct l3_process *pc, u_char * p)
{
int qd_len = 0;
- char tmp[32];
p++;
qd_len = *p++;
@@ -74,91 +93,99 @@ l3dss1_parse_facility(struct l3_process *pc, u_char *p)
l3_debug(pc->st, "qd_len == 0");
return;
}
- if((*p & 0x1F) != 0x11) { /* Service discriminator, supplementary service */
+ if ((*p & 0x1F) != 0x11) { /* Service discriminator, supplementary service */
l3_debug(pc->st, "supplementary service != 0x11");
return;
}
- while(qd_len > 0 && !(*p & 0x80)) { /* extension ? */
- p++; qd_len--;
- }
- if(qd_len < 2) {
+ while (qd_len > 0 && !(*p & 0x80)) { /* extension ? */
+ p++;
+ qd_len--;
+ }
+ if (qd_len < 2) {
l3_debug(pc->st, "qd_len < 2");
return;
}
- p++; qd_len--;
- if((*p & 0xE0) != 0xA0) { /* class and form */
+ p++;
+ qd_len--;
+ if ((*p & 0xE0) != 0xA0) { /* class and form */
l3_debug(pc->st, "class and form != 0xA0");
return;
}
- switch(*p & 0x1F) { /* component tag */
- case 1: /* invoke */
- {
- unsigned char nlen, ilen;
- int ident;
-
- p++; qd_len--;
- if(qd_len < 1) {
- l3_debug(pc->st, "qd_len < 1");
- break;
- }
- if(*p & 0x80) { /* length format */
- l3_debug(pc->st, "*p & 0x80 length format");
- break;
- }
- nlen = *p++; qd_len--;
- if(qd_len < nlen) {
- l3_debug(pc->st, "qd_len < nlen");
- return;
- }
- qd_len -= nlen;
-
- if(nlen < 2) {
- l3_debug(pc->st, "nlen < 2");
- return;
- }
- if(*p != 0x02) { /* invoke identifier tag */
- l3_debug(pc->st, "invoke identifier tag !=0x02");
- return;
- }
- p++; nlen--;
- if(*p & 0x80) { /* length format */
- l3_debug(pc->st, "*p & 0x80 length format 2");
- break;
- }
- ilen = *p++; nlen--;
- if(ilen > nlen || ilen == 0) {
- l3_debug(pc->st, "ilen > nlen || ilen == 0");
- return;
- }
- nlen -= ilen;
- ident = 0;
- while(ilen > 0) {
- ident = (ident << 8) | (*p++ & 0xFF); /* invoke identifier */
- ilen--;
- }
-
- if(nlen < 2) {
- l3_debug(pc->st, "nlen < 2 22");
- return;
- }
- if(*p != 0x02) { /* operation value */
- l3_debug(pc->st, "operation value !=0x02");
- return;
- }
- p++; nlen--;
- ilen = *p++; nlen--;
- if(ilen > nlen || ilen == 0) {
- l3_debug(pc->st, "ilen > nlen || ilen == 0 22");
- return;
- }
- nlen -= ilen;
- ident = 0;
- while(ilen > 0) {
- ident = (ident << 8) | (*p++ & 0xFF);
- ilen--;
- }
-
- #define FOO1(s,a,b) \
+ switch (*p & 0x1F) { /* component tag */
+ case 1: /* invoke */
+ {
+ unsigned char nlen = 0, ilen;
+ int ident;
+
+ p++;
+ qd_len--;
+ if (qd_len < 1) {
+ l3_debug(pc->st, "qd_len < 1");
+ break;
+ }
+ if (*p & 0x80) { /* length format */
+ l3_debug(pc->st, "*p & 0x80 length format");
+ break;
+ }
+ nlen = *p++;
+ qd_len--;
+ if (qd_len < nlen) {
+ l3_debug(pc->st, "qd_len < nlen");
+ return;
+ }
+ qd_len -= nlen;
+
+ if (nlen < 2) {
+ l3_debug(pc->st, "nlen < 2");
+ return;
+ }
+ if (*p != 0x02) { /* invoke identifier tag */
+ l3_debug(pc->st, "invoke identifier tag !=0x02");
+ return;
+ }
+ p++;
+ nlen--;
+ if (*p & 0x80) { /* length format */
+ l3_debug(pc->st, "*p & 0x80 length format 2");
+ break;
+ }
+ ilen = *p++;
+ nlen--;
+ if (ilen > nlen || ilen == 0) {
+ l3_debug(pc->st, "ilen > nlen || ilen == 0");
+ return;
+ }
+ nlen -= ilen;
+ ident = 0;
+ while (ilen > 0) {
+ ident = (ident << 8) | (*p++ & 0xFF); /* invoke identifier */
+ ilen--;
+ }
+
+ if (nlen < 2) {
+ l3_debug(pc->st, "nlen < 2 22");
+ return;
+ }
+ if (*p != 0x02) { /* operation value */
+ l3_debug(pc->st, "operation value !=0x02");
+ return;
+ }
+ p++;
+ nlen--;
+ ilen = *p++;
+ nlen--;
+ if (ilen > nlen || ilen == 0) {
+ l3_debug(pc->st, "ilen > nlen || ilen == 0 22");
+ return;
+ }
+ nlen -= ilen;
+ ident = 0;
+ while (ilen > 0) {
+ ident = (ident << 8) | (*p++ & 0xFF);
+ ilen--;
+ }
+
+#define FOO1(s,a,b) \
while(nlen > 1) { \
int ilen = p[1]; \
if(nlen < ilen+2) { \
@@ -174,72 +201,74 @@ l3dss1_parse_facility(struct l3_process *pc, u_char *p)
p += ilen+2; \
} \
}
-
- switch(ident) {
- default:
- break;
- case 0x22: /* during */
- FOO1("1A",0x30,FOO1("1C",0xA1,FOO1("1D",0x30,FOO1("1E",0x02,({
- ident = 0;
- while(ilen > 0) {
- ident = (ident<<8) | *p++;
- ilen--;
- }
- if (ident > pc->para.chargeinfo) {
- pc->para.chargeinfo = ident;
- pc->st->l3.l3l4(pc, CC_INFO_CHARGE, NULL);
- }
- if (pc->st->l3.debug & L3_DEB_CHARGE) {
- if (*(p+2) == 0) {
- sprintf(tmp, "charging info during %d", pc->para.chargeinfo);
- l3_debug(pc->st, tmp);
- }
- else {
- sprintf(tmp, "charging info final %d", pc->para.chargeinfo);
- l3_debug(pc->st, tmp);
- }
- }
- })))))
- break;
- case 0x24: /* final */
- FOO1("2A",0x30,FOO1("2B",0x30,FOO1("2C",0xA1,FOO1("2D",0x30,FOO1("2E",0x02,({
- ident = 0;
- while(ilen > 0) {
- ident = (ident<<8) | *p++;
- ilen--;
- }
- if (ident > pc->para.chargeinfo) {
- pc->para.chargeinfo = ident;
- pc->st->l3.l3l4(pc, CC_INFO_CHARGE, NULL);
- }
- if (pc->st->l3.debug & L3_DEB_CHARGE) {
- sprintf(tmp, "charging info final %d", pc->para.chargeinfo);
- l3_debug(pc->st, tmp);
- }
- }))))))
- break;
- }
- #undef FOO1
-
- }
- break;
- case 2: /* return result */
- l3_debug(pc->st, "return result break");
- break;
- case 3: /* return error */
- l3_debug(pc->st, "return error break");
- break;
- default:
- l3_debug(pc->st, "default break");
- break;
+
+ switch (ident) {
+ default:
+ break;
+ case 0x22: /* during */
+ FOO1("1A", 0x30, FOO1("1C", 0xA1, FOO1("1D", 0x30, FOO1("1E", 0x02, ( {
+ ident = 0;
+ nlen = (nlen)?nlen:0; /* Make gcc happy */
+ while (ilen > 0) {
+ ident = (ident << 8) | *p++;
+ ilen--;
+ }
+ if (ident > pc->para.chargeinfo) {
+ pc->para.chargeinfo = ident;
+ pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
+ }
+ if (pc->st->l3.debug & L3_DEB_CHARGE) {
+ if (*(p + 2) == 0) {
+ l3_debug(pc->st, "charging info during %d", pc->para.chargeinfo);
+ }
+ else {
+ l3_debug(pc->st, "charging info final %d", pc->para.chargeinfo);
+ }
+ }
+ }
+ )))))
+ break;
+ case 0x24: /* final */
+ FOO1("2A", 0x30, FOO1("2B", 0x30, FOO1("2C", 0xA1, FOO1("2D", 0x30, FOO1("2E", 0x02, ( {
+ ident = 0;
+ nlen = (nlen)?nlen:0; /* Make gcc happy */
+ while (ilen > 0) {
+ ident = (ident << 8) | *p++;
+ ilen--;
+ }
+ if (ident > pc->para.chargeinfo) {
+ pc->para.chargeinfo = ident;
+ pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
+ }
+ if (pc->st->l3.debug & L3_DEB_CHARGE) {
+ l3_debug(pc->st, "charging info final %d", pc->para.chargeinfo);
+ }
+ }
+ ))))))
+ break;
+ }
+#undef FOO1
+
+ }
+ break;
+ case 2: /* return result */
+ l3_debug(pc->st, "return result break");
+ break;
+ case 3: /* return error */
+ l3_debug(pc->st, "return error break");
+ break;
+ default:
+ l3_debug(pc->st, "default break");
+ break;
}
}
-#endif
+#endif
-static int
-l3dss1_check_messagetype_validity(int mt) {
+static int
+l3dss1_check_messagetype_validity(int mt)
+{
/* verify if a message type exists */
- switch(mt) {
+ switch (mt) {
case MT_ALERTING:
case MT_CALL_PROCEEDING:
case MT_CONNECT:
@@ -283,7 +312,7 @@ l3dss1_message(struct l3_process *pc, u_char mt)
return;
p = skb_put(skb, 4);
MsgHead(p, pc->callref, mt);
- pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
}
static void
@@ -314,165 +343,244 @@ l3dss1_release_cmpl(struct l3_process *pc, u_char pr, void *arg)
StopAllL3Timer(pc);
pc->para.cause = cause;
newl3state(pc, 0);
- pc->st->l3.l3l4(pc, CC_RELEASE_CNF, NULL);
+ pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
release_l3_process(pc);
}
-#ifdef EXT_BEARER_CAPS
-
-u_char *EncodeASyncParams(u_char *p, u_char si2)
-{ // 7c 06 88 90 21 42 00 bb
-
- p[0] = p[1] = 0; p[2] = 0x80;
- if (si2 & 32) // 7 data bits
- p[2] += 16;
- else // 8 data bits
- p[2] +=24;
-
- if (si2 & 16) // 2 stop bits
- p[2] += 96;
- else // 1 stop bit
- p[2] = 32;
-
- if (si2 & 8) // even parity
- p[2] += 2;
- else // no parity
- p[2] += 3;
-
- switch (si2 & 0x07)
- {
- case 0: p[0] = 66; // 1200 bit/s
- break;
- case 1: p[0] = 88; // 1200/75 bit/s
- break;
- case 2: p[0] = 87; // 75/1200 bit/s
- break;
- case 3: p[0] = 67; // 2400 bit/s
- break;
- case 4: p[0] = 69; // 4800 bit/s
- break;
- case 5: p[0] = 72; // 9600 bit/s
- break;
- case 6: p[0] = 73; // 14400 bit/s
- break;
- case 7: p[0] = 75; // 19200 bit/s
- break;
- }
- return p+3;
+#if EXT_BEARER_CAPS
+
+u_char *
+EncodeASyncParams(u_char * p, u_char si2)
+{ // 7c 06 88 90 21 42 00 bb
+
+ p[0] = p[1] = 0;
+ p[2] = 0x80;
+ if (si2 & 32) // 7 data bits
+
+ p[2] += 16;
+ else // 8 data bits
+
+ p[2] += 24;
+
+ if (si2 & 16) // 2 stop bits
+
+ p[2] += 96;
+ else // 1 stop bit
+
+ p[2] = 32;
+
+ if (si2 & 8) // even parity
+
+ p[2] += 2;
+ else // no parity
+
+ p[2] += 3;
+
+ switch (si2 & 0x07) {
+ case 0:
+ p[0] = 66; // 1200 bit/s
+
+ break;
+ case 1:
+ p[0] = 88; // 1200/75 bit/s
+
+ break;
+ case 2:
+ p[0] = 87; // 75/1200 bit/s
+
+ break;
+ case 3:
+ p[0] = 67; // 2400 bit/s
+
+ break;
+ case 4:
+ p[0] = 69; // 4800 bit/s
+
+ break;
+ case 5:
+ p[0] = 72; // 9600 bit/s
+
+ break;
+ case 6:
+ p[0] = 73; // 14400 bit/s
+
+ break;
+ case 7:
+ p[0] = 75; // 19200 bit/s
+
+ break;
+ }
+ return p + 3;
}
-u_char EncodeSyncParams(u_char si2, u_char ai)
+u_char
+EncodeSyncParams(u_char si2, u_char ai)
{
- switch (si2)
- {
- case 0: return ai + 2; // 1200 bit/s
- case 1: return ai + 24; // 1200/75 bit/s
- case 2: return ai + 23; // 75/1200 bit/s
- case 3: return ai + 3; // 2400 bit/s
- case 4: return ai + 5; // 4800 bit/s
- case 5: return ai + 8; // 9600 bit/s
- case 6: return ai + 9; // 14400 bit/s
- case 7: return ai + 11; // 19200 bit/s
- case 8: return ai + 14; // 48000 bit/s
- case 9: return ai + 15; // 56000 bit/s
- case 15: return ai + 40; // negotiate bit/s
- default: break;
- }
- return ai;
+ switch (si2) {
+ case 0:
+ return ai + 2; // 1200 bit/s
+
+ case 1:
+ return ai + 24; // 1200/75 bit/s
+
+ case 2:
+ return ai + 23; // 75/1200 bit/s
+
+ case 3:
+ return ai + 3; // 2400 bit/s
+
+ case 4:
+ return ai + 5; // 4800 bit/s
+
+ case 5:
+ return ai + 8; // 9600 bit/s
+
+ case 6:
+ return ai + 9; // 14400 bit/s
+
+ case 7:
+ return ai + 11; // 19200 bit/s
+
+ case 8:
+ return ai + 14; // 48000 bit/s
+
+ case 9:
+ return ai + 15; // 56000 bit/s
+
+ case 15:
+ return ai + 40; // negotiate bit/s
+
+ default:
+ break;
+ }
+ return ai;
}
-static u_char DecodeASyncParams(u_char si2, u_char *p)
-{ u_char info;
-
- switch (p[5])
- {
- case 66: // 1200 bit/s
- break; // si2 bleibt gleich
- case 88: // 1200/75 bit/s
- si2 += 1;
- break;
- case 87: // 75/1200 bit/s
- si2 += 2;
- break;
- case 67: // 2400 bit/s
- si2 += 3;
- break;
- case 69: // 4800 bit/s
- si2 += 4;
- break;
- case 72: // 9600 bit/s
- si2 += 5;
- break;
- case 73: // 14400 bit/s
- si2 += 6;
- break;
- case 75: // 19200 bit/s
- si2 += 7;
- break;
- }
-
- info = p[7] & 0x7f;
- if ((info & 16) && (!(info & 8))) // 7 data bits
- si2 += 32; // else 8 data bits
- if ((info & 96) == 96) // 2 stop bits
- si2 += 16; // else 1 stop bit
- if ((info & 2) && (!(info & 1))) // even parity
- si2 += 8; // else no parity
-
- return si2;
+static u_char
+DecodeASyncParams(u_char si2, u_char * p)
+{
+ u_char info;
+
+ switch (p[5]) {
+ case 66: // 1200 bit/s
+
+ break; // si2 don't change
+
+ case 88: // 1200/75 bit/s
+
+ si2 += 1;
+ break;
+ case 87: // 75/1200 bit/s
+
+ si2 += 2;
+ break;
+ case 67: // 2400 bit/s
+
+ si2 += 3;
+ break;
+ case 69: // 4800 bit/s
+
+ si2 += 4;
+ break;
+ case 72: // 9600 bit/s
+
+ si2 += 5;
+ break;
+ case 73: // 14400 bit/s
+
+ si2 += 6;
+ break;
+ case 75: // 19200 bit/s
+
+ si2 += 7;
+ break;
+ }
+
+ info = p[7] & 0x7f;
+ if ((info & 16) && (!(info & 8))) // 7 data bits
+
+ si2 += 32; // else 8 data bits
+
+ if ((info & 96) == 96) // 2 stop bits
+
+ si2 += 16; // else 1 stop bit
+
+ if ((info & 2) && (!(info & 1))) // even parity
+
+ si2 += 8; // else no parity
+
+ return si2;
}
-static u_char DecodeSyncParams(u_char si2, u_char info)
+static u_char
+DecodeSyncParams(u_char si2, u_char info)
{
- info &= 0x7f;
- switch (info)
- {
- case 40: // bit/s aushandeln --- hat nicht geklappt, ai wird 165 statt 175!
- return si2 + 15;
- case 15: // 56000 bit/s --- hat nicht geklappt, ai wird 0 statt 169 !
- return si2 + 9;
- case 14: // 48000 bit/s
- return si2 + 8;
- case 11: // 19200 bit/s
- return si2 + 7;
- case 9: // 14400 bit/s
- return si2 + 6;
- case 8: // 9600 bit/s
- return si2 + 5;
- case 5: // 4800 bit/s
- return si2 + 4;
- case 3: // 2400 bit/s
- return si2 + 3;
- case 23: // 75/1200 bit/s
- return si2 + 2;
- case 24: // 1200/75 bit/s
- return si2 + 1;
- default: // 1200 bit/s
- return si2;
- }
+ info &= 0x7f;
+ switch (info) {
+ case 40: // bit/s negotiation failed ai := 165 not 175!
+
+ return si2 + 15;
+ case 15: // 56000 bit/s failed, ai := 0 not 169 !
+
+ return si2 + 9;
+ case 14: // 48000 bit/s
+
+ return si2 + 8;
+ case 11: // 19200 bit/s
+
+ return si2 + 7;
+ case 9: // 14400 bit/s
+
+ return si2 + 6;
+ case 8: // 9600 bit/s
+
+ return si2 + 5;
+ case 5: // 4800 bit/s
+
+ return si2 + 4;
+ case 3: // 2400 bit/s
+
+ return si2 + 3;
+ case 23: // 75/1200 bit/s
+
+ return si2 + 2;
+ case 24: // 1200/75 bit/s
+
+ return si2 + 1;
+ default: // 1200 bit/s
+
+ return si2;
+ }
}
-static u_char DecodeSI2(struct sk_buff *skb)
-{ u_char *p; //, *pend=skb->data + skb->len;
-
- if ((p = findie(skb->data, skb->len, 0x7c, 0)))
- {
- switch (p[4] & 0x0f)
- {
- case 0x01: if (p[1] == 0x04) // sync. Bitratenadaption
- return DecodeSyncParams(160, p[5]); // V.110/X.30
- else if (p[1] == 0x06) // async. Bitratenadaption
- return DecodeASyncParams(192, p); // V.110/X.30
- break;
- case 0x08: // if (p[5] == 0x02) // sync. Bitratenadaption
- return DecodeSyncParams(176, p[5]); // V.120
- break;
- }
- }
- return 0;
+static u_char
+DecodeSI2(struct sk_buff *skb)
+{
+ u_char *p; //, *pend=skb->data + skb->len;
+
+ if ((p = findie(skb->data, skb->len, 0x7c, 0))) {
+ switch (p[4] & 0x0f) {
+ case 0x01:
+ if (p[1] == 0x04) // sync. Bitratenadaption
+
+ return DecodeSyncParams(160, p[5]); // V.110/X.30
+
+ else if (p[1] == 0x06) // async. Bitratenadaption
+
+ return DecodeASyncParams(192, p); // V.110/X.30
+
+ break;
+ case 0x08: // if (p[5] == 0x02) // sync. Bitratenadaption
+
+ return DecodeSyncParams(176, p[5]); // V.120
+
+ break;
+ }
+ }
+ return 0;
}
#endif
@@ -498,7 +606,7 @@ l3dss1_setup_req(struct l3_process *pc, u_char pr,
/*
* Set Bearer Capability, Map info from 1TR6-convention to EDSS1
*/
-#ifdef HISAX_EURO_SENDCOMPLETE
+#if HISAX_EURO_SENDCOMPLETE
*p++ = 0xa1; /* complete indicator */
#endif
switch (pc->para.setup.si1) {
@@ -558,11 +666,11 @@ l3dss1_setup_req(struct l3_process *pc, u_char pr,
msn = pc->para.setup.eazmsn;
sub = NULL;
sp = msn;
- while (*sp) {
+ while (*sp) {
if ('.' == *sp) {
sub = sp;
*sp = 0;
- } else
+ } else
sp++;
}
if (*msn) {
@@ -579,20 +687,20 @@ l3dss1_setup_req(struct l3_process *pc, u_char pr,
}
if (sub) {
*sub++ = '.';
- *p++ = 0x6d; /* Calling party subaddress */
- *p++ = strlen(sub) + 2;
+ *p++ = 0x6d; /* Calling party subaddress */
+ *p++ = strlen(sub) + 2;
*p++ = 0x80; /* NSAP coded */
*p++ = 0x50; /* local IDI format */
- while (*sub)
+ while (*sub)
*p++ = *sub++ & 0x7f;
}
sub = NULL;
sp = teln;
- while (*sp) {
+ while (*sp) {
if ('.' == *sp) {
sub = sp;
*sp = 0;
- } else
+ } else
sp++;
}
*p++ = 0x70;
@@ -604,31 +712,47 @@ l3dss1_setup_req(struct l3_process *pc, u_char pr,
if (sub) {
*sub++ = '.';
- *p++ = 0x71; /* Called party subaddress */
- *p++ = strlen(sub) + 2;
+ *p++ = 0x71; /* Called party subaddress */
+ *p++ = strlen(sub) + 2;
*p++ = 0x80; /* NSAP coded */
*p++ = 0x50; /* local IDI format */
- while (*sub)
+ while (*sub)
*p++ = *sub++ & 0x7f;
}
-
-#ifdef EXT_BEARER_CAPS
- if ((pc->para.setup.si2 >= 160) && (pc->para.setup.si2 <= 175))
- { // sync. Bitratenadaption, V.110/X.30
- *p++ = 0x7c; *p++ = 0x04; *p++ = 0x88; *p++ = 0x90; *p++ = 0x21;
- *p++ = EncodeSyncParams(pc->para.setup.si2 - 160, 0x80);
- }
- else if ((pc->para.setup.si2 >= 176) && (pc->para.setup.si2 <= 191))
- { // sync. Bitratenadaption, V.120
- *p++ = 0x7c; *p++ = 0x05; *p++ = 0x88; *p++ = 0x90; *p++ = 0x28;
- *p++ = EncodeSyncParams(pc->para.setup.si2 - 176, 0);
- *p++ = 0x82;
- }
- else if (pc->para.setup.si2 >= 192)
- { // async. Bitratenadaption, V.110/X.30
- *p++ = 0x7c; *p++ = 0x06; *p++ = 0x88; *p++ = 0x90; *p++ = 0x21;
- p = EncodeASyncParams(p, pc->para.setup.si2 - 192);
- }
+#if EXT_BEARER_CAPS
+ if ((pc->para.setup.si2 >= 160) && (pc->para.setup.si2 <= 175)) { // sync. Bitratenadaption, V.110/X.30
+
+ *p++ = 0x7c;
+ *p++ = 0x04;
+ *p++ = 0x88;
+ *p++ = 0x90;
+ *p++ = 0x21;
+ *p++ = EncodeSyncParams(pc->para.setup.si2 - 160, 0x80);
+ } else if ((pc->para.setup.si2 >= 176) && (pc->para.setup.si2 <= 191)) { // sync. Bitratenadaption, V.120
+
+ *p++ = 0x7c;
+ *p++ = 0x05;
+ *p++ = 0x88;
+ *p++ = 0x90;
+ *p++ = 0x28;
+ *p++ = EncodeSyncParams(pc->para.setup.si2 - 176, 0);
+ *p++ = 0x82;
+ } else if (pc->para.setup.si2 >= 192) { // async. Bitratenadaption, V.110/X.30
+
+ *p++ = 0x7c;
+ *p++ = 0x06;
+ *p++ = 0x88;
+ *p++ = 0x90;
+ *p++ = 0x21;
+ p = EncodeASyncParams(p, pc->para.setup.si2 - 192);
+#if HISAX_SEND_STD_LLC_IE
+ } else {
+ *p++ = 0x7c;
+ *p++ = 0x02;
+ *p++ = 0x88;
+ *p++ = 0x90;
+#endif
+ }
#endif
l = p - tmp;
if (!(skb = l3_alloc_skb(l)))
@@ -637,7 +761,7 @@ l3dss1_setup_req(struct l3_process *pc, u_char pr,
L3DelTimer(&pc->timer);
L3AddTimer(&pc->timer, T303, CC_T303);
newl3state(pc, 1);
- pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
}
static void
@@ -657,7 +781,7 @@ l3dss1_call_proc(struct l3_process *pc, u_char pr, void *arg)
dev_kfree_skb(skb);
newl3state(pc, 3);
L3AddTimer(&pc->timer, T310, CC_T310);
- pc->st->l3.l3l4(pc, CC_PROCEEDING_IND, NULL);
+ pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
}
static void
@@ -677,7 +801,7 @@ l3dss1_setup_ack(struct l3_process *pc, u_char pr, void *arg)
dev_kfree_skb(skb);
newl3state(pc, 2);
L3AddTimer(&pc->timer, T304, CC_T304);
- pc->st->l3.l3l4(pc, CC_MORE_INFO, NULL);
+ pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
}
static void
@@ -699,7 +823,7 @@ l3dss1_disconnect(struct l3_process *pc, u_char pr, void *arg)
dev_kfree_skb(skb);
newl3state(pc, 12);
pc->para.cause = cause;
- pc->st->l3.l3l4(pc, CC_DISCONNECT_IND, NULL);
+ pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
}
static void
@@ -711,7 +835,7 @@ l3dss1_connect(struct l3_process *pc, u_char pr, void *arg)
L3DelTimer(&pc->timer); /* T310 */
newl3state(pc, 10);
pc->para.chargeinfo = 0;
- pc->st->l3.l3l4(pc, CC_SETUP_CNF, NULL);
+ pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
}
static void
@@ -722,49 +846,48 @@ l3dss1_alerting(struct l3_process *pc, u_char pr, void *arg)
dev_kfree_skb(skb);
L3DelTimer(&pc->timer); /* T304 */
newl3state(pc, 4);
- pc->st->l3.l3l4(pc, CC_ALERTING_IND, NULL);
+ pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
}
static void
l3dss1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg)
{
- /* This routine is called if here was no SETUP made (checks in dss1up and in
- * l3dss1_setup) and a RELEASE_COMPLETE have to be sent with an error code
- * It is called after it is veryfied that Layer2 is up.
- * The cause value is allready in pc->para.cause
- * MT_STATUS_ENQUIRE in the NULL state is handled too
- */
+ /* This routine is called if here was no SETUP made (checks in dss1up and in
+ * l3dss1_setup) and a RELEASE_COMPLETE have to be sent with an error code
+ * MT_STATUS_ENQUIRE in the NULL state is handled too
+ */
u_char tmp[16];
- u_char *p=tmp;
+ u_char *p = tmp;
int l;
struct sk_buff *skb;
switch (pc->para.cause) {
- case 81: /* 0x51 invalid callreference */
- case 96: /* 0x60 mandory IE missing */
- case 101: /* 0x65 incompatible Callstate */
- MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
- *p++ = IE_CAUSE;
- *p++ = 0x2;
- *p++ = 0x80;
- *p++ = pc->para.cause | 0x80;
- break;
- default:
- printk(KERN_ERR "HiSax internal error l3dss1_msg_without_setup\n");
- return;
- }
+ case 81: /* 0x51 invalid callreference */
+ case 88: /* 0x58 incomp destination */
+ case 96: /* 0x60 mandory IE missing */
+ case 101: /* 0x65 incompatible Callstate */
+ MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
+ *p++ = IE_CAUSE;
+ *p++ = 0x2;
+ *p++ = 0x80;
+ *p++ = pc->para.cause | 0x80;
+ break;
+ default:
+ printk(KERN_ERR "HiSax internal error l3dss1_msg_without_setup\n");
+ return;
+ }
l = p - tmp;
if (!(skb = l3_alloc_skb(l)))
return;
memcpy(skb_put(skb, l), tmp, l);
- pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
release_l3_process(pc);
}
static void
l3dss1_setup(struct l3_process *pc, u_char pr, void *arg)
{
- u_char *p, *ptmp[8];
+ u_char *p, *ptmp[8];
int i;
int bcfound = 0;
char tmp[80];
@@ -772,9 +895,9 @@ l3dss1_setup(struct l3_process *pc, u_char pr, void *arg)
/* ETS 300-104 1.3.4 and 1.3.5
* we need to detect unknown inform. element from 0 to 7
- */
+ */
p = skb->data;
- for(i = 0; i < 8; i++)
+ for (i = 0; i < 8; i++)
ptmp[i] = skb->data;
if (findie(ptmp[1], skb->len, 0x01, 0)
|| findie(ptmp[2], skb->len, 0x02, 0)
@@ -782,18 +905,14 @@ l3dss1_setup(struct l3_process *pc, u_char pr, void *arg)
|| findie(ptmp[5], skb->len, 0x05, 0)
|| findie(ptmp[6], skb->len, 0x06, 0)
|| findie(ptmp[7], skb->len, 0x07, 0)) {
- /* if ie is < 8 and not 0 nor 4, send RELEASE_COMPLETE
- * cause 0x60
- */
- pc->para.cause = 0x60;
+ /* if ie is < 8 and not 0 nor 4, send RELEASE_COMPLETE
+ * cause 0x60
+ */
+ pc->para.cause = 0x60;
dev_kfree_skb(skb);
- if (pc->state == 0)
- pc->st->l3.l3l4(pc, CC_ESTABLISH, NULL);
- else
- l3dss1_msg_without_setup(pc, pr, NULL);
+ l3dss1_msg_without_setup(pc, pr, NULL);
return;
}
-
/*
* Channel Identification
*/
@@ -804,9 +923,14 @@ l3dss1_setup(struct l3_process *pc, u_char pr, void *arg)
bcfound++;
else if (pc->debug & L3_DEB_WARN)
l3_debug(pc->st, "setup without bchannel");
- } else if (pc->debug & L3_DEB_WARN)
- l3_debug(pc->st, "setup without bchannel");
-
+ } else {
+ if (pc->debug & L3_DEB_WARN)
+ l3_debug(pc->st, "setup without bchannel");
+ pc->para.cause = 0x60;
+ dev_kfree_skb(skb);
+ l3dss1_msg_without_setup(pc, pr, NULL);
+ return;
+ }
/*
* Bearer Capabilities
*/
@@ -824,10 +948,10 @@ l3dss1_setup(struct l3_process *pc, u_char pr, void *arg)
/* Unrestricted digital information */
pc->para.setup.si1 = 7;
/* JIM, 05.11.97 I wanna set service indicator 2 */
-#ifdef EXT_BEARER_CAPS
- pc->para.setup.si2 = DecodeSI2(skb);
- printk(KERN_DEBUG "HiSax: SI=%d, AI=%d\n",
- pc->para.setup.si1, pc->para.setup.si2);
+#if EXT_BEARER_CAPS
+ pc->para.setup.si2 = DecodeSI2(skb);
+ printk(KERN_DEBUG "HiSax: SI=%d, AI=%d\n",
+ pc->para.setup.si1, pc->para.setup.si2);
#endif
break;
case 0x09:
@@ -849,12 +973,9 @@ l3dss1_setup(struct l3_process *pc, u_char pr, void *arg)
if (pc->debug & L3_DEB_WARN)
l3_debug(pc->st, "setup without bearer capabilities");
/* ETS 300-104 1.3.3 */
- pc->para.cause = 0x60;
+ pc->para.cause = 0x60;
dev_kfree_skb(skb);
- if (pc->state == 0)
- pc->st->l3.l3l4(pc, CC_ESTABLISH, NULL);
- else
- l3dss1_msg_without_setup(pc, pr, NULL);
+ l3dss1_msg_without_setup(pc, pr, NULL);
return;
}
@@ -867,8 +988,8 @@ l3dss1_setup(struct l3_process *pc, u_char pr, void *arg)
p = skb->data;
if ((p = findie(p, skb->len, 0x71, 0))) {
/* Called party subaddress */
- if ((p[1]>=2) && (p[2]==0x80) && (p[3]==0x50)) {
- tmp[0]='.';
+ if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) {
+ tmp[0] = '.';
iecpy(&tmp[1], p, 2);
strcat(pc->para.setup.eazmsn, tmp);
} else if (pc->debug & L3_DEB_WARN)
@@ -892,24 +1013,28 @@ l3dss1_setup(struct l3_process *pc, u_char pr, void *arg)
p = skb->data;
if ((p = findie(p, skb->len, 0x6d, 0))) {
/* Calling party subaddress */
- if ((p[1]>=2) && (p[2]==0x80) && (p[3]==0x50)) {
- tmp[0]='.';
+ if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) {
+ tmp[0] = '.';
iecpy(&tmp[1], p, 2);
strcat(pc->para.setup.phone, tmp);
} else if (pc->debug & L3_DEB_WARN)
l3_debug(pc->st, "wrong calling subaddress");
}
-
dev_kfree_skb(skb);
if (bcfound) {
if ((pc->para.setup.si1 != 7) && (pc->debug & L3_DEB_WARN)) {
- sprintf(tmp, "non-digital call: %s -> %s",
- pc->para.setup.phone, pc->para.setup.eazmsn);
- l3_debug(pc->st, tmp);
+ l3_debug(pc->st, "non-digital call: %s -> %s",
+ pc->para.setup.phone, pc->para.setup.eazmsn);
+ }
+ if ((pc->para.setup.si1 != 7) &&
+ test_bit(FLG_PTP, &pc->st->l2.flag)) {
+ pc->para.cause = 0x58;
+ l3dss1_msg_without_setup(pc, pr, NULL);
+ return;
}
newl3state(pc, 6);
- pc->st->l3.l3l4(pc, CC_SETUP_IND, NULL);
+ pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
} else
release_l3_process(pc);
}
@@ -938,7 +1063,7 @@ l3dss1_connect_ack(struct l3_process *pc, u_char pr, void *arg)
dev_kfree_skb(skb);
newl3state(pc, 10);
L3DelTimer(&pc->timer);
- pc->st->l3.l3l4(pc, CC_SETUP_COMPLETE_IND, NULL);
+ pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
}
static void
@@ -967,7 +1092,7 @@ l3dss1_disconnect_req(struct l3_process *pc, u_char pr, void *arg)
return;
memcpy(skb_put(skb, l), tmp, l);
newl3state(pc, 11);
- pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
L3AddTimer(&pc->timer, T305, CC_T305);
}
@@ -994,8 +1119,8 @@ l3dss1_reject_req(struct l3_process *pc, u_char pr, void *arg)
if (!(skb = l3_alloc_skb(l)))
return;
memcpy(skb_put(skb, l), tmp, l);
- pc->st->l3.l3l2(pc->st, DL_DATA, skb);
- pc->st->l3.l3l4(pc, CC_RELEASE_IND, NULL);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
+ pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
newl3state(pc, 0);
release_l3_process(pc);
}
@@ -1016,8 +1141,8 @@ l3dss1_release(struct l3_process *pc, u_char pr, void *arg)
}
p = skb->data;
if ((p = findie(p, skb->len, IE_FACILITY, 0))) {
-#ifdef HISAX_DE_AOC
- l3dss1_parse_facility(pc,p);
+#if HISAX_DE_AOC
+ l3dss1_parse_facility(pc, p);
#else
p = NULL;
#endif
@@ -1026,7 +1151,7 @@ l3dss1_release(struct l3_process *pc, u_char pr, void *arg)
StopAllL3Timer(pc);
pc->para.cause = cause;
l3dss1_message(pc, MT_RELEASE_COMPLETE);
- pc->st->l3.l3l4(pc, CC_RELEASE_IND, NULL);
+ pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
newl3state(pc, 0);
release_l3_process(pc);
}
@@ -1064,15 +1189,15 @@ l3dss1_status_enq(struct l3_process *pc, u_char pr, void *arg)
if (!(skb = l3_alloc_skb(l)))
return;
memcpy(skb_put(skb, l), tmp, l);
- pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
}
static void
l3dss1_status_req(struct l3_process *pc, u_char pr, void *arg)
{
- /* ETS 300-104 7.4.1, 8.4.1, 10.3.1, 11.4.1, 12.4.1, 13.4.1, 14.4.1...
- if setup has been made and a non expected message type is received, we must send MT_STATUS cause 0x62 */
- u_char tmp[16];
+ /* ETS 300-104 7.4.1, 8.4.1, 10.3.1, 11.4.1, 12.4.1, 13.4.1, 14.4.1...
+ if setup has been made and a non expected message type is received, we must send MT_STATUS cause 0x62 */
+ u_char tmp[16];
u_char *p = tmp;
int l;
struct sk_buff *skb = arg;
@@ -1084,7 +1209,7 @@ l3dss1_status_req(struct l3_process *pc, u_char pr, void *arg)
*p++ = IE_CAUSE;
*p++ = 0x2;
*p++ = 0x80;
- *p++ = 0x62 | 0x80; /* status sending */
+ *p++ = 0x62 | 0x80; /* status sending */
*p++ = 0x14; /* CallState */
*p++ = 0x1;
@@ -1094,7 +1219,7 @@ l3dss1_status_req(struct l3_process *pc, u_char pr, void *arg)
if (!(skb = l3_alloc_skb(l)))
return;
memcpy(skb_put(skb, l), tmp, l);
- pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
}
static void
@@ -1107,18 +1232,18 @@ l3dss1_release_ind(struct l3_process *pc, u_char pr, void *arg)
if ((p = findie(p, skb->len, IE_CALL_STATE, 0))) {
p++;
- if (1== *p++)
+ if (1 == *p++)
callState = *p;
}
- if(callState == 0) {
+ if (callState == 0) {
/* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1
* set down layer 3 without sending any message
*/
- pc->st->l3.l3l4(pc, CC_RELEASE_IND, NULL);
+ pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
newl3state(pc, 0);
release_l3_process(pc);
} else {
- pc->st->l3.l3l4(pc, CC_IGNORE, NULL);
+ pc->st->l3.l3l4(pc->st, CC_IGNORE | INDICATION, pc);
}
}
@@ -1131,7 +1256,7 @@ l3dss1_t303(struct l3_process *pc, u_char pr, void *arg)
l3dss1_setup_req(pc, pr, arg);
} else {
L3DelTimer(&pc->timer);
- pc->st->l3.l3l4(pc, CC_NOSETUP_RSP_ERR, NULL);
+ pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc);
release_l3_process(pc);
}
}
@@ -1142,7 +1267,7 @@ l3dss1_t304(struct l3_process *pc, u_char pr, void *arg)
L3DelTimer(&pc->timer);
pc->para.cause = 0xE6;
l3dss1_disconnect_req(pc, pr, NULL);
- pc->st->l3.l3l4(pc, CC_SETUP_ERR, NULL);
+ pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
}
@@ -1171,7 +1296,7 @@ l3dss1_t305(struct l3_process *pc, u_char pr, void *arg)
return;
memcpy(skb_put(skb, l), tmp, l);
newl3state(pc, 19);
- pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
L3AddTimer(&pc->timer, T308, CC_T308_1);
}
@@ -1181,7 +1306,7 @@ l3dss1_t310(struct l3_process *pc, u_char pr, void *arg)
L3DelTimer(&pc->timer);
pc->para.cause = 0xE6;
l3dss1_disconnect_req(pc, pr, NULL);
- pc->st->l3.l3l4(pc, CC_SETUP_ERR, NULL);
+ pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
}
static void
@@ -1190,7 +1315,7 @@ l3dss1_t313(struct l3_process *pc, u_char pr, void *arg)
L3DelTimer(&pc->timer);
pc->para.cause = 0xE6;
l3dss1_disconnect_req(pc, pr, NULL);
- pc->st->l3.l3l4(pc, CC_CONNECT_ERR, NULL);
+ pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
}
static void
@@ -1206,15 +1331,37 @@ static void
l3dss1_t308_2(struct l3_process *pc, u_char pr, void *arg)
{
L3DelTimer(&pc->timer);
- pc->st->l3.l3l4(pc, CC_RELEASE_ERR, NULL);
+ pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
release_l3_process(pc);
}
static void
+l3dss1_t318(struct l3_process *pc, u_char pr, void *arg)
+{
+ L3DelTimer(&pc->timer);
+ pc->para.cause = 0x66; /* Timer expiry */
+ pc->para.loc = 0; /* local */
+ pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
+ newl3state(pc, 19);
+ l3dss1_message(pc, MT_RELEASE);
+ L3AddTimer(&pc->timer, T308, CC_T308_1);
+}
+
+static void
+l3dss1_t319(struct l3_process *pc, u_char pr, void *arg)
+{
+ L3DelTimer(&pc->timer);
+ pc->para.cause = 0x66; /* Timer expiry */
+ pc->para.loc = 0; /* local */
+ pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
+ newl3state(pc, 10);
+}
+
+static void
l3dss1_restart(struct l3_process *pc, u_char pr, void *arg)
{
L3DelTimer(&pc->timer);
- pc->st->l3.l3l4(pc, CC_DLRL, NULL);
+ pc->st->l3.l3l4(pc->st, CC_DLRL | INDICATION, pc);
release_l3_process(pc);
}
@@ -1233,31 +1380,30 @@ l3dss1_status(struct l3_process *pc, u_char pr, void *arg)
if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
p++;
l = *p++;
- t += sprintf(t,"Status CR %x Cause:", pc->callref);
+ t += sprintf(t, "Status CR %x Cause:", pc->callref);
while (l--) {
- cause = *p;
- t += sprintf(t," %2x",*p++);
+ cause = *p;
+ t += sprintf(t, " %2x", *p++);
}
} else
- sprintf(t,"Status CR %x no Cause", pc->callref);
+ sprintf(t, "Status CR %x no Cause", pc->callref);
l3_debug(pc->st, tmp);
p = skb->data;
t = tmp;
- t += sprintf(t,"Status state %x ", pc->state);
+ t += sprintf(t, "Status state %x ", pc->state);
if ((p = findie(p, skb->len, IE_CALL_STATE, 0))) {
p++;
- if (1== *p++) {
- callState = *p;
- t += sprintf(t,"peer state %x" , *p);
- }
- else
- t += sprintf(t,"peer state len error");
+ if (1 == *p++) {
+ callState = *p;
+ t += sprintf(t, "peer state %x", *p);
+ } else
+ t += sprintf(t, "peer state len error");
} else
- sprintf(t,"no peer state");
+ sprintf(t, "no peer state");
l3_debug(pc->st, tmp);
- if(((cause & 0x7f) == 0x6f) && (callState == 0)) {
- /* ETS 300-104 7.6.1, 8.6.1, 10.6.1...
- * if received MT_STATUS with cause == 0x6f and call
+ if (((cause & 0x7f) == 0x6f) && (callState == 0)) {
+ /* ETS 300-104 7.6.1, 8.6.1, 10.6.1...
+ * if received MT_STATUS with cause == 0x6f and call
* state == 0, then we must set down layer 3
*/
l3dss1_release_ind(pc, pr, arg);
@@ -1268,56 +1414,189 @@ l3dss1_status(struct l3_process *pc, u_char pr, void *arg)
static void
l3dss1_facility(struct l3_process *pc, u_char pr, void *arg)
{
- u_char *p;
+ u_char *p;
struct sk_buff *skb = arg;
p = skb->data;
if ((p = findie(p, skb->len, IE_FACILITY, 0))) {
-#ifdef HISAX_DE_AOC
- l3dss1_parse_facility(pc,p);
+#if HISAX_DE_AOC
+ l3dss1_parse_facility(pc, p);
#else
p = NULL;
#endif
}
}
+static void
+l3dss1_suspend_req(struct l3_process *pc, u_char pr, void *arg)
+{
+ struct sk_buff *skb;
+ u_char tmp[32];
+ u_char *p = tmp;
+ u_char i, l;
+ u_char *msg = pc->chan->setup.phone;
+
+ MsgHead(p, pc->callref, MT_SUSPEND);
+
+ *p++ = IE_CALLID;
+ l = *msg++;
+ if (l && (l <= 10)) { /* Max length 10 octets */
+ *p++ = l;
+ for (i = 0; i < l; i++)
+ *p++ = *msg++;
+ } else {
+ l3_debug(pc->st, "SUS wrong CALLID len %d", l);
+ return;
+ }
+ l = p - tmp;
+ if (!(skb = l3_alloc_skb(l)))
+ return;
+ memcpy(skb_put(skb, l), tmp, l);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
+ newl3state(pc, 15);
+ L3AddTimer(&pc->timer, T319, CC_T319);
+}
+
+static void
+l3dss1_suspend_ack(struct l3_process *pc, u_char pr, void *arg)
+{
+ struct sk_buff *skb = arg;
+
+ L3DelTimer(&pc->timer);
+ newl3state(pc, 0);
+ dev_kfree_skb(skb);
+ pc->para.cause = -1;
+ pc->st->l3.l3l4(pc->st, CC_SUSPEND | CONFIRM, pc);
+ release_l3_process(pc);
+}
+
+static void
+l3dss1_suspend_rej(struct l3_process *pc, u_char pr, void *arg)
+{
+ u_char *p;
+ struct sk_buff *skb = arg;
+ int cause = -1;
+
+ L3DelTimer(&pc->timer);
+ p = skb->data;
+ if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
+ p++;
+ if (*p++ == 2)
+ pc->para.loc = *p++;
+ cause = *p & 0x7f;
+ }
+ dev_kfree_skb(skb);
+ pc->para.cause = cause;
+ pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
+ newl3state(pc, 10);
+}
+
+static void
+l3dss1_resume_req(struct l3_process *pc, u_char pr, void *arg)
+{
+ struct sk_buff *skb;
+ u_char tmp[32];
+ u_char *p = tmp;
+ u_char i, l;
+ u_char *msg = pc->para.setup.phone;
+
+ MsgHead(p, pc->callref, MT_RESUME);
+
+ *p++ = IE_CALLID;
+ l = *msg++;
+ if (l && (l <= 10)) { /* Max length 10 octets */
+ *p++ = l;
+ for (i = 0; i < l; i++)
+ *p++ = *msg++;
+ } else {
+ l3_debug(pc->st, "RES wrong CALLID len %d", l);
+ return;
+ }
+ l = p - tmp;
+ if (!(skb = l3_alloc_skb(l)))
+ return;
+ memcpy(skb_put(skb, l), tmp, l);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
+ newl3state(pc, 17);
+ L3AddTimer(&pc->timer, T319, CC_T319);
+}
+
+static void
+l3dss1_resume_ack(struct l3_process *pc, u_char pr, void *arg)
+{
+ u_char *p;
+ struct sk_buff *skb = arg;
+
+ L3DelTimer(&pc->timer);
+ p = skb->data;
+ if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
+ pc->para.bchannel = p[2] & 0x3;
+ if ((!pc->para.bchannel) && (pc->debug & L3_DEB_WARN))
+ l3_debug(pc->st, "resume ack without bchannel");
+ } else if (pc->debug & L3_DEB_WARN)
+ l3_debug(pc->st, "resume ack without bchannel");
+ dev_kfree_skb(skb);
+ pc->st->l3.l3l4(pc->st, CC_RESUME | CONFIRM, pc);
+ newl3state(pc, 10);
+}
+
+static void
+l3dss1_resume_rej(struct l3_process *pc, u_char pr, void *arg)
+{
+ u_char *p;
+ struct sk_buff *skb = arg;
+ int cause = -1;
+
+ L3DelTimer(&pc->timer);
+ p = skb->data;
+ if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
+ p++;
+ if (*p++ == 2)
+ pc->para.loc = *p++;
+ cause = *p & 0x7f;
+ }
+ dev_kfree_skb(skb);
+ pc->para.cause = cause;
+ newl3state(pc, 0);
+ pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
+ release_l3_process(pc);
+}
-
static void
l3dss1_global_restart(struct l3_process *pc, u_char pr, void *arg)
{
u_char tmp[32];
u_char *p;
- u_char ri, chan=0;
+ u_char ri, ch = 0, chan = 0;
int l;
struct sk_buff *skb = arg;
struct l3_process *up;
-
+
newl3state(pc, 2);
L3DelTimer(&pc->timer);
p = skb->data;
if ((p = findie(p, skb->len, IE_RESTART_IND, 0))) {
- ri = p[2];
- sprintf(tmp, "Restart %x", ri);
+ ri = p[2];
+ l3_debug(pc->st, "Restart %x", ri);
} else {
- sprintf(tmp, "Restart without restart IE");
+ l3_debug(pc->st, "Restart without restart IE");
ri = 0x86;
}
- l3_debug(pc->st, tmp);
p = skb->data;
if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
chan = p[2] & 3;
- sprintf(tmp, "Restart for channel %d", chan);
- l3_debug(pc->st, tmp);
+ ch = p[2];
+ if (pc->st->l3.debug)
+ l3_debug(pc->st, "Restart for channel %d", chan);
}
dev_kfree_skb(skb);
newl3state(pc, 2);
up = pc->st->l3.proc;
while (up) {
- if ((ri & 7)==7)
- up->st->lli.l4l3(up->st, CC_RESTART, up);
+ if ((ri & 7) == 7)
+ up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
else if (up->para.bchannel == chan)
- up->st->lli.l4l3(up->st, CC_RESTART, up);
+ up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
up = up->next;
}
p = tmp;
@@ -1325,9 +1604,9 @@ l3dss1_global_restart(struct l3_process *pc, u_char pr, void *arg)
if (chan) {
*p++ = IE_CHANNEL_ID;
*p++ = 1;
- *p++ = chan | 0x80;
+ *p++ = ch | 0x80;
}
- *p++ = 0x79; /* RESTART Ind */
+ *p++ = 0x79; /* RESTART Ind */
*p++ = 1;
*p++ = ri;
l = p - tmp;
@@ -1335,32 +1614,33 @@ l3dss1_global_restart(struct l3_process *pc, u_char pr, void *arg)
return;
memcpy(skb_put(skb, l), tmp, l);
newl3state(pc, 0);
- pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
}
-
/* *INDENT-OFF* */
static struct stateentry downstatelist[] =
{
{SBIT(0),
- CC_ESTABLISH, l3dss1_msg_without_setup},
+ CC_SETUP | REQUEST, l3dss1_setup_req},
{SBIT(0),
- CC_SETUP_REQ, l3dss1_setup_req},
+ CC_RESUME | REQUEST, l3dss1_resume_req},
{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) | SBIT(10),
- CC_DISCONNECT_REQ, l3dss1_disconnect_req},
+ CC_DISCONNECT | REQUEST, l3dss1_disconnect_req},
{SBIT(12),
- CC_RELEASE_REQ, l3dss1_release_req},
+ CC_RELEASE | REQUEST, l3dss1_release_req},
{ALL_STATES,
- CC_DLRL, l3dss1_reset},
+ CC_DLRL | REQUEST, l3dss1_reset},
{ALL_STATES,
- CC_RESTART, l3dss1_restart},
+ CC_RESTART | REQUEST, l3dss1_restart},
{SBIT(6),
- CC_IGNORE, l3dss1_reset},
+ CC_IGNORE | REQUEST, l3dss1_reset},
{SBIT(6),
- CC_REJECT_REQ, l3dss1_reject_req},
+ CC_REJECT | REQUEST, l3dss1_reject_req},
{SBIT(6),
- CC_ALERTING_REQ, l3dss1_alert_req},
+ CC_ALERTING | REQUEST, l3dss1_alert_req},
{SBIT(6) | SBIT(7),
- CC_SETUP_RSP, l3dss1_setup_rsp},
+ CC_SETUP | RESPONSE, l3dss1_setup_rsp},
+ {SBIT(10),
+ CC_SUSPEND | REQUEST, l3dss1_suspend_req},
{SBIT(1),
CC_T303, l3dss1_t303},
{SBIT(2),
@@ -1371,14 +1651,18 @@ static struct stateentry downstatelist[] =
CC_T313, l3dss1_t313},
{SBIT(11),
CC_T305, l3dss1_t305},
+ {SBIT(15),
+ CC_T319, l3dss1_t319},
+ {SBIT(17),
+ CC_T318, l3dss1_t318},
{SBIT(19),
CC_T308_1, l3dss1_t308_1},
{SBIT(19),
CC_T308_2, l3dss1_t308_2},
};
-static int downsllen = sizeof(downstatelist) /
-sizeof(struct stateentry);
+#define DOWNSLLEN \
+ (sizeof(downstatelist) / sizeof(struct stateentry))
static struct stateentry datastatelist[] =
{
@@ -1408,10 +1692,10 @@ static struct stateentry datastatelist[] =
SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19),
MT_RELEASE_COMPLETE, l3dss1_release_cmpl},
{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) |
- SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) /*| SBIT(19)*/,
+ SBIT(11) | SBIT(12) | SBIT(15) /* | SBIT(17) | SBIT(19)*/,
MT_RELEASE, l3dss1_release},
{SBIT(19), MT_RELEASE, l3dss1_release_ind},
- {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10),
+ {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) | SBIT(15),
MT_DISCONNECT, l3dss1_disconnect},
{SBIT(11),
MT_DISCONNECT, l3dss1_release_req},
@@ -1423,61 +1707,57 @@ static struct stateentry datastatelist[] =
MT_CONNECT_ACKNOWLEDGE, l3dss1_status_req},
{SBIT(8),
MT_CONNECT_ACKNOWLEDGE, l3dss1_connect_ack},
- {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19),
+ {SBIT(15),
+ MT_SUSPEND_ACKNOWLEDGE, l3dss1_suspend_ack},
+ {SBIT(15),
+ MT_SUSPEND_REJECT, l3dss1_suspend_rej},
+ {SBIT(17),
+ MT_RESUME_ACKNOWLEDGE, l3dss1_resume_ack},
+ {SBIT(17),
+ MT_RESUME_REJECT, l3dss1_resume_rej},
+ {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(15) | SBIT(17) | SBIT(19),
MT_INVALID, l3dss1_status_req},
};
-static int datasllen = sizeof(datastatelist) / sizeof(struct stateentry);
+#define DATASLLEN \
+ (sizeof(datastatelist) / sizeof(struct stateentry))
static struct stateentry globalmes_list[] =
{
{ALL_STATES,
- MT_STATUS, l3dss1_status},
+ MT_STATUS, l3dss1_status},
{SBIT(0),
MT_RESTART, l3dss1_global_restart},
/* {SBIT(1),
- MT_RESTART_ACKNOWLEDGE, l3dss1_restart_ack},
+ MT_RESTART_ACKNOWLEDGE, l3dss1_restart_ack},
*/
};
-static int globalm_len = sizeof(globalmes_list) / sizeof(struct stateentry);
-
-#if 0
-static struct stateentry globalcmd_list[] =
-{
- {ALL_STATES,
- CC_STATUS, l3dss1_status_req},
- {SBIT(0),
- CC_RESTART, l3dss1_restart_req},
-};
-
-static int globalc_len = sizeof(globalcmd_list) / sizeof(struct stateentry);
-#endif
+#define GLOBALM_LEN \
+ (sizeof(globalmes_list) / sizeof(struct stateentry))
/* *INDENT-ON* */
+
static void
global_handler(struct PStack *st, int mt, struct sk_buff *skb)
{
int i;
- char tmp[64];
struct l3_process *proc = st->l3.global;
-
- for (i = 0; i < globalm_len; i++)
+
+ for (i = 0; i < GLOBALM_LEN; i++)
if ((mt == globalmes_list[i].primitive) &&
((1 << proc->state) & globalmes_list[i].state))
break;
- if (i == globalm_len) {
+ if (i == GLOBALM_LEN) {
dev_kfree_skb(skb);
if (st->l3.debug & L3_DEB_STATE) {
- sprintf(tmp, "dss1 global state %d mt %x unhandled",
+ l3_debug(st, "dss1 global state %d mt %x unhandled",
proc->state, mt);
- l3_debug(st, tmp);
}
return;
} else {
if (st->l3.debug & L3_DEB_STATE) {
- sprintf(tmp, "dss1 global %d mt %x",
+ l3_debug(st, "dss1 global %d mt %x",
proc->state, mt);
- l3_debug(st, tmp);
}
globalmes_list[i].rout(proc, mt, skb);
}
@@ -1490,24 +1770,34 @@ dss1up(struct PStack *st, int pr, void *arg)
char *ptr;
struct sk_buff *skb = arg;
struct l3_process *proc;
- char tmp[80];
+ switch (pr) {
+ case (DL_DATA | INDICATION):
+ case (DL_UNIT_DATA | INDICATION):
+ break;
+ case (DL_ESTABLISH | CONFIRM):
+ case (DL_ESTABLISH | INDICATION):
+ case (DL_RELEASE | INDICATION):
+ case (DL_RELEASE | CONFIRM):
+ l3_msg(st, pr, arg);
+ return;
+ break;
+ }
if (skb->data[0] != PROTO_DIS_EURO) {
if (st->l3.debug & L3_DEB_PROTERR) {
- sprintf(tmp, "dss1up%sunexpected discriminator %x message len %d",
- (pr == DL_DATA) ? " " : "(broadcast) ",
- skb->data[0], skb->len);
- l3_debug(st, tmp);
+ l3_debug(st, "dss1up%sunexpected discriminator %x message len %d",
+ (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
+ skb->data[0], skb->len);
}
dev_kfree_skb(skb);
return;
}
cr = getcallref(skb->data);
mt = skb->data[skb->data[1] + 2];
- if (!cr) { /* Global CallRef */
+ if (!cr) { /* Global CallRef */
global_handler(st, mt, skb);
return;
- } else if (cr == -1) { /* Dummy Callref */
+ } else if (cr == -1) { /* Dummy Callref */
dev_kfree_skb(skb);
return;
} else if (!(proc = getl3proc(st, cr))) {
@@ -1515,7 +1805,7 @@ dss1up(struct PStack *st, int pr, void *arg)
* this callreference is active
*/
if (mt == MT_SETUP) {
- /* Setup creates a new transaction process */
+ /* Setup creates a new transaction process */
if (!(proc = new_l3_process(st, cr))) {
/* May be to answer with RELEASE_COMPLETE and
* CAUSE 0x2f "Resource unavailable", but this
@@ -1526,14 +1816,14 @@ dss1up(struct PStack *st, int pr, void *arg)
}
} else if (mt == MT_STATUS) {
cause = 0;
- if((ptr = findie(skb->data, skb->len, IE_CAUSE, 0)) != NULL) {
- ptr++;
- if (*ptr++ == 2)
- ptr++;
- cause = *ptr & 0x7f;
+ if ((ptr = findie(skb->data, skb->len, IE_CAUSE, 0)) != NULL) {
+ ptr++;
+ if (*ptr++ == 2)
+ ptr++;
+ cause = *ptr & 0x7f;
}
callState = 0;
- if((ptr = findie(skb->data, skb->len, IE_CALL_STATE, 0)) != NULL) {
+ if ((ptr = findie(skb->data, skb->len, IE_CALL_STATE, 0)) != NULL) {
ptr++;
if (*ptr++ == 2)
ptr++;
@@ -1549,29 +1839,29 @@ dss1up(struct PStack *st, int pr, void *arg)
return;
} else {
/* ETS 300-104 part 2.4.2
- * if setup has not been made and a message type
+ * if setup has not been made and a message type
* MT_STATUS is received with call state != 0,
* we must send MT_RELEASE_COMPLETE cause 101
*/
dev_kfree_skb(skb);
if ((proc = new_l3_process(st, cr))) {
- proc->para.cause = 0x65; /* 101 */
- proc->st->l3.l3l4(proc, CC_ESTABLISH, NULL);
+ proc->para.cause = 0x65; /* 101 */
+ l3dss1_msg_without_setup(proc, 0, NULL);
}
return;
}
- } else if (mt == MT_RELEASE_COMPLETE){
+ } else if (mt == MT_RELEASE_COMPLETE) {
dev_kfree_skb(skb);
return;
} else {
/* ETS 300-104 part 2
- * if setup has not been made and a message type
+ * if setup has not been made and a message type
* (except MT_SETUP and RELEASE_COMPLETE) is received,
* we must send MT_RELEASE_COMPLETE cause 81 */
dev_kfree_skb(skb);
if ((proc = new_l3_process(st, cr))) {
- proc->para.cause = 0x51; /* 81 */
- proc->st->l3.l3l4(proc, CC_ESTABLISH, NULL);
+ proc->para.cause = 0x51; /* 81 */
+ l3dss1_msg_without_setup(proc, 0, NULL);
}
return;
}
@@ -1581,28 +1871,25 @@ dss1up(struct PStack *st, int pr, void *arg)
* if setup has been made and invalid message type is received,
* we must send MT_STATUS cause 0x62
*/
- mt = MT_INVALID; /* sorry, not clean, but do the right thing ;-) */
+ mt = MT_INVALID; /* sorry, not clean, but do the right thing ;-) */
}
-
- for (i = 0; i < datasllen; i++)
+ for (i = 0; i < DATASLLEN; i++)
if ((mt == datastatelist[i].primitive) &&
((1 << proc->state) & datastatelist[i].state))
break;
- if (i == datasllen) {
+ if (i == DATASLLEN) {
dev_kfree_skb(skb);
if (st->l3.debug & L3_DEB_STATE) {
- sprintf(tmp, "dss1up%sstate %d mt %x unhandled",
- (pr == DL_DATA) ? " " : "(broadcast) ",
+ l3_debug(st, "dss1up%sstate %d mt %x unhandled",
+ (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
proc->state, mt);
- l3_debug(st, tmp);
}
return;
} else {
if (st->l3.debug & L3_DEB_STATE) {
- sprintf(tmp, "dss1up%sstate %d mt %x",
- (pr == DL_DATA) ? " " : "(broadcast) ",
+ l3_debug(st, "dss1up%sstate %d mt %x",
+ (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
proc->state, mt);
- l3_debug(st, tmp);
}
datastatelist[i].rout(proc, pr, skb);
}
@@ -1614,9 +1901,11 @@ dss1down(struct PStack *st, int pr, void *arg)
int i, cr;
struct l3_process *proc;
struct Channel *chan;
- char tmp[80];
- if (CC_SETUP_REQ == pr) {
+ if (((DL_ESTABLISH | REQUEST) == pr) || ((DL_RELEASE | REQUEST) == pr)) {
+ l3_msg(st, pr, NULL);
+ return;
+ } else if (((CC_SETUP | REQUEST) == pr) || ((CC_RESUME | REQUEST) == pr)) {
chan = arg;
cr = newcallref();
cr |= 0x80;
@@ -1630,24 +1919,22 @@ dss1down(struct PStack *st, int pr, void *arg)
proc = arg;
}
if (!proc) {
- printk(KERN_ERR "HiSax internal error dss1down without proc\n");
+ printk(KERN_ERR "HiSax dss1down without proc pr=%04x\n", pr);
return;
}
- for (i = 0; i < downsllen; i++)
+ for (i = 0; i < DOWNSLLEN; i++)
if ((pr == downstatelist[i].primitive) &&
((1 << proc->state) & downstatelist[i].state))
break;
- if (i == downsllen) {
+ if (i == DOWNSLLEN) {
if (st->l3.debug & L3_DEB_STATE) {
- sprintf(tmp, "dss1down state %d prim %d unhandled",
+ l3_debug(st, "dss1down state %d prim %d unhandled",
proc->state, pr);
- l3_debug(st, tmp);
}
} else {
if (st->l3.debug & L3_DEB_STATE) {
- sprintf(tmp, "dss1down state %d prim %d",
+ l3_debug(st, "dss1down state %d prim %d",
proc->state, pr);
- l3_debug(st, tmp);
}
downstatelist[i].rout(proc, pr, arg);
}
diff --git a/drivers/isdn/hisax/l3dss1.h b/drivers/isdn/hisax/l3dss1.h
index 8508c3109..10e612482 100644
--- a/drivers/isdn/hisax/l3dss1.h
+++ b/drivers/isdn/hisax/l3dss1.h
@@ -1,8 +1,12 @@
-/* $Id: l3dss1.h,v 1.5 1998/02/02 13:34:30 keil Exp $
+/* $Id: l3dss1.h,v 1.6 1998/03/19 13:18:50 keil Exp $
*
* DSS1 (Euro) D-channel protocol defines
*
* $Log: l3dss1.h,v $
+ * Revision 1.6 1998/03/19 13:18:50 keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
* Revision 1.5 1998/02/02 13:34:30 keil
* Support australian Microlink net and german AOCD
*
@@ -63,8 +67,9 @@
#define MT_INVALID 0xff
-#define IE_CAUSE 0x08
#define IE_BEARER 0x04
+#define IE_CAUSE 0x08
+#define IE_CALLID 0x10
#define IE_FACILITY 0x1c
#define IE_CALL_STATE 0x14
#define IE_CHANNEL_ID 0x18
diff --git a/drivers/isdn/hisax/lmgr.c b/drivers/isdn/hisax/lmgr.c
index b3e9819b2..d6ef0b630 100644
--- a/drivers/isdn/hisax/lmgr.c
+++ b/drivers/isdn/hisax/lmgr.c
@@ -1,11 +1,21 @@
-/* $Id: lmgr.c,v 1.2 1997/10/29 19:09:34 keil Exp $
+/* $Id: lmgr.c,v 1.5 1998/11/15 23:55:12 keil Exp $
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
*
*
* Layermanagement module
*
* $Log: lmgr.c,v $
+ * Revision 1.5 1998/11/15 23:55:12 keil
+ * changes from 2.0
+ *
+ * Revision 1.4 1998/05/25 12:58:19 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.3 1998/03/07 22:57:06 tsbogend
+ * made HiSax working on Linux/Alpha
+ *
* Revision 1.2 1997/10/29 19:09:34 keil
* new L1
*
@@ -26,7 +36,7 @@ error_handling_dchan(struct PStack *st, int Error)
case 'D':
case 'G':
case 'H':
- st->l2.l2tei(st, MDL_ERROR_REQ, NULL);
+ st->l2.l2tei(st, MDL_ERROR | REQUEST, NULL);
break;
}
}
@@ -34,17 +44,15 @@ error_handling_dchan(struct PStack *st, int Error)
static void
hisax_manager(struct PStack *st, int pr, void *arg)
{
- char tm[32], str[256];
- int Code;
+ long Code;
switch (pr) {
- case MDL_ERROR_IND:
- Code = (int) arg;
- jiftime(tm, jiffies);
- sprintf(str, "%s manager: MDL_ERROR %c %s\n", tm,
- Code, test_bit(FLG_LAPD, &st->l2.flag) ?
+ case (MDL_ERROR | INDICATION):
+ Code = (long) arg;
+ HiSax_putstatus(st->l1.hardware, "manager: MDL_ERROR",
+ "%c %s\n", (char)Code,
+ test_bit(FLG_LAPD, &st->l2.flag) ?
"D-channel" : "B-channel");
- HiSax_putstatus(st->l1.hardware, str);
if (test_bit(FLG_LAPD, &st->l2.flag))
error_handling_dchan(st, Code);
break;
diff --git a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c
index 8bf4757c9..ccd103fed 100644
--- a/drivers/isdn/hisax/mic.c
+++ b/drivers/isdn/hisax/mic.c
@@ -1,4 +1,4 @@
-/* $Id: mic.c,v 1.6 1998/02/17 15:39:57 keil Exp $
+/* $Id: mic.c,v 1.7 1998/04/15 16:44:32 keil Exp $
* mic.c low level stuff for mic cards
*
@@ -8,6 +8,9 @@
*
*
* $Log: mic.c,v $
+ * Revision 1.7 1998/04/15 16:44:32 keil
+ * new init code
+ *
* Revision 1.6 1998/02/17 15:39:57 keil
* fix reset problem
*
@@ -37,7 +40,7 @@
extern const char *CardType[];
-const char *mic_revision = "$Revision: 1.6 $";
+const char *mic_revision = "$Revision: 1.7 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -220,10 +223,7 @@ mic_card_msg(struct IsdnCardState *cs, int mt, void *arg)
I4L_IRQ_FLAG, "HiSax", cs));
case CARD_INIT:
inithscx(cs); /* /RTSA := ISAC RST */
- clear_pending_isac_ints(cs);
- clear_pending_hscx_ints(cs);
- initisac(cs);
- inithscx(cs);
+ inithscxisac(cs, 3);
return(0);
case CARD_TEST:
return(0);
diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c
index 54f9c14d8..746451ba0 100644
--- a/drivers/isdn/hisax/netjet.c
+++ b/drivers/isdn/hisax/netjet.c
@@ -1,13 +1,30 @@
-/* $Id: netjet.c,v 1.3 1998/02/12 23:08:05 keil Exp $
+/* $Id: netjet.c,v 1.8 1998/11/15 23:55:14 keil Exp $
* netjet.c low level stuff for Traverse Technologie NETJet ISDN cards
*
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
*
* Thanks to Traverse Technologie Australia for documents and informations
*
*
* $Log: netjet.c,v $
+ * Revision 1.8 1998/11/15 23:55:14 keil
+ * changes from 2.0
+ *
+ * Revision 1.7 1998/09/30 22:24:48 keil
+ * Fix missing line in setstack*
+ *
+ * Revision 1.6 1998/08/13 23:36:54 keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 1.5 1998/05/25 12:58:21 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.4 1998/04/15 16:42:35 keil
+ * new init code
+ * new PCI init (2.1.94)
+ *
* Revision 1.3 1998/02/12 23:08:05 keil
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
@@ -25,15 +42,12 @@
#include "hscx.h"
#include "isdnl1.h"
#include <linux/pci.h>
-#include <linux/bios32.h>
#include <linux/interrupt.h>
-#define fcstab ppp_crc16_table
#include <linux/ppp_defs.h>
-extern __u16 ppp_crc16_table[256]; /* from ppp code */
extern const char *CardType[];
-const char *NETjet_revision = "$Revision: 1.3 $";
+const char *NETjet_revision = "$Revision: 1.8 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -62,6 +76,12 @@ const char *NETjet_revision = "$Revision: 1.3 $";
#define NETJET_ISAC_OFF 0xc0
#define NETJET_ISACIRQ 0x10
+#define NETJET_IRQM0_READ 0x0c
+#define NETJET_IRQM0_READ_1 0x04
+#define NETJET_IRQM0_READ_2 0x08
+#define NETJET_IRQM0_WRITE 0x03
+#define NETJET_IRQM0_WRITE_1 0x01
+#define NETJET_IRQM0_WRITE_2 0x02
#define NETJET_DMA_SIZE 512
@@ -115,6 +135,42 @@ ReadISACfifo(struct IsdnCardState *cs, u_char *data, int size)
insb(cs->hw.njet.isac, data, size);
}
+__u16 fcstab[256] =
+{
+ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+ 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+ 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+ 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
+ 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
+ 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
+ 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
+ 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
+ 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
+ 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
+ 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
+ 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
+ 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
+ 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
+ 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
+ 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
+ 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
+ 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
+ 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
+ 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
+ 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
+ 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
+ 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
+ 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
+ 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
+ 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
+ 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
+ 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
+ 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
+ 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
+ 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
+ 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
+};
+
static void
WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size)
{
@@ -146,25 +202,20 @@ void
mode_tiger(struct BCState *bcs, int mode, int bc)
{
struct IsdnCardState *cs = bcs->cs;
- char tmp[64];
- if (cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "Tiger mode %d bchan %d/%d",
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "Tiger mode %d bchan %d/%d",
mode, bc, bcs->channel);
- debugl1(cs, tmp);
- }
bcs->mode = mode;
bcs->channel = bc;
switch (mode) {
case (L1_MODE_NULL):
fill_mem(bcs, bcs->hw.tiger.send,
NETJET_DMA_SIZE, bc, 0xff);
- if (cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "Tiger stat rec %d/%d send %d",
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "Tiger stat rec %d/%d send %d",
bcs->hw.tiger.r_tot, bcs->hw.tiger.r_err,
bcs->hw.tiger.s_tot);
- debugl1(cs, tmp);
- }
if ((cs->bcs[0].mode == L1_MODE_NULL) &&
(cs->bcs[1].mode == L1_MODE_NULL)) {
cs->hw.njet.dmactrl = 0;
@@ -197,16 +248,14 @@ mode_tiger(struct BCState *bcs, int mode, int bc)
test_and_set_bit(BC_FLG_EMPTY, &bcs->Flag);
break;
}
- if (cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "tiger: set %x %x %x %x/%x pulse=%d",
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "tiger: set %x %x %x %x/%x pulse=%d",
bytein(cs->hw.njet.base + NETJET_DMACTRL),
bytein(cs->hw.njet.base + NETJET_IRQMASK0),
bytein(cs->hw.njet.base + NETJET_IRQSTAT0),
inl(cs->hw.njet.base + NETJET_DMA_READ_ADR),
inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR),
bytein(cs->hw.njet.base + NETJET_PULSE_CNT));
- debugl1(cs, tmp);
- }
}
static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
@@ -266,7 +315,7 @@ static void printframe(struct IsdnCardState *cs, u_char *buf, int count, char *s
val >>= 1;\
}
-static void make_raw_data(struct BCState *bcs) {
+static int make_raw_data(struct BCState *bcs) {
register u_int i,s_cnt=0;
register u_char j;
register u_char val;
@@ -274,13 +323,15 @@ static void make_raw_data(struct BCState *bcs) {
register u_char s_val = 0;
register u_char bitcnt = 0;
u_int fcs;
- char tmp[64];
-
+ if (!bcs->tx_skb) {
+ debugl1(bcs->cs, "tiger make_raw: NULL skb");
+ return(1);
+ }
bcs->hw.tiger.sendbuf[s_cnt++] = HDLC_FLAG_VALUE;
fcs = PPP_INITFCS;
- for (i=0; i<bcs->hw.tiger.tx_skb->len; i++) {
- val = bcs->hw.tiger.tx_skb->data[i];
+ for (i=0; i<bcs->tx_skb->len; i++) {
+ val = bcs->tx_skb->data[i];
fcs = PPP_FCS (fcs, val);
MAKE_RAW_BYTE;
}
@@ -303,11 +354,9 @@ static void make_raw_data(struct BCState *bcs) {
}
val >>= 1;
}
- if (bcs->cs->debug & L1_DEB_HSCX) {
- sprintf(tmp,"tiger make_raw: in %d out %d.%d",
- bcs->hw.tiger.tx_skb->len, s_cnt, bitcnt);
- debugl1(bcs->cs,tmp);
- }
+ if (bcs->cs->debug & L1_DEB_HSCX)
+ debugl1(bcs->cs,"tiger make_raw: in %ld out %d.%d",
+ bcs->tx_skb->len, s_cnt, bitcnt);
if (bitcnt) {
while (8>bitcnt++) {
s_val >>= 1;
@@ -316,8 +365,9 @@ static void make_raw_data(struct BCState *bcs) {
bcs->hw.tiger.sendbuf[s_cnt++] = s_val;
}
bcs->hw.tiger.sendcnt = s_cnt;
- bcs->tx_cnt -= bcs->hw.tiger.tx_skb->len;
+ bcs->tx_cnt -= bcs->tx_skb->len;
bcs->hw.tiger.sp = bcs->hw.tiger.sendbuf;
+ return(0);
}
static void got_frame(struct BCState *bcs, int count) {
@@ -349,7 +399,6 @@ static void read_raw(struct BCState *bcs, u_int *buf, int cnt){
register u_char r_val = bcs->hw.tiger.r_val;
register u_int bitcnt = bcs->hw.tiger.r_bitcnt;
u_int *p = buf;
- char tmp[64];
for (i=0;i<cnt;i++) {
val = bcs->channel ? ((*p>>8) & 0xff) : (*p & 0xff);
@@ -370,11 +419,9 @@ static void read_raw(struct BCState *bcs, u_int *buf, int cnt){
} else {
r_one=0;
state= HDLC_FLAG_SEARCH;
- if (bcs->cs->debug & L1_DEB_HSCX) {
- sprintf(tmp,"tiger read_raw: zBit(%d,%d,%d) %x",
+ if (bcs->cs->debug & L1_DEB_HSCX)
+ debugl1(bcs->cs,"tiger read_raw: zBit(%d,%d,%d) %x",
bcs->hw.tiger.r_tot,i,j,val);
- debugl1(bcs->cs,tmp);
- }
}
} else if (state == HDLC_FLAG_SEARCH) {
if (val & 1) {
@@ -387,11 +434,9 @@ static void read_raw(struct BCState *bcs, u_int *buf, int cnt){
bitcnt=0;
r_val=0;
state=HDLC_FLAG_FOUND;
- if (bcs->cs->debug & L1_DEB_HSCX) {
- sprintf(tmp,"tiger read_raw: flag(%d,%d,%d) %x",
+ if (bcs->cs->debug & L1_DEB_HSCX)
+ debugl1(bcs->cs,"tiger read_raw: flag(%d,%d,%d) %x",
bcs->hw.tiger.r_tot,i,j,val);
- debugl1(bcs->cs,tmp);
- }
}
r_one=0;
}
@@ -425,12 +470,10 @@ static void read_raw(struct BCState *bcs, u_int *buf, int cnt){
bcs->hw.tiger.r_fcs = PPP_INITFCS;
bcs->hw.tiger.rcvbuf[0] = r_val;
bcs->hw.tiger.r_fcs = PPP_FCS (bcs->hw.tiger.r_fcs, r_val);
- if (bcs->cs->debug & L1_DEB_HSCX) {
- sprintf(tmp,"tiger read_raw: byte1(%d,%d,%d) rval %x val %x i %x",
+ if (bcs->cs->debug & L1_DEB_HSCX)
+ debugl1(bcs->cs,"tiger read_raw: byte1(%d,%d,%d) rval %x val %x i %x",
bcs->hw.tiger.r_tot,i,j,r_val,val,
bcs->cs->hw.njet.irqstat0);
- debugl1(bcs->cs,tmp);
- }
}
} else if (state == HDLC_FRAME_FOUND) {
if (val & 1) {
@@ -453,11 +496,9 @@ static void read_raw(struct BCState *bcs, u_int *buf, int cnt){
state=HDLC_FLAG_SEARCH;
bcs->hw.tiger.r_err++;
} else {
- if (bcs->cs->debug & L1_DEB_HSCX) {
- sprintf(tmp,"tiger frame end(%d,%d): fcs(%x) i %x",
+ if (bcs->cs->debug & L1_DEB_HSCX)
+ debugl1(bcs->cs,"tiger frame end(%d,%d): fcs(%x) i %x",
i,j,bcs->hw.tiger.r_fcs, bcs->cs->hw.njet.irqstat0);
- debugl1(bcs->cs, tmp);
- }
if (bcs->hw.tiger.r_fcs == PPP_GOODFCS) {
got_frame(bcs, (bitcnt>>3)-3);
} else
@@ -509,7 +550,15 @@ static void read_tiger(struct IsdnCardState *cs) {
u_int *p;
int cnt = NETJET_DMA_SIZE/2;
- if (cs->hw.njet.irqstat0 & 4)
+ if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_READ) {
+ debugl1(cs,"tiger warn read double dma %x/%x",
+ cs->hw.njet.irqstat0, cs->hw.njet.last_is0);
+ return;
+ } else {
+ cs->hw.njet.last_is0 &= ~NETJET_IRQM0_READ;
+ cs->hw.njet.last_is0 |= (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ);
+ }
+ if (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ_1)
p = cs->bcs[0].hw.tiger.rec + NETJET_DMA_SIZE - 1;
else
p = cs->bcs[0].hw.tiger.rec + cnt - 1;
@@ -517,32 +566,28 @@ static void read_tiger(struct IsdnCardState *cs) {
read_raw(cs->bcs, p, cnt);
if (cs->bcs[1].mode == L1_MODE_HDLC)
read_raw(cs->bcs + 1, p, cnt);
- cs->hw.njet.irqstat0 &= 0xf3;
+ cs->hw.njet.irqstat0 &= ~NETJET_IRQM0_READ;
}
static void write_raw(struct BCState *bcs, u_int *buf, int cnt);
static void fill_dma(struct BCState *bcs)
{
- char tmp[64];
register u_int *p, *sp;
register int cnt;
- if (!bcs->hw.tiger.tx_skb)
+ if (!bcs->tx_skb)
return;
- if (bcs->cs->debug & L1_DEB_HSCX) {
- sprintf(tmp,"tiger fill_dma1: c%d %4x", bcs->channel,
+ if (bcs->cs->debug & L1_DEB_HSCX)
+ debugl1(bcs->cs,"tiger fill_dma1: c%d %4x", bcs->channel,
bcs->Flag);
- debugl1(bcs->cs,tmp);
- }
if (test_and_set_bit(BC_FLG_BUSY, &bcs->Flag))
return;
- make_raw_data(bcs);
- if (bcs->cs->debug & L1_DEB_HSCX) {
- sprintf(tmp,"tiger fill_dma2: c%d %4x", bcs->channel,
+ if (make_raw_data(bcs))
+ return;
+ if (bcs->cs->debug & L1_DEB_HSCX)
+ debugl1(bcs->cs,"tiger fill_dma2: c%d %4x", bcs->channel,
bcs->Flag);
- debugl1(bcs->cs,tmp);
- }
if (test_and_clear_bit(BC_FLG_NOFRAME, &bcs->Flag)) {
write_raw(bcs, bcs->hw.tiger.sendp, bcs->hw.tiger.free);
} else if (test_and_clear_bit(BC_FLG_HALF, &bcs->Flag)) {
@@ -582,17 +627,14 @@ static void fill_dma(struct BCState *bcs)
}
write_raw(bcs, p, cnt);
}
- if (bcs->cs->debug & L1_DEB_HSCX) {
- sprintf(tmp,"tiger fill_dma3: c%d %4x", bcs->channel,
+ if (bcs->cs->debug & L1_DEB_HSCX)
+ debugl1(bcs->cs,"tiger fill_dma3: c%d %4x", bcs->channel,
bcs->Flag);
- debugl1(bcs->cs,tmp);
- }
}
static void write_raw(struct BCState *bcs, u_int *buf, int cnt) {
u_int mask, val, *p=buf;
u_int i, s_cnt;
- char tmp[64];
if (cnt <= 0)
return;
@@ -617,26 +659,23 @@ static void write_raw(struct BCState *bcs, u_int *buf, int cnt) {
p = bcs->hw.tiger.send;
}
bcs->hw.tiger.s_tot += s_cnt;
- if (bcs->cs->debug & L1_DEB_HSCX) {
- sprintf(tmp,"tiger write_raw: c%d %x-%x %d/%d %d %x", bcs->channel,
- (u_int)buf, (u_int)p, s_cnt, cnt, bcs->hw.tiger.sendcnt,
- bcs->cs->hw.njet.irqstat0);
- debugl1(bcs->cs,tmp);
- }
+ if (bcs->cs->debug & L1_DEB_HSCX)
+ debugl1(bcs->cs,"tiger write_raw: c%d %x-%x %d/%d %d %x", bcs->channel,
+ (u_int)buf, (u_int)p, s_cnt, cnt,
+ bcs->hw.tiger.sendcnt, bcs->cs->hw.njet.irqstat0);
if (bcs->cs->debug & L1_DEB_HSCX_FIFO)
printframe(bcs->cs, bcs->hw.tiger.sp, s_cnt, "snd");
bcs->hw.tiger.sp += s_cnt;
bcs->hw.tiger.sendp = p;
if (!bcs->hw.tiger.sendcnt) {
- if (!bcs->hw.tiger.tx_skb) {
- sprintf(tmp,"tiger write_raw: NULL skb s_cnt %d", s_cnt);
- debugl1(bcs->cs, tmp);
+ if (!bcs->tx_skb) {
+ debugl1(bcs->cs,"tiger write_raw: NULL skb s_cnt %d", s_cnt);
} else {
if (bcs->st->lli.l1writewakeup &&
- (PACKET_NOACK != bcs->hw.tiger.tx_skb->pkt_type))
- bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.tiger.tx_skb->len);
- dev_kfree_skb(bcs->hw.tiger.tx_skb);
- bcs->hw.tiger.tx_skb = NULL;
+ (PACKET_NOACK != bcs->tx_skb->pkt_type))
+ bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
+ dev_kfree_skb(bcs->tx_skb);
+ bcs->tx_skb = NULL;
}
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->hw.tiger.free = cnt - s_cnt;
@@ -646,7 +685,7 @@ static void write_raw(struct BCState *bcs, u_int *buf, int cnt) {
test_and_clear_bit(BC_FLG_HALF, &bcs->Flag);
test_and_set_bit(BC_FLG_NOFRAME, &bcs->Flag);
}
- if ((bcs->hw.tiger.tx_skb = skb_dequeue(&bcs->squeue))) {
+ if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
fill_dma(bcs);
} else {
mask ^= 0xffffffff;
@@ -656,11 +695,9 @@ static void write_raw(struct BCState *bcs, u_int *buf, int cnt) {
if (p>bcs->hw.tiger.s_end)
p = bcs->hw.tiger.send;
}
- if (bcs->cs->debug & L1_DEB_HSCX) {
- sprintf(tmp, "tiger write_raw: fill rest %d",
+ if (bcs->cs->debug & L1_DEB_HSCX)
+ debugl1(bcs->cs, "tiger write_raw: fill rest %d",
cnt - s_cnt);
- debugl1(bcs->cs,tmp);
- }
}
bcs->event |= 1 << B_XMTBUFREADY;
queue_task(&bcs->tqueue, &tq_immediate);
@@ -671,24 +708,28 @@ static void write_raw(struct BCState *bcs, u_int *buf, int cnt) {
test_and_set_bit(BC_FLG_HALF, &bcs->Flag);
fill_mem(bcs, buf, cnt, bcs->channel, 0xff);
bcs->hw.tiger.free += cnt;
- if (bcs->cs->debug & L1_DEB_HSCX) {
- sprintf(tmp,"tiger write_raw: fill half");
- debugl1(bcs->cs,tmp);
- }
+ if (bcs->cs->debug & L1_DEB_HSCX)
+ debugl1(bcs->cs,"tiger write_raw: fill half");
} else if (test_and_clear_bit(BC_FLG_HALF, &bcs->Flag)) {
test_and_set_bit(BC_FLG_EMPTY, &bcs->Flag);
fill_mem(bcs, buf, cnt, bcs->channel, 0xff);
- if (bcs->cs->debug & L1_DEB_HSCX) {
- sprintf(tmp,"tiger write_raw: fill full");
- debugl1(bcs->cs,tmp);
- }
+ if (bcs->cs->debug & L1_DEB_HSCX)
+ debugl1(bcs->cs,"tiger write_raw: fill full");
}
}
static void write_tiger(struct IsdnCardState *cs) {
u_int *p, cnt = NETJET_DMA_SIZE/2;
- if (cs->hw.njet.irqstat0 & 1)
+ if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_WRITE) {
+ debugl1(cs,"tiger warn write double dma %x/%x",
+ cs->hw.njet.irqstat0, cs->hw.njet.last_is0);
+ return;
+ } else {
+ cs->hw.njet.last_is0 &= ~NETJET_IRQM0_WRITE;
+ cs->hw.njet.last_is0 |= (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE);
+ }
+ if (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE_1)
p = cs->bcs[0].hw.tiger.send + NETJET_DMA_SIZE - 1;
else
p = cs->bcs[0].hw.tiger.send + cnt - 1;
@@ -696,7 +737,7 @@ static void write_tiger(struct IsdnCardState *cs) {
write_raw(cs->bcs, p, cnt);
if (cs->bcs[1].mode == L1_MODE_HDLC)
write_raw(cs->bcs + 1, p, cnt);
- cs->hw.njet.irqstat0 &= 0xfc;
+ cs->hw.njet.irqstat0 &= ~NETJET_IRQM0_WRITE;
}
static void
@@ -706,45 +747,58 @@ tiger_l2l1(struct PStack *st, int pr, void *arg)
long flags;
switch (pr) {
- case (PH_DATA_REQ):
+ case (PH_DATA | REQUEST):
save_flags(flags);
cli();
- if (st->l1.bcs->hw.tiger.tx_skb) {
+ if (st->l1.bcs->tx_skb) {
skb_queue_tail(&st->l1.bcs->squeue, skb);
restore_flags(flags);
} else {
- st->l1.bcs->hw.tiger.tx_skb = skb;
+ st->l1.bcs->tx_skb = skb;
st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
restore_flags(flags);
}
break;
- case (PH_PULL_IND):
- if (st->l1.bcs->hw.tiger.tx_skb) {
+ case (PH_PULL | INDICATION):
+ if (st->l1.bcs->tx_skb) {
printk(KERN_WARNING "tiger_l2l1: this shouldn't happen\n");
break;
}
save_flags(flags);
cli();
- st->l1.bcs->hw.tiger.tx_skb = skb;
+ st->l1.bcs->tx_skb = skb;
st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
restore_flags(flags);
break;
- case (PH_PULL_REQ):
- if (!st->l1.bcs->hw.tiger.tx_skb) {
+ case (PH_PULL | REQUEST):
+ if (!st->l1.bcs->tx_skb) {
test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
- st->l1.l1l2(st, PH_PULL_CNF, NULL);
+ st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
} else
test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
break;
+ case (PH_ACTIVATE | REQUEST):
+ test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+ mode_tiger(st->l1.bcs, st->l1.mode, st->l1.bc);
+ l1_msg_b(st, pr, arg);
+ break;
+ case (PH_DEACTIVATE | REQUEST):
+ l1_msg_b(st, pr, arg);
+ break;
+ case (PH_DEACTIVATE | CONFIRM):
+ test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+ test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ mode_tiger(st->l1.bcs, 0, st->l1.bc);
+ st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+ break;
}
}
+
void
close_tigerstate(struct BCState *bcs)
{
- struct sk_buff *skb;
-
- mode_tiger(bcs, 0, 0);
+ mode_tiger(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
if (bcs->hw.tiger.rcvbuf) {
kfree(bcs->hw.tiger.rcvbuf);
@@ -754,32 +808,26 @@ close_tigerstate(struct BCState *bcs)
kfree(bcs->hw.tiger.sendbuf);
bcs->hw.tiger.sendbuf = NULL;
}
- while ((skb = skb_dequeue(&bcs->rqueue))) {
- dev_kfree_skb(skb);
- }
- while ((skb = skb_dequeue(&bcs->squeue))) {
- dev_kfree_skb(skb);
- }
- if (bcs->hw.tiger.tx_skb) {
- dev_kfree_skb(bcs->hw.tiger.tx_skb);
- bcs->hw.tiger.tx_skb = NULL;
+ discard_queue(&bcs->rqueue);
+ discard_queue(&bcs->squeue);
+ if (bcs->tx_skb) {
+ dev_kfree_skb(bcs->tx_skb);
+ bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
}
}
}
static int
-open_tigerstate(struct IsdnCardState *cs, int bc)
+open_tigerstate(struct IsdnCardState *cs, struct BCState *bcs)
{
- struct BCState *bcs = cs->bcs + bc;
-
if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
- if (!(bcs->hw.tiger.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_KERNEL))) {
+ if (!(bcs->hw.tiger.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for tiger.rcvbuf\n");
return (1);
}
- if (!(bcs->hw.tiger.sendbuf = kmalloc(RAW_BUFMAX, GFP_KERNEL))) {
+ if (!(bcs->hw.tiger.sendbuf = kmalloc(RAW_BUFMAX, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for tiger.sendbuf\n");
return (1);
@@ -787,7 +835,7 @@ open_tigerstate(struct IsdnCardState *cs, int bc)
skb_queue_head_init(&bcs->rqueue);
skb_queue_head_init(&bcs->squeue);
}
- bcs->hw.tiger.tx_skb = NULL;
+ bcs->tx_skb = NULL;
bcs->hw.tiger.sendcnt = 0;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->event = 0;
@@ -795,34 +843,17 @@ open_tigerstate(struct IsdnCardState *cs, int bc)
return (0);
}
-static void
-tiger_manl1(struct PStack *st, int pr,
- void *arg)
-{
- switch (pr) {
- case (PH_ACTIVATE_REQ):
- test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
- mode_tiger(st->l1.bcs, st->l1.mode, st->l1.bc);
- st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
- break;
- case (PH_DEACTIVATE_REQ):
- if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
- mode_tiger(st->l1.bcs, 0, 0);
- test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
- break;
- }
-}
-
int
setstack_tiger(struct PStack *st, struct BCState *bcs)
{
- if (open_tigerstate(st->l1.hardware, bcs->channel))
+ bcs->channel = st->l1.bc;
+ if (open_tigerstate(st->l1.hardware, bcs))
return (-1);
st->l1.bcs = bcs;
st->l2.l2l1 = tiger_l2l1;
- st->ma.manl1 = tiger_manl1;
setstack_manager(st);
bcs->st = st;
+ setstack_l1_B(st);
return (0);
}
@@ -830,8 +861,6 @@ setstack_tiger(struct PStack *st, struct BCState *bcs)
__initfunc(void
inittiger(struct IsdnCardState *cs))
{
- char tmp[128];
-
if (!(cs->bcs[0].hw.tiger.send = kmalloc(NETJET_DMA_SIZE * sizeof(unsigned int),
GFP_KERNEL | GFP_DMA))) {
printk(KERN_WARNING
@@ -845,9 +874,8 @@ inittiger(struct IsdnCardState *cs))
cs->bcs[1].hw.tiger.s_end = cs->bcs[0].hw.tiger.s_end;
memset(cs->bcs[0].hw.tiger.send, 0xff, NETJET_DMA_SIZE * sizeof(unsigned int));
- sprintf(tmp, "tiger: send buf %x - %x", (u_int)cs->bcs[0].hw.tiger.send,
+ debugl1(cs, "tiger: send buf %x - %x", (u_int)cs->bcs[0].hw.tiger.send,
(u_int)(cs->bcs[0].hw.tiger.send + NETJET_DMA_SIZE - 1));
- debugl1(cs, tmp);
outl(virt_to_bus(cs->bcs[0].hw.tiger.send),
cs->hw.njet.base + NETJET_DMA_READ_START);
outl(virt_to_bus(cs->bcs[0].hw.tiger.s_irq),
@@ -860,9 +888,8 @@ inittiger(struct IsdnCardState *cs))
"HiSax: No memory for tiger.rec\n");
return;
}
- sprintf(tmp, "tiger: rec buf %x - %x", (u_int)cs->bcs[0].hw.tiger.rec,
+ debugl1(cs, "tiger: rec buf %x - %x", (u_int)cs->bcs[0].hw.tiger.rec,
(u_int)(cs->bcs[0].hw.tiger.rec + NETJET_DMA_SIZE - 1));
- debugl1(cs, tmp);
cs->bcs[1].hw.tiger.rec = cs->bcs[0].hw.tiger.rec;
memset(cs->bcs[0].hw.tiger.rec, 0xff, NETJET_DMA_SIZE * sizeof(unsigned int));
outl(virt_to_bus(cs->bcs[0].hw.tiger.rec),
@@ -871,11 +898,10 @@ inittiger(struct IsdnCardState *cs))
cs->hw.njet.base + NETJET_DMA_WRITE_IRQ);
outl(virt_to_bus(cs->bcs[0].hw.tiger.rec + NETJET_DMA_SIZE - 1),
cs->hw.njet.base + NETJET_DMA_WRITE_END);
- sprintf(tmp, "tiger: dmacfg %x/%x pulse=%d",
+ debugl1(cs, "tiger: dmacfg %x/%x pulse=%d",
inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR),
inl(cs->hw.njet.base + NETJET_DMA_READ_ADR),
bytein(cs->hw.njet.base + NETJET_PULSE_CNT));
- debugl1(cs, tmp);
cs->hw.njet.last_is0 = 0;
cs->bcs[0].BC_SetStack = setstack_tiger;
cs->bcs[1].BC_SetStack = setstack_tiger;
@@ -906,8 +932,8 @@ static void
netjet_interrupt(int intno, void *dev_id, struct pt_regs *regs)
{
struct IsdnCardState *cs = dev_id;
- u_char val, sval, stat = 1;
- char tmp[128];
+ u_char val, sval;
+ long flags;
if (!cs) {
printk(KERN_WARNING "NETjet: Spurious interrupt!\n");
@@ -916,49 +942,49 @@ netjet_interrupt(int intno, void *dev_id, struct pt_regs *regs)
if (!((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT1)) &
NETJET_ISACIRQ)) {
val = ReadISAC(cs, ISAC_ISTA);
- if (cs->debug & L1_DEB_ISAC) {
- sprintf(tmp, "tiger: i1 %x %x", sval, val);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "tiger: i1 %x %x", sval, val);
if (val) {
isac_interrupt(cs, val);
- stat |= 2;
+ WriteISAC(cs, ISAC_MASK, 0xFF);
+ WriteISAC(cs, ISAC_MASK, 0x0);
}
}
- if ((cs->hw.njet.irqstat0 = bytein(cs->hw.njet.base + NETJET_IRQSTAT0))) {
-/* sprintf(tmp, "tiger: ist0 %x %x %x %x/%x pulse=%d",
+ save_flags(flags);
+ cli();
+ if ((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT0))) {
+ if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+ restore_flags(flags);
+ return;
+ }
+ cs->hw.njet.irqstat0 = sval;
+ restore_flags(flags);
+/* debugl1(cs, "tiger: ist0 %x %x %x %x/%x pulse=%d",
sval,
bytein(cs->hw.njet.base + NETJET_DMACTRL),
bytein(cs->hw.njet.base + NETJET_IRQMASK0),
inl(cs->hw.njet.base + NETJET_DMA_READ_ADR),
inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR),
bytein(cs->hw.njet.base + NETJET_PULSE_CNT));
- debugl1(cs, tmp);
*/
- if (cs->hw.njet.last_is0 & cs->hw.njet.irqstat0 & 0xf) {
- sprintf(tmp, "tiger: ist0 %x->%x irq lost",
- cs->hw.njet.last_is0, cs->hw.njet.irqstat0);
- debugl1(cs, tmp);
- }
- cs->hw.njet.last_is0 = cs->hw.njet.irqstat0;
/* cs->hw.njet.irqmask0 = ((0x0f & cs->hw.njet.irqstat0) ^ 0x0f) | 0x30;
*/ byteout(cs->hw.njet.base + NETJET_IRQSTAT0, cs->hw.njet.irqstat0);
/* byteout(cs->hw.njet.base + NETJET_IRQMASK0, cs->hw.njet.irqmask0);
-*/ if (cs->hw.njet.irqstat0 & 0x0c)
+*/ if (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ)
read_tiger(cs);
- if (cs->hw.njet.irqstat0 & 0x03)
+ if (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE)
write_tiger(cs);
- }
+ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+ } else
+ restore_flags(flags);
+
/* if (!testcnt--) {
cs->hw.njet.dmactrl = 0;
byteout(cs->hw.njet.base + NETJET_DMACTRL,
cs->hw.njet.dmactrl);
byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0);
}
-*/ if (stat & 2) {
- WriteISAC(cs, ISAC_MASK, 0xFF);
- WriteISAC(cs, ISAC_MASK, 0x0);
- }
+*/
}
static void
@@ -1006,11 +1032,13 @@ NETjet_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
case CARD_SETIRQ:
return(request_irq(cs->irq, &netjet_interrupt,
- I4L_IRQ_FLAG, "HiSax", cs));
+ I4L_IRQ_FLAG | SA_SHIRQ, "HiSax", cs));
case CARD_INIT:
inittiger(cs);
clear_pending_isac_ints(cs);
initisac(cs);
+ /* Reenable all IRQ */
+ cs->writeisac(cs, ISAC_MASK, 0);
return(0);
case CARD_TEST:
return(0);
@@ -1020,7 +1048,7 @@ NETjet_card_msg(struct IsdnCardState *cs, int mt, void *arg)
-static int pci_index __initdata = 0;
+static struct pci_dev *dev_netjet __initdata = NULL;
__initfunc(int
setup_netjet(struct IsdnCard *card))
@@ -1028,52 +1056,37 @@ setup_netjet(struct IsdnCard *card))
int bytecnt;
struct IsdnCardState *cs = card->cs;
char tmp[64];
-#if CONFIG_PCI
- u_char pci_bus, pci_device_fn, pci_irq;
- u_int pci_ioaddr, found;
-#endif
strcpy(tmp, NETjet_revision);
printk(KERN_INFO "HiSax: Traverse Tech. NETjet driver Rev. %s\n", HiSax_getrev(tmp));
if (cs->typ != ISDN_CTYPE_NETJET)
return(0);
+ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
#if CONFIG_PCI
- found = 0;
- for (; pci_index < 0xff; pci_index++) {
- if (pcibios_find_device(PCI_VENDOR_TRAVERSE_TECH,
- PCI_NETJET_ID, pci_index, &pci_bus, &pci_device_fn)
- == PCIBIOS_SUCCESSFUL)
- found = 1;
- else
- break;
- /* get IRQ */
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_INTERRUPT_LINE, &pci_irq);
-
- /* get IO address */
- pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_0, &pci_ioaddr);
- if (found)
- break;
- }
- if (!found) {
- printk(KERN_WARNING "NETjet: No PCI card found\n");
+ if (!pci_present()) {
+ printk(KERN_ERR "Netjet: no PCI bus present\n");
return(0);
}
- if (!pci_irq) {
+ if ((dev_netjet = pci_find_device(PCI_VENDOR_TRAVERSE_TECH,
+ PCI_NETJET_ID, dev_netjet))) {
+ cs->irq = dev_netjet->irq;
+ if (!cs->irq) {
printk(KERN_WARNING "NETjet: No IRQ for PCI card found\n");
return(0);
}
- if (!pci_ioaddr) {
+ cs->hw.njet.base = dev_netjet->base_address[0] &
+ PCI_BASE_ADDRESS_IO_MASK;
+ if (!cs->hw.njet.base) {
printk(KERN_WARNING "NETjet: No IO-Adr for PCI card found\n");
return(0);
}
- pci_ioaddr &= ~3; /* remove io/mem flag */
- cs->hw.njet.base = pci_ioaddr;
- cs->hw.njet.auxa = pci_ioaddr + NETJET_AUXDATA;
- cs->hw.njet.isac = pci_ioaddr | NETJET_ISAC_OFF;
- cs->irq = pci_irq;
+ cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+ cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
bytecnt = 256;
+ } else {
+ printk(KERN_WARNING "NETjet: No PCI card found\n");
+ return(0);
+ }
#else
printk(KERN_WARNING "NETjet: NO_PCI_BIOS\n");
printk(KERN_WARNING "NETjet: unable to config NETJET PCI\n");
diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
index 59a8a94e3..13717f856 100644
--- a/drivers/isdn/hisax/niccy.c
+++ b/drivers/isdn/hisax/niccy.c
@@ -1,4 +1,4 @@
-/* $Id: niccy.c,v 1.2 1998/02/11 17:31:04 keil Exp $
+/* $Id: niccy.c,v 1.4 1998/04/16 19:16:48 keil Exp $
* niccy.c low level stuff for Dr. Neuhaus NICCY PnP and NICCY PCI and
* compatible (SAGEM cybermodem)
@@ -8,24 +8,28 @@
* Thanks to Dr. Neuhaus and SAGEM for informations
*
* $Log: niccy.c,v $
- * Revision 1.2 1998/02/11 17:31:04 keil
- * new file
+ * Revision 1.4 1998/04/16 19:16:48 keil
+ * need config.h
*
+ * Revision 1.3 1998/04/15 16:42:59 keil
+ * new init code
*
+ * Revision 1.2 1998/02/11 17:31:04 keil
+ * new file
*
*/
-#include <linux/config.h>
+
#define __NO_VERSION__
+#include <linux/config.h>
#include "hisax.h"
#include "isac.h"
#include "hscx.h"
#include "isdnl1.h"
#include <linux/pci.h>
-#include <linux/bios32.h>
extern const char *CardType[];
-const char *niccy_revision = "$Revision: 1.2 $";
+const char *niccy_revision = "$Revision: 1.4 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -44,6 +48,10 @@ const char *niccy_revision = "$Revision: 1.2 $";
/* PCI stuff */
#define PCI_VENDOR_DR_NEUHAUS 0x1267
#define PCI_NICCY_ID 0x1016
+#define PCI_IRQ_CTRL_REG 0x38
+#define PCI_IRQ_ENABLE 0x1f00
+#define PCI_IRQ_DISABLE 0xff0000
+#define PCI_IRQ_ASSERT 0x800000
static inline u_char
readreg(unsigned int ale, unsigned int adr, u_char off)
@@ -152,6 +160,13 @@ niccy_interrupt(int intno, void *dev_id, struct pt_regs *regs)
printk(KERN_WARNING "Niccy: Spurious interrupt!\n");
return;
}
+ if (cs->subtyp == NICCY_PCI) {
+ int ival;
+ ival = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
+ if (!(ival & PCI_IRQ_ASSERT)) /* IRQ not for us (shared) */
+ return;
+ outl(ival, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
+ }
val = readreg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_ISTA + 0x40);
Start_HSCX:
if (val) {
@@ -191,9 +206,15 @@ niccy_interrupt(int intno, void *dev_id, struct pt_regs *regs)
void
release_io_niccy(struct IsdnCardState *cs)
{
- if (cs->subtyp == NICCY_PCI)
+ if (cs->subtyp == NICCY_PCI) {
+ int val;
+
+ val = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
+ val &= PCI_IRQ_DISABLE;
+ outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
+ release_region(cs->hw.niccy.cfg_reg, 0x80);
release_region(cs->hw.niccy.isac, 4);
- else {
+ } else {
release_region(cs->hw.niccy.isac, 2);
release_region(cs->hw.niccy.isac_ale, 2);
}
@@ -202,12 +223,20 @@ release_io_niccy(struct IsdnCardState *cs)
static void
niccy_reset(struct IsdnCardState *cs)
{
- // No reset procedure known
+ int val, nval;
+
+ val = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
+ nval = val | PCI_IRQ_ENABLE;
+ outl(nval, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
+
+ inithscxisac(cs, 3);
}
static int
niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg)
{
+ int imode;
+
switch (mt) {
case CARD_RESET:
niccy_reset(cs);
@@ -216,13 +245,15 @@ niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg)
release_io_niccy(cs);
return(0);
case CARD_SETIRQ:
+ if (cs->subtyp == NICCY_PCI)
+ imode = I4L_IRQ_FLAG | SA_SHIRQ;
+ else
+ imode = I4L_IRQ_FLAG;
return(request_irq(cs->irq, &niccy_interrupt,
- I4L_IRQ_FLAG, "HiSax", cs));
+ imode, "HiSax", cs));
+ break;
case CARD_INIT:
- clear_pending_isac_ints(cs);
- clear_pending_hscx_ints(cs);
- initisac(cs);
- inithscx(cs);
+ niccy_reset(cs);
return(0);
case CARD_TEST:
return(0);
@@ -230,7 +261,7 @@ niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
-static int pci_index __initdata = 0;
+static struct pci_dev *niccy_dev __initdata = NULL;
__initfunc(int
setup_niccy(struct IsdnCard *card))
@@ -272,49 +303,41 @@ setup_niccy(struct IsdnCard *card))
request_region(cs->hw.niccy.isac_ale, 2, "niccy addr");
} else {
#if CONFIG_PCI
- u_char pci_bus, pci_device_fn, pci_irq;
u_int pci_ioaddr;
+ if (!pci_present()) {
+ printk(KERN_ERR "Niccy: no PCI bus present\n");
+ return(0);
+ }
+
cs->subtyp = 0;
- for (; pci_index < 0xff; pci_index++) {
- if (pcibios_find_device(PCI_VENDOR_DR_NEUHAUS,
- PCI_NICCY_ID, pci_index, &pci_bus, &pci_device_fn)
- == PCIBIOS_SUCCESSFUL)
- cs->subtyp = NICCY_PCI;
- else
- break;
+ if ((niccy_dev = pci_find_device(PCI_VENDOR_DR_NEUHAUS,
+ PCI_NICCY_ID, niccy_dev))) {
/* get IRQ */
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_INTERRUPT_LINE, &pci_irq);
-
- /* get IO address */
- /* if it won't work try the other PCI addresses
- * PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_5
- */
- pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_2, &pci_ioaddr);
- if (cs->subtyp)
- break;
- }
- if (!cs->subtyp) {
- printk(KERN_WARNING "Niccy: No PCI card found\n");
+ if (!niccy_dev->irq) {
+ printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n");
return(0);
}
- if (!pci_irq) {
- printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n");
+ cs->irq = niccy_dev->irq;
+ if (!niccy_dev->base_address[0]) {
+ printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n");
return(0);
}
-
- if (!pci_ioaddr) {
+ cs->hw.niccy.cfg_reg = niccy_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+ if (!niccy_dev->base_address[1]) {
printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n");
return(0);
}
- pci_ioaddr &= ~3; /* remove io/mem flag */
+ pci_ioaddr = niccy_dev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA;
cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR;
cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA;
cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR;
- cs->irq = pci_irq;
+ cs->subtyp = NICCY_PCI;
+ } else {
+ printk(KERN_WARNING "Niccy: No PCI card found\n");
+ return(0);
+ }
if (check_region((cs->hw.niccy.isac), 4)) {
printk(KERN_WARNING
"HiSax: %s data port %x-%x already in use\n",
@@ -324,6 +347,17 @@ setup_niccy(struct IsdnCard *card))
return (0);
} else
request_region(cs->hw.niccy.isac, 4, "niccy");
+ if (check_region(cs->hw.niccy.cfg_reg, 0x80)) {
+ printk(KERN_WARNING
+ "HiSax: %s pci port %x-%x already in use\n",
+ CardType[card->typ],
+ cs->hw.niccy.cfg_reg,
+ cs->hw.niccy.cfg_reg + 0x80);
+ release_region(cs->hw.niccy.isac, 4);
+ return (0);
+ } else {
+ request_region(cs->hw.niccy.cfg_reg, 0x80, "niccy pci");
+ }
#else
printk(KERN_WARNING "Niccy: io0 0 and NO_PCI_BIOS\n");
printk(KERN_WARNING "Niccy: unable to config NICCY PCI\n");
@@ -334,7 +368,6 @@ setup_niccy(struct IsdnCard *card))
"HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n",
CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI",
cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale);
- niccy_reset(cs);
cs->readisac = &ReadISAC;
cs->writeisac = &WriteISAC;
cs->readisacfifo = &ReadISACfifo;
diff --git a/drivers/isdn/hisax/q931.c b/drivers/isdn/hisax/q931.c
index a0ba3645a..d3c269a04 100644
--- a/drivers/isdn/hisax/q931.c
+++ b/drivers/isdn/hisax/q931.c
@@ -1,4 +1,4 @@
-/* $Id: q931.c,v 1.6 1997/07/27 21:09:44 keil Exp $
+/* $Id: q931.c,v 1.7 1998/11/15 23:55:17 keil Exp $
* q931.c code to decode ITU Q.931 call control messages
*
@@ -14,6 +14,9 @@
*
*
* $Log: q931.c,v $
+ * Revision 1.7 1998/11/15 23:55:17 keil
+ * changes from 2.0
+ *
* Revision 1.6 1997/07/27 21:09:44 keil
* move functions to isdnl3.c
*
@@ -159,7 +162,7 @@ struct MessageType mt_n0[] =
{MT_N0_CLO_ACK, "CLOse ACKnowledge"}
};
-int mt_n0_len = (sizeof(mt_n0) / sizeof(struct MessageType));
+#define MT_N0_LEN (sizeof(mt_n0) / sizeof(struct MessageType))
static
struct MessageType mt_n1[] =
@@ -196,7 +199,7 @@ struct MessageType mt_n1[] =
{MT_N1_STAT, "STATus"}
};
-int mt_n1_len = (sizeof(mt_n1) / sizeof(struct MessageType));
+#define MT_N1_LEN (sizeof(mt_n1) / sizeof(struct MessageType))
static struct MessageType fac_1tr6[] =
{
@@ -220,9 +223,7 @@ static struct MessageType fac_1tr6[] =
{FAC_Rueckwechsel, "Rueckwechsel"},
{FAC_Umleitung, "Umleitung"}
};
-int fac_1tr6_len = (sizeof(fac_1tr6) / sizeof(struct MessageType));
-
-
+#define FAC_1TR6_LEN (sizeof(fac_1tr6) / sizeof(struct MessageType))
static int
prbits(char *dest, u_char b, int start, int len)
@@ -925,7 +926,7 @@ static struct InformationElement we_0[] =
{WE0_userInfo, "User Info", general}
};
-static int we_0_len = (sizeof(we_0) / sizeof(struct InformationElement));
+#define WE_0_LEN (sizeof(we_0) / sizeof(struct InformationElement))
static struct InformationElement we_6[] =
{
@@ -937,7 +938,7 @@ static struct InformationElement we_6[] =
{WE6_statusCalled, "Status Called", general},
{WE6_addTransAttr, "Additional Transmission Attributes", general}
};
-static int we_6_len = (sizeof(we_6) / sizeof(struct InformationElement));
+#define WE_6_LEN (sizeof(we_6) / sizeof(struct InformationElement))
int
QuickHex(char *txt, u_char * p, int cnt)
@@ -964,39 +965,92 @@ QuickHex(char *txt, u_char * p, int cnt)
}
void
-LogFrame(struct IsdnCardState *sp, u_char * buf, int size)
+LogFrame(struct IsdnCardState *cs, u_char * buf, int size)
{
char *dp;
if (size < 1)
return;
- dp = sp->dlogspace;
- if (size < 4096 / 3 - 10) {
- dp += sprintf(dp, "HEX:");
+ dp = cs->dlog;
+ if (size < MAX_DLOG_SPACE / 3 - 10) {
+ *dp++ = 'H';
+ *dp++ = 'E';
+ *dp++ = 'X';
+ *dp++ = ':';
dp += QuickHex(dp, buf, size);
dp--;
*dp++ = '\n';
*dp = 0;
+ HiSax_putstatus(cs, NULL, cs->dlog);
} else
- sprintf(dp, "LogFrame: warning Frame too big (%d)\n",
- size);
- HiSax_putstatus(sp, sp->dlogspace);
+ HiSax_putstatus(cs, "LogFrame: ", "warning Frame too big (%d)", size);
}
void
-dlogframe(struct IsdnCardState *sp, u_char * buf, int size, char *comment)
+dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir)
{
- u_char *bend = buf + size;
+ u_char *bend, *buf;
char *dp;
unsigned char pd, cr_l, cr, mt;
- int i, cs = 0, cs_old = 0, cs_fest = 0;
+ unsigned char sapi, tei, ftyp;
+ int i, cset = 0, cs_old = 0, cs_fest = 0;
+ int size, finish = 0;
- if (size < 1)
+ if (skb->len < 3)
return;
/* display header */
- dp = sp->dlogspace;
- dp += sprintf(dp, "%s\n", comment);
-
+ dp = cs->dlog;
+ dp += jiftime(dp, jiffies);
+ *dp++ = ' ';
+ sapi = skb->data[0] >> 2;
+ tei = skb->data[1] >> 1;
+ ftyp = skb->data[2];
+ buf = skb->data;
+ dp += sprintf(dp, "frame %s ", dir ? "network->user" : "user->network");
+ size = skb->len;
+
+ if (tei == GROUP_TEI) {
+ if (sapi == CTRL_SAPI) { /* sapi 0 */
+ if (ftyp == 3) {
+ dp += sprintf(dp, "broadcast\n");
+ buf += 3;
+ size -= 3;
+ } else {
+ dp += sprintf(dp, "no UI broadcast\n");
+ finish = 1;
+ }
+ } else if (sapi == TEI_SAPI) {
+ dp += sprintf(dp, "tei managment\n");
+ finish = 1;
+ } else {
+ dp += sprintf(dp, "unknown sapi %d broadcast\n", sapi);
+ finish = 1;
+ }
+ } else {
+ if (sapi == CTRL_SAPI) {
+ if (!(ftyp & 1)) { /* IFrame */
+ dp += sprintf(dp, "with tei %d\n", tei);
+ buf += 4;
+ size -= 4;
+ } else {
+ dp += sprintf(dp, "SFrame with tei %d\n", tei);
+ finish = 1;
+ }
+ } else {
+ dp += sprintf(dp, "unknown sapi %d tei %d\n", sapi, tei);
+ finish = 1;
+ }
+ }
+ bend = skb->data + skb->len;
+ if (buf >= bend) {
+ dp += sprintf(dp, "frame too short\n");
+ finish = 1;
+ }
+ if (finish) {
+ *dp = 0;
+ HiSax_putstatus(cs, NULL, cs->dlog);
+ return;
+ }
if ((0xfe & buf[0]) == PROTO_DIS_N0) { /* 1TR6 */
/* locate message type */
pd = *buf++;
@@ -1007,11 +1061,11 @@ dlogframe(struct IsdnCardState *sp, u_char * buf, int size, char *comment)
cr = 0;
mt = *buf++;
if (pd == PROTO_DIS_N0) { /* N0 */
- for (i = 0; i < mt_n0_len; i++)
+ for (i = 0; i < MT_N0_LEN; i++)
if (mt_n0[i].nr == mt)
break;
/* display message type if it exists */
- if (i == mt_n0_len)
+ if (i == MT_N0_LEN)
dp += sprintf(dp, "callref %d %s size %d unknown message type N0 %x!\n",
cr & 0x7f, (cr & 0x80) ? "called" : "caller",
size, mt);
@@ -1020,11 +1074,11 @@ dlogframe(struct IsdnCardState *sp, u_char * buf, int size, char *comment)
cr & 0x7f, (cr & 0x80) ? "called" : "caller",
size, mt_n0[i].descr);
} else { /* N1 */
- for (i = 0; i < mt_n1_len; i++)
+ for (i = 0; i < MT_N1_LEN; i++)
if (mt_n1[i].nr == mt)
break;
/* display message type if it exists */
- if (i == mt_n1_len)
+ if (i == MT_N1_LEN)
dp += sprintf(dp, "callref %d %s size %d unknown message type N1 %x!\n",
cr & 0x7f, (cr & 0x80) ? "called" : "caller",
size, mt);
@@ -1041,8 +1095,8 @@ dlogframe(struct IsdnCardState *sp, u_char * buf, int size, char *comment)
switch ((*buf >> 4) & 7) {
case 1:
dp += sprintf(dp, " Shift %x\n", *buf & 0xf);
- cs_old = cs;
- cs = *buf & 7;
+ cs_old = cset;
+ cset = *buf & 7;
cs_fest = *buf & 8;
break;
case 3:
@@ -1066,33 +1120,33 @@ dlogframe(struct IsdnCardState *sp, u_char * buf, int size, char *comment)
continue;
}
/* No, locate it in the table */
- if (cs == 0) {
- for (i = 0; i < we_0_len; i++)
+ if (cset == 0) {
+ for (i = 0; i < WE_0_LEN; i++)
if (*buf == we_0[i].nr)
break;
/* When found, give appropriate msg */
- if (i != we_0_len) {
+ if (i != WE_0_LEN) {
dp += sprintf(dp, " %s\n", we_0[i].descr);
dp += we_0[i].f(dp, buf);
} else
- dp += sprintf(dp, " Codeset %d attribute %x attribute size %d\n", cs, *buf, buf[1]);
- } else if (cs == 6) {
- for (i = 0; i < we_6_len; i++)
+ dp += sprintf(dp, " Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
+ } else if (cset == 6) {
+ for (i = 0; i < WE_6_LEN; i++)
if (*buf == we_6[i].nr)
break;
/* When found, give appropriate msg */
- if (i != we_6_len) {
+ if (i != WE_6_LEN) {
dp += sprintf(dp, " %s\n", we_6[i].descr);
dp += we_6[i].f(dp, buf);
} else
- dp += sprintf(dp, " Codeset %d attribute %x attribute size %d\n", cs, *buf, buf[1]);
+ dp += sprintf(dp, " Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
} else
- dp += sprintf(dp, " Unknown Codeset %d attribute %x attribute size %d\n", cs, *buf, buf[1]);
+ dp += sprintf(dp, " Unknown Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
/* Skip to next element */
if (cs_fest == 8) {
- cs = cs_old;
+ cset = cs_old;
cs_old = 0;
cs_fest = 0;
}
@@ -1170,6 +1224,6 @@ dlogframe(struct IsdnCardState *sp, u_char * buf, int size, char *comment)
} else {
dp += sprintf(dp, "Unknown protocol %x!", buf[0]);
}
- dp += sprintf(dp, "\n");
- HiSax_putstatus(sp, sp->dlogspace);
+ *dp = 0;
+ HiSax_putstatus(cs, NULL, cs->dlog);
}
diff --git a/drivers/isdn/hisax/rawhdlc.c b/drivers/isdn/hisax/rawhdlc.c
index b878cb699..17ac5c602 100644
--- a/drivers/isdn/hisax/rawhdlc.c
+++ b/drivers/isdn/hisax/rawhdlc.c
@@ -1,4 +1,4 @@
-/* $Id: rawhdlc.c,v 1.2 1998/02/09 10:53:51 keil Exp $
+/* $Id: rawhdlc.c,v 1.3 1998/06/17 19:51:21 he Exp $
* rawhdlc.c support routines for cards that don't support HDLC
*
diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
index 46d3edaf0..85e64001a 100644
--- a/drivers/isdn/hisax/sedlbauer.c
+++ b/drivers/isdn/hisax/sedlbauer.c
@@ -1,11 +1,14 @@
-/* $Id: sedlbauer.c,v 1.6 1998/02/09 18:46:06 keil Exp $
+/* $Id: sedlbauer.c,v 1.9 1998/11/15 23:55:20 keil Exp $
* sedlbauer.c low level stuff for Sedlbauer cards
- * includes Support for the Sedlbauer Speed Star
- * derived from the original file dynalink.c from Karsten Keil
+ * includes support for the Sedlbauer speed star (speed star II),
+ * support for the Sedlbauer speed fax+,
+ * support for the Sedlbauer ISDN-Controller PC/104 and
+ * support for the Sedlbauer speed pci
+ * derived from the original file asuscom.c from Karsten Keil
*
* Copyright (C) 1997,1998 Marcus Niemann (for the modifications to
- * the original file dynalink.c)
+ * the original file asuscom.c)
*
* Author Marcus Niemann (niemann@www-bib.fh-bielefeld.de)
*
@@ -14,6 +17,15 @@
* Edgar Toernig
*
* $Log: sedlbauer.c,v $
+ * Revision 1.9 1998/11/15 23:55:20 keil
+ * changes from 2.0
+ *
+ * Revision 1.8 1998/08/13 23:34:51 keil
+ * starting speedfax+ (ISAR) support
+ *
+ * Revision 1.7 1998/04/15 16:44:33 keil
+ * new init code
+ *
* Revision 1.6 1998/02/09 18:46:06 keil
* Support for Sedlbauer PCMCIA (Marcus Niemann)
*
@@ -35,36 +47,91 @@
*
*/
+/* Supported cards:
+ * Card: Chip: Configuration: Comment:
+ * ---------------------------------------------------------------------
+ * Speed Card ISAC_HSCX DIP-SWITCH
+ * Speed Win ISAC_HSCX ISAPNP
+ * Speed Fax+ ISAC_ISAR ISAPNP #HDLC works#
+ * Speed Star ISAC_HSCX CARDMGR
+ * Speed Win2 IPAC ISAPNP
+ * ISDN PC/104 IPAC DIP-SWITCH
+ * Speed Star2 IPAC CARDMGR
+ * Speed PCI IPAC PNP
+ *
+ * Important:
+ * For the sedlbauer speed fax+ to work properly you have to download
+ * the firmware onto the card.
+ * For example: hisaxctrl <DriverID> 9 ISAR.BIN
+*/
+
+#define SEDLBAUER_PCI 1
+
#define __NO_VERSION__
+#include <linux/config.h>
#include "hisax.h"
#include "isac.h"
+#include "ipac.h"
#include "hscx.h"
+#include "isar.h"
#include "isdnl1.h"
+#include <linux/pci.h>
extern const char *CardType[];
-const char *Sedlbauer_revision = "$Revision: 1.6 $";
+const char *Sedlbauer_revision = "$Revision: 1.9 $";
const char *Sedlbauer_Types[] =
-{"None", "Speed Card", "Speed Win", "Speed Star"};
+ {"None", "speed card/win", "speed star", "speed fax+",
+ "speed win II / ISDN PC/104", "speed star II", "speed pci"};
+
+#ifdef SEDLBAUER_PCI
+#define PCI_VENDOR_SEDLBAUER 0xe159
+#define PCI_SPEEDPCI_ID 0x02
+#endif
-#define SEDL_SPEED_CARD 1
-#define SEDL_SPEED_WIN 2
-#define SEDL_SPEED_STAR 3
+#define SEDL_SPEED_CARD_WIN 1
+#define SEDL_SPEED_STAR 2
+#define SEDL_SPEED_FAX 3
+#define SEDL_SPEED_WIN2_PC104 4
+#define SEDL_SPEED_STAR2 5
+#define SEDL_SPEED_PCI 6
+
+#define SEDL_CHIP_TEST 0
+#define SEDL_CHIP_ISAC_HSCX 1
+#define SEDL_CHIP_ISAC_ISAR 2
+#define SEDL_CHIP_IPAC 3
+
+#define SEDL_BUS_ISA 1
+#define SEDL_BUS_PCI 2
+#define SEDL_BUS_PCMCIA 3
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
-#define SEDL_RESET_ON 0
-#define SEDL_RESET_OFF 1
-#define SEDL_ISAC 2
-#define SEDL_HSCX 3
-#define SEDL_ADR 4
+#define SEDL_HSCX_ISA_RESET_ON 0
+#define SEDL_HSCX_ISA_RESET_OFF 1
+#define SEDL_HSCX_ISA_ISAC 2
+#define SEDL_HSCX_ISA_HSCX 3
+#define SEDL_HSCX_ISA_ADR 4
+
+#define SEDL_HSCX_PCMCIA_RESET 0
+#define SEDL_HSCX_PCMCIA_ISAC 1
+#define SEDL_HSCX_PCMCIA_HSCX 2
+#define SEDL_HSCX_PCMCIA_ADR 4
+
+#define SEDL_ISAR_ISA_ISAC 4
+#define SEDL_ISAR_ISA_ISAR 6
+#define SEDL_ISAR_ISA_ADR 8
+#define SEDL_ISAR_ISA_ISAR_RESET_ON 10
+#define SEDL_ISAR_ISA_ISAR_RESET_OFF 12
-#define SEDL_PCMCIA_RESET 0
-#define SEDL_PCMCIA_ISAC 1
-#define SEDL_PCMCIA_HSCX 2
-#define SEDL_PCMCIA_ADR 4
+#define SEDL_IPAC_ANY_ADR 0
+#define SEDL_IPAC_ANY_IPAC 2
+
+#define SEDL_IPAC_PCI_BASE 0
+#define SEDL_IPAC_PCI_ADR 0xc0
+#define SEDL_IPAC_PCI_IPAC 0xc8
#define SEDL_RESET 0x3 /* same as DOS driver */
@@ -139,6 +206,29 @@ WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
}
static u_char
+ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
+{
+ return (readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80));}
+
+static void
+WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80, value);
+}
+
+static void
+ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+ readfifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size);
+}
+
+static void
+WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+ writefifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size);
+}
+
+static u_char
ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
{
return (readreg(cs->hw.sedl.adr,
@@ -152,6 +242,34 @@ WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0), value);
}
+/* ISAR access routines
+ * mode = 0 access with IRQ on
+ * mode = 1 access with IRQ off
+ * mode = 2 access with IRQ off and using last offset
+ */
+
+static u_char
+ReadISAR(struct IsdnCardState *cs, int mode, u_char offset)
+{
+ if (mode == 0)
+ return (readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset));
+ else if (mode == 1)
+ byteout(cs->hw.sedl.adr, offset);
+ return(bytein(cs->hw.sedl.hscx));
+}
+
+static void
+WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value)
+{
+ if (mode == 0)
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset, value);
+ else {
+ if (mode == 1)
+ byteout(cs->hw.sedl.adr, offset);
+ byteout(cs->hw.sedl.hscx, value);
+ }
+}
+
/*
* fast interrupt HSCX stuff goes here
*/
@@ -180,7 +298,7 @@ sedlbauer_interrupt(int intno, void *dev_id, struct pt_regs *regs)
return;
}
- if ((cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) && (*cs->busy_flag == 1)) {
+ if ((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && (*cs->busy_flag == 1)) {
/* The card tends to generate interrupts while being removed
causing us to just crash the kernel. bad. */
printk(KERN_WARNING "Sedlbauer: card not available!\n");
@@ -223,11 +341,101 @@ sedlbauer_interrupt(int intno, void *dev_id, struct pt_regs *regs)
}
}
+static void
+sedlbauer_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+{
+ struct IsdnCardState *cs = dev_id;
+ u_char ista, val, icnt = 20;
+
+ if (!cs) {
+ printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n");
+ return;
+ }
+ ista = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA);
+Start_IPAC:
+ if (cs->debug & L1_DEB_IPAC)
+ debugl1(cs, "IPAC ISTA %02X", ista);
+ if (ista & 0x0f) {
+ val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40);
+ if (ista & 0x01)
+ val |= 0x01;
+ if (ista & 0x04)
+ val |= 0x02;
+ if (ista & 0x08)
+ val |= 0x04;
+ if (val)
+ hscx_int_main(cs, val);
+ }
+ if (ista & 0x20) {
+ val = 0xfe & readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA | 0x80);
+ if (val) {
+ isac_interrupt(cs, val);
+ }
+ }
+ if (ista & 0x10) {
+ val = 0x01;
+ isac_interrupt(cs, val);
+ }
+ ista = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA);
+ if ((ista & 0x3f) && icnt) {
+ icnt--;
+ goto Start_IPAC;
+ }
+ if (!icnt)
+ printk(KERN_WARNING "Sedlbauer IRQ LOOP\n");
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xFF);
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xC0);
+}
+
+static void
+sedlbauer_interrupt_isar(int intno, void *dev_id, struct pt_regs *regs)
+{
+ struct IsdnCardState *cs = dev_id;
+ u_char val;
+ int cnt = 20;
+
+ if (!cs) {
+ printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n");
+ return;
+ }
+
+ val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT);
+ Start_ISAR:
+ if (val & ISAR_IRQSTA)
+ isar_int_main(cs);
+ val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
+ Start_ISAC:
+ if (val)
+ isac_interrupt(cs, val);
+ val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT);
+ if ((val & ISAR_IRQSTA) && --cnt) {
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "ISAR IntStat after IntRoutine");
+ goto Start_ISAR;
+ }
+ val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
+ if (val && --cnt) {
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "ISAC IntStat after IntRoutine");
+ goto Start_ISAC;
+ }
+ if (!cnt)
+ printk(KERN_WARNING "Sedlbauer IRQ LOOP\n");
+
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, 0);
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF);
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0);
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, ISAR_IRQMSK);
+}
+
void
release_io_sedlbauer(struct IsdnCardState *cs)
{
- int bytecnt = 8;
+ int bytecnt = (cs->subtyp == SEDL_SPEED_FAX) ? 16 : 8;
+ if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
+ bytecnt = 256;
+ }
if (cs->hw.sedl.cfg_reg)
release_region(cs->hw.sedl.cfg_reg, bytecnt);
}
@@ -237,16 +445,36 @@ reset_sedlbauer(struct IsdnCardState *cs)
{
long flags;
- if (cs->typ != ISDN_CTYPE_SEDLBAUER_PCMCIA) {
- byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */
- save_flags(flags);
- sti();
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
- byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
- restore_flags(flags);
+ printk(KERN_INFO "Sedlbauer: resetting card\n");
+
+ if (!((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) &&
+ (cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX))) {
+ if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x20);
+ save_flags(flags);
+ sti();
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(1);
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x0);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(1);
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_CONF, 0x0);
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ACFG, 0xff);
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_AOE, 0x0);
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xc0);
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_PCFG, 0x12);
+ restore_flags(flags);
+ } else {
+ byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */
+ save_flags(flags);
+ sti();
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(1);
+ byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(1);
+ restore_flags(flags);
+ }
}
}
@@ -261,94 +489,256 @@ Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg)
release_io_sedlbauer(cs);
return(0);
case CARD_SETIRQ:
- return(request_irq(cs->irq, &sedlbauer_interrupt,
+ if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+ return(request_irq(cs->irq, &sedlbauer_interrupt_isar,
I4L_IRQ_FLAG, "HiSax", cs));
+ } else if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
+ return(request_irq(cs->irq, &sedlbauer_interrupt_ipac,
+ I4L_IRQ_FLAG, "HiSax", cs));
+ } else {
+ return(request_irq(cs->irq, &sedlbauer_interrupt,
+ I4L_IRQ_FLAG, "HiSax", cs));
+ }
case CARD_INIT:
- clear_pending_isac_ints(cs);
- clear_pending_hscx_ints(cs);
- initisac(cs);
- inithscx(cs);
+ if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+ clear_pending_isac_ints(cs);
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
+ ISAR_IRQBIT, 0);
+ initisac(cs);
+ initisar(cs);
+ /* Reenable all IRQ */
+ cs->writeisac(cs, ISAC_MASK, 0);
+ /* RESET Receiver and Transmitter */
+ cs->writeisac(cs, ISAC_CMDR, 0x41);
+ } else {
+ inithscxisac(cs, 3);
+ }
return(0);
case CARD_TEST:
return(0);
+ case CARD_LOAD_FIRM:
+ if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+ if (isar_load_firmware(cs, arg))
+ return(1);
+ else
+ ll_run(cs);
+ }
+ return(0);
}
return(0);
}
+
+#ifdef SEDLBAUER_PCI
+static int pci_index __initdata = 0;
+#endif
+
__initfunc(int
setup_sedlbauer(struct IsdnCard *card))
{
- int bytecnt;
+ int bytecnt, ver, val;
struct IsdnCardState *cs = card->cs;
char tmp[64];
strcpy(tmp, Sedlbauer_revision);
printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp));
+
if (cs->typ == ISDN_CTYPE_SEDLBAUER) {
- cs->subtyp = SEDL_SPEED_CARD;
+ cs->subtyp = SEDL_SPEED_CARD_WIN;
+ cs->hw.sedl.bus = SEDL_BUS_ISA;
+ cs->hw.sedl.chip = SEDL_CHIP_TEST;
} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) {
cs->subtyp = SEDL_SPEED_STAR;
+ cs->hw.sedl.bus = SEDL_BUS_PCMCIA;
+ cs->hw.sedl.chip = SEDL_CHIP_TEST;
+ } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) {
+ cs->subtyp = SEDL_SPEED_FAX;
+ cs->hw.sedl.bus = SEDL_BUS_ISA;
+ cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
} else
return (0);
bytecnt = 8;
- cs->hw.sedl.cfg_reg = card->para[1];
- cs->irq = card->para[0];
- if (cs->subtyp == SEDL_SPEED_STAR) {
- cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_ADR;
- cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_ISAC;
- cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_HSCX;
- cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_RESET;
- cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_RESET;
+ if (card->para[1]) {
+ cs->hw.sedl.cfg_reg = card->para[1];
+ cs->irq = card->para[0];
+ if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+ bytecnt = 16;
+ }
} else {
- cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ADR;
- cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAC;
- cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX;
- cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_RESET_ON;
- cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_RESET_OFF;
- }
-
- /* In case of the sedlbauer pcmcia card, this region is in use,
+/* Probe for Sedlbauer speed pci */
+#if SEDLBAUER_PCI
+#if CONFIG_PCI
+ for (; pci_index < 255; pci_index++) {
+ unsigned char pci_bus, pci_device_fn;
+ unsigned int ioaddr;
+ unsigned char irq;
+
+ if (pcibios_find_device (PCI_VENDOR_SEDLBAUER,
+ PCI_SPEEDPCI_ID, pci_index,
+ &pci_bus, &pci_device_fn) != 0) {
+ continue;
+ }
+ pcibios_read_config_byte(pci_bus, pci_device_fn,
+ PCI_INTERRUPT_LINE, &irq);
+ pcibios_read_config_dword(pci_bus, pci_device_fn,
+ PCI_BASE_ADDRESS_0, &ioaddr);
+ cs->irq = irq;
+ cs->hw.sedl.cfg_reg = ioaddr & PCI_BASE_ADDRESS_IO_MASK;
+ if (!cs->hw.sedl.cfg_reg) {
+ printk(KERN_WARNING "Sedlbauer: No IO-Adr for PCI card found\n");
+ return(0);
+ }
+ cs->hw.sedl.bus = SEDL_BUS_PCI;
+ cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+ cs->subtyp = SEDL_SPEED_PCI;
+ bytecnt = 256;
+ byteout(cs->hw.sedl.cfg_reg, 0xff);
+ byteout(cs->hw.sedl.cfg_reg, 0x00);
+ byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
+ byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
+ break;
+ }
+ if (pci_index == 255) {
+ printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
+ return(0);
+ }
+ pci_index++;
+#else
+ printk(KERN_WARNING "Sedlbauer: NO_PCI_BIOS\n");
+ return (0);
+#endif /* CONFIG_PCI */
+#endif /* SEDLBAUER_PCI */
+ }
+
+ /* In case of the sedlbauer pcmcia card, this region is in use,
reserved for us by the card manager. So we do not check it
here, it would fail. */
- if (cs->typ != ISDN_CTYPE_SEDLBAUER_PCMCIA &&
- check_region((cs->hw.sedl.cfg_reg), bytecnt)) {
+ if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA &&
+ check_region((cs->hw.sedl.cfg_reg), bytecnt)) {
printk(KERN_WARNING
- "HiSax: %s config port %x-%x already in use\n",
- CardType[card->typ],
- cs->hw.sedl.cfg_reg,
- cs->hw.sedl.cfg_reg + bytecnt);
- return (0);
+ "HiSax: %s config port %x-%x already in use\n",
+ CardType[card->typ],
+ cs->hw.sedl.cfg_reg,
+ cs->hw.sedl.cfg_reg + bytecnt);
+ return (0);
} else {
request_region(cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn");
}
printk(KERN_INFO
- "Sedlbauer: defined at 0x%x IRQ %d\n",
+ "Sedlbauer: defined at 0x%x-0x%x IRQ %d\n",
cs->hw.sedl.cfg_reg,
+ cs->hw.sedl.cfg_reg + bytecnt,
cs->irq);
- printk(KERN_WARNING
- "Sedlbauer %s uses ports 0x%x-0x%x\n",
- Sedlbauer_Types[cs->subtyp],
- cs->hw.sedl.cfg_reg,
- cs->hw.sedl.cfg_reg + bytecnt);
- printk(KERN_INFO "Sedlbauer: resetting card\n");
- reset_sedlbauer(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 = &Sedl_card_msg;
- ISACVersion(cs, "Sedlbauer:");
- if (HscxVersion(cs, "Sedlbauer:")) {
- printk(KERN_WARNING
- "Sedlbauer: wrong HSCX versions check IO address\n");
- release_io_sedlbauer(cs);
- return (0);
+
+/*
+ * testing ISA and PCMCIA Cards for IPAC, default is ISAC
+ * do not test for PCI card, because ports are different
+ * and PCI card uses only IPAC (for the moment)
+ */
+ if (cs->hw.sedl.bus != SEDL_BUS_PCI) {
+ val = readreg(cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR,
+ cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID);
+ if (val == 1) {
+ /* IPAC */
+ cs->subtyp = SEDL_SPEED_WIN2_PC104;
+ if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
+ cs->subtyp = SEDL_SPEED_STAR2;
+ }
+ cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+ } else {
+ /* ISAC_HSCX oder ISAC_ISAR */
+ if (cs->hw.sedl.chip == SEDL_CHIP_TEST) {
+ cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
+ }
+ }
+ }
+
+/*
+ * hw.sedl.chip is now properly set
+ */
+ printk(KERN_INFO "Sedlbauer: %s detected\n",
+ Sedlbauer_Types[cs->subtyp]);
+
+
+ if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
+ /* IPAC */
+ if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
+ cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR;
+ cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
+ cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
+ } else {
+ cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
+ cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
+ cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
+ }
+ test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+ cs->readisac = &ReadISAC_IPAC;
+ cs->writeisac = &WriteISAC_IPAC;
+ cs->readisacfifo = &ReadISACfifo_IPAC;
+ cs->writeisacfifo = &WriteISACfifo_IPAC;
+
+ val = readreg(cs->hw.sedl.adr,cs->hw.sedl.isac, IPAC_ID);
+ printk(KERN_INFO "Sedlbauer: IPAC version %x\n", val);
+ reset_sedlbauer(cs);
+ } else {
+ /* ISAC_HSCX oder ISAC_ISAR */
+ cs->readisac = &ReadISAC;
+ cs->writeisac = &WriteISAC;
+ cs->readisacfifo = &ReadISACfifo;
+ cs->writeisacfifo = &WriteISACfifo;
+ if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+ cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ADR;
+ cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAC;
+ cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR;
+ cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_ON;
+ cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_OFF;
+ cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
+ cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
+ test_and_set_bit(HW_ISAR, &cs->HW_Flags);
+
+ ISACVersion(cs, "Sedlbauer:");
+
+ cs->BC_Read_Reg = &ReadISAR;
+ cs->BC_Write_Reg = &WriteISAR;
+ cs->BC_Send_Data = &isar_fill_fifo;
+ ver = ISARVersion(cs, "Sedlbauer:");
+ if (ver < 0) {
+ printk(KERN_WARNING
+ "Sedlbauer: wrong ISAR version (ret = %d)\n", ver);
+ release_io_sedlbauer(cs);
+ return (0);
+ }
+ } else {
+ if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
+ cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
+ cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC;
+ cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX;
+ cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
+ cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
+ } else {
+ cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR;
+ cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC;
+ cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX;
+ cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
+ cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
+ }
+ ISACVersion(cs, "Sedlbauer:");
+
+ if (HscxVersion(cs, "Sedlbauer:")) {
+ printk(KERN_WARNING
+ "Sedlbauer: wrong HSCX versions check IO address\n");
+ release_io_sedlbauer(cs);
+ return (0);
+ }
+ reset_sedlbauer(cs);
+ }
}
return (1);
}
diff --git a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c
index 43d0641da..655abfadc 100644
--- a/drivers/isdn/hisax/sportster.c
+++ b/drivers/isdn/hisax/sportster.c
@@ -1,4 +1,4 @@
-/* $Id: sportster.c,v 1.5 1998/02/02 13:29:46 keil Exp $
+/* $Id: sportster.c,v 1.7 1998/11/15 23:55:22 keil Exp $
* sportster.c low level stuff for USR Sportster internal TA
*
@@ -7,6 +7,12 @@
* Thanks to Christian "naddy" Weisgerber (3Com, US Robotics) for documentation
*
* $Log: sportster.c,v $
+ * Revision 1.7 1998/11/15 23:55:22 keil
+ * changes from 2.0
+ *
+ * Revision 1.6 1998/04/15 16:44:35 keil
+ * new init code
+ *
* Revision 1.5 1998/02/02 13:29:46 keil
* fast io
*
@@ -30,7 +36,7 @@
#include "isdnl1.h"
extern const char *CardType[];
-const char *sportster_revision = "$Revision: 1.5 $";
+const char *sportster_revision = "$Revision: 1.7 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -187,12 +193,10 @@ Sportster_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(request_irq(cs->irq, &sportster_interrupt,
I4L_IRQ_FLAG, "HiSax", cs));
case CARD_INIT:
- clear_pending_isac_ints(cs);
- clear_pending_hscx_ints(cs);
- initisac(cs);
- inithscx(cs);
+ inithscxisac(cs, 1);
cs->hw.spt.res_irq |= SPORTSTER_INTE; /* IRQ On */
byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
+ inithscxisac(cs, 2);
return(0);
case CARD_TEST:
return(0);
diff --git a/drivers/isdn/hisax/tei.c b/drivers/isdn/hisax/tei.c
index a52078746..c9d94fe4d 100644
--- a/drivers/isdn/hisax/tei.c
+++ b/drivers/isdn/hisax/tei.c
@@ -1,12 +1,34 @@
-/* $Id: tei.c,v 2.7 1998/02/12 23:08:11 keil Exp $
+/* $Id: tei.c,v 2.11 1998/11/15 23:55:24 keil Exp $
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
* based on the teles driver from Jan den Ouden
*
+ * This file is (c) under GNU PUBLIC LICENSE
+ * For changes and modifications please read
+ * ../../../Documentation/isdn/HiSax.cert
+ *
* Thanks to Jan den Ouden
* Fritz Elfert
*
* $Log: tei.c,v $
+ * Revision 2.11 1998/11/15 23:55:24 keil
+ * changes from 2.0
+ *
+ * Revision 2.10 1998/05/25 14:08:10 keil
+ * HiSax 3.0
+ * fixed X.75 and leased line to work again
+ * Point2Point and fixed TEI are runtime options now:
+ * hisaxctrl <id> 7 1 set PTP
+ * hisaxctrl <id> 8 <TEIVALUE *2 >
+ * set fixed TEI to TEIVALUE (0-63)
+ *
+ * Revision 2.9 1998/05/25 12:58:23 keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.8 1998/03/07 22:57:07 tsbogend
+ * made HiSax working on Linux/Alpha
+ *
* Revision 2.7 1998/02/12 23:08:11 keil
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
@@ -50,7 +72,7 @@
#include "isdnl2.h"
#include <linux/random.h>
-const char *tei_revision = "$Revision: 2.7 $";
+const char *tei_revision = "$Revision: 2.11 $";
#define ID_REQUEST 1
#define ID_ASSIGNED 2
@@ -151,26 +173,24 @@ put_tei_msg(struct PStack *st, u_char m_id, unsigned int ri, u_char tei)
bp[2] = ri & 0xff;
bp[3] = m_id;
bp[4] = (tei << 1) | 1;
- st->l2.l2l1(st, PH_DATA_REQ, skb);
+ st->l2.l2l1(st, PH_DATA | REQUEST, skb);
}
static void
tei_id_request(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
- char tmp[64];
if (st->l2.tei != -1) {
- sprintf(tmp, "assign request for allready asigned tei %d",
+ st->ma.tei_m.printdebug(&st->ma.tei_m,
+ "assign request for allready asigned tei %d",
st->l2.tei);
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
return;
}
st->ma.ri = random_ri();
- if (st->ma.debug) {
- sprintf(tmp, "assign request ri %d", st->ma.ri);
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
- }
+ if (st->ma.debug)
+ st->ma.tei_m.printdebug(&st->ma.tei_m,
+ "assign request ri %d", st->ma.ri);
put_tei_msg(st, ID_REQUEST, st->ma.ri, 127);
FsmChangeState(&st->ma.tei_m, ST_TEI_IDREQ);
FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 1);
@@ -184,26 +204,24 @@ tei_id_assign(struct FsmInst *fi, int event, void *arg)
struct sk_buff *skb = arg;
struct IsdnCardState *cs;
int ri, tei;
- char tmp[64];
ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
tei = skb->data[4] >> 1;
- if (st->ma.debug) {
- sprintf(tmp, "identity assign ri %d tei %d", ri, tei);
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
- }
+ if (st->ma.debug)
+ st->ma.tei_m.printdebug(&st->ma.tei_m,
+ "identity assign ri %d tei %d", ri, tei);
if ((ost = findtei(st, tei))) { /* same tei is in use */
if (ri != ost->ma.ri) {
- sprintf(tmp, "possible duplicate assignment tei %d", tei);
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
- ost->l2.l2tei(ost, MDL_ERROR_REQ, NULL);
+ st->ma.tei_m.printdebug(&st->ma.tei_m,
+ "possible duplicate assignment tei %d", tei);
+ ost->l2.l2tei(ost, MDL_ERROR | RESPONSE, NULL);
}
} else if (ri == st->ma.ri) {
FsmDelTimer(&st->ma.t202, 1);
FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
- st->ma.manl2(st, MDL_ASSIGN_REQ, (void *) (int) tei);
+ st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) tei);
cs = (struct IsdnCardState *) st->l1.hardware;
- cs->cardmsg(cs, MDL_ASSIGN_REQ, NULL);
+ cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
}
}
@@ -213,14 +231,12 @@ tei_id_denied(struct FsmInst *fi, int event, void *arg)
struct PStack *st = fi->userdata;
struct sk_buff *skb = arg;
int ri, tei;
- char tmp[64];
ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
tei = skb->data[4] >> 1;
- if (st->ma.debug) {
- sprintf(tmp, "identity denied ri %d tei %d", ri, tei);
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
- }
+ if (st->ma.debug)
+ st->ma.tei_m.printdebug(&st->ma.tei_m,
+ "identity denied ri %d tei %d", ri, tei);
}
static void
@@ -229,13 +245,11 @@ tei_id_chk_req(struct FsmInst *fi, int event, void *arg)
struct PStack *st = fi->userdata;
struct sk_buff *skb = arg;
int tei;
- char tmp[64];
tei = skb->data[4] >> 1;
- if (st->ma.debug) {
- sprintf(tmp, "identity check req tei %d", tei);
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
- }
+ if (st->ma.debug)
+ st->ma.tei_m.printdebug(&st->ma.tei_m,
+ "identity check req tei %d", tei);
if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) {
FsmDelTimer(&st->ma.t202, 4);
FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
@@ -250,19 +264,17 @@ tei_id_remove(struct FsmInst *fi, int event, void *arg)
struct sk_buff *skb = arg;
struct IsdnCardState *cs;
int tei;
- char tmp[64];
tei = skb->data[4] >> 1;
- if (st->ma.debug) {
- sprintf(tmp, "identity remove tei %d", tei);
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
- }
+ if (st->ma.debug)
+ st->ma.tei_m.printdebug(&st->ma.tei_m,
+ "identity remove tei %d", tei);
if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) {
FsmDelTimer(&st->ma.t202, 5);
FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
- st->ma.manl2(st, MDL_REMOVE_REQ, 0);
+ st->l3.l3l2(st, MDL_REMOVE | REQUEST, 0);
cs = (struct IsdnCardState *) st->l1.hardware;
- cs->cardmsg(cs, MDL_REMOVE_REQ, NULL);
+ cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
}
}
@@ -270,12 +282,10 @@ static void
tei_id_verify(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
- char tmp[64];
- if (st->ma.debug) {
- sprintf(tmp, "id verify request for tei %d", st->l2.tei);
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
- }
+ if (st->ma.debug)
+ st->ma.tei_m.printdebug(&st->ma.tei_m,
+ "id verify request for tei %d", st->l2.tei);
put_tei_msg(st, ID_VERIFY, 0, st->l2.tei);
FsmChangeState(&st->ma.tei_m, ST_TEI_IDVERIFY);
FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 2);
@@ -286,24 +296,21 @@ static void
tei_id_req_tout(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
- char tmp[64];
struct IsdnCardState *cs;
if (--st->ma.N202) {
st->ma.ri = random_ri();
- if (st->ma.debug) {
- sprintf(tmp, "assign req(%d) ri %d",
- 4 - st->ma.N202, st->ma.ri);
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
- }
+ if (st->ma.debug)
+ st->ma.tei_m.printdebug(&st->ma.tei_m,
+ "assign req(%d) ri %d", 4 - st->ma.N202,
+ st->ma.ri);
put_tei_msg(st, ID_REQUEST, st->ma.ri, 127);
FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 3);
} else {
- sprintf(tmp, "assign req failed");
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
- st->ma.manl2(st, MDL_ERROR_IND, 0);
+ st->ma.tei_m.printdebug(&st->ma.tei_m, "assign req failed");
+ st->l3.l3l2(st, MDL_ERROR | RESPONSE, 0);
cs = (struct IsdnCardState *) st->l1.hardware;
- cs->cardmsg(cs, MDL_REMOVE_REQ, NULL);
+ cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
FsmChangeState(fi, ST_TEI_NOP);
}
}
@@ -312,23 +319,21 @@ static void
tei_id_ver_tout(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
- char tmp[64];
struct IsdnCardState *cs;
if (--st->ma.N202) {
- if (st->ma.debug) {
- sprintf(tmp, "id verify req(%d) for tei %d",
+ if (st->ma.debug)
+ st->ma.tei_m.printdebug(&st->ma.tei_m,
+ "id verify req(%d) for tei %d",
3 - st->ma.N202, st->l2.tei);
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
- }
put_tei_msg(st, ID_VERIFY, 0, st->l2.tei);
FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 4);
} else {
- sprintf(tmp, "verify req for tei %d failed", st->l2.tei);
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
- st->ma.manl2(st, MDL_REMOVE_REQ, 0);
+ st->ma.tei_m.printdebug(&st->ma.tei_m,
+ "verify req for tei %d failed", st->l2.tei);
+ st->l3.l3l2(st, MDL_REMOVE | REQUEST, 0);
cs = (struct IsdnCardState *) st->l1.hardware;
- cs->cardmsg(cs, MDL_REMOVE_REQ, NULL);
+ cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
FsmChangeState(fi, ST_TEI_NOP);
}
}
@@ -338,31 +343,34 @@ tei_l1l2(struct PStack *st, int pr, void *arg)
{
struct sk_buff *skb = arg;
int mt;
- char tmp[64];
- if (pr == PH_DATA_IND) {
+ if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ if (pr == (PH_DATA | INDICATION)) {
if (skb->len < 3) {
- sprintf(tmp, "short mgr frame %d/3", skb->len);
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
+ st->ma.tei_m.printdebug(&st->ma.tei_m,
+ "short mgr frame %ld/3", skb->len);
} else if (((skb->data[0] >> 2) != TEI_SAPI) ||
((skb->data[1] >> 1) != GROUP_TEI)) {
- sprintf(tmp, "wrong mgr sapi/tei %x/%x",
+ st->ma.tei_m.printdebug(&st->ma.tei_m,
+ "wrong mgr sapi/tei %x/%x",
skb->data[0], skb->data[1]);
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
} else if ((skb->data[2] & 0xef) != UI) {
- sprintf(tmp, "mgr frame is not ui %x",
- skb->data[2]);
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
+ st->ma.tei_m.printdebug(&st->ma.tei_m,
+ "mgr frame is not ui %x", skb->data[2]);
} else {
skb_pull(skb, 3);
if (skb->len < 5) {
- sprintf(tmp, "short mgr frame %d/5", skb->len);
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
+ st->ma.tei_m.printdebug(&st->ma.tei_m,
+ "short mgr frame %ld/5", skb->len);
} else if (skb->data[0] != TEI_ENTITY_ID) {
/* wrong management entity identifier, ignore */
- sprintf(tmp, "tei handler wrong entity id %x\n",
+ st->ma.tei_m.printdebug(&st->ma.tei_m,
+ "tei handler wrong entity id %x",
skb->data[0]);
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
} else {
mt = skb->data[3];
if (mt == ID_ASSIGNED)
@@ -374,15 +382,14 @@ tei_l1l2(struct PStack *st, int pr, void *arg)
else if (mt == ID_REMOVE)
FsmEvent(&st->ma.tei_m, EV_REMOVE, skb);
else {
- sprintf(tmp, "tei handler wrong mt %x\n",
- mt);
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
+ st->ma.tei_m.printdebug(&st->ma.tei_m,
+ "tei handler wrong mt %x\n", mt);
}
}
}
} else {
- sprintf(tmp, "tei handler wrong pr %x\n", pr);
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
+ st->ma.tei_m.printdebug(&st->ma.tei_m,
+ "tei handler wrong pr %x\n", pr);
}
dev_kfree_skb(skb);
}
@@ -390,20 +397,24 @@ tei_l1l2(struct PStack *st, int pr, void *arg)
static void
tei_l2tei(struct PStack *st, int pr, void *arg)
{
+ struct IsdnCardState *cs;
+
+ if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
+ if (pr == (MDL_ASSIGN | INDICATION)) {
+ if (st->ma.debug)
+ st->ma.tei_m.printdebug(&st->ma.tei_m,
+ "fixed assign tei %d", st->l2.tei);
+ st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) st->l2.tei);
+ cs = (struct IsdnCardState *) st->l1.hardware;
+ cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
+ }
+ return;
+ }
switch (pr) {
- case (MDL_ASSIGN_IND):
-#ifdef TEI_FIXED
- if (st->ma.debug) {
- char tmp[64];
- sprintf(tmp, "fixed assign tei %d", TEI_FIXED);
- st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
- }
- st->ma.manl2(st, MDL_ASSIGN_REQ, (void *) (int) TEI_FIXED);
-#else
+ case (MDL_ASSIGN | INDICATION):
FsmEvent(&st->ma.tei_m, EV_IDREQ, arg);
-#endif
break;
- case (MDL_ERROR_REQ):
+ case (MDL_ERROR | REQUEST):
FsmEvent(&st->ma.tei_m, EV_VERIFY, arg);
break;
default:
@@ -412,14 +423,14 @@ tei_l2tei(struct PStack *st, int pr, void *arg)
}
static void
-tei_debug(struct FsmInst *fi, char *s)
+tei_debug(struct FsmInst *fi, char *fmt, ...)
{
+ va_list args;
struct PStack *st = fi->userdata;
- char tm[32], str[256];
- jiftime(tm, jiffies);
- sprintf(str, "%s Tei %s\n", tm, s);
- HiSax_putstatus(st->l1.hardware, str);
+ va_start(args, fmt);
+ VHiSax_putstatus(st->l1.hardware, "tei ", fmt, args);
+ va_end(args);
}
void
@@ -439,9 +450,8 @@ setstack_tei(struct PStack *st)
}
void
-init_tei(struct IsdnCardState *sp, int protocol)
+init_tei(struct IsdnCardState *cs, int protocol)
{
-
}
void
diff --git a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c
index f7e38253b..180eee6a1 100644
--- a/drivers/isdn/hisax/teleint.c
+++ b/drivers/isdn/hisax/teleint.c
@@ -1,11 +1,17 @@
-/* $Id: teleint.c,v 1.5 1998/02/02 13:40:47 keil Exp $
+/* $Id: teleint.c,v 1.7 1998/11/15 23:55:26 keil Exp $
* teleint.c low level stuff for TeleInt isdn cards
*
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
*
*
* $Log: teleint.c,v $
+ * Revision 1.7 1998/11/15 23:55:26 keil
+ * changes from 2.0
+ *
+ * Revision 1.6 1998/04/15 16:45:31 keil
+ * new init code
+ *
* Revision 1.5 1998/02/02 13:40:47 keil
* fast io
*
@@ -32,7 +38,7 @@
extern const char *CardType[];
-const char *TeleInt_revision = "$Revision: 1.5 $";
+const char *TeleInt_revision = "$Revision: 1.7 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -64,17 +70,20 @@ static inline void
readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
{
register u_char ret;
- int max_delay = 2000;
+ register int max_delay = 20000;
+ register int i;
+
byteout(ale, off);
-
- ret = HFC_BUSY & bytein(ale);
- while (ret && --max_delay)
+ for (i = 0; i<size; i++) {
ret = HFC_BUSY & bytein(ale);
- if (!max_delay) {
- printk(KERN_WARNING "TeleInt Busy not inaktive\n");
- return;
+ while (ret && --max_delay)
+ ret = HFC_BUSY & bytein(ale);
+ if (!max_delay) {
+ printk(KERN_WARNING "TeleInt Busy not inaktive\n");
+ return;
+ }
+ data[i] = bytein(adr);
}
- insb(adr, data, size);
}
@@ -104,18 +113,21 @@ static inline void
writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
{
register u_char ret;
- int max_delay = 2000;
-
+ register int max_delay = 20000;
+ register int i;
+
/* fifo write without cli because it's allready done */
byteout(ale, off);
- ret = HFC_BUSY & bytein(ale);
- while (ret && --max_delay)
+ for (i = 0; i<size; i++) {
ret = HFC_BUSY & bytein(ale);
- if (!max_delay) {
- printk(KERN_WARNING "TeleInt Busy not inaktive\n");
- return;
+ while (ret && --max_delay)
+ ret = HFC_BUSY & bytein(ale);
+ if (!max_delay) {
+ printk(KERN_WARNING "TeleInt Busy not inaktive\n");
+ return;
+ }
+ byteout(adr, data[i]);
}
- outsb(adr, data, size);
}
/* Interface functions */
@@ -157,11 +169,8 @@ ReadHFC(struct IsdnCardState *cs, int data, u_char reg)
cs->hw.hfc.cip = reg;
byteout(cs->hw.hfc.addr | 1, reg);
ret = bytein(cs->hw.hfc.addr);
- if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2)) {
- char tmp[32];
- sprintf(tmp, "hfc RD %02x %02x", reg, ret);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2))
+ debugl1(cs, "hfc RD %02x %02x", reg, ret);
} else
ret = bytein(cs->hw.hfc.addr | 1);
return (ret);
@@ -174,11 +183,8 @@ WriteHFC(struct IsdnCardState *cs, int data, u_char reg, u_char value)
cs->hw.hfc.cip = reg;
if (data)
byteout(cs->hw.hfc.addr, value);
- if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2)) {
- char tmp[32];
- sprintf(tmp, "hfc W%c %02x %02x", data ? 'D' : 'C', reg, value);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2))
+ debugl1(cs, "hfc W%c %02x %02x", data ? 'D' : 'C', reg, value);
}
static void
@@ -271,6 +277,9 @@ TeleInt_card_msg(struct IsdnCardState *cs, int mt, void *arg)
inithfc(cs);
clear_pending_isac_ints(cs);
initisac(cs);
+ /* Reenable all IRQ */
+ cs->writeisac(cs, ISAC_MASK, 0);
+ cs->writeisac(cs, ISAC_CMDR, 0x41);
cs->hw.hfc.timer.expires = jiffies + 1;
add_timer(&cs->hw.hfc.timer);
return(0);
diff --git a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c
index 7cd173154..3137a8b7e 100644
--- a/drivers/isdn/hisax/teles0.c
+++ b/drivers/isdn/hisax/teles0.c
@@ -1,4 +1,4 @@
-/* $Id: teles0.c,v 2.6 1998/02/03 23:27:47 keil Exp $
+/* $Id: teles0.c,v 2.8 1998/04/15 16:44:28 keil Exp $
* teles0.c low level stuff for Teles Memory IO isdn cards
* based on the teles driver from Jan den Ouden
@@ -10,6 +10,12 @@
* Beat Doebeli
*
* $Log: teles0.c,v $
+ * Revision 2.8 1998/04/15 16:44:28 keil
+ * new init code
+ *
+ * Revision 2.7 1998/03/07 22:57:08 tsbogend
+ * made HiSax working on Linux/Alpha
+ *
* Revision 2.6 1998/02/03 23:27:47 keil
* IRQ 9
*
@@ -48,7 +54,7 @@
extern const char *CardType[];
-const char *teles0_revision = "$Revision: 2.6 $";
+const char *teles0_revision = "$Revision: 2.8 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -62,7 +68,7 @@ readisac(unsigned int adr, u_char off)
static inline void
writeisac(unsigned int adr, u_char off, u_char data)
{
- writeb(data, adr + ((off & 1) ? 0x2ff : 0x100) + off);
+ writeb(data, adr + ((off & 1) ? 0x2ff : 0x100) + off); mb();
}
@@ -77,14 +83,14 @@ static inline void
writehscx(unsigned int adr, int hscx, u_char off, u_char data)
{
writeb(data, adr + (hscx ? 0x1c0 : 0x180) +
- ((off & 1) ? 0x1ff : 0) + off);
+ ((off & 1) ? 0x1ff : 0) + off); mb();
}
static inline void
read_fifo_isac(unsigned int adr, u_char * data, int size)
{
register int i;
- register u_char *ad = (u_char *) (adr + 0x100);
+ register u_char *ad = (u_char *) ((long)adr + 0x100);
for (i = 0; i < size; i++)
data[i] = readb(ad);
}
@@ -93,16 +99,17 @@ static inline void
write_fifo_isac(unsigned int adr, u_char * data, int size)
{
register int i;
- register u_char *ad = (u_char *) (adr + 0x100);
- for (i = 0; i < size; i++)
- writeb(data[i], ad);
+ register u_char *ad = (u_char *) ((long)adr + 0x100);
+ for (i = 0; i < size; i++) {
+ writeb(data[i], ad); mb();
+ }
}
static inline void
read_fifo_hscx(unsigned int adr, int hscx, u_char * data, int size)
{
register int i;
- register u_char *ad = (u_char *) (adr + (hscx ? 0x1c0 : 0x180));
+ register u_char *ad = (u_char *) ((long)adr + (hscx ? 0x1c0 : 0x180));
for (i = 0; i < size; i++)
data[i] = readb(ad);
}
@@ -111,9 +118,10 @@ static inline void
write_fifo_hscx(unsigned int adr, int hscx, u_char * data, int size)
{
int i;
- register u_char *ad = (u_char *) (adr + (hscx ? 0x1c0 : 0x180));
- for (i = 0; i < size; i++)
- writeb(data[i], ad);
+ register u_char *ad = (u_char *) ((long)adr + (hscx ? 0x1c0 : 0x180));
+ for (i = 0; i < size; i++) {
+ writeb(data[i], ad); mb();
+ }
}
/* Interface functions */
@@ -264,9 +272,9 @@ reset_teles0(struct IsdnCardState *cs)
byteout(cs->hw.teles0.cfg_reg + 4, cfval | 1);
HZDELAY(HZ / 10 + 1);
}
- writeb(0, cs->hw.teles0.membase + 0x80);
+ writeb(0, cs->hw.teles0.membase + 0x80); mb();
HZDELAY(HZ / 5 + 1);
- writeb(1, cs->hw.teles0.membase + 0x80);
+ writeb(1, cs->hw.teles0.membase + 0x80); mb();
HZDELAY(HZ / 5 + 1);
restore_flags(flags);
return(0);
@@ -286,10 +294,7 @@ Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(request_irq(cs->irq, &teles0_interrupt,
I4L_IRQ_FLAG, "HiSax", cs));
case CARD_INIT:
- clear_pending_isac_ints(cs);
- clear_pending_hscx_ints(cs);
- initisac(cs);
- inithscx(cs);
+ inithscxisac(cs, 3);
return(0);
case CARD_TEST:
return(0);
diff --git a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c
index 871b10e4a..297ccb740 100644
--- a/drivers/isdn/hisax/teles3.c
+++ b/drivers/isdn/hisax/teles3.c
@@ -1,4 +1,4 @@
-/* $Id: teles3.c,v 2.7 1998/02/02 13:29:48 keil Exp $
+/* $Id: teles3.c,v 2.10 1999/02/15 14:37:15 cpetig Exp $
* teles3.c low level stuff for Teles 16.3 & PNP isdn cards
*
@@ -11,6 +11,15 @@
* Beat Doebeli
*
* $Log: teles3.c,v $
+ * Revision 2.10 1999/02/15 14:37:15 cpetig
+ * oops, missed something in last commit
+ *
+ * Revision 2.9 1999/02/15 14:11:02 cpetig
+ * fixed a bug with Teles PCMCIA, it doesn't have a config register
+ *
+ * Revision 2.8 1998/04/15 16:44:30 keil
+ * new init code
+ *
* Revision 2.7 1998/02/02 13:29:48 keil
* fast io
*
@@ -69,7 +78,7 @@
#include "isdnl1.h"
extern const char *CardType[];
-const char *teles3_revision = "$Revision: 2.7 $";
+const char *teles3_revision = "$Revision: 2.10 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -214,15 +223,14 @@ void
release_io_teles3(struct IsdnCardState *cs)
{
if (cs->typ == ISDN_CTYPE_TELESPCMCIA)
- release_region(cs->hw.teles3.cfg_reg, 97);
+ release_region(cs->hw.teles3.hscx[0], 97);
else {
- if (cs->hw.teles3.cfg_reg) {
+ if (cs->hw.teles3.cfg_reg)
if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
release_region(cs->hw.teles3.cfg_reg, 1);
} else {
release_region(cs->hw.teles3.cfg_reg, 8);
}
- }
release_ioregs(cs, 0x7);
}
}
@@ -305,10 +313,7 @@ Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(request_irq(cs->irq, &teles3_interrupt,
I4L_IRQ_FLAG, "HiSax", cs));
case CARD_INIT:
- clear_pending_isac_ints(cs);
- clear_pending_hscx_ints(cs);
- initisac(cs);
- inithscx(cs);
+ inithscxisac(cs, 3);
return(0);
case CARD_TEST:
return(0);
@@ -342,7 +347,7 @@ setup_teles3(struct IsdnCard *card))
cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20;
cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820;
} else if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
- cs->hw.teles3.cfg_reg = card->para[1];
+ cs->hw.teles3.cfg_reg = 0;
cs->hw.teles3.hscx[0] = card->para[1] - 0x20;
cs->hw.teles3.hscx[1] = card->para[1];
cs->hw.teles3.isac = card->para[1] + 0x20;
@@ -362,12 +367,12 @@ setup_teles3(struct IsdnCard *card))
cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
- if (check_region((cs->hw.teles3.cfg_reg), 97)) {
+ if (check_region((cs->hw.teles3.hscx[0]), 97)) {
printk(KERN_WARNING
"HiSax: %s ports %x-%x already in use\n",
CardType[cs->typ],
- cs->hw.teles3.cfg_reg,
- cs->hw.teles3.cfg_reg + 96);
+ cs->hw.teles3.hscx[0],
+ cs->hw.teles3.hscx[0] + 96);
return (0);
} else
request_region(cs->hw.teles3.hscx[0], 97, "HiSax Teles PCMCIA");
@@ -400,13 +405,12 @@ setup_teles3(struct IsdnCard *card))
CardType[cs->typ],
cs->hw.teles3.isac + 32,
cs->hw.teles3.isac + 64);
- if (cs->hw.teles3.cfg_reg) {
+ if (cs->hw.teles3.cfg_reg)
if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
release_region(cs->hw.teles3.cfg_reg, 1);
} else {
release_region(cs->hw.teles3.cfg_reg, 8);
}
- }
return (0);
} else
request_region(cs->hw.teles3.isac + 32, 32, "HiSax isac");
@@ -416,13 +420,12 @@ setup_teles3(struct IsdnCard *card))
CardType[cs->typ],
cs->hw.teles3.hscx[0] + 32,
cs->hw.teles3.hscx[0] + 64);
- if (cs->hw.teles3.cfg_reg) {
+ if (cs->hw.teles3.cfg_reg)
if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
release_region(cs->hw.teles3.cfg_reg, 1);
} else {
release_region(cs->hw.teles3.cfg_reg, 8);
}
- }
release_ioregs(cs, 1);
return (0);
} else
@@ -433,13 +436,12 @@ setup_teles3(struct IsdnCard *card))
CardType[cs->typ],
cs->hw.teles3.hscx[1] + 32,
cs->hw.teles3.hscx[1] + 64);
- if (cs->hw.teles3.cfg_reg) {
+ if (cs->hw.teles3.cfg_reg)
if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
release_region(cs->hw.teles3.cfg_reg, 1);
} else {
release_region(cs->hw.teles3.cfg_reg, 8);
}
- }
release_ioregs(cs, 3);
return (0);
} else
diff --git a/drivers/isdn/hisax/teles3c.c b/drivers/isdn/hisax/teles3c.c
index 3042f7139..8ba6a311a 100644
--- a/drivers/isdn/hisax/teles3c.c
+++ b/drivers/isdn/hisax/teles3c.c
@@ -1,11 +1,14 @@
-/* $Id: teles3c.c,v 1.2 1998/02/02 13:27:07 keil Exp $
+/* $Id: teles3c.c,v 1.3 1998/11/15 23:55:27 keil Exp $
* teles3c.c low level stuff for teles 16.3c
*
- * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author Karsten Keil (keil@isdn4linux.de)
*
*
* $Log: teles3c.c,v $
+ * Revision 1.3 1998/11/15 23:55:27 keil
+ * changes from 2.0
+ *
* Revision 1.2 1998/02/02 13:27:07 keil
* New
*
@@ -20,14 +23,13 @@
extern const char *CardType[];
-const char *teles163c_revision = "$Revision: 1.2 $";
+const char *teles163c_revision = "$Revision: 1.3 $";
static void
t163c_interrupt(int intno, void *dev_id, struct pt_regs *regs)
{
struct IsdnCardState *cs = dev_id;
u_char val, stat;
- char tmp[32];
if (!cs) {
printk(KERN_WARNING "teles3c: Spurious interrupt!\n");
@@ -36,16 +38,12 @@ t163c_interrupt(int intno, void *dev_id, struct pt_regs *regs)
if ((HFCD_ANYINT | HFCD_BUSY_NBUSY) &
(stat = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_STAT))) {
val = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_INT_S1);
- if (cs->debug & L1_DEB_ISAC) {
- sprintf(tmp, "teles3c: stat(%02x) s1(%02x)", stat, val);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "teles3c: stat(%02x) s1(%02x)", stat, val);
hfc2bds0_interrupt(cs, val);
} else {
- if (cs->debug & L1_DEB_ISAC) {
- sprintf(tmp, "teles3c: irq_no_irq stat(%02x)", stat);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "teles3c: irq_no_irq stat(%02x)", stat);
}
}
@@ -110,13 +108,9 @@ static int
t163c_card_msg(struct IsdnCardState *cs, int mt, void *arg)
{
long flags;
- char tmp[32];
- if (cs->debug & L1_DEB_ISAC) {
-
- sprintf(tmp, "teles3c: card_msg %x", mt);
- debugl1(cs, tmp);
- }
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "teles3c: card_msg %x", mt);
switch (mt) {
case CARD_RESET:
reset_t163c(cs);
diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c
index fe5737344..d08730e17 100644
--- a/drivers/isdn/icn/icn.c
+++ b/drivers/isdn/icn/icn.c
@@ -1,4 +1,4 @@
-/* $Id: icn.c,v 1.49 1998/02/13 11:14:15 keil Exp $
+/* $Id: icn.c,v 1.56 1999/04/12 13:15:07 fritz Exp $
* ISDN low-level module for the ICN active ISDN-Card.
*
@@ -19,6 +19,30 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: icn.c,v $
+ * Revision 1.56 1999/04/12 13:15:07 fritz
+ * Fixed a cast.
+ *
+ * Revision 1.55 1999/04/12 12:34:02 fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.54 1999/01/05 18:29:39 he
+ * merged remaining schedule_timeout() changes from 2.1.127
+ *
+ * Revision 1.53 1998/06/17 19:51:28 he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.52 1998/05/20 19:29:58 tsbogend
+ * fixed bug introduced by changes for new BSENT callback
+ *
+ * Revision 1.51 1998/03/07 22:29:55 fritz
+ * Adapted Detlef's chenges for 2.1.
+ *
+ * Revision 1.50 1998/03/07 17:41:54 detabc
+ * add d-channel connect and disconnect support statcallback
+ * from icn low-level to link->level
+ *
* Revision 1.49 1998/02/13 11:14:15 keil
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
@@ -209,7 +233,7 @@
#undef MAP_DEBUG
static char
-*revision = "$Revision: 1.49 $";
+*revision = "$Revision: 1.56 $";
static int icn_addcard(int, char *, char *);
@@ -232,10 +256,10 @@ icn_free_queue(icn_card * card, int channel)
cli();
card->xlen[channel] = 0;
card->sndcount[channel] = 0;
- if (card->xskb[channel]) {
+ if ((skb = card->xskb[channel])) {
card->xskb[channel] = NULL;
restore_flags(flags);
- dev_kfree_skb(card->xskb[channel]);
+ dev_kfree_skb(skb);
} else
restore_flags(flags);
}
@@ -529,6 +553,11 @@ icn_pollbchan_send(int channel, icn_card * card)
cmd.parm.length = card->xlen[channel];
card->interface.statcallb(&cmd);
}
+ } else {
+ save_flags(flags);
+ cli();
+ card->xskb[channel] = skb;
+ restore_flags(flags);
}
card->xmit_lock[channel] = 0;
if (!icn_trymaplock_channel(card, mch))
@@ -580,8 +609,11 @@ static icn_stat icn_stat_table[] =
{
{"BCON_", ISDN_STAT_BCONN, 1}, /* B-Channel connected */
{"BDIS_", ISDN_STAT_BHUP, 2}, /* B-Channel disconnected */
- {"DCON_", ISDN_STAT_DCONN, 0}, /* D-Channel connected */
- {"DDIS_", ISDN_STAT_DHUP, 0}, /* D-Channel disconnected */
+ /*
+ ** add d-channel connect and disconnect support to link-level
+ */
+ {"DCON_", ISDN_STAT_DCONN, 10}, /* D-Channel connected */
+ {"DDIS_", ISDN_STAT_DHUP, 11}, /* D-Channel disconnected */
{"DCAL_I", ISDN_STAT_ICALL, 3}, /* Incoming call dialup-line */
{"DSCA_I", ISDN_STAT_ICALL, 3}, /* Incoming call 1TR6-SPV */
{"FCALL", ISDN_STAT_ICALL, 4}, /* Leased line connection up */
@@ -630,7 +662,33 @@ icn_parse_status(u_char * status, int channel, icn_card * card)
cmd.driver = card->myid;
cmd.arg = channel;
switch (action) {
+ case 11:
+ save_flags(flags);
+ cli();
+ icn_free_queue(card,channel);
+ card->rcvidx[channel] = 0;
+
+ if (card->flags &
+ ((channel)?ICN_FLAGS_B2ACTIVE:ICN_FLAGS_B1ACTIVE)) {
+
+ isdn_ctrl ncmd;
+
+ card->flags &= ~((channel)?
+ ICN_FLAGS_B2ACTIVE:ICN_FLAGS_B1ACTIVE);
+
+ memset(&ncmd, 0, sizeof(ncmd));
+
+ ncmd.driver = card->myid;
+ ncmd.arg = channel;
+ ncmd.command = ISDN_STAT_BHUP;
+ restore_flags(flags);
+ card->interface.statcallb(&cmd);
+ } else
+ restore_flags(flags);
+
+ break;
case 1:
+ icn_free_queue(card,channel);
card->flags |= (channel) ?
ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE;
break;
@@ -1539,7 +1597,7 @@ icn_command(isdn_ctrl * c, icn_card * card)
c->parm.num[0] ? "N" : "ALL", c->parm.num);
} else
sprintf(cbuf, "%02d;EAZ%s\n", (int) a,
- c->parm.num[0] ? c->parm.num : "0123456789");
+ c->parm.num[0] ? (char *)(c->parm.num) : "0123456789");
i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
}
break;
diff --git a/drivers/isdn/icn/icn.h b/drivers/isdn/icn/icn.h
index 4aba68b38..3bd2819ce 100644
--- a/drivers/isdn/icn/icn.h
+++ b/drivers/isdn/icn/icn.h
@@ -318,9 +318,9 @@ static char *icn_id2 = "\0";
#ifdef MODULE
MODULE_AUTHOR("Fritz Elfert");
MODULE_PARM(portbase, "i");
-MODULE_PARM_DESC(portbase, "Port address of first card");
+MODULE_PARM_DESC(portbase, "Port adress of first card");
MODULE_PARM(membase, "i");
-MODULE_PARM_DESC(membase, "Shared memory address of all cards");
+MODULE_PARM_DESC(membase, "Shared memory adress of all cards");
MODULE_PARM(icn_id, "s");
MODULE_PARM_DESC(icn_id, "ID-String of first card");
MODULE_PARM(icn_id2, "s");
diff --git a/drivers/isdn/isdn_audio.c b/drivers/isdn/isdn_audio.c
index d097366ed..67307a0ec 100644
--- a/drivers/isdn/isdn_audio.c
+++ b/drivers/isdn/isdn_audio.c
@@ -1,9 +1,10 @@
-/* $Id: isdn_audio.c,v 1.10 1998/02/20 17:09:40 fritz Exp $
+/* $Id: isdn_audio.c,v 1.13 1999/04/12 12:33:09 fritz Exp $
* Linux ISDN subsystem, audio conversion and compression (linklevel).
*
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
* DTMF code (c) 1996 by Christian Mock (cm@kukuruz.ping.at)
+ * Silence detection (c) 1998 by Armin Schindler (mac@gismo.telekom.de)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,6 +21,15 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_audio.c,v $
+ * Revision 1.13 1999/04/12 12:33:09 fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.12 1998/07/26 18:48:43 armin
+ * Added silence detection in voice receive mode.
+ *
+ * Revision 1.11 1998/04/10 10:35:10 paul
+ * fixed (silly?) warnings from egcs on Alpha.
+ *
* Revision 1.10 1998/02/20 17:09:40 fritz
* Changes for recent kernels.
*
@@ -61,7 +71,7 @@
#include "isdn_audio.h"
#include "isdn_common.h"
-char *isdn_audio_revision = "$Revision: 1.10 $";
+char *isdn_audio_revision = "$Revision: 1.13 $";
/*
* Misc. lookup-tables.
@@ -276,7 +286,7 @@ static inline void
isdn_audio_tlookup(const char *table, char *buff, unsigned long n)
{
while (n--)
- *buff++ = table[*buff];
+ *buff++ = table[*(unsigned char *)buff];
}
#endif
@@ -660,3 +670,92 @@ isdn_audio_calc_dtmf(modem_info * info, unsigned char *buf, int len, int fmt)
len -= c;
}
}
+
+silence_state *
+isdn_audio_silence_init(silence_state * s)
+{
+ if (!s)
+ s = (silence_state *) kmalloc(sizeof(silence_state), GFP_ATOMIC);
+ if (s) {
+ s->idx = 0;
+ s->state = 0;
+ }
+ return s;
+}
+
+void
+isdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt)
+{
+ silence_state *s = info->silence_state;
+ int i;
+ signed char c;
+
+ if (!info->emu.vpar[1]) return;
+
+ for (i = 0; i < len; i++) {
+ if (fmt)
+ c = isdn_audio_alaw_to_ulaw[*buf++];
+ else
+ c = *buf++;
+
+ if (c > 0) c -= 128;
+ c = abs(c);
+
+ if (c > (info->emu.vpar[1] * 4)) {
+ s->idx = 0;
+ s->state = 1;
+ } else {
+ if (s->idx < 210000) s->idx++;
+ }
+ }
+}
+
+void
+isdn_audio_eval_silence(modem_info * info)
+{
+ silence_state *s = info->silence_state;
+ struct sk_buff *skb;
+ unsigned long flags;
+ int di;
+ int ch;
+ char what;
+ char *p;
+
+ what = ' ';
+
+ if (s->idx > (info->emu.vpar[2] * 800)) {
+ s->idx = 0;
+ if (!s->state) { /* silence from beginning of rec */
+ what = 's';
+ } else {
+ what = 'q';
+ }
+ }
+ if ((what == 's') || (what == 'q')) {
+ printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
+ (what=='s') ? "silence":"quiet");
+ skb = dev_alloc_skb(2);
+ p = (char *) skb_put(skb, 2);
+ p[0] = 0x10;
+ p[1] = what;
+ if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {
+ printk(KERN_WARNING
+ "isdn_audio: insufficient skb_headroom, dropping\n");
+ kfree_skb(skb);
+ return;
+ }
+ ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
+ ISDN_AUDIO_SKB_LOCK(skb) = 0;
+ save_flags(flags);
+ cli();
+ di = info->isdn_driver;
+ ch = info->isdn_channel;
+ __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
+ dev->drv[di]->rcvcount[ch] += 2;
+ restore_flags(flags);
+ /* Schedule dequeuing */
+ if ((dev->modempoll) && (info->rcvsched))
+ isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
+ wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
+ }
+}
diff --git a/drivers/isdn/isdn_audio.h b/drivers/isdn/isdn_audio.h
index 0cf8267cf..ee33ce020 100644
--- a/drivers/isdn/isdn_audio.h
+++ b/drivers/isdn/isdn_audio.h
@@ -1,8 +1,8 @@
-/* $Id: isdn_audio.h,v 1.5 1997/02/03 22:45:21 fritz Exp $
+/* $Id: isdn_audio.h,v 1.7 1999/04/12 12:33:11 fritz Exp $
* Linux ISDN subsystem, audio conversion and compression (linklevel).
*
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,12 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_audio.h,v $
+ * Revision 1.7 1999/04/12 12:33:11 fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.6 1998/07/26 18:48:44 armin
+ * Added silence detection in voice receive mode.
+ *
* Revision 1.5 1997/02/03 22:45:21 fritz
* Reformatted according CodingStyle
*
@@ -51,6 +57,11 @@ typedef struct dtmf_state {
int buf[DTMF_NPOINTS];
} dtmf_state;
+typedef struct silence_state {
+ int state;
+ unsigned int idx;
+} silence_state;
+
extern void isdn_audio_ulaw2alaw(unsigned char *, unsigned long);
extern void isdn_audio_alaw2ulaw(unsigned char *, unsigned long);
extern adpcm_state *isdn_audio_adpcm_init(adpcm_state *, int);
@@ -60,3 +71,6 @@ extern int isdn_audio_2adpcm_flush(adpcm_state * s, unsigned char *out);
extern void isdn_audio_calc_dtmf(modem_info *, unsigned char *, int, int);
extern void isdn_audio_eval_dtmf(modem_info *);
dtmf_state *isdn_audio_dtmf_init(dtmf_state *);
+extern void isdn_audio_calc_silence(modem_info *, unsigned char *, int, int);
+extern void isdn_audio_eval_silence(modem_info *);
+silence_state *isdn_audio_silence_init(silence_state *);
diff --git a/drivers/isdn/isdn_cards.c b/drivers/isdn/isdn_cards.c
index 30a4a7703..06fa3e7d7 100644
--- a/drivers/isdn/isdn_cards.c
+++ b/drivers/isdn/isdn_cards.c
@@ -1,8 +1,8 @@
-/* $Id: isdn_cards.c,v 1.7 1998/02/20 17:24:28 fritz Exp $
+/* $Id: isdn_cards.c,v 1.9 1999/04/12 12:33:11 fritz Exp $
* Linux ISDN subsystem, initialization for non-modularized drivers.
*
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,12 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_cards.c,v $
+ * Revision 1.9 1999/04/12 12:33:11 fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.8 1999/03/29 11:13:23 armin
+ * Added eicon driver init.
+ *
* Revision 1.7 1998/02/20 17:24:28 fritz
* Added ACT2000 init.
*
@@ -56,6 +62,10 @@ extern void HiSax_init(void);
extern void pcbit_init(void);
#endif
+#ifdef CONFIG_ISDN_DRV_EICON
+extern void eicon_init(void);
+#endif
+
#ifdef CONFIG_ISDN_DRV_AVMB1
extern void avmb1_init(void);
extern void capi_init(void);
@@ -88,4 +98,7 @@ isdn_cards_init(void)
#if CONFIG_ISDN_DRV_ACT2000
act2000_init();
#endif
+#if CONFIG_ISDN_DRV_EICON
+ eicon_init();
+#endif
}
diff --git a/drivers/isdn/isdn_cards.h b/drivers/isdn/isdn_cards.h
index e6e2aa127..78173e747 100644
--- a/drivers/isdn/isdn_cards.h
+++ b/drivers/isdn/isdn_cards.h
@@ -1,8 +1,8 @@
-/* $Id: isdn_cards.h,v 1.2 1997/02/03 23:31:55 fritz Exp $
+/* $Id: isdn_cards.h,v 1.3 1999/04/12 12:33:13 fritz Exp $
* Linux ISDN subsystem, initialization for non-modularized drivers.
*
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_cards.h,v $
+ * Revision 1.3 1999/04/12 12:33:13 fritz
+ * Changes from 2.0 tree.
+ *
* Revision 1.2 1997/02/03 23:31:55 fritz
* Reformatted according CodingStyle
*
diff --git a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c
index 92e2ee544..779a327fa 100644
--- a/drivers/isdn/isdn_common.c
+++ b/drivers/isdn/isdn_common.c
@@ -1,8 +1,8 @@
-/* $Id: isdn_common.c,v 1.55 1998/02/23 23:35:32 fritz Exp $
+/* $Id: isdn_common.c,v 1.75 1999/04/18 14:06:47 fritz Exp $
* Linux ISDN subsystem, common used functions (linklevel).
*
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
* Copyright 1995,96 Thinking Objects Software GmbH Wuerzburg
* Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
*
@@ -20,11 +20,85 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Note: This file differs from the corresponding revision as present in the
- * isdn4linux CVS repository because some later bug fixes have been extracted
- * from the repository and merged into this file. -- Henner Eisen
- *
* $Log: isdn_common.c,v $
+ * Revision 1.75 1999/04/18 14:06:47 fritz
+ * Removed TIMRU stuff.
+ *
+ * Revision 1.74 1999/04/12 13:16:45 fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.73 1999/04/12 12:33:15 fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.72 1999/03/02 12:04:44 armin
+ * -added ISDN_STAT_ADDCH to increase supported channels after
+ * register_isdn().
+ * -ttyI now goes on-hook on ATZ when B-Ch is connected.
+ * -added timer-function for register S7 (Wait for Carrier).
+ * -analog modem (ISDN_PROTO_L2_MODEM) implementations.
+ * -on L2_MODEM a string will be appended to the CONNECT-Message,
+ * which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN.
+ * -variable "dialing" used for ATA also, for interrupting call
+ * establishment and register S7.
+ *
+ * Revision 1.71 1999/01/28 09:10:43 armin
+ * Fixed bad while-loop in isdn_readbch().
+ *
+ * Revision 1.70 1999/01/15 19:58:54 he
+ * removed compatibiltity macro
+ *
+ * Revision 1.69 1998/09/07 21:59:58 he
+ * flush method for 2.1.118 and above
+ * updated IIOCTLNETGPN
+ *
+ * Revision 1.68 1998/08/31 21:09:45 he
+ * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface'
+ * peer phone number)
+ *
+ * Revision 1.67 1998/06/26 15:12:21 fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 1.66 1998/06/17 19:50:41 he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.65 1998/06/07 00:20:00 fritz
+ * abc cleanup.
+ *
+ * Revision 1.64 1998/06/02 12:10:03 detabc
+ * wegen einer einstweiliger verfuegung gegen DW ist zur zeit
+ * die abc-extension bis zur klaerung der rechtslage nicht verfuegbar
+ *
+ * Revision 1.63 1998/05/03 17:40:38 detabc
+ * Include abc-extension-support for >= 2.1.x Kernels in
+ * isdn_net.c and isdn_common.c. alpha-test OK and running !
+ *
+ * Revision 1.62 1998/04/14 16:28:43 he
+ * Fixed user space access with interrupts off and remaining
+ * copy_{to,from}_user() -> -EFAULT return codes
+ *
+ * Revision 1.61 1998/03/22 18:50:46 hipp
+ * Added BSD Compression for syncPPP .. UNTESTED at the moment
+ *
+ * Revision 1.60 1998/03/19 13:18:18 keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
+ * Revision 1.59 1998/03/09 17:46:23 he
+ * merged in 2.1.89 changes
+ *
+ * Revision 1.58 1998/03/07 22:35:24 fritz
+ * Starting generic module support (Nothing usable yet).
+ *
+ * Revision 1.57 1998/03/07 18:21:01 cal
+ * Dynamic Timeout-Rule-Handling vs. 971110 included
+ *
+ * Revision 1.56 1998/02/25 17:49:38 he
+ * Changed return codes caused be failing copy_{to,from}_user to -EFAULT
+ *
* Revision 1.55 1998/02/23 23:35:32 fritz
* Eliminated some compiler warnings.
*
@@ -269,7 +343,7 @@
isdn_dev *dev = (isdn_dev *) 0;
-static char *isdn_revision = "$Revision: 1.55 $";
+static char *isdn_revision = "$Revision: 1.75 $";
extern char *isdn_net_revision;
extern char *isdn_tty_revision;
@@ -290,13 +364,36 @@ static int isdn_writebuf_stub(int, int, const u_char *, int, int);
void
isdn_MOD_INC_USE_COUNT(void)
{
+ int i;
+
MOD_INC_USE_COUNT;
+ for (i = 0; i < dev->drivers; i++) {
+ isdn_ctrl cmd;
+
+ cmd.driver = i;
+ cmd.arg = 0;
+ cmd.command = ISDN_CMD_LOCK;
+ isdn_command(&cmd);
+ dev->drv[i]->locks++;
+ }
}
void
isdn_MOD_DEC_USE_COUNT(void)
{
+ int i;
+
MOD_DEC_USE_COUNT;
+ for (i = 0; i < dev->drivers; i++)
+ if (dev->drv[i]->locks > 0) {
+ isdn_ctrl cmd;
+
+ cmd.driver = i;
+ cmd.arg = 0;
+ cmd.command = ISDN_CMD_UNLOCK;
+ isdn_command(&cmd);
+ dev->drv[i]->locks--;
+ }
}
#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
@@ -312,6 +409,82 @@ isdn_dumppkt(char *s, u_char * p, int len, int dumplen)
}
#endif
+/*
+ * I picked the pattern-matching-functions from an old GNU-tar version (1.10)
+ * It was originally written and put to PD by rs@mirror.TMC.COM (Rich Salz)
+ */
+static int
+isdn_star(char *s, char *p)
+{
+ while (isdn_wildmat(s, p)) {
+ if (*++s == '\0')
+ return (2);
+ }
+ return (0);
+}
+
+/*
+ * Shell-type Pattern-matching for incoming caller-Ids
+ * This function gets a string in s and checks, if it matches the pattern
+ * given in p.
+ *
+ * Return:
+ * 0 = match.
+ * 1 = no match.
+ * 2 = no match. Would eventually match, if s would be longer.
+ *
+ * Possible Patterns:
+ *
+ * '?' matches one character
+ * '*' matches zero or more characters
+ * [xyz] matches the set of characters in brackets.
+ * [^xyz] matches any single character not in the set of characters
+ */
+
+int
+isdn_wildmat(char *s, char *p)
+{
+ register int last;
+ register int matched;
+ register int reverse;
+ register int nostar = 1;
+
+ for (; *p; s++, p++)
+ switch (*p) {
+ case '\\':
+ /*
+ * Literal match with following character,
+ * fall through.
+ */
+ p++;
+ default:
+ if (*s != *p)
+ return (*s == '\0')?2:1;
+ continue;
+ case '?':
+ /* Match anything. */
+ if (*s == '\0')
+ return (2);
+ continue;
+ case '*':
+ nostar = 0;
+ /* Trailing star matches everything. */
+ return (*++p ? isdn_star(s, p) : 0);
+ case '[':
+ /* [^....] means inverse character class. */
+ if ((reverse = (p[1] == '^')))
+ p++;
+ for (last = 0, matched = 0; *++p && (*p != ']'); last = *p)
+ /* This next line requires a good C compiler. */
+ if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
+ matched = 1;
+ if (matched == reverse)
+ return (1);
+ continue;
+ }
+ return (*s == '\0')?0:nostar;
+}
+
static void
isdn_free_queue(struct sk_buff_head *queue)
{
@@ -345,7 +518,6 @@ static void
isdn_timer_funct(ulong dummy)
{
int tf = dev->tflags;
-
if (tf & ISDN_TIMER_FAST) {
if (tf & ISDN_TIMER_MODEMREAD)
isdn_tty_readmodem();
@@ -374,13 +546,16 @@ isdn_timer_funct(ulong dummy)
if (tf & ISDN_TIMER_KEEPALIVE)
isdn_net_slarp_out();
}
+ if (tf & ISDN_TIMER_CARRIER)
+ isdn_tty_carrier_timeout();
#if (defined CONFIG_ISDN_PPP) && (defined CONFIG_ISDN_MPP)
if (tf & ISDN_TIMER_IPPP)
isdn_ppp_timer_timeout();
#endif
}
}
- if (tf) {
+ if (tf)
+ {
int flags;
save_flags(flags);
@@ -506,6 +681,29 @@ isdn_all_eaz(int di, int ch)
isdn_command(&cmd);
}
+/*
+ * Begin of a CAPI like LL<->HL interface, currently used only for
+ * supplementary service (CAPI 2.0 part III)
+ */
+#include "avmb1/capicmd.h" /* this should be moved in a common place */
+
+int
+isdn_capi_rec_hl_msg(capi_msg *cm) {
+
+ int di;
+ int ch;
+
+ di = (cm->adr.Controller & 0x7f) -1;
+ ch = isdn_dc2minor(di, (cm->adr.Controller>>8)& 0x7f);
+ switch(cm->Command) {
+ case CAPI_FACILITY:
+ /* in the moment only handled in tty */
+ return(isdn_tty_capi_facility(cm));
+ default:
+ return(-1);
+ }
+}
+
static int
isdn_status_callback(isdn_ctrl * c)
{
@@ -540,13 +738,13 @@ isdn_status_callback(isdn_ctrl * c)
wake_up_interruptible(&dev->drv[di]->st_waitq);
break;
case ISDN_STAT_RUN:
- dev->drv[di]->running = 1;
+ dev->drv[di]->flags |= DRV_FLAG_RUNNING;
for (i = 0; i < ISDN_MAX_CHANNELS; i++)
if (dev->drvmap[i] == di)
isdn_all_eaz(di, dev->chanmap[i]);
break;
case ISDN_STAT_STOP:
- dev->drv[di]->running = 0;
+ dev->drv[di]->flags &= ~DRV_FLAG_RUNNING;
break;
case ISDN_STAT_ICALL:
if (i < 0)
@@ -562,19 +760,17 @@ isdn_status_callback(isdn_ctrl * c)
return 0;
}
/* Try to find a network-interface which will accept incoming call */
- cmd.driver = di;
- cmd.arg = c->arg;
- cmd.command = ISDN_CMD_LOCK;
- isdn_command(&cmd);
r = isdn_net_find_icall(di, c->arg, i, c->parm.setup);
switch (r) {
case 0:
/* No network-device replies.
- * Try ttyI's
+ * Try ttyI's.
+ * These return 0 on no match, 1 on match and
+ * 3 on eventually match, if CID is longer.
*/
- if (isdn_tty_find_icall(di, c->arg, c->parm.setup) >= 0)
- retval = 1;
- else if (dev->drv[di]->reject_bus) {
+ retval = isdn_tty_find_icall(di, c->arg, c->parm.setup);
+ if ((!retval) && (dev->drv[di]->flags & DRV_FLAG_REJBUS)) {
+ /* No tty responding */
cmd.driver = di;
cmd.arg = c->arg;
cmd.command = ISDN_CMD_HANGUP;
@@ -606,13 +802,14 @@ isdn_status_callback(isdn_ctrl * c)
/* ... then start callback. */
isdn_net_dial();
break;
+ case 5:
+ /* Number would eventually match, if longer */
+ retval = 3;
+ break;
}
- if (retval != 1) {
- cmd.driver = di;
- cmd.arg = c->arg;
- cmd.command = ISDN_CMD_UNLOCK;
- isdn_command(&cmd);
- }
+#ifdef ISDN_DEBUG_STATCALLB
+ printk(KERN_DEBUG "ICALL: ret=%d\n", retval);
+#endif
return retval;
break;
case ISDN_STAT_CINF:
@@ -664,7 +861,7 @@ isdn_status_callback(isdn_ctrl * c)
#endif
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
- dev->drv[di]->flags &= ~(1 << (c->arg));
+ dev->drv[di]->online &= ~(1 << (c->arg));
isdn_info_update();
/* Signal hangup to network-devices */
if (isdn_net_stat_callback(i, c))
@@ -682,7 +879,7 @@ isdn_status_callback(isdn_ctrl * c)
/* Signal B-channel-connect to network-devices */
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
- dev->drv[di]->flags |= (1 << (c->arg));
+ dev->drv[di]->online |= (1 << (c->arg));
isdn_info_update();
if (isdn_net_stat_callback(i, c))
break;
@@ -698,7 +895,7 @@ isdn_status_callback(isdn_ctrl * c)
#endif
if (dev->global_flags & ISDN_GLOBAL_STOPPED)
return 0;
- dev->drv[di]->flags &= ~(1 << (c->arg));
+ dev->drv[di]->online &= ~(1 << (c->arg));
isdn_info_update();
#ifdef CONFIG_ISDN_X25
/* Signal hangup to network-devices */
@@ -723,6 +920,9 @@ isdn_status_callback(isdn_ctrl * c)
break;
break;
case ISDN_STAT_ADDCH:
+ if (isdn_add_channels(dev->drv[di], di, c->arg, 1))
+ return -1;
+ isdn_info_update();
break;
case ISDN_STAT_UNLOAD:
save_flags(flags);
@@ -741,7 +941,9 @@ isdn_status_callback(isdn_ctrl * c)
isdn_free_queue(&dev->drv[di]->rpqueue[i]);
kfree(dev->drv[di]->rpqueue);
kfree(dev->drv[di]->rcv_waitq);
+#if LINUX_VERSION_CODE < 131841
kfree(dev->drv[di]->snd_waitq);
+#endif
kfree(dev->drv[di]);
dev->drv[di] = NULL;
dev->drvid[di][0] = '\0';
@@ -750,6 +952,8 @@ isdn_status_callback(isdn_ctrl * c)
return 0;
case ISDN_STAT_L1ERR:
break;
+ case CAPI_PUT_MESSAGE:
+ return(isdn_capi_rec_hl_msg(&c->parm.cmsg));
default:
return -1;
}
@@ -785,7 +989,11 @@ isdn_getnum(char **p)
* of the mapping (di,ch)<->minor, happen during the sleep? --he
*/
int
+#if LINUX_VERSION_CODE < 131841
isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, struct wait_queue **sleep)
+#else
+isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_queue_head_t *sleep)
+#endif
{
int left;
int count;
@@ -819,7 +1027,8 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, struct w
dflag = 0;
count_pull = count_put = 0;
- while ((count_pull < skb->len) && (left-- > 0)) {
+ while ((count_pull < skb->len) && (left > 0)) {
+ left--;
if (dev->drv[di]->DLEflag & DLEmask) {
*cp++ = DLE;
dev->drv[di]->DLEflag &= ~DLEmask;
@@ -894,8 +1103,6 @@ isdn_minor2chan(int minor)
return (dev->chanmap[minor]);
}
-#define INF_DV 0x01 /* Data version for /dev/isdninfo */
-
static char *
isdn_statstr(void)
{
@@ -931,7 +1138,7 @@ isdn_statstr(void)
p = istatbuf + strlen(istatbuf);
for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
if (dev->drv[i]) {
- sprintf(p, "%ld ", dev->drv[i]->flags);
+ sprintf(p, "%ld ", dev->drv[i]->online);
p = istatbuf + strlen(istatbuf);
} else {
sprintf(p, "? ");
@@ -997,7 +1204,7 @@ isdn_read(struct file *file, char *buf, size_t count, loff_t * off)
drvidx = isdn_minor2drv(minor);
if (drvidx < 0)
return -ENODEV;
- if (!dev->drv[drvidx]->running)
+ if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
return -ENODEV;
chidx = isdn_minor2chan(minor);
if( ! (p = kmalloc(count,GFP_KERNEL)) ) return -ENOMEM;
@@ -1067,7 +1274,7 @@ isdn_write(struct file *file, const char *buf, size_t count, loff_t * off)
drvidx = isdn_minor2drv(minor);
if (drvidx < 0)
return -ENODEV;
- if (!dev->drv[drvidx]->running)
+ if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
return -ENODEV;
chidx = isdn_minor2chan(minor);
while (isdn_writebuf_stub(drvidx, chidx, buf, count, 1) != count)
@@ -1081,7 +1288,7 @@ isdn_write(struct file *file, const char *buf, size_t count, loff_t * off)
/*
* We want to use the isdnctrl device to load the firmware
*
- if (!dev->drv[drvidx]->running)
+ if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
return -ENODEV;
*/
if (dev->drv[drvidx]->interface->writecmd)
@@ -1132,143 +1339,6 @@ isdn_poll(struct file *file, poll_table * wait)
return POLLERR;
}
-/*
- * This accesses user space with interrupts off, but is not needed by
- * any of the isdn4k-util programs anyway. Thus, in contrast to your
- * first impression after looking at the code, fixing is trival!*/
-#if 0
-static int
-isdn_set_allcfg(char *src)
-{
- int ret;
- int i;
- ulong flags;
- isdn_net_ioctl_cfg cfg;
- isdn_net_ioctl_phone phone;
-
- if ((ret = isdn_net_rmall()))
- return ret;
- if (copy_from_user((char *) &i, src, sizeof(int))) return -EFAULT;
- save_flags(flags);
- cli();
- src += sizeof(int);
- while (i) {
- int phone_len;
- int out_flag;
-
- if (copy_from_user((char *) &cfg, src, sizeof(cfg))) {
- restore_flags(flags);
- return -EFAULT;
- }
- src += sizeof(cfg);
- if (!isdn_net_new(cfg.name, NULL)) {
- restore_flags(flags);
- return -EIO;
- }
- if ((ret = isdn_net_setcfg(&cfg))) {
- restore_flags(flags);
- return ret;
- }
- phone_len = out_flag = 0;
- while (out_flag < 2) {
- if ((ret = verify_area(VERIFY_READ, src, 1))) {
- restore_flags(flags);
- return ret;
- }
- get_user(phone.phone[phone_len], src++);
- if ((phone.phone[phone_len] == ' ') ||
- (phone.phone[phone_len] == '\0')) {
- if (phone_len) {
- phone.phone[phone_len] = '\0';
- strcpy(phone.name, cfg.name);
- phone.outgoing = out_flag;
- if ((ret = isdn_net_addphone(&phone))) {
- restore_flags(flags);
- return ret;
- }
- } else
- out_flag++;
- phone_len = 0;
- }
- if (++phone_len >= sizeof(phone.phone))
- printk(KERN_WARNING
- "%s: IIOCSETSET phone number too long, ignored\n",
- cfg.name);
- }
- i--;
- }
- restore_flags(flags);
- return 0;
-}
-
-static int
-isdn_get_allcfg(char *dest)
-{
- isdn_net_ioctl_cfg cfg;
- isdn_net_ioctl_phone phone;
- isdn_net_dev *p;
- ulong flags;
- int ret;
-
- /* Walk through netdev-chain */
- save_flags(flags);
- cli();
- p = dev->netdev;
- while (p) {
- isdn_net_local *lp = p->local;
-
- if ((ret = verify_area(VERIFY_WRITE, (void *) dest, sizeof(cfg) + 200))) {
- restore_flags(flags);
- return ret;
- }
- strcpy(cfg.eaz, lp->msn);
- cfg.exclusive = lp->exclusive;
- if (lp->pre_device >= 0) {
- sprintf(cfg.drvid, "%s,%d", dev->drvid[lp->pre_device],
- lp->pre_channel);
- } else
- cfg.drvid[0] = '\0';
- cfg.onhtime = lp->onhtime;
- cfg.charge = lp->charge;
- cfg.l2_proto = lp->l2_proto;
- cfg.l3_proto = lp->l3_proto;
- cfg.p_encap = lp->p_encap;
- cfg.secure = (lp->flags & ISDN_NET_SECURE) ? 1 : 0;
- cfg.callback = (lp->flags & ISDN_NET_CALLBACK) ? 1 : 0;
- cfg.chargehup = (lp->hupflags & ISDN_CHARGEHUP) ? 1 : 0;
- cfg.ihup = (lp->hupflags & ISDN_INHUP) ? 1 : 0;
- cfg.chargeint = lp->chargeint;
- if (copy_to_user(dest, lp->name, 10)) {
- restore_flags(flags);
- return -EFAULT;
- }
- dest += 10;
- if (copy_to_user(dest, (char *) &cfg, sizeof(cfg))) {
- restore_flags(flags);
- return -EFAULT;
- }
- dest += sizeof(cfg);
- strcpy(phone.name, lp->name);
- phone.outgoing = 0;
- if ((ret = isdn_net_getphones(&phone, dest)) < 0) {
- restore_flags(flags);
- return ret;
- } else
- dest += ret;
- strcpy(phone.name, lp->name);
- phone.outgoing = 1;
- if ((ret = isdn_net_getphones(&phone, dest)) < 0) {
- restore_flags(flags);
- return ret;
- } else
- dest += ret;
- put_user(0, dest);
- p = p->next;
- }
- restore_flags(flags);
- return 0;
-}
-#endif
static int
isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
@@ -1316,6 +1386,17 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
} else
return -EINVAL;
break;
+#ifdef CONFIG_NETDEVICES
+ case IIOCNETGPN:
+ /* Get peer phone number of a connected
+ * isdn network interface */
+ if (arg) {
+ if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+ return -EFAULT;
+ return isdn_net_getpeer(&phone, (isdn_net_ioctl_phone *) arg);
+ } else
+ return -EINVAL;
+#endif
default:
return -EINVAL;
}
@@ -1327,7 +1408,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
if (drvidx < 0)
return -ENODEV;
chidx = isdn_minor2chan(minor);
- if (!dev->drv[drvidx]->running)
+ if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
return -ENODEV;
return 0;
}
@@ -1513,26 +1594,11 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
}
if (drvidx == -1)
return -ENODEV;
- dev->drv[drvidx]->reject_bus = iocts.arg;
- return 0;
-#if 0
- case IIOCGETSET:
- /* Get complete setup (all network-interfaces and profile-
- settings of all tty-devices */
- if (arg)
- return (isdn_get_allcfg((char *) arg));
+ if (iocts.arg)
+ dev->drv[drvidx]->flags |= DRV_FLAG_REJBUS;
else
- return -EINVAL;
- break;
- case IIOCSETSET:
- /* Set complete setup (all network-interfaces and profile-
- settings of all tty-devices */
- if (arg)
- return (isdn_set_allcfg((char *) arg));
- else
- return -EINVAL;
- break;
-#endif
+ dev->drv[drvidx]->flags &= ~DRV_FLAG_REJBUS;
+ return 0;
case IIOCSIGPRF:
dev->profd = current;
return 0;
@@ -1544,7 +1610,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
int i;
if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
- (ISDN_MODEM_ANZREG + ISDN_MSNLEN)
+ (ISDN_MODEM_ANZREG + ISDN_MSNLEN + ISDN_LMSNLEN)
* ISDN_MAX_CHANNELS)))
return ret;
@@ -1556,8 +1622,11 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
if (copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN))
return -EFAULT;
p += ISDN_MSNLEN;
+ if (copy_to_user(p, dev->mdm.info[i].emu.plmsn, ISDN_LMSNLEN))
+ return -EFAULT;
+ p += ISDN_LMSNLEN;
}
- return (ISDN_MODEM_ANZREG + ISDN_MSNLEN) * ISDN_MAX_CHANNELS;
+ return (ISDN_MODEM_ANZREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS;
} else
return -EINVAL;
break;
@@ -1721,7 +1790,6 @@ isdn_open(struct inode *ino, struct file *filep)
uint minor = MINOR(ino->i_rdev);
int drvidx;
int chidx;
- isdn_ctrl c;
if (minor == ISDN_MINOR_STATUS) {
infostruct *p;
@@ -1744,31 +1812,25 @@ isdn_open(struct inode *ino, struct file *filep)
if (drvidx < 0)
return -ENODEV;
chidx = isdn_minor2chan(minor);
- if (!dev->drv[drvidx]->running)
+ if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
return -ENODEV;
- if (!(dev->drv[drvidx]->flags & (1 << chidx)))
+ if (!(dev->drv[drvidx]->online & (1 << chidx)))
return -ENODEV;
- c.command = ISDN_CMD_LOCK;
- c.driver = drvidx;
- isdn_command(&c);
- MOD_INC_USE_COUNT;
+ isdn_MOD_INC_USE_COUNT();
return 0;
}
if (minor <= ISDN_MINOR_CTRLMAX) {
drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
if (drvidx < 0)
return -ENODEV;
- c.command = ISDN_CMD_LOCK;
- c.driver = drvidx;
- MOD_INC_USE_COUNT;
- isdn_command(&c);
+ isdn_MOD_INC_USE_COUNT();
return 0;
}
#ifdef CONFIG_ISDN_PPP
if (minor <= ISDN_MINOR_PPPMAX) {
int ret;
if (!(ret = isdn_ppp_open(minor - ISDN_MINOR_PPP, filep)))
- MOD_INC_USE_COUNT;
+ isdn_MOD_INC_USE_COUNT();
return ret;
}
#endif
@@ -1779,13 +1841,12 @@ static int
isdn_close(struct inode *ino, struct file *filep)
{
uint minor = MINOR(ino->i_rdev);
- int drvidx;
- isdn_ctrl c;
- MOD_DEC_USE_COUNT;
if (minor == ISDN_MINOR_STATUS) {
infostruct *p = dev->infochain;
infostruct *q = NULL;
+
+ MOD_DEC_USE_COUNT;
while (p) {
if (p->private == (char *) &(filep->private_data)) {
if (q)
@@ -1801,24 +1862,12 @@ isdn_close(struct inode *ino, struct file *filep)
printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n");
return 0;
}
- if (minor < ISDN_MINOR_CTRL) {
- drvidx = isdn_minor2drv(minor);
- if (drvidx < 0)
- return 0;
- c.command = ISDN_CMD_UNLOCK;
- c.driver = drvidx;
- isdn_command(&c);
+ isdn_MOD_DEC_USE_COUNT();
+ if (minor < ISDN_MINOR_CTRL)
return 0;
- }
if (minor <= ISDN_MINOR_CTRLMAX) {
- drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
- if (drvidx < 0)
- return 0;
if (dev->profd == current)
dev->profd = NULL;
- c.command = ISDN_CMD_UNLOCK;
- c.driver = drvidx;
- isdn_command(&c);
return 0;
}
#ifdef CONFIG_ISDN_PPP
@@ -1872,7 +1921,6 @@ isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
ulong flags;
ulong features;
ulong vfeatures;
- isdn_ctrl cmd;
save_flags(flags);
cli();
@@ -1890,7 +1938,7 @@ isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
if ((dev->usage[i] & ISDN_USAGE_EXCLUSIVE) &&
((pre_dev != d) || (pre_chan != dev->chanmap[i])))
continue;
- if ((dev->drv[d]->running)) {
+ if (dev->drv[d]->flags & DRV_FLAG_RUNNING) {
if (((dev->drv[d]->interface->features & features) == features) ||
(((dev->drv[d]->interface->features & vfeatures) == vfeatures) &&
(dev->drv[d]->interface->features & ISDN_FEATURE_L2_TRANS))) {
@@ -1898,10 +1946,6 @@ isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
dev->usage[i] |= usage;
isdn_info_update();
- cmd.driver = d;
- cmd.arg = 0;
- cmd.command = ISDN_CMD_LOCK;
- isdn_command(&cmd);
restore_flags(flags);
return i;
} else {
@@ -1909,10 +1953,6 @@ isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
dev->usage[i] |= usage;
isdn_info_update();
- cmd.driver = d;
- cmd.arg = 0;
- cmd.command = ISDN_CMD_LOCK;
- isdn_command(&cmd);
restore_flags(flags);
return i;
}
@@ -1932,7 +1972,6 @@ isdn_free_channel(int di, int ch, int usage)
{
int i;
ulong flags;
- isdn_ctrl cmd;
save_flags(flags);
cli();
@@ -1946,12 +1985,6 @@ isdn_free_channel(int di, int ch, int usage)
dev->obytes[i] = 0;
isdn_info_update();
isdn_free_queue(&dev->drv[di]->rpqueue[ch]);
- cmd.driver = di;
- cmd.arg = ch;
- cmd.command = ISDN_CMD_UNLOCK;
- restore_flags(flags);
- isdn_command(&cmd);
- return;
}
restore_flags(flags);
}
@@ -1996,7 +2029,6 @@ isdn_writebuf_stub(int drvidx, int chan, const u_char * buf, int len,
copy_from_user(skb_put(skb, len), buf, len);
else
memcpy(skb_put(skb, len), buf, len);
-
ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb);
if (ret <= 0)
dev_kfree_skb(skb);
@@ -2052,100 +2084,213 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
return ret;
}
-/*
- * Low-level-driver registration
- */
+int
+register_isdn_module(isdn_module *m) {
+#if 0
+ isdn_module_list **pp = &dev->modules;
+ isdn_module *new = kmalloc(sizeof(isdn_module_list), GFP_KERNEL);
-EXPORT_SYMBOL(register_isdn);
+ if (!new) {
+ printk(KERN_WARNING "isdn: Out of memory in register_isdn_module\n");
+ return -1;
+ }
+ while (*pp && (*pp)->orig != m)
+ pp = &(*pp)->next;
+ if (*pp != NULL) {
+ printk(KERN_WARNING "isdn: Module %s already registered\n", m->name);
+ return -1;
+ }
+ while (*pp && ((*pp)->module.priority < m->priority))
+ pp = &(*pp)->next;
+ new->next = *pp;
+ new->orig = m;
+ new->module = *m;
+
+ *pp = new;
+#endif
+ return 0;
+}
int
-register_isdn(isdn_if * i)
+unregister_isdn_module(isdn_module *m) {
+#if 0
+ isdn_module_list **pp = &dev->modules;
+
+ while (*pp && *pp != m)
+ pp = &(*pp)->next;
+ if (*pp == NULL) {
+ printk(KERN_WARNING "isdn: Module %s not found\n", m->name);
+ return -1;
+ }
+#endif
+ return 0;
+}
+
+int
+isdn_add_channels(driver *d, int drvidx, int n, int adding)
{
- driver *d;
- int n,
- j,
- k;
+ int j, k, m;
ulong flags;
- int drvidx;
- if (dev->drivers >= ISDN_MAX_DRIVERS) {
- printk(KERN_WARNING "register_isdn: Max. %d drivers supported\n",
- ISDN_MAX_DRIVERS);
+#if LINUX_VERSION_CODE >= 131841
+ init_waitqueue_head(&d->st_waitq);
+#endif
+ if (d->flags & DRV_FLAG_RUNNING)
+ return -1;
+ if (n < 1)
return 0;
- }
- n = i->channels;
+
+ m = (adding) ? d->channels + n : n;
+
if (dev->channels + n > ISDN_MAX_CHANNELS) {
printk(KERN_WARNING "register_isdn: Max. %d channels supported\n",
ISDN_MAX_CHANNELS);
- return 0;
- }
- if (!i->writebuf_skb) {
- printk(KERN_WARNING "register_isdn: No write routine given.\n");
- return 0;
- }
- if (!(d = (driver *) kmalloc(sizeof(driver), GFP_KERNEL))) {
- printk(KERN_WARNING "register_isdn: Could not alloc driver-struct\n");
- return 0;
+ return -1;
}
- memset((char *) d, 0, sizeof(driver));
- if (!(d->rcverr = (int *) kmalloc(sizeof(int) * n, GFP_KERNEL))) {
+
+ if ((adding) && (d->rcverr))
+ kfree(d->rcverr);
+ if (!(d->rcverr = (int *) kmalloc(sizeof(int) * m, GFP_KERNEL))) {
printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");
- kfree(d);
- return 0;
+ return -1;
}
- memset((char *) d->rcverr, 0, sizeof(int) * n);
- if (!(d->rcvcount = (int *) kmalloc(sizeof(int) * n, GFP_KERNEL))) {
+ memset((char *) d->rcverr, 0, sizeof(int) * m);
+
+ if ((adding) && (d->rcvcount))
+ kfree(d->rcvcount);
+ if (!(d->rcvcount = (int *) kmalloc(sizeof(int) * m, GFP_KERNEL))) {
printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
- kfree(d->rcverr);
- kfree(d);
- return 0;
+ if (!adding) kfree(d->rcverr);
+ return -1;
+ }
+ memset((char *) d->rcvcount, 0, sizeof(int) * m);
+
+ if ((adding) && (d->rpqueue)) {
+ for (j = 0; j < d->channels; j++)
+ isdn_free_queue(&d->rpqueue[j]);
+ kfree(d->rpqueue);
}
- memset((char *) d->rcvcount, 0, sizeof(int) * n);
if (!(d->rpqueue =
- (struct sk_buff_head *) kmalloc(sizeof(struct sk_buff_head) * n, GFP_KERNEL))) {
+ (struct sk_buff_head *) kmalloc(sizeof(struct sk_buff_head) * m, GFP_KERNEL))) {
printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n");
- kfree(d->rcvcount);
- kfree(d->rcverr);
- kfree(d);
- return 0;
+ if (!adding) {
+ kfree(d->rcvcount);
+ kfree(d->rcverr);
+ }
+ return -1;
}
- for (j = 0; j < n; j++) {
+ for (j = 0; j < m; j++) {
skb_queue_head_init(&d->rpqueue[j]);
}
+
+ if ((adding) && (d->rcv_waitq))
+ kfree(d->rcv_waitq);
+#if LINUX_VERSION_CODE < 131841
if (!(d->rcv_waitq = (struct wait_queue **)
- kmalloc(sizeof(struct wait_queue *) * n, GFP_KERNEL))) {
+ kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL))) {
+#else
+ d->rcv_waitq = (wait_queue_head_t *)
+ kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_KERNEL);
+ if (!d->rcv_waitq) {
+#endif
printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n");
- kfree(d->rpqueue);
- kfree(d->rcvcount);
- kfree(d->rcverr);
- kfree(d);
- return 0;
+ if (!adding) {
+ kfree(d->rpqueue);
+ kfree(d->rcvcount);
+ kfree(d->rcverr);
+ }
+ return -1;
}
- memset((char *) d->rcv_waitq, 0, sizeof(struct wait_queue *) * n);
+#if LINUX_VERSION_CODE < 131841
+ memset((char *) d->rcv_waitq, 0, sizeof(struct wait_queue *) * m);
+
+ if ((adding) && (d->snd_waitq))
+ kfree(d->snd_waitq);
if (!(d->snd_waitq = (struct wait_queue **)
- kmalloc(sizeof(struct wait_queue *) * n, GFP_KERNEL))) {
+ kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL))) {
printk(KERN_WARNING "register_isdn: Could not alloc snd_waitq\n");
- kfree(d->rcv_waitq);
- kfree(d->rpqueue);
- kfree(d->rcvcount);
- kfree(d->rcverr);
- kfree(d);
+ if (!adding) {
+ kfree(d->rcv_waitq);
+ kfree(d->rpqueue);
+ kfree(d->rcvcount);
+ kfree(d->rcverr);
+ }
+ return -1;
+ }
+ memset((char *) d->snd_waitq, 0, sizeof(struct wait_queue *) * m);
+#else
+ d->snd_waitq = d->rcv_waitq + m;
+ for (j = 0; j < m; j++) {
+ init_waitqueue_head(&d->rcv_waitq[m]);
+ init_waitqueue_head(&d->snd_waitq[m]);
+ }
+#endif
+
+ dev->channels += n;
+ save_flags(flags);
+ cli();
+ for (j = d->channels; j < m; j++)
+ for (k = 0; k < ISDN_MAX_CHANNELS; k++)
+ if (dev->chanmap[k] < 0) {
+ dev->chanmap[k] = j;
+ dev->drvmap[k] = drvidx;
+ break;
+ }
+ restore_flags(flags);
+ d->channels = m;
+ return 0;
+}
+
+/*
+ * Low-level-driver registration
+ */
+
+EXPORT_SYMBOL(register_isdn);
+EXPORT_SYMBOL(register_isdn_module);
+EXPORT_SYMBOL(unregister_isdn_module);
+#ifdef CONFIG_ISDN_PPP
+EXPORT_SYMBOL(isdn_ppp_register_compressor);
+EXPORT_SYMBOL(isdn_ppp_unregister_compressor);
+#endif
+
+int
+register_isdn(isdn_if * i)
+{
+ driver *d;
+ int j;
+ ulong flags;
+ int drvidx;
+
+ if (dev->drivers >= ISDN_MAX_DRIVERS) {
+ printk(KERN_WARNING "register_isdn: Max. %d drivers supported\n",
+ ISDN_MAX_DRIVERS);
+ return 0;
+ }
+ if (!i->writebuf_skb) {
+ printk(KERN_WARNING "register_isdn: No write routine given.\n");
+ return 0;
+ }
+ if (!(d = (driver *) kmalloc(sizeof(driver), GFP_KERNEL))) {
+ printk(KERN_WARNING "register_isdn: Could not alloc driver-struct\n");
return 0;
}
- memset((char *) d->snd_waitq, 0, sizeof(struct wait_queue *) * n);
- d->channels = n;
- d->loaded = 1;
+ memset((char *) d, 0, sizeof(driver));
+
d->maxbufsize = i->maxbufsize;
d->pktcount = 0;
d->stavail = 0;
- d->running = 0;
- d->flags = 0;
+ d->flags = DRV_FLAG_LOADED;
+ d->online = 0;
d->interface = i;
+ d->channels = 0;
for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
if (!dev->drv[drvidx])
break;
+ if (isdn_add_channels(d, drvidx, i->channels, 0)) {
+ kfree(d);
+ return 0;
+ }
i->channels = drvidx;
-
i->rcvcallb_skb = isdn_receive_skb_callback;
i->statcallb = isdn_status_callback;
if (!strlen(i->id))
@@ -2155,15 +2300,7 @@ register_isdn(isdn_if * i)
for (j = 0; j < drvidx; j++)
if (!strcmp(i->id, dev->drvid[j]))
sprintf(i->id, "line%d", drvidx);
- for (j = 0; j < n; j++)
- for (k = 0; k < ISDN_MAX_CHANNELS; k++)
- if (dev->chanmap[k] < 0) {
- dev->chanmap[k] = j;
- dev->drvmap[k] = drvidx;
- break;
- }
dev->drv[drvidx] = d;
- dev->channels += n;
strcpy(dev->drvid[drvidx], i->id);
isdn_info_update();
dev->drivers++;
@@ -2215,12 +2352,21 @@ isdn_init(void)
memset((char *) dev, 0, sizeof(isdn_dev));
init_timer(&dev->timer);
dev->timer.function = isdn_timer_funct;
+#if LINUX_VERSION_CODE < 131841
dev->sem = MUTEX;
+#else
+ init_MUTEX(&dev->sem);
+ init_waitqueue_head(&dev->info_waitq);
+#endif
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
dev->drvmap[i] = -1;
dev->chanmap[i] = -1;
dev->m_idx[i] = -1;
strcpy(dev->num[i], "???");
+#if LINUX_VERSION_CODE >= 131841
+ init_waitqueue_head(&dev->mdm.info[i].open_wait);
+ init_waitqueue_head(&dev->mdm.info[i].close_wait);
+#endif
}
if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) {
printk(KERN_WARNING "isdn: Could not register control devices\n");
diff --git a/drivers/isdn/isdn_common.h b/drivers/isdn/isdn_common.h
index 6cb503b9f..3ba4855b7 100644
--- a/drivers/isdn/isdn_common.h
+++ b/drivers/isdn/isdn_common.h
@@ -1,8 +1,8 @@
-/* $Id: isdn_common.h,v 1.9 1998/02/20 17:19:01 fritz Exp $
+/* $Id: isdn_common.h,v 1.15 1999/04/18 14:06:50 fritz Exp $
* header for Linux ISDN subsystem, common used functions and debugging-switches (linklevel).
*
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
* Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg
* Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
*
@@ -20,11 +20,36 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Note: This file differs from the corresponding revision as present in the
- * isdn4linux CVS repository because some later bug fixes have been extracted
- * from the repository and merged into this file. -- Henner Eisen
- *
* $Log: isdn_common.h,v $
+ * Revision 1.15 1999/04/18 14:06:50 fritz
+ * Removed TIMRU stuff.
+ *
+ * Revision 1.14 1999/04/12 12:33:18 fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.13 1999/03/02 12:04:47 armin
+ * -added ISDN_STAT_ADDCH to increase supported channels after
+ * register_isdn().
+ * -ttyI now goes on-hook on ATZ when B-Ch is connected.
+ * -added timer-function for register S7 (Wait for Carrier).
+ * -analog modem (ISDN_PROTO_L2_MODEM) implementations.
+ * -on L2_MODEM a string will be appended to the CONNECT-Message,
+ * which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN.
+ * -variable "dialing" used for ATA also, for interrupting call
+ * establishment and register S7.
+ *
+ * Revision 1.12 1998/06/26 15:12:27 fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 1.11 1998/04/14 16:28:47 he
+ * Fixed user space access with interrupts off and remaining
+ * copy_{to,from}_user() -> -EFAULT return codes
+ *
+ * Revision 1.10 1998/03/07 18:21:03 cal
+ * Dynamic Timeout-Rule-Handling vs. 971110 included
+ *
* Revision 1.9 1998/02/20 17:19:01 fritz
* Added common stub for sending commands to lowlevel.
*
@@ -90,10 +115,16 @@ extern char *isdn_map_eaz2msn(char *msn, int di);
extern void isdn_timer_ctrl(int tf, int onoff);
extern void isdn_unexclusive_channel(int di, int ch);
extern int isdn_getnum(char **);
+#if LINUX_VERSION_CODE < 131841
extern int isdn_readbchan(int, int, u_char *, u_char *, int, struct wait_queue**);
+#else
+extern int isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *);
+#endif
extern int isdn_get_free_channel(int, int, int, int, int);
extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
extern int register_isdn(isdn_if * i);
+extern int isdn_wildmat(char *, char *);
+extern int isdn_add_channels(driver *, int, int, int);
#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
extern void isdn_dumppkt(char *, u_char *, int, int);
#endif
diff --git a/drivers/isdn/isdn_concap.c b/drivers/isdn/isdn_concap.c
index 0d9abb226..1ca6c34e3 100644
--- a/drivers/isdn/isdn_concap.c
+++ b/drivers/isdn/isdn_concap.c
@@ -1,10 +1,21 @@
-/* $Id: isdn_concap.c,v 1.2 1998/01/31 22:49:21 keil Exp $
+/* $Id: isdn_concap.c,v 1.5 1998/10/30 18:44:48 he Exp $
* Stuff to support the concap_proto by isdn4linux. isdn4linux - specific
* stuff goes here. Stuff that depends only on the concap protocol goes to
* another -- protocol specific -- source file.
*
* $Log: isdn_concap.c,v $
+ * Revision 1.5 1998/10/30 18:44:48 he
+ * pass return value from isdn_net_dial_req for dialmode change
+ *
+ * Revision 1.4 1998/10/30 17:55:24 he
+ * dialmode for x25iface and multulink ppp
+ *
+ * Revision 1.3 1998/05/26 22:39:22 he
+ * sync'ed with 2.1.102 where appropriate (CAPABILITY changes)
+ * concap typo
+ * cleared dev.tbusy in isdn_net BCONN status callback
+ *
* Revision 1.2 1998/01/31 22:49:21 keil
* correct comments
*
@@ -20,14 +31,9 @@
#include <linux/concap.h>
#include "isdn_concap.h"
-/* The declaration of this (or a plublic variant thereof) should really go
- in linux/isdn.h. But we really need it here (and isdn_ppp, like us, also
- refers to that private function currently owned by isdn_net.c) */
-extern int isdn_net_force_dial_lp(isdn_net_local *);
-
/* The following set of device service operations are for encapsulation
- protocols that require for reliable datalink sematics. That means:
+ protocols that require for reliable datalink semantics. That means:
- before any data is to be submitted the connection must explicitly
be set up.
@@ -66,9 +72,9 @@ int isdn_concap_dl_connect_req(struct concap_proto *concap)
IX25DEBUG( "isdn_concap_dl_connect_req: %s \n", ndev -> name);
/* dial ... */
- ret = isdn_net_force_dial_lp( lp );
+ ret = isdn_net_dial_req( lp );
if ( ret ) IX25DEBUG("dialing failed\n");
- return 0;
+ return ret;
}
int isdn_concap_dl_disconn_req(struct concap_proto *concap)
diff --git a/drivers/isdn/isdn_net.c b/drivers/isdn/isdn_net.c
index daafceb1a..9e4426af0 100644
--- a/drivers/isdn/isdn_net.c
+++ b/drivers/isdn/isdn_net.c
@@ -1,8 +1,8 @@
-/* $Id: isdn_net.c,v 1.55 1998/02/23 19:38:22 fritz Exp $
+/* $Id: isdn_net.c,v 1.84 1999/04/18 14:06:55 fritz Exp $
* Linux ISDN subsystem, network interfaces and related functions (linklevel).
*
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994-1998 by Fritz Elfert (fritz@isdn4linux.de)
* Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg
* Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
*
@@ -20,11 +20,119 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Note: This file differs from the corresponding revision as present in the
- * isdn4linux CVS repository because some later bug fixes have been extracted
- * from the repository and merged into this file. -- Henner Eisen
- *
* $Log: isdn_net.c,v $
+ * Revision 1.84 1999/04/18 14:06:55 fritz
+ * Removed TIMRU stuff.
+ *
+ * Revision 1.83 1999/04/12 12:33:23 fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.82 1999/01/17 00:55:58 he
+ * added mark_bh in BCONN statcallb and cleaned up some dead code
+ *
+ * Revision 1.81 1999/01/15 16:36:52 he
+ * replaced icmp_send() by dst_link_failure()
+ *
+ * Revision 1.80 1998/12/01 13:06:22 paul
+ * Also huptimeout with dialmode == manual
+ *
+ * Revision 1.79 1998/10/30 17:55:27 he
+ * dialmode for x25iface and multulink ppp
+ *
+ * Revision 1.78 1998/10/26 18:20:46 he
+ * re-inserted p=p->next in isdn_net_find_icall() (fixes kernel lock up
+ * on incoming call not matching the first interface)
+ *
+ * Revision 1.77 1998/10/23 10:18:44 paul
+ * Implementation of "dialmode" (successor of "status")
+ * You also need current isdnctrl for this!
+ *
+ * Revision 1.76 1998/09/07 22:00:05 he
+ * flush method for 2.1.118 and above
+ * updated IIOCTLNETGPN
+ *
+ * Revision 1.75 1998/08/31 21:09:50 he
+ * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface'
+ * peer phone number)
+ *
+ * Revision 1.74 1998/07/30 11:28:32 paul
+ * printk message only appeared when status is off and interface is rawIP,
+ * which is confusing for people who don't know about "isdnctrl status <if> on".
+ *
+ * Revision 1.73 1998/06/26 22:01:37 keil
+ * tx_queue_len = 5 was too small
+ *
+ * Revision 1.72 1998/06/26 15:12:31 fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 1.71 1998/06/18 22:43:08 fritz
+ * Bugfix: Setting ndev->do_ioctl had beed accidetly removed at abc-cleanup.
+ *
+ * Revision 1.70 1998/06/17 19:50:49 he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.69 1998/06/09 12:27:37 cal
+ * Changed default of local netdev flags: ISDN_NET_STOPPED is default now,
+ * so autodial is suppressed for that device until it is switched on using
+ * 'isdnctrl status dev-name on'.
+ *
+ * Revision 1.68 1998/06/07 00:20:05 fritz
+ * abc cleanup.
+ *
+ * Revision 1.67 1998/06/02 12:10:08 detabc
+ * wegen einer einstweiliger verfuegung gegen DW ist zur zeit
+ * die abc-extension bis zur klaerung der rechtslage nicht verfuegbar
+ *
+ * Revision 1.66 1998/05/26 22:39:24 he
+ * sync'ed with 2.1.102 where appropriate (CAPABILITY changes)
+ * concap typo
+ * cleared dev.tbusy in isdn_net BCONN status callback
+ *
+ * Revision 1.65 1998/05/22 10:01:11 detabc
+ * in case of a icmp-unreach condition the tcp-keepalive-entrys
+ * will be dropped from the internal double-link-list (only abc-extension).
+ * send icmp unreach only if the skb->protocol == ETH_P_IP
+ * speedup abc-no-dchan redial
+ *
+ * Revision 1.64 1998/05/07 19:58:39 detabc
+ * bugfix in abc_delayed_hangup
+ * optimize keepalive-tests for abc_rawip
+ *
+ * Revision 1.63 1998/05/05 23:23:36 detabc
+ * change ICMP_HOST_UNREACH to ICMP_NET_UNREACH (only abc-ext.)
+ * set dev->tbusy to zero in isdn_net_unreachable() (only abc-ext.)
+ * drop all new packets and send ICMP_NET_UNREACH for
+ * min. dialwait to max. dialwait * 6 time. (only abc-ext.)
+ * change random-deliver of packets (small first) from all emcapsulation
+ * to only rawip with ABC-Router-Flag enabled.
+ *
+ * Revision 1.62 1998/05/03 17:40:42 detabc
+ * Include abc-extension-support for >= 2.1.x Kernels in
+ * isdn_net.c and isdn_common.c. alpha-test OK and running !
+ *
+ * Revision 1.61 1998/04/16 19:19:42 keil
+ * Fix from vger (tx max qlength)
+ *
+ * Revision 1.60 1998/04/14 16:28:49 he
+ * Fixed user space access with interrupts off and remaining
+ * copy_{to,from}_user() -> -EFAULT return codes
+ *
+ * Revision 1.59 1998/03/07 22:37:33 fritz
+ * Bugfix: restore_flags missing.
+ *
+ * Revision 1.58 1998/03/07 18:21:05 cal
+ * Dynamic Timeout-Rule-Handling vs. 971110 included
+ *
+ * Revision 1.57 1998/02/25 18:31:13 fritz
+ * Added debugging output in adjust_header.
+ *
+ * Revision 1.56 1998/02/25 17:49:42 he
+ * Changed return codes caused be failing copy_{to,from}_user to -EFAULT
+ *
* Revision 1.55 1998/02/23 19:38:22 fritz
* Corrected check for modified feature-flags.
*
@@ -248,9 +356,7 @@
#include <linux/isdn.h>
#include <net/arp.h>
#include <net/dst.h>
-#ifndef DEV_NUMBUFFS
#include <net/pkt_sched.h>
-#endif
#include <linux/inetdevice.h>
#include "isdn_common.h"
#include "isdn_net.h"
@@ -265,14 +371,10 @@
/* Prototypes */
int isdn_net_force_dial_lp(isdn_net_local *);
-static int isdn_net_wildmat(char *s, char *p);
static int isdn_net_start_xmit(struct sk_buff *, struct device *);
static int isdn_net_xmit(struct device *, isdn_net_local *, struct sk_buff *);
-#ifdef DEV_NUMBUFFS
-static void dev_purge_queues(struct device *dev); /* move this to net/core/dev.c */
-#endif
-char *isdn_net_revision = "$Revision: 1.55 $";
+char *isdn_net_revision = "$Revision: 1.84 $";
/*
* Code for raw-networking over ISDN
@@ -293,16 +395,21 @@ isdn_net_unreachable(struct device *dev, struct sk_buff *skb, char *reason)
dst_link_failure(skb);
}
+ else { /* dial not triggered by rawIP packet */
+ printk(KERN_DEBUG "isdn_net: %s: %s\n",
+ dev->name,
+ (reason != NULL) ? reason : "reason unknown");
+ }
}
static void
isdn_net_reset(struct device *dev)
{
#ifdef CONFIG_ISDN_X25
- struct concap_device_ops * dops =
+ struct concap_device_ops * dops =
( (isdn_net_local *) dev->priv ) -> dops;
- struct concap_proto * cprot =
- ( (isdn_net_local *) dev->priv ) -> netdev -> cprot;
+ struct concap_proto * cprot =
+ ( (isdn_net_local *) dev->priv ) -> netdev -> cprot;
#endif
ulong flags;
@@ -311,7 +418,7 @@ isdn_net_reset(struct device *dev)
dev->interrupt = 0;
dev->tbusy = 0;
#ifdef CONFIG_ISDN_X25
- if( cprot && cprot -> pops && dops )
+ if( cprot && cprot -> pops && dops )
cprot -> pops -> restart ( cprot, dev, dops );
#endif
restore_flags(flags);
@@ -338,7 +445,7 @@ isdn_net_open(struct device *dev)
if (ifa != NULL)
memcpy(dev->dev_addr+2, &ifa->ifa_local, 4);
}
-
+
/* If this interface has slaves, start them also */
if ((p = (((isdn_net_local *) dev->priv)->slave))) {
@@ -362,6 +469,7 @@ isdn_net_bind_channel(isdn_net_local * lp, int idx)
save_flags(flags);
cli();
+ lp->flags |= ISDN_NET_CONNECTED;
lp->isdn_device = dev->drvmap[idx];
lp->isdn_channel = dev->chanmap[idx];
dev->rx_netdev[idx] = lp->netdev;
@@ -387,10 +495,6 @@ isdn_net_unbind_channel(isdn_net_local * lp)
dev_kfree_skb(lp->sav_skb);
lp->sav_skb = NULL;
}
-#ifdef DEV_NUMBUFFS
- if (!lp->master) /* purge only for master device */
- dev_purge_queues(&lp->netdev->dev);
-#else
if (!lp->master) { /* reset only master device */
/* Moral equivalent of dev_purge_queues():
BEWARE! This chunk of code cannot be called from hardware
@@ -398,7 +502,6 @@ isdn_net_unbind_channel(isdn_net_local * lp)
*/
qdisc_reset(lp->netdev->dev.qdisc);
}
-#endif
lp->dialstate = 0;
dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
dev->st_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
@@ -444,7 +547,13 @@ isdn_net_autohup()
if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) {
anymore = 1;
l->huptimer++;
- if ((l->onhtime) && (l->huptimer > l->onhtime)) {
+ /*
+ * if there is some dialmode where timeout-hangup
+ * should _not_ be done, check for that here
+ */
+ if ((l->onhtime) &&
+ (l->huptimer > l->onhtime))
+ {
if (l->hupflags & ISDN_MANCHARGE &&
l->hupflags & ISDN_CHARGEHUP) {
while (jiffies - l->chargetime > l->chargeint)
@@ -469,6 +578,11 @@ isdn_net_autohup()
} else if (l->hupflags & ISDN_INHUP)
isdn_net_hangup(&p->dev);
}
+
+ if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*l) == ISDN_NET_DM_OFF)) {
+ isdn_net_hangup(&p->dev);
+ break;
+ }
}
p = (isdn_net_dev *) p->next;
}
@@ -487,7 +601,7 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
{
isdn_net_dev *p = dev->st_netdev[idx];
int cmd = c->command;
-
+
if (p) {
isdn_net_local *lp = p->local;
#ifdef CONFIG_ISDN_X25
@@ -538,23 +652,12 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
failed. If there are generic encap protocol
receiver routines signal the closure of
the link*/
-
- if( !(lp->flags & ISDN_NET_CONNECTED)
+
+ if( !(lp->flags & ISDN_NET_CONNECTED)
&& pops && pops -> disconn_ind )
pops -> disconn_ind(cprot);
#endif /* CONFIG_ISDN_X25 */
if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) {
- lp->flags &= ~ISDN_NET_CONNECTED;
- if (lp->first_skb) {
- dev_kfree_skb(lp->first_skb);
- lp->first_skb = NULL;
- }
- if (lp->sav_skb) {
- dev_kfree_skb(lp->sav_skb);
- lp->sav_skb = NULL;
- }
- isdn_free_channel(lp->isdn_device, lp->isdn_channel,
- ISDN_USAGE_NET);
#ifdef CONFIG_ISDN_PPP
isdn_ppp_free(lp);
#endif
@@ -562,10 +665,7 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
printk(KERN_INFO "%s: remote hangup\n", lp->name);
printk(KERN_INFO "%s: Chargesum is %d\n", lp->name,
lp->charge);
- lp->isdn_device = -1;
- lp->isdn_channel = -1;
- dev->st_netdev[idx] = NULL;
- dev->rx_netdev[idx] = NULL;
+ isdn_net_unbind_channel(lp);
return 1;
}
break;
@@ -607,6 +707,11 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
lp->chargetime = jiffies;
printk(KERN_DEBUG "isdn_net: chargetime of %s now %d\n",
lp->name, lp->chargetime);
+
+ /* reset dial-timeout */
+ lp->dialstarted = 0;
+ lp->dialwait_timer = 0;
+
/* Immediately send first skb to speed up arp */
#ifdef CONFIG_ISDN_PPP
if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
@@ -617,13 +722,13 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
if( pops )
if( pops->connect_ind)
pops->connect_ind(cprot);
-
#endif /* CONFIG_ISDN_X25 */
if (lp->first_skb) {
-
+
if (!(isdn_net_xmit(&p->dev, lp, lp->first_skb)))
lp->first_skb = NULL;
- } else {
+ }
+ else {
/*
* dev.tbusy is usually cleared implicitly by isdn_net_xmit(,,lp->first_skb).
* With an empty lp->first_skb, we need to do this ourselves
@@ -721,6 +826,13 @@ isdn_net_dial(void)
break;
}
anymore = 1;
+
+ if(lp->dialtimeout > 0)
+ if(lp->dialstarted == 0 || jiffies > (lp->dialstarted + lp->dialtimeout + lp->dialwait)) {
+ lp->dialstarted = jiffies;
+ lp->dialwait_timer = 0;
+ }
+
lp->dialstate++;
/* Fall through */
case 2:
@@ -735,12 +847,22 @@ isdn_net_dial(void)
lp->dialretry = 0;
anymore = 1;
lp->dialstate++;
- /* Falls through */
+ /* Fall through */
case 3:
/* Setup interface, dial current phone-number, switch to next number.
* If list of phone-numbers is exhausted, increment
* retry-counter.
*/
+ if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)) {
+ char *s;
+ if (dev->global_flags & ISDN_GLOBAL_STOPPED)
+ s = "dial suppressed: isdn system stopped";
+ else
+ s = "dial suppressed: dialmode `off'";
+ isdn_net_unreachable(&p->dev, lp->first_skb, s);
+ isdn_net_hangup(&p->dev);
+ break;
+ }
cmd.driver = lp->isdn_device;
cmd.command = ISDN_CMD_SETL2;
cmd.arg = lp->isdn_channel + (lp->l2_proto << 8);
@@ -765,6 +887,16 @@ isdn_net_dial(void)
lp->dialstate = 4;
printk(KERN_INFO "%s: Open leased line ...\n", lp->name);
} else {
+ if(lp->dialtimeout > 0)
+ if(jiffies > (lp->dialstarted + lp->dialtimeout)) {
+ restore_flags(flags);
+ lp->dialwait_timer = jiffies + lp->dialwait;
+ lp->dialstarted = 0;
+ isdn_net_unreachable(&p->dev, lp->first_skb, "dial: timed out");
+ isdn_net_hangup(&p->dev);
+ break;
+ }
+
sprintf(cmd.parm.setup.phone, "%s", lp->dial->num);
/*
* Switch to next number or back to start if at end of list.
@@ -772,6 +904,17 @@ isdn_net_dial(void)
if (!(lp->dial = (isdn_net_phone *) lp->dial->next)) {
lp->dial = lp->phone[1];
lp->dialretry++;
+
+ if (lp->dialretry > lp->dialmax) {
+ restore_flags(flags);
+ if (lp->dialtimeout == 0) {
+ lp->dialwait_timer = jiffies + lp->dialwait;
+ lp->dialstarted = 0;
+ isdn_net_unreachable(&p->dev, lp->first_skb, "dial: tried all numbers dialmax times");
+ }
+ isdn_net_hangup(&p->dev);
+ break;
+ }
}
restore_flags(flags);
cmd.driver = lp->isdn_device;
@@ -786,7 +929,7 @@ isdn_net_dial(void)
isdn_info_update();
}
printk(KERN_INFO "%s: dialing %d %s...\n", lp->name,
- lp->dialretry - 1, cmd.parm.setup.phone);
+ lp->dialretry, cmd.parm.setup.phone);
lp->dtimer = 0;
#ifdef ISDN_DEBUG_NET_DIAL
printk(KERN_DEBUG "dial: d=%d c=%d\n", lp->isdn_device,
@@ -810,15 +953,11 @@ isdn_net_dial(void)
break;
case 4:
/* Wait for D-Channel-connect.
- * If timeout and max retries not
- * reached, switch back to state 3.
+ * If timeout, switch back to state 3.
+ * Dialmax-handling moved to state 3.
*/
- if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) {
- if (lp->dialretry < lp->dialmax) {
- lp->dialstate = 3;
- } else
- isdn_net_hangup(&p->dev);
- }
+ if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
+ lp->dialstate = 3;
anymore = 1;
break;
case 5:
@@ -895,7 +1034,8 @@ isdn_net_dial(void)
/* Remote does callback. Hangup after cbdelay, then wait for incoming
* call (in state 4).
*/
- if (lp->dtimer++ > lp->cbdelay) {
+ if (lp->dtimer++ > lp->cbdelay)
+ {
printk(KERN_INFO "%s: hangup waiting for callback ...\n", lp->name);
lp->dtimer = 0;
lp->dialstate = 4;
@@ -930,7 +1070,6 @@ isdn_net_hangup(struct device *d)
#endif
if (lp->flags & ISDN_NET_CONNECTED) {
- lp->flags &= ~ISDN_NET_CONNECTED;
printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name);
#ifdef CONFIG_ISDN_PPP
isdn_ppp_free(lp);
@@ -938,7 +1077,7 @@ isdn_net_hangup(struct device *d)
#ifdef CONFIG_ISDN_X25
/* try if there are generic encap protocol
receiver routines and signal the closure of
- the link */
+ the link */
if( pops && pops -> disconn_ind )
pops -> disconn_ind(cprot);
#endif /* CONFIG_ISDN_X25 */
@@ -968,7 +1107,7 @@ isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp)
char addinfo[100];
addinfo[0] = '\0';
- /* This check stolen from 2.1.72 dev_queue_xmit_nit() */
+ /* This check stolen from 2.1.72 dev_queue_xmit_nit() */
if (skb->nh.raw < skb->data || skb->nh.raw >= skb->tail) {
/* fall back to old isdn_net_log_packet method() */
char * buf = skb->data;
@@ -1062,20 +1201,17 @@ isdn_net_send_skb(struct device *ndev, isdn_net_local * lp,
if (ret == len) {
lp->transcount += len;
clear_bit(0, (void *) &(ndev->tbusy));
- mark_bh(NET_BH);
return 0;
}
if (ret < 0) {
dev_kfree_skb(skb);
lp->stats.tx_errors++;
clear_bit(0, (void *) &(ndev->tbusy));
- mark_bh(NET_BH);
return 0;
}
return 1;
}
-
/*
* Helper function for isdn_net_start_xmit.
* When called, the connection is already established.
@@ -1150,9 +1286,11 @@ isdn_net_adjust_hdr(struct sk_buff *skb, struct device *dev)
if (!skb)
return;
if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
- ulong pullsize = (ulong)skb->nh.raw - (ulong)skb->data - ETH_HLEN;
- if (pullsize)
+ int pullsize = (ulong)skb->nh.raw - (ulong)skb->data - ETH_HLEN;
+ if (pullsize > 0) {
+ printk(KERN_DEBUG "isdn_net: Pull junk %d\n", pullsize);
skb_pull(skb, pullsize);
+ }
}
}
@@ -1166,7 +1304,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct device *ndev)
{
isdn_net_local *lp = (isdn_net_local *) ndev->priv;
#ifdef CONFIG_ISDN_X25
- struct concap_proto * cprot = lp -> netdev -> cprot;
+ struct concap_proto * cprot = lp -> netdev -> cprot;
#endif
if (ndev->tbusy) {
@@ -1179,7 +1317,7 @@ isdn_net_start_xmit(struct sk_buff *skb, struct device *ndev)
ndev->tbusy = 1; /* left instead of obsolete test_and_set_bit() */
#ifdef CONFIG_ISDN_X25
/* At this point hard_start_xmit() passes control to the encapsulation
- protocol (if present).
+ protocol (if present).
For X.25 auto-dialing is completly bypassed because:
- It does not conform with the semantics of a reliable datalink
service as needed by X.25 PLP.
@@ -1205,17 +1343,46 @@ isdn_net_start_xmit(struct sk_buff *skb, struct device *ndev)
#endif
if (!(lp->flags & ISDN_NET_CONNECTED)) {
int chi;
+ /* only do autodial if allowed by config */
+ if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) {
+ isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'");
+ dev_kfree_skb(skb);
+ ndev->tbusy = 0;
+ return 0;
+ }
if (lp->phone[1]) {
ulong flags;
save_flags(flags);
cli();
+
+ if(lp->dialwait_timer <= 0)
+ if(lp->dialstarted > 0 && lp->dialtimeout > 0 && jiffies < lp->dialstarted + lp->dialtimeout + lp->dialwait)
+ lp->dialwait_timer = lp->dialstarted + lp->dialtimeout + lp->dialwait;
+
+ if(lp->dialwait_timer > 0) {
+ if(jiffies < lp->dialwait_timer) {
+ isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached");
+ dev_kfree_skb(skb);
+ ndev->tbusy = 0;
+ restore_flags(flags);
+ return 0;
+ } else
+ lp->dialwait_timer = 0;
+ }
+
/* Grab a free ISDN-Channel */
- if ((chi =
+ if (((chi =
isdn_get_free_channel(ISDN_USAGE_NET,
lp->l2_proto,
lp->l3_proto,
lp->pre_device,
- lp->pre_channel)) < 0) {
+ lp->pre_channel)) < 0) &&
+ ((chi =
+ isdn_get_free_channel(ISDN_USAGE_NET,
+ lp->l2_proto,
+ lp->l3_proto,
+ lp->pre_device,
+ lp->pre_channel^1)) < 0)) {
restore_flags(flags);
isdn_net_unreachable(ndev, skb,
"No channel");
@@ -1227,7 +1394,6 @@ isdn_net_start_xmit(struct sk_buff *skb, struct device *ndev)
if (dev->net_verbose)
isdn_net_log_skb(skb, lp);
lp->dialstate = 1;
- lp->flags |= ISDN_NET_CONNECTED;
/* Connect interface with channel */
isdn_net_bind_channel(lp, chi);
#ifdef CONFIG_ISDN_PPP
@@ -1290,8 +1456,8 @@ isdn_net_close(struct device *dev)
{
struct device *p;
#ifdef CONFIG_ISDN_X25
- struct concap_proto * cprot =
- ( (isdn_net_local *) dev->priv ) -> netdev -> cprot;
+ struct concap_proto * cprot =
+ ( (isdn_net_local *) dev->priv ) -> netdev -> cprot;
/* printk(KERN_DEBUG "isdn_net_close %s\n" , dev-> name ); */
#endif
@@ -1304,9 +1470,9 @@ isdn_net_close(struct device *dev)
/* If this interface has slaves, stop them also */
while (p) {
#ifdef CONFIG_ISDN_X25
- cprot = ( (isdn_net_local *) p->priv )
- -> netdev -> cprot;
- if( cprot && cprot -> pops )
+ cprot = ( (isdn_net_local *) p->priv )
+ -> netdev -> cprot;
+ if( cprot && cprot -> pops )
cprot -> pops -> close( cprot );
#endif
isdn_net_hangup(p);
@@ -1392,7 +1558,7 @@ isdn_net_slarp_send(isdn_net_local *lp, int is_reply)
int len;
cisco_hdr *ch;
cisco_slarp *s;
-
+
if (!skb) {
printk(KERN_WARNING
"%s: Could not allocate SLARP reply\n", lp->name);
@@ -1406,7 +1572,7 @@ isdn_net_slarp_send(isdn_net_local *lp, int is_reply)
s = (cisco_slarp *)skb_put(skb, sizeof(cisco_slarp));
if (is_reply) {
s->code = htonl(CISCO_SLARP_REPLY);
- memset(&s->slarp.reply.ifaddr, 0, sizeof(__u32));
+ memset(&s->slarp.reply.ifaddr, 0, sizeof(__u32));
memset(&s->slarp.reply.netmask, 0, sizeof(__u32));
} else {
lp->cisco_myseq++;
@@ -1589,7 +1755,7 @@ isdn_net_receive(struct device *ndev, struct sk_buff *skb)
default:
#ifdef CONFIG_ISDN_X25
/* try if there are generic sync_device receiver routines */
- if(cprot) if(cprot -> pops)
+ if(cprot) if(cprot -> pops)
if( cprot -> pops -> data_ind){
cprot -> pops -> data_ind(cprot,skb);
return;
@@ -1600,6 +1766,7 @@ isdn_net_receive(struct device *ndev, struct sk_buff *skb)
kfree_skb(skb);
return;
}
+
netif_rx(skb);
return;
}
@@ -1788,16 +1955,12 @@ isdn_net_init(struct device *ndev)
ndev->type = ARPHRD_ETHER;
ndev->addr_len = ETH_ALEN;
- ndev->tx_queue_len = 10; /* for clients without MPPP 5 is better. */
+ /* for clients with MPPP maybe higher values better */
+ ndev->tx_queue_len = 30;
for (i = 0; i < ETH_ALEN; i++)
ndev->broadcast[i] = 0xff;
-#ifdef DEV_NUMBUFFS
- for (i = 0; i < DEV_NUMBUFFS; i++)
- skb_queue_head_init(&ndev->buffs[i]);
-#endif
-
/* The ISDN-specific entries in the device structure. */
ndev->open = &isdn_net_open;
ndev->hard_start_xmit = &isdn_net_start_xmit;
@@ -1813,86 +1976,15 @@ isdn_net_init(struct device *ndev)
max_hlhdr_len = dev->drv[drvidx]->interface->hl_hdrlen;
ndev->hard_header_len = ETH_HLEN + max_hlhdr_len;
-
ndev->stop = &isdn_net_close;
ndev->get_stats = &isdn_net_get_stats;
ndev->rebuild_header = &isdn_net_rebuild_header;
-
#ifdef CONFIG_ISDN_PPP
ndev->do_ioctl = isdn_ppp_dev_ioctl;
#endif
return 0;
}
-/*
- * I picked the pattern-matching-functions from an old GNU-tar version (1.10)
- * It was originally written and put to PD by rs@mirror.TMC.COM (Rich Salz)
- */
-
-static int
-isdn_net_Star(char *s, char *p)
-{
- while (isdn_net_wildmat(s, p) == 0)
- if (*++s == '\0')
- return (0);
- return (1);
-}
-
-/*
- * Shell-type Pattern-matching for incoming caller-Ids
- * This function gets a string in s and checks, if it matches the pattern
- * given in p. It returns 1 on success, 0 otherwise.
- *
- * Possible Patterns:
- *
- * '?' matches one character
- * '*' matches zero or more characters
- * [xyz] matches the set of characters in brackets.
- * [^xyz] matches any single character not in the set of characters
- */
-
-static int
-isdn_net_wildmat(char *s, char *p)
-{
- register int last;
- register int matched;
- register int reverse;
-
- for (; *p; s++, p++)
- switch (*p) {
- case '\\':
- /*
- * Literal match with following character,
- * fall through.
- */
- p++;
- default:
- if (*s != *p)
- return (0);
- continue;
- case '?':
- /* Match anything. */
- if (*s == '\0')
- return (0);
- continue;
- case '*':
- /* Trailing star matches everything. */
- return (*++p ? isdn_net_Star(s, p) : 1);
- case '[':
- /* [^....] means inverse character class. */
- if ((reverse = (p[1] == '^')))
- p++;
- for (last = 0, matched = 0; *++p && (*p != ']'); last = *p)
- /* This next line requires a good C compiler. */
- if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
- matched = 1;
- if (matched == reverse)
- return (0);
- continue;
- }
- return (*s == '\0');
-}
-
static void
isdn_net_swapbind(int drvidx)
{
@@ -1945,6 +2037,8 @@ isdn_net_swap_usage(int i1, int i2)
* 2 = Reject call, wait cbdelay, then call back
* 3 = Reject call
* 4 = Wait cbdelay, then call back
+ * 5 = No appropriate interface for this call,
+ * would eventually match if CID was longer.
*/
int
isdn_net_find_icall(int di, int ch, int idx, setup_parm setup)
@@ -1953,6 +2047,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm setup)
int si1;
int si2;
int ematch;
+ int wret;
int swapped;
int sidx = 0;
isdn_net_dev *p;
@@ -1987,13 +2082,13 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm setup)
}
n = (isdn_net_phone *) 0;
p = dev->netdev;
- ematch = 0;
+ ematch = wret = swapped = 0;
#ifdef ISDN_DEBUG_NET_ICALL
printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx,
dev->usage[idx]);
#endif
- swapped = 0;
while (p) {
+ int matchret;
isdn_net_local *lp = p->local;
/* If last check has triggered as binding-swap, revert it */
@@ -2006,18 +2101,22 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm setup)
break;
}
swapped = 0;
- if (!strcmp(isdn_map_eaz2msn(lp->msn, di), eaz))
+ if (!(matchret = isdn_wildmat(eaz, isdn_map_eaz2msn(lp->msn, di))))
ematch = 1;
+ /* Remember if more numbers eventually can match */
+ if (matchret > wret)
+ wret = matchret;
#ifdef ISDN_DEBUG_NET_ICALL
printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n",
lp->name, lp->msn, lp->flags, lp->dialstate);
#endif
- if ((!strcmp(isdn_map_eaz2msn(lp->msn, di), eaz)) && /* EAZ is matching */
- (((!(lp->flags & ISDN_NET_CONNECTED)) && /* but not connected */
- (USG_NONE(dev->usage[idx]))) || /* and ch. unused or */
- ((((lp->dialstate == 4) || (lp->dialstate == 12)) && /* if dialing */
- (!(lp->flags & ISDN_NET_CALLBACK))) /* but no callback */
- ))) {
+ if ((!matchret) && /* EAZ is matching */
+ (((!(lp->flags & ISDN_NET_CONNECTED)) && /* but not connected */
+ (USG_NONE(dev->usage[idx]))) || /* and ch. unused or */
+ ((((lp->dialstate == 4) || (lp->dialstate == 12)) && /* if dialing */
+ (!(lp->flags & ISDN_NET_CALLBACK))) /* but no callback */
+ )))
+ {
#ifdef ISDN_DEBUG_NET_ICALL
printk(KERN_DEBUG "n_fi: match1, pdev=%d pch=%d\n",
lp->pre_device, lp->pre_channel);
@@ -2085,8 +2184,6 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm setup)
#ifdef ISDN_DEBUG_NET_ICALL
printk(KERN_DEBUG "n_fi: already on 2nd channel\n");
#endif
- p = (isdn_net_dev *) p->next;
- continue;
}
}
}
@@ -2096,7 +2193,7 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm setup)
n = lp->phone[0];
if (lp->flags & ISDN_NET_SECURE) {
while (n) {
- if (isdn_net_wildmat(nr, n->num))
+ if (!isdn_wildmat(nr, n->num))
break;
n = (isdn_net_phone *) n->next;
}
@@ -2105,7 +2202,21 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm setup)
#ifdef ISDN_DEBUG_NET_ICALL
printk(KERN_DEBUG "n_fi: match3\n");
#endif
- /* Here we got an interface matched, now see if it is up.
+ /* matching interface found */
+
+ /*
+ * Is the state STOPPED?
+ * If so, no dialin is allowed,
+ * so reject actively.
+ * */
+ if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
+ restore_flags(flags);
+ printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n",
+ lp->name);
+ return 3;
+ }
+ /*
+ * Is the interface up?
* If not, reject the call actively.
*/
if (!p->dev.start) {
@@ -2140,6 +2251,17 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm setup)
}
if (lp->flags & ISDN_NET_CALLBACK) {
int chi;
+ /*
+ * Is the state MANUAL?
+ * If so, no callback can be made,
+ * so reject actively.
+ * */
+ if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
+ restore_flags(flags);
+ printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n",
+ lp->name);
+ return 3;
+ }
printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n",
lp->name, nr, eaz);
if (lp->phone[1]) {
@@ -2155,7 +2277,6 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm setup)
/* Setup dialstate. */
lp->dtimer = 0;
lp->dialstate = 11;
- lp->flags |= ISDN_NET_CONNECTED;
/* Connect interface with channel */
isdn_net_bind_channel(lp, chi);
#ifdef CONFIG_ISDN_PPP
@@ -2217,10 +2338,10 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm setup)
p = (isdn_net_dev *) p->next;
}
/* If none of configured EAZ/MSN matched and not verbose, be silent */
- if (ematch || dev->net_verbose)
+ if (!ematch || dev->net_verbose)
printk(KERN_INFO "isdn_net: call from %s -> %d %s ignored\n", nr, di, eaz);
restore_flags(flags);
- return 0;
+ return (wret == 2)?5:0;
}
/*
@@ -2253,6 +2374,7 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
ulong flags;
save_flags(flags);
cli();
+
/* Grab a free ISDN-Channel */
if ((chi = isdn_get_free_channel(ISDN_USAGE_NET, lp->l2_proto,
lp->l3_proto,
@@ -2263,7 +2385,6 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
return -EAGAIN;
}
lp->dialstate = 1;
- lp->flags |= ISDN_NET_CONNECTED;
/* Connect interface with channel */
isdn_net_bind_channel(lp, chi);
#ifdef CONFIG_ISDN_PPP
@@ -2285,6 +2406,20 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
}
/*
+ * This is called from certain upper protocol layers (multilink ppp
+ * and x25iface encapsulation module) that want to initiate dialing
+ * themselves.
+ */
+int
+isdn_net_dial_req(isdn_net_local * lp)
+{
+ /* is there a better error code? */
+ if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) return -EBUSY;
+
+ return isdn_net_force_dial_lp(lp);
+}
+
+/*
* Force a net-interface to dial out.
* This is always called from within userspace (ISDN_IOCTL_NET_DIAL).
*/
@@ -2383,8 +2518,13 @@ isdn_net_new(char *name, struct device *master)
netdev->local->onhtime = 10; /* Default hangup-time for saving costs
of those who forget configuring this */
netdev->local->dialmax = 1;
- netdev->local->flags = ISDN_NET_CBHUP; /* Hangup before Callback */
+ netdev->local->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL; /* Hangup before Callback, manual dial */
netdev->local->cbdelay = 25; /* Wait 5 secs before Callback */
+ netdev->local->dialtimeout = -1; /* Infinite Dial-Timeout */
+ netdev->local->dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */
+ netdev->local->dialstarted = 0; /* Jiffies of last dial-start */
+ netdev->local->dialwait_timer = 0; /* Jiffies of earliest next dial-start */
+
/* Put into to netdev-chain */
netdev->next = (void *) dev->netdev;
dev->netdev = netdev;
@@ -2465,7 +2605,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
save_flags(flags);
cli(); /* avoid races with incoming events trying to
call cprot->pops methods */
- if( cprot && cprot -> pops )
+ if( cprot && cprot -> pops )
cprot -> pops -> proto_del ( cprot );
p -> cprot = NULL;
lp -> dops = NULL;
@@ -2479,7 +2619,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
p -> cprot = isdn_concap_new( cfg -> p_encap );
/* p -> cprot == NULL now if p_encap is not supported
by means of the concap_proto mechanism */
- /* the protocol is not configured yet; this will
+ /* the protocol is not configured yet; this will
happen later when isdn_net_reset() is called */
#endif
}
@@ -2508,7 +2648,7 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
if( cfg->p_encap >= 0 &&
cfg->p_encap <= ISDN_NET_ENCAP_MAX_ENCAP )
break;
- printk(KERN_WARNING
+ printk(KERN_WARNING
"%s: encapsulation protocol %d not supported\n",
p->local->name, cfg->p_encap);
return -EINVAL;
@@ -2583,6 +2723,8 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
lp->triggercps = cfg->triggercps;
lp->slavedelay = cfg->slavedelay * HZ;
lp->pppbind = cfg->pppbind;
+ lp->dialtimeout = cfg->dialtimeout >= 0 ? cfg->dialtimeout * HZ : -1;
+ lp->dialwait = cfg->dialwait * HZ;
if (cfg->secure)
lp->flags |= ISDN_NET_SECURE;
else
@@ -2604,6 +2746,16 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
lp->flags &= ~ISDN_NET_CALLBACK;
break;
}
+ lp->flags &= ~ISDN_NET_DIALMODE_MASK; /* first all bits off */
+ if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) {
+ /* old isdnctrl version, where only 0 or 1 is given */
+ printk(KERN_WARNING
+ "Old isdnctrl version detected! Please update.\n");
+ lp->flags |= ISDN_NET_DM_OFF; /* turn on `off' bit */
+ }
+ else {
+ lp->flags |= cfg->dialmode; /* turn on selected bits */
+ }
if (cfg->chargehup)
lp->hupflags |= ISDN_CHARGEHUP;
else
@@ -2671,6 +2823,7 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
if (lp->flags & ISDN_NET_CBOUT)
cfg->callback = 2;
cfg->cbhup = (lp->flags & ISDN_NET_CBHUP) ? 1 : 0;
+ cfg->dialmode = lp->flags & ISDN_NET_DIALMODE_MASK;
cfg->chargehup = (lp->hupflags & 4) ? 1 : 0;
cfg->ihup = (lp->hupflags & 8) ? 1 : 0;
cfg->cbdelay = lp->cbdelay;
@@ -2680,6 +2833,8 @@ isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
cfg->chargeint = (lp->hupflags & ISDN_CHARGEHUP) ?
(lp->chargeint / HZ) : 0;
cfg->pppbind = lp->pppbind;
+ cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1;
+ cfg->dialwait = lp->dialwait / HZ;
if (lp->slave)
strcpy(cfg->slave, ((isdn_net_local *) lp->slave->priv)->name);
else
@@ -2749,9 +2904,37 @@ isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
}
/*
- * Delete a phone-number from an interface.
+ * Copy a string containing the peer's phone number of a connected interface
+ * to user space.
*/
+int
+isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone *peer)
+{
+ isdn_net_dev *p = isdn_net_findif(phone->name);
+ int ch, dv, idx;
+ if (!p) return -ENODEV;
+ /*
+ * Theoretical race: while this executes, the remote number might
+ * become invalid (hang up) or change (new connection), resulting
+ * in (partially) wrong number copied to user. This race
+ * currently ignored.
+ */
+ ch = p->local->isdn_channel;
+ dv = p->local->isdn_device;
+ if(ch<0 && dv<0) return -ENOTCONN;
+ idx = isdn_dc2minor(dv, ch);
+ if (idx<0) return -ENODEV;
+ /* for pre-bound channels, we need this extra check */
+ if ( strncmp(dev->num[idx],"???",3) == 0 ) return -ENOTCONN;
+ strncpy(phone->phone,dev->num[idx],ISDN_MSNLEN);
+ phone->outgoing=USG_OUTGOING(idx);
+ if ( copy_to_user(peer,phone,sizeof(*peer)) ) return -EFAULT;
+ return 0;
+}
+/*
+ * Delete a phone-number from an interface.
+ */
int
isdn_net_delphone(isdn_net_ioctl_phone * phone)
{
@@ -2957,21 +3140,3 @@ isdn_net_rmall(void)
restore_flags(flags);
return 0;
}
-
-#ifdef DEV_NUMBUFFS
-/*
- * helper function to flush device queues
- * the better place would be net/core/dev.c
- */
-static void
-dev_purge_queues(struct device *dev)
-{
- int i;
- for (i = 0; i < DEV_NUMBUFFS; i++) {
- struct sk_buff *skb;
- while ((skb = skb_dequeue(&dev->buffs[i])))
- dev_kfree_skb(skb);
- }
-
-}
-#endif
diff --git a/drivers/isdn/isdn_net.h b/drivers/isdn/isdn_net.h
index 19a084dd2..79d4ff615 100644
--- a/drivers/isdn/isdn_net.h
+++ b/drivers/isdn/isdn_net.h
@@ -1,8 +1,8 @@
-/* $Id: isdn_net.h,v 1.6 1997/10/09 21:28:54 fritz Exp $
+/* $Id: isdn_net.h,v 1.9 1999/04/12 12:33:27 fritz Exp $
* header for Linux ISDN subsystem, network related functions (linklevel).
*
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
* Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg
* Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
*
@@ -21,6 +21,16 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_net.h,v $
+ * Revision 1.9 1999/04/12 12:33:27 fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.8 1998/10/30 17:55:33 he
+ * dialmode for x25iface and multulink ppp
+ *
+ * Revision 1.7 1998/08/31 21:09:55 he
+ * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface'
+ * peer phone number)
+ *
* Revision 1.6 1997/10/09 21:28:54 fritz
* New HL<->LL interface:
* New BSENT callback with nr. of bytes included.
@@ -99,6 +109,7 @@ extern int isdn_net_setcfg(isdn_net_ioctl_cfg *);
extern int isdn_net_getcfg(isdn_net_ioctl_cfg *);
extern int isdn_net_addphone(isdn_net_ioctl_phone *);
extern int isdn_net_getphones(isdn_net_ioctl_phone *, char *);
+extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *);
extern int isdn_net_delphone(isdn_net_ioctl_phone *);
extern int isdn_net_find_icall(int, int, int, setup_parm);
extern void isdn_net_hangup(struct device *);
@@ -111,3 +122,4 @@ extern int isdn_net_send_skb(struct device *, isdn_net_local *,
struct sk_buff *);
extern int isdn_net_rcv_skb(int, struct sk_buff *);
extern void isdn_net_slarp_out(void);
+extern int isdn_net_dial_req(isdn_net_local *);
diff --git a/drivers/isdn/isdn_ppp.c b/drivers/isdn/isdn_ppp.c
index 5da3a49f0..7bce66d44 100644
--- a/drivers/isdn/isdn_ppp.c
+++ b/drivers/isdn/isdn_ppp.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.c,v 1.33 1998/02/20 17:11:54 fritz Exp $
+/* $Id: isdn_ppp.c,v 1.47 1999/04/18 14:06:59 fritz Exp $
*
* Linux ISDN subsystem, functions for synchronous PPP (linklevel).
*
@@ -18,11 +18,50 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * Note: This file differs from the corresponding revision as present in the
- * isdn4linux CVS repository because some later bug fixes have been extracted
- * from the repository and merged into this file. -- Henner Eisen
- *
* $Log: isdn_ppp.c,v $
+ * Revision 1.47 1999/04/18 14:06:59 fritz
+ * Removed TIMRU stuff.
+ *
+ * Revision 1.46 1999/04/12 12:33:35 fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.45 1998/12/30 17:48:24 paul
+ * fixed syncPPP callback out
+ *
+ * Revision 1.44 1998/10/30 17:55:34 he
+ * dialmode for x25iface and multulink ppp
+ *
+ * Revision 1.43 1998/10/29 17:23:54 hipp
+ * Minor MPPP fixes, verboser logging.
+ *
+ * Revision 1.42 1998/07/20 11:30:07 hipp
+ * Readded compression check
+ *
+ * Revision 1.41 1998/07/08 16:50:57 hipp
+ * Compression changes
+ *
+ * Revision 1.40 1998/04/06 19:07:27 hipp
+ * added check, whether compression is enabled.
+ *
+ * Revision 1.39 1998/03/25 22:46:53 hipp
+ * Some additional CCP changes.
+ *
+ * Revision 1.38 1998/03/24 16:33:06 hipp
+ * More CCP changes. BSD compression now "works" on a local loopback link.
+ * Moved some isdn_ppp stuff from isdn.h to isdn_ppp.h
+ *
+ * Revision 1.37 1998/03/22 18:50:49 hipp
+ * Added BSD Compression for syncPPP .. UNTESTED at the moment
+ *
+ * Revision 1.36 1998/03/09 17:46:30 he
+ * merged in 2.1.89 changes
+ *
+ * Revision 1.35 1998/03/07 18:21:11 cal
+ * Dynamic Timeout-Rule-Handling vs. 971110 included
+ *
+ * Revision 1.34 1998/02/25 17:49:48 he
+ * Changed return codes caused be failing copy_{to,from}_user to -EFAULT
+ *
* Revision 1.33 1998/02/20 17:11:54 fritz
* Changes for recent kernels.
*
@@ -157,13 +196,16 @@
* experimental for dynamic addressing: readdress IP frames
*/
#undef ISDN_SYNCPPP_READDRESS
+#define CONFIG_ISDN_CCP 1
#include <linux/config.h>
#define __NO_VERSION__
#include <linux/module.h>
#include <linux/version.h>
-#include <linux/isdn.h>
#include <linux/poll.h>
+#include <linux/isdn.h>
+#include <linux/ppp-comp.h>
+
#include "isdn_common.h"
#include "isdn_ppp.h"
#include "isdn_net.h"
@@ -180,13 +222,33 @@ static int isdn_ppp_closewait(int slot);
static void isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp,
struct sk_buff *skb, int proto);
static int isdn_ppp_if_get_unit(char *namebuf);
-static int isdn_ppp_set_compressor(struct ippp_struct *is,int num);
+static int isdn_ppp_set_compressor(struct ippp_struct *is,struct isdn_ppp_comp_data *);
static struct sk_buff *isdn_ppp_decompress(struct sk_buff *,
- struct ippp_struct *,struct ippp_struct *);
+ struct ippp_struct *,struct ippp_struct *,int proto);
static void isdn_ppp_receive_ccp(isdn_net_dev * net_dev, isdn_net_local * lp,
- struct sk_buff *skb);
+ struct sk_buff *skb,int proto);
static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
struct ippp_struct *is,struct ippp_struct *master,int type);
+static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
+ struct sk_buff *skb);
+
+/* New CCP stuff */
+static void isdn_ppp_ccp_kickup(struct ippp_struct *is);
+static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
+ unsigned char code, unsigned char id,
+ unsigned char *data, int len);
+static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is);
+static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
+ unsigned char id);
+static void isdn_ppp_ccp_timer_callback(unsigned long closure);
+static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is,
+ unsigned char id);
+static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is,
+ struct isdn_ppp_resetparams *rp);
+static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
+ unsigned char id);
+
+
#ifdef CONFIG_ISDN_MPP
static int isdn_ppp_bundle(struct ippp_struct *, int unit);
@@ -199,18 +261,16 @@ static int isdn_ppp_fill_mpqueue(isdn_net_dev *, struct sk_buff **skb,
static void isdn_ppp_free_mpqueue(isdn_net_dev *);
#endif
-char *isdn_ppp_revision = "$Revision: 1.33 $";
+char *isdn_ppp_revision = "$Revision: 1.47 $";
static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
static struct isdn_ppp_compressor *ipc_head = NULL;
-extern int isdn_net_force_dial_lp(isdn_net_local *);
-
/*
* frame log (debug)
*/
static void
-isdn_ppp_frame_log(char *info, char *data, int len, int maxlen)
+isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot)
{
int cnt,
j,
@@ -223,13 +283,14 @@ isdn_ppp_frame_log(char *info, char *data, int len, int maxlen)
for (i = 0, cnt = 0; cnt < maxlen; i++) {
for (j = 0; j < 16 && cnt < maxlen; j++, cnt++)
sprintf(buf + j * 3, "%02x ", (unsigned char) data[cnt]);
- printk(KERN_DEBUG "%s[%d]: %s\n", info, i, buf);
+ printk(KERN_DEBUG "[%d/%d].%s[%d]: %s\n",unit,slot, info, i, buf);
}
}
/*
* unbind isdn_net_local <=> ippp-device
* note: it can happen, that we hangup/free the master before the slaves
+ * in this case we bind another lp to the master device
*/
int
isdn_ppp_free(isdn_net_local * lp)
@@ -267,8 +328,7 @@ isdn_ppp_free(isdn_net_local * lp)
if ((is->state & IPPP_CONNECT))
isdn_ppp_closewait(lp->ppp_slot); /* force wakeup on ippp device */
else if (is->state & IPPP_ASSIGNED)
- is->state = IPPP_OPEN; /* fallback to 'OPEN but not ASSIGEND' staet */
-
+ is->state = IPPP_OPEN; /* fallback to 'OPEN but not ASSIGNED' state */
if (is->debug & 0x1)
printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_slot, (long) lp, (long) is->lp);
@@ -320,14 +380,16 @@ isdn_ppp_bind(isdn_net_local * lp)
}
}
} else {
- for (i = 0; i < ISDN_MAX_CHANNELS; i++)
- if (ippp_table[i]->minor == lp->pppbind && ippp_table[i]->state == IPPP_OPEN)
+ for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+ if (ippp_table[i]->minor == lp->pppbind &&
+ (ippp_table[i]->state & IPPP_OPEN) == IPPP_OPEN)
break;
+ }
}
if (i >= ISDN_MAX_CHANNELS) {
restore_flags(flags);
- printk(KERN_WARNING "isdn_ppp_bind: Can't find usable ippp device.\n");
+ printk(KERN_WARNING "isdn_ppp_bind: Can't find a (free) connection to the ipppd daemon.\n");
return -1;
}
unit = isdn_ppp_if_get_unit(lp->name); /* get unit number from interface name .. ugly! */
@@ -336,6 +398,15 @@ isdn_ppp_bind(isdn_net_local * lp)
return -1;
}
lp->ppp_slot = i;
+
+ /* reset some values */
+ lp->netdev->ib.bundled = 0;
+ lp->netdev->ib.next_num = 0;
+ lp->netdev->ib.modify = 0;
+ lp->netdev->ib.last = NULL;
+ lp->netdev->ib.min = 0;
+ lp->netdev->ib.sq = NULL;
+
is = ippp_table[i];
is->lp = lp;
is->unit = unit;
@@ -359,7 +430,9 @@ isdn_ppp_wakeup_daemon(isdn_net_local * lp)
ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
+#if LINUX_VERSION_CODE < 131841
if (ippp_table[lp->ppp_slot]->wq)
+#endif
wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
}
@@ -377,7 +450,11 @@ isdn_ppp_closewait(int slot)
return 0;
is = ippp_table[slot];
+#if LINUX_VERSION_CODE < 131841
if (is->state && is->wq)
+#else
+ if (is->state)
+#endif
wake_up_interruptible(&is->wq);
is->state = IPPP_CLOSEWAIT;
@@ -418,14 +495,19 @@ isdn_ppp_open(int min, struct file *file)
}
is = file->private_data = ippp_table[slot];
+#if 0
if (is->debug & 0x1)
+#endif
printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n", slot, min, is->state);
/* compression stuff */
- is->compressor = NULL;
- is->decomp_stat = is->comp_stat = NULL;
- is->link_compressor = NULL;
- is->link_decomp_stat = is->link_comp_stat = NULL;
+ is->link_compressor = is->compressor = NULL;
+ is->link_decompressor = is->decompressor = NULL;
+ is->link_comp_stat = is->comp_stat = NULL;
+ is->link_decomp_stat = is->decomp_stat = NULL;
+ is->compflags = 0;
+
+ is->reset = isdn_ppp_ccp_reset_alloc(is);
is->lp = NULL;
is->mp_seqno = 0; /* MP sequence number */
@@ -437,8 +519,11 @@ isdn_ppp_open(int min, struct file *file)
is->mru = 1524; /* MRU, default 1524 */
is->maxcid = 16; /* VJ: maxcid */
is->tk = current;
+#if LINUX_VERSION_CODE < 131841
is->wq = NULL; /* read() wait queue */
- is->wq1 = NULL; /* select() wait queue */
+#else
+ init_waitqueue_head(&is->wq);
+#endif
is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
is->last = is->rq;
is->minor = min;
@@ -491,10 +576,30 @@ isdn_ppp_release(int min, struct file *file)
is->last = is->rq;
#ifdef CONFIG_ISDN_PPP_VJ
+/* TODO: if this was the previous master: link the slcomp to the new master */
slhc_free(is->slcomp);
is->slcomp = NULL;
#endif
+/* TODO: if this was the previous master: link the the stuff to the new master */
+ if(is->comp_stat)
+ is->compressor->free(is->comp_stat);
+ if(is->link_comp_stat)
+ is->link_compressor->free(is->link_comp_stat);
+ if(is->link_decomp_stat)
+ is->link_decompressor->free(is->link_decomp_stat);
+ if(is->decomp_stat)
+ is->decompressor->free(is->decomp_stat);
+ is->compressor = is->link_compressor = NULL;
+ is->decompressor = is->link_decompressor = NULL;
+ is->comp_stat = is->link_comp_stat = NULL;
+ is->decomp_stat = is->link_decomp_stat = NULL;
+
+ if(is->reset)
+ kfree(is->reset);
+ is->reset = NULL;
+
+ /* this slot is ready for new connections */
is->state = 0;
}
@@ -505,7 +610,7 @@ static int
get_arg(void *b, void *val, int len)
{
if (len <= 0)
- len = sizeof(unsigned long);
+ len = sizeof(void *);
if (copy_from_user((void *) val, b, len))
return -EFAULT;
return 0;
@@ -515,15 +620,12 @@ get_arg(void *b, void *val, int len)
* set arg .. ioctl helper
*/
static int
-set_arg(void *b, unsigned long val, void *str)
+set_arg(void *b, void *val,int len)
{
- if (!str) {
- if (copy_to_user(b, (void *) &val, 4))
- return -EFAULT;
- } else {
- if (copy_to_user(b, str, val))
- return -EFAULT;
- }
+ if(len <= 0)
+ len = sizeof(void *);
+ if (copy_to_user(b, (void *) val, len))
+ return -EFAULT;
return 0;
}
@@ -534,9 +636,10 @@ int
isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
{
unsigned long val;
- int num,r;
+ int r,i,j;
struct ippp_struct *is;
isdn_net_local *lp;
+ struct isdn_ppp_comp_data data;
is = (struct ippp_struct *) file->private_data;
lp = is->lp;
@@ -552,7 +655,7 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
#ifdef CONFIG_ISDN_MPP
if (!(is->state & IPPP_CONNECT))
return -EINVAL;
- if ((r = get_arg((void *) arg, &val, 0)))
+ if ((r = get_arg((void *) arg, &val, sizeof(val) )))
return r;
printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
(int) min, (int) is->unit, (int) val);
@@ -562,24 +665,30 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
#endif
break;
case PPPIOCGUNIT: /* get ppp/isdn unit number */
- if ((r = set_arg((void *) arg, is->unit, NULL)))
+ if ((r = set_arg((void *) arg, &is->unit, sizeof(is->unit) )))
+ return r;
+ break;
+ case PPPIOCGIFNAME:
+ if(!lp)
+ return -EINVAL;
+ if ((r = set_arg((void *) arg, lp->name,strlen(lp->name))))
return r;
break;
case PPPIOCGMPFLAGS: /* get configuration flags */
- if ((r = set_arg((void *) arg, is->mpppcfg, NULL)))
+ if ((r = set_arg((void *) arg, &is->mpppcfg, sizeof(is->mpppcfg) )))
return r;
break;
case PPPIOCSMPFLAGS: /* set configuration flags */
- if ((r = get_arg((void *) arg, &val, 0)))
+ if ((r = get_arg((void *) arg, &val, sizeof(val) )))
return r;
is->mpppcfg = val;
break;
case PPPIOCGFLAGS: /* get configuration flags */
- if ((r = set_arg((void *) arg, is->pppcfg, NULL)))
+ if ((r = set_arg((void *) arg, &is->pppcfg,sizeof(is->pppcfg) )))
return r;
break;
case PPPIOCSFLAGS: /* set configuration flags */
- if ((r = get_arg((void *) arg, &val, 0))) {
+ if ((r = get_arg((void *) arg, &val, sizeof(val) ))) {
return r;
}
if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) {
@@ -598,12 +707,12 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
if (lp) {
struct ppp_idle pidle;
pidle.xmit_idle = pidle.recv_idle = lp->huptimer;
- if ((r = set_arg((void *) arg, sizeof(struct ppp_idle), &pidle)))
+ if ((r = set_arg((void *) arg, &pidle,sizeof(struct ppp_idle))))
return r;
}
break;
case PPPIOCSMRU: /* set receive unit size for PPP */
- if ((r = get_arg((void *) arg, &val, 0)))
+ if ((r = get_arg((void *) arg, &val, sizeof(val) )))
return r;
is->mru = val;
break;
@@ -612,7 +721,7 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
case PPPIOCSMPMTU:
break;
case PPPIOCSMAXCID: /* set the maximum compression slot id */
- if ((r = get_arg((void *) arg, &val, 0)))
+ if ((r = get_arg((void *) arg, &val, sizeof(val) )))
return r;
val++;
if (is->maxcid != val) {
@@ -635,31 +744,33 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
}
break;
case PPPIOCGDEBUG:
- if ((r = set_arg((void *) arg, is->debug, 0)))
+ if ((r = set_arg((void *) arg, &is->debug, sizeof(is->debug) )))
return r;
break;
case PPPIOCSDEBUG:
- if ((r = get_arg((void *) arg, &val, 0)))
+ if ((r = get_arg((void *) arg, &val, sizeof(val) )))
return r;
is->debug = val;
break;
case PPPIOCGCOMPRESSORS:
{
- unsigned long protos = 0;
+ unsigned long protos[8] = {0,};
struct isdn_ppp_compressor *ipc = ipc_head;
while(ipc) {
- protos |= (0x1<<ipc->num);
+ j = ipc->num / (sizeof(long)*8);
+ i = ipc->num % (sizeof(long)*8);
+ if(j < 8)
+ protos[j] |= (0x1<<i);
ipc = ipc->next;
}
- if ((r = set_arg((void *) arg, protos, 0)))
+ if ((r = set_arg((void *) arg,protos,8*sizeof(long) )))
return r;
}
break;
case PPPIOCSCOMPRESSOR:
- if ((r = get_arg((void *) arg, &num, sizeof(int))))
+ if ((r = get_arg((void *) arg, &data, sizeof(struct isdn_ppp_comp_data))))
return r;
- return isdn_ppp_set_compressor(is, num);
- break;
+ return isdn_ppp_set_compressor(is, &data);
case PPPIOCGCALLINFO:
{
struct pppcallinfo pci;
@@ -678,7 +789,7 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
if(lp->flags & ISDN_NET_CALLBACK)
pci.calltype |= CALLTYPE_CALLBACK;
}
- return set_arg((void *)arg,sizeof(struct pppcallinfo),&pci);
+ return set_arg((void *)arg,&pci,sizeof(struct pppcallinfo));
}
default:
break;
@@ -701,9 +812,12 @@ isdn_ppp_poll(struct file *file, poll_table * wait)
printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n",
MINOR(file->f_dentry->d_inode->i_rdev));
+ /* just registers wait_queue hook. This doesn't really wait. */
poll_wait(file, &is->wq, wait);
if (!(is->state & IPPP_OPEN)) {
+ if(is->state == IPPP_CLOSEWAIT)
+ return POLLHUP;
printk(KERN_DEBUG "isdn_ppp: device not open\n");
return POLLERR;
}
@@ -777,7 +891,9 @@ isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot)
is->last = bl->next;
restore_flags(flags);
+#if LINUX_VERSION_CODE < 131841
if (is->wq)
+#endif
wake_up_interruptible(&is->wq);
return len;
@@ -864,7 +980,8 @@ isdn_ppp_write(int min, struct file *file, const char *buf, int count)
if (lp->isdn_device < 0 || lp->isdn_channel < 0)
return 0;
- if (dev->drv[lp->isdn_device]->running && lp->dialstate == 0 &&
+ if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) &&
+ lp->dialstate == 0 &&
(lp->flags & ISDN_NET_CONNECTED)) {
int cnt;
struct sk_buff *skb;
@@ -877,8 +994,11 @@ isdn_ppp_write(int min, struct file *file, const char *buf, int count)
return -EFAULT;
if (is->debug & 0x40) {
printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len);
- isdn_ppp_frame_log("xmit", skb->data, skb->len, 32);
+ isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
}
+
+ isdn_ppp_send_ccp(lp->netdev,lp,skb); /* keeps CCP/compression states in sync */
+
if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb)) != count) {
if (lp->sav_skb) {
dev_kfree_skb(lp->sav_skb);
@@ -962,8 +1082,9 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
is = ippp_table[lp->ppp_slot];
if (is->debug & 0x4) {
- printk(KERN_DEBUG "ippp_receive: len: %d\n", (int) skb->len);
- isdn_ppp_frame_log("receive", skb->data, skb->len, 32);
+ printk(KERN_DEBUG "ippp_receive: is:%08lx lp:%08lx slot:%d unit:%d len:%d\n",
+ (long)is,(long)lp,lp->ppp_slot,is->unit,(int) skb->len);
+ isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
}
if (net_dev->local->master) {
printk(KERN_WARNING "isdn_ppp_receice: net_dev != master\n");
@@ -981,13 +1102,18 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
#ifdef CONFIG_ISDN_MPP
if (!(is->mpppcfg & SC_REJ_MP_PROT)) {
int sqno_end;
-
- if(proto == PPP_LINK_COMP) {
- printk(KERN_DEBUG "received single link compressed frame\n");
- skb = isdn_ppp_decompress(skb,is,NULL);
- if(!skb)
- return;
- proto = isdn_ppp_strip_proto(skb);
+
+ if(is->compflags & SC_LINK_DECOMP_ON) {
+ if(proto == PPP_LINK_COMP) {
+ if(is->debug & 0x10)
+ printk(KERN_DEBUG "received single link compressed frame\n");
+ skb = isdn_ppp_decompress(skb,is,NULL,proto);
+ if(!skb)
+ return;
+ proto = isdn_ppp_strip_proto(skb);
+ }
+ else
+ isdn_ppp_decompress(skb,is,NULL,proto);
}
if (proto == PPP_MP) {
@@ -1054,7 +1180,8 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
}
min_sqno &= mask;
for (lpq = net_dev->queue;;) {
- ippp_table[lpq->ppp_slot]->last_link_seqno &= mask;
+ if(ippp_table[lpq->ppp_slot]->last_link_seqno >= 0)
+ ippp_table[lpq->ppp_slot]->last_link_seqno &= mask;
lpq = lpq->next;
if (lpq == net_dev->queue)
break;
@@ -1149,17 +1276,31 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
if (is->debug & 0x10) {
printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto);
- isdn_ppp_frame_log("rpush", skb->data, skb->len, 32);
+ isdn_ppp_frame_log("rpush", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
}
if(proto == PPP_COMP) {
if(!lp->master)
- skb = isdn_ppp_decompress(skb,is,is);
+ skb = isdn_ppp_decompress(skb,is,is,proto);
else
- skb = isdn_ppp_decompress(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot]);
- if(!skb)
+ skb = isdn_ppp_decompress(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot],proto);
+
+ if(!skb) {
+ printk(KERN_DEBUG "ippp: compressed frame discarded!\n");
return;
+ }
+
proto = isdn_ppp_strip_proto(skb);
+ if (is->debug & 0x10) {
+ printk(KERN_DEBUG "RPostDecomp, skb %d %04x\n", (int) skb->len, proto);
+ isdn_ppp_frame_log("R-Decomp", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
+ }
+ }
+ else if(is->compflags & SC_DECOMP_ON) { /* If decomp is ON */
+ if(!lp->master)
+ isdn_ppp_decompress(skb,is,is,proto);
+ else
+ isdn_ppp_decompress(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot],proto);
}
switch (proto) {
@@ -1226,7 +1367,13 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
#endif
break;
case PPP_CCP:
- isdn_ppp_receive_ccp(net_dev,lp,skb);
+ case PPP_LINK_CCP:
+ isdn_ppp_receive_ccp(net_dev,lp,skb,proto);
+ /* Dont pop up ResetReq/Ack stuff to the daemon any
+ longer - the job is done already */
+ if(skb->data[0] == CCP_RESETREQ ||
+ skb->data[0] == CCP_RESETACK)
+ break;
/* fall through */
default:
isdn_ppp_fill_rq(skb->data, skb->len, proto, lp->ppp_slot); /* push data to pppd device */
@@ -1234,10 +1381,10 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
return;
}
+ /* Reset hangup-timer */
+ lp->huptimer = 0;
netif_rx(skb);
/* net_dev->local->stats.rx_packets++; *//* done in isdn_net.c */
- /* Reset hangup-timer */
- lp->huptimer = 0;
return;
}
@@ -1338,7 +1485,6 @@ isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
lp = nlp;
}
ipt = ippp_table[lp->ppp_slot];
-
lp->huptimer = 0;
/*
@@ -1354,6 +1500,8 @@ isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
if (ipt->debug & 0x4)
printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len);
+ if (ipts->debug & 0x40)
+ isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32,ipts->unit,lp->ppp_slot);
#ifdef CONFIG_ISDN_PPP_VJ
if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes, but check this again */
@@ -1393,10 +1541,11 @@ isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
}
#endif
- /*
- * normal or bundle compression
- */
- skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0);
+ /*
+ * normal (single link) or bundle compression
+ */
+ if(ipts->compflags & SC_COMP_ON)
+ skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0);
if (ipt->debug & 0x24)
printk(KERN_DEBUG "xmit2 skb, len %d, proto %04x\n", (int) skb->len, proto);
@@ -1430,9 +1579,10 @@ isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
#endif
/*
- * 'link' compression
+ * 'link in bundle' compression ...
*/
- skb = isdn_ppp_compress(skb,&proto,ipt,ipts,1);
+ if(ipt->compflags & SC_LINK_COMP_ON)
+ skb = isdn_ppp_compress(skb,&proto,ipt,ipts,1);
if( (ipt->pppcfg & SC_COMP_PROT) && (proto <= 0xff) ) {
unsigned char *data = isdn_ppp_skb_push(&skb,1);
@@ -1459,7 +1609,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
if (ipts->debug & 0x40) {
printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len);
- isdn_ppp_frame_log("xmit", skb->data, skb->len, 32);
+ isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,ipt->unit,lp->ppp_slot);
}
if (isdn_net_send_skb(dev, lp, skb)) {
if (lp->sav_skb) { /* whole sav_skb processing with disabled IRQs ?? */
@@ -1473,6 +1623,12 @@ isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
#ifdef CONFIG_ISDN_MPP
+/*
+ * free SQ queue
+ * -------------
+ * Note: We need two queues for MPPP. The SQ queue holds fully (re)assembled frames,
+ * that can't be delivered, because there is an outstanding earlier frame
+ */
static void
isdn_ppp_free_sqqueue(isdn_net_dev * p)
{
@@ -1489,6 +1645,12 @@ isdn_ppp_free_sqqueue(isdn_net_dev * p)
}
+/*
+ * free MP queue
+ * -------------
+ * Note: The MP queue holds all frame fragments of frames, that can't be
+ * reassembled, because there is at least one missing fragment.
+ */
static void
isdn_ppp_free_mpqueue(isdn_net_dev * p)
{
@@ -1550,7 +1712,9 @@ isdn_ppp_bundle(struct ippp_struct *is, int unit)
return 0;
}
-
+/*
+ * Mask sequence numbers in MP queue
+ */
static void
isdn_ppp_mask_queue(isdn_net_dev * dev, long mask)
{
@@ -1561,6 +1725,11 @@ isdn_ppp_mask_queue(isdn_net_dev * dev, long mask)
}
}
+/*
+ * put a fragment at the right place into the MP queue
+ * Also checks, whether this fragment completes a frame. In this case
+ * the fragments are copied together into one SKB
+ */
static int
isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff **skb, int BEbyte, long *sqnop, int min_sqno)
{
@@ -1761,13 +1930,11 @@ isdn_ppp_cleanup_mpqueue(isdn_net_dev * dev, long min_sqno)
slhc_toss(ippp_table[dev->local->ppp_slot]->slcomp);
#endif
}
+#endif
/*
* a buffered packet timed-out?
*/
-
-#endif
-
void
isdn_ppp_timer_timeout(void)
{
@@ -1939,7 +2106,7 @@ isdn_ppp_dial_slave(char *name)
if (!sdev)
return 2;
- isdn_net_force_dial_lp((isdn_net_local *) sdev->priv);
+ isdn_net_dial_req((isdn_net_local *) sdev->priv);
return 0;
#else
return -1;
@@ -1980,47 +2147,440 @@ isdn_ppp_hangup_slave(char *name)
/*
* PPP compression stuff
*/
-static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struct *is,struct ippp_struct *master)
+
+
+/* Push an empty CCP Data Frame up to the daemon to wake it up and let it
+ generate a CCP Reset-Request or tear down CCP altogether */
+
+static void isdn_ppp_ccp_kickup(struct ippp_struct *is)
+{
+ isdn_ppp_fill_rq(NULL, 0, PPP_COMP, is->lp->ppp_slot);
+}
+
+/* In-kernel handling of CCP Reset-Request and Reset-Ack is necessary,
+ but absolutely nontrivial. The most abstruse problem we are facing is
+ that the generation, reception and all the handling of timeouts and
+ resends including proper request id management should be entirely left
+ to the (de)compressor, but indeed is not covered by the current API to
+ the (de)compressor. The API is a prototype version from PPP where only
+ some (de)compressors have yet been implemented and all of them are
+ rather simple in their reset handling. Especially, their is only one
+ outstanding ResetAck at a time with all of them and ResetReq/-Acks do
+ not have parameters. For this very special case it was sufficient to
+ just return an error code from the decompressor and have a single
+ reset() entry to communicate all the necessary information between
+ the framework and the (de)compressor. Bad enough, LZS is different
+ (and any other compressor may be different, too). It has multiple
+ histories (eventually) and needs to Reset each of them independently
+ and thus uses multiple outstanding Acks and history numbers as an
+ additional parameter to Reqs/Acks.
+ All that makes it harder to port the reset state engine into the
+ kernel because it is not just the same simple one as in (i)pppd but
+ it must be able to pass additional parameters and have multiple out-
+ standing Acks. We are trying to achieve the impossible by handling
+ reset transactions independent by their id. The id MUST change when
+ the data portion changes, thus any (de)compressor who uses more than
+ one resettable state must provide and recognize individual ids for
+ each individual reset transaction. The framework itself does _only_
+ differentiate them by id, because it has no other semantics like the
+ (de)compressor might.
+ This looks like a major redesign of the interface would be nice,
+ but I don't have an idea how to do it better. */
+
+/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. This is
+ getting that lengthy because there is no simple "send-this-frame-out"
+ function above but every wrapper does a bit different. Hope I guess
+ correct in this hack... */
+
+static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
+ unsigned char code, unsigned char id,
+ unsigned char *data, int len)
+{
+ struct sk_buff *skb;
+ unsigned char *p;
+ int count;
+ int cnt = 0;
+ isdn_net_local *lp = is->lp;
+
+ /* Alloc large enough skb */
+ skb = dev_alloc_skb(len + 16);
+ if(!skb) {
+ printk(KERN_WARNING
+ "ippp: CCP cannot send reset - out of memory\n");
+ return;
+ }
+
+ /* We may need to stuff an address and control field first */
+ if(!(is->pppcfg & SC_COMP_AC)) {
+ p = skb_put(skb, 2);
+ *p++ = 0xff;
+ *p++ = 0x03;
+ }
+
+ /* Stuff proto, code, id and length */
+ p = skb_put(skb, 6);
+ *p++ = (proto >> 8);
+ *p++ = (proto & 0xff);
+ *p++ = code;
+ *p++ = id;
+ cnt = 4 + len;
+ *p++ = (cnt >> 8);
+ *p++ = (cnt & 0xff);
+
+ /* Now stuff remaining bytes */
+ if(len) {
+ p = skb_put(skb, len);
+ memcpy(p, data, len);
+ }
+
+ /* skb is now ready for xmit */
+ printk(KERN_DEBUG "Sending CCP Frame:\n");
+ isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
+
+ /* Just ripped from isdn_ppp_write. Dunno whether it makes sense,
+ especially dunno what the sav_skb stuff is good for. */
+
+ count = skb->len;
+ if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel,
+ 1, skb)) != count) {
+ if (lp->sav_skb) {
+ dev_kfree_skb(lp->sav_skb);
+ printk(KERN_INFO
+ "isdn_ppp_write: freeing sav_skb (%d,%d)!\n",
+ cnt, count);
+ } else
+ printk(KERN_INFO
+ "isdn_ppp_write: Can't write PPP frame to LL (%d,%d)!\n",
+ cnt, count);
+ lp->sav_skb = skb;
+ }
+}
+
+/* Allocate the reset state vector */
+static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is)
+{
+ struct ippp_ccp_reset *r;
+ printk(KERN_DEBUG "ippp_ccp: allocating reset data structure\n");
+ r = kmalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL);
+ if(!r)
+ return NULL;
+ memset(r, 0, sizeof(struct ippp_ccp_reset));
+ is->reset = r;
+ return r;
+}
+
+/* Free a given state and clear everything up for later reallocation */
+static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
+ unsigned char id)
+{
+ struct ippp_ccp_reset_state *rs;
+
+ if(is->reset->rs[id]) {
+ printk(KERN_DEBUG "ippp_ccp: freeing state for id %d\n", id);
+ rs = is->reset->rs[id];
+ /* Make sure the kernel will not call back later */
+ if(rs->ta)
+ del_timer(&rs->timer);
+ is->reset->rs[id] = NULL;
+ kfree(rs);
+ } else {
+ printk(KERN_WARNING "ippp_ccp: id %d is not allocated\n", id);
+ }
+}
+
+/* The timer callback function which is called when a ResetReq has timed out,
+ aka has never been answered by a ResetAck */
+static void isdn_ppp_ccp_timer_callback(unsigned long closure)
{
-#if 1
- printk(KERN_ERR "compression not included!\n");
- dev_kfree_skb(skb);
- return NULL;
+ struct ippp_ccp_reset_state *rs =
+ (struct ippp_ccp_reset_state *)closure;
+
+ if(!rs) {
+ printk(KERN_ERR "ippp_ccp: timer cb with zero closure.\n");
+ return;
+ }
+ if(rs->ta && rs->state == CCPResetSentReq) {
+ /* We are correct here */
+ printk(KERN_DEBUG "ippp_ccp: CCP Reset timed out for id %d\n",
+ rs->id);
+ if(!rs->expra) {
+ /* Hmm, there is no Ack really expected. We can clean
+ up the state now, it will be reallocated if the
+ decompressor insists on another reset */
+ rs->ta = 0;
+ isdn_ppp_ccp_reset_free_state(rs->is, rs->id);
+ return;
+ }
+ /* Push it again */
+ isdn_ppp_ccp_xmit_reset(rs->is, PPP_CCP, CCP_RESETREQ, rs->id,
+ rs->data, rs->dlen);
+ /* Restart timer */
+ rs->timer.expires = jiffies + HZ*5;
+ add_timer(&rs->timer);
+ } else {
+ printk(KERN_WARNING "ippp_ccp: timer cb in wrong state %d\n",
+ rs->state);
+ }
+}
+
+/* Allocate a new reset transaction state */
+static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is,
+ unsigned char id)
+{
+ struct ippp_ccp_reset_state *rs;
+ if(is->reset->rs[id]) {
+ printk(KERN_WARNING "ippp_ccp: old state exists for id %d\n",
+ id);
+ return NULL;
+ } else {
+ rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
+ if(!rs)
+ return NULL;
+ memset(rs, 0, sizeof(struct ippp_ccp_reset_state));
+ rs->state = CCPResetIdle;
+ rs->is = is;
+ rs->id = id;
+ rs->timer.data = (unsigned long)rs;
+ rs->timer.function = isdn_ppp_ccp_timer_callback;
+ is->reset->rs[id] = rs;
+ }
+ return rs;
+}
+
+
+/* A decompressor wants a reset with a set of parameters - do what is
+ necessary to fulfill it */
+static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is,
+ struct isdn_ppp_resetparams *rp)
+{
+ struct ippp_ccp_reset_state *rs;
+
+ if(rp->valid) {
+ /* The decompressor defines parameters by itself */
+ if(rp->rsend) {
+ /* And he wants us to send a request */
+ if(!(rp->idval)) {
+ printk(KERN_ERR "ippp_ccp: decompressor must"
+ " specify reset id\n");
+ return;
+ }
+ if(is->reset->rs[rp->id]) {
+ /* There is already a transaction in existence
+ for this id. May be still waiting for a
+ Ack or may be wrong. */
+ rs = is->reset->rs[rp->id];
+ if(rs->state == CCPResetSentReq && rs->ta) {
+ printk(KERN_DEBUG "ippp_ccp: reset"
+ " trans still in progress"
+ " for id %d\n", rp->id);
+ } else {
+ printk(KERN_WARNING "ippp_ccp: reset"
+ " trans in wrong state %d for"
+ " id %d\n", rs->state, rp->id);
+ }
+ } else {
+ /* Ok, this is a new transaction */
+ printk(KERN_DEBUG "ippp_ccp: new trans for id"
+ " %d to be started\n", rp->id);
+ rs = isdn_ppp_ccp_reset_alloc_state(is, rp->id);
+ if(!rs) {
+ printk(KERN_ERR "ippp_ccp: out of mem"
+ " allocing ccp trans\n");
+ return;
+ }
+ rs->state = CCPResetSentReq;
+ rs->expra = rp->expra;
+ if(rp->dtval) {
+ rs->dlen = rp->dlen;
+ memcpy(rs->data, rp->data, rp->dlen);
+ }
+ /* HACK TODO - add link comp here */
+ isdn_ppp_ccp_xmit_reset(is, PPP_CCP,
+ CCP_RESETREQ, rs->id,
+ rs->data, rs->dlen);
+ /* Start the timer */
+ rs->timer.expires = jiffies + 5*HZ;
+ add_timer(&rs->timer);
+ rs->ta = 1;
+ }
+ } else {
+ printk(KERN_DEBUG "ippp_ccp: no reset sent\n");
+ }
+ } else {
+ /* The reset params are invalid. The decompressor does not
+ care about them, so we just send the minimal requests
+ and increase ids only when an Ack is received for a
+ given id */
+ if(is->reset->rs[is->reset->lastid]) {
+ /* There is already a transaction in existence
+ for this id. May be still waiting for a
+ Ack or may be wrong. */
+ rs = is->reset->rs[is->reset->lastid];
+ if(rs->state == CCPResetSentReq && rs->ta) {
+ printk(KERN_DEBUG "ippp_ccp: reset"
+ " trans still in progress"
+ " for id %d\n", rp->id);
+ } else {
+ printk(KERN_WARNING "ippp_ccp: reset"
+ " trans in wrong state %d for"
+ " id %d\n", rs->state, rp->id);
+ }
+ } else {
+ printk(KERN_DEBUG "ippp_ccp: new trans for id"
+ " %d to be started\n", is->reset->lastid);
+ rs = isdn_ppp_ccp_reset_alloc_state(is,
+ is->reset->lastid);
+ if(!rs) {
+ printk(KERN_ERR "ippp_ccp: out of mem"
+ " allocing ccp trans\n");
+ return;
+ }
+ rs->state = CCPResetSentReq;
+ /* We always expect an Ack if the decompressor doesnt
+ know better */
+ rs->expra = 1;
+ rs->dlen = 0;
+ /* HACK TODO - add link comp here */
+ isdn_ppp_ccp_xmit_reset(is, PPP_CCP, CCP_RESETREQ,
+ rs->id, NULL, 0);
+ /* Start the timer */
+ rs->timer.expires = jiffies + 5*HZ;
+ add_timer(&rs->timer);
+ rs->ta = 1;
+ }
+ }
+}
+
+/* An Ack was received for this id. This means we stop the timer and clean
+ up the state prior to calling the decompressors reset routine. */
+static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
+ unsigned char id)
+{
+ struct ippp_ccp_reset_state *rs = is->reset->rs[id];
+
+ if(rs) {
+ if(rs->ta && rs->state == CCPResetSentReq) {
+ /* Great, we are correct */
+ if(!rs->expra)
+ printk(KERN_DEBUG "ippp_ccp: ResetAck received"
+ " for id %d but not expected\n", id);
+ } else {
+ printk(KERN_INFO "ippp_ccp: ResetAck received out of"
+ "sync for id %d\n", id);
+ }
+ if(rs->ta) {
+ rs->ta = 0;
+ del_timer(&rs->timer);
+ }
+ isdn_ppp_ccp_reset_free_state(is, id);
+ } else {
+ printk(KERN_INFO "ippp_ccp: ResetAck received for unknown id"
+ " %d\n", id);
+ }
+ /* Make sure the simple reset stuff uses a new id next time */
+ is->reset->lastid++;
+}
+
+static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struct *is,struct ippp_struct *master,
+ int proto)
+{
+#ifndef CONFIG_ISDN_CCP
+ if(proto == PPP_COMP || proto == PPP_LINK_COMP) {
+ printk(KERN_ERR "isdn_ppp: Ouch! Compression not included!\n");
+ dev_kfree_skb(skb);
+ return NULL;
+ }
+ return skb;
#else
+ void *stat = NULL;
+ struct isdn_ppp_compressor *ipc = NULL;
+ struct sk_buff *skb_out;
+ int len;
+ struct ippp_struct *ri;
+ struct isdn_ppp_resetparams rsparm;
+ unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
+
if(!master) {
/*
- * single link compression
+ * single link decompression
*/
- if(!is->link_compressor) {
- printk(KERN_ERR "ippp: no (link) compressor defined!\n");
+ if(!is->link_decompressor) {
+ printk(KERN_ERR "ippp: no link decompressor defined!\n");
dev_kfree_skb(skb);
return NULL;
}
if(!is->link_decomp_stat) {
- printk(KERN_DEBUG "ippp: initialize link compressor\n");
+ printk(KERN_DEBUG "ippp: no link decompressor data allocated\n");
+ dev_kfree_skb(skb);
+ return NULL;
}
-/*
- -> decompress link
-*/
- }
+ stat = is->link_decomp_stat;
+ ipc = is->link_decompressor;
+ ri = is;
+ }
else {
/*
* 'normal' or bundle-compression
*/
- if(!master->compressor) {
- printk(KERN_ERR "ippp: no (link) compressor defined!\n");
+ if(!master->decompressor) {
+ printk(KERN_ERR "ippp: no decompressor defined!\n");
dev_kfree_skb(skb);
return NULL;
}
if(!master->decomp_stat) {
-#if 0
- master->decomp_stat = (master->compressor->decomp_alloc)( .. );
-#endif
- printk(KERN_DEBUG "ippp: initialize compressor\n");
+ printk(KERN_DEBUG "ippp: no decompressor data allocated\n");
+ dev_kfree_skb(skb);
+ return NULL;
}
+ stat = master->decomp_stat;
+ ipc = master->decompressor;
+ ri = master;
+ }
+
+ /*
+ printk(KERN_DEBUG "ippp: Decompress valid!\n");
+ */
+
+ if((master && proto == PPP_COMP) || (!master && proto == PPP_LINK_COMP) ) {
+ /* Set up reset params for the decompressor */
+ memset(&rsparm, 0, sizeof(rsparm));
+ rsparm.data = rsdata;
+ rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
+
+/* !!!HACK,HACK,HACK!!! 2048 is only assumed */
+ skb_out = dev_alloc_skb(2048);
+ len = ipc->decompress(stat,skb,skb_out, &rsparm);
+ dev_kfree_skb(skb);
+ if(len <= 0) {
+ /* Ok, some error */
+ switch(len) {
+ case DECOMP_ERROR:
+ ri->pppcfg |= SC_DC_ERROR;
+ printk(KERN_INFO "ippp: decomp wants reset %s params\n",
+ rsparm.valid ? "with" : "without");
+
+ isdn_ppp_ccp_reset_trans(ri, &rsparm);
+
+ break;
+ case DECOMP_FATALERROR:
+ ri->pppcfg |= SC_DC_FERROR;
+ /* Kick ipppd to recognize the error */
+ isdn_ppp_ccp_kickup(ri);
+ break;
+ }
+ /* Did I see a leak here ? */
+ dev_kfree_skb(skb_out);
+ return NULL;
+ }
+ return skb_out;
+ }
+ else {
+ /*
+ printk(KERN_DEBUG "isdn_ppp: [%d] Calling incomp with this frame!\n",is->unit);
+ */
+ ipc->incomp(stat,skb,proto);
+ return skb;
}
-
- return skb;
#endif
}
@@ -2034,19 +2594,29 @@ static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struc
static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
struct ippp_struct *is,struct ippp_struct *master,int type)
{
-#if 1
- return skb_in;
-#else
int ret;
int new_proto;
struct isdn_ppp_compressor *compressor;
void *stat;
struct sk_buff *skb_out;
+#ifdef CONFIG_ISDN_CCP
+ /* we do not compress control protocols */
+ if(*proto < 0 || *proto > 0x3fff) {
+#else
+ {
+#endif
+ return skb_in;
+ }
+
if(type) { /* type=1 => Link compression */
+#if 0
compressor = is->link_compressor;
stat = is->link_comp_stat;
new_proto = PPP_LINK_COMP;
+#else
+ return skb_in;
+#endif
}
else {
if(!master) {
@@ -2061,15 +2631,16 @@ static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
}
if(!compressor) {
- printk(KERN_ERR "No compressor set!\n");
+ printk(KERN_ERR "isdn_ppp: No compressor set!\n");
return skb_in;
}
if(!stat) {
- /* init here ? */
+ printk(KERN_ERR "isdn_ppp: Compressor not initialized?\n");
return skb_in;
}
- skb_out = dev_alloc_skb(skb_in->len);
+ /* Allow for at least 150 % expansion (for now) */
+ skb_out = dev_alloc_skb(skb_in->len + skb_in->len/2 + 32);
if(!skb_out)
return skb_in;
@@ -2082,24 +2653,225 @@ static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
dev_kfree_skb(skb_in);
*proto = new_proto;
return skb_out;
-#endif
-
}
/*
* we received a CCP frame ..
- * not a clean solution, but we SHOULD handle a few cased in the kernel
+ * not a clean solution, but we MUST handle a few cases in the kernel
*/
static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
- struct sk_buff *skb)
+ struct sk_buff *skb,int proto)
{
-#if 0
- printk(KERN_DEBUG "isdn_ppp_receive_cpp: %02x %02x %02x %02x %02x %02x %02x %02x\n",
- skb->data[0],skb->data[1],skb->data[2],skb->data[3],
- skb->data[4],skb->data[5],skb->data[6],skb->data[7] );
-#endif
+ struct ippp_struct *is = ippp_table[lp->ppp_slot];
+ struct ippp_struct *mis;
+ int len;
+ struct isdn_ppp_resetparams rsparm;
+ unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
+
+ printk(KERN_DEBUG "Received CCP frame from peer\n");
+ isdn_ppp_frame_log("ccp-rcv", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
+
+ if(lp->master)
+ mis = ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot];
+ else
+ mis = is;
+
+ switch(skb->data[0]) {
+ case CCP_CONFREQ:
+ case CCP_TERMREQ:
+ case CCP_TERMACK:
+ if(is->debug & 0x10)
+ printk(KERN_DEBUG "Disable (de)compression here!\n");
+ if(proto == PPP_CCP)
+ mis->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);
+ else
+ is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON);
+ break;
+ case CCP_CONFACK:
+ /* if we RECEIVE an ackowledge we enable the decompressor */
+ if(is->debug & 0x10)
+ printk(KERN_DEBUG "Enable decompression here!\n");
+ if(proto == PPP_CCP)
+ mis->compflags |= SC_DECOMP_ON;
+ else
+ is->compflags |= SC_LINK_DECOMP_ON;
+ break;
+
+ case CCP_RESETACK:
+ printk(KERN_DEBUG "Received ResetAck from peer\n");
+ len = (skb->data[2] << 8) | skb->data[3];
+ len -= 4;
+
+ if(proto == PPP_CCP) {
+ /* If a reset Ack was outstanding for this id, then
+ clean up the state engine */
+ isdn_ppp_ccp_reset_ack_rcvd(mis, skb->data[1]);
+ if(mis->decompressor && mis->decomp_stat)
+ mis->decompressor->
+ reset(mis->decomp_stat,
+ skb->data[0],
+ skb->data[1],
+ len ? &skb->data[4] : NULL,
+ len, NULL);
+ /* TODO: This is not easy to decide here */
+ mis->compflags &= ~SC_DECOMP_DISCARD;
+ mis->pppcfg &= ~SC_DC_ERROR;
+ }
+ else {
+ isdn_ppp_ccp_reset_ack_rcvd(is, skb->data[1]);
+ if(is->link_decompressor && is->link_decomp_stat)
+ is->link_decompressor->
+ reset(is->link_decomp_stat,
+ skb->data[0],
+ skb->data[1],
+ len ? &skb->data[4] : NULL,
+ len, NULL);
+ /* TODO: neither here */
+ is->compflags &= ~SC_LINK_DECOMP_DISCARD;
+ is->pppcfg &= ~SC_DC_ERROR;
+ }
+ break;
+
+ case CCP_RESETREQ:
+ printk(KERN_DEBUG "Received ResetReq from peer\n");
+ /* Receiving a ResetReq means we must reset our compressor */
+ /* Set up reset params for the reset entry */
+ memset(&rsparm, 0, sizeof(rsparm));
+ rsparm.data = rsdata;
+ rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
+ /* Isolate data length */
+ len = (skb->data[2] << 8) | skb->data[3];
+ len -= 4;
+ if(proto == PPP_CCP) {
+ if(mis->compressor && mis->comp_stat)
+ mis->compressor->
+ reset(mis->comp_stat,
+ skb->data[0],
+ skb->data[1],
+ len ? &skb->data[4] : NULL,
+ len, &rsparm);
+ }
+ else {
+ if(is->link_compressor && is->link_comp_stat)
+ is->link_compressor->
+ reset(is->link_comp_stat,
+ skb->data[0],
+ skb->data[1],
+ len ? &skb->data[4] : NULL,
+ len, &rsparm);
+ }
+ /* Ack the Req as specified by rsparm */
+ if(rsparm.valid) {
+ /* Compressor reset handler decided how to answer */
+ if(rsparm.rsend) {
+ /* We should send a Frame */
+ isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
+ rsparm.idval ? rsparm.id
+ : skb->data[1],
+ rsparm.dtval ?
+ rsparm.data : NULL,
+ rsparm.dtval ?
+ rsparm.dlen : 0);
+ } else {
+ printk(KERN_DEBUG "ResetAck suppressed\n");
+ }
+ } else {
+ /* We answer with a straight reflected Ack */
+ isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
+ skb->data[1],
+ len ? &skb->data[4] : NULL,
+ len);
+ }
+ break;
+ }
}
+
+/*
+ * Daemon sends a CCP frame ...
+ */
+
+/* TODO: Clean this up with new Reset semantics */
+
+static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb)
+{
+ struct ippp_struct *mis,*is = ippp_table[lp->ppp_slot];
+ int proto;
+ unsigned char *data;
+
+ if(!skb || skb->len < 3)
+ return;
+
+ /* Daemon may send with or without address and control field comp */
+ data = skb->data;
+ if(!(is->pppcfg & SC_COMP_AC) && data[0] == 0xff && data[1] == 0x03) {
+ data += 2;
+ if(skb->len < 5)
+ return;
+ }
+
+ proto = ((int)data[0]<<8)+data[1];
+ if(proto != PPP_CCP && proto != PPP_LINK_CCP)
+ return;
+
+ printk(KERN_DEBUG "Received CCP frame from daemon:\n");
+ isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
+
+ if(lp->master)
+ mis = ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot];
+ else
+ mis = is;
+
+ if(mis != is)
+ printk(KERN_DEBUG "isdn_ppp: Ouch! Master CCP sends on slave slot!\n");
+
+ switch(data[2]) {
+ case CCP_CONFREQ:
+ case CCP_TERMREQ:
+ case CCP_TERMACK:
+ if(is->debug & 0x10)
+ printk(KERN_DEBUG "Disable (de)compression here!\n");
+ if(proto == PPP_CCP)
+ is->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);
+ else
+ is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON);
+ break;
+ case CCP_CONFACK:
+ /* if we SEND an ackowledge we can/must enable the compressor */
+ if(is->debug & 0x10)
+ printk(KERN_DEBUG "Enable compression here!\n");
+ if(proto == PPP_CCP)
+ is->compflags |= SC_COMP_ON;
+ else
+ is->compflags |= SC_LINK_COMP_ON;
+ break;
+ case CCP_RESETACK:
+ /* If we send a ACK we should reset our compressor */
+ if(is->debug & 0x10)
+ printk(KERN_DEBUG "Reset decompression state here!\n");
+ printk(KERN_DEBUG "ResetAck from daemon passed by\n");
+ if(proto == PPP_CCP) {
+ /* link to master? */
+ if(is->compressor && is->comp_stat)
+ is->compressor->reset(is->comp_stat, 0, 0,
+ NULL, 0, NULL);
+ is->compflags &= ~SC_COMP_DISCARD;
+ }
+ else {
+ if(is->link_compressor && is->link_comp_stat)
+ is->link_compressor->reset(is->link_comp_stat,
+ 0, 0, NULL, 0, NULL);
+ is->compflags &= ~SC_LINK_COMP_DISCARD;
+ }
+ break;
+ case CCP_RESETREQ:
+ /* Just let it pass by */
+ printk(KERN_DEBUG "ResetReq from daemon passed by\n");
+ break;
+ }
+}
+
+
int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc)
{
ipc->next = ipc_head;
@@ -2123,15 +2895,63 @@ int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc)
return 0;
}
-static int isdn_ppp_set_compressor(struct ippp_struct *is,int num)
+static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_data *data)
{
struct isdn_ppp_compressor *ipc = ipc_head;
+ int ret;
+ void *stat;
+ int num = data->num;
+
+ if(is->debug & 0x10)
+ printk(KERN_DEBUG "[%d] Set %s type %d\n",is->unit,
+ (data->flags&IPPP_COMP_FLAG_XMIT)?"compressor":"decompressor",num);
while(ipc) {
if(ipc->num == num) {
- return 0;
- is->compressor = ipc;
- is->link_compressor = ipc;
+ stat = ipc->alloc(data);
+ if(stat) {
+ ret = ipc->init(stat,data,is->unit,0);
+ if(!ret) {
+ printk(KERN_ERR "Can't init (de)compression!\n");
+ ipc->free(stat);
+ stat = NULL;
+ break;
+ }
+ }
+ else {
+ printk(KERN_ERR "Can't alloc (de)compression!\n");
+ break;
+ }
+
+ if(data->flags & IPPP_COMP_FLAG_XMIT) {
+ if(data->flags & IPPP_COMP_FLAG_LINK) {
+ if(is->link_comp_stat)
+ is->link_compressor->free(is->link_comp_stat);
+ is->link_comp_stat = stat;
+ is->link_compressor = ipc;
+ }
+ else {
+ if(is->comp_stat)
+ is->compressor->free(is->comp_stat);
+ is->comp_stat = stat;
+ is->compressor = ipc;
+ }
+ }
+ else {
+ if(data->flags & IPPP_COMP_FLAG_LINK) {
+ if(is->link_decomp_stat)
+ is->link_decompressor->free(is->link_decomp_stat);
+ is->link_decomp_stat = stat;
+ is->link_decompressor = ipc;
+ }
+ else {
+ if(is->decomp_stat)
+ is->decompressor->free(is->decomp_stat);
+ is->decomp_stat = stat;
+ is->decompressor = ipc;
+ }
+ }
+ return 0;
}
ipc = ipc->next;
}
@@ -2139,16 +2959,3 @@ static int isdn_ppp_set_compressor(struct ippp_struct *is,int num)
}
-#if 0
-static struct symbol_table isdn_ppp_syms =
-{
-#include <linux/symtab_begin.h>
- X(isdn_ppp_register_compressor),
- X(isdn_ppp_unregister_compressor),
-#include <linux/symtab_end.h>
-};
-#endif
-
-
-
-
diff --git a/drivers/isdn/isdn_ppp.h b/drivers/isdn/isdn_ppp.h
index 0e05af08b..2c60240a5 100644
--- a/drivers/isdn/isdn_ppp.h
+++ b/drivers/isdn/isdn_ppp.h
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.h,v 1.12 1998/01/31 22:07:48 keil Exp $
+/* $Id: isdn_ppp.h,v 1.13 1998/03/22 18:50:50 hipp Exp $
* header for Linux ISDN subsystem, functions for synchronous PPP (linklevel).
*
@@ -19,6 +19,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_ppp.h,v $
+ * Revision 1.13 1998/03/22 18:50:50 hipp
+ * Added BSD Compression for syncPPP .. UNTESTED at the moment
+ *
* Revision 1.12 1998/01/31 22:07:48 keil
* changes for newer kernels
*
@@ -84,6 +87,9 @@ extern void isdn_ppp_release(int, struct file *);
extern int isdn_ppp_dial_slave(char *);
extern void isdn_ppp_wakeup_daemon(isdn_net_local *);
+extern int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc);
+extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc);
+
#define IPPP_OPEN 0x01
#define IPPP_CONNECT 0x02
#define IPPP_CLOSEWAIT 0x04
diff --git a/drivers/isdn/isdn_tty.c b/drivers/isdn/isdn_tty.c
index a37178676..bfa895424 100644
--- a/drivers/isdn/isdn_tty.c
+++ b/drivers/isdn/isdn_tty.c
@@ -1,8 +1,8 @@
-/* $Id: isdn_tty.c,v 1.47 1998/02/22 19:44:14 fritz Exp $
+/* $Id: isdn_tty.c,v 1.63 1999/04/12 12:33:39 fritz Exp $
* Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
*
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
* Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg
*
* This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,73 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_tty.c,v $
+ * Revision 1.63 1999/04/12 12:33:39 fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.62 1999/03/02 12:04:48 armin
+ * -added ISDN_STAT_ADDCH to increase supported channels after
+ * register_isdn().
+ * -ttyI now goes on-hook on ATZ when B-Ch is connected.
+ * -added timer-function for register S7 (Wait for Carrier).
+ * -analog modem (ISDN_PROTO_L2_MODEM) implementations.
+ * -on L2_MODEM a string will be appended to the CONNECT-Message,
+ * which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN.
+ * -variable "dialing" used for ATA also, for interrupting call
+ * establishment and register S7.
+ *
+ * Revision 1.61 1999/01/27 22:53:11 he
+ * minor updates (spellings, jiffies wrap around in isdn_tty)
+ *
+ * Revision 1.60 1998/11/15 23:57:32 keil
+ * changes for 2.1.127
+ *
+ * Revision 1.59 1998/08/20 13:50:15 keil
+ * More support for hybrid modem (not working yet)
+ *
+ * Revision 1.58 1998/07/26 18:48:45 armin
+ * Added silence detection in voice receive mode.
+ *
+ * Revision 1.57 1998/06/26 15:12:36 fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 1.56 1998/06/18 23:31:51 fritz
+ * Replaced cli()/restore_flags() in isdn_tty_write() by locking.
+ * Removed direct-senddown feature in isdn_tty_write because it will
+ * never succeed with locking and is useless anyway.
+ *
+ * Revision 1.55 1998/06/17 19:50:55 he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.54 1998/06/07 00:20:13 fritz
+ * abc cleanup.
+ *
+ * Revision 1.53 1998/06/02 12:10:16 detabc
+ * wegen einer einstweiliger verfuegung gegen DW ist zur zeit
+ * die abc-extension bis zur klaerung der rechtslage nicht verfuegbar
+ *
+ * Revision 1.52 1998/03/19 13:18:21 keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
+ * Revision 1.51 1998/03/08 14:26:11 detabc
+ * change kfree_skb to dev_kfree_skb
+ * remove SET_SKB_FREE
+ *
+ * Revision 1.50 1998/03/08 13:14:28 detabc
+ * abc-extension support for kernels > 2.1.x
+ * first try (sorry experimental)
+ *
+ * Revision 1.49 1998/03/08 00:01:59 fritz
+ * Bugfix: Lowlevel module usage and channel usage were not
+ * reset on NO DCHANNEL.
+ *
+ * Revision 1.48 1998/03/07 12:28:15 tsbogend
+ * fixed kernel unaligned traps on Linux/Alpha
+ *
* Revision 1.47 1998/02/22 19:44:14 fritz
* Bugfixes and improvements regarding V.110, V.110 now running.
*
@@ -254,7 +321,7 @@ static int bit2si[8] =
static int si2bit[8] =
{4, 1, 4, 4, 4, 4, 4, 4};
-char *isdn_tty_revision = "$Revision: 1.47 $";
+char *isdn_tty_revision = "$Revision: 1.63 $";
#define DLE 0x10
#define ETX 0x03
@@ -270,6 +337,8 @@ char *isdn_tty_revision = "$Revision: 1.47 $";
#define REG_LF 4
#define REG_BS 5
+#define REG_WAITC 7
+
#define REG_RESP 12
#define BIT_RESP 1
#define REG_RESPNUM 12
@@ -287,8 +356,6 @@ char *isdn_tty_revision = "$Revision: 1.47 $";
#define REG_CPPP 12
#define BIT_CPPP 128
-#define REG_DELXMT 13
-#define BIT_DELXMT 1
#define REG_T70 13
#define BIT_T70 2
#define BIT_T70_EXT 32
@@ -300,6 +367,8 @@ char *isdn_tty_revision = "$Revision: 1.47 $";
#define BIT_CIDONCE 16
#define REG_RUNG 13
#define BIT_RUNG 64
+#define REG_RESRXT 13
+#define BIT_RESRXT 128
#define REG_L2PROT 14
#define REG_L3PROT 15
@@ -389,6 +458,8 @@ isdn_tty_readmodem(void)
r = 0;
#ifdef CONFIG_ISDN_AUDIO
isdn_audio_eval_dtmf(info);
+ if ((info->vonline & 1) && (info->emu.vpar[1]))
+ isdn_audio_eval_silence(info);
#endif
if ((tty = info->tty)) {
if (info->mcr & UART_MCR_RTS) {
@@ -445,6 +516,8 @@ isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb)
if (info->vonline)
isdn_audio_calc_dtmf(info, skb->data, skb->len, ifmt);
+ if ((info->vonline & 1) && (info->emu.vpar[1]))
+ isdn_audio_calc_silence(info, skb->data, skb->len, ifmt);
#endif
if ((info->online < 2)
#ifdef CONFIG_ISDN_AUDIO
@@ -566,8 +639,8 @@ isdn_tty_tint(modem_info * info)
info->isdn_channel, 1, skb)) == len) {
struct tty_struct *tty = info->tty;
info->send_outstanding++;
- info->msr |= UART_MSR_CTS;
- info->lsr |= UART_LSR_TEMT;
+ info->msr &= ~UART_MSR_CTS;
+ info->lsr &= ~UART_LSR_TEMT;
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
tty->ldisc.write_wakeup)
(tty->ldisc.write_wakeup) (tty);
@@ -579,8 +652,6 @@ isdn_tty_tint(modem_info * info)
dev_kfree_skb(skb);
return;
}
- if (slen)
- skb_pull(skb, slen);
skb_queue_head(&info->xmit_queue, skb);
}
@@ -702,7 +773,6 @@ isdn_tty_senddown(modem_info * info)
int audio_len;
#endif
struct sk_buff *skb;
- unsigned long flags;
#ifdef CONFIG_ISDN_AUDIO
if (info->vonline & 4) {
@@ -717,18 +787,20 @@ isdn_tty_senddown(modem_info * info)
}
}
#endif
- save_flags(flags);
- cli();
- if (!(buflen = info->xmit_count)) {
- restore_flags(flags);
+ if (!(buflen = info->xmit_count))
return;
- }
- if ((info->emu.mdmreg[REG_CTS] & BIT_CTS) != 0)
+ if ((info->emu.mdmreg[REG_CTS] & BIT_CTS) != 0)
info->msr &= ~UART_MSR_CTS;
- info->lsr &= ~UART_LSR_TEMT;
+ info->lsr &= ~UART_LSR_TEMT;
+ /* info->xmit_count is modified here and in isdn_tty_write().
+ * So we return here if isdn_tty_write() is in the
+ * critical section.
+ */
+ atomic_inc(&info->xmit_lock);
+ if (!(atomic_dec_and_test(&info->xmit_lock)))
+ return;
if (info->isdn_driver < 0) {
info->xmit_count = 0;
- restore_flags(flags);
return;
}
skb_res = dev->drv[info->isdn_driver]->interface->hl_hdrlen + 4;
@@ -742,7 +814,6 @@ isdn_tty_senddown(modem_info * info)
skb = dev_alloc_skb(skb_res + buflen);
#endif
if (!skb) {
- restore_flags(flags);
printk(KERN_WARNING
"isdn_tty: Out of memory in ttyI%d senddown\n",
info->line);
@@ -751,7 +822,6 @@ isdn_tty_senddown(modem_info * info)
skb_reserve(skb, skb_res);
memcpy(skb_put(skb, buflen), info->xmit_buf, buflen);
info->xmit_count = 0;
- restore_flags(flags);
#ifdef CONFIG_ISDN_AUDIO
if (info->vonline & 2) {
/* For now, ifmt is fixed to 1 (alaw), since this
@@ -859,7 +929,7 @@ isdn_tty_dial(char *n, modem_info * info, atemu * m)
break;
}
#ifdef CONFIG_ISDN_AUDIO
- if (si == 1) {
+ if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) {
l2 = ISDN_PROTO_L2_TRANS;
usg = ISDN_USAGE_VOICE;
}
@@ -907,9 +977,11 @@ isdn_tty_dial(char *n, modem_info * info, atemu * m)
cmd.parm.setup.si2 = m->mdmreg[REG_SI2];
cmd.command = ISDN_CMD_DIAL;
info->dialing = 1;
+ info->emu.carrierwait = 0;
strcpy(dev->num[i], n);
isdn_info_update();
isdn_command(&cmd);
+ isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
}
}
@@ -942,6 +1014,10 @@ isdn_tty_modem_hup(modem_info * info, int local)
kfree(info->dtmf_state);
info->dtmf_state = NULL;
}
+ if (info->silence_state) {
+ kfree(info->silence_state);
+ info->silence_state = NULL;
+ }
if (info->adpcms) {
kfree(info->adpcms);
info->adpcms = NULL;
@@ -965,8 +1041,9 @@ isdn_tty_modem_hup(modem_info * info, int local)
}
isdn_all_eaz(info->isdn_driver, info->isdn_channel);
info->emu.mdmreg[REG_RINGCNT] = 0;
- usage = (info->emu.mdmreg[REG_SI1I] == 1) ?
- ISDN_USAGE_VOICE : ISDN_USAGE_MODEM;
+ usage = ((info->emu.mdmreg[REG_SI1I] != 1) ||
+ (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM)) ?
+ ISDN_USAGE_MODEM : ISDN_USAGE_VOICE;
isdn_free_channel(info->isdn_driver, info->isdn_channel,
usage);
}
@@ -978,6 +1055,226 @@ isdn_tty_modem_hup(modem_info * info, int local)
}
}
+/*
+ * Begin of a CAPI like interface, currently used only for
+ * supplementary service (CAPI 2.0 part III)
+ */
+#include "avmb1/capicmd.h" /* this should be moved in a common place */
+
+int
+isdn_tty_capi_facility(capi_msg *cm) {
+ return(-1); /* dummy */
+}
+
+/* isdn_tty_suspend() tries to suspend the current tty connection
+ */
+static void
+isdn_tty_suspend(char *id, modem_info * info, atemu * m)
+{
+ isdn_ctrl cmd;
+
+ int l;
+
+ if (!info)
+ return;
+
+#ifdef ISDN_DEBUG_MODEM_SERVICES
+ printk(KERN_DEBUG "Msusp ttyI%d\n", info->line);
+#endif
+ l = strlen(id);
+ if ((info->isdn_driver >= 0) && l) {
+ cmd.parm.cmsg.Length = l+17;
+ cmd.parm.cmsg.Command = CAPI_FACILITY;
+ cmd.parm.cmsg.Subcommand = CAPI_REQ;
+ cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
+ cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */
+ cmd.parm.cmsg.para[1] = 0;
+ cmd.parm.cmsg.para[2] = l + 3;
+ cmd.parm.cmsg.para[3] = 4; /* 16 bit 0x0004 Suspend */
+ cmd.parm.cmsg.para[4] = 0;
+ cmd.parm.cmsg.para[5] = l;
+ strncpy(&cmd.parm.cmsg.para[6], id, l);
+ cmd.command = CAPI_PUT_MESSAGE;
+ cmd.driver = info->isdn_driver;
+ cmd.arg = info->isdn_channel;
+ isdn_command(&cmd);
+ }
+}
+
+/* isdn_tty_resume() tries to resume a suspended call
+ * setup of the lower levels before that. unfortunatly here is no
+ * checking for compatibility of used protocols implemented by Q931
+ * It does the same things like isdn_tty_dial, the last command
+ * is different, may be we can merge it.
+ */
+
+static void
+isdn_tty_resume(char *id, modem_info * info, atemu * m)
+{
+ int usg = ISDN_USAGE_MODEM;
+ int si = 7;
+ int l2 = m->mdmreg[REG_L2PROT];
+ isdn_ctrl cmd;
+ ulong flags;
+ int i;
+ int j;
+ int l;
+
+ l = strlen(id);
+ if (!l) {
+ isdn_tty_modem_result(4, info);
+ return;
+ }
+ for (j = 7; j >= 0; j--)
+ if (m->mdmreg[REG_SI1] & (1 << j)) {
+ si = bit2si[j];
+ break;
+ }
+#ifdef CONFIG_ISDN_AUDIO
+ if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) {
+ l2 = ISDN_PROTO_L2_TRANS;
+ usg = ISDN_USAGE_VOICE;
+ }
+#endif
+ m->mdmreg[REG_SI1I] = si2bit[si];
+ save_flags(flags);
+ cli();
+ i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1);
+ if (i < 0) {
+ restore_flags(flags);
+ isdn_tty_modem_result(6, info);
+ } else {
+ info->isdn_driver = dev->drvmap[i];
+ info->isdn_channel = dev->chanmap[i];
+ info->drv_index = i;
+ dev->m_idx[i] = info->line;
+ dev->usage[i] |= ISDN_USAGE_OUTGOING;
+ info->last_dir = 1;
+// strcpy(info->last_num, n);
+ isdn_info_update();
+ restore_flags(flags);
+ cmd.driver = info->isdn_driver;
+ cmd.arg = info->isdn_channel;
+ cmd.command = ISDN_CMD_CLREAZ;
+ isdn_command(&cmd);
+ strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
+ cmd.driver = info->isdn_driver;
+ cmd.command = ISDN_CMD_SETEAZ;
+ isdn_command(&cmd);
+ cmd.driver = info->isdn_driver;
+ cmd.command = ISDN_CMD_SETL2;
+ info->last_l2 = l2;
+ cmd.arg = info->isdn_channel + (l2 << 8);
+ isdn_command(&cmd);
+ cmd.driver = info->isdn_driver;
+ cmd.command = ISDN_CMD_SETL3;
+ cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
+ isdn_command(&cmd);
+ cmd.driver = info->isdn_driver;
+ cmd.arg = info->isdn_channel;
+ cmd.parm.cmsg.Length = l+17;
+ cmd.parm.cmsg.Command = CAPI_FACILITY;
+ cmd.parm.cmsg.Subcommand = CAPI_REQ;
+ cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
+ cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */
+ cmd.parm.cmsg.para[1] = 0;
+ cmd.parm.cmsg.para[2] = l+3;
+ cmd.parm.cmsg.para[3] = 5; /* 16 bit 0x0005 Resume */
+ cmd.parm.cmsg.para[4] = 0;
+ cmd.parm.cmsg.para[5] = l;
+ strncpy(&cmd.parm.cmsg.para[6], id, l);
+ cmd.command =CAPI_PUT_MESSAGE;
+/* info->dialing = 1;
+ strcpy(dev->num[i], n);
+ isdn_info_update();
+*/
+ isdn_command(&cmd);
+ }
+}
+
+/* isdn_tty_send_msg() sends a message to a HL driver
+ * This is used for hybrid modem cards to send AT commands to it
+ */
+
+static void
+isdn_tty_send_msg(modem_info * info, atemu * m, char *msg)
+{
+ int usg = ISDN_USAGE_MODEM;
+ int si = 7;
+ int l2 = m->mdmreg[REG_L2PROT];
+ isdn_ctrl cmd;
+ ulong flags;
+ int i;
+ int j;
+ int l;
+
+ l = strlen(msg);
+ if (!l) {
+ isdn_tty_modem_result(4, info);
+ return;
+ }
+ for (j = 7; j >= 0; j--)
+ if (m->mdmreg[REG_SI1] & (1 << j)) {
+ si = bit2si[j];
+ break;
+ }
+#ifdef CONFIG_ISDN_AUDIO
+ if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) {
+ l2 = ISDN_PROTO_L2_TRANS;
+ usg = ISDN_USAGE_VOICE;
+ }
+#endif
+ m->mdmreg[REG_SI1I] = si2bit[si];
+ save_flags(flags);
+ cli();
+ i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1);
+ if (i < 0) {
+ restore_flags(flags);
+ isdn_tty_modem_result(6, info);
+ } else {
+ info->isdn_driver = dev->drvmap[i];
+ info->isdn_channel = dev->chanmap[i];
+ info->drv_index = i;
+ dev->m_idx[i] = info->line;
+ dev->usage[i] |= ISDN_USAGE_OUTGOING;
+ info->last_dir = 1;
+ isdn_info_update();
+ restore_flags(flags);
+ cmd.driver = info->isdn_driver;
+ cmd.arg = info->isdn_channel;
+ cmd.command = ISDN_CMD_CLREAZ;
+ isdn_command(&cmd);
+ strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
+ cmd.driver = info->isdn_driver;
+ cmd.command = ISDN_CMD_SETEAZ;
+ isdn_command(&cmd);
+ cmd.driver = info->isdn_driver;
+ cmd.command = ISDN_CMD_SETL2;
+ info->last_l2 = l2;
+ cmd.arg = info->isdn_channel + (l2 << 8);
+ isdn_command(&cmd);
+ cmd.driver = info->isdn_driver;
+ cmd.command = ISDN_CMD_SETL3;
+ cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
+ isdn_command(&cmd);
+ cmd.driver = info->isdn_driver;
+ cmd.arg = info->isdn_channel;
+ cmd.parm.cmsg.Length = l+14;
+ cmd.parm.cmsg.Command = CAPI_MANUFACTURER;
+ cmd.parm.cmsg.Subcommand = CAPI_REQ;
+ cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
+ cmd.parm.cmsg.para[0] = l+1;
+ strncpy(&cmd.parm.cmsg.para[1], msg, l);
+ cmd.parm.cmsg.para[l+1] = 0xd;
+ cmd.command =CAPI_PUT_MESSAGE;
+/* info->dialing = 1;
+ strcpy(dev->num[i], n);
+ isdn_info_update();
+*/
+ isdn_command(&cmd);
+ }
+}
+
static inline int
isdn_tty_paranoia_check(modem_info * info, kdev_t device, const char *routine)
{
@@ -1138,15 +1435,16 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
{
int c;
int total = 0;
- ulong flags;
modem_info *info = (modem_info *) tty->driver_data;
if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_write"))
return 0;
if (!tty)
return 0;
- save_flags(flags);
- cli();
+ if (from_user)
+ down(&info->write_sem);
+ /* See isdn_tty_senddown() */
+ atomic_inc(&info->xmit_lock);
while (1) {
c = MIN(count, info->xmit_size - info->xmit_count);
if (info->isdn_driver >= 0)
@@ -1205,10 +1503,6 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
} else
#endif
info->xmit_count += c;
- if (m->mdmreg[REG_DELXMT] & BIT_DELXMT) {
- isdn_tty_senddown(info);
- isdn_tty_tint(info);
- }
} else {
info->msr |= UART_MSR_CTS;
info->lsr |= UART_LSR_TEMT;
@@ -1228,7 +1522,9 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
}
if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue)))
isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
- restore_flags(flags);
+ atomic_dec(&info->xmit_lock);
+ if (from_user)
+ up(&info->write_sem);
return total;
}
@@ -1359,7 +1655,7 @@ isdn_tty_get_lsr_info(modem_info * info, uint * value)
status = info->lsr;
restore_flags(flags);
result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
- put_user(result, (ulong *) value);
+ put_user(result, (uint *) value);
return 0;
}
@@ -1383,7 +1679,7 @@ isdn_tty_get_modem_info(modem_info * info, uint * value)
| ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
| ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
| ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
- put_user(result, (ulong *) value);
+ put_user(result, (uint *) value);
return 0;
}
@@ -1567,8 +1863,12 @@ isdn_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
static int
isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * info)
{
+#if LINUX_VERSION_CODE < 131841
struct wait_queue wait =
{current, NULL};
+#else
+ DECLARE_WAITQUEUE(wait, NULL);
+#endif
int do_clocal = 0;
unsigned long flags;
int retval;
@@ -1892,6 +2192,7 @@ isdn_tty_reset_profile(atemu * m)
m->profile[19] = 0;
m->profile[20] = 0;
m->pmsn[0] = '\0';
+ m->plmsn[0] = '\0';
}
#ifdef CONFIG_ISDN_AUDIO
@@ -1912,6 +2213,7 @@ isdn_tty_modem_reset_regs(modem_info * info, int force)
if ((m->mdmreg[REG_DTRR] & BIT_DTRR) || force) {
memcpy(m->mdmreg, m->profile, ISDN_MODEM_ANZREG);
memcpy(m->msn, m->pmsn, ISDN_MSNLEN);
+ memcpy(m->lmsn, m->plmsn, ISDN_LMSNLEN);
info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
}
#ifdef CONFIG_ISDN_AUDIO
@@ -1925,6 +2227,7 @@ modem_write_profile(atemu * m)
{
memcpy(m->profile, m->mdmreg, ISDN_MODEM_ANZREG);
memcpy(m->pmsn, m->msn, ISDN_MSNLEN);
+ memcpy(m->plmsn, m->lmsn, ISDN_LMSNLEN);
if (dev->profd)
send_sig(SIGIO, dev->profd, 1);
}
@@ -1988,6 +2291,11 @@ isdn_tty_modem_init(void)
}
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
info = &m->info[i];
+#if LINUX_VERSION_CODE < 131841
+ info->write_sem = MUTEX;
+#else
+ init_MUTEX(&info->write_sem);
+#endif
sprintf(info->last_cause, "0000");
sprintf(info->last_num, "none");
info->last_dir = 0;
@@ -2004,8 +2312,13 @@ isdn_tty_modem_init(void)
info->blocked_open = 0;
info->callout_termios = m->cua_modem.init_termios;
info->normal_termios = m->tty_modem.init_termios;
+#if LINUX_VERSION_CODE < 131841
info->open_wait = 0;
info->close_wait = 0;
+#else
+ init_waitqueue_head(&info->open_wait);
+ init_waitqueue_head(&info->close_wait);
+#endif
info->isdn_driver = -1;
info->isdn_channel = -1;
info->drv_index = -1;
@@ -2024,25 +2337,67 @@ isdn_tty_modem_init(void)
return 0;
}
+static int
+isdn_tty_match_icall(char *cid, atemu *emu, int di)
+{
+#ifdef ISDN_DEBUG_MODEM_ICALL
+ printk(KERN_DEBUG "m_fi: msn=%s lmsn=%s mmsn=%s mreg[SI1]=%d mreg[SI2]=%d\n",
+ emu->msn, emu->lmsn, isdn_map_eaz2msn(emu->msn, di),
+ emu->mdmreg[REG_SI1], emu->mdmreg[REG_SI2]);
+#endif
+ if (strlen(emu->lmsn)) {
+ char *p = emu->lmsn;
+ char *q;
+ int tmp;
+ int ret = 0;
+
+ while (1) {
+ if ((q = strchr(p, ';')))
+ *q = '\0';
+ if ((tmp = isdn_wildmat(cid, isdn_map_eaz2msn(p, di))) > ret)
+ ret = tmp;
+#ifdef ISDN_DEBUG_MODEM_ICALL
+ printk(KERN_DEBUG "m_fi: lmsnX=%s mmsn=%s -> tmp=%d\n",
+ p, isdn_map_eaz2msn(emu->msn, di), tmp);
+#endif
+ if (q) {
+ *q = ';';
+ p = q;
+ p++;
+ }
+ if (!tmp)
+ return 0;
+ if (!q)
+ break;
+ }
+ return ret;
+ } else
+ return isdn_wildmat(cid, isdn_map_eaz2msn(emu->msn, di));
+}
+
/*
* An incoming call-request has arrived.
* Search the tty-devices for an appropriate device and bind
* it to the ISDN-Channel.
- * Return Index to dev->mdm or -1 if none found.
+ * Return:
+ *
+ * 0 = No matching device found.
+ * 1 = A matching device found.
+ * 3 = No match found, but eventually would match, if
+ * CID is longer.
*/
int
isdn_tty_find_icall(int di, int ch, setup_parm setup)
{
char *eaz;
int i;
+ int wret;
int idx;
int si1;
int si2;
char nr[32];
ulong flags;
- save_flags(flags);
- cli();
if (!setup.phone[0]) {
nr[0] = '0';
nr[1] = '\0';
@@ -2059,17 +2414,14 @@ isdn_tty_find_icall(int di, int ch, setup_parm setup)
#ifdef ISDN_DEBUG_MODEM_ICALL
printk(KERN_DEBUG "m_fi: eaz=%s si1=%d si2=%d\n", eaz, si1, si2);
#endif
+ wret = 0;
+ save_flags(flags);
+ cli();
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
modem_info *info = &dev->mdm.info[i];
-#ifdef ISDN_DEBUG_MODEM_ICALL
- printk(KERN_DEBUG "m_fi: i=%d msn=%s mmsn=%s mreg18=%d mreg19=%d\n", i,
- info->emu.msn, isdn_map_eaz2msn(info->emu.msn, di),
- info->emu.mdmreg[REG_SI1], info->emu.mdmreg[REG_SI2]);
-#endif
- if ((!strcmp(isdn_map_eaz2msn(info->emu.msn, di),
- eaz)) && /* EAZ is matching */
- (info->emu.mdmreg[REG_SI1] & si2bit[si1]) && /* SI1 is matching */
- (info->emu.mdmreg[REG_SI2] == si2)) { /* SI2 is matching */
+
+ if ((info->emu.mdmreg[REG_SI1] & si2bit[si1]) && /* SI1 is matching */
+ (info->emu.mdmreg[REG_SI2] == si2)) { /* SI2 is matching */
idx = isdn_dc2minor(di, ch);
#ifdef ISDN_DEBUG_MODEM_ICALL
printk(KERN_DEBUG "m_fi: match1\n");
@@ -2081,34 +2433,42 @@ isdn_tty_find_icall(int di, int ch, setup_parm setup)
#ifndef FIX_FILE_TRANSFER
(info->flags & ISDN_ASYNC_NORMAL_ACTIVE) &&
#endif
- (info->isdn_driver == -1) &&
- (info->isdn_channel == -1) &&
- (USG_NONE(dev->usage[idx]))) {
- info->isdn_driver = di;
- info->isdn_channel = ch;
- info->drv_index = idx;
- dev->m_idx[idx] = info->line;
- dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
- dev->usage[idx] |= (si1 == 1) ? ISDN_USAGE_VOICE : ISDN_USAGE_MODEM;
- strcpy(dev->num[idx], nr);
- info->emu.mdmreg[REG_SI1I] = si2bit[si1];
- info->emu.mdmreg[REG_PLAN] = setup.plan;
- info->emu.mdmreg[REG_SCREEN] = setup.screen;
- isdn_info_update();
- restore_flags(flags);
- printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,
- info->line);
- info->msr |= UART_MSR_RI;
- isdn_tty_modem_result(2, info);
- isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1);
- return info->line;
+ (info->isdn_driver == -1) &&
+ (info->isdn_channel == -1) &&
+ (USG_NONE(dev->usage[idx]))) {
+ int matchret;
+
+ if ((matchret = isdn_tty_match_icall(eaz, &info->emu, di)) > wret)
+ wret = matchret;
+ if (!matchret) { /* EAZ is matching */
+ info->isdn_driver = di;
+ info->isdn_channel = ch;
+ info->drv_index = idx;
+ dev->m_idx[idx] = info->line;
+ dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
+ dev->usage[idx] |= ((si1 != 1) || (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM)) ?
+ ISDN_USAGE_MODEM : ISDN_USAGE_VOICE;
+ strcpy(dev->num[idx], nr);
+ strcpy(info->emu.cpn, eaz);
+ info->emu.mdmreg[REG_SI1I] = si2bit[si1];
+ info->emu.mdmreg[REG_PLAN] = setup.plan;
+ info->emu.mdmreg[REG_SCREEN] = setup.screen;
+ isdn_info_update();
+ restore_flags(flags);
+ printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,
+ info->line);
+ info->msr |= UART_MSR_RI;
+ isdn_tty_modem_result(2, info);
+ isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1);
+ return 1;
+ }
}
}
}
- printk(KERN_INFO "isdn_tty: call from %s -> %s %s\n", nr, eaz,
- dev->drv[di]->reject_bus ? "rejected" : "ignored");
restore_flags(flags);
- return -1;
+ printk(KERN_INFO "isdn_tty: call from %s -> %s %s\n", nr, eaz,
+ ((dev->drv[di]->flags & DRV_FLAG_REJBUS) && (wret != 2))? "rejected" : "ignored");
+ return (wret == 2)?3:0;
}
#define TTY_IS_ACTIVE(info) \
@@ -2129,7 +2489,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl * c)
case ISDN_STAT_CINF:
printk(KERN_DEBUG "CHARGEINFO on ttyI%d: %ld %s\n", info->line, c->arg, c->parm.num);
info->emu.charge = (unsigned) simple_strtoul(c->parm.num, &e, 10);
- if (e == c->parm.num)
+ if (e == (char *)c->parm.num)
info->emu.charge = 0;
break;
@@ -2170,10 +2530,11 @@ isdn_tty_stat_callback(int i, isdn_ctrl * c)
printk(KERN_DEBUG "tty_STAT_DHUP ttyI%d\n", info->line);
#endif
if (TTY_IS_ACTIVE(info)) {
- if (info->dialing == 1) {
- info->dialing = 0;
+ if (info->dialing == 1)
isdn_tty_modem_result(7, info);
- }
+ if (info->dialing > 1)
+ isdn_tty_modem_result(3, info);
+ info->dialing = 0;
#ifdef ISDN_DEBUG_MODEM_HUP
printk(KERN_DEBUG "Mhup in ISDN_STAT_DHUP\n");
#endif
@@ -2192,14 +2553,20 @@ isdn_tty_stat_callback(int i, isdn_ctrl * c)
if (TTY_IS_ACTIVE(info)) {
info->msr |= UART_MSR_DCD;
info->emu.charge = 0;
- if (info->dialing) {
- info->dialing = 0;
+ if (info->dialing & 0xf)
info->last_dir = 1;
- } else
+ else
info->last_dir = 0;
+ info->dialing = 0;
info->rcvsched = 1;
- if (USG_MODEM(dev->usage[i]))
- isdn_tty_modem_result(5, info);
+ if (USG_MODEM(dev->usage[i])) {
+ if (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) {
+ strcpy(info->emu.connmsg, c->parm.num);
+ isdn_tty_modem_result(1, info);
+ }
+ else
+ isdn_tty_modem_result(5, info);
+ }
if (USG_VOICE(dev->usage[i]))
isdn_tty_modem_result(11, info);
return 1;
@@ -2229,11 +2596,7 @@ isdn_tty_stat_callback(int i, isdn_ctrl * c)
sprintf(info->last_cause, "0000");
isdn_tty_modem_result(6, info);
}
- info->msr &= ~UART_MSR_DCD;
- if (info->online) {
- isdn_tty_modem_result(3, info);
- info->online = 0;
- }
+ isdn_tty_modem_hup(info, 0);
return 1;
}
break;
@@ -2394,7 +2757,7 @@ isdn_tty_modem_result(int code, modem_info * info)
"CONNECT 64000", "NO DIALTONE", "BUSY", "NO ANSWER",
"RINGING", "NO MSN/EAZ", "VCON", "RUNG"};
ulong flags;
- char s[10];
+ char s[ISDN_MSNLEN+10];
switch (code) {
case 2:
@@ -2474,7 +2837,20 @@ isdn_tty_modem_result(int code, modem_info * info)
}
isdn_tty_at_cout(msg[code], info);
switch (code) {
+ case 1:
+ switch (m->mdmreg[REG_L2PROT]) {
+ case ISDN_PROTO_L2_MODEM:
+ isdn_tty_at_cout(" ", info);
+ isdn_tty_at_cout(m->connmsg, info);
+ break;
+ }
+ break;
case 2:
+ /* Append CPN, if enabled */
+ if ((m->mdmreg[REG_RESRXT] & BIT_RESRXT)) {
+ sprintf(s, "/%s", m->cpn);
+ isdn_tty_at_cout(s, info);
+ }
/* Print CID only once, _after_ 1.st RING */
if ((m->mdmreg[REG_CIDONCE] & BIT_CIDONCE) &&
(m->mdmreg[REG_RINGCNT] == 1)) {
@@ -2561,7 +2937,9 @@ isdn_tty_show_profile(int ridx, modem_info * info)
static void
isdn_tty_get_msnstr(char *n, char **p)
{
- while ((*p[0] >= '0' && *p[0] <= '9') || (*p[0] == ','))
+ while ((*p[0] >= '0' && *p[0] <= '9') ||
+ /* Why a comma ??? */
+ (*p[0] == ','))
*n++ = *p[0]++;
*n = '\0';
}
@@ -2627,6 +3005,9 @@ isdn_tty_report(modem_info * info)
case ISDN_PROTO_L2_TRANS:
isdn_tty_at_cout("transparent", info);
break;
+ case ISDN_PROTO_L2_MODEM:
+ isdn_tty_at_cout("modem", info);
+ break;
default:
isdn_tty_at_cout("unknown", info);
break;
@@ -2669,6 +3050,8 @@ isdn_tty_cmd_ATand(char **p, modem_info * info)
int i;
char rb[100];
+#define MAXRB (sizeof(rb) - 1)
+
switch (*p[0]) {
case 'B':
/* &B - Set Buffersize */
@@ -2720,6 +3103,15 @@ isdn_tty_cmd_ATand(char **p, modem_info * info)
isdn_tty_reset_profile(m);
isdn_tty_modem_reset_regs(info, 1);
break;
+ case 'L':
+ /* &L -Set Numbers to listen on */
+ p[0]++;
+ i = 0;
+ while ((strchr("0123456789,*[]?;", *p[0])) &&
+ (i < ISDN_LMSNLEN))
+ m->lmsn[i++] = *p[0]++;
+ m->lmsn[i] = '\0';
+ break;
case 'R':
/* &R - Set V.110 bitrate adaption */
p[0]++;
@@ -2775,6 +3167,11 @@ isdn_tty_cmd_ATand(char **p, modem_info * info)
sprintf(rb, "\r\nEAZ/MSN: %.50s\r\n",
strlen(m->msn) ? m->msn : "None");
isdn_tty_at_cout(rb, info);
+ if (strlen(m->lmsn)) {
+ isdn_tty_at_cout("\r\nListen: ", info);
+ isdn_tty_at_cout(m->lmsn, info);
+ isdn_tty_at_cout("\r\n", info);
+ }
break;
case 'W':
/* &W - Write Profile */
@@ -2940,9 +3337,10 @@ isdn_tty_cmd_ATA(modem_info * info)
#ifdef CONFIG_ISDN_AUDIO
/* If more than one bit set in reg18, autoselect Layer2 */
if ((m->mdmreg[REG_SI1] & m->mdmreg[REG_SI1I]) != m->mdmreg[REG_SI1]) {
- if (m->mdmreg[REG_SI1I] == 1)
- l2 = ISDN_PROTO_L2_TRANS;
- else
+ if (m->mdmreg[REG_SI1I] == 1) {
+ if (l2 != ISDN_PROTO_L2_MODEM)
+ l2 = ISDN_PROTO_L2_TRANS;
+ } else
l2 = ISDN_PROTO_L2_X75I;
}
#endif
@@ -2958,7 +3356,10 @@ isdn_tty_cmd_ATA(modem_info * info)
cmd.driver = info->isdn_driver;
cmd.arg = info->isdn_channel;
cmd.command = ISDN_CMD_ACCEPTD;
+ info->dialing = 16;
+ info->emu.carrierwait = 0;
isdn_command(&cmd);
+ isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
} else
isdn_tty_modem_result(8, info);
}
@@ -3222,6 +3623,11 @@ isdn_tty_cmd_PLUSV(char **p, modem_info * info)
printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n");
PARSE_ERROR1;
}
+ info->silence_state = isdn_audio_silence_init(info->silence_state);
+ if (!info->silence_state) {
+ printk(KERN_WARNING "isdn_tty: Couldn't malloc silence state\n");
+ PARSE_ERROR1;
+ }
if (m->vpar[3] < 5) {
info->adpcmr = isdn_audio_adpcm_init(info->adpcmr, m->vpar[3]);
if (!info->adpcmr) {
@@ -3248,31 +3654,27 @@ isdn_tty_cmd_PLUSV(char **p, modem_info * info)
break;
case '=':
p[0]++;
- switch (*p[0]) {
- case '0':
- case '1':
- case '2':
- case '3':
- par1 = isdn_getnum(p);
- if ((par1 < 0) || (par1 > 31))
- PARSE_ERROR1;
- if (*p[0] != ',')
- PARSE_ERROR1;
- p[0]++;
- par2 = isdn_getnum(p);
- if ((par2 < 0) || (par2 > 255))
- PARSE_ERROR1;
- m->vpar[1] = par1;
- m->vpar[2] = par2;
- break;
- case '?':
- p[0]++;
- isdn_tty_at_cout("\r\n<0-31>,<0-255>",
- info);
- break;
- default:
+ if ((*p[0]>='0') && (*p[0]<='9')) {
+ par1 = isdn_getnum(p);
+ if ((par1 < 0) || (par1 > 31))
PARSE_ERROR1;
- }
+ if (*p[0] != ',')
+ PARSE_ERROR1;
+ p[0]++;
+ par2 = isdn_getnum(p);
+ if ((par2 < 0) || (par2 > 255))
+ PARSE_ERROR1;
+ m->vpar[1] = par1;
+ m->vpar[2] = par2;
+ break;
+ } else
+ if (*p[0] == '?') {
+ p[0]++;
+ isdn_tty_at_cout("\r\n<0-31>,<0-255>",
+ info);
+ break;
+ } else
+ PARSE_ERROR1;
break;
default:
PARSE_ERROR1;
@@ -3446,7 +3848,7 @@ isdn_tty_parse_at(modem_info * info)
p++;
if (info->msr & UART_MSR_DCD)
/* if B-Channel is up */
- isdn_tty_modem_result(5, info);
+ isdn_tty_modem_result((m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) ? 1:5, info);
else
isdn_tty_modem_result(3, info);
return;
@@ -3487,29 +3889,46 @@ isdn_tty_parse_at(modem_info * info)
case 'Z':
/* Z - Load Registers from Profile */
p++;
+ if (info->msr & UART_MSR_DCD) {
+ info->online = 0;
+ isdn_tty_on_hook(info);
+ }
isdn_tty_modem_reset_regs(info, 1);
break;
-#ifdef CONFIG_ISDN_AUDIO
case '+':
p++;
switch (*p) {
+#ifdef CONFIG_ISDN_AUDIO
case 'F':
p++;
if (isdn_tty_cmd_PLUSF(&p, info))
return;
break;
case 'V':
- if (!(m->mdmreg[REG_SI1] & 1))
+ if ((!(m->mdmreg[REG_SI1] & 1)) ||
+ (m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM))
PARSE_ERROR;
p++;
if (isdn_tty_cmd_PLUSV(&p, info))
return;
break;
+#endif /* CONFIG_ISDN_AUDIO */
+ case 'S': /* SUSPEND */
+ p++;
+ isdn_tty_get_msnstr(ds, &p);
+ isdn_tty_suspend(ds, info, m);
+ break;
+ case 'R': /* RESUME */
+ isdn_tty_get_msnstr(ds, &p);
+ isdn_tty_resume(ds, info, m);
+ case 'M': /* MESSAGE */
+ p++;
+ isdn_tty_send_msg(info, m, p);
+ break;
default:
PARSE_ERROR;
}
break;
-#endif /* CONFIG_ISDN_AUDIO */
case '&':
p++;
if (isdn_tty_cmd_ATand(&p, info))
@@ -3674,3 +4093,28 @@ isdn_tty_modem_xmit(void)
}
isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, ton);
}
+
+/*
+ * Check all channels if we have a 'no carrier' timeout.
+ * Timeout value is set by Register S7.
+ */
+void
+isdn_tty_carrier_timeout(void)
+{
+ int ton = 0;
+ int i;
+
+ for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+ modem_info *info = &dev->mdm.info[i];
+ if (info->dialing) {
+ if (info->emu.carrierwait++ > info->emu.mdmreg[REG_WAITC]) {
+ info->dialing = 0;
+ isdn_tty_modem_result(3, info);
+ isdn_tty_modem_hup(info, 1);
+ }
+ else
+ ton = 1;
+ }
+ }
+ isdn_timer_ctrl(ISDN_TIMER_CARRIER, ton);
+}
diff --git a/drivers/isdn/isdn_tty.h b/drivers/isdn/isdn_tty.h
index 986cb54f7..663648e58 100644
--- a/drivers/isdn/isdn_tty.h
+++ b/drivers/isdn/isdn_tty.h
@@ -1,8 +1,8 @@
-/* $Id: isdn_tty.h,v 1.10 1997/03/02 14:29:26 fritz Exp $
+/* $Id: isdn_tty.h,v 1.13 1999/04/12 12:33:46 fritz Exp $
* header for Linux ISDN subsystem, tty related functions (linklevel).
*
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
* Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg
*
* This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,24 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_tty.h,v $
+ * Revision 1.13 1999/04/12 12:33:46 fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.12 1999/03/02 12:04:51 armin
+ * -added ISDN_STAT_ADDCH to increase supported channels after
+ * register_isdn().
+ * -ttyI now goes on-hook on ATZ when B-Ch is connected.
+ * -added timer-function for register S7 (Wait for Carrier).
+ * -analog modem (ISDN_PROTO_L2_MODEM) implementations.
+ * -on L2_MODEM a string will be appended to the CONNECT-Message,
+ * which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN.
+ * -variable "dialing" used for ATA also, for interrupting call
+ * establishment and register S7.
+ *
+ * Revision 1.11 1998/03/19 13:18:27 keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
* Revision 1.10 1997/03/02 14:29:26 fritz
* More ttyI related cleanup.
*
@@ -56,6 +74,7 @@
extern void isdn_tty_modem_escape(void);
extern void isdn_tty_modem_ring(void);
+extern void isdn_tty_carrier_timeout(void);
extern void isdn_tty_modem_xmit(void);
extern int isdn_tty_modem_init(void);
extern void isdn_tty_readmodem(void);
@@ -63,3 +82,4 @@ extern int isdn_tty_find_icall(int, int, setup_parm);
extern void isdn_tty_cleanup_xmit(modem_info *);
extern int isdn_tty_stat_callback(int, isdn_ctrl *);
extern int isdn_tty_rcv_skb(int, int, int, struct sk_buff *);
+extern int isdn_tty_capi_facility(capi_msg *cm);
diff --git a/drivers/isdn/isdn_x25iface.c b/drivers/isdn/isdn_x25iface.c
index 2ae21fcf3..d0594fe34 100644
--- a/drivers/isdn/isdn_x25iface.c
+++ b/drivers/isdn/isdn_x25iface.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_x25iface.c,v 1.3 1998/02/20 17:25:20 fritz Exp $
+/* $Id: isdn_x25iface.c,v 1.6 1999/01/27 22:53:19 he Exp $
* stuff needed to support the Linux X.25 PLP code on top of devices that
* can provide a lab_b service using the concap_proto mechanism.
* This module supports a network interface wich provides lapb_sematics
@@ -10,6 +10,17 @@
* goes to another -- device related -- concap_proto support source file.
*
* $Log: isdn_x25iface.c,v $
+ * Revision 1.6 1999/01/27 22:53:19 he
+ * minor updates (spellings, jiffies wrap around in isdn_tty)
+ *
+ * Revision 1.5 1998/10/30 17:55:39 he
+ * dialmode for x25iface and multulink ppp
+ *
+ * Revision 1.4 1998/06/17 19:51:00 he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
* Revision 1.3 1998/02/20 17:25:20 fritz
* Changes for recent kernels.
*
@@ -302,7 +313,12 @@ int isdn_x25iface_xmit(struct concap_proto *cprot, struct sk_buff *skb)
case 0x01: /* dl_connect request */
if( *state == WAN_DISCONNECTED ){
*state = WAN_CONNECTING;
- cprot -> dops -> connect_req(cprot);
+ ret = cprot -> dops -> connect_req(cprot);
+ if(ret){
+ /* reset state and notify upper layer about
+ * immidiatly failed attempts */
+ isdn_x25iface_disconn_ind(cprot);
+ }
} else {
illegal_state_warn( *state, firstbyte );
}
diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c
index 46d4f6518..2e580e1c7 100644
--- a/drivers/isdn/isdnloop/isdnloop.c
+++ b/drivers/isdn/isdnloop/isdnloop.c
@@ -1,4 +1,4 @@
-/* $Id: isdnloop.c,v 1.4 1998/02/24 21:39:05 he Exp $
+/* $Id: isdnloop.c,v 1.8 1998/11/18 18:59:43 armin Exp $
* ISDN low-level module implementing a dummy loop driver.
*
@@ -19,6 +19,20 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdnloop.c,v $
+ * Revision 1.8 1998/11/18 18:59:43 armin
+ * changes for 2.1.127
+ *
+ * Revision 1.7 1998/10/30 18:58:03 he
+ * typecast to suppress a compiler warning
+ *
+ * Revision 1.6 1998/06/17 19:51:37 he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.5 1998/04/14 20:59:32 he
+ * merged 2.1.94 changes
+ *
* Revision 1.4 1998/02/24 21:39:05 he
* L2_PROT_X25DTE / DCE
* additional state 17 and new internal signal messages "BCON_I"
@@ -42,7 +56,7 @@
#include "isdnloop.h"
static char
-*revision = "$Revision: 1.4 $";
+*revision = "$Revision: 1.8 $";
static int isdnloop_addcard(char *);
@@ -1312,7 +1326,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card)
c->parm.num[0] ? "N" : "ALL", c->parm.num);
} else
sprintf(cbuf, "%02d;EAZ%s\n", (int) a,
- c->parm.num[0] ? c->parm.num : "0123456789");
+ c->parm.num[0] ? c->parm.num : (u_char *) "0123456789");
i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
}
break;
diff --git a/drivers/isdn/isdnloop/isdnloop.h b/drivers/isdn/isdnloop/isdnloop.h
index cacd686d7..42906c143 100644
--- a/drivers/isdn/isdnloop/isdnloop.h
+++ b/drivers/isdn/isdnloop/isdnloop.h
@@ -1,4 +1,4 @@
-/* $Id: isdnloop.h,v 1.2 1997/10/01 09:22:07 fritz Exp $
+/* $Id: isdnloop.h,v 1.3 1998/04/14 20:59:35 he Exp $
* Loopback lowlevel module for testing of linklevel.
*
@@ -19,6 +19,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdnloop.h,v $
+ * Revision 1.3 1998/04/14 20:59:35 he
+ * merged 2.1.94 changes
+ *
* Revision 1.2 1997/10/01 09:22:07 fritz
* Removed old compatibility stuff for 2.0.X kernels.
* From now on, this code is for 2.1.X ONLY!
diff --git a/drivers/isdn/pcbit/callbacks.c b/drivers/isdn/pcbit/callbacks.c
index 14c0bdcb8..afa22b740 100644
--- a/drivers/isdn/pcbit/callbacks.c
+++ b/drivers/isdn/pcbit/callbacks.c
@@ -11,6 +11,13 @@
* callbacks for the FSM
*/
+/*
+ * Fix: 19981230 - Carlos Morgado <chbm@techie.com>
+ * Port of Nelson Escravana's <nelson.escravana@usa.net> fix to CalledPN
+ * NULL pointer dereference in cb_in_1 (originally fixed in 2.0)
+ */
+
+
#define __NO_VERSION__
#include <linux/module.h>
@@ -164,12 +171,24 @@ void cb_in_1(struct pcbit_dev * dev, struct pcbit_chan* chan,
* ictl.num >= strlen() + strlen() + 5
*/
+ if (cbdata->data.setup.CallingPN == NULL) {
+ printk(KERN_DEBUG "NULL CallingPN to phone; using 0\n");
+ strcpy(ictl.parm.setup.phone, "0");
+ }
+ else {
strcpy(ictl.parm.setup.phone, cbdata->data.setup.CallingPN);
+ }
+ if (cbdata->data.setup.CalledPN == NULL) {
+ printk(KERN_DEBUG "NULL CalledPN to eazmsn; using 0\n");
+ strcpy(ictl.parm.setup.eazmsn, "0");
+ }
+ else {
strcpy(ictl.parm.setup.eazmsn, cbdata->data.setup.CalledPN);
- ictl.parm.setup.si1 = 7;
- ictl.parm.setup.si2 = 0;
- ictl.parm.setup.plan = 0;
- ictl.parm.setup.screen = 0;
+ }
+ ictl.parm.setup.si1 = 7;
+ ictl.parm.setup.si2 = 0;
+ ictl.parm.setup.plan = 0;
+ ictl.parm.setup.screen = 0;
#ifdef DEBUG
printk(KERN_DEBUG "statstr: %s\n", ictl.num);
diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c
index 43c36fa9e..a3186ac11 100644
--- a/drivers/isdn/pcbit/drv.c
+++ b/drivers/isdn/pcbit/drv.c
@@ -86,6 +86,9 @@ int pcbit_init_dev(int board, int mem_base, int irq)
dev_pcbit[board] = dev;
memset(dev, 0, sizeof(struct pcbit_dev));
+#if LINUX_VERSION_CODE >= 131841
+ init_waitqueue_head(&dev->set_running_wq);
+#endif
if (mem_base >= 0xA0000 && mem_base <= 0xFFFFF )
dev->sh_mem = (unsigned char*) mem_base;
diff --git a/drivers/isdn/pcbit/pcbit.h b/drivers/isdn/pcbit/pcbit.h
index 20051bf3e..0dbdb5fd1 100644
--- a/drivers/isdn/pcbit/pcbit.h
+++ b/drivers/isdn/pcbit/pcbit.h
@@ -68,7 +68,11 @@ struct pcbit_dev {
struct frame_buf *write_queue;
/* Protocol start */
+#if LINUX_VERSION_CODE < 131841
struct wait_queue *set_running_wq;
+#else
+ wait_queue_head_t set_running_wq;
+#endif
struct timer_list set_running_timer;
struct timer_list error_recover_timer;
diff --git a/drivers/isdn/sc/message.c b/drivers/isdn/sc/message.c
index 628cdc803..4d4765f79 100644
--- a/drivers/isdn/sc/message.c
+++ b/drivers/isdn/sc/message.c
@@ -1,5 +1,5 @@
/*
- * $Id: message.c,v 1.3 1998/01/31 22:10:55 keil Exp $
+ * $Id: message.c,v 1.4 1999/01/05 18:29:47 he Exp $
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
*
* message.c - functions for sending and receiving control messages