S: United Kingdom
N: Ron Holt
-E: ron@sovereign.org
+E: ron@holt.org
+E: rholt@netcom.com
W: http://www.holt.org/
P: 1024/1FD44539 DF 4B EB 9F 5B 68 38 9A 40 E3 FB 71 D1 C8 0B 56
D: Kernel development
the radio tuner. This is supported in the video4linux
radio-miropcm20 driver.
+Micronas Intermetall MSP 3400 support
+CONFIG_VIDEO_MSP3400
+ This option enables the driver for the Micronas Intermetall MSP 3400
+ series sound decoder/mixer chips often found on BT848-style TV cards.
+
+ Say Y here if your sound card has a MSP 3400 series sound decoder or
+ mixer chip.
+
+ This driver is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. The module will be called msp3400.o.
+
SB32/AWE support
CONFIG_AWE32_SYNTH
Say Y here if you have a Sound Blaster SB32, AWE32-PnP, SB AWE64 or
CONFIG_ISDN_DRV_AVMB1_B1PCI
Enable support for the PCI version of the AVM B1 card.
+AVM B1 PCI V4 support
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+ Enable support for the V4 version of AVM B1 PCI card.
+
AVM T1/T1-B ISA support
CONFIG_ISDN_DRV_AVMB1_T1ISA
Enable support for the AVM T1 T1B card.
Enable support for the AVM T1 T1B card.
Note: This is a PRI card and handle 30 B-channels.
+AVM C4 support
+CONFIG_ISDN_DRV_AVMB1_C4
+ Enable support for the AVM C4 PCI card.
+ This card handle 4 BRI ISDN lines (8 channels).
+
Verbose reason code reporting (kernel size +=7K)
CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
If you say Y here, the AVM B1 driver will give verbose reasons for
Max Riegel (riegel@max.franken.de)
For making the ICN hardware-documentation and test-equipment available.
+Armin Schindler (mac@melware.de)
+ For the eicon active card driver.
+
Gerhard 'Fido' Schneider (fido@wuff.mayn.de)
For heavy-duty-beta-testing with his BBS ;)
Thomas Uhl (uhl@think.de)
For distributing the cards.
For pushing me to work ;-)
+
The functionality is almost the same as that of a serial device
(the line-discs are handled by the kernel), which lets you run
SLIP, CSLIP and asynchronous PPP through the devices. We have tested
- Seyon, minicom, CSLIP (uri-dip) PPP and mgetty (compiled with NO_FAX),
- XCept.
+ Seyon, minicom, CSLIP (uri-dip) PPP, mgetty, XCept and Hylafax.
The modem-emulation supports the following:
1.3.1 Commands:
AT&D3 Same as AT&D2 but also resets all registers.
AT&Ex Set the EAZ/MSN for this channel to x.
AT&F Reset all registers and profile to "factory-defaults"
+ AT&Lx Set list of phone numbers to listen on. x is a
+ list of wildcard patterns separated by semicolon.
+ If this is set, it has precedence over the MSN set
+ by AT&E.
AT&Rx Select V.110 bitrate adaption.
This command enables V.110 protocol with 9600 baud
(x=9600), 19200 baud (x=19200) or 38400 baud
15 0 Layer-3 protocol:
0 = transparent
1 = transparent with audio features (e.g. DSP)
- 2 = Fax G3 (S14 has to be set to 11)
+ 2 = Fax G3 Class 2 commands (S14 has to be set to 11)
+ 2 = Fax G3 Class 1 commands (S14 has to be set to 11)
16 250 Send-Packet-size/16
17 8 Window-size (not yet implemented)
18 4 Bit coded register, Service-Octet-1 to accept,
If an incoming call matches one network interface, it gets connected to it.
If another incoming call for the same EAZ arrives, which does not match
a network interface, the first tty gets a "RING" and so on.
- As soon as voice gets supported (with the availability of the Diehl-driver),
- the service-identifier will be evaluated in addition.
2 System prerequisites:
-$Id: README.eicon,v 1.5 1999/10/11 18:13:25 armin Exp $
+$Id: README.eicon,v 1.6 2000/01/27 09:54:44 armin Exp $
-(c) 1999 Cytronics & Melware (info@melware.de)
+(c) 1999,2000 Armin Schindler (mac@melware.de)
+(c) 1999,2000 Cytronics & Melware (info@melware.de)
This document describes the eicon driver for the
-Eicon.Diehl active ISDN cards.
+Eicon active ISDN cards.
It is meant to be used with isdn4linux, an ISDN link-level module for Linux.
- ETSI (Euro-DSS1)
- 1TR6 (German ISDN) *not testet*
-
+- other protocols exist for the range of DIVA Server cards,
+ but they are not fully testet yet.
You can load the module simply by using the insmod or modprobe function :
insmod eicon [id=driverid] [membase=<membase>] [irq=<irq>]
-The module will automatically probe the PCI-cards. If the id-options
+The module will automatically probe the PCI-cards. If the id-option
is omitted, the driver will assume 'eicon0' for the first pci card and
increases the digit with each further card. With a given driver-id
the module appends a number starting with '0'.
Details about using the eiconctrl utility are in 'man eiconctrl'
or will be printed by starting eiconctrl without any parameters.
+ISDNLOG:
+With eicon driver version 1.77 or newer and the eiconctrl utility
+of version 1.1 or better, you can use the isdnlog user program
+with your DIVA Server BRI card.
+Just use "eiconctrl isdnlog on" and the driver will generate
+the necessary D-Channel traces for isdnlog.
+
+
Thanks to
Deutsche Mailbox Saar-Lor-Lux GmbH
for sponsoring and testing fax
- You might want to access a public X.25 data network from your Linux box.
You can use i4l if you were physically connected to the X.25 switch
- by an ISDN line (leased line as well as dial up connection should work)
+ by an ISDN B-channel (leased line as well as dial up connection should
+ work).
+
+ This corresponds to ITU-T recommendation X.31 Case A (circuit-mode
+ access to PSPDN [packet switched public data network]).
+
+ NOTE: X.31 also covers a Case B (access to PSPDN via virtual
+ circuit / packet mode service). The latter mode (which in theory
+ also allows using the D-channel) is not supported by isdn4linux.
+ It should however be possible to establish such packet mode connections
+ with certain active isdn cards provided that the firmware supports X.31
+ and the driver exports this functionality to the user. Currently,
+ the AVM B1 driver is the only driver which does so. (It should be
+ possible to access D-channel X.31 with active AVM cards using the
+ CAPI interface of the AVM-B1 driver).
- Or you might want to operate certain ISDN teleservices on your linux
box. A lot of those teleservices run on top of the ISO-8208
VERSION = 2
PATCHLEVEL = 2
SUBLEVEL = 15
-EXTRAVERSION = pre14
+EXTRAVERSION = pre15
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
@echo -n \#define UTS_VERSION \"\#`cat .version` > .ver
@if [ -n "$(CONFIG_SMP)" ] ; then echo -n " SMP" >> .ver; fi
@if [ -f .name ]; then echo -n \-`cat .name` >> .ver; fi
- @echo ' '`date`'"' >> .ver
- @echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> .ver
+ @echo ' '`LANG=C date`'"' >> .ver
+ @echo \#define LINUX_COMPILE_TIME \"`LANG=C date +%T`\" >> .ver
@echo \#define LINUX_COMPILE_BY \"`whoami`\" >> .ver
@echo \#define LINUX_COMPILE_HOST \"`hostname`\" >> .ver
@if [ -x /bin/dnsdomainname ]; then \
-/* $Id: irq.c,v 1.93 1999/04/21 06:15:45 anton Exp $
+/* $Id: irq.c,v 1.93.2.1 2000/02/17 18:05:29 davem Exp $
* arch/sparc/kernel/irq.c: Interrupt request handling routines. On the
* Sparc the IRQ's are basically 'cast in stone'
* and you are supposed to probe the prom's device
-/* $Id: srmmu.c,v 1.187.2.8 1999/12/23 01:58:38 davem Exp $
+/* $Id: srmmu.c,v 1.187.2.9 2000/03/05 17:39:18 davem Exp $
* srmmu.c: SRMMU specific routines for memory management.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
-/* $Id: swift.S,v 1.1.2.3 1999/10/14 01:00:17 davem Exp $
+/* $Id: swift.S,v 1.1.2.4 2000/03/05 17:39:17 davem Exp $
* swift.S: MicroSparc-II mmu/cache operations.
*
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
-/* $Id: entry.S,v 1.103.2.4 1999/10/24 17:29:13 davem Exp $
+/* $Id: entry.S,v 1.103.2.5 2000/03/06 22:30:22 davem Exp $
* arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points.
*
* Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
-/* $Id: head.S,v 1.60.2.4 1999/11/12 15:45:47 davem Exp $
+/* $Id: head.S,v 1.60.2.5 2000/03/06 22:30:25 davem Exp $
* head.S: Initial boot code for the Sparc64 port of Linux.
*
* Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu)
-/* $Id: setup.c,v 1.43.2.2 1999/10/24 17:29:20 davem Exp $
+/* $Id: setup.c,v 1.43.2.3 2000/03/03 23:50:37 davem Exp $
* linux/arch/sparc64/kernel/setup.c
*
* Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
-/* $Id: blockops.S,v 1.16.2.1 1999/10/07 20:48:14 davem Exp $
+/* $Id: blockops.S,v 1.16.2.2 2000/03/03 23:50:32 davem Exp $
* blockops.S: UltraSparc block zero optimized routines.
*
* Copyright (C) 1996,1998 David S. Miller (davem@caip.rutgers.edu)
-/* $Id: init.c,v 1.127.2.6 1999/12/05 07:24:42 davem Exp $
+/* $Id: init.c,v 1.127.2.8 2000/03/03 23:50:41 davem Exp $
* arch/sparc64/mm/init.c
*
* Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
-/* $Id: ultra.S,v 1.32.2.1 1999/10/24 17:29:34 davem Exp $
+/* $Id: ultra.S,v 1.32.2.3 2000/03/03 23:50:46 davem Exp $
* ultra.S: Don't expand these all over the place...
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
fi
if [ "$CONFIG_PCI" != "n" ]; then
dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV
+ if [ "$CONFIG_VIDEO_BT848" != "n" ]; then
+ comment ' MSP3400 sound decoder support is in the section "additional'
+ comment ' low level sound drivers". You may need to enable it there.'
+ fi
fi
if [ "$CONFIG_PARPORT" != "n" ]; then
dep_tristate 'Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT
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
+ if [ "$CONFIG_ISDN_DRV_AVMB1_B1PCI" != "n" ]; then
+ if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
+ bool ' AVM B1 PCI V4 support' CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+ fi
+ fi
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
+ if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
+ bool ' AVM C4 support' CONFIG_ISDN_DRV_AVMB1_C4
+ fi
bool ' Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
fi
endmenu
#
-# $Id: Makefile,v 1.7 1999/09/15 08:16:03 calle Exp $
+# $Id: Makefile,v 1.8 2000/01/25 14:33:38 calle Exp $
#
# Makefile for the CAPI and AVM-B1 device drivers.
#
# parent makes..
#
# $Log: Makefile,v $
+# Revision 1.8 2000/01/25 14:33:38 calle
+# - Added Support AVM B1 PCI V4.0 (tested with prototype)
+# - splitted up t1pci.c into b1dma.c for common function with b1pciv4
+# - support for revision register
+#
# Revision 1.7 1999/09/15 08:16:03 calle
# Implementation of 64Bit extention complete.
#
ifdef CONFIG_ISDN_DRV_AVMB1_C4
O_OBJS += c4.o
endif
- OX_OBJS += capiutil.o capidrv.o b1.o
+ OX_OBJS += capiutil.o capidrv.o b1.o b1dma.o
else
ifeq ($(CONFIG_ISDN_DRV_AVMB1),m)
O_TARGET += kernelcapi.o
ifdef CONFIG_ISDN_DRV_AVMB1_C4
M_OBJS += c4.o
endif
- MX_OBJS += capiutil.o capidrv.o b1.o
+ MX_OBJS += capiutil.o capidrv.o b1.o b1dma.o
endif
endif
/*
- * $Id: avmcard.h,v 1.6 1999/11/05 16:38:01 calle Exp $
+ * $Id: avmcard.h,v 1.7 2000/01/25 14:33:38 calle Exp $
*
* Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: avmcard.h,v $
+ * Revision 1.7 2000/01/25 14:33:38 calle
+ * - Added Support AVM B1 PCI V4.0 (tested with prototype)
+ * - splitted up t1pci.c into b1dma.c for common function with b1pciv4
+ * - support for revision register
+ *
* Revision 1.6 1999/11/05 16:38:01 calle
* Cleanups before kernel 2.4:
* - Changed all messages to use card->name or driver->name instead of
unsigned irq;
unsigned long membase;
enum avmcardtype cardtype;
+ unsigned char revision;
+ unsigned char class;
int cardnr; /* for t1isa */
char msgbuf[128]; /* capimsg msg part */
#define B1_WRITE 0x01
#define B1_INSTAT 0x02
#define B1_OUTSTAT 0x03
-#define B1_RESET 0x10
#define B1_ANALYSE 0x04
+#define B1_REVISION 0x05
+#define B1_RESET 0x10
#define B1_STAT0(cardtype) ((cardtype) == avm_m1 ? 0x81200000l : 0x80A00000l)
}
}
+/* b1.c */
int b1_detect(unsigned int base, enum avmcardtype cardtype);
+void b1_getrevision(avmcard *card);
int b1_load_t4file(avmcard *card, capiloaddatapart * t4file);
int b1_load_config(avmcard *card, capiloaddatapart * config);
int b1_loaded(avmcard *card);
+
int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data);
void b1_reset_ctr(struct capi_ctr *ctrl);
void b1_register_appl(struct capi_ctr *ctrl, __u16 appl,
int b1ctl_read_proc(char *page, char **start, off_t off,
int count, int *eof, struct capi_ctr *ctrl);
+/* b1dma.c */
+int b1pciv4_detect(avmcard *card);
+int t1pci_detect(avmcard *card);
+void b1dma_reset(avmcard *card);
+void b1dma_interrupt(int interrupt, void *devptr, struct pt_regs *regs);
+
+int b1dma_load_firmware(struct capi_ctr *ctrl, capiloaddata *data);
+void b1dma_reset_ctr(struct capi_ctr *ctrl);
+void b1dma_remove_ctr(struct capi_ctr *ctrl);
+void b1dma_register_appl(struct capi_ctr *ctrl,
+ __u16 appl,
+ capi_register_params *rp);
+void b1dma_release_appl(struct capi_ctr *ctrl, __u16 appl);
+void b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
+int b1dmactl_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, struct capi_ctr *ctrl);
#endif /* _AVMCARD_H_ */
/*
- * $Id: b1.c,v 1.12 1999/11/05 16:38:01 calle Exp $
+ * $Id: b1.c,v 1.13 2000/01/25 14:33:38 calle Exp $
*
* Common module for AVM B1 cards.
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: b1.c,v $
+ * Revision 1.13 2000/01/25 14:33:38 calle
+ * - Added Support AVM B1 PCI V4.0 (tested with prototype)
+ * - splitted up t1pci.c into b1dma.c for common function with b1pciv4
+ * - support for revision register
+ *
* Revision 1.12 1999/11/05 16:38:01 calle
* Cleanups before kernel 2.4:
* - Changed all messages to use card->name or driver->name instead of
#include "capicmd.h"
#include "capiutil.h"
-static char *revision = "$Revision: 1.12 $";
+static char *revision = "$Revision: 1.13 $";
/* ------------------------------------------------------------- */
return 0;
}
+void b1_getrevision(avmcard *card)
+{
+ card->class = inb(card->port + B1_ANALYSE);
+ card->revision = inb(card->port + B1_REVISION);
+}
+
int b1_load_t4file(avmcard *card, capiloaddatapart * t4file)
{
unsigned char buf[256];
EXPORT_SYMBOL(b1_irq_table);
EXPORT_SYMBOL(b1_detect);
+EXPORT_SYMBOL(b1_getrevision);
EXPORT_SYMBOL(b1_load_t4file);
EXPORT_SYMBOL(b1_load_config);
EXPORT_SYMBOL(b1_loaded);
--- /dev/null
+/*
+ * $Id: b1dma.c,v 1.3 2000/02/26 01:00:53 keil Exp $
+ *
+ * Common module for AVM B1 cards that support dma with AMCC
+ *
+ * (c) Copyright 2000 by Carsten Paeth (calle@calle.in-berlin.de)
+ *
+ * $Log: b1dma.c,v $
+ * Revision 1.3 2000/02/26 01:00:53 keil
+ * changes from 2.3.47
+ *
+ * Revision 1.2 2000/01/25 14:44:47 calle
+ * typo in b1pciv4_detect().
+ *
+ * Revision 1.1 2000/01/25 14:36:43 calle
+ * common function for T1 PCI and B1 PCI V4.
+ *
+ *
+ */
+
+#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/capi.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include "capilli.h"
+#include "avmcard.h"
+#include "capicmd.h"
+#include "capiutil.h"
+
+static char *revision = "$Revision: 1.3 $";
+
+/* ------------------------------------------------------------- */
+
+MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
+
+int suppress_pollack = 0;
+MODULE_PARM(suppress_pollack, "0-1i");
+
+/* ------------------------------------------------------------- */
+
+static void b1dma_dispatch_tx(avmcard *card);
+
+/* ------------------------------------------------------------- */
+
+/* S5933 */
+
+#define AMCC_RXPTR 0x24
+#define AMCC_RXLEN 0x28
+#define AMCC_TXPTR 0x2c
+#define AMCC_TXLEN 0x30
+
+#define AMCC_INTCSR 0x38
+# define EN_READ_TC_INT 0x00008000L
+# define EN_WRITE_TC_INT 0x00004000L
+# define EN_TX_TC_INT EN_READ_TC_INT
+# define EN_RX_TC_INT EN_WRITE_TC_INT
+# define AVM_FLAG 0x30000000L
+
+# define ANY_S5933_INT 0x00800000L
+# define READ_TC_INT 0x00080000L
+# define WRITE_TC_INT 0x00040000L
+# define TX_TC_INT READ_TC_INT
+# define RX_TC_INT WRITE_TC_INT
+# define MASTER_ABORT_INT 0x00100000L
+# define TARGET_ABORT_INT 0x00200000L
+# define BUS_MASTER_INT 0x00200000L
+# define ALL_INT 0x000C0000L
+
+#define AMCC_MCSR 0x3c
+# define A2P_HI_PRIORITY 0x00000100L
+# define EN_A2P_TRANSFERS 0x00000400L
+# define P2A_HI_PRIORITY 0x00001000L
+# define EN_P2A_TRANSFERS 0x00004000L
+# define RESET_A2P_FLAGS 0x04000000L
+# define RESET_P2A_FLAGS 0x02000000L
+
+/* ------------------------------------------------------------- */
+
+#define b1dmaoutmeml(addr, value) writel(value, addr)
+#define b1dmainmeml(addr) readl(addr)
+#define b1dmaoutmemw(addr, value) writew(value, addr)
+#define b1dmainmemw(addr) readw(addr)
+#define b1dmaoutmemb(addr, value) writeb(value, addr)
+#define b1dmainmemb(addr) readb(addr)
+
+/* ------------------------------------------------------------- */
+
+static inline int b1dma_tx_empty(unsigned int port)
+{
+ return inb(port + 0x03) & 0x1;
+}
+
+static inline int b1dma_rx_full(unsigned int port)
+{
+ return inb(port + 0x02) & 0x1;
+}
+
+static int b1dma_tolink(avmcard *card, void *buf, unsigned int len)
+{
+ unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */
+ unsigned char *s = (unsigned char *)buf;
+ while (len--) {
+ while ( !b1dma_tx_empty(card->port)
+ && time_before(jiffies, stop));
+ if (!b1dma_tx_empty(card->port))
+ return -1;
+ t1outp(card->port, 0x01, *s++);
+ }
+ return 0;
+}
+
+static int b1dma_fromlink(avmcard *card, void *buf, unsigned int len)
+{
+ unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */
+ unsigned char *s = (unsigned char *)buf;
+ while (len--) {
+ while ( !b1dma_rx_full(card->port)
+ && time_before(jiffies, stop));
+ if (!b1dma_rx_full(card->port))
+ return -1;
+ *s++ = t1inp(card->port, 0x00);
+ }
+ return 0;
+}
+
+static int WriteReg(avmcard *card, __u32 reg, __u8 val)
+{
+ __u8 cmd = 0x00;
+ if ( b1dma_tolink(card, &cmd, 1) == 0
+ && b1dma_tolink(card, ®, 4) == 0) {
+ __u32 tmp = val;
+ return b1dma_tolink(card, &tmp, 4);
+ }
+ return -1;
+}
+
+static __u8 ReadReg(avmcard *card, __u32 reg)
+{
+ __u8 cmd = 0x01;
+ if ( b1dma_tolink(card, &cmd, 1) == 0
+ && b1dma_tolink(card, ®, 4) == 0) {
+ __u32 tmp;
+ if (b1dma_fromlink(card, &tmp, 4) == 0)
+ return (__u8)tmp;
+ }
+ return 0xff;
+}
+
+/* ------------------------------------------------------------- */
+
+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;
+}
+
+/* ------------------------------------------------------------- */
+
+void b1dma_reset(avmcard *card)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ card->csr = 0x0;
+ b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr);
+ b1dmaoutmeml(card->mbase+AMCC_MCSR, 0);
+ b1dmaoutmeml(card->mbase+AMCC_RXLEN, 0);
+ b1dmaoutmeml(card->mbase+AMCC_TXLEN, 0);
+
+ t1outp(card->port, 0x10, 0x00);
+ t1outp(card->port, 0x07, 0x00);
+
+ restore_flags(flags);
+
+ b1dmaoutmeml(card->mbase+AMCC_MCSR, 0);
+ udelay(10 * 1000);
+ b1dmaoutmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */
+ udelay(10 * 1000);
+ b1dmaoutmeml(card->mbase+AMCC_MCSR, 0);
+ if (card->cardtype == avm_t1pci)
+ udelay(42 * 1000);
+ else
+ udelay(10 * 1000);
+}
+
+/* ------------------------------------------------------------- */
+
+int b1dma_detect(avmcard *card)
+{
+ b1dmaoutmeml(card->mbase+AMCC_MCSR, 0);
+ udelay(10 * 1000);
+ b1dmaoutmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */
+ udelay(10 * 1000);
+ b1dmaoutmeml(card->mbase+AMCC_MCSR, 0);
+ udelay(42 * 1000);
+
+ b1dmaoutmeml(card->mbase+AMCC_RXLEN, 0);
+ b1dmaoutmeml(card->mbase+AMCC_TXLEN, 0);
+ card->csr = 0x0;
+ b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr);
+
+ if (b1dmainmeml(card->mbase+AMCC_MCSR) != 0x000000E6)
+ return 1;
+
+ b1dmaoutmeml(card->mbase+AMCC_RXPTR, 0xffffffff);
+ b1dmaoutmeml(card->mbase+AMCC_TXPTR, 0xffffffff);
+ if ( b1dmainmeml(card->mbase+AMCC_RXPTR) != 0xfffffffc
+ || b1dmainmeml(card->mbase+AMCC_TXPTR) != 0xfffffffc)
+ return 2;
+
+ b1dmaoutmeml(card->mbase+AMCC_RXPTR, 0x0);
+ b1dmaoutmeml(card->mbase+AMCC_TXPTR, 0x0);
+ if ( b1dmainmeml(card->mbase+AMCC_RXPTR) != 0x0
+ || b1dmainmeml(card->mbase+AMCC_TXPTR) != 0x0)
+ return 3;
+
+ t1outp(card->port, 0x10, 0x00);
+ t1outp(card->port, 0x07, 0x00);
+
+ t1outp(card->port, 0x02, 0x02);
+ t1outp(card->port, 0x03, 0x02);
+
+ if ( (t1inp(card->port, 0x02) & 0xFE) != 0x02
+ || t1inp(card->port, 0x3) != 0x03)
+ return 4;
+
+ t1outp(card->port, 0x02, 0x00);
+ t1outp(card->port, 0x03, 0x00);
+
+ if ( (t1inp(card->port, 0x02) & 0xFE) != 0x00
+ || t1inp(card->port, 0x3) != 0x01)
+ return 5;
+
+ return 0;
+}
+
+int t1pci_detect(avmcard *card)
+{
+ int ret;
+
+ if ((ret = b1dma_detect(card)) != 0)
+ return ret;
+
+ /* Transputer test */
+
+ if ( WriteReg(card, 0x80001000, 0x11) != 0
+ || WriteReg(card, 0x80101000, 0x22) != 0
+ || WriteReg(card, 0x80201000, 0x33) != 0
+ || WriteReg(card, 0x80301000, 0x44) != 0)
+ return 6;
+
+ if ( ReadReg(card, 0x80001000) != 0x11
+ || ReadReg(card, 0x80101000) != 0x22
+ || ReadReg(card, 0x80201000) != 0x33
+ || ReadReg(card, 0x80301000) != 0x44)
+ return 7;
+
+ if ( WriteReg(card, 0x80001000, 0x55) != 0
+ || WriteReg(card, 0x80101000, 0x66) != 0
+ || WriteReg(card, 0x80201000, 0x77) != 0
+ || WriteReg(card, 0x80301000, 0x88) != 0)
+ return 8;
+
+ if ( ReadReg(card, 0x80001000) != 0x55
+ || ReadReg(card, 0x80101000) != 0x66
+ || ReadReg(card, 0x80201000) != 0x77
+ || ReadReg(card, 0x80301000) != 0x88)
+ return 9;
+
+ return 0;
+}
+
+int b1pciv4_detect(avmcard *card)
+{
+ int ret, i;
+
+ if ((ret = b1dma_detect(card)) != 0)
+ return ret;
+
+ for (i=0; i < 5 ; i++) {
+ if (WriteReg(card, 0x80A00000, 0x21) != 0)
+ return 6;
+ if ((ReadReg(card, 0x80A00000) & 0x01) != 0x01)
+ return 7;
+ }
+ for (i=0; i < 5 ; i++) {
+ if (WriteReg(card, 0x80A00000, 0x20) != 0)
+ return 8;
+ if ((ReadReg(card, 0x80A00000) & 0x01) != 0x00)
+ return 9;
+ }
+
+ return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static void b1dma_dispatch_tx(avmcard *card)
+{
+ avmcard_dmainfo *dma = card->dma;
+ unsigned long flags;
+ struct sk_buff *skb;
+ __u8 cmd, subcmd;
+ __u16 len;
+ __u32 txlen;
+ int inint;
+ void *p;
+
+ save_flags(flags);
+ cli();
+
+ inint = card->interrupt;
+
+ if (card->csr & EN_TX_TC_INT) { /* tx busy */
+ restore_flags(flags);
+ return;
+ }
+
+ skb = skb_dequeue(&dma->send_queue);
+ if (!skb) {
+#ifdef CONFIG_B1DMA_DEBUG
+ printk(KERN_DEBUG "tx(%d): underrun\n", inint);
+#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_B1DMA_DEBUG
+ printk(KERN_DEBUG "tx(%d): put msg len=%d\n",
+ inint, txlen);
+#endif
+ } else {
+ txlen = skb->len-2;
+#ifdef CONFIG_B1DMA_POLLDEBUG
+ if (skb->data[2] == SEND_POLLACK)
+ printk(KERN_INFO "%s: send ack\n", card->name);
+#endif
+#ifdef CONFIG_B1DMA_DEBUG
+ printk(KERN_DEBUG "tx(%d): put 0x%x len=%d\n",
+ inint, skb->data[2], txlen);
+#endif
+ memcpy(dma->sendbuf, skb->data+2, skb->len-2);
+ }
+ txlen = (txlen + 3) & ~3;
+
+ b1dmaoutmeml(card->mbase+AMCC_TXPTR, virt_to_phys(dma->sendbuf));
+ b1dmaoutmeml(card->mbase+AMCC_TXLEN, txlen);
+
+ card->csr |= EN_TX_TC_INT;
+
+ if (!inint)
+ b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr);
+
+ 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);
+ b1dma_dispatch_tx(card);
+}
+
+/* ------------------------------------------------------------- */
+
+static void b1dma_handle_rx(avmcard *card)
+{
+ avmctrl_info *cinfo = &card->ctrlinfo[0];
+ avmcard_dmainfo *dma = card->dma;
+ struct capi_ctr *ctrl = cinfo->capi_ctrl;
+ struct sk_buff *skb;
+ void *p = dma->recvbuf+4;
+ __u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize;
+ __u8 b1cmd = _get_byte(&p);
+
+#ifdef CONFIG_B1DMA_DEBUG
+ printk(KERN_DEBUG "rx: 0x%x %lu\n", 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);
+
+ 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);
+ 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);
+
+ ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
+
+ break;
+
+ case RECEIVE_FREE_NCCI:
+
+ ApplId = _get_word(&p);
+ NCCI = _get_word(&p);
+
+ if (NCCI != 0xffffffff)
+ ctrl->free_ncci(ctrl, ApplId, NCCI);
+ else ctrl->appl_released(ctrl, ApplId);
+ break;
+
+ case RECEIVE_START:
+#ifdef CONFIG_B1DMA_POLLDEBUG
+ printk(KERN_INFO "%s: receive poll\n", card->name);
+#endif
+ if (!suppress_pollack)
+ queue_pollack(card);
+ ctrl->resume_output(ctrl);
+ break;
+
+ case RECEIVE_STOP:
+ ctrl->suspend_output(ctrl);
+ break;
+
+ case RECEIVE_INIT:
+
+ 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(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: b1dma_interrupt: 0x%x ???\n",
+ card->name, b1cmd);
+ return;
+ }
+}
+
+/* ------------------------------------------------------------- */
+
+static void b1dma_handle_interrupt(avmcard *card)
+{
+ __u32 status = b1dmainmeml(card->mbase+AMCC_INTCSR);
+ __u32 newcsr;
+
+ if ((status & ANY_S5933_INT) == 0)
+ return;
+
+ newcsr = card->csr | (status & ALL_INT);
+ if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT;
+ if (status & RX_TC_INT) newcsr &= ~EN_RX_TC_INT;
+ b1dmaoutmeml(card->mbase+AMCC_INTCSR, newcsr);
+
+ if ((status & RX_TC_INT) != 0) {
+ __u8 *recvbuf = card->dma->recvbuf;
+ __u32 rxlen;
+ if (card->dma->recvlen == 0) {
+ card->dma->recvlen = *((__u32 *)recvbuf);
+ rxlen = (card->dma->recvlen + 3) & ~3;
+ b1dmaoutmeml(card->mbase+AMCC_RXPTR,
+ virt_to_phys(recvbuf+4));
+ b1dmaoutmeml(card->mbase+AMCC_RXLEN, rxlen);
+ } else {
+ b1dma_handle_rx(card);
+ card->dma->recvlen = 0;
+ b1dmaoutmeml(card->mbase+AMCC_RXPTR, virt_to_phys(recvbuf));
+ b1dmaoutmeml(card->mbase+AMCC_RXLEN, 4);
+ }
+ }
+
+ if ((status & TX_TC_INT) != 0) {
+ card->csr &= ~EN_TX_TC_INT;
+ b1dma_dispatch_tx(card);
+ } else if (card->csr & EN_TX_TC_INT) {
+ if (b1dmainmeml(card->mbase+AMCC_TXLEN) == 0) {
+ card->csr &= ~EN_TX_TC_INT;
+ b1dma_dispatch_tx(card);
+ }
+ }
+ b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr);
+}
+
+void b1dma_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
+{
+ avmcard *card;
+
+ card = (avmcard *) devptr;
+
+ if (!card) {
+ printk(KERN_WARNING "b1dma: interrupt: wrong device\n");
+ return;
+ }
+ if (card->interrupt) {
+ printk(KERN_ERR "%s: reentering interrupt hander\n", card->name);
+ return;
+ }
+
+ card->interrupt = 1;
+
+ b1dma_handle_interrupt(card);
+
+ card->interrupt = 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static int b1dma_loaded(avmcard *card)
+{
+ unsigned long stop;
+ unsigned char ans;
+ unsigned long tout = 2;
+ unsigned int base = card->port;
+
+ for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
+ if (b1_tx_empty(base))
+ break;
+ }
+ if (!b1_tx_empty(base)) {
+ printk(KERN_ERR "%s: b1dma_loaded: tx err, corrupted t4 file ?\n",
+ card->name);
+ return 0;
+ }
+ b1_put_byte(base, SEND_POLLACK);
+ for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
+ if (b1_rx_full(base)) {
+ if ((ans = b1_get_byte(base)) == RECEIVE_POLLDWORD) {
+ return 1;
+ }
+ printk(KERN_ERR "%s: b1dma_loaded: got 0x%x, firmware not running in dword mode\n", card->name, ans);
+ return 0;
+ }
+ }
+ printk(KERN_ERR "%s: b1dma_loaded: firmware not running\n", card->name);
+ return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static void b1dma_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);
+ b1dma_dispatch_tx(card);
+}
+
+int b1dma_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
+{
+ avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+ avmcard *card = cinfo->card;
+ unsigned long flags;
+ int retval;
+
+ b1dma_reset(card);
+
+ if ((retval = b1_load_t4file(card, &data->firmware))) {
+ b1dma_reset(card);
+ printk(KERN_ERR "%s: failed to load t4file!!\n",
+ card->name);
+ return retval;
+ }
+
+ if (data->configuration.len > 0 && data->configuration.data) {
+ if ((retval = b1_load_config(card, &data->configuration))) {
+ b1dma_reset(card);
+ printk(KERN_ERR "%s: failed to load config!!\n",
+ card->name);
+ return retval;
+ }
+ }
+
+ if (!b1dma_loaded(card)) {
+ b1dma_reset(card);
+ printk(KERN_ERR "%s: failed to load t4file.\n", card->name);
+ return -EIO;
+ }
+
+ save_flags(flags);
+ cli();
+
+ card->csr = AVM_FLAG;
+ b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr);
+ b1dmaoutmeml(card->mbase+AMCC_MCSR,
+ EN_A2P_TRANSFERS|EN_P2A_TRANSFERS
+ |A2P_HI_PRIORITY|P2A_HI_PRIORITY
+ |RESET_A2P_FLAGS|RESET_P2A_FLAGS);
+ t1outp(card->port, 0x07, 0x30);
+ t1outp(card->port, 0x10, 0xF0);
+
+ card->dma->recvlen = 0;
+ b1dmaoutmeml(card->mbase+AMCC_RXPTR, virt_to_phys(card->dma->recvbuf));
+ b1dmaoutmeml(card->mbase+AMCC_RXLEN, 4);
+ card->csr |= EN_RX_TC_INT;
+ b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr);
+ restore_flags(flags);
+
+ b1dma_send_init(card);
+
+ return 0;
+}
+
+void b1dma_reset_ctr(struct capi_ctr *ctrl)
+{
+ avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+ avmcard *card = cinfo->card;
+
+ b1dma_reset(card);
+
+ memset(cinfo->version, 0, sizeof(cinfo->version));
+ ctrl->reseted(ctrl);
+}
+
+
+/* ------------------------------------------------------------- */
+
+
+void b1dma_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 (want > 0) nconn = want;
+ else nconn = ctrl->profile.nbchannel * -want;
+ if (nconn == 0) nconn = ctrl->profile.nbchannel;
+
+ 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);
+ b1dma_dispatch_tx(card);
+
+ ctrl->appl_registered(ctrl, appl);
+}
+
+/* ------------------------------------------------------------- */
+
+void b1dma_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;
+
+ 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);
+ b1dma_dispatch_tx(card);
+}
+
+/* ------------------------------------------------------------- */
+
+void b1dma_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);
+ b1dma_dispatch_tx(card);
+}
+
+/* ------------------------------------------------------------- */
+
+int b1dmactl_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;
+ unsigned long flags;
+ __u8 flag;
+ int len = 0;
+ char *s;
+ __u32 txaddr, txlen, rxaddr, rxlen, csr;
+
+ 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);
+
+ save_flags(flags);
+ cli();
+
+ txaddr = (__u32)phys_to_virt(b1dmainmeml(card->mbase+0x2c));
+ txaddr -= (__u32)card->dma->sendbuf;
+ txlen = b1dmainmeml(card->mbase+0x30);
+
+ rxaddr = (__u32)phys_to_virt(b1dmainmeml(card->mbase+0x24));
+ rxaddr -= (__u32)card->dma->recvbuf;
+ rxlen = b1dmainmeml(card->mbase+0x28);
+
+ csr = b1dmainmeml(card->mbase+AMCC_INTCSR);
+
+ restore_flags(flags);
+
+ len += sprintf(page+len, "%-16s 0x%lx\n",
+ "csr (cached)", (unsigned long)card->csr);
+ len += sprintf(page+len, "%-16s 0x%lx\n",
+ "csr", (unsigned long)csr);
+ len += sprintf(page+len, "%-16s %lu\n",
+ "txoff", (unsigned long)txaddr);
+ len += sprintf(page+len, "%-16s %lu\n",
+ "txlen", (unsigned long)txlen);
+ len += sprintf(page+len, "%-16s %lu\n",
+ "rxoff", (unsigned long)rxaddr);
+ len += sprintf(page+len, "%-16s %lu\n",
+ "rxlen", (unsigned long)rxlen);
+
+ if (off+count >= len)
+ *eof = 1;
+ if (len < off)
+ return 0;
+ *start = page + off;
+ return ((count < len-off) ? count : len-off);
+}
+
+/* ------------------------------------------------------------- */
+
+EXPORT_SYMBOL(b1dma_reset);
+EXPORT_SYMBOL(t1pci_detect);
+EXPORT_SYMBOL(b1pciv4_detect);
+EXPORT_SYMBOL(b1dma_interrupt);
+
+EXPORT_SYMBOL(b1dma_load_firmware);
+EXPORT_SYMBOL(b1dma_reset_ctr);
+EXPORT_SYMBOL(b1dma_register_appl);
+EXPORT_SYMBOL(b1dma_release_appl);
+EXPORT_SYMBOL(b1dma_send_message);
+EXPORT_SYMBOL(b1dmactl_read_proc);
+
+#ifdef MODULE
+#define b1dma_init init_module
+void cleanup_module(void);
+#endif
+
+int b1dma_init(void)
+{
+ char *p;
+ char rev[10];
+
+ if ((p = strchr(revision, ':'))) {
+ strncpy(rev, p + 1, sizeof(rev));
+ p = strchr(rev, '$');
+ *p = 0;
+ } else
+ strcpy(rev, "1.0");
+
+ printk(KERN_INFO "b1dma: revision %s\n", rev);
+
+ return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+}
+#endif
/*
- * $Id: b1isa.c,v 1.5 1999/11/05 16:38:01 calle Exp $
+ * $Id: b1isa.c,v 1.7 2000/02/02 18:36:03 calle Exp $
*
* Module for AVM B1 ISA-card.
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: b1isa.c,v $
+ * Revision 1.7 2000/02/02 18:36:03 calle
+ * - Modules are now locked while init_module is running
+ * - fixed problem with memory mapping if address is not aligned
+ *
+ * Revision 1.6 2000/01/25 14:37:39 calle
+ * new message after successfull detection including card revision and
+ * used resources.
+ *
* Revision 1.5 1999/11/05 16:38:01 calle
* Cleanups before kernel 2.4:
* - Changed all messages to use card->name or driver->name instead of
#include "capilli.h"
#include "avmcard.h"
-static char *revision = "$Revision: 1.5 $";
+static char *revision = "$Revision: 1.7 $";
/* ------------------------------------------------------------- */
/* ------------------------------------------------------------- */
-static struct capi_driver_interface *di;
-
-/* ------------------------------------------------------------- */
-
static void b1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
{
avmcard *card;
}
/* ------------------------------------------------------------- */
+static struct capi_driver_interface *di;
+
+/* ------------------------------------------------------------- */
+
static void b1isa_remove_ctr(struct capi_ctr *ctrl)
{
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
avmcard *card;
int retval;
+ MOD_INC_USE_COUNT;
+
card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
if (!card) {
printk(KERN_WARNING "b1isa: no memory.\n");
+ MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(card, 0, sizeof(avmcard));
if (!cinfo) {
printk(KERN_WARNING "b1isa: no memory.\n");
kfree(card);
+ MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(cinfo, 0, sizeof(avmctrl_info));
card->port, card->port + AVMB1_PORTLEN);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EBUSY;
}
if (b1_irq_table[card->irq & 0xf] == 0) {
printk(KERN_WARNING "b1isa: irq %d not valid.\n", card->irq);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EINVAL;
}
if ( card->port != 0x150 && card->port != 0x250
printk(KERN_WARNING "b1isa: illegal port 0x%x.\n", card->port);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EINVAL;
}
b1_reset(card->port);
card->port, retval);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EIO;
}
b1_reset(card->port);
+ b1_getrevision(card);
request_region(p->port, AVMB1_PORTLEN, card->name);
release_region(card->port, AVMB1_PORTLEN);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EBUSY;
}
release_region(card->port, AVMB1_PORTLEN);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EBUSY;
}
- MOD_INC_USE_COUNT;
+ printk(KERN_INFO
+ "%s: AVM B1 ISA at i/o %#x, irq %d, revision %d\n",
+ driver->name, card->port, card->irq, card->revision);
+
return 0;
}
if (!cinfo)
return "";
- sprintf(cinfo->infobuf, "%s %s 0x%x %d",
+ sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d",
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->irq : 0,
+ cinfo->card ? cinfo->card->revision : 0
);
return cinfo->infobuf;
}
/*
- * $Id: b1pci.c,v 1.18 1999/11/05 16:38:01 calle Exp $
+ * $Id: b1pci.c,v 1.20 2000/02/02 18:36:03 calle Exp $
*
* Module for AVM B1 PCI-card.
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: b1pci.c,v $
+ * Revision 1.20 2000/02/02 18:36:03 calle
+ * - Modules are now locked while init_module is running
+ * - fixed problem with memory mapping if address is not aligned
+ *
+ * Revision 1.19 2000/01/25 14:33:38 calle
+ * - Added Support AVM B1 PCI V4.0 (tested with prototype)
+ * - splitted up t1pci.c into b1dma.c for common function with b1pciv4
+ * - support for revision register
+ *
* Revision 1.18 1999/11/05 16:38:01 calle
* Cleanups before kernel 2.4:
* - Changed all messages to use card->name or driver->name instead of
#include "capilli.h"
#include "avmcard.h"
-static char *revision = "$Revision: 1.18 $";
+static char *revision = "$Revision: 1.20 $";
/* ------------------------------------------------------------- */
if (!cinfo)
return "";
- sprintf(cinfo->infobuf, "%s %s 0x%x %d",
+ sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d",
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->irq : 0,
+ cinfo->card ? cinfo->card->revision : 0
);
return cinfo->infobuf;
}
avmctrl_info *cinfo;
int retval;
+ MOD_INC_USE_COUNT;
+
card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
if (!card) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
+ MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(card, 0, sizeof(avmcard));
if (!cinfo) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(cinfo, 0, sizeof(avmctrl_info));
driver->name, card->port, card->port + AVMB1_PORTLEN);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EBUSY;
}
b1_reset(card->port);
driver->name, card->port, retval);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EIO;
}
b1_reset(card->port);
+ b1_getrevision(card);
request_region(p->port, AVMB1_PORTLEN, card->name);
release_region(card->port, AVMB1_PORTLEN);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EBUSY;
}
release_region(card->port, AVMB1_PORTLEN);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EBUSY;
}
- MOD_INC_USE_COUNT;
+ if (card->revision >= 4) {
+ printk(KERN_INFO
+ "%s: AVM B1 PCI V4 at i/o %#x, irq %d, revision %d (no dma)\n",
+ driver->name, card->port, card->irq, card->revision);
+ } else {
+ printk(KERN_INFO
+ "%s: AVM B1 PCI at i/o %#x, irq %d, revision %d\n",
+ driver->name, card->port, card->irq, card->revision);
+ }
return 0;
}
0, /* no add_card function */
};
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+/* ------------------------------------------------------------- */
+
+static struct capi_driver_interface *div4;
+
+/* ------------------------------------------------------------- */
+
+static void b1pciv4_remove_ctr(struct capi_ctr *ctrl)
+{
+ avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+ avmcard *card = cinfo->card;
+
+ b1dma_reset(card);
+
+ div4->detach_ctr(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;
+}
+
+static char *b1pciv4_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 r%d",
+ 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,
+ cinfo->card ? cinfo->card->revision : 0
+ );
+ return cinfo->infobuf;
+}
+
+/* ------------------------------------------------------------- */
+
+static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p)
+{
+ unsigned long base, page_offset;
+ avmcard *card;
+ avmctrl_info *cinfo;
+ int retval;
+
+ 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), GFP_ATOMIC);
+ if (!cinfo) {
+ printk(KERN_WARNING "%s: no memory.\n", driver->name);
+ kfree(card->dma);
+ kfree(card);
+ return -ENOMEM;
+ }
+ memset(cinfo, 0, sizeof(avmctrl_info));
+ card->ctrlinfo = cinfo;
+ cinfo->card = card;
+ sprintf(card->name, "b1pciv4-%x", p->port);
+ card->port = p->port;
+ card->irq = p->irq;
+ card->membase = p->membase;
+ card->cardtype = avm_b1pci;
+
+ 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 (card->mbase) {
+ card->mbase += page_offset;
+ } else {
+ printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
+ driver->name, card->membase);
+ kfree(card->ctrlinfo);
+ kfree(card->dma);
+ kfree(card);
+ return -EIO;
+ }
+
+ b1dma_reset(card);
+
+ if ((retval = b1pciv4_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;
+ }
+ b1dma_reset(card);
+ b1_getrevision(card);
+
+ request_region(p->port, AVMB1_PORTLEN, card->name);
+
+ retval = request_irq(card->irq, b1dma_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;
+ }
+
+ cinfo->capi_ctrl = div4->attach_ctr(driver, card->name, cinfo);
+ if (!cinfo->capi_ctrl) {
+ printk(KERN_ERR "%s: attach controller failed.\n", driver->name);
+ iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
+ free_irq(card->irq, card);
+ release_region(card->port, AVMB1_PORTLEN);
+ kfree(card->ctrlinfo);
+ kfree(card->dma);
+ kfree(card);
+ return -EBUSY;
+ }
+ card->cardnr = cinfo->capi_ctrl->cnr;
+
+ skb_queue_head_init(&card->dma->send_queue);
+
+ printk(KERN_INFO
+ "%s: AVM B1 PCI V4 at i/o %#x, irq %d, mem %#lx, revision %d (dma)\n",
+ driver->name, card->port, card->irq,
+ card->membase, card->revision);
+
+ MOD_INC_USE_COUNT;
+
+ return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+
+static struct capi_driver b1pciv4_driver = {
+ "b1pciv4",
+ "0.0",
+ b1dma_load_firmware,
+ b1dma_reset_ctr,
+ b1pciv4_remove_ctr,
+ b1dma_register_appl,
+ b1dma_release_appl,
+ b1dma_send_message,
+
+ b1pciv4_procinfo,
+ b1dmactl_read_proc,
+ 0, /* use standard driver_read_proc */
+
+ 0, /* no add_card function */
+};
+
+#endif /* CONFIG_ISDN_DRV_AVMB1_B1PCIV4 */
+
#ifdef MODULE
#define b1pci_init init_module
void cleanup_module(void);
static int ncards = 0;
+static int add_card(struct pci_dev *dev)
+{
+ struct capi_driver *driver = &b1pci_driver;
+ struct capicardparams param;
+ int retval;
+
+ if (dev->base_address[ 2] & PCI_BASE_ADDRESS_IO_MASK) { /* B1 PCI V4 */
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+ driver = &b1pciv4_driver;
+#endif
+ param.membase = dev->base_address[ 0] & PCI_BASE_ADDRESS_MEM_MASK;
+ param.port = dev->base_address[ 2] & PCI_BASE_ADDRESS_IO_MASK;
+ param.irq = dev->irq;
+ printk(KERN_INFO
+ "%s: PCI BIOS reports AVM-B1 V4 at i/o %#x, irq %d, mem %#x\n",
+ driver->name, param.port, param.irq, param.membase);
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+ retval = b1pciv4_add_card(driver, ¶m);
+#else
+ retval = b1pci_add_card(driver, ¶m);
+#endif
+ if (retval != 0) {
+ printk(KERN_ERR
+ "%s: no AVM-B1 V4 at i/o %#x, irq %d, mem %#x detected\n",
+ driver->name, param.port, param.irq, param.membase);
+ }
+ } else {
+ param.membase = 0;
+ param.port = dev->base_address[ 1] & PCI_BASE_ADDRESS_IO_MASK;
+ param.irq = dev->irq;
+ printk(KERN_INFO
+ "%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
+ driver->name, param.port, param.irq);
+ retval = b1pci_add_card(driver, ¶m);
+ if (retval != 0) {
+ printk(KERN_ERR
+ "%s: no AVM-B1 at i/o %#x, irq %d detected\n",
+ driver->name, param.port, param.irq);
+ }
+ }
+ return retval;
+}
+
int b1pci_init(void)
{
struct capi_driver *driver = &b1pci_driver;
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+ struct capi_driver *driverv4 = &b1pciv4_driver;
+#endif
struct pci_dev *dev = NULL;
char *p;
int retval;
return -EIO;
}
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+ printk(KERN_INFO "%s: revision %s\n", driverv4->name, driverv4->revision);
+
+ div4 = attach_capi_driver(driverv4);
+
+ if (!div4) {
+ detach_capi_driver(driver);
+ printk(KERN_ERR "%s: failed to attach capi_driver\n",
+ driverv4->name);
+ return -EIO;
+ }
+#endif
+
#ifdef CONFIG_PCI
if (!pci_present()) {
printk(KERN_ERR "%s: no PCI bus present\n", driver->name);
detach_capi_driver(driver);
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+ detach_capi_driver(driverv4);
+#endif
return -EIO;
}
while ((dev = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, dev))) {
- struct capicardparams param;
-
- param.port = dev->base_address[ 1] & PCI_BASE_ADDRESS_IO_MASK;
- param.irq = dev->irq;
- printk(KERN_INFO
- "%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
- driver->name, param.port, param.irq);
- retval = b1pci_add_card(driver, ¶m);
+ retval = add_card(dev);
if (retval != 0) {
- printk(KERN_ERR
- "%s: no AVM-B1 at i/o %#x, irq %d detected\n",
- driver->name, param.port, param.irq);
#ifdef MODULE
cleanup_module();
#endif
void cleanup_module(void)
{
detach_capi_driver(&b1pci_driver);
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+ detach_capi_driver(&b1pciv4_driver);
+#endif
}
#endif
/*
- * $Id: b1pcmcia.c,v 1.5 1999/11/05 16:38:01 calle Exp $
+ * $Id: b1pcmcia.c,v 1.7 2000/02/02 18:36:03 calle Exp $
*
* Module for AVM B1/M1/M2 PCMCIA-card.
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: b1pcmcia.c,v $
+ * Revision 1.7 2000/02/02 18:36:03 calle
+ * - Modules are now locked while init_module is running
+ * - fixed problem with memory mapping if address is not aligned
+ *
+ * Revision 1.6 2000/01/25 14:37:39 calle
+ * new message after successfull detection including card revision and
+ * used resources.
+ *
* Revision 1.5 1999/11/05 16:38:01 calle
* Cleanups before kernel 2.4:
* - Changed all messages to use card->name or driver->name instead of
#include "capilli.h"
#include "avmcard.h"
-static char *revision = "$Revision: 1.5 $";
+static char *revision = "$Revision: 1.7 $";
/* ------------------------------------------------------------- */
{
avmctrl_info *cinfo;
avmcard *card;
+ char *cardname;
int retval;
+ MOD_INC_USE_COUNT;
+
card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
if (!card) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
+ MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(card, 0, sizeof(avmcard));
if (!cinfo) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(cinfo, 0, sizeof(avmctrl_info));
driver->name, card->port, retval);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EIO;
}
b1_reset(card->port);
+ b1_getrevision(card);
retval = request_irq(card->irq, b1pcmcia_interrupt, 0, card->name, card);
if (retval) {
driver->name, card->irq);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EBUSY;
}
free_irq(card->irq, card);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EBUSY;
}
+ switch (cardtype) {
+ case avm_m1: cardname = "M1"; break;
+ case avm_m2: cardname = "M2"; break;
+ default : cardname = "B1 PCMCIA"; break;
+ }
+
+ printk(KERN_INFO
+ "%s: AVM %s at i/o %#x, irq %d, revision %d\n",
+ driver->name, cardname, card->port, card->irq, card->revision);
- MOD_INC_USE_COUNT;
return cinfo->capi_ctrl->cnr;
}
if (!cinfo)
return "";
- sprintf(cinfo->infobuf, "%s %s 0x%x %d",
+ sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d",
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->irq : 0,
+ cinfo->card ? cinfo->card->revision : 0
);
return cinfo->infobuf;
}
/*
- * $Id: c4.c,v 1.2 2000/01/21 20:52:58 keil Exp $
+ * $Id: c4.c,v 1.5 2000/03/16 15:21:03 calle Exp $
*
* Module for AVM C4 card.
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: c4.c,v $
+ * Revision 1.5 2000/03/16 15:21:03 calle
+ * Bugfix in c4_remove: loop 5 times instead of 4 :-(
+ *
+ * Revision 1.4 2000/02/02 18:36:03 calle
+ * - Modules are now locked while init_module is running
+ * - fixed problem with memory mapping if address is not aligned
+ *
+ * Revision 1.3 2000/01/25 14:37:39 calle
+ * new message after successfull detection including card revision and
+ * used resources.
+ *
* Revision 1.2 2000/01/21 20:52:58 keil
* pci_find_subsys as local function for 2.2.X kernel
*
#include "capilli.h"
#include "avmcard.h"
-static char *revision = "$Revision: 1.2 $";
+static char *revision = "$Revision: 1.5 $";
#undef CONFIG_C4_DEBUG
#undef CONFIG_C4_POLLDEBUG
c4_reset(card);
- for (i=0; i <= 4; i++) {
+ for (i=0; i < 4; i++) {
cinfo = &card->ctrlinfo[i];
if (cinfo->capi_ctrl)
di->detach_ctr(cinfo->capi_ctrl);
static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
{
- unsigned long page_offset, base;
+ unsigned long base, page_offset;
avmctrl_info *cinfo;
avmcard *card;
int retval;
int i;
+ MOD_INC_USE_COUNT;
+
card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
if (!card) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
+ MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(card, 0, sizeof(avmcard));
if (!card->dma) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(card->dma, 0, sizeof(avmcard_dmainfo));
kfree(card->ctrlinfo);
kfree(card->dma);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(cinfo, 0, sizeof(avmctrl_info)*4);
kfree(card->ctrlinfo);
kfree(card->dma);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EBUSY;
}
- base = card->membase & PAGE_MASK;
+ base = card->membase & PAGE_MASK;
page_offset = card->membase - base;
- card->mbase = ioremap_nocache(base, page_offset + 64);
+ card->mbase = ioremap_nocache(base, page_offset + 128);
+ if (card->mbase) {
+ card->mbase += page_offset;
+ } else {
+ printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
+ driver->name, card->membase);
+ kfree(card->ctrlinfo);
+ kfree(card->dma);
+ kfree(card);
+ MOD_DEC_USE_COUNT;
+ return -EIO;
+ }
if ((retval = c4_detect(card)) != 0) {
printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
kfree(card->ctrlinfo);
kfree(card->dma);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EIO;
}
c4_reset(card);
kfree(card->ctrlinfo);
kfree(card->dma);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EBUSY;
}
kfree(card->dma);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EBUSY;
}
if (i == 0)
skb_queue_head_init(&card->dma->send_queue);
- MOD_INC_USE_COUNT;
+ printk(KERN_INFO
+ "%s: AVM C4 at i/o %#x, irq %d, mem %#lx\n",
+ driver->name, card->port, card->irq, card->membase);
return 0;
}
/*
- * $Id: capi.c,v 1.22 1999/11/13 21:27:16 keil Exp $
+ * $Id: capi.c,v 1.23 2000/02/26 01:00:53 keil Exp $
*
* CAPI 2.0 Interface for Linux
*
* Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: capi.c,v $
+ * Revision 1.23 2000/02/26 01:00:53 keil
+ * changes from 2.3.47
+ *
* Revision 1.22 1999/11/13 21:27:16 keil
* remove KERNELVERSION
*
/*
- * $Id: kcapi.c,v 1.11 1999/11/23 13:29:29 calle Exp $
+ * $Id: kcapi.c,v 1.12 2000/01/28 16:45:39 calle Exp $
*
* Kernel CAPI 2.0 Module
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: kcapi.c,v $
+ * Revision 1.12 2000/01/28 16:45:39 calle
+ * new manufacturer command KCAPI_CMD_ADDCARD (generic addcard),
+ * will search named driver and call the add_card function if one exist.
+ *
* Revision 1.11 1999/11/23 13:29:29 calle
* Bugfix: incoming capi message were never traced.
*
#include <linux/b1lli.h>
#endif
-static char *revision = "$Revision: 1.11 $";
+static char *revision = "$Revision: 1.12 $";
/* ------------------------------------------------------------- */
static struct sk_buff_head recv_queue;
static struct capi_interface_user *capi_users = 0;
static struct capi_driver *drivers;
-#ifdef CONFIG_AVMB1_COMPAT
-static struct capi_driver *b1isa_driver;
-static struct capi_driver *t1isa_driver;
-#endif
static long notify_up_set = 0;
static long notify_down_set = 0;
driver->next = 0;
*pp = driver;
printk(KERN_NOTICE "kcapi: driver %s attached\n", driver->name);
-#ifdef CONFIG_AVMB1_COMPAT
- if (strcmp(driver->name, "b1isa") == 0 && driver->add_card)
- b1isa_driver = driver;
- if (strcmp(driver->name, "t1isa") == 0 && driver->add_card)
- t1isa_driver = driver;
-#endif
sprintf(driver->procfn, "capi/drivers/%s", driver->name);
driver->procent = create_proc_entry(driver->procfn, 0, 0);
if (driver->procent) {
for (pp = &drivers; *pp && *pp != driver; pp = &(*pp)->next) ;
if (*pp) {
*pp = (*pp)->next;
-#ifdef CONFIG_AVMB1_COMPAT
- if (driver == b1isa_driver) b1isa_driver = 0;
- if (driver == t1isa_driver) t1isa_driver = 0;
-#endif
printk(KERN_NOTICE "kcapi: driver %s detached\n", driver->name);
} else {
printk(KERN_ERR "kcapi: driver %s double detach ?\n", driver->name);
return CAPI_NOERROR;
}
+static struct capi_driver *find_driver(char *name)
+{
+ struct capi_driver *dp;
+ for (dp = drivers; dp; dp = dp->next)
+ if (strcmp(dp->name, name) == 0)
+ return dp;
+ return 0;
+}
+
#ifdef CONFIG_AVMB1_COMPAT
static int old_capi_manufacturer(unsigned int cmd, void *data)
{
cparams.cardnr = cdef.cardnr;
switch (cdef.cardtype) {
- case AVM_CARDTYPE_B1: driver = b1isa_driver; break;
- case AVM_CARDTYPE_T1: driver = t1isa_driver; break;
- default: driver = 0;
+ case AVM_CARDTYPE_B1:
+ driver = find_driver("b1isa");
+ break;
+ case AVM_CARDTYPE_T1:
+ driver = find_driver("t1isa");
+ break;
+ default:
+ driver = 0;
+ break;
}
if (!driver) {
printk(KERN_ERR "kcapi: driver not loaded.\n");
return -ESRCH;
gdef.cardstate = card->cardstate;
- if (card->driver == b1isa_driver)
- gdef.cardtype = AVM_CARDTYPE_B1;
- else if (card->driver == t1isa_driver)
+ if (card->driver == find_driver("t1isa"))
gdef.cardtype = AVM_CARDTYPE_T1;
else gdef.cardtype = AVM_CARDTYPE_B1;
static int capi_manufacturer(unsigned int cmd, void *data)
{
struct capi_ctr *card;
- kcapi_flagdef fdef;
int retval;
switch (cmd) {
return old_capi_manufacturer(cmd, data);
#endif
case KCAPI_CMD_TRACE:
+ {
+ kcapi_flagdef fdef;
+
if ((retval = copy_from_user((void *) &fdef, data,
sizeof(kcapi_flagdef))))
return retval;
card->cnr, card->traceflag);
return 0;
}
+
+ case KCAPI_CMD_ADDCARD:
+ {
+ struct capi_driver *driver;
+ capicardparams cparams;
+ kcapi_carddef cdef;
+
+ if ((retval = copy_from_user((void *) &cdef, data,
+ sizeof(cdef))))
+ return retval;
+
+ cparams.port = cdef.port;
+ cparams.irq = cdef.irq;
+ cparams.membase = cdef.membase;
+ cparams.cardnr = cdef.cardnr;
+ cparams.cardtype = 0;
+ cdef.driver[sizeof(cdef.driver)-1] = 0;
+
+ if ((driver = find_driver(cdef.driver)) == 0) {
+ printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n",
+ cdef.driver);
+ return -ESRCH;
+ }
+
+ if (!driver->add_card) {
+ printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver);
+ return -EIO;
+ }
+
+ return driver->add_card(driver, &cparams);
+ }
+
+ default:
+ printk(KERN_ERR "kcapi: manufacturer command %d unknown.\n",
+ cmd);
+ break;
+
+ }
return -EINVAL;
}
/*
- * $Id: t1isa.c,v 1.8 1999/11/05 16:38:01 calle Exp $
+ * $Id: t1isa.c,v 1.10 2000/02/02 18:36:04 calle Exp $
*
* Module for AVM T1 HEMA-card.
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: t1isa.c,v $
+ * Revision 1.10 2000/02/02 18:36:04 calle
+ * - Modules are now locked while init_module is running
+ * - fixed problem with memory mapping if address is not aligned
+ *
+ * Revision 1.9 2000/01/25 14:37:39 calle
+ * new message after successfull detection including card revision and
+ * used resources.
+ *
* Revision 1.8 1999/11/05 16:38:01 calle
* Cleanups before kernel 2.4:
* - Changed all messages to use card->name or driver->name instead of
#include "capilli.h"
#include "avmcard.h"
-static char *revision = "$Revision: 1.8 $";
+static char *revision = "$Revision: 1.10 $";
/* ------------------------------------------------------------- */
avmcard *card;
int retval;
+ MOD_INC_USE_COUNT;
+
card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
if (!card) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
+ MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(card, 0, sizeof(avmcard));
if (!cinfo) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(cinfo, 0, sizeof(avmctrl_info));
driver->name, card->port);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EINVAL;
}
driver->name, card->port, card->port + AVMB1_PORTLEN);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EBUSY;
}
if (hema_irq_table[card->irq & 0xf] == 0) {
driver->name, card->irq);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EINVAL;
}
for (ctrl = driver->controller; ctrl; ctrl = ctrl->next) {
driver->name, card->cardnr, cardp->port);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EBUSY;
}
}
driver->name, card->port, retval);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EIO;
}
t1_disable_irq(card->port);
release_region(card->port, AVMB1_PORTLEN);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EBUSY;
}
release_region(card->port, AVMB1_PORTLEN);
kfree(card->ctrlinfo);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EBUSY;
}
- MOD_INC_USE_COUNT;
+ printk(KERN_INFO
+ "%s: AVM T1 ISA at i/o %#x, irq %d, card %d\n",
+ driver->name, card->port, card->irq, card->cardnr);
+
return 0;
}
/*
- * $Id: t1pci.c,v 1.3 1999/11/13 21:27:16 keil Exp $
+ * $Id: t1pci.c,v 1.5 2000/02/02 18:36:04 calle Exp $
*
* Module for AVM T1 PCI-card.
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: t1pci.c,v $
+ * Revision 1.5 2000/02/02 18:36:04 calle
+ * - Modules are now locked while init_module is running
+ * - fixed problem with memory mapping if address is not aligned
+ *
+ * Revision 1.4 2000/01/25 14:33:38 calle
+ * - Added Support AVM B1 PCI V4.0 (tested with prototype)
+ * - splitted up t1pci.c into b1dma.c for common function with b1pciv4
+ * - support for revision register
+ *
* Revision 1.3 1999/11/13 21:27:16 keil
* remove KERNELVERSION
*
#include "capilli.h"
#include "avmcard.h"
-static char *revision = "$Revision: 1.3 $";
+static char *revision = "$Revision: 1.5 $";
#undef CONFIG_T1PCI_DEBUG
#undef CONFIG_T1PCI_POLLDEBUG
/* ------------------------------------------------------------- */
-static 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 t1pci_dispatch_tx(avmcard *card);
-
-/* ------------------------------------------------------------- */
-
-/* S5933 */
-
-#define AMCC_RXPTR 0x24
-#define AMCC_RXLEN 0x28
-#define AMCC_TXPTR 0x2c
-#define AMCC_TXLEN 0x30
-
-#define AMCC_INTCSR 0x38
-# define EN_READ_TC_INT 0x00008000L
-# define EN_WRITE_TC_INT 0x00004000L
-# define EN_TX_TC_INT EN_READ_TC_INT
-# define EN_RX_TC_INT EN_WRITE_TC_INT
-# define AVM_FLAG 0x30000000L
-
-# define ANY_S5933_INT 0x00800000L
-# define READ_TC_INT 0x00080000L
-# define WRITE_TC_INT 0x00040000L
-# define TX_TC_INT READ_TC_INT
-# define RX_TC_INT WRITE_TC_INT
-# define MASTER_ABORT_INT 0x00100000L
-# define TARGET_ABORT_INT 0x00200000L
-# define BUS_MASTER_INT 0x00200000L
-# define ALL_INT 0x000C0000L
-
-#define AMCC_MCSR 0x3c
-# define A2P_HI_PRIORITY 0x00000100L
-# define EN_A2P_TRANSFERS 0x00000400L
-# define P2A_HI_PRIORITY 0x00001000L
-# define EN_P2A_TRANSFERS 0x00004000L
-# define RESET_A2P_FLAGS 0x04000000L
-# define RESET_P2A_FLAGS 0x02000000L
-
-/* ------------------------------------------------------------- */
-
-#define t1outmeml(addr, value) writel(value, addr)
-#define t1inmeml(addr) readl(addr)
-#define t1outmemw(addr, value) writew(value, addr)
-#define t1inmemw(addr) readw(addr)
-#define t1outmemb(addr, value) writeb(value, addr)
-#define t1inmemb(addr) readb(addr)
-
-/* ------------------------------------------------------------- */
-
-static inline int t1pci_tx_empty(unsigned int port)
-{
- return inb(port + 0x03) & 0x1;
-}
-
-static inline int t1pci_rx_full(unsigned int port)
-{
- return inb(port + 0x02) & 0x1;
-}
-
-static int t1pci_tolink(avmcard *card, void *buf, unsigned int len)
-{
- unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */
- unsigned char *s = (unsigned char *)buf;
- while (len--) {
- while ( !t1pci_tx_empty(card->port)
- && time_before(jiffies, stop));
- if (!t1pci_tx_empty(card->port))
- return -1;
- t1outp(card->port, 0x01, *s++);
- }
- return 0;
-}
-
-static int t1pci_fromlink(avmcard *card, void *buf, unsigned int len)
-{
- unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */
- unsigned char *s = (unsigned char *)buf;
- while (len--) {
- while ( !t1pci_rx_full(card->port)
- && time_before(jiffies, stop));
- if (!t1pci_rx_full(card->port))
- return -1;
- *s++ = t1inp(card->port, 0x00);
- }
- return 0;
-}
-
-static int WriteReg(avmcard *card, __u32 reg, __u8 val)
-{
- __u8 cmd = 0x00;
- if ( t1pci_tolink(card, &cmd, 1) == 0
- && t1pci_tolink(card, ®, 4) == 0) {
- __u32 tmp = val;
- return t1pci_tolink(card, &tmp, 4);
- }
- return -1;
-}
-
-static __u8 ReadReg(avmcard *card, __u32 reg)
-{
- __u8 cmd = 0x01;
- if ( t1pci_tolink(card, &cmd, 1) == 0
- && t1pci_tolink(card, ®, 4) == 0) {
- __u32 tmp;
- if (t1pci_fromlink(card, &tmp, 4) == 0)
- return (__u8)tmp;
- }
- return 0xff;
-}
-
-/* ------------------------------------------------------------- */
-
-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 t1pci_reset(avmcard *card)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
- card->csr = 0x0;
- t1outmeml(card->mbase+AMCC_INTCSR, card->csr);
- t1outmeml(card->mbase+AMCC_MCSR, 0);
- t1outmeml(card->mbase+AMCC_RXLEN, 0);
- t1outmeml(card->mbase+AMCC_TXLEN, 0);
-
- t1outp(card->port, T1_RESETLINK, 0x00);
- t1outp(card->port, 0x07, 0x00);
-
- restore_flags(flags);
-
- t1outmeml(card->mbase+AMCC_MCSR, 0);
- udelay(10 * 1000);
- t1outmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */
- udelay(10 * 1000);
- t1outmeml(card->mbase+AMCC_MCSR, 0);
- udelay(42 * 1000);
-
-}
-
-/* ------------------------------------------------------------- */
-
-static int t1pci_detect(avmcard *card)
-{
- t1outmeml(card->mbase+AMCC_MCSR, 0);
- udelay(10 * 1000);
- t1outmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */
- udelay(10 * 1000);
- t1outmeml(card->mbase+AMCC_MCSR, 0);
- udelay(42 * 1000);
-
- t1outmeml(card->mbase+AMCC_RXLEN, 0);
- t1outmeml(card->mbase+AMCC_TXLEN, 0);
- card->csr = 0x0;
- t1outmeml(card->mbase+AMCC_INTCSR, card->csr);
-
- if (t1inmeml(card->mbase+AMCC_MCSR) != 0x000000E6)
- return 1;
-
- t1outmeml(card->mbase+AMCC_RXPTR, 0xffffffff);
- t1outmeml(card->mbase+AMCC_TXPTR, 0xffffffff);
- if ( t1inmeml(card->mbase+AMCC_RXPTR) != 0xfffffffc
- || t1inmeml(card->mbase+AMCC_TXPTR) != 0xfffffffc)
- return 2;
-
- t1outmeml(card->mbase+AMCC_RXPTR, 0x0);
- t1outmeml(card->mbase+AMCC_TXPTR, 0x0);
- if ( t1inmeml(card->mbase+AMCC_RXPTR) != 0x0
- || t1inmeml(card->mbase+AMCC_TXPTR) != 0x0)
- return 3;
-
- t1outp(card->port, T1_RESETLINK, 0x00);
- t1outp(card->port, 0x07, 0x00);
-
- t1outp(card->port, 0x02, 0x02);
- t1outp(card->port, 0x03, 0x02);
-
- if ( (t1inp(card->port, 0x02) & 0xFE) != 0x02
- || t1inp(card->port, 0x3) != 0x03)
- return 4;
-
- t1outp(card->port, 0x02, 0x00);
- t1outp(card->port, 0x03, 0x00);
-
- if ( (t1inp(card->port, 0x02) & 0xFE) != 0x00
- || t1inp(card->port, 0x3) != 0x01)
- return 5;
-
- /* Transputer test */
-
- if ( WriteReg(card, 0x80001000, 0x11) != 0
- || WriteReg(card, 0x80101000, 0x22) != 0
- || WriteReg(card, 0x80201000, 0x33) != 0
- || WriteReg(card, 0x80301000, 0x44) != 0)
- return 6;
-
- if ( ReadReg(card, 0x80001000) != 0x11
- || ReadReg(card, 0x80101000) != 0x22
- || ReadReg(card, 0x80201000) != 0x33
- || ReadReg(card, 0x80301000) != 0x44)
- return 7;
-
- if ( WriteReg(card, 0x80001000, 0x55) != 0
- || WriteReg(card, 0x80101000, 0x66) != 0
- || WriteReg(card, 0x80201000, 0x77) != 0
- || WriteReg(card, 0x80301000, 0x88) != 0)
- return 8;
-
- if ( ReadReg(card, 0x80001000) != 0x55
- || ReadReg(card, 0x80101000) != 0x66
- || ReadReg(card, 0x80201000) != 0x77
- || ReadReg(card, 0x80301000) != 0x88)
- return 9;
-
- return 0;
-}
-
-/* ------------------------------------------------------------- */
-
-static void t1pci_dispatch_tx(avmcard *card)
-{
- avmcard_dmainfo *dma = card->dma;
- unsigned long flags;
- struct sk_buff *skb;
- __u8 cmd, subcmd;
- __u16 len;
- __u32 txlen;
- int inint;
- void *p;
-
- save_flags(flags);
- cli();
-
- inint = card->interrupt;
-
- if (card->csr & EN_TX_TC_INT) { /* tx busy */
- restore_flags(flags);
- return;
- }
-
- skb = skb_dequeue(&dma->send_queue);
- if (!skb) {
-#ifdef CONFIG_T1PCI_DEBUG
- printk(KERN_DEBUG "tx(%d): underrun\n", inint);
-#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_T1PCI_DEBUG
- printk(KERN_DEBUG "tx(%d): put msg len=%d\n",
- inint, txlen);
-#endif
- } else {
- txlen = skb->len-2;
-#ifdef CONFIG_T1PCI_POLLDEBUG
- if (skb->data[2] == SEND_POLLACK)
- printk(KERN_INFO "%s: ack to t1\n", card->name);
-#endif
-#ifdef CONFIG_T1PCI_DEBUG
- printk(KERN_DEBUG "tx(%d): put 0x%x len=%d\n",
- inint, skb->data[2], txlen);
-#endif
- memcpy(dma->sendbuf, skb->data+2, skb->len-2);
- }
- txlen = (txlen + 3) & ~3;
-
- t1outmeml(card->mbase+AMCC_TXPTR, virt_to_phys(dma->sendbuf));
- t1outmeml(card->mbase+AMCC_TXLEN, txlen);
-
- card->csr |= EN_TX_TC_INT;
-
- if (!inint)
- t1outmeml(card->mbase+AMCC_INTCSR, card->csr);
-
- 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);
- t1pci_dispatch_tx(card);
-}
-
-/* ------------------------------------------------------------- */
-
-static void t1pci_handle_rx(avmcard *card)
-{
- avmctrl_info *cinfo = &card->ctrlinfo[0];
- avmcard_dmainfo *dma = card->dma;
- struct capi_ctr *ctrl = cinfo->capi_ctrl;
- struct sk_buff *skb;
- void *p = dma->recvbuf+4;
- __u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize;
- __u8 b1cmd = _get_byte(&p);
-
-#ifdef CONFIG_T1PCI_DEBUG
- printk(KERN_DEBUG "rx: 0x%x %lu\n", 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);
-
- 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);
- 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);
-
- ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
-
- break;
-
- case RECEIVE_FREE_NCCI:
-
- ApplId = _get_word(&p);
- NCCI = _get_word(&p);
-
- if (NCCI != 0xffffffff)
- ctrl->free_ncci(ctrl, ApplId, NCCI);
- else ctrl->appl_released(ctrl, ApplId);
- break;
-
- case RECEIVE_START:
-#ifdef CONFIG_T1PCI_POLLDEBUG
- printk(KERN_INFO "%s: poll from t1\n", card->name);
-#endif
- if (!suppress_pollack)
- queue_pollack(card);
- ctrl->resume_output(ctrl);
- break;
-
- case RECEIVE_STOP:
- ctrl->suspend_output(ctrl);
- break;
-
- case RECEIVE_INIT:
-
- 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(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: t1pci_interrupt: 0x%x ???\n",
- card->name, b1cmd);
- return;
- }
-}
-
-/* ------------------------------------------------------------- */
-
-static void t1pci_handle_interrupt(avmcard *card)
-{
- __u32 status = t1inmeml(card->mbase+AMCC_INTCSR);
- __u32 newcsr;
-
- if ((status & ANY_S5933_INT) == 0)
- return;
-
- newcsr = card->csr | (status & ALL_INT);
- if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT;
- if (status & RX_TC_INT) newcsr &= ~EN_RX_TC_INT;
- t1outmeml(card->mbase+AMCC_INTCSR, newcsr);
-
- if ((status & RX_TC_INT) != 0) {
- __u8 *recvbuf = card->dma->recvbuf;
- __u32 rxlen;
- if (card->dma->recvlen == 0) {
- card->dma->recvlen = *((__u32 *)recvbuf);
- rxlen = (card->dma->recvlen + 3) & ~3;
- t1outmeml(card->mbase+AMCC_RXPTR,
- virt_to_phys(recvbuf+4));
- t1outmeml(card->mbase+AMCC_RXLEN, rxlen);
- } else {
- t1pci_handle_rx(card);
- card->dma->recvlen = 0;
- t1outmeml(card->mbase+AMCC_RXPTR, virt_to_phys(recvbuf));
- t1outmeml(card->mbase+AMCC_RXLEN, 4);
- }
- }
-
- if ((status & TX_TC_INT) != 0) {
- card->csr &= ~EN_TX_TC_INT;
- t1pci_dispatch_tx(card);
- } else if (card->csr & EN_TX_TC_INT) {
- if (t1inmeml(card->mbase+AMCC_TXLEN) == 0) {
- card->csr &= ~EN_TX_TC_INT;
- t1pci_dispatch_tx(card);
- }
- }
- t1outmeml(card->mbase+AMCC_INTCSR, card->csr);
-}
-
-static void t1pci_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
-{
- avmcard *card;
-
- card = (avmcard *) devptr;
-
- if (!card) {
- printk(KERN_WARNING "t1pci: interrupt: wrong device\n");
- return;
- }
- if (card->interrupt) {
- printk(KERN_ERR "%s: reentering interrupt hander\n", card->name);
- return;
- }
-
- card->interrupt = 1;
-
- t1pci_handle_interrupt(card);
-
- card->interrupt = 0;
-}
-
-/* ------------------------------------------------------------- */
-
-static int t1pci_loaded(avmcard *card)
-{
- unsigned long stop;
- unsigned char ans;
- unsigned long tout = 2;
- unsigned int base = card->port;
-
- for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
- if (b1_tx_empty(base))
- break;
- }
- if (!b1_tx_empty(base)) {
- printk(KERN_ERR "%s: t1pci_loaded: tx err, corrupted t4 file ?\n",
- card->name);
- return 0;
- }
- b1_put_byte(base, SEND_POLLACK);
- for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
- if (b1_rx_full(base)) {
- if ((ans = b1_get_byte(base)) == RECEIVE_POLLDWORD) {
- return 1;
- }
- printk(KERN_ERR "%s: t1pci_loaded: got 0x%x, firmware not running in dword mode\n", card->name, ans);
- return 0;
- }
- }
- printk(KERN_ERR "%s: t1pci_loaded: firmware not running\n", card->name);
- return 0;
-}
-
-/* ------------------------------------------------------------- */
-
-static void t1pci_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);
- t1pci_dispatch_tx(card);
-}
-
-static int t1pci_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
-{
- avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
- avmcard *card = cinfo->card;
- unsigned long flags;
- int retval;
-
- t1pci_reset(card);
-
- if ((retval = b1_load_t4file(card, &data->firmware))) {
- t1pci_reset(card);
- printk(KERN_ERR "%s: failed to load t4file!!\n",
- card->name);
- return retval;
- }
-
- if (data->configuration.len > 0 && data->configuration.data) {
- if ((retval = b1_load_config(card, &data->configuration))) {
- t1pci_reset(card);
- printk(KERN_ERR "%s: failed to load config!!\n",
- card->name);
- return retval;
- }
- }
-
- if (!t1pci_loaded(card)) {
- t1pci_reset(card);
- printk(KERN_ERR "%s: failed to load t4file.\n", card->name);
- return -EIO;
- }
-
- save_flags(flags);
- cli();
-
- card->csr = AVM_FLAG;
- t1outmeml(card->mbase+AMCC_INTCSR, card->csr);
- t1outmeml(card->mbase+AMCC_MCSR,
- EN_A2P_TRANSFERS|EN_P2A_TRANSFERS
- |A2P_HI_PRIORITY|P2A_HI_PRIORITY
- |RESET_A2P_FLAGS|RESET_P2A_FLAGS);
- t1outp(card->port, 0x07, 0x30);
- t1outp(card->port, 0x10, 0xF0);
-
- card->dma->recvlen = 0;
- t1outmeml(card->mbase+AMCC_RXPTR, virt_to_phys(card->dma->recvbuf));
- t1outmeml(card->mbase+AMCC_RXLEN, 4);
- card->csr |= EN_RX_TC_INT;
- t1outmeml(card->mbase+AMCC_INTCSR, card->csr);
- restore_flags(flags);
-
- t1pci_send_init(card);
-
- return 0;
-}
-
-void t1pci_reset_ctr(struct capi_ctr *ctrl)
-{
- avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
- avmcard *card = cinfo->card;
-
- t1pci_reset(card);
-
- memset(cinfo->version, 0, sizeof(cinfo->version));
- ctrl->reseted(ctrl);
-}
-
static void t1pci_remove_ctr(struct capi_ctr *ctrl)
{
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
avmcard *card = cinfo->card;
- t1pci_reset(card);
+ b1dma_reset(card);
di->detach_ctr(ctrl);
free_irq(card->irq, card);
/* ------------------------------------------------------------- */
-
-void t1pci_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 (want > 0) nconn = want;
- else nconn = ctrl->profile.nbchannel * -want;
- if (nconn == 0) nconn = ctrl->profile.nbchannel;
-
- 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);
- t1pci_dispatch_tx(card);
-
- ctrl->appl_registered(ctrl, appl);
-}
-
-/* ------------------------------------------------------------- */
-
-void t1pci_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;
-
- 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);
- t1pci_dispatch_tx(card);
-}
-
-/* ------------------------------------------------------------- */
-
-
-static void t1pci_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);
- t1pci_dispatch_tx(card);
-}
-
-/* ------------------------------------------------------------- */
-
-static char *t1pci_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 t1pci_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;
- unsigned long flags;
- __u8 flag;
- int len = 0;
- char *s;
- __u32 txaddr, txlen, rxaddr, rxlen, csr;
-
- 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);
-
- save_flags(flags);
- cli();
-
- txaddr = (__u32)phys_to_virt(t1inmeml(card->mbase+0x2c));
- txaddr -= (__u32)card->dma->sendbuf;
- txlen = t1inmeml(card->mbase+0x30);
-
- rxaddr = (__u32)phys_to_virt(t1inmeml(card->mbase+0x24));
- rxaddr -= (__u32)card->dma->recvbuf;
- rxlen = t1inmeml(card->mbase+0x28);
-
- csr = t1inmeml(card->mbase+AMCC_INTCSR);
-
- restore_flags(flags);
-
- len += sprintf(page+len, "%-16s 0x%lx\n",
- "csr (cached)", (unsigned long)card->csr);
- len += sprintf(page+len, "%-16s 0x%lx\n",
- "csr", (unsigned long)csr);
- len += sprintf(page+len, "%-16s %lu\n",
- "txoff", (unsigned long)txaddr);
- len += sprintf(page+len, "%-16s %lu\n",
- "txlen", (unsigned long)txlen);
- len += sprintf(page+len, "%-16s %lu\n",
- "rxoff", (unsigned long)rxaddr);
- len += sprintf(page+len, "%-16s %lu\n",
- "rxlen", (unsigned long)rxlen);
-
- if (off+count >= len)
- *eof = 1;
- if (len < off)
- return 0;
- *start = page + off;
- return ((count < len-off) ? count : len-off);
-}
-
-/* ------------------------------------------------------------- */
-
static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
{
- unsigned long page_offset, base;
+ unsigned long base, page_offset;
avmcard *card;
avmctrl_info *cinfo;
int retval;
+ MOD_INC_USE_COUNT;
+
card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
if (!card) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
+ MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(card, 0, sizeof(avmcard));
if (!card->dma) {
printk(KERN_WARNING "%s: no memory.\n", driver->name);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(card->dma, 0, sizeof(avmcard_dmainfo));
printk(KERN_WARNING "%s: no memory.\n", driver->name);
kfree(card->dma);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(cinfo, 0, sizeof(avmctrl_info));
kfree(card->ctrlinfo);
kfree(card->dma);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EBUSY;
}
- base = card->membase & PAGE_MASK;
+ base = card->membase & PAGE_MASK;
page_offset = card->membase - base;
card->mbase = ioremap_nocache(base, page_offset + 64);
+ if (card->mbase) {
+ card->mbase += page_offset;
+ } else {
+ printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
+ driver->name, card->membase);
+ kfree(card->ctrlinfo);
+ kfree(card->dma);
+ kfree(card);
+ MOD_DEC_USE_COUNT;
+ return -EIO;
+ }
- t1pci_reset(card);
+ b1dma_reset(card);
if ((retval = t1pci_detect(card)) != 0) {
printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
kfree(card->ctrlinfo);
kfree(card->dma);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EIO;
}
- t1pci_reset(card);
+ b1dma_reset(card);
request_region(p->port, AVMB1_PORTLEN, card->name);
- retval = request_irq(card->irq, t1pci_interrupt, SA_SHIRQ, card->name, card);
+ retval = request_irq(card->irq, b1dma_interrupt, SA_SHIRQ, card->name, card);
if (retval) {
printk(KERN_ERR "%s: unable to get IRQ %d.\n",
driver->name, card->irq);
kfree(card->ctrlinfo);
kfree(card->dma);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EBUSY;
}
kfree(card->ctrlinfo);
kfree(card->dma);
kfree(card);
+ MOD_DEC_USE_COUNT;
return -EBUSY;
}
card->cardnr = cinfo->capi_ctrl->cnr;
skb_queue_head_init(&card->dma->send_queue);
- MOD_INC_USE_COUNT;
+ printk(KERN_INFO
+ "%s: AVM T1 PCI at i/o %#x, irq %d, mem %#lx\n",
+ driver->name, card->port, card->irq, card->membase);
return 0;
}
/* ------------------------------------------------------------- */
+static char *t1pci_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 struct capi_driver t1pci_driver = {
"t1pci",
"0.0",
- t1pci_load_firmware,
- t1pci_reset_ctr,
+ b1dma_load_firmware,
+ b1dma_reset_ctr,
t1pci_remove_ctr,
- t1pci_register_appl,
- t1pci_release_appl,
- t1pci_send_message,
+ b1dma_register_appl,
+ b1dma_release_appl,
+ b1dma_send_message,
t1pci_procinfo,
- t1pci_read_proc,
+ b1dmactl_read_proc,
0, /* use standard driver_read_proc */
0, /* no add_card function */
-/*
- * $Id: divert_procfs.c,v 1.5 1999/09/14 20:31:01 werner Exp $
+/*
+ * $Id: divert_procfs.c,v 1.6 2000/02/14 19:23:03 werner Exp $
*
* Filesystem handling for the diversion supplementary services.
*
* Copyright 1998 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)
*
* 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.
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: divert_procfs.c,v $
+ * Revision 1.6 2000/02/14 19:23:03 werner
+ *
+ * Changed handling of proc filesystem tables to a more portable version
+ *
* Revision 1.5 1999/09/14 20:31:01 werner
*
* Removed obsoleted functions for proc fs and synced with new ones.
#include <linux/version.h>
#include <linux/poll.h>
#ifdef CONFIG_PROC_FS
- #include <linux/proc_fs.h>
+#include <linux/proc_fs.h>
#else
- #include <linux/fs.h>
+#include <linux/fs.h>
#endif
#include <linux/isdnif.h>
#include "isdn_divert.h"
/*********************************/
/* Variables for interface queue */
/*********************************/
-ulong if_used = 0; /* number of interface users */
-static struct divert_info *divert_info_head = NULL; /* head of queue */
-static struct divert_info *divert_info_tail = NULL; /* pointer to last entry */
-static struct wait_queue *rd_queue = 0; /* Queue IO */
+ulong if_used = 0; /* number of interface users */
+static struct divert_info *divert_info_head = NULL; /* head of queue */
+static struct divert_info *divert_info_tail = NULL; /* pointer to last entry */
+static struct wait_queue *rd_queue = 0; /* Queue IO */
/*********************************/
/* put an info buffer into queue */
/*********************************/
-void put_info_buffer(char *cp)
-{ struct divert_info *ib;
- int flags;
-
- if (if_used <= 0) return;
- if (!cp) return;
- if (!*cp) return;
- if (!(ib = (struct divert_info *) kmalloc(sizeof(struct divert_info)+strlen(cp), GFP_ATOMIC))) return; /* no memory */
- strcpy(ib->info_start,cp); /* set output string */
- ib->next = NULL;
- save_flags(flags);
- cli();
- ib->usage_cnt = if_used;
- if (!divert_info_head)
- divert_info_head = ib; /* new head */
- else
- divert_info_tail->next = ib; /* follows existing messages */
- divert_info_tail = ib; /* new tail */
- restore_flags(flags);
-
- /* delete old entrys */
- while (divert_info_head->next)
- { if ((divert_info_head->usage_cnt <= 0) &&
- (divert_info_head->next->usage_cnt <= 0))
- { ib = divert_info_head;
- divert_info_head = divert_info_head->next;
- kfree(ib);
- }
- else break;
- } /* divert_info_head->next */
- wake_up_interruptible(&(rd_queue));
-} /* put_info_buffer */
+void
+put_info_buffer(char *cp)
+{
+ struct divert_info *ib;
+ int flags;
+
+ if (if_used <= 0)
+ return;
+ if (!cp)
+ return;
+ if (!*cp)
+ return;
+ if (!(ib = (struct divert_info *) kmalloc(sizeof(struct divert_info) + strlen(cp), GFP_ATOMIC)))
+ return; /* no memory */
+ strcpy(ib->info_start, cp); /* set output string */
+ ib->next = NULL;
+ save_flags(flags);
+ cli();
+ ib->usage_cnt = if_used;
+ if (!divert_info_head)
+ divert_info_head = ib; /* new head */
+ else
+ divert_info_tail->next = ib; /* follows existing messages */
+ divert_info_tail = ib; /* new tail */
+ restore_flags(flags);
+
+ /* delete old entrys */
+ while (divert_info_head->next) {
+ if ((divert_info_head->usage_cnt <= 0) &&
+ (divert_info_head->next->usage_cnt <= 0)) {
+ ib = divert_info_head;
+ divert_info_head = divert_info_head->next;
+ kfree(ib);
+ } else
+ break;
+ } /* divert_info_head->next */
+ wake_up_interruptible(&(rd_queue));
+} /* put_info_buffer */
/**********************************/
/* deflection device read routine */
/**********************************/
-static ssize_t isdn_divert_read(struct file *file, char *buf, size_t count, loff_t *off)
-{ struct divert_info *inf;
- int len;
-
- if (!*((struct divert_info **)file->private_data))
- { if (file->f_flags & O_NONBLOCK)
- return -EAGAIN;
- interruptible_sleep_on(&(rd_queue));
- }
- if (!(inf = *((struct divert_info **)file->private_data))) return(0);
-
- inf->usage_cnt--; /* new usage count */
- (struct divert_info **)file->private_data = &inf->next; /* next structure */
- if ((len = strlen(inf->info_start)) <= count)
- { if (copy_to_user(buf, inf->info_start, len))
- return -EFAULT;
- file->f_pos += len;
- return(len);
- }
- return(0);
-} /* isdn_divert_read */
+static ssize_t
+isdn_divert_read(struct file *file, char *buf, size_t count, loff_t * off)
+{
+ struct divert_info *inf;
+ int len;
+
+ if (!*((struct divert_info **) file->private_data)) {
+ if (file->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+ interruptible_sleep_on(&(rd_queue));
+ }
+ if (!(inf = *((struct divert_info **) file->private_data)))
+ return (0);
+
+ inf->usage_cnt--; /* new usage count */
+ (struct divert_info **) file->private_data = &inf->next; /* next structure */
+ if ((len = strlen(inf->info_start)) <= count) {
+ if (copy_to_user(buf, inf->info_start, len))
+ return -EFAULT;
+ file->f_pos += len;
+ return (len);
+ }
+ return (0);
+} /* isdn_divert_read */
/**********************************/
/* deflection device write routine */
/**********************************/
-static ssize_t isdn_divert_write(struct file *file, const char *buf, size_t count, loff_t *off)
+static ssize_t
+isdn_divert_write(struct file *file, const char *buf, size_t count, loff_t * off)
{
- return(-ENODEV);
-} /* isdn_divert_write */
+ return (-ENODEV);
+} /* isdn_divert_write */
/***************************************/
/* select routines for various kernels */
/***************************************/
-static unsigned int isdn_divert_poll(struct file *file, poll_table * wait)
-{ unsigned int mask = 0;
+static unsigned int
+isdn_divert_poll(struct file *file, poll_table * wait)
+{
+ unsigned int mask = 0;
- poll_wait(file, &(rd_queue), wait);
- /* mask = POLLOUT | POLLWRNORM; */
- if (*((struct divert_info **)file->private_data))
- { mask |= POLLIN | POLLRDNORM;
- }
- return mask;
-} /* isdn_divert_poll */
+ poll_wait(file, &(rd_queue), wait);
+ /* mask = POLLOUT | POLLWRNORM; */
+ if (*((struct divert_info **) file->private_data)) {
+ mask |= POLLIN | POLLRDNORM;
+ }
+ return mask;
+} /* isdn_divert_poll */
/****************/
/* Open routine */
/****************/
-static int isdn_divert_open(struct inode *ino, struct file *filep)
-{ int flags;
-
- MOD_INC_USE_COUNT;
- save_flags(flags);
- cli();
- if_used++;
- if (divert_info_head)
- (struct divert_info **)filep->private_data = &(divert_info_tail->next);
- else
- (struct divert_info **)filep->private_data = &divert_info_head;
- restore_flags(flags);
- /* start_divert(); */
- return(0);
-} /* isdn_divert_open */
+static int
+isdn_divert_open(struct inode *ino, struct file *filep)
+{
+ int flags;
+
+ MOD_INC_USE_COUNT;
+ save_flags(flags);
+ cli();
+ if_used++;
+ if (divert_info_head)
+ (struct divert_info **) filep->private_data = &(divert_info_tail->next);
+ else
+ (struct divert_info **) filep->private_data = &divert_info_head;
+ restore_flags(flags);
+ /* start_divert(); */
+ return (0);
+} /* isdn_divert_open */
/*******************/
/* close routine */
/*******************/
-static int isdn_divert_close(struct inode *ino, struct file *filep)
-{ struct divert_info *inf;
- int flags;
-
- save_flags(flags);
- cli();
- if_used--;
- inf = *((struct divert_info **)filep->private_data);
- while (inf)
- { inf->usage_cnt--;
- inf = inf->next;
- }
- restore_flags(flags);
- if (if_used <= 0)
- while (divert_info_head)
- { inf = divert_info_head;
- divert_info_head = divert_info_head->next;
- kfree(inf);
- }
- MOD_DEC_USE_COUNT;
- return(0);
-} /* isdn_divert_close */
+static int
+isdn_divert_close(struct inode *ino, struct file *filep)
+{
+ struct divert_info *inf;
+ int flags;
+
+ save_flags(flags);
+ cli();
+ if_used--;
+ inf = *((struct divert_info **) filep->private_data);
+ while (inf) {
+ inf->usage_cnt--;
+ inf = inf->next;
+ }
+ restore_flags(flags);
+ if (if_used <= 0)
+ while (divert_info_head) {
+ inf = divert_info_head;
+ divert_info_head = divert_info_head->next;
+ kfree(inf);
+ }
+ MOD_DEC_USE_COUNT;
+ return (0);
+} /* isdn_divert_close */
/*********/
/* IOCTL */
/*********/
-static int isdn_divert_ioctl(struct inode *inode, struct file *file,
- uint cmd, ulong arg)
-{ divert_ioctl dioctl;
- int i, flags;
- divert_rule *rulep;
- char *cp;
-
- if ((i = copy_from_user(&dioctl,(char *) arg, sizeof(dioctl))))
- return(i);
-
- switch (cmd)
- {
- case IIOCGETVER:
- dioctl.drv_version = DIVERT_IIOC_VERSION ; /* set version */
- break;
-
- case IIOCGETDRV:
- if ((dioctl.getid.drvid = divert_if.name_to_drv(dioctl.getid.drvnam)) < 0)
- return(-EINVAL);
- break;
-
- case IIOCGETNAM:
- cp = divert_if.drv_to_name(dioctl.getid.drvid);
- if (!cp) return(-EINVAL);
- if (!*cp) return(-EINVAL);
- strcpy(dioctl.getid.drvnam,cp);
- break;
-
- case IIOCGETRULE:
- if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
- return(-EINVAL);
- dioctl.getsetrule.rule = *rulep; /* copy data */
- break;
-
- case IIOCMODRULE:
- if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
- return(-EINVAL);
- save_flags(flags);
- cli();
- *rulep = dioctl.getsetrule.rule; /* copy data */
- restore_flags(flags);
- return(0); /* no copy required */
- break;
-
- case IIOCINSRULE:
- return(insertrule(dioctl.getsetrule.ruleidx,&dioctl.getsetrule.rule));
- break;
-
- case IIOCDELRULE:
- return(deleterule(dioctl.getsetrule.ruleidx));
- break;
-
- case IIOCDODFACT:
- return(deflect_extern_action(dioctl.fwd_ctrl.subcmd,
- dioctl.fwd_ctrl.callid,
- dioctl.fwd_ctrl.to_nr));
-
- case IIOCDOCFACT:
- case IIOCDOCFDIS:
- case IIOCDOCFINT:
- if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid))
- return(-EINVAL); /* invalid driver */
- if ((i = cf_command(dioctl.cf_ctrl.drvid,
- (cmd == IIOCDOCFACT) ? 1: (cmd == IIOCDOCFDIS) ? 0:2,
- dioctl.cf_ctrl.cfproc,
- dioctl.cf_ctrl.msn,
- dioctl.cf_ctrl.service,
- dioctl.cf_ctrl.fwd_nr,
- &dioctl.cf_ctrl.procid)))
- return(i);
- break;
-
- default:
- return(-EINVAL);
- } /* switch cmd */
- return(copy_to_user((char *) arg, &dioctl, sizeof(dioctl))); /* success */
-} /* isdn_divert_ioctl */
+static int
+isdn_divert_ioctl(struct inode *inode, struct file *file,
+ uint cmd, ulong arg)
+{
+ divert_ioctl dioctl;
+ int i, flags;
+ divert_rule *rulep;
+ char *cp;
+
+ if ((i = copy_from_user(&dioctl, (char *) arg, sizeof(dioctl))))
+ return (i);
+
+ switch (cmd) {
+ case IIOCGETVER:
+ dioctl.drv_version = DIVERT_IIOC_VERSION; /* set version */
+ break;
+
+ case IIOCGETDRV:
+ if ((dioctl.getid.drvid = divert_if.name_to_drv(dioctl.getid.drvnam)) < 0)
+ return (-EINVAL);
+ break;
+
+ case IIOCGETNAM:
+ cp = divert_if.drv_to_name(dioctl.getid.drvid);
+ if (!cp)
+ return (-EINVAL);
+ if (!*cp)
+ return (-EINVAL);
+ strcpy(dioctl.getid.drvnam, cp);
+ break;
+
+ case IIOCGETRULE:
+ if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
+ return (-EINVAL);
+ dioctl.getsetrule.rule = *rulep; /* copy data */
+ break;
+
+ case IIOCMODRULE:
+ if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
+ return (-EINVAL);
+ save_flags(flags);
+ cli();
+ *rulep = dioctl.getsetrule.rule; /* copy data */
+ restore_flags(flags);
+ return (0); /* no copy required */
+ break;
+
+ case IIOCINSRULE:
+ return (insertrule(dioctl.getsetrule.ruleidx, &dioctl.getsetrule.rule));
+ break;
+
+ case IIOCDELRULE:
+ return (deleterule(dioctl.getsetrule.ruleidx));
+ break;
+
+ case IIOCDODFACT:
+ return (deflect_extern_action(dioctl.fwd_ctrl.subcmd,
+ dioctl.fwd_ctrl.callid,
+ dioctl.fwd_ctrl.to_nr));
+
+ case IIOCDOCFACT:
+ case IIOCDOCFDIS:
+ case IIOCDOCFINT:
+ if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid))
+ return (-EINVAL); /* invalid driver */
+ if ((i = cf_command(dioctl.cf_ctrl.drvid,
+ (cmd == IIOCDOCFACT) ? 1 : (cmd == IIOCDOCFDIS) ? 0 : 2,
+ dioctl.cf_ctrl.cfproc,
+ dioctl.cf_ctrl.msn,
+ dioctl.cf_ctrl.service,
+ dioctl.cf_ctrl.fwd_nr,
+ &dioctl.cf_ctrl.procid)))
+ return (i);
+ break;
+
+ default:
+ return (-EINVAL);
+ } /* switch cmd */
+ return (copy_to_user((char *) arg, &dioctl, sizeof(dioctl))); /* success */
+} /* isdn_divert_ioctl */
#ifdef CONFIG_PROC_FS
isdn_divert_lseek,
isdn_divert_read,
isdn_divert_write,
- NULL, /* isdn_readdir */
- isdn_divert_poll, /* isdn_poll */
- isdn_divert_ioctl, /* isdn_ioctl */
- NULL, /* isdn_mmap */
+ NULL, /* isdn_readdir */
+ isdn_divert_poll, /* isdn_poll */
+ isdn_divert_ioctl, /* isdn_ioctl */
+ NULL, /* isdn_mmap */
isdn_divert_open,
- NULL, /* flush */
+ NULL, /* flush */
isdn_divert_close,
- NULL /* fsync */
-};
-
-struct inode_operations divert_file_inode_operations = {
- &isdn_fops, /* default proc file-ops */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
+ NULL /* fsync */
};
+struct inode_operations divert_file_inode_operations;
/****************************/
/* isdn subdir in /proc/net */
/****************************/
static struct proc_dir_entry *isdn_proc_entry = NULL;
static struct proc_dir_entry *isdn_divert_entry = NULL;
-#endif CONFIG_PROC_FS
+#endif /* CONFIG_PROC_FS */
/***************************************************************************/
/* divert_dev_init must be called before the proc filesystem may be used */
/***************************************************************************/
-int divert_dev_init(void)
-{ int i;
+int
+divert_dev_init(void)
+{
#ifdef CONFIG_PROC_FS
- isdn_proc_entry = create_proc_entry("isdn", S_IFDIR | S_IRUGO | S_IXUGO ,proc_net);
- if (!isdn_proc_entry)
- return(-1);
- isdn_divert_entry = create_proc_entry("divert",S_IFREG | S_IRUGO,isdn_proc_entry);
- if (!isdn_divert_entry)
- {
- remove_proc_entry("isdn",proc_net);
- return(-1);
- }
- isdn_divert_entry->ops = &divert_file_inode_operations;
-#endif CONFIG_PROC_FS
-
- return(0);
-} /* divert_dev_init */
+ isdn_proc_entry = create_proc_entry("isdn", S_IFDIR | S_IRUGO | S_IXUGO, proc_net);
+ if (!isdn_proc_entry)
+ return (-1);
+ isdn_divert_entry = create_proc_entry("divert", S_IFREG | S_IRUGO, isdn_proc_entry);
+ if (!isdn_divert_entry) {
+ remove_proc_entry("isdn", proc_net);
+ return (-1);
+ }
+ memset(&divert_file_inode_operations, 0, sizeof(struct inode_operations));
+ divert_file_inode_operations.default_file_ops = &isdn_fops;
+ isdn_divert_entry->ops = &divert_file_inode_operations;
+#endif /* CONFIG_PROC_FS */
+
+ return (0);
+} /* divert_dev_init */
/***************************************************************************/
/* divert_dev_deinit must be called before leaving isdn when included as */
/* a module. */
/***************************************************************************/
-int divert_dev_deinit(void)
-{ int i;
+int
+divert_dev_deinit(void)
+{
#ifdef CONFIG_PROC_FS
- remove_proc_entry("divert",isdn_proc_entry);
- remove_proc_entry("isdn",proc_net);
-#endif CONFIG_PROC_FS
-
- return(0);
-} /* divert_dev_deinit */
+ remove_proc_entry("divert", isdn_proc_entry);
+ remove_proc_entry("isdn", proc_net);
+#endif /* CONFIG_PROC_FS */
+ return (0);
+} /* divert_dev_deinit */
-/* $Id: eicon.h,v 1.18 1999/11/25 11:43:27 armin Exp $
+/* $Id: eicon.h,v 1.19 2000/01/23 21:21:23 armin Exp $
*
- * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
+ * ISDN low-level module for Eicon active ISDN-Cards.
*
* Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1998,99 by Armin Schindler (mac@melware.de)
- * Copyright 1999 Cytronics & Melware (info@melware.de)
+ * Copyright 1998-2000 by Armin Schindler (mac@melware.de)
+ * Copyright 1999,2000 Cytronics & Melware (info@melware.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
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: eicon.h,v $
+ * Revision 1.19 2000/01/23 21:21:23 armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
* Revision 1.18 1999/11/25 11:43:27 armin
* Fixed statectrl and connect message.
* X.75 fix and HDLC/transparent with autoconnect.
/* Macro for delay via schedule() */
#define SLEEP(j) { \
- current->state = TASK_INTERRUPTIBLE; \
+ current->state = TASK_UNINTERRUPTIBLE; \
schedule_timeout(j); \
}
#define XLOG_ERR_UNKNOWN (18)
#define XLOG_OK (0)
+#define TRACE_OK (1)
+
typedef struct {
__u8 Id __attribute__ ((packed));
__u8 uX __attribute__ ((packed));
extern ulong DebugVar;
extern void eicon_log(eicon_card * card, int level, const char *fmt, ...);
+extern void eicon_putstatus(eicon_card * card, char * buf);
#endif /* __KERNEL__ */
-/* $Id: eicon_dsp.h,v 1.4 1999/07/25 15:12:02 armin Exp $
+/* $Id: eicon_dsp.h,v 1.5 2000/01/23 21:21:23 armin Exp $
*
- * ISDN lowlevel-module for Eicon.Diehl active cards.
+ * ISDN lowlevel-module for Eicon active cards.
* DSP definitions
*
- * Copyright 1999 by Armin Schindler (mac@melware.de)
- * Copyright 1999 Cytronics & Melware (info@melware.de)
+ * Copyright 1999,2000 by Armin Schindler (mac@melware.de)
+ * Copyright 1999,2000 Cytronics & Melware (info@melware.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
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: eicon_dsp.h,v $
+ * Revision 1.5 2000/01/23 21:21:23 armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
* Revision 1.4 1999/07/25 15:12:02 armin
* fix of some debug logs.
* enabled ISA-cards option.
-/* $Id: eicon_idi.c,v 1.28 2000/01/20 19:55:34 keil Exp $
+/* $Id: eicon_idi.c,v 1.33 2000/03/06 15:45:17 armin Exp $
*
- * ISDN lowlevel-module for Eicon.Diehl active cards.
+ * ISDN lowlevel-module for Eicon active cards.
* IDI interface
*
- * Copyright 1998,99 by Armin Schindler (mac@melware.de)
- * Copyright 1999 Cytronics & Melware (info@melware.de)
+ * Copyright 1998-2000 by Armin Schindler (mac@melware.de)
+ * Copyright 1999,2000 Cytronics & Melware (info@melware.de)
*
* Thanks to Deutsche Mailbox Saar-Lor-Lux GmbH
* for sponsoring and testing fax
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: eicon_idi.c,v $
+ * Revision 1.33 2000/03/06 15:45:17 armin
+ * Fixed incomplete number handling with BRI PtP connection.
+ *
+ * Revision 1.32 2000/03/04 17:04:21 armin
+ * Fix of statemachine, B-connect before D-connect,
+ * thanks to Helmut Adams <adams@ipcon.de>
+ * Minor change in send-data packet handling.
+ *
+ * Revision 1.31 2000/02/22 16:26:40 armin
+ * Fixed membase error message.
+ * Fixed missing log buffer struct.
+ *
+ * Revision 1.30 2000/02/16 16:08:46 armin
+ * Fixed virtual channel handling of IDI.
+ *
+ * Revision 1.29 2000/01/23 21:21:23 armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
* Revision 1.28 2000/01/20 19:55:34 keil
* Add FAX Class 1 support
*
#undef EICON_FULL_SERVICE_OKTETT
-char *eicon_idi_revision = "$Revision: 1.28 $";
+char *eicon_idi_revision = "$Revision: 1.33 $";
eicon_manifbuf *manbuf;
}
int
-idi_put_req(eicon_REQ *reqbuf, int rq, int signet)
+idi_put_req(eicon_REQ *reqbuf, int rq, int signet, int Ch)
{
reqbuf->Req = rq;
- reqbuf->ReqCh = 0;
+ reqbuf->ReqCh = Ch;
reqbuf->ReqId = 1;
reqbuf->XBuffer.length = 1;
reqbuf->XBuffer.P[0] = 0;
break;
case REMOVE:
case REMOVE|0x700:
- idi_put_req(reqbuf, REMOVE, layer);
+ idi_put_req(reqbuf, REMOVE, layer, 0);
break;
case INDICATE_REQ:
- idi_put_req(reqbuf, INDICATE_REQ, 0);
+ idi_put_req(reqbuf, INDICATE_REQ, 0, 0);
break;
case HANGUP:
- idi_put_req(reqbuf, HANGUP, 0);
+ idi_put_req(reqbuf, HANGUP, 0, 0);
break;
case REJECT:
- idi_put_req(reqbuf, REJECT, 0);
+ idi_put_req(reqbuf, REJECT, 0 ,0);
break;
case CALL_ALERT:
- idi_put_req(reqbuf, CALL_ALERT, 0);
+ idi_put_req(reqbuf, CALL_ALERT, 0, 0);
break;
case CALL_RES:
idi_call_res_req(reqbuf, chan);
break;
case IDI_N_CONNECT|0x700:
- idi_put_req(reqbuf, IDI_N_CONNECT, 1);
+ idi_put_req(reqbuf, IDI_N_CONNECT, 1, 0);
break;
case IDI_N_CONNECT_ACK|0x700:
- idi_put_req(reqbuf, IDI_N_CONNECT_ACK, 1);
+ idi_put_req(reqbuf, IDI_N_CONNECT_ACK, 1, 0);
break;
case IDI_N_DISC|0x700:
- idi_put_req(reqbuf, IDI_N_DISC, 1);
+ idi_put_req(reqbuf, IDI_N_DISC, 1, chan->e.IndCh);
break;
case IDI_N_DISC_ACK|0x700:
- idi_put_req(reqbuf, IDI_N_DISC_ACK, 1);
+ idi_put_req(reqbuf, IDI_N_DISC_ACK, 1, chan->e.IndCh);
break;
default:
eicon_log(card, 1, "idi_req: Ch%d: Unknown request\n", chan->No);
message->osa[i] = buffer[pos++];
eicon_log(ccard, 2, "idi_inf: Ch%d: OSA=%s\n", chan->No, message->osa);
break;
+ case CAD:
+ pos += wlen;
+ eicon_log(ccard, 2, "idi_inf: Ch%d: Connected Address in ind, len:%x\n",
+ chan->No, wlen);
+ break;
case BC:
if (wlen > sizeof(message->bc)) {
pos += wlen;
reqbuf = (eicon_REQ *)skb_put(skb, sizeof(eicon_t30_s) + sizeof(eicon_REQ));
reqbuf->Req = IDI_N_EDATA;
- reqbuf->ReqCh = 0;
+ reqbuf->ReqCh = chan->e.IndCh;
reqbuf->ReqId = 1;
reqbuf->XBuffer.length = idi_fill_in_T30(chan, reqbuf->XBuffer.P);
reqbuf = (eicon_REQ *)skb_put(skb, 1 + len + sizeof(eicon_REQ));
reqbuf->Req = IDI_N_UDATA;
- reqbuf->ReqCh = 0;
+ reqbuf->ReqCh = chan->e.IndCh;
reqbuf->ReqId = 1;
reqbuf->XBuffer.length = len + 1;
}
}
+void
+eicon_parse_trace(eicon_card *ccard, unsigned char *buffer, int len)
+{
+ int i,j,n;
+ int buflen = len * 3 + 30;
+ char *p;
+ struct trace_s {
+ unsigned long time;
+ unsigned short size;
+ unsigned short code;
+ unsigned char data[1];
+ } *q;
+
+ if (!(p = kmalloc(buflen, GFP_ATOMIC))) {
+ eicon_log(ccard, 1, "idi_err: Ch??: could not allocate trace buffer\n");
+ return;
+ }
+ memset(p, 0, buflen);
+ q = (struct trace_s *)buffer;
+
+ if (DebugVar & 512) {
+ if ((q->code == 3) || (q->code == 4)) {
+ n = (short) *(q->data);
+ if (n) {
+ j = sprintf(p, "DTRC:");
+ for (i = 0; i < n; i++) {
+ j += sprintf(p + j, "%02x ", q->data[i+2]);
+ }
+ j += sprintf(p + j, "\n");
+ }
+ }
+ } else {
+ j = sprintf(p, "XLOG: %lx %04x %04x ",
+ q->time, q->size, q->code);
+
+ for (i = 0; i < q->size; i++) {
+ j += sprintf(p + j, "%02x ", q->data[i]);
+ }
+ j += sprintf(p + j, "\n");
+ }
+ if (strlen(p))
+ eicon_putstatus(ccard, p);
+ kfree(p);
+}
+
void
idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
{
return;
}
- if (ind->Ind != 8)
+ if ((ind->Ind != 8) && (ind->Ind != 0xc))
dlev = 144;
else
dlev = 128;
- eicon_log(ccard, dlev, "idi_hdl: Ch%d: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", chan->No,
+ eicon_log(ccard, dlev, "idi_hdl: Ch%d: Ind=%x Id=%x Ch=%x MInd=%x MLen=%x Len=%x\n", chan->No,
ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length);
free_buff = 1;
break;
case 3: /* incomplete number */
eicon_log(ccard, 8, "idi_req: Ch%d: Incomplete Number\n", chan->No);
- switch(ccard->type) {
- case EICON_CTYPE_MAESTRAP:
- case EICON_CTYPE_S2M:
- /* TODO (other protocols) */
- chan->fsm_state = EICON_STATE_ICALLW;
- break;
- default:
- idi_do_req(ccard, chan, HANGUP, 0);
- }
+ chan->fsm_state = EICON_STATE_ICALLW;
break;
}
break;
/* On most incoming calls we use automatic connect */
/* idi_do_req(ccard, chan, IDI_N_CONNECT, 1); */
}
- } else
- idi_hangup(ccard, chan);
+ } else {
+ if (chan->fsm_state != EICON_STATE_ACTIVE)
+ idi_hangup(ccard, chan);
+ }
break;
case CALL_CON:
eicon_log(ccard, 8, "idi_ind: Ch%d: Call_Con\n", chan->No);
if (chan->No == ccard->nchannels) {
/* Management Indication */
- idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length);
- chan->fsm_state = 1;
+ if (ind->Ind == 0x04) { /* Trace_Ind */
+ eicon_parse_trace(ccard, ind->RBuffer.P, ind->RBuffer.length);
+ } else {
+ idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length);
+ chan->fsm_state = 1;
+ }
}
else
switch(ind->Ind) {
break;
case IDI_N_CONNECT:
eicon_log(ccard, 16,"idi_ind: Ch%d: N_Connect\n", chan->No);
+ chan->e.IndCh = ind->IndCh;
if (chan->e.B2Id) idi_do_req(ccard, chan, IDI_N_CONNECT_ACK, 1);
if (chan->l2prot == ISDN_PROTO_L2_FAX) {
break;
idi_fax_hangup(ccard, chan);
}
#endif
+ chan->e.IndCh = 0;
save_flags(flags);
cli();
chan->queued = 0;
#endif
break;
case IDI_N_DATA_ACK:
- eicon_log(ccard, 16, "idi_ind: Ch%d: N_DATA_ACK\n", chan->No);
+ eicon_log(ccard, 128, "idi_ind: Ch%d: N_DATA_ACK\n", chan->No);
break;
case IDI_N_DATA:
skb_pull(skb, sizeof(eicon_IND) - 1);
/* Management Interface */
if (chan->No == ccard->nchannels) {
/* Managementinterface: changing state */
- if (chan->e.Req == 0x04)
+ if (chan->e.Req != 0x02)
chan->fsm_state = 1;
}
} else {
/* Network layer */
switch(chan->e.Req & 0x0f) {
+ case IDI_N_CONNECT:
+ chan->e.IndCh = ack->RcCh;
+ eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No,
+ ack->RcId, ack->RcCh, ack->Reference);
+ break;
case IDI_N_MDATA:
case IDI_N_DATA:
if ((chan->e.Req & 0x0f) == IDI_N_DATA) {
dCh, ack->Rc, ack->RcId, ack->RcCh);
break;
default:
- eicon_log(ccard, 1, "eicon_err: Ch%d: Ack Not OK !!: Rc=%d Id=%x Ch=%d Req=%d\n",
- dCh, ack->Rc, ack->RcId, ack->RcCh, chan->e.Req);
+ if (dCh != ccard->nchannels)
+ eicon_log(ccard, 1, "eicon_err: Ch%d: Ack Not OK !!: Rc=%d Id=%x Ch=%d Req=%d\n",
+ dCh, ack->Rc, ack->RcId, ack->RcCh, chan->e.Req);
}
if (dCh == ccard->nchannels) { /* Management */
chan->fsm_state = 2;
+ eicon_log(ccard, 8, "eicon_err: Ch%d: Ack Not OK !!: Rc=%d Id=%x Ch=%d Req=%d\n",
+ dCh, ack->Rc, ack->RcId, ack->RcCh, chan->e.Req);
} else if (dCh >= 0) {
/* any other channel */
/* card reports error: we hangup */
reqbuf = (eicon_REQ *)skb_put(xmit_skb, plen + sizeof(eicon_REQ));
if (((len - offset) > 270) &&
+ (chan->l2prot != ISDN_PROTO_L2_MODEM) &&
+ (chan->l2prot != ISDN_PROTO_L2_FAX) &&
(chan->l2prot != ISDN_PROTO_L2_TRANS)) {
reqbuf->Req = IDI_N_MDATA;
} else {
reqbuf->Req = IDI_N_DATA;
- if (ack) reqbuf->Req |= N_D_BIT;
+ /* if (ack) reqbuf->Req |= N_D_BIT; */
}
- reqbuf->ReqCh = 0;
+ reqbuf->ReqCh = chan->e.IndCh;
reqbuf->ReqId = 1;
memcpy(&reqbuf->XBuffer.P, skb->data + offset, plen);
reqbuf->XBuffer.length = plen;
chan = &(card->bch[card->nchannels]);
- if (chan->e.D3Id)
- return -EBUSY;
- chan->e.D3Id = 1;
- while((skb2 = skb_dequeue(&chan->e.X)))
- dev_kfree_skb(skb2);
- chan->e.busy = 0;
+ if (!(chan->e.D3Id)) {
+ chan->e.D3Id = 1;
+ while((skb2 = skb_dequeue(&chan->e.X)))
+ dev_kfree_skb(skb2);
+ chan->e.busy = 0;
- if ((ret = eicon_idi_manage_assign(card))) {
- chan->e.D3Id = 0;
- return(ret);
- }
+ if ((ret = eicon_idi_manage_assign(card))) {
+ chan->e.D3Id = 0;
+ return(ret);
+ }
- timeout = jiffies + 50;
- while (timeout > jiffies) {
- if (chan->e.B2Id) break;
- SLEEP(10);
- }
- if (!chan->e.B2Id) {
- chan->e.D3Id = 0;
- return -EIO;
+ timeout = jiffies + 50;
+ while (timeout > jiffies) {
+ if (chan->e.B2Id) break;
+ SLEEP(10);
+ }
+ if (!chan->e.B2Id) {
+ chan->e.D3Id = 0;
+ return -EIO;
+ }
}
chan->fsm_state = 0;
if (!(manbuf = kmalloc(sizeof(eicon_manifbuf), GFP_KERNEL))) {
eicon_log(card, 1, "idi_err: alloc_manifbuf failed\n");
- chan->e.D3Id = 0;
return -ENOMEM;
}
if (copy_from_user(manbuf, mb, sizeof(eicon_manifbuf))) {
kfree(manbuf);
- chan->e.D3Id = 0;
return -EFAULT;
}
if (skb2)
dev_kfree_skb(skb2);
kfree(manbuf);
- chan->e.D3Id = 0;
return -ENOMEM;
}
SLEEP(10);
}
if ((!chan->fsm_state) || (chan->fsm_state == 2)) {
- eicon_idi_manage_remove(card);
kfree(manbuf);
- chan->e.D3Id = 0;
return -EIO;
}
-
- if ((ret = eicon_idi_manage_remove(card))) {
- kfree(manbuf);
- chan->e.D3Id = 0;
- return(ret);
- }
-
if (copy_to_user(mb, manbuf, sizeof(eicon_manifbuf))) {
kfree(manbuf);
- chan->e.D3Id = 0;
return -EFAULT;
}
kfree(manbuf);
- chan->e.D3Id = 0;
return(0);
}
-/* $Id: eicon_idi.h,v 1.8 1999/11/25 11:43:27 armin Exp $
+/* $Id: eicon_idi.h,v 1.9 2000/01/23 21:21:23 armin Exp $
*
- * ISDN lowlevel-module for the Eicon.Diehl active cards.
+ * ISDN lowlevel-module for the Eicon active cards.
* IDI-Interface
*
- * Copyright 1998,99 by Armin Schindler (mac@melware.de)
- * Copyright 1999 Cytronics & Melware (info@melware.de)
+ * Copyright 1998-2000 by Armin Schindler (mac@melware.de)
+ * Copyright 1999,2000 Cytronics & Melware (info@melware.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
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: eicon_idi.h,v $
+ * Revision 1.9 2000/01/23 21:21:23 armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
* Revision 1.8 1999/11/25 11:43:27 armin
* Fixed statectrl and connect message.
* X.75 fix and HDLC/transparent with autoconnect.
-/* $Id: eicon_io.c,v 1.9 1999/11/18 20:55:25 armin Exp $
+/* $Id: eicon_io.c,v 1.10 2000/01/23 21:21:23 armin Exp $
*
- * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
+ * ISDN low-level module for Eicon active ISDN-Cards.
* Code for communicating with hardware.
*
- * Copyright 1999 by Armin Schindler (mac@melware.de)
- * Copyright 1999 Cytronics & Melware (info@melware.de)
+ * Copyright 1999,2000 by Armin Schindler (mac@melware.de)
+ * Copyright 1999,2000 Cytronics & Melware (info@melware.de)
*
- * Thanks to Eicon Technology Diehl GmbH & Co. oHG for
+ * Thanks to Eicon Technology GmbH & Co. oHG for
* documents, informations and hardware.
*
* This program is free software; you can redistribute it and/or modify
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: eicon_io.c,v $
+ * Revision 1.10 2000/01/23 21:21:23 armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
* Revision 1.9 1999/11/18 20:55:25 armin
* Ready_Int fix of ISA cards.
*
-/* $Id: eicon_isa.c,v 1.12 1999/11/27 12:56:19 armin Exp $
+/* $Id: eicon_isa.c,v 1.14 2000/02/22 16:26:40 armin Exp $
*
- * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
+ * ISDN low-level module for Eicon active ISDN-Cards.
* Hardware-specific code for old ISA cards.
*
- * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1998,99 by Armin Schindler (mac@melware.de)
- * Copyright 1999 Cytronics & Melware (info@melware.de)
+ * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
+ * Copyright 1998-2000 by Armin Schindler (mac@melware.de)
+ * Copyright 1999,2000 Cytronics & Melware (info@melware.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
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: eicon_isa.c,v $
+ * Revision 1.14 2000/02/22 16:26:40 armin
+ * Fixed membase error message.
+ * Fixed missing log buffer struct.
+ *
+ * Revision 1.13 2000/01/23 21:21:23 armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
* Revision 1.12 1999/11/27 12:56:19 armin
* Forgot some iomem changes for last ioremap compat.
*
#define release_shmem release_region
#define request_shmem request_region
-char *eicon_isa_revision = "$Revision: 1.12 $";
+char *eicon_isa_revision = "$Revision: 1.14 $";
#undef EICON_MCA_DEBUG
if (!strlen(Id))
return -1;
+ if (Mem == -1)
+ return -1;
+
/* Check for valid membase address */
if ((Mem < 0x0c0000) ||
(Mem > 0x0fc000) ||
-/* $Id: eicon_isa.h,v 1.7 1999/11/18 21:14:30 armin Exp $
+/* $Id: eicon_isa.h,v 1.8 2000/01/23 21:21:23 armin Exp $
*
- * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
+ * ISDN low-level module for Eicon active ISDN-Cards.
*
- * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1998,99 by Armin Schindler (mac@melware.de)
- * Copyright 1999 Cytronics & Melware (info@melware.de)
+ * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
+ * Copyright 1998-2000 by Armin Schindler (mac@melware.de)
+ * Copyright 1999,2000 Cytronics & Melware (info@melware.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
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: eicon_isa.h,v $
+ * Revision 1.8 2000/01/23 21:21:23 armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
* Revision 1.7 1999/11/18 21:14:30 armin
* New ISA memory mapped IO
*
-/* $Id: eicon_mod.c,v 1.23 2000/01/20 19:55:34 keil Exp $
+/* $Id: eicon_mod.c,v 1.25 2000/02/22 16:26:40 armin Exp $
*
- * ISDN lowlevel-module for Eicon.Diehl active cards.
+ * ISDN lowlevel-module for Eicon active cards.
*
- * Copyright 1997 by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1998,99 by Armin Schindler (mac@melware.de)
- * Copyright 1999 Cytronics & Melware (info@melware.de)
+ * Copyright 1997 by Fritz Elfert (fritz@isdn4linux.de)
+ * Copyright 1998-2000 by Armin Schindler (mac@melware.de)
+ * Copyright 1999,2000 Cytronics & Melware (info@melware.de)
*
- * Thanks to Eicon Technology Diehl GmbH & Co. oHG for
+ * Thanks to Eicon Technology GmbH & Co. oHG for
* documents, informations and hardware.
*
* Deutsche Telekom AG for S2M support.
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: eicon_mod.c,v $
+ * Revision 1.25 2000/02/22 16:26:40 armin
+ * Fixed membase error message.
+ * Fixed missing log buffer struct.
+ *
+ * Revision 1.24 2000/01/23 21:21:23 armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
* Revision 1.23 2000/01/20 19:55:34 keil
* Add FAX Class 1 support
*
static eicon_card *cards = (eicon_card *) NULL; /* glob. var , contains
start of card-list */
-static char *eicon_revision = "$Revision: 1.23 $";
+static char *eicon_revision = "$Revision: 1.25 $";
extern char *eicon_pci_revision;
extern char *eicon_isa_revision;
#endif
static char *id = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
-MODULE_DESCRIPTION( "Driver for Eicon.Diehl active ISDN cards");
+MODULE_DESCRIPTION( "Driver for Eicon active ISDN cards");
MODULE_AUTHOR( "Armin Schindler");
MODULE_SUPPORTED_DEVICE( "ISDN subsystem");
MODULE_PARM_DESC(id, "ID-String of first card");
u_char *p;
struct sk_buff *skb;
- if (!card)
- return;
+ if (!card) {
+ if (!(card = cards))
+ return;
+ }
save_flags(flags);
cli();
-/* $Id: eicon_pci.c,v 1.10 1999/08/22 20:26:49 calle Exp $
+/* $Id: eicon_pci.c,v 1.11 2000/01/23 21:21:23 armin Exp $
*
- * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
+ * ISDN low-level module for Eicon active ISDN-Cards.
* Hardware-specific code for PCI cards.
*
- * Copyright 1998,99 by Armin Schindler (mac@melware.de)
- * Copyright 1999 Cytronics & Melware (info@melware.de)
+ * Copyright 1998-2000 by Armin Schindler (mac@melware.de)
+ * Copyright 1999,2000 Cytronics & Melware (info@melware.de)
*
- * Thanks to Eicon Technology Diehl GmbH & Co. oHG for
+ * Thanks to Eicon Technology GmbH & Co. oHG for
* documents, informations and hardware.
*
* Deutsche Telekom AG for S2M support.
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: eicon_pci.c,v $
+ * Revision 1.11 2000/01/23 21:21:23 armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
* Revision 1.10 1999/08/22 20:26:49 calle
* backported changes from kernel 2.3.14:
* - several #include "config.h" gone, others come.
#include "eicon_pci.h"
-char *eicon_pci_revision = "$Revision: 1.10 $";
+char *eicon_pci_revision = "$Revision: 1.11 $";
#if CONFIG_PCI /* intire stuff is only for PCI */
-/* $Id: eicon_pci.h,v 1.3 1999/03/29 11:19:51 armin Exp $
+/* $Id: eicon_pci.h,v 1.4 2000/01/23 21:21:23 armin Exp $
*
- * ISDN low-level module for Eicon.Diehl active ISDN-Cards (PCI part).
+ * ISDN low-level module for Eicon active ISDN-Cards (PCI part).
*
- * Copyright 1998,99 by Armin Schindler (mac@melware.de)
- * Copyright 1999 Cytronics & Melware (info@melware.de)
+ * Copyright 1998-2000 by Armin Schindler (mac@melware.de)
+ * Copyright 1999,2000 Cytronics & Melware (info@melware.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
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: eicon_pci.h,v $
+ * Revision 1.4 2000/01/23 21:21:23 armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
* Revision 1.3 1999/03/29 11:19:51 armin
* I/O stuff now in seperate file (eicon_io.c)
* Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
-/* $Id: config.c,v 2.43 2000/01/20 19:49:36 keil Exp $
+/* $Id: config.c,v 2.44 2000/02/26 00:35:12 keil Exp $
* Author Karsten Keil (keil@isdn4linux.de)
* based on the teles driver from Jan den Ouden
*
*
* $Log: config.c,v $
+ * Revision 2.44 2000/02/26 00:35:12 keil
+ * Fix skb freeing in interrupt context
+ *
* Revision 2.43 2000/01/20 19:49:36 keil
* Support teles 13.3c vendor version 2.1
*
printk(KERN_INFO "HiSax: Linux Driver for passive ISDN cards\n");
#ifdef MODULE
- printk(KERN_INFO "HiSax: Version 3.3d (module)\n");
+ printk(KERN_INFO "HiSax: Version 3.3e (module)\n");
#else
- printk(KERN_INFO "HiSax: Version 3.3d (kernel)\n");
+ printk(KERN_INFO "HiSax: Version 3.3e (kernel)\n");
#endif
strcpy(tmp, l1_revision);
printk(KERN_INFO "HiSax: Layer1 Revision %s\n", HiSax_getrev(tmp));
-/* $Id: hfc_pci.c,v 1.25 1999/12/19 13:09:42 keil Exp $
+/* $Id: hfc_pci.c,v 1.27 2000/02/26 00:35:12 keil Exp $
* hfc_pci.c low level driver for CCD´s hfc-pci based cards
*
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: hfc_pci.c,v $
+ * Revision 1.27 2000/02/26 00:35:12 keil
+ * Fix skb freeing in interrupt context
+ *
+ * Revision 1.26 2000/02/09 20:22:55 werner
+ *
+ * Updated PCI-ID table
+ *
* Revision 1.25 1999/12/19 13:09:42 keil
* changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for
* signal proof delays
extern const char *CardType[];
-static const char *hfcpci_revision = "$Revision: 1.25 $";
+static const char *hfcpci_revision = "$Revision: 1.27 $";
/* table entry in the PCI devices list */
typedef struct {
{0x1051, 0x0100, "Motorola MC145575", "MC145575"},
{0x1397, 0xB100, "Seyeon", "B100"},
{0x15B0, 0x2BD0, "Zoltrix", "2BD0"},
+ {0x114f, 0x71, "Digi intl.","Digicom"},
{0, 0, NULL, NULL},
};
-/* $Id: hisax.h,v 2.40 2000/01/20 19:51:46 keil Exp $
+/* $Id: hisax.h,v 2.41 2000/02/26 00:35:13 keil Exp $
* Basic declarations, defines and prototypes
*
* $Log: hisax.h,v $
+ * Revision 2.41 2000/02/26 00:35:13 keil
+ * Fix skb freeing in interrupt context
+ *
* Revision 2.40 2000/01/20 19:51:46 keil
* Fix AddTimer message
* Change CONFIG defines
#include <linux/tty.h>
#include <linux/serial_reg.h>
-#undef ERROR_STATISTIC
+#define ERROR_STATISTIC
#define REQUEST 0
#define CONFIRM 1
-/* $Id: l3dss1.c,v 2.22 2000/01/20 19:44:20 keil Exp $
+/* $Id: l3dss1.c,v 2.23 2000/02/26 01:38:14 keil Exp $
* EURO/DSS1 D-channel protocol
*
* Fritz Elfert
*
* $Log: l3dss1.c,v $
+ * Revision 2.23 2000/02/26 01:38:14 keil
+ * Fixes for V.110 encoding LLC from Jens Jakobsen
+ *
* Revision 2.22 2000/01/20 19:44:20 keil
* Fixed uninitialiesed location
* Fixed redirecting number IE in Setup
#include <linux/config.h>
extern char *HiSax_getrev(const char *revision);
-const char *dss1_revision = "$Revision: 2.22 $";
+const char *dss1_revision = "$Revision: 2.23 $";
#define EXT_BEARER_CAPS 1
EncodeASyncParams(u_char * p, u_char si2)
{ // 7c 06 88 90 21 42 00 bb
- p[0] = p[1] = 0;
+ p[0] = 0;
+ p[1] = 0x40; // Intermediate rate: 16 kbit/s jj 2000.02.19
p[2] = 0x80;
if (si2 & 32) // 7 data bits
p[2] += 96;
else // 1 stop bit
- p[2] = 32;
+ p[2] += 32;
if (si2 & 8) // even parity
a23fbf8879c1432b04640b8b04bdf419 tei.c
ce248e56c2e1326012d0b25f92bbf99b callc.c
bf9605b36429898f7be6630034e83230 cert.c
-233960fa9fc46aaffcaa883b5b59cf4e l3dss1.c
+6ce0a184127be1a44747e2017ed24ad9 l3dss1.c
a3a570781f828b6d59e6b231653133de l3_1tr6.c
8188deeb4a1b34c574cd51638cd214d0 elsa.c
a3c2b8e9d2c623658888b5f1d4317c2a diva.c
Version: 2.6.3i
Charset: noconv
-iQCVAwUBOIdqVzpxHvX/mS9tAQGaWQP+Pj0oVxbhusXnlNOQ+FV6YOGj1HGMXPsO
-C/9555qSbvcKg64OO8VdU1LWq/RCsAwBkJ3eSizF5LbWD8lhCHUpkNlzEv4fIaHe
-fAA9zLnC8Vk4h/YLwUNfZxezYvf22NGSydXGZH4VvLAigF0OGRlKaewsR61KZ/Fh
-4GnVqcxYaH8=
-=eINS
+iQCVAwUBONEHHTpxHvX/mS9tAQG/pAP/UyLx23V9mOgiYaId1Gm6xthyM8TP4bfE
+ov4cNmUHQtHINLXtkAP+eacw/kCiiYhdxBIrNaUC+KQkyiFPOs8frx6espxTfDte
+VZDhKDY5NYch2n3OKPLX26pNNJeu7DELMpFR6vvGByokv1RRYVs2wBk0Q5dnfPaq
+WsW0HeL/vBA=
+=fSCb
-----END PGP SIGNATURE-----
-/* $Id: teles3.c,v 2.14 1999/12/23 15:09:32 keil Exp $
+/* $Id: teles3.c,v 2.15 2000/02/03 16:40:10 keil Exp $
* teles3.c low level stuff for Teles 16.3 & PNP isdn cards
*
* Beat Doebeli
*
* $Log: teles3.c,v $
+ * Revision 2.15 2000/02/03 16:40:10 keil
+ * Fix teles pcmcia
+ *
* Revision 2.14 1999/12/23 15:09:32 keil
* change email
*
#include "isdnl1.h"
extern const char *CardType[];
-const char *teles3_revision = "$Revision: 2.14 $";
+const char *teles3_revision = "$Revision: 2.15 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
release_io_teles3(struct IsdnCardState *cs)
{
if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
- release_region(cs->hw.teles3.hscx[0], 97);
+ release_region(cs->hw.teles3.hscx[1], 96);
} else {
if (cs->hw.teles3.cfg_reg) {
if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
- if (check_region((cs->hw.teles3.hscx[0]), 97)) {
+ if (check_region((cs->hw.teles3.hscx[1]), 96 )) {
printk(KERN_WARNING
"HiSax: %s ports %x-%x already in use\n",
CardType[cs->typ],
- cs->hw.teles3.hscx[0],
- cs->hw.teles3.hscx[0] + 96);
+ cs->hw.teles3.hscx[1],
+ cs->hw.teles3.hscx[1] + 96);
return (0);
} else
- request_region(cs->hw.teles3.hscx[0], 97, "HiSax Teles PCMCIA");
+ request_region(cs->hw.teles3.hscx[1], 96, "HiSax Teles PCMCIA");
} else {
if (cs->hw.teles3.cfg_reg) {
if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
-/* $Id: isdn_common.c,v 1.97 2000/01/23 18:45:37 keil Exp $
+/* $Id: isdn_common.c,v 1.100 2000/03/03 16:37:11 kai Exp $
* Linux ISDN subsystem, common used functions (linklevel).
*
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_common.c,v $
+ * Revision 1.100 2000/03/03 16:37:11 kai
+ * incorporated some cosmetic changes from the official kernel tree back
+ * into CVS
+ *
+ * Revision 1.99 2000/02/26 01:00:52 keil
+ * changes from 2.3.47
+ *
+ * Revision 1.98 2000/02/16 14:56:27 paul
+ * translated ISDN_MODEM_ANZREG to ISDN_MODEM_NUMREG for english speakers
+ *
* Revision 1.97 2000/01/23 18:45:37 keil
* Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN)
*
isdn_dev *dev = (isdn_dev *) 0;
-static char *isdn_revision = "$Revision: 1.97 $";
+static char *isdn_revision = "$Revision: 1.100 $";
extern char *isdn_net_revision;
extern char *isdn_tty_revision;
int i;
if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
- (ISDN_MODEM_ANZREG + ISDN_MSNLEN + ISDN_LMSNLEN)
+ (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN)
* ISDN_MAX_CHANNELS)))
return ret;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
if (copy_to_user(p, dev->mdm.info[i].emu.profile,
- ISDN_MODEM_ANZREG))
+ ISDN_MODEM_NUMREG))
return -EFAULT;
- p += ISDN_MODEM_ANZREG;
+ p += ISDN_MODEM_NUMREG;
if (copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN))
return -EFAULT;
p += ISDN_MSNLEN;
return -EFAULT;
p += ISDN_LMSNLEN;
}
- return (ISDN_MODEM_ANZREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS;
+ return (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS;
} else
return -EINVAL;
break;
int i;
if ((ret = verify_area(VERIFY_READ, (void *) arg,
- (ISDN_MODEM_ANZREG + ISDN_MSNLEN)
+ (ISDN_MODEM_NUMREG + ISDN_MSNLEN)
* ISDN_MAX_CHANNELS)))
return ret;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
if (copy_from_user(dev->mdm.info[i].emu.profile, p,
- ISDN_MODEM_ANZREG))
+ ISDN_MODEM_NUMREG))
return -EFAULT;
- p += ISDN_MODEM_ANZREG;
+ p += ISDN_MODEM_NUMREG;
if (copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
return -EFAULT;
p += ISDN_MSNLEN;
static struct file_operations isdn_fops =
{
- isdn_lseek,
- isdn_read,
- isdn_write,
- NULL, /* isdn_readdir */
- isdn_poll, /* isdn_poll */
- isdn_ioctl, /* isdn_ioctl */
- NULL, /* isdn_mmap */
- isdn_open,
- NULL, /* flush */
- isdn_close,
- NULL /* fsync */
+ llseek: isdn_lseek,
+ read: isdn_read,
+ write: isdn_write,
+ poll: isdn_poll,
+ ioctl: isdn_ioctl,
+ open: isdn_open,
+ release: isdn_close,
};
char *
return rev;
}
+
/*
* Allocate and initialize all data, register modem-devices
*/
-/* $Id: isdn_net.c,v 1.103 2000/01/23 18:45:37 keil Exp $
+/* $Id: isdn_net.c,v 1.114 2000/03/16 16:37:41 kai 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.114 2000/03/16 16:37:41 kai
+ * Allow phone numbers starting with "*" as outgoing numbers for
+ * networking interface. Some PBX's need this to allow dialing internal
+ * numbers (mine, for example ;-)
+ *
+ * Revision 1.113 2000/03/16 15:46:37 kai
+ * a little bugfix and cosmetic changes
+ *
+ * Revision 1.112 2000/03/04 16:20:42 detabc
+ * copy frames before rewriting frame's saddr
+ *
+ * Revision 1.111 2000/02/28 22:28:24 he
+ * moved tx_timeout warning messages in old (2.2.x) branch where it really only
+ * indicates problems.
+ *
+ * Revision 1.110 2000/02/26 01:00:53 keil
+ * changes from 2.3.47
+ *
+ * Revision 1.109 2000/02/25 11:29:17 paul
+ * changed chargetime to ulong from int (after about 20 days the "chargetime of
+ * ipppX is now 1234" message displays a negative number on alpha).
+ *
+ * Revision 1.108 2000/02/15 12:54:01 kai
+ * set TX timeout back to 2 secs for 2.2.x, just to be safe
+ *
+ * Revision 1.107 2000/02/13 09:52:05 kai
+ * increased TX_TIMEOUT to 20sec
+ *
+ * Revision 1.106 2000/02/12 19:26:55 kai
+ * adopted to latest 2.3 softnet changes.
+ *
+ * tested with PPP and MPPP, it works here.
+ * can somebody check raw-ip?
+ *
+ * also changed std2kern, stddiff for bash-1 compatibility,
+ * hope this doesn't break anything.
+ *
+ * Revision 1.105 2000/02/12 11:43:26 he
+ * SOFTNET related changes, first try. Compatible with linux 2.2.x, but
+ * not tested for kernels with softnet (>= 2.3.43) yet.
+ *
+ * Revision 1.104 2000/02/06 21:49:59 detabc
+ * add rewriting of socket's and frame's saddr for udp-ipv4 dynip-connections.
+ * Include checksum-recompute of ip- and udp-header's.
+ *
* Revision 1.103 2000/01/23 18:45:37 keil
* Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN)
*
#endif
-#ifndef ISDN_NEW_TBUSY
-#define ISDN_NEW_TBUSY
-#endif
-#ifdef ISDN_NEW_TBUSY
/*
* Outline of new tbusy handling:
*
*/
/*
- * Tell upper layers that the network device is ready to xmit more frames.
+ * About SOFTNET:
+ * Most of the changes were pretty obvious and basically done by HE already.
+ *
+ * One problem of the isdn net device code is that is uses struct net_device
+ * for masters and slaves. However, only master interface are registered to
+ * the network layer, and therefore, it only makes sense to call netif_*
+ * functions on them.
+ *
+ * --KG
*/
-static void __inline__ isdn_net_dev_xon(struct device * dev)
-{
- dev->tbusy = 0;
- mark_bh(NET_BH);
-}
-static void __inline__ isdn_net_lp_xon(isdn_net_local * lp)
+/*
+ * Find out if the netdevice has been ifup-ed yet.
+ * For slaves, look at the corresponding master.
+ */
+static int __inline__ isdn_net_started(isdn_net_dev *n)
{
- lp->netdev->dev.tbusy = 0;
- if(lp->master) lp->master->tbusy = 0;
- mark_bh(NET_BH);
+ isdn_net_local *lp = n->local;
+ struct device *dev;
+
+ if (lp->master)
+ dev = lp->master;
+ else
+ dev = &n->dev;
+ return dev->start;
}
/*
- * Ask upper layers to temporarily cease passing us more xmit frames.
+ * wake up the network -> net_device queue.
+ * For slaves, wake the corresponding master interface.
*/
-static void __inline__ isdn_net_dev_xoff(struct device * dev)
+static void __inline__ isdn_net_lp_xon(isdn_net_local * lp)
{
- dev->tbusy = 1;
+ if (lp->master)
+ netif_wake_queue(lp->master);
+ else
+ netif_wake_queue(&lp->netdev->dev);
}
-#endif
+
+/* For 2.2.x we leave the transmitter busy timeout at 2 secs, just
+ * to be safe.
+ * For 2.3.x we push it up to 20 secs, because call establishment
+ * (in particular callback) may take such a long time, and we
+ * don't want confusing messages in the log. However, there is a slight
+ * possibility that this large timeout will break other things like MPPP,
+ * which might rely on the tx timeout. If so, we'll find out this way...
+ */
+
+#define ISDN_NET_TX_TIMEOUT (2*HZ)
/* Prototypes */
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.103 $";
+char *isdn_net_revision = "$Revision: 1.114 $";
/*
* Code for raw-networking over ISDN
#endif
ulong flags;
+ /* not sure if the cli() is needed at all --KG */
save_flags(flags);
cli(); /* Avoid glitch on writes to CMD regs */
- dev->interrupt = 0;
-#ifdef ISDN_NEW_TBUSY
- isdn_net_dev_xon(dev);
-#else
- dev->tbusy = 0;
-#endif
#ifdef CONFIG_ISDN_X25
if( cprot && cprot -> pops && dops )
cprot -> pops -> restart ( cprot, dev, dops );
struct device *p;
struct in_device *in_dev;
+ /* moved here from isdn_net_reset, because only the master has an
+ interface associated which is supposed to be started. BTW:
+ we need to call netif_start_queue, not netif_wake_queue here */
+ netif_start_queue(dev);
+
isdn_net_reset(dev);
- dev->start = 1;
/* Fill in the MAC-level header (not needed, but for compatibility... */
for (i = 0; i < ETH_ALEN - sizeof(u32); i++)
dev->dev_addr[i] = 0xfc;
if ((p = (((isdn_net_local *) dev->priv)->slave))) {
while (p) {
isdn_net_reset(p);
- p->start = 1;
p = (((isdn_net_local *) p->priv)->slave);
}
}
isdn_net_hangup(&p->dev);
} else if (jiffies - l->chargetime > l->chargeint) {
printk(KERN_DEBUG
- "isdn_net: %s: chtime = %d, chint = %d\n",
+ "isdn_net: %s: chtime = %lu, chint = %d\n",
l->name, l->chargetime, l->chargeint);
isdn_net_hangup(&p->dev);
}
mdev = &lp->netdev->dev;
if (!isdn_net_send_skb(mdev, lp, lp->sav_skb)) {
lp->sav_skb = NULL;
-#ifndef ISDN_NEW_TBUSY
- mark_bh(NET_BH);
-#endif
} else {
return 1;
}
}
-#ifdef ISDN_NEW_TBUSY
isdn_net_lp_xon(lp);
-#else
- if (test_and_clear_bit(0, (void *) &(p->dev.tbusy)))
- mark_bh(NET_BH);
-#endif
}
return 1;
case ISDN_STAT_DCONN:
* we correct the timestamp here.
*/
lp->chargetime = jiffies;
- printk(KERN_DEBUG "isdn_net: chargetime of %s now %d\n",
+ printk(KERN_DEBUG "isdn_net: chargetime of %s now %lu\n",
lp->name, lp->chargetime);
/* reset dial-timeout */
if (!(isdn_net_xmit(&p->dev, lp, lp->first_skb)))
lp->first_skb = NULL;
}
-#ifdef ISDN_NEW_TBUSY
if(! lp->first_skb) isdn_net_lp_xon(lp);
-#else
- else {
- /*
- * dev.tbusy is usually cleared implicitly by isdn_net_xmit(,,lp->first_skb).
- * With an empty lp->first_skb, we need to do this ourselves
- */
- lp->netdev->dev.tbusy = 0;
- mark_bh(NET_BH);
- }
-#endif /* ISDN_NEW_TBUSY */
return 1;
}
break;
if (lp->hupflags & ISDN_WAITCHARGE)
lp->hupflags |= ISDN_HAVECHARGE;
lp->chargetime = jiffies;
- printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %d\n",
+ printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n",
lp->name, lp->chargetime);
return 1;
}
return 0;
}
-/*
- * Check, if a number contains wildcard-characters, in which case it
- * is for incoming purposes only.
- */
-static int
-isdn_net_checkwild(char *num)
-{
- return ((strchr(num, '?')) ||
- (strchr(num, '*')) ||
- (strchr(num, '[')) ||
- (strchr(num, ']')) ||
- (strchr(num, '^')));
-}
-
/*
* Perform dialout for net-interfaces and timeout-handling for
* D-Channel-up and B-Channel-up Messages.
*
* Return: 0 on success, !0 on failure.
*/
-#ifndef ISDN_NEW_TBUSY
-/*
- * Side-effects: ndev->tbusy is cleared on success.
- */
-#endif
-int
-isdn_net_send_skb
+int isdn_net_send_skb
(struct device *ndev, isdn_net_local * lp,struct sk_buff *skb)
{
int ret;
ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb);
if (ret == len) {
lp->transcount += len;
-#ifndef ISDN_NEW_TBUSY
- clear_bit(0, (void *) &(ndev->tbusy));
-#endif
return 0;
}
if (ret < 0) {
dev_kfree_skb(skb);
lp->stats.tx_errors++;
-#ifndef ISDN_NEW_TBUSY
- clear_bit(0, (void *) &(ndev->tbusy));
-#endif
return 0;
}
return 1;
if (lp->srobin == ndev)
ret = isdn_net_send_skb(ndev, lp, skb);
else
-#ifdef ISDN_NEW_TBUSY
ret = isdn_net_start_xmit(skb, lp->srobin);
-#else
- ret = ndev->tbusy = isdn_net_start_xmit(skb, lp->srobin);
-#endif
lp->srobin = (slp->slave) ? slp->slave : ndev;
slp = (isdn_net_local *) (lp->srobin->priv);
if (!((slp->flags & ISDN_NET_CONNECTED) && (slp->dialstate == 0)))
}
}
+
+
/*
* Try sending a packet.
* If this interface isn't connected to a ISDN-Channel, find a free channel,
#ifdef CONFIG_ISDN_X25
struct concap_proto * cprot = lp -> netdev -> cprot;
#endif
+ /* some comment as with the softnet TX timeout
+ when this happens, it's a bug in the HL card driver
+ and should be fixed there, so we can supposedly get rid of
+ this here at all.
+ I added a debugging message to find out if it ever occurs --KG
+ */
+
if (ndev->tbusy) {
- if (jiffies - ndev->trans_start < (2 * HZ))
+ if (jiffies - ndev->trans_start < ISDN_NET_TX_TIMEOUT)
return 1;
- if (!lp->dialstate)
+ if (!lp->dialstate){
lp->stats.tx_errors++;
+ printk(KERN_WARNING "isdn_tx_timeout dev %s dialstate %d\n",
+ ndev->name, lp->dialstate);
+ }
ndev->trans_start = jiffies;
-#ifdef ISDN_NEW_TBUSY
- isdn_net_dev_xon(ndev);
-#endif
+ netif_wake_queue(ndev);
}
-#ifndef ISDN_NEW_TBUSY
- ndev->tbusy = 1; /* left instead of obsolete test_and_set_bit() */
-#endif
#ifdef CONFIG_ISDN_X25
/* At this point hard_start_xmit() passes control to the encapsulation
protocol (if present).
*/
if( cprot ) {
int ret = cprot -> pops -> encap_and_xmit ( cprot , skb);
-#ifdef ISDN_NEW_TBUSY
- if(ret) isdn_net_dev_xoff(ndev);
-#endif
+ if(ret) netif_stop_queue(ndev);
return ret;
} else
#endif
if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) {
isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'");
dev_kfree_skb(skb);
-#ifndef ISDN_NEW_TBUSY
- ndev->tbusy = 0;
-#endif
return 0;
}
if (lp->phone[1]) {
if(jiffies < lp->dialwait_timer) {
isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached");
dev_kfree_skb(skb);
-#ifndef ISDN_NEW_TBUSY
- ndev->tbusy = 0;
-#endif
restore_flags(flags);
return 0;
} else
isdn_net_unreachable(ndev, skb,
"No channel");
dev_kfree_skb(skb);
-#ifndef ISDN_NEW_TBUSY
- ndev->tbusy = 0;
-#endif
return 0;
}
/* Log packet, which triggered dialing */
}
restore_flags(flags);
isdn_net_dial(); /* Initiate dialing */
-#ifdef ISDN_NEW_TBUSY
- isdn_net_dev_xoff(ndev);
-#endif
+ netif_stop_queue(ndev);
return 1; /* let upper layer requeue skb packet */
}
#endif
}
lp->first_skb = skb;
/* Initiate dialing */
-#ifndef ISDN_NEW_TBUSY
- ndev->tbusy = 0;
-#endif
restore_flags(flags);
isdn_net_dial();
return 0;
isdn_net_unreachable(ndev, skb,
"No phone number");
dev_kfree_skb(skb);
-#ifndef ISDN_NEW_TBUSY
- ndev->tbusy = 0;
-#endif
return 0;
}
} else {
int ret;
if (lp->first_skb) {
if (isdn_net_xmit(ndev, lp, lp->first_skb)){
-#ifdef ISDN_NEW_TBUSY
- isdn_net_dev_xoff(ndev);
-#endif
+ netif_stop_queue(ndev);
return 1;
}
lp->first_skb = NULL;
}
ret = (isdn_net_xmit(ndev, lp, skb));
-#ifdef ISDN_NEW_TBUSY
- if(ret) isdn_net_dev_xoff(ndev);
-#endif
+ if(ret) netif_stop_queue(ndev);
return ret;
} else
-#ifdef ISDN_NEW_TBUSY
- isdn_net_dev_xoff(ndev);
-#else
- ndev->tbusy = 1;
-#endif
+ netif_stop_queue(ndev);
}
}
return 1;
#ifdef CONFIG_ISDN_X25
if( cprot && cprot -> pops ) cprot -> pops -> close( cprot );
#endif
- dev->tbusy = 1;
+ netif_stop_queue(dev);
dev->start = 0;
if ((p = (((isdn_net_local *) dev->priv)->slave))) {
/* If this interface has slaves, stop them also */
cprot -> pops -> close( cprot );
#endif
isdn_net_hangup(p);
- p->tbusy = 1;
- p->start = 0;
p = (((isdn_net_local *) p->priv)->slave);
}
}
* Is the interface up?
* If not, reject the call actively.
*/
- if (!p->dev.start) {
+ if (!isdn_net_started(p)) {
restore_flags(flags);
printk(KERN_INFO "%s: incoming call, interface down -> rejected\n",
lp->name);
p = (((isdn_net_local *) p->priv)->slave);
}
((isdn_net_local *) q->priv)->slave = &(netdev->dev);
- q->interrupt = 0;
- q->tbusy = 0;
- q->start = master->start;
} else {
/* Device shall be a master */
if (register_netdev(&netdev->dev) != 0) {
if (n->local->master)
return NULL;
/* Master must not be started yet */
- if (n->dev.start)
+ if (isdn_net_started(n))
return NULL;
return (isdn_net_new(newname, &(n->dev)));
}
#ifdef CONFIG_ISDN_X25
struct concap_proto * cprot = p -> cprot;
#endif
- if (p->dev.start) {
- printk(KERN_WARNING
- "%s: cannot change encap when if is up\n",
+ if (isdn_net_started(p)) {
+ printk(KERN_WARNING "%s: cannot change encap when if is up\n",
lp->name);
return -EBUSY;
}
isdn_net_dev *p = isdn_net_findif(phone->name);
isdn_net_phone *n;
- if (isdn_net_checkwild(phone->phone) && (phone->outgoing & 1))
- return -EINVAL;
if (p) {
if (!(n = (isdn_net_phone *) kmalloc(sizeof(isdn_net_phone), GFP_KERNEL)))
return -ENOMEM;
save_flags(flags);
cli();
- if (p->local->master) {
- /* If it's a slave, it may be removed even if it is busy. However
- * it has to be hung up first.
- */
- isdn_net_hangup(&p->dev);
- p->dev.start = 0;
- }
- if (p->dev.start) {
+
+ if (isdn_net_started(p)) {
restore_flags(flags);
return -EBUSY;
}
-/* $Id: isdn_ppp.c,v 1.61 1999/11/20 22:14:14 detabc Exp $
+/* $Id: isdn_ppp.c,v 1.63 2000/03/16 15:46:37 kai 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.63 2000/03/16 15:46:37 kai
+ * a little bugfix and cosmetic changes
+ *
+ * Revision 1.62 2000/02/12 19:26:55 kai
+ * adopted to latest 2.3 softnet changes.
+ *
+ * tested with PPP and MPPP, it works here.
+ * can somebody check raw-ip?
+ *
+ * also changed std2kern, stddiff for bash-1 compatibility,
+ * hope this doesn't break anything.
+ *
* 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.
static void isdn_ppp_free_mpqueue(isdn_net_dev *);
#endif
-char *isdn_ppp_revision = "$Revision: 1.61 $";
+char *isdn_ppp_revision = "$Revision: 1.63 $";
static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
case PPPIOCGIFNAME:
if(!lp)
return -EINVAL;
- if ((r = set_arg((void *) arg, lp->name,strlen(lp->name))))
+ if ((r = set_arg((void *) arg, lp->name, strlen(lp->name))))
return r;
break;
case PPPIOCGMPFLAGS: /* get configuration flags */
}
if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) {
if (lp) {
- lp->netdev->dev.tbusy = 0;
- mark_bh(NET_BH); /* OK .. we are ready to send buffers */
+ /* OK .. we are ready to send buffers */
+ netif_wake_queue(&lp->netdev->dev);
}
}
is->pppcfg = val;
break;
default:
dev_kfree_skb(skb);
- printk(KERN_ERR "isdn_ppp: skipped frame with unsupported protocoll: %#x.\n", skb->protocol);
+ printk(KERN_ERR "isdn_ppp: skipped frame with unsupported protocol: %#x.\n", skb->protocol);
return 0;
}
if (lp->sav_skb) { /* find a non-busy device */
isdn_net_local *nlp = lp->next;
- while (lp->sav_skb) {
+ while (nlp->sav_skb) {
if (lp == nlp)
return 1;
nlp = nd->queue = nd->queue->next;
#ifdef CONFIG_ISDN_PPP_VJ
int toss = 0;
#endif
-/* z.z einfaches aussortieren gammeliger pakete. Fuer die Zukunft:
- eventuell, solange vorne kein B-paket ist und sqno<=min_sqno: auch rauswerfen
- wenn sqno<min_sqno und Luecken vorhanden sind: auch weg (die koennen nicht mehr gefuellt werden)
- bei paketen groesser min_sqno: ueber mp_mrru: wenn summe ueber pktlen der rumhaengenden Pakete
- groesser als mrru ist: raus damit , Pakete muessen allerdings zusammenhaengen sonst koennte
- ja ein Paket mit B und eins mit E dazwischenpassen */
+ /* currently we just discard ancient packets.
+ To do:
+ Maybe, as long as there's no B-packet in front and sqno <= min_sqno: discard.
+ If sqno < min_sqno and there are gaps: discard (the gaps won't be filled anyway).
+ Packets with sqno > min_sqno: Larger than mp_mrru: If sum of all pktlen of pending
+ packets large than mrru: discard - packets need to be consecutive, though, if not
+ there could be an B and an E-packet in between.
+ */
struct mpqueue *ql,
*q = dev->mp_last;
-/* $Id: isdn_tty.c,v 1.82 2000/01/23 18:45:37 keil Exp $
+/* $Id: isdn_tty.c,v 1.84 2000/02/16 15:10:14 paul 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.84 2000/02/16 15:10:14 paul
+ * If a ttyI has no open FDs, don't connect incoming calls to it.
+ * (Hangup on close of last FD is still to be done.)
+ *
+ * Revision 1.83 2000/02/16 14:59:33 paul
+ * translated ISDN_MODEM_ANZREG to ISDN_MODEM_NUMREG for english speakers;
+ * used defines for result codes;
+ * fixed RING ... RUNG problem (no empty lines in between).
+ *
* Revision 1.82 2000/01/23 18:45:37 keil
* Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN)
*
static int si2bit[8] =
{4, 1, 4, 4, 4, 4, 4, 4};
-char *isdn_tty_revision = "$Revision: 1.82 $";
+char *isdn_tty_revision = "$Revision: 1.84 $";
/* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
isdn_tty_modem_do_ncarrier(unsigned long data)
{
modem_info *info = (modem_info *) data;
- isdn_tty_modem_result(3, info);
+ isdn_tty_modem_result(RESULT_NO_CARRIER, info);
}
/* Next routine is called, whenever the DTR-signal is raised.
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);
+ isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
} else {
info->isdn_driver = dev->drvmap[i];
info->isdn_channel = dev->chanmap[i];
if (info->online) {
info->last_lhup = local;
info->online = 0;
- /* NO CARRIER message */
- isdn_tty_modem_result(3, info);
+ isdn_tty_modem_result(RESULT_NO_CARRIER, info);
}
#ifdef CONFIG_ISDN_AUDIO
info->vonline = 0;
#endif
if ((info->msr & UART_MSR_RI) &&
(info->emu.mdmreg[REG_RUNG] & BIT_RUNG))
- isdn_tty_modem_result(12, info);
+ isdn_tty_modem_result(RESULT_RUNG, info);
info->msr &= ~(UART_MSR_DCD | UART_MSR_RI);
info->lsr |= UART_LSR_TEMT;
if (info->isdn_driver >= 0) {
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);
+ isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
} else {
info->isdn_driver = dev->drvmap[i];
info->isdn_channel = dev->chanmap[i];
l = strlen(msg);
if (!l) {
- isdn_tty_modem_result(4, info);
+ isdn_tty_modem_result(RESULT_ERROR, info);
return;
}
for (j = 7; j >= 0; j--)
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);
+ isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
} else {
info->isdn_driver = dev->drvmap[i];
info->isdn_channel = dev->chanmap[i];
#ifdef ISDN_DEBUG_MODEM_HUP
printk(KERN_DEBUG "Mhup in isdn_tty_write\n");
#endif
- isdn_tty_modem_result(3, info);
+ isdn_tty_modem_result(RESULT_NO_CARRIER, info);
isdn_tty_modem_hup(info, 1);
} else
c = isdn_tty_edit_at(buf, c, info, from_user);
{
atemu *m = &info->emu;
if ((m->mdmreg[REG_DTRR] & BIT_DTRR) || force) {
- memcpy(m->mdmreg, m->profile, ISDN_MODEM_ANZREG);
+ memcpy(m->mdmreg, m->profile, ISDN_MODEM_NUMREG);
memcpy(m->msn, m->pmsn, ISDN_MSNLEN);
memcpy(m->lmsn, m->plmsn, ISDN_LMSNLEN);
info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
static void
modem_write_profile(atemu * m)
{
- memcpy(m->profile, m->mdmreg, ISDN_MODEM_ANZREG);
+ memcpy(m->profile, m->mdmreg, ISDN_MODEM_NUMREG);
memcpy(m->pmsn, m->msn, ISDN_MSNLEN);
memcpy(m->plmsn, m->lmsn, ISDN_LMSNLEN);
if (dev->profd)
return 0;
}
+
+/*
+ * isdn_tty_match_icall(char *MSN, atemu *tty_emulator, int dev_idx)
+ * match the MSN against the MSNs (glob patterns) defined for tty_emulator,
+ * and return 0 for match, 1 for no match, 2 if MSN could match if longer.
+ */
+
static int
isdn_tty_match_icall(char *cid, atemu *emu, int di)
{
int idx;
int si1;
int si2;
- char nr[32];
+ char *nr;
ulong flags;
if (!setup.phone[0]) {
- nr[0] = '0';
- nr[1] = '\0';
+ nr = "0";
printk(KERN_INFO "isdn_tty: Incoming call without OAD, assuming '0'\n");
} else
- strcpy(nr, setup.phone);
+ nr = setup.phone;
si1 = (int) setup.si1;
si2 = (int) setup.si2;
if (!setup.eazmsn[0]) {
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
modem_info *info = &dev->mdm.info[i];
+ if (info->count == 0)
+ continue;
if ((info->emu.mdmreg[REG_SI1] & si2bit[si1]) && /* SI1 is matching */
(info->emu.mdmreg[REG_SI2] == si2)) { /* SI2 is matching */
idx = isdn_dc2minor(di, ch);
printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,
info->line);
info->msr |= UART_MSR_RI;
- isdn_tty_modem_result(2, info);
+ isdn_tty_modem_result(RESULT_RING, info);
isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1);
return 1;
}
#endif
if (TTY_IS_ACTIVE(info)) {
if (info->dialing == 1)
- isdn_tty_modem_result(7, info);
+ isdn_tty_modem_result(RESULT_BUSY, info);
if (info->dialing > 1)
- isdn_tty_modem_result(3, info);
+ isdn_tty_modem_result(RESULT_NO_CARRIER, info);
info->dialing = 0;
#ifdef ISDN_DEBUG_MODEM_HUP
printk(KERN_DEBUG "Mhup in ISDN_STAT_DHUP\n");
if (USG_MODEM(dev->usage[i])) {
if (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) {
strcpy(info->emu.connmsg, c->parm.num);
- isdn_tty_modem_result(1, info);
+ isdn_tty_modem_result(RESULT_CONNECT, info);
} else
- isdn_tty_modem_result(5, info);
+ isdn_tty_modem_result(RESULT_CONNECT64000, info);
}
if (USG_VOICE(dev->usage[i]))
- isdn_tty_modem_result(11, info);
+ isdn_tty_modem_result(RESULT_VCON, info);
return 1;
}
break;
info->last_l2 = -1;
info->last_si = 0;
sprintf(info->last_cause, "0000");
- isdn_tty_modem_result(6, info);
+ isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
}
isdn_tty_modem_hup(info, 0);
return 1;
* For CONNECT-messages also switch to online-mode.
* For RING-message handle auto-ATA if register 0 != 0
*/
+
static void
isdn_tty_modem_result(int code, modem_info * info)
{
char s[ISDN_MSNLEN+10];
switch (code) {
- case 2:
- m->mdmreg[REG_RINGCNT]++; /* RING */
+ case RESULT_RING:
+ m->mdmreg[REG_RINGCNT]++;
if (m->mdmreg[REG_RINGCNT] == m->mdmreg[REG_RINGATA])
/* Automatically accept incoming call */
isdn_tty_cmd_ATA(info);
break;
- case 3:
- /* NO CARRIER */
+ case RESULT_NO_CARRIER:
#ifdef ISDN_DEBUG_MODEM_HUP
printk(KERN_DEBUG "modem_result: NO CARRIER %d %d\n",
(info->flags & ISDN_ASYNC_CLOSING),
}
#endif
break;
- case 1:
- case 5:
+ case RESULT_CONNECT:
+ case RESULT_CONNECT64000:
sprintf(info->last_cause, "0000");
if (!info->online)
info->online = 2;
break;
- case 11:
+ case RESULT_VCON:
#ifdef ISDN_DEBUG_MODEM_VOICE
printk(KERN_DEBUG "res3: send VCON on ttyI%d\n",
info->line);
if (!info->online)
info->online = 1;
break;
- }
+ } /* switch(code) */
+
if (m->mdmreg[REG_RESP] & BIT_RESP) {
/* Show results */
- isdn_tty_at_cout("\r\n", info);
if (m->mdmreg[REG_RESPNUM] & BIT_RESPNUM) {
- /* Show numeric results */
- sprintf(s, "%d", code);
+ /* Show numeric results only */
+ sprintf(s, "\r\n%d\r\n", code);
isdn_tty_at_cout(s, info);
} else {
- if ((code == 2) &&
- (m->mdmreg[REG_RUNG] & BIT_RUNG) &&
- (m->mdmreg[REG_RINGCNT] > 1))
- return;
- if ((code == 2) && (!(m->mdmreg[REG_CIDONCE] & BIT_CIDONCE))) {
- isdn_tty_at_cout("CALLER NUMBER: ", info);
- isdn_tty_at_cout(dev->num[info->drv_index], info);
- isdn_tty_at_cout("\r\n", info);
+ if (code == RESULT_RING) {
+ /* return if "show RUNG" and ringcounter>1 */
+ if ((m->mdmreg[REG_RUNG] & BIT_RUNG) &&
+ (m->mdmreg[REG_RINGCNT] > 1))
+ return;
+ /* print CID, _before_ _every_ ring */
+ if (!(m->mdmreg[REG_CIDONCE] & BIT_CIDONCE)) {
+ isdn_tty_at_cout("\r\nCALLER NUMBER: ", info);
+ isdn_tty_at_cout(dev->num[info->drv_index], info);
+ }
}
+ isdn_tty_at_cout("\r\n", info);
isdn_tty_at_cout(msg[code], info);
switch (code) {
- case 1:
+ case RESULT_CONNECT:
switch (m->mdmreg[REG_L2PROT]) {
case ISDN_PROTO_L2_MODEM:
isdn_tty_at_cout(" ", info);
break;
}
break;
- case 2:
+ case RESULT_RING:
/* Append CPN, if enabled */
if ((m->mdmreg[REG_CPN] & BIT_CPN)) {
sprintf(s, "/%s", m->cpn);
isdn_tty_at_cout(s, info);
}
- /* Print CID only once, _after_ 1.st RING */
+ /* Print CID only once, _after_ 1st RING */
if ((m->mdmreg[REG_CIDONCE] & BIT_CIDONCE) &&
(m->mdmreg[REG_RINGCNT] == 1)) {
isdn_tty_at_cout("\r\n", info);
isdn_tty_at_cout(dev->num[info->drv_index], info);
}
break;
- case 3:
- case 6:
- case 7:
- case 8:
+ case RESULT_NO_CARRIER:
+ case RESULT_NO_DIALTONE:
+ case RESULT_BUSY:
+ case RESULT_NO_ANSWER:
m->mdmreg[REG_RINGCNT] = 0;
/* Append Cause-Message if enabled */
if (m->mdmreg[REG_RESPXT] & BIT_RESPXT) {
isdn_tty_at_cout(s, info);
}
break;
- case 5:
+ case RESULT_CONNECT64000:
/* Append Protocol to CONNECT message */
switch (m->mdmreg[REG_L2PROT]) {
case ISDN_PROTO_L2_X75I:
}
break;
}
+ isdn_tty_at_cout("\r\n", info);
}
- isdn_tty_at_cout("\r\n", info);
}
- if (code == 3) {
+ if (code == RESULT_NO_CARRIER) {
save_flags(flags);
cli();
if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
}
}
+
/*
* Display a modem-register-value.
*/
*q = 0;
}
-#define PARSE_ERROR { isdn_tty_modem_result(4, info); return; }
-#define PARSE_ERROR1 { isdn_tty_modem_result(4, info); return 1; }
+#define PARSE_ERROR { isdn_tty_modem_result(RESULT_ERROR, info); return; }
+#define PARSE_ERROR1 { isdn_tty_modem_result(RESULT_ERROR, info); return 1; }
static void
isdn_tty_report(modem_info * info)
/* &L -Set Numbers to listen on */
p[0]++;
i = 0;
- while ((strchr("0123456789,-*[]?;", *p[0])) &&
- (i < ISDN_LMSNLEN) && *p[0])
+ while (*p[0] && (strchr("0123456789,-*[]?;", *p[0])) &&
+ (i < ISDN_LMSNLEN))
m->lmsn[i++] = *p[0]++;
m->lmsn[i] = '\0';
break;
/* &V - Show registers */
p[0]++;
isdn_tty_at_cout("\r\n", info);
- for (i = 0; i < ISDN_MODEM_ANZREG; i++) {
+ for (i = 0; i < ISDN_MODEM_NUMREG; i++) {
sprintf(rb, "S%02d=%03d%s", i,
m->mdmreg[i], ((i + 1) % 10) ? " " : "\r\n");
isdn_tty_at_cout(rb, info);
int bval;
mreg = isdn_getnum(p);
- if (mreg < 0 || mreg >= ISDN_MODEM_ANZREG)
+ if (mreg < 0 || mreg >= ISDN_MODEM_NUMREG)
PARSE_ERROR1;
switch (*p[0]) {
case '=':
isdn_command(&cmd);
isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
} else
- isdn_tty_modem_result(8, info);
+ isdn_tty_modem_result(RESULT_NO_ANSWER, info);
}
#ifdef CONFIG_ISDN_AUDIO
if (!m->vpar[0])
PARSE_ERROR1;
if (info->online != 1) {
- isdn_tty_modem_result(8, info);
+ isdn_tty_modem_result(RESULT_NO_ANSWER, info);
return 1;
}
info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state);
printk(KERN_DEBUG "AT: +VRX\n");
#endif
info->vonline |= 1;
- isdn_tty_modem_result(1, info);
+ isdn_tty_modem_result(RESULT_CONNECT, info);
return 0;
break;
case 4:
if (!m->vpar[0])
PARSE_ERROR1;
if (info->online != 1) {
- isdn_tty_modem_result(8, info);
+ isdn_tty_modem_result(RESULT_NO_ANSWER, info);
return 1;
}
info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state);
#endif
m->lastDLE = 0;
info->vonline |= 2;
- isdn_tty_modem_result(1, info);
+ isdn_tty_modem_result(RESULT_CONNECT, info);
return 0;
break;
case 7:
if (info->msr & UART_MSR_DCD)
PARSE_ERROR;
if (info->msr & UART_MSR_RI) {
- isdn_tty_modem_result(3, info);
+ isdn_tty_modem_result(RESULT_NO_CARRIER, info);
return;
}
isdn_tty_getdial(++p, ds, sizeof ds);
p += strlen(p);
if (!strlen(m->msn))
- isdn_tty_modem_result(10, info);
+ isdn_tty_modem_result(RESULT_NO_MSN_EAZ, info);
else if (strlen(ds))
isdn_tty_dial(ds, info, m);
else
p++;
if (info->msr & UART_MSR_DCD)
/* if B-Channel is up */
- isdn_tty_modem_result((m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) ? 1:5, info);
+ isdn_tty_modem_result((m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) ? RESULT_CONNECT:RESULT_CONNECT64000, info);
else
- isdn_tty_modem_result(3, info);
+ isdn_tty_modem_result(RESULT_NO_CARRIER, info);
return;
case 'Q':
/* Q - Turn Emulator messages on/off */
#ifdef CONFIG_ISDN_AUDIO
if (!info->vonline)
#endif
- isdn_tty_modem_result(0, info);
+ isdn_tty_modem_result(RESULT_OK, info);
}
/* Need own toupper() because standard-toupper is not available
((jiffies - info->emu.lastplus) > PLUSWAIT2)) {
info->emu.pluscount = 0;
info->online = 0;
- isdn_tty_modem_result(0, info);
+ isdn_tty_modem_result(RESULT_OK, info);
}
}
}
modem_info *info = &dev->mdm.info[i];
if (info->msr & UART_MSR_RI) {
ton = 1;
- isdn_tty_modem_result(2, info);
+ isdn_tty_modem_result(RESULT_RING, info);
}
}
isdn_timer_ctrl(ISDN_TIMER_MODEMRING, ton);
if (info->dialing) {
if (info->emu.carrierwait++ > info->emu.mdmreg[REG_WAITC]) {
info->dialing = 0;
- isdn_tty_modem_result(3, info);
+ isdn_tty_modem_result(RESULT_NO_CARRIER, info);
isdn_tty_modem_hup(info, 1);
}
else
-/* $Id: isdn_tty.h,v 1.18 2000/01/20 19:55:33 keil Exp $
+/* $Id: isdn_tty.h,v 1.19 2000/02/16 14:59:33 paul 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.19 2000/02/16 14:59:33 paul
+ * translated ISDN_MODEM_ANZREG to ISDN_MODEM_NUMREG for english speakers;
+ * used defines for result codes;
+ * fixed RING ... RUNG problem (no empty lines in between).
+ *
* Revision 1.18 2000/01/20 19:55:33 keil
* Add FAX Class 1 support
*
* Definition of some special Registers of AT-Emulator
*/
#define REG_RINGATA 0
-#define REG_RINGCNT 1
+#define REG_RINGCNT 1 /* ring counter register */
#define REG_ESC 2
#define REG_CR 3
#define REG_LF 4
#define REG_WAITC 7
-#define REG_RESP 12
-#define BIT_RESP 1
-#define REG_RESPNUM 12
-#define BIT_RESPNUM 2
+#define REG_RESP 12 /* show response messages register */
+#define BIT_RESP 1 /* show response messages bit */
+#define REG_RESPNUM 12 /* show numeric responses register */
+#define BIT_RESPNUM 2 /* show numeric responses bit */
#define REG_ECHO 12
#define BIT_ECHO 4
#define REG_DCD 12
#define BIT_RESPXT 8
#define REG_CIDONCE 13
#define BIT_CIDONCE 16
-#define REG_RUNG 13
-#define BIT_RUNG 64
+#define REG_RUNG 13 /* show RUNG message register */
+#define BIT_RUNG 64 /* show RUNG message bit */
#define REG_DISPLAY 13
#define BIT_DISPLAY 128
#define BIT_CPN 1
#define BIT_CPNFCON 2
+/* defines for result codes */
+#define RESULT_OK 0
+#define RESULT_CONNECT 1
+#define RESULT_RING 2
+#define RESULT_NO_CARRIER 3
+#define RESULT_ERROR 4
+#define RESULT_CONNECT64000 5
+#define RESULT_NO_DIALTONE 6
+#define RESULT_BUSY 7
+#define RESULT_NO_ANSWER 8
+#define RESULT_RINGING 9
+#define RESULT_NO_MSN_EAZ 10
+#define RESULT_VCON 11
+#define RESULT_RUNG 12
+
#define TTY_IS_FCLASS1(info) \
((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) && \
(info->emu.mdmreg[REG_L3PROT] == ISDN_PROTO_L3_FCLASS1))
-/* $Id: isdn_v110.c,v 1.3 1999/10/30 09:49:28 keil Exp $
+/* $Id: isdn_v110.c,v 1.4 2000/03/16 16:34:12 kai Exp $
* Linux ISDN subsystem, V.110 related functions (linklevel).
*
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_v110.c,v $
+ * Revision 1.4 2000/03/16 16:34:12 kai
+ * some translation work
+ *
+ * there shouldn't be any German comments lurking around anymore ;-)
+ *
* Revision 1.3 1999/10/30 09:49:28 keil
* Reinit of v110 structs
*
#undef ISDN_V110_DEBUG
-char *isdn_v110_revision = "$Revision: 1.3 $";
+char *isdn_v110_revision = "$Revision: 1.4 $";
#define V110_38400 255
#define V110_19200 15
#define V110_9600 3
-/* Die folgenden Daten sind fertig kodierte Matrizen, jeweils
- als online und offline matrix für 9600, 19200 und 38400
+/*
+ * The following data are precoded matrices, online and offline matrix
+ * for 9600, 19200 und 38400, respectively
*/
static unsigned char V110_OnMatrix_9600[] =
{0xfc, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff,
static unsigned char V110_OffMatrix_38400[] =
{0x00, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff};
-
-/* FlipBits dreht die Reihenfolge von jeweils keylen bits in einem byte um.
- Aus der Bitreihenfolge 76543210 werden bei keylen=4 die bits 45670123,
- bei keylen=2 die bits 67452301. Dies ist notwendig, weil die reihenfolge
- auf der isdn-leitung falsch herum ist.
+/*
+ * FlipBits reorders sequences of keylen bits in one byte.
+ * E.g. source order 7654321 will be converted to 45670123 when keylen = 4,
+ * and to 67452301 when keylen = 2. This is necessary because ordering on
+ * the isdn line is the the other way.
*/
-
static __inline unsigned char
FlipBits(unsigned char c, int keylen)
{
}
-/* ValidHeaderBytes prüft, wieviele bytes in v->decodebuf gültig sind */
-
+/*
+ * ValidHeaderBytes return the number of valid bytes in v->decodebuf
+ */
static int
ValidHeaderBytes(isdn_v110_stream * v)
{
return i;
}
-/* SyncHeader schiebt den decodebuf pointer auf den nächsten gültigen header */
-
+/*
+ * SyncHeader moves the decodebuf ptr to the next valid header
+ */
static void
SyncHeader(isdn_v110_stream * v)
{
int dbit = v->dbit;
unsigned char b = v->b;
- while (line < len) { /* sind schon alle matrizenzeilen abgearbeitet? */
- if ((line % 10) == 0) { /* die 0. zeile der matrix ist immer null ! */
- if (m[line] != 0x00) { /* nicht 0 ? dann fehler! */
+ while (line < len) { /* Are we done with all lines of the matrix? */
+ if ((line % 10) == 0) { /* the 0. line of the matrix is always 0 ! */
+ if (m[line] != 0x00) { /* not 0 ? -> error! */
#ifdef ISDN_V110_DEBUG
printk(KERN_DEBUG "isdn_v110: DecodeMatrix, V110 Bad Header\n");
+ /* returning now is not the right thing, though :-( */
#endif
-
-/*
- dann einen return zu machen, ist auch irgendwie nicht das richtige! :-(
- v->introducer = 0; v->dbit = 1; v->b = 0;
- return buflen; anzahl schon erzeugter daten zurückgeben!
- */
- }
- line++; /* sonst die nächste matrixzeile nehmen */
+ }
+ line++; /* next line of matrix */
continue;
- } else if ((line % 10) == 5) { /* in zeile 5 stehen nur e-bits ! */
- if ((m[line] & 0x70) != 0x30) { /* 011 muß am anfang stehen! */
+ } else if ((line % 10) == 5) { /* in line 5 there's only e-bits ! */
+ if ((m[line] & 0x70) != 0x30) { /* 011 has to be at the beginning! */
#ifdef ISDN_V110_DEBUG
printk(KERN_DEBUG "isdn_v110: DecodeMatrix, V110 Bad 5th line\n");
+ /* returning now is not the right thing, though :-( */
#endif
-/* dann einen return zu machen, ist auch irgendwie nicht das richtige! :-(
- v->introducer = 0; v->dbit = 1; v->b = 0;
- return buflen;
- */
}
- line++; /* alles klar, nächste zeile */
+ line++; /* next line */
continue;
} else if (!introducer) { /* every byte starts with 10 (stopbit, startbit) */
- introducer = (m[line] & mbit) ? 0 : 1; /* aktuelles bit der matrix */
+ introducer = (m[line] & mbit) ? 0 : 1; /* current bit of the matrix */
next_byte:
- if (mbit > 2) { /* war es das letzte bit dieser matrixzeile ? */
- mbit >>= 1; /* nein, nimm das nächste in dieser zeile */
+ if (mbit > 2) { /* was it the last bit in this line ? */
+ mbit >>= 1; /* no -> take next */
continue;
- } /* sonst links in der nächsten zeile anfangen */
+ } /* otherwise start with leftmost bit in the next line */
mbit = 64;
line++;
continue;
- } else { /* sonst müssen wir ein datenbit setzen */
- if (m[line] & mbit) /* war das bit in der matrix gesetzt ? */
- b |= dbit; /* ja, dann setz es auch im datenbyte */
+ } else { /* otherwise we need to set a data bit */
+ if (m[line] & mbit) /* was that bit set in the matrix ? */
+ b |= dbit; /* yes -> set it in the data byte */
else
- b &= dbit - 1; /* nein, lösch bit im datenbyte */
- if (dbit < 128) /* haben wir schon ein ganzes byte voll ? */
- dbit <<= 1; /* nein, auf zum nächsten datenbit */
- else { /* ein ganzes datenbyte ist voll */
- buf[buflen++] = b; /* byte in den output buffer kopieren */
- introducer = b = 0; /* Init der Introsequenz und des datenbytes */
- dbit = 1; /* als nächstes suchen wir das nullte bit */
+ b &= dbit - 1; /* no -> clear it in the data byte */
+ if (dbit < 128) /* is that data byte done ? */
+ dbit <<= 1; /* no, got the next bit */
+ else { /* data byte is done */
+ buf[buflen++] = b; /* copy byte into the output buffer */
+ introducer = b = 0; /* init of the intro sequence and of the data byte */
+ dbit = 1; /* next we look for the 0th bit */
}
- goto next_byte; /* suche das nächste bit in der matrix */
+ goto next_byte; /* look for next bit in the matrix */
}
}
v->introducer = introducer;
v->dbit = dbit;
v->b = b;
- return buflen; /* return anzahl der bytes im output buffer */
+ return buflen; /* return number of bytes in the output buffer */
}
-/* DecodeStream erhält vom input stream V110 kodierte Daten, die zu den
- V110 frames zusammengepackt werden müssen. Die Daten können an diese
- Schnittstelle so übergeben werden, wie sie von der Leitung kommen, ohne
- darauf achten zu müssen, das frames usw. eingehalten werden.
+/*
+ * DecodeStream receives V.110 coded data from the input stream. It recovers the
+ * original frames.
+ * The input stream doesn't need to be framed
*/
struct sk_buff *
isdn_v110_decode(isdn_v110_stream * v, struct sk_buff *skb)
dev_kfree_skb(skb);
return NULL; /* no, try later */
}
- if (ValidHeaderBytes(v) != v->nbytes) { /* ist es ein ungültiger header ? */
- SyncHeader(v); /* nein, such einen header */
+ if (ValidHeaderBytes(v) != v->nbytes) { /* is that a valid header? */
+ SyncHeader(v); /* no -> look for header */
goto ReSync;
}
len = (v->decodelen - (v->decodelen % (10 * v->nbytes))) / v->nbytes;
int introducer = 3;
int ibit[] = {0, 1, 1};
- while ((i < len) && (line < mlen)) { /* solange noch input da ist */
- switch (line % 10) { /* in welcher matrixzeile sind wir ? */
+ while ((i < len) && (line < mlen)) { /* while we still have input data */
+ switch (line % 10) { /* in which line of the matrix are we? */
case 0:
- m[line++] = 0x00; /* zeile 0 ist immer 0 */
- mbit = 128; /* und es geht mit dem 7. bit weiter */
+ m[line++] = 0x00; /* line 0 is always 0 */
+ mbit = 128; /* go on with the 7th bit */
break;
case 5:
- m[line++] = 0xbf; /* zeile 5 ist immer 10111111 */
- mbit = 128; /* und es geht mit dem 7. bit weiter */
+ m[line++] = 0xbf; /* line 5 is always 10111111 */
+ mbit = 128; /* go on with the 7th bit */
break;
}
if (line >= mlen) {
return line;
}
next_bit:
- switch (mbit) { /* ganz linkes oder rechtes bit ? */
+ switch (mbit) { /* leftmost or rightmost bit ? */
case 1:
- line++; /* ganz rechts ! dann in die nächste */
+ line++; /* rightmost -> go to next line */
if (line >= mlen) {
printk(KERN_WARNING "isdn_v110 (EncodeMatrix): buffer full!\n");
return line;
}
case 128:
- m[line] = 128; /* ganz links byte auf 1000000 setzen */
- mbit = 64; /* aktuelles bit in der matrixzeile */
+ m[line] = 128; /* leftmost -> set byte to 1000000 */
+ mbit = 64; /* current bit in the matrix line */
continue;
}
- if (introducer) { /* 110 sequenz setzen ? */
- introducer--; /* ein digit weniger setzen */
- m[line] |= ibit[introducer] ? mbit : 0; /* entsprechendes bit setzen */
- mbit >>= 1; /* bit der matrixzeile >> 1 */
- goto next_bit; /* und dort weiter machen */
- } /* else datenbits in die matrix packen! */
- m[line] |= (buf[i] & dbit) ? mbit : 0; /* datenbit in matrix setzen */
- if (dbit == 128) { /* war es das letzte datenbit ? */
- dbit = 1; /* dann mach beim nächsten weiter */
- i++; /* nächste datenbyte des input buffers */
- if (i < len) /* war es schon das letzte ? */
- introducer = 3; /* nein, schreib den introducer 110 */
- else { /* war das letzte datenbyte ! */
- m[line] |= (mbit - 1) & 0xfe; /* setz restliche bits der zeile auf 1 */
+ if (introducer) { /* set 110 sequence ? */
+ introducer--; /* set on digit less */
+ m[line] |= ibit[introducer] ? mbit : 0; /* set corresponding bit */
+ mbit >>= 1; /* bit of matrix line >> 1 */
+ goto next_bit; /* and go on there */
+ } /* else push data bits into the matrix! */
+ m[line] |= (buf[i] & dbit) ? mbit : 0; /* set data bit in matrix */
+ if (dbit == 128) { /* was it the last one? */
+ dbit = 1; /* then go on with first bit of */
+ i++; /* next byte in input buffer */
+ if (i < len) /* input buffer done ? */
+ introducer = 3; /* no, write introducer 110 */
+ else { /* input buffer done ! */
+ m[line] |= (mbit - 1) & 0xfe; /* set remaining bits in line to 1 */
break;
}
- } else /* nicht das letzte datenbit */
- dbit <<= 1; /* dann gehe zum nächsten datenbit */
- mbit >>= 1; /* und setz bit der matrix weiter */
+ } else /* not the last data bit */
+ dbit <<= 1; /* then go to next data bit */
+ mbit >>= 1; /* go to next bit of matrix */
goto next_bit;
}
- /* evtl. noch restliche zeilen in der matrix generieren... */
+ /* if necessary, generate remaining lines of the matrix... */
if ((line) && ((line + 10) < mlen))
switch (++line % 10) {
case 1:
case 9:
m[line++] = 0xfe;
}
- return line; /* soviele matrixzeilen sind es */
+ return line; /* that's how many lines we have */
}
/*
return nskb;
}
mlen = EncodeMatrix(skb->data, rlen, v110buf, size);
- /* jetzt noch jeweils 2 oder 4 bits auf den output stream verteilen! */
+ /* now distribute 2 or 4 bits each to the output stream! */
rbuf = skb_put(nskb, size);
olen = 0;
sval1 = 8 - v->nbits;
-/* $Id: isdn_v110.h,v 1.2 1999/10/30 09:49:28 keil Exp $
+/* $Id: isdn_v110.h,v 1.3 2000/03/16 16:34:12 kai Exp $
* Linux ISDN subsystem, V.110 related functions (linklevel).
*
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_v110.h,v $
+ * Revision 1.3 2000/03/16 16:34:12 kai
+ * some translation work
+ *
+ * there shouldn't be any German comments lurking around anymore ;-)
+ *
* Revision 1.2 1999/10/30 09:49:28 keil
* Reinit of v110 structs
*
#ifndef _isdn_v110_h_
#define _isdn_v110_h_
-/* isdn_v110_encode erhält len Nettodaten in buf, kodiert diese und liefert
- das Ergebnis wieder in buf. Wieviele Bytes kodiert wurden wird als
- return zurück gegeben. Diese Daten können dann 1:1 auf die Leitung
- gegeben werden.
-*/
+/*
+ * isdn_v110_encode will take raw data and encode it using V.110
+ */
extern struct sk_buff *isdn_v110_encode(isdn_v110_stream *, struct sk_buff *);
-/* isdn_v110_decode erhält vom input stream V110 kodierte Daten, die zu den
- V110 frames zusammengepackt werden müssen. Die Daten können an diese
- Schnittstelle so übergeben werden, wie sie von der Leitung kommen, ohne
- darauf achten zu müssen, das frames usw. eingehalten werden.
+/*
+ * isdn_v110_decode receives V.110 coded data from the stream and rebuilds
+ * frames from them. The source stream doesn't need to be framed.
*/
extern struct sk_buff *isdn_v110_decode(isdn_v110_stream *, struct sk_buff *);
continue;
/* read PCI IO base address and IRQ to check */
- pci_read_config_dword(net_dev, PCI_BASE_ADDRESS_0, &pci_iobase);
- pci_read_config_byte(net_dev, PCI_INTERRUPT_LINE, &pci_irqline);
+ pci_iobase = net_dev->base_address[0];
+ pci_irqline = net_dev->irq;
pci_iobase &= ~0x7f; /* mask off bit0~6 */
/* Enable Master/IO access, Disable memory access */
pci_write_config_byte(net_dev, PCI_LATENCY_TIMER, 0x80);
/* Read Chip revesion */
- pci_read_config_dword(net_dev, 8, &dev_rev);
+ pci_read_config_dword(net_dev, PCI_REVISION_ID, &dev_rev);
/* IO range check */
if (check_region(pci_iobase, CHK_IO_SIZE(pci_id, dev_rev))) {
}
/* No Tx resource check, it never happen normally */
if (db->tx_queue_cnt >= TX_FREE_DESC_CNT) {
- dev_kfree_skb(skb);
dev->tbusy = 1;
- return -EBUSY;
+ return 1;
}
/* transmit this packet */
txptr = db->tx_insert_ptr;
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 3 13:49:59 1997
- * Modified at: Fri Jan 14 21:07:20 2000
+ * Modified at: Sat Mar 11 07:41:54 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Sources: serial.c by Linus Torvalds
*
switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
irda_task_execute(self, __irport_change_speed, NULL, NULL,
(void *) irq->ifr_baudrate);
break;
case SIOCSDONGLE: /* Set dongle */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
/* Initialize dongle */
dongle = irda_device_dongle_init(dev, irq->ifr_dongle);
if (!dongle)
NULL);
break;
case SIOCSMEDIABUSY: /* Set media busy */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
irda_device_set_media_busy(self->netdev, TRUE);
break;
case SIOCGRECEIVING: /* Check if we are receiving right now */
irq->ifr_receiving = irport_is_receiving(self);
break;
case SIOCSDTRRTS:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
irport_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
break;
default:
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Tue Dec 9 21:18:38 1997
- * Modified at: Fri Jan 14 21:02:27 2000
+ * Modified at: Sat Mar 11 07:43:30 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Sources: slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
* Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
#include <asm/segment.h>
#include <asm/uaccess.h>
+#include <asm/termios.h>
#include <net/irda/irda.h>
#include <net/irda/irtty.h>
{
struct termios old_termios;
int cflag;
-
+
old_termios = *(self->tty->termios);
cflag = self->tty->termios->c_cflag;
{
struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
+ IRDA_DEBUG(2, __FUNCTION__ "(%ld)\n", jiffies);
+
if (!self || !self->netdev) {
IRDA_DEBUG(0, __FUNCTION__ "(), not ready yet!\n");
return;
self->tx_buff.data += actual;
self->tx_buff.len -= actual;
-
- self->stats.tx_packets++;
} else {
/*
* Now serial buffer is almost free & we can start
/* Tell network layer that we want more frames */
mark_bh(NET_BH);
}
+ self->stats.tx_packets++;
}
}
switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
irda_task_execute(self, irtty_change_speed, NULL, NULL,
(void *) irq->ifr_baudrate);
break;
case SIOCSDONGLE: /* Set dongle */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
/* Initialize dongle */
dongle = irda_device_dongle_init(dev, irq->ifr_dongle);
if (!dongle)
NULL);
break;
case SIOCSMEDIABUSY: /* Set media busy */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
irda_device_set_media_busy(self->netdev, TRUE);
break;
case SIOCGRECEIVING: /* Check if we are receiving right now */
irq->ifr_receiving = irtty_is_receiving(self);
break;
case SIOCSDTRRTS:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
irtty_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
break;
case SIOCSMODE:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
irtty_set_mode(dev, irq->ifr_mode);
break;
default:
* Status: Stable.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Nov 7 21:43:15 1998
- * Modified at: Wed Jan 26 13:00:29 2000
+ * Modified at: Fri Mar 10 11:53:26 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
nsc_ircc_change_speed(self, irq->ifr_baudrate);
break;
case SIOCSMEDIABUSY: /* Set media busy */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
irda_device_set_media_busy(self->netdev, TRUE);
break;
case SIOCGRECEIVING: /* Check if we are receiving right now */
switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
/* toshoboe_setbaud(self, irq->ifr_baudrate); */
/* Just change speed once - inserted by Paul Bristow */
self->new_speed = irq->ifr_baudrate;
break;
case SIOCSMEDIABUSY: /* Set media busy */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
irda_device_set_media_busy(self->netdev, TRUE);
break;
case SIOCGRECEIVING: /* Check if we are receiving right now */
* Status: Experimental.
* Author: Paul VanderSpek
* Created at: Wed Nov 4 11:46:16 1998
- * Modified at: Tue Jan 11 13:09:48 2000
+ * Modified at: Fri Mar 10 11:53:53 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
w83977af_change_speed(self, irq->ifr_baudrate);
break;
case SIOCSMEDIABUSY: /* Set media busy */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
irda_device_set_media_busy(self->netdev, TRUE);
break;
case SIOCGRECEIVING: /* Check if we are receiving right now */
*
* 6/8/99 - Official Release 0.2.0
* Merged into the kernel code
- *
- * 1/10/00 - Added Spinlocks for smp.
*
+ * 3/10/00 - Enabled FDX and fixed bugs produced thereafter.
+ * Put in smp code
* 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
*/
static char *version =
-"Olympic.c v0.2.1 1/10/00 - Peter De Schrijver & Mike Phillips" ;
+"Olympic.c v0.4.0 3/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)",
#if OLYMPIC_NETWORK_MONITOR
writew(ntohs(OPEN_ADAPTER_ENABLE_FDX | OPEN_ADAPTER_PASS_ADC_MAC | OPEN_ADAPTER_PASS_ATT_MAC | OPEN_ADAPTER_PASS_BEACON),init_srb+8);
#else
- writew(OPEN_ADAPTER_ENABLE_FDX,init_srb+8);
+ writew(ntohs(OPEN_ADAPTER_ENABLE_FDX),init_srb+8);
#endif
if (olympic_priv->olympic_laa[0]) {
if (!(sisr & SISR_MI)) /* Interrupt isn't for us */
return ;
- spin_lock(&olympic_priv->olympic_lock) ;
+ 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)
__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;
}
+ spin_lock_irqsave(&olympic_priv->olympic_lock, flags) ;
+
if(olympic_priv->free_tx_ring_entries) {
olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].buffer=virt_to_bus(skb->data);
olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].status_length=skb->len | (0x80000000);
writew((((readw(olympic_mmio+TXENQ_1)) & 0x8000) ^ 0x8000) | 1,olympic_mmio+TXENQ_1);
dev->tbusy=0;
- spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags) ;
+ spin_unlock_irqrestore(&olympic_priv->olympic_lock, flags) ;
return 0;
} else {
- spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags) ;
+ spin_unlock_irqrestore(&olympic_priv->olympic_lock, flags) ;
return 1;
- }
-
+ }
}
options = olympic_priv->olympic_copy_all_options;
if (dev->flags&IFF_PROMISC)
- options |= (3<<5) ; /* All LLC and MAC frames, all through the main rx channel */
+ options |= 0x61 ;
else
- options &= ~(3<<5) ;
+ options &= ~0x61 ;
if (dev->mc_count) {
set_mc_list = 1 ;
__u16 lan_status = 0, lan_status_diff ; /* Initialize to stop compiler warning */
__u8 fdx_prot_error ;
__u16 next_ptr;
-
+ int i ;
#if OLYMPIC_NETWORK_MONITOR
struct trh_hdr *mac_hdr ;
#endif
/* Is the ASB free ? */
- if (!(readl(olympic_priv->olympic_mmio + SISR) & SISR_ASB_FREE)) {
+ if (readb(asb_block + 2) != 0xff) {
olympic_priv->asb_queued = 1 ;
writel(LISR_ASB_FREE_REQ,olympic_priv->olympic_mmio+LISR_SUM);
return ;
return ;
} else if (readb(arb_block) == ARB_LAN_CHANGE_STATUS) { /* Lan.change.status */
- lan_status = readw(arb_block+6);
+ lan_status = ntohs(readw(arb_block+6)) ;
fdx_prot_error = readb(arb_block+8) ;
/* Issue ARB Free */
dev->tbusy = 1 ;
dev->interrupt = 1 ;
dev->start = 0 ;
+
olympic_priv->srb = readw(olympic_priv->olympic_lap + LAPWWO) ;
+ olympic_priv->rx_status_last_received++;
+ olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1;
+ for(i=0;i<OLYMPIC_RX_RING_SIZE;i++) {
+ dev_kfree_skb(olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received]);
+ olympic_priv->rx_status_last_received++;
+ olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1;
+ }
+
free_irq(dev->irq,dev);
printk(KERN_WARNING "%s: Adapter has been closed \n", dev->name) ;
-
+ MOD_DEC_USE_COUNT ;
} /* If serious error */
if (olympic_priv->olympic_message_level) {
__u8 *olympic_mmio;
__u8 *olympic_lap;
- spinlock_t olympic_lock ;
+ spinlock_t olympic_lock ;
volatile int srb_queued; /* True if an SRB is still posted */
struct wait_queue *srb_wait;
__u8 phys_addr[4] ;
__u8 up_node_addr[6] ;
- __u8 up_phys_addr[6] ;
+ __u8 up_phys_addr[4] ;
__u8 poll_addr[6] ;
__u16 reserved ;
__u16 acc_priority ;
static int AdapterNum = 0;
-#ifdef MODULE
static int rate[SKTR_MAX_ADAPTERS] = { SPEED_16, };
-#endif
/* Use 0 for production, 1 for verification, 2 for debug, and
* 3 for very verbose debug.
#ifdef CONFIG_SCSI_PLUTO_MODULE
#define SD_EXTRA_DEVS 40
#else
-#define SD_EXTRA_DEVS 16
+#define SD_EXTRA_DEVS 21
#endif
-#define ST_EXTRA_DEVS 2
-#define SR_EXTRA_DEVS 4
+#define ST_EXTRA_DEVS 3
+#define SR_EXTRA_DEVS 8
#define SG_EXTRA_DEVS (SD_EXTRA_DEVS + SR_EXTRA_DEVS + ST_EXTRA_DEVS)
#endif
*
* Linux MegaRAID device driver
*
- * Copyright 1998 American Megatrends Inc.
+ * Copyright 1999 American Megatrends Inc.
*
* 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 of the License, or (at your option) any later version.
*
- * Version : 1.04
+ * Version : 1.07b
*
* Description: Linux device driver for AMI MegaRAID controller
*
* The addtional 32 bit field for 64bit address in the newly defined
* mailbox64 structure is set to 0 at this point.
*
+ * Version 1.05
+ * Changed the queing implementation for handling SCBs and completed
+ * commands.
+ * Added spinlocks in the interrupt service routine to enable the dirver
+ * function in the SMP environment.
+ * Fixed the problem of unnecessary aborts in the abort entry point, which
+ * also enables the driver to handle large amount of I/O requests for
+ * long duration of time.
+ *
+ * Version 1.07
+ * Removed the usage of uaccess.h file for kernel versions less than
+ * 2.0.36, as this file is not present in those versions.
+ *
+ * Version 1.07b
+ * The MegaRAID 466 cards with 3.00 firmware lockup and seem to very
+ * occasionally hang. We check such cards and report them. You can
+ * get firmware upgrades to flash the board to 3.10 for free.
+ *
* BUGS:
* Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that
* fails to detect the controller as a pci device on the system.
#define CRLFSTR "\n"
#define IOCTL_CMD_NEW 0x81
-#define MEGARAID_VERSION "v1.04 (August 16, 1999)"
+#define MEGARAID_VERSION "v107 (December 22, 1999)"
+
#include <linux/config.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/malloc.h>
#include <linux/ioport.h>
#include <linux/fcntl.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/irq.h>
+#if LINUX_VERSION_CODE > 0x020024
#include <asm/uaccess.h>
+#endif
#include "sd.h"
#include "scsi.h"
#define MAX_SERBUF 160
#define COM_BASE 0x2f8
-#define ENQUEUE(obj,type,list,next) \
-{ type **node; long cpuflag; \
- spin_lock_irqsave(&mega_lock,cpuflag);\
- for(node=&(list); *node; node=(type **)&(*node)->##next); \
- (*node) = obj; \
- (*node)->##next = NULL; \
- spin_unlock_irqrestore(&mega_lock,cpuflag);\
-}
-
-/* a non-locking version (if we already have the lock) */
-#define ENQUEUE_NL(obj,type,list,next) \
-{ type **node; \
- for(node=&(list); *node; node=(type **)&(*node)->##next); \
- (*node) = obj; \
- (*node)->##next = NULL; \
-}
-
-#define DEQUEUE(obj,type,list,next) \
-{ long cpuflag; \
- spin_lock_irqsave(&mega_lock,cpuflag);\
- if ((obj=list) != NULL) {\
- list = (type *)(list)->##next; \
- } \
- spin_unlock_irqrestore(&mega_lock,cpuflag);\
-};
u32 RDINDOOR (mega_host_config * megaCfg)
{
u_char * mboxData,
mega_scb * scb,
int intr);
-static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
+static int mega_build_sglist (mega_host_config * megaCfg, mega_scb * scb,
u32 * buffer, u32 * length);
static int mega_busyWaitMbox(mega_host_config *);
static void mega_runpendq (mega_host_config *);
-static void mega_rundoneq (void);
+static void mega_rundoneq (mega_host_config *);
static void mega_cmd_done (mega_host_config *, mega_scb *, int);
static mega_scb *mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt);
-static inline void freeSgList(mega_host_config *megaCfg);
+static inline void mega_freeSgList(mega_host_config *megaCfg);
static void mega_Convert8ldTo40ld( mega_RAIDINQ *inquiry,
mega_Enquiry3 *enquiry3,
megaRaidProductInfo *productInfo );
+
+
+
+#if LINUX_VERSION_CODE > 0x020100
+# include <asm/spinlock.h>
+# include <linux/smp.h>
+# define cpuid smp_processor_id()
+# if LINUX_VERSION_CODE < 0x020195
+# define DRIVER_LOCK_T unsigned long cpu_flags = 0;
+# define DRIVER_LOCK_INIT(p) \
+ spin_lock_init(&p->mega_lock);
+# define DRIVER_LOCK(p) \
+ if(!p->cpu_lock_count[cpuid]) { \
+ spin_lock_irqsave(&p->mega_lock, cpu_flags); \
+ p->cpu_lock_count[cpuid]++; \
+ } else { \
+ p->cpu_lock_count[cpuid]++; \
+ }
+# define DRIVER_UNLOCK(p) \
+ if(--p->cpu_lock_count[cpuid] == 0) \
+ spin_unlock_irqrestore(&p->mega_lock, cpu_flags);
+# define IO_LOCK(p) spin_lock_irqsave(&io_request_lock,cpu_flags);
+# define IO_UNLOCK(p) spin_unlock_irqrestore(&io_request_lock,cpu_flags);
+# else
+# define DRIVER_LOCK_T
+# define DRIVER_LOCK_INIT(p)
+# define DRIVER_LOCK(p)
+# define DRIVER_UNLOCK(p)
+# define IO_LOCK_T unsigned long io_flags = 0;
+# define IO_LOCK spin_lock_irqsave(&io_request_lock,io_flags);
+# define IO_UNLOCK spin_unlock_irqrestore(&io_request_lock,io_flags);
+# endif
+#else
+# define cpuid 0
+# define DRIVER_LOCK_T long cpu_flags;
+# define DRIVER_LOCK_INIT(p)
+# define DRIVER_LOCK(p) \
+ save_flags(cpu_flags); \
+ cli();
+# define DRIVER_UNLOCK(p) \
+ restore_flags(cpu_flags);
+# define IO_LOCK_T unsigned long io_flags = 0;
+# define IO_LOCK(p) DRIVER_LOCK(p)
+# define IO_UNLOCK(p) DRIVER_UNLOCK(p)
+# define le32_to_cpu(x) (x)
+# define cpu_to_le32(x) (x)
+#endif
+
/* set SERDEBUG to 1 to enable serial debugging */
#define SERDEBUG 0
#if SERDEBUG
/* Use "megaraid=skipXX" as LILO option to prohibit driver from scanning
XX scsi id on each channel. Used for Madrona motherboard, where SAF_TE
processor id cannot be scanned */
+
static char *megaraid;
#if LINUX_VERSION_CODE > 0x20100
#ifdef MODULE
static mega_scb *pLastScb = NULL;
-/* Queue of pending/completed SCBs */
-static Scsi_Cmnd *qCompleted = NULL;
#if SERDEBUG
volatile static spinlock_t serial_lock;
#endif
-volatile static spinlock_t mega_lock;
struct proc_dir_entry proc_scsi_megaraid =
{
#define TRACE(A)
#endif
-void callDone (Scsi_Cmnd * SCpnt)
+static void callDone (Scsi_Cmnd * SCpnt)
{
if (SCpnt->result) {
TRACE (("*** %.08lx %.02x <%d.%d.%d> = %x\n", SCpnt->serial_number,
* Free a SCB structure
*=======================
*/
-static void freeSCB (mega_host_config *megaCfg, mega_scb * pScb)
+static void mega_freeSCB (mega_host_config *megaCfg, mega_scb * pScb)
{
- mega_scb **ppScb;
+
+ mega_scb *pScbtmp;
+
+ if ((pScb == NULL) || (pScb->idx >= 0xFE)) {
+ return ;
+ }
/* Unlink from pending queue */
- for(ppScb=&megaCfg->qPending; *ppScb; ppScb=&(*ppScb)->next) {
- if (*ppScb == pScb) {
- *ppScb = pScb->next;
+
+ if(pScb == megaCfg->qPendingH) {
+ if(megaCfg->qPendingH == megaCfg->qPendingT )
+ megaCfg->qPendingH = megaCfg->qPendingT = NULL;
+ else {
+ megaCfg->qPendingH = megaCfg->qPendingH->next;
+ }
+ megaCfg->qPcnt--;
+ }
+ else {
+ for(pScbtmp=megaCfg->qPendingH; pScbtmp; pScbtmp=pScbtmp->next) {
+ if (pScbtmp->next == pScb) {
+ pScbtmp->next = pScb->next;
+ if(pScb == megaCfg->qPendingT) {
+ megaCfg->qPendingT = pScbtmp;
+ }
+ megaCfg->qPcnt--;
break;
}
}
+ }
- /* Link back into list */
+ /* Link back into free list */
pScb->state = SCB_FREE;
pScb->SCpnt = NULL;
- pScb->next = megaCfg->qFree;
- megaCfg->qFree = pScb;
+ if(megaCfg->qFreeH == (mega_scb *) NULL ) {
+ megaCfg->qFreeH = megaCfg->qFreeT = pScb;
+ }
+ else {
+ megaCfg->qFreeT->next = pScb;
+ megaCfg->qFreeT = pScb;
+ }
+ megaCfg->qFreeT->next = NULL;
+ megaCfg->qFcnt++;
+
}
/*===========================
* Allocate a SCB structure
*===========================
*/
-static mega_scb * allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
+static mega_scb * mega_allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
{
mega_scb *pScb;
/* Unlink command from Free List */
- if ((pScb = megaCfg->qFree) != NULL) {
- megaCfg->qFree = pScb->next;
+ if ((pScb = megaCfg->qFreeH) != NULL) {
+ megaCfg->qFreeH = pScb->next;
+ megaCfg->qFcnt--;
pScb->isrcount = jiffies;
pScb->next = NULL;
* Initialize SCB structures
*================================================
*/
-static int initSCB (mega_host_config * megaCfg)
+static int mega_initSCB (mega_host_config * megaCfg)
{
int idx;
- megaCfg->qFree = NULL;
+ megaCfg->qFreeH = NULL;
+ megaCfg->qFcnt = 0;
+#if DEBUG
+if(megaCfg->max_cmds >= MAX_COMMANDS) {
+printk("megaraid:ctlr max cmds = %x : MAX_CMDS = %x", megaCfg->max_cmds, MAX_COMMANDS);
+}
+#endif
+
for (idx = megaCfg->max_cmds-1; idx >= 0; idx--) {
megaCfg->scbList[idx].idx = idx;
megaCfg->scbList[idx].sgList = kmalloc(sizeof(mega_sglist) * MAX_SGLIST,
GFP_ATOMIC | GFP_DMA);
if (megaCfg->scbList[idx].sgList == NULL) {
printk(KERN_WARNING "Can't allocate sglist for id %d\n",idx);
- freeSgList(megaCfg);
+ mega_freeSgList(megaCfg);
return -1;
}
if (idx < MAX_COMMANDS) {
/* Link to free list */
- freeSCB(megaCfg, &megaCfg->scbList[idx]);
+ mega_freeSCB(megaCfg, &megaCfg->scbList[idx]);
}
}
return 0;
}
/* Run through the list of completed requests */
-static void mega_rundoneq ()
+static void mega_rundoneq (mega_host_config *megaCfg)
{
Scsi_Cmnd *SCpnt;
- while (1) {
- DEQUEUE (SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
- if (SCpnt == NULL)
- return;
+ while ((SCpnt = megaCfg->qCompletedH) != NULL) {
+ megaCfg->qCompletedH = (Scsi_Cmnd *)SCpnt->host_scribble;
+ megaCfg->qCcnt--;
+ SCpnt->host_scribble = (unsigned char *) NULL ; // XC : sep 14
/* Callback */
callDone (SCpnt);
}
+ megaCfg->qCompletedH = megaCfg->qCompletedT = NULL;
}
/*
- Runs through the list of pending requests
- Assumes that mega_lock spin_lock has been acquired.
-*/
+ * Runs through the list of pending requests
+ * Assumes that mega_lock spin_lock has been acquired.
+ */
static void mega_runpendq(mega_host_config *megaCfg)
{
mega_scb *pScb;
/* Issue any pending commands to the card */
- for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
+ for(pScb=megaCfg->qPendingH; pScb; pScb=pScb->next) {
if (pScb->state == SCB_ACTIVE) {
- megaIssueCmd(megaCfg, pScb->mboxData, pScb, 1);
+ if(megaIssueCmd(megaCfg, pScb->mboxData, pScb, 1))
+ return;
}
}
}
/* Add command to the list of completed requests */
-static void mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb,
+static void
+mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb,
int status)
{
int islogical;
}
SCpnt = pScb->SCpnt;
- /*freeSCB(megaCfg, pScb);*/ /*delay this to the end of this func.*/
pthru = &pScb->pthru;
mbox = (mega_mailbox *) &pScb->mboxData;
TRACE(("pScb->idx = ",pScb->idx));
TRACE(("pScb->state = ",pScb->state));
TRACE(("pScb->state = ",pScb->state));
- printk("Problem...!\n");
+ printk("megaraid:Problem...!\n");
while(1);
}
/* not IOCTL_CMD_NEW SCB, freeSCB()*/
/* For IOCTL_CMD_NEW SCB, delay freeSCB() in megaraid_queue()
* after copy data back to user space*/
- freeSCB(megaCfg, pScb);
+ mega_freeSCB(megaCfg, pScb);
/* Add Scsi_Command to end of completed queue */
- ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+ if( megaCfg->qCompletedH == NULL ) {
+ megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
+ }
+ else {
+ megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
+ megaCfg->qCompletedT = SCpnt;
+ }
+ megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
+ megaCfg->qCcnt++;
}
/*-------------------------------------------------------------------
if ( islogical ) {
lun = (SCpnt->target * 8) + lun;
-#if 1
if ( lun > FC_MAX_LOGICAL_DRIVES ){
SCpnt->result = (DID_BAD_TARGET << 16);
callDone (SCpnt);
return NULL;
}
-#endif
}
/*-----------------------------------------------------
*
case READ_CAPACITY:
case INQUIRY:
/* Allocate a SCB and initialize passthru */
- if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
+ if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
SCpnt->result = (DID_ERROR << 16);
callDone (SCpnt);
return NULL;
case READ_10:
case WRITE_10:
/* Allocate a SCB and initialize mailbox */
- if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
+ if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
SCpnt->result = (DID_ERROR << 16);
callDone (SCpnt);
return NULL;
}
/* Calculate Scatter-Gather info */
- mbox->numsgelements = build_sglist (megaCfg, pScb,
+ mbox->numsgelements = mega_build_sglist (megaCfg, pScb,
(u32 *) & mbox->xferaddr,
(u32 *) & seg);
*-----------------------------------------------------*/
else {
/* Allocate a SCB and initialize passthru */
- if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
+ if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
SCpnt->result = (DID_ERROR << 16);
callDone (SCpnt);
return NULL;
pthru->cdblen = SCpnt->cmd_len;
memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len);
- pthru->numsgelements = build_sglist (megaCfg, pScb,
+ pthru->numsgelements = mega_build_sglist (megaCfg, pScb,
(u32 *) & pthru->dataxferaddr,
(u32 *) & pthru->dataxferlen);
unsigned char *data = (unsigned char *)SCpnt->request_buffer;
int i;
- if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
+ if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
SCpnt->result = (DID_ERROR << 16);
callDone (SCpnt);
return NULL;
}
-#if 0
- printk("\nBUF: ");
- for (i=0;i<18;i++) {
- printk(" %x",data[i]);
- }
- printk("......\n");
-#endif
-
mboxdata = (u8 *) & pScb->mboxData;
mbox = (mega_ioctl_mbox *) & pScb->mboxData;
mailbox = (mega_mailbox *) & pScb->mboxData;
mailbox->cmd = MEGA_MBOXCMD_PASSTHRU;
mailbox->xferaddr = virt_to_bus (pthru);
- pthru->numsgelements = build_sglist (megaCfg, pScb,
+ pthru->numsgelements = mega_build_sglist (megaCfg, pScb,
(u32 *) & pthru->dataxferaddr,
(u32 *) & pthru->dataxferlen);
}
/* else normal (nonpassthru) command */
+#if LINUX_VERSION_CODE > 0x020024
+/*
+ * usage of the function copy from user is used in case of data more than
+ * 4KB. This is used only with adapters which supports more than 8 logical
+ * drives. This feature is disabled on kernels earlier or same as 2.0.36
+ * as the uaccess.h file is not available with those kernels.
+ */
+
if (SCpnt->cmnd[0] == IOCTL_CMD_NEW) {
/* use external data area for large xfers */
/* If cmnd[0] is set to IOCTL_CMD_NEW then *
copy_from_user(kern_area,user_area,xfer_size);
pScb->kern_area = kern_area;
}
+#endif
mbox->cmd = data[0];
mbox->channel = data[1];
}
else {
- mbox->numsgelements = build_sglist (megaCfg, pScb,
+ mbox->numsgelements = mega_build_sglist (megaCfg, pScb,
(u32 *) & mbox->xferaddr,
(u32 *) & seg);
}
#endif
+#if DEBUG
+static unsigned int cum_time = 0;
+static unsigned int cum_time_cnt = 0;
+#endif
+
/*--------------------------------------------------------------------
* Interrupt service routine
*--------------------------------------------------------------------*/
static void megaraid_isr (int irq, void *devp, struct pt_regs *regs)
{
+#if LINUX_VERSION_CODE >= 0x20100
+ IO_LOCK_T
+#endif
mega_host_config *megaCfg;
u_char byte, idx, sIdx, tmpBox[MAILBOX_SIZE];
- u32 dword;
+ u32 dword=0;
mega_mailbox *mbox;
mega_scb *pScb;
- long flags;
- int qCnt, qStatus;
+ u_char qCnt, qStatus;
+ u_char completed[MAX_FIRMWARE_STATUS];
+ Scsi_Cmnd *SCpnt;
megaCfg = (mega_host_config *) devp;
mbox = (mega_mailbox *)tmpBox;
-#if LINUX_VERSION_CODE >= 0x20100
- spin_lock_irqsave (&io_request_lock, flags);
-#endif
-
- while (megaCfg->host->irq == irq) {
-
- spin_lock_irqsave (&mega_lock, flags);
+ if (megaCfg->host->irq == irq) {
if (megaCfg->flag & IN_ISR) {
TRACE (("ISR called reentrantly!!\n"));
+ printk ("ISR called reentrantly!!\n");
}
megaCfg->flag |= IN_ISR;
printk(KERN_WARNING "Error: mailbox busy in isr!\n");
}
-
/* Check if a valid interrupt is pending */
if (megaCfg->flag & BOARD_QUARTZ) {
dword = RDOUTDOOR (megaCfg);
if (dword != 0x10001234) {
/* Spurious interrupt */
megaCfg->flag &= ~IN_ISR;
- spin_unlock_irqrestore (&mega_lock, flags);
- break;
+ return;
}
- WROUTDOOR (megaCfg, dword);
-
- /* Copy to temp location */
- memcpy(tmpBox, (mega_mailbox *)megaCfg->mbox, MAILBOX_SIZE);
-
- /* Acknowledge interrupt */
- WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
- while (RDINDOOR (megaCfg) & 0x02);
}
else {
byte = READ_PORT (megaCfg->host->io_port, INTR_PORT);
if ((byte & VALID_INTR_BYTE) == 0) {
/* Spurious interrupt */
megaCfg->flag &= ~IN_ISR;
- spin_unlock_irqrestore (&mega_lock, flags);
- break;
+ return;
}
WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
+ }
- /* Copy to temp location */
- memcpy(tmpBox, (mega_mailbox *)megaCfg->mbox, MAILBOX_SIZE);
+ for(idx=0;idx<MAX_FIRMWARE_STATUS;idx++ ) completed[idx] = 0;
+#if LINUX_VERSION_CODE >= 0x20100
+ IO_LOCK;
+#endif
+
+ qCnt = 0xff;
+ while ((qCnt = megaCfg->mbox->numstatus) == 0xFF)
+ ;
+
+ qStatus = 0xff;
+ while ((qStatus = megaCfg->mbox->status) == 0xFF)
+ ;
+
+ /* Get list of completed requests */
+ for (idx = 0; idx<qCnt; idx++) {
+ while ((sIdx = megaCfg->mbox->completed[idx]) == 0xFF) {
+ printk("p");
+ }
+ completed[idx] = sIdx;
+ sIdx = 0xFF;
+ }
+
+ if (megaCfg->flag & BOARD_QUARTZ) {
+ WROUTDOOR (megaCfg, dword);
/* Acknowledge interrupt */
+ WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
+ while (RDINDOOR (megaCfg) & 0x02);
+ }
+ else {
CLEAR_INTR (megaCfg->host->io_port);
}
- qCnt = mbox->numstatus;
- qStatus = mbox->status;
+#if DEBUG
+ if(qCnt >= MAX_FIRMWARE_STATUS) {
+ printk("megaraid_isr: cmplt=%d ", qCnt);
+ }
+#endif
for (idx = 0; idx < qCnt; idx++) {
- sIdx = mbox->completed[idx];
- if (sIdx > 0) {
+ sIdx = completed[idx];
+ if ((sIdx > 0) && (sIdx <= MAX_COMMANDS)) {
pScb = &megaCfg->scbList[sIdx - 1];
/* ASSERT(pScb->state == SCB_ISSUED); */
#if DEBUG
if (((jiffies) - pScb->isrcount) > maxCmdTime) {
maxCmdTime = (jiffies) - pScb->isrcount;
- printk("cmd time = %u\n", maxCmdTime);
+ printk("megaraid_isr : cmd time = %u\n", maxCmdTime);
}
#endif
-
+/*
+ * Assuming that the scsi command, for which an abort request was received
+ * earlier has completed.
+ */
if (pScb->state == SCB_ABORTED) {
- printk("Received aborted SCB! %u\n", (int)((jiffies)-pScb->isrcount));
+ SCpnt = pScb->SCpnt;
+ }
+ if (pScb->state == SCB_RESET) {
+ SCpnt = pScb->SCpnt;
+ mega_freeSCB (megaCfg, pScb);
+ SCpnt->result = (DID_RESET << 16) ;
+ if( megaCfg->qCompletedH == NULL ) {
+ megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
+ }
+ else {
+ megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
+ megaCfg->qCompletedT = SCpnt;
+ }
+ megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
+ megaCfg->qCcnt++;
+ continue;
}
if (*(pScb->SCpnt->cmnd)==IOCTL_CMD_NEW)
mega_cmd_done(megaCfg, pScb, qStatus);
}
-
+ else {
+ printk("megaraid: wrong cmd id completed from firmware:id=%x\n",sIdx);
+ for(;;);
+ }
}
- spin_unlock_irqrestore (&mega_lock, flags);
-
- megaCfg->flag &= ~IN_ISR;
- mega_rundoneq();
+ mega_rundoneq(megaCfg);
+ megaCfg->flag &= ~IN_ISR;
/* Loop through any pending requests */
- spin_lock_irqsave(&mega_lock, flags);
mega_runpendq(megaCfg);
- spin_unlock_irqrestore(&mega_lock,flags);
+#if LINUX_VERSION_CODE >= 0x20100
+ IO_UNLOCK;
+#endif
}
-#if LINUX_VERSION_CODE >= 0x20100
- spin_unlock_irqrestore (&io_request_lock, flags);
-#endif
}
/*==================================================*/
mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;
u_char byte;
u32 cmdDone;
- Scsi_Cmnd *SCpnt;
u32 phys_mbox;
u8 retval=-1;
phys_mbox = virt_to_bus (megaCfg->mbox);
-#if 0
- if (intr && mbox->busy) {
- return 0;
- }
-#endif
-
#if DEBUG
showMbox(pScb);
#endif
/* Wait until mailbox is free */
- while (mega_busyWaitMbox (megaCfg)) {
+ if (mega_busyWaitMbox (megaCfg)) {
printk("Blocked mailbox......!!\n");
udelay(1000);
/* Abort command */
if (pScb == NULL) {
- printk("NULL pScb in megaIssue\n");
TRACE(("NULL pScb in megaIssue\n"));
+ printk("NULL pScb in megaIssue\n");
}
- SCpnt = pScb->SCpnt;
- freeSCB(megaCfg, pScb);
-
- SCpnt->result = (DID_ABORT << 16);
- callDone(SCpnt);
+ mega_cmd_done (megaCfg, pScb, 0x08);
return -1;
}
if (pScb) {
mega_cmd_done (megaCfg, pScb, mbox->status);
- mega_rundoneq ();
}
WRINDOOR (megaCfg, phys_mbox | 0x2);
while (!((byte = READ_PORT (megaCfg->host->io_port, INTR_PORT)) & INTR_VALID));
WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
-
ENABLE_INTR (megaCfg->host->io_port);
CLEAR_INTR (megaCfg->host->io_port);
if (pScb) {
mega_cmd_done (megaCfg, pScb, mbox->status);
- mega_rundoneq ();
}
else {
TRACE (("Error: NULL pScb!\n"));
}
-
}
enable_irq(megaCfg->host->irq);
retval=mbox->status;
}
+#if DEBUG
while (mega_busyWaitMbox (megaCfg)) {
printk("Blocked mailbox on exit......!\n");
udelay(1000);
}
+#endif
return retval;
}
/*-------------------------------------------------------------------
* Copies data to SGLIST
*-------------------------------------------------------------------*/
-static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
+static int mega_build_sglist (mega_host_config * megaCfg, mega_scb * scb,
u32 * buffer, u32 * length)
{
struct scatterlist *sgList;
paddr = (paddr + 4 + 16) & 0xfffffff0;
/* Register mailbox area with the firmware */
- if (megaCfg->flag & BOARD_QUARTZ) {
- }
- else {
+ if (!(megaCfg->flag & BOARD_QUARTZ)) {
WRITE_PORT (megaCfg->host->io_port, MBOX_PORT0, paddr & 0xFF);
WRITE_PORT (megaCfg->host->io_port, MBOX_PORT1, (paddr >> 8) & 0xFF);
WRITE_PORT (megaCfg->host->io_port, MBOX_PORT2, (paddr >> 16) & 0xFF);
u32 paddr;
u8 retval;
- spin_lock_init (&mega_lock);
-
/* Initialize adapter inquiry mailbox*/
paddr = virt_to_bus (megaCfg->mega_buffer);
mbox = (mega_mailbox *) mboxData;
/*(megaCfg->flag & BOARD_40LD)?FC_MAX_TARGETS_PER_CHANNEL:MAX_TARGET+1;*/
megaCfg->host->max_lun = /* max lun */
(megaCfg->flag & BOARD_40LD) ? FC_MAX_LOGICAL_DRIVES : MAX_LOGICAL_DRIVES;
+ megaCfg->host->cmd_per_lun = MAX_CMD_PER_LUN;
megaCfg->numldrv = enquiry3Pnt->numLDrv;
megaCfg->max_cmds = megaCfg->productInfo.MaxConcCmds;
+ if(megaCfg->max_cmds > MAX_COMMANDS) megaCfg->max_cmds = MAX_COMMANDS - 1;
-#if 0
- int i;
- printk (KERN_DEBUG "---- Logical drive info from enquiry3 struct----\n");
- for (i = 0; i < megaCfg->numldrv; i++) {
- printk ("%d: size: %d prop: %x state: %x\n", i,
- enquiry3Pnt->lDrvSize[i],
- enquiry3Pnt->lDrvProp[i],
- enquiry3Pnt->lDrvState[i]);
- }
+ megaCfg->host->can_queue = megaCfg->max_cmds;
- printk (KERN_DEBUG "---- Physical drive info ----\n");
- for (i = 0; i < FC_MAX_PHYSICAL_DEVICES; i++) {
- if (i && !(i % 8))
- printk ("\n");
- printk ("%d: %x ", i, enquiry3Pnt->pDrvState[i]);
+ if (megaCfg->host->can_queue >= MAX_COMMANDS) {
+ megaCfg->host->can_queue = MAX_COMMANDS-1;
}
- printk ("\n");
-#endif
#ifdef HP /* use HP firmware and bios version encoding */
sprintf (megaCfg->fwVer, "%c%d%d.%d%d",
return 0;
}
-int findCard (Scsi_Host_Template * pHostTmpl,
+int mega_findCard (Scsi_Host_Template * pHostTmpl,
u16 pciVendor, u16 pciDev,
long flag)
{
#if LINUX_VERSION_CODE < 0x20100
while (!pcibios_find_device (pciVendor, pciDev, pciIdx, &pciBus, &pciDevFun)) {
-
-#if 0
- } /* keep auto-indenters happy */
-#endif
#else
struct pci_dev *pdev = pci_devices;
#endif
if ((flag & BOARD_QUARTZ) && (skip_id == -1)) {
u16 magic;
+#if LINUX_VERSION_CODE < 0x20100
pcibios_read_config_word (pciBus, pciDevFun,
PCI_CONF_AMISIG,
&magic);
- if (magic != AMI_SIGNATURE) {
+#else
+ pci_read_config_word (pdev, PCI_CONF_AMISIG, &magic);
+#endif
+ if ((magic != AMI_SIGNATURE) && (magic != AMI_SIGNATURE_471) ){
pciIdx++;
continue; /* not an AMI board */
}
host->host_no, (u_int) megaBase, megaIrq);
/* Copy resource info into structure */
- megaCfg->qPending = NULL;
- megaCfg->qFree = NULL;
+ megaCfg->qCompletedH = NULL;
+ megaCfg->qCompletedT = NULL;
+ megaCfg->qPendingH = NULL;
+ megaCfg->qPendingT = NULL;
+ megaCfg->qFreeH = NULL;
+ megaCfg->qFreeT = NULL;
+ megaCfg->qFcnt = 0;
+ megaCfg->qPcnt = 0;
+ megaCfg->qCcnt = 0;
megaCfg->flag = flag;
megaCfg->host = host;
megaCfg->base = megaBase;
mega_register_mailbox (megaCfg, virt_to_bus ((void *) &megaCfg->mailbox64));
mega_i_query_adapter (megaCfg);
-
+
+ if (flag == BOARD_QUARTZ) {
+ /* Check to see if this is a Dell PERC RAID controller model 466 */
+ u16 subsysid, subsysvid;
+#if LINUX_VERSION_CODE < 0x20100
+ pcibios_read_config_word (pciBus, pciDevFun,
+ PCI_SUBSYSTEM_VENDOR_ID,
+ &subsysvid);
+ pcibios_read_config_word (pciBus, pciDevFun,
+ PCI_SUBSYSTEM_ID,
+ &subsysid);
+#else
+ pci_read_config_word (pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsysvid);
+ pci_read_config_word (pdev, PCI_SUBSYSTEM_ID, &subsysid);
+#endif
+ if ( (subsysid == 0x1111) && (subsysvid == 0x1111) &&
+ (!strcmp(megaCfg->fwVer,"3.00") || !strcmp(megaCfg->fwVer,"3.01"))) {
+ printk(KERN_WARNING
+"megaraid: Your card is a Dell PERC 2/SC RAID controller with firmware\n"
+"megaraid: 3.00 or 3.01. This driver is known to have corruption issues\n"
+"megaraid: with those firmware versions on this specific card. In order\n"
+"megaraid: to protect your data, please upgrade your firmware to version\n"
+"megaraid: 3.10 or later, available from the Dell Technical Support web\n"
+"megaraid: site at\n"
+"http://support.dell.com/us/en/filelib/download/index.asp?fileid=2489\n");
+ megaraid_release (host);
+#ifdef MODULE
+ continue;
+#else
+ while(1) schedule_timeout(1 * HZ);
+#endif
+ }
+ }
+
/* Initialize SCBs */
- if (initSCB (megaCfg)) {
- scsi_unregister (host);
+ if (mega_initSCB (megaCfg)) {
+ megaraid_release (host);
continue;
}
printk ("megaraid: " MEGARAID_VERSION CRLFSTR);
- count += findCard (pHostTmpl, 0x101E, 0x9010, 0);
- count += findCard (pHostTmpl, 0x101E, 0x9060, 0);
- count += findCard (pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ);
+ count += mega_findCard (pHostTmpl, 0x101E, 0x9010, 0);
+ count += mega_findCard (pHostTmpl, 0x101E, 0x9060, 0);
+ count += mega_findCard (pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ);
return count;
}
release_region (megaCfg->host->io_port, 16);
}
- freeSgList(megaCfg);
+ mega_freeSgList(megaCfg);
scsi_unregister (pSHost);
return 0;
}
-static inline void freeSgList(mega_host_config *megaCfg)
+static inline void mega_freeSgList(mega_host_config *megaCfg)
{
int i;
*-----------------------------------------------------------------*/
int megaraid_queue (Scsi_Cmnd * SCpnt, void (*pktComp) (Scsi_Cmnd *))
{
+ DRIVER_LOCK_T
mega_host_config *megaCfg;
mega_scb *pScb;
- long flags;
-
- spin_lock_irqsave(&mega_lock,flags);
megaCfg = (mega_host_config *) SCpnt->host->hostdata;
+ DRIVER_LOCK(megaCfg);
if (!(megaCfg->flag & (1L << SCpnt->channel))) {
if (SCpnt->channel < SCpnt->host->max_channel)
/* If driver in abort or reset.. cancel this command */
if (megaCfg->flag & IN_ABORT) {
SCpnt->result = (DID_ABORT << 16);
- ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+ /* Add Scsi_Command to end of completed queue */
+ if( megaCfg->qCompletedH == NULL ) {
+ megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
+ }
+ else {
+ megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
+ megaCfg->qCompletedT = SCpnt;
+ }
+ megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
+ megaCfg->qCcnt++;
- spin_unlock_irqrestore(&mega_lock,flags);
+ DRIVER_UNLOCK(megaCfg);
return 0;
}
else if (megaCfg->flag & IN_RESET) {
SCpnt->result = (DID_RESET << 16);
- ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+ /* Add Scsi_Command to end of completed queue */
+ if( megaCfg->qCompletedH == NULL ) {
+ megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
+ }
+ else {
+ megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
+ megaCfg->qCompletedT = SCpnt;
+ }
+ megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
+ megaCfg->qCcnt++;
- spin_unlock_irqrestore(&mega_lock,flags);
+ DRIVER_UNLOCK(megaCfg);
return 0;
}
+ megaCfg->flag |= IN_QUEUE;
/* Allocate and build a SCB request */
if ((pScb = mega_build_cmd (megaCfg, SCpnt)) != NULL) {
/*build SCpnt for IOCTL_CMD_NEW cmd in mega_ioctl()*/
/* Add SCB to the head of the pending queue */
- ENQUEUE_NL (pScb, mega_scb, megaCfg->qPending, next);
-
- /* Issue any pending command to the card if not in ISR */
- if (!(megaCfg->flag & IN_ISR)) {
- mega_runpendq(megaCfg);
+ /* Add SCB to the head of the pending queue */
+ if( megaCfg->qPendingH == NULL ) {
+ megaCfg->qPendingH = megaCfg->qPendingT = pScb;
}
else {
- printk("IRQ pend...\n");
+ megaCfg->qPendingT->next = pScb;
+ megaCfg->qPendingT = pScb;
}
+ megaCfg->qPendingT->next = NULL;
+ megaCfg->qPcnt++;
+ mega_runpendq(megaCfg);
+
+#if LINUX_VERSION_CODE > 0x020024
if ( SCpnt->cmnd[0]==IOCTL_CMD_NEW )
{ /* user data from external user buffer */
char *user_area;
kfree(pScb->kern_area);
- freeSCB(megaCfg, pScb);
+ mega_freeSCB(megaCfg, pScb);
}
-
+#endif
}
- spin_unlock_irqrestore(&mega_lock,flags);
+ megaCfg->flag &= ~IN_QUEUE;
+ DRIVER_UNLOCK(megaCfg);
return 0;
}
/*---------------------------------------------------------------------
* Abort a previous SCSI request
*---------------------------------------------------------------------*/
-int megaraid_abort (Scsi_Cmnd * SCpnt)
+int
+megaraid_abort (Scsi_Cmnd * SCpnt)
{
mega_host_config *megaCfg;
- int rc, idx;
- long flags;
+ int rc; //, idx;
mega_scb *pScb;
- rc = SCSI_ABORT_SUCCESS;
-
- spin_lock_irqsave (&mega_lock, flags);
+ rc = SCSI_ABORT_NOT_RUNNING;
megaCfg = (mega_host_config *) SCpnt->host->hostdata;
megaCfg->flag |= IN_ABORT;
- for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
+ for(pScb=megaCfg->qPendingH; pScb; pScb=pScb->next) {
if (pScb->SCpnt == SCpnt) {
/* Found an aborting command */
#if DEBUG
showMbox(pScb);
#endif
- printk("Abort: %d %u\n",
- SCpnt->timeout_per_command,
- (uint)((jiffies) - pScb->isrcount));
+/*
+ * If the command is queued to be issued to the firmware, abort the scsi cmd,
+ * If the command is already aborted in a previous call to the _abort entry
+ * point, return SCSI_ABORT_SNOOZE, suggesting a reset.
+ * If the command is issued to the firmware, which might complete after
+ * some time, we will mark the scb as aborted, and return to the mid layer,
+ * that abort could not be done.
+ * In the ISR, when this command actually completes, we will perform a normal
+ * completion.
+ *
+ * Oct 27, 1999
+ */
switch(pScb->state) {
case SCB_ABORTED: /* Already aborted */
rc = SCSI_ABORT_SNOOZE;
break;
case SCB_ISSUED: /* Waiting on ISR result */
- rc = SCSI_ABORT_PENDING;
+ rc = SCSI_ABORT_NOT_RUNNING;
pScb->state = SCB_ABORTED;
break;
+ case SCB_ACTIVE: /* still on the pending queue */
+ mega_freeSCB (megaCfg, pScb);
+ SCpnt->result = (DID_ABORT << 16) ;
+ if( megaCfg->qCompletedH == NULL ) {
+ megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
+ }
+ else {
+ megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
+ megaCfg->qCompletedT = SCpnt;
+ }
+ megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
+ megaCfg->qCcnt++;
+ rc = SCSI_ABORT_SUCCESS;
+ break;
+ default:
+ printk("megaraid_abort: unknown command state!!\n");
+ rc = SCSI_ABORT_NOT_RUNNING;
+ break;
}
+ break;
}
}
-#if 0
- TRACE (("ABORT!!! %.08lx %.02x <%d.%d.%d>\n",
- SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
- SCpnt->lun));
- for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
- if (pScb->SCpnt == SCpnt) {
- ser_printk("** %d<%x> %c\n", pScb->SCpnt->pid, pScb->idx+1,
- pScb->state == SCB_ACTIVE ? 'A' : 'I');
+ megaCfg->flag &= ~IN_ABORT;
+
#if DEBUG
- showMbox(pScb);
-#endif
- }
- }
+if(megaCfg->flag & IN_QUEUE) printk("ma:flag is in queue\n");
+if(megaCfg->qCompletedH == NULL) printk("ma:qchead == null\n");
#endif
-
- /*
- * Walk list of SCBs for any that are still outstanding
- */
- for (idx = 0; idx < megaCfg->max_cmds; idx++) {
- if (megaCfg->scbList[idx].state != SCB_FREE) {
- if (megaCfg->scbList[idx].SCpnt == SCpnt) {
- freeSCB (megaCfg, &megaCfg->scbList[idx]);
-
- SCpnt->result = (DID_ABORT << 16) | (SUGGEST_RETRY << 24);
- ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
- }
- }
- }
- megaCfg->flag &= ~IN_ABORT;
-
- spin_unlock_irqrestore (&mega_lock, flags);
-
- mega_rundoneq();
+/*
+ * This is required here to complete any completed requests to be communicated
+ * over to the mid layer.
+ * Calling just mega_rundoneq() did not work.
+ */
+if(megaCfg->qCompletedH) {
+ SCpnt = megaCfg->qCompletedH;
+ megaCfg->qCompletedH = (Scsi_Cmnd *)SCpnt->host_scribble;
+ megaCfg->qCcnt--;
+
+ SCpnt->host_scribble = (unsigned char *) NULL ;
+ /* Callback */
+ callDone (SCpnt);
+}
+ mega_rundoneq(megaCfg);
return rc;
}
{
mega_host_config *megaCfg;
int idx;
- long flags;
-
- spin_lock_irqsave (&mega_lock, flags);
+ int rc;
+ mega_scb *pScb;
+ rc = SCSI_RESET_NOT_RUNNING;
megaCfg = (mega_host_config *) SCpnt->host->hostdata;
megaCfg->flag |= IN_RESET;
+ printk ("megaraid_RESET: %.08lx cmd=%.02x <c=%d.t=%d.l=%d>, flag = %x\n",
+ SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
+ SCpnt->lun, rstflags);
+
TRACE (("RESET: %.08lx %.02x <%d.%d.%d>\n",
SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
SCpnt->lun));
for (idx = 0; idx < megaCfg->max_cmds; idx++) {
if (megaCfg->scbList[idx].state != SCB_FREE) {
SCpnt = megaCfg->scbList[idx].SCpnt;
+ pScb = &megaCfg->scbList[idx];
if (SCpnt != NULL) {
- freeSCB (megaCfg, &megaCfg->scbList[idx]);
- SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24);
- ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+ pScb->state = SCB_RESET;
+ break;
}
}
}
megaCfg->flag &= ~IN_RESET;
- spin_unlock_irqrestore (&mega_lock, flags);
-
- mega_rundoneq();
- return SCSI_RESET_PUNT;
+ mega_rundoneq(megaCfg);
+ return rc;
}
/*-------------------------------------------------------------
#include "scsi_module.c"
#endif
-
#define IN_ISR 0x80000000L
#define IN_ABORT 0x40000000L
#define IN_RESET 0x20000000L
+#define IN_QUEUE 0x10000000L
#define BOARD_QUARTZ 0x08000000L
#define BOARD_40LD 0x04000000L
#define MEGA_CMD_TIMEOUT 10
-#define MAX_SGLIST 17
-#define MAX_COMMANDS 250
+/* Feel free to fiddle with these.. max values are:
+ SGLIST 0..26
+ COMMANDS 0..253
+ CMDPERLUN 0..63
+*/
+#define MAX_SGLIST 0x1A
+#define MAX_COMMANDS 127
#define MAX_CMD_PER_LUN 63
+#define MAX_FIRMWARE_STATUS 46
#define MAX_LOGICAL_DRIVES 8
#define MAX_CHANNEL 5
#define PCI_CONF_IRQ_OFFSET 0x3c
#define PCI_CONF_AMISIG 0xa0
#define AMI_SIGNATURE 0x3344
+#define AMI_SIGNATURE_471 0xCCCC
#if LINUX_VERSION_CODE < 0x20100
#define MEGARAID \
u32 dataxferlen;
} mega_passthru;
-typedef struct _mega_mailbox {
+struct _mega_mailbox {
/* 0x0 */ u8 cmd;
/* 0x1 */ u8 cmdid;
/* 0x2 */ u16 numsectors;
/* 0x12 */ u8 completed[46];
u8 mraid_poll;
u8 mraid_ack;
- u8 pad[16];
-} mega_mailbox;
+ u8 pad[16]; /* for alignment purposes */
+}__attribute__((packed));
+typedef struct _mega_mailbox mega_mailbox;
typedef struct {
u32 xferSegment; /* for 64-bit controllers */
u32 flag;
u32 base;
- mega_scb *qFree;
- mega_scb *qPending;
+ mega_scb *qFreeH;
+ mega_scb *qFreeT;
+ mega_scb *qPendingH;
+ mega_scb *qPendingT;
+
+ Scsi_Cmnd *qCompletedH;
+ Scsi_Cmnd *qCompletedT;
+ u32 qFcnt;
+ u32 qPcnt;
+ u32 qCcnt;
u32 nReads[FC_MAX_LOGICAL_DRIVES];
u32 nWrites[FC_MAX_LOGICAL_DRIVES];
* SCSI code to reset bus.*/
{"QUANTUM","LPS525S","3110", BLIST_NOLUN}, /* Locks sometimes if polled for lun != 0 */
{"QUANTUM","PD1225S","3110", BLIST_NOLUN}, /* Locks sometimes if polled for lun != 0 */
+{"QUANTUM","FIREBALL ST4.3S","0F0C",BLIST_NOLUN},/* Locks sometimes if polled for lun != 0 */
{"MEDIAVIS","CDR-H93MV","1.31", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */
{"SANKYO", "CP525","6.64", BLIST_NOLUN}, /* causes failed REQ SENSE, extra reset */
{"HP", "C1750A", "3226", BLIST_NOLUN}, /* scanjet iic */
{"YAMAHA","CRW6416S","1.0c", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */
{"MITSUMI", "CD-R CR-2201CS", "6119", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */
{"RELISYS", "Scorpio", "*", BLIST_NOLUN}, /* responds to all LUN */
+{"MICROTEK", "ScanMaker II", "5.61", BLIST_NOLUN}, /* responds to all LUN */
/*
* Other types of devices that have special flags.
struct dquot *get_empty_dquot(void)
{
struct dquot *dquot;
- int count;
repeat:
dquot = find_best_free();
/*
* Try pruning the dcache to free up some dquots ...
*/
-// printk(KERN_DEBUG "get_empty_dquot: pruning %d\n", count);
if (prune_dcache(0, 128))
{
- free_inode_memory(count);
+ free_inode_memory(10);
goto repeat;
}
break;
case Q_GETQUOTA:
if (((type == USRQUOTA && current->euid != id) ||
- (type == GRPQUOTA && in_group_p(id))) &&
+ (type == GRPQUOTA && !in_egroup_p(id))) &&
!capable(CAP_SYS_RESOURCE))
goto out;
break;
return 1;
}
+ /* if nfsd_server is zero, NFSD_MAXFH will be zero too, so
+ * find_fhe() will NEVER find the file handle NOR an empty space,
+ * and expire_slot will not be able to expire any file handle,
+ * because NFSD_MAXFH is zero ... */
+
+ if (nfsd_nservers <= 0) {
+ return 0;
+ }
+
expire_slot(cache);
goto repeat;
}
#define ASIZ_task_parent_exec_id 0x00000004
#define AOFF_task_self_exec_id 0x000005a0
#define ASIZ_task_self_exec_id 0x00000004
+#define AOFF_task_oom_kill_try 0x000005a4
+#define ASIZ_task_oom_kill_try 0x00000004
#define AOFF_mm_mmap 0x00000000
#define ASIZ_mm_mmap 0x00000004
#define AOFF_mm_mmap_avl 0x00000004
#define AOFF_task_mm 0x00000668
#define ASIZ_task_mm 0x00000004
#define AOFF_task_sigmask_lock 0x0000066c
-#define ASIZ_task_sigmask_lock 0x00000008
-#define AOFF_task_sig 0x00000674
+#define ASIZ_task_sigmask_lock 0x00000001
+#define AOFF_task_sig 0x00000670
#define ASIZ_task_sig 0x00000004
-#define AOFF_task_signal 0x00000678
+#define AOFF_task_signal 0x00000674
#define ASIZ_task_signal 0x00000008
-#define AOFF_task_blocked 0x00000680
+#define AOFF_task_blocked 0x0000067c
#define ASIZ_task_blocked 0x00000008
-#define AOFF_task_sigqueue 0x00000688
+#define AOFF_task_sigqueue 0x00000684
#define ASIZ_task_sigqueue 0x00000004
-#define AOFF_task_sigqueue_tail 0x0000068c
+#define AOFF_task_sigqueue_tail 0x00000688
#define ASIZ_task_sigqueue_tail 0x00000004
-#define AOFF_task_sas_ss_sp 0x00000690
+#define AOFF_task_sas_ss_sp 0x0000068c
#define ASIZ_task_sas_ss_sp 0x00000004
-#define AOFF_task_sas_ss_size 0x00000694
+#define AOFF_task_sas_ss_size 0x00000690
#define ASIZ_task_sas_ss_size 0x00000004
-#define AOFF_task_parent_exec_id 0x00000698
+#define AOFF_task_parent_exec_id 0x00000694
#define ASIZ_task_parent_exec_id 0x00000004
-#define AOFF_task_self_exec_id 0x0000069c
+#define AOFF_task_self_exec_id 0x00000698
#define ASIZ_task_self_exec_id 0x00000004
+#define AOFF_task_oom_kill_try 0x0000069c
+#define ASIZ_task_oom_kill_try 0x00000004
#define AOFF_mm_mmap 0x00000000
#define ASIZ_mm_mmap 0x00000004
#define AOFF_mm_mmap_avl 0x00000004
-/* $Id: pgtable.h,v 1.78.2.1 1999/08/07 10:52:48 davem Exp $ */
+/* $Id: pgtable.h,v 1.78.2.2 2000/02/27 04:44:44 davem Exp $ */
#ifndef _SPARC_PGTABLE_H
#define _SPARC_PGTABLE_H
#include <asm/psr.h>
-/* Define this to use the verbose/debugging versions in arch/sparc/lib/debuglocks.c */
-#define SPIN_LOCK_DEBUG
+/*
+ * Define this to use the verbose/debugging versions in
+ * arch/sparc/lib/debuglocks.c
+ *
+ * Be sure to make check_asm whenever changing this option.
+ */
+#undef SPIN_LOCK_DEBUG
#ifdef SPIN_LOCK_DEBUG
struct _spinlock_debug {
typedef unsigned char spinlock_t;
#define SPIN_LOCK_UNLOCKED 0
-#define spin_lock_init(lock) (*(lock) = 0)
+#define spin_lock_init(lock) (*((unsigned char *)(lock)) = 0)
#define spin_is_locked(lock) (*((volatile unsigned char *)(lock)) != 0)
-#define spin_unlock_wait(lock) do { barrier(); } while(*(volatile unsigned char *)lock)
+
+#define spin_unlock_wait(lock) \
+do { \
+ barrier(); \
+} while(*((volatile unsigned char *)lock))
extern __inline__ void spin_lock(spinlock_t *lock)
{
orcc %%g2, 0x0, %%g0
bne,a 2f
ldub [%0], %%g2
- .text 2
+ .subsection 2
2: orcc %%g2, 0x0, %%g0
bne,a 2b
ldub [%0], %%g2
__asm__ __volatile__("stb %%g0, [%0]" : : "r" (lock) : "memory");
}
-extern __inline__ void spin_lock_irq(spinlock_t *lock)
-{
- __asm__ __volatile__("
- rd %%psr, %%g2
- or %%g2, %0, %%g2
- wr %%g2, 0x0, %%psr
- nop; nop; nop;
-1: ldstub [%1], %%g2
- orcc %%g2, 0x0, %%g0
- bne,a 2f
- ldub [%1], %%g2
- .text 2
-2: orcc %%g2, 0x0, %%g0
- bne,a 2b
- ldub [%1], %%g2
- b,a 1b
- .previous
-" : /* No outputs */
- : "i" (PSR_PIL), "r" (lock)
- : "g2", "memory", "cc");
-}
-
-extern __inline__ void spin_unlock_irq(spinlock_t *lock)
-{
- __asm__ __volatile__("
- rd %%psr, %%g2
- andn %%g2, %1, %%g2
- stb %%g0, [%0]
- wr %%g2, 0x0, %%psr
- nop; nop; nop;
-" : /* No outputs. */
- : "r" (lock), "i" (PSR_PIL)
- : "g2", "memory");
-}
+#define spin_lock_irqsave(lock, flags) \
+ do { __save_and_cli(flags); spin_lock(lock); } while (0)
+#define spin_unlock_irqrestore(lock, flags) \
+ do { spin_unlock(lock); __restore_flags(flags); } while (0)
-#define spin_lock_irqsave(__lock, flags) \
-do { \
- register spinlock_t *__lp asm("g1"); \
- __lp = (__lock); \
- __asm__ __volatile__( \
- "rd %%psr, %0\n\t" \
- "or %0, %1, %%g2\n\t" \
- "wr %%g2, 0x0, %%psr\n\t" \
- "nop; nop; nop;\n" \
- "1:\n\t" \
- "ldstub [%2], %%g2\n\t" \
- "orcc %%g2, 0x0, %%g0\n\t" \
- "bne,a 2f\n\t" \
- " ldub [%2], %%g2\n\t" \
- ".text 2\n" \
- "2:\n\t" \
- "orcc %%g2, 0x0, %%g0\n\t" \
- "bne,a 2b\n\t" \
- " ldub [%2], %%g2\n\t" \
- "b,a 1b\n\t" \
- ".previous\n" \
- : "=r" (flags) \
- : "i" (PSR_PIL), "r" (__lp) \
- : "g2", "memory", "cc"); \
-} while(0)
-
-extern __inline__ void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
-{
- __asm__ __volatile__("
- stb %%g0, [%0]
- wr %1, 0x0, %%psr
- nop; nop; nop;
-" : /* No outputs. */
- : "r" (lock), "r" (flags)
- : "memory", "cc");
-}
+#define spin_lock_irq(lock) do { __cli(); spin_lock(lock); } while (0)
+#define spin_unlock_irq(lock) do { spin_unlock(lock); __sti(); } while (0)
/* Read-write spinlocks, allowing multiple readers
* but only one writer.
ldstub [%%g1 + 3], %%g2
" : /* no outputs */
: "r" (lp)
- : "g2", "g4", "g7", "memory", "cc");
+ : "g2", "g4", "memory", "cc");
}
#define read_lock(lock) \
ldstub [%%g1 + 3], %%g2
" : /* no outputs */
: "r" (lp)
- : "g2", "g4", "g7", "memory", "cc");
+ : "g2", "g4", "memory", "cc");
}
#define read_unlock(lock) \
ldstub [%%g1 + 3], %%g2
" : /* no outputs */
: "r" (lp)
- : "g2", "g4", "g7", "memory", "cc");
+ : "g2", "g4", "memory", "cc");
}
#define write_unlock(rw) do { (rw)->lock = 0; } while(0)
-/* $Id: vaddrs.h,v 1.22 1999/04/20 13:22:55 anton Exp $ */
+/* $Id: vaddrs.h,v 1.22.2.1 2000/03/05 19:26:24 davem Exp $ */
#ifndef _SPARC_VADDRS_H
#define _SPARC_VADDRS_H
#define ASIZ_task_parent_exec_id 0x00000004
#define AOFF_task_self_exec_id 0x0000082c
#define ASIZ_task_self_exec_id 0x00000004
-#define ASIZ_task 0x00000830
+#define AOFF_task_oom_kill_try 0x00000830
+#define ASIZ_task_oom_kill_try 0x00000004
+#define ASIZ_task 0x00000840
#define AOFF_mm_mmap 0x00000000
#define ASIZ_mm_mmap 0x00000008
#define AOFF_mm_mmap_avl 0x00000008
#define ASIZ_task_parent_exec_id 0x00000004
#define AOFF_task_self_exec_id 0x00000a1c
#define ASIZ_task_self_exec_id 0x00000004
-#define ASIZ_task 0x00000a20
+#define AOFF_task_oom_kill_try 0x00000a20
+#define ASIZ_task_oom_kill_try 0x00000004
+#define ASIZ_task 0x00000a30
#define AOFF_mm_mmap 0x00000000
#define ASIZ_mm_mmap 0x00000008
#define AOFF_mm_mmap_avl 0x00000008
#define ASIZ_task_parent_exec_id 0x00000004
#define AOFF_task_self_exec_id 0x00000a24
#define ASIZ_task_self_exec_id 0x00000004
+#define AOFF_task_oom_kill_try 0x00000a28
+#define ASIZ_task_oom_kill_try 0x00000004
#define ASIZ_task 0x00000a30
#define AOFF_mm_mmap 0x00000000
#define ASIZ_mm_mmap 0x00000008
-/* $Id: floppy.h,v 1.18.2.3 2000/01/09 18:29:32 ecd Exp $
+/* $Id: floppy.h,v 1.18.2.4 2000/02/27 04:44:47 davem Exp $
* asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
-/* $Id: pgtable.h,v 1.103.2.2 1999/12/05 07:24:45 davem Exp $
+/* $Id: pgtable.h,v 1.103.2.3 2000/02/27 04:44:47 davem Exp $
* pgtable.h: SpitFire page table operations.
*
* Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
-/* $Id: system.h,v 1.50 1999/05/08 03:03:22 davem Exp $ */
+/* $Id: system.h,v 1.50.2.1 2000/03/06 22:30:28 davem Exp $ */
#ifndef __SPARC64_SYSTEM_H
#define __SPARC64_SYSTEM_H
-/* $Id: isdn.h,v 1.88 2000/01/20 19:59:43 keil Exp $
+/* $Id: isdn.h,v 1.95 2000/03/04 16:20:42 detabc Exp $
*
* Main header for the Linux ISDN subsystem (linklevel).
*
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn.h,v $
+ * Revision 1.95 2000/03/04 16:20:42 detabc
+ * copy frames before rewriting frame's saddr
+ *
+ * Revision 1.94 2000/02/26 00:29:40 keil
+ * more softnet changes
+ *
+ * Revision 1.93 2000/02/25 11:29:17 paul
+ * changed chargetime to ulong from int (after about 20 days the "chargetime of
+ * ipppX is now 1234" message displays a negative number on alpha).
+ *
+ * Revision 1.92 2000/02/17 13:15:56 keil
+ * fix backward compatibility for 2.2
+ *
+ * Revision 1.91 2000/02/16 14:56:27 paul
+ * translated ISDN_MODEM_ANZREG to ISDN_MODEM_NUMREG for english speakers
+ *
+ * Revision 1.90 2000/02/06 21:50:00 detabc
+ * add rewriting of socket's and frame's saddr for udp-ipv4 dynip-connections.
+ * Include checksum-recompute of ip- and udp-header's.
+ *
+ * Revision 1.89 2000/02/05 22:11:33 detabc
+ * Add rewriting of socket's and frame's saddr adressfield for
+ * dynip-connections. Only for tcp/ipv4 and switchable per interface.
+ * Include checksum-recompute of ip- and tcp-header's.
+ *
* Revision 1.88 2000/01/20 19:59:43 keil
* Add FAX Class 1 support
*
#undef CONFIG_ISDN_WITH_ABC_CONN_ERROR
#undef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS
#undef CONFIG_ISDN_WITH_ABC_FRAME_LIMIT
+#undef CONFIG_ISDN_WITH_ABC_IPV4_RW_SOCKADDR
+#undef CONFIG_ISDN_WITH_ABC_IPV4_RWUDP_SOCKADDR
/* New ioctl-codes */
#define ISDN_USAGE_EXCLUSIVE 64 /* This bit is set, if channel is exclusive */
#define ISDN_USAGE_OUTGOING 128 /* This bit is set, if channel is outgoing */
-#define ISDN_MODEM_ANZREG 24 /* Number of Modem-Registers */
+#define ISDN_MODEM_NUMREG 24 /* Number of Modem-Registers */
#define ISDN_LMSNLEN 255 /* Length of tty's Listen-MSN string */
#define ISDN_CMSGLEN 50 /* Length of CONNECT-Message to add for Modem */
# include <linux/concap.h>
#endif
+
#include <linux/isdnif.h>
#define ISDN_DRVIOCTL_MASK 0x7f /* Mask for Device-ioctl */
/* 0 = Transparent */
int huptimer; /* Timeout-counter for auto-hangup */
int charge; /* Counter for charging units */
- int chargetime; /* Timer for Charging info */
+ ulong chargetime; /* Timer for Charging info */
int hupflags; /* Flags for charge-unit-hangup: */
/* bit0: chargeint is invalid */
/* bit1: Getting charge-interval */
/* Private data of AT-command-interpreter */
typedef struct atemu {
- u_char profile[ISDN_MODEM_ANZREG]; /* Modem-Regs. Profile 0 */
- u_char mdmreg[ISDN_MODEM_ANZREG]; /* Modem-Registers */
+ u_char profile[ISDN_MODEM_NUMREG]; /* Modem-Regs. Profile 0 */
+ u_char mdmreg[ISDN_MODEM_NUMREG]; /* Modem-Registers */
char pmsn[ISDN_MSNLEN]; /* EAZ/MSNs Profile 0 */
char msn[ISDN_MSNLEN]; /* EAZ/MSN */
char plmsn[ISDN_LMSNLEN]; /* Listening MSNs Profile 0 */
/* Utility-Macros */
#define MIN(a,b) ((a<b)?a:b)
#define MAX(a,b) ((a>b)?a:b)
+/*
+ * Tell upper layers that the network device is ready to xmit more frames.
+ */
+static void __inline__ netif_wake_queue(struct device * dev)
+{
+ dev->tbusy = 0;
+ mark_bh(NET_BH);
+}
+
+/*
+ * called during net_device open()
+ */
+static void __inline__ netif_start_queue(struct device * dev)
+{
+ dev->tbusy = 0;
+ /* actually, we never use the interrupt flag at all */
+ dev->interrupt = 0;
+ dev->start = 1;
+}
+
+/*
+ * Ask upper layers to temporarily cease passing us more xmit frames.
+ */
+static void __inline__ netif_stop_queue(struct device * dev)
+{
+ dev->tbusy = 1;
+}
#endif /* __KERNEL__ */
#endif /* isdn_h */
/*
- * $Id: kernelcapi.h,v 1.4 1999/09/10 17:24:19 calle Exp $
+ * $Id: kernelcapi.h,v 1.5 2000/01/28 16:45:40 calle Exp $
*
* Kernel CAPI 2.0 Interface for Linux
*
* (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
*
* $Log: kernelcapi.h,v $
+ * Revision 1.5 2000/01/28 16:45:40 calle
+ * new manufacturer command KCAPI_CMD_ADDCARD (generic addcard),
+ * will search named driver and call the add_card function if one exist.
+ *
* Revision 1.4 1999/09/10 17:24:19 calle
* Changes for proposed standard for CAPI2.0:
* - AK148 "Linux Exention"
int flag;
} kcapi_flagdef;
+typedef struct kcapi_carddef {
+ char driver[32];
+ unsigned int port;
+ unsigned irq;
+ unsigned int membase;
+ int cardnr;
+} kcapi_carddef;
+
/* new ioctls >= 10 */
#define KCAPI_CMD_TRACE 10
+#define KCAPI_CMD_ADDCARD 11 /* add card to named driver */
/*
* flag > 2 => trace also data
break;
case IPC_SET:
buf = arg.buf;
- err = copy_from_user (&tbuf, buf, sizeof (*buf));
- if (err)
- err = -EFAULT;
+ err = -EFAULT;
+ if(copy_from_user (&tbuf, buf, sizeof (*buf)))
+ goto out;
break;
}
err = -EIDRM;
- if (semary[id] == IPC_UNUSED || semary[id] == IPC_NOID)
- goto out;
- if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
+ if ((sma != semary[id]) || (sma->sem_perm.seq != (unsigned int) semid / SEMMNI))
goto out;
switch (cmd) {
goto out;
for (i = 0; i < sma->sem_nsems; i++)
sem_io[i] = sma->sem_base[i].semval;
+ err = -EFAULT;
if (copy_to_user (array, sem_io, nsems*sizeof(ushort)))
- err = -EFAULT;
+ goto out;
break;
case SETVAL:
err = -EACCES;
tbuf.sem_otime = sma->sem_otime;
tbuf.sem_ctime = sma->sem_ctime;
tbuf.sem_nsems = sma->sem_nsems;
+ err = -EFAULT;
if (copy_to_user (buf, &tbuf, sizeof(*buf)))
- err = -EFAULT;
+ goto out;
break;
case SETALL:
err = -EACCES;
return err;
}
+
+static struct sem_undo* freeundos(struct sem_undo* un)
+{
+ struct sem_undo* u;
+ struct sem_undo** up;
+
+ for (up = ¤t->semundo;(u=*up);up=&u->proc_next) {
+ if(un==u) {
+ un=u->proc_next;
+ *up=un;
+ kfree(u);
+ return un;
+ }
+ }
+ printk ("freeundos undo list error id=%d\n", un->semid);
+ return un->proc_next;
+}
+
+
asmlinkage int sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
{
int id, size, error = -EINVAL;
/* Make sure we have an undo structure
* for this process and this semaphore set.
*/
- for (un = current->semundo; un; un = un->proc_next)
- if (un->semid == semid)
+ un = current->semundo;
+ while(un != NULL) {
+ if(un->semid==semid)
break;
+ if(un->semid==-1)
+ un=freeundos(un);
+ else
+ un=un->proc_next;
+ }
if (!un) {
size = sizeof(struct sem_undo) + sizeof(short)*sma->sem_nsems;
un = (struct sem_undo *) kmalloc(size, GFP_ATOMIC);
* X.25 001 Jonathan Naylor Started coding.
* X.25 002 Jonathan Naylor Centralised disconnect handling.
* New timer architecture.
+ * 2000-11-03 Henner Eisen MSG_EOR handling more POSIX compliant.
*/
#include <linux/config.h>
unsigned char *asmptr;
int size, qbit = 0;
- if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_OOB))
+ if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_OOB | MSG_EOR))
return -EINVAL;
if (sk->zapped)
msg->msg_flags |= MSG_TRUNC;
}
+ /* Currently, each datagram always contains a complete record */
+ msg->msg_flags |= MSG_EOR;
+
skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
if (sx25 != NULL) {
void x25_link_control(struct sk_buff *skb, struct x25_neigh *neigh, unsigned short frametype)
{
struct sk_buff *skbn;
+ int confirm;
switch (frametype) {
case X25_RESTART_REQUEST:
+ confirm = !x25_t20timer_pending(neigh);
x25_stop_t20timer(neigh);
- if (!x25_t20timer_pending(neigh))
- x25_transmit_restart_confirmation(neigh);
neigh->state = X25_LINK_STATE_3;
+ if (confirm) x25_transmit_restart_confirmation(neigh);
break;
case X25_RESTART_CONFIRMATION: