From 91c8c33b13261a19488dc04f71fcd838f5b692a5 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 23 Nov 2007 15:12:01 -0500 Subject: [PATCH] Linux 2.0.36pre13 This won't be the last. I'm told the final 5.1 revision super save the universe adaptec driver will be out in a few days. I'm going to do a pre14 when that occurs. No point having 2.0.36 appear the day before the new adaptec driver passes its final testing. Anyway.. the changes 2.0.36pre13 changes o lxdialog handles differences between Ncurses versions nicely [Thomas Dickey] o Bridging might actually compile and work right now [me] o A quota hanging bug has been killed [c/o DaveM] o New EEPro10 driver update [Bao] o SMP deadlock possibility fixed [Leonard] o SYSV define and shm swap off now work right [me] o ISDN update [Karsten Keil] o make xconfig bug fixes [Andrew Veliath] o Incorrect definition of one of the IP options fixed [ANK] o paride update [Grant Guenther] o Ensoniq known in PCI vendor data [Bill Nottingham] o Alpha returns -ENOSYS not -EPERM for invalid syscalls o TCP/IP accounting now doesnt account packets with invalid headers --- Documentation/Configure.help | 147 +++-- Documentation/isdn/README.HiSax | 37 +- drivers/isdn/Config.in | 7 +- drivers/isdn/hisax/Makefile | 22 +- drivers/isdn/hisax/arcofi.c | 25 +- drivers/isdn/hisax/avm_a1.c | 7 +- drivers/isdn/hisax/avm_a1p.c | 330 +++++++++++ drivers/isdn/hisax/avm_pci.c | 752 +++++++++++++++++++++++++ drivers/isdn/hisax/callc.c | 87 ++- drivers/isdn/hisax/config.c | 116 +++- drivers/isdn/hisax/elsa.c | 33 +- drivers/isdn/hisax/elsa_ser.c | 223 +++++--- drivers/isdn/hisax/hfc_2bds0.c | 81 +-- drivers/isdn/hisax/hfc_2bs0.c | 74 +-- drivers/isdn/hisax/hisax.h | 86 ++- drivers/isdn/hisax/hscx.c | 49 +- drivers/isdn/hisax/hscx_irq.c | 59 +- drivers/isdn/hisax/isac.c | 23 +- drivers/isdn/hisax/isdnl1.c | 137 +++-- drivers/isdn/hisax/isdnl1.h | 12 +- drivers/isdn/hisax/isdnl2.c | 98 +++- drivers/isdn/hisax/isdnl3.c | 10 +- drivers/isdn/hisax/l3_1tr6.c | 221 +++++--- drivers/isdn/hisax/l3_1tr6.h | 6 +- drivers/isdn/hisax/l3dss1.c | 966 ++++++++++++++++++-------------- drivers/isdn/hisax/netjet.c | 76 +-- drivers/isdn/hisax/sedlbauer.c | 197 +++++-- drivers/net/eepro.c | 386 ++++++++----- fs/ext2/ialloc.c | 22 +- include/asm-i386/irq.h | 5 + include/linux/ip.h | 2 +- mm/swapfile.c | 1 + net/bridge/br.c | 4 +- net/ipv4/ip_input.c | 26 +- net/netrom/af_netrom.c | 8 +- net/netrom/nr_loopback.c | 23 +- scripts/lxdialog/dialog.h | 18 + scripts/lxdialog/lxdialog.c | 3 + scripts/lxdialog/menubox.c | 5 + scripts/lxdialog/textbox.c | 8 + 40 files changed, 3232 insertions(+), 1160 deletions(-) create mode 100644 drivers/isdn/hisax/avm_a1p.c create mode 100644 drivers/isdn/hisax/avm_pci.c diff --git a/Documentation/Configure.help b/Documentation/Configure.help index 49c6d23091d7..0481e8009153 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -4488,11 +4488,33 @@ CONFIG_ISDN_DRV_HISAX 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, @@ -4507,64 +4529,95 @@ CONFIG_HISAX_16_3 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 diff --git a/Documentation/isdn/README.HiSax b/Documentation/isdn/README.HiSax index 593994f1767a..53f8de99472e 100644 --- a/Documentation/isdn/README.HiSax +++ b/Documentation/isdn/README.HiSax @@ -31,6 +31,8 @@ Creatix S0Box 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 @@ -45,6 +47,7 @@ Dynalink IS64PH (OEM version of ASUSCOM NETWORK INC. ISDNLink 128K adapter) 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 @@ -72,7 +75,7 @@ It can be configured using the command line feature while loading the kernel 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 @@ -154,12 +157,12 @@ Card types: 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 @@ -243,8 +246,10 @@ Card types: 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 ------------------ @@ -283,7 +288,7 @@ At the moment, debugging messages are enabled with the hisaxctrl tool: hisaxctrl DebugCmd - default is HiSax, if you didn't specified one. + default is HiSax, if you didn't specify one. DebugCmd is 1 for generic debugging 11 for layer 1 development debugging @@ -320,18 +325,18 @@ With DebugCmd set to 11: 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 2 - in ms Value between 50 an 800 ms are recommended. + in ms Value between 50 and 800 ms is recommended. Warning @@ -377,7 +382,9 @@ Special thanks to: 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. @@ -402,7 +409,7 @@ Original from Juergen Quade, new version KKe. 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. @@ -420,7 +427,7 @@ to i.e. the internet: vi /etc/lilo.conf lilo - Your lilo.conf _might_ look as the following: + Your lilo.conf _might_ look like the following: # LILO configuration-file # global section @@ -462,7 +469,7 @@ to i.e. the internet: /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 @@ -478,7 +485,8 @@ to i.e. the internet: /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 @@ -530,6 +538,7 @@ case "$1" in /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 diff --git a/drivers/isdn/Config.in b/drivers/isdn/Config.in index 64e2a6974e31..0e8ca1edc85d 100644 --- a/drivers/isdn/Config.in +++ b/drivers/isdn/Config.in @@ -22,7 +22,8 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then bool 'HiSax Support for EURO/DSS1' CONFIG_HISAX_EURO if [ "$CONFIG_HISAX_EURO" != "n" ]; then bool 'Support for german 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 @@ -31,12 +32,14 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then 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 diff --git a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile index 65e1341ee187..179b4e6a0093 100644 --- a/drivers/isdn/hisax/Makefile +++ b/drivers/isdn/hisax/Makefile @@ -1,5 +1,12 @@ 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 @@ -53,6 +60,18 @@ ifeq ($(CONFIG_HISAX_AVM_A1),y) 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 @@ -118,7 +137,8 @@ ifeq ($(CONFIG_HISAX_NICCY),y) 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 := diff --git a/drivers/isdn/hisax/arcofi.c b/drivers/isdn/hisax/arcofi.c index 29c43ddcb892..e38fefab47f4 100644 --- a/drivers/isdn/hisax/arcofi.c +++ b/drivers/isdn/hisax/arcofi.c @@ -1,12 +1,18 @@ -/* $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 * @@ -27,9 +33,8 @@ 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]; @@ -55,11 +60,6 @@ send_arcofi(struct IsdnCardState *cs, const u_char *msg, int bc, int receive) { 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)) { @@ -68,8 +68,9 @@ send_arcofi(struct IsdnCardState *cs, const u_char *msg, int bc, int receive) { } } restore_flags(flags); - sprintf(tmp, "arcofi tout %d", cnt); - debugl1(cs, tmp); + if (cnt <= 0) { + printk(KERN_WARNING"HiSax arcofi monitor timed out\n"); + debugl1(cs, "HiSax arcofi monitor timed out"); + } return(cnt); } - diff --git a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c index 42434c789308..d911ab254b58 100644 --- a/drivers/isdn/hisax/avm_a1.c +++ b/drivers/isdn/hisax/avm_a1.c @@ -1,4 +1,4 @@ -/* $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 * @@ -6,6 +6,9 @@ * * * $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 * @@ -60,7 +63,7 @@ #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 diff --git a/drivers/isdn/hisax/avm_a1p.c b/drivers/isdn/hisax/avm_a1p.c new file mode 100644 index 000000000000..24ad589fb437 --- /dev/null +++ b/drivers/isdn/hisax/avm_a1p.c @@ -0,0 +1,330 @@ +/* $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); +} diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c new file mode 100644 index 000000000000..64fbcb906916 --- /dev/null +++ b/drivers/isdn/hisax/avm_pci.c @@ -0,0 +1,752 @@ +/* $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 +#include "hisax.h" +#include "isac.h" +#include "isdnl1.h" +#include +#include +#include + +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 (cnthw.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 (cnthw.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); +} diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c index 3cb5f9ce7c4f..e35d271e1c6d 100644 --- a/drivers/isdn/hisax/callc.c +++ b/drivers/isdn/hisax/callc.c @@ -1,4 +1,4 @@ -/* $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 @@ -7,6 +7,12 @@ * 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 * @@ -71,7 +77,7 @@ extern long mod_use_count_; #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; @@ -87,7 +93,7 @@ static struct Fsm callcfsm = 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 @@ -1260,7 +1266,7 @@ dchan_l3l4(struct PStack *st, int pr, void *arg) 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); @@ -1269,9 +1275,11 @@ dchan_l3l4(struct PStack *st, int pr, void *arg) 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); @@ -1318,7 +1326,7 @@ dchan_l3l4(struct PStack *st, int pr, void *arg) 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); } @@ -1344,10 +1352,7 @@ init_d_st(struct Channel *chanp) st->l2.window = 1; st->l2.T200 = 1000; /* 1000 milliseconds */ st->l2.N200 = 3; /* try 3 times */ - if (st->protocol == ISDN_PTYPE_1TR6) - st->l2.T203 = 10000; /* 10000 milliseconds */ - 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 @@ -1433,9 +1438,9 @@ CallcNewChan(struct IsdnCardState *csta) 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); } @@ -1501,7 +1506,7 @@ lldata_handler(struct PStack *st, int pr, void *arg) 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; } @@ -1531,7 +1536,7 @@ lltrans_handler(struct PStack *st, int pr, void *arg) 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; } @@ -1558,7 +1563,10 @@ init_b_st(struct Channel *chanp, int incoming) 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): @@ -1607,10 +1615,6 @@ init_b_st(struct Channel *chanp, int incoming) 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); } @@ -1631,7 +1635,7 @@ leased_l4l3(struct PStack *st, int pr, void *arg) 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; } @@ -1666,7 +1670,7 @@ leased_l1l2(struct PStack *st, int pr, void *arg) break; default: printk(KERN_WARNING - "transd_l1l2 unknown primitive %d\n", pr); + "transd_l1l2 unknown primitive %x\n", pr); break; } } @@ -1761,7 +1765,8 @@ HiSax_command(isdn_ctrl * ic) struct Channel *chanp; char tmp[128]; int i; - unsigned int num; + u_int num; + u_long adr; if (!csta) { printk(KERN_ERR @@ -1784,12 +1789,21 @@ HiSax_command(isdn_ctrl * ic) } 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; @@ -1839,7 +1853,7 @@ HiSax_command(isdn_ctrl * ic) lli_got_manufacturer(chanp, csta, &ic->parm.cmsg); break; default: - break; + break; } break; #endif @@ -1924,15 +1938,27 @@ HiSax_command(isdn_ctrl * ic) 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 */ @@ -1945,6 +1971,11 @@ HiSax_command(isdn_ctrl * ic) 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; diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index f23309cc404e..e44acf78d968 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -1,10 +1,27 @@ -/* $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 * @@ -56,7 +73,7 @@ #include #include #include "hisax.h" - +#include /* * This structure array contains one entry per card. An entry looks * like this: @@ -89,7 +106,9 @@ * 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 * @@ -99,8 +118,8 @@ #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 X(elsa_init_pcmcia), @@ -117,6 +136,32 @@ void register_elsa_symbols(void) { #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 + X(avm_a1_init_pcmcia), + X(HiSax_closecard), +#include +}; +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 @@ -176,8 +221,8 @@ void register_elsa_symbols(void) { #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 X(sedl_init_pcmcia), @@ -352,7 +397,7 @@ HiSaxVersion(void)) 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); @@ -445,6 +490,13 @@ HiSax_init(void)) return 0; } #endif +#ifdef CONFIG_HISAX_AVM_A1_PCMCIA + if (type[0] == ISDN_CTYPE_A1_PCMCIA) { + /* we have to export and return in this case */ + register_avm_a1_symbols(); + return 0; + } +#endif #endif nrcards = 0; HiSaxVersion(); @@ -489,6 +541,7 @@ HiSax_init(void)) case ISDN_CTYPE_16_3: case ISDN_CTYPE_TELESPCMCIA: case ISDN_CTYPE_A1: + case ISDN_CTYPE_A1_PCMCIA: case ISDN_CTYPE_ELSA_PNP: case ISDN_CTYPE_ELSA_PCMCIA: case ISDN_CTYPE_IX1MICROR2: @@ -497,6 +550,7 @@ HiSax_init(void)) case ISDN_CTYPE_TELEINT: case ISDN_CTYPE_SEDLBAUER: case ISDN_CTYPE_SEDLBAUER_PCMCIA: + case ISDN_CTYPE_SEDLBAUER_FAX: case ISDN_CTYPE_SPORTSTER: case ISDN_CTYPE_MIC: case ISDN_CTYPE_TELES3C: @@ -508,6 +562,7 @@ HiSax_init(void)) case ISDN_CTYPE_NETJET: case ISDN_CTYPE_AMD7930: case ISDN_CTYPE_TELESPCI: + case ISDN_CTYPE_FRITZPCI: break; } } @@ -647,6 +702,55 @@ int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) cards[0].typ = ISDN_CTYPE_SEDLBAUER_PCMCIA; nzproto = 1; + if (!HiSax_id) + HiSax_id = HiSaxID; + if (!HiSaxID[0]) + strcpy(HiSaxID, "HiSax"); + for (i = 0; i < HISAX_MAX_CARDS; i++) + if (cards[i].typ > 0) + nrcards++; + printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", + nrcards, (nrcards > 1) ? "s" : ""); + + CallcNew(); + Isdnl3New(); + Isdnl2New(); + Isdnl1New(); + TeiNew(); + HiSax_inithardware(busy_flag); + printk(KERN_NOTICE "HiSax: module installed\n"); + 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]) diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c index 92972565c5fd..f133dfbfef6e 100644 --- a/drivers/isdn/hisax/elsa.c +++ b/drivers/isdn/hisax/elsa.c @@ -1,4 +1,4 @@ -/* $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 * @@ -11,6 +11,9 @@ * * * $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 * @@ -69,7 +72,7 @@ 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"}; @@ -422,9 +425,19 @@ elsa_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) 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) { @@ -478,7 +491,7 @@ release_io_elsa(struct IsdnCardState *cs) 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); } @@ -576,6 +589,8 @@ set_arcofi(struct IsdnCardState *cs, int bc) { 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 @@ -720,7 +735,7 @@ Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg) { int pwr, len, ret = 0; u_char *msg; - long flags; + long flags; switch (mt) { case CARD_RESET: @@ -733,10 +748,11 @@ Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg) 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; @@ -772,7 +788,7 @@ Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg) 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; @@ -1150,7 +1166,6 @@ setup_elsa(struct IsdnCard *card) } printk(KERN_INFO "Elsa: timer OK; resetting card\n"); } - reset_elsa(cs); cs->BC_Read_Reg = &ReadHSCX; cs->BC_Write_Reg = &WriteHSCX; cs->BC_Send_Data = &hscx_fill_fifo; diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c index 49b1dc1b3701..611214cf8080 100644 --- a/drivers/isdn/hisax/elsa_ser.c +++ b/drivers/isdn/hisax/elsa_ser.c @@ -1,4 +1,3 @@ -#include /* CONFIG_SERIAL_NOPAUSE_IO */ #include #include @@ -11,11 +10,14 @@ #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]; @@ -23,9 +25,18 @@ const char *ModemIn[] = {"RBR","IER","IIR","LCR","MCR","LSR","MSR","SCR"}; 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) @@ -123,11 +134,13 @@ static void change_speed(struct IsdnCardState *cs, int baud) 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); } @@ -191,7 +204,7 @@ static int mstartup(struct IsdnCardState *cs) /* * 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); @@ -208,7 +221,7 @@ static void mshutdown(struct IsdnCardState *cs) #ifdef SERIAL_DEBUG_OPEN - printk("Shutting down serial ...."); + printk(KERN_DEBUG"Shutting down serial ...."); #endif save_flags(flags); cli(); /* Disable interrupts */ @@ -233,6 +246,9 @@ static void mshutdown(struct IsdnCardState *cs) serial_inp(cs, UART_RX); /* read data port to reset things */ restore_flags(flags); +#ifdef SERIAL_DEBUG_OPEN + printk(" done\n"); +#endif } inline int @@ -242,31 +258,33 @@ write_modem(struct BCState *bcs) { 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); @@ -276,20 +294,20 @@ write_modem(struct BCState *bcs) { 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); @@ -350,12 +368,12 @@ static inline void transmit_chars(struct IsdnCardState *cs, int *intr_done) 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++]); @@ -486,7 +504,7 @@ static void rs_interrupt_elsa(int irq, struct IsdnCardState *cs) #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); @@ -495,7 +513,7 @@ close_elsastate(struct BCState *bcs) { struct sk_buff *skb; -// modehscx(bcs, 0, 0); + modehscx(bcs, 0, bcs->channel); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { if (bcs->hw.hscx.rcvbuf) { if (bcs->mode != L1_MODE_MODEM) @@ -508,47 +526,14 @@ close_elsastate(struct BCState *bcs) 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; @@ -587,35 +572,135 @@ void 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; @@ -626,7 +711,7 @@ setstack_elsa(struct PStack *st, struct BCState *bcs) 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; @@ -666,7 +751,7 @@ init_modem(struct IsdnCardState *cs) { if (mstartup(cs)) { printk(KERN_WARNING "Elsa: problem startup modem\n"); } -// modem_set_init(cs); + modem_set_init(cs); } void diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c index 10f0e27f9156..d1c3dc593638 100644 --- a/drivers/isdn/hisax/hfc_2bds0.c +++ b/drivers/isdn/hisax/hfc_2bds0.c @@ -1,4 +1,4 @@ -/* $Id: hfc_2bds0.c,v 1.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 * @@ -6,6 +6,12 @@ * * * $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 * @@ -330,9 +336,9 @@ hfc_fill_fifo(struct BCState *bcs) 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); @@ -365,11 +371,11 @@ hfc_fill_fifo(struct BCState *bcs) 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); @@ -380,26 +386,26 @@ hfc_fill_fifo(struct BCState *bcs) cli(); WaitForBusy(cs); WaitNoBusy(cs); - WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->hw.hfc.tx_skb->data[idx++]); - while (idx < bcs->hw.hfc.tx_skb->len) { + WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx++]); + while (idx < bcs->tx_skb->len) { cli(); if (!WaitNoBusy(cs)) break; - WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->hw.hfc.tx_skb->data[idx]); + WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx]); sti(); idx++; } - if (idx != bcs->hw.hfc.tx_skb->len) { + if (idx != bcs->tx_skb->len) { sti(); debugl1(cs, "FIFO Send BUSY error"); printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel); } else { - bcs->tx_cnt -= bcs->hw.hfc.tx_skb->len; + bcs->tx_cnt -= bcs->tx_skb->len; if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->hw.hfc.tx_skb->pkt_type)) - bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hfc.tx_skb->len); - dev_kfree_skb(bcs->hw.hfc.tx_skb, 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(); @@ -558,30 +564,30 @@ hfc_l2l1(struct PStack *st, int pr, void *arg) 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 @@ -590,12 +596,16 @@ hfc_l2l1(struct PStack *st, int pr, void *arg) 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; } } @@ -603,29 +613,26 @@ hfc_l2l1(struct PStack *st, int pr, void *arg) 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; @@ -635,12 +642,14 @@ open_hfcstate(struct IsdnCardState *cs, 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); } @@ -970,7 +979,7 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val) if (cs->debug) debugl1(cs, "hfcd spurious 0x01 IRQ"); } else { - if (bcs->hw.hfc.tx_skb) { + if (bcs->tx_skb) { if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { hfc_fill_fifo(bcs); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); @@ -979,7 +988,7 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val) 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); @@ -998,7 +1007,7 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val) if (cs->debug) debugl1(cs, "hfcd spurious 0x02 IRQ"); } else { - if (bcs->hw.hfc.tx_skb) { + if (bcs->tx_skb) { if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { hfc_fill_fifo(bcs); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); @@ -1007,7 +1016,7 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val) 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); diff --git a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c index 08209e4a0d9d..0c1c33cd7b31 100644 --- a/drivers/isdn/hisax/hfc_2bs0.c +++ b/drivers/isdn/hisax/hfc_2bs0.c @@ -1,4 +1,4 @@ -/* $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 * @@ -6,6 +6,12 @@ * * * $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 * @@ -270,9 +276,9 @@ hfc_fill_fifo(struct BCState *bcs) 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); @@ -306,11 +312,11 @@ hfc_fill_fifo(struct BCState *bcs) 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); @@ -318,18 +324,18 @@ hfc_fill_fifo(struct BCState *bcs) } cip = HFC_CIP | HFC_FIFO_IN | HFC_SEND | HFC_CHANNEL(bcs->channel); idx = 0; - while ((idx < bcs->hw.hfc.tx_skb->len) && WaitNoBusy(cs)) - cs->BC_Write_Reg(cs, HFC_DATA_NODEB, cip, bcs->hw.hfc.tx_skb->data[idx++]); - if (idx != bcs->hw.hfc.tx_skb->len) { + while ((idx < bcs->tx_skb->len) && WaitNoBusy(cs)) + cs->BC_Write_Reg(cs, HFC_DATA_NODEB, cip, bcs->tx_skb->data[idx++]); + if (idx != bcs->tx_skb->len) { debugl1(cs, "FIFO Send BUSY error"); printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel); } else { - count = bcs->hw.hfc.tx_skb->len; + count = bcs->tx_skb->len; bcs->tx_cnt -= count; - if (PACKET_NOACK == bcs->hw.hfc.tx_skb->pkt_type) + if (PACKET_NOACK == bcs->tx_skb->pkt_type) count = -1; - dev_kfree_skb(bcs->hw.hfc.tx_skb, 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)); @@ -395,14 +401,14 @@ main_irq_hfc(struct BCState *bcs) restore_flags(flags); udelay(1); cli(); - if (bcs->hw.hfc.tx_skb) { + if (bcs->tx_skb) { transmit = 1; test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); hfc_fill_fifo(bcs); if (test_bit(BC_FLG_BUSY, &bcs->Flag)) transmit = 0; } else { - if ((bcs->hw.hfc.tx_skb = skb_dequeue(&bcs->squeue))) { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { transmit = 1; test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); hfc_fill_fifo(bcs); @@ -432,6 +438,7 @@ mode_hfc(struct BCState *bcs, int mode, int bc) } bcs->mode = mode; bcs->channel = bc; + switch (mode) { case (L1_MODE_NULL): if (bc) @@ -478,30 +485,30 @@ hfc_l2l1(struct PStack *st, int pr, void *arg) 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 @@ -510,12 +517,16 @@ hfc_l2l1(struct PStack *st, int pr, void *arg) 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; } } @@ -524,13 +535,13 @@ hfc_l2l1(struct PStack *st, int pr, void *arg) 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); } } @@ -538,16 +549,13 @@ close_hfcstate(struct BCState *bcs) } static int -open_hfcstate(struct IsdnCardState *cs, - int bc) +open_hfcstate(struct IsdnCardState *cs, struct BCState *bcs) { - struct BCState *bcs = cs->bcs + bc; - if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { skb_queue_head_init(&bcs->rqueue); skb_queue_head_init(&bcs->squeue); } - bcs->hw.hfc.tx_skb = NULL; + bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); bcs->event = 0; bcs->tx_cnt = 0; @@ -557,12 +565,14 @@ open_hfcstate(struct IsdnCardState *cs, 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); } diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h index 92ad7a62eefb..9aa790ffff01 100644 --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h @@ -1,8 +1,22 @@ -/* $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 * @@ -104,6 +118,7 @@ #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 @@ -127,7 +142,6 @@ #define MDL_INFO_CONN 0x02E4 #define MDL_INFO_REL 0x02E8 - #define CC_SETUP 0x0300 #define CC_RESUME 0x0304 #define CC_MORE_INFO 0x0310 @@ -163,6 +177,7 @@ #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) @@ -346,21 +361,34 @@ struct l3_process { }; struct hscx_hw { + int hscx; + int rcvidx; + int count; /* Current skb sent count */ + u_char *rcvbuf; /* B-Channel receive Buffer */ +}; + +struct isar_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; @@ -391,7 +419,6 @@ struct amd7930_hw { struct hdlc_state *hdlc_state; struct tq_struct tq_rcv; struct tq_struct tq_xmt; - struct sk_buff *tx_skb; /* B-Channel transmit Buffer */ }; @@ -413,15 +440,19 @@ struct BCState { int Flag; struct IsdnCardState *cs; int tx_cnt; /* B-Channel transmit counter */ + struct sk_buff *tx_skb; /* B-Channel transmit Buffer */ struct sk_buff_head rqueue; /* B-Channel receive Queue */ struct sk_buff_head squeue; /* B-Channel send Queue */ struct PStack *st; + 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; @@ -438,6 +469,7 @@ struct Channel { 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 */ @@ -471,7 +503,7 @@ struct elsa_hw { u_char LCR; u_char MCR; u_char ctrl_reg; -}; +}; struct teles3_hw { unsigned int cfg_reg; @@ -540,8 +572,14 @@ struct sedl_hw { 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 { @@ -593,6 +631,7 @@ struct hfcD_hw { #define HW_IOM1 0 #define HW_IPAC 1 +#define HW_ISAR 2 #define FLG_TWO_DCHAN 4 #define FLG_L1_DBUSY 5 #define FLG_DBUSY_TIMER 6 @@ -696,8 +735,11 @@ struct IsdnCardState { #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 @@ -751,6 +793,24 @@ struct IsdnCardState { #define CARD_AVM_A1 0 #endif +#ifdef CONFIG_HISAX_AVM_A1_PCMCIA +#define CARD_AVM_A1_PCMCIA (1<< ISDN_CTYPE_A1_PCMCIA) +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_AVM_A1_PCMCIA 0 +#endif + +#ifdef CONFIG_HISAX_FRITZPCI +#define CARD_FRITZPCI (1<< ISDN_CTYPE_FRITZPCI) +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_FRITZPCI 0 +#endif + #ifdef CONFIG_HISAX_ELSA #define CARD_ELSA (1<< ISDN_CTYPE_ELSA) | (1<< ISDN_CTYPE_ELSA_PNP) | \ (1<< ISDN_CTYPE_ELSA_PCMCIA) | (1<< ISDN_CTYPE_ELSA_PCI) @@ -803,7 +863,7 @@ struct IsdnCardState { #endif #ifdef CONFIG_HISAX_SEDLBAUER -#define CARD_SEDLBAUER (1 << ISDN_CTYPE_SEDLBAUER) | (1 << ISDN_CTYPE_SEDLBAUER_PCMCIA) +#define CARD_SEDLBAUER (1 << ISDN_CTYPE_SEDLBAUER) | (1 << ISDN_CTYPE_SEDLBAUER_PCMCIA) | ( 1 << ISDN_CTYPE_SEDLBAUER_FAX) #ifndef ISDN_CHIP_ISAC #define ISDN_CHIP_ISAC 1 #endif @@ -872,6 +932,7 @@ struct IsdnCardState { | 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 @@ -885,9 +946,14 @@ struct IsdnCardState { #undef TEI_PER_CARD #define TEI_PER_CARD 1 #define HISAX_EURO_SENDCOMPLETE 1 -#ifdef CONFIG_HISAX_ML +#define EXT_BEARER_CAPS 1 +#define HISAX_SEND_STD_LLC_IE 1 +#ifdef CONFIG_HISAX_NO_SENDCOMPLETE #undef HISAX_EURO_SENDCOMPLETE #endif +#ifdef CONFIG_HISAX_NO_LLC +#undef HISAX_SEND_STD_LLC_IE +#endif #undef HISAX_DE_AOC #ifdef CONFIG_DE_AOC #define HISAX_DE_AOC 1 diff --git a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c index 13a7e709bf8e..c235de1e42a2 100644 --- a/drivers/isdn/hisax/hscx.c +++ b/drivers/isdn/hisax/hscx.c @@ -1,4 +1,4 @@ -/* $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 * @@ -6,6 +6,12 @@ * * * $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 * @@ -67,7 +73,7 @@ void modehscx(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; - int hscx = bcs->channel; + int hscx = bcs->hw.hscx.hscx; if (cs->debug & L1_DEB_HSCX) { char tmp[40]; @@ -76,11 +82,16 @@ modehscx(struct BCState *bcs, int mode, int bc) 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); @@ -100,8 +111,8 @@ modehscx(struct BCState *bcs, int mode, int bc) } switch (mode) { case (L1_MODE_NULL): - cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0xff); - cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0xff); + cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0x1f); + cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0x1f); cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x84); break; case (L1_MODE_TRANS): @@ -136,11 +147,11 @@ hscx_l2l1(struct PStack *st, int pr, void *arg) 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); @@ -148,17 +159,17 @@ hscx_l2l1(struct PStack *st, int pr, void *arg) } 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 @@ -184,7 +195,7 @@ hscx_l2l1(struct PStack *st, int pr, void *arg) 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); @@ -192,20 +203,17 @@ close_hscxstate(struct BCState *bcs) } 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 @@ -215,7 +223,7 @@ open_hscxstate(struct IsdnCardState *cs, 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; @@ -226,7 +234,8 @@ open_hscxstate(struct IsdnCardState *cs, 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; @@ -276,6 +285,8 @@ inithscx(struct IsdnCardState *cs)) 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); } diff --git a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c index 46da67f15d7e..f3844876045a 100644 --- a/drivers/isdn/hisax/hscx_irq.c +++ b/drivers/isdn/hisax/hscx_irq.c @@ -1,4 +1,4 @@ -/* $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 * @@ -7,6 +7,9 @@ * 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 * @@ -83,7 +86,7 @@ hscx_empty_fifo(struct BCState *bcs, int count) if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "hscx_empty_fifo: incoming packet too large"); - WriteHSCXCMDR(cs, bcs->channel, 0x80); + WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); bcs->hw.hscx.rcvidx = 0; return; } @@ -91,15 +94,15 @@ hscx_empty_fifo(struct BCState *bcs, int count) bcs->hw.hscx.rcvidx += count; save_flags(flags); cli(); - READHSCXFIFO(cs, bcs->channel, ptr, count); - WriteHSCXCMDR(cs, bcs->channel, 0x80); + READHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count); + WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); restore_flags(flags); if (cs->debug & L1_DEB_HSCX_FIFO) { char tmp[256]; char *t = tmp; 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); } @@ -118,34 +121,34 @@ hscx_fill_fifo(struct BCState *bcs) if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "hscx_fill_fifo"); - if (!bcs->hw.hscx.tx_skb) + if (!bcs->tx_skb) return; - if (bcs->hw.hscx.tx_skb->len <= 0) + if (bcs->tx_skb->len <= 0) return; more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; - if (bcs->hw.hscx.tx_skb->len > fifo_size) { + if (bcs->tx_skb->len > fifo_size) { more = !0; count = fifo_size; } else - count = bcs->hw.hscx.tx_skb->len; + count = bcs->tx_skb->len; - waitforXFW(cs, bcs->channel); + waitforXFW(cs, bcs->hw.hscx.hscx); save_flags(flags); cli(); - ptr = bcs->hw.hscx.tx_skb->data; - skb_pull(bcs->hw.hscx.tx_skb, count); + ptr = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, count); bcs->tx_cnt -= count; bcs->hw.hscx.count += count; - WRITEHSCXFIFO(cs, bcs->channel, ptr, count); - WriteHSCXCMDR(cs, bcs->channel, more ? 0x8 : 0xa); + WRITEHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count); + WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa); restore_flags(flags); if (cs->debug & L1_DEB_HSCX_FIFO) { char tmp[256]; char *t = tmp; 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); } @@ -219,20 +222,20 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) } } if (val & 0x10) { /* XPR */ - if (bcs->hw.hscx.tx_skb) { - if (bcs->hw.hscx.tx_skb->len) { + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { hscx_fill_fifo(bcs); return; } else { if (bcs->st->lli.l1writewakeup && - (PACKET_NOACK != bcs->hw.hscx.tx_skb->pkt_type)) + (PACKET_NOACK != bcs->tx_skb->pkt_type)) bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count); - dev_kfree_skb(bcs->hw.hscx.tx_skb, 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); @@ -261,12 +264,12 @@ hscx_int_main(struct IsdnCardState *cs, u_char val) /* 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); @@ -294,12 +297,12 @@ hscx_int_main(struct IsdnCardState *cs, u_char val) /* 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); diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c index ee6ec7b695cd..d100fdfa2609 100644 --- a/drivers/isdn/hisax/isac.c +++ b/drivers/isdn/hisax/isac.c @@ -1,4 +1,4 @@ -/* $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 * @@ -6,6 +6,9 @@ * * * $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 * @@ -156,7 +159,7 @@ isac_empty_fifo(struct IsdnCardState *cs, int count) if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) debugl1(cs, "isac_empty_fifo"); - if ((cs->rcvidx + count) >= MAX_DFRAME_LEN) { + if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { if (cs->debug & L1_DEB_WARN) { char tmp[40]; sprintf(tmp, "isac_empty_fifo overrun %d", @@ -322,12 +325,12 @@ isac_interrupt(struct IsdnCardState *cs, u_char val) } 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) { @@ -412,9 +415,9 @@ isac_interrupt(struct IsdnCardState *cs, u_char val) 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; diff --git a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c index 5608600fe71e..b2eb696bfa4c 100644 --- a/drivers/isdn/hisax/isdnl1.c +++ b/drivers/isdn/hisax/isdnl1.c @@ -1,4 +1,4 @@ -/* $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 @@ -11,6 +11,26 @@ * * * $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 * @@ -77,7 +97,7 @@ * */ -const char *l1_revision = "$Revision: 1.15.2.12 $"; +const char *l1_revision = "$Revision: 1.15.2.18 $"; #define __NO_VERSION__ #include @@ -106,6 +126,14 @@ extern int setup_telespci(struct IsdnCard *card); 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 @@ -165,7 +193,8 @@ const char *CardType[] = "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[]; @@ -530,8 +559,10 @@ BChannel_proc_xmt(struct BCState *bcs) { struct PStack *st = bcs->st; - if (test_bit(BC_FLG_BUSY, &bcs->Flag)) + if (test_bit(BC_FLG_BUSY, &bcs->Flag)) { + debugl1(bcs->cs, "BC_BUSY Error"); return; + } if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags)) st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); @@ -641,7 +672,8 @@ closecard(int cardnr) 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); } @@ -658,6 +690,7 @@ HISAX_INITFUNC(static int init_card(struct IsdnCardState *cs)) 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) { @@ -672,8 +705,8 @@ HISAX_INITFUNC(static int init_card(struct IsdnCardState *cs)) 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); @@ -701,13 +734,14 @@ checkcard(int cardnr, char *id, int *busy_flag)) 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; @@ -821,6 +855,16 @@ checkcard(int cardnr, char *id, int *busy_flag)) 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: @@ -852,6 +896,7 @@ checkcard(int cardnr, char *id, int *busy_flag)) #if CARD_SEDLBAUER case ISDN_CTYPE_SEDLBAUER: case ISDN_CTYPE_SEDLBAUER_PCMCIA: + case ISDN_CTYPE_SEDLBAUER_FAX: ret = setup_sedlbauer(card); break; #endif @@ -897,7 +942,7 @@ checkcard(int cardnr, char *id, int *busy_flag)) 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); @@ -923,7 +968,9 @@ checkcard(int cardnr, char *id, int *busy_flag)) } 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); } @@ -1002,7 +1049,7 @@ HiSax_closecard(int cardnr) while (i!=last) { cards[i] = cards[i+1]; i++; - } + } nrcards--; } @@ -1020,6 +1067,12 @@ HiSax_reportcard(int cardnr) 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) { @@ -1224,12 +1277,12 @@ static void 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); } } @@ -1263,9 +1316,22 @@ l1_activate(struct FsmInst *fi, int event, void *arg) 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}, @@ -1429,34 +1495,34 @@ l1_msg(struct IsdnCardState *cs, int pr, void *arg) { 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; } } @@ -1504,5 +1570,6 @@ setstack_l1_B(struct PStack *st) st->l1.l1m.userdata = st; st->l1.l1m.userint = 0; st->l1.l1m.printdebug = l1m_debug; + st->l1.Flags = 0; FsmInitTimer(&st->l1.l1m, &st->l1.timer); } diff --git a/drivers/isdn/hisax/isdnl1.h b/drivers/isdn/hisax/isdnl1.h index d40a3bb32a66..a874ef36d548 100644 --- a/drivers/isdn/hisax/isdnl1.h +++ b/drivers/isdn/hisax/isdnl1.h @@ -1,6 +1,12 @@ -/* $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 * @@ -38,7 +44,7 @@ #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 @@ -53,7 +59,7 @@ #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); diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c index 9bb4f3599b15..ff9046290f65 100644 --- a/drivers/isdn/hisax/isdnl2.c +++ b/drivers/isdn/hisax/isdnl2.c @@ -1,4 +1,4 @@ -/* $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 @@ -7,6 +7,9 @@ * 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 * @@ -48,7 +51,7 @@ #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); @@ -253,6 +256,16 @@ IsRR(u_char * data, int ext) 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) { @@ -398,9 +411,16 @@ l2_dl_establish(struct FsmInst *fi, int event, void *arg) struct PStack *st = fi->userdata; int state = fi->state; - FsmChangeState(fi, ST_L2_3); - if (state == ST_L2_1) - st->l2.l2tei(st, MDL_ASSIGN | 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 @@ -692,19 +712,37 @@ l2_got_dm(struct FsmInst *fi, int event, void *arg) 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); } } @@ -817,9 +855,11 @@ l2_got_st7_super(struct FsmInst *fi, int event, void *arg) PollFlag = (skb->data[1] & 0x1) == 0x1; nr = skb->data[1] >> 1; } else { - st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N'); + if (skb->len >2) { + st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'N'); + establishlink(fi); + } FreeSkb(skb); - establishlink(fi); return; } } else { @@ -908,9 +948,7 @@ l2_got_iframe(struct FsmInst *fi, int event, void *arg) i = l2addrsize(l2); if (test_bit(FLG_MOD128, &l2->flag)) { if (skb->len <= (i + 1)) { - st->ma.layer(st, MDL_ERROR | 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'); @@ -1369,8 +1407,8 @@ static struct FsmNode L2FnList[] HISAX_INITDATA = {ST_L2_4, EV_L2_DM, l2_got_dm}, {ST_L2_5, EV_L2_DM, l2_got_dm}, {ST_L2_6, EV_L2_DM, l2_got_dm}, - {ST_L2_7, EV_L2_DM, l2_mdl_error}, - {ST_L2_8, EV_L2_DM, l2_mdl_error}, + {ST_L2_7, EV_L2_DM, l2_got_dm}, + {ST_L2_8, EV_L2_DM, l2_got_dm}, {ST_L2_1, EV_L2_UI, l2_got_ui}, {ST_L2_2, EV_L2_UI, l2_got_ui}, {ST_L2_3, EV_L2_UI, l2_got_ui}, @@ -1424,7 +1462,7 @@ isdnl2_l1l2(struct PStack *st, int pr, void *arg) } 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); @@ -1439,9 +1477,11 @@ isdnl2_l1l2(struct PStack *st, int pr, void *arg) else if (IsFRMR(datap, test_bit(FLG_MOD128, &st->l2.flag))) ret = FsmEvent(&st->l2.l2m, EV_L2_FRMR, skb); else { - ret = 0; + 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); @@ -1576,13 +1616,13 @@ transl2_l3l2(struct PStack *st, int pr, void *arg) switch (pr) { case (DL_DATA | REQUEST): case (DL_UNIT_DATA | REQUEST): - st->l2.l2l1(st, PH_DATA, 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; } } diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c index 5b1663c689b5..fd50c3b8adc6 100644 --- a/drivers/isdn/hisax/isdnl3.c +++ b/drivers/isdn/hisax/isdnl3.c @@ -1,4 +1,4 @@ -/* $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 @@ -7,6 +7,9 @@ * 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 * @@ -42,7 +45,7 @@ #include "isdnl3.h" #include -const char *l3_revision = "$Revision: 1.10.2.4 $"; +const char *l3_revision = "$Revision: 1.10.2.5 $"; static struct Fsm l3fsm = @@ -329,7 +332,8 @@ release_l3_process(struct l3_process *p) pp = np; np = np->next; } - printk(KERN_ERR "HiSax internal L3 error CR not in list\n"); + printk(KERN_ERR "HiSax internal L3 error CR(%d) not in list\n", p->callref); + l3_debug(p->st, "HiSax internal L3 error CR(%d) not in list", p->callref); }; void diff --git a/drivers/isdn/hisax/l3_1tr6.c b/drivers/isdn/hisax/l3_1tr6.c index 1448185dd6da..568ed489a076 100644 --- a/drivers/isdn/hisax/l3_1tr6.c +++ b/drivers/isdn/hisax/l3_1tr6.c @@ -1,4 +1,4 @@ -/* $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 * @@ -6,6 +6,9 @@ * * * $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 * @@ -38,7 +41,7 @@ #include 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; \ @@ -56,66 +59,34 @@ l3_1TR6_message(struct l3_process *pc, u_char mt, u_char pd) return; p = skb_put(skb, 4); MsgHead(p, pc->callref, mt, pd); - pc->st->l3.l3l2(pc->st, DL_DATA | 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 @@ -204,7 +175,7 @@ l3_1tr6_setup_req(struct l3_process *pc, u_char pr, void *arg) L3DelTimer(&pc->timer); L3AddTimer(&pc->timer, T303, CC_T303); newl3state(pc, 1); - pc->st->l3.l3l2(pc->st, DL_DATA | REQUEST, skb); + l3_msg(pc->st, DL_DATA | REQUEST, skb); } static void @@ -220,17 +191,29 @@ l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg) /* Channel Identification */ p = skb->data; if ((p = findie(p, skb->len, WE0_chanID, 0))) { - pc->para.bchannel = p[2] & 0x3; - bcfound++; - } else if (pc->st->l3.debug & L3_DEB_WARN) - l3_debug(pc->st, "setup without bchannel"); + if (p[1] != 1) { + l3_1tr6_error(pc, "setup wrong chanID len", skb); + return; + } + if ((p[2] & 0xf4) != 0x80) { + l3_1tr6_error(pc, "setup wrong WE0_chanID", skb); + return; + } + if ((pc->para.bchannel = p[2] & 0x3)) + bcfound++; + } else { + l3_1tr6_error(pc, "missing setup chanID", skb); + return; + } p = skb->data; if ((p = findie(p, skb->len, WE6_serviceInd, 6))) { pc->para.setup.si1 = p[2]; pc->para.setup.si2 = p[3]; - } else if (pc->st->l3.debug & L3_DEB_WARN) - l3_debug(pc->st, "setup without service indicator"); + } else { + l3_1tr6_error(pc, "missing setup SI", skb); + return; + } p = skb->data; if ((p = findie(p, skb->len, WE0_destAddr, 0))) @@ -276,9 +259,19 @@ l3_1tr6_setup_ack(struct l3_process *pc, u_char pr, void *arg) p = skb->data; newl3state(pc, 2); if ((p = findie(p, skb->len, WE0_chanID, 0))) { + if (p[1] != 1) { + l3_1tr6_error(pc, "setup_ack wrong chanID len", skb); + return; + } + if ((p[2] & 0xf4) != 0x80) { + l3_1tr6_error(pc, "setup_ack wrong WE0_chanID", skb); + return; + } pc->para.bchannel = p[2] & 0x3; - } else if (pc->st->l3.debug & L3_DEB_WARN) - l3_debug(pc->st, "setup answer without bchannel"); + } else { + l3_1tr6_error(pc, "missing setup_ack WE0_chanID", skb); + return; + } dev_kfree_skb(skb, FREE_READ); L3AddTimer(&pc->timer, T304, CC_T304); pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc); @@ -293,9 +286,23 @@ l3_1tr6_call_sent(struct l3_process *pc, u_char pr, void *arg) L3DelTimer(&pc->timer); p = skb->data; if ((p = findie(p, skb->len, WE0_chanID, 0))) { + if (p[1] != 1) { + l3_1tr6_error(pc, "call sent wrong chanID len", skb); + return; + } + if ((p[2] & 0xf4) != 0x80) { + l3_1tr6_error(pc, "call sent wrong WE0_chanID", skb); + return; + } + if ((pc->state == 2) && (pc->para.bchannel != (p[2] & 0x3))) { + l3_1tr6_error(pc, "call sent wrong chanID value", skb); + return; + } pc->para.bchannel = p[2] & 0x3; - } else if (pc->st->l3.debug & L3_DEB_WARN) - l3_debug(pc->st, "setup answer without bchannel"); + } else { + l3_1tr6_error(pc, "missing call sent WE0_chanID", skb); + return; + } dev_kfree_skb(skb, FREE_READ); L3AddTimer(&pc->timer, T310, CC_T310); newl3state(pc, 3); @@ -356,6 +363,10 @@ l3_1tr6_connect(struct l3_process *pc, u_char pr, void *arg) struct sk_buff *skb = arg; L3DelTimer(&pc->timer); /* T310 */ + if (!findie(skb->data, skb->len, WE6_date, 6)) { + l3_1tr6_error(pc, "missing connect date", skb); + return; + } newl3state(pc, 10); dev_kfree_skb(skb, FREE_READ); pc->para.chargeinfo = 0; @@ -380,8 +391,11 @@ l3_1tr6_rel(struct l3_process *pc, u_char pr, void *arg) pc->para.cause = 0; pc->para.loc = 0; } - } else + } else { pc->para.cause = -1; + l3_1tr6_error(pc, "missing REL cause", skb); + return; + } dev_kfree_skb(skb, FREE_READ); StopAllL3Timer(pc); newl3state(pc, 0); @@ -448,6 +462,10 @@ l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg) l3_debug(pc->st, "cause not found"); pc->para.cause = -1; } + if (!findie(skb->data, skb->len, WE6_date, 6)) { + l3_1tr6_error(pc, "missing connack date", skb); + return; + } dev_kfree_skb(skb, FREE_READ); newl3state(pc, 12); pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc); @@ -459,6 +477,10 @@ l3_1tr6_connect_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; + if (!findie(skb->data, skb->len, WE6_date, 6)) { + l3_1tr6_error(pc, "missing connack date", skb); + return; + } dev_kfree_skb(skb, FREE_READ); newl3state(pc, 10); pc->para.chargeinfo = 0; @@ -502,7 +524,7 @@ l3_1tr6_setup_rsp(struct l3_process *pc, u_char pr, void *arg) if (!(skb = l3_alloc_skb(l))) return; memcpy(skb_put(skb, l), tmp, l); - pc->st->l3.l3l2(pc->st, DL_DATA | REQUEST, skb); + l3_msg(pc->st, DL_DATA | REQUEST, skb); L3DelTimer(&pc->timer); L3AddTimer(&pc->timer, T313, CC_T313); } @@ -545,19 +567,10 @@ l3_1tr6_disconnect_req(struct l3_process *pc, u_char pr, void *arg) if (!(skb = l3_alloc_skb(l))) return; memcpy(skb_put(skb, l), tmp, l); - pc->st->l3.l3l2(pc->st, DL_DATA | 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) { @@ -567,8 +580,8 @@ l3_1tr6_t303(struct l3_process *pc, u_char pr, void *arg) l3_1tr6_setup_req(pc, pr, arg); } else { L3DelTimer(&pc->timer); - pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc); - release_l3_process(pc); + pc->para.cause = 0; + l3_1tr6_disconnect_req(pc, 0, NULL); } } @@ -613,7 +626,7 @@ l3_1tr6_t305(struct l3_process *pc, u_char pr, void *arg) if (!(skb = l3_alloc_skb(l))) return; memcpy(skb_put(skb, l), tmp, l); - pc->st->l3.l3l2(pc->st, DL_DATA | REQUEST, skb); + l3_msg(pc->st, DL_DATA | REQUEST, skb); L3AddTimer(&pc->timer, T308, CC_T308_1); } @@ -692,6 +705,8 @@ sizeof(struct stateentry); static struct stateentry datastln1[] = { + {SBIT(0), + MT_N1_INVALID, l3_1tr6_invalid}, {SBIT(0), MT_N1_SETUP, l3_1tr6_setup}, {SBIT(1), @@ -711,8 +726,13 @@ static struct stateentry datastln1[] = {SBIT(10), MT_N1_INFO, l3_1tr6_info}, {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | - SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19), + SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17), MT_N1_REL, l3_1tr6_rel}, + {SBIT(19), + MT_N1_REL, l3_1tr6_rel_ack}, + {SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | + SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17), + MT_N1_REL_ACK, l3_1tr6_invalid}, {SBIT(19), MT_N1_REL_ACK, l3_1tr6_rel_ack} }; @@ -781,7 +801,28 @@ up1tr6(struct PStack *st, int pr, void *arg) } } 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"); @@ -790,9 +831,7 @@ up1tr6(struct PStack *st, int pr, void *arg) 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++) diff --git a/drivers/isdn/hisax/l3_1tr6.h b/drivers/isdn/hisax/l3_1tr6.h index f192de49c32b..63da58ee02a0 100644 --- a/drivers/isdn/hisax/l3_1tr6.h +++ b/drivers/isdn/hisax/l3_1tr6.h @@ -1,8 +1,11 @@ -/* $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 * @@ -67,6 +70,7 @@ #define MT_N1_REG_ACK 0x6C #define MT_N1_REG_REJ 0x6F #define MT_N1_STAT 0x63 +#define MT_N1_INVALID 0 /* * W Elemente diff --git a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c index 217a440ebf35..8bba9c04590e 100644 --- a/drivers/isdn/hisax/l3dss1.c +++ b/drivers/isdn/hisax/l3dss1.c @@ -1,4 +1,4 @@ -/* $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 * @@ -9,6 +9,9 @@ * 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 * @@ -47,7 +50,7 @@ #include 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 @@ -58,9 +61,9 @@ const char *dss1_revision = "$Revision: 1.16.2.4 $"; *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; @@ -70,91 +73,99 @@ l3dss1_parse_facility(struct l3_process *pc, u_char *p) l3_debug(pc->st, "qd_len == 0"); return; } - if((*p & 0x1F) != 0x11) { /* Service discriminator, supplementary service */ + if ((*p & 0x1F) != 0x11) { /* Service discriminator, supplementary service */ l3_debug(pc->st, "supplementary service != 0x11"); return; } - while(qd_len > 0 && !(*p & 0x80)) { /* extension ? */ - p++; qd_len--; - } - if(qd_len < 2) { + while (qd_len > 0 && !(*p & 0x80)) { /* extension ? */ + p++; + qd_len--; + } + if (qd_len < 2) { l3_debug(pc->st, "qd_len < 2"); return; } - p++; qd_len--; - if((*p & 0xE0) != 0xA0) { /* class and form */ + p++; + qd_len--; + if ((*p & 0xE0) != 0xA0) { /* class and form */ l3_debug(pc->st, "class and form != 0xA0"); return; } - switch(*p & 0x1F) { /* component tag */ - case 1: /* invoke */ - { - unsigned char nlen, ilen; - int ident; - - p++; qd_len--; - if(qd_len < 1) { - l3_debug(pc->st, "qd_len < 1"); - break; - } - if(*p & 0x80) { /* length format */ - l3_debug(pc->st, "*p & 0x80 length format"); - break; - } - nlen = *p++; qd_len--; - if(qd_len < nlen) { - l3_debug(pc->st, "qd_len < nlen"); - return; - } - qd_len -= nlen; - - if(nlen < 2) { - l3_debug(pc->st, "nlen < 2"); - return; - } - if(*p != 0x02) { /* invoke identifier tag */ - l3_debug(pc->st, "invoke identifier tag !=0x02"); - return; - } - p++; nlen--; - if(*p & 0x80) { /* length format */ - l3_debug(pc->st, "*p & 0x80 length format 2"); - break; - } - ilen = *p++; nlen--; - if(ilen > nlen || ilen == 0) { - l3_debug(pc->st, "ilen > nlen || ilen == 0"); - return; - } - nlen -= ilen; - ident = 0; - while(ilen > 0) { - ident = (ident << 8) | (*p++ & 0xFF); /* invoke identifier */ - ilen--; - } - - if(nlen < 2) { - l3_debug(pc->st, "nlen < 2 22"); - return; - } - if(*p != 0x02) { /* operation value */ - l3_debug(pc->st, "operation value !=0x02"); - return; - } - p++; nlen--; - ilen = *p++; nlen--; - if(ilen > nlen || ilen == 0) { - l3_debug(pc->st, "ilen > nlen || ilen == 0 22"); - return; - } - nlen -= ilen; - ident = 0; - while(ilen > 0) { - ident = (ident << 8) | (*p++ & 0xFF); - ilen--; - } - - #define FOO1(s,a,b) \ + switch (*p & 0x1F) { /* component tag */ + case 1: /* invoke */ + { + unsigned char nlen, 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) { \ @@ -170,68 +181,72 @@ l3dss1_parse_facility(struct l3_process *pc, u_char *p) p += ilen+2; \ } \ } - - switch(ident) { - default: - break; - case 0x22: /* during */ - FOO1("1A",0x30,FOO1("1C",0xA1,FOO1("1D",0x30,FOO1("1E",0x02,({ - ident = 0; - while(ilen > 0) { - ident = (ident<<8) | *p++; - ilen--; - } - if (ident > pc->para.chargeinfo) { - pc->para.chargeinfo = ident; - pc->st->l3.l3l4(pc->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: @@ -310,161 +325,240 @@ l3dss1_release_cmpl(struct l3_process *pc, u_char pr, void *arg) 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 @@ -490,7 +584,7 @@ l3dss1_setup_req(struct l3_process *pc, u_char pr, /* * Set Bearer Capability, Map info from 1TR6-convention to EDSS1 */ -#ifdef HISAX_EURO_SENDCOMPLETE +#if HISAX_EURO_SENDCOMPLETE *p++ = 0xa1; /* complete indicator */ #endif switch (pc->para.setup.si1) { @@ -550,11 +644,11 @@ l3dss1_setup_req(struct l3_process *pc, u_char pr, msn = pc->para.setup.eazmsn; sub = NULL; sp = msn; - while (*sp) { + while (*sp) { if ('.' == *sp) { sub = sp; *sp = 0; - } else + } else sp++; } if (*msn) { @@ -571,20 +665,20 @@ l3dss1_setup_req(struct l3_process *pc, u_char pr, } if (sub) { *sub++ = '.'; - *p++ = 0x6d; /* Calling party subaddress */ - *p++ = strlen(sub) + 2; + *p++ = 0x6d; /* Calling party subaddress */ + *p++ = strlen(sub) + 2; *p++ = 0x80; /* NSAP coded */ *p++ = 0x50; /* local IDI format */ - while (*sub) + while (*sub) *p++ = *sub++ & 0x7f; } sub = NULL; sp = teln; - while (*sp) { + while (*sp) { if ('.' == *sp) { sub = sp; *sp = 0; - } else + } else sp++; } *p++ = 0x70; @@ -596,33 +690,47 @@ l3dss1_setup_req(struct l3_process *pc, u_char pr, if (sub) { *sub++ = '.'; - *p++ = 0x71; /* Called party subaddress */ - *p++ = strlen(sub) + 2; + *p++ = 0x71; /* Called party subaddress */ + *p++ = strlen(sub) + 2; *p++ = 0x80; /* NSAP coded */ *p++ = 0x50; /* local IDI format */ - while (*sub) + while (*sub) *p++ = *sub++ & 0x7f; } - -#ifdef EXT_BEARER_CAPS - if ((pc->para.setup.si2 >= 160) && (pc->para.setup.si2 <= 175)) - { // sync. Bitratenadaption, V.110/X.30 - *p++ = 0x7c; *p++ = 0x04; *p++ = 0x88; *p++ = 0x90; *p++ = 0x21; - *p++ = EncodeSyncParams(pc->para.setup.si2 - 160, 0x80); - } - else if ((pc->para.setup.si2 >= 176) && (pc->para.setup.si2 <= 191)) - { // sync. Bitratenadaption, V.120 - *p++ = 0x7c; *p++ = 0x05; *p++ = 0x88; *p++ = 0x90; *p++ = 0x28; - *p++ = EncodeSyncParams(pc->para.setup.si2 - 176, 0); - *p++ = 0x82; - } - else if (pc->para.setup.si2 >= 192) - { // async. Bitratenadaption, V.110/X.30 - *p++ = 0x7c; *p++ = 0x06; *p++ = 0x88; *p++ = 0x90; *p++ = 0x21; - p = EncodeASyncParams(p, pc->para.setup.si2 - 192); - } 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))) @@ -722,30 +830,30 @@ l3dss1_alerting(struct l3_process *pc, u_char pr, void *arg) 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; @@ -757,7 +865,7 @@ l3dss1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg) 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]; @@ -765,9 +873,9 @@ l3dss1_setup(struct l3_process *pc, u_char pr, void *arg) /* ETS 300-104 1.3.4 and 1.3.5 * we need to detect unknown inform. element from 0 to 7 - */ + */ p = skb->data; - for(i = 0; i < 8; i++) + for (i = 0; i < 8; i++) ptmp[i] = skb->data; if (findie(ptmp[1], skb->len, 0x01, 0) || findie(ptmp[2], skb->len, 0x02, 0) @@ -775,15 +883,14 @@ l3dss1_setup(struct l3_process *pc, u_char pr, void *arg) || findie(ptmp[5], skb->len, 0x05, 0) || findie(ptmp[6], skb->len, 0x06, 0) || findie(ptmp[7], skb->len, 0x07, 0)) { - /* if ie is < 8 and not 0 nor 4, send RELEASE_COMPLETE - * cause 0x60 - */ - pc->para.cause = 0x60; + /* if ie is < 8 and not 0 nor 4, send RELEASE_COMPLETE + * cause 0x60 + */ + pc->para.cause = 0x60; dev_kfree_skb(skb, FREE_READ); - l3dss1_msg_without_setup(pc, pr, NULL); + l3dss1_msg_without_setup(pc, pr, NULL); return; } - /* * Channel Identification */ @@ -796,8 +903,8 @@ l3dss1_setup(struct l3_process *pc, u_char pr, void *arg) 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; @@ -819,10 +926,10 @@ l3dss1_setup(struct l3_process *pc, u_char pr, void *arg) /* Unrestricted digital information */ pc->para.setup.si1 = 7; /* JIM, 05.11.97 I wanna set service indicator 2 */ -#ifdef EXT_BEARER_CAPS - pc->para.setup.si2 = DecodeSI2(skb); - printk(KERN_DEBUG "HiSax: SI=%d, AI=%d\n", - pc->para.setup.si1, pc->para.setup.si2); +#if EXT_BEARER_CAPS + pc->para.setup.si2 = DecodeSI2(skb); + printk(KERN_DEBUG "HiSax: SI=%d, AI=%d\n", + pc->para.setup.si1, pc->para.setup.si2); #endif break; case 0x09: @@ -844,9 +951,9 @@ l3dss1_setup(struct l3_process *pc, u_char pr, void *arg) if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "setup without bearer capabilities"); /* ETS 300-104 1.3.3 */ - pc->para.cause = 0x60; + pc->para.cause = 0x60; dev_kfree_skb(skb, FREE_READ); - l3dss1_msg_without_setup(pc, pr, NULL); + l3dss1_msg_without_setup(pc, pr, NULL); return; } @@ -859,8 +966,8 @@ l3dss1_setup(struct l3_process *pc, u_char pr, void *arg) p = skb->data; if ((p = findie(p, skb->len, 0x71, 0))) { /* Called party subaddress */ - if ((p[1]>=2) && (p[2]==0x80) && (p[3]==0x50)) { - tmp[0]='.'; + if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) { + tmp[0] = '.'; iecpy(&tmp[1], p, 2); strcat(pc->para.setup.eazmsn, tmp); } else if (pc->debug & L3_DEB_WARN) @@ -884,24 +991,23 @@ l3dss1_setup(struct l3_process *pc, u_char pr, void *arg) p = skb->data; if ((p = findie(p, skb->len, 0x6d, 0))) { /* Calling party subaddress */ - if ((p[1]>=2) && (p[2]==0x80) && (p[3]==0x50)) { - tmp[0]='.'; + if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) { + tmp[0] = '.'; iecpy(&tmp[1], p, 2); strcat(pc->para.setup.phone, tmp); } else if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "wrong calling subaddress"); } - dev_kfree_skb(skb, 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; } @@ -1013,8 +1119,8 @@ l3dss1_release(struct l3_process *pc, u_char pr, void *arg) } p = skb->data; if ((p = findie(p, skb->len, IE_FACILITY, 0))) { -#ifdef HISAX_DE_AOC - l3dss1_parse_facility(pc,p); +#if HISAX_DE_AOC + l3dss1_parse_facility(pc, p); #else p = NULL; #endif @@ -1067,9 +1173,9 @@ l3dss1_status_enq(struct l3_process *pc, u_char pr, void *arg) 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; @@ -1081,7 +1187,7 @@ l3dss1_status_req(struct l3_process *pc, u_char pr, void *arg) *p++ = IE_CAUSE; *p++ = 0x2; *p++ = 0x80; - *p++ = 0x62 | 0x80; /* status sending */ + *p++ = 0x62 | 0x80; /* status sending */ *p++ = 0x14; /* CallState */ *p++ = 0x1; @@ -1104,10 +1210,10 @@ l3dss1_release_ind(struct l3_process *pc, u_char pr, void *arg) if ((p = findie(p, skb->len, IE_CALL_STATE, 0))) { p++; - if (1== *p++) + if (1 == *p++) callState = *p; } - if(callState == 0) { + if (callState == 0) { /* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1 * set down layer 3 without sending any message */ @@ -1211,8 +1317,8 @@ static void l3dss1_t318(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); - pc->para.cause = 0x66; /* Timer expiry */ - pc->para.loc = 0; /* local */ + pc->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); @@ -1223,8 +1329,8 @@ static void l3dss1_t319(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); - pc->para.cause = 0x66; /* Timer expiry */ - pc->para.loc = 0; /* local */ + pc->para.cause = 0x66; /* Timer expiry */ + pc->para.loc = 0; /* local */ pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc); newl3state(pc, 10); } @@ -1252,30 +1358,30 @@ l3dss1_status(struct l3_process *pc, u_char pr, void *arg) if ((p = findie(p, skb->len, IE_CAUSE, 0))) { p++; l = *p++; - t += sprintf(t,"Status CR %x Cause:", pc->callref); + t += sprintf(t, "Status CR %x Cause:", pc->callref); while (l--) { - cause = *p; - t += sprintf(t," %2x",*p++); + cause = *p; + t += sprintf(t, " %2x", *p++); } } else - sprintf(t,"Status CR %x no Cause", pc->callref); + sprintf(t, "Status CR %x no Cause", pc->callref); l3_debug(pc->st, tmp); p = skb->data; t = tmp; - t += sprintf(t,"Status state %x ", pc->state); + t += sprintf(t, "Status state %x ", pc->state); if ((p = findie(p, skb->len, IE_CALL_STATE, 0))) { p++; - if (1== *p++) { - callState = *p; - t += sprintf(t,"peer state %x" , *p); + 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); @@ -1286,13 +1392,13 @@ l3dss1_status(struct l3_process *pc, u_char pr, void *arg) static void l3dss1_facility(struct l3_process *pc, u_char pr, void *arg) { - u_char *p; + u_char *p; struct sk_buff *skb = arg; p = skb->data; if ((p = findie(p, skb->len, IE_FACILITY, 0))) { -#ifdef HISAX_DE_AOC - l3dss1_parse_facility(pc,p); +#if HISAX_DE_AOC + l3dss1_parse_facility(pc, p); #else p = NULL; #endif @@ -1305,21 +1411,21 @@ l3dss1_suspend_req(struct l3_process *pc, u_char pr, void *arg) struct sk_buff *skb; u_char tmp[32]; u_char *p = tmp; - u_char i,l; + u_char 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;ist, "SUS wrong CALLID len %d", l); return; - } + } l = p - tmp; if (!(skb = l3_alloc_skb(l))) return; @@ -1369,21 +1475,21 @@ l3dss1_resume_req(struct l3_process *pc, u_char pr, void *arg) struct sk_buff *skb; u_char tmp[32]; u_char *p = tmp; - u_char i,l; + u_char 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;ist, "RES wrong CALLID len %d", l); return; - } + } l = p - tmp; if (!(skb = l3_alloc_skb(l))) return; @@ -1433,23 +1539,23 @@ l3dss1_resume_rej(struct l3_process *pc, u_char pr, void *arg) 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; @@ -1458,17 +1564,17 @@ l3dss1_global_restart(struct l3_process *pc, u_char pr, void *arg) 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; @@ -1478,7 +1584,7 @@ l3dss1_global_restart(struct l3_process *pc, u_char pr, void *arg) *p++ = 1; *p++ = ch | 0x80; } - *p++ = 0x79; /* RESTART Ind */ + *p++ = 0x79; /* RESTART Ind */ *p++ = 1; *p++ = ri; l = p - tmp; @@ -1488,7 +1594,6 @@ l3dss1_global_restart(struct l3_process *pc, u_char pr, void *arg) newl3state(pc, 0); l3_msg(pc->st, DL_DATA | REQUEST, skb); } - /* *INDENT-OFF* */ static struct stateentry downstatelist[] = { @@ -1597,34 +1702,24 @@ static int datasllen = sizeof(datastatelist) / sizeof(struct stateentry); static struct stateentry globalmes_list[] = { {ALL_STATES, - MT_STATUS, l3dss1_status}, + MT_STATUS, l3dss1_status}, {SBIT(0), MT_RESTART, l3dss1_global_restart}, /* {SBIT(1), - MT_RESTART_ACKNOWLEDGE, l3dss1_restart_ack}, + MT_RESTART_ACKNOWLEDGE, l3dss1_restart_ack}, */ }; static int globalm_len = sizeof(globalmes_list) / sizeof(struct stateentry); -#if 0 -static struct stateentry globalcmd_list[] = -{ - {ALL_STATES, - CC_STATUS | 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)) @@ -1668,18 +1763,18 @@ dss1up(struct PStack *st, int pr, void *arg) 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))) { @@ -1687,7 +1782,7 @@ dss1up(struct PStack *st, int pr, void *arg) * this callreference is active */ if (mt == MT_SETUP) { - /* Setup creates a new transaction process */ + /* Setup creates a new transaction process */ if (!(proc = new_l3_process(st, cr))) { /* May be to answer with RELEASE_COMPLETE and * CAUSE 0x2f "Resource unavailable", but this @@ -1698,14 +1793,14 @@ dss1up(struct PStack *st, int pr, void *arg) } } else if (mt == MT_STATUS) { cause = 0; - if((ptr = findie(skb->data, skb->len, IE_CAUSE, 0)) != NULL) { - ptr++; - if (*ptr++ == 2) - ptr++; - cause = *ptr & 0x7f; + if ((ptr = findie(skb->data, skb->len, IE_CAUSE, 0)) != NULL) { + ptr++; + if (*ptr++ == 2) + ptr++; + cause = *ptr & 0x7f; } callState = 0; - if((ptr = findie(skb->data, skb->len, IE_CALL_STATE, 0)) != NULL) { + if ((ptr = findie(skb->data, skb->len, IE_CALL_STATE, 0)) != NULL) { ptr++; if (*ptr++ == 2) ptr++; @@ -1721,28 +1816,28 @@ dss1up(struct PStack *st, int pr, void *arg) return; } else { /* ETS 300-104 part 2.4.2 - * if setup has not been made and a message type + * if setup has not been made and a message type * MT_STATUS is received with call state != 0, * we must send MT_RELEASE_COMPLETE cause 101 */ dev_kfree_skb(skb, 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; @@ -1753,9 +1848,8 @@ dss1up(struct PStack *st, int pr, void *arg) * if setup has been made and invalid message type is received, * we must send MT_STATUS cause 0x62 */ - mt = MT_INVALID; /* sorry, not clean, but do the right thing ;-) */ + mt = MT_INVALID; /* sorry, not clean, but do the right thing ;-) */ } - for (i = 0; i < datasllen; i++) if ((mt == datastatelist[i].primitive) && ((1 << proc->state) & datastatelist[i].state)) @@ -1785,7 +1879,7 @@ dss1down(struct PStack *st, int pr, void *arg) 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)) { diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c index 83a0991d8d76..28277c528ae9 100644 --- a/drivers/isdn/hisax/netjet.c +++ b/drivers/isdn/hisax/netjet.c @@ -1,4 +1,4 @@ -/* $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 * @@ -8,6 +8,12 @@ * * * $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 * @@ -53,7 +59,7 @@ 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) @@ -338,14 +344,14 @@ static int make_raw_data(struct BCState *bcs) { 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; ihw.tiger.tx_skb->len; i++) { - val = bcs->hw.tiger.tx_skb->data[i]; + for (i=0; itx_skb->len; i++) { + val = bcs->tx_skb->data[i]; fcs = PPP_FCS (fcs, val); MAKE_RAW_BYTE; } @@ -370,7 +376,7 @@ static int make_raw_data(struct BCState *bcs) { } 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) { @@ -381,7 +387,7 @@ static int make_raw_data(struct BCState *bcs) { bcs->hw.tiger.sendbuf[s_cnt++] = s_val; } bcs->hw.tiger.sendcnt = s_cnt; - bcs->tx_cnt -= bcs->hw.tiger.tx_skb->len; + bcs->tx_cnt -= bcs->tx_skb->len; bcs->hw.tiger.sp = bcs->hw.tiger.sendbuf; return(0); } @@ -605,7 +611,7 @@ static void fill_dma(struct BCState *bcs) 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, @@ -706,15 +712,15 @@ static void write_raw(struct BCState *bcs, u_int *buf, int cnt) { 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; @@ -724,7 +730,7 @@ static void write_raw(struct BCState *bcs, u_int *buf, int cnt) { test_and_clear_bit(BC_FLG_HALF, &bcs->Flag); test_and_set_bit(BC_FLG_NOFRAME, &bcs->Flag); } - if ((bcs->hw.tiger.tx_skb = skb_dequeue(&bcs->squeue))) { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { fill_dma(bcs); } else { mask ^= 0xffffffff; @@ -797,28 +803,28 @@ tiger_l2l1(struct PStack *st, int pr, void *arg) 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 @@ -827,12 +833,16 @@ tiger_l2l1(struct PStack *st, int pr, void *arg) 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; } } @@ -841,7 +851,7 @@ tiger_l2l1(struct PStack *st, int pr, void *arg) 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); @@ -853,26 +863,24 @@ close_tigerstate(struct BCState *bcs) } 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); @@ -880,7 +888,7 @@ open_tigerstate(struct IsdnCardState *cs, int bc) skb_queue_head_init(&bcs->rqueue); skb_queue_head_init(&bcs->squeue); } - bcs->hw.tiger.tx_skb = NULL; + bcs->tx_skb = NULL; bcs->hw.tiger.sendcnt = 0; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); bcs->event = 0; @@ -891,12 +899,14 @@ open_tigerstate(struct IsdnCardState *cs, int bc) 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); } diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c index d754c4142913..b9a5a3e73485 100644 --- a/drivers/isdn/hisax/sedlbauer.c +++ b/drivers/isdn/hisax/sedlbauer.c @@ -1,11 +1,12 @@ -/* $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) * @@ -14,6 +15,15 @@ * 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 * @@ -38,19 +48,22 @@ #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) @@ -66,6 +79,9 @@ const char *Sedlbauer_Types[] = #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 @@ -138,6 +154,29 @@ WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) 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) { @@ -223,6 +262,55 @@ sedlbauer_interrupt(int intno, void *dev_id, struct pt_regs *regs) } } +static void +sedlbauer_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char ista, val, icnt = 20; + 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) { @@ -237,17 +325,33 @@ reset_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); } } @@ -263,8 +367,13 @@ Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg) release_io_sedlbauer(cs); return(0); case CARD_SETIRQ: - return(request_irq(cs->irq, &sedlbauer_interrupt, + if (cs->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); @@ -277,7 +386,7 @@ Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg) __initfunc(int setup_sedlbauer(struct IsdnCard *card)) { - int bytecnt; + int bytecnt, val; struct IsdnCardState *cs = card->cs; char tmp[64]; @@ -310,44 +419,58 @@ setup_sedlbauer(struct IsdnCard *card)) /* 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); } diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c index 18544d1a5dcb..2c3a6b26b199 100644 --- a/drivers/net/eepro.c +++ b/drivers/net/eepro.c @@ -1,19 +1,15 @@ /* 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. @@ -27,9 +23,19 @@ 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 @@ -67,7 +73,7 @@ */ 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 @@ -113,22 +119,26 @@ static const char *version = #include #include - /* 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 @@ -140,18 +150,29 @@ struct eepro_local { 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); @@ -200,14 +221,18 @@ it is reset to the default of 24K, and, hence, 8K for the trasnmit 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 */ @@ -228,6 +253,7 @@ buffer (transmit-buffer = 32K - receive-buffer). #define BANK2_SELECT 0x80 /* Bank 0 registers */ + #define COMMAND_REG 0x00 /* Register 0 */ #define MC_SETUP 0x03 #define XMT_CMD 0x04 @@ -263,6 +289,7 @@ buffer (transmit-buffer = 32K - receive-buffer). #define IO_PORT_32_BIT 0x0c /* Bank 1 registers */ + #define REG1 0x01 #define WORD_WIDTH 0x02 #define INT_ENABLE 0x80 @@ -273,6 +300,7 @@ buffer (transmit-buffer = 32K - receive-buffer). #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 */ @@ -285,7 +313,7 @@ buffer (transmit-buffer = 32K - receive-buffer). #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 @@ -299,20 +327,26 @@ buffer (transmit-buffer = 32K - receive-buffer). #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; @@ -327,6 +361,7 @@ eepro_probe(struct device *dev) int ioaddr = eepro_portlist[i]; if (check_region(ioaddr, EEPRO_IO_EXTENT)) continue; + if (eepro_probe1(dev, ioaddr) == 0) return 0; } @@ -339,24 +374,23 @@ eepro_probe(struct device *dev) 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)) { @@ -372,44 +406,54 @@ int eepro_probe1(struct device *dev, short ioaddr) /* 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; @@ -419,6 +463,16 @@ int eepro_probe1(struct device *dev, short ioaddr) 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; @@ -432,7 +486,7 @@ int eepro_probe1(struct device *dev, short ioaddr) } } 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 */ @@ -486,9 +540,12 @@ int eepro_probe1(struct device *dev, short ioaddr) */ 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 */ @@ -496,32 +553,28 @@ static int eepro_grab_irq(struct device *dev) /* 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); } @@ -532,7 +585,6 @@ static int eepro_grab_irq(struct device *dev) /* 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. */ @@ -554,10 +606,27 @@ eepro_open(struct device *dev) 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 */ @@ -571,15 +640,12 @@ eepro_open(struct device *dev) 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++) @@ -588,19 +654,31 @@ eepro_open(struct device *dev) 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); @@ -610,25 +688,26 @@ eepro_open(struct device *dev) /* 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"); @@ -639,45 +718,55 @@ eepro_open(struct device *dev) 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; } @@ -694,64 +783,68 @@ eepro_send_packet(struct sk_buff *skb, struct device *dev) 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) { @@ -765,38 +858,35 @@ 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"); @@ -813,41 +903,39 @@ eepro_close(struct device *dev) 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; } @@ -857,12 +945,12 @@ static struct enet_statistics * 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) { @@ -870,7 +958,7 @@ 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) { /* @@ -880,7 +968,6 @@ set_multicast_list(struct device *dev) * 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); @@ -889,6 +976,7 @@ set_multicast_list(struct device *dev) 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 */ @@ -898,6 +986,7 @@ set_multicast_list(struct device *dev) 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; @@ -907,7 +996,6 @@ set_multicast_list(struct device *dev) 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); @@ -919,6 +1007,7 @@ set_multicast_list(struct device *dev) 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; @@ -927,15 +1016,17 @@ set_multicast_list(struct device *dev) 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 @@ -950,15 +1041,17 @@ set_multicast_list(struct device *dev) 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); @@ -970,7 +1063,7 @@ set_multicast_list(struct device *dev) } } } while (++boguscount < 100); - + /* Re-enable RX and TX interrupts */ outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); @@ -980,8 +1073,8 @@ set_multicast_list(struct device *dev) /* 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) @@ -1014,7 +1107,6 @@ read_eeprom(int ioaddr, int location) 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); @@ -1035,47 +1127,47 @@ hardware_send_packet(struct device *dev, void *buf, short length) 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); } @@ -1084,19 +1176,20 @@ hardware_send_packet(struct device *dev, void *buf, short length) 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); @@ -1105,34 +1198,36 @@ hardware_send_packet(struct device *dev, void *buf, short length) 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"); } @@ -1151,68 +1246,78 @@ eepro_rx(struct device *dev) /* 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"); } @@ -1226,17 +1331,17 @@ eepro_transmit_interrupt(struct device *dev) 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 { @@ -1246,41 +1351,45 @@ eepro_transmit_interrupt(struct device *dev) 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; } @@ -1288,6 +1397,7 @@ void cleanup_module(void) { unregister_netdev(&dev_eepro); + kfree_s(dev_eepro.priv,sizeof(struct eepro_local)); dev_eepro.priv=NULL; diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index 56d527a2516f..369350e670dc 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -205,14 +205,30 @@ void ext2_free_inode (struct inode * inode) 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) { @@ -249,8 +265,6 @@ void ext2_free_inode (struct inode * inode) 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); diff --git a/include/asm-i386/irq.h b/include/asm-i386/irq.h index 1190e2009ab2..ea31d746d340 100644 --- a/include/asm-i386/irq.h +++ b/include/asm-i386/irq.h @@ -162,6 +162,8 @@ extern void enable_irq(unsigned int); "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 \ @@ -190,7 +192,10 @@ extern void enable_irq(unsigned int); "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" \ diff --git a/include/linux/ip.h b/include/linux/ip.h index 74d0fa81a6bf..6bbe740a011c 100644 --- a/include/linux/ip.h +++ b/include/linux/ip.h @@ -65,7 +65,7 @@ struct route { #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 */ diff --git a/mm/swapfile.c b/mm/swapfile.c index f7eda6c4d236..96d260394d08 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -5,6 +5,7 @@ * Swap reorganised 29.12.95, Stephen Tweedie */ +#include #include #include #include diff --git a/net/bridge/br.c b/net/bridge/br.c index 64dab8cf9310..6df6e677c14c 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -921,7 +921,7 @@ unsigned long flags; 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); } @@ -975,7 +975,7 @@ unsigned long flags; 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); } diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 9fea00c8a562..7e9ca4a05ae2 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -251,14 +251,6 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) 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 @@ -294,6 +286,24 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) */ 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 alias device, if any. diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 2bfcda94b8d5..04e8224ab098 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -237,7 +237,7 @@ static struct sock *nr_find_socket(unsigned char index, unsigned char id) /* * 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; @@ -246,7 +246,7 @@ static struct sock *nr_find_peer(unsigned char index, unsigned char id) 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; } @@ -936,10 +936,10 @@ int nr_rx_frame(struct sk_buff *skb, struct device *dev) 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); } diff --git a/net/netrom/nr_loopback.c b/net/netrom/nr_loopback.c index bb2c0c816ba6..0edbeed4e3d1 100644 --- a/net/netrom/nr_loopback.c +++ b/net/netrom/nr_loopback.c @@ -11,6 +11,8 @@ * * History * NET/ROM 006 Tomi(OH2BNS) Created this file. + * Changed the way the loopback + * queue is consumed. * */ @@ -53,15 +55,16 @@ int nr_loopback_queue(struct sk_buff *skb) { 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; } @@ -85,16 +88,16 @@ static void nr_loopback_timer(unsigned long param) 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(); } } diff --git a/scripts/lxdialog/dialog.h b/scripts/lxdialog/dialog.h index 3be5feb21a02..0e30d00d0b25 100644 --- a/scripts/lxdialog/dialog.h +++ b/scripts/lxdialog/dialog.h @@ -28,6 +28,24 @@ #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 diff --git a/scripts/lxdialog/lxdialog.c b/scripts/lxdialog/lxdialog.c index fb150f7f6d6f..f84ebf527b84 100644 --- a/scripts/lxdialog/lxdialog.c +++ b/scripts/lxdialog/lxdialog.c @@ -63,6 +63,9 @@ main (int argc, const char * const * argv) (void) setlocale (LC_ALL, ""); #endif +#ifdef TRACE + trace(TRACE_CALLS|TRACE_UPDATE); +#endif if (argc < 2) { Usage (argv[0]); exit (-1); diff --git a/scripts/lxdialog/menubox.c b/scripts/lxdialog/menubox.c index ad4380870380..d717bf90af6e 100644 --- a/scripts/lxdialog/menubox.c +++ b/scripts/lxdialog/menubox.c @@ -39,8 +39,12 @@ print_item (WINDOW * win, const char *item, int choice, int selected, int hotkey /* 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) { @@ -141,6 +145,7 @@ dialog_menu (const char *title, const char *prompt, int height, int width, 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) { diff --git a/scripts/lxdialog/textbox.c b/scripts/lxdialog/textbox.c index df50f2c54da4..5127e5f2c017 100644 --- a/scripts/lxdialog/textbox.c +++ b/scripts/lxdialog/textbox.c @@ -90,6 +90,8 @@ dialog_textbox (const char *title, const char *file, int height, int width) /* 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); @@ -101,6 +103,7 @@ dialog_textbox (const char *title, const char *file, int height, int width) 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) { @@ -459,8 +462,12 @@ print_line (WINDOW * win, int row, int width) 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 } /* @@ -530,6 +537,7 @@ print_position (WINDOW * win, int height, int width) 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); -- 2.39.5