chipset in a more general way. This chipset is used on various
ISDN-cards (like AVM A1, Elsa ISDN cards, Teles S0-16.0,
Teles S0-16.3, Teles S0-8, Teles/Creatix PnP, ITK micro ix1 and
- many compatibles). It's a complete rewrite of the original Teles
- driver.
+ many compatibles). It supports other chipsets too.
See Documentation/isdn/README.HiSax for further informations on
using this driver.
+HiSax Support for EURO/DSS1
+CONFIG_HISAX_EURO
+ Enable this if you have a EURO ISDN line.
+
+Support for german chargeinfo
+CONFIG_DE_AOC
+If you have german AOC, you can enable this to get the charginfo.
+
+Disable sending complete
+CONFIG_HISAX_NO_SENDCOMPLETE
+If you have trouble with some ugly exchanges or you live in Australia
+select this option.
+
+Disable sending low layer compatibility
+CONFIG_HISAX_NO_LLC
+If you have trouble with some ugly exchanges try to select this
+option.
+
+HiSax Support for german 1TR6
+CONFIG_HISAX_1TR6
+Enable this if you have a old german 1TR6 line.
+Note: Many older local switches are using 1TR6 on internal S0.
+
HiSax Support for Teles 16.0/8.0
CONFIG_HISAX_16_0
This enables HiSax support for the Teles ISDN-cards S0-16.0,
the Teles/Creatix PnP and the Teles PCMCIA.
See Documentation/isdn/README.HiSax on how to configure it
using the different cards, a different D-channel protocol, or
- non-standard IRQ/port/shmem settings.
+ non-standard IRQ/port settings.
+
+HiSax Support for Teles 16.3c
+CONFIG_HISAX_TELES3C
+ This enables HiSax support for the Teles 16.3c PnP.
+ See Documentation/isdn/README.HiSax on how to configure it.
+
+HiSax Support for Teles PCI
+CONFIG_HISAX_TELESPCI
+ This enables HiSax support for the Teles PCI.
+ See Documentation/isdn/README.HiSax on how to configure it.
+
+HiSax Support for Teles S0Box
+CONFIG_HISAX_S0BOX
+ This enables HiSax support for the Teles/Creatix parallel port S0BOX.
+ See Documentation/isdn/README.HiSax on how to configure it.
HiSax Support for AVM A1 (Fritz)
CONFIG_HISAX_AVM_A1
- This enables HiSax support for the AVM A1 (aka "Fritz").
+ This enables HiSax support for the AVM A1 (aka "Fritz!").
See Documentation/isdn/README.HiSax on how to configure it
using the different cards, a different D-channel protocol, or
- non-standard IRQ/port/shmem settings.
+ non-standard IRQ/port settings.
-HiSax Support for Elsa ISA cards
-CONFIG_HISAX_ELSA_PCC
- This enables HiSax support for the Elsa Mircolink cards and
- for the Elsa Quickstep series cards for the ISA bus.
- You don't have to select "HiSax Support for Elsa PCMCIA card"
- at the same time.
- See Documentation/isdn/README.HiSax on how to configure it
- using the different cards, a different D-channel protocol, or
- non-standard IRQ/port/shmem settings.
+HiSax Support for AVM PCI (Fritz!PCI)
+CONFIG_HISAX_FRITZPCI
+ This enables HiSax support for the AVM "Fritz!PCI").
+ See Documentation/isdn/README.HiSax on how to configure it.
+
+HiSax Support for AVM A1 PCMCIA (Fritz)
+CONFIG_HISAX_AVM_A1_PCMCIA
+ This enables HiSax support for the AVM A1 "Fritz!PCMCIA").
+ See Documentation/isdn/README.HiSax on how to configure it.
-HiSax Support for Elsa PCMCIA card
-CONFIG_HISAX_ELSA_PCMCIA
- This enables HiSax support for the Elsa PCMCIA card.
- You don't have to select "HiSax Support for Elsa ISA cards" at
- the same time.
+HiSax Support for Elsa ISA cards
+CONFIG_HISAX_ELSA
+ This enables HiSax support for all Elsa cards.
See Documentation/isdn/README.HiSax on how to configure it
using the different cards, a different D-channel protocol, or
- non-standard IRQ/port/shmem settings.
+ non-standard IRQ/port settings.
HiSax Support for ITK ix1-micro Revision 2
CONFIG_HISAX_IX1MICROR2
This enables HiSax support for the ITK ix1-micro Revision 2 card.
- See Documentation/isdn/README.HiSax on how to configure it
- using the different cards, a different D-channel protocol, or
- non-standard IRQ/port/shmem settings.
-
-HiSax Support for EURO/DSS1
-CONFIG_HISAX_EURO
- You should choose your D-channel protocol your local
- telephone service provider uses here by saying Y or N.
- NOTE: This is mutually exclusive with HiSax Support for
- german 1TR6 and US/NI-1 if you have only one ISDN card
- installed.
-
-HiSax Support for US/NI-1
-CONFIG_HISAX_NI1
- You should choose your D-channel protocol your local
- telephone service provider uses here by saying Y or N.
- NOTE: This is mutually exclusive with HiSax Support for
- german 1TR6 and EURO/DSS1 if you have only one ISDN card
- installed. (not working yet, under developement)
-
-HiSax Support for german 1TR6
-CONFIG_HISAX_1TR6
- You should choose your D-channel protocol your local
- telephone service provider uses here by saying Y or N.
- NOTE: This is mutually exclusive with HiSax Support for
- EURO/DSS1 and US/NI-1 if you have only one ISDN card
- installed.
+ See Documentation/isdn/README.HiSax on how to configure it.
+
+HiSax Support for Eicon.Diehl Diva cards
+CONFIG_HISAX_DIEHLDIVA
+ This enables HiSax support for all none Pro versions of Eicon.Diehl's
+ Diva series passiv cards.
+ See Documentation/isdn/README.HiSax on how to configure it.
+
+HiSax Support for ASUSCOM cards
+CONFIG_HISAX_ASUSCOM
+ This enables HiSax support for all AsusCom passiv cards.
+ See Documentation/isdn/README.HiSax on how to configure it.
+
+HiSax Support for TELEINT cards
+CONFIG_HISAX_TELEINT
+ This enables HiSax support for TeleInts semi-activ card and for other
+ HFC-2BS0 based cards
+ See Documentation/isdn/README.HiSax on how to configure it.
+
+HiSax Support for Sedlbauer speed card/win/star/PC104/fax
+CONFIG_HISAX_SEDLBAUER
+ This enables HiSax support for all Sedlbauer passiv cards.
+ See Documentation/isdn/README.HiSax on how to configure it.
+
+HiSax Support for USR Sportster internal TA
+CONFIG_HISAX_SPORTSTER
+ This enables HiSax support for the USR (3Com) Sportster internal TA passiv card.
+ See Documentation/isdn/README.HiSax on how to configure it.
+
+HiSax Support for MIC card
+CONFIG_HISAX_MIC
+ This enables HiSax support for the MIC passiv card.
+ See Documentation/isdn/README.HiSax on how to configure it.
+
+HiSax Support for NETjet card
+CONFIG_HISAX_NETJET
+ This enables HiSax support for the NetJet PCI and maybe for other
+ Tiger300 based passiv cards.
+ See Documentation/isdn/README.HiSax on how to configure it.
+
+HiSax Support for Niccy PnP/PCI card
+CONFIG_HISAX_NICCY
+ This enables HiSax support for Dr. Neuhaus (Sagem) Niccy series
+ passiv cards.
+ See Documentation/isdn/README.HiSax on how to configure it.
PCBIT-D support
CONFIG_ISDN_DRV_PCBIT
Creatix PnP S0
Compaq ISDN S0 ISA card
AVM A1 (Fritz, Teledat 150)
+AVM Fritz PCMCIA
+AVM Fritz PCI
ELSA Microlink PCC-16, PCF, PCF-Pro, PCC-8
ELSA Quickstep 1000
ELSA Quickstep 1000PCI
HFC-2BS0 based cards (TeleInt SA1)
Sedlbauer Speed Card (Speed Win, Teledat 100)
Sedlbauer Speed Star (PCMCIA)
+Sedlbauer ISDN-Controller PC/104
USR Sportster internal TA (compatible Stollmann tina-pp V3)
ith Kommunikationstechnik GmbH MIC 16 ISA card
Traverse Technologie NETjet PCI S0 card
with LILO or LOADLIN or, if built as a module, using insmod/modprobe with
parameters.
There is also some config needed before you compile the kernel and/or
-modules. It is enclose in the normal "make [menu]config" target at the
+modules. It is included in the normal "make [menu]config" target at the
kernel. Don't forget it, especially to select the right D-channel protocol.
Please note: All PnP cards need to be configured with isapnp and will work
24 Dr. Neuhaus Niccy PnP irq, io0, io1 (from isapnp setup)
24 Dr. Neuhaus Niccy PCI no parameter
25 Teles S0Box irq, io (of the used lpt port)
+ 26 AVM A1 PCMCIA (Fritz!) irq, io (set with card manager)
+ 27 AVM PCI (Fritz!PCI) no parameter
At the moment IRQ sharing is only possible with PCI cards. Please make sure
that your IRQ is free and enabled for ISA use.
-Note: For using the ELSA PCMCIA you need the cardmanager under MSDOS for
-enabling in the moment, then boot linux with loadlin.
Examples for module loading
21 Teles PCI no parameter
22 Sedlbauer Speed Star (PCMCIA) pa=irq, pb=io (set with card manager)
24 Dr. Neuhaus Niccy PnP ONLY WORKS AS A MODULE !
- 24 Dr. Neuhaus Niccy PCI no parameter
- 25 Teles S0Box irq, io (of the used lpt port)
+ 24 Dr. Neuhaus Niccy PCI no parameter
+ 25 Teles S0Box irq, io (of the used lpt port)
+ 26 AVM A1 PCMCIA (Fritz!) irq, io (set with card manager)
+ 27 AVM PCI (Fritz!PCI) no parameter
Running the driver
------------------
hisaxctrl <DriverId> DebugCmd <debugging_flags>
-<DriverId> default is HiSax, if you didn't specified one.
+<DriverId> default is HiSax, if you didn't specify one.
DebugCmd is 1 for generic debugging
11 for layer 1 development debugging
With DebugCmd set to 13:
1 Warnings (default: on)
- 2 l3 protocol discriptor errors
+ 2 l3 protocol descriptor errors
4 l3 state machine
8 charge info debugging (1TR6)
For example, 'hisaxctrl HiSax 1 0x3ff' enables full generic debugging.
Because of some obscure problems with some switch equipment, the delay
-between CONNECT message and sending the first data on th B-channel is now
+between the CONNECT message and sending the first data on the B-channel is now
configurable with
hisaxctrl <DriverId> 2 <delay>
-<delay> in ms Value between 50 an 800 ms are recommended.
+<delay> in ms Value between 50 and 800 ms is recommended.
Warning
Firma S.u.S.E
Firma ith Kommunikationstechnik GmbH
Firma Traverse Technologie Australia
-
+ Firma Medusa GmbH (www.medusa.de).
+ Firma Quant-X Austria for sponsoring a DEC Alpha board+CPU
+
My girl friend and partner in life Ute for her patience with me.
Attention NEW VERSION, the old leased line syntax won't work !!!
You can use HiSax to connect your Linux-Box via an ISDN leased line
-to i.e. the internet:
+to e.g. the Internet:
1. Build a kernel which includes the HiSax driver either as a module
or as part of the kernel.
vi /etc/lilo.conf
<add HiSax driver parameter in the global section (see below)>
lilo
- Your lilo.conf _might_ look as the following:
+ Your lilo.conf _might_ look like the following:
# LILO configuration-file
# global section
/sbin/isdnctrl secure isdn0 on
/sbin/isdnctrl huptimeout isdn0 0
/sbin/isdnctrl l2_prot isdn0 hdlc
- # Attention you must not set a outgoing number !!! This won't work !!!
+ # Attention you must not set an outgoing number !!! This won't work !!!
# The incomming number is LEASED0 for the first card, LEASED1 for the
# second and so on.
/sbin/isdnctrl addphone isdn0 in LEASED0
/sbin/hisaxctrl HiSax 5 1
Remarks:
-a) If you have a CISCO don´t forget to switch off the KEEP ALIVE option!
+a) If you have a CISCO don't forget to switch off the KEEP ALIVE option!
+b) Use state of the art isdn4k-utils
Here an example script:
#!/bin/sh
/sbin/isdnctrl encap isdn0s cisco-h
fi
fi
+ /sbin/isdnctrl status isdn0 on
# configure tcp/ip
/sbin/ifconfig isdn0 ${LOCAL_IP} pointopoint ${REMOTE_IP}
/sbin/route add -host ${REMOTE_IP} isdn0
bool 'HiSax Support for EURO/DSS1' CONFIG_HISAX_EURO
if [ "$CONFIG_HISAX_EURO" != "n" ]; then
bool 'Support for german chargeinfo' CONFIG_DE_AOC
- bool 'Support for australian Microlink service (not for std. EURO)' CONFIG_HISAX_ML
+ 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 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 PCI (Fritz!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/PC104/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
L_OBJS :=
M_OBJS :=
+LX_OBJS :=
+MX_OBJS :=
+O_OBJS :=
+OX_OBJS :=
+L_TARGET :=
+O_TARGET :=
+
O_OBJS := isdnl1.o tei.o isdnl2.o isdnl3.o \
lmgr.o q931.o callc.o fsm.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
HSCX_OBJ := hscx.o
endif
-O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(HFC_OBJ) $(HFC_2BDS0) $(ARCOFI_OBJ)
+O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(ARCOFI_OBJ)
+O_OBJS += $(HFC_OBJ) $(HFC_2BDS0)
OX_OBJS += config.o
O_TARGET :=
-/* $Id: arcofi.c,v 1.1.2.3 1998/05/27 18:04:48 keil Exp $
+/* $Id: arcofi.c,v 1.1.2.5 1998/09/30 22:20:03 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.1.2.5 1998/09/30 22:20:03 keil
+ * Cosmetics
+ *
+ * Revision 1.1.2.4 1998/09/27 13:05:29 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
* Revision 1.1.2.3 1998/05/27 18:04:48 keil
* HiSax 3.0
*
int
send_arcofi(struct IsdnCardState *cs, const u_char *msg, int bc, int receive) {
u_char val;
- char tmp[32];
long flags;
- int cnt=50;
+ int cnt=30;
cs->mon_txp = 0;
cs->mon_txc = msg[0];
while (cnt && !test_bit(HW_MON1_TX_END, &cs->HW_Flags)) {
cnt--;
udelay(500);
-#if 0
- current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + (10 * HZ) / 1000; /* Timeout 10ms */
- schedule();
-#endif
}
if (receive) {
while (cnt && !test_bit(HW_MON1_RX_END, &cs->HW_Flags)) {
}
}
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);
}
-
-/* $Id: avm_a1.c,v 1.6.2.10 1998/05/27 18:04:50 keil Exp $
+/* $Id: avm_a1.c,v 1.6.2.11 1998/09/27 13:05:30 keil Exp $
* avm_a1.c low level stuff for AVM A1 (Fritz) isdn cards
*
*
*
* $Log: avm_a1.c,v $
+ * Revision 1.6.2.11 1998/09/27 13:05:30 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
* Revision 1.6.2.10 1998/05/27 18:04:50 keil
* HiSax 3.0
*
#include "isdnl1.h"
extern const char *CardType[];
-const char *avm_revision = "$Revision: 1.6.2.10 $";
+static const char *avm_revision = "$Revision: 1.6.2.11 $";
#define AVM_A1_STAT_ISAC 0x01
#define AVM_A1_STAT_HSCX 0x02
--- /dev/null
+/* $Id: avm_a1p.c,v 1.1.2.2 1998/09/27 13:05:33 keil Exp $
+ *
+ * avm_a1p.c low level stuff for the following AVM cards:
+ * A1 PCMCIA
+ * FRITZ!Card PCMCIA
+ * FRITZ!Card PCMCIA 2.0
+ *
+ * Author Carsten Paeth (calle@calle.in-berlin.de)
+ *
+ * $Log: avm_a1p.c,v $
+ * Revision 1.1.2.2 1998/09/27 13:05:33 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
+ * Revision 1.1.2.1 1998/07/15 14:43:26 calle
+ * Support for AVM passive PCMCIA cards:
+ * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0
+ *
+ *
+ */
+#define __NO_VERSION__
+#include "hisax.h"
+#include "isac.h"
+#include "hscx.h"
+#include "isdnl1.h"
+
+/* register offsets */
+#define ADDRREG_OFFSET 0x02
+#define DATAREG_OFFSET 0x03
+#define ASL0_OFFSET 0x04
+#define ASL1_OFFSET 0x05
+#define MODREG_OFFSET 0x06
+#define VERREG_OFFSET 0x07
+
+/* address offsets */
+#define ISAC_FIFO_OFFSET 0x00
+#define ISAC_REG_OFFSET 0x20
+#define HSCX_CH_DIFF 0x40
+#define HSCX_FIFO_OFFSET 0x80
+#define HSCX_REG_OFFSET 0xa0
+
+/* read bits ASL0 */
+#define ASL0_R_TIMER 0x10 /* active low */
+#define ASL0_R_ISAC 0x20 /* active low */
+#define ASL0_R_HSCX 0x40 /* active low */
+#define ASL0_R_TESTBIT 0x80
+#define ASL0_R_IRQPENDING (ASL0_R_ISAC|ASL0_R_HSCX|ASL0_R_TIMER)
+
+/* write bits ASL0 */
+#define ASL0_W_RESET 0x01
+#define ASL0_W_TDISABLE 0x02
+#define ASL0_W_TRESET 0x04
+#define ASL0_W_IRQENABLE 0x08
+#define ASL0_W_TESTBIT 0x80
+
+/* write bits ASL1 */
+#define ASL1_W_LED0 0x10
+#define ASL1_W_LED1 0x20
+#define ASL1_W_ENABLE_S0 0xC0
+
+#define byteout(addr,val) outb(val,addr)
+#define bytein(addr) inb(addr)
+
+static const char *avm_revision = "$Revision: 1.1.2.2 $";
+
+static inline u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+ long flags;
+ u_char ret;
+
+ offset -= 0x20;
+ save_flags(flags);
+ cli();
+ byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset);
+ ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET);
+ restore_flags(flags);
+ return ret;
+}
+
+static inline void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+ long flags;
+
+ offset -= 0x20;
+
+ save_flags(flags);
+ cli();
+ byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset);
+ byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value);
+ restore_flags(flags);
+}
+
+static inline void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+ long flags;
+
+ save_flags(flags);
+ cli();
+ byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET);
+ insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
+ restore_flags(flags);
+}
+
+static inline void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+ long flags;
+
+ save_flags(flags);
+ cli();
+ byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET);
+ outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
+ restore_flags(flags);
+}
+
+static inline u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
+{
+ u_char ret;
+ long flags;
+
+ offset -= 0x20;
+
+ save_flags(flags);
+ cli();
+ byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
+ HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset);
+ ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET);
+ restore_flags(flags);
+ return ret;
+}
+
+static inline void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
+{
+ long flags;
+
+ offset -= 0x20;
+
+ save_flags(flags);
+ cli();
+ byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
+ HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset);
+ byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value);
+ restore_flags(flags);
+}
+
+static inline void
+ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
+{
+ long flags;
+
+ save_flags(flags);
+ cli();
+ byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
+ HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF);
+ insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
+ restore_flags(flags);
+}
+
+static inline void
+WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
+{
+ long flags;
+
+ save_flags(flags);
+ cli();
+ byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
+ HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF);
+ outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
+ restore_flags(flags);
+}
+
+/*
+ * fast interrupt HSCX stuff goes here
+ */
+
+#define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg)
+#define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data)
+#define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt)
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt)
+
+#include "hscx_irq.c"
+
+static void
+avm_a1p_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 PCMCIA: Spurious interrupt!\n");
+ return;
+ }
+ while ((sval = (~bytein(cs->hw.avm.cfg_reg+ASL0_OFFSET) & ASL0_R_IRQPENDING))) {
+ if (cs->debug & L1_DEB_INTSTAT) {
+ sprintf(tmp, "avm IntStatus %x", sval);
+ debugl1(cs, tmp);
+ }
+ if (sval & ASL0_R_HSCX) {
+ val = ReadHSCX(cs, 1, HSCX_ISTA);
+ if (val) {
+ hscx_int_main(cs, val);
+ stat |= 1;
+ }
+ }
+ if (sval & ASL0_R_ISAC) {
+ val = ReadISAC(cs, ISAC_ISTA);
+ if (val) {
+ isac_interrupt(cs, val);
+ stat |= 2;
+ }
+ }
+ }
+ if (stat & 1) {
+ WriteHSCX(cs, 0, HSCX_MASK, 0xff);
+ WriteHSCX(cs, 1, HSCX_MASK, 0xff);
+ WriteHSCX(cs, 0, HSCX_MASK, 0x00);
+ WriteHSCX(cs, 1, HSCX_MASK, 0x00);
+ }
+ if (stat & 2) {
+ WriteISAC(cs, ISAC_MASK, 0xff);
+ WriteISAC(cs, ISAC_MASK, 0x00);
+ }
+}
+
+static int
+AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+ int ret;
+ switch (mt) {
+ case CARD_RESET:
+ byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
+ HZDELAY(HZ / 5 + 1);
+ byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
+ HZDELAY(HZ / 5 + 1);
+ byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
+ return 0;
+
+ case CARD_RELEASE:
+ /* free_irq is done in HiSax_closecard(). */
+ /* free_irq(cs->irq, cs); */
+ return 0;
+
+ case CARD_SETIRQ:
+ ret = request_irq(cs->irq, &avm_a1p_interrupt,
+ I4L_IRQ_FLAG, "HiSax", cs);
+ if (ret)
+ return ret;
+ byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,
+ ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE);
+ return 0;
+
+ case CARD_INIT:
+ clear_pending_isac_ints(cs);
+ clear_pending_hscx_ints(cs);
+ inithscxisac(cs, 1);
+ inithscxisac(cs, 2);
+ return 0;
+
+ case CARD_TEST:
+ /* we really don't need it for the PCMCIA Version */
+ return 0;
+
+ default:
+ /* all card drivers ignore others, so we do the same */
+ return 0;
+ }
+ return 0;
+}
+
+__initfunc(int
+setup_avm_a1_pcmcia(struct IsdnCard *card))
+{
+ u_char model, vers;
+ struct IsdnCardState *cs = card->cs;
+ long flags;
+ char tmp[64];
+
+
+ strcpy(tmp, avm_revision);
+ printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n",
+ HiSax_getrev(tmp));
+ if (cs->typ != ISDN_CTYPE_A1_PCMCIA)
+ return (0);
+
+ cs->hw.avm.cfg_reg = card->para[1];
+ cs->irq = card->para[0];
+
+
+ save_flags(flags);
+ outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0);
+ sti();
+
+ byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
+ HZDELAY(HZ / 5 + 1);
+ byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
+ HZDELAY(HZ / 5 + 1);
+ byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
+
+ byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET, ASL0_W_TDISABLE|ASL0_W_TRESET);
+
+ restore_flags(flags);
+
+ model = bytein(cs->hw.avm.cfg_reg+MODREG_OFFSET);
+ vers = bytein(cs->hw.avm.cfg_reg+VERREG_OFFSET);
+
+ printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %d\n",
+ cs->hw.avm.cfg_reg, cs->irq, model, vers);
+
+ cs->readisac = &ReadISAC;
+ cs->writeisac = &WriteISAC;
+ cs->readisacfifo = &ReadISACfifo;
+ cs->writeisacfifo = &WriteISACfifo;
+ cs->BC_Read_Reg = &ReadHSCX;
+ cs->BC_Write_Reg = &WriteHSCX;
+ cs->BC_Send_Data = &hscx_fill_fifo;
+ cs->cardmsg = &AVM_card_msg;
+
+ ISACVersion(cs, "AVM A1 PCMCIA:");
+ if (HscxVersion(cs, "AVM A1 PCMCIA:")) {
+ printk(KERN_WARNING
+ "AVM A1 PCMCIA: wrong HSCX versions check IO address\n");
+ return (0);
+ }
+ return (1);
+}
--- /dev/null
+/* $Id: avm_pci.c,v 1.1.2.3 1998/09/27 23:52:57 keil Exp $
+
+ * avm_pci.c low level stuff for AVM Fritz!PCI isdn cards
+ * Thanks to AVM, Berlin for informations
+ *
+ * Author Karsten Keil (keil@temic-ech.spacenet.de)
+ *
+ *
+ * $Log: avm_pci.c,v $
+ * Revision 1.1.2.3 1998/09/27 23:52:57 keil
+ * Fix error handling
+ *
+ * Revision 1.1.2.2 1998/09/27 13:03:16 keil
+ * Fix segfaults on connect
+ *
+ * Revision 1.1.2.1 1998/08/25 14:01:24 calle
+ * Ported driver for AVM Fritz!Card PCI from the 2.1 tree.
+ * I could not test it.
+ *
+ * Revision 1.1 1998/08/20 13:47:30 keil
+ * first version
+ *
+ *
+ *
+ */
+#define __NO_VERSION__
+#include <linux/config.h>
+#include "hisax.h"
+#include "isac.h"
+#include "isdnl1.h"
+#include <linux/pci.h>
+#include <linux/bios32.h>
+#include <linux/interrupt.h>
+
+extern const char *CardType[];
+static const char *avm_pci_rev = "$Revision: 1.1.2.3 $";
+
+#define PCI_VENDOR_AVM 0x1244
+#define PCI_FRITZPCI_ID 0xa00
+
+#define HDLC_FIFO 0x0
+#define HDLC_STATUS 0x4
+
+#define AVM_HDLC_1 0x00
+#define AVM_HDLC_2 0x01
+#define AVM_ISAC_FIFO 0x02
+#define AVM_ISAC_REG_LOW 0x04
+#define AVM_ISAC_REG_HIGH 0x06
+
+#define AVM_STATUS0_IRQ_ISAC 0x010000
+#define AVM_STATUS0_IRQ_HDLC 0x020000
+#define AVM_STATUS0_IRQ_TIMER 0x040000
+#define AVM_STATUS0_IRQ_MASK 0x070000
+
+#define AVM_STATUS0_RESET 0x01
+#define AVM_STATUS0_DIS_TIMER 0x02
+#define AVM_STATUS0_RES_TIMER 0x04
+#define AVM_STATUS0_ENA_IRQ 0x08
+#define AVM_STATUS0_TESTBIT 0x10
+
+#define AVM_STATUS1_INT_SEL 0x0f
+#define AVM_STATUS1_ENA_IOM 0x80
+
+#define HDLC_MODE_ITF_FLG 0x010000
+#define HDLC_MODE_TRANS 0x020000
+#define HDLC_MODE_CCR_7 0x040000
+#define HDLC_MODE_CCR_16 0x080000
+#define HDLC_MODE_TESTLOOP 0x800000
+
+#define HDLC_INT_XPR 0x80
+#define HDLC_INT_XDU 0x40
+#define HDLC_INT_RPR 0x20
+#define HDLC_INT_MASK 0xE0
+
+#define HDLC_STAT_RME 0x01
+#define HDLC_STAT_RDO 0x10
+#define HDLC_STAT_CRCVFRRAB 0x0E
+#define HDLC_STAT_CRCVFR 0x06
+#define HDLC_STAT_RML_MASK 0x3f00
+
+#define HDLC_CMD_XRS 0x80
+#define HDLC_CMD_XME 0x01
+#define HDLC_CMD_RRS 0x20
+#define HDLC_CMD_XML_MASK 0x3f00
+
+
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+ register u_int idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;
+ register u_char val;
+ register long flags;
+
+ save_flags(flags);
+ cli();
+ if (idx != inl(cs->hw.avm.cfg_reg + 4))
+ outl(idx, cs->hw.avm.cfg_reg + 4);
+ val = inb(cs->hw.avm.isac + (offset & 0xf));
+ restore_flags(flags);
+ return (val);
+}
+
+static void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+ register u_int idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;
+ register long flags;
+
+ save_flags(flags);
+ cli();
+ if (idx != inl(cs->hw.avm.cfg_reg + 4))
+ outl(idx, cs->hw.avm.cfg_reg + 4);
+ outb(value, cs->hw.avm.isac + (offset & 0xf));
+ restore_flags(flags);
+}
+
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+ if (AVM_ISAC_FIFO != inl(cs->hw.avm.cfg_reg + 4))
+ outl(AVM_ISAC_FIFO, cs->hw.avm.cfg_reg + 4);
+ insb(cs->hw.avm.isac, data, size);
+}
+
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+ if (AVM_ISAC_FIFO != inl(cs->hw.avm.cfg_reg + 4))
+ outl(AVM_ISAC_FIFO, cs->hw.avm.cfg_reg + 4);
+ outsb(cs->hw.avm.isac, data, size);
+}
+
+static inline u_int
+ReadHDLC(struct IsdnCardState *cs, int chan, u_char offset)
+{
+ register u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
+ register u_int val;
+ register long flags;
+
+ save_flags(flags);
+ cli();
+ if (idx != inl(cs->hw.avm.cfg_reg + 4))
+ outl(idx, cs->hw.avm.cfg_reg + 4);
+ val = inl(cs->hw.avm.isac + offset);
+ restore_flags(flags);
+ return (val);
+}
+
+static inline void
+WriteHDLC(struct IsdnCardState *cs, int chan, u_char offset, u_int value)
+{
+ register u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
+ register long flags;
+
+ save_flags(flags);
+ cli();
+ if (idx != inl(cs->hw.avm.cfg_reg + 4))
+ outl(idx, cs->hw.avm.cfg_reg + 4);
+ outl(value, cs->hw.avm.isac + offset);
+ restore_flags(flags);
+}
+
+static u_char
+ReadHDLC_s(struct IsdnCardState *cs, int chan, u_char offset)
+{
+ return(0xff & ReadHDLC(cs, chan, offset));
+}
+
+static void
+WriteHDLC_s(struct IsdnCardState *cs, int chan, u_char offset, u_char value)
+{
+ WriteHDLC(cs, chan, offset, value);
+}
+
+static inline
+struct BCState *Sel_BCS(struct IsdnCardState *cs, int channel)
+{
+ if (cs->bcs[0].mode && (cs->bcs[0].channel == channel))
+ return(&cs->bcs[0]);
+ else if (cs->bcs[1].mode && (cs->bcs[1].channel == channel))
+ return(&cs->bcs[1]);
+ else
+ return(NULL);
+}
+
+void inline
+hdlc_sched_event(struct BCState *bcs, int event)
+{
+ bcs->event |= 1 << event;
+ queue_task(&bcs->tqueue, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+}
+
+void
+modehdlc(struct BCState *bcs, int mode, int bc)
+{
+ struct IsdnCardState *cs = bcs->cs;
+ int hdlc = bcs->channel;
+
+ if (cs->debug & L1_DEB_HSCX) {
+ char tmp[40];
+ sprintf(tmp, "hdlc %c mode %d ichan %d",
+ 'A' + hdlc, mode, bc);
+ debugl1(cs, tmp);
+ }
+ bcs->mode = mode;
+ bcs->channel = bc;
+ switch (mode) {
+ case (L1_MODE_NULL):
+ bcs->hw.hdlc.ctrl = HDLC_MODE_TRANS | HDLC_CMD_XRS | HDLC_CMD_RRS;
+ WriteHDLC(cs, bcs->channel, HDLC_STATUS, bcs->hw.hdlc.ctrl);
+ break;
+ case (L1_MODE_TRANS):
+ bcs->hw.hdlc.ctrl = HDLC_MODE_TRANS | HDLC_CMD_XRS | HDLC_CMD_RRS;
+ WriteHDLC(cs, bcs->channel, HDLC_STATUS, bcs->hw.hdlc.ctrl);
+ bcs->hw.hdlc.ctrl = HDLC_MODE_TRANS | HDLC_CMD_XRS;
+ WriteHDLC(cs, bcs->channel, HDLC_STATUS, bcs->hw.hdlc.ctrl);
+ bcs->hw.hdlc.ctrl = HDLC_MODE_TRANS;
+ hdlc_sched_event(bcs, B_XMTBUFREADY);
+ break;
+ case (L1_MODE_HDLC):
+ bcs->hw.hdlc.ctrl = HDLC_MODE_ITF_FLG | HDLC_CMD_XRS | HDLC_CMD_RRS;
+ WriteHDLC(cs, bcs->channel, HDLC_STATUS, bcs->hw.hdlc.ctrl);
+ bcs->hw.hdlc.ctrl = HDLC_MODE_ITF_FLG | HDLC_CMD_XRS;
+ WriteHDLC(cs, bcs->channel, HDLC_STATUS, bcs->hw.hdlc.ctrl);
+ bcs->hw.hdlc.ctrl = HDLC_MODE_ITF_FLG;
+ hdlc_sched_event(bcs, B_XMTBUFREADY);
+ break;
+ }
+}
+
+static inline void
+hdlc_empty_fifo(struct BCState *bcs, int count)
+{
+ register u_int *ptr;
+ u_char *p;
+ u_int idx = bcs->channel ? AVM_HDLC_2 : AVM_HDLC_1;
+ int cnt=0;
+ struct IsdnCardState *cs = bcs->cs;
+
+ if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) {
+ u_char tmp[32];
+ sprintf(tmp, "hdlc_empty_fifo %d", count);
+ debugl1(cs, tmp);
+ }
+ if (bcs->hw.hdlc.rcvidx + count > HSCX_BUFMAX) {
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "hdlc_empty_fifo: incoming packet too large");
+ return;
+ }
+ ptr = (u_int *) p = bcs->hw.hdlc.rcvbuf + bcs->hw.hdlc.rcvidx;
+ bcs->hw.hdlc.rcvidx += count;
+ if (idx != inl(cs->hw.avm.cfg_reg + 4))
+ outl(idx, cs->hw.avm.cfg_reg + 4);
+ while (cnt<count) {
+ *ptr++ = inl(cs->hw.avm.isac);
+ cnt += 4;
+ }
+ if (cs->debug & L1_DEB_HSCX_FIFO) {
+ char tmp[256];
+ char *t = tmp;
+
+ t += sprintf(t, "hdlc_empty_fifo %c cnt %d",
+ bcs->channel ? 'B' : 'A', count);
+ QuickHex(t, p, count);
+ debugl1(cs, tmp);
+ }
+}
+
+static inline void
+hdlc_fill_fifo(struct BCState *bcs)
+{
+ struct IsdnCardState *cs = bcs->cs;
+ int count, cnt =0;
+ int fifo_size = 32;
+ u_char *p;
+ u_int *ptr;
+ u_int idx = bcs->channel ? AVM_HDLC_2 : AVM_HDLC_1;
+
+
+ if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+ debugl1(cs, "hdlc_fill_fifo");
+ if (!bcs->tx_skb)
+ return;
+ if (bcs->tx_skb->len <= 0)
+ return;
+
+ bcs->hw.hdlc.ctrl &= ~HDLC_CMD_XME;
+ if (bcs->tx_skb->len > fifo_size) {
+ count = fifo_size;
+ } else {
+ count = bcs->tx_skb->len;
+ if (bcs->mode != L1_MODE_TRANS)
+ bcs->hw.hdlc.ctrl |= HDLC_CMD_XME;
+ }
+ if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) {
+ u_char tmp[32];
+ sprintf(tmp, "hdlc_fill_fifo %d/%ld", count, bcs->tx_skb->len);
+ debugl1(cs, tmp);
+ }
+ ptr = (u_int *) p = bcs->tx_skb->data;
+ skb_pull(bcs->tx_skb, count);
+ bcs->tx_cnt -= count;
+ bcs->hw.hdlc.count += count;
+ if (idx != inl(cs->hw.avm.cfg_reg + 4))
+ outl(idx, cs->hw.avm.cfg_reg + 4);
+ bcs->hw.hdlc.ctrl &= ~HDLC_CMD_XML_MASK;
+ bcs->hw.hdlc.ctrl |= ((count == fifo_size) ? 0 : count)<<8;
+ outl(bcs->hw.hdlc.ctrl, cs->hw.avm.isac + HDLC_STATUS);
+ while (cnt<count) {
+ outl(*ptr++, cs->hw.avm.isac);
+ cnt += 4;
+ }
+ if (cs->debug & L1_DEB_HSCX_FIFO) {
+ char tmp[256];
+ char *t = tmp;
+
+ t += sprintf(t, "hdlc_fill_fifo %c cnt %d",
+ bcs->channel ? 'B' : 'A', count);
+ QuickHex(t, p, count);
+ debugl1(cs, tmp);
+ }
+}
+
+static void
+fill_hdlc(struct BCState *bcs)
+{
+ long flags;
+ save_flags(flags);
+ cli();
+ hdlc_fill_fifo(bcs);
+ restore_flags(flags);
+}
+
+static inline void
+HDLC_irq(struct BCState *bcs, u_int stat) {
+ u_char tmp[32];
+ int len;
+ struct sk_buff *skb;
+
+ if (bcs->cs->debug & L1_DEB_HSCX) {
+ sprintf(tmp, "ch%d stat %#x", bcs->channel, stat);
+ debugl1(bcs->cs, tmp);
+ }
+ if (stat & HDLC_INT_RPR) {
+ if (stat & HDLC_STAT_RDO) {
+ if (bcs->cs->debug & L1_DEB_HSCX) {
+ debugl1(bcs->cs, "RDO");
+ } else {
+ sprintf(tmp, "ch%d stat %#x", bcs->channel, stat);
+ debugl1(bcs->cs, tmp);
+ }
+ bcs->hw.hdlc.ctrl &= ~HDLC_STAT_RML_MASK;
+ bcs->hw.hdlc.ctrl |= HDLC_CMD_RRS;
+ WriteHDLC(bcs->cs, bcs->channel, HDLC_STATUS, bcs->hw.hdlc.ctrl);
+ bcs->hw.hdlc.ctrl &= ~HDLC_CMD_RRS;
+ WriteHDLC(bcs->cs, bcs->channel, HDLC_STATUS, bcs->hw.hdlc.ctrl);
+ bcs->hw.hdlc.rcvidx = 0;
+ } else {
+ if (!(len = (stat & HDLC_STAT_RML_MASK)>>8))
+ len = 32;
+ hdlc_empty_fifo(bcs, len);
+ if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) {
+ if (((stat & HDLC_STAT_CRCVFRRAB)==HDLC_STAT_CRCVFR) ||
+ (bcs->mode == L1_MODE_TRANS)) {
+ if (!(skb = dev_alloc_skb(bcs->hw.hdlc.rcvidx)))
+ printk(KERN_WARNING "HDLC: receive out of memory\n");
+ else {
+ memcpy(skb_put(skb, bcs->hw.hdlc.rcvidx),
+ bcs->hw.hdlc.rcvbuf, bcs->hw.hdlc.rcvidx);
+ skb_queue_tail(&bcs->rqueue, skb);
+ }
+ bcs->hw.hdlc.rcvidx = 0;
+ hdlc_sched_event(bcs, B_RCVBUFREADY);
+ } else {
+ if (bcs->cs->debug & L1_DEB_HSCX) {
+ debugl1(bcs->cs, "invalid frame");
+ } else {
+ sprintf(tmp, "ch%d invalid frame %#x", bcs->channel, stat);
+ debugl1(bcs->cs, tmp);
+ }
+ bcs->hw.hdlc.rcvidx = 0;
+ }
+ }
+ }
+ }
+ if (stat & HDLC_INT_XDU) {
+ /* Here we lost an TX interrupt, so
+ * restart transmitting the whole frame.
+ */
+ if (bcs->tx_skb) {
+ skb_push(bcs->tx_skb, bcs->hw.hdlc.count);
+ bcs->tx_cnt += bcs->hw.hdlc.count;
+ bcs->hw.hdlc.count = 0;
+// hdlc_sched_event(bcs, B_XMTBUFREADY);
+ sprintf(tmp, "ch%d XDU", bcs->channel);
+ } else {
+ sprintf(tmp, "ch%d XDU without skb", bcs->channel);
+ }
+ if (bcs->cs->debug & L1_DEB_WARN)
+ debugl1(bcs->cs, tmp);
+ bcs->hw.hdlc.ctrl &= ~HDLC_STAT_RML_MASK;
+ bcs->hw.hdlc.ctrl |= HDLC_CMD_XRS;
+ WriteHDLC(bcs->cs, bcs->channel, HDLC_STATUS, bcs->hw.hdlc.ctrl);
+ bcs->hw.hdlc.ctrl &= ~HDLC_CMD_XRS;
+ WriteHDLC(bcs->cs, bcs->channel, HDLC_STATUS, bcs->hw.hdlc.ctrl);
+ hdlc_fill_fifo(bcs);
+ } else if (stat & HDLC_INT_XPR) {
+ if (bcs->tx_skb) {
+ if (bcs->tx_skb->len) {
+ hdlc_fill_fifo(bcs);
+ return;
+ } else {
+ if (bcs->st->lli.l1writewakeup &&
+ (PACKET_NOACK != bcs->tx_skb->pkt_type))
+ bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hdlc.count);
+ dev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+ bcs->hw.hdlc.count = 0;
+ bcs->tx_skb = NULL;
+ }
+ }
+ if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+ bcs->hw.hdlc.count = 0;
+ test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+ hdlc_fill_fifo(bcs);
+ } else {
+ test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+ hdlc_sched_event(bcs, B_XMTBUFREADY);
+ }
+ }
+}
+
+inline void
+HDLC_irq_main(struct IsdnCardState *cs)
+{
+ u_int stat;
+ long flags;
+ struct BCState *bcs;
+
+ save_flags(flags);
+ cli();
+ stat = ReadHDLC(cs, 0, HDLC_STATUS);
+ if (stat & HDLC_INT_MASK) {
+ if (!(bcs = Sel_BCS(cs, 0))) {
+ if (cs->debug)
+ debugl1(cs, "hdlc spurious channel 0 IRQ");
+ } else
+ HDLC_irq(bcs, stat);
+ }
+ stat = ReadHDLC(cs, 1, HDLC_STATUS);
+ if (stat & HDLC_INT_MASK) {
+ if (!(bcs = Sel_BCS(cs, 1))) {
+ if (cs->debug)
+ debugl1(cs, "hdlc spurious channel 1 IRQ");
+ } else
+ HDLC_irq(bcs, stat);
+ }
+ restore_flags(flags);
+}
+
+void
+hdlc_l2l1(struct PStack *st, int pr, void *arg)
+{
+ struct sk_buff *skb = arg;
+ long flags;
+
+ switch (pr) {
+ case (PH_DATA | REQUEST):
+ save_flags(flags);
+ cli();
+ if (st->l1.bcs->tx_skb) {
+ skb_queue_tail(&st->l1.bcs->squeue, skb);
+ restore_flags(flags);
+ } else {
+ st->l1.bcs->tx_skb = skb;
+ test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ st->l1.bcs->hw.hdlc.count = 0;
+ restore_flags(flags);
+ st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+ }
+ break;
+ case (PH_PULL | INDICATION):
+ if (st->l1.bcs->tx_skb) {
+ printk(KERN_WARNING "hdlc_l2l1: this shouldn't happen\n");
+ break;
+ }
+ test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ st->l1.bcs->tx_skb = skb;
+ st->l1.bcs->hw.hdlc.count = 0;
+ st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+ break;
+ 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 | 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);
+ modehdlc(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);
+ modehdlc(st->l1.bcs, 0, st->l1.bc);
+ st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+ break;
+ }
+}
+
+void
+close_hdlcstate(struct BCState *bcs)
+{
+ modehdlc(bcs, 0, 0);
+ if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
+ if (bcs->hw.hdlc.rcvbuf) {
+ kfree(bcs->hw.hdlc.rcvbuf);
+ bcs->hw.hdlc.rcvbuf = NULL;
+ }
+ discard_queue(&bcs->rqueue);
+ discard_queue(&bcs->squeue);
+ if (bcs->tx_skb) {
+ dev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+ bcs->tx_skb = NULL;
+ test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+ }
+ }
+}
+
+int
+open_hdlcstate(struct IsdnCardState *cs, struct BCState *bcs)
+{
+ if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
+ if (!(bcs->hw.hdlc.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
+ printk(KERN_WARNING
+ "HiSax: No memory for hdlc.rcvbuf\n");
+ return (1);
+ }
+ skb_queue_head_init(&bcs->rqueue);
+ skb_queue_head_init(&bcs->squeue);
+ }
+ bcs->tx_skb = NULL;
+ test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+ bcs->event = 0;
+ bcs->hw.hdlc.rcvidx = 0;
+ bcs->tx_cnt = 0;
+ return (0);
+}
+
+int
+setstack_hdlc(struct PStack *st, struct BCState *bcs)
+{
+ bcs->channel = st->l1.bc;
+ if (open_hdlcstate(st->l1.hardware, bcs))
+ return (-1);
+ st->l1.bcs = bcs;
+ st->l2.l2l1 = hdlc_l2l1;
+ setstack_manager(st);
+ bcs->st = st;
+ setstack_l1_B(st);
+ return (0);
+}
+
+HISAX_INITFUNC(void
+clear_pending_hdlc_ints(struct IsdnCardState *cs))
+{
+ int val;
+ char tmp[64];
+
+ val = ReadHDLC(cs, 0, HDLC_STATUS);
+ sprintf(tmp, "HDLC 1 STA %x", val);
+ debugl1(cs, tmp);
+ val = ReadHDLC(cs, 1, HDLC_STATUS);
+ sprintf(tmp, "HDLC 2 STA %x", val);
+ debugl1(cs, tmp);
+}
+
+HISAX_INITFUNC(void
+inithdlc(struct IsdnCardState *cs))
+{
+ cs->bcs[0].BC_SetStack = setstack_hdlc;
+ cs->bcs[1].BC_SetStack = setstack_hdlc;
+ cs->bcs[0].BC_Close = close_hdlcstate;
+ cs->bcs[1].BC_Close = close_hdlcstate;
+ modehdlc(cs->bcs, 0, 0);
+ modehdlc(cs->bcs + 1, 0, 0);
+}
+
+static void
+avm_pci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+ struct IsdnCardState *cs = dev_id;
+ u_char val, stat = 0;
+ u_int sval;
+
+ if (!cs) {
+ printk(KERN_WARNING "AVM PCI: Spurious interrupt!\n");
+ return;
+ }
+ sval = inl(cs->hw.avm.cfg_reg);
+ if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK)
+ /* possible a shared IRQ reqest */
+ return;
+ if (!(sval & AVM_STATUS0_IRQ_ISAC)) {
+ val = ReadISAC(cs, ISAC_ISTA);
+ isac_interrupt(cs, val);
+ stat |= 2;
+ }
+ if (!(sval & AVM_STATUS0_IRQ_HDLC)) {
+ HDLC_irq_main(cs);
+ }
+ if (stat & 2) {
+ WriteISAC(cs, ISAC_MASK, 0xFF);
+ WriteISAC(cs, ISAC_MASK, 0x0);
+ }
+}
+
+static void
+reset_avmpci(struct IsdnCardState *cs)
+{
+ long flags;
+
+ save_flags(flags);
+ sti();
+ outb(AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER, cs->hw.avm.cfg_reg + 2);
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + (10 * HZ) / 1000; /* Timeout 10ms */
+ schedule();
+ outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2);
+ outb(AVM_STATUS1_ENA_IOM, cs->hw.avm.cfg_reg + 3);
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + (10 * HZ) / 1000; /* Timeout 10ms */
+ schedule();
+}
+
+static int
+AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+ switch (mt) {
+ case CARD_RESET:
+ reset_avmpci(cs);
+ return(0);
+ case CARD_RELEASE:
+ outb(0, cs->hw.avm.cfg_reg + 2);
+ release_region(cs->hw.avm.cfg_reg, 32);
+ return(0);
+ case CARD_SETIRQ:
+ return(request_irq(cs->irq, &avm_pci_interrupt,
+ I4L_IRQ_FLAG | SA_SHIRQ, "HiSax", cs));
+ case CARD_INIT:
+ clear_pending_isac_ints(cs);
+ initisac(cs);
+ clear_pending_hdlc_ints(cs);
+ inithdlc(cs);
+ outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER,
+ cs->hw.avm.cfg_reg + 2);
+ WriteISAC(cs, ISAC_MASK, 0);
+ outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER |
+ AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2);
+ /* RESET Receiver and Transmitter */
+ WriteISAC(cs, ISAC_CMDR, 0x41);
+ return(0);
+ case CARD_TEST:
+ return(0);
+ }
+ return(0);
+}
+
+static int pci_index __initdata = 0;
+
+__initfunc(int
+setup_avm_pci(struct IsdnCard *card))
+{
+ u_int val;
+ struct IsdnCardState *cs = card->cs;
+ char tmp[64];
+
+ strcpy(tmp, avm_pci_rev);
+ printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp));
+ if (cs->typ != ISDN_CTYPE_FRITZPCI)
+ return (0);
+#if CONFIG_PCI
+ for (pci_index = 0; pci_index < 255; pci_index++) {
+ unsigned char pci_bus, pci_device_fn;
+ unsigned int ioaddr;
+ unsigned char irq;
+
+ if (pcibios_find_device (PCI_VENDOR_AVM,
+ PCI_FRITZPCI_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_1, &ioaddr);
+ cs->irq = irq;
+ cs->hw.avm.cfg_reg = ioaddr & PCI_BASE_ADDRESS_IO_MASK;
+ if (!cs->hw.avm.cfg_reg) {
+ printk(KERN_WARNING "FritzPCI: No IO-Adr for PCI card found\n");
+ return(0);
+ }
+ cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
+ }
+ if (pci_index == 8) {
+ printk(KERN_WARNING "FritzPCI: No PCI card found\n");
+ return(0);
+ }
+#else
+ printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n");
+ return (0);
+#endif /* CONFIG_PCI */
+
+ if (check_region((cs->hw.avm.cfg_reg), 32)) {
+ printk(KERN_WARNING
+ "HiSax: %s config port %x-%x already in use\n",
+ CardType[card->typ],
+ cs->hw.avm.cfg_reg,
+ cs->hw.avm.cfg_reg + 31);
+ return (0);
+ } else {
+ request_region(cs->hw.avm.cfg_reg, 32, "avm PCI");
+ }
+
+ val = inl(cs->hw.avm.cfg_reg);
+ printk(KERN_INFO "AVM PCI: stat %#x\n", val);
+ printk(KERN_INFO "AVM PCI: Class %X Rev %d\n",
+ val & 0xff, (val>>8) & 0xff);
+
+ printk(KERN_INFO
+ "HiSax: %s config irq:%d base:0x%X\n",
+ CardType[cs->typ], cs->irq,
+ cs->hw.avm.cfg_reg);
+
+ cs->readisac = &ReadISAC;
+ cs->writeisac = &WriteISAC;
+ cs->readisacfifo = &ReadISACfifo;
+ cs->writeisacfifo = &WriteISACfifo;
+ cs->BC_Read_Reg = &ReadHDLC_s;
+ cs->BC_Write_Reg = &WriteHDLC_s;
+ cs->BC_Send_Data = &fill_hdlc;
+ cs->cardmsg = &AVM_card_msg;
+ ISACVersion(cs, "AVM PCI:");
+ return (1);
+}
-/* $Id: callc.c,v 1.30.2.9 1998/05/27 18:04:53 keil Exp $
+/* $Id: callc.c,v 1.30.2.11 1998/09/30 22:20:05 keil Exp $
* Author Karsten Keil (keil@temic-ech.spacenet.de)
* based on the teles driver from Jan den Ouden
* Fritz Elfert
*
* $Log: callc.c,v $
+ * Revision 1.30.2.11 1998/09/30 22:20:05 keil
+ * Cosmetics
+ *
+ * Revision 1.30.2.10 1998/09/27 13:05:35 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
* Revision 1.30.2.9 1998/05/27 18:04:53 keil
* HiSax 3.0
*
#define MOD_USE_COUNT mod_use_count_
#endif /* MODULE */
-const char *lli_revision = "$Revision: 1.30.2.9 $";
+const char *lli_revision = "$Revision: 1.30.2.11 $";
extern struct IsdnCard cards[];
extern int nrcards;
static int chancount = 0;
/* experimental REJECT after ALERTING for CALLBACK to beat the 4s delay */
-#define ALERT_REJECT 1
+#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
chanp++;
i++;
}
- return;
+ return;
} else if (pr == (CC_SETUP | INDICATION)) {
if (!(chanp = selectfreechannel(pc->st))) {
pc->st->lli.l4l3(pc->st, CC_DLRL | REQUEST, pc);
pc->chan = chanp;
FsmEvent(&chanp->fi, EV_SETUP_IND, NULL);
}
- return;
- }
- chanp = pc->chan;
+ return;
+ }
+ if (!(chanp = pc->chan))
+ return;
+
switch (pr) {
case (CC_DISCONNECT | INDICATION):
FsmEvent(&chanp->fi, EV_DISCONNECT_IND, NULL);
default:
if (chanp->debug & 0x800) {
jiftime(tm, jiffies);
- sprintf(tmp, "%s Channel %d L3->L4 unknown primitiv %d\n",
+ sprintf(tmp, "%s Channel %d L3->L4 unknown primitiv %x\n",
tm, chanp->chan, pr);
HiSax_putstatus(chanp->cs, tmp);
}
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 */
- else
- st->l2.T203 = 10000; /* 5000 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
printk(KERN_INFO "HiSax: 2 channels added\n");
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);
+ 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);
}
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;
}
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;
}
char tmp[128];
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):
setstack_l3bc(st, chanp);
break;
}
- if (chanp->leased)
- st->l1.bc = chanp->chan & 1;
- else
- st->l1.bc = chanp->proc->para.bchannel - 1;
return (0);
}
case (DL_RELEASE | REQUEST):
break;
default:
- printk(KERN_WARNING "transd_l4l3 unknown primitive %d\n",
+ printk(KERN_WARNING "transd_l4l3 unknown primitive %x\n",
pr);
break;
}
break;
default:
printk(KERN_WARNING
- "transd_l1l2 unknown primitive %d\n", pr);
+ "transd_l1l2 unknown primitive %x\n", pr);
break;
}
}
struct Channel *chanp;
char tmp[128];
int i;
- unsigned int num;
+ u_int num;
+ u_long adr;
if (!csta) {
printk(KERN_ERR
}
chanp->l2_protocol = ic->arg >> 8;
break;
+ case (ISDN_CMD_SETL3):
+ chanp = csta->channel + (ic->arg & 0xff);
+ if (chanp->debug & 1) {
+ sprintf(tmp, "SETL3 card %d %ld", csta->cardnr + 1,
+ ic->arg >> 8);
+ link_debug(chanp, tmp, 1);
+ }
+ 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)",
ic->parm.setup.eazmsn, ic->parm.setup.phone,
- ic->parm.setup.si1, ic->parm.setup.si2);
+ ic->parm.setup.si1, ic->parm.setup.si2);
link_debug(chanp, tmp, 1);
}
chanp->setup = ic->parm.setup;
lli_got_manufacturer(chanp, csta, &ic->parm.cmsg);
break;
default:
- break;
+ break;
}
break;
#endif
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 {
+ } 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;
sprintf(tmp, "set card in PTP mode\n");
HiSax_putstatus(csta, tmp);
printk(KERN_DEBUG "HiSax: %s", tmp);
+ 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);
+ sprintf(tmp, "set card in PTMP mode\n");
+ HiSax_putstatus(csta, tmp);
+ printk(KERN_DEBUG "HiSax: %s", tmp);
}
break;
case (8): /* set card in FIXED TEI mode */
HiSax_putstatus(csta, tmp);
printk(KERN_DEBUG "HiSax: %s", tmp);
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):
MOD_USE_COUNT = 0;
-/* $Id: config.c,v 1.15.2.11 1998/05/27 18:05:07 keil Exp $
+/* $Id: config.c,v 1.15.2.16 1998/09/27 13:05:48 keil Exp $
* Author Karsten Keil (keil@temic-ech.spacenet.de)
* based on the teles driver from Jan den Ouden
*
*
* $Log: config.c,v $
+ * Revision 1.15.2.16 1998/09/27 13:05:48 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
+ * Revision 1.15.2.15 1998/09/12 18:43:56 niemann
+ * Added new card: Sedlbauer ISDN-Controller PC/104
+ *
+ * Revision 1.15.2.14 1998/08/25 14:01:27 calle
+ * Ported driver for AVM Fritz!Card PCI from the 2.1 tree.
+ * I could not test it.
+ *
+ * Revision 1.15.2.13 1998/07/30 20:51:24 niemann
+ * Fixed Sedlbauer Speed Card PCMCIA missing isdnl3new
+ *
+ * Revision 1.15.2.12 1998/07/15 14:43:29 calle
+ * Support for AVM passive PCMCIA cards:
+ * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0
+ *
* Revision 1.15.2.11 1998/05/27 18:05:07 keil
* HiSax 3.0
*
#include <linux/timer.h>
#include <linux/config.h>
#include "hisax.h"
-
+#include <linux/module.h>
/*
* This structure array contains one entry per card. An entry looks
* like this:
* 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 PCI (Fritz!PCI) no parameter
+ * 28 reserved
*
* protocol can be either ISDN_PTYPE_EURO or ISDN_PTYPE_1TR6 or ISDN_PTYPE_NI1
*
#ifdef CONFIG_HISAX_ELSA
#define DEFAULT_CARD ISDN_CTYPE_ELSA
#define DEFAULT_CFG {0,0,0,0}
-int elsa_init_pcmcia(void*, int, int*, int);
#ifdef MODULE
+int elsa_init_pcmcia(void*, int, int*, int);
static struct symbol_table hisax_syms_elsa = {
#include <linux/symtab_begin.h>
X(elsa_init_pcmcia),
#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}
+#ifdef MODULE
+int avm_a1_init_pcmcia(void*, int, int*, int);
+void HiSax_closecard(int cardnr);
+static struct symbol_table hisax_syms_avm_a1= {
+#include <linux/symtab_begin.h>
+ X(avm_a1_init_pcmcia),
+ X(HiSax_closecard),
+#include <linux/symtab_end.h>
+};
+void register_avm_a1_symbols(void) {
+ register_symtab(&hisax_syms_avm_a1);
+}
+#endif
+#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
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_SEDLBAUER
#define DEFAULT_CFG {11,0x270,0,0}
-int sedl_init_pcmcia(void*, int, int*, int);
#ifdef MODULE
+int sedl_init_pcmcia(void*, int, int*, int);
static struct symbol_table hisax_syms_sedl= {
#include <linux/symtab_begin.h>
X(sedl_init_pcmcia),
char tmp[64];
printk(KERN_INFO "HiSax: Linux Driver for passive ISDN cards\n");
- printk(KERN_INFO "HiSax: Version 3.0\n");
+ printk(KERN_INFO "HiSax: Version 3.0b\n");
strcpy(tmp, l1_revision);
printk(KERN_INFO "HiSax: Layer1 Revision %s\n", HiSax_getrev(tmp));
strcpy(tmp, l2_revision);
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 */
+ register_avm_a1_symbols();
+ return 0;
+ }
+#endif
#endif
nrcards = 0;
HiSaxVersion();
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:
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_NETJET:
case ISDN_CTYPE_AMD7930:
case ISDN_CTYPE_TELESPCI:
+ case ISDN_CTYPE_FRITZPCI:
break;
}
}
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");
+ 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)
+{
+ int i;
+ int nzproto = 0;
+
+ nrcards = 0;
+ HiSaxVersion();
+ if (id) /* If id= string used */
+ HiSax_id = id;
+ /* Initialize all 16 structs, even though we only accept
+ two pcmcia cards
+ */
+ for (i = 0; i < 16; 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_A1_PCMCIA;
+ nzproto = 1;
+
if (!HiSax_id)
HiSax_id = HiSaxID;
if (!HiSaxID[0])
-/* $Id: elsa.c,v 1.14.2.11 1998/05/27 18:05:14 keil Exp $
+/* $Id: elsa.c,v 1.14.2.12 1998/09/27 13:05:53 keil Exp $
* elsa.c low level stuff for Elsa isdn cards
*
*
*
* $Log: elsa.c,v $
+ * Revision 1.14.2.12 1998/09/27 13:05:53 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
* Revision 1.14.2.11 1998/05/27 18:05:14 keil
* HiSax 3.0
*
extern const char *CardType[];
-const char *Elsa_revision = "$Revision: 1.14.2.11 $";
+const char *Elsa_revision = "$Revision: 1.14.2.12 $";
const char *Elsa_Types[] =
{"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro",
"PCMCIA", "QS 1000", "QS 3000", "QS 1000 PCI", "QS 3000 PCI"};
printk(KERN_WARNING "Elsa: Spurious interrupt!\n");
return;
}
- val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */
+ val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */
if (!(val & ELSA_PCI_IRQ_MASK))
- return;
+ return;
+#if ARCOFI_USE
+ if (cs->hw.elsa.MFlag) {
+ val = serial_inp(cs, UART_IIR);
+ if (!(val & UART_IIR_NO_INT)) {
+ sprintf(tmp,"IIR %02x", val);
+ debugl1(cs, tmp);
+ 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) {
release_region(cs->hw.elsa.cfg, 0x80);
}
if (cs->subtyp == ELSA_QS3000PCI) {
- byteout(cs->hw.elsa.cfg + 0x4c, 0x03); /* enable ELSA PCI IRQ */
+ 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);
}
udelay(ARCDEL);
send_arcofi(cs, ARCOFI_XOP_F, bc, 0);
restore_flags(flags);
+ sprintf(tmp,"end set_arcofi bc=%d", bc);
+ debugl1(cs, tmp);
}
static int
{
int pwr, len, ret = 0;
u_char *msg;
- long flags;
+ long flags;
switch (mt) {
case CARD_RESET:
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);
+ reset_elsa(cs);
return(ret);
case CARD_INIT:
cs->debug |= L1_DEB_IPAC;
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);
+ cs->hw.elsa.counter);
if (abs(cs->hw.elsa.counter - 13) < 3) {
printk(KERN_INFO "Elsa: timer and irq OK\n");
ret = 0;
}
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;
-#include <linux/config.h> /* CONFIG_SERIAL_NOPAUSE_IO */
#include <linux/serial.h>
#include <linux/serial_reg.h>
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
-#define SERIAL_DEBUG_OPEN 1
-#define SERIAL_DEBUG_INTR 1
-#define SERIAL_DEBUG_FLOW 1
+//#define SERIAL_DEBUG_OPEN 1
+//#define SERIAL_DEBUG_INTR 1
+//#define SERIAL_DEBUG_FLOW 1
+#undef SERIAL_DEBUG_OPEN
+#undef SERIAL_DEBUG_INTR
+#undef SERIAL_DEBUG_FLOW
#undef SERIAL_DEBUG_REG
-//#define SERIAL_DEBUG_REG
+//#define SERIAL_DEBUG_REG 1
#ifdef SERIAL_DEBUG_REG
static u_char deb[32];
const char *ModemOut[] = {"THR","IER","FCR","LCR","MCR","LSR","MSR","SCR"};
#endif
-static char *MInit_1 = "AT &F &C1 E0 &D2 L2 M1 S64=13\n\0";
-static char *MInit_2 = "AT+FCLASS=0 V1 S2=128 X1 \\V8\n\0";
-static char *MInit_3 = "AT %G0 %B2400 L0 M0 &G0 %E1 %L1 %M0 %C3 \\N3\n\0";
+static char *MInit_1 = "AT&F&C1E0&D2\r\0";
+static char *MInit_2 = "ATL2M1S64=13\r\0";
+static char *MInit_3 = "AT+FCLASS=0\r\0";
+static char *MInit_4 = "ATV1S2=128X1\r\0";
+static char *MInit_5 = "AT\\V8\\N3\r\0";
+static char *MInit_6 = "ATL0M0&G0%E1\r\0";
+static char *MInit_7 = "AT%L1%M0%C3\r\0";
+
+static char *MInit_speed28800 = "AT%G0%B28800\r\0";
+
+static char *MInit_dialout = "ATs7=60 x1 d\r\0";
+static char *MInit_dialin = "ATs7=60 x1 a\r\0";
static inline unsigned int serial_in(struct IsdnCardState *cs, int offset)
sprintf(tmp,"modem quot=0x%x", quot);
debugl1(cs, tmp);
- save_flags(flags); cli();
+ save_flags(flags);
+ cli();
serial_outp(cs, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
serial_outp(cs, UART_DLL, quot & 0xff); /* LS of divisor */
serial_outp(cs, UART_DLM, quot >> 8); /* MS of divisor */
serial_outp(cs, UART_LCR, cval); /* reset DLAB */
+ serial_inp(cs, UART_RX);
restore_flags(flags);
}
/*
* and set the speed of the serial port
*/
- change_speed(cs, 57600*2);
+ change_speed(cs, BASE_BAUD);
cs->hw.elsa.MFlag = 1;
errout:
restore_flags(flags);
#ifdef SERIAL_DEBUG_OPEN
- printk("Shutting down serial ....");
+ printk(KERN_DEBUG"Shutting down serial ....");
#endif
save_flags(flags); cli(); /* Disable interrupts */
serial_inp(cs, UART_RX); /* read data port to reset things */
restore_flags(flags);
+#ifdef SERIAL_DEBUG_OPEN
+ printk(" done\n");
+#endif
}
inline int
int count, len, fp, buflen;
long flags;
- if (!bcs->hw.hscx.tx_skb)
+ if (!bcs->tx_skb)
return 0;
- if (bcs->hw.hscx.tx_skb->len <= 0)
+ if (bcs->tx_skb->len <= 0)
return 0;
save_flags(flags);
cli();
buflen = MAX_MODEM_BUF - cs->hw.elsa.transcnt;
- len = MIN(buflen, bcs->hw.hscx.tx_skb->len);
+ len = MIN(buflen, bcs->tx_skb->len);
fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp;
fp &= (MAX_MODEM_BUF -1);
count = MIN(len, MAX_MODEM_BUF - fp);
if (count < len) {
- memcpy(cs->hw.elsa.transbuf + fp, skb_pull(bcs->hw.hscx.tx_skb, count), count);
+ memcpy(cs->hw.elsa.transbuf + fp, bcs->tx_skb->data, count);
+ skb_pull(bcs->tx_skb, count);
cs->hw.elsa.transcnt += count;
ret = count;
count = len - count;
fp = 0;
}
- memcpy(cs->hw.elsa.transbuf + fp, skb_pull(bcs->hw.hscx.tx_skb, count), count);
+ memcpy((cs->hw.elsa.transbuf + fp), bcs->tx_skb->data, count);
+ skb_pull(bcs->tx_skb, count);
cs->hw.elsa.transcnt += count;
ret += count;
if (cs->hw.elsa.transcnt &&
!(cs->hw.elsa.IER & UART_IER_THRI)) {
- cs->hw.elsa.IER |= UART_IER_THRI;
+ cs->hw.elsa.IER |= UART_IER_THRI;
serial_outp(cs, UART_IER, cs->hw.elsa.IER);
}
restore_flags(flags);
inline void
modem_fill(struct BCState *bcs) {
- if (bcs->hw.hscx.tx_skb) {
- if (bcs->hw.hscx.tx_skb->len) {
+ if (bcs->tx_skb) {
+ if (bcs->tx_skb->len) {
write_modem(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, FREE_WRITE);
- bcs->hw.hscx.tx_skb = NULL;
+ dev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+ 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);
write_modem(bcs);
sprintf(tmp, "transmit_chars: p(%x) cnt(%x)", cs->hw.elsa.transp,
cs->hw.elsa.transcnt);
debugl1(cs, tmp);
+
if (cs->hw.elsa.transcnt <= 0) {
cs->hw.elsa.IER &= ~UART_IER_THRI;
serial_out(cs, UART_IER, cs->hw.elsa.IER);
return;
}
-
count = 16;
do {
serial_outp(cs, UART_TX, cs->hw.elsa.transbuf[cs->hw.elsa.transp++]);
#endif
}
-extern int open_hscxstate(struct IsdnCardState *cs, int bc);
+extern int open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs);
extern void modehscx(struct BCState *bcs, int mode, int bc);
extern void hscx_l2l1(struct PStack *st, int pr, void *arg);
{
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) {
if (bcs->mode != L1_MODE_MODEM)
while ((skb = skb_dequeue(&bcs->squeue))) {
dev_kfree_skb(skb, FREE_WRITE);
}
- if (bcs->hw.hscx.tx_skb) {
- dev_kfree_skb(bcs->hw.hscx.tx_skb, FREE_WRITE);
- bcs->hw.hscx.tx_skb = NULL;
+ if (bcs->tx_skb) {
+ dev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+ bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
}
}
}
-void
-modem_l2l1(struct PStack *st, int pr, void *arg)
-{
- struct sk_buff *skb = arg;
- long flags;
-
- if (pr == (PH_DATA | REQUEST)) {
- save_flags(flags);
- cli();
- if (st->l1.bcs->hw.hscx.tx_skb) {
- skb_queue_tail(&st->l1.bcs->squeue, skb);
- restore_flags(flags);
- } else {
- st->l1.bcs->hw.hscx.tx_skb = skb;
- test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
- st->l1.bcs->hw.hscx.count = 0;
- restore_flags(flags);
- write_modem(st->l1.bcs);
- }
- } else if (pr == (PH_ACTIVATE | REQUEST)) {
- test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
- st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
- set_arcofi(st->l1.bcs->cs, st->l1.bc);
- st->l1.bcs->cs->hw.elsa.MFlag=2;
- } else if (pr == (PH_DEACTIVATE | REQUEST)) {
- test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
- send_arcofi(st->l1.bcs->cs, ARCOFI_XOP_0, st->l1.bc, 0);
- st->l1.bcs->cs->hw.elsa.MFlag=1;
- } else {
- printk(KERN_WARNING"ElsaSer: unknown pr %x\n", pr);
- }
-}
-
void
modem_write_cmd(struct IsdnCardState *cs, u_char *buf, int len) {
int count, fp;
modem_set_init(struct IsdnCardState *cs) {
long flags;
int timeout;
-
+ u_char tmp[32];
+#define RCV_DELAY 20000
save_flags(flags);
sti();
modem_write_cmd(cs, MInit_1, strlen(MInit_1));
timeout = 1000;
while(timeout-- && cs->hw.elsa.transcnt)
udelay(1000);
- udelay(50000);
+ sprintf(tmp, "msi tout=%d", timeout);
+ debugl1(cs, tmp);
+ udelay(RCV_DELAY);
modem_write_cmd(cs, MInit_2, strlen(MInit_2));
timeout = 1000;
while(timeout-- && cs->hw.elsa.transcnt)
udelay(1000);
- udelay(50000);
+ sprintf(tmp, "msi tout=%d", timeout);
+ debugl1(cs, tmp);
+ udelay(RCV_DELAY);
modem_write_cmd(cs, MInit_3, strlen(MInit_3));
timeout = 1000;
while(timeout-- && cs->hw.elsa.transcnt)
udelay(1000);
- udelay(50000);
+ sprintf(tmp, "msi tout=%d", timeout);
+ debugl1(cs, tmp);
+ udelay(RCV_DELAY);
+ modem_write_cmd(cs, MInit_4, strlen(MInit_4));
+ timeout = 1000;
+ while(timeout-- && cs->hw.elsa.transcnt)
+ udelay(1000);
+ sprintf(tmp, "msi tout=%d", timeout);
+ debugl1(cs, tmp);
+ udelay(RCV_DELAY );
+ modem_write_cmd(cs, MInit_5, strlen(MInit_5));
+ timeout = 1000;
+ while(timeout-- && cs->hw.elsa.transcnt)
+ udelay(1000);
+ sprintf(tmp, "msi tout=%d", timeout);
+ debugl1(cs, tmp);
+ udelay(RCV_DELAY);
+ modem_write_cmd(cs, MInit_6, strlen(MInit_6));
+ timeout = 1000;
+ while(timeout-- && cs->hw.elsa.transcnt)
+ udelay(1000);
+ sprintf(tmp, "msi tout=%d", timeout);
+ debugl1(cs, tmp);
+ udelay(RCV_DELAY);
+ modem_write_cmd(cs, MInit_7, strlen(MInit_7));
+ timeout = 1000;
+ while(timeout-- && cs->hw.elsa.transcnt)
+ udelay(1000);
+ sprintf(tmp, "msi tout=%d", timeout);
+ debugl1(cs, tmp);
+ udelay(RCV_DELAY);
+ restore_flags(flags);
+}
+
+void
+modem_set_dial(struct IsdnCardState *cs, int outgoing) {
+ long flags;
+ int timeout;
+ u_char tmp[32];
+#define RCV_DELAY 20000
+
+ save_flags(flags);
+ sti();
+ modem_write_cmd(cs, MInit_speed28800, strlen(MInit_speed28800));
+ timeout = 1000;
+ while(timeout-- && cs->hw.elsa.transcnt)
+ udelay(1000);
+ sprintf(tmp, "msi tout=%d", timeout);
+ debugl1(cs, tmp);
+ udelay(RCV_DELAY);
+ if (outgoing)
+ modem_write_cmd(cs, MInit_dialout, strlen(MInit_dialout));
+ else
+ modem_write_cmd(cs, MInit_dialin, strlen(MInit_dialin));
+ timeout = 1000;
+ while(timeout-- && cs->hw.elsa.transcnt)
+ udelay(1000);
+ sprintf(tmp, "msi tout=%d", timeout);
+ debugl1(cs, tmp);
+ udelay(RCV_DELAY);
restore_flags(flags);
}
+void
+modem_l2l1(struct PStack *st, int pr, void *arg)
+{
+ struct sk_buff *skb = arg;
+ long flags;
+
+ if (pr == (PH_DATA | REQUEST)) {
+ save_flags(flags);
+ cli();
+ if (st->l1.bcs->tx_skb) {
+ skb_queue_tail(&st->l1.bcs->squeue, skb);
+ restore_flags(flags);
+ } else {
+ 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);
+ write_modem(st->l1.bcs);
+ }
+ } else if (pr == (PH_ACTIVATE | REQUEST)) {
+ test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+ st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
+ set_arcofi(st->l1.bcs->cs, st->l1.bc);
+ mstartup(st->l1.bcs->cs);
+ modem_set_dial(st->l1.bcs->cs, test_bit(FLG_ORIG, &st->l2.flag));
+ st->l1.bcs->cs->hw.elsa.MFlag=2;
+ } else if (pr == (PH_DEACTIVATE | REQUEST)) {
+ test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+ send_arcofi(st->l1.bcs->cs, ARCOFI_XOP_0, st->l1.bc, 0);
+ st->l1.bcs->cs->hw.elsa.MFlag=1;
+ } else {
+ printk(KERN_WARNING"ElsaSer: unknown pr %x\n", pr);
+ }
+}
+
int
setstack_elsa(struct PStack *st, struct BCState *bcs)
{
+ bcs->channel = st->l1.bc;
switch (st->l1.mode) {
case L1_MODE_HDLC:
case L1_MODE_TRANS:
- if (open_hscxstate(st->l1.hardware, bcs->channel))
+ if (open_hscxstate(st->l1.hardware, bcs))
return (-1);
st->l2.l2l1 = hscx_l2l1;
break;
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;
if (mstartup(cs)) {
printk(KERN_WARNING "Elsa: problem startup modem\n");
}
-// modem_set_init(cs);
+ modem_set_init(cs);
}
void
-/* $Id: hfc_2bds0.c,v 1.1.2.6 1998/06/27 22:54:07 keil Exp $
+/* $Id: hfc_2bds0.c,v 1.1.2.8 1998/09/30 22:23:55 keil Exp $
*
* specific routines for CCD's HFC 2BDS0
*
*
*
* $Log: hfc_2bds0.c,v $
+ * Revision 1.1.2.8 1998/09/30 22:23:55 keil
+ * Fix missing line in setstack*
+ *
+ * Revision 1.1.2.7 1998/09/27 13:06:01 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
* Revision 1.1.2.6 1998/06/27 22:54:07 keil
* make 16.3c working with 3.0
*
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);
count = GetFreeFifoBytes_B(bcs);
if (cs->debug & L1_DEB_HSCX) {
sprintf(tmp, "hfc_fill_fifo %d count(%ld/%d),%lx",
- bcs->channel, bcs->hw.hfc.tx_skb->len,
+ 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);
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, FREE_WRITE);
- 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, FREE_WRITE);
+ bcs->tx_skb = NULL;
}
WaitForBusy(cs);
cli();
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 | INDICATION):
- if (st->l1.bcs->hw.hfc.tx_skb) {
+ 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 | REQUEST):
- if (!st->l1.bcs->hw.hfc.tx_skb) {
+ if (!st->l1.bcs->tx_skb) {
test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
} else
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);
- st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
+ l1_msg_b(st, pr, arg);
break;
case (PH_DEACTIVATE | REQUEST):
- if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
- mode_2bs0(st->l1.bcs, 0, 0);
+ 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)
{
- mode_2bs0(bcs, 0, 0);
+ mode_2bs0(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
discard_queue(&bcs->rqueue);
discard_queue(&bcs->squeue);
- if (bcs->hw.hfc.tx_skb) {
- dev_kfree_skb(bcs->hw.hfc.tx_skb, FREE_WRITE);
- bcs->hw.hfc.tx_skb = NULL;
+ if (bcs->tx_skb) {
+ dev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+ 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;
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;
setstack_manager(st);
bcs->st = st;
+ setstack_l1_B(st);
return (0);
}
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);
debugl1(cs, tmp);
}
} 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);
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);
debugl1(cs, tmp);
}
} 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);
-/* $Id: hfc_2bs0.c,v 1.1.2.5 1998/05/27 18:05:27 keil Exp $
+/* $Id: hfc_2bs0.c,v 1.1.2.7 1998/09/30 22:23:59 keil Exp $
* specific routines for CCD's HFC 2BS0
*
*
*
* $Log: hfc_2bs0.c,v $
+ * Revision 1.1.2.7 1998/09/30 22:23:59 keil
+ * Fix missing line in setstack*
+ *
+ * Revision 1.1.2.6 1998/09/27 13:06:05 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
* Revision 1.1.2.5 1998/05/27 18:05:27 keil
* HiSax 3.0
*
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);
count = GetFreeFifoBytes(bcs);
if (cs->debug & L1_DEB_HSCX) {
sprintf(tmp, "hfc_fill_fifo %d count(%ld/%d)",
- bcs->channel, bcs->hw.hfc.tx_skb->len,
+ 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);
}
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, FREE_WRITE);
- bcs->hw.hfc.tx_skb = NULL;
+ dev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+ 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));
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);
}
bcs->mode = mode;
bcs->channel = bc;
+
switch (mode) {
case (L1_MODE_NULL):
if (bc)
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 | INDICATION):
- if (st->l1.bcs->hw.hfc.tx_skb) {
+ 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 | REQUEST):
- if (!st->l1.bcs->hw.hfc.tx_skb) {
+ if (!st->l1.bcs->tx_skb) {
test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
} else
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);
- st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
+ l1_msg_b(st, pr, arg);
break;
case (PH_DEACTIVATE | REQUEST):
- if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
- mode_hfc(st->l1.bcs, 0, 0);
+ 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)
{
- mode_hfc(bcs, 0, 0);
+ mode_hfc(bcs, 0, bcs->channel);
if (test_bit(BC_FLG_INIT, &bcs->Flag)) {
discard_queue(&bcs->rqueue);
discard_queue(&bcs->squeue);
- if (bcs->hw.hfc.tx_skb) {
- dev_kfree_skb(bcs->hw.hfc.tx_skb, FREE_WRITE);
- bcs->hw.hfc.tx_skb = NULL;
+ if (bcs->tx_skb) {
+ dev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+ 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;
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;
setstack_manager(st);
bcs->st = st;
+ setstack_l1_B(st);
return (0);
}
-/* $Id: hisax.h,v 1.13.2.11 1998/05/27 18:05:30 keil Exp $
+/* $Id: hisax.h,v 1.13.2.15 1998/09/30 22:28:04 keil Exp $
* Basic declarations, defines and prototypes
*
* $Log: hisax.h,v $
+ * Revision 1.13.2.15 1998/09/30 22:28:04 keil
+ * more work for isar support
+ *
+ * Revision 1.13.2.14 1998/09/27 13:06:09 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
+ * Revision 1.13.2.13 1998/08/25 14:01:30 calle
+ * Ported driver for AVM Fritz!Card PCI from the 2.1 tree.
+ * I could not test it.
+ *
+ * Revision 1.13.2.12 1998/07/15 14:43:33 calle
+ * Support for AVM passive PCMCIA cards:
+ * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0
+ *
* Revision 1.13.2.11 1998/05/27 18:05:30 keil
* HiSax 3.0
*
#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 MDL_INFO_CONN 0x02E4
#define MDL_INFO_REL 0x02E8
-
#define CC_SETUP 0x0300
#define CC_RESUME 0x0304
#define CC_MORE_INFO 0x0310
#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)
};
struct hscx_hw {
+ int hscx;
+ int rcvidx;
+ int count; /* Current skb sent count */
+ u_char *rcvbuf; /* B-Channel receive Buffer */
+};
+
+struct isar_hw {
+ int dpath;
+ int rcvidx;
+ int txcnt;
+ u_char *rcvbuf; /* B-Channel receive Buffer */
+};
+
+struct hdlc_hw {
+ u_int 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;
struct hdlc_state *hdlc_state;
struct tq_struct tq_rcv;
struct tq_struct tq_xmt;
- struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
};
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;
+ 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 amd7930_hw amd7930;
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 */
u_char LCR;
u_char MCR;
u_char ctrl_reg;
-};
+};
struct teles3_hw {
unsigned int cfg_reg;
unsigned int adr;
unsigned int isac;
unsigned int hscx;
+ unsigned int isar;
unsigned int reset_on;
unsigned int reset_off;
+ volatile u_char bstat;
+ volatile u_char iis;
+ volatile u_char cmsb;
+ volatile u_char clsb;
+ volatile u_char par[8];
};
struct spt_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
#define ISDN_CTYPE_AMD7930 23
#define ISDN_CTYPE_NICCY 24
#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
#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)
#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
| CARD_IX1MICROR2 | CARD_DIEHLDIVA | CARD_ASUSCOM \
| CARD_TELEINT | CARD_SEDLBAUER | CARD_SPORTSTER \
| CARD_MIC | CARD_NETJET | CARD_TELES3C | CARD_AMD7930 \
+ | CARD_AVM_A1_PCMCIA | CARD_FRITZPCI\
| CARD_NICCY | CARD_S0BOX | CARD_TELESPCI)
#define TEI_PER_CARD 0
#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
-/* $Id: hscx.c,v 1.3.2.7 1998/06/26 22:02:55 keil Exp $
+/* $Id: hscx.c,v 1.3.2.9 1998/09/27 13:06:14 keil Exp $
* hscx.c HSCX specific routines
*
*
*
* $Log: hscx.c,v $
+ * Revision 1.3.2.9 1998/09/27 13:06:14 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
+ * Revision 1.3.2.8 1998/09/15 15:25:04 keil
+ * Repair HSCX init
+ *
* Revision 1.3.2.7 1998/06/26 22:02:55 keil
* send flags between hdlc frames
*
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];
debugl1(cs, tmp);
}
bcs->mode = mode;
+ bcs->channel = bc;
+ cs->BC_Write_Reg(cs, hscx, HSCX_CCR1,
+ test_bit(HW_IPAC, &cs->HW_Flags) ? 0x82 : 0x85);
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);
}
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):
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);
}
break;
case (PH_PULL | INDICATION):
- if (st->l1.bcs->hw.hscx.tx_skb) {
+ 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 | REQUEST):
- if (!st->l1.bcs->hw.hscx.tx_skb) {
+ if (!st->l1.bcs->tx_skb) {
test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
} else
void
close_hscxstate(struct BCState *bcs)
{
- 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);
}
discard_queue(&bcs->rqueue);
discard_queue(&bcs->squeue);
- if (bcs->hw.hscx.tx_skb) {
- dev_kfree_skb(bcs->hw.hscx.tx_skb, FREE_WRITE);
- bcs->hw.hscx.tx_skb = NULL;
+ if (bcs->tx_skb) {
+ dev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+ bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
}
}
}
int
-open_hscxstate(struct IsdnCardState *cs,
- int bc)
+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
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;
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;
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);
}
-/* $Id: hscx_irq.c,v 1.5.2.3 1998/06/24 14:43:56 keil Exp $
+/* $Id: hscx_irq.c,v 1.5.2.4 1998/09/27 13:06:16 keil Exp $
* hscx_irq.c low level b-channel stuff for Siemens HSCX
*
* This is an include file for fast inline IRQ stuff
*
* $Log: hscx_irq.c,v $
+ * Revision 1.5.2.4 1998/09/27 13:06:16 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
* Revision 1.5.2.3 1998/06/24 14:43:56 keil
* Fix recovery of TX IRQ loss
*
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;
}
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;
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);
}
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;
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);
}
}
}
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, FREE_WRITE);
- bcs->hw.hscx.count = 0;
- bcs->hw.hscx.tx_skb = NULL;
+ dev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+ bcs->hw.hscx.count = 0;
+ 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);
/* 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);
+ WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
if (cs->debug & L1_DEB_WARN) {
sprintf(tmp, "HSCX B EXIR %x Lost TX", exval);
debugl1(cs, tmp);
/* 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);
+ WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
if (cs->debug & L1_DEB_WARN) {
sprintf(tmp, "HSCX A EXIR %x Lost TX", exval);
debugl1(cs, tmp);
-/* $Id: isac.c,v 1.7.2.7 1998/05/27 18:05:38 keil Exp $
+/* $Id: isac.c,v 1.7.2.8 1998/09/27 13:06:18 keil Exp $
* isac.c ISAC specific routines
*
*
*
* $Log: isac.c,v $
+ * Revision 1.7.2.8 1998/09/27 13:06:18 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
* Revision 1.7.2.7 1998/05/27 18:05:38 keil
* HiSax 3.0
*
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->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
if (cs->debug & L1_DEB_WARN) {
char tmp[40];
sprintf(tmp, "isac_empty_fifo overrun %d",
}
if (exval & 2) {
cs->ph_state = (exval >> 2) & 0xf;
- if (cs->debug & L1_DEB_ISAC) {
- sprintf(tmp, "ph_state change %x", cs->ph_state);
- debugl1(cs, tmp);
+ if (cs->debug & L1_DEB_ISAC) {
+ sprintf(tmp, "ph_state change %x", cs->ph_state);
+ debugl1(cs, tmp);
+ }
+ isac_sched_event(cs, D_L1STATECHANGE);
}
- isac_sched_event(cs, D_L1STATECHANGE);
- }
if (exval & 1) {
exval = cs->readisac(cs, ISAC_CIR1);
if (cs->debug & L1_DEB_ISAC) {
sprintf(tmp, "ISAC MOR1 %02x", cs->mon_rx[cs->mon_rxp -1]);
debugl1(cs, tmp);
}
- cs->mocr |= 0x40;
- cs->writeisac(cs, ISAC_MOCR, cs->mocr);
- }
+ cs->mocr |= 0x40;
+ cs->writeisac(cs, ISAC_MOCR, cs->mocr);
+ }
afterMONR1:
if (v1 & 0x04) {
cs->mocr &= 0xf0;
-/* $Id: isdnl1.c,v 1.15.2.12 1998/05/27 18:05:43 keil Exp $
+/* $Id: isdnl1.c,v 1.15.2.18 1998/09/30 22:26:35 keil Exp $
* isdnl1.c common low level stuff for Siemens Chipsetbased isdn cards
* based on the teles driver from Jan den Ouden
*
*
* $Log: isdnl1.c,v $
+ * Revision 1.15.2.18 1998/09/30 22:26:35 keil
+ * Add init of l1.Flags
+ *
+ * Revision 1.15.2.17 1998/09/27 23:54:17 keil
+ * cosmetics
+ *
+ * Revision 1.15.2.16 1998/09/27 13:06:22 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
+ * Revision 1.15.2.15 1998/09/12 18:44:00 niemann
+ * Added new card: Sedlbauer ISDN-Controller PC/104
+ *
+ * Revision 1.15.2.14 1998/08/25 14:01:35 calle
+ * Ported driver for AVM Fritz!Card PCI from the 2.1 tree.
+ * I could not test it.
+ *
+ * Revision 1.15.2.13 1998/07/15 14:43:37 calle
+ * Support for AVM passive PCMCIA cards:
+ * A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0
+ *
* Revision 1.15.2.12 1998/05/27 18:05:43 keil
* HiSax 3.0
*
*
*/
-const char *l1_revision = "$Revision: 1.15.2.12 $";
+const char *l1_revision = "$Revision: 1.15.2.18 $";
#define __NO_VERSION__
#include <linux/config.h>
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_pci(struct IsdnCard *card);
+#endif
+
#if CARD_ELSA
extern int setup_elsa(struct IsdnCard *card);
#endif
"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"
+ "AMD 7930", "NICCY", "S0Box", "AVM A1 (PCMCIA)", "AVM Fritz!PCI",
+ "Sedlbauer Speed Fax +"
};
extern struct IsdnCard cards[];
{
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 | CONFIRM, NULL);
csta->mon_tx = NULL;
}
csta->cardmsg(csta, CARD_RELEASE, NULL);
- del_timer(&csta->dbusytimer);
+ if (csta->dbusytimer.function != NULL)
+ del_timer(&csta->dbusytimer);
ll_unload(csta);
}
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->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);
+ "%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);
save_flags(flags);
cli();
if (!(cs = (struct IsdnCardState *)
- kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC))) {
+ 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;
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_pci(card);
+ break;
+#endif
#if CARD_ELSA
case ISDN_CTYPE_ELSA:
case ISDN_CTYPE_ELSA_PNP:
#if CARD_SEDLBAUER
case ISDN_CTYPE_SEDLBAUER:
case ISDN_CTYPE_SEDLBAUER_PCMCIA:
+ case ISDN_CTYPE_SEDLBAUER_FAX:
ret = setup_sedlbauer(card);
break;
#endif
restore_flags(flags);
return (0);
}
- if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN, GFP_ATOMIC))) {
+ if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for isac rcvbuf\n");
return (1);
}
init_tei(cs, cs->protocol);
CallcNewChan(cs);
- ll_run(cs);
+ /* ISAR needs firmware download first */
+ if (!test_bit(HW_ISAR, &cs->HW_Flags))
+ ll_run(cs);
restore_flags(flags);
return (1);
}
while (i!=last) {
cards[i] = cards[i+1];
i++;
- }
+ }
nrcards--;
}
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) {
l1_timer3(struct FsmInst *fi, int event, void *arg)
{
struct PStack *st = fi->userdata;
-
+
test_and_clear_bit(FLG_L1_T3RUN, &st->l1.Flags);
- if (test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags))
+ 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);
+ if (st->l1.l1m.state != ST_L1_F6) {
+ FsmChangeState(fi, ST_L1_F3);
st->l1.l1hw(st, HW_ENABLE | REQUEST, NULL);
}
}
st->l1.l1hw(st, HW_RESET | REQUEST, NULL);
}
+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},
while (st) {
switch(pr) {
case (HW_RESET | INDICATION):
- FsmEvent(&st->l1.l1m, EV_RESET_IND, arg);
- break;
+ FsmEvent(&st->l1.l1m, EV_RESET_IND, arg);
+ break;
case (HW_DEACTIVATE | CONFIRM):
- FsmEvent(&st->l1.l1m, EV_DEACT_CNF, arg);
- break;
+ FsmEvent(&st->l1.l1m, EV_DEACT_CNF, arg);
+ break;
case (HW_DEACTIVATE | INDICATION):
- FsmEvent(&st->l1.l1m, EV_DEACT_IND, arg);
- break;
+ FsmEvent(&st->l1.l1m, EV_DEACT_IND, arg);
+ break;
case (HW_POWERUP | CONFIRM):
- FsmEvent(&st->l1.l1m, EV_POWER_UP, arg);
- break;
+ FsmEvent(&st->l1.l1m, EV_POWER_UP, arg);
+ break;
case (HW_RSYNC | INDICATION):
- FsmEvent(&st->l1.l1m, EV_RSYNC_IND, arg);
- break;
+ FsmEvent(&st->l1.l1m, EV_RSYNC_IND, arg);
+ break;
case (HW_INFO2 | INDICATION):
- FsmEvent(&st->l1.l1m, EV_INFO2_IND, arg);
- break;
+ 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) {
+ FsmEvent(&st->l1.l1m, EV_INFO4_IND, arg);
+ break;
+ default:
+ if (cs->debug) {
sprintf(tmp, "l1msg %04X unhandled", pr);
- debugl1(cs, tmp);
- }
- break;
- }
+ debugl1(cs, tmp);
+ }
+ break;
+ }
st = st->next;
}
}
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);
}
-/* $Id: isdnl1.h,v 1.4.2.4 1998/05/27 18:05:49 keil Exp $
+/* $Id: isdnl1.h,v 1.4.2.6 1998/09/30 22:20:04 keil Exp $
* $Log: isdnl1.h,v $
+ * Revision 1.4.2.6 1998/09/30 22:20:04 keil
+ * Cosmetics
+ *
+ * Revision 1.4.2.5 1998/09/27 13:06:28 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
* Revision 1.4.2.4 1998/05/27 18:05:49 keil
* HiSax 3.0
*
#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_RECEIVE_FRAME 0x100
#define L1_DEB_MONITOR 0x200
#define D_RCVBUFREADY 0
#define B_RCVBUFREADY 0
#define B_XMTBUFREADY 1
-extern void debugl1(struct IsdnCardState *sp, char *msg);
+extern void debugl1(struct IsdnCardState *cs, char *msg);
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);
-/* $Id: isdnl2.c,v 1.10.2.9 1998/06/19 15:17:56 keil Exp $
+/* $Id: isdnl2.c,v 1.10.2.10 1998/09/27 13:06:30 keil Exp $
* Author Karsten Keil (keil@temic-ech.spacenet.de)
* based on the teles driver from Jan den Ouden
* Fritz Elfert
*
* $Log: isdnl2.c,v $
+ * Revision 1.10.2.10 1998/09/27 13:06:30 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
* Revision 1.10.2.9 1998/06/19 15:17:56 keil
* fix LAPB tx_cnt for none I-frames
*
#include "hisax.h"
#include "isdnl2.h"
-const char *l2_revision = "$Revision: 1.10.2.9 $";
+const char *l2_revision = "$Revision: 1.10.2.10 $";
static void l2m_debug(struct FsmInst *fi, char *s);
return ((data[0] & 0xf) == 1);
}
+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)
{
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 | INDICATION, 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
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 {
+ 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;
}
- } else if (fi->state != ST_L2_4) {
- if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
- FsmDelTimer(&st->l2.t200, 2);
- if (fi->state == ST_L2_5)
- discard_queue(&st->l2.i_queue);
- if (test_bit(FLG_LAPB, &st->l2.flag))
- st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
- if (fi->state == ST_L2_6)
- st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
- else
- st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
- FsmChangeState(fi, ST_L2_4);
}
}
PollFlag = (skb->data[1] & 0x1) == 0x1;
nr = skb->data[1] >> 1;
} else {
- st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
+ if (skb->len >2) {
+ st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
+ establishlink(fi);
+ }
FreeSkb(skb);
- establishlink(fi);
return;
}
} else {
i = l2addrsize(l2);
if (test_bit(FLG_MOD128, &l2->flag)) {
if (skb->len <= (i + 1)) {
- st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N');
FreeSkb(skb);
- establishlink(fi);
return;
} else if ((skb->len - i - 1) > l2->maxlen) {
st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'O');
{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},
}
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);
else if (IsFRMR(datap, test_bit(FLG_MOD128, &st->l2.flag)))
ret = FsmEvent(&st->l2.l2m, EV_L2_FRMR, skb);
else {
- ret = 0;
+ 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');
- FreeSkb(skb);
}
if (ret) {
FreeSkb(skb);
switch (pr) {
case (DL_DATA | REQUEST):
case (DL_UNIT_DATA | REQUEST):
- st->l2.l2l1(st, PH_DATA, arg);
+ st->l2.l2l1(st, PH_DATA | REQUEST, arg);
break;
case (DL_ESTABLISH | REQUEST):
- st->l2.l2l1(st, PH_ACTIVATE, NULL);
+ st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL);
break;
case (DL_RELEASE | REQUEST):
- st->l2.l2l1(st, PH_DEACTIVATE, NULL);
+ st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
break;
}
}
-/* $Id: isdnl3.c,v 1.10.2.4 1998/05/27 18:05:59 keil Exp $
+/* $Id: isdnl3.c,v 1.10.2.5 1998/09/27 13:06:39 keil Exp $
* Author Karsten Keil (keil@temic-ech.spacenet.de)
* based on the teles driver from Jan den Ouden
* Fritz Elfert
*
* $Log: isdnl3.c,v $
+ * Revision 1.10.2.5 1998/09/27 13:06:39 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
* Revision 1.10.2.4 1998/05/27 18:05:59 keil
* HiSax 3.0
*
#include "isdnl3.h"
#include <linux/config.h>
-const char *l3_revision = "$Revision: 1.10.2.4 $";
+const char *l3_revision = "$Revision: 1.10.2.5 $";
static
struct Fsm l3fsm =
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
-/* $Id: l3_1tr6.c,v 1.11.2.3 1998/05/27 18:06:04 keil Exp $
+/* $Id: l3_1tr6.c,v 1.11.2.4 1998/09/27 13:06:42 keil Exp $
* German 1TR6 D-channel protocol
*
*
*
* $Log: l3_1tr6.c,v $
+ * Revision 1.11.2.4 1998/09/27 13:06:42 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
* Revision 1.11.2.3 1998/05/27 18:06:04 keil
* HiSax 3.0
*
#include <linux/ctype.h>
extern char *HiSax_getrev(const char *revision);
-const char *l3_1tr6_revision = "$Revision: 1.11.2.3 $";
+const char *l3_1tr6_revision = "$Revision: 1.11.2.4 $";
#define MsgHead(ptr, cref, mty, dis) \
*ptr++ = dis; \
return;
p = skb_put(skb, 4);
MsgHead(p, pc->callref, mt, pd);
- pc->st->l3.l3l2(pc->st, DL_DATA | REQUEST, 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, FREE_READ);
+ 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, FREE_READ);
+ if (pc->st->l3.debug & L3_DEB_WARN)
+ l3_debug(pc->st, msg);
+ l3_1tr6_release_req(pc, 0, NULL);
}
static void
L3DelTimer(&pc->timer);
L3AddTimer(&pc->timer, T303, CC_T303);
newl3state(pc, 1);
- pc->st->l3.l3l2(pc->st, DL_DATA | REQUEST, skb);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
}
static void
/* 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)))
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, FREE_READ);
L3AddTimer(&pc->timer, T304, CC_T304);
pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
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, FREE_READ);
L3AddTimer(&pc->timer, T310, CC_T310);
newl3state(pc, 3);
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, FREE_READ);
pc->para.chargeinfo = 0;
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, FREE_READ);
StopAllL3Timer(pc);
newl3state(pc, 0);
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, FREE_READ);
newl3state(pc, 12);
pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
{
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, FREE_READ);
newl3state(pc, 10);
pc->para.chargeinfo = 0;
if (!(skb = l3_alloc_skb(l)))
return;
memcpy(skb_put(skb, l), tmp, l);
- pc->st->l3.l3l2(pc->st, DL_DATA | REQUEST, skb);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
L3DelTimer(&pc->timer);
L3AddTimer(&pc->timer, T313, CC_T313);
}
if (!(skb = l3_alloc_skb(l)))
return;
memcpy(skb_put(skb, l), tmp, l);
- pc->st->l3.l3l2(pc->st, DL_DATA | REQUEST, 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)
{
l3_1tr6_setup_req(pc, pr, arg);
} else {
L3DelTimer(&pc->timer);
- pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc);
- release_l3_process(pc);
+ pc->para.cause = 0;
+ l3_1tr6_disconnect_req(pc, 0, NULL);
}
}
if (!(skb = l3_alloc_skb(l)))
return;
memcpy(skb_put(skb, l), tmp, l);
- pc->st->l3.l3l2(pc->st, DL_DATA | REQUEST, skb);
+ l3_msg(pc->st, DL_DATA | REQUEST, skb);
L3AddTimer(&pc->timer, T308, CC_T308_1);
}
static struct stateentry datastln1[] =
{
+ {SBIT(0),
+ MT_N1_INVALID, l3_1tr6_invalid},
{SBIT(0),
MT_N1_SETUP, l3_1tr6_setup},
{SBIT(1),
{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}
};
}
} 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, FREE_READ);
+ return;
+ }
+ } else {
+ dev_kfree_skb(skb, FREE_READ);
+ 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, FREE_READ);
+ return;
+ } else {
if (!(proc = new_l3_process(st, cr))) {
if (st->l3.debug & L3_DEB_PROTERR) {
sprintf(tmp, "up1tr6 no roc mem");
dev_kfree_skb(skb, FREE_READ);
return;
}
- } else {
- dev_kfree_skb(skb, FREE_READ);
- return;
+ mt = MT_N1_INVALID;
}
}
for (i = 0; i < datastln1_len; i++)
-/* $Id: l3_1tr6.h,v 1.1.2.1 1997/10/17 22:14:15 keil Exp $
+/* $Id: l3_1tr6.h,v 1.1.2.2 1998/09/27 13:06:46 keil Exp $
*
* German 1TR6 D-channel protocol defines
*
* $Log: l3_1tr6.h,v $
+ * Revision 1.1.2.2 1998/09/27 13:06:46 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
* Revision 1.1.2.1 1997/10/17 22:14:15 keil
* update to last hisax version
*
#define MT_N1_REG_ACK 0x6C
#define MT_N1_REG_REJ 0x6F
#define MT_N1_STAT 0x63
+#define MT_N1_INVALID 0
/*
* W Elemente
-/* $Id: l3dss1.c,v 1.16.2.4 1998/05/27 18:06:08 keil Exp $
+/* $Id: l3dss1.c,v 1.16.2.5 1998/09/27 13:06:48 keil Exp $
* EURO/DSS1 D-channel protocol
*
* Fritz Elfert
*
* $Log: l3dss1.c,v $
+ * Revision 1.16.2.5 1998/09/27 13:06:48 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
* Revision 1.16.2.4 1998/05/27 18:06:08 keil
* HiSax 3.0
*
#include <linux/ctype.h>
extern char *HiSax_getrev(const char *revision);
-const char *dss1_revision = "$Revision: 1.16.2.4 $";
+const char *dss1_revision = "$Revision: 1.16.2.5 $";
#define EXT_BEARER_CAPS 1
*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;
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, 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) { \
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->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;
- 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;
+
+ 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->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;
+ 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:
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
/*
* 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) {
msn = pc->para.setup.eazmsn;
sub = NULL;
sp = msn;
- while (*sp) {
+ while (*sp) {
if ('.' == *sp) {
sub = sp;
*sp = 0;
- } else
+ } else
sp++;
}
if (*msn) {
}
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;
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);
- } else {
- *p++ = 0x7c; *p++ = 0x02; *p++ = 0x88; *p++ = 0x90;
- }
+#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)))
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
- * 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 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;
- }
+ 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;
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];
/* 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)
|| 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, FREE_READ);
- l3dss1_msg_without_setup(pc, pr, NULL);
+ l3dss1_msg_without_setup(pc, pr, NULL);
return;
}
-
/*
* Channel Identification
*/
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;
+ l3_debug(pc->st, "setup without bchannel");
+ pc->para.cause = 0x60;
dev_kfree_skb(skb, FREE_READ);
l3dss1_msg_without_setup(pc, pr, NULL);
return;
/* 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:
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, FREE_READ);
- l3dss1_msg_without_setup(pc, pr, NULL);
+ l3dss1_msg_without_setup(pc, pr, NULL);
return;
}
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)
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, FREE_READ);
if (bcfound) {
if ((pc->para.setup.si1 != 7) && (pc->debug & L3_DEB_WARN)) {
l3_debug(pc->st, "non-digital call: %s -> %s",
- pc->para.setup.phone, pc->para.setup.eazmsn);
+ 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;
+ test_bit(FLG_PTP, &pc->st->l2.flag)) {
+ pc->para.cause = 0x58;
l3dss1_msg_without_setup(pc, pr, NULL);
return;
}
}
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_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;
*p++ = IE_CAUSE;
*p++ = 0x2;
*p++ = 0x80;
- *p++ = 0x62 | 0x80; /* status sending */
+ *p++ = 0x62 | 0x80; /* status sending */
*p++ = 0x14; /* CallState */
*p++ = 0x1;
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
*/
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->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);
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->para.cause = 0x66; /* Timer expiry */
+ pc->para.loc = 0; /* local */
pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
newl3state(pc, 10);
}
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);
+ if (1 == *p++) {
+ callState = *p;
+ t += sprintf(t, "peer state %x", *p);
} else
- t += sprintf(t,"peer state len error");
+ 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);
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
struct sk_buff *skb;
u_char tmp[32];
u_char *p = tmp;
- u_char i,l;
+ 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 */
+ if (l && (l <= 10)) { /* Max length 10 octets */
*p++ = l;
- for (i=0;i<l;i++)
+ 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;
struct sk_buff *skb;
u_char tmp[32];
u_char *p = tmp;
- u_char i,l;
+ 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 */
+ if (l && (l <= 10)) { /* Max length 10 octets */
*p++ = l;
- for (i=0;i<l;i++)
+ 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;
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, ch=0, 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];
- l3_debug(pc->st, "Restart %x", ri);
+ ri = p[2];
+ l3_debug(pc->st, "Restart %x", ri);
} else {
l3_debug(pc->st, "Restart without restart IE");
ri = 0x86;
if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
chan = p[2] & 3;
ch = p[2];
- if (pc->st->l3.debug)
+ if (pc->st->l3.debug)
l3_debug(pc->st, "Restart for channel %d", chan);
}
dev_kfree_skb(skb, FREE_READ);
newl3state(pc, 2);
up = pc->st->l3.proc;
while (up) {
- if ((ri & 7)==7)
+ 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 | REQUEST, up);
+ up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
up = up->next;
}
p = tmp;
*p++ = 1;
*p++ = ch | 0x80;
}
- *p++ = 0x79; /* RESTART Ind */
+ *p++ = 0x79; /* RESTART Ind */
*p++ = 1;
*p++ = ri;
l = p - tmp;
newl3state(pc, 0);
l3_msg(pc->st, DL_DATA | REQUEST, skb);
}
-
/* *INDENT-OFF* */
static struct stateentry downstatelist[] =
{
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 | REQUEST, l3dss1_status_req},
- {SBIT(0),
- CC_RESTART | REQUEST, l3dss1_restart_req},
-};
-
-static int globalc_len = sizeof(globalcmd_list) / sizeof(struct stateentry);
-#endif
/* *INDENT-ON* */
+
static void
global_handler(struct PStack *st, int mt, struct sk_buff *skb)
{
int i;
struct l3_process *proc = st->l3.global;
-
+
for (i = 0; i < globalm_len; i++)
if ((mt == globalmes_list[i].primitive) &&
((1 << proc->state) & globalmes_list[i].state))
if (skb->data[0] != PROTO_DIS_EURO) {
if (st->l3.debug & L3_DEB_PROTERR) {
l3_debug(st, "dss1up%sunexpected discriminator %x message len %d",
- (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
- skb->data[0], skb->len);
+ (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
+ skb->data[0], skb->len);
}
dev_kfree_skb(skb, FREE_READ);
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, FREE_READ);
return;
} else if (!(proc = getl3proc(st, cr))) {
* 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
}
} 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++;
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, FREE_READ);
if ((proc = new_l3_process(st, cr))) {
- proc->para.cause = 0x65; /* 101 */
+ 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, FREE_READ);
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, FREE_READ);
if ((proc = new_l3_process(st, cr))) {
- proc->para.cause = 0x51; /* 81 */
+ proc->para.cause = 0x51; /* 81 */
l3dss1_msg_without_setup(proc, 0, NULL);
}
return;
* 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++)
if ((mt == datastatelist[i].primitive) &&
((1 << proc->state) & datastatelist[i].state))
struct l3_process *proc;
struct Channel *chan;
- if (((DL_ESTABLISH | REQUEST)== pr) || ((DL_RELEASE | REQUEST)== 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)) {
-/* $Id: netjet.c,v 1.1.2.7 1998/05/27 18:06:17 keil Exp $
+/* $Id: netjet.c,v 1.1.2.9 1998/09/30 22:24:02 keil Exp $
* netjet.c low level stuff for Traverse Technologie NETJet ISDN cards
*
*
*
* $Log: netjet.c,v $
+ * Revision 1.1.2.9 1998/09/30 22:24:02 keil
+ * Fix missing line in setstack*
+ *
+ * Revision 1.1.2.8 1998/09/27 13:06:56 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
* Revision 1.1.2.7 1998/05/27 18:06:17 keil
* HiSax 3.0
*
extern const char *CardType[];
-const char *NETjet_revision = "$Revision: 1.1.2.7 $";
+const char *NETjet_revision = "$Revision: 1.1.2.9 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
u_int fcs;
char tmp[64];
- if (!bcs->hw.tiger.tx_skb) {
+ 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;
}
}
if (bcs->cs->debug & L1_DEB_HSCX) {
sprintf(tmp,"tiger make_raw: in %ld out %d.%d",
- bcs->hw.tiger.tx_skb->len, s_cnt, bitcnt);
+ bcs->tx_skb->len, s_cnt, bitcnt);
debugl1(bcs->cs,tmp);
}
if (bitcnt) {
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);
}
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,
bcs->hw.tiger.sp += s_cnt;
bcs->hw.tiger.sendp = p;
if (!bcs->hw.tiger.sendcnt) {
- if (!bcs->hw.tiger.tx_skb) {
+ if (!bcs->tx_skb) {
sprintf(tmp,"tiger write_raw: NULL skb s_cnt %d", s_cnt);
debugl1(bcs->cs, tmp);
} 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, FREE_WRITE);
- 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, FREE_WRITE);
+ bcs->tx_skb = NULL;
}
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
bcs->hw.tiger.free = cnt - s_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;
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 | INDICATION):
- if (st->l1.bcs->hw.tiger.tx_skb) {
+ 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 | REQUEST):
- if (!st->l1.bcs->hw.tiger.tx_skb) {
+ if (!st->l1.bcs->tx_skb) {
test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
} else
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);
- st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
+ l1_msg_b(st, pr, arg);
break;
case (PH_DEACTIVATE | REQUEST):
- if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
- mode_tiger(st->l1.bcs, 0, 0);
+ 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)
{
- 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);
}
discard_queue(&bcs->rqueue);
discard_queue(&bcs->squeue);
- if (bcs->hw.tiger.tx_skb) {
- dev_kfree_skb(bcs->hw.tiger.tx_skb, FREE_WRITE);
- bcs->hw.tiger.tx_skb = NULL;
+ if (bcs->tx_skb) {
+ dev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+ 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);
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;
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;
setstack_manager(st);
bcs->st = st;
+ setstack_l1_B(st);
return (0);
}
-/* $Id: sedlbauer.c,v 1.1.2.5 1998/04/08 21:58:44 keil Exp $
+/* $Id: sedlbauer.c,v 1.1.2.8 1998/09/30 22:28:10 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
+ * and support for the Sedlbauer ISDN-Controller PC/104
+ * 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)
*
* Edgar Toernig
*
* $Log: sedlbauer.c,v $
+ * Revision 1.1.2.8 1998/09/30 22:28:10 keil
+ * more work for isar support
+ *
+ * Revision 1.1.2.7 1998/09/27 13:07:01 keil
+ * Apply most changes from 2.1.X (HiSax 3.1)
+ *
+ * Revision 1.1.2.6 1998/09/12 18:44:06 niemann
+ * Added new card: Sedlbauer ISDN-Controller PC/104
+ *
* Revision 1.1.2.5 1998/04/08 21:58:44 keil
* New init code
*
#define __NO_VERSION__
#include "hisax.h"
#include "isac.h"
+#include "ipac.h"
#include "hscx.h"
#include "isdnl1.h"
extern const char *CardType[];
-const char *Sedlbauer_revision = "$Revision: 1.1.2.5 $";
+const char *Sedlbauer_revision = "$Revision: 1.1.2.8 $";
const char *Sedlbauer_Types[] =
-{"None", "Speed Card", "Speed Win", "Speed Star"};
+{"None", "Speed Card", "Speed Win", "Speed Star", "Speed Fax+", "ISDN PC/104"};
#define SEDL_SPEED_CARD 1
#define SEDL_SPEED_WIN 2
#define SEDL_SPEED_STAR 3
+#define SEDL_SPEED_FAX 4
+#define SEDL_SPEED_PC104 5
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
#define SEDL_PCMCIA_HSCX 2
#define SEDL_PCMCIA_ADR 4
+#define SEDL_PC104_ADR 0
+#define SEDL_PC104_IPAC 2
+
#define SEDL_RESET 0x3 /* same as DOS driver */
static inline u_char
writefifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0, data, 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)
{
}
}
+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;
+ char tmp[64];
+
+ 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) {
+ sprintf(tmp, "IPAC ISTA %02X", ista);
+ debugl1(cs, tmp);
+ }
+ 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);
+}
+
void
release_io_sedlbauer(struct IsdnCardState *cs)
{
{
long flags;
- if (cs->typ != ISDN_CTYPE_SEDLBAUER_PCMCIA) {
- byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */
+ printk(KERN_INFO "Sedlbauer %s: resetting card\n",
+ Sedlbauer_Types[cs->subtyp]);
+ if (cs->subtyp != SEDL_SPEED_STAR) {
+ if (cs->subtyp == SEDL_SPEED_PC104)
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x20);
+ else
+ byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */
save_flags(flags);
sti();
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + 1;
schedule();
- byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */
+ if (cs->subtyp == SEDL_SPEED_PC104)
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x0);
+ else
+ byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + 1;
schedule();
+ if (cs->subtyp == SEDL_SPEED_PC104) {
+ 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);
}
}
release_io_sedlbauer(cs);
return(0);
case CARD_SETIRQ:
- return(request_irq(cs->irq, &sedlbauer_interrupt,
+ if (cs->subtyp == SEDL_SPEED_PC104) {
+ 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:
inithscxisac(cs, 3);
return(0);
__initfunc(int
setup_sedlbauer(struct IsdnCard *card))
{
- int bytecnt;
+ int bytecnt, val;
struct IsdnCardState *cs = card->cs;
char tmp[64];
/* 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->typ != ISDN_CTYPE_SEDLBAUER_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);
+
+ val = readreg(cs->hw.sedl.cfg_reg + SEDL_PC104_ADR,
+ cs->hw.sedl.cfg_reg + SEDL_PC104_IPAC, IPAC_ID);
+ if (val == 1) {
+ cs->subtyp = SEDL_SPEED_PC104;
+ cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_PC104_ADR;
+ cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_PC104_IPAC;
+ cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_PC104_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;
+ printk(KERN_INFO "Sedlbauer %s: IPAC version %x\n",
+ Sedlbauer_Types[cs->subtyp], val);
+ reset_sedlbauer(cs);
+ } else {
+ cs->readisac = &ReadISAC;
+ cs->writeisac = &WriteISAC;
+ cs->readisacfifo = &ReadISACfifo;
+ cs->writeisacfifo = &WriteISACfifo;
+ ISACVersion(cs, "Sedlbauer:");
+ if (HscxVersion(cs, "Sedlbauer:")) {
+ printk(KERN_WARNING
+ "Sedlbauer %s: wrong HSCX versions check IO address\n",
+ Sedlbauer_Types[cs->subtyp]);
+ release_io_sedlbauer(cs);
+ return (0);
+ }
+ reset_sedlbauer(cs);
}
return (1);
}
/* eepro.c: Intel EtherExpress Pro/10 device driver for Linux. */
/*
- Written 1994, 1995,1996 by Bao C. Ha.
- Last Update, 2/7/98, Phillip R. Jaenke
+ Written 1994-1998 by Bao C. Ha.
- Copyright (C) 1994, 1995,1996 by Bao C. Ha.
+ Copyright (C) 1994-1998 by Bao C. Ha.
This software may be used and distributed
according to the terms of the GNU Public License,
incorporated herein by reference.
- The author may be reached at bao.ha@srs.gov
- or 418 Hastings Place, Martinez, GA 30907.
-
- Phillip R. Jaenke may be reached at prj@nls.net
- or P.O. Box 413, Twinsburg, OH 44087, ATTN: Linux
+ The author may be reached at bao@hacom.net
+ or Hacom, 2477 Wrightsboro Rd., Augusta, GA 30904.
Things remaining to do:
Better record keeping of errors.
This is a compatibility hardware problem.
Versions:
-
- 0.10 Added several I/O addresses previously not included.
- (PRJ, 2/7/98)
+
+ 0.10c Some cosmetic changes. (9/28/98, BCH)
+
+ 0.10b Should work now with (some) Pro/10+. At least for
+ me (and my two cards) it does. _No_ guarantee for
+ function with non-Pro/10+ cards! (don't have any)
+ (RMC, 9/11/96)
+
+ 0.10 Added support for the Etherexpress Pro/10+. The
+ IRQ map was changed significantly from the old
+ pro/10. The new interrupt map was provided by
+ Rainer M. Canavan (Canavan@Zeus.cs.bonn.edu).
+ (BCH, 9/3/96)
0.09 Fixed a race condition in the transmit algorithm,
which causes crashes under heavy load with fast
*/
static const char *version =
- "eepro.c: v0.10 7/31/96 Bao C. Ha (bao.ha@srs.gov)\n";
+ "eepro.c: v0.10c 9/28/98 Bao C. Ha (bao@hacom.net)\n";
#include <linux/module.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-
/* First, a few definitions that the brave might change. */
+
/* A zero-terminated list of I/O addresses to be probed. */
static unsigned int eepro_portlist[] =
- { 0x200, 0x240, 0x260, 0x280, 0x2C0, 0x300, 0x310, 0x320, 0x340, 0x360, 0};
+ { 0x300, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0};
/* use 0 for production, 1 for verification, >2 for debug */
+
#ifndef NET_DEBUG
-#define NET_DEBUG 3
+#define NET_DEBUG 1
#endif
+
static unsigned int net_debug = NET_DEBUG;
/* The number of low I/O ports used by the ethercard. */
+
#define EEPRO_IO_EXTENT 16
/* Different 82595 chips */
+
#define LAN595 0
#define LAN595TX 1
#define LAN595FX 2
unsigned tx_start; /* start of the transmit chain */
int tx_last; /* pointer to last packet in the transmit chain */
unsigned tx_end; /* end of the transmit chain (plus 1) */
- int eepro; /* a flag, TRUE=1 for the EtherExpress Pro/10,
- FALSE = 0 for other 82595-based lan cards. */
+ int eepro; /* 1 for the EtherExpress Pro/10,
+ 2 for the EtherExpress Pro/10+,
+ 0 for other 82595-based lan cards. */
int version; /* a flag to indicate if this is a TX or FX
version of the 82595 chip. */
int stepping;
};
/* The station (ethernet) address prefix, used for IDing the board. */
-#define SA_ADDR0 0x00
+
+#define SA_ADDR0 0x00 /* Etherexpress Pro/10 */
#define SA_ADDR1 0xaa
#define SA_ADDR2 0x00
+#define SA2_ADDR0 0x00 /* Etherexpress Pro/10+ */
+#define SA2_ADDR1 0xa0
+#define SA2_ADDR2 0xc9
+
+#define SA3_ADDR0 0x00 /* more Etherexpress Pro/10+ */
+#define SA3_ADDR1 0xaa
+#define SA3_ADDR2 0x00
+#define SA3_ADDR3 0xc9
+
/* Index to functions, as function prototypes. */
extern int eepro_probe(struct device *dev);
buffer (transmit-buffer = 32K - receive-buffer).
*/
+
#define RAM_SIZE 0x8000
#define RCV_HEADER 8
#define RCV_RAM 0x6000 /* 24KB default for RCV buffer */
#define RCV_LOWER_LIMIT 0x00 /* 0x0000 */
+
/* #define RCV_UPPER_LIMIT ((RCV_RAM - 2) >> 8) */ /* 0x5ffe */
#define RCV_UPPER_LIMIT (((rcv_ram) - 2) >> 8)
+
/* #define XMT_RAM (RAM_SIZE - RCV_RAM) */ /* 8KB for XMT buffer */
#define XMT_RAM (RAM_SIZE - (rcv_ram)) /* 8KB for XMT buffer */
+
/* #define XMT_LOWER_LIMIT (RCV_RAM >> 8) */ /* 0x6000 */
#define XMT_LOWER_LIMIT ((rcv_ram) >> 8)
#define XMT_UPPER_LIMIT ((RAM_SIZE - 2) >> 8) /* 0x7ffe */
#define BANK2_SELECT 0x80
/* Bank 0 registers */
+
#define COMMAND_REG 0x00 /* Register 0 */
#define MC_SETUP 0x03
#define XMT_CMD 0x04
#define IO_PORT_32_BIT 0x0c
/* Bank 1 registers */
+
#define REG1 0x01
#define WORD_WIDTH 0x02
#define INT_ENABLE 0x80
#define XMT_UPPER_LIMIT_REG 0x0b
/* Bank 2 registers */
+
#define XMT_Chain_Int 0x20 /* Interrupt at the end of the transmit chain */
#define XMT_Chain_ErrStop 0x40 /* Interrupt at the end of the chain even if there are errors */
#define RCV_Discard_BadFrame 0x80 /* Throw bad frames away, and continue to receive others */
#define REG13 0x0d
#define FDX 0x00
#define A_N_ENABLE 0x02
-
+
#define I_ADD_REG0 0x04
#define I_ADD_REG1 0x05
#define I_ADD_REG2 0x06
#define EEDI 0x04
#define EEDO 0x08
+/* Check for a network adaptor of this type, and return '0' if one exists.
-/* Check for a network adaptor of this type, and return '0' iff one exists.
If dev->base_addr == 0, probe all likely locations.
If dev->base_addr == 1, always return failure.
If dev->base_addr == 2, allocate space for the device and return success
(detachable devices only).
+
*/
+
#ifdef HAVE_DEVLIST
+
/* Support for a alternate probe manager, which will eliminate the
boilerplate below. */
+
struct netdev_entry netcard_drv =
{"eepro", eepro_probe1, EEPRO_IO_EXTENT, eepro_portlist};
+
#else
-int
+
+int
eepro_probe(struct device *dev)
{
int i;
int ioaddr = eepro_portlist[i];
if (check_region(ioaddr, EEPRO_IO_EXTENT))
continue;
+
if (eepro_probe1(dev, ioaddr) == 0)
return 0;
}
probes on the ISA bus. A good device probes avoids doing writes, and
verifies that the correct device exists and functions. */
-int eepro_probe1(struct device *dev, short ioaddr)
+int
+eepro_probe1(struct device *dev, short ioaddr)
{
unsigned short station_addr[6], id, counter;
int i;
- int eepro; /* a flag, TRUE=1 for the EtherExpress Pro/10,
- FALSE = 0 for other 82595-based lan cards. */
+ int eepro;
const char *ifmap[] = {"AUI", "10Base2", "10BaseT"};
enum iftype { AUI=0, BNC=1, TPE=2 };
/* Now, we are going to check for the signature of the
ID_REG (register 2 of bank 0) */
-
if (((id=inb(ioaddr + ID_REG)) & ID_REG_MASK) == ID_REG_SIG) {
/* We seem to have the 82595 signature, let's
play with its counter (last 2 bits of
register 2 of bank 0) to be sure. */
-
+
counter = (id & R_ROBIN_BITS);
if (((id=inb(ioaddr+ID_REG)) & R_ROBIN_BITS) ==
(counter + 0x40)) {
/* Check the station address for the manufacturer's code */
- if (station_addr[2] != 0x00aa || (station_addr[1] & 0xff00) != 0x0000) {
- eepro = 0;
- printk("%s: Intel 82595-based lan card at %#x,",
+ if ((station_addr[2] == 0x00aa) && (station_addr[1]!= 0x00c9)) {
+ eepro = 1;
+ printk("%s: Intel EtherExpress Pro/10 ISA at %#x,",
+ dev->name, ioaddr);
+ } else
+ if ( (station_addr[2] == 0x00a0)
+ || ((station_addr[2] == 0x00aa) && (station_addr[1] == 0x00c9) )) {
+ eepro = 2;
+ printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,",
dev->name, ioaddr);
}
else {
- eepro = 1;
- printk("%s: Intel EtherExpress Pro/10 at %#x,",
+ eepro = 0;
+ printk("%s: Intel 82595-based lan card at %#x,",
dev->name, ioaddr);
}
/* Fill in the 'dev' fields. */
dev->base_addr = ioaddr;
-
+
for (i=0; i < 6; i++) {
dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i];
printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
}
-
+
if ((dev->mem_end & 0x3f) < 3 || /* RX buffer must be more than 3K */
(dev->mem_end & 0x3f) > 29) /* and less than 29K */
dev->mem_end = RCV_RAM; /* or it will be set to 24K */
else dev->mem_end = 1024*dev->mem_end; /* Maybe I should shift << 10 */
/* From now on, dev->mem_end contains the actual size of rx buffer */
-
+
if (net_debug > 3)
printk(", %dK RCV buffer", (int)(dev->mem_end)/1024);
-
+
outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
id = inb(ioaddr + REG3);
if (id & TPE_BIT)
dev->if_port = TPE;
else dev->if_port = BNC;
+ if (net_debug>3)
+ printk("id: %x\n", id);
+
if (dev->irq < 2 && eepro) {
i = read_eeprom(ioaddr, 1);
- switch (i & 0x07) {
+ if (eepro == 1)
+ switch (i & 0x07) {
case 0: dev->irq = 9; break;
case 1: dev->irq = 3; break;
case 2: dev->irq = 5; break;
printk(" illegal interrupt vector stored in EEPROM.\n");
return ENODEV;
}
+ else switch (i & 0x07) {
+ case 0: dev->irq = 3; break;
+ case 1: dev->irq = 4; break;
+ case 2: dev->irq = 5; break;
+ case 3: dev->irq = 7; break;
+ case 4: dev->irq = 9; break;
+ case 5: dev->irq = 10; break;
+ case 6: dev->irq = 11; break;
+ case 7: dev->irq = 12; break;
+ }
}
else if (dev->irq == 2)
dev->irq = 9;
}
}
else printk(", %s.\n", ifmap[dev->if_port]);
-
+
if ((dev->mem_start & 0xf) > 0) /* I don't know if this is */
net_debug = dev->mem_start & 7; /* still useful or not */
*/
static char irqrmap[] = {-1,-1,0,1,-1,2,-1,-1,-1,0,3,4,-1,-1,-1,-1};
-static int eepro_grab_irq(struct device *dev)
+static char irqrmap2[] = {-1,-1,4,0,1,2,-1,3,-1,4,5,6,7,-1,-1,-1};
+
+static int
+eepro_grab_irq(struct device *dev)
{
- int irqlist[] = { 5, 9, 10, 11, 4, 3, 0};
+ int irqlist[] = { 3, 4, 5, 7, 9, 10, 11, 12 };
int *irqp = irqlist, temp_reg, ioaddr = dev->base_addr;
outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */
/* Enable the interrupt line. */
temp_reg = inb(ioaddr + REG1);
outb(temp_reg | INT_ENABLE, ioaddr + REG1);
-
+
outb(BANK0_SELECT, ioaddr); /* be CAREFUL, BANK 0 now */
/* clear all interrupts */
outb(ALL_MASK, ioaddr + STATUS_REG);
+
/* Let EXEC event to interrupt */
outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG);
do {
outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */
-
temp_reg = inb(ioaddr + INT_NO_REG);
outb((temp_reg & 0xf8) | irqrmap[*irqp], ioaddr + INT_NO_REG);
-
outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */
-
if (request_irq (*irqp, NULL, 0, "bogus", NULL) != EBUSY) {
/* Twinkle the interrupt, and check if it's seen */
autoirq_setup(0);
-
outb(DIAGNOSE_CMD, ioaddr); /* RESET the 82595 */
if (*irqp == autoirq_report(2) && /* It's a good IRQ line */
(request_irq(dev->irq = *irqp, &eepro_interrupt, 0, "eepro", NULL) == 0))
break;
-
/* clear all interrupts */
outb(ALL_MASK, ioaddr + STATUS_REG);
}
/* Disable the physical interrupt line. */
temp_reg = inb(ioaddr + REG1);
outb(temp_reg & 0x7f, ioaddr + REG1);
-
outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */
/* Mask all the interrupts. */
if (net_debug > 3)
printk("eepro: entering eepro_open routine.\n");
- if (dev->dev_addr[0] == SA_ADDR0 &&
+ if ((dev->dev_addr[0] == SA_ADDR0 &&
dev->dev_addr[1] == SA_ADDR1 &&
- dev->dev_addr[2] == SA_ADDR2)
- lp->eepro = 1; /* Yes, an Intel EtherExpress Pro/10 */
+ dev->dev_addr[2] == SA_ADDR2)&&
+ (dev->dev_addr[3] != SA3_ADDR3))
+ {
+ lp->eepro = 1;
+ if (net_debug > 3) printk("p->eepro = 1;\n");
+ } /* Yes, an Intel EtherExpress Pro/10 */
+
+ else if ((dev->dev_addr[0] == SA2_ADDR0 &&
+ dev->dev_addr[1] == SA2_ADDR1 &&
+ dev->dev_addr[2] == SA2_ADDR2)||
+ (dev->dev_addr[0] == SA3_ADDR0 &&
+ dev->dev_addr[1] == SA3_ADDR1 &&
+ dev->dev_addr[2] == SA3_ADDR2 &&
+ dev->dev_addr[3] == SA3_ADDR3))
+ {
+ lp->eepro = 2; /* Yes, an Intel EtherExpress Pro/10+ */
+ if (net_debug > 3) printk("p->eepro = 2;\n");
+ }
+
else lp->eepro = 0; /* No, it is a generic 82585 lan card */
/* Get the interrupt vector for the 82595 */
return -EAGAIN;
/* Initialize the 82595. */
-
outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
temp_reg = inb(ioaddr + EEPROM_REG);
-
lp->stepping = temp_reg >> 5; /* Get the stepping number of the 595 */
if (net_debug > 3)
printk("The stepping of the 82595 is %d\n", lp->stepping);
-
if (temp_reg & 0x10) /* Check the TurnOff Enable bit */
outb(temp_reg & 0xef, ioaddr + EEPROM_REG);
for (i=0; i < 6; i++)
temp_reg = inb(ioaddr + REG1); /* Setup Transmit Chaining */
outb(temp_reg | XMT_Chain_Int | XMT_Chain_ErrStop /* and discard bad RCV frames */
| RCV_Discard_BadFrame, ioaddr + REG1);
-
temp_reg = inb(ioaddr + REG2); /* Match broadcast */
outb(temp_reg | 0x14, ioaddr + REG2);
-
temp_reg = inb(ioaddr + REG3);
outb(temp_reg & 0x3f, ioaddr + REG3); /* clear test mode */
/* Set the receiving mode */
outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */
+
+ /* Set the interrupt vector */
+ temp_reg = inb(ioaddr + INT_NO_REG);
+ if (lp->eepro == 2)
+ outb((temp_reg & 0xf8) | irqrmap2[dev->irq], ioaddr + INT_NO_REG);
+ else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
+
temp_reg = inb(ioaddr + INT_NO_REG);
- outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
-
+
+ if (lp->eepro == 2)
+ outb((temp_reg & 0xf0) | irqrmap2[dev->irq] | 0x08,ioaddr+INT_NO_REG);
+ else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
+
+ if (net_debug > 3)
+ printk("eepro_open: content of INT Reg is %x\n", temp_reg);
+
+
/* Initialize the RCV and XMT upper and lower limits */
outb(RCV_LOWER_LIMIT, ioaddr + RCV_LOWER_LIMIT_REG);
outb(RCV_UPPER_LIMIT, ioaddr + RCV_UPPER_LIMIT_REG);
/* Enable the interrupt line. */
temp_reg = inb(ioaddr + REG1);
outb(temp_reg | INT_ENABLE, ioaddr + REG1);
-
outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */
-
+
/* Let RX and TX events to interrupt */
outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
+
/* clear all interrupts */
outb(ALL_MASK, ioaddr + STATUS_REG);
-
+
/* Initialize RCV */
outw(RCV_LOWER_LIMIT << 8, ioaddr + RCV_BAR);
lp->rx_start = (RCV_LOWER_LIMIT << 8) ;
outw((RCV_UPPER_LIMIT << 8) | 0xfe, ioaddr + RCV_STOP);
-
+
/* Initialize XMT */
outw(XMT_LOWER_LIMIT << 8, ioaddr + XMT_BAR);
-
+
/* Check for the i82595TX and i82595FX */
old8 = inb(ioaddr + 8);
outb(~old8, ioaddr + 8);
+
if ((temp_reg = inb(ioaddr + 8)) == old8) {
if (net_debug > 3)
printk("i82595 detected!\n");
outb(old8, ioaddr + 8);
old9 = inb(ioaddr + 9);
outb(~old9, ioaddr + 9);
- if ((temp_reg = inb(ioaddr + 9)) == ~old9) {
+
+ if (((temp_reg = inb(ioaddr + 9)) == ( (~old9)&0xff) )) {
enum iftype { AUI=0, BNC=1, TPE=2 };
- if (net_debug > 3)
+
+ if (net_debug > 3) {
+ printk("temp_reg: %#x ~old9: %#x\n",temp_reg, ~old9);
printk("i82595FX detected!\n");
+ }
+
lp->version = LAN595FX;
outb(old9, ioaddr + 9);
+
if (dev->if_port != TPE) { /* Hopefully, this will fix the
problem of using Pentiums and
pro/10 w/ BNC. */
outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
temp_reg = inb(ioaddr + REG13);
+
/* disable the full duplex mode since it is not
applicable with the 10Base2 cable. */
outb(temp_reg & ~(FDX | A_N_ENABLE), REG13);
outb(BANK0_SELECT, ioaddr); /* be CAREFUL, BANK 0 now */
}
}
- else if (net_debug > 3)
+ else if (net_debug > 3) {
+ printk("temp_reg: %#x ~old9: %#x\n",temp_reg,((~old9)&0xff));
printk("i82595TX detected!\n");
+ }
}
outb(SEL_RESET_CMD, ioaddr);
+
/* We are supposed to wait for 2 us after a SEL_RESET */
SLOW_DOWN_IO;
SLOW_DOWN_IO;
-
+
lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT << 8; /* or = RCV_RAM */
lp->tx_last = 0;
dev->tbusy = 0;
dev->interrupt = 0;
dev->start = 1;
-
+
if (net_debug > 3)
printk("eepro: exiting eepro_open routine.\n");
-
+
outb(RCV_ENABLE_CMD, ioaddr);
-
MOD_INC_USE_COUNT;
+
return 0;
}
if (dev->tbusy) {
/* If we get here, some higher level has decided we are broken.
There should really be a "kick me" function call instead. */
+
int tickssofar = jiffies - dev->trans_start;
+
if (tickssofar < 40)
return 1;
+
if (net_debug > 1)
printk("%s: transmit timed out, %s?\n", dev->name,
"network cable problem");
+
lp->stats.tx_errors++;
-
+
/* Try to restart the adaptor. */
outb(SEL_RESET_CMD, ioaddr);
+
/* We are supposed to wait for 2 us after a SEL_RESET */
SLOW_DOWN_IO;
SLOW_DOWN_IO;
-
+
/* Do I also need to flush the transmit buffers here? YES? */
lp->tx_start = lp->tx_end = rcv_ram;
lp->tx_last = 0;
dev->tbusy=0;
dev->trans_start = jiffies;
-
outb(RCV_ENABLE_CMD, ioaddr);
-
}
-
+
/* If some higher layer thinks we've missed an tx-done interrupt
we are passed NULL. Caution: dev_tint() handles the cli()/sti()
itself. */
+
if (skb == NULL) {
dev_tint(dev);
return 0;
}
-
+
/* Block a timer-based transmit from overlapping. */
+
if (set_bit(0, (void*)&dev->tbusy) != 0)
printk("%s: Transmitter access conflict.\n", dev->name);
else {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
unsigned char *buf = skb->data;
-
hardware_send_packet(dev, buf, length);
dev->trans_start = jiffies;
}
-
+
dev_kfree_skb (skb, FREE_WRITE);
-
+
/* You might need to clean up and record Tx statistics here. */
/* lp->stats.tx_aborted_errors++; */
-
+
if (net_debug > 5)
printk("eepro: exiting eepro_send_packet routine.\n");
return 0;
}
-
/* The typical workload of the driver:
Handle the network interface interrupts. */
+
static void
eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
printk ("eepro_interrupt(): irq %d for unknown device.\n", irq);
return;
}
+
dev->interrupt = 1;
ioaddr = dev->base_addr;
-
+
do {
status = inb(ioaddr + STATUS_REG);
if (status & RX_INT) {
if (net_debug > 4)
printk("eepro: packet received interrupt.\n");
-
/* Acknowledge the RX_INT */
outb(RX_INT, ioaddr + STATUS_REG);
-
/* Get the received packets */
eepro_rx(dev);
}
-
else if (status & TX_INT) {
if (net_debug > 4)
printk("eepro: packet transmit interrupt.\n");
-
/* Acknowledge the TX_INT */
outb(TX_INT, ioaddr + STATUS_REG);
-
/* Process the status of transmitted packets */
eepro_transmit_interrupt(dev);
}
} while ((boguscount-- > 0) && (status & 0x06));
-
+
dev->interrupt = 0;
+
if (net_debug > 5)
printk("eepro: exiting eepro_interrupt routine.\n");
dev->tbusy = 1;
dev->start = 0;
-
+
outb(BANK1_SELECT, ioaddr); /* Switch back to Bank 1 */
-
+
/* Disable the physical interrupt line. */
temp_reg = inb(ioaddr + REG1);
outb(temp_reg & 0x7f, ioaddr + REG1);
-
outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */
-
+
/* Flush the Tx and disable Rx. */
outb(STOP_RCV_CMD, ioaddr);
+
lp->tx_start = lp->tx_end = rcv_ram ;
lp->tx_last = 0;
-
+
/* Mask all the interrupts. */
outb(ALL_MASK, ioaddr + INT_MASK_REG);
-
+
/* clear all interrupts */
outb(ALL_MASK, ioaddr + STATUS_REG);
-
+
/* Reset the 82595 */
outb(RESET_CMD, ioaddr);
-
+
/* release the interrupt */
free_irq(dev->irq, NULL);
-
irq2dev_map[dev->irq] = 0;
-
+
/* Update the statistics here. What statistics? */
-
/* We are supposed to wait for 200 us after a RESET */
SLOW_DOWN_IO;
SLOW_DOWN_IO; /* May not be enough? */
-
MOD_DEC_USE_COUNT;
+
return 0;
}
eepro_get_stats(struct device *dev)
{
struct eepro_local *lp = (struct eepro_local *)dev->priv;
-
return &lp->stats;
}
/* Set or clear the multicast filter for this adaptor.
*/
+
static void
set_multicast_list(struct device *dev)
{
short ioaddr = dev->base_addr;
unsigned short mode;
struct dev_mc_list *dmi=dev->mc_list;
-
+
if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || dev->mc_count > 63)
{
/*
* flag is already set. If not we assert it.
*/
dev->flags|=IFF_PROMISC;
-
outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
mode = inb(ioaddr + REG2);
outb(mode | PRMSC_Mode, ioaddr + REG2);
outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */
printk("%s: promiscuous mode enabled.\n", dev->name);
}
+
else if (dev->mc_count==0 )
{
outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */
}
+
else
{
unsigned short status, *eaddrs;
corruption of the HOST_ADDRESS_REG by interrupt
service routines. */
outb(ALL_MASK, ioaddr + INT_MASK_REG);
-
outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
mode = inb(ioaddr + REG2);
outb(mode | Multi_IA, ioaddr + REG2);
outw(0, ioaddr + IO_PORT);
outw(0, ioaddr + IO_PORT);
outw(6*(dev->mc_count + 1), ioaddr + IO_PORT);
+
for (i = 0; i < dev->mc_count; i++)
{
eaddrs=(unsigned short *)dmi->dmi_addr;
outw(*eaddrs++, ioaddr + IO_PORT);
outw(*eaddrs++, ioaddr + IO_PORT);
}
+
eaddrs = (unsigned short *) dev->dev_addr;
outw(eaddrs[0], ioaddr + IO_PORT);
outw(eaddrs[1], ioaddr + IO_PORT);
outw(eaddrs[2], ioaddr + IO_PORT);
outw(lp->tx_end, ioaddr + XMT_BAR);
outb(MC_SETUP, ioaddr);
-
+
/* Update the transmit queue */
i = lp->tx_end + XMT_HEADER + 6*(dev->mc_count + 1);
+
if (lp->tx_start != lp->tx_end)
{
/* update the next address and the chain bit in the
else {
lp->tx_start = lp->tx_end = i ;
}
-
+
/* Acknowledge that the MC setup is done */
do { /* We should be doing this in the eepro_interrupt()! */
SLOW_DOWN_IO;
SLOW_DOWN_IO;
+
if (inb(ioaddr + STATUS_REG) & 0x08)
{
i = inb(ioaddr);
outb(0x08, ioaddr + STATUS_REG);
+
if (i & 0x20) { /* command ABORTed */
printk("%s: multicast setup failed.\n",
dev->name);
}
}
} while (++boguscount < 100);
-
+
/* Re-enable RX and TX interrupts */
outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
/* The horrible routine to read a word from the serial EEPROM. */
/* IMPORTANT - the 82595 will be set to Bank 0 after the eeprom is read */
-
/* The delay between EEPROM clock transitions. */
+
#define eeprom_delay() { int _i = 40; while (--_i > 0) { __SLOW_DOWN_IO; }}
#define EE_READ_CMD (6 << 6)
retval = (retval << 1) | ((inb(ee_addr) & EEDO) ? 1 : 0);
outb(ctrl_val, ee_addr); eeprom_delay();
}
-
/* Terminate the EEPROM access. */
ctrl_val &= ~EECS;
outb(ctrl_val | EESK, ee_addr);
if (net_debug > 5)
printk("eepro: entering hardware_send_packet routine.\n");
-
+
while (boguscount-- > 0) {
-
+
/* Disable RX and TX interrupts. Necessary to avoid
corruption of the HOST_ADDRESS_REG by interrupt
service routines. */
outb(ALL_MASK, ioaddr + INT_MASK_REG);
-
+
if (dev->interrupt == 1) {
/* Enable RX and TX interrupts */
outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
continue;
}
-
+
/* determine how much of the transmit buffer space is available */
if (lp->tx_end > lp->tx_start)
tx_available = XMT_RAM - (lp->tx_end - lp->tx_start);
else if (lp->tx_end < lp->tx_start)
tx_available = lp->tx_start - lp->tx_end;
else tx_available = XMT_RAM;
-
+
if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER)
>= tx_available) /* No space available ??? */
{
eepro_transmit_interrupt(dev); /* Clean up the transmiting queue */
-
/* Enable RX and TX interrupts */
outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
continue;
}
-
+
last = lp->tx_end;
end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
-
if (end >= RAM_SIZE) { /* the transmit buffer is wrapped around */
+
if ((RAM_SIZE - last) <= XMT_HEADER) {
/* Arrrr!!!, must keep the xmt header together,
several days were lost to chase this one down. */
last = rcv_ram;
end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
}
+
else end = rcv_ram + (end - RAM_SIZE);
}
outw(0, ioaddr + IO_PORT);
outw(end, ioaddr + IO_PORT);
outw(length, ioaddr + IO_PORT);
-
+
if (lp->version == LAN595)
outsw(ioaddr + IO_PORT, buf, (length + 3) >> 1);
+
else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */
unsigned short temp = inb(ioaddr + INT_MASK_REG);
outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG);
outsl(ioaddr + IO_PORT_32_BIT, buf, (length + 3) >> 2);
outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
}
-
+
/* A dummy read to flush the DRAM write pipeline */
status = inw(ioaddr + IO_PORT);
-
+
if (lp->tx_start == lp->tx_end) {
outw(last, ioaddr + XMT_BAR);
outb(XMT_CMD, ioaddr);
else {
/* update the next address and the chain bit in the
last packet */
+
if (lp->tx_end != last) {
outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
outw(last, ioaddr + IO_PORT);
}
+
outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);
status = inw(ioaddr + IO_PORT);
outw(status | CHAIN_BIT, ioaddr + IO_PORT);
-
+
/* Continue the transmit command */
outb(RESUME_XMT_CMD, ioaddr);
}
-
lp->tx_last = last;
lp->tx_end = end;
-
+
/* Enable RX and TX interrupts */
outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
if (dev->tbusy) {
dev->tbusy = 0;
}
-
+
if (net_debug > 5)
printk("eepro: exiting hardware_send_packet routine.\n");
+
return;
}
-
dev->tbusy = 1;
+
if (net_debug > 5)
printk("eepro: exiting hardware_send_packet routine.\n");
}
/* Set the read pointer to the start of the RCV */
outw(rcv_car, ioaddr + HOST_ADDRESS_REG);
+
rcv_event = inw(ioaddr + IO_PORT);
-
while (rcv_event == RCV_DONE) {
+
rcv_status = inw(ioaddr + IO_PORT);
rcv_next_frame = inw(ioaddr + IO_PORT);
rcv_size = inw(ioaddr + IO_PORT);
-
+
if ((rcv_status & (RX_OK | RX_ERROR)) == RX_OK) {
+
/* Malloc up new buffer. */
struct sk_buff *skb;
-
rcv_size &= 0x3fff;
skb = dev_alloc_skb(rcv_size+5);
+
if (skb == NULL) {
printk("%s: Memory squeeze, dropping packet.\n", dev->name);
lp->stats.rx_dropped++;
break;
}
+
skb->dev = dev;
skb_reserve(skb,2);
-
+
if (lp->version == LAN595)
insw(ioaddr+IO_PORT, skb_put(skb,rcv_size), (rcv_size + 3) >> 1);
+
else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */
unsigned short temp = inb(ioaddr + INT_MASK_REG);
outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG);
insl(ioaddr+IO_PORT_32_BIT, skb_put(skb,rcv_size), (rcv_size + 3) >> 2);
outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
}
-
skb->protocol = eth_type_trans(skb,dev);
netif_rx(skb);
lp->stats.rx_packets++;
}
+
else { /* Not sure will ever reach here,
I set the 595 to discard bad received frames */
lp->stats.rx_errors++;
+
if (rcv_status & 0x0100)
lp->stats.rx_over_errors++;
+
else if (rcv_status & 0x0400)
lp->stats.rx_frame_errors++;
+
else if (rcv_status & 0x0800)
lp->stats.rx_crc_errors++;
+
printk("%s: event = %#x, status = %#x, next = %#x, size = %#x\n",
dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size);
}
+
if (rcv_status & 0x1000)
lp->stats.rx_length_errors++;
+
if (--boguscount == 0)
break;
-
+
rcv_car = lp->rx_start + RCV_HEADER + rcv_size;
lp->rx_start = rcv_next_frame;
outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG);
rcv_event = inw(ioaddr + IO_PORT);
-
}
if (rcv_car == 0)
rcv_car = (RCV_UPPER_LIMIT << 8) | 0xff;
+
outw(rcv_car - 1, ioaddr + RCV_STOP);
-
+
if (net_debug > 5)
printk("eepro: exiting eepro_rx routine.\n");
}
short xmt_status;
while (lp->tx_start != lp->tx_end) {
-
+
outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG);
xmt_status = inw(ioaddr+IO_PORT);
+
if ((xmt_status & TX_DONE_BIT) == 0) break;
-
+
xmt_status = inw(ioaddr+IO_PORT);
lp->tx_start = inw(ioaddr+IO_PORT);
-
dev->tbusy = 0;
mark_bh(NET_BH);
-
+
if (xmt_status & 0x2000)
lp->stats.tx_packets++;
else {
printk("%s: XMT status = %#x\n",
dev->name, xmt_status);
}
+
if (xmt_status & 0x000f) {
lp->stats.collisions += (xmt_status & 0x000f);
}
+
if ((xmt_status & 0x0040) == 0x0) {
lp->stats.tx_heartbeat_errors++;
}
-
+
if (--boguscount == 0)
break;
}
}
#ifdef MODULE
+
static char devicename[9] = { 0, };
static struct device dev_eepro = {
devicename, /* device name is inserted by linux/drivers/net/net_init.c */
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, eepro_probe };
-
static int io = 0x200;
static int irq = 0;
static int mem = (RCV_RAM/1024); /* Size of the rx buffer in KB */
-int
+int
init_module(void)
{
if (io == 0)
printk("eepro: You should not use auto-probing with insmod!\n");
+
dev_eepro.base_addr = io;
dev_eepro.irq = irq;
dev_eepro.mem_end = mem;
if (register_netdev(&dev_eepro) != 0)
return -EIO;
+
return 0;
}
cleanup_module(void)
{
unregister_netdev(&dev_eepro);
+
kfree_s(dev_eepro.priv,sizeof(struct eepro_local));
dev_eepro.priv=NULL;
inode->i_nlink);
return;
}
- if (!inode->i_sb) {
+ sb = inode->i_sb;
+ if (!sb) {
printk("ext2_free_inode: inode on nonexistent device\n");
return;
}
ext2_debug ("freeing inode %lu\n", inode->i_ino);
- sb = inode->i_sb;
+ /* We need to kill quota references now, before grabbing the
+ * superblock lock because writing the quota out to disk
+ * may need to lock the superblock as well.
+ *
+ * It is safe to do this early instead of the original
+ * places because we cannot be here in ext2_free_inode
+ * if any other references to this inode exist at all.
+ *
+ * Based upon a 2.1.x fix by Bill Hawes. --DaveM
+ */
+ if (sb->dq_op) {
+ sb->dq_op->free_inode (inode, 1);
+ if (IS_WRITABLE (inode))
+ sb->dq_op->drop(inode);
+ }
+
lock_super (sb);
if (inode->i_ino < EXT2_FIRST_INO(sb) ||
inode->i_ino > sb->u.ext2_sb.s_es->s_inodes_count) {
ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh);
}
- if (sb->dq_op)
- sb->dq_op->free_inode (inode, 1);
sb->s_dirt = 1;
clear_inode (inode);
unlock_super (sb);
"jnc 3f\n\t" \
"cmpb "SYMBOL_NAME_STR(active_kernel_processor)", %al\n\t" \
"je 4f\n\t" \
+ "cmpb "SYMBOL_NAME_STR(boot_cpu_id)", %al\n\t" \
+ "jne 2f\n\t" \
"movb $1, "SYMBOL_NAME_STR(smp_blocked_interrupt_pending)"\n\t" \
"2: " \
SMP_PROF_INT_SPINS \
"movb %al, "SYMBOL_NAME_STR(active_kernel_processor)"\n\t" \
"4: " \
"incl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \
+ "cmpb "SYMBOL_NAME_STR(boot_cpu_id)", %al\n\t" \
+ "jne 7f\n\t" \
"movb $0, "SYMBOL_NAME_STR(smp_blocked_interrupt_pending)"\n\t" \
+ "7: " \
"popfl\n\t" \
"popl %edx\n\t" \
"popl %ecx\n\t" \
#define IPOPT_TS_TSONLY 0 /* timestamps only */
#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
-#define IPOPT_TS_PRESPEC 2 /* specified modules only */
+#define IPOPT_TS_PRESPEC 3 /* specified modules only */
struct options {
__u32 faddr; /* Saved first hop address */
* Swap reorganised 29.12.95, Stephen Tweedie
*/
+#include <linux/config.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/head.h>
skb->pkt_bridged = IS_BRIDGED;
skb->arp = 1; /* do not resolve... */
skb->h.raw = skb->data + ETH_HLEN;
- dev_queue_xmit(dev,skb);
+ dev_queue_xmit(skb, dev, SOPRI_INTERACTIVE);
return(0);
}
skb->arp = 1; /* do not resolve... */
skb->h.raw = skb->data + ETH_HLEN;
- dev_queue_xmit(dev,skb);
+ dev_queue_xmit(skb, dev, SOPRI_INTERACTIVE);
return(0);
}
ip_statistics.IpInReceives++;
- /*
- * Account for the packet (even if the packet is
- * not accepted by the firewall!).
- */
-
-#ifdef CONFIG_IP_ACCT
- ip_fw_chk(iph,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_IN);
-#endif
/*
* Tag the ip header of this packet so we can find it
*/
skb_trim(skb,ntohs(iph->tot_len));
+
+ if(skb->len < (iph->ihl<<2))
+ {
+ ip_statistics.IpInHdrErrors++;
+ kfree_skb(skb, FREE_WRITE);
+ return 0;
+ }
+
+ /*
+ * Account for the packet (even if the packet is
+ * not accepted by the firewall!). We do this after
+ * the sanity checks and the additional ihl check
+ * so we dont account garbage as we might do before.
+ */
+
+#ifdef CONFIG_IP_ACCT
+ ip_fw_chk(iph,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_IN);
+#endif
/*
* Try to select closest <src,dst> alias device, if any.
/*
* Find a connected NET/ROM socket given their circuit IDs.
*/
-static struct sock *nr_find_peer(unsigned char index, unsigned char id)
+static struct sock *nr_find_peer(unsigned char index, unsigned char id, ax25_address *dest)
{
struct sock *s;
unsigned long flags;
cli();
for (s = nr_list; s != NULL; s = s->next) {
- if (s->protinfo.nr->your_index == index && s->protinfo.nr->your_id == id) {
+ if (s->protinfo.nr->your_index == index && s->protinfo.nr->your_id == id && ax25cmp(&s->protinfo.nr->dest_addr, dest) == 0) {
restore_flags(flags);
return s;
}
if (circuit_index == 0 && circuit_id == 0) {
if (frametype == NR_CONNACK && flags == NR_CHOKE_FLAG)
- sk = nr_find_peer(peer_circuit_index, peer_circuit_id);
+ sk = nr_find_peer(peer_circuit_index, peer_circuit_id, src);
} else {
if (frametype == NR_CONNREQ)
- sk = nr_find_peer(circuit_index, circuit_id);
+ sk = nr_find_peer(circuit_index, circuit_id, src);
else
sk = nr_find_socket(circuit_index, circuit_id);
}
*
* History
* NET/ROM 006 Tomi(OH2BNS) Created this file.
+ * Changed the way the loopback
+ * queue is consumed.
*
*/
{
struct sk_buff *skbn;
- skbn = skb_copy(skb, GFP_ATOMIC);
+ skbn = skb_clone(skb, GFP_ATOMIC);
kfree_skb(skb, FREE_WRITE);
- if (skbn != NULL)
+ if (skbn != NULL) {
skb_queue_tail(&loopback_queue, skbn);
- if (!nr_loopback_running())
- nr_set_loopback_timer();
+ if (!nr_loopback_running())
+ nr_set_loopback_timer();
+ }
return 1;
}
ax25_address *nr_dest;
struct device *dev;
- while ((skb = skb_dequeue(&loopback_queue)) != NULL) {
+ if ((skb = skb_dequeue(&loopback_queue)) != NULL) {
nr_dest = (ax25_address *)(skb->data + 7);
- if ((dev = nr_dev_get(nr_dest)) == NULL) {
- kfree_skb(skb, FREE_READ);
- continue;
- }
+ dev = nr_dev_get(nr_dest);
- if (nr_rx_frame(skb, dev) == 0)
+ if (dev == NULL || nr_rx_frame(skb, dev) == 0)
kfree_skb(skb, FREE_READ);
+
+ if (!skb_queue_empty(&loopback_queue) && !nr_loopback_running())
+ nr_set_loopback_timer();
}
}
#include CURSES_LOC
+/*
+ * Colors in ncurses 1.9.9e do not work properly since foreground and
+ * background colors are OR'd rather than separately masked. This version
+ * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible
+ * with standard curses. The simplest fix (to make this work with standard
+ * curses) uses the wbkgdset() function, not used in the original hack.
+ * Turn it off if we're building with 1.9.9e, since it just confuses things.
+ */
+#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE)
+#define OLD_NCURSES 1
+#undef wbkgdset
+#define wbkgdset(w,p) /*nothing*/
+#else
+#define OLD_NCURSES 0
+#endif
+
+#define TR(params) _tracef params
+
#define ESC 27
#define TAB 9
#define MAX_LEN 2048
(void) setlocale (LC_ALL, "");
#endif
+#ifdef TRACE
+ trace(TRACE_CALLS|TRACE_UPDATE);
+#endif
if (argc < 2) {
Usage (argv[0]);
exit (-1);
/* Clear 'residue' of last item */
wattrset (win, menubox_attr);
wmove (win, choice, 0);
+#if OLD_NCURSES
for (i = 0; i < menu_width; i++)
waddch (win, ' ');
+#else
+ wclrtoeol(win);
+#endif
wattrset (win, selected ? item_selected_attr : item_attr);
mvwaddstr (win, choice, item_x, menu_item);
if (hotkey) {
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
+ wbkgdset (dialog, dialog_attr & A_COLOR);
waddch (dialog, ACS_RTEE);
if (title != NULL) {
/* Create window for text region, used for scrolling text */
text = subwin (dialog, height - 4, width - 2, y + 1, x + 1);
+ wattrset (text, dialog_attr);
+ wbkgdset (text, dialog_attr & A_COLOR);
keypad (text, TRUE);
for (i = 0; i < width - 2; i++)
waddch (dialog, ACS_HLINE);
wattrset (dialog, dialog_attr);
+ wbkgdset (dialog, dialog_attr & A_COLOR);
waddch (dialog, ACS_RTEE);
if (title != NULL) {
getyx (win, y, x);
/* Clear 'residue' of previous line */
+#if OLD_NCURSES
for (i = 0; i < width - x; i++)
waddch (win, ' ');
+#else
+ wclrtoeol(win);
+#endif
}
/*
exit (-1);
}
wattrset (win, position_indicator_attr);
+ wbkgdset (win, position_indicator_attr & A_COLOR);
percent = !file_size ?
100 : ((fpos - bytes_read + page - buf) * 100) / file_size;
wmove (win, height - 3, width - 9);