S: Cliffwood, New Jersey 07721
S: USA
+N: Andrew Stanley-Jones
+E: asj@lanmedia.com
+D: LanMedia Corp. Device WAN card device driver
+S: #102, 686 W. Maude Ave
+S: Sunyvale, CA 94086
+S: USA
+
N: Henrik Storner
E: storner@image.dk
W: http://www.image.dk/~storner/
The module will be called cosa.o. For general information about
modules read Documentation/modules.txt.
+Lan Media sync serial boards support
+CONFIG_LANMEDIA
+ This is a driver for the following Lan Media family of serial boards.
+
+ LMC 1000 board allows you to connect synchronous serial devices (for
+ example base-band modems, or any other device with the X.21, V.24,
+ V.35 or V.36 interface) to your Linux box.
+
+ LMC 1200 with on board DSU board allows you to connect your Linux
+ box dirrectly to a T1 or E1 circuit.
+
+ LMC 5200 board provides a HSSI interface capable of runnig up to
+ 52 mbits per second.
+
+ LMC 5245 board connects directly to a T3 circuit saving the
+ additional external hardware.
+
+ To change setting such as syncPPP vs cisco HDLC or clock source you
+ will need lmcctl. It it available at ftp.lanmedia.com.
+
+ The driver will be compiled as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called lmc.o. For general information about
+ modules read Documentation/modules.txt.
+
Red Creek Hardware VPN (EXPERIMENTAL)
CONFIG_RCPCI
This is a driver for hardware which provides a Virtual Private
If you have trouble with some ugly exchanges try to select this
option.
+Disable keypad protocol option
+CONFIG_HISAX_NO_KEYPAD
+ If you like to send special dialstrings including * or # without
+ using the keypad protocol, select this option.
+
HiSax Support for german 1TR6
CONFIG_HISAX_1TR6
Enable this if you have a old german 1TR6 line.
-HiSax Support for Teles 16.0/8.0
+Teles 16.0/8.0
CONFIG_HISAX_16_0
This enables HiSax support for the Teles ISDN-cards S0-16.0, S0-8
and many compatibles.
different cards, a different D-channel protocol, or non-standard
IRQ/port/shmem settings.
-HiSax Support for Teles 16.3 or PNP or PCMCIA
+Teles 16.3 or PNP or PCMCIA
CONFIG_HISAX_16_3
This enables HiSax support for the Teles ISDN-cards S0-16.3 the
Teles/Creatix PnP and the Teles PCMCIA.
different cards, a different D-channel protocol, or non-standard
IRQ/port settings.
-HiSax Support for Teles PCI
+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
+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)
+AVM A1 (Fritz)
CONFIG_HISAX_AVM_A1
This enables HiSax support for the AVM A1 (aka "Fritz").
different cards, a different D-channel protocol, or non-standard
IRQ/port settings.
-HiSax Support for AVM PnP/PCI (Fritz!PNP/PCI)
+AVM PnP/PCI (Fritz!PNP/PCI)
CONFIG_HISAX_FRITZPCI
This enables HiSax support for the AVM "Fritz!PnP" and "Fritz!PCI".
See Documentation/isdn/README.HiSax on how to configure it.
-HiSax Support for AVM A1 PCMCIA (Fritz)
+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 cards
+Elsa cards
CONFIG_HISAX_ELSA
This enables HiSax support for the Elsa Mircolink ISA cards, for the
Elsa Quickstep series cards and Elsa PCMCIA.
different cards, a different D-channel protocol, or non-standard
IRQ/port settings.
-HiSax Support for ITK ix1-micro Revision 2
+ITK ix1-micro Revision 2
CONFIG_HISAX_IX1MICROR2
This enables HiSax support for the ITK ix1-micro Revision 2 card.
different cards, a different D-channel protocol, or non-standard
IRQ/port settings.
-HiSax Support for Eicon.Diehl Diva cards
+Eicon.Diehl Diva cards
CONFIG_HISAX_DIEHLDIVA
This enables HiSax support for the Eicon.Diehl Diva none PRO
versions passive ISDN cards.
different cards, a different D-channel protocol, or non-standard
IRQ/port settings.
-HiSax Support for ASUSCOM cards
+ASUSCOM ISA cards
CONFIG_HISAX_ASUSCOM
This enables HiSax support for the AsusCom and their OEM versions
- passive ISDN cards.
+ passive ISDN ISA 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 settings.
-HiSax Support for TELEINT cards
+TELEINT cards
CONFIG_HISAX_TELEINT
This enables HiSax support for the TELEINT SA1 semiactiv ISDN card.
different cards, a different D-channel protocol, or non-standard
IRQ/port settings.
-HiSax Support for HFC-S based cards
+HFC-S based cards
CONFIG_HISAX_HFCS
This enables HiSax support for the HFC-S 2BDS0 based cards, like
teles 16.3c.
different cards, a different D-channel protocol, or non-standard
IRQ/port settings.
-HiSax Support for Sedlbauer cards
+Sedlbauer cards
CONFIG_HISAX_SEDLBAUER
This enables HiSax support for the Sedlbauer passive ISDN cards.
different cards, a different D-channel protocol, or non-standard
IRQ/port settings.
-HiSax Support for USR Sportster internal TA
+USR Sportster internal TA
CONFIG_HISAX_SPORTSTER
This enables HiSax support for the USR Sportster internal TA card.
See Documentation/isdn/README.HiSax on how to configure it using a
different D-channel protocol, or non-standard IRQ/port settings.
-HiSax Support for MIC card
+MIC card
CONFIG_HISAX_MIC
This enables HiSax support for the ITH MIC card.
See Documentation/isdn/README.HiSax on how to configure it using a
different D-channel protocol, or non-standard IRQ/port settings.
-HiSax Support for NETjet card
+NETjet card
CONFIG_HISAX_NETJET
This enables HiSax support for the NetJet from Traverse
Technologies.
See Documentation/isdn/README.HiSax on how to configure it using a
different D-channel protocol, or non-standard IRQ/port settings.
-HiSax Support for Niccy PnP/PCI card
+Niccy PnP/PCI card
CONFIG_HISAX_NICCY
This enables HiSax support for the Dr. Neuhaus Niccy PnP or PCI.
See Documentation/isdn/README.HiSax on how to configure it using a
different D-channel protocol, or non-standard IRQ/port settings.
-HiSax Support for Siemens I-Surf card
+Siemens I-Surf card
CONFIG_HISAX_ISURF
This enables HiSax support for the Siemens I-Talk/I-Surf card with
ISAR chip.
See Documentation/isdn/README.HiSax on how to configure it using a
different D-channel protocol, or non-standard IRQ/port settings.
-HiSax Support for HST Saphir card
+HST Saphir card
CONFIG_HISAX_HSTSAPHIR
This enables HiSax support for the HST Saphir card.
See Documentation/isdn/README.HiSax on how to configure it using a
different D-channel protocol, or non-standard IRQ/port settings.
-HiSax Support for Telekom A4T card
+Telekom A4T card
CONFIG_HISAX_BKM_A4T
This enables HiSax support for the Telekom A4T card.
See Documentation/isdn/README.HiSax on how to configure it using a
different D-channel protocol, or non-standard IRQ/port settings.
-HiSax Support for Scitel Quadro card
+Scitel Quadro card
CONFIG_HISAX_SCT_QUADRO
This enables HiSax support for the Scitel Quadro card.
See Documentation/isdn/README.HiSax on how to configure it using a
different D-channel protocol, or non-standard IRQ/port settings.
-HiSax Support for Gazel cards
+Gazel cards
CONFIG_HISAX_GAZEL
This enables HiSax support for the Gazel cards.
See Documentation/isdn/README.HiSax on how to configure it using a
different D-channel protocol, or non-standard IRQ/port settings.
-HiSax Support for HFC PCI-Bus cards
+HFC PCI-Bus cards
CONFIG_HISAX_HFC_PCI
This enables HiSax support for the HFC-S PCI 2BDS0 based cards.
For more informations see under Documentation/isdn/README.hfc-pci.
-HiSax Support for Winbond W6692 based cards
+Winbond W6692 based cards
CONFIG_HISAX_W6692
This enables HiSax support for Winbond W6692 based PCI ISDN cards.
See Documentation/isdn/README.HiSax on how to configure it using a
different D-channel protocol, or non-standard IRQ/port settings.
-HiSax Support for Am7930 (EXPERIMENTAL)
+HFC-S+, HFC-SP, HFC-PCMCIA cards (EXPERIMENTAL)
+CONFIG_HISAX_HFC_SX
+ This enables HiSax support for the HFC-S+, HFC-SP and HFC-PCMCIA cards.
+ This code is not finished yet.
+
+Am7930 (EXPERIMENTAL)
CONFIG_HISAX_AMD7930
This enables HiSax support for the AMD7930 chips on some SPARCs.
This code is not finished yet.
Choose Y here if you have this FM radio card, and then fill in the
port address below.
- If you have GemTeks combined (PnP) sound- and radio card you must use
- this driver as a module and setup the card with isapnptools. You must
- also pass the module a suitable io parameter, 0x248 has been reported
- to be used by these cards.
-
In order to control your radio card, you will need to use programs
that are compatible with the Video for Linux API. Information on
this API and pointers to "v4l" programs may be found on the WWW at
Choose Y here if you have this FM radio card, and then fill in the
port address below.
+ If you have GemTeks combined (PnP) sound- and radio card you might want
+ to use this driver as a module and setup the card with isapnptools. You
+ must also pass the module a suitable io parameter. If you have trouble
+ getting the driver to work with the card as a module, please try building
+ it into the kernel by answering Y.
+
In order to control your radio card, you will need to use programs
that are compatible with the Video for Linux API. Information on
this API and pointers to "v4l" programs may be found on the WWW at
GemTek i/o port
CONFIG_RADIO_GEMTEK_PORT
- Enter either 0x20c, 0x30c, 0x24c or 0x34c here. The card default is
- 0x34c, if you haven't changed the jumper setting on the card.
+ Enter either 0x20c, 0x30c, 0x24c or 0x34c here. 0x20c and 0x248 have
+ been reported to work with the combined sound/radio card. The card
+ default is 0x34c, if you haven't changed the jumper setting on the card.
Trust FM Radio Card
CONFIG_RADIO_TRUST
Gazel ISDN cards
HFC-PCI based cards
Winbond W6692 based cards
+HFC-S+, HFC-SP/PCMCIA cards
Note: PCF, PCF-Pro: up to now, only the ISDN part is supported
PCC-8: not tested yet
Teles PCI is EXPERIMENTAL
Teles S0Box is EXPERIMENTAL
Eicon.Diehl Diva U interface not tested
+ HFC-S+, HFC-SP/PCMCIA are experimental
If you know other passive cards with the Siemens chipset, please let me know.
To use the PNP cards you need the isapnptools.
34 Gazel ISDN cards (PCI) none
35 HFC 2BDS0 PCI none
36 W6692 based PCI cards none
+ 37 HFC 2BDS0 S+, SP/PCMCIA irq,io (pcmcia must be set with cardmgr)
At the moment IRQ sharing is only possible with PCI cards. Please make sure
34 Gazel ISDN cards (PCI) no parameter
35 HFC 2BDS0 PCI no parameter
36 W6692 based PCI cards none
+ 37 HFC 2BDS0 S+,SP/PCMCIA pa=irq, pb=io
Running the driver
------------------
--- /dev/null
+Installation:
+
+Apply patch. (if your reading this in
+/usr/src/linux/Documentation/network/bonding.txt, then it's already
+applied.)
+
+Run make menuconfig/xconfig/config, and select 'bonding device' in
+network devices.
+
+Build the new kernel/modules.
+
+Get update ifenslave.c (included in tar file.) (location to be determined.)
+
+install ifenslave.c; do:
+ gcc -O2 -o ifenslave ifenslave.c
+ cp ifenslave /sbin/ifenslave
+
+Modify /etc/conf.modules by adding the line:
+ alias bond0 bonding
+
+If you running a RH5.0 or newer distribution, do:
+
+cd /etc/sysconfig/network-scripts
+cp ifcfg-eth0 ifcfg-bond0
+edit ifcfg-bond0, and make it look the following:
+
+DEVICE=bond0
+USERCTL=no
+ONBOOT=yes
+BOOTPROTO=none
+BROADCAST=XXX.XXX.XXX.255
+NETWORK=XXX.XXX.XXX.0
+NETMASK=255.255.255.0
+IPADDR=XXX.XXX.XXX.XXX
+
+(put the approiate values for you network in where the XXX's are at.)
+
+Then, edit ifcfg-eth0/ifcfg-eth1 (and all the other slave devices), and make them
+look like this:
+
+DEVICE=eth0
+USERCTL=no
+ONBOOT=yes
+MASTER=bond0
+SLAVE=yes
+BOOTPROTO=none
+
+Reboot, and the network should come up bonded together.
+
+For other distributions, you need to do something like:
+
+/sbin/ifconfig bond0 addresss netmask xxx.xxx.xxx.xxx broadcast xxx.xxx.xxx.xxx up
+/sbin/ifenslave bond0 eth0
+/sbin/ifenslave bond0 eth1
+
+When properly configured, it will look this:
+
+[root]# /sbin/ifconfig
+bond0 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4
+ inet addr:XXX.XXX.XXX.YYY Bcast:XXX.XXX.XXX.255 Mask:255.255.252.0
+ UP BROADCAST RUNNING MASTER MULTICAST MTU:1500 Metric:1
+ RX packets:7224794 errors:0 dropped:0 overruns:0 frame:0
+ TX packets:3286647 errors:1 dropped:0 overruns:1 carrier:0
+ collisions:0 txqueuelen:0
+
+eth0 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4
+ inet addr:XXX.XXX.XXX.YYY Bcast:XXX.XXX.XXX.255 Mask:255.255.252.0
+ UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1
+ RX packets:3573025 errors:0 dropped:0 overruns:0 frame:0
+ TX packets:1643167 errors:1 dropped:0 overruns:1 carrier:0
+ collisions:0 txqueuelen:100
+ Interrupt:10 Base address:0x1080
+
+eth1 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4
+ inet addr:XXX.XXX.XXX.YYY Bcast:XXX.XXX.XXX.255 Mask:255.255.252.0
+ UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1
+ RX packets:3651769 errors:0 dropped:0 overruns:0 frame:0
+ TX packets:1643480 errors:0 dropped:0 overruns:0 carrier:0
+ collisions:0 txqueuelen:100
+ Interrupt:9 Base address:0x1400
+
+Questions:
+
+1. Is it SMP safe?
+
+ Yes. The old 2.0.xx channel bonding patch wasn't SMP safe.
+This one was designed from the start to be SMP safe.
+
+2. What type of cards can it work with it?
+
+ Any Ethernet type cards (ie, you can even mix cards - a tulip
+and a 3com 3c905, for example). You can even bond together Gigabit
+Ethernet cards!
+
+3. How many bond devices can I have?
+
+ Just one at this time.
+
+4. How many slaves can a bond device have?
+
+ Limited by the number of cards you can place in your system.
+
+5. What happens when a slave dies?
+
+ Currently, the ethernet drivers don't really handle this
+situation very well. The tulip driver never stalls; it just starts to
+throw packets away!
+
+6. If this was fixed, can bonding be used for High Availability?
+
+ Yes!
+
+7. Which switches/systems does it work with?
+
+ Cisco 5500 series (look for EtherChannel support).
+ SunTrunking software.
+
+8. Where does the bond0 device get it's mac address from?
+
+ It's taken from the first slave device. If you remove that
+first slave device, the MAC address continues to be associated with
+it. If you wish to remove that MAC address, you have to ifconfig
+bond0 down, and then modprobe -r bonding. If you wish, you can also
+assign a MAC address when you ifconfig the bond0 device.
+
+9. Which transmit policy is used?
+
+ Round robin, based on order of enslaving.
\ No newline at end of file
W: http://csua.berkeley.edu/~gam3/knfsd
S: Maintained
+LANMEDIA WAN CARD DRIVER
+P: Andrew Stanley-Jones
+M: asj@lanmedia.com
+W: http://www.lanmedia.com/
+S: Supported
+
LAPB module
P: Henner Eisen
M: eis@baty.hanse.de
VERSION = 2
PATCHLEVEL = 2
SUBLEVEL = 15
-EXTRAVERSION = pre4
+EXTRAVERSION = pre5
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
else
prom_print(RELOC("...failed\n"));
}
+#endif /* CONFIG_SMP */
/* If OpenFirmware version >= 3, then use quiesce call */
if (RELOC(prom_version) >= 3) {
phys = offset + KERNELBASE;
}
-#endif
return phys;
}
-/* $Id: sys32.S,v 1.8 1998/10/28 08:10:37 jj Exp $
+/* $Id: sys32.S,v 1.8.2.1 2000/01/24 11:36:55 jj Exp $
* sys32.S: I-cache tricks for 32-bit compatability layer simple
* conversions.
*
.align 32
.globl sys32_lseek
- .globl sys32_chmod, sys32_chown, sys32_lchown, sys32_mknod
+ .globl sys32_chmod, sys32_mknod
sys32_lseek:
sra %o1, 0, %o1
sethi %hi(sys_lseek), %g1
orcc %g2, %lo(0xffff), %g2
jmpl %g1 + %lo(sys_chmod), %g0
and %o1, %g2, %o1
-sys32_chown:
- sethi %hi(0xffff), %g2
- sethi %hi(sys_chown), %g1
- orcc %g2, %lo(0xffff), %g2
- and %o1, %g2, %o1
- jmpl %g1 + %lo(sys_chown), %g0
- and %o2, %g2, %o2
-sys32_lchown:
- sethi %hi(0xffff), %g2
- sethi %hi(sys_lchown), %g1
- orcc %g2, %lo(0xffff), %g2
- and %o1, %g2, %o1
- jmpl %g1 + %lo(sys_lchown), %g0
- and %o2, %g2, %o2
sys32_mknod:
sethi %hi(0xffff), %g2
sethi %hi(sys_mknod), %g1
-/* $Id: sys_sparc32.c,v 1.107.2.5 1999/11/12 11:17:47 davem Exp $
+/* $Id: sys_sparc32.c,v 1.107.2.7 2000/01/24 11:36:50 jj Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
return ret;
}
+#define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid)
+#define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid)
+
extern asmlinkage int sys_setreuid(uid_t ruid, uid_t euid);
asmlinkage int sys32_setreuid(__kernel_uid_t32 ruid, __kernel_uid_t32 euid)
{
- uid_t sruid, seuid;
-
- sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid);
- seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid);
- return sys_setreuid(sruid, seuid);
+ return sys_setreuid(low2highuid(ruid), low2highuid(euid));
}
extern asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid);
__kernel_uid_t32 euid,
__kernel_uid_t32 suid)
{
- uid_t sruid, seuid, ssuid;
-
- sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid);
- seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid);
- ssuid = (suid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)suid);
- return sys_setresuid(sruid, seuid, ssuid);
+ return sys_setresuid(low2highuid(ruid), low2highuid(euid), low2highuid(suid));
}
extern asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
asmlinkage int sys32_setregid(__kernel_gid_t32 rgid, __kernel_gid_t32 egid)
{
- gid_t srgid, segid;
-
- srgid = (rgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)rgid);
- segid = (egid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)egid);
- return sys_setregid(srgid, segid);
+ return sys_setregid(low2highgid(rgid), low2highgid(egid));
}
extern asmlinkage int sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid);
__kernel_gid_t32 egid,
__kernel_gid_t32 sgid)
{
- gid_t srgid, segid, ssgid;
-
- srgid = (rgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)rgid);
- segid = (egid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)egid);
- ssgid = (sgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)sgid);
- return sys_setresgid(srgid, segid, ssgid);
+ return sys_setresgid(low2highgid(rgid), low2highgid(egid), low2highgid(sgid));
}
extern asmlinkage int sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
return ret;
}
+extern asmlinkage long sys_chown(const char *, uid_t,gid_t);
+extern asmlinkage long sys_lchown(const char *, uid_t,gid_t);
+extern asmlinkage long sys_fchown(unsigned int, uid_t,gid_t);
+
+asmlinkage long sys32_chown16(const char * filename, u16 user, u16 group)
+{
+ return sys_chown(filename, low2highuid(user), low2highgid(group));
+}
+
+asmlinkage long sys32_lchown16(const char * filename, u16 user, u16 group)
+{
+ return sys_lchown(filename, low2highuid(user), low2highgid(group));
+}
+
+asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group)
+{
+ return sys_fchown(fd, low2highuid(user), low2highgid(group));
+}
+
struct tms32 {
__kernel_clock_t32 tms_utime;
__kernel_clock_t32 tms_stime;
-/* $Id: systbls.S,v 1.53.2.1 1999/09/22 11:37:39 jj Exp $
+/* $Id: systbls.S,v 1.53.2.3 2000/01/24 22:14:40 davem Exp $
* systbls.S: System call entry point tables for OS compatibility.
* The native Linux system call table lives here also.
*
sys_call_table32:
/*0*/ .word sys_nis_syscall, sparc_exit, sys_fork, sys_read, sys_write
/*5*/ .word sys_open, sys_close, sys32_wait4, sys_creat, sys_link
-/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys32_chown, sys32_mknod
-/*15*/ .word sys32_chmod, sys32_lchown, sparc_brk, sys_perfctr, sys32_lseek
+/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys32_chown16, sys32_mknod
+/*15*/ .word sys32_chmod, sys32_lchown16, sparc_brk, sys_perfctr, sys32_lseek
/*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid
/*25*/ .word sys_time, sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause
/*30*/ .word sys32_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice
.word sys32_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_nis_syscall, sys_nis_syscall
/*110*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
.word sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
-/*120*/ .word sys32_readv, sys32_writev, sys32_settimeofday, sys_fchown, sys_fchmod
+/*120*/ .word sys32_readv, sys32_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod
.word sys_nis_syscall, sys32_setreuid, sys32_setregid, sys_rename, sys_truncate
/*130*/ .word sys_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
.word sys_nis_syscall, sys_mkdir, sys_rmdir, sys32_utimes, sys_nis_syscall
.word sys_close, sunos_wait4, sys_creat
.word sys_link, sys_unlink, sunos_execv
.word sys_chdir, sunos_nosys, sys32_mknod
- .word sys32_chmod, sys32_lchown, sunos_brk
+ .word sys32_chmod, sys32_lchown16, sunos_brk
.word sunos_nosys, sys32_lseek, sunos_getpid
.word sunos_nosys, sunos_nosys, sunos_nosys
.word sunos_getuid, sunos_nosys, sys_ptrace
.word sys32_sigstack, sys32_recvmsg, sys32_sendmsg
.word sunos_nosys, sys32_gettimeofday, sys32_getrusage
.word sunos_getsockopt, sunos_nosys, sunos_readv
- .word sunos_writev, sys32_settimeofday, sys_fchown
+ .word sunos_writev, sys32_settimeofday, sys32_fchown16
.word sys_fchmod, sys32_recvfrom, sys32_setreuid
.word sys_setregid, sys_rename, sys_truncate
.word sys_ftruncate, sys_flock, sunos_nosys
return cdrom_lockdoor (drive, lock, NULL);
}
+/*
+ * the buffer struct used by ide_cdrom_get_capabilities()
+ */
+struct get_capabilities_buf {
+ char pad[8];
+ struct atapi_capabilities_page cap; /* this is 4 bytes short of ATAPI standard */
+ char extra_cap[4]; /* Acer 50X needs the regulation size buffer */
+};
+
+static
+int ide_cdrom_get_capabilities (ide_drive_t *drive, struct get_capabilities_buf *buf)
+{
+ int stat, attempts = 3, buflen = sizeof(*buf);
+
+ /*
+ * Most drives don't care about the buffer size; they return as much info as there's room for.
+ * But some older drives (?) had trouble with the standard size, preferring 4 bytes less.
+ * And the modern Acer 50X rejects anything smaller than the standard size.
+ */
+ if (!(drive->id && !strcmp(drive->id->model,"ATAPI CD ROM DRIVE 50X MAX")))
+ buflen -= sizeof(buf->extra_cap); /* for all drives except Acer 50X */
+
+ do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
+ stat = cdrom_mode_sense (drive, PAGE_CAPABILITIES, 0, (char *)buf, buflen, NULL);
+ if (stat == 0) {
+ /*
+ * The ACER/AOpen 24X cdrom has the speed fields byte-swapped from the standard.
+ */
+ if (!(drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4))) {
+ buf->cap.curspeed = ntohs(buf->cap.curspeed);
+ buf->cap.maxspeed = ntohs(buf->cap.maxspeed);
+ }
+ CDROM_STATE_FLAGS (drive)->current_speed = (((unsigned int)buf->cap.curspeed) + (176/2)) / 176;
+ CDROM_CONFIG_FLAGS(drive)->max_speed = (((unsigned int)buf->cap.maxspeed) + (176/2)) / 176;
+ return 0;
+ }
+ } while (--attempts);
+ return stat;
+}
+
static
int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
{
- int stat, attempts = 3;
- struct {
- char pad[8];
- struct atapi_capabilities_page cap;
- } buf;
+ int stat;
+ struct get_capabilities_buf buf;
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
struct atapi_request_sense reqbuf;
stat=cdrom_select_speed (drive, speed, &reqbuf);
return stat;
/* Now with that done, update the speed fields */
- do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
- if (attempts-- <= 0)
- return 0;
- stat = cdrom_mode_sense (drive, PAGE_CAPABILITIES, 0,
- (char *)&buf, sizeof (buf), NULL);
- } while (stat);
-
- /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
- if (drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) {
- CDROM_STATE_FLAGS (drive)->current_speed =
- (((unsigned int)buf.cap.curspeed) + (176/2)) / 176;
- CDROM_CONFIG_FLAGS (drive)->max_speed =
- (((unsigned int)buf.cap.maxspeed) + (176/2)) / 176;
- } else {
- CDROM_STATE_FLAGS (drive)->current_speed =
- (ntohs(buf.cap.curspeed) + (176/2)) / 176;
- CDROM_CONFIG_FLAGS (drive)->max_speed =
- (ntohs(buf.cap.maxspeed) + (176/2)) / 176;
- }
+ if (ide_cdrom_get_capabilities(drive,&buf))
+ return 0;
+
cdi->speed = CDROM_STATE_FLAGS (drive)->current_speed;
return 0;
}
static
int ide_cdrom_probe_capabilities (ide_drive_t *drive)
{
- int stat, nslots = 0, attempts = 3;
- struct {
- char pad[8];
- struct atapi_capabilities_page cap;
- } buf;
+ int stat, nslots = 0;
+ struct get_capabilities_buf buf;
if (CDROM_CONFIG_FLAGS (drive)->nec260) {
CDROM_CONFIG_FLAGS (drive)->no_eject = 0;
return nslots;
}
- do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
- if (attempts-- <= 0)
- return 0;
- stat = cdrom_mode_sense (drive, PAGE_CAPABILITIES, 0,
- (char *)&buf, sizeof (buf), NULL);
- } while (stat);
-
+ if (ide_cdrom_get_capabilities(drive,&buf))
+ return 0;
if (buf.cap.lock == 0)
CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;
if (buf.cap.eject)
}
}
- /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
- if (drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) {
- CDROM_STATE_FLAGS (drive)->current_speed =
- (((unsigned int)buf.cap.curspeed) + (176/2)) / 176;
- CDROM_CONFIG_FLAGS (drive)->max_speed =
- (((unsigned int)buf.cap.maxspeed) + (176/2)) / 176;
- } else {
- CDROM_STATE_FLAGS (drive)->current_speed =
- (ntohs(buf.cap.curspeed) + (176/2)) / 176;
- CDROM_CONFIG_FLAGS (drive)->max_speed =
- (ntohs(buf.cap.maxspeed) + (176/2)) / 176;
- }
-
printk ("%s: ATAPI %dX %s",
drive->name, CDROM_CONFIG_FLAGS (drive)->max_speed,
(CDROM_CONFIG_FLAGS (drive)->dvd) ? "DVD-ROM" : "CD-ROM");
drive->name, drive->present, drive->media,
(cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI");
#endif
+ delay_50ms(); /* needed for some systems (e.g. crw9624 as drive0 with disk as slave) */
SELECT_DRIVE(hwif,drive);
delay_50ms();
if (IN_BYTE(IDE_SELECT_REG) != drive->select.all && !drive->present) {
dep_tristate 'Miro PCM20 Radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV
dep_tristate 'GemTek Radio Card support' CONFIG_RADIO_GEMTEK $CONFIG_VIDEO_DEV
if [ "$CONFIG_RADIO_GEMTEK" = "y" ]; then
- hex ' GemTek i/o port (0x20c, 0x30c, 0x24c or 0x34c)' CONFIG_RADIO_GEMTEK_PORT 34c
+ hex ' GemTek i/o port (0x20c, 0x24c, 0x248, 0x30c, or 0x34c)' CONFIG_RADIO_GEMTEK_PORT 34c
fi
dep_tristate 'Trust FM Radio' CONFIG_RADIO_TRUST $CONFIG_VIDEO_DEV
if [ "$CONFIG_RADIO_TRUST" = "y" ]; then
nr -= num;
if (nr == 0)
break;
+ current->state = TASK_RUNNING;
get_user(c, b);
+ current->state = TASK_INTERRUPTIBLE;
if (opost(c, tty) < 0)
break;
b++; nr--;
if (tty->driver.flush_chars)
tty->driver.flush_chars(tty);
} else {
+ current->state = TASK_RUNNING;
c = tty->driver.write(tty, 1, b, nr);
+ current->state = TASK_INTERRUPTIBLE;
if (c < 0) {
retval = c;
goto break_out;
MODULE_AUTHOR("Jonas Munsin");
MODULE_DESCRIPTION("A driver for the GemTek Radio Card");
MODULE_PARM(io, "i");
-MODULE_PARM_DESC(io, "I/O address of the GemTek card (0x20c, 0x30c, 0x24c or 0x34c (or 0x248 for the combined sound/radiocard))");
+MODULE_PARM_DESC(io, "I/O address of the GemTek card (0x20c, 0x30c, 0x24c or 0x34c (0x20c or 0x248 have been reported to work for the combined sound/radiocard)).");
EXPORT_NO_SYMBOLS;
{
if(io==-1)
{
- printk(KERN_ERR "You must set an I/O address with io=0x20c, io=0x30c, io=0x24c or io=0x34c (or io=0x248 for the combined sound/radiocard)\n");
+ printk(KERN_ERR "You must set an I/O address with io=0x20c, io=0x30c, io=0x24c or io=0x34c (io=0x20c or io=0x248 for the combined sound/radiocard)\n");
return -EINVAL;
}
return gemtek_init(NULL);
if [ "$CONFIG_ISDN_AUDIO" != "n" ]; then
bool ' Support AT-Fax Class 2 commands' CONFIG_ISDN_TTY_FAX
fi
-bool ' Support isdn diversion services' CONFIG_ISDN_DIVERSION
if [ "$CONFIG_X25" != "n" ]; then
bool ' X.25 PLP on top of ISDN' CONFIG_ISDN_X25
fi
-dep_tristate ' ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN
-dep_tristate ' isdnloop support' CONFIG_ISDN_DRV_LOOP $CONFIG_ISDN
-dep_tristate ' PCBIT-D support' CONFIG_ISDN_DRV_PCBIT $CONFIG_ISDN
-dep_tristate ' HiSax SiemensChipSet driver support' CONFIG_ISDN_DRV_HISAX $CONFIG_ISDN
+
+mainmenu_option next_comment
+comment 'ISDN feature submodules'
+ dep_tristate 'isdnloop support' CONFIG_ISDN_DRV_LOOP $CONFIG_ISDN
+ bool 'Support isdn diversion services' CONFIG_ISDN_DIVERSION
+endmenu
+
+comment 'low-level hardware drivers'
+
+mainmenu_option next_comment
+comment 'Passive ISDN cards'
+dep_tristate 'HiSax SiemensChipSet driver support' CONFIG_ISDN_DRV_HISAX $CONFIG_ISDN
if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
- bool ' HiSax Support for EURO/DSS1' CONFIG_HISAX_EURO
+ comment ' D-channel protocol features'
+ bool ' HiSax Support for EURO/DSS1' CONFIG_HISAX_EURO
if [ "$CONFIG_HISAX_EURO" != "n" ]; then
- bool ' Support for german chargeinfo' CONFIG_DE_AOC
- bool ' Disable sending complete' CONFIG_HISAX_NO_SENDCOMPLETE
- bool ' Disable sending low layer compatibility' CONFIG_HISAX_NO_LLC
+ bool ' Support for german chargeinfo' CONFIG_DE_AOC
+ bool ' Disable sending complete' CONFIG_HISAX_NO_SENDCOMPLETE
+ bool ' Disable sending low layer compatibility' CONFIG_HISAX_NO_LLC
+ bool ' Disable keypad protocol option' CONFIG_HISAX_NO_KEYPAD
fi
- bool ' HiSax Support for german 1TR6' CONFIG_HISAX_1TR6
- bool ' HiSax Support for Teles 16.0/8.0' CONFIG_HISAX_16_0
- bool ' HiSax Support for Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
- bool ' HiSax Support for Teles PCI' CONFIG_HISAX_TELESPCI
- bool ' HiSax Support for Teles S0Box' CONFIG_HISAX_S0BOX
- bool ' HiSax Support for AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1
- bool ' HiSax Support for AVM PnP/PCI (Fritz!PnP/PCI)' CONFIG_HISAX_FRITZPCI
- bool ' HiSax Support for AVM A1 PCMCIA (Fritz)' CONFIG_HISAX_AVM_A1_PCMCIA
- bool ' HiSax Support for Elsa cards' CONFIG_HISAX_ELSA
- bool ' HiSax Support for ITK ix1-micro Revision 2' CONFIG_HISAX_IX1MICROR2
- bool ' HiSax Support for Eicon.Diehl Diva cards' CONFIG_HISAX_DIEHLDIVA
- bool ' HiSax Support for ASUSCOM cards' CONFIG_HISAX_ASUSCOM
- bool ' HiSax Support for TELEINT cards' CONFIG_HISAX_TELEINT
- bool ' HiSax Support for HFC-S based cards' CONFIG_HISAX_HFCS
- bool ' HiSax Support for Sedlbauer cards' CONFIG_HISAX_SEDLBAUER
- bool ' HiSax Support for USR Sportster internal TA' CONFIG_HISAX_SPORTSTER
- bool ' HiSax Support for MIC card' CONFIG_HISAX_MIC
- bool ' HiSax Support for NETjet card' CONFIG_HISAX_NETJET
- bool ' HiSax Support for Niccy PnP/PCI card' CONFIG_HISAX_NICCY
- bool ' HiSax Support for Siemens I-Surf card' CONFIG_HISAX_ISURF
- bool ' HiSax Support for HST Saphir card' CONFIG_HISAX_HSTSAPHIR
- bool ' HiSax Support for Telekom A4T card' CONFIG_HISAX_BKM_A4T
- bool ' HiSax Support for Scitel Quadro card' CONFIG_HISAX_SCT_QUADRO
- bool ' HiSax Support for Gazel cards' CONFIG_HISAX_GAZEL
- bool ' HiSax Support for HFC PCI-Bus cards' CONFIG_HISAX_HFC_PCI
- bool ' HiSax Support for Winbond W6692 based cards' CONFIG_HISAX_W6692
+ bool ' HiSax Support for german 1TR6' CONFIG_HISAX_1TR6
+ comment ' HiSax supported cards'
+ bool ' Teles 16.0/8.0' CONFIG_HISAX_16_0
+ bool ' Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
+ bool ' Teles PCI' CONFIG_HISAX_TELESPCI
+ bool ' Teles S0Box' CONFIG_HISAX_S0BOX
+ bool ' AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1
+ bool ' AVM PnP/PCI (Fritz!PnP/PCI)' CONFIG_HISAX_FRITZPCI
+ bool ' AVM A1 PCMCIA (Fritz)' CONFIG_HISAX_AVM_A1_PCMCIA
+ bool ' Elsa cards' CONFIG_HISAX_ELSA
+ bool ' ITK ix1-micro Revision 2' CONFIG_HISAX_IX1MICROR2
+ bool ' Eicon.Diehl Diva cards' CONFIG_HISAX_DIEHLDIVA
+ bool ' ASUSCOM ISA cards' CONFIG_HISAX_ASUSCOM
+ bool ' TELEINT cards' CONFIG_HISAX_TELEINT
+ bool ' HFC-S based cards' CONFIG_HISAX_HFCS
+ bool ' Sedlbauer cards' CONFIG_HISAX_SEDLBAUER
+ bool ' USR Sportster internal TA' CONFIG_HISAX_SPORTSTER
+ bool ' MIC card' CONFIG_HISAX_MIC
+ bool ' NETjet card' CONFIG_HISAX_NETJET
+ bool ' Niccy PnP/PCI card' CONFIG_HISAX_NICCY
+ bool ' Siemens I-Surf card' CONFIG_HISAX_ISURF
+ bool ' HST Saphir card' CONFIG_HISAX_HSTSAPHIR
+ bool ' Telekom A4T card' CONFIG_HISAX_BKM_A4T
+ bool ' Scitel Quadro card' CONFIG_HISAX_SCT_QUADRO
+ bool ' Gazel cards' CONFIG_HISAX_GAZEL
+ bool ' HFC PCI-Bus cards' CONFIG_HISAX_HFC_PCI
+ bool ' Winbond W6692 based cards' CONFIG_HISAX_W6692
if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
-# bool ' HiSax Support for TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
+ bool ' HFC-S+, HFC-SP, HFC-PCMCIA cards' CONFIG_HISAX_HFC_SX
+# bool ' TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
- bool ' HiSax Support for Am7930' CONFIG_HISAX_AMD7930
+ bool ' Am7930' CONFIG_HISAX_AMD7930
fi
fi
fi
+endmenu
+
+mainmenu_option next_comment
+comment 'Active ISDN cards'
+dep_tristate 'ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN
+dep_tristate 'PCBIT-D support' CONFIG_ISDN_DRV_PCBIT $CONFIG_ISDN
if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
- dep_tristate ' Spellcaster support (EXPERIMENTAL)' CONFIG_ISDN_DRV_SC $CONFIG_ISDN
- dep_tristate ' IBM Active 2000 support (EXPERIMENTAL)' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN
+ dep_tristate 'Spellcaster support (EXPERIMENTAL)' CONFIG_ISDN_DRV_SC $CONFIG_ISDN
+ dep_tristate 'IBM Active 2000 support (EXPERIMENTAL)' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN
fi
-dep_tristate ' Eicon.Diehl active card support' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN
+dep_tristate 'Eicon active card support' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN
if [ "$CONFIG_ISDN_DRV_EICON" != "n" ]; then
- bool ' Eicon S,SX,SCOM,Quadro,S2M support' CONFIG_ISDN_DRV_EICON_ISA
+ bool ' Eicon S,SX,SCOM,Quadro,S2M support' CONFIG_ISDN_DRV_EICON_ISA
fi
-dep_tristate ' AVM CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN
+dep_tristate 'AVM CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN
if [ "$CONFIG_ISDN_DRV_AVMB1" != "n" ]; then
- bool ' AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA
- bool ' AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI
- bool ' AVM T1/T1-B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA
- bool ' AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
- bool ' AVM T1/T1-B PCI support' CONFIG_ISDN_DRV_AVMB1_T1PCI
- bool ' Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
+ bool ' AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA
+ bool ' AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI
+ bool ' AVM T1/T1-B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA
+ bool ' AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
+ bool ' AVM T1/T1-B PCI support' CONFIG_ISDN_DRV_AVMB1_T1PCI
+ bool ' AVM C4 support' CONFIG_ISDN_DRV_AVMB1_C4
+ bool ' Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
fi
+endmenu
--- /dev/null
+/*
+ * $Id: c4.c,v 1.2 2000/01/21 20:52:58 keil Exp $
+ *
+ * Module for AVM C4 card.
+ *
+ * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
+ *
+ * $Log: c4.c,v $
+ * Revision 1.2 2000/01/21 20:52:58 keil
+ * pci_find_subsys as local function for 2.2.X kernel
+ *
+ * Revision 1.1 2000/01/20 10:51:37 calle
+ * Added driver for C4.
+ *
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/capi.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include "capicmd.h"
+#include "capiutil.h"
+#include "capilli.h"
+#include "avmcard.h"
+
+static char *revision = "$Revision: 1.2 $";
+
+#undef CONFIG_C4_DEBUG
+#undef CONFIG_C4_POLLDEBUG
+
+/* ------------------------------------------------------------- */
+
+#ifndef PCI_VENDOR_ID_DEC
+#define PCI_VENDOR_ID_DEC 0x1011
+#endif
+
+#ifndef PCI_DEVICE_ID_DEC_21285
+#define PCI_DEVICE_ID_DEC_21285 0x1065
+#endif
+
+#ifndef PCI_VENDOR_ID_AVM
+#define PCI_VENDOR_ID_AVM 0x1244
+#endif
+
+#ifndef PCI_DEVICE_ID_AVM_C4
+#define PCI_DEVICE_ID_AVM_C4 0x0800
+#endif
+
+/* ------------------------------------------------------------- */
+
+int suppress_pollack = 0;
+
+MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
+
+MODULE_PARM(suppress_pollack, "0-1i");
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver_interface *di;
+
+/* ------------------------------------------------------------- */
+
+static void c4_dispatch_tx(avmcard *card);
+
+/* ------------------------------------------------------------- */
+
+#define DC21285_DRAM_A0MR 0x40000000
+#define DC21285_DRAM_A1MR 0x40004000
+#define DC21285_DRAM_A2MR 0x40008000
+#define DC21285_DRAM_A3MR 0x4000C000
+
+#define CAS_OFFSET 0x88
+
+#define DC21285_ARMCSR_BASE 0x42000000
+
+#define PCI_OUT_INT_STATUS 0x30
+#define PCI_OUT_INT_MASK 0x34
+#define MAILBOX_0 0x50
+#define MAILBOX_1 0x54
+#define MAILBOX_2 0x58
+#define MAILBOX_3 0x5C
+#define DOORBELL 0x60
+#define DOORBELL_SETUP 0x64
+
+#define CHAN_1_CONTROL 0x90
+#define CHAN_2_CONTROL 0xB0
+#define DRAM_TIMING 0x10C
+#define DRAM_ADDR_SIZE_0 0x110
+#define DRAM_ADDR_SIZE_1 0x114
+#define DRAM_ADDR_SIZE_2 0x118
+#define DRAM_ADDR_SIZE_3 0x11C
+#define SA_CONTROL 0x13C
+#define XBUS_CYCLE 0x148
+#define XBUS_STROBE 0x14C
+#define DBELL_PCI_MASK 0x150
+#define DBELL_SA_MASK 0x154
+
+#define SDRAM_SIZE 0x1000000
+
+/* ------------------------------------------------------------- */
+
+#define MBOX_PEEK_POKE MAILBOX_0
+
+#define DBELL_ADDR 0x01
+#define DBELL_DATA 0x02
+#define DBELL_RNWR 0x40
+#define DBELL_INIT 0x80
+
+/* ------------------------------------------------------------- */
+
+#define MBOX_UP_ADDR MAILBOX_0
+#define MBOX_UP_LEN MAILBOX_1
+#define MBOX_DOWN_ADDR MAILBOX_2
+#define MBOX_DOWN_LEN MAILBOX_3
+
+#define DBELL_UP_HOST 0x00000100
+#define DBELL_UP_ARM 0x00000200
+#define DBELL_DOWN_HOST 0x00000400
+#define DBELL_DOWN_ARM 0x00000800
+#define DBELL_RESET_HOST 0x40000000
+#define DBELL_RESET_ARM 0x80000000
+
+/* ------------------------------------------------------------- */
+
+#define DRAM_TIMING_DEF 0x001A01A5
+#define DRAM_AD_SZ_DEF0 0x00000045
+#define DRAM_AD_SZ_NULL 0x00000000
+
+#define SA_CTL_ALLRIGHT 0x64AA0271
+
+#define INIT_XBUS_CYCLE 0x100016DB
+#define INIT_XBUS_STROBE 0xF1F1F1F1
+
+/* ------------------------------------------------------------- */
+
+#define RESET_TIMEOUT (15*HZ) /* 15 sec */
+#define PEEK_POKE_TIMEOUT (HZ/10) /* 0.1 sec */
+
+/* ------------------------------------------------------------- */
+
+#define c4outmeml(addr, value) writel(value, addr)
+#define c4inmeml(addr) readl(addr)
+#define c4outmemw(addr, value) writew(value, addr)
+#define c4inmemw(addr) readw(addr)
+#define c4outmemb(addr, value) writeb(value, addr)
+#define c4inmemb(addr) readb(addr)
+
+/* ------------------------------------------------------------- */
+
+static inline int wait_for_doorbell(avmcard *card, unsigned long t)
+{
+ unsigned long stop;
+
+ stop = jiffies + t;
+ while (c4inmeml(card->mbase+DOORBELL) != 0xffffffff) {
+ if (!time_before(jiffies, stop))
+ return -1;
+ }
+ return 0;
+}
+
+static int c4_poke(avmcard *card, unsigned long off, unsigned long value)
+{
+
+ if (wait_for_doorbell(card, HZ/10) < 0)
+ return -1;
+
+ c4outmeml(card->mbase+MBOX_PEEK_POKE, off);
+ c4outmeml(card->mbase+DOORBELL, DBELL_ADDR);
+
+ if (wait_for_doorbell(card, HZ/10) < 0)
+ return -1;
+
+ c4outmeml(card->mbase+MBOX_PEEK_POKE, value);
+ c4outmeml(card->mbase+DOORBELL, DBELL_DATA | DBELL_ADDR);
+
+ return 0;
+}
+
+static int c4_peek(avmcard *card, unsigned long off, unsigned long *valuep)
+{
+ if (wait_for_doorbell(card, HZ/10) < 0)
+ return -1;
+
+ c4outmeml(card->mbase+MBOX_PEEK_POKE, off);
+ c4outmeml(card->mbase+DOORBELL, DBELL_RNWR | DBELL_ADDR);
+
+ if (wait_for_doorbell(card, HZ/10) < 0)
+ return -1;
+
+ *valuep = c4inmeml(card->mbase+MBOX_PEEK_POKE);
+
+ return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static int c4_load_t4file(avmcard *card, capiloaddatapart * t4file)
+{
+ __u32 val;
+ unsigned char *dp;
+ int left, retval;
+ __u32 loadoff = 0;
+
+ dp = t4file->data;
+ left = t4file->len;
+ while (left >= sizeof(__u32)) {
+ if (t4file->user) {
+ retval = copy_from_user(&val, dp, sizeof(val));
+ if (retval)
+ return -EFAULT;
+ } else {
+ memcpy(&val, dp, sizeof(val));
+ }
+ if (c4_poke(card, loadoff, val)) {
+ printk(KERN_ERR "%s: corrupted firmware file ?\n",
+ card->name);
+ return -EIO;
+ }
+ left -= sizeof(__u32);
+ dp += sizeof(__u32);
+ loadoff += sizeof(__u32);
+ }
+ if (left) {
+ val = 0;
+ if (t4file->user) {
+ retval = copy_from_user(&val, dp, left);
+ if (retval)
+ return -EFAULT;
+ } else {
+ memcpy(&val, dp, left);
+ }
+ if (c4_poke(card, loadoff, val)) {
+ printk(KERN_ERR "%s: corrupted firmware file ?\n",
+ card->name);
+ return -EIO;
+ }
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static inline void _put_byte(void **pp, __u8 val)
+{
+ __u8 *s = *pp;
+ *s++ = val;
+ *pp = s;
+}
+
+static inline void _put_word(void **pp, __u32 val)
+{
+ __u8 *s = *pp;
+ *s++ = val & 0xff;
+ *s++ = (val >> 8) & 0xff;
+ *s++ = (val >> 16) & 0xff;
+ *s++ = (val >> 24) & 0xff;
+ *pp = s;
+}
+
+static inline void _put_slice(void **pp, unsigned char *dp, unsigned int len)
+{
+ unsigned i = len;
+ _put_word(pp, i);
+ while (i-- > 0)
+ _put_byte(pp, *dp++);
+}
+
+static inline __u8 _get_byte(void **pp)
+{
+ __u8 *s = *pp;
+ __u8 val;
+ val = *s++;
+ *pp = s;
+ return val;
+}
+
+static inline __u32 _get_word(void **pp)
+{
+ __u8 *s = *pp;
+ __u32 val;
+ val = *s++;
+ val |= (*s++ << 8);
+ val |= (*s++ << 16);
+ val |= (*s++ << 24);
+ *pp = s;
+ return val;
+}
+
+static inline __u32 _get_slice(void **pp, unsigned char *dp)
+{
+ unsigned int len, i;
+
+ len = i = _get_word(pp);
+ while (i-- > 0) *dp++ = _get_byte(pp);
+ return len;
+}
+
+/* ------------------------------------------------------------- */
+
+static void c4_reset(avmcard *card)
+{
+ unsigned long stop;
+
+ c4outmeml(card->mbase+DOORBELL, DBELL_RESET_ARM);
+
+ stop = jiffies + HZ*10;
+ while (c4inmeml(card->mbase+DOORBELL) != 0xffffffff) {
+ if (!time_before(jiffies, stop))
+ return;
+ c4outmeml(card->mbase+DOORBELL, DBELL_ADDR);
+ }
+
+ c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0);
+ c4_poke(card, DC21285_ARMCSR_BASE + CHAN_2_CONTROL, 0);
+}
+
+/* ------------------------------------------------------------- */
+
+static int c4_detect(avmcard *card)
+{
+ unsigned long stop, dummy;
+
+ c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c);
+ if (c4inmeml(card->mbase+PCI_OUT_INT_MASK) != 0x0c)
+ return 1;
+
+ c4outmeml(card->mbase+DOORBELL, DBELL_RESET_ARM);
+
+ stop = jiffies + HZ*10;
+ while (c4inmeml(card->mbase+DOORBELL) != 0xffffffff) {
+ if (!time_before(jiffies, stop))
+ return 2;
+ c4outmeml(card->mbase+DOORBELL, DBELL_ADDR);
+ }
+
+ c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0);
+ c4_poke(card, DC21285_ARMCSR_BASE + CHAN_2_CONTROL, 0);
+
+ c4outmeml(card->mbase+MAILBOX_0, 0x55aa55aa);
+ if (c4inmeml(card->mbase+MAILBOX_0) != 0x55aa55aa) return 3;
+
+ c4outmeml(card->mbase+MAILBOX_0, 0xaa55aa55);
+ if (c4inmeml(card->mbase+MAILBOX_0) != 0xaa55aa55) return 4;
+
+ if (c4_poke(card, DC21285_ARMCSR_BASE+DBELL_SA_MASK, 0)) return 5;
+ if (c4_poke(card, DC21285_ARMCSR_BASE+DBELL_PCI_MASK, 0)) return 6;
+ if (c4_poke(card, DC21285_ARMCSR_BASE+SA_CONTROL, SA_CTL_ALLRIGHT))
+ return 7;
+ if (c4_poke(card, DC21285_ARMCSR_BASE+XBUS_CYCLE, INIT_XBUS_CYCLE))
+ return 8;
+ if (c4_poke(card, DC21285_ARMCSR_BASE+XBUS_STROBE, INIT_XBUS_STROBE))
+ return 8;
+ if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_TIMING, 0)) return 9;
+
+ udelay(1000);
+
+ if (c4_peek(card, DC21285_DRAM_A0MR, &dummy)) return 10;
+ if (c4_peek(card, DC21285_DRAM_A1MR, &dummy)) return 11;
+ if (c4_peek(card, DC21285_DRAM_A2MR, &dummy)) return 12;
+ if (c4_peek(card, DC21285_DRAM_A3MR, &dummy)) return 13;
+
+ if (c4_poke(card, DC21285_DRAM_A0MR+CAS_OFFSET, 0)) return 14;
+ if (c4_poke(card, DC21285_DRAM_A1MR+CAS_OFFSET, 0)) return 15;
+ if (c4_poke(card, DC21285_DRAM_A2MR+CAS_OFFSET, 0)) return 16;
+ if (c4_poke(card, DC21285_DRAM_A3MR+CAS_OFFSET, 0)) return 17;
+
+ udelay(1000);
+
+ if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_TIMING, DRAM_TIMING_DEF))
+ return 18;
+
+ if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_0,DRAM_AD_SZ_DEF0))
+ return 19;
+ if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_1,DRAM_AD_SZ_NULL))
+ return 20;
+ if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_2,DRAM_AD_SZ_NULL))
+ return 21;
+ if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_3,DRAM_AD_SZ_NULL))
+ return 22;
+
+ /* Transputer test */
+
+ if ( c4_poke(card, 0x000000, 0x11111111)
+ || c4_poke(card, 0x400000, 0x22222222)
+ || c4_poke(card, 0x800000, 0x33333333)
+ || c4_poke(card, 0xC00000, 0x44444444))
+ return 23;
+
+ if ( c4_peek(card, 0x000000, &dummy) || dummy != 0x11111111
+ || c4_peek(card, 0x400000, &dummy) || dummy != 0x22222222
+ || c4_peek(card, 0x800000, &dummy) || dummy != 0x33333333
+ || c4_peek(card, 0xC00000, &dummy) || dummy != 0x44444444)
+ return 24;
+
+ if ( c4_poke(card, 0x000000, 0x55555555)
+ || c4_poke(card, 0x400000, 0x66666666)
+ || c4_poke(card, 0x800000, 0x77777777)
+ || c4_poke(card, 0xC00000, 0x88888888))
+ return 25;
+
+ if ( c4_peek(card, 0x000000, &dummy) || dummy != 0x55555555
+ || c4_peek(card, 0x400000, &dummy) || dummy != 0x66666666
+ || c4_peek(card, 0x800000, &dummy) || dummy != 0x77777777
+ || c4_peek(card, 0xC00000, &dummy) || dummy != 0x88888888)
+ return 26;
+
+ return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static void c4_dispatch_tx(avmcard *card)
+{
+ avmcard_dmainfo *dma = card->dma;
+ unsigned long flags;
+ struct sk_buff *skb;
+ __u8 cmd, subcmd;
+ __u16 len;
+ __u32 txlen;
+ void *p;
+
+ save_flags(flags);
+ cli();
+
+ if (card->csr & DBELL_DOWN_ARM) { /* tx busy */
+ restore_flags(flags);
+ return;
+ }
+
+ skb = skb_dequeue(&dma->send_queue);
+ if (!skb) {
+#ifdef CONFIG_C4_DEBUG
+ printk(KERN_DEBUG "%s: tx underrun\n", card->name);
+#endif
+ restore_flags(flags);
+ return;
+ }
+
+ len = CAPIMSG_LEN(skb->data);
+
+ if (len) {
+ cmd = CAPIMSG_COMMAND(skb->data);
+ subcmd = CAPIMSG_SUBCOMMAND(skb->data);
+
+ p = dma->sendbuf;
+
+ if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
+ __u16 dlen = CAPIMSG_DATALEN(skb->data);
+ _put_byte(&p, SEND_DATA_B3_REQ);
+ _put_slice(&p, skb->data, len);
+ _put_slice(&p, skb->data + len, dlen);
+ } else {
+ _put_byte(&p, SEND_MESSAGE);
+ _put_slice(&p, skb->data, len);
+ }
+ txlen = (__u8 *)p - (__u8 *)dma->sendbuf;
+#ifdef CONFIG_C4_DEBUG
+ printk(KERN_DEBUG "%s: tx put msg len=%d\n", card->name, txlen);
+#endif
+ } else {
+ txlen = skb->len-2;
+#ifdef CONFIG_C4_POLLDEBUG
+ if (skb->data[2] == SEND_POLLACK)
+ printk(KERN_INFO "%s: ack to c4\n", card->name);
+#endif
+#ifdef CONFIG_C4_DEBUG
+ printk(KERN_DEBUG "%s: tx put 0x%x len=%d\n",
+ card->name, skb->data[2], txlen);
+#endif
+ memcpy(dma->sendbuf, skb->data+2, skb->len-2);
+ }
+ txlen = (txlen + 3) & ~3;
+
+ c4outmeml(card->mbase+MBOX_DOWN_ADDR, virt_to_phys(dma->sendbuf));
+ c4outmeml(card->mbase+MBOX_DOWN_LEN, txlen);
+
+ card->csr |= DBELL_DOWN_ARM;
+
+ c4outmeml(card->mbase+DOORBELL, DBELL_DOWN_ARM);
+
+ restore_flags(flags);
+ dev_kfree_skb(skb);
+}
+
+/* ------------------------------------------------------------- */
+
+static void queue_pollack(avmcard *card)
+{
+ struct sk_buff *skb;
+ void *p;
+
+ skb = alloc_skb(3, GFP_ATOMIC);
+ if (!skb) {
+ printk(KERN_CRIT "%s: no memory, lost poll ack\n",
+ card->name);
+ return;
+ }
+ p = skb->data;
+ _put_byte(&p, 0);
+ _put_byte(&p, 0);
+ _put_byte(&p, SEND_POLLACK);
+ skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
+
+ skb_queue_tail(&card->dma->send_queue, skb);
+ c4_dispatch_tx(card);
+}
+
+/* ------------------------------------------------------------- */
+
+static void c4_handle_rx(avmcard *card)
+{
+ avmcard_dmainfo *dma = card->dma;
+ struct capi_ctr *ctrl;
+ avmctrl_info *cinfo;
+ struct sk_buff *skb;
+ void *p = dma->recvbuf;
+ __u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize;
+ __u8 b1cmd = _get_byte(&p);
+ __u32 cidx;
+
+
+#ifdef CONFIG_C4_DEBUG
+ printk(KERN_DEBUG "%s: rx 0x%x len=%lu\n", card->name,
+ b1cmd, (unsigned long)dma->recvlen);
+#endif
+
+ switch (b1cmd) {
+ case RECEIVE_DATA_B3_IND:
+
+ ApplId = (unsigned) _get_word(&p);
+ MsgLen = _get_slice(&p, card->msgbuf);
+ DataB3Len = _get_slice(&p, card->databuf);
+ cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr;
+ if (cidx > 3) cidx = 0;
+ ctrl = card->ctrlinfo[cidx].capi_ctrl;
+
+ if (MsgLen < 30) { /* not CAPI 64Bit */
+ memset(card->msgbuf+MsgLen, 0, 30-MsgLen);
+ MsgLen = 30;
+ CAPIMSG_SETLEN(card->msgbuf, 30);
+ }
+ if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) {
+ printk(KERN_ERR "%s: incoming packet dropped\n",
+ card->name);
+ } else {
+ memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
+ memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len);
+ ctrl->handle_capimsg(ctrl, ApplId, skb);
+ }
+ break;
+
+ case RECEIVE_MESSAGE:
+
+ ApplId = (unsigned) _get_word(&p);
+ MsgLen = _get_slice(&p, card->msgbuf);
+ cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr;
+ if (cidx > 3) cidx = 0;
+ ctrl = card->ctrlinfo[cidx].capi_ctrl;
+
+ if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
+ printk(KERN_ERR "%s: incoming packet dropped\n",
+ card->name);
+ } else {
+ memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
+ ctrl->handle_capimsg(ctrl, ApplId, skb);
+ }
+ break;
+
+ case RECEIVE_NEW_NCCI:
+
+ ApplId = _get_word(&p);
+ NCCI = _get_word(&p);
+ WindowSize = _get_word(&p);
+ cidx = (NCCI&0x7f) - card->cardnr;
+ if (cidx > 3) cidx = 0;
+ ctrl = card->ctrlinfo[cidx].capi_ctrl;
+
+ ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
+
+ break;
+
+ case RECEIVE_FREE_NCCI:
+
+ ApplId = _get_word(&p);
+ NCCI = _get_word(&p);
+
+ if (NCCI != 0xffffffff) {
+ cidx = (NCCI&0x7f) - card->cardnr;
+ if (cidx > 3) cidx = 0;
+ ctrl = card->ctrlinfo[cidx].capi_ctrl;
+ ctrl->free_ncci(ctrl, ApplId, NCCI);
+ } else {
+ for (cidx=0; cidx < 4; cidx++) {
+ ctrl = card->ctrlinfo[cidx].capi_ctrl;
+ ctrl->appl_released(ctrl, ApplId);
+ }
+ }
+ break;
+
+ case RECEIVE_START:
+#ifdef CONFIG_C4_POLLDEBUG
+ printk(KERN_INFO "%s: poll from c4\n", card->name);
+#endif
+ if (!suppress_pollack)
+ queue_pollack(card);
+ for (cidx=0; cidx < 4; cidx++) {
+ ctrl = card->ctrlinfo[cidx].capi_ctrl;
+ ctrl->resume_output(ctrl);
+ }
+ break;
+
+ case RECEIVE_STOP:
+ for (cidx=0; cidx < 4; cidx++) {
+ ctrl = card->ctrlinfo[cidx].capi_ctrl;
+ ctrl->suspend_output(ctrl);
+ }
+ break;
+
+ case RECEIVE_INIT:
+
+ cidx = card->nlogcontr++;
+ cinfo = &card->ctrlinfo[cidx];
+ ctrl = cinfo->capi_ctrl;
+ cinfo->versionlen = _get_slice(&p, cinfo->versionbuf);
+ b1_parse_version(cinfo);
+ printk(KERN_INFO "%s: %s-card (%s) now active\n",
+ card->name,
+ cinfo->version[VER_CARDTYPE],
+ cinfo->version[VER_DRIVER]);
+ ctrl->ready(cinfo->capi_ctrl);
+ break;
+
+ case RECEIVE_TASK_READY:
+ ApplId = (unsigned) _get_word(&p);
+ MsgLen = _get_slice(&p, card->msgbuf);
+ card->msgbuf[MsgLen--] = 0;
+ while ( MsgLen >= 0
+ && ( card->msgbuf[MsgLen] == '\n'
+ || card->msgbuf[MsgLen] == '\r'))
+ card->msgbuf[MsgLen--] = 0;
+ printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
+ card->name, ApplId, card->msgbuf);
+ break;
+
+ case RECEIVE_DEBUGMSG:
+ MsgLen = _get_slice(&p, card->msgbuf);
+ card->msgbuf[MsgLen--] = 0;
+ while ( MsgLen >= 0
+ && ( card->msgbuf[MsgLen] == '\n'
+ || card->msgbuf[MsgLen] == '\r'))
+ card->msgbuf[MsgLen--] = 0;
+ printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
+ break;
+
+ default:
+ printk(KERN_ERR "%s: c4_interrupt: 0x%x ???\n",
+ card->name, b1cmd);
+ return;
+ }
+}
+
+/* ------------------------------------------------------------- */
+
+static void c4_handle_interrupt(avmcard *card)
+{
+ __u32 status = c4inmeml(card->mbase+DOORBELL);
+
+ if (status & DBELL_RESET_HOST) {
+ int i;
+ c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c);
+ printk(KERN_ERR "%s: unexpected reset\n", card->name);
+ for (i=0; i < 4; i++) {
+ avmctrl_info *cinfo = &card->ctrlinfo[i];
+ memset(cinfo->version, 0, sizeof(cinfo->version));
+ if (cinfo->capi_ctrl)
+ cinfo->capi_ctrl->reseted(cinfo->capi_ctrl);
+ }
+ return;
+ }
+
+ status &= (DBELL_UP_HOST | DBELL_DOWN_HOST);
+ if (!status)
+ return;
+ c4outmeml(card->mbase+DOORBELL, status);
+
+ if ((status & DBELL_UP_HOST) != 0) {
+ card->dma->recvlen = c4inmeml(card->mbase+MBOX_UP_LEN);
+ c4outmeml(card->mbase+MBOX_UP_LEN, 0);
+ c4_handle_rx(card);
+ card->dma->recvlen = 0;
+ c4outmeml(card->mbase+MBOX_UP_LEN, sizeof(card->dma->recvbuf));
+ c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM);
+ }
+
+ if ((status & DBELL_DOWN_HOST) != 0) {
+ card->csr &= ~DBELL_DOWN_ARM;
+ c4_dispatch_tx(card);
+ } else if (card->csr & DBELL_DOWN_HOST) {
+ if (c4inmeml(card->mbase+MBOX_DOWN_LEN) == 0) {
+ card->csr &= ~DBELL_DOWN_ARM;
+ c4_dispatch_tx(card);
+ }
+ }
+}
+
+static void c4_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
+{
+ avmcard *card;
+
+ card = (avmcard *) devptr;
+
+ if (!card) {
+ printk(KERN_WARNING "%s: interrupt: wrong device\n", card->name);
+ return;
+ }
+ if (card->interrupt) {
+ printk(KERN_ERR "%s: reentering interrupt hander\n",
+ card->name);
+ return;
+ }
+
+ card->interrupt = 1;
+
+ c4_handle_interrupt(card);
+
+ card->interrupt = 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static void c4_send_init(avmcard *card)
+{
+ struct sk_buff *skb;
+ void *p;
+
+ skb = alloc_skb(15, GFP_ATOMIC);
+ if (!skb) {
+ printk(KERN_CRIT "%s: no memory, lost register appl.\n",
+ card->name);
+ return;
+ }
+ p = skb->data;
+ _put_byte(&p, 0);
+ _put_byte(&p, 0);
+ _put_byte(&p, SEND_INIT);
+ _put_word(&p, AVM_NAPPS);
+ _put_word(&p, AVM_NCCI_PER_CHANNEL*30);
+ _put_word(&p, card->cardnr - 1);
+ skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
+
+ skb_queue_tail(&card->dma->send_queue, skb);
+ c4_dispatch_tx(card);
+}
+
+static int c4_send_config(avmcard *card, capiloaddatapart * config)
+{
+ struct sk_buff *skb;
+ __u8 val[sizeof(__u32)];
+ void *p;
+ unsigned char *dp;
+ int left, retval;
+
+ skb = alloc_skb(12 + ((config->len+3)/4)*5, GFP_ATOMIC);
+ if (!skb) {
+ printk(KERN_CRIT "%s: no memory, can't send config.\n",
+ card->name);
+ return -ENOMEM;
+ }
+ p = skb->data;
+ _put_byte(&p, 0);
+ _put_byte(&p, 0);
+ _put_byte(&p, SEND_CONFIG);
+ _put_word(&p, 1);
+ _put_byte(&p, SEND_CONFIG);
+ _put_word(&p, config->len); /* 12 */
+
+ dp = config->data;
+ left = config->len;
+ while (left >= sizeof(__u32)) {
+ if (config->user) {
+ retval = copy_from_user(val, dp, sizeof(val));
+ if (retval) {
+ dev_kfree_skb(skb);
+ return -EFAULT;
+ }
+ } else {
+ memcpy(val, dp, sizeof(val));
+ }
+ _put_byte(&p, SEND_CONFIG);
+ _put_byte(&p, val[0]);
+ _put_byte(&p, val[1]);
+ _put_byte(&p, val[2]);
+ _put_byte(&p, val[3]);
+ left -= sizeof(val);
+ dp += sizeof(val);
+ }
+ if (left) {
+ memset(val, 0, sizeof(val));
+ if (config->user) {
+ retval = copy_from_user(&val, dp, left);
+ if (retval) {
+ dev_kfree_skb(skb);
+ return -EFAULT;
+ }
+ } else {
+ memcpy(&val, dp, left);
+ }
+ _put_byte(&p, SEND_CONFIG);
+ _put_byte(&p, val[0]);
+ _put_byte(&p, val[1]);
+ _put_byte(&p, val[2]);
+ _put_byte(&p, val[3]);
+ }
+
+ skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
+
+ skb_queue_tail(&card->dma->send_queue, skb);
+ c4_dispatch_tx(card);
+
+ return 0;
+}
+
+static int c4_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
+{
+ avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+ avmcard *card = cinfo->card;
+ unsigned long flags;
+ int retval;
+
+ if ((retval = c4_load_t4file(card, &data->firmware))) {
+ printk(KERN_ERR "%s: failed to load t4file!!\n",
+ card->name);
+ c4_reset(card);
+ return retval;
+ }
+
+ save_flags(flags);
+ cli();
+
+ card->csr = 0;
+ c4outmeml(card->mbase+MBOX_UP_LEN, 0);
+ c4outmeml(card->mbase+MBOX_DOWN_LEN, 0);
+ c4outmeml(card->mbase+DOORBELL, DBELL_INIT);
+ udelay(1000);
+ c4outmeml(card->mbase+DOORBELL,
+ DBELL_UP_HOST | DBELL_DOWN_HOST | DBELL_RESET_HOST);
+
+ c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x08);
+
+ card->dma->recvlen = 0;
+ c4outmeml(card->mbase+MBOX_UP_ADDR, virt_to_phys(card->dma->recvbuf));
+ c4outmeml(card->mbase+MBOX_UP_LEN, sizeof(card->dma->recvbuf));
+ c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM);
+ restore_flags(flags);
+
+ if (data->configuration.len > 0 && data->configuration.data)
+ c4_send_config(card, &data->configuration);
+
+ c4_send_init(card);
+
+ return 0;
+}
+
+
+void c4_reset_ctr(struct capi_ctr *ctrl)
+{
+ avmcard *card = ((avmctrl_info *)(ctrl->driverdata))->card;
+ avmctrl_info *cinfo;
+ int i;
+
+ c4_reset(card);
+
+ for (i=0; i < 4; i++) {
+ cinfo = &card->ctrlinfo[i];
+ memset(cinfo->version, 0, sizeof(cinfo->version));
+ if (cinfo->capi_ctrl)
+ cinfo->capi_ctrl->reseted(cinfo->capi_ctrl);
+ }
+}
+
+static void c4_remove_ctr(struct capi_ctr *ctrl)
+{
+ avmcard *card = ((avmctrl_info *)(ctrl->driverdata))->card;
+ avmctrl_info *cinfo;
+ int i;
+
+ c4_reset(card);
+
+ for (i=0; i <= 4; i++) {
+ cinfo = &card->ctrlinfo[i];
+ if (cinfo->capi_ctrl)
+ di->detach_ctr(cinfo->capi_ctrl);
+ }
+
+ free_irq(card->irq, card);
+ iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
+ release_region(card->port, AVMB1_PORTLEN);
+ ctrl->driverdata = 0;
+ kfree(card->ctrlinfo);
+ kfree(card->dma);
+ kfree(card);
+
+ MOD_DEC_USE_COUNT;
+}
+
+/* ------------------------------------------------------------- */
+
+
+void c4_register_appl(struct capi_ctr *ctrl,
+ __u16 appl,
+ capi_register_params *rp)
+{
+ avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+ avmcard *card = cinfo->card;
+ struct sk_buff *skb;
+ int want = rp->level3cnt;
+ int nconn;
+ void *p;
+
+ if (ctrl->cnr == card->cardnr) {
+
+ if (want > 0) nconn = want;
+ else nconn = ctrl->profile.nbchannel * 4 * -want;
+ if (nconn == 0) nconn = ctrl->profile.nbchannel * 4;
+
+ skb = alloc_skb(23, GFP_ATOMIC);
+ if (!skb) {
+ printk(KERN_CRIT "%s: no memory, lost register appl.\n",
+ card->name);
+ return;
+ }
+ p = skb->data;
+ _put_byte(&p, 0);
+ _put_byte(&p, 0);
+ _put_byte(&p, SEND_REGISTER);
+ _put_word(&p, appl);
+ _put_word(&p, 1024 * (nconn+1));
+ _put_word(&p, nconn);
+ _put_word(&p, rp->datablkcnt);
+ _put_word(&p, rp->datablklen);
+ skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
+
+ skb_queue_tail(&card->dma->send_queue, skb);
+ c4_dispatch_tx(card);
+ }
+
+ ctrl->appl_registered(ctrl, appl);
+}
+
+/* ------------------------------------------------------------- */
+
+void c4_release_appl(struct capi_ctr *ctrl, __u16 appl)
+{
+ avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+ avmcard *card = cinfo->card;
+ struct sk_buff *skb;
+ void *p;
+
+ if (ctrl->cnr == card->cardnr) {
+ skb = alloc_skb(7, GFP_ATOMIC);
+ if (!skb) {
+ printk(KERN_CRIT "%s: no memory, lost release appl.\n",
+ card->name);
+ return;
+ }
+ p = skb->data;
+ _put_byte(&p, 0);
+ _put_byte(&p, 0);
+ _put_byte(&p, SEND_RELEASE);
+ _put_word(&p, appl);
+
+ skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
+ skb_queue_tail(&card->dma->send_queue, skb);
+ c4_dispatch_tx(card);
+ }
+}
+
+/* ------------------------------------------------------------- */
+
+
+static void c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
+{
+ avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+ avmcard *card = cinfo->card;
+ skb_queue_tail(&card->dma->send_queue, skb);
+ c4_dispatch_tx(card);
+}
+
+/* ------------------------------------------------------------- */
+
+static char *c4_procinfo(struct capi_ctr *ctrl)
+{
+ avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+
+ if (!cinfo)
+ return "";
+ sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx",
+ cinfo->cardname[0] ? cinfo->cardname : "-",
+ cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
+ cinfo->card ? cinfo->card->port : 0x0,
+ cinfo->card ? cinfo->card->irq : 0,
+ cinfo->card ? cinfo->card->membase : 0
+ );
+ return cinfo->infobuf;
+}
+
+static int c4_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, struct capi_ctr *ctrl)
+{
+ avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+ avmcard *card = cinfo->card;
+ __u8 flag;
+ int len = 0;
+ char *s;
+
+ len += sprintf(page+len, "%-16s %s\n", "name", card->name);
+ len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
+ len += sprintf(page+len, "%-16s %d\n", "irq", card->irq);
+ len += sprintf(page+len, "%-16s 0x%lx\n", "membase", card->membase);
+ switch (card->cardtype) {
+ case avm_b1isa: s = "B1 ISA"; break;
+ case avm_b1pci: s = "B1 PCI"; break;
+ case avm_b1pcmcia: s = "B1 PCMCIA"; break;
+ case avm_m1: s = "M1"; break;
+ case avm_m2: s = "M2"; break;
+ case avm_t1isa: s = "T1 ISA (HEMA)"; break;
+ case avm_t1pci: s = "T1 PCI"; break;
+ case avm_c4: s = "C4"; break;
+ default: s = "???"; break;
+ }
+ len += sprintf(page+len, "%-16s %s\n", "type", s);
+ if ((s = cinfo->version[VER_DRIVER]) != 0)
+ len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
+ if ((s = cinfo->version[VER_CARDTYPE]) != 0)
+ len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
+ if ((s = cinfo->version[VER_SERIAL]) != 0)
+ len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
+
+ if (card->cardtype != avm_m1) {
+ flag = ((__u8 *)(ctrl->profile.manu))[3];
+ if (flag)
+ len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n",
+ "protocol",
+ (flag & 0x01) ? " DSS1" : "",
+ (flag & 0x02) ? " CT1" : "",
+ (flag & 0x04) ? " VN3" : "",
+ (flag & 0x08) ? " NI1" : "",
+ (flag & 0x10) ? " AUSTEL" : "",
+ (flag & 0x20) ? " ESS" : "",
+ (flag & 0x40) ? " 1TR6" : ""
+ );
+ }
+ if (card->cardtype != avm_m1) {
+ flag = ((__u8 *)(ctrl->profile.manu))[5];
+ if (flag)
+ len += sprintf(page+len, "%-16s%s%s%s%s\n",
+ "linetype",
+ (flag & 0x01) ? " point to point" : "",
+ (flag & 0x02) ? " point to multipoint" : "",
+ (flag & 0x08) ? " leased line without D-channel" : "",
+ (flag & 0x04) ? " leased line with D-channel" : ""
+ );
+ }
+ len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname);
+
+ if (off+count >= len)
+ *eof = 1;
+ if (len < off)
+ return 0;
+ *start = page + off;
+ return ((count < len-off) ? count : len-off);
+}
+
+/* ------------------------------------------------------------- */
+
+static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
+{
+ unsigned long page_offset, base;
+ avmctrl_info *cinfo;
+ avmcard *card;
+ int retval;
+ int i;
+
+ card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
+
+ if (!card) {
+ printk(KERN_WARNING "%s: no memory.\n", driver->name);
+ return -ENOMEM;
+ }
+ memset(card, 0, sizeof(avmcard));
+ card->dma = (avmcard_dmainfo *) kmalloc(sizeof(avmcard_dmainfo), GFP_ATOMIC);
+ if (!card->dma) {
+ printk(KERN_WARNING "%s: no memory.\n", driver->name);
+ kfree(card);
+ return -ENOMEM;
+ }
+ memset(card->dma, 0, sizeof(avmcard_dmainfo));
+ cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info)*4, GFP_ATOMIC);
+ if (!cinfo) {
+ printk(KERN_WARNING "%s: no memory.\n", driver->name);
+ kfree(card->ctrlinfo);
+ kfree(card->dma);
+ kfree(card);
+ return -ENOMEM;
+ }
+ memset(cinfo, 0, sizeof(avmctrl_info)*4);
+ card->ctrlinfo = cinfo;
+ for (i=0; i < 4; i++) {
+ cinfo = &card->ctrlinfo[i];
+ cinfo->card = card;
+ }
+ sprintf(card->name, "c4-%x", p->port);
+ card->port = p->port;
+ card->irq = p->irq;
+ card->membase = p->membase;
+ card->cardtype = avm_c4;
+
+ if (check_region(card->port, AVMB1_PORTLEN)) {
+ printk(KERN_WARNING
+ "%s: ports 0x%03x-0x%03x in use.\n",
+ driver->name, card->port, card->port + AVMB1_PORTLEN);
+ kfree(card->ctrlinfo);
+ kfree(card->dma);
+ kfree(card);
+ return -EBUSY;
+ }
+
+ base = card->membase & PAGE_MASK;
+ page_offset = card->membase - base;
+ card->mbase = ioremap_nocache(base, page_offset + 64);
+
+ if ((retval = c4_detect(card)) != 0) {
+ printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
+ driver->name, card->port, retval);
+ iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
+ kfree(card->ctrlinfo);
+ kfree(card->dma);
+ kfree(card);
+ return -EIO;
+ }
+ c4_reset(card);
+
+ request_region(p->port, AVMB1_PORTLEN, card->name);
+
+ retval = request_irq(card->irq, c4_interrupt, SA_SHIRQ, card->name, card);
+ if (retval) {
+ printk(KERN_ERR "%s: unable to get IRQ %d.\n",
+ driver->name, card->irq);
+ iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
+ release_region(card->port, AVMB1_PORTLEN);
+ kfree(card->ctrlinfo);
+ kfree(card->dma);
+ kfree(card);
+ return -EBUSY;
+ }
+
+ for (i=0; i < 4; i++) {
+ cinfo = &card->ctrlinfo[i];
+ cinfo->card = card;
+ cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo);
+ if (!cinfo->capi_ctrl) {
+ printk(KERN_ERR "%s: attach controller failed (%d).\n",
+ driver->name, i);
+ for (i--; i >= 0; i--) {
+ cinfo = &card->ctrlinfo[i];
+ di->detach_ctr(cinfo->capi_ctrl);
+ }
+ iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
+ free_irq(card->irq, card);
+ release_region(card->port, AVMB1_PORTLEN);
+ kfree(card->dma);
+ kfree(card->ctrlinfo);
+ kfree(card);
+ return -EBUSY;
+ }
+ if (i == 0)
+ card->cardnr = cinfo->capi_ctrl->cnr;
+ }
+
+ skb_queue_head_init(&card->dma->send_queue);
+
+ MOD_INC_USE_COUNT;
+
+ return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver c4_driver = {
+ "c4",
+ "0.0",
+ c4_load_firmware,
+ c4_reset_ctr,
+ c4_remove_ctr,
+ c4_register_appl,
+ c4_release_appl,
+ c4_send_message,
+
+ c4_procinfo,
+ c4_read_proc,
+ 0, /* use standard driver_read_proc */
+
+ 0, /* no add_card function */
+};
+
+#ifdef MODULE
+#define c4_init init_module
+void cleanup_module(void);
+#endif
+
+#ifndef PCI_ANY_ID
+#define PCI_ANY_ID (~0)
+#endif
+
+static struct pci_dev *
+pci_find_subsys(unsigned int vendor, unsigned int device,
+ unsigned int ss_vendor, unsigned int ss_device,
+ struct pci_dev *from)
+{
+ unsigned short subsystem_vendor, subsystem_device;
+
+ while ((from = pci_find_device(vendor, device, from))) {
+ pci_read_config_word(from, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
+ pci_read_config_word(from, PCI_SUBSYSTEM_ID, &subsystem_device);
+ if ((ss_vendor == PCI_ANY_ID || subsystem_vendor == ss_vendor) &&
+ (ss_device == PCI_ANY_ID || subsystem_device == ss_device))
+ return from;
+ }
+ return NULL;
+}
+
+static int ncards = 0;
+
+int c4_init(void)
+{
+ struct capi_driver *driver = &c4_driver;
+ struct pci_dev *dev = NULL;
+ char *p;
+ int retval;
+
+ if ((p = strchr(revision, ':'))) {
+ strncpy(driver->revision, p + 1, sizeof(driver->revision));
+ p = strchr(driver->revision, '$');
+ *p = 0;
+ }
+
+ printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
+
+ di = attach_capi_driver(driver);
+
+ if (!di) {
+ printk(KERN_ERR "%s: failed to attach capi_driver\n",
+ driver->name);
+ return -EIO;
+ }
+
+#ifdef CONFIG_PCI
+ if (!pci_present()) {
+ printk(KERN_ERR "%s: no PCI bus present\n", driver->name);
+ detach_capi_driver(driver);
+ return -EIO;
+ }
+
+ while ((dev = pci_find_subsys(
+ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285,
+ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4, dev))) {
+ struct capicardparams param;
+
+ param.port = dev->base_address[ 1] & PCI_BASE_ADDRESS_IO_MASK;
+ param.irq = dev->irq;
+ param.membase = dev->base_address[ 0] & PCI_BASE_ADDRESS_MEM_MASK;
+
+ printk(KERN_INFO
+ "%s: PCI BIOS reports AVM-C4 at i/o %#x, irq %d, mem %#x\n",
+ driver->name, param.port, param.irq, param.membase);
+ retval = c4_add_card(driver, ¶m);
+ if (retval != 0) {
+ printk(KERN_ERR
+ "%s: no AVM-C4 at i/o %#x, irq %d detected, mem %#x\n",
+ driver->name, param.port, param.irq, param.membase);
+#ifdef MODULE
+ cleanup_module();
+#endif
+ return retval;
+ }
+ ncards++;
+ }
+ if (ncards) {
+ printk(KERN_INFO "%s: %d C4 card(s) detected\n",
+ driver->name, ncards);
+ return 0;
+ }
+ printk(KERN_ERR "%s: NO C4 card detected\n", driver->name);
+ return -ESRCH;
+#else
+ printk(KERN_ERR "%s: kernel not compiled with PCI.\n", driver->name);
+ return -EIO;
+#endif
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+ detach_capi_driver(&c4_driver);
+}
+#endif
-/* $Id: eicon_idi.c,v 1.27 1999/11/29 13:12:03 armin Exp $
+/* $Id: eicon_idi.c,v 1.28 2000/01/20 19:55:34 keil Exp $
*
* ISDN lowlevel-module for Eicon.Diehl active cards.
* IDI interface
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: eicon_idi.c,v $
+ * Revision 1.28 2000/01/20 19:55:34 keil
+ * Add FAX Class 1 support
+ *
* Revision 1.27 1999/11/29 13:12:03 armin
* Autoconnect on L2_TRANS doesn't work with link_level correctly,
* changed back to former mode.
#undef EICON_FULL_SERVICE_OKTETT
-char *eicon_idi_revision = "$Revision: 1.27 $";
+char *eicon_idi_revision = "$Revision: 1.28 $";
eicon_manifbuf *manbuf;
reqbuf->XBuffer.P[l++] = 1;
}
switch(chan->l3prot) {
- case ISDN_PROTO_L3_FAX:
+ case ISDN_PROTO_L3_FCLASS2:
#ifdef CONFIG_ISDN_TTY_FAX
reqbuf->XBuffer.P[l++] = 6;
reqbuf->XBuffer.P[l++] = NLC;
-/* $Id: eicon_mod.c,v 1.22 1999/11/27 12:56:19 armin Exp $
+/* $Id: eicon_mod.c,v 1.23 2000/01/20 19:55:34 keil Exp $
*
* ISDN lowlevel-module for Eicon.Diehl active cards.
*
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: eicon_mod.c,v $
+ * Revision 1.23 2000/01/20 19:55:34 keil
+ * Add FAX Class 1 support
+ *
* Revision 1.22 1999/11/27 12:56:19 armin
* Forgot some iomem changes for last ioremap compat.
*
static eicon_card *cards = (eicon_card *) NULL; /* glob. var , contains
start of card-list */
-static char *eicon_revision = "$Revision: 1.22 $";
+static char *eicon_revision = "$Revision: 1.23 $";
extern char *eicon_pci_revision;
extern char *eicon_isa_revision;
break;
chan->l3prot = (c->arg >> 8);
#ifdef CONFIG_ISDN_TTY_FAX
- if (chan->l3prot == ISDN_PROTO_L3_FAX)
+ if (chan->l3prot == ISDN_PROTO_L3_FCLASS2)
chan->fax = c->parm.fax;
#endif
return 0;
ISDN_FEATURE_L2_MODEM |
ISDN_FEATURE_L2_FAX |
ISDN_FEATURE_L3_TRANSDSP |
- ISDN_FEATURE_L3_FAX;
+ ISDN_FEATURE_L3_FCLASS2;
card->hwif.pci.card = (void *)card;
card->hwif.pci.PCIreg = pcic->PCIreg;
card->hwif.pci.PCIcfg = pcic->PCIcfg;
ISDN_FEATURE_L2_MODEM |
ISDN_FEATURE_L2_FAX |
ISDN_FEATURE_L3_TRANSDSP |
- ISDN_FEATURE_L3_FAX;
+ ISDN_FEATURE_L3_FCLASS2;
card->hwif.pci.card = (void *)card;
card->hwif.pci.shmem = (eicon_pci_shmem *)pcic->shmem;
card->hwif.pci.PCIreg = pcic->PCIreg;
HFC_2BDS0 += hfc_pci.o
endif
+ifeq ($(CONFIG_HISAX_HFC_SX),y)
+ HFC_2BDS0 += hfc_sx.o
+endif
+
ifeq ($(CONFIG_HISAX_NICCY),y)
O_OBJS += niccy.o
ISAC_OBJ := isac.o
-/* $Id: config.c,v 2.42 1999/12/19 13:09:41 keil Exp $
+/* $Id: config.c,v 2.43 2000/01/20 19:49:36 keil Exp $
* Author Karsten Keil (keil@isdn4linux.de)
* based on the teles driver from Jan den Ouden
*
*
* $Log: config.c,v $
+ * Revision 2.43 2000/01/20 19:49:36 keil
+ * Support teles 13.3c vendor version 2.1
+ *
* Revision 2.42 1999/12/19 13:09:41 keil
* changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for
* signal proof delays
*
+ * Revision 2.41 1999/11/18 00:00:43 werner
+ *
+ * Added support for HFC-S+ and HFC-SP cards
+ *
* Revision 2.40 1999/10/30 13:09:45 keil
* Version 3.3c
*
* 34 Gazel ISDN cards
* 35 HFC 2BDS0 PCI none
* 36 Winbond 6692 PCI none
+ * 37 HFC 2BDS0 S+/SP p0=irq p1=iobase
*
* protocol can be either ISDN_PTYPE_EURO or ISDN_PTYPE_1TR6 or ISDN_PTYPE_NI1
*
"AMD 7930", "NICCY", "S0Box", "AVM A1 (PCMCIA)", "AVM Fritz PnP/PCI",
"Sedlbauer Speed Fax +", "Siemens I-Surf", "Acer P10", "HST Saphir",
"Telekom A4T", "Scitel Quadro", "Gazel", "HFC 2BDS0 PCI", "Winbond 6692",
+ "HFC 2BDS0 SX",
};
void HiSax_closecard(int cardnr);
#define DEFAULT_CFG {0,0,0,0}
#endif
+#ifdef CONFIG_HISAX_HFC_SX
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_HFC_SX
+#define DEFAULT_CFG {5,0x2E0,0,0}
+#endif
+
#ifdef CONFIG_HISAX_AMD7930
#undef DEFAULT_CARD
printk(KERN_INFO "HiSax: Linux Driver for passive ISDN cards\n");
#ifdef MODULE
- printk(KERN_INFO "HiSax: Version 3.3c (module)\n");
+ printk(KERN_INFO "HiSax: Version 3.3d (module)\n");
#else
- printk(KERN_INFO "HiSax: Version 3.3c (kernel)\n");
+ printk(KERN_INFO "HiSax: Version 3.3d (kernel)\n");
#endif
strcpy(tmp, l1_revision);
printk(KERN_INFO "HiSax: Layer1 Revision %s\n", HiSax_getrev(tmp));
extern int setup_hfcpci(struct IsdnCard *card);
#endif
+#if CARD_HFC_SX
+extern int setup_hfcsx(struct IsdnCard *card);
+#endif
+
#if CARD_AMD7930
extern int setup_amd7930(struct IsdnCard *card);
#endif
ret = setup_hfcpci(card);
break;
#endif
+#if CARD_HFC_SX
+ case ISDN_CTYPE_HFC_SX:
+ ret = setup_hfcsx(card);
+ break;
+#endif
#if CARD_NICCY
case ISDN_CTYPE_NICCY:
ret = setup_niccy(card);
case ISDN_CTYPE_FRITZPCI:
case ISDN_CTYPE_HSTSAPHIR:
case ISDN_CTYPE_GAZEL:
+ case ISDN_CTYPE_HFC_SX:
cards[i].para[0] = irq[i];
cards[i].para[1] = io[i];
break;
--- /dev/null
+/* $Id: hfc_sx.c,v 1.3 2000/01/20 19:49:36 keil Exp $
+
+ * hfc_sx.c low level driver for CCD´s hfc-s+/sp based cards
+ *
+ * Author Werner Cornelius (werner@isdn4linux.de)
+ * based on existing driver for CCD HFC PCI cards
+ *
+ * Copyright 1999 by Werner Cornelius (werner@isdn4linux.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Log: hfc_sx.c,v $
+ * Revision 1.3 2000/01/20 19:49:36 keil
+ * Support teles 13.3c vendor version 2.1
+ *
+ * Revision 1.2 1999/12/19 13:09:42 keil
+ * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for
+ * signal proof delays
+ *
+ * Revision 1.1 1999/11/18 00:09:18 werner
+ *
+ * Initial release of files for HFC-S+ and HFC-SP cards with 32K-RAM.
+ * Audio and Echo are supported.
+ *
+ *
+ *
+ */
+
+#include <linux/config.h>
+#define __NO_VERSION__
+#include "hisax.h"
+#include "hfc_sx.h"
+#include "isdnl1.h"
+#include <linux/interrupt.h>
+
+extern const char *CardType[];
+
+static const char *hfcsx_revision = "$Revision: 1.3 $";
+
+/***************************************/
+/* IRQ-table for CCDs demo board */
+/* IRQs 6,5,10,11,12,15 are supported */
+/***************************************/
+
+/* Teles 16.3c Vendor Id TAG2620, Version 1.0, Vendor version 2.1
+ *
+ * Thanks to Uwe Wisniewski
+ *
+ * ISA-SLOT Signal PIN
+ * B25 IRQ3 92 IRQ_G
+ * B23 IRQ5 94 IRQ_A
+ * B4 IRQ2/9 95 IRQ_B
+ * D3 IRQ10 96 IRQ_C
+ * D4 IRQ11 97 IRQ_D
+ * D5 IRQ12 98 IRQ_E
+ * D6 IRQ15 99 IRQ_F
+ */
+
+#undef CCD_DEMO_BOARD
+#ifdef CCD_DEMO_BOARD
+static u_char ccd_sp_irqtab[16] = {
+ 0,0,0,0,0,2,1,0,0,0,3,4,5,0,0,6
+};
+#else /* Teles 16.3c */
+static u_char ccd_sp_irqtab[16] = {
+ 0,0,0,7,0,1,0,0,0,2,3,4,5,0,0,6
+};
+#endif
+#define NT_T1_COUNT 20 /* number of 3.125ms interrupts for G2 timeout */
+
+#define byteout(addr,val) outb(val,addr)
+#define bytein(addr) inb(addr)
+
+/******************************/
+/* In/Out access to registers */
+/******************************/
+static inline void
+Write_hfc(struct IsdnCardState *cs, u_char regnum, u_char val)
+{ register int flags;
+
+ save_flags(flags);
+ cli();
+ byteout(cs->hw.hfcsx.base+1, regnum);
+ byteout(cs->hw.hfcsx.base, val);
+ restore_flags(flags);
+}
+
+static inline u_char
+Read_hfc(struct IsdnCardState *cs, u_char regnum)
+{ register int flags;
+ register u_char ret;
+
+ save_flags(flags);
+ cli();
+ byteout(cs->hw.hfcsx.base+1, regnum);
+ ret = bytein(cs->hw.hfcsx.base);
+ restore_flags(flags);
+ return(ret);
+}
+
+
+/**************************************************/
+/* select a fifo and remember which one for reuse */
+/**************************************************/
+static void
+fifo_select(struct IsdnCardState *cs, u_char fifo)
+{ int flags;
+
+ if (fifo == cs->hw.hfcsx.last_fifo)
+ return; /* still valid */
+
+ save_flags(flags);
+ cli();
+ byteout(cs->hw.hfcsx.base+1, HFCSX_FIF_SEL);
+ byteout(cs->hw.hfcsx.base, fifo);
+ while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
+ udelay(4);
+ byteout(cs->hw.hfcsx.base, fifo);
+ while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
+ restore_flags(flags);
+}
+
+/******************************************/
+/* reset the specified fifo to defaults. */
+/* If its a send fifo init needed markers */
+/******************************************/
+static void
+reset_fifo(struct IsdnCardState *cs, u_char fifo)
+{ int flags;
+
+ save_flags(flags);
+ cli();
+ fifo_select(cs, fifo); /* first select the fifo */
+ byteout(cs->hw.hfcsx.base+1, HFCSX_CIRM);
+ byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.cirm | 0x80); /* reset cmd */
+ udelay(1);
+ while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
+ restore_flags(flags);
+}
+
+
+/*************************************************************/
+/* write_fifo writes the skb contents to the desired fifo */
+/* if no space is available or an error occurs 0 is returned */
+/* the skb is not released in any way. */
+/*************************************************************/
+static int
+write_fifo(struct IsdnCardState *cs, struct sk_buff *skb, u_char fifo, int trans_max)
+{ unsigned short *msp;
+ int fifo_size, count, z1, z2;
+ u_char f_msk, f1, f2, *src;
+
+ if (skb->len <= 0) return(0);
+ if (fifo & 1) return(0); /* no write fifo */
+
+ fifo_select(cs, fifo);
+ if (fifo & 4) {
+ fifo_size = D_FIFO_SIZE; /* D-channel */
+ f_msk = MAX_D_FRAMES;
+ if (trans_max) return(0); /* only HDLC */
+ }
+ else {
+ fifo_size = cs->hw.hfcsx.b_fifo_size; /* B-channel */
+ f_msk = MAX_B_FRAMES;
+ }
+
+ z1 = Read_hfc(cs, HFCSX_FIF_Z1H);
+ z1 = ((z1 << 8) | Read_hfc(cs, HFCSX_FIF_Z1L));
+
+ /* Check for transparent mode */
+ if (trans_max) {
+ z2 = Read_hfc(cs, HFCSX_FIF_Z2H);
+ z2 = ((z2 << 8) | Read_hfc(cs, HFCSX_FIF_Z2L));
+ count = z2 - z1;
+ if (count <= 0)
+ count += fifo_size; /* free bytes */
+ if (count < skb->len+1) return(0); /* no room */
+ count = fifo_size - count; /* bytes still not send */
+ if (count > 2 * trans_max) return(0); /* delay to long */
+ count = skb->len;
+ src = skb->data;
+ while (count--)
+ Write_hfc(cs, HFCSX_FIF_DWR, *src++);
+ return(1); /* success */
+ }
+
+ msp = ((struct hfcsx_extra *)(cs->hw.hfcsx.extra))->marker;
+ msp += (((fifo >> 1) & 3) * (MAX_B_FRAMES+1));
+ f1 = Read_hfc(cs, HFCSX_FIF_F1) & f_msk;
+ f2 = Read_hfc(cs, HFCSX_FIF_F2) & f_msk;
+
+ count = f1 - f2; /* frame count actually buffered */
+ if (count < 0)
+ count += (f_msk + 1); /* if wrap around */
+ if (count > f_msk-1) {
+ if (cs->debug & L1_DEB_ISAC_FIFO)
+ debugl1(cs, "hfcsx_write_fifo %d more as %d frames",fifo,f_msk-1);
+ return(0);
+ }
+
+ *(msp + f1) = z1; /* remember marker */
+
+ if (cs->debug & L1_DEB_ISAC_FIFO)
+ debugl1(cs, "hfcsx_write_fifo %d f1(%x) f2(%x) z1(f1)(%x)",
+ fifo, f1, f2, z1);
+ /* now determine free bytes in FIFO buffer */
+ count = *(msp + f2) - z1;
+ if (count <= 0)
+ count += fifo_size; /* count now contains available bytes */
+
+ if (cs->debug & L1_DEB_ISAC_FIFO)
+ debugl1(cs, "hfcsx_write_fifo %d count(%ld/%d)",
+ fifo, skb->len, count);
+ if (count < skb->len) {
+ if (cs->debug & L1_DEB_ISAC_FIFO)
+ debugl1(cs, "hfcsx_write_fifo %d no fifo mem", fifo);
+ return(0);
+ }
+
+ count = skb->len; /* get frame len */
+ src = skb->data; /* source pointer */
+ while (count--)
+ Write_hfc(cs, HFCSX_FIF_DWR, *src++);
+
+ Read_hfc(cs, HFCSX_FIF_INCF1); /* increment F1 */
+ udelay(1);
+ while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
+ return(1);
+}
+
+/***************************************************************/
+/* read_fifo reads data to an skb from the desired fifo */
+/* if no data is available or an error occurs NULL is returned */
+/* the skb is not released in any way. */
+/***************************************************************/
+static struct sk_buff *
+read_fifo(struct IsdnCardState *cs, u_char fifo, int trans_max)
+{ int fifo_size, count, z1, z2;
+ u_char f_msk, f1, f2, *dst;
+ struct sk_buff *skb;
+
+ if (!(fifo & 1)) return(NULL); /* no read fifo */
+ fifo_select(cs, fifo);
+ if (fifo & 4) {
+ fifo_size = D_FIFO_SIZE; /* D-channel */
+ f_msk = MAX_D_FRAMES;
+ if (trans_max) return(NULL); /* only hdlc */
+ }
+ else {
+ fifo_size = cs->hw.hfcsx.b_fifo_size; /* B-channel */
+ f_msk = MAX_B_FRAMES;
+ }
+
+ /* transparent mode */
+ if (trans_max) {
+ z1 = Read_hfc(cs, HFCSX_FIF_Z1H);
+ z1 = ((z1 << 8) | Read_hfc(cs, HFCSX_FIF_Z1L));
+ z2 = Read_hfc(cs, HFCSX_FIF_Z2H);
+ z2 = ((z2 << 8) | Read_hfc(cs, HFCSX_FIF_Z2L));
+ /* now determine bytes in actual FIFO buffer */
+ count = z1 - z2;
+ if (count <= 0)
+ count += fifo_size; /* count now contains buffered bytes */
+ count++;
+ if (count > trans_max)
+ count = trans_max; /* limit length */
+ if ((skb = dev_alloc_skb(count))) {
+ dst = skb_put(skb, count);
+ while (count--)
+ *dst++ = Read_hfc(cs, HFCSX_FIF_DRD);
+ return(skb);
+ }
+ else return(NULL); /* no memory */
+ }
+
+ do {
+ f1 = Read_hfc(cs, HFCSX_FIF_F1) & f_msk;
+ f2 = Read_hfc(cs, HFCSX_FIF_F2) & f_msk;
+
+ if (f1 == f2) return(NULL); /* no frame available */
+
+ z1 = Read_hfc(cs, HFCSX_FIF_Z1H);
+ z1 = ((z1 << 8) | Read_hfc(cs, HFCSX_FIF_Z1L));
+ z2 = Read_hfc(cs, HFCSX_FIF_Z2H);
+ z2 = ((z2 << 8) | Read_hfc(cs, HFCSX_FIF_Z2L));
+
+ if (cs->debug & L1_DEB_ISAC_FIFO)
+ debugl1(cs, "hfcsx_read_fifo %d f1(%x) f2(%x) z1(f2)(%x) z2(f2)(%x)",
+ fifo, f1, f2, z1, z2);
+ /* now determine bytes in actual FIFO buffer */
+ count = z1 - z2;
+ if (count <= 0)
+ count += fifo_size; /* count now contains buffered bytes */
+ count++;
+
+ if (cs->debug & L1_DEB_ISAC_FIFO)
+ debugl1(cs, "hfcsx_read_fifo %d count %ld)",
+ fifo, count);
+
+ if ((count > fifo_size) || (count < 4)) {
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "hfcsx_read_fifo %d paket inv. len %d ", fifo , count);
+ while (count) {
+ count--; /* empty fifo */
+ Read_hfc(cs, HFCSX_FIF_DRD);
+ }
+ skb = NULL;
+ } else
+ if ((skb = dev_alloc_skb(count - 3))) {
+ count -= 3;
+ dst = skb_put(skb, count);
+
+ while (count--)
+ *dst++ = Read_hfc(cs, HFCSX_FIF_DRD);
+
+ Read_hfc(cs, HFCSX_FIF_DRD); /* CRC 1 */
+ Read_hfc(cs, HFCSX_FIF_DRD); /* CRC 2 */
+ if (Read_hfc(cs, HFCSX_FIF_DRD)) {
+ dev_kfree_skb(skb);
+ if (cs->debug & L1_DEB_ISAC_FIFO)
+ debugl1(cs, "hfcsx_read_fifo %d crc error", fifo);
+ skb = NULL;
+ }
+ } else {
+ printk(KERN_WARNING "HFC-SX: receive out of memory\n");
+ return(NULL);
+ }
+
+ Read_hfc(cs, HFCSX_FIF_INCF2); /* increment F2 */
+ udelay(1);
+ while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */
+ udelay(1);
+ } while (!skb); /* retry in case of crc error */
+ return(skb);
+}
+
+/******************************************/
+/* free hardware resources used by driver */
+/******************************************/
+void
+release_io_hfcsx(struct IsdnCardState *cs)
+{
+ int flags;
+
+ save_flags(flags);
+ cli();
+ cs->hw.hfcsx.int_m2 = 0; /* interrupt output off ! */
+ Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
+ restore_flags(flags);
+ Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET); /* Reset On */
+ sti();
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */
+ Write_hfc(cs, HFCSX_CIRM, 0); /* Reset Off */
+ del_timer(&cs->hw.hfcsx.timer);
+ release_region(cs->hw.hfcsx.base, 2); /* release IO-Block */
+ kfree(cs->hw.hfcsx.extra);
+ cs->hw.hfcsx.extra = NULL;
+}
+
+/**********************************************************/
+/* set_fifo_size determines the size of the RAM and FIFOs */
+/* returning 0 -> need to reset the chip again. */
+/**********************************************************/
+static int set_fifo_size(struct IsdnCardState *cs)
+{
+
+ if (cs->hw.hfcsx.b_fifo_size) return(1); /* already determined */
+
+ if ((cs->hw.hfcsx.chip >> 4) == 9) {
+ cs->hw.hfcsx.b_fifo_size = B_FIFO_SIZE_32K;
+ return(1);
+ }
+
+ cs->hw.hfcsx.b_fifo_size = B_FIFO_SIZE_8K;
+ cs->hw.hfcsx.cirm |= 0x10; /* only 8K of ram */
+ return(0);
+
+}
+
+/********************************************************************************/
+/* function called to reset the HFC SX chip. A complete software reset of chip */
+/* and fifos is done. */
+/********************************************************************************/
+static void
+reset_hfcsx(struct IsdnCardState *cs)
+{
+ long flags;
+
+ save_flags(flags);
+ cli();
+ cs->hw.hfcsx.int_m2 = 0; /* interrupt output off ! */
+ Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
+
+ printk(KERN_INFO "HFC_SX: resetting card\n");
+ while (1) {
+ Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET | cs->hw.hfcsx.cirm ); /* Reset */
+ sti();
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */
+ Write_hfc(cs, HFCSX_CIRM, cs->hw.hfcsx.cirm); /* Reset Off */
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */
+ if (Read_hfc(cs, HFCSX_STATUS) & 2)
+ printk(KERN_WARNING "HFC-SX init bit busy\n");
+ cs->hw.hfcsx.last_fifo = 0xff; /* invalidate */
+ if (!set_fifo_size(cs)) continue;
+ break;
+ }
+
+ cs->hw.hfcsx.trm = 0 + HFCSX_BTRANS_THRESMASK; /* no echo connect , threshold */
+ Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm);
+
+ Write_hfc(cs, HFCSX_CLKDEL, 0x0e); /* ST-Bit delay for TE-Mode */
+ cs->hw.hfcsx.sctrl_e = HFCSX_AUTO_AWAKE;
+ Write_hfc(cs, HFCSX_SCTRL_E, cs->hw.hfcsx.sctrl_e); /* S/T Auto awake */
+ cs->hw.hfcsx.bswapped = 0; /* no exchange */
+ cs->hw.hfcsx.nt_mode = 0; /* we are in TE mode */
+ cs->hw.hfcsx.ctmt = HFCSX_TIM3_125 | HFCSX_AUTO_TIMER;
+ Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt);
+
+ cs->hw.hfcsx.int_m1 = HFCSX_INTS_DTRANS | HFCSX_INTS_DREC |
+ HFCSX_INTS_L1STATE | HFCSX_INTS_TIMER;
+ Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+
+ /* Clear already pending ints */
+ if (Read_hfc(cs, HFCSX_INT_S1));
+
+ Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 2); /* HFC ST 2 */
+ udelay(10);
+ Write_hfc(cs, HFCSX_STATES, 2); /* HFC ST 2 */
+ cs->hw.hfcsx.mst_m = HFCSX_MASTER; /* HFC Master Mode */
+
+ Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
+ cs->hw.hfcsx.sctrl = 0x40; /* set tx_lo mode, error in datasheet ! */
+ Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl);
+ cs->hw.hfcsx.sctrl_r = 0;
+ Write_hfc(cs, HFCSX_SCTRL_R, cs->hw.hfcsx.sctrl_r);
+
+ /* Init GCI/IOM2 in master mode */
+ /* Slots 0 and 1 are set for B-chan 1 and 2 */
+ /* D- and monitor/CI channel are not enabled */
+ /* STIO1 is used as output for data, B1+B2 from ST->IOM+HFC */
+ /* STIO2 is used as data input, B1+B2 from IOM->ST */
+ /* ST B-channel send disabled -> continous 1s */
+ /* The IOM slots are always enabled */
+ cs->hw.hfcsx.conn = 0x36; /* set data flow directions */
+ Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
+ Write_hfc(cs, HFCSX_B1_SSL, 0x80); /* B1-Slot 0 STIO1 out enabled */
+ Write_hfc(cs, HFCSX_B2_SSL, 0x81); /* B2-Slot 1 STIO1 out enabled */
+ Write_hfc(cs, HFCSX_B1_RSL, 0x80); /* B1-Slot 0 STIO2 in enabled */
+ Write_hfc(cs, HFCSX_B2_RSL, 0x81); /* B2-Slot 1 STIO2 in enabled */
+
+ /* Finally enable IRQ output */
+ cs->hw.hfcsx.int_m2 = HFCSX_IRQ_ENABLE;
+ Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
+ if (Read_hfc(cs, HFCSX_INT_S2));
+ restore_flags(flags);
+}
+
+/***************************************************/
+/* Timer function called when kernel timer expires */
+/***************************************************/
+static void
+hfcsx_Timer(struct IsdnCardState *cs)
+{
+ cs->hw.hfcsx.timer.expires = jiffies + 75;
+ /* WD RESET */
+/* WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcsx.ctmt | 0x80);
+ add_timer(&cs->hw.hfcsx.timer);
+ */
+}
+
+
+/*********************************/
+/* schedule a new D-channel task */
+/*********************************/
+static void
+sched_event_D_sx(struct IsdnCardState *cs, int event)
+{
+ test_and_set_bit(event, &cs->event);
+ queue_task(&cs->tqueue, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+}
+
+/*********************************/
+/* schedule a new b_channel task */
+/*********************************/
+static void
+hfcsx_sched_event(struct BCState *bcs, int event)
+{
+ bcs->event |= 1 << event;
+ queue_task(&bcs->tqueue, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+}
+
+/************************************************/
+/* select a b-channel entry matching and active */
+/************************************************/
+static
+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);
+}
+
+/*******************************/
+/* D-channel receive procedure */
+/*******************************/
+static
+int
+receive_dmsg(struct IsdnCardState *cs)
+{
+ struct sk_buff *skb;
+ int count = 5;
+
+ if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+ debugl1(cs, "rec_dmsg blocked");
+ return (1);
+ }
+
+ do {
+ skb = read_fifo(cs, HFCSX_SEL_D_RX, 0);
+ if (skb) {
+ skb_queue_tail(&cs->rq, skb);
+ sched_event_D_sx(cs, D_RCVBUFREADY);
+ }
+ } while (--count && skb);
+
+ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+ return (1);
+}
+
+/**********************************/
+/* B-channel main receive routine */
+/**********************************/
+void
+main_rec_hfcsx(struct BCState *bcs)
+{
+ long flags;
+ struct IsdnCardState *cs = bcs->cs;
+ int count = 5;
+ struct sk_buff *skb;
+
+ save_flags(flags);
+
+ Begin:
+ count--;
+ cli();
+ if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+ debugl1(cs, "rec_data %d blocked", bcs->channel);
+ restore_flags(flags);
+ return;
+ }
+ sti();
+ skb = read_fifo(cs, ((bcs->channel) && (!cs->hw.hfcsx.bswapped)) ?
+ HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX,
+ (bcs->mode == L1_MODE_TRANS) ?
+ HFCSX_BTRANS_THRESHOLD : 0);
+
+ if (skb) {
+ cli();
+ skb_queue_tail(&bcs->rqueue, skb);
+ sti();
+ hfcsx_sched_event(bcs, B_RCVBUFREADY);
+ }
+
+ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+ if (count && skb)
+ goto Begin;
+ restore_flags(flags);
+ return;
+}
+
+/**************************/
+/* D-channel send routine */
+/**************************/
+static void
+hfcsx_fill_dfifo(struct IsdnCardState *cs)
+{
+ if (!cs->tx_skb)
+ return;
+ if (cs->tx_skb->len <= 0)
+ return;
+
+ if (write_fifo(cs, cs->tx_skb, HFCSX_SEL_D_TX, 0)) {
+ dev_kfree_skb(cs->tx_skb);
+ cs->tx_skb = NULL;
+ }
+ return;
+}
+
+/**************************/
+/* B-channel send routine */
+/**************************/
+static void
+hfcsx_fill_fifo(struct BCState *bcs)
+{
+ struct IsdnCardState *cs = bcs->cs;
+ int flags;
+
+ if (!bcs->tx_skb)
+ return;
+ if (bcs->tx_skb->len <= 0)
+ return;
+
+ save_flags(flags);
+ sti();
+
+ if (write_fifo(cs, bcs->tx_skb,
+ ((bcs->channel) && (!cs->hw.hfcsx.bswapped)) ?
+ HFCSX_SEL_B2_TX : HFCSX_SEL_B1_TX,
+ (bcs->mode == L1_MODE_TRANS) ?
+ HFCSX_BTRANS_THRESHOLD : 0)) {
+
+ bcs->tx_cnt -= bcs->tx_skb->len;
+ if (bcs->st->lli.l1writewakeup &&
+ (PACKET_NOACK != bcs->tx_skb->pkt_type))
+ bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
+ dev_kfree_skb(bcs->tx_skb);
+ bcs->tx_skb = NULL;
+ test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+ }
+
+ cli();
+ restore_flags(flags);
+ return;
+}
+
+/**********************************************/
+/* D-channel l1 state call for leased NT-mode */
+/**********************************************/
+static void
+dch_nt_l2l1(struct PStack *st, int pr, void *arg)
+{
+ struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
+
+ switch (pr) {
+ case (PH_DATA | REQUEST):
+ case (PH_PULL | REQUEST):
+ case (PH_PULL | INDICATION):
+ st->l1.l1hw(st, pr, arg);
+ break;
+ case (PH_ACTIVATE | REQUEST):
+ st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
+ break;
+ case (PH_TESTLOOP | REQUEST):
+ if (1 & (long) arg)
+ debugl1(cs, "PH_TEST_LOOP B1");
+ if (2 & (long) arg)
+ debugl1(cs, "PH_TEST_LOOP B2");
+ if (!(3 & (long) arg))
+ debugl1(cs, "PH_TEST_LOOP DISABLED");
+ st->l1.l1hw(st, HW_TESTLOOP | REQUEST, arg);
+ break;
+ default:
+ if (cs->debug)
+ debugl1(cs, "dch_nt_l2l1 msg %04X unhandled", pr);
+ break;
+ }
+}
+
+
+
+/***********************/
+/* set/reset echo mode */
+/***********************/
+static int
+hfcsx_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic)
+{
+ int flags;
+ int i = *(unsigned int *) ic->parm.num;
+
+ if ((ic->arg == 98) &&
+ (!(cs->hw.hfcsx.int_m1 & (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC + HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC)))) {
+ save_flags(flags);
+ cli();
+ Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 0); /* HFC ST G0 */
+ udelay(10);
+ cs->hw.hfcsx.sctrl |= SCTRL_MODE_NT;
+ Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl); /* set NT-mode */
+ udelay(10);
+ Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 1); /* HFC ST G1 */
+ udelay(10);
+ Write_hfc(cs, HFCSX_STATES, 1 | HFCSX_ACTIVATE | HFCSX_DO_ACTION);
+ cs->dc.hfcsx.ph_state = 1;
+ cs->hw.hfcsx.nt_mode = 1;
+ cs->hw.hfcsx.nt_timer = 0;
+ cs->stlist->l2.l2l1 = dch_nt_l2l1;
+ restore_flags(flags);
+ debugl1(cs, "NT mode activated");
+ return (0);
+ }
+ if ((cs->chanlimit > 1) || (cs->hw.hfcsx.bswapped) ||
+ (cs->hw.hfcsx.nt_mode) || (ic->arg != 12))
+ return (-EINVAL);
+
+ save_flags(flags);
+ cli();
+ if (i) {
+ cs->logecho = 1;
+ cs->hw.hfcsx.trm |= 0x20; /* enable echo chan */
+ cs->hw.hfcsx.int_m1 |= HFCSX_INTS_B2REC;
+ /* reset Channel !!!!! */
+ } else {
+ cs->logecho = 0;
+ cs->hw.hfcsx.trm &= ~0x20; /* disable echo chan */
+ cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_B2REC;
+ }
+ cs->hw.hfcsx.sctrl_r &= ~SCTRL_B2_ENA;
+ cs->hw.hfcsx.sctrl &= ~SCTRL_B2_ENA;
+ cs->hw.hfcsx.conn |= 0x10; /* B2-IOM -> B2-ST */
+ cs->hw.hfcsx.ctmt &= ~2;
+ Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt);
+ Write_hfc(cs, HFCSX_SCTRL_R, cs->hw.hfcsx.sctrl_r);
+ Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl);
+ Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
+ Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm);
+ Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+ restore_flags(flags);
+ return (0);
+} /* hfcsx_auxcmd */
+
+/*****************************/
+/* E-channel receive routine */
+/*****************************/
+static void
+receive_emsg(struct IsdnCardState *cs)
+{
+ int flags;
+ int count = 5;
+ u_char *ptr;
+ struct sk_buff *skb;
+
+
+ save_flags(flags);
+ cli();
+ if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+ debugl1(cs, "echo_rec_data blocked");
+ restore_flags(flags);
+ return;
+ }
+ sti();
+
+ do {
+ skb = read_fifo(cs, HFCSX_SEL_B2_RX, 0);
+ if (skb) {
+ if (cs->debug & DEB_DLOG_HEX) {
+ ptr = cs->dlog;
+ if ((skb->len) < MAX_DLOG_SPACE / 3 - 10) {
+ *ptr++ = 'E';
+ *ptr++ = 'C';
+ *ptr++ = 'H';
+ *ptr++ = 'O';
+ *ptr++ = ':';
+ ptr += QuickHex(ptr, skb->data, skb->len);
+ ptr--;
+ *ptr++ = '\n';
+ *ptr = 0;
+ HiSax_putstatus(cs, NULL, cs->dlog);
+ } else
+ HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", skb->len);
+ }
+ dev_kfree_skb(skb);
+ }
+ } while (--count && skb);
+
+ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+ restore_flags(flags);
+ return;
+} /* receive_emsg */
+
+
+/*********************/
+/* Interrupt handler */
+/*********************/
+static void
+hfcsx_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+ struct IsdnCardState *cs = dev_id;
+ u_char exval;
+ struct BCState *bcs;
+ int count = 15;
+ long flags;
+ u_char val, stat;
+
+ if (!cs) {
+ printk(KERN_WARNING "HFC-SX: Spurious interrupt!\n");
+ return;
+ }
+ if (!(cs->hw.hfcsx.int_m2 & 0x08))
+ return; /* not initialised */
+
+ if (HFCSX_ANYINT & (stat = Read_hfc(cs, HFCSX_STATUS))) {
+ val = Read_hfc(cs, HFCSX_INT_S1);
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "HFC-SX: stat(%02x) s1(%02x)", stat, val);
+ } else
+ return;
+
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "HFC-SX irq %x %s", val,
+ test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
+ "locked" : "unlocked");
+ val &= cs->hw.hfcsx.int_m1;
+ if (val & 0x40) { /* state machine irq */
+ exval = Read_hfc(cs, HFCSX_STATES) & 0xf;
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcsx.ph_state,
+ exval);
+ cs->dc.hfcsx.ph_state = exval;
+ sched_event_D_sx(cs, D_L1STATECHANGE);
+ val &= ~0x40;
+ }
+ if (val & 0x80) { /* timer irq */
+ if (cs->hw.hfcsx.nt_mode) {
+ if ((--cs->hw.hfcsx.nt_timer) < 0)
+ sched_event_D_sx(cs, D_L1STATECHANGE);
+ }
+ val &= ~0x80;
+ Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER);
+ }
+ while (val) {
+ save_flags(flags);
+ cli();
+ if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+ cs->hw.hfcsx.int_s1 |= val;
+ restore_flags(flags);
+ return;
+ }
+ if (cs->hw.hfcsx.int_s1 & 0x18) {
+ exval = val;
+ val = cs->hw.hfcsx.int_s1;
+ cs->hw.hfcsx.int_s1 = exval;
+ }
+ if (val & 0x08) {
+ if (!(bcs = Sel_BCS(cs, cs->hw.hfcsx.bswapped ? 1 : 0))) {
+ if (cs->debug)
+ debugl1(cs, "hfcsx spurious 0x08 IRQ");
+ } else
+ main_rec_hfcsx(bcs);
+ }
+ if (val & 0x10) {
+ if (cs->logecho)
+ receive_emsg(cs);
+ else if (!(bcs = Sel_BCS(cs, 1))) {
+ if (cs->debug)
+ debugl1(cs, "hfcsx spurious 0x10 IRQ");
+ } else
+ main_rec_hfcsx(bcs);
+ }
+ if (val & 0x01) {
+ if (!(bcs = Sel_BCS(cs, cs->hw.hfcsx.bswapped ? 1 : 0))) {
+ if (cs->debug)
+ debugl1(cs, "hfcsx spurious 0x01 IRQ");
+ } else {
+ if (bcs->tx_skb) {
+ if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+ hfcsx_fill_fifo(bcs);
+ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+ } else
+ debugl1(cs, "fill_data %d blocked", bcs->channel);
+ } else {
+ if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+ if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+ hfcsx_fill_fifo(bcs);
+ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+ } else
+ debugl1(cs, "fill_data %d blocked", bcs->channel);
+ } else {
+ hfcsx_sched_event(bcs, B_XMTBUFREADY);
+ }
+ }
+ }
+ }
+ if (val & 0x02) {
+ if (!(bcs = Sel_BCS(cs, 1))) {
+ if (cs->debug)
+ debugl1(cs, "hfcsx spurious 0x02 IRQ");
+ } else {
+ if (bcs->tx_skb) {
+ if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+ hfcsx_fill_fifo(bcs);
+ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+ } else
+ debugl1(cs, "fill_data %d blocked", bcs->channel);
+ } else {
+ if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+ if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+ hfcsx_fill_fifo(bcs);
+ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+ } else
+ debugl1(cs, "fill_data %d blocked", bcs->channel);
+ } else {
+ hfcsx_sched_event(bcs, B_XMTBUFREADY);
+ }
+ }
+ }
+ }
+ if (val & 0x20) { /* receive dframe */
+ receive_dmsg(cs);
+ }
+ if (val & 0x04) { /* dframe transmitted */
+ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+ del_timer(&cs->dbusytimer);
+ if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+ sched_event_D_sx(cs, D_CLEARBUSY);
+ if (cs->tx_skb) {
+ if (cs->tx_skb->len) {
+ if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+ hfcsx_fill_dfifo(cs);
+ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+ } else {
+ debugl1(cs, "hfcsx_fill_dfifo irq blocked");
+ }
+ goto afterXPR;
+ } else {
+ dev_kfree_skb(cs->tx_skb);
+ cs->tx_cnt = 0;
+ cs->tx_skb = NULL;
+ }
+ }
+ if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
+ cs->tx_cnt = 0;
+ if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+ hfcsx_fill_dfifo(cs);
+ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+ } else {
+ debugl1(cs, "hfcsx_fill_dfifo irq blocked");
+ }
+ } else
+ sched_event_D_sx(cs, D_XMTBUFREADY);
+ }
+ afterXPR:
+ if (cs->hw.hfcsx.int_s1 && count--) {
+ val = cs->hw.hfcsx.int_s1;
+ cs->hw.hfcsx.int_s1 = 0;
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "HFC-SX irq %x loop %d", val, 15 - count);
+ } else
+ val = 0;
+ restore_flags(flags);
+ }
+}
+
+/********************************************************************/
+/* timer callback for D-chan busy resolution. Currently no function */
+/********************************************************************/
+static void
+hfcsx_dbusy_timer(struct IsdnCardState *cs)
+{
+}
+
+/*************************************/
+/* Layer 1 D-channel hardware access */
+/*************************************/
+static void
+HFCSX_l1hw(struct PStack *st, int pr, void *arg)
+{
+ struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
+ struct sk_buff *skb = arg;
+ int flags;
+
+ switch (pr) {
+ case (PH_DATA | REQUEST):
+ if (cs->debug & DEB_DLOG_HEX)
+ LogFrame(cs, skb->data, skb->len);
+ if (cs->debug & DEB_DLOG_VERBOSE)
+ dlogframe(cs, skb, 0);
+ if (cs->tx_skb) {
+ skb_queue_tail(&cs->sq, skb);
+#ifdef L2FRAME_DEBUG /* psa */
+ if (cs->debug & L1_DEB_LAPD)
+ Logl2Frame(cs, skb, "PH_DATA Queued", 0);
+#endif
+ } else {
+ cs->tx_skb = skb;
+ cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG /* psa */
+ if (cs->debug & L1_DEB_LAPD)
+ Logl2Frame(cs, skb, "PH_DATA", 0);
+#endif
+ if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+ hfcsx_fill_dfifo(cs);
+ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+ } else
+ debugl1(cs, "hfcsx_fill_dfifo blocked");
+
+ }
+ break;
+ case (PH_PULL | INDICATION):
+ if (cs->tx_skb) {
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
+ skb_queue_tail(&cs->sq, skb);
+ break;
+ }
+ if (cs->debug & DEB_DLOG_HEX)
+ LogFrame(cs, skb->data, skb->len);
+ if (cs->debug & DEB_DLOG_VERBOSE)
+ dlogframe(cs, skb, 0);
+ cs->tx_skb = skb;
+ cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG /* psa */
+ if (cs->debug & L1_DEB_LAPD)
+ Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
+#endif
+ if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+ hfcsx_fill_dfifo(cs);
+ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+ } else
+ debugl1(cs, "hfcsx_fill_dfifo blocked");
+ break;
+ case (PH_PULL | REQUEST):
+#ifdef L2FRAME_DEBUG /* psa */
+ if (cs->debug & L1_DEB_LAPD)
+ debugl1(cs, "-> PH_REQUEST_PULL");
+#endif
+ if (!cs->tx_skb) {
+ test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+ st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+ } else
+ test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+ break;
+ case (HW_RESET | REQUEST):
+ Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 3); /* HFC ST 3 */
+ udelay(6);
+ Write_hfc(cs, HFCSX_STATES, 3); /* HFC ST 2 */
+ cs->hw.hfcsx.mst_m |= HFCSX_MASTER;
+ Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
+ Write_hfc(cs, HFCSX_STATES, HFCSX_ACTIVATE | HFCSX_DO_ACTION);
+ l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
+ break;
+ case (HW_ENABLE | REQUEST):
+ Write_hfc(cs, HFCSX_STATES, HFCSX_ACTIVATE | HFCSX_DO_ACTION);
+ break;
+ case (HW_DEACTIVATE | REQUEST):
+ cs->hw.hfcsx.mst_m &= ~HFCSX_MASTER;
+ Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
+ break;
+ case (HW_INFO3 | REQUEST):
+ cs->hw.hfcsx.mst_m |= HFCSX_MASTER;
+ Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
+ break;
+ case (HW_TESTLOOP | REQUEST):
+ switch ((int) arg) {
+ case (1):
+ Write_hfc(cs, HFCSX_B1_SSL, 0x80); /* tx slot */
+ Write_hfc(cs, HFCSX_B1_RSL, 0x80); /* rx slot */
+ save_flags(flags);
+ cli();
+ cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~7) | 1;
+ Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
+ restore_flags(flags);
+ break;
+
+ case (2):
+ Write_hfc(cs, HFCSX_B2_SSL, 0x81); /* tx slot */
+ Write_hfc(cs, HFCSX_B2_RSL, 0x81); /* rx slot */
+ save_flags(flags);
+ cli();
+ cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~0x38) | 0x08;
+ Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
+ restore_flags(flags);
+ break;
+
+ default:
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "hfcsx_l1hw loop invalid %4x", (int) arg);
+ return;
+ }
+ save_flags(flags);
+ cli();
+ cs->hw.hfcsx.trm |= 0x80; /* enable IOM-loop */
+ Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm);
+ restore_flags(flags);
+ break;
+ default:
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "hfcsx_l1hw unknown pr %4x", pr);
+ break;
+ }
+}
+
+/***********************************************/
+/* called during init setting l1 stack pointer */
+/***********************************************/
+void
+setstack_hfcsx(struct PStack *st, struct IsdnCardState *cs)
+{
+ st->l1.l1hw = HFCSX_l1hw;
+}
+
+/**************************************/
+/* send B-channel data if not blocked */
+/**************************************/
+static void
+hfcsx_send_data(struct BCState *bcs)
+{
+ struct IsdnCardState *cs = bcs->cs;
+
+ if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+ hfcsx_fill_fifo(bcs);
+ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+ } else
+ debugl1(cs, "send_data %d blocked", bcs->channel);
+}
+
+/***************************************************************/
+/* activate/deactivate hardware for selected channels and mode */
+/***************************************************************/
+void
+mode_hfcsx(struct BCState *bcs, int mode, int bc)
+{
+ struct IsdnCardState *cs = bcs->cs;
+ int flags, fifo2;
+
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "HFCSX bchannel mode %d bchan %d/%d",
+ mode, bc, bcs->channel);
+ bcs->mode = mode;
+ bcs->channel = bc;
+ fifo2 = bc;
+ save_flags(flags);
+ cli();
+ if (cs->chanlimit > 1) {
+ cs->hw.hfcsx.bswapped = 0; /* B1 and B2 normal mode */
+ cs->hw.hfcsx.sctrl_e &= ~0x80;
+ } else {
+ if (bc) {
+ if (mode != L1_MODE_NULL) {
+ cs->hw.hfcsx.bswapped = 1; /* B1 and B2 exchanged */
+ cs->hw.hfcsx.sctrl_e |= 0x80;
+ } else {
+ cs->hw.hfcsx.bswapped = 0; /* B1 and B2 normal mode */
+ cs->hw.hfcsx.sctrl_e &= ~0x80;
+ }
+ fifo2 = 0;
+ } else {
+ cs->hw.hfcsx.bswapped = 0; /* B1 and B2 normal mode */
+ cs->hw.hfcsx.sctrl_e &= ~0x80;
+ }
+ }
+ switch (mode) {
+ case (L1_MODE_NULL):
+ if (bc) {
+ cs->hw.hfcsx.sctrl &= ~SCTRL_B2_ENA;
+ cs->hw.hfcsx.sctrl_r &= ~SCTRL_B2_ENA;
+ } else {
+ cs->hw.hfcsx.sctrl &= ~SCTRL_B1_ENA;
+ cs->hw.hfcsx.sctrl_r &= ~SCTRL_B1_ENA;
+ }
+ if (fifo2) {
+ cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC);
+ } else {
+ cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC);
+ }
+ break;
+ case (L1_MODE_TRANS):
+ if (bc) {
+ cs->hw.hfcsx.sctrl |= SCTRL_B2_ENA;
+ cs->hw.hfcsx.sctrl_r |= SCTRL_B2_ENA;
+ } else {
+ cs->hw.hfcsx.sctrl |= SCTRL_B1_ENA;
+ cs->hw.hfcsx.sctrl_r |= SCTRL_B1_ENA;
+ }
+ if (fifo2) {
+ cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC);
+ cs->hw.hfcsx.ctmt |= 2;
+ cs->hw.hfcsx.conn &= ~0x18;
+ } else {
+ cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC);
+ cs->hw.hfcsx.ctmt |= 1;
+ cs->hw.hfcsx.conn &= ~0x03;
+ }
+ break;
+ case (L1_MODE_HDLC):
+ if (bc) {
+ cs->hw.hfcsx.sctrl |= SCTRL_B2_ENA;
+ cs->hw.hfcsx.sctrl_r |= SCTRL_B2_ENA;
+ } else {
+ cs->hw.hfcsx.sctrl |= SCTRL_B1_ENA;
+ cs->hw.hfcsx.sctrl_r |= SCTRL_B1_ENA;
+ }
+ if (fifo2) {
+ cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC);
+ cs->hw.hfcsx.ctmt &= ~2;
+ cs->hw.hfcsx.conn &= ~0x18;
+ } else {
+ cs->hw.hfcsx.int_m1 |= (HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC);
+ cs->hw.hfcsx.ctmt &= ~1;
+ cs->hw.hfcsx.conn &= ~0x03;
+ }
+ break;
+ case (L1_MODE_EXTRN):
+ if (bc) {
+ cs->hw.hfcsx.conn |= 0x10;
+ cs->hw.hfcsx.sctrl |= SCTRL_B2_ENA;
+ cs->hw.hfcsx.sctrl_r |= SCTRL_B2_ENA;
+ cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC);
+ } else {
+ cs->hw.hfcsx.conn |= 0x02;
+ cs->hw.hfcsx.sctrl |= SCTRL_B1_ENA;
+ cs->hw.hfcsx.sctrl_r |= SCTRL_B1_ENA;
+ cs->hw.hfcsx.int_m1 &= ~(HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC);
+ }
+ break;
+ }
+ Write_hfc(cs, HFCSX_SCTRL_E, cs->hw.hfcsx.sctrl_e);
+ Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+ Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl);
+ Write_hfc(cs, HFCSX_SCTRL_R, cs->hw.hfcsx.sctrl_r);
+ Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt);
+ Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
+ if (mode != L1_MODE_EXTRN) {
+ reset_fifo(cs, fifo2 ? HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX);
+ reset_fifo(cs, fifo2 ? HFCSX_SEL_B2_TX : HFCSX_SEL_B1_TX);
+ }
+ restore_flags(flags);
+}
+
+/******************************/
+/* Layer2 -> Layer 1 Transfer */
+/******************************/
+static void
+hfcsx_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->cs->BC_Send_Data(st->l1.bcs);
+ restore_flags(flags);
+ }
+ break;
+ case (PH_PULL | INDICATION):
+ if (st->l1.bcs->tx_skb) {
+ printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
+ break;
+ }
+ save_flags(flags);
+ cli();
+/* test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ */ st->l1.bcs->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->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);
+ mode_hfcsx(st->l1.bcs, st->l1.mode, st->l1.bc);
+ l1_msg_b(st, pr, arg);
+ break;
+ case (PH_DEACTIVATE | REQUEST):
+ l1_msg_b(st, pr, arg);
+ break;
+ case (PH_DEACTIVATE | CONFIRM):
+ test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+ test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ mode_hfcsx(st->l1.bcs, 0, st->l1.bc);
+ st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+ break;
+ }
+}
+
+/******************************************/
+/* deactivate B-channel access and queues */
+/******************************************/
+static void
+close_hfcsx(struct BCState *bcs)
+{
+ mode_hfcsx(bcs, 0, bcs->channel);
+ if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
+ discard_queue(&bcs->rqueue);
+ discard_queue(&bcs->squeue);
+ if (bcs->tx_skb) {
+ dev_kfree_skb(bcs->tx_skb);
+ bcs->tx_skb = NULL;
+ test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+ }
+ }
+}
+
+/*************************************/
+/* init B-channel queues and control */
+/*************************************/
+static int
+open_hfcsxstate(struct IsdnCardState *cs, struct BCState *bcs)
+{
+ if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
+ 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->tx_cnt = 0;
+ return (0);
+}
+
+/*********************************/
+/* inits the stack for B-channel */
+/*********************************/
+static int
+setstack_2b(struct PStack *st, struct BCState *bcs)
+{
+ bcs->channel = st->l1.bc;
+ if (open_hfcsxstate(st->l1.hardware, bcs))
+ return (-1);
+ st->l1.bcs = bcs;
+ st->l2.l2l1 = hfcsx_l2l1;
+ setstack_manager(st);
+ bcs->st = st;
+ setstack_l1_B(st);
+ return (0);
+}
+
+/***************************/
+/* handle L1 state changes */
+/***************************/
+static void
+hfcsx_bh(struct IsdnCardState *cs)
+{
+ int flags;
+/* struct PStack *stptr;
+ */
+ if (!cs)
+ return;
+ if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
+ if (!cs->hw.hfcsx.nt_mode)
+ switch (cs->dc.hfcsx.ph_state) {
+ case (0):
+ l1_msg(cs, HW_RESET | INDICATION, NULL);
+ break;
+ case (3):
+ l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
+ break;
+ case (8):
+ l1_msg(cs, HW_RSYNC | INDICATION, NULL);
+ break;
+ case (6):
+ l1_msg(cs, HW_INFO2 | INDICATION, NULL);
+ break;
+ case (7):
+ l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
+ break;
+ default:
+ break;
+ } else {
+ switch (cs->dc.hfcsx.ph_state) {
+ case (2):
+ save_flags(flags);
+ cli();
+ if (cs->hw.hfcsx.nt_timer < 0) {
+ cs->hw.hfcsx.nt_timer = 0;
+ cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
+ Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+ /* Clear already pending ints */
+ if (Read_hfc(cs, HFCSX_INT_S1));
+
+ Write_hfc(cs, HFCSX_STATES, 4 | HFCSX_LOAD_STATE);
+ udelay(10);
+ Write_hfc(cs, HFCSX_STATES, 4);
+ cs->dc.hfcsx.ph_state = 4;
+ } else {
+ cs->hw.hfcsx.int_m1 |= HFCSX_INTS_TIMER;
+ Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+ cs->hw.hfcsx.ctmt &= ~HFCSX_AUTO_TIMER;
+ cs->hw.hfcsx.ctmt |= HFCSX_TIM3_125;
+ Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER);
+ Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER);
+ cs->hw.hfcsx.nt_timer = NT_T1_COUNT;
+ Write_hfc(cs, HFCSX_STATES, 2 | HFCSX_NT_G2_G3); /* allow G2 -> G3 transition */
+ }
+ restore_flags(flags);
+ break;
+ case (1):
+ case (3):
+ case (4):
+ save_flags(flags);
+ cli();
+ cs->hw.hfcsx.nt_timer = 0;
+ cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
+ Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+ restore_flags(flags);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
+ DChannel_proc_rcv(cs);
+ if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
+ DChannel_proc_xmt(cs);
+}
+
+
+/********************************/
+/* called for card init message */
+/********************************/
+__initfunc(void
+ inithfcsx(struct IsdnCardState *cs))
+{
+ cs->setstack_d = setstack_hfcsx;
+ cs->dbusytimer.function = (void *) hfcsx_dbusy_timer;
+ cs->dbusytimer.data = (long) cs;
+ init_timer(&cs->dbusytimer);
+ cs->tqueue.routine = (void *) (void *) hfcsx_bh;
+ cs->BC_Send_Data = &hfcsx_send_data;
+ cs->bcs[0].BC_SetStack = setstack_2b;
+ cs->bcs[1].BC_SetStack = setstack_2b;
+ cs->bcs[0].BC_Close = close_hfcsx;
+ cs->bcs[1].BC_Close = close_hfcsx;
+ mode_hfcsx(cs->bcs, 0, 0);
+ mode_hfcsx(cs->bcs + 1, 0, 1);
+}
+
+
+
+/*******************************************/
+/* handle card messages from control layer */
+/*******************************************/
+static int
+hfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+ long flags;
+
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "HFCSX: card_msg %x", mt);
+ switch (mt) {
+ case CARD_RESET:
+ reset_hfcsx(cs);
+ return (0);
+ case CARD_RELEASE:
+ release_io_hfcsx(cs);
+ return (0);
+ case CARD_INIT:
+ inithfcsx(cs);
+ save_flags(flags);
+ sti();
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */
+ /* now switch timer interrupt off */
+ cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER;
+ Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+ /* reinit mode reg */
+ Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);
+ restore_flags(flags);
+ return (0);
+ case CARD_TEST:
+ return (0);
+ }
+ return (0);
+}
+
+
+
+__initfunc(int
+ setup_hfcsx(struct IsdnCard *card))
+{
+ struct IsdnCardState *cs = card->cs;
+ char tmp[64];
+ int flags;
+
+ strcpy(tmp, hfcsx_revision);
+ printk(KERN_INFO "HiSax: HFC-SX driver Rev. %s\n", HiSax_getrev(tmp));
+ cs->hw.hfcsx.base = card->para[1] & 0xfffe;
+ cs->irq = card->para[0];
+ cs->hw.hfcsx.int_s1 = 0;
+ cs->dc.hfcsx.ph_state = 0;
+ cs->hw.hfcsx.fifo = 255;
+ if (cs->typ == ISDN_CTYPE_HFC_SX) {
+ if ((!cs->hw.hfcsx.base) ||
+ check_region((cs->hw.hfcsx.base), 2)) {
+ printk(KERN_WARNING
+ "HiSax: HFC-SX io-base 0x%x already in use\n",
+ cs->hw.hfcsx.base);
+ return(0);
+ } else {
+ request_region(cs->hw.hfcsx.base, 2, "HFCSX isdn");
+ }
+ byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF);
+ byteout(cs->hw.hfcsx.base + 1,
+ ((cs->hw.hfcsx.base >> 8) & 3) | 0x54);
+ udelay(10);
+ cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID);
+ switch (cs->hw.hfcsx.chip >> 4) {
+ case 1:
+ tmp[0] ='+';
+ break;
+ case 9:
+ tmp[0] ='P';
+ break;
+ default:
+ printk(KERN_WARNING
+ "HFC-SX: invalid chip id 0x%x\n",
+ cs->hw.hfcsx.chip >> 4);
+ release_region(cs->hw.hfcsx.base, 2);
+ return(0);
+ }
+ if (!ccd_sp_irqtab[cs->irq & 0xF]) {
+ printk(KERN_WARNING
+ "HFC_SX: invalid irq %d specified\n",cs->irq & 0xF);
+ release_region(cs->hw.hfcsx.base, 2);
+ return(0);
+ }
+ save_flags(flags);
+ cli();
+ if (!(cs->hw.hfcsx.extra = (void *)
+ kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC))) {
+ restore_flags(flags);
+ release_region(cs->hw.hfcsx.base, 2);
+ printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");
+ return(0);
+ }
+ restore_flags(flags);
+
+ printk(KERN_INFO
+ "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n",
+ tmp[0], (u_int) cs->hw.hfcsx.base,
+ cs->irq, HZ);
+ cs->hw.hfcsx.int_m2 = 0; /* disable alle interrupts */
+ cs->hw.hfcsx.int_m1 = 0;
+ Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
+ Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
+ } else
+ return (0); /* no valid card type */
+
+ cs->readisac = NULL;
+ cs->writeisac = NULL;
+ cs->readisacfifo = NULL;
+ cs->writeisacfifo = NULL;
+ cs->BC_Read_Reg = NULL;
+ cs->BC_Write_Reg = NULL;
+ cs->irq_func = &hfcsx_interrupt;
+
+ cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer;
+ cs->hw.hfcsx.timer.data = (long) cs;
+ cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */
+ cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not evaluated */
+ init_timer(&cs->hw.hfcsx.timer);
+
+ reset_hfcsx(cs);
+ cs->cardmsg = &hfcsx_card_msg;
+ cs->auxcmd = &hfcsx_auxcmd;
+ return (1);
+}
+
+
+
+
--- /dev/null
+/* $Id: hfc_sx.h,v 1.1 1999/11/18 00:09:18 werner Exp $
+
+ * specific defines for CCD's HFC 2BDS0 S+,SP chips
+ *
+ * Author Werner Cornelius (werner@isdn4linux.de)
+ *
+ * Copyright 1999 by Werner Cornelius (werner@isdn4linux.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Log: hfc_sx.h,v $
+ * Revision 1.1 1999/11/18 00:09:18 werner
+ *
+ * Initial release of files for HFC-S+ and HFC-SP cards with 32K-RAM.
+ * Audio and Echo are supported.
+ *
+ *
+ *
+ */
+
+/*********************************************/
+/* thresholds for transparent B-channel mode */
+/* change mask and threshold simultaneously */
+/*********************************************/
+#define HFCSX_BTRANS_THRESHOLD 128
+#define HFCSX_BTRANS_THRESMASK 0x00
+
+/* GCI/IOM bus monitor registers */
+
+#define HFCSX_C_I 0x02
+#define HFCSX_TRxR 0x03
+#define HFCSX_MON1_D 0x0A
+#define HFCSX_MON2_D 0x0B
+
+
+/* GCI/IOM bus timeslot registers */
+
+#define HFCSX_B1_SSL 0x20
+#define HFCSX_B2_SSL 0x21
+#define HFCSX_AUX1_SSL 0x22
+#define HFCSX_AUX2_SSL 0x23
+#define HFCSX_B1_RSL 0x24
+#define HFCSX_B2_RSL 0x25
+#define HFCSX_AUX1_RSL 0x26
+#define HFCSX_AUX2_RSL 0x27
+
+/* GCI/IOM bus data registers */
+
+#define HFCSX_B1_D 0x28
+#define HFCSX_B2_D 0x29
+#define HFCSX_AUX1_D 0x2A
+#define HFCSX_AUX2_D 0x2B
+
+/* GCI/IOM bus configuration registers */
+
+#define HFCSX_MST_EMOD 0x2D
+#define HFCSX_MST_MODE 0x2E
+#define HFCSX_CONNECT 0x2F
+
+
+/* Interrupt and status registers */
+
+#define HFCSX_TRM 0x12
+#define HFCSX_B_MODE 0x13
+#define HFCSX_CHIP_ID 0x16
+#define HFCSX_CIRM 0x18
+#define HFCSX_CTMT 0x19
+#define HFCSX_INT_M1 0x1A
+#define HFCSX_INT_M2 0x1B
+#define HFCSX_INT_S1 0x1E
+#define HFCSX_INT_S2 0x1F
+#define HFCSX_STATUS 0x1C
+
+/* S/T section registers */
+
+#define HFCSX_STATES 0x30
+#define HFCSX_SCTRL 0x31
+#define HFCSX_SCTRL_E 0x32
+#define HFCSX_SCTRL_R 0x33
+#define HFCSX_SQ 0x34
+#define HFCSX_CLKDEL 0x37
+#define HFCSX_B1_REC 0x3C
+#define HFCSX_B1_SEND 0x3C
+#define HFCSX_B2_REC 0x3D
+#define HFCSX_B2_SEND 0x3D
+#define HFCSX_D_REC 0x3E
+#define HFCSX_D_SEND 0x3E
+#define HFCSX_E_REC 0x3F
+
+/****************/
+/* FIFO section */
+/****************/
+#define HFCSX_FIF_SEL 0x10
+#define HFCSX_FIF_Z1L 0x80
+#define HFCSX_FIF_Z1H 0x84
+#define HFCSX_FIF_Z2L 0x88
+#define HFCSX_FIF_Z2H 0x8C
+#define HFCSX_FIF_INCF1 0xA8
+#define HFCSX_FIF_DWR 0xAC
+#define HFCSX_FIF_F1 0xB0
+#define HFCSX_FIF_F2 0xB4
+#define HFCSX_FIF_INCF2 0xB8
+#define HFCSX_FIF_DRD 0xBC
+
+/* bits in status register (READ) */
+#define HFCSX_SX_PROC 0x02
+#define HFCSX_NBUSY 0x04
+#define HFCSX_TIMER_ELAP 0x10
+#define HFCSX_STATINT 0x20
+#define HFCSX_FRAMEINT 0x40
+#define HFCSX_ANYINT 0x80
+
+/* bits in CTMT (Write) */
+#define HFCSX_CLTIMER 0x80
+#define HFCSX_TIM3_125 0x04
+#define HFCSX_TIM25 0x10
+#define HFCSX_TIM50 0x14
+#define HFCSX_TIM400 0x18
+#define HFCSX_TIM800 0x1C
+#define HFCSX_AUTO_TIMER 0x20
+#define HFCSX_TRANSB2 0x02
+#define HFCSX_TRANSB1 0x01
+
+/* bits in CIRM (Write) */
+#define HFCSX_IRQ_SELMSK 0x07
+#define HFCSX_IRQ_SELDIS 0x00
+#define HFCSX_RESET 0x08
+#define HFCSX_FIFO_RESET 0x80
+
+
+/* bits in INT_M1 and INT_S1 */
+#define HFCSX_INTS_B1TRANS 0x01
+#define HFCSX_INTS_B2TRANS 0x02
+#define HFCSX_INTS_DTRANS 0x04
+#define HFCSX_INTS_B1REC 0x08
+#define HFCSX_INTS_B2REC 0x10
+#define HFCSX_INTS_DREC 0x20
+#define HFCSX_INTS_L1STATE 0x40
+#define HFCSX_INTS_TIMER 0x80
+
+/* bits in INT_M2 */
+#define HFCSX_PROC_TRANS 0x01
+#define HFCSX_GCI_I_CHG 0x02
+#define HFCSX_GCI_MON_REC 0x04
+#define HFCSX_IRQ_ENABLE 0x08
+
+/* bits in STATES */
+#define HFCSX_STATE_MSK 0x0F
+#define HFCSX_LOAD_STATE 0x10
+#define HFCSX_ACTIVATE 0x20
+#define HFCSX_DO_ACTION 0x40
+#define HFCSX_NT_G2_G3 0x80
+
+/* bits in HFCD_MST_MODE */
+#define HFCSX_MASTER 0x01
+#define HFCSX_SLAVE 0x00
+/* remaining bits are for codecs control */
+
+/* bits in HFCD_SCTRL */
+#define SCTRL_B1_ENA 0x01
+#define SCTRL_B2_ENA 0x02
+#define SCTRL_MODE_TE 0x00
+#define SCTRL_MODE_NT 0x04
+#define SCTRL_LOW_PRIO 0x08
+#define SCTRL_SQ_ENA 0x10
+#define SCTRL_TEST 0x20
+#define SCTRL_NONE_CAP 0x40
+#define SCTRL_PWR_DOWN 0x80
+
+/* bits in SCTRL_E */
+#define HFCSX_AUTO_AWAKE 0x01
+#define HFCSX_DBIT_1 0x04
+#define HFCSX_IGNORE_COL 0x08
+#define HFCSX_CHG_B1_B2 0x80
+
+/**********************************/
+/* definitions for FIFO selection */
+/**********************************/
+#define HFCSX_SEL_D_RX 5
+#define HFCSX_SEL_D_TX 4
+#define HFCSX_SEL_B1_RX 1
+#define HFCSX_SEL_B1_TX 0
+#define HFCSX_SEL_B2_RX 3
+#define HFCSX_SEL_B2_TX 2
+
+#define MAX_D_FRAMES 15
+#define MAX_B_FRAMES 31
+#define B_SUB_VAL_32K 0x0200
+#define B_FIFO_SIZE_32K (0x2000 - B_SUB_VAL_32K)
+#define B_SUB_VAL_8K 0x1A00
+#define B_FIFO_SIZE_8K (0x2000 - B_SUB_VAL_8K)
+#define D_FIFO_SIZE 512
+#define D_FREG_MASK 0xF
+
+/************************************************************/
+/* structure holding additional dynamic data -> send marker */
+/************************************************************/
+struct hfcsx_extra {
+ unsigned short marker[2*(MAX_B_FRAMES+1) + (MAX_D_FRAMES+1)];
+};
+
+extern void main_irq_hfcsx(struct BCState *bcs);
+extern void inithfcsx(struct IsdnCardState *cs);
+extern void releasehfcsx(struct IsdnCardState *cs);
-/* $Id: hisax.h,v 2.38 1999/11/14 23:37:03 keil Exp $
+/* $Id: hisax.h,v 2.40 2000/01/20 19:51:46 keil Exp $
* Basic declarations, defines and prototypes
*
* $Log: hisax.h,v $
+ * Revision 2.40 2000/01/20 19:51:46 keil
+ * Fix AddTimer message
+ * Change CONFIG defines
+ *
+ * Revision 2.39 1999/11/18 00:00:43 werner
+ *
+ * Added support for HFC-S+ and HFC-SP cards
+ *
* Revision 2.38 1999/11/14 23:37:03 keil
* new ISA memory mapped IO
*
struct timer_list timer;
};
+struct hfcSX_hw {
+ unsigned int base;
+ unsigned char cirm;
+ unsigned char ctmt;
+ unsigned char conn;
+ unsigned char mst_m;
+ unsigned char int_m1;
+ unsigned char int_m2;
+ unsigned char int_s1;
+ unsigned char sctrl;
+ unsigned char sctrl_r;
+ unsigned char sctrl_e;
+ unsigned char trm;
+ unsigned char stat;
+ unsigned char fifo;
+ unsigned char bswapped;
+ unsigned char nt_mode;
+ unsigned char chip;
+ int b_fifo_size;
+ unsigned char last_fifo;
+ void *extra;
+ int nt_timer;
+ struct timer_list timer;
+};
+
struct hfcD_hw {
unsigned int addr;
unsigned int bfifosize;
int ph_state;
};
+struct hfcsx_chip {
+ int ph_state;
+};
+
struct w6692_chip {
int ph_state;
};
struct njet_hw njet;
struct hfcD_hw hfcD;
struct hfcPCI_hw hfcpci;
+ struct hfcSX_hw hfcsx;
struct ix1_hw niccy;
struct isurf_hw isurf;
struct saphir_hw saphir;
struct isac_chip isac;
struct hfcd_chip hfcd;
struct hfcpci_chip hfcpci;
+ struct hfcsx_chip hfcsx;
struct w6692_chip w6692;
} dc;
u_char *rcvbuf;
#define ISDN_CTYPE_GAZEL 34
#define ISDN_CTYPE_HFC_PCI 35
#define ISDN_CTYPE_W6692 36
-#define ISDN_CTYPE_COUNT 36
+#define ISDN_CTYPE_HFC_SX 37
+#define ISDN_CTYPE_COUNT 37
#ifdef ISDN_CHIP_ISAC
#define CARD_HFC_PCI 0
#endif
+#ifdef CONFIG_HISAX_HFC_SX
+#define CARD_HFC_SX 1
+#else
+#define CARD_HFC_SX 0
+#endif
+
#ifdef CONFIG_HISAX_AMD7930
#define CARD_AMD7930 1
#else
#ifdef CONFIG_HISAX_EURO
#undef TEI_PER_CARD
#define TEI_PER_CARD 1
-#define HISAX_EURO_SENDCOMPLETE 1
-#define EXT_BEARER_CAPS 1
-#define HISAX_SEND_STD_LLC_IE 1
-#ifdef CONFIG_HISAX_NO_SENDCOMPLETE
-#undef HISAX_EURO_SENDCOMPLETE
-#endif
-#ifdef CONFIG_HISAX_NO_LLC
-#undef HISAX_SEND_STD_LLC_IE
-#endif
-#undef HISAX_DE_AOC
-#ifdef CONFIG_DE_AOC
-#define HISAX_DE_AOC 1
-#endif
#endif
/* L1 Debug */
-/* $Id: isar.c,v 1.8 1999/12/19 13:00:56 keil Exp $
+/* $Id: isar.c,v 1.9 2000/01/20 19:47:45 keil Exp $
* isar.c ISAR (Siemens PSB 7110) specific routines
*
*
*
* $Log: isar.c,v $
+ * Revision 1.9 2000/01/20 19:47:45 keil
+ * Add Fax Class 1 support
+ *
* Revision 1.8 1999/12/19 13:00:56 keil
* Fix races in setting a new mode
*
#define MIN(a,b) ((a<b)?a:b)
+#define DLE 0x10
+#define ETX 0x03
+
+
+const u_char faxmodulation_s[] = "3,24,48,72,73,74,96,97,98,121,122,145,146";
+const u_char faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146};
+#define FAXMODCNT 13
+
void isar_setup(struct IsdnCardState *cs);
+static void isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para);
+static inline void ll_deliver_faxstat(struct BCState *bcs, u_char status);
static inline int
waitforHIA(struct IsdnCardState *cs, int timeout)
isar_bh(struct BCState *bcs)
{
BChannel_bh(bcs);
+ if (test_and_clear_bit(B_LL_NOCARRIER, &bcs->event))
+ ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_NOCARR);
+ if (test_and_clear_bit(B_LL_CONNECT, &bcs->event))
+ ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT);
+ if (test_and_clear_bit(B_LL_OK, &bcs->event))
+ ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_OK);
}
static void
mark_bh(IMMEDIATE_BH);
}
+static inline void
+send_DLE_ETX(struct BCState *bcs)
+{
+ u_char dleetx[2] = {DLE,ETX};
+ struct sk_buff *skb;
+
+ if ((skb = dev_alloc_skb(2))) {
+ memcpy(skb_put(skb, 2), dleetx, 2);
+ skb_queue_tail(&bcs->rqueue, skb);
+ isar_sched_event(bcs, B_RCVBUFREADY);
+ } else {
+ printk(KERN_WARNING "HiSax: skb out of memory\n");
+ }
+}
+
+static inline int
+dle_count(unsigned char *buf, int len)
+{
+ int count = 0;
+
+ while (len--)
+ if (*buf++ == DLE)
+ count++;
+ return count;
+}
+
+static inline void
+insert_dle(unsigned char *dest, unsigned char *src, int count) {
+ /* <DLE> in input stream have to be flagged as <DLE><DLE> */
+ while (count--) {
+ *dest++ = *src;
+ if (*src++ == DLE)
+ *dest++ = DLE;
+ }
+}
+
static inline void
isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs)
{
}
}
break;
+ case L1_MODE_FAX:
+ if (bcs->hw.isar.state != STFAX_ACTIV) {
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "isar_rcv_frame: not ACTIV");
+ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+ bcs->hw.isar.rcvidx = 0;
+ break;
+ }
+ if (bcs->hw.isar.cmd == PCTRL_CMD_FRM) {
+ rcv_mbox(cs, ireg, bcs->hw.isar.rcvbuf);
+ bcs->hw.isar.rcvidx = ireg->clsb +
+ dle_count(bcs->hw.isar.rcvbuf, ireg->clsb);
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "isar_rcv_frame: raw(%d) dle(%d)",
+ ireg->clsb, bcs->hw.isar.rcvidx);
+ if ((skb = dev_alloc_skb(bcs->hw.isar.rcvidx))) {
+ insert_dle((u_char *)skb_put(skb, bcs->hw.isar.rcvidx),
+ bcs->hw.isar.rcvbuf, ireg->clsb);
+ skb_queue_tail(&bcs->rqueue, skb);
+ isar_sched_event(bcs, B_RCVBUFREADY);
+ if (ireg->cmsb & SART_NMD) { /* ABORT */
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "isar_rcv_frame: no more data");
+ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+ bcs->hw.isar.rcvidx = 0;
+ send_DLE_ETX(bcs);
+ sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) |
+ ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC,
+ 0, NULL);
+ bcs->hw.isar.state = STFAX_ESCAPE;
+ isar_sched_event(bcs, B_LL_NOCARRIER);
+ }
+ } else {
+ printk(KERN_WARNING "HiSax: skb out of memory\n");
+ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+ }
+ break;
+ }
+ if (bcs->hw.isar.cmd != PCTRL_CMD_FRH) {
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "isar_rcv_frame: unknown fax mode %x",
+ bcs->hw.isar.cmd);
+ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+ bcs->hw.isar.rcvidx = 0;
+ break;
+ }
+ /* PCTRL_CMD_FRH */
+ if ((bcs->hw.isar.rcvidx + ireg->clsb) > HSCX_BUFMAX) {
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "isar_rcv_frame: incoming packet too large");
+ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+ bcs->hw.isar.rcvidx = 0;
+ } else if (ireg->cmsb & HDLC_ERROR) {
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "isar frame error %x len %d",
+ ireg->cmsb, ireg->clsb);
+ bcs->hw.isar.rcvidx = 0;
+ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+ } else {
+ if (ireg->cmsb & HDLC_FSD)
+ bcs->hw.isar.rcvidx = 0;
+ ptr = bcs->hw.isar.rcvbuf + bcs->hw.isar.rcvidx;
+ bcs->hw.isar.rcvidx += ireg->clsb;
+ rcv_mbox(cs, ireg, ptr);
+ if (ireg->cmsb & HDLC_FED) {
+ if (bcs->hw.isar.rcvidx < 3) { /* last 2 bytes are the FCS */
+ printk(KERN_WARNING "ISAR: HDLC frame too short(%d)\n",
+ bcs->hw.isar.rcvidx);
+ } else if (!(skb = dev_alloc_skb(bcs->hw.isar.rcvidx))) {
+ printk(KERN_WARNING "ISAR: receive out of memory\n");
+ } else {
+ memcpy(skb_put(skb, bcs->hw.isar.rcvidx),
+ bcs->hw.isar.rcvbuf,
+ bcs->hw.isar.rcvidx);
+ skb_queue_tail(&bcs->rqueue, skb);
+ isar_sched_event(bcs, B_RCVBUFREADY);
+ send_DLE_ETX(bcs);
+ isar_sched_event(bcs, B_LL_OK);
+ }
+ }
+ }
+ break;
default:
printk(KERN_ERR"isar_rcv_frame mode (%x)error\n", bcs->mode);
cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
count = bcs->tx_skb->len;
msb = HDLC_FED;
}
- if (!bcs->hw.isar.txcnt)
- msb |= HDLC_FST;
save_flags(flags);
cli();
ptr = bcs->tx_skb->data;
+ if (!bcs->hw.isar.txcnt) {
+ msb |= HDLC_FST;
+ if ((bcs->mode == L1_MODE_FAX) &&
+ (bcs->hw.isar.cmd == PCTRL_CMD_FTH)) {
+ if (bcs->tx_skb->len > 1) {
+ if ((ptr[0]== 0xff) && (ptr[1] == 0x13))
+ /* last frame */
+ test_and_set_bit(BC_FLG_LASTDATA,
+ &bcs->Flag);
+ }
+ }
+ }
skb_pull(bcs->tx_skb, count);
bcs->tx_cnt -= count;
bcs->hw.isar.txcnt += count;
switch (bcs->mode) {
- case L1_MODE_NULL:
- printk(KERN_ERR"isar_fill_fifo wrong mode 0\n");
- break;
- case L1_MODE_TRANS:
- case L1_MODE_V32:
- if (!sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
- 0, count, ptr)) {
- if (cs->debug)
- debugl1(cs, "isar bin data send dp%d failed",
- bcs->hw.isar.dpath);
- }
- break;
- case L1_MODE_HDLC:
- if (!sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
- msb, count, ptr)) {
+ case L1_MODE_NULL:
+ printk(KERN_ERR"isar_fill_fifo wrong mode 0\n");
+ break;
+ case L1_MODE_TRANS:
+ case L1_MODE_V32:
+ sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
+ 0, count, ptr);
+ break;
+ case L1_MODE_HDLC:
+ sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
+ msb, count, ptr);
+ break;
+ case L1_MODE_FAX:
+ if (bcs->hw.isar.state != STFAX_ACTIV) {
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "isar_fill_fifo: not ACTIV");
+ } else if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) {
+ sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
+ msb, count, ptr);
+ } else if (bcs->hw.isar.cmd == PCTRL_CMD_FTM) {
+ sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
+ 0, count, ptr);
+ } else {
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "isar_fill_fifo: not FTH/FTM");
+ }
+ break;
+ default:
if (cs->debug)
- debugl1(cs, "isar hdlc data send dp%d failed",
- bcs->hw.isar.dpath);
- }
- break;
- default:
- printk(KERN_ERR"isar_fill_fifo mode (%x)error\n", bcs->mode);
- break;
+ debugl1(cs, "isar_fill_fifo mode(%x) error", bcs->mode);
+ printk(KERN_ERR"isar_fill_fifo mode(%x) error\n", bcs->mode);
+ break;
}
restore_flags(flags);
}
if (bcs->st->lli.l1writewakeup &&
(PACKET_NOACK != bcs->tx_skb->pkt_type))
bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.isar.txcnt);
+ if (bcs->mode == L1_MODE_FAX) {
+ if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) {
+ if (test_bit(BC_FLG_LASTDATA, &bcs->Flag)) {
+ test_and_set_bit(BC_FLG_NMD_DATA, &bcs->Flag);
+ }
+ } else if (bcs->hw.isar.cmd == PCTRL_CMD_FTM) {
+ if (test_bit(BC_FLG_DLEETX, &bcs->Flag)) {
+ test_and_set_bit(BC_FLG_LASTDATA, &bcs->Flag);
+ test_and_set_bit(BC_FLG_NMD_DATA, &bcs->Flag);
+ }
+ }
+ }
dev_kfree_skb(bcs->tx_skb);
bcs->hw.isar.txcnt = 0;
bcs->tx_skb = NULL;
test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
isar_fill_fifo(bcs);
} else {
+ if (test_and_clear_bit(BC_FLG_DLEETX, &bcs->Flag)) {
+ if (test_and_clear_bit(BC_FLG_LASTDATA, &bcs->Flag)) {
+ if (test_and_clear_bit(BC_FLG_NMD_DATA, &bcs->Flag)) {
+ u_char dummy = 0;
+ sendmsg(bcs->cs, SET_DPS(bcs->hw.isar.dpath) |
+ ISAR_HIS_SDATA, 0x01, 1, &dummy);
+ }
+ test_and_set_bit(BC_FLG_LL_OK, &bcs->Flag);
+ } else {
+ isar_sched_event(bcs, B_LL_CONNECT);
+ }
+ }
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
isar_sched_event(bcs, B_XMTBUFREADY);
}
}
}
+
const char *dmril[] = {"NO SPEED", "1200/75", "NODEF2", "75/1200", "NODEF4",
"300", "600", "1200", "2400", "4800", "7200",
"9600nt", "9600t", "12000", "14400", "WRONG"};
}
static void
-isar_pump_status_ev(struct BCState *bcs, u_char devt) {
+isar_pump_statev_modem(struct BCState *bcs, u_char devt) {
struct IsdnCardState *cs = bcs->cs;
u_char dps = SET_DPS(bcs->hw.isar.dpath);
}
}
+static inline void
+ll_deliver_faxstat(struct BCState *bcs, u_char status)
+{
+ isdn_ctrl ic;
+ struct Channel *chanp = (struct Channel *) bcs->st->lli.userdata;
+
+ if (bcs->cs->debug & L1_DEB_HSCX)
+ debugl1(bcs->cs, "HL->LL FAXIND %x", status);
+ ic.driver = bcs->cs->myid;
+ ic.command = ISDN_STAT_FAXIND;
+ ic.arg = chanp->chan;
+ ic.parm.aux.cmd = status;
+ bcs->cs->iif.statcallb(&ic);
+}
+
+static void
+isar_pump_statev_fax(struct BCState *bcs, u_char devt) {
+ struct IsdnCardState *cs = bcs->cs;
+ u_char dps = SET_DPS(bcs->hw.isar.dpath);
+ u_char p1;
+
+ switch(devt) {
+ case PSEV_10MS_TIMER:
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "pump stev TIMER");
+ break;
+ case PSEV_RSP_READY:
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "pump stev RSP_READY");
+ bcs->hw.isar.state = STFAX_READY;
+ l1_msg_b(bcs->st, PH_ACTIVATE | REQUEST, NULL);
+ if (test_bit(BC_FLG_ORIG, &bcs->Flag)) {
+ isar_pump_cmd(bcs, ISDN_FAX_CLASS1_FRH, 3);
+ } else {
+ isar_pump_cmd(bcs, ISDN_FAX_CLASS1_FTH, 3);
+ }
+ break;
+ case PSEV_LINE_TX_H:
+ if (bcs->hw.isar.state == STFAX_LINE) {
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "pump stev LINE_TX_H");
+ bcs->hw.isar.state = STFAX_CONT;
+ sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
+ } else {
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "pump stev LINE_TX_H wrong st %x",
+ bcs->hw.isar.state);
+ }
+ break;
+ case PSEV_LINE_RX_H:
+ if (bcs->hw.isar.state == STFAX_LINE) {
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "pump stev LINE_RX_H");
+ bcs->hw.isar.state = STFAX_CONT;
+ sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
+ } else {
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "pump stev LINE_RX_H wrong st %x",
+ bcs->hw.isar.state);
+ }
+ break;
+ case PSEV_LINE_TX_B:
+ if (bcs->hw.isar.state == STFAX_LINE) {
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "pump stev LINE_TX_B");
+ bcs->hw.isar.state = STFAX_CONT;
+ sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
+ } else {
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "pump stev LINE_TX_B wrong st %x",
+ bcs->hw.isar.state);
+ }
+ break;
+ case PSEV_LINE_RX_B:
+ if (bcs->hw.isar.state == STFAX_LINE) {
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "pump stev LINE_RX_B");
+ bcs->hw.isar.state = STFAX_CONT;
+ sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_CONT, 0, NULL);
+ } else {
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "pump stev LINE_RX_B wrong st %x",
+ bcs->hw.isar.state);
+ }
+ break;
+ case PSEV_RSP_CONN:
+ if (bcs->hw.isar.state == STFAX_CONT) {
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "pump stev RSP_CONN");
+ bcs->hw.isar.state = STFAX_ACTIV;
+ test_and_set_bit(ISAR_RATE_REQ, &bcs->hw.isar.reg->Flags);
+ sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL);
+ if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) {
+ /* 1s Flags before data */
+ if (test_and_set_bit(BC_FLG_FTI_RUN, &bcs->Flag))
+ del_timer(&bcs->hw.isar.ftimer);
+ /* 1000 ms */
+ bcs->hw.isar.ftimer.expires =
+ jiffies + ((1000 * HZ)/1000);
+ test_and_set_bit(BC_FLG_LL_CONN,
+ &bcs->Flag);
+ add_timer(&bcs->hw.isar.ftimer);
+ } else {
+ isar_sched_event(bcs, B_LL_CONNECT);
+ }
+ } else {
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "pump stev RSP_CONN wrong st %x",
+ bcs->hw.isar.state);
+ }
+ break;
+ case PSEV_FLAGS_DET:
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "pump stev FLAGS_DET");
+ break;
+ case PSEV_RSP_DISC:
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "pump stev RSP_DISC");
+ if (bcs->hw.isar.state == STFAX_ESCAPE) {
+ switch(bcs->hw.isar.newcmd) {
+ case PCTRL_CMD_FTH:
+ case PCTRL_CMD_FTM:
+ p1 = 10;
+ sendmsg(cs, dps | ISAR_HIS_PUMPCTRL,
+ PCTRL_CMD_SILON, 1, &p1);
+ bcs->hw.isar.state = STFAX_SILDET;
+ break;
+ case PCTRL_CMD_FRH:
+ case PCTRL_CMD_FRM:
+ p1 = bcs->hw.isar.newmod;
+ bcs->hw.isar.newmod = 0;
+ bcs->hw.isar.cmd = bcs->hw.isar.newcmd;
+ bcs->hw.isar.newcmd = 0;
+ sendmsg(cs, dps | ISAR_HIS_PUMPCTRL,
+ bcs->hw.isar.cmd, 1, &p1);
+ bcs->hw.isar.state = STFAX_LINE;
+ break;
+ default:
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "RSP_DISC unknown newcmd %x", bcs->hw.isar.newcmd);
+ break;
+ }
+ } else if (bcs->hw.isar.state == STFAX_ACTIV) {
+ if (test_and_clear_bit(BC_FLG_LL_OK, &bcs->Flag)) {
+ isar_sched_event(bcs, B_LL_OK);
+ } else if (bcs->hw.isar.cmd == PCTRL_CMD_FRM) {
+ send_DLE_ETX(bcs);
+ isar_sched_event(bcs, B_LL_NOCARRIER);
+ } else {
+ ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR);
+ }
+ bcs->hw.isar.state = STFAX_READY;
+ } else {
+ bcs->hw.isar.state = STFAX_READY;
+ ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR);
+ }
+ break;
+ case PSEV_RSP_SILDET:
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "pump stev RSP_SILDET");
+ if (bcs->hw.isar.state == STFAX_SILDET) {
+ p1 = bcs->hw.isar.newmod;
+ bcs->hw.isar.newmod = 0;
+ bcs->hw.isar.cmd = bcs->hw.isar.newcmd;
+ bcs->hw.isar.newcmd = 0;
+ sendmsg(cs, dps | ISAR_HIS_PUMPCTRL,
+ bcs->hw.isar.cmd, 1, &p1);
+ bcs->hw.isar.state = STFAX_LINE;
+ }
+ break;
+ case PSEV_RSP_SILOFF:
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "pump stev RSP_SILOFF");
+ break;
+ case PSEV_RSP_FCERR:
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "pump stev RSP_FCERR");
+ bcs->hw.isar.state = STFAX_ESCAPE;
+ sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL);
+ ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR);
+ break;
+ default:
+ break;
+ }
+}
+
static char debbuf[128];
void
} else {
debugl1(cs, "isar spurious IIS_RDATA %x/%x/%x",
ireg->iis, ireg->cmsb, ireg->clsb);
- printk(KERN_WARNING"isar spurious IIS_RDATA %x/%x/%x\n",
- ireg->iis, ireg->cmsb, ireg->clsb);
cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
}
break;
case ISAR_IIS_PSTEV:
if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) {
rcv_mbox(cs, ireg, (u_char *)ireg->par);
- isar_pump_status_ev(bcs, ireg->cmsb);
+ if (bcs->mode == L1_MODE_V32) {
+ isar_pump_statev_modem(bcs, ireg->cmsb);
+ } else if (bcs->mode == L1_MODE_FAX) {
+ isar_pump_statev_fax(bcs, ireg->cmsb);
+ } else {
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "isar IIS_PSTEV pmode %d stat %x",
+ bcs->mode, ireg->cmsb);
+ }
} else {
debugl1(cs, "isar spurious IIS_PSTEV %x/%x/%x",
ireg->iis, ireg->cmsb, ireg->clsb);
- printk(KERN_WARNING"isar spurious IIS_PSTEV %x/%x/%x\n",
- ireg->iis, ireg->cmsb, ireg->clsb);
cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
}
break;
} else {
debugl1(cs, "isar spurious IIS_PSTRSP %x/%x/%x",
ireg->iis, ireg->cmsb, ireg->clsb);
- printk(KERN_WARNING"isar spurious IIS_PSTRSP %x/%x/%x\n",
- ireg->iis, ireg->cmsb, ireg->clsb);
cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
}
break;
restore_flags(flags);
}
+static void
+ftimer_handler(struct BCState *bcs) {
+ if (bcs->cs->debug)
+ debugl1(bcs->cs, "ftimer flags %04x",
+ bcs->Flag);
+ test_and_clear_bit(BC_FLG_FTI_RUN, &bcs->Flag);
+ if (test_and_clear_bit(BC_FLG_LL_CONN, &bcs->Flag)) {
+ isar_sched_event(bcs, B_LL_CONNECT);
+ }
+}
+
static void
setup_pump(struct BCState *bcs) {
struct IsdnCardState *cs = bcs->cs;
case L1_MODE_NULL:
case L1_MODE_TRANS:
case L1_MODE_HDLC:
- if (!sendmsg(cs, dps | ISAR_HIS_PUMPCFG, PMOD_BYPASS, 0, NULL)) {
- if (cs->debug)
- debugl1(cs, "isar pump bypass cfg dp%d failed",
- bcs->hw.isar.dpath);
- }
+ sendmsg(cs, dps | ISAR_HIS_PUMPCFG, PMOD_BYPASS, 0, NULL);
break;
case L1_MODE_V32:
ctrl = PMOD_DATAMODEM;
param[2] = PV32P3_AMOD | PV32P3_V32B | PV32P3_V23B;
param[3] = PV32P4_UT144;
param[4] = PV32P5_UT144;
- if (!sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 6, param)) {
- if (cs->debug)
- debugl1(cs, "isar pump datamodem cfg dp%d failed",
- bcs->hw.isar.dpath);
- }
+ sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 6, param);
break;
case L1_MODE_FAX:
ctrl = PMOD_FAX;
param[1] = PFAXP2_ATN;
}
param[0] = 6; /* 6 db */
- if (!sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param)) {
- if (cs->debug)
- debugl1(cs, "isar pump faxmodem cfg dp%d failed",
- bcs->hw.isar.dpath);
- }
+ sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param);
+ bcs->hw.isar.state = STFAX_NULL;
+ bcs->hw.isar.newcmd = 0;
+ bcs->hw.isar.newmod = 0;
+ test_and_set_bit(BC_FLG_FTI_RUN, &bcs->Flag);
break;
}
udelay(1000);
switch (bcs->mode) {
case L1_MODE_NULL:
- if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_DISABLE, 0, NULL)) {
- if (cs->debug)
- debugl1(cs, "isar sart disable dp%d failed",
- bcs->hw.isar.dpath);
- }
+ sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_DISABLE, 0,
+ NULL);
break;
case L1_MODE_TRANS:
- if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_BINARY, 2, "\0\0")) {
- if (cs->debug)
- debugl1(cs, "isar sart binary dp%d failed",
- bcs->hw.isar.dpath);
- }
+ sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_BINARY, 2,
+ "\0\0");
break;
case L1_MODE_HDLC:
case L1_MODE_FAX:
param[0] = 0;
- if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1, param)) {
- if (cs->debug)
- debugl1(cs, "isar sart hdlc dp%d failed",
- bcs->hw.isar.dpath);
- }
+ sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1,
+ param);
break;
case L1_MODE_V32:
ctrl = SMODE_V14 | SCTRL_HDMC_BOTH;
param[0] = S_P1_CHS_8;
param[1] = S_P2_BFT_DEF;
- if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, ctrl, 2, param)) {
- if (cs->debug)
- debugl1(cs, "isar sart v14 dp%d failed",
- bcs->hw.isar.dpath);
- }
+ sendmsg(cs, dps | ISAR_HIS_SARTCFG, ctrl, 2,
+ param);
break;
}
udelay(1000);
&bcs->hw.isar.reg->Flags))
bcs->hw.isar.dpath = 1;
else {
- printk(KERN_WARNING"isar modeisar analog works only with DP1\n");
- debugl1(cs, "isar modeisar analog works only with DP1");
+ printk(KERN_WARNING"isar modeisar analog funktions only with DP1\n");
+ debugl1(cs, "isar modeisar analog funktions only with DP1");
return(1);
}
break;
return(0);
}
+static void
+isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para)
+{
+ struct IsdnCardState *cs = bcs->cs;
+ u_char dps = SET_DPS(bcs->hw.isar.dpath);
+ u_char ctrl = 0, nom = 0, p1 = 0;
+
+ switch(cmd) {
+ case ISDN_FAX_CLASS1_FTM:
+ if (bcs->hw.isar.state == STFAX_READY) {
+ p1 = para;
+ ctrl = PCTRL_CMD_FTM;
+ nom = 1;
+ bcs->hw.isar.state = STFAX_LINE;
+ bcs->hw.isar.cmd = ctrl;
+ bcs->hw.isar.mod = para;
+ bcs->hw.isar.newmod = 0;
+ bcs->hw.isar.newcmd = 0;
+ } else if ((bcs->hw.isar.state == STFAX_ACTIV) &&
+ (bcs->hw.isar.cmd == PCTRL_CMD_FTM) &&
+ (bcs->hw.isar.mod == para)) {
+ ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT);
+ } else {
+ bcs->hw.isar.newmod = para;
+ bcs->hw.isar.newcmd = PCTRL_CMD_FTM;
+ nom = 0;
+ ctrl = PCTRL_CMD_ESC;
+ bcs->hw.isar.state = STFAX_ESCAPE;
+ }
+ break;
+ case ISDN_FAX_CLASS1_FTH:
+ if (bcs->hw.isar.state == STFAX_READY) {
+ p1 = para;
+ ctrl = PCTRL_CMD_FTH;
+ nom = 1;
+ bcs->hw.isar.state = STFAX_LINE;
+ bcs->hw.isar.cmd = ctrl;
+ bcs->hw.isar.mod = para;
+ bcs->hw.isar.newmod = 0;
+ bcs->hw.isar.newcmd = 0;
+ } else if ((bcs->hw.isar.state == STFAX_ACTIV) &&
+ (bcs->hw.isar.cmd == PCTRL_CMD_FTH) &&
+ (bcs->hw.isar.mod == para)) {
+ ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT);
+ } else {
+ bcs->hw.isar.newmod = para;
+ bcs->hw.isar.newcmd = PCTRL_CMD_FTH;
+ nom = 0;
+ ctrl = PCTRL_CMD_ESC;
+ bcs->hw.isar.state = STFAX_ESCAPE;
+ }
+ break;
+ case ISDN_FAX_CLASS1_FRM:
+ if (bcs->hw.isar.state == STFAX_READY) {
+ p1 = para;
+ ctrl = PCTRL_CMD_FRM;
+ nom = 1;
+ bcs->hw.isar.state = STFAX_LINE;
+ bcs->hw.isar.cmd = ctrl;
+ bcs->hw.isar.mod = para;
+ bcs->hw.isar.newmod = 0;
+ bcs->hw.isar.newcmd = 0;
+ } else if ((bcs->hw.isar.state == STFAX_ACTIV) &&
+ (bcs->hw.isar.cmd == PCTRL_CMD_FRM) &&
+ (bcs->hw.isar.mod == para)) {
+ ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT);
+ } else {
+ bcs->hw.isar.newmod = para;
+ bcs->hw.isar.newcmd = PCTRL_CMD_FRM;
+ nom = 0;
+ ctrl = PCTRL_CMD_ESC;
+ bcs->hw.isar.state = STFAX_ESCAPE;
+ }
+ break;
+ case ISDN_FAX_CLASS1_FRH:
+ if (bcs->hw.isar.state == STFAX_READY) {
+ p1 = para;
+ ctrl = PCTRL_CMD_FRH;
+ nom = 1;
+ bcs->hw.isar.state = STFAX_LINE;
+ bcs->hw.isar.cmd = ctrl;
+ bcs->hw.isar.mod = para;
+ bcs->hw.isar.newmod = 0;
+ bcs->hw.isar.newcmd = 0;
+ } else if ((bcs->hw.isar.state == STFAX_ACTIV) &&
+ (bcs->hw.isar.cmd == PCTRL_CMD_FRH) &&
+ (bcs->hw.isar.mod == para)) {
+ ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_CONNECT);
+ } else {
+ bcs->hw.isar.newmod = para;
+ bcs->hw.isar.newcmd = PCTRL_CMD_FRH;
+ nom = 0;
+ ctrl = PCTRL_CMD_ESC;
+ bcs->hw.isar.state = STFAX_ESCAPE;
+ }
+ break;
+ }
+ if (ctrl)
+ sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, ctrl, nom, &p1);
+}
+
void
isar_setup(struct IsdnCardState *cs)
{
msg = 61;
for (i=0; i<2; i++) {
/* Buffer Config */
- if (!sendmsg(cs, (i ? ISAR_HIS_DPS2 : ISAR_HIS_DPS1) |
- ISAR_HIS_P12CFG, 4, 1, &msg)) {
- if (cs->debug)
- debugl1(cs, "isar P%dCFG failed", i+1);
- }
+ sendmsg(cs, (i ? ISAR_HIS_DPS2 : ISAR_HIS_DPS1) |
+ ISAR_HIS_P12CFG, 4, 1, &msg);
cs->bcs[i].hw.isar.mml = msg;
cs->bcs[i].mode = 0;
cs->bcs[i].hw.isar.dpath = i + 1;
l1_msg_b(st, PH_ACTIVATE | REQUEST, arg);
break;
case L1_MODE_V32:
+ case L1_MODE_FAX:
if (modeisar(st->l1.bcs, st->l1.mode, st->l1.bc))
l1_msg_b(st, PH_DEACTIVATE | REQUEST, arg);
break;
debugl1(bcs->cs, "closeisar clear BC_FLG_BUSY");
}
}
+ del_timer(&bcs->hw.isar.ftimer);
}
int
bcs->event = 0;
bcs->hw.isar.rcvidx = 0;
bcs->tx_cnt = 0;
+ bcs->hw.isar.ftimer.function = (void *) ftimer_handler;
+ bcs->hw.isar.ftimer.data = (long) bcs;
+ init_timer(&bcs->hw.isar.ftimer);
return (0);
}
int
isar_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) {
u_long adr;
- int features;
+ int features, i;
+ struct BCState *bcs;
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "isar_auxcmd cmd/ch %x/%d", ic->command, ic->arg);
switch (ic->command) {
+ case (ISDN_CMD_FAXCMD):
+ bcs = cs->channel[ic->arg].bcs;
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "isar_auxcmd cmd/subcmd %d/%d",
+ ic->parm.aux.cmd, ic->parm.aux.subcmd);
+ switch(ic->parm.aux.cmd) {
+ case ISDN_FAX_CLASS1_CTRL:
+ if (ic->parm.aux.subcmd == ETX)
+ test_and_set_bit(BC_FLG_DLEETX,
+ &bcs->Flag);
+ break;
+ case ISDN_FAX_CLASS1_FRM:
+ case ISDN_FAX_CLASS1_FRH:
+ case ISDN_FAX_CLASS1_FTM:
+ case ISDN_FAX_CLASS1_FTH:
+ if (ic->parm.aux.subcmd == AT_QUERY) {
+ sprintf(ic->parm.aux.para,
+ "%d", bcs->hw.isar.mod);
+ ic->command = ISDN_STAT_FAXIND;
+ ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY;
+ cs->iif.statcallb(ic);
+ return(0);
+ } else if (ic->parm.aux.subcmd == AT_EQ_QUERY) {
+ strcpy(ic->parm.aux.para, faxmodulation_s);
+ ic->command = ISDN_STAT_FAXIND;
+ ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY;
+ cs->iif.statcallb(ic);
+ return(0);
+ } else if (ic->parm.aux.subcmd == AT_EQ_VALUE) {
+ for(i=0;i<FAXMODCNT;i++)
+ if (faxmodulation[i]==ic->parm.aux.para[0])
+ break;
+ if ((FAXMODCNT > i) &&
+ test_bit(BC_FLG_INIT, &bcs->Flag)) {
+ isar_pump_cmd(bcs,
+ ic->parm.aux.cmd,
+ ic->parm.aux.para[0]);
+ return(0);
+ }
+ }
+ /* wrong modulation or not activ */
+ /* fall through */
+ default:
+ ic->command = ISDN_STAT_FAXIND;
+ ic->parm.aux.cmd = ISDN_FAX_CLASS1_ERROR;
+ cs->iif.statcallb(ic);
+ }
+ break;
case (ISDN_CMD_IOCTL):
switch (ic->arg) {
case (9): /* load firmware */
- features = ISDN_FEATURE_L2_MODEM;
+ features = ISDN_FEATURE_L2_MODEM |
+ ISDN_FEATURE_L2_FAX |
+ ISDN_FEATURE_L3_FCLASS1;
memcpy(&adr, ic->parm.num, sizeof(ulong));
if (isar_load_firmware(cs, (u_char *)adr))
return(1);
-/* $Id: isar.h,v 1.6 1999/10/14 20:25:29 keil Exp $
+/* $Id: isar.h,v 1.7 2000/01/20 19:47:45 keil Exp $
* isar.h ISAR (Siemens PSB 7110) specific defines
*
* Author Karsten Keil (keil@isdn4linux.de)
*
*
* $Log: isar.h,v $
+ * Revision 1.7 2000/01/20 19:47:45 keil
+ * Add Fax Class 1 support
+ *
* Revision 1.6 1999/10/14 20:25:29 keil
* add a statistic for error monitoring
*
#define PSEV_REM_REN 0xcd
#define PSEV_GSTN_CLR 0xd4
+#define PSEV_RSP_READY 0xbc
+#define PSEV_LINE_TX_H 0xb3
+#define PSEV_LINE_TX_B 0xb2
+#define PSEV_LINE_RX_H 0xb1
+#define PSEV_LINE_RX_B 0xb0
+#define PSEV_RSP_CONN 0xb5
+#define PSEV_RSP_DISC 0xb7
+#define PSEV_RSP_FCERR 0xb9
+#define PSEV_RSP_SILDET 0xbe
+#define PSEV_RSP_SILOFF 0xab
+#define PSEV_FLAGS_DET 0xba
+
+#define PCTRL_CMD_FTH 0xa7
+#define PCTRL_CMD_FRH 0xa5
+#define PCTRL_CMD_FTM 0xa8
+#define PCTRL_CMD_FRM 0xa6
+#define PCTRL_CMD_SILON 0xac
+#define PCTRL_CMD_CONT 0xa2
+#define PCTRL_CMD_ESC 0xa4
+#define PCTRL_CMD_SILOFF 0xab
+#define PCTRL_CMD_HALT 0xa9
+
#define PCTRL_LOC_RET 0xcf
#define PCTRL_LOC_REN 0xce
#define BSTEV_TBO 0x1f
#define BSTEV_RBO 0x2f
+/* FAX State Machine */
+#define STFAX_NULL 0
+#define STFAX_READY 1
+#define STFAX_LINE 2
+#define STFAX_CONT 3
+#define STFAX_ACTIV 4
+#define STFAX_ESCAPE 5
+#define STFAX_SILDET 6
+
extern int ISARVersion(struct IsdnCardState *cs, char *s);
extern void isar_int_main(struct IsdnCardState *cs);
extern void initisar(struct IsdnCardState *cs);
-/* $Id: isdnl1.c,v 2.36 1999/08/25 16:50:57 keil Exp $
+/* $Id: isdnl1.c,v 2.37 2000/01/20 19:51:46 keil Exp $
* isdnl1.c common low level stuff for Siemens Chipsetbased isdn cards
* based on the teles driver from Jan den Ouden
*
*
* $Log: isdnl1.c,v $
+ * Revision 2.37 2000/01/20 19:51:46 keil
+ * Fix AddTimer message
+ * Change CONFIG defines
+ *
* Revision 2.36 1999/08/25 16:50:57 keil
* Fix bugs which cause 2.3.14 hangs (waitqueue init)
*
*
*/
-const char *l1_revision = "$Revision: 2.36 $";
+const char *l1_revision = "$Revision: 2.37 $";
#define __NO_VERSION__
#include "hisax.h"
stptr = stptr->next;
if (!found)
dev_kfree_skb(skb);
- }
+ } else
+ dev_kfree_skb(skb);
}
}
struct PStack *st = fi->userdata;
FsmChangeState(fi, ST_L1_F3);
-// if (!test_bit(FLG_L1_T3RUN, &st->l1.Flags)) {
- FsmDelTimer(&st->l1.timer, 1);
- FsmAddTimer(&st->l1.timer, 550, EV_TIMER_DEACT, NULL, 2);
- test_and_set_bit(FLG_L1_DEACTTIMER, &st->l1.Flags);
-// }
+ FsmRestartTimer(&st->l1.timer, 550, EV_TIMER_DEACT, NULL, 2);
+ test_and_set_bit(FLG_L1_DEACTTIMER, &st->l1.Flags);
}
static void
if (test_bit(FLG_L1_ACTIVATING, &st->l1.Flags)) {
FsmChangeState(fi, ST_L1_F4);
st->l1.l1hw(st, HW_INFO3 | REQUEST, NULL);
- FsmDelTimer(&st->l1.timer, 1);
- FsmAddTimer(&st->l1.timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
+ FsmRestartTimer(&st->l1.timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
test_and_set_bit(FLG_L1_T3RUN, &st->l1.Flags);
} else
FsmChangeState(fi, ST_L1_F3);
if (!test_bit(FLG_L1_ACTIVATED, &st->l1.Flags)) {
if (test_and_clear_bit(FLG_L1_T3RUN, &st->l1.Flags))
FsmDelTimer(&st->l1.timer, 3);
- FsmAddTimer(&st->l1.timer, 110, EV_TIMER_ACT, NULL, 2);
+ FsmRestartTimer(&st->l1.timer, 110, EV_TIMER_ACT, NULL, 2);
test_and_set_bit(FLG_L1_ACTTIMER, &st->l1.Flags);
}
}
struct PStack *st = fi->userdata;
FsmChangeState(fi, ST_L1_WAIT_ACT);
- FsmAddTimer(&st->l1.timer, st->l1.delay, EV_TIMER_ACT, NULL, 2);
+ FsmRestartTimer(&st->l1.timer, st->l1.delay, EV_TIMER_ACT, NULL, 2);
}
static void
struct PStack *st = fi->userdata;
FsmChangeState(fi, ST_L1_WAIT_DEACT);
- FsmAddTimer(&st->l1.timer, 10, EV_TIMER_DEACT, NULL, 2);
+ FsmRestartTimer(&st->l1.timer, 10, EV_TIMER_DEACT, NULL, 2);
}
static void
-/* $Id: l3_1tr6.c,v 2.9 1999/07/01 08:11:55 keil Exp $
+/* $Id: l3_1tr6.c,v 2.10 2000/01/20 19:42:01 keil Exp $
* German 1TR6 D-channel protocol
*
*
*
* $Log: l3_1tr6.c,v $
+ * Revision 2.10 2000/01/20 19:42:01 keil
+ * Fixed uninitialiesed location
+ *
* Revision 2.9 1999/07/01 08:11:55 keil
* Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
*
#include <linux/ctype.h>
extern char *HiSax_getrev(const char *revision);
-const char *l3_1tr6_revision = "$Revision: 2.9 $";
+const char *l3_1tr6_revision = "$Revision: 2.10 $";
#define MsgHead(ptr, cref, mty, dis) \
*ptr++ = dis; \
{
newl3state(pc, 0);
pc->para.cause = 0x1b; /* Destination out of order */
+ pc->para.loc = 0;
pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
release_l3_process(pc);
}
-/* $Id: l3dss1.c,v 2.21 1999/12/19 20:25:17 keil Exp $
+/* $Id: l3dss1.c,v 2.22 2000/01/20 19:44:20 keil Exp $
* EURO/DSS1 D-channel protocol
*
* Fritz Elfert
*
* $Log: l3dss1.c,v $
+ * Revision 2.22 2000/01/20 19:44:20 keil
+ * Fixed uninitialiesed location
+ * Fixed redirecting number IE in Setup
+ * Changes from certification
+ * option for disabling use of KEYPAD protocol
+ *
* Revision 2.21 1999/12/19 20:25:17 keil
* fixed LLC for outgoing analog calls
* IE Signal is valid on older local switches
#include "isdnl3.h"
#include "l3dss1.h"
#include <linux/ctype.h>
+#include <linux/config.h>
extern char *HiSax_getrev(const char *revision);
-const char *dss1_revision = "$Revision: 2.21 $";
+const char *dss1_revision = "$Revision: 2.22 $";
#define EXT_BEARER_CAPS 1
static int ie_SETUP[] = {IE_COMPLETE, IE_BEARER | IE_MANDATORY,
IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY, IE_PROGRESS,
IE_NET_FAC, IE_DISPLAY, IE_KEYPAD, IE_SIGNAL, IE_CALLING_PN,
- IE_CALLING_SUB, IE_CALLED_PN, IE_CALLED_SUB, IE_LLC, IE_HLC,
- IE_USER_USER, -1};
+ IE_CALLING_SUB, IE_CALLED_PN, IE_CALLED_SUB, IE_REDIR_NR,
+ IE_LLC, IE_HLC, IE_USER_USER, -1};
static int ie_SETUP_ACKNOWLEDGE[] = {IE_CHANNEL_ID | IE_MANDATORY, IE_FACILITY,
IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, -1};
static int ie_STATUS[] = {IE_CAUSE | IE_MANDATORY, IE_CALL_STATE |
u_char tmp[128];
u_char *p = tmp;
u_char channel = 0;
+
u_char send_keypad;
u_char screen = 0x80;
u_char *teln;
MsgHead(p, pc->callref, MT_SETUP);
teln = pc->para.setup.phone;
+#ifndef CONFIG_HISAX_NO_KEYPAD
send_keypad = (strchr(teln,'*') || strchr(teln,'#')) ? 1 : 0;
+#else
+ send_keypad = 0;
+#endif
+#ifndef CONFIG_HISAX_NO_SENDCOMPLETE
+ if (!send_keypad)
+ *p++ = 0xa1; /* complete indicator */
+#endif
/*
* Set Bearer Capability, Map info from 1TR6-convention to EDSS1
*/
-#if HISAX_EURO_SENDCOMPLETE
- if (!send_keypad)
- *p++ = 0xa1; /* complete indicator */
-#endif
if (!send_keypad)
switch (pc->para.setup.si1) {
case 1: /* Telephony */
*p++ = 0x90;
*p++ = 0x21;
p = EncodeASyncParams(p, pc->para.setup.si2 - 192);
-#if HISAX_SEND_STD_LLC_IE
+#ifndef CONFIG_HISAX_NO_LLC
} else {
switch (pc->para.setup.si1) {
case 1: /* Telephony */
l3dss1_dl_reset(struct l3_process *pc, u_char pr, void *arg)
{
pc->para.cause = 0x29; /* Temporary failure */
+ pc->para.loc = 0;
l3dss1_disconnect_req(pc, pr, NULL);
pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
}
{
newl3state(pc, 0);
pc->para.cause = 0x1b; /* Destination out of order */
+ pc->para.loc = 0;
pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
release_l3_process(pc);
}
-/* $Id: l3dss1.h,v 1.7 1999/07/01 08:12:02 keil Exp $
+/* $Id: l3dss1.h,v 1.8 2000/01/20 19:46:15 keil Exp $
*
* DSS1 (Euro) D-channel protocol defines
*
* $Log: l3dss1.h,v $
+ * Revision 1.8 2000/01/20 19:46:15 keil
+ * Changes from certification
+ *
* Revision 1.7 1999/07/01 08:12:02 keil
* Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
*
#define T304 30000
#define T305 30000
#define T308 4000
+/* for layer 1 certification T309 < layer1 T3 (e.g. 4000) */
+/* This makes some tests easier and quicker */
#define T309 40000
#define T310 30000
#define T313 4000
# Read ../../../Documentation/isdn/HiSax.cert for more informations.
#
3c2b1c96274cba97a8261d1cecc662b8 isac.c
-a9a15d069dbacb383cc24c238cb5ebbe isdnl1.c
+dd3955847bbf680b41233478fe521d88 isdnl1.c
bb51bd223040b511c18f091da5ab6456 isdnl2.c
b7aa7f97b2374967a4aca7c52991142c isdnl3.c
a23fbf8879c1432b04640b8b04bdf419 tei.c
ce248e56c2e1326012d0b25f92bbf99b callc.c
bf9605b36429898f7be6630034e83230 cert.c
-2dbd5fadc33657c654f71385ff84127a l3dss1.c
-2d748ced0eea375b21fe7ea91ca7917c l3_1tr6.c
+233960fa9fc46aaffcaa883b5b59cf4e l3dss1.c
+a3a570781f828b6d59e6b231653133de l3_1tr6.c
8188deeb4a1b34c574cd51638cd214d0 elsa.c
a3c2b8e9d2c623658888b5f1d4317c2a diva.c
# end of md5sums
Version: 2.6.3i
Charset: noconv
-iQCVAwUBOGUfJzpxHvX/mS9tAQFpwwP/UFR+IP3URpDrRPJgWdzaP+Ho/nu4uOQM
-+l2d0MNZlBPIPiRJnP921mcSXUw37OsuXf8cfqihuCgc+2+ExNZe9s9o/Wz5TttA
-L1fhoP85OXy6m5Ap77Feh1tzxAQodRwIzzFvrXqUUN82JW32Q931dJzxVbYtgP16
-SkErM8N2GbM=
-=QeLI
+iQCVAwUBOIdqVzpxHvX/mS9tAQGaWQP+Pj0oVxbhusXnlNOQ+FV6YOGj1HGMXPsO
+C/9555qSbvcKg64OO8VdU1LWq/RCsAwBkJ3eSizF5LbWD8lhCHUpkNlzEv4fIaHe
+fAA9zLnC8Vk4h/YLwUNfZxezYvf22NGSydXGZH4VvLAigF0OGRlKaewsR61KZ/Fh
+4GnVqcxYaH8=
+=eINS
-----END PGP SIGNATURE-----
-/* $Id: sedlbauer.c,v 1.19 1999/12/19 13:09:42 keil Exp $
+/* $Id: sedlbauer.c,v 1.20 2000/01/20 19:47:45 keil Exp $
* sedlbauer.c low level stuff for Sedlbauer cards
* includes support for the Sedlbauer speed star (speed star II),
* Edgar Toernig
*
* $Log: sedlbauer.c,v $
+ * Revision 1.20 2000/01/20 19:47:45 keil
+ * Add Fax Class 1 support
+ *
* Revision 1.19 1999/12/19 13:09:42 keil
* changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for
* signal proof delays
extern const char *CardType[];
-const char *Sedlbauer_revision = "$Revision: 1.19 $";
+const char *Sedlbauer_revision = "$Revision: 1.20 $";
const char *Sedlbauer_Types[] =
{"None", "speed card/win", "speed star", "speed fax+",
(sub_id == PCI_SUB_ID_SPEEDFAXP)) {
cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
cs->subtyp = SEDL_SPEEDFAX_PCI;
- cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg +
- SEDL_ISAR_PCI_ISAR_RESET_ON;
- cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg +
- SEDL_ISAR_PCI_ISAR_RESET_OFF;
} else {
cs->hw.sedl.chip = SEDL_CHIP_IPAC;
cs->subtyp = SEDL_SPEED_PCI;
}
bytecnt = 256;
+ cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
+ cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
byteout(cs->hw.sedl.cfg_reg, 0xff);
byteout(cs->hw.sedl.cfg_reg, 0x00);
byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
-/* $Id: isdn_common.c,v 1.93 1999/11/04 13:11:36 keil Exp $
+/* $Id: isdn_common.c,v 1.97 2000/01/23 18:45:37 keil Exp $
* Linux ISDN subsystem, common used functions (linklevel).
*
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_common.c,v $
+ * Revision 1.97 2000/01/23 18:45:37 keil
+ * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN)
+ *
+ * Revision 1.96 2000/01/20 19:55:33 keil
+ * Add FAX Class 1 support
+ *
+ * Revision 1.95 2000/01/09 20:43:13 detabc
+ * exand logical bind-group's for both call's (in and out).
+ * add first part of kernel-config-help for abc-extension.
+ *
+ * Revision 1.94 1999/11/20 22:14:13 detabc
+ * added channel dial-skip in case of external use
+ * (isdn phone or another isdn device) on the same NTBA.
+ * usefull with two or more card's connected the different NTBA's.
+ * global switchable in kernel-config and also per netinterface.
+ *
+ * add auto disable of netinterface's in case of:
+ * to many connection's in short time.
+ * config mistakes (wrong encapsulation, B2-protokoll or so on) on local
+ * or remote side.
+ * wrong password's or something else to a ISP (syncppp).
+ *
+ * possible encapsulations for this future are:
+ * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP,
+ * and ISDN_NET_ENCAP_CISCOHDLCK.
+ *
* Revision 1.93 1999/11/04 13:11:36 keil
* Reinit of v110 structs
*
isdn_dev *dev = (isdn_dev *) 0;
-static char *isdn_revision = "$Revision: 1.93 $";
+static char *isdn_revision = "$Revision: 1.97 $";
extern char *isdn_net_revision;
extern char *isdn_tty_revision;
static int isdn_writebuf_stub(int, int, const u_char *, int, int);
+static void set_global_features(void);
void
isdn_MOD_INC_USE_COUNT(void)
int
isdn_command(isdn_ctrl *cmd)
{
+ if (cmd->driver == -1) {
+ printk(KERN_WARNING "isdn_command command(%x) driver -1\n", cmd->command);
+ return(1);
+ }
if (cmd->command == ISDN_CMD_SETL2) {
- int idx = isdn_dc2minor(cmd->driver, cmd->arg & 255);
- unsigned long l2prot = (cmd->arg >> 8) & 255;
- unsigned long features = (dev->drv[cmd->driver]->interface->features
- >> ISDN_FEATURE_L2_SHIFT) &
- ISDN_FEATURE_L2_MASK;
- unsigned long l2_feature = (1 << l2prot);
-
- switch (l2prot) {
- case ISDN_PROTO_L2_V11096:
- case ISDN_PROTO_L2_V11019:
- case ISDN_PROTO_L2_V11038:
- /* If V.110 requested, but not supported by
- * HL-driver, set emulator-flag and change
- * Layer-2 to transparent
- */
- if (!(features & l2_feature)) {
- dev->v110emu[idx] = l2prot;
- cmd->arg = (cmd->arg & 255) |
- (ISDN_PROTO_L2_TRANS << 8);
- } else
- dev->v110emu[idx] = 0;
- }
+ int idx = isdn_dc2minor(cmd->driver, cmd->arg & 255);
+ unsigned long l2prot = (cmd->arg >> 8) & 255;
+ unsigned long features = (dev->drv[cmd->driver]->interface->features
+ >> ISDN_FEATURE_L2_SHIFT) &
+ ISDN_FEATURE_L2_MASK;
+ unsigned long l2_feature = (1 << l2prot);
+
+ switch (l2prot) {
+ case ISDN_PROTO_L2_V11096:
+ case ISDN_PROTO_L2_V11019:
+ case ISDN_PROTO_L2_V11038:
+ /* If V.110 requested, but not supported by
+ * HL-driver, set emulator-flag and change
+ * Layer-2 to transparent
+ */
+ if (!(features & l2_feature)) {
+ dev->v110emu[idx] = l2prot;
+ cmd->arg = (cmd->arg & 255) |
+ (ISDN_PROTO_L2_TRANS << 8);
+ } else
+ dev->v110emu[idx] = 0;
+ }
}
return dev->drv[cmd->driver]->interface->command(cmd);
}
for (i = 0; i < ISDN_MAX_CHANNELS; i++)
if (dev->drvmap[i] == di)
isdn_all_eaz(di, dev->chanmap[i]);
+ set_global_features();
break;
case ISDN_STAT_STOP:
dev->drv[di]->flags &= ~DRV_FLAG_RUNNING;
dev->drv[di] = NULL;
dev->drvid[di][0] = '\0';
isdn_info_update();
+ set_global_features();
restore_flags(flags);
return 0;
case ISDN_STAT_L1ERR:
* are serialized by means of a semaphore.
*/
switch (cmd) {
+ case IIOCNETDWRSET:
+ printk(KERN_INFO "INFO: ISDN_DW_ABC_EXTENSION not enabled\n");
+ return(-EINVAL);
case IIOCNETLCR:
printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");
return -ENODEV;
for (i = 0; i < 10; i++) {
sprintf(bname, "%s%s",
strlen(dev->drv[drvidx]->msn2eaz[i]) ?
- dev->drv[drvidx]->msn2eaz[i] : "-",
+ dev->drv[drvidx]->msn2eaz[i] : "_",
(i < 9) ? "," : "\0");
if (copy_to_user(p, bname, strlen(bname) + 1))
return -EFAULT;
int
isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
- ,int pre_chan)
+ ,int pre_chan, char *msn)
{
int i;
ulong flags;
if ((dev->usage[i] & ISDN_USAGE_EXCLUSIVE) &&
((pre_dev != d) || (pre_chan != dev->chanmap[i])))
continue;
+ if (!strcmp(isdn_map_eaz2msn(msn, d), "-"))
+ continue;
if (dev->usage[i] & ISDN_USAGE_DISABLED)
continue; /* usage not allowed */
if (dev->drv[d]->flags & DRV_FLAG_RUNNING) {
* Low-level-driver registration
*/
+static void
+set_global_features(void)
+{
+ int drvidx;
+
+ dev->global_features = 0;
+ for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) {
+ if (!dev->drv[drvidx])
+ continue;
+ if (dev->drv[drvidx]->interface)
+ dev->global_features |= dev->drv[drvidx]->interface->features;
+ }
+}
#ifdef CONFIG_ISDN_DIVERSION
extern isdn_divert_if *divert_if;
strcpy(dev->drvid[drvidx], i->id);
isdn_info_update();
dev->drivers++;
+ set_global_features();
restore_flags(flags);
return 1;
}
-/* $Id: isdn_common.h,v 1.17 1999/10/27 21:21:17 detabc Exp $
+/* $Id: isdn_common.h,v 1.18 2000/01/23 18:45:37 keil Exp $
* header for Linux ISDN subsystem, common used functions and debugging-switches (linklevel).
*
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_common.h,v $
+ * Revision 1.18 2000/01/23 18:45:37 keil
+ * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN)
+ *
* Revision 1.17 1999/10/27 21:21:17 detabc
* Added support for building logically-bind-group's per interface.
* usefull for outgoing call's with more then one isdn-card.
extern void isdn_unexclusive_channel(int di, int ch);
extern int isdn_getnum(char **);
extern int isdn_readbchan(int, int, u_char *, u_char *, int, struct wait_queue**);
-extern int isdn_get_free_channel(int, int, int, int, int);
+extern int isdn_get_free_channel(int, int, int, int, int, char *);
extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
extern int register_isdn(isdn_if * i);
extern int isdn_wildmat(char *, char *);
-/* $Id: isdn_net.c,v 1.95 1999/10/27 21:21:17 detabc Exp $
+/* $Id: isdn_net.c,v 1.103 2000/01/23 18:45:37 keil Exp $
* Linux ISDN subsystem, network interfaces and related functions (linklevel).
*
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_net.c,v $
+ * Revision 1.103 2000/01/23 18:45:37 keil
+ * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN)
+ *
+ * Revision 1.102 2000/01/09 20:43:14 detabc
+ * exand logical bind-group's for both call's (in and out).
+ * add first part of kernel-config-help for abc-extension.
+ *
+ * Revision 1.101 1999/12/05 16:06:08 detabc
+ * add resethandling for rawip-compression.
+ * at now all B2-Protocols are usable with rawip-compression
+ *
+ * Revision 1.100 1999/12/04 15:05:25 detabc
+ * bugfix abc-rawip-bsdcompress with channel-bundeling
+ *
+ * Revision 1.99 1999/11/30 11:29:06 detabc
+ * add a on the fly frame-counter and limit
+ *
+ * Revision 1.98 1999/11/28 14:49:07 detabc
+ * In case of rawip-compress adjust dev[x]->ibytes/obytes to reflect the
+ * uncompressed size.
+ *
+ * Revision 1.97 1999/11/26 15:54:59 detabc
+ * added compression (isdn_bsdcompress) for rawip interfaces with x75i B2-protocol.
+ *
+ * Revision 1.96 1999/11/20 22:14:13 detabc
+ * added channel dial-skip in case of external use
+ * (isdn phone or another isdn device) on the same NTBA.
+ * usefull with two or more card's connected the different NTBA's.
+ * global switchable in kernel-config and also per netinterface.
+ *
+ * add auto disable of netinterface's in case of:
+ * to many connection's in short time.
+ * config mistakes (wrong encapsulation, B2-protokoll or so on) on local
+ * or remote side.
+ * wrong password's or something else to a ISP (syncppp).
+ *
+ * possible encapsulations for this future are:
+ * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP,
+ * and ISDN_NET_ENCAP_CISCOHDLCK.
+ *
* Revision 1.95 1999/10/27 21:21:17 detabc
* Added support for building logically-bind-group's per interface.
* usefull for outgoing call's with more then one isdn-card.
static int isdn_net_start_xmit(struct sk_buff *, struct device *);
static int isdn_net_xmit(struct device *, isdn_net_local *, struct sk_buff *);
-char *isdn_net_revision = "$Revision: 1.95 $";
+char *isdn_net_revision = "$Revision: 1.103 $";
/*
* Code for raw-networking over ISDN
strcpy(addinfo, " IDP");
break;
}
- printk(KERN_INFO "OPEN: %d.%d.%d.%d -> %d.%d.%d.%d%s\n",
+ printk(KERN_INFO
+ "OPEN: %d.%d.%d.%d -> %d.%d.%d.%d%s\n",
p[12], p[13], p[14], p[15],
p[16], p[17], p[18], p[19],
addinfo);
break;
case ETH_P_ARP:
- printk(KERN_INFO "OPEN: ARP %d.%d.%d.%d -> *.*.*.* ?%d.%d.%d.%d\n",
+ printk(KERN_INFO
+ "OPEN: ARP %d.%d.%d.%d -> *.*.*.* ?%d.%d.%d.%d\n",
p[14], p[15], p[16], p[17],
p[24], p[25], p[26], p[27]);
break;
*/
#endif
int
-isdn_net_send_skb(struct device *ndev, isdn_net_local * lp,
- struct sk_buff *skb)
+isdn_net_send_skb
+ (struct device *ndev, isdn_net_local * lp,struct sk_buff *skb)
{
int ret;
int len = skb->len; /* save len */
} else
lp->dialwait_timer = 0;
}
-
/* Grab a free ISDN-Channel */
if (((chi =
isdn_get_free_channel(
lp->l2_proto,
lp->l3_proto,
lp->pre_device,
- lp->pre_channel)
+ lp->pre_channel,
+ lp->msn)
) < 0) &&
((chi =
isdn_get_free_channel(
lp->l2_proto,
lp->l3_proto,
lp->pre_device,
- lp->pre_channel^1)
+ lp->pre_channel^1,
+ lp->msn)
) < 0)) {
restore_flags(flags);
isdn_net_unreachable(ndev, skb,
p = (isdn_net_dev *) p->next;
continue;
}
- }
+ }
if (lp->flags & ISDN_NET_CALLBACK) {
int chi;
/*
isdn_get_free_channel(
ISDN_USAGE_NET,
lp->l2_proto,
- lp->l3_proto,
+ lp->l3_proto,
lp->pre_device,
- lp->pre_channel)
+ lp->pre_channel,
+ lp->msn)
) < 0) {
printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n", lp->name);
lp->l2_proto,
lp->l3_proto,
lp->pre_device,
- lp->pre_channel)
+ lp->pre_channel,
+ lp->msn)
) < 0) {
printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name);
restore_flags(flags);
/* If binding is exclusive, try to grab the channel */
save_flags(flags);
- if ((i = isdn_get_free_channel(ISDN_USAGE_NET, lp->l2_proto,
- lp->l3_proto,
- drvidx,
- chidx)) < 0) {
+ if ((i = isdn_get_free_channel(ISDN_USAGE_NET,
+ lp->l2_proto, lp->l3_proto, drvidx,
+ chidx, lp->msn)) < 0) {
/* Grab failed, because desired channel is in use */
lp->exclusive = -1;
restore_flags(flags);
-/* $Id: isdn_ppp.c,v 1.60 1999/11/04 20:29:55 he Exp $
+/* $Id: isdn_ppp.c,v 1.61 1999/11/20 22:14:14 detabc Exp $
*
* Linux ISDN subsystem, functions for synchronous PPP (linklevel).
*
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_ppp.c,v $
+ * Revision 1.61 1999/11/20 22:14:14 detabc
+ * added channel dial-skip in case of external use
+ * (isdn phone or another isdn device) on the same NTBA.
+ * usefull with two or more card's connected the different NTBA's.
+ * global switchable in kernel-config and also per netinterface.
+ *
+ * add auto disable of netinterface's in case of:
+ * to many connection's in short time.
+ * config mistakes (wrong encapsulation, B2-protokoll or so on) on local
+ * or remote side.
+ * wrong password's or something else to a ISP (syncppp).
+ *
+ * possible encapsulations for this future are:
+ * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP,
+ * and ISDN_NET_ENCAP_CISCOHDLCK.
+ *
* Revision 1.60 1999/11/04 20:29:55 he
* applied Andre Beck's reset_free fix
*
static void isdn_ppp_free_mpqueue(isdn_net_dev *);
#endif
-char *isdn_ppp_revision = "$Revision: 1.60 $";
+char *isdn_ppp_revision = "$Revision: 1.61 $";
static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
-/* $Id: isdn_tty.c,v 1.80 1999/11/07 13:34:30 armin Exp $
+/* $Id: isdn_tty.c,v 1.82 2000/01/23 18:45:37 keil Exp $
* Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
*
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_tty.c,v $
+ * Revision 1.82 2000/01/23 18:45:37 keil
+ * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN)
+ *
+ * Revision 1.81 2000/01/20 19:55:33 keil
+ * Add FAX Class 1 support
+ *
* Revision 1.80 1999/11/07 13:34:30 armin
* Fixed AT command line editor
*
#endif
#define FIX_FILE_TRANSFER
+#define DUMMY_HAYES_AT
/* Prototypes */
static int si2bit[8] =
{4, 1, 4, 4, 4, 4, 4, 4};
-char *isdn_tty_revision = "$Revision: 1.80 $";
+char *isdn_tty_revision = "$Revision: 1.82 $";
/* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
m->mdmreg[REG_SI1I] = si2bit[si];
save_flags(flags);
cli();
- i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1);
+ i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
if (i < 0) {
restore_flags(flags);
isdn_tty_modem_result(6, info);
m->mdmreg[REG_SI1I] = si2bit[si];
save_flags(flags);
cli();
- i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1);
+ i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
if (i < 0) {
restore_flags(flags);
isdn_tty_modem_result(6, info);
m->mdmreg[REG_SI1I] = si2bit[si];
save_flags(flags);
cli();
- i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1);
+ i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
if (i < 0) {
restore_flags(flags);
isdn_tty_modem_result(6, info);
}
}
} else
+ if (TTY_IS_FCLASS1(info)) {
+ int cc = isdn_tty_handleDLEdown(info, m, c);
+
+ if (info->vonline & 4) { /* ETX seen */
+ isdn_ctrl c;
+
+ c.command = ISDN_CMD_FAXCMD;
+ c.driver = info->isdn_driver;
+ c.arg = info->isdn_channel;
+ c.parm.aux.cmd = ISDN_FAX_CLASS1_CTRL;
+ c.parm.aux.subcmd = ETX;
+ isdn_command(&c);
+ }
+ info->vonline = 0;
+ printk(KERN_DEBUG "fax dle cc/c %d/%d\n", cc,c);
+ info->xmit_count += cc;
+ } else
#endif
info->xmit_count += c;
} else {
(info->flags & (ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE))
int
-isdn_tty_stat_callback(int i, isdn_ctrl * c)
+isdn_tty_stat_callback(int i, isdn_ctrl *c)
{
int mi;
modem_info *info;
if (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) {
strcpy(info->emu.connmsg, c->parm.num);
isdn_tty_modem_result(1, info);
- }
- else
+ } else
isdn_tty_modem_result(5, info);
}
if (USG_VOICE(dev->usage[i]))
#ifdef CONFIG_ISDN_TTY_FAX
case ISDN_STAT_FAXIND:
if (TTY_IS_ACTIVE(info)) {
- isdn_tty_fax_command(info);
+ isdn_tty_fax_command(info, c);
}
break;
#endif
info->xmit_size /= 10;
}
break;
+ case 'C':
+ /* &C - DCD Status */
+ p[0]++;
+ switch (isdn_getnum(p)) {
+ case 0:
+ m->mdmreg[REG_DCD] &= ~BIT_DCD;
+ break;
+ case 1:
+ m->mdmreg[REG_DCD] |= BIT_DCD;
+ break;
+ default:
+ PARSE_ERROR1
+ }
+ break;
case 'D':
- /* &D - Set DCD-Low-behavior */
+ /* &D - Set DTR-Low-behavior */
p[0]++;
switch (isdn_getnum(p)) {
case 0:
isdn_tty_reset_profile(m);
isdn_tty_modem_reset_regs(info, 1);
break;
+#ifdef DUMMY_HAYES_AT
+ case 'K':
+ /* only for be compilant with common scripts */
+ /* &K Flowcontrol - no function */
+ p[0]++;
+ isdn_getnum(p);
+ break;
+#endif
case 'L':
/* &L -Set Numbers to listen on */
p[0]++;
sprintf(rs, "\r\n%d",
(m->mdmreg[REG_SI1] & 1) ? 8 : 0);
#ifdef CONFIG_ISDN_TTY_FAX
- if (m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX)
- sprintf(rs, "\r\n2");
+ if (TTY_IS_FCLASS2(info))
+ sprintf(rs, "\r\n2");
+ else if (TTY_IS_FCLASS1(info))
+ sprintf(rs, "\r\n1");
#endif
isdn_tty_at_cout(rs, info);
break;
m->mdmreg[REG_PSIZE] * 16;
break;
#ifdef CONFIG_ISDN_TTY_FAX
+ case '1':
+ p[0]++;
+ if (!(dev->global_features &
+ ISDN_FEATURE_L3_FCLASS1))
+ PARSE_ERROR1;
+ m->mdmreg[REG_SI1] = 1;
+ m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_FAX;
+ m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_FCLASS1;
+ info->xmit_size =
+ m->mdmreg[REG_PSIZE] * 16;
+ break;
case '2':
p[0]++;
+ if (!(dev->global_features &
+ ISDN_FEATURE_L3_FCLASS2))
+ PARSE_ERROR1;
m->mdmreg[REG_SI1] = 1;
m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_FAX;
- m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_FAX;
+ m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_FCLASS2;
info->xmit_size =
m->mdmreg[REG_PSIZE] * 16;
break;
break;
case '?':
p[0]++;
+ strcpy(rs, "\r\n0,");
#ifdef CONFIG_ISDN_TTY_FAX
- isdn_tty_at_cout("\r\n0,2,8", info);
-#else
- isdn_tty_at_cout("\r\n0,8", info);
+ if (dev->global_features &
+ ISDN_FEATURE_L3_FCLASS1)
+ strcat(rs, "1,");
+ if (dev->global_features &
+ ISDN_FEATURE_L3_FCLASS2)
+ strcat(rs, "2,");
#endif
+ strcat(rs, "8");
+ isdn_tty_at_cout(rs, info);
break;
default:
PARSE_ERROR1;
default:
}
break;
+#ifdef DUMMY_HAYES_AT
+ case 'L':
+ case 'M':
+ /* only for be compilant with common scripts */
+ /* no function */
+ p++;
+ isdn_getnum(&p);
+ break;
+#endif
case 'O':
/* O - Go online */
p++;
-/* $Id: isdn_tty.h,v 1.17 1999/09/21 19:00:35 armin Exp $
+/* $Id: isdn_tty.h,v 1.18 2000/01/20 19:55:33 keil Exp $
* header for Linux ISDN subsystem, tty related functions (linklevel).
*
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_tty.h,v $
+ * Revision 1.18 2000/01/20 19:55:33 keil
+ * Add FAX Class 1 support
+ *
* Revision 1.17 1999/09/21 19:00:35 armin
* Extended FCON message with added CPN
* can now be activated with Bit 1 of Reg 23.
#define BIT_CPN 1
#define BIT_CPNFCON 2
+#define TTY_IS_FCLASS1(info) \
+ ((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) && \
+ (info->emu.mdmreg[REG_L3PROT] == ISDN_PROTO_L3_FCLASS1))
+#define TTY_IS_FCLASS2(info) \
+ ((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) && \
+ (info->emu.mdmreg[REG_L3PROT] == ISDN_PROTO_L3_FCLASS2))
+
extern void isdn_tty_modem_escape(void);
extern void isdn_tty_modem_ring(void);
extern void isdn_tty_carrier_timeout(void);
extern void isdn_tty_modem_hup(modem_info *, int);
#ifdef CONFIG_ISDN_TTY_FAX
extern int isdn_tty_cmd_PLUSF_FAX(char **, modem_info *);
-extern int isdn_tty_fax_command(modem_info *);
+extern int isdn_tty_fax_command(modem_info *, isdn_ctrl *);
extern void isdn_tty_fax_bitorder(modem_info *, struct sk_buff *);
#endif
-/* $Id: isdn_ttyfax.c,v 1.4 1999/09/21 19:00:35 armin Exp $
+/* $Id: isdn_ttyfax.c,v 1.6 2000/01/26 00:41:13 keil Exp $
* Linux ISDN subsystem, tty_fax AT-command emulator (linklevel).
*
* Copyright 1999 by Armin Schindler (mac@melware.de)
* Copyright 1999 by Ralf Spachmann (mel@melware.de)
- * Copyright 1999 by Cytronics & Melware
+ * Copyright 1999 by Cytronics & Melware
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_ttyfax.c,v $
+ * Revision 1.6 2000/01/26 00:41:13 keil
+ * add "00" as dummy msn in isdn_get_free_channel call
+ *
+ * Revision 1.5 2000/01/20 19:55:33 keil
+ * Add FAX Class 1 support
+ *
* Revision 1.4 1999/09/21 19:00:35 armin
* Extended FCON message with added CPN
* can now be activated with Bit 1 of Reg 23.
#include "isdn_ttyfax.h"
-static char *isdn_tty_fax_revision = "$Revision: 1.4 $";
+static char *isdn_tty_fax_revision = "$Revision: 1.6 $";
#define PARSE_ERROR1 { isdn_tty_fax_modem_result(1, info); return 1; }
static char *
isdn_getrev(const char *revision)
{
- char *rev;
- char *p;
+ char *rev;
+ char *p;
- if ((p = strchr(revision, ':'))) {
- rev = p + 2;
- p = strchr(rev, '$');
- *--p = 0;
- } else
- rev = "???";
- return rev;
+ if ((p = strchr(revision, ':'))) {
+ rev = p + 2;
+ p = strchr(rev, '$');
+ *--p = 0;
+ } else
+ rev = "???";
+ return rev;
}
-
/*
* Fax Class 2 Modem results
*
*/
-static void isdn_tty_fax_modem_result(int code, modem_info * info)
+
+static void
+isdn_tty_fax_modem_result(int code, modem_info * info)
{
atemu *m = &info->emu;
T30_s *f = info->fax;
static char *msg[] =
{"OK", "ERROR", "+FCON", "+FCSI:", "+FDIS:",
"+FHNG:", "+FDCS:", "CONNECT", "+FTSI:",
- "+FCFR", "+FPTS:", "+FET:" };
+ "+FCFR", "+FPTS:", "+FET:"};
isdn_tty_at_cout("\r\n", info);
case 3: /* +FCSI */
case 8: /* +FTSI */
sprintf(rs, "\"%s\"", f->r_id);
- isdn_tty_at_cout(rs, info);
+ isdn_tty_at_cout(rs, info);
break;
case 4: /* +FDIS */
rs[0] = 0;
rp = &f->r_resolution;
- for(i = 0; i < 8; i++) {
+ for (i = 0; i < 8; i++) {
sprintf(rss, "%c%s", rp[i] + 48,
(i < 7) ? "," : "");
strcat(rs, rss);
isdn_tty_at_cout(rs, info);
#ifdef ISDN_TTY_FAX_CMD_DEBUG
printk(KERN_DEBUG "isdn_tty: Fax DIS=%s on ttyI%d\n",
- rs, info->line);
+ rs, info->line);
#endif
break;
case 5: /* +FHNG */
sprintf(rs, "%d", f->code);
- isdn_tty_at_cout(rs, info);
+ isdn_tty_at_cout(rs, info);
info->faxonline = 0;
break;
case 6: /* +FDCS */
rs[0] = 0;
rp = &f->r_resolution;
- for(i = 0; i < 8; i++) {
+ for (i = 0; i < 8; i++) {
sprintf(rss, "%c%s", rp[i] + 48,
(i < 7) ? "," : "");
strcat(rs, rss);
isdn_tty_at_cout(rs, info);
#ifdef ISDN_TTY_FAX_CMD_DEBUG
printk(KERN_DEBUG "isdn_tty: Fax DCS=%s on ttyI%d\n",
- rs, info->line);
+ rs, info->line);
#endif
break;
case 7: /* CONNECT */
info->faxonline |= 2;
break;
- case 9: /* FCFR */
+ case 9: /* FCFR */
break;
- case 10: /* FPTS */
+ case 10: /* FPTS */
isdn_tty_at_cout("1", info);
break;
- case 11: /* FET */
+ case 11: /* FET */
sprintf(rs, "%d", f->fet);
- isdn_tty_at_cout(rs, info);
+ isdn_tty_at_cout(rs, info);
break;
}
isdn_tty_at_cout("\r\n", info);
switch (code) {
- case 7: /* CONNECT */
+ case 7: /* CONNECT */
info->online = 2;
if (info->faxonline & 1) {
sprintf(rs, "%c", XON);
- isdn_tty_at_cout(rs, info);
+ isdn_tty_at_cout(rs, info);
+ }
+ break;
+ }
+}
+
+int
+isdn_tty_fax_command1(modem_info * info, isdn_ctrl * c)
+{
+ static char *msg[] =
+ {"OK", "CONNECT", "NO CARRIER", "ERROR", "FCERROR"};
+
+#ifdef ISDN_TTY_FAX_CMD_DEBUG
+ printk(KERN_DEBUG "isdn_tty: FCLASS1 cmd(%d)\n", c->parm.aux.cmd);
+#endif
+ if (c->parm.aux.cmd < ISDN_FAX_CLASS1_QUERY) {
+ if (info->online)
+ info->online = 1;
+ isdn_tty_at_cout("\r\n", info);
+ isdn_tty_at_cout(msg[c->parm.aux.cmd], info);
+ isdn_tty_at_cout("\r\n", info);
+ }
+ switch (c->parm.aux.cmd) {
+ case ISDN_FAX_CLASS1_CONNECT:
+ info->online = 2;
+ break;
+ case ISDN_FAX_CLASS1_OK:
+ case ISDN_FAX_CLASS1_FCERROR:
+ case ISDN_FAX_CLASS1_ERROR:
+ case ISDN_FAX_CLASS1_NOCARR:
+ break;
+ case ISDN_FAX_CLASS1_QUERY:
+ isdn_tty_at_cout("\r\n", info);
+ if (!c->parm.aux.para[0]) {
+ isdn_tty_at_cout(msg[ISDN_FAX_CLASS1_ERROR], info);
+ isdn_tty_at_cout("\r\n", info);
+ } else {
+ isdn_tty_at_cout(c->parm.aux.para, info);
+ isdn_tty_at_cout("\r\nOK\r\n", info);
}
break;
}
+ return (0);
}
int
-isdn_tty_fax_command(modem_info * info)
+isdn_tty_fax_command(modem_info * info, isdn_ctrl * c)
{
T30_s *f = info->fax;
char rs[10];
+ if (TTY_IS_FCLASS1(info))
+ return (isdn_tty_fax_command1(info, c));
+
#ifdef ISDN_TTY_FAX_CMD_DEBUG
printk(KERN_DEBUG "isdn_tty: Fax cmd %d on ttyI%d\n",
- f->r_code, info->line);
+ f->r_code, info->line);
#endif
- switch(f->r_code) {
+ switch (f->r_code) {
case ISDN_TTY_FAX_FCON:
info->faxonline = 1;
- isdn_tty_fax_modem_result(2, info); /* +FCON */
- return(0);
+ isdn_tty_fax_modem_result(2, info); /* +FCON */
+ return (0);
case ISDN_TTY_FAX_FCON_I:
info->faxonline = 16;
- isdn_tty_fax_modem_result(2, info); /* +FCON */
- return(0);
+ isdn_tty_fax_modem_result(2, info); /* +FCON */
+ return (0);
case ISDN_TTY_FAX_RID:
if (info->faxonline & 1)
- isdn_tty_fax_modem_result(3, info); /* +FCSI */
+ isdn_tty_fax_modem_result(3, info); /* +FCSI */
if (info->faxonline & 16)
- isdn_tty_fax_modem_result(8, info); /* +FTSI */
- return(0);
+ isdn_tty_fax_modem_result(8, info); /* +FTSI */
+ return (0);
case ISDN_TTY_FAX_DIS:
- isdn_tty_fax_modem_result(4, info); /* +FDIS */
- return(0);
+ isdn_tty_fax_modem_result(4, info); /* +FDIS */
+ return (0);
case ISDN_TTY_FAX_HNG:
if (f->phase == ISDN_FAX_PHASE_C) {
if (f->direction == ISDN_TTY_FAX_CONN_IN) {
sprintf(rs, "%c%c", DLE, ETX);
- isdn_tty_at_cout(rs, info);
+ isdn_tty_at_cout(rs, info);
} else {
sprintf(rs, "%c", 0x18);
- isdn_tty_at_cout(rs, info);
+ isdn_tty_at_cout(rs, info);
}
- info->faxonline &= ~2; /* leave data mode */
+ info->faxonline &= ~2; /* leave data mode */
info->online = 1;
}
f->phase = ISDN_FAX_PHASE_E;
- isdn_tty_fax_modem_result(5, info); /* +FHNG */
- isdn_tty_fax_modem_result(0, info); /* OK */
- return(0);
+ isdn_tty_fax_modem_result(5, info); /* +FHNG */
+ isdn_tty_fax_modem_result(0, info); /* OK */
+ return (0);
case ISDN_TTY_FAX_DCS:
- isdn_tty_fax_modem_result(6, info); /* +FDCS */
- isdn_tty_fax_modem_result(7, info); /* CONNECT */
+ isdn_tty_fax_modem_result(6, info); /* +FDCS */
+ isdn_tty_fax_modem_result(7, info); /* CONNECT */
f->phase = ISDN_FAX_PHASE_C;
- return(0);
+ return (0);
case ISDN_TTY_FAX_TRAIN_OK:
- isdn_tty_fax_modem_result(6, info); /* +FDCS */
- isdn_tty_fax_modem_result(0, info); /* OK */
- return(0);
+ isdn_tty_fax_modem_result(6, info); /* +FDCS */
+ isdn_tty_fax_modem_result(0, info); /* OK */
+ return (0);
case ISDN_TTY_FAX_SENT:
- isdn_tty_fax_modem_result(0, info); /* OK */
- return(0);
+ isdn_tty_fax_modem_result(0, info); /* OK */
+ return (0);
case ISDN_TTY_FAX_CFR:
- isdn_tty_fax_modem_result(9, info); /* +FCFR */
- return(0);
+ isdn_tty_fax_modem_result(9, info); /* +FCFR */
+ return (0);
case ISDN_TTY_FAX_ET:
sprintf(rs, "%c%c", DLE, ETX);
- isdn_tty_at_cout(rs, info);
- isdn_tty_fax_modem_result(10, info); /* +FPTS */
- isdn_tty_fax_modem_result(11, info); /* +FET */
- isdn_tty_fax_modem_result(0, info); /* OK */
- info->faxonline &= ~2; /* leave data mode */
+ isdn_tty_at_cout(rs, info);
+ isdn_tty_fax_modem_result(10, info); /* +FPTS */
+ isdn_tty_fax_modem_result(11, info); /* +FET */
+ isdn_tty_fax_modem_result(0, info); /* OK */
+ info->faxonline &= ~2; /* leave data mode */
info->online = 1;
f->phase = ISDN_FAX_PHASE_D;
- return(0);
+ return (0);
case ISDN_TTY_FAX_PTS:
- isdn_tty_fax_modem_result(10, info); /* +FPTS */
+ isdn_tty_fax_modem_result(10, info); /* +FPTS */
if (f->direction == ISDN_TTY_FAX_CONN_OUT) {
if (f->fet == 1)
f->phase = ISDN_FAX_PHASE_B;
if (f->fet == 0)
- isdn_tty_fax_modem_result(0, info); /* OK */
+ isdn_tty_fax_modem_result(0, info); /* OK */
}
- return(0);
+ return (0);
case ISDN_TTY_FAX_EOP:
- info->faxonline &= ~2; /* leave data mode */
+ info->faxonline &= ~2; /* leave data mode */
info->online = 1;
f->phase = ISDN_FAX_PHASE_D;
- return(0);
+ return (0);
}
- return(-1);
+ return (-1);
}
void
-isdn_tty_fax_bitorder(modem_info *info, struct sk_buff *skb)
+isdn_tty_fax_bitorder(modem_info * info, struct sk_buff *skb)
{
__u8 LeftMask;
__u8 RightMask;
int i;
if (!info->fax->bor) {
- for(i = 0; i < skb->len; i++) {
+ for (i = 0; i < skb->len; i++) {
Data = skb->data[i];
for (
- LeftMask = 0x80, RightMask = 0x01;
- LeftMask > RightMask;
- LeftMask >>= 1, RightMask <<= 1
- ) {
+ LeftMask = 0x80, RightMask = 0x01;
+ LeftMask > RightMask;
+ LeftMask >>= 1, RightMask <<= 1
+ ) {
fBit = (Data & LeftMask);
if (Data & RightMask)
Data |= LeftMask;
}
}
+/*
+ * Parse AT+F.. FAX class 1 commands
+ */
+
+int
+isdn_tty_cmd_FCLASS1(char **p, modem_info * info)
+{
+ static char *cmd[] =
+ {"AE", "TS", "RS", "TM", "RM", "TH", "RH"};
+ isdn_ctrl c;
+ int par, i;
+ long flags;
+
+ for (c.parm.aux.cmd = 0; c.parm.aux.cmd < 7; c.parm.aux.cmd++)
+ if (!strncmp(p[0], cmd[c.parm.aux.cmd], 2))
+ break;
+
+#ifdef ISDN_TTY_FAX_CMD_DEBUG
+ printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 (%s,%d)\n", p[0], c.parm.aux.cmd);
+#endif
+ if (c.parm.aux.cmd == 7)
+ PARSE_ERROR1;
+
+ p[0] += 2;
+ switch (*p[0]) {
+ case '?':
+ p[0]++;
+ c.parm.aux.subcmd = AT_QUERY;
+ break;
+ case '=':
+ p[0]++;
+ if (*p[0] == '?') {
+ p[0]++;
+ c.parm.aux.subcmd = AT_EQ_QUERY;
+ } else {
+ par = isdn_getnum(p);
+ if ((par < 0) || (par > 255))
+ PARSE_ERROR1;
+ c.parm.aux.subcmd = AT_EQ_VALUE;
+ c.parm.aux.para[0] = par;
+ }
+ break;
+ case 0:
+ c.parm.aux.subcmd = AT_COMMAND;
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ c.command = ISDN_CMD_FAXCMD;
+#ifdef ISDN_TTY_FAX_CMD_DEBUG
+ printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 %d/%d/%d)\n",
+ c.parm.aux.cmd, c.parm.aux.subcmd, c.parm.aux.para[0]);
+#endif
+ if (info->isdn_driver < 0) {
+ save_flags(flags);
+ cli();
+ if ((c.parm.aux.subcmd == AT_EQ_VALUE) ||
+ (c.parm.aux.subcmd == AT_COMMAND)) {
+ restore_flags(flags);
+ PARSE_ERROR1;
+ }
+ /* get a temporary connection to the first free fax driver */
+ i = isdn_get_free_channel(ISDN_USAGE_FAX, ISDN_PROTO_L2_FAX,
+ ISDN_PROTO_L3_FCLASS1, -1, -1, "00");
+ if (i < 0) {
+ restore_flags(flags);
+ PARSE_ERROR1;
+ }
+ info->isdn_driver = dev->drvmap[i];
+ info->isdn_channel = dev->chanmap[i];
+ info->drv_index = i;
+ dev->m_idx[i] = info->line;
+ c.driver = info->isdn_driver;
+ c.arg = info->isdn_channel;
+ isdn_command(&c);
+ isdn_free_channel(info->isdn_driver, info->isdn_channel,
+ ISDN_USAGE_FAX);
+ info->isdn_driver = -1;
+ info->isdn_channel = -1;
+ if (info->drv_index >= 0) {
+ dev->m_idx[info->drv_index] = -1;
+ info->drv_index = -1;
+ }
+ restore_flags(flags);
+ } else {
+ c.driver = info->isdn_driver;
+ c.arg = info->isdn_channel;
+ isdn_command(&c);
+ }
+ return 1;
+}
+
/*
* Parse AT+F.. FAX class 2 commands
*/
-int isdn_tty_cmd_PLUSF_FAX(char **p, modem_info * info)
+int
+isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
{
atemu *m = &info->emu;
T30_s *f = info->fax;
int par;
char rs[50];
char rss[50];
- int maxdccval[]={1,5,2,2,3,2,0,7};
+ int maxdccval[] =
+ {1, 5, 2, 2, 3, 2, 0, 7};
/* FAA still unchanged */
- if (!strncmp(p[0], "AA", 2)) { /* TODO */
+ if (!strncmp(p[0], "AA", 2)) { /* TODO */
p[0] += 2;
switch (*p[0]) {
case '?':
PARSE_ERROR1;
}
return 0;
- }
-
+ }
/* BADLIN=value - dummy 0=disable errorchk disabled, 1-255 nr. of lines for making page bad */
- if (!strncmp(p[0], "BADLIN", 6)) {
- p[0] += 6;
+ if (!strncmp(p[0], "BADLIN", 6)) {
+ p[0] += 6;
switch (*p[0]) {
case '?':
p[0]++;
- sprintf(rs, "\r\n%d",f->badlin);
- isdn_tty_at_cout(rs, info);
+ sprintf(rs, "\r\n%d", f->badlin);
+ isdn_tty_at_cout(rs, info);
break;
case '=':
- p[0]++;
- if (*p[0] == '?')
- {
- p[0]++;
- sprintf(rs, "\r\n0-255");
- isdn_tty_at_cout(rs, info);
- }
- else
- {
- par = isdn_getnum(p);
- if ((par < 0) || (par > 255))
- PARSE_ERROR1;
- f->badlin = par;
+ p[0]++;
+ if (*p[0] == '?') {
+ p[0]++;
+ sprintf(rs, "\r\n0-255");
+ isdn_tty_at_cout(rs, info);
+ } else {
+ par = isdn_getnum(p);
+ if ((par < 0) || (par > 255))
+ PARSE_ERROR1;
+ f->badlin = par;
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: Fax FBADLIN=%d\n", par);
+ printk(KERN_DEBUG "isdn_tty: Fax FBADLIN=%d\n", par);
#endif
- }
- break;
+ }
+ break;
default:
- PARSE_ERROR1;
+ PARSE_ERROR1;
}
- return 0;
- }
-
+ return 0;
+ }
/* BADMUL=value - dummy 0=disable errorchk disabled (treshold multiplier) */
- if (!strncmp(p[0], "BADMUL", 6)){
- p[0] +=6;
+ if (!strncmp(p[0], "BADMUL", 6)) {
+ p[0] += 6;
switch (*p[0]) {
case '?':
p[0]++;
- sprintf(rs, "\r\n%d", f->badmul);
- isdn_tty_at_cout(rs, info);
+ sprintf(rs, "\r\n%d", f->badmul);
+ isdn_tty_at_cout(rs, info);
break;
case '=':
- p[0]++;
- if (*p[0] == '?')
- {
- p[0]++;
- sprintf(rs, "\r\n0-255");
- isdn_tty_at_cout(rs, info);
- }
- else
- {
- par = isdn_getnum(p);
- if ((par < 0) || (par > 255))
- PARSE_ERROR1;
- f->badmul = par;
+ p[0]++;
+ if (*p[0] == '?') {
+ p[0]++;
+ sprintf(rs, "\r\n0-255");
+ isdn_tty_at_cout(rs, info);
+ } else {
+ par = isdn_getnum(p);
+ if ((par < 0) || (par > 255))
+ PARSE_ERROR1;
+ f->badmul = par;
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: Fax FBADMUL=%d\n", par);
+ printk(KERN_DEBUG "isdn_tty: Fax FBADMUL=%d\n", par);
#endif
- }
- break;
+ }
+ break;
default:
PARSE_ERROR1;
}
- return 0;
- }
-
+ return 0;
+ }
/* BOR=n - Phase C bit order, 0=direct, 1=reverse */
- if (!strncmp(p[0], "BOR", 3)){
- p[0] +=3;
+ if (!strncmp(p[0], "BOR", 3)) {
+ p[0] += 3;
switch (*p[0]) {
case '?':
p[0]++;
- sprintf(rs, "\r\n%d", f->bor);
- isdn_tty_at_cout(rs, info);
+ sprintf(rs, "\r\n%d", f->bor);
+ isdn_tty_at_cout(rs, info);
break;
case '=':
- p[0]++;
- if (*p[0] == '?')
- {
- p[0]++;
- sprintf(rs, "\r\n0,1");
- isdn_tty_at_cout(rs, info);
- }
- else
- {
- par = isdn_getnum(p);
- if ((par < 0) || (par > 1))
- PARSE_ERROR1;
- f->bor = par;
+ p[0]++;
+ if (*p[0] == '?') {
+ p[0]++;
+ sprintf(rs, "\r\n0,1");
+ isdn_tty_at_cout(rs, info);
+ } else {
+ par = isdn_getnum(p);
+ if ((par < 0) || (par > 1))
+ PARSE_ERROR1;
+ f->bor = par;
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: Fax FBOR=%d\n", par);
+ printk(KERN_DEBUG "isdn_tty: Fax FBOR=%d\n", par);
#endif
- }
- break;
- default:
- PARSE_ERROR1;
- }
- return 0;
- }
-
+ }
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ return 0;
+ }
/* NBC=n - No Best Capabilities */
- if (!strncmp(p[0], "NBC", 3)){
- p[0] +=3;
+ if (!strncmp(p[0], "NBC", 3)) {
+ p[0] += 3;
switch (*p[0]) {
case '?':
p[0]++;
- sprintf(rs, "\r\n%d", f->nbc);
- isdn_tty_at_cout(rs, info);
+ sprintf(rs, "\r\n%d", f->nbc);
+ isdn_tty_at_cout(rs, info);
break;
case '=':
- p[0]++;
- if (*p[0] == '?')
- {
- p[0]++;
- sprintf(rs, "\r\n0,1");
- isdn_tty_at_cout(rs, info);
- }
- else
- {
- par = isdn_getnum(p);
- if ((par < 0) || (par > 1))
- PARSE_ERROR1;
- f->nbc = par;
+ p[0]++;
+ if (*p[0] == '?') {
+ p[0]++;
+ sprintf(rs, "\r\n0,1");
+ isdn_tty_at_cout(rs, info);
+ } else {
+ par = isdn_getnum(p);
+ if ((par < 0) || (par > 1))
+ PARSE_ERROR1;
+ f->nbc = par;
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: Fax FNBC=%d\n", par);
+ printk(KERN_DEBUG "isdn_tty: Fax FNBC=%d\n", par);
#endif
- }
- break;
- default:
- PARSE_ERROR1;
- }
- return 0;
- }
-
+ }
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ return 0;
+ }
/* BUF? - Readonly buffersize readout */
- if (!strncmp(p[0], "BUF?", 4)) {
- p[0] += 4;
+ if (!strncmp(p[0], "BUF?", 4)) {
+ p[0] += 4;
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: Fax FBUF? (%d) \n", (16 * m->mdmreg[REG_PSIZE]));
+ printk(KERN_DEBUG "isdn_tty: Fax FBUF? (%d) \n", (16 * m->mdmreg[REG_PSIZE]));
#endif
- p[0]++;
- sprintf(rs, "\r\n %d ", (16 * m->mdmreg[REG_PSIZE]));
- isdn_tty_at_cout(rs, info);
- return 0;
- }
-
+ p[0]++;
+ sprintf(rs, "\r\n %d ", (16 * m->mdmreg[REG_PSIZE]));
+ isdn_tty_at_cout(rs, info);
+ return 0;
+ }
/* CIG=string - local fax station id string for polling rx */
- if (!strncmp(p[0], "CIG", 3)) {
+ if (!strncmp(p[0], "CIG", 3)) {
int i, r;
- p[0] += 3;
+ p[0] += 3;
switch (*p[0]) {
case '?':
p[0]++;
sprintf(rs, "\r\n\"%s\"", f->pollid);
- isdn_tty_at_cout(rs, info);
- break;
+ isdn_tty_at_cout(rs, info);
+ break;
case '=':
- p[0]++;
- if (*p[0] == '?')
- {
- p[0]++;
- sprintf(rs, "\r\n\"STRING\"");
- isdn_tty_at_cout(rs, info);
- }
- else
- {
- if (*p[0] =='"')
- p[0]++;
- for(i=0; (*p[0]) && i < (FAXIDLEN-1) && (*p[0] != '"'); i++)
- {
- f->pollid[i] = *p[0]++;
- }
- if (*p[0] =='"')
- p[0]++;
- for(r=i; r < FAXIDLEN; r++)
- {
- f->pollid[r] = 32;
- }
- f->pollid[FAXIDLEN-1] = 0;
+ p[0]++;
+ if (*p[0] == '?') {
+ p[0]++;
+ sprintf(rs, "\r\n\"STRING\"");
+ isdn_tty_at_cout(rs, info);
+ } else {
+ if (*p[0] == '"')
+ p[0]++;
+ for (i = 0; (*p[0]) && i < (FAXIDLEN - 1) && (*p[0] != '"'); i++) {
+ f->pollid[i] = *p[0]++;
+ }
+ if (*p[0] == '"')
+ p[0]++;
+ for (r = i; r < FAXIDLEN; r++) {
+ f->pollid[r] = 32;
+ }
+ f->pollid[FAXIDLEN - 1] = 0;
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: Fax local poll ID rx \"%s\"\n", f->pollid);
+ printk(KERN_DEBUG "isdn_tty: Fax local poll ID rx \"%s\"\n", f->pollid);
#endif
- }
- break;
+ }
+ break;
default:
PARSE_ERROR1;
}
- return 0;
- }
-
+ return 0;
+ }
/* CQ=n - copy qlty chk, 0= no chk, 1=only 1D chk, 2=1D+2D chk */
- if (!strncmp(p[0], "CQ", 2)) {
- p[0] += 2;
+ if (!strncmp(p[0], "CQ", 2)) {
+ p[0] += 2;
switch (*p[0]) {
case '?':
p[0]++;
- sprintf(rs, "\r\n%d", f->cq);
- isdn_tty_at_cout(rs, info);
+ sprintf(rs, "\r\n%d", f->cq);
+ isdn_tty_at_cout(rs, info);
break;
case '=':
- p[0]++;
- if (*p[0] == '?')
- {
- p[0]++;
- sprintf(rs, "\r\n0,1,2");
- isdn_tty_at_cout(rs, info);
- }
- else
- {
- par = isdn_getnum(p);
- if ((par < 0) || (par > 2))
- PARSE_ERROR1;
- f->cq = par;
+ p[0]++;
+ if (*p[0] == '?') {
+ p[0]++;
+ sprintf(rs, "\r\n0,1,2");
+ isdn_tty_at_cout(rs, info);
+ } else {
+ par = isdn_getnum(p);
+ if ((par < 0) || (par > 2))
+ PARSE_ERROR1;
+ f->cq = par;
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: Fax FCQ=%d\n", par);
+ printk(KERN_DEBUG "isdn_tty: Fax FCQ=%d\n", par);
#endif
- }
- break;
+ }
+ break;
default:
PARSE_ERROR1;
}
- return 0;
- }
-
+ return 0;
+ }
/* CR=n - can receive? 0= no data rx or poll remote dev, 1=do receive data or poll remote dev */
- if (!strncmp(p[0], "CR", 2)) {
- p[0] += 2;
+ if (!strncmp(p[0], "CR", 2)) {
+ p[0] += 2;
switch (*p[0]) {
case '?':
p[0]++;
- sprintf(rs, "\r\n%d", f->cr); /* read actual value from struct and print */
- isdn_tty_at_cout(rs, info);
+ sprintf(rs, "\r\n%d", f->cr); /* read actual value from struct and print */
+ isdn_tty_at_cout(rs, info);
break;
case '=':
- p[0]++;
- if (*p[0] == '?')
- {
- p[0]++;
- sprintf(rs, "\r\n0,1"); /* display online help */
- isdn_tty_at_cout(rs, info);
- }
- else
- {
- par = isdn_getnum(p);
- if ((par < 0) || (par > 1))
- PARSE_ERROR1;
- f->cr = par;
+ p[0]++;
+ if (*p[0] == '?') {
+ p[0]++;
+ sprintf(rs, "\r\n0,1"); /* display online help */
+ isdn_tty_at_cout(rs, info);
+ } else {
+ par = isdn_getnum(p);
+ if ((par < 0) || (par > 1))
+ PARSE_ERROR1;
+ f->cr = par;
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: Fax FCR=%d\n", par);
+ printk(KERN_DEBUG "isdn_tty: Fax FCR=%d\n", par);
#endif
- }
- break;
+ }
+ break;
default:
PARSE_ERROR1;
}
- return 0;
- }
-
+ return 0;
+ }
/* CTCRTY=value - ECM retry count */
- if (!strncmp(p[0], "CTCRTY", 6)){
- p[0] +=6;
+ if (!strncmp(p[0], "CTCRTY", 6)) {
+ p[0] += 6;
switch (*p[0]) {
case '?':
p[0]++;
- sprintf(rs, "\r\n%d",f->ctcrty);
- isdn_tty_at_cout(rs, info);
+ sprintf(rs, "\r\n%d", f->ctcrty);
+ isdn_tty_at_cout(rs, info);
break;
case '=':
- p[0]++;
- if (*p[0] == '?')
- {
- p[0]++;
- sprintf(rs, "\r\n0-255");
- isdn_tty_at_cout(rs, info);
- }
- else
- {
- par = isdn_getnum(p);
- if ((par < 0) || (par > 255))
- PARSE_ERROR1;
- f->ctcrty = par;
+ p[0]++;
+ if (*p[0] == '?') {
+ p[0]++;
+ sprintf(rs, "\r\n0-255");
+ isdn_tty_at_cout(rs, info);
+ } else {
+ par = isdn_getnum(p);
+ if ((par < 0) || (par > 255))
+ PARSE_ERROR1;
+ f->ctcrty = par;
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: Fax FCTCRTY=%d\n", par);
+ printk(KERN_DEBUG "isdn_tty: Fax FCTCRTY=%d\n", par);
#endif
- }
- break;
+ }
+ break;
default:
PARSE_ERROR1;
}
- return 0;
- }
-
+ return 0;
+ }
/* DCC=vr,br,wd,ln,df,ec,bf,st - DCE capabilities parms */
- if (!strncmp(p[0], "DCC", 3)) {
+ if (!strncmp(p[0], "DCC", 3)) {
char *rp = &f->resolution;
int i;
- p[0] += 3;
- switch(*p[0]) {
+ p[0] += 3;
+ switch (*p[0]) {
case '?':
p[0]++;
- strcpy(rs, "\r\n");
- for(i = 0; i < 8; i++) {
- sprintf(rss, "%c%s", rp[i] + 48,
- (i < 7) ? "," : "");
- strcat(rs, rss);
- }
- isdn_tty_at_cout(rs, info);
+ strcpy(rs, "\r\n");
+ for (i = 0; i < 8; i++) {
+ sprintf(rss, "%c%s", rp[i] + 48,
+ (i < 7) ? "," : "");
+ strcat(rs, rss);
+ }
+ isdn_tty_at_cout(rs, info);
break;
case '=':
- p[0]++;
- if (*p[0] == '?') {
- isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)",info);
- p[0]++;
- } else {
- for (i=0; (((*p[0]>='0')&&(*p[0]<='9'))||(*p[0]==','))&&(i<8); i++) {
+ p[0]++;
+ if (*p[0] == '?') {
+ isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)", info);
+ p[0]++;
+ } else {
+ for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 8); i++) {
if (*p[0] != ',') {
if ((*p[0] - 48) > maxdccval[i]) {
PARSE_ERROR1;
}
rp[i] = *p[0] - 48;
p[0]++;
- if (*p[0] == ',')
+ if (*p[0] == ',')
p[0]++;
- } else p[0]++;
+ } else
+ p[0]++;
}
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: Fax FDCC capabilities DCE=%d,%d,%d,%d,%d,%d,%d,%d\n",
- rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]);
+ printk(KERN_DEBUG "isdn_tty: Fax FDCC capabilities DCE=%d,%d,%d,%d,%d,%d,%d,%d\n",
+ rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]);
#endif
- }
+ }
break;
default:
PARSE_ERROR1;
}
- return 0;
- }
-
+ return 0;
+ }
/* DIS=vr,br,wd,ln,df,ec,bf,st - current session parms */
- if (!strncmp(p[0], "DIS", 3)) {
+ if (!strncmp(p[0], "DIS", 3)) {
char *rp = &f->resolution;
int i;
- p[0] += 3;
- switch(*p[0]) {
+ p[0] += 3;
+ switch (*p[0]) {
case '?':
p[0]++;
- strcpy(rs, "\r\n");
- for(i = 0; i < 8; i++) {
- sprintf(rss, "%c%s", rp[i] + 48,
- (i < 7) ? "," : "");
- strcat(rs, rss);
- }
- isdn_tty_at_cout(rs, info);
+ strcpy(rs, "\r\n");
+ for (i = 0; i < 8; i++) {
+ sprintf(rss, "%c%s", rp[i] + 48,
+ (i < 7) ? "," : "");
+ strcat(rs, rss);
+ }
+ isdn_tty_at_cout(rs, info);
break;
case '=':
- p[0]++;
- if (*p[0] == '?') {
- isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)",info);
- p[0]++;
- } else {
- for (i=0; (((*p[0]>='0')&&(*p[0]<='9'))||(*p[0]==','))&&(i<8); i++) {
+ p[0]++;
+ if (*p[0] == '?') {
+ isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)", info);
+ p[0]++;
+ } else {
+ for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 8); i++) {
if (*p[0] != ',') {
if ((*p[0] - 48) > maxdccval[i]) {
PARSE_ERROR1;
}
rp[i] = *p[0] - 48;
p[0]++;
- if (*p[0] == ',')
+ if (*p[0] == ',')
p[0]++;
- } else p[0]++;
+ } else
+ p[0]++;
}
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: Fax FDIS session parms=%d,%d,%d,%d,%d,%d,%d,%d\n",
- rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]);
+ printk(KERN_DEBUG "isdn_tty: Fax FDIS session parms=%d,%d,%d,%d,%d,%d,%d,%d\n",
+ rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]);
#endif
- }
+ }
break;
default:
PARSE_ERROR1;
}
- return 0;
- }
-
- /* DR - Receive Phase C data command, initiates document reception */
- if (!strncmp(p[0], "DR", 2)) {
- p[0] += 2;
+ return 0;
+ }
+ /* DR - Receive Phase C data command, initiates document reception */
+ if (!strncmp(p[0], "DR", 2)) {
+ p[0] += 2;
if ((info->faxonline & 16) && /* incoming connection */
- ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D))) {
+ ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D))) {
#ifdef ISDN_TTY_FAX_STAT_DEBUG
printk(KERN_DEBUG "isdn_tty: Fax FDR\n");
#endif
isdn_command(&cmd);
if (f->phase == ISDN_FAX_PHASE_B) {
f->phase = ISDN_FAX_PHASE_C;
- } else if (f->phase == ISDN_FAX_PHASE_D) {
- switch(f->fet) {
+ } else if (f->phase == ISDN_FAX_PHASE_D) {
+ switch (f->fet) {
case 0: /* next page will be received */
f->phase = ISDN_FAX_PHASE_C;
- isdn_tty_fax_modem_result(7, info); /* CONNECT */
+ isdn_tty_fax_modem_result(7, info); /* CONNECT */
break;
case 1: /* next doc will be received */
f->phase = ISDN_FAX_PHASE_B;
case 2: /* fax session is terminating */
f->phase = ISDN_FAX_PHASE_E;
break;
- default:
+ default:
PARSE_ERROR1;
}
}
} else {
PARSE_ERROR1;
}
- return 1;
+ return 1;
}
-
/* DT=df,vr,wd,ln - TX phase C data command (release DCE to proceed with negotiation) */
- if (!strncmp(p[0], "DT", 2)) {
- int i, val[]={4,0,2,3};
+ if (!strncmp(p[0], "DT", 2)) {
+ int i, val[] =
+ {4, 0, 2, 3};
char *rp = &f->resolution;
- p[0] += 2;
- if (!info->faxonline & 1) /* not outgoing connection */
+ p[0] += 2;
+ if (!info->faxonline & 1) /* not outgoing connection */
PARSE_ERROR1;
- for (i=0; (((*p[0]>='0')&&(*p[0]<='9'))||(*p[0]==','))&&(i<4); i++) {
+ for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 4); i++) {
if (*p[0] != ',') {
if ((*p[0] - 48) > maxdccval[val[i]]) {
PARSE_ERROR1;
}
rp[val[i]] = *p[0] - 48;
p[0]++;
- if (*p[0] == ',')
+ if (*p[0] == ',')
p[0]++;
- } else p[0]++;
+ } else
+ p[0]++;
}
#ifdef ISDN_TTY_FAX_STAT_DEBUG
printk(KERN_DEBUG "isdn_tty: Fax FDT tx data command parms=%d,%d,%d,%d\n",
isdn_command(&cmd);
if (f->phase == ISDN_FAX_PHASE_D) {
f->phase = ISDN_FAX_PHASE_C;
- isdn_tty_fax_modem_result(7, info); /* CONNECT */
+ isdn_tty_fax_modem_result(7, info); /* CONNECT */
}
} else {
PARSE_ERROR1;
}
- return 1;
- }
-
+ return 1;
+ }
/* ECM=n - Error mode control 0=disabled, 2=enabled, handled by DCE alone incl. buff of partial pages */
- if (!strncmp(p[0], "ECM", 3)) {
- p[0] += 3;
+ if (!strncmp(p[0], "ECM", 3)) {
+ p[0] += 3;
switch (*p[0]) {
case '?':
p[0]++;
- sprintf(rs, "\r\n%d",f->ecm);
- isdn_tty_at_cout(rs, info);
+ sprintf(rs, "\r\n%d", f->ecm);
+ isdn_tty_at_cout(rs, info);
break;
case '=':
- p[0]++;
- if (*p[0] == '?')
- {
- p[0]++;
- sprintf(rs, "\r\n0,2");
- isdn_tty_at_cout(rs, info);
- }
- else
- {
- par = isdn_getnum(p);
- if ((par != 0) && (par != 2))
- PARSE_ERROR1;
- f->ecm = par;
+ p[0]++;
+ if (*p[0] == '?') {
+ p[0]++;
+ sprintf(rs, "\r\n0,2");
+ isdn_tty_at_cout(rs, info);
+ } else {
+ par = isdn_getnum(p);
+ if ((par != 0) && (par != 2))
+ PARSE_ERROR1;
+ f->ecm = par;
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: Fax FECM=%d\n", par);
+ printk(KERN_DEBUG "isdn_tty: Fax FECM=%d\n", par);
#endif
- }
- break;
+ }
+ break;
default:
PARSE_ERROR1;
}
- return 0;
- }
-
+ return 0;
+ }
/* ET=n - End of page or document */
if (!strncmp(p[0], "ET=", 3)) {
p[0] += 3;
}
return 0;
}
-
/* K - terminate */
if (!strncmp(p[0], "K", 1)) {
p[0] += 1;
isdn_tty_modem_hup(info, 1);
return 1;
}
-
/* LID=string - local fax ID */
- if (!strncmp(p[0], "LID", 3)) {
+ if (!strncmp(p[0], "LID", 3)) {
int i, r;
- p[0] += 3;
+ p[0] += 3;
switch (*p[0]) {
case '?':
p[0]++;
sprintf(rs, "\r\n\"%s\"", f->id);
- isdn_tty_at_cout(rs, info);
- break;
+ isdn_tty_at_cout(rs, info);
+ break;
case '=':
- p[0]++;
- if (*p[0] == '?')
- {
- p[0]++;
- sprintf(rs, "\r\n\"STRING\"");
- isdn_tty_at_cout(rs, info);
- }
- else
- {
- if (*p[0] =='"')
- p[0]++;
- for(i=0; (*p[0]) && i < (FAXIDLEN-1) && (*p[0] != '"'); i++)
- {
- f->id[i] = *p[0]++;
- }
- if (*p[0] =='"')
- p[0]++;
- for(r=i; r < FAXIDLEN; r++)
- {
- f->id[r] = 32;
- }
- f->id[FAXIDLEN-1] = 0;
+ p[0]++;
+ if (*p[0] == '?') {
+ p[0]++;
+ sprintf(rs, "\r\n\"STRING\"");
+ isdn_tty_at_cout(rs, info);
+ } else {
+ if (*p[0] == '"')
+ p[0]++;
+ for (i = 0; (*p[0]) && i < (FAXIDLEN - 1) && (*p[0] != '"'); i++) {
+ f->id[i] = *p[0]++;
+ }
+ if (*p[0] == '"')
+ p[0]++;
+ for (r = i; r < FAXIDLEN; r++) {
+ f->id[r] = 32;
+ }
+ f->id[FAXIDLEN - 1] = 0;
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: Fax local ID \"%s\"\n", f->id);
+ printk(KERN_DEBUG "isdn_tty: Fax local ID \"%s\"\n", f->id);
#endif
- }
- break;
+ }
+ break;
default:
PARSE_ERROR1;
}
- return 0;
- }
-
+ return 0;
+ }
/* MDL? - DCE Model */
- if (!strncmp(p[0], "MDL?", 4)) {
- p[0] += 4;
+ if (!strncmp(p[0], "MDL?", 4)) {
+ p[0] += 4;
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: FMDL?\n");
+ printk(KERN_DEBUG "isdn_tty: FMDL?\n");
#endif
- isdn_tty_at_cout("\r\nisdn4linux", info);
- return 0;
- }
-
+ isdn_tty_at_cout("\r\nisdn4linux", info);
+ return 0;
+ }
/* MFR? - DCE Manufacturer */
- if (!strncmp(p[0], "MFR?", 4)) {
- p[0] += 4;
+ if (!strncmp(p[0], "MFR?", 4)) {
+ p[0] += 4;
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: FMFR?\n");
+ printk(KERN_DEBUG "isdn_tty: FMFR?\n");
#endif
- isdn_tty_at_cout("\r\nisdn4linux", info);
- return 0;
- }
-
+ isdn_tty_at_cout("\r\nisdn4linux", info);
+ return 0;
+ }
/* MINSP=n - Minimum Speed for Phase C */
- if (!strncmp(p[0], "MINSP", 5)) {
- p[0] += 5;
+ if (!strncmp(p[0], "MINSP", 5)) {
+ p[0] += 5;
switch (*p[0]) {
case '?':
p[0]++;
- sprintf(rs, "\r\n%d",f->minsp);
- isdn_tty_at_cout(rs, info);
+ sprintf(rs, "\r\n%d", f->minsp);
+ isdn_tty_at_cout(rs, info);
break;
case '=':
- p[0]++;
- if (*p[0] == '?')
- {
- p[0]++;
- sprintf(rs, "\r\n0-5");
- isdn_tty_at_cout(rs, info);
- }
- else
- {
- par = isdn_getnum(p);
- if ((par < 0) || (par > 5))
- PARSE_ERROR1;
- f->minsp = par;
+ p[0]++;
+ if (*p[0] == '?') {
+ p[0]++;
+ sprintf(rs, "\r\n0-5");
+ isdn_tty_at_cout(rs, info);
+ } else {
+ par = isdn_getnum(p);
+ if ((par < 0) || (par > 5))
+ PARSE_ERROR1;
+ f->minsp = par;
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: Fax FMINSP=%d\n", par);
+ printk(KERN_DEBUG "isdn_tty: Fax FMINSP=%d\n", par);
#endif
- }
- break;
+ }
+ break;
default:
PARSE_ERROR1;
}
- return 0;
- }
-
+ return 0;
+ }
/* PHCTO=value - DTE phase C timeout */
- if (!strncmp(p[0], "PHCTO", 5)){
- p[0] +=5;
+ if (!strncmp(p[0], "PHCTO", 5)) {
+ p[0] += 5;
switch (*p[0]) {
case '?':
p[0]++;
- sprintf(rs, "\r\n%d",f->phcto);
- isdn_tty_at_cout(rs, info);
+ sprintf(rs, "\r\n%d", f->phcto);
+ isdn_tty_at_cout(rs, info);
break;
case '=':
- p[0]++;
- if (*p[0] == '?')
- {
- p[0]++;
- sprintf(rs, "\r\n0-255");
- isdn_tty_at_cout(rs, info);
- }
- else
- {
- par = isdn_getnum(p);
- if ((par < 0) || (par > 255))
- PARSE_ERROR1;
- f->phcto = par;
+ p[0]++;
+ if (*p[0] == '?') {
+ p[0]++;
+ sprintf(rs, "\r\n0-255");
+ isdn_tty_at_cout(rs, info);
+ } else {
+ par = isdn_getnum(p);
+ if ((par < 0) || (par > 255))
+ PARSE_ERROR1;
+ f->phcto = par;
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: Fax FPHCTO=%d\n", par);
+ printk(KERN_DEBUG "isdn_tty: Fax FPHCTO=%d\n", par);
#endif
- }
- break;
+ }
+ break;
default:
PARSE_ERROR1;
}
- return 0;
- }
-
+ return 0;
+ }
/* REL=n - Phase C received EOL alignment */
- if (!strncmp(p[0], "REL", 3)) {
- p[0] += 3;
+ if (!strncmp(p[0], "REL", 3)) {
+ p[0] += 3;
switch (*p[0]) {
case '?':
p[0]++;
- sprintf(rs, "\r\n%d",f->rel);
- isdn_tty_at_cout(rs, info);
+ sprintf(rs, "\r\n%d", f->rel);
+ isdn_tty_at_cout(rs, info);
break;
case '=':
- p[0]++;
- if (*p[0] == '?')
- {
- p[0]++;
- sprintf(rs, "\r\n0,1");
- isdn_tty_at_cout(rs, info);
- }
- else
- {
- par = isdn_getnum(p);
- if ((par < 0) || (par > 1))
- PARSE_ERROR1;
- f->rel = par;
+ p[0]++;
+ if (*p[0] == '?') {
+ p[0]++;
+ sprintf(rs, "\r\n0,1");
+ isdn_tty_at_cout(rs, info);
+ } else {
+ par = isdn_getnum(p);
+ if ((par < 0) || (par > 1))
+ PARSE_ERROR1;
+ f->rel = par;
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: Fax FREL=%d\n", par);
+ printk(KERN_DEBUG "isdn_tty: Fax FREL=%d\n", par);
#endif
- }
- break;
+ }
+ break;
default:
PARSE_ERROR1;
}
- return 0;
- }
-
+ return 0;
+ }
/* REV? - DCE Revision */
- if (!strncmp(p[0], "REV?", 4)) {
- p[0] += 4;
+ if (!strncmp(p[0], "REV?", 4)) {
+ p[0] += 4;
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: FREV?\n");
+ printk(KERN_DEBUG "isdn_tty: FREV?\n");
#endif
strcpy(rss, isdn_tty_fax_revision);
sprintf(rs, "\r\nRev: %s", isdn_getrev(rss));
- isdn_tty_at_cout(rs, info);
- return 0;
- }
-
+ isdn_tty_at_cout(rs, info);
+ return 0;
+ }
/* Phase C Transmit Data Block Size */
- if (!strncmp(p[0], "TBC=", 4)) { /* dummy, not used */
+ if (!strncmp(p[0], "TBC=", 4)) { /* dummy, not used */
p[0] += 4;
#ifdef ISDN_TTY_FAX_STAT_DEBUG
- printk(KERN_DEBUG "isdn_tty: Fax FTBC=%c\n", *p[0]);
+ printk(KERN_DEBUG "isdn_tty: Fax FTBC=%c\n", *p[0]);
#endif
- switch (*p[0]) {
- case '0':
- p[0]++;
- break;
- default:
- PARSE_ERROR1;
- }
- return 0;
+ switch (*p[0]) {
+ case '0':
+ p[0]++;
+ break;
+ default:
+ PARSE_ERROR1;
+ }
+ return 0;
}
-
- printk(KERN_DEBUG "isdn_tty: unknown token=>AT+F%s<\n", p[0]);
+ printk(KERN_DEBUG "isdn_tty: unknown token=>AT+F%s<\n", p[0]);
PARSE_ERROR1;
}
+int
+isdn_tty_cmd_PLUSF_FAX(char **p, modem_info * info)
+{
+ if (TTY_IS_FCLASS2(info))
+ return (isdn_tty_cmd_FCLASS2(p, info));
+ else if (TTY_IS_FCLASS1(info))
+ return (isdn_tty_cmd_FCLASS1(p, info));
+ PARSE_ERROR1;
+}
* Put the ECP detected port in the more PS2 like mode.
*/
parport_pc_write_econtrol(p, 0x34);
- parport_pc_write_control(p, 0x8);
- parport_pc_write_data(p, 0);
- udelay (50);
- parport_pc_write_control(p, 0xc);
- udelay (50);
if (parport_probe_hook)
(*parport_probe_hook)(p);
endmenu
tristate 'Dummy net driver support' CONFIG_DUMMY
+tristate 'Bonding driver support' CONFIG_BONDING
tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
if [ "$CONFIG_NETLINK" = "y" ]; then
endif
endif
+ifeq ($(CONFIG_BONDING),y)
+L_OBJS += bonding.o
+else
+ ifeq ($(CONFIG_BONDING),m)
+ M_OBJS += bonding.o
+ endif
+endif
+
ifeq ($(CONFIG_DE600),y)
L_OBJS += de600.o
else
extern int tc515_probe(struct device *dev);
extern int lance_probe(struct device *dev);
extern int rcpci_probe(struct device *);
-extern int dmfe_reg_board(struct device *);
+extern int dmfe_probe(struct device *);
/* Gigabit Ethernet adapters */
extern int yellowfin_probe(struct device *dev);
#endif
#ifdef CONFIG_DM9102
- {dmfe_reg_board, 0},
+ {dmfe_probe, 0},
#endif
#ifdef CONFIG_YELLOWFIN
{via_rhine_probe, 0},
#endif
#ifdef CONFI_NET_DM9102
- {dmfe_reg_board, 0},
+ {dmfe_probe, 0},
#endif
{NULL, 0},
};
--- /dev/null
+/*
+ * originally based on the dummy device.
+ *
+ * Copyright 1999, Thomas Davis, tadavis@lbl.gov.
+ * Licensed under the GPL. Based on dummy.c, and eql.c devices.
+ *
+ * bond.c: a bonding/etherchannel/sun trunking net driver
+ *
+ * This is useful to talk to a Cisco 5500, running Etherchannel, aka:
+ * Linux Channel Bonding
+ * Sun Trunking (Solaris)
+ *
+ * How it works:
+ * ifconfig bond0 ipaddress netmask up
+ * will setup a network device, with an ip address. No mac address
+ * will be assigned at this time. The hw mac address will come from
+ * the first slave bonded to the channel. All slaves will then use
+ * this hw mac address.
+ *
+ * ifconfig bond0 down
+ * will release all slaves, marking them as down.
+ *
+ * ifenslave bond0 eth0
+ * will attache eth0 to bond0 as a slave. eth0 hw mac address will either
+ * a: be used as initial mac address
+ * b: if a hw mac address already is there, eth0's hw mac address
+ * will then be set from bond0.
+ *
+ * v0.1 - first working version.
+ * v0.2 - changed stats to be calculated by summing slaves stats.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/uaccess.h>
+#include <linux/errno.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <linux/if_bonding.h>
+
+static int bond_xmit(struct sk_buff *skb, struct device *dev);
+static struct net_device_stats *bond_get_stats(struct device *dev);
+
+static int bond_open(struct device *dev)
+{
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int bond_close(struct device *master)
+{
+ bonding_t *private = (struct bonding *) master->priv;
+ slave_queue_t *queue = (struct slave_queue *) private->queue;
+ slave_t *slave, *next;
+
+ for( slave=queue->head; slave != NULL; slave=next) {
+#ifdef BONDING_DEBUG
+ printk("freeing = %s\n", slave->dev->name);
+#endif
+ slave->dev->flags &= ~IFF_SLAVE;
+ slave->dev->slave = NULL;
+ next = slave->next;
+ kfree(slave);
+ queue->num_slaves++;
+ }
+
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+/* fake multicast ability */
+static void set_multicast_list(struct device *dev)
+{
+}
+
+static int bond_enslave(struct device *master, struct device *slave)
+{
+ bonding_t *private = (struct bonding *) master->priv;
+ slave_queue_t *queue = (struct slave_queue *) private->queue;
+ slave_t *new_slave;
+ int flags;
+
+ if (master == NULL || slave == NULL)
+ return -ENODEV;
+
+#ifdef BONDING_DEBUG
+ printk (KERN_WARNING "%s: enslaving '%s'\n", master->name, slave->name);
+#endif
+
+ save_flags(flags);
+ cli();
+
+ /* not running. */
+ if ((slave->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
+ restore_flags(flags);
+ return -EINVAL;
+ }
+
+ /* already enslaved */
+ if (master->flags & IFF_SLAVE || slave->flags & IFF_SLAVE) {
+ restore_flags(flags);
+ return -EBUSY;
+ }
+
+ slave->slave = master; /* save the master in slave->slave */
+ slave->flags |= IFF_SLAVE;
+
+ if ((new_slave = kmalloc(sizeof(slave_t), GFP_KERNEL)) == NULL) {
+ return -ENOMEM;
+ }
+ memset(new_slave, 0, sizeof(slave_t));
+
+ new_slave->dev = slave;
+
+ if (queue->head == NULL) {
+ queue->head = new_slave;
+ queue->current_slave = queue->head;
+ } else {
+ queue->tail->next = new_slave;
+ }
+
+ queue->tail = new_slave;
+ queue->num_slaves++;
+
+ restore_flags(flags);
+
+ return 0;
+}
+
+static int bond_release(struct device *master, struct device *slave)
+{
+ printk (KERN_DEBUG "%s: releasing `%s`\n", master->name, slave->name);
+
+ return -EINVAL;
+}
+
+static int bond_sethwaddr(struct device *master, struct device *slave)
+{
+ memcpy(master->dev_addr, slave->dev_addr, slave->addr_len);
+ return 0;
+}
+
+static int bond_ioctl(struct device *master, struct ifreq *ifr, int cmd)
+{
+ struct device *slave = dev_get(ifr->ifr_slave);
+
+#ifdef BONDING_DEBUG
+ printk("master=%s, slave=%s\n", master->name, slave->name);
+#endif
+
+ switch (cmd) {
+ case BOND_ENSLAVE:
+ return bond_enslave(master, slave);
+ case BOND_RELEASE:
+ return bond_release(master, slave);
+ case BOND_SETHWADDR:
+ return bond_sethwaddr(master, slave);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+#ifdef CONFIG_NET_FASTROUTE
+static int bond_accept_fastpath(struct device *dev, struct dst_entry *dst)
+{
+ return -1;
+}
+#endif
+
+__initfunc(int bond_init(struct device *dev))
+{
+ bonding_t *bond;
+
+ /* Initialize the device structure. */
+ dev->hard_start_xmit = bond_xmit;
+
+ dev->priv = kmalloc(sizeof(struct bonding), GFP_KERNEL);
+ if (dev->priv == NULL)
+ return -ENOMEM;
+
+ memset(dev->priv, 0, sizeof(struct bonding));
+
+ bond = (struct bonding *) dev->priv;
+
+ bond->queue = kmalloc(sizeof(struct slave_queue), GFP_KERNEL);
+ if (bond->queue == NULL)
+ return -ENOMEM;
+
+ memset(bond->queue, 0, sizeof(struct slave_queue));
+
+ bond->stats = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL);
+ if (bond->stats == NULL)
+ return -ENOMEM;
+
+ memset(bond->stats, 0, sizeof(struct enet_statistics));
+
+ dev->get_stats = bond_get_stats;
+
+ dev->open = bond_open;
+ dev->stop = bond_close;
+ dev->set_multicast_list = set_multicast_list;
+
+ dev->do_ioctl = bond_ioctl;
+
+ /* Fill in the fields of the device structure with ethernet-generic
+ values. */
+ ether_setup(dev);
+ dev->tx_queue_len = 0;
+ dev->flags |= (IFF_MASTER|IFF_MULTICAST);
+#ifdef CONFIG_NET_FASTROUTE
+ dev->accept_fastpath = bond_accept_fastpath;
+#endif
+
+ return 0;
+}
+
+static int bond_xmit(struct sk_buff *skb, struct device *dev)
+{
+ struct device *slave;
+ struct bonding *bond = (struct bonding *) dev->priv;
+ struct slave_queue *queue = bond->queue;
+ int good = 0;
+
+ while (good == 0) {
+ slave = queue->current_slave->dev;
+ if (slave->flags & (IFF_UP|IFF_RUNNING)) {
+ skb->dev = slave;
+ skb->priority = 1;
+ dev_queue_xmit(skb);
+ good = 1;
+ }
+ if (queue->current_slave->next != NULL) {
+ queue->current_slave = queue->current_slave->next;
+ } else {
+ queue->current_slave = queue->head;
+ }
+ }
+
+ return 0;
+}
+
+static struct net_device_stats *bond_get_stats(struct device *dev)
+{
+ bonding_t *private = dev->priv;
+ slave_queue_t *queue = private->queue;
+ struct net_device_stats *stats = private->stats, *sstats;
+ slave_t *slave;
+
+ memset(private->stats, 0, sizeof(struct net_device_stats));
+ for (slave=queue->head; slave != NULL; slave=slave->next) {
+ sstats = slave->dev->get_stats(slave->dev);
+
+ stats->rx_packets += sstats->rx_packets;
+ stats->rx_bytes += sstats->rx_bytes;
+ stats->rx_errors += sstats->rx_errors;
+ stats->rx_dropped += sstats->rx_dropped;
+
+ stats->tx_packets += sstats->tx_packets;
+ stats->tx_bytes += sstats->tx_bytes;
+ stats->tx_errors += sstats->tx_errors;
+ stats->tx_dropped += sstats->tx_dropped;
+
+ stats->multicast += sstats->multicast;
+ stats->collisions += sstats->collisions;
+
+ stats->rx_length_errors += sstats->rx_length_errors;
+ stats->rx_over_errors += sstats->rx_over_errors;
+ stats->rx_crc_errors += sstats->rx_crc_errors;
+ stats->rx_frame_errors += sstats->rx_frame_errors;
+ stats->rx_fifo_errors += sstats->rx_fifo_errors;
+ stats->rx_missed_errors += sstats->rx_missed_errors;
+
+ stats->tx_aborted_errors += sstats->tx_aborted_errors;
+ stats->tx_carrier_errors += sstats->tx_carrier_errors;
+ stats->tx_fifo_errors += sstats->tx_fifo_errors;
+ stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors;
+ stats->tx_window_errors += sstats->tx_window_errors;
+
+ }
+
+ return stats;
+}
+
+#ifdef MODULE
+
+__initfunc(static int bond_probe(struct device *dev))
+{
+ bond_init(dev);
+ return 0;
+}
+
+static char bond_name[16];
+
+static struct device dev_bond = {
+ bond_name, /* Needs to be writeable */
+ 0, 0, 0, 0,
+ 0x0, 0,
+ 0, 0, 0, NULL, bond_probe };
+
+int init_module(void)
+{
+ /* Find a name for this unit */
+ int err=dev_alloc_name(&dev_bond,"bond%d");
+
+ if (err<0)
+ return err;
+
+ if (register_netdev(&dev_bond) != 0)
+ return -EIO;
+
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ struct bonding *bond = (struct bonding *) dev_bond.priv;
+
+ unregister_netdev(&dev_bond);
+
+ kfree(bond->queue);
+ kfree(bond->stats);
+ kfree(dev_bond.priv);
+
+ dev_bond.priv = NULL;
+}
+#endif /* MODULE */
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
};
/* function declaration ------------------------------------- */
-static int dmfe_probe(struct device *);
+int dmfe_probe(struct device *);
static int dmfe_open(struct device *);
static int dmfe_start_xmit(struct sk_buff *, struct device *);
static int dmfe_stop(struct device *);
* Status: Stable.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Nov 7 21:43:15 1998
- * Modified at: Wed Jan 19 08:59:16 2000
+ * Modified at: Wed Jan 26 13:00:29 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
int reg;
int i = 0;
-#ifdef CONFIG_APM
- apm_register_callback(nsc_ircc_apmproc);
-#endif /* CONFIG_APM */
-
/* Probe for all the NSC chipsets we know about */
for (chip=chips; chip->name ; chip++,i++) {
IRDA_DEBUG(2, __FUNCTION__"(), Probing for %s ...\n",
}
}
+#ifdef CONFIG_APM
+ /* Make sure at least one chip was found before enabling APM */
+ if (ret == 0)
+ apm_register_callback(nsc_ircc_apmproc);
+#endif /* CONFIG_APM */
+
return ret;
}
}
out:
/* Not busy transmitting anymore if window is not full */
- if (self->tx_fifo.free < MAX_WINDOW)
+ if (self->tx_fifo.free < MAX_TX_WINDOW)
dev->tbusy = 0;
/* Restore bank register */
}
/* Make sure we have room for more frames */
- if (self->tx_fifo.free < MAX_WINDOW) {
+ if (self->tx_fifo.free < MAX_TX_WINDOW) {
/* Not busy transmitting anymore */
self->netdev->tbusy = 0;
/* Read all entries in status FIFO */
switch_bank(iobase, BANK5);
- while (((status = inb(iobase+FRM_ST)) & FRM_ST_VLD) &&
- (st_fifo->tail < MAX_WINDOW))
- {
- st_fifo->entries[st_fifo->tail].status = status;
+ while ((status = inb(iobase+FRM_ST)) & FRM_ST_VLD) {
+ /* We must empty the status FIFO no matter what */
+ len = inb(iobase+RFLFL) | ((inb(iobase+RFLFH) & 0x1f) << 8);
- len = inb(iobase+RFLFL) | (inb(iobase+RFLFH) << 8);
-
+ if (st_fifo->tail >= MAX_RX_WINDOW)
+ continue;
+
+ st_fifo->entries[st_fifo->tail].status = status;
st_fifo->entries[st_fifo->tail].len = len;
st_fifo->pending_bytes += len;
st_fifo->tail++;
st_fifo->len++;
}
/* Try to process all entries in status FIFO */
- while (st_fifo->len) {
+ while (st_fifo->len > 0) {
/* Get first entry */
status = st_fifo->entries[st_fifo->head].status;
len = st_fifo->entries[st_fifo->head].len;
bank = inb(iobase+BSR);
- /* Status event, or end of frame detected in FIFO */
- if (eir & (EIR_SFIF_EV|EIR_LS_EV)) {
+ /* Status FIFO event*/
+ if (eir & EIR_SFIF_EV) {
if (nsc_ircc_dma_receive_complete(self, iobase)) {
/* Wait for next status FIFO interrupt */
self->ier = IER_SFIF_IE;
/* Start timer */
outb(IRCR1_TMR_EN, iobase+IRCR1);
- self->ier = IER_TMR_IE;
+ self->ier = IER_TMR_IE | IER_SFIF_IE;
}
} else if (eir & EIR_TMR_EV) { /* Timer finished */
/* Disable timer */
/* Prepare for receive */
nsc_ircc_dma_receive(self);
- self->ier = IER_LS_IE|IER_SFIF_IE;
+ self->ier = IER_SFIF_IE;
}
} else {
/* Not finished yet, so interrupt on DMA again */
/* the watchdog process that cruises around */
-static void lmc_watchdog (unsigned long data) /*FOLD00*/
+static void lmc_watchdog (unsigned long data) /*fold00*/
{
struct device *dev = (struct device *) data;
lmc_softc_t *sc;
/*
* Switch to common hdlc%d naming. We name by type not by vendor
*/
- dev->name = (char *)(dev+1);
+ dev->name = (char *) (((u32) (dev)) + sizeof (struct ppp_device));
dev_alloc_name(dev, "hdlc%d");
-
+
Lmc_Count++;
if(lmc_first_load == 0){
* Allocate space for the private data structure
*/
- /* FIXME: we adjust to 8 byte align, but we then kfree the adjusted value
- BUG BUG BUG - fortunately kmalloc will be 8 byte aligned.. */
-
- sc = (void *) (((long) kmalloc (sizeof (lmc_softc_t), GFP_KERNEL) + 7) & ~7);
+ sc = kmalloc (sizeof (lmc_softc_t), GFP_KERNEL);
if (sc == NULL) {
printk (KERN_WARNING "%s: Cannot allocate memory for device state\n",
dev->name);
del_timer (&sc->timer);
sppp_close (dev);
lmc_ifdown (dev);
- printk(KERN_DEBUG "%s: Close ran\n", dev->name);
return 0;
}
}
-static int lmc_rx (struct device *dev) /*FOLD00*/
+static int lmc_rx (struct device *dev) /*fold00*/
{
lmc_softc_t *sc;
int i;
* 6/8/99 - Official Release 0.2.0
* Merged into the kernel code
*
- * To Do:
- *
- * Sanitize for smp
+ * 1/10/00 - Added Spinlocks for smp.
*
+ * To Do:
+ * IPv6 Multicast
+ *
* If Problems do Occur
* Most problems can be rectified by either closing and opening the interface
* (ifconfig down and up) or rmmod and insmod'ing the driver (a bit difficult
#include <asm/io.h>
#include <asm/system.h>
#include <asm/bitops.h>
+#include <asm/spinlock.h>
#include "olympic.h"
*/
static char *version =
-"Olympic.c v0.2.0 6/8/99 - Peter De Schrijver & Mike Phillips" ;
+"Olympic.c v0.2.1 1/10/00 - Peter De Schrijver & Mike Phillips" ;
static char *open_maj_error[] = {"No error", "Lobe Media Test", "Physical Insertion",
"Address Verification", "Neighbor Notification (Ring Poll)",
}
}
+ spin_lock_init(&olympic_priv->olympic_lock) ;
+
#if OLYMPIC_DEBUG
printk("BCTL: %x\n",readl(olympic_mmio+BCTL));
printk("GPR: %x\n",readw(olympic_mmio+GPR));
if (!(sisr & SISR_MI)) /* Interrupt isn't for us */
return ;
+ spin_lock(&olympic_priv->olympic_lock) ;
+
if (dev->interrupt)
printk(KERN_WARNING "%s: Re-entering interrupt \n",dev->name) ;
dev->interrupt = 0 ;
writel(SISR_MI,olympic_mmio+SISR_MASK_SUM);
-
+ spin_unlock(&olympic_priv->olympic_lock) ;
}
static int olympic_xmit(struct sk_buff *skb, struct device *dev)
{
struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
- __u8 *olympic_mmio=olympic_priv->olympic_mmio;
+ __u8 *olympic_mmio=olympic_priv->olympic_mmio;
+ unsigned long flags ;
+
+ spin_lock_irqsave(&olympic_priv->olympic_lock, flags) ;
if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+ spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags) ;
return 1;
}
writew((((readw(olympic_mmio+TXENQ_1)) & 0x8000) ^ 0x8000) | 1,olympic_mmio+TXENQ_1);
dev->tbusy=0;
-
+ spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags) ;
return 0;
- } else
+ } else {
+ spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags) ;
return 1;
+ }
}
__u8 *olympic_mmio;
__u8 *olympic_lap;
+ spinlock_t olympic_lock ;
+
volatile int srb_queued; /* True if an SRB is still posted */
struct wait_queue *srb_wait;
struct pardevice *dev = parport_register_device(port, "IEEE 1284 probe", NULL, NULL, NULL, 0, &dev);
int result = 0;
+ int lives = 1;
if (!dev) {
printk("%s: unable to register for probe.\n", port->name);
parport_claim_or_block(dev);
+ try_again:
switch (parport_ieee1284_nibble_mode_ok(port, 4)) {
case 2:
current->state=TASK_INTERRUPTIBLE;
break;
}
+ if (result < 1 && lives--) {
+ /* Reset the peripherals and try again. */
+ parport_pc_write_control(port, 0x8);
+ parport_pc_write_data(port, 0);
+ udelay (50);
+ parport_pc_write_control(port, 0xc);
+ udelay (500);
+ goto try_again;
+ }
+
+ printk (KERN_DEBUG "parport_probe: %s%s\n",
+ lives ? "" : "after reset: ",
+ result < 1 ? "failed" : "succeeded");
+
parport_release(dev);
parport_unregister_device(dev);
* instead of slowing down if those exist. That's hard to do with simple
* checksums though.
*/
- if(aic7xxx_verbose & VERBOSE_NEGOTIATION)
+ if(aic7xxx_verbose & VERBOSE_NEGOTIATION2)
{
printk(INFO_LEAD "reducing SCSI transfer speed due to Domain "
"validation failure.\n", p->host_no, CTL_OF_CMD(cmd));
}
else
{
- if(aic7xxx_verbose & VERBOSE_NEGOTIATION)
+ if(aic7xxx_verbose & VERBOSE_NEGOTIATION2)
{
printk(INFO_LEAD "Performing Domain validation.\n",
p->host_no, CTL_OF_CMD(cmd));
}
else
{
- if( (aic7xxx_verbose & VERBOSE_NEGOTIATION) &&
+ if( (aic7xxx_verbose & VERBOSE_NEGOTIATION2) &&
(p->needdv & (1<<tindex)) )
{
printk(INFO_LEAD "Successfully completed Domain validation.\n",
{"NRC","MBR-7","*", BLIST_FORCELUN | BLIST_SINGLELUN},
{"NRC","MBR-7.4","*", BLIST_FORCELUN | BLIST_SINGLELUN},
{"REGAL","CDC-4X","*", BLIST_MAX5LUN | BLIST_SINGLELUN},
+{"LASOUND","CDX7405","3.10", BLIST_MAX5LUN | BLIST_SINGLELUN},
{"NAKAMICH","MJ-4.8S","*", BLIST_FORCELUN | BLIST_SINGLELUN},
{"NAKAMICH","MJ-5.16S","*", BLIST_FORCELUN | BLIST_SINGLELUN},
{"PIONEER","CD-ROM DRM-600","*", BLIST_FORCELUN | BLIST_SINGLELUN},
* would be a ten byte read where only a six byte read was supported.
* Also, on a system where READ CAPACITY failed, we have have read
* past the end of the disk.
+ *
+ * Don't screw with the ten byte flag unless we are certain that
+ * the drive does not understand the command /axboe
*/
if (SCpnt->sense_buffer[2] == ILLEGAL_REQUEST) {
if (rscsi_disks[DEVICE_NR(SCpnt->request.rq_dev)].ten) {
- rscsi_disks[DEVICE_NR(SCpnt->request.rq_dev)].ten = 0;
+ if (SCpnt->cmnd[0] == READ_10 || SCpnt->cmnd[0] == WRITE_10 ||
+ SCpnt->sense_buffer[12] == 0x20)
+ rscsi_disks[DEVICE_NR(SCpnt->request.rq_dev)].ten = 0;
requeue_sd_request(SCpnt);
result = 0;
} else {
this_count = this_count << 1;
}
- if (((this_count > 0xff) || (block > 0x1fffff)) && rscsi_disks[dev].ten)
+ if (((this_count > 0xff) || (block > 0x1fffff)) || rscsi_disks[dev].ten)
{
if (this_count > 0xffff)
this_count = 0xffff;
QNX4DEBUG(("filp->f_pos = %ld\n", (long) filp->f_pos));
while (filp->f_pos < inode->i_size) {
- blknum = qnx4_block_map( inode, filp->f_pos / QNX4_BLOCK_SIZE );
+ blknum = qnx4_block_map( inode, filp->f_pos >> QNX4_BLOCK_SIZE_SHIFT );
bh = bread(inode->i_dev, blknum, QNX4_BLOCK_SIZE);
if(bh==NULL) {
printk(KERN_ERR "qnx4_readdir: bread failed (%ld)\n", blknum);
break;
}
- ix = (filp->f_pos / QNX4_DIR_ENTRY_SIZE - (filp->f_pos / QNX4_BLOCK_SIZE) * QNX4_INODES_PER_BLOCK) % QNX4_INODES_PER_BLOCK;
+ ix = ( (filp->f_pos >> QNX4_DIR_ENTRY_SIZE_SHIFT) - (filp->f_pos >> QNX4_BLOCK_SIZE_SHIFT) * QNX4_INODES_PER_BLOCK) & QNX4_INODES_PER_BLOCK_MASK;
while (ix < QNX4_INODES_PER_BLOCK) {
offset = ix * QNX4_DIR_ENTRY_SIZE;
de = (struct qnx4_inode_entry *) (bh->b_data + offset);
--- /dev/null
+/*
+ * Bond several ethernet interfaces into a Cisco, running 'Etherchannel'.
+ *
+ *
+ * Portions are (c) Copyright 1995 Simon "Guru Aleph-Null" Janes
+ * NCM: Network and Communications Management, Inc.
+ *
+ * BUT, I'm the one who modified it for ethernet, so:
+ * (c) Copyright 1999, Thomas Davis, tadavis@lbl.gov
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU Public License, incorporated herein by reference.
+ *
+ */
+
+#ifndef _LINUX_IF_BONDING_H
+#define _LINUX_IF_BONDING_H
+
+#include <linux/timer.h>
+
+#define BOND_ENSLAVE (SIOCDEVPRIVATE)
+#define BOND_RELEASE (SIOCDEVPRIVATE + 1)
+#define BOND_SETHWADDR (SIOCDEVPRIVATE + 2)
+
+typedef struct slave {
+ struct device *dev;
+ struct slave *next;
+ struct slave *prev;
+} slave_t;
+
+typedef struct slave_queue {
+ slave_t *head;
+ slave_t *tail;
+ slave_t *current_slave;
+ int num_slaves;
+ struct device *master_dev;
+ char lock;
+} slave_queue_t;
+
+typedef struct bonding {
+ slave_queue_t *queue;
+ int min_slaves;
+ int max_slaves;
+ struct net_device_stats *stats;
+ struct timer_list timer;
+ char timer_on;
+} bonding_t;
+
+#endif /* _LINUX_BOND_H */
+
+/*
+ * Local variables:
+ * version-control: t
+ * kept-new-versions: 5
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
-/* $Id: isdn.h,v 1.81 1999/10/27 21:21:18 detabc Exp $
+/* $Id: isdn.h,v 1.88 2000/01/20 19:59:43 keil Exp $
*
* Main header for the Linux ISDN subsystem (linklevel).
*
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn.h,v $
+ * Revision 1.88 2000/01/20 19:59:43 keil
+ * Add FAX Class 1 support
+ *
+ * Revision 1.87 2000/01/09 20:43:15 detabc
+ * exand logical bind-group's for both call's (in and out).
+ * add first part of kernel-config-help for abc-extension.
+ *
+ * Revision 1.86 1999/12/05 16:06:09 detabc
+ * add resethandling for rawip-compression.
+ * at now all B2-Protocols are usable with rawip-compression
+ *
+ * Revision 1.85 1999/11/30 11:29:06 detabc
+ * add a on the fly frame-counter and limit
+ *
+ * Revision 1.84 1999/11/28 14:49:08 detabc
+ * In case of rawip-compress adjust dev[x]->ibytes/obytes to reflect the
+ * uncompressed size.
+ *
+ * Revision 1.83 1999/11/26 15:54:59 detabc
+ * added compression (isdn_bsdcompress) for rawip interfaces with x75i B2-protocol.
+ *
+ * Revision 1.82 1999/11/20 22:14:14 detabc
+ * added channel dial-skip in case of external use
+ * (isdn phone or another isdn device) on the same NTBA.
+ * usefull with two or more card's connected the different NTBA's.
+ * global switchable in kernel-config and also per netinterface.
+ *
+ * add auto disable of netinterface's in case of:
+ * to many connection's in short time.
+ * config mistakes (wrong encapsulation, B2-protokoll or so on) on local
+ * or remote side.
+ * wrong password's or something else to a ISP (syncppp).
+ *
+ * possible encapsulations for this future are:
+ * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP,
+ * and ISDN_NET_ENCAP_CISCOHDLCK.
+ *
* Revision 1.81 1999/10/27 21:21:18 detabc
* Added support for building logically-bind-group's per interface.
* usefull for outgoing call's with more then one isdn-card.
#undef CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR
#undef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
#undef CONFIG_ISDN_WITH_ABC_ICALL_BIND
+#undef CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
+#undef CONFIG_ISDN_WITH_ABC_CONN_ERROR
+#undef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS
+#undef CONFIG_ISDN_WITH_ABC_FRAME_LIMIT
/* New ioctl-codes */
#define IIOCGETCPS _IO('I',21)
#define IIOCGETDVR _IO('I',22)
#define IIOCNETLCR _IO('I',23) /* dwabc ioctl for LCR from isdnlog */
+#define IIOCNETDWRSET _IO('I',24) /* dwabc ioctl to reset abc-values to default on a net-interface */
#define IIOCNETALN _IO('I',32)
#define IIOCNETDLN _IO('I',33)
isdn_v110_stream *v110[ISDN_MAX_CHANNELS]; /* V.110 private data */
struct semaphore sem; /* serialize list access*/
isdn_module *modules;
+ unsigned long global_features;
} isdn_dev;
extern isdn_dev *dev;
-/* $Id: isdnif.h,v 1.32 1999/10/11 22:03:00 keil Exp $
+/* $Id: isdnif.h,v 1.33 2000/01/20 19:59:43 keil Exp $
*
* Linux ISDN subsystem
*
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdnif.h,v $
+ * Revision 1.33 2000/01/20 19:59:43 keil
+ * Add FAX Class 1 support
+ *
* Revision 1.32 1999/10/11 22:03:00 keil
* COMPAT_NEED_UACCESS (no include in isdn_compat.h)
*
/*
* Values for Layer-3-protocol-selection
*/
-#define ISDN_PROTO_L3_TRANS 0 /* Transparent */
-#define ISDN_PROTO_L3_TRANSDSP 1 /* Transparent with DSP */
-#define ISDN_PROTO_L3_FAX 2 /* Fax Group 2/3 */
-#define ISDN_PROTO_L3_MAX 7 /* Max. 8 Protocols */
+#define ISDN_PROTO_L3_TRANS 0 /* Transparent */
+#define ISDN_PROTO_L3_TRANSDSP 1 /* Transparent with DSP */
+#define ISDN_PROTO_L3_FCLASS2 2 /* Fax Group 2/3 CLASS 2 */
+#define ISDN_PROTO_L3_FCLASS1 3 /* Fax Group 2/3 CLASS 1 */
+#define ISDN_PROTO_L3_MAX 7 /* Max. 8 Protocols */
#ifdef __KERNEL__
/* Layer 3 */
#define ISDN_FEATURE_L3_TRANS (0x10000 << ISDN_PROTO_L3_TRANS)
#define ISDN_FEATURE_L3_TRANSDSP (0x10000 << ISDN_PROTO_L3_TRANSDSP)
-#define ISDN_FEATURE_L3_FAX (0x10000 << ISDN_PROTO_L3_FAX)
+#define ISDN_FEATURE_L3_FCLASS2 (0x10000 << ISDN_PROTO_L3_FCLASS2)
+#define ISDN_FEATURE_L3_FCLASS1 (0x10000 << ISDN_PROTO_L3_FCLASS1)
#define ISDN_FEATURE_L3_MASK (0x0FF0000) /* Max. 8 Protocols */
#define ISDN_FEATURE_L3_SHIFT (16)
#endif /* TTY_FAX */
+#define ISDN_FAX_CLASS1_FAE 0
+#define ISDN_FAX_CLASS1_FTS 1
+#define ISDN_FAX_CLASS1_FRS 2
+#define ISDN_FAX_CLASS1_FTM 3
+#define ISDN_FAX_CLASS1_FRM 4
+#define ISDN_FAX_CLASS1_FTH 5
+#define ISDN_FAX_CLASS1_FRH 6
+#define ISDN_FAX_CLASS1_CTRL 7
+
+#define ISDN_FAX_CLASS1_OK 0
+#define ISDN_FAX_CLASS1_CONNECT 1
+#define ISDN_FAX_CLASS1_NOCARR 2
+#define ISDN_FAX_CLASS1_ERROR 3
+#define ISDN_FAX_CLASS1_FCERROR 4
+#define ISDN_FAX_CLASS1_QUERY 5
+
+typedef struct {
+ __u8 cmd;
+ __u8 subcmd;
+ __u8 para[50];
+} aux_s;
+
+#define AT_COMMAND 0
+#define AT_EQ_VALUE 1
+#define AT_QUERY 2
+#define AT_EQ_QUERY 3
+
/* CAPI structs */
/* this is compatible to the old union size */
int command; /* Command or Status (see above) */
ulong arg; /* Additional Data */
union {
- ulong errcode; /* Type of error with STAT_L1ERR */
- int length; /* Amount of bytes sent with STAT_BSENT */
- u_char num[50];/* Additional Data */
+ ulong errcode; /* Type of error with STAT_L1ERR */
+ int length; /* Amount of bytes sent with STAT_BSENT */
+ u_char num[50]; /* Additional Data */
setup_parm setup;/* For SETUP msg */
capi_msg cmsg; /* For CAPI like messages */
- char display[85];/* display message data */
- dss1_cmd_stat dss1_io; /* DSS1 IO-parameter/result */
+ char display[85];/* display message data */
+ dss1_cmd_stat dss1_io; /* DSS1 IO-parameter/result */
+ aux_s aux; /* for modem commands/indications */
#ifdef CONFIG_ISDN_TTY_FAX
T30_s *fax; /* Pointer to ttys fax struct */
#endif
#define QNX4_VALID_FS 0x0001 /* Clean fs. */
#define QNX4_ERROR_FS 0x0002 /* fs has errors. */
#define QNX4_BLOCK_SIZE 0x200 /* blocksize of 512 bytes */
-#define QNX4_DIR_ENTRY_SIZE 0x040 /* dir entry size */
+#define QNX4_BLOCK_SIZE_SHIFT 9
+#define QNX4_DIR_ENTRY_SIZE 0x040 /* dir entry size of 64 bytes */
+#define QNX4_DIR_ENTRY_SIZE_SHIFT 6
#define QNX4_XBLK_ENTRY_SIZE 0x200 /* xblk entry size */
#define QNX4_INODES_PER_BLOCK 0x08 /* 512 / 64 */
-
+#define QNX4_INODES_PER_BLOCK_MASK 0x07
/* for filenames */
#define QNX4_SHORT_NAME_MAX 16
#define QNX4_NAME_MAX 48
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Fri Nov 13 14:37:40 1998
- * Modified at: Thu Jan 13 18:27:38 2000
+ * Modified at: Sun Jan 23 17:47:00 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
int len;
};
-#define MAX_WINDOW 7
+#define MAX_TX_WINDOW 7
+#define MAX_RX_WINDOW 7
struct st_fifo {
- struct st_fifo_entry entries[MAX_WINDOW];
+ struct st_fifo_entry entries[MAX_RX_WINDOW];
int pending_bytes;
int head;
int tail;
};
struct tx_fifo {
- struct frame_cb queue[MAX_WINDOW]; /* Info about frames in queue */
- int ptr; /* Currently being sent */
- int len; /* Lenght of queue */
- int free; /* Next free slot */
- void *tail; /* Next free start in DMA mem */
+ struct frame_cb queue[MAX_TX_WINDOW]; /* Info about frames in queue */
+ int ptr; /* Currently being sent */
+ int len; /* Lenght of queue */
+ int free; /* Next free slot */
+ void *tail; /* Next free start in DMA mem */
};
/* Private data for each instance */
struct st_fifo st_fifo; /* Info about received frames */
struct tx_fifo tx_fifo; /* Info about frames to be transmitted */
- int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */
- int tx_len; /* Number of frames in tx_buff */
-
struct device *netdev; /* Yes! we are some kind of netdevice */
struct net_device_stats stats;
if (!(options & WUNTRACED) && !(p->flags & PF_PTRACED))
continue;
read_unlock(&tasklist_lock);
+ current->state = TASK_RUNNING; /* We *must* do this before touching userspace! */
retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;
if (!retval && stat_addr)
retval = put_user((p->exit_code << 8) | 0x7f, stat_addr);
current->times.tms_cutime += p->times.tms_utime + p->times.tms_cutime;
current->times.tms_cstime += p->times.tms_stime + p->times.tms_cstime;
read_unlock(&tasklist_lock);
+ current->state = TASK_RUNNING; /* We *must* do this before touching userspace! */
retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;
if (!retval && stat_addr)
retval = put_user(p->exit_code, stat_addr);
*/
if (!(current->flags & PF_MEMALLOC)) {
int freed;
+ if (current->state != TASK_RUNNING && (gfp_mask & __GFP_WAIT)) {
+ printk("gfp called by non-running (%d) task from %p!\n",
+ current->state, __builtin_return_address(0));
+ /* if we're not running, we can't sleep */
+ gfp_mask &= ~__GFP_WAIT;
+ }
if (nr_free_pages <= freepages.low) {
wake_up_interruptible(&kswapd_wait);
freed = try_to_free_pages(gfp_mask);
current->flags &= ~PF_MEMALLOC;
+ if ((gfp_mask & __GFP_MED) && nr_free_pages > freepages.min / 2)
+ goto ok_to_allocate;
+
if (!freed && !(gfp_mask & __GFP_HIGH))
goto nopage;
}
#else
netdev_dropping = 0;
#endif
+ if (skb->dev->flags & IFF_SLAVE && skb->dev->slave) {
+ skb->dev = skb->dev->slave;
+ }
skb_queue_tail(&backlog,skb);
mark_bh(NET_BH);
return;
continue;
found_ok_skb:
+ /* Below we'll be accessing user memory, which might sleep, so... */
+ current->state = TASK_RUNNING;
+
/* Lock the buffer. We can be fairly relaxed as
* an interrupt will never steal a buffer we are
* using unless I've missed something serious in
break;
}
+ remove_wait_queue(sk->sleep, &wait);
+ current->state = TASK_RUNNING;
+
if(copied >= 0 && msg->msg_name) {
tp->af_specific->addr2sockaddr(sk, (struct sockaddr *)
msg->msg_name);
*addr_len = tp->af_specific->sockaddr_len;
}
- remove_wait_queue(sk->sleep, &wait);
- current->state = TASK_RUNNING;
-
/* Clean up data we have read: This will do ACK frames. */
cleanup_rbuf(sk, copied);
release_sock(sk);
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Oct 9 09:22:27 1999
- * Modified at: Sun Dec 12 12:24:32 1999
+ * Modified at: Sun Jan 23 09:16:36 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
- * Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ * Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
#include <net/irda/wrapper.h>
extern int irtty_init(void);
-extern int pc87108_init(void);
+extern int nsc_ircc_init(void);
+extern int ircc_init(void);
extern int w83977af_init(void);
extern int esi_init(void);
extern int tekram_init(void);
w83977af_init();
#endif
#ifdef CONFIG_NSC_FIR
- pc87108_init();
+ nsc_ircc_init();
#endif
#ifdef CONFIG_TOSHIBA_FIR
toshoboe_init();
#ifdef CONFIG_LITELINK_DONGLE
litelink_init();
#endif
-#ifdef CONFIG_AIRPORT_DONGLE
- airport_init();
-#endif
#ifdef CONFIG_OLD_BELKIN
old_belkin_init();
#endif