diff --git a/Documentation/Changes b/Documentation/Changes
index 8db20b179f2ecfce4d4a2ca786e37a8ba13f4151..a883b8d5d3a523fb45d48ef47b03b358b3243e77 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -63,6 +63,7 @@ running, the suggested command should tell you.
 - Pcmcia-cs              3.1.2                   ; cardmgr -V
 - PPP                    2.3.9                   ; pppd --version
 - Util-linux             2.9i                    ; chsh -v
+- isdn4k-utils           v3.1beta7               ; isdnctrl 2>&1|grep version
 
 Upgrade notes
 *************
@@ -245,9 +246,6 @@ modules) are currently distributed separately: see
    DHCP clients for 2.0 do not work with the new networking code in the
 2.2 kernel.  You will need to upgrade your dhcpcd / dhcpclient.
 
-   The ISDN code in the stock 2.2 kernel may not work for you.  If it
-doesn't, look in ftp://ftp.suse.com/pub/isdn4linux for updated versions.
-
    In 2.0.x the kernel could be configured to drop source routed IP
 packets via a compile time configuration option.  In 2.2.x, this has
 been replaced by a sysctl.  See Documentation/networking/ip-sysctl.txt
@@ -494,6 +492,15 @@ config.h file needs to
 
    so be sure to check that when you recompile.
 
+ISDN4Linux
+==========
+Since 2.3.27 here is a new length of the phonenumber field, old utils
+have to recompile, a upgrade to isdn4k-utils.v3.1beta7 or later is
+recomented.
+Older isdn4k-utils versions don't support EXTRAVERSION into kernel version
+string.
+
+
 Where to get the files
 **********************
 
@@ -775,6 +782,11 @@ Patch
 The 2.5 release:
 ftp://ftp.gnu.org/gnu/patch/patch-2.5.tar.gz
 
+ISDN4Linux
+==========
+The v3.1beta7 release:
+ftp://ftp.isdn4linux.de/pub/isdn4linux/utils/testing/isdn4k-utils.v3.1beta7.tar.gz
+
 Other Info
 ==========
 
diff --git a/Documentation/isdn/00-INDEX b/Documentation/isdn/00-INDEX
index 919af90576546aa79caea0142a13258f0a369d3f..b7161af1a78f298cf4a01acc890438718ecb198e 100644
--- a/Documentation/isdn/00-INDEX
+++ b/Documentation/isdn/00-INDEX
@@ -6,12 +6,18 @@ INTERFACE
 	- description of Linklevel and Hardwarelevel ISDN interface.
 README
 	- general info on what you need and what to do for Linux ISDN.
+README.FAQ
+	- general info for FAQ.
 README.audio
 	- info for running audio over ISDN.
+README.fax
+	- info for using Fax over ISDN.
 README.icn
 	- info on the ICN-ISDN-card and its driver.
 README.HiSax
 	- info on the HiSax driver which replaces the old teles.
+README.hfc-pci
+	- info on hfc-pci based cards.
 README.pcbit
 	- info on the PCBIT-D ISDN adapter and driver.
 README.syncppp
@@ -22,8 +28,12 @@ README.avmb1
 	- info on driver for AVM-B1 ISDN card.
 README.act2000
 	- info on driver for IBM ACT-2000 card.
+README.eicon
+	- info on driver for Eicon active cards.
 README.concap
 	- info on "CONCAP" ecapsulation protocol interface used for X.25.
+README.diversion
+	- info on module for isdn diversion services.
 README.sc
 	- info on driver for Spellcaster cards.
 README.x25
diff --git a/Documentation/isdn/CREDITS b/Documentation/isdn/CREDITS
index 31da77e3b1e46ad3d0957f335c4071d31cf07e4c..beef990bab6baa61828ca88b15aea0d69b3d500e 100644
--- a/Documentation/isdn/CREDITS
+++ b/Documentation/isdn/CREDITS
@@ -15,8 +15,11 @@ Volker G
   For contribution of man-pages, the imontty-tool and a perfect
   maintaining of the mailing-list at hub-wue.
 
+Matthias Hessler (hessler@isdn4linux.de)
+  For creating and maintaining the FAQ.
+
 Bernhard Hailer (Bernhard.Hailer@lrz.uni-muenchen.de)
-  For maintaining the FAQ.
+  For creating the FAQ, and the leafsite HOWTO. 
 
 Michael 'Ghandi' Herold (michael@abadonna.franken.de)
   For contribution of the vbox answering machine.
diff --git a/Documentation/isdn/README b/Documentation/isdn/README
index dcd14151eb9bcb49bce3040b9545bd968fb65589..3cf623d48eec5dfb0e69f372e34996ccb6b5a92e 100644
--- a/Documentation/isdn/README
+++ b/Documentation/isdn/README
@@ -11,7 +11,7 @@ README for the ISDN-subsystem
   necessary. Those programs and some contributed utilities are available
   at
 
-   ftp.franken.de
+   ftp.isdn4linux.de
 
    /pub/isdn4linux/isdn4k-utils-<VersionNumber>.tar.gz
 
@@ -22,19 +22,23 @@ README for the ISDN-subsystem
    reasons, the mailing-list's primary language is german. However mails
    written in english have been welcome all the time.
 
-   to subscribe: write a email to majordomo@hub-wue.franken.de,
+   to subscribe: write a email to majordomo@listserv.isdn4linux.de,
    Subject irrelevant, in the message body:
    subscribe isdn4linux <your_email_address>
 
-   To write to the mailing-list, write to isdn4linux@hub-wue.franken.de
+   To write to the mailing-list, write to isdn4linux@listserv.isdn4linux.de
 
    This mailinglist is bidirectionally gated to the newsgroup
 
      de.alt.comm.isdn4linux
 
-  There is also a well maintained FAQ (both english and german) available
-  at ftp.franken.de in /pub/isdn4linux/FAQ/
-  This FAQ is also available at http://www.lrz-muenchen.de/~ui161ab/www/isdn/
+  There is also a well maintained FAQ in English available at
+     http://www.mhessler.de/i4lfaq/
+  It can be viewed online, or downloaded in sgml/text/html format.
+  The FAQ can also be viewed online at
+     http://www.isdn4inux.de/faq/
+  or downloaded from
+     ftp://ftp.isdn4linux.de/pub/isdn4linux/FAQ/
 
   1.1 Technical details
 
@@ -266,6 +270,8 @@ README for the ISDN-subsystem
              23   0         Bit coded register:
                             Bit 0:    0 = Add CPN to RING message off
                                       1 = Add CPN to RING message on
+                            Bit 1:    0 = Add CPN to FCON message off
+                                      1 = Add CPN to FCON message on
 
   Last but not least a (at the moment fairly primitive) device to request
   the line-status (/dev/isdninfo) is made available.
@@ -581,7 +587,7 @@ README for the ISDN-subsystem
    If other drivers will not be affected, I will include the changes
    in the next release.
    For developers only, there is a second mailing-list. Write to me
-   (fritz@wuemaus.franken.de), if you want to join that list.
+   (fritz@isdn4linux.de), if you want to join that list.
 
 Have fun!
 
diff --git a/Documentation/isdn/README.FAQ b/Documentation/isdn/README.FAQ
new file mode 100644
index 0000000000000000000000000000000000000000..356f7944641d50d71fd0d737a725a6a3d715a0dc
--- /dev/null
+++ b/Documentation/isdn/README.FAQ
@@ -0,0 +1,26 @@
+
+The FAQ for isdn4linux
+======================
+
+Please note that there is a big FAQ available in the isdn4k-utils.
+You find it in:
+ isdn4k-utils/FAQ/i4lfaq.sgml
+
+In case you just want to see the FAQ online, or download the newest version,
+you can have a look at my website:
+http://www.mhessler.de/i4lfaq/ (view + download)
+or:
+http://www.isdn4linux.de/faq/ (view)
+
+As the extension tells, the FAQ is in SGML format, and you can convert it
+into text/html/... format by using the sgml2txt/sgml2html/... tools.
+Alternatively, you can also do a 'configure; make all' in the FAQ directory.
+
+
+Please have a look at the FAQ before posting anything in the Mailinglist,
+or the newsgroup!
+
+
+Matthias Hessler
+hessler@isdn4linux.de
+
diff --git a/Documentation/isdn/README.HiSax b/Documentation/isdn/README.HiSax
index 7faff4a349221622007ec219cdbea6a533ada9e5..ee95d85f41479b76df5373ad43ab82766d5b75ac 100644
--- a/Documentation/isdn/README.HiSax
+++ b/Documentation/isdn/README.HiSax
@@ -63,6 +63,7 @@ Berkom Telekom A4T
 Scitel Quadro
 Gazel ISDN cards
 HFC-PCI based cards
+Winbond W6692 based cards
 
 Note: PCF, PCF-Pro: up to now, only the ISDN part is supported
       PCC-8: not tested yet
@@ -182,6 +183,7 @@ Card types:
    34	Gazel ISDN cards (ISA)   irq,io
    34	Gazel ISDN cards (PCI)   none
    35	HFC 2BDS0 PCI            none
+   36	W6692 based PCI cards    none
 
 
 At the moment IRQ sharing is only possible with PCI cards. Please make sure
@@ -285,6 +287,7 @@ type
    34	Gazel ISDN cards (ISA)  pa=irq, pb=io
    34	Gazel ISDN cards (PCI)  no parameter
    35	HFC 2BDS0 PCI           no parameter
+   36	W6692 based PCI cards   none
 
 Running the driver
 ------------------
@@ -425,6 +428,7 @@ Special thanks to:
 	Klaus Lichtenwalder (Klaus.Lichtenwalder@WebForum.DE), for ELSA PCMCIA support
 	Enrik Berkhan (enrik@starfleet.inka.de) for S0BOX specific stuff
 	Ton van Rosmalen for Teles PCI
+	Petr Novak <petr.novak@i.cz> for Winbond W6692 support
         and more people who are hunting bugs. (If I forgot somebody, please
 	send me a mail).
 
diff --git a/Documentation/isdn/README.avmb1 b/Documentation/isdn/README.avmb1
index 34eee2125b2f47d62b8ac6dcc6669e1c587ebba7..6fa9406dfece99ef3bf1b79809e94932797ae524 100644
--- a/Documentation/isdn/README.avmb1
+++ b/Documentation/isdn/README.avmb1
@@ -169,7 +169,7 @@ capi20
 
 Questions
 ---------
-Check out the FAQ (ftp.franken.de) or subscribe to the
+Check out the FAQ (ftp.isdn4linux.de) or subscribe to the
 linux-avmb1@calle.in-berlin.de mailing list by sending
 a mail to majordomo@calle.in-berlin.de with
 subscribe linux-avmb1
diff --git a/Documentation/isdn/README.eicon b/Documentation/isdn/README.eicon
index d55cc14ad0052be07415daab1ef612ebb6dca3cb..b40e1ecd23c529a7d0072d47008fe982bb708740 100644
--- a/Documentation/isdn/README.eicon
+++ b/Documentation/isdn/README.eicon
@@ -1,6 +1,6 @@
-$Id: README.eicon,v 1.4 1999/07/11 17:17:30 armin Exp $
+$Id: README.eicon,v 1.5 1999/10/11 18:13:25 armin Exp $
 
-(c) 1999 Cytronics & Melware
+(c) 1999 Cytronics & Melware (info@melware.de)
 
 This document describes the eicon driver for the
 Eicon.Diehl active ISDN cards.
@@ -24,17 +24,26 @@ It is meant to be used with isdn4linux, an ISDN link-level module for Linux.
 
 
 Supported Cards
----------------
+===============
 
+Old ISA type
+------------
 - S-Card ISA
 - SX-Card ISA
 - SXn-Card ISA
 - SCOM-Card ISA
 - Quadro-Card ISA
 - S2M-Card ISA
+
+DIVA Server family
+------------------
 - DIVA Server BRI/PCI 2M
 - DIVA Server PRI/PCI 2M (9M 23M 30M)
-  (Only analog modem functions of the DSPs are currently implemented)
+	supported functions of onboard DSPs:
+	- analog modem
+	- fax group 2/3 (Fax Class 2 commands)
+	- DTMF detection
+
 
 ISDN D-Channel Protocols
 ------------------------
@@ -76,6 +85,10 @@ Example for loading and starting a PRI card with E-DSS1 Protocol.
 Details about using the eiconctrl utility are in 'man eiconctrl'
 or will be printed by starting eiconctrl without any parameters.
 
+Thanks to 
+	Deutsche Mailbox Saar-Lor-Lux GmbH
+	for sponsoring and testing fax
+	capabilities with Diva Server cards.
 
 
 Any reports about bugs, errors and even wishes are welcome.
diff --git a/Documentation/isdn/README.fax b/Documentation/isdn/README.fax
index 897abd0ef53843521988a6cc92ef7bfc159d33df..eeff9ce9f2c0d983a6a91a94900480760867aaee 100644
--- a/Documentation/isdn/README.fax
+++ b/Documentation/isdn/README.fax
@@ -9,7 +9,7 @@ This only makes sense under the following conditions :
 
 - You need the commands as dummy, because you are using
   hylafax (with patch) for AVM capi.
-- You want to use the fax capabillities of your isdn-card.
+- You want to use the fax capabilities of your isdn-card.
   (supported cards are listed below)
 
 
@@ -21,8 +21,12 @@ NOTE: This implementation does *not* support fax with passive
 Supported ISDN-Cards
 --------------------
 
-Eicon DIVA Server BRI/PCI (will be ready soon)
-Eicon DIVA Server PRI/PCI (will be ready soon)
+Eicon DIVA Server BRI/PCI
+	- full support with both B-channels.
+
+Eicon DIVA Server PRI/PCI
+	- full support on amount of B-channels
+		depending on DSPs on board.
 
 
 
diff --git a/Documentation/isdn/README.hfc-pci b/Documentation/isdn/README.hfc-pci
index 94e0d4352543ec2d45f4e7715db6316e01a38928..6cc311e359240627ac3518d1dcbf9888c614e212 100644
--- a/Documentation/isdn/README.hfc-pci
+++ b/Documentation/isdn/README.hfc-pci
@@ -20,6 +20,21 @@ This enables the echo mode. If Hex logging is activated the isdnctrlx
 devices show a output with a line beginning of HEX: for the providers
 exchange and ECHO: for isdn devices sending to the provider.
 
+If more than one HFC-PCI cards are installed, a specific card may be selected
+at the hisax module load command line. Supply the load command with the desired
+IO-address of the desired card. 
+Example:
+There tree cards installed in your machine at IO-base addresses 0xd000, 0xd400 
+and 0xdc00
+If you want to use the card at 0xd400 standalone you should supply the insmod
+or depmod with type=35 io=0xd400.
+If you want to use all three cards, but the order needs to be at 0xdc00,0xd400,
+0xd000 you may give the parameters type=35,35,35 io=0xdc00,0xd400,0xd00 
+Then the desired card will be the initialised in the desired order.
+If the io parameter is used the io addresses of all used cards should be 
+supplied else the parameter is assumed 0 and a auto search for a free card is
+invoked which may not give the wanted result. 
+
 Comments and reports to werner@isdn4linux.de or werner@titro.de .
 
 
diff --git a/Documentation/isdn/README.pcbit b/Documentation/isdn/README.pcbit
index fb696422f911193583ae945a39c2334373f165d7..5125002282e5e4129da192477f692c19a6b09b12 100644
--- a/Documentation/isdn/README.pcbit
+++ b/Documentation/isdn/README.pcbit
@@ -32,7 +32,7 @@ allow normal operation. Plans for the future include cooperation with
 the manufacturer in order to solve this problem.
 
 Information/hints/help can be obtained in the linux isdn
-mailing list (isdn4linux@hub-wue.franken.de) or directly from me.
+mailing list (isdn4linux@listserv.isdn4linux.de) or directly from me.
 
 regards,
   Pedro.
diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
index 9673a46e78fa3b76d29e233255fb8d4b120f2d30..4263c68d5e7088706ca33edf108d3a987b888ad1 100644
--- a/Documentation/oops-tracing.txt
+++ b/Documentation/oops-tracing.txt
@@ -16,6 +16,37 @@ If you are totally stumped as to whom to send the report, send it to
 linux-kernel@vger.rutgers.edu. Thanks for your help in making Linux as
 stable as humanly possible.
 
+Where is the_oops.txt?
+----------------------
+
+Normally the Oops text is read from the kernel buffers by klogd and
+handed to syslogd which writes it to a syslog file, typically
+/var/log/messages (depends on /etc/syslog.conf).  Sometimes klogd dies,
+in which case you can run dmesg > file to read the data from the kernel
+buffers and save it.  Or you can cat /proc/kmsg > file, however you
+have to break in to stop the transfer, kmsg is a "never ending file".
+If the machine has crashed so badly that you cannot enter commands or
+the disk is not available then you have three options :-
+
+(1) Hand copy the text from the screen and type it in after the machine
+    has restarted.  Messy but it is the only option if you have not
+    planned for a crash.
+
+(2) Boot with a serial console (see Documentation/serial-console.txt),
+    run a null modem to a second machine and capture the output there
+    using your favourite communication program.  Minicom works well.
+
+(3) Patch the kernel with one of the crash dump patches.  These save
+    data to a floppy disk or video rom or a swap partition.  None of
+    these are standard kernel patches so you have to find and apply
+    them yourself.  Search kernel archives for kmsgdump, lkcd and
+    oops+smram.
+
+No matter how you capture the log output, feed the resulting file to
+ksymoops along with /proc/ksyms and /proc/modules that applied at the
+time of the crash.  /var/log/ksymoops can be useful to capture the
+latter, man ksymoops for details.
+
 
 Full Information
 ----------------
diff --git a/MAINTAINERS b/MAINTAINERS
index 14efbdd5dfb4a9c9abaf4feb3a94c8a9a5c959dd..118d5e64dafe5a1d3d0ddf5836ff0e65f9313095 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -482,10 +482,18 @@ P:	Jaroslav Kysela
 M:	perex@suse.cz
 S:	Maintained
 
-ISDN SUBSYSTEM
+ISDN SUBSYSTEM (general)
 P:	Fritz Elfert
-M:	fritz@wuemaus.franken.de
-L:	isdn4linux@hub-wue.franken.de
+M:	fritz@isdn4linux.de
+L:	isdn4linux@listserv.isdn4linux.de
+W:	http://www.isdn4linux.de
+S:	Maintained
+
+ISDN SUBSYSTEM (card drivers)
+P:	Karsten Keil
+M:	kkeil@suse.de
+L:	isdn4linux@listserv.isdn4linux.de
+W:	http://www.isdn4linux.de
 S:	Maintained
 
 JOYSTICK DRIVER
diff --git a/Makefile b/Makefile
index f40b5f6f571f07e28b3b0cc924ade1ad52a61d86..45a55b331ae7fa50cd7fd31b9b5ea155e3938939 100644
--- a/Makefile
+++ b/Makefile
@@ -390,6 +390,7 @@ clean:	archclean
 	rm -f .tmp*
 	rm -f drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c
 	rm -f drivers/char/conmakehash
+	rm -f drivers/pci/devlist.h drivers/pci/gen-devlist
 	rm -f drivers/sound/bin2hex drivers/sound/hex2hex
 	rm -f net/khttpd/make_times_h
 	rm -f net/khttpd/times.h
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index 9a75fb233bf37043795f699176d5ddbc8262b8f0..cdeaf9a35f822143a7bfa7b7df2e8140c7d79c11 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -1367,8 +1367,10 @@ static int apm(void *unused)
 	/* Install our power off handler.. */
 	if (power_off_enabled)
 		acpi_power_off = apm_power_off;
-	sysrq_power_off = apm_power_off;
 
+#ifdef CONFIG_MAGIC_SYSRQ
+	sysrq_power_off = apm_power_off;
+#endif
 	apm_mainloop();
 	return 0;
 }
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index 7a275f9181f476223135680ed5cc00017af31df9..b21a915aa33e9f6017c753de183c2a18eb629335 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -129,3 +129,4 @@ EXPORT_SYMBOL(mca_is_adapter_used);
 EXPORT_SYMBOL(screen_info);
 #endif
 
+EXPORT_SYMBOL(get_wchan);
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index 75659aac40dcd178af7b69152c18122a9342847d..1bccad67bf4aa89a0dcb6891dd8c13dce94157a3 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -650,6 +650,19 @@ int request_irq(unsigned int irq,
 	int retval;
 	struct irqaction * action;
 
+#if 1
+	/*
+	 * Sanity-check: shared interrupts should REALLY pass in
+	 * a real dev-ID, otherwise we'll have trouble later trying
+	 * to figure out which interrupt is which (messes up the
+	 * interrupt freeing logic etc).
+	 */
+	if (irqflags & SA_SHIRQ) {
+		if (!dev_id)
+			printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]);
+	}
+#endif
+
 	if (irq >= NR_IRQS)
 		return -EINVAL;
 	if (!handler)
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 934fb082eae04ede721dd2d3a34e91c099e65a60..429c4eacd9b12420cc35f4245d8011623810334a 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -685,3 +685,37 @@ asmlinkage int sys_execve(struct pt_regs regs)
 	unlock_kernel();
 	return error;
 }
+
+/*
+ * These bracket the sleeping functions..
+ */
+extern void scheduling_functions_start_here(void);
+extern void scheduling_functions_end_here(void);
+#define first_sched	((unsigned long) scheduling_functions_start_here)
+#define last_sched	((unsigned long) scheduling_functions_end_here)
+
+unsigned long get_wchan(struct task_struct *p)
+{
+	unsigned long ebp, esp, eip;
+	unsigned long stack_page;
+	int count = 0;
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+	stack_page = (unsigned long)p;
+	esp = p->thread.esp;
+	if (!stack_page || esp < stack_page || esp > 8188+stack_page)
+		return 0;
+	/* include/asm-i386/system.h:switch_to() pushes ebp last. */
+	ebp = *(unsigned long *) esp;
+	do {
+		if (ebp < stack_page || ebp > 8184+stack_page)
+			return 0;
+		eip = *(unsigned long *) (ebp+4);
+		if (eip < first_sched || eip >= last_sched)
+			return eip;
+		ebp = *(unsigned long *) ebp;
+	} while (count++ < 16);
+	return 0;
+}
+#undef last_sched
+#undef first_sched
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index b27d120958a75e4c341638d2dad9888299e8952a..a3ee727bde292d2fabea1d60b22145eda867b4a8 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -1821,13 +1821,13 @@ int __init amiga_floppy_init(void)
 		return -ENOMEM;
 	}
 
-	if (!request_irq(IRQ_AMIGA_DSKBLK, fd_block_done, 0, "floppy_dma", NULL)) {
+	if (request_irq(IRQ_AMIGA_DSKBLK, fd_block_done, 0, "floppy_dma", NULL)) {
 		printk("fd: cannot get irq for dma\n");
 		amiga_chip_free(raw_buf);
 		unregister_blkdev(MAJOR_NR,"fd");
 		return -EBUSY;
 	}
-	if (!request_irq(IRQ_AMIGA_CIAA_TB, ms_isr, 0, "floppy_timer", NULL)) {
+	if (request_irq(IRQ_AMIGA_CIAA_TB, ms_isr, 0, "floppy_timer", NULL)) {
 		printk("fd: cannot get irq for timer\n");
 		free_irq(IRQ_AMIGA_DSKBLK, NULL);
 		amiga_chip_free(raw_buf);
diff --git a/drivers/char/dn_keyb.c b/drivers/char/dn_keyb.c
index 38010e29b63e9846b027b845a9bae0a4336a5853..f663790db122e1789b097d66671bdcf014a7a2e6 100644
--- a/drivers/char/dn_keyb.c
+++ b/drivers/char/dn_keyb.c
@@ -1,4 +1,3 @@
-#include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
@@ -18,8 +17,9 @@
 #include <asm/apollohw.h>
 #include <asm/uaccess.h>
 
+#include "busmouse.h"
 
-extern void handle_scancode(unsigned char);
+/* extern void handle_scancode(unsigned char,int ); */
 
 #define DNKEY_CAPS 0x7e
 #define BREAK_FLAG 0x80
@@ -37,18 +37,12 @@ extern void handle_scancode(unsigned char);
 #define APOLLO_KBD_MODE_MOUSE   0x02
 #define APOLLO_KBD_MODE_CHANGE 0xff
 
-#define MSE_UPDATE_ON() mouse_update_allowed=1
-#define MSE_UPDATE_OFF() mouse_update_allowed=0
-
 static u_char keyb_cmds[APOLLO_KEYB_CMD_ENTRIES];
 static short keyb_cmd_read=0, keyb_cmd_write=0;
 static int keyb_cmd_transmit=0;
+static int msedev;
 
 static unsigned int kbd_mode=APOLLO_KBD_MODE_KEYB;
-static short mouse_dx,mouse_dy,mouse_buttons;
-static int mouse_ready=0,mouse_update_allowed=0,mouse_active=0;
-static DECLARE_WAIT_QUEUE_HEAD(mouse_wait);
-static struct fasync_struct *mouse_fasyncptr=NULL;
 
 #if 0
 static void debug_keyb_timer_handler(unsigned long ignored);
@@ -302,103 +296,6 @@ static void debug_keyb_timer_handler(unsigned long ignored) {
 }
 #endif
 
-static unsigned int mouse_poll(struct file *file, poll_table * wait)
-{
-        poll_wait(&mouse_wait, wait);
-        if (mouse_ready)
-                return POLLIN | POLLRDNORM;
-        return 0;
-}
-
-static ssize_t write_mouse(struct file * file, const char * buffer,
-			   size_t count, loff_t *ppos)
-{
-        return -EINVAL;
-}
-
-static ssize_t read_mouse(struct file * file, char * buffer,
-			  size_t count, loff_t *ppos)
-{
-	int dx,dy,r;
-	unsigned char buttons;
-
-	if (count < 3)
-		return -EINVAL;
-	if ((r = verify_area(VERIFY_WRITE, buffer, count)))
-   		return r;
-	if (!mouse_ready)
-		return -EAGAIN;	
-
-	MSE_UPDATE_OFF();
-	dx=mouse_dx;	
-	dy=mouse_dy;	
-	if (dx < -127)
-		dx = -127;
-	else
-	if (dx > 127)
-   		dx = 127;
-	if (dy < -127)
-   		dy = -127;
-	else
-	if (dy > 127)
-   		dy = 127;
-	buttons=(mouse_buttons & 1 ? 4 : 0) |
-			(mouse_buttons & 2 ? 1 : 0) |
-			(mouse_buttons & 4 ? 2 : 0);
-
-	mouse_dx-=dx;
-	mouse_dy-=dy;
-	MSE_UPDATE_ON();
-
-	if (put_user(buttons | 0x80, buffer++) ||
-	    put_user((char)dx, buffer++) ||
-	    put_user((char)dy, buffer++))
-		return -EINVAL;
-
-	if (count > 3)
-		if (clear_user(buffer, count - 3))
-			return -EFAULT;
-	return count;
-}
-
-static int fasync_mouse(int fd, struct file *filp, int on)
-{
-        int retval;
-
-        retval = fasync_helper(fd, filp, on, &mouse_fasyncptr);
-        if (retval < 0)
-                return retval;
-        return 0;
-}
-
-
-static int release_mouse(struct inode * inode, struct file * file)
-{
-        fasync_mouse(-1, file, 0);
-        if (--mouse_active)
-                return 0;
-        MSE_UPDATE_OFF();
-        MOD_DEC_USE_COUNT;
-        return 0;
-}
-
-static int open_mouse(struct inode * inode, struct file * file)
-{
-        if (mouse_active++)
-                return 0;
-        /*
-         *  use VBL to poll mouse deltas
-         */
-
-        mouse_dx = 0;
-        mouse_dy = 0;
-        mouse_buttons = 0;
-        mouse_active = 1;
-        MOD_INC_USE_COUNT;
-        MSE_UPDATE_ON();
-        return 0;
-}
-
 static void dn_keyb_process_key_event(unsigned char scancode) {
 
 	static unsigned char lastscancode;
@@ -411,7 +308,7 @@ static void dn_keyb_process_key_event(unsigned char scancode) {
 
 	if(prev_scancode==APOLLO_KBD_MODE_CHANGE) {
 		kbd_mode=scancode;
-/*		printk("modechange: %d\n",scancode);*/
+/*		printk("modechange: %d\n",scancode); */
 	}
 	else if((scancode & (~BREAK_FLAG)) == DNKEY_CAPS) {
     	/* printk("handle_scancode: %02x\n",DNKEY_CAPS); */
@@ -440,7 +337,8 @@ static void dn_keyb_process_mouse_event(unsigned char mouse_data) {
 
 	static short mouse_byte_count=0;
 	static u_char mouse_packet[3];
-	
+	short mouse_buttons;	
+
 	mouse_packet[mouse_byte_count++]=mouse_data;
 
 	if(mouse_byte_count==3) {
@@ -552,23 +450,20 @@ void write_keyb_cmd(u_short length, u_char *cmd) {
 
 }
 
-struct file_operations apollo_mouse_fops = {
-        NULL,           /* mouse_seek */
-        read_mouse,
-        write_mouse,
-        NULL,           /* mouse_readdir */
-        mouse_poll,     /* mouse_poll */
-        NULL,           /* mouse_ioctl */
-        NULL,           /* mouse_mmap */
-        open_mouse,
-	NULL,		/* flush */
-        release_mouse,
-        NULL,
-        fasync_mouse,
-};
+static int release_mouse(struct inode * inode, struct file * file)
+{
+        MOD_DEC_USE_COUNT;
+        return 0;
+}
+
+static int open_mouse(struct inode * inode, struct file * file)
+{
+        MOD_INC_USE_COUNT;
+        return 0;
+}
 
-static struct miscdevice apollo_mouse = {
-        APOLLO_MOUSE_MINOR, "apollomouse", &apollo_mouse_fops
+static struct busmouse apollo_mouse = {
+        APOLLO_MOUSE_MINOR, "apollomouse", open_mouse, release_mouse,7
 };
 
 int __init dn_keyb_init(void){
@@ -583,12 +478,12 @@ int __init dn_keyb_init(void){
   memcpy(key_maps[8], dnalt_map, sizeof(plain_map));
   memcpy(key_maps[12], dnctrl_alt_map, sizeof(plain_map));
 
-  mouse_dx=0; 
-  mouse_dy=0; 
-  mouse_buttons=0; 
-  mouse_wait=NULL;
 
-  misc_register(&apollo_mouse);
+  msedev=register_busmouse(&apollo_mouse);
+  if (msedev < 0)
+      printk(KERN_WARNING "Unable to install Apollo mouse driver.\n");
+   else
+      printk(KERN_INFO "Apollo mouse installed.\n");
 
   /* program UpDownMode */
 
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 30a76a04ea6c2674dcf21ce88590f66ed194b2b1..bce9c6e02f806ccc6adbe603882d115084e1b4eb 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -73,13 +73,13 @@
 		m = min(count, maxio); \
 		for (i = 0; i < m; i++) { \
 			for (t = 0; t < timeout && !ENABLE; t++) \
-				wait_some(2); \
+				wait_some(HZ/50); \
 			if(!ENABLE) \
 				return -EIO; \
 			f; \
 		} \
 		count -= m; \
-		if (m == maxio) wait_some(2); \
+		if (m == maxio) wait_some(HZ/50); \
 	} \
 }
 
@@ -87,7 +87,7 @@
 { \
 	int t; \
 	for(t = 0; t < n && !DSP56K_TRANSMIT; t++) \
-		wait_some(1); \
+		wait_some(HZ/100); \
 	if(!DSP56K_TRANSMIT) { \
 		return -EIO; \
 	} \
@@ -97,7 +97,7 @@
 { \
 	int t; \
 	for(t = 0; t < n && !DSP56K_RECEIVE; t++) \
-		wait_some(1); \
+		wait_some(HZ/100); \
 	if(!DSP56K_RECEIVE) { \
 		return -EIO; \
 	} \
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 5935ea1227137a842700986204eb9c892cd2fbc5..5f19cfe55d6418773306bf823703d182fb9c2b7c 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -509,10 +509,10 @@ static int pp_open (struct inode * inode, struct file * file)
 	if (!pp)
 		return -ENOMEM;
 
-	memset (pp, 0, sizeof (struct pp_struct));
 	pp->state.mode = IEEE1284_MODE_COMPAT;
 	pp->state.phase = init_phase (pp->state.mode);
 	pp->flags = 0;
+	pp->irqresponse = 0;
 	atomic_set (&pp->irqc, 0);
 	init_waitqueue_head (&pp->irq_wait);
 
@@ -539,8 +539,9 @@ static int pp_release (struct inode * inode, struct file * file)
 	}
 
 	if (pp->pdev) {
+		const char *name = pp->pdev->name;
 		parport_unregister_device (pp->pdev);
-		kfree (pp->pdev->name);
+		kfree (name);
 		pp->pdev = NULL;
 		printk (KERN_DEBUG CHRDEV "%x: unregistered pardevice\n",
 			minor);
diff --git a/drivers/isdn/Config.in b/drivers/isdn/Config.in
index 52b80809b39032e48389d5b521febc17257ce747..e88f5da946f9923bb12a477ce05360671c567952 100644
--- a/drivers/isdn/Config.in
+++ b/drivers/isdn/Config.in
@@ -2,76 +2,78 @@
 # ISDN device configuration
 #
 if [ "$CONFIG_INET" != "n" ]; then
-   bool '  Support synchronous PPP' CONFIG_ISDN_PPP
-   if [ "$CONFIG_ISDN_PPP" != "n" ]; then
-      bool '    Use VJ-compression with synchronous PPP' CONFIG_ISDN_PPP_VJ
-      bool '    Support generic MP (RFC 1717)' CONFIG_ISDN_MPP
-   fi
+  bool 'Support synchronous PPP' CONFIG_ISDN_PPP
+  if [ "$CONFIG_ISDN_PPP" != "n" ]; then
+    bool 'Use VJ-compression with synchronous PPP' CONFIG_ISDN_PPP_VJ
+    bool 'Support generic MP (RFC 1717)' CONFIG_ISDN_MPP
+  fi
 fi
-bool '  Support audio via ISDN' CONFIG_ISDN_AUDIO
+bool 'Support audio via ISDN' CONFIG_ISDN_AUDIO
 if [ "$CONFIG_ISDN_AUDIO" != "n" ]; then
-   bool '    Support AT-Fax Class 2 commands' CONFIG_ISDN_TTY_FAX
+  bool 'Support AT-Fax Class 2 commands' CONFIG_ISDN_TTY_FAX
 fi
-bool '  Support isdn diversion services' CONFIG_ISDN_DIVERSION
-if [ "$CONFIG_X25" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
-   bool '    X.25 PLP on top of ISDN (EXPERIMENTAL)' CONFIG_ISDN_X25
+bool 'Support isdn diversion services' CONFIG_ISDN_DIVERSION
+if [ "$CONFIG_X25" != "n" ]; then
+  bool 'X.25 PLP on top of ISDN (EXPERIMENTAL)' CONFIG_ISDN_X25
 fi
-dep_tristate '  ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN
-dep_tristate '  isdnloop support' CONFIG_ISDN_DRV_LOOP $CONFIG_ISDN
-dep_tristate '  PCBIT-D support' CONFIG_ISDN_DRV_PCBIT $CONFIG_ISDN
-dep_tristate '  HiSax SiemensChipSet driver support' CONFIG_ISDN_DRV_HISAX $CONFIG_ISDN
+dep_tristate 'ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN
+dep_tristate 'isdnloop support' CONFIG_ISDN_DRV_LOOP $CONFIG_ISDN
+dep_tristate 'PCBIT-D support' CONFIG_ISDN_DRV_PCBIT $CONFIG_ISDN
+dep_tristate 'HiSax SiemensChipSet driver support' CONFIG_ISDN_DRV_HISAX $CONFIG_ISDN
 if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
-   bool '    HiSax Support for EURO/DSS1' CONFIG_HISAX_EURO
-   if [ "$CONFIG_HISAX_EURO" != "n" ]; then
-      bool '      Support for german chargeinfo' CONFIG_DE_AOC
-      bool '      Disable sending complete' CONFIG_HISAX_NO_SENDCOMPLETE
-      bool '      Disable sending low layer compatibility' CONFIG_HISAX_NO_LLC
-   fi
-   bool '    HiSax Support for german 1TR6' CONFIG_HISAX_1TR6
-   bool '    HiSax Support for Teles 16.0/8.0' CONFIG_HISAX_16_0
-   bool '    HiSax Support for Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
-   bool '    HiSax Support for Teles PCI' CONFIG_HISAX_TELESPCI 
-   bool '    HiSax Support for Teles S0Box' CONFIG_HISAX_S0BOX 
-   bool '    HiSax Support for AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1
-   bool '    HiSax Support for AVM PnP/PCI (Fritz!PnP/PCI)' CONFIG_HISAX_FRITZPCI
-   bool '    HiSax Support for AVM A1 PCMCIA (Fritz)' CONFIG_HISAX_AVM_A1_PCMCIA
-   bool '    HiSax Support for Elsa cards' CONFIG_HISAX_ELSA
-   bool '    HiSax Support for ITK ix1-micro Revision 2' CONFIG_HISAX_IX1MICROR2
-   bool '    HiSax Support for Eicon.Diehl Diva cards' CONFIG_HISAX_DIEHLDIVA
-   bool '    HiSax Support for ASUSCOM cards' CONFIG_HISAX_ASUSCOM
-   bool '    HiSax Support for TELEINT cards' CONFIG_HISAX_TELEINT
-   bool '    HiSax Support for HFC-S based cards' CONFIG_HISAX_HFCS
-   bool '    HiSax Support for Sedlbauer cards' CONFIG_HISAX_SEDLBAUER
-   bool '    HiSax Support for USR Sportster internal TA' CONFIG_HISAX_SPORTSTER
-   bool '    HiSax Support for MIC card' CONFIG_HISAX_MIC
-   bool '    HiSax Support for NETjet card' CONFIG_HISAX_NETJET
-   bool '    HiSax Support for Niccy PnP/PCI card' CONFIG_HISAX_NICCY
-   bool '    HiSax Support for Siemens I-Surf card' CONFIG_HISAX_ISURF
-   bool '    HiSax Support for HST Saphir card' CONFIG_HISAX_HSTSAPHIR
-   bool '    HiSax Support for Telekom A4T card' CONFIG_HISAX_BKM_A4T
-   bool '    HiSax Support for Scitel Quadro card' CONFIG_HISAX_SCT_QUADRO
-   bool '    HiSax Support for Gazel cards' CONFIG_HISAX_GAZEL
-   bool '    HiSax Support for HFC PCI-Bus cards' CONFIG_HISAX_HFC_PCI
-   if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
-#      bool '    HiSax Support for TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
-      if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
-	 bool '    HiSax Support for Am7930' CONFIG_HISAX_AMD7930
-      fi
-   fi
+    bool 'HiSax Support for EURO/DSS1' CONFIG_HISAX_EURO
+    if [ "$CONFIG_HISAX_EURO" != "n" ]; then
+	    bool 'Support for german chargeinfo' CONFIG_DE_AOC
+	    bool 'Disable sending complete' CONFIG_HISAX_NO_SENDCOMPLETE
+	    bool 'Disable sending low layer compatibility' CONFIG_HISAX_NO_LLC
+    fi
+    bool 'HiSax Support for german 1TR6' CONFIG_HISAX_1TR6
+    bool 'HiSax Support for Teles 16.0/8.0' CONFIG_HISAX_16_0
+    bool 'HiSax Support for Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
+    bool 'HiSax Support for Teles PCI' CONFIG_HISAX_TELESPCI 
+    bool 'HiSax Support for Teles S0Box' CONFIG_HISAX_S0BOX 
+    bool 'HiSax Support for AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1
+    bool 'HiSax Support for AVM PnP/PCI (Fritz!PnP/PCI)' CONFIG_HISAX_FRITZPCI
+    bool 'HiSax Support for AVM A1 PCMCIA (Fritz)' CONFIG_HISAX_AVM_A1_PCMCIA
+    bool 'HiSax Support for Elsa cards' CONFIG_HISAX_ELSA
+    bool 'HiSax Support for ITK ix1-micro Revision 2' CONFIG_HISAX_IX1MICROR2
+    bool 'HiSax Support for Eicon.Diehl Diva cards' CONFIG_HISAX_DIEHLDIVA
+    bool 'HiSax Support for ASUSCOM cards' CONFIG_HISAX_ASUSCOM
+    bool 'HiSax Support for TELEINT cards' CONFIG_HISAX_TELEINT
+    bool 'HiSax Support for HFC-S based cards' CONFIG_HISAX_HFCS
+    bool 'HiSax Support for Sedlbauer cards' CONFIG_HISAX_SEDLBAUER
+    bool 'HiSax Support for USR Sportster internal TA' CONFIG_HISAX_SPORTSTER
+    bool 'HiSax Support for MIC card' CONFIG_HISAX_MIC
+    bool 'HiSax Support for NETjet card' CONFIG_HISAX_NETJET
+    bool 'HiSax Support for Niccy PnP/PCI card' CONFIG_HISAX_NICCY
+    bool 'HiSax Support for Siemens I-Surf card' CONFIG_HISAX_ISURF
+    bool 'HiSax Support for HST Saphir card' CONFIG_HISAX_HSTSAPHIR
+    bool 'HiSax Support for Telekom A4T card' CONFIG_HISAX_BKM_A4T
+    bool 'HiSax Support for Scitel Quadro card' CONFIG_HISAX_SCT_QUADRO
+    bool 'HiSax Support for Gazel cards' CONFIG_HISAX_GAZEL
+    bool 'HiSax Support for HFC PCI-Bus cards' CONFIG_HISAX_HFC_PCI
+    if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
+        bool 'HiSax Support for Winbond W6692 based cards (EXPERIMENTAL)' CONFIG_HISAX_W6692
+#	bool 'HiSax Support for TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
+	if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
+		bool 'HiSax Support for Am7930' CONFIG_HISAX_AMD7930
+	fi
+    fi
 fi
 if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
-	dep_tristate '  Spellcaster support (EXPERIMENTAL)' CONFIG_ISDN_DRV_SC $CONFIG_ISDN
-	dep_tristate '  IBM Active 2000 support (EXPERIMENTAL)' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN
+	dep_tristate 'Spellcaster support (EXPERIMENTAL)' CONFIG_ISDN_DRV_SC $CONFIG_ISDN
+	dep_tristate 'IBM Active 2000 support (EXPERIMENTAL)' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN
 fi
-dep_tristate '  Eicon.Diehl active card support' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN
+dep_tristate 'Eicon.Diehl active card support' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN
 if [ "$CONFIG_ISDN_DRV_EICON" != "n" ]; then
-    bool '    Eicon S, SX, SCOM, Quadro, S2M support' CONFIG_ISDN_DRV_EICON_ISA
+    bool 'Eicon S,SX,SCOM,Quadro,S2M support' CONFIG_ISDN_DRV_EICON_ISA
 fi
-dep_tristate '  AVM CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN
+dep_tristate 'AVM CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN
 if [ "$CONFIG_ISDN_DRV_AVMB1" != "n" ]; then
-   bool '    AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA
-   bool '    AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI
-   bool '    AVM T1/T1B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA
-   bool '    AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
-   bool '    Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
+    bool 'AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA
+    bool 'AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI
+    bool 'AVM T1/T1-B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA
+    bool 'AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
+    bool 'AVM T1/T1-B PCI support' CONFIG_ISDN_DRV_AVMB1_T1PCI
+    bool 'Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
 fi
diff --git a/drivers/isdn/act2000/act2000_isa.c b/drivers/isdn/act2000/act2000_isa.c
index 80f06b0808132b29ae6409ad8f938a26f10dd57c..99c93dbed6ec808bbeda19b0c7d4e9e771d095c8 100644
--- a/drivers/isdn/act2000/act2000_isa.c
+++ b/drivers/isdn/act2000/act2000_isa.c
@@ -1,4 +1,4 @@
-/* $Id: act2000_isa.c,v 1.8 1999/01/05 18:29:25 he Exp $
+/* $Id: act2000_isa.c,v 1.10 1999/10/24 18:46:05 fritz Exp $
  *
  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
  *
@@ -20,6 +20,13 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: act2000_isa.c,v $
+ * Revision 1.10  1999/10/24 18:46:05  fritz
+ * Changed isa_ prefix to act2000_isa_ to prevent name-clash in latest
+ * kernels.
+ *
+ * Revision 1.9  1999/09/04 06:20:04  keil
+ * Changes from kernel set_current_state()
+ *
  * Revision 1.8  1999/01/05 18:29:25  he
  * merged remaining schedule_timeout() changes from 2.1.127
  *
@@ -61,17 +68,17 @@ static act2000_card *irq2card_map[16] =
 	0, 0, 0, 0, 0, 0, 0, 0,	0, 0, 0, 0, 0, 0, 0, 0
 };
 
-static int isa_irqs[] =
+static int act2000_isa_irqs[] =
 {
         3, 5, 7, 10, 11, 12, 15
 };
-#define ISA_NRIRQS (sizeof(isa_irqs)/sizeof(int))
+#define ISA_NRIRQS (sizeof(act2000_isa_irqs)/sizeof(int))
 
 static void
-isa_delay(long t)
+act2000_isa_delay(long t)
 {
         sti();
-        current->state = TASK_INTERRUPTIBLE;
+        set_current_state(TASK_INTERRUPTIBLE);
         schedule_timeout(t);
         sti();
 }
@@ -83,7 +90,7 @@ isa_delay(long t)
  *   0 = Signature not found.
  */
 static int
-isa_reset(unsigned short portbase)
+act2000_isa_reset(unsigned short portbase)
 {
         unsigned char reg;
         int i;
@@ -109,7 +116,7 @@ isa_reset(unsigned short portbase)
 }
 
 int
-isa_detect(unsigned short portbase)
+act2000_isa_detect(unsigned short portbase)
 {
         int ret = 0;
         unsigned long flags;
@@ -117,13 +124,13 @@ isa_detect(unsigned short portbase)
         save_flags(flags);
         cli();
         if (!check_region(portbase, ISA_REGION))
-                ret = isa_reset(portbase);
+                ret = act2000_isa_reset(portbase);
         restore_flags(flags);
         return ret;
 }
 
 static void
-isa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+act2000_isa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
         act2000_card *card = irq2card_map[irq];
         u_char istatus;
@@ -138,7 +145,7 @@ isa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                 /* RX fifo has data */
 		istatus &= ISA_ISR_OUT_MASK;
 		outb(0, ISA_PORT_SIS);
-		isa_receive(card);
+		act2000_isa_receive(card);
 		outb(ISA_SIS_INT, ISA_PORT_SIS);
         }
         if (istatus & ISA_ISR_ERR) {
@@ -151,7 +158,7 @@ isa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 }
 
 static void
-isa_select_irq(act2000_card * card)
+act2000_isa_select_irq(act2000_card * card)
 {
 	unsigned char reg;
 
@@ -183,9 +190,9 @@ isa_select_irq(act2000_card * card)
 }
 
 static void
-isa_enable_irq(act2000_card * card)
+act2000_isa_enable_irq(act2000_card * card)
 {
-	isa_select_irq(card);
+	act2000_isa_select_irq(card);
 	/* Enable READ irq */
 	outb(ISA_SIS_INT, ISA_PORT_SIS);
 }
@@ -195,7 +202,7 @@ isa_enable_irq(act2000_card * card)
  * If irq is -1, choose next free irq, else irq is given explicitely.
  */
 int
-isa_config_irq(act2000_card * card, short irq)
+act2000_isa_config_irq(act2000_card * card, short irq)
 {
         int i;
         unsigned long flags;
@@ -213,8 +220,8 @@ isa_config_irq(act2000_card * card, short irq)
         if (irq == -1) {
                 /* Auto select */
                 for (i = 0; i < ISA_NRIRQS; i++) {
-                        if (!request_irq(isa_irqs[i], &isa_interrupt, 0, card->regname, NULL)) {
-                                card->irq = isa_irqs[i];
+                        if (!request_irq(act2000_isa_irqs[i], &act2000_isa_interrupt, 0, card->regname, NULL)) {
+                                card->irq = act2000_isa_irqs[i];
                                 irq2card_map[card->irq] = card;
                                 card->flags |= ACT2000_FLAGS_IVALID;
                                 break;
@@ -222,7 +229,7 @@ isa_config_irq(act2000_card * card, short irq)
                 }
         } else {
                 /* Fixed irq */
-                if (!request_irq(irq, &isa_interrupt, 0, card->regname, NULL)) {
+                if (!request_irq(irq, &act2000_isa_interrupt, 0, card->regname, NULL)) {
                         card->irq = irq;
                         irq2card_map[card->irq] = card;
 			card->flags |= ACT2000_FLAGS_IVALID;
@@ -234,7 +241,7 @@ isa_config_irq(act2000_card * card, short irq)
                        "act2000: Could not request irq\n");
                 return -EBUSY;
         } else {
-		isa_select_irq(card);
+		act2000_isa_select_irq(card);
                 /* Disable READ and WRITE irq */
                 outb(0, ISA_PORT_SIS);
                 outb(0, ISA_PORT_SOS);
@@ -243,7 +250,7 @@ isa_config_irq(act2000_card * card, short irq)
 }
 
 int
-isa_config_port(act2000_card * card, unsigned short portbase)
+act2000_isa_config_port(act2000_card * card, unsigned short portbase)
 {
         if (card->flags & ACT2000_FLAGS_PVALID) {
                 release_region(card->port, ISA_REGION);
@@ -262,7 +269,7 @@ isa_config_port(act2000_card * card, unsigned short portbase)
  * Release ressources, used by an adaptor.
  */
 void
-isa_release(act2000_card * card)
+act2000_isa_release(act2000_card * card)
 {
         unsigned long flags;
 
@@ -280,7 +287,7 @@ isa_release(act2000_card * card)
 }
 
 static int
-isa_writeb(act2000_card * card, u_char data)
+act2000_isa_writeb(act2000_card * card, u_char data)
 {
         u_char timeout = 40;
 
@@ -297,7 +304,7 @@ isa_writeb(act2000_card * card, u_char data)
 }
 
 static int
-isa_readb(act2000_card * card, u_char * data)
+act2000_isa_readb(act2000_card * card, u_char * data)
 {
         u_char timeout = 40;
 
@@ -314,13 +321,13 @@ isa_readb(act2000_card * card, u_char * data)
 }
 
 void
-isa_receive(act2000_card *card)
+act2000_isa_receive(act2000_card *card)
 {
 	u_char c;
 
         if (test_and_set_bit(ACT2000_LOCK_RX, (void *) &card->ilock) != 0)
 		return;
-	while (!isa_readb(card, &c)) {
+	while (!act2000_isa_readb(card, &c)) {
 		if (card->idat.isa.rcvidx < 8) {
                         card->idat.isa.rcvhdr[card->idat.isa.rcvidx++] = c;
 			if (card->idat.isa.rcvidx == 8) {
@@ -332,7 +339,7 @@ isa_receive(act2000_card *card)
 					if (card->idat.isa.rcvskb == NULL) {
 						card->idat.isa.rcvignore = 1;
 						printk(KERN_WARNING
-						       "isa_receive: no memory\n");
+						       "act2000_isa_receive: no memory\n");
 						test_and_clear_bit(ACT2000_LOCK_RX, (void *) &card->ilock);
 						return;
 					}
@@ -341,12 +348,12 @@ isa_receive(act2000_card *card)
 				} else {
 					card->idat.isa.rcvidx = 0;
 					printk(KERN_WARNING
-					       "isa_receive: Invalid CAPI msg\n");
+					       "act2000_isa_receive: Invalid CAPI msg\n");
 					{
 						int i; __u8 *p; __u8 *c; __u8 tmp[30];
 						for (i = 0, p = (__u8 *)&card->idat.isa.rcvhdr, c = tmp; i < 8; i++)
 							c += sprintf(c, "%02x ", *(p++));
-						printk(KERN_WARNING "isa_receive: %s\n", tmp);
+						printk(KERN_WARNING "act2000_isa_receive: %s\n", tmp);
 					}
 				}
 			}
@@ -377,7 +384,7 @@ isa_receive(act2000_card *card)
 }
 
 void
-isa_send(act2000_card * card)
+act2000_isa_send(act2000_card * card)
 {
 	unsigned long flags;
 	struct sk_buff *skb;
@@ -410,11 +417,8 @@ isa_send(act2000_card * card)
 		skb = card->sbuf;
 		l = 0;
 		while (skb->len) {
-			if (isa_writeb(card, *(skb->data))) {
+			if (act2000_isa_writeb(card, *(skb->data))) {
 				/* Fifo is full, but more data to send */
-#if 0
-				printk(KERN_DEBUG "isa_send: %d bytes\n", l);
-#endif
 				test_and_clear_bit(ACT2000_LOCK_TX, (void *) &card->ilock);
 				/* Schedule myself */
 				act2000_schedule_tx(card);
@@ -437,9 +441,6 @@ isa_send(act2000_card * card)
 		} else
 			dev_kfree_skb(skb);
 		card->sbuf = NULL;
-#if 0
-		printk(KERN_DEBUG "isa_send: %d bytes\n", l);
-#endif
 	}
 }
 
@@ -447,7 +448,7 @@ isa_send(act2000_card * card)
  * Get firmware ID, check for 'ISDN' signature.
  */
 static int
-isa_getid(act2000_card * card)
+act2000_isa_getid(act2000_card * card)
 {
 
         act2000_fwid fid;
@@ -457,7 +458,7 @@ isa_getid(act2000_card * card)
         while (1) {
                 if (count > 510)
                         return -EPROTO;
-                if (isa_readb(card, p++))
+                if (act2000_isa_readb(card, p++))
                         break;
                 count++;
         }
@@ -476,7 +477,7 @@ isa_getid(act2000_card * card)
         printk(KERN_INFO "act2000: Firmware-ID: %s\n", fid.revision);
 	if (card->flags & ACT2000_FLAGS_IVALID) {
 		printk(KERN_DEBUG "Enabling Interrupts ...\n");
-		isa_enable_irq(card);
+		act2000_isa_enable_irq(card);
 	}
         return 0;
 }
@@ -485,7 +486,7 @@ isa_getid(act2000_card * card)
  * Download microcode into card, check Firmware signature.
  */
 int
-isa_download(act2000_card * card, act2000_ddef * cb)
+act2000_isa_download(act2000_card * card, act2000_ddef * cb)
 {
         int length;
         int ret;
@@ -497,9 +498,9 @@ isa_download(act2000_card * card, act2000_ddef * cb)
         u_char *buf;
         act2000_ddef cblock;
 
-        if (!isa_reset(card->port))
+        if (!act2000_isa_reset(card->port))
                 return -ENXIO;
-        isa_delay(HZ / 2);
+        act2000_isa_delay(HZ / 2);
         if ((ret = verify_area(VERIFY_READ, (void *) cb, sizeof(cblock))))
                 return ret;
         copy_from_user(&cblock, (char *) cb, sizeof(cblock));
@@ -517,7 +518,7 @@ isa_download(act2000_card * card, act2000_ddef * cb)
                 b = buf;
                 copy_from_user(buf, p, l);
                 while (c < l) {
-                        if (isa_writeb(card, *b++)) {
+                        if (act2000_isa_writeb(card, *b++)) {
                                 printk(KERN_WARNING
                                        "act2000: loader timed out"
                                        " len=%d c=%d\n", length, c);
@@ -530,6 +531,6 @@ isa_download(act2000_card * card, act2000_ddef * cb)
                 p += l;
         }
         kfree(buf);
-        isa_delay(HZ / 2);
-        return (isa_getid(card));
+        act2000_isa_delay(HZ / 2);
+        return (act2000_isa_getid(card));
 }
diff --git a/drivers/isdn/act2000/act2000_isa.h b/drivers/isdn/act2000/act2000_isa.h
index 35a68e7d2ca04092f1edb49c51c077feca9bc10d..ff3e5419aeb7f3f3fb4ac0c2c84ab8c4a4ef926d 100644
--- a/drivers/isdn/act2000/act2000_isa.h
+++ b/drivers/isdn/act2000/act2000_isa.h
@@ -1,4 +1,4 @@
-/* $Id: act2000_isa.h,v 1.2 1998/11/05 22:12:43 fritz Exp $
+/* $Id: act2000_isa.h,v 1.3 1999/10/24 18:46:05 fritz Exp $
  *
  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
  *
@@ -20,6 +20,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: act2000_isa.h,v $
+ * Revision 1.3  1999/10/24 18:46:05  fritz
+ * Changed isa_ prefix to act2000_isa_ to prevent name-clash in latest
+ * kernels.
+ *
  * Revision 1.2  1998/11/05 22:12:43  fritz
  * Changed mail-address.
  *
@@ -141,12 +145,12 @@ typedef enum {
 
 /* Prototypes */
 
-extern int isa_detect(unsigned short portbase);
-extern int isa_config_irq(act2000_card * card, short irq);
-extern int isa_config_port(act2000_card * card, unsigned short portbase);
-extern int isa_download(act2000_card * card, act2000_ddef * cb);
-extern void isa_release(act2000_card * card);
-extern void isa_receive(act2000_card *card);
-extern void isa_send(act2000_card *card);
+extern int act2000_isa_detect(unsigned short portbase);
+extern int act2000_isa_config_irq(act2000_card * card, short irq);
+extern int act2000_isa_config_port(act2000_card * card, unsigned short portbase);
+extern int act2000_isa_download(act2000_card * card, act2000_ddef * cb);
+extern void act2000_isa_release(act2000_card * card);
+extern void act2000_isa_receive(act2000_card *card);
+extern void act2000_isa_send(act2000_card *card);
 
 #endif                          /* act2000_isa_h */
diff --git a/drivers/isdn/act2000/capi.c b/drivers/isdn/act2000/capi.c
index df2fd68d33a29cf32bfa90ee74c735f9391fef24..9502b314e1c370962992195e0bb0e9810352cb2c 100644
--- a/drivers/isdn/act2000/capi.c
+++ b/drivers/isdn/act2000/capi.c
@@ -113,10 +113,6 @@ static actcapi_msgdsc valid_msg[] = {
 	{{ 0x84, 0x03}, "DISCONNECT_B3_RESP"},
 	{{ 0x86, 0x03}, "DATA_B3_RESP"},
 	{{ 0xff, 0x03}, "MANUFACTURER_RESP"},
-#if 0
-/* CAPI 2.0 */
-	{{ 0x05, 0x80}, "LISTEN_REQ (CAPI 2.0)"},
-#endif
 #endif
 	{{ 0x00, 0x00}, NULL},
 };
diff --git a/drivers/isdn/act2000/capi.h b/drivers/isdn/act2000/capi.h
index 69a1041005ffc1cb6394a92bdacbc8eeb7109e33..0500550db90f7b0a328d0e03fd6a9e185449173a 100644
--- a/drivers/isdn/act2000/capi.h
+++ b/drivers/isdn/act2000/capi.h
@@ -322,19 +322,6 @@ typedef struct actcapi_msg {
 			__u16 plci;
 			__u16 info;
 		} select_b3_protocol_conf;
-#if 0
-		struct listen_req {
-			__u32 controller;
-			__u32 infomask;  
-			__u32 cipmask;
-			__u32 cipmask2;
-			__u16 dummy; /* 2 Length-bytes of 2 Structs MUST always be 0!!! */
-		} listen_req;
-		struct listen_conf {
-			__u32  controller;
-			__u16 info;
-		} listen_conf;
-#else
 		struct listen_req {
 			__u8  controller;
 			__u32 infomask __attribute__ ((packed));  
@@ -345,7 +332,6 @@ typedef struct actcapi_msg {
 			__u8  controller;
 			__u16 info __attribute__ ((packed));
 		} listen_conf;
-#endif
 		struct data_b3_req {
 			__u16 fakencci;
 			__u16 datalen;
diff --git a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c
index 2ec5e2fd4132a73ab0d6fe899338b5afddeef87e..f152792532ad88a274da22bc8ca3d514dc794c64 100644
--- a/drivers/isdn/act2000/module.c
+++ b/drivers/isdn/act2000/module.c
@@ -1,4 +1,4 @@
-/* $Id: module.c,v 1.9 1999/04/12 13:13:56 fritz Exp $
+/* $Id: module.c,v 1.11 1999/10/30 09:48:04 keil Exp $
  *
  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
  *
@@ -20,6 +20,13 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: module.c,v $
+ * Revision 1.11  1999/10/30 09:48:04  keil
+ * miss one prefix act2000
+ *
+ * Revision 1.10  1999/10/24 18:46:05  fritz
+ * Changed isa_ prefix to act2000_isa_ to prevent name-clash in latest
+ * kernels.
+ *
  * Revision 1.9  1999/04/12 13:13:56  fritz
  * Made cards pointer static to avoid name-clash.
  *
@@ -56,12 +63,12 @@
 #include "act2000_isa.h"
 #include "capi.h"
 
-static unsigned short isa_ports[] =
+static unsigned short act2000_isa_ports[] =
 {
         0x0200, 0x0240, 0x0280, 0x02c0, 0x0300, 0x0340, 0x0380,
         0xcfe0, 0xcfa0, 0xcf60, 0xcf20, 0xcee0, 0xcea0, 0xce60,
 };
-#define ISA_NRPORTS (sizeof(isa_ports)/sizeof(unsigned short))
+#define ISA_NRPORTS (sizeof(act2000_isa_ports)/sizeof(unsigned short))
 
 static act2000_card *cards = (act2000_card *) NULL;
 
@@ -238,7 +245,7 @@ act2000_transmit(struct act2000_card *card)
 {
 	switch (card->bus) {
 		case ACT2000_BUS_ISA:
-			isa_send(card);
+			act2000_isa_send(card);
 			break;
 		case ACT2000_BUS_PCMCIA:
 		case ACT2000_BUS_MCA:
@@ -253,7 +260,7 @@ act2000_receive(struct act2000_card *card)
 {
 	switch (card->bus) {
 		case ACT2000_BUS_ISA:
-			isa_receive(card);
+			act2000_isa_receive(card);
 			break;
 		case ACT2000_BUS_PCMCIA:
 		case ACT2000_BUS_MCA:
@@ -296,7 +303,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c)
 				case ACT2000_IOCTL_LOADBOOT:
 					switch (card->bus) {
 						case ACT2000_BUS_ISA:
-							ret = isa_download(card,
+							ret = act2000_isa_download(card,
 									   (act2000_ddef *)a);
 							if (!ret) {
 								card->flags |= ACT2000_FLAGS_LOADED;
@@ -701,10 +708,6 @@ act2000_alloccard(int bus, int port, int irq, char *id)
         card->interface.features =
 		ISDN_FEATURE_L2_X75I |
 		ISDN_FEATURE_L2_HDLC |
-#if 0
-/* Not yet! New Firmware is on the way ... */
-		ISDN_FEATURE_L2_TRANS |
-#endif
 		ISDN_FEATURE_L3_TRANS |
 		ISDN_FEATURE_P_UNKNOWN;
         card->interface.hl_hdrlen = 20;
@@ -762,7 +765,7 @@ unregister_card(act2000_card * card)
         card->interface.statcallb(&cmd);
         switch (card->bus) {
 		case ACT2000_BUS_ISA:
-			isa_release(card);
+			act2000_isa_release(card);
 			break;
 		case ACT2000_BUS_MCA:
 		case ACT2000_BUS_PCMCIA:
@@ -796,11 +799,11 @@ act2000_addcard(int bus, int port, int irq, char *id)
 		switch (bus) {
 			case ACT2000_BUS_ISA:
 				for (i = 0; i < ISA_NRPORTS; i++)
-					if (isa_detect(isa_ports[i])) {
+					if (act2000_isa_detect(act2000_isa_ports[i])) {
 						printk(KERN_INFO
 						       "act2000: Detected ISA card at port 0x%x\n",
-						       isa_ports[i]);
-						act2000_alloccard(bus, isa_ports[i], irq, id);
+						       act2000_isa_ports[i]);
+						act2000_alloccard(bus, act2000_isa_ports[i], irq, id);
 					}
 				break;
 			case ACT2000_BUS_MCA:
@@ -823,10 +826,10 @@ act2000_addcard(int bus, int port, int irq, char *id)
 			added++;
 			switch (p->bus) {
 				case ACT2000_BUS_ISA:
-					if (isa_detect(p->port)) {
+					if (act2000_isa_detect(p->port)) {
 						if (act2000_registercard(p))
 							break;
-						if (isa_config_port(p, p->port)) {
+						if (act2000_isa_config_port(p, p->port)) {
 							printk(KERN_WARNING
 							       "act2000: Could not request port 0x%04x\n",
 							       p->port);
@@ -834,7 +837,7 @@ act2000_addcard(int bus, int port, int irq, char *id)
 							p->interface.statcallb = NULL;
 							break;
 						}
-						if (isa_config_irq(p, p->irq)) {
+						if (act2000_isa_config_irq(p, p->irq)) {
 							printk(KERN_INFO
 							       "act2000: No IRQ available, fallback to polling\n");
 							/* Fall back to polled operation */
diff --git a/drivers/isdn/avmb1/Makefile b/drivers/isdn/avmb1/Makefile
index 9f73ea2e3699e358b0bdfa68ea82d7e0ccbf9661..111c39466fb9409eeb0721dbd33fa1d8e6e9db90 100644
--- a/drivers/isdn/avmb1/Makefile
+++ b/drivers/isdn/avmb1/Makefile
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile,v 1.6 1999/07/20 06:41:44 calle Exp $
+# $Id: Makefile,v 1.7 1999/09/15 08:16:03 calle Exp $
 #
 # Makefile for the CAPI and AVM-B1 device drivers.
 #
@@ -11,6 +11,9 @@
 # parent makes..
 #
 # $Log: Makefile,v $
+# Revision 1.7  1999/09/15 08:16:03  calle
+# Implementation of 64Bit extention complete.
+#
 # Revision 1.6  1999/07/20 06:41:44  calle
 # Bugfix: After the redesign of the AVM B1 driver, the driver didn't even
 #         compile, if not selected as modules.
@@ -90,6 +93,12 @@ ifeq ($(CONFIG_ISDN_DRV_AVMB1),y)
   ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
   OX_OBJS   += b1pcmcia.o
   endif
+  ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI
+  O_OBJS   += t1pci.o
+  endif
+  ifdef CONFIG_ISDN_DRV_AVMB1_C4
+  O_OBJS   += c4.o
+  endif
   OX_OBJS  += capiutil.o capidrv.o b1.o
 else
   ifeq ($(CONFIG_ISDN_DRV_AVMB1),m)
@@ -105,10 +114,16 @@ else
   ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA
   M_OBJS   += t1isa.o
   endif
-  MX_OBJS  += capiutil.o capidrv.o b1.o
   ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
   MX_OBJS  += b1pcmcia.o
   endif
+  ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI
+  M_OBJS   += t1pci.o
+  endif
+  ifdef CONFIG_ISDN_DRV_AVMB1_C4
+  M_OBJS   += c4.o
+  endif
+  MX_OBJS  += capiutil.o capidrv.o b1.o
   endif
 endif
 
diff --git a/drivers/isdn/avmb1/avmcard.h b/drivers/isdn/avmb1/avmcard.h
index e94c5637cdec2f24e0decc4527cb8beeea92a88d..f4b5df6891194afdf72df6402317001633862e1b 100644
--- a/drivers/isdn/avmb1/avmcard.h
+++ b/drivers/isdn/avmb1/avmcard.h
@@ -1,9 +1,21 @@
 /*
- * $Id: avmcard.h,v 1.4 1999/08/04 10:10:08 calle Exp $
+ * $Id: avmcard.h,v 1.6 1999/11/05 16:38:01 calle Exp $
  *
  * Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: avmcard.h,v $
+ * 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
+ *   constant string.
+ * - Moved some data from struct avmcard into new struct avmctrl_info.
+ *   Changed all lowlevel capi driver to match the new structur.
+ *
+ * Revision 1.5  1999/09/07 09:02:53  calle
+ * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and
+ * DATA_B3_IND is always directly after the CAPI message. The "Data" member
+ * ist never used inside the kernel.
+ *
  * Revision 1.4  1999/08/04 10:10:08  calle
  * Bugfix: corrected /proc functions, added structure for new AVM cards.
  *
@@ -73,6 +85,7 @@ typedef struct avmcard_dmainfo {
 	__u8  sendbuf[128+2048];
 } avmcard_dmainfo;
 
+
 typedef struct avmcard {
 	char name[32];
 	unsigned int port;
@@ -81,25 +94,34 @@ typedef struct avmcard {
 	enum avmcardtype cardtype;
 	int cardnr; /* for t1isa */
 
-	int versionlen;
-	char versionbuf[1024];
-	char *version[AVM_MAXVERSION];
-
-	char cardname[32];
-
-	char infobuf[128];	/* for function procinfo */
 	char msgbuf[128];	/* capimsg msg part */
 	char databuf[2048];	/* capimsg data part */
 
 	int interrupt;
 
 	void *mbase;
-	__u32 csr;
+	volatile __u32 csr;
 	avmcard_dmainfo *dma;
 
-	struct capi_ctr *ctrl;
+	struct avmctrl_info {
+		char cardname[32];
+
+		int versionlen;
+		char versionbuf[1024];
+		char *version[AVM_MAXVERSION];
+
+		char infobuf[128];	/* for function procinfo */
+
+		struct avmcard  *card;
+		struct capi_ctr *capi_ctrl;
+
+	} *ctrlinfo;
+
+	int nlogcontr;
 } avmcard;
 
+typedef struct avmctrl_info avmctrl_info;
+
 extern int b1_irq_table[16];
 
 /*
@@ -540,16 +562,16 @@ static inline void b1_setinterrupt(unsigned int base, unsigned irq,
 }
 
 int b1_detect(unsigned int base, enum avmcardtype cardtype);
-int b1_load_t4file(unsigned int base, capiloaddatapart * t4file);
-int b1_load_config(unsigned int base, capiloaddatapart * config);
-int b1_loaded(unsigned int base);
+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,
 				capi_register_params *rp);
 void b1_release_appl(struct capi_ctr *ctrl, __u16 appl);
 void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
-void b1_parse_version(avmcard *card);
+void b1_parse_version(avmctrl_info *card);
 void b1_handle_interrupt(avmcard * card);
 
 int b1ctl_read_proc(char *page, char **start, off_t off,
diff --git a/drivers/isdn/avmb1/b1.c b/drivers/isdn/avmb1/b1.c
index c4dffdacbc7484c6da9c446b936663e3d45c7f54..900b31c8c1632a0475ae0199482dcaab2f5b4020 100644
--- a/drivers/isdn/avmb1/b1.c
+++ b/drivers/isdn/avmb1/b1.c
@@ -1,11 +1,29 @@
 /*
- * $Id: b1.c,v 1.8 1999/08/22 20:26:22 calle Exp $
+ * $Id: b1.c,v 1.12 1999/11/05 16:38:01 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.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
+ *   constant string.
+ * - Moved some data from struct avmcard into new struct avmctrl_info.
+ *   Changed all lowlevel capi driver to match the new structur.
+ *
+ * Revision 1.11  1999/10/11 22:04:12  keil
+ * COMPAT_NEED_UACCESS (no include in isdn_compat.h)
+ *
+ * Revision 1.10  1999/09/15 08:16:03  calle
+ * Implementation of 64Bit extention complete.
+ *
+ * Revision 1.9  1999/09/07 09:02:53  calle
+ * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and
+ * DATA_B3_IND is always directly after the CAPI message. The "Data" member
+ * ist never used inside the kernel.
+ *
  * Revision 1.8  1999/08/22 20:26:22  calle
  * backported changes from kernel 2.3.14:
  * - several #include "config.h" gone, others come.
@@ -62,13 +80,13 @@
 #include <linux/ioport.h>
 #include <linux/capi.h>
 #include <asm/io.h>
-#include <linux/isdn_compat.h>
+#include <asm/uaccess.h>
 #include "capilli.h"
 #include "avmcard.h"
 #include "capicmd.h"
 #include "capiutil.h"
 
-static char *revision = "$Revision: 1.8 $";
+static char *revision = "$Revision: 1.12 $";
 
 /* ------------------------------------------------------------- */
 
@@ -140,11 +158,12 @@ int b1_detect(unsigned int base, enum avmcardtype cardtype)
 	return 0;
 }
 
-int b1_load_t4file(unsigned int base, capiloaddatapart * t4file)
+int b1_load_t4file(avmcard *card, capiloaddatapart * t4file)
 {
 	unsigned char buf[256];
 	unsigned char *dp;
 	int i, left, retval;
+	unsigned int base = card->port;
 
 	dp = t4file->data;
 	left = t4file->len;
@@ -158,7 +177,8 @@ int b1_load_t4file(unsigned int base, capiloaddatapart * t4file)
 		}
 		for (i = 0; i < sizeof(buf); i++)
 			if (b1_save_put_byte(base, buf[i]) < 0) {
-				printk(KERN_ERR "b1_load_t4file: corrupted t4 file ?\n");
+				printk(KERN_ERR "%s: corrupted firmware file ?\n",
+						card->name);
 				return -EIO;
 			}
 		left -= sizeof(buf);
@@ -174,17 +194,19 @@ int b1_load_t4file(unsigned int base, capiloaddatapart * t4file)
 		}
 		for (i = 0; i < left; i++)
 			if (b1_save_put_byte(base, buf[i]) < 0) {
-				printk(KERN_ERR "b1_load_t4file: corrupted t4 file ?\n");
+				printk(KERN_ERR "%s: corrupted firmware file ?\n",
+						card->name);
 				return -EIO;
 			}
 	}
 	return 0;
 }
 
-int b1_load_config(unsigned int base, capiloaddatapart * config)
+int b1_load_config(avmcard *card, capiloaddatapart * config)
 {
 	unsigned char buf[256];
 	unsigned char *dp;
+	unsigned int base = card->port;
 	int i, j, left, retval;
 
 	dp = config->data;
@@ -233,8 +255,9 @@ int b1_load_config(unsigned int base, capiloaddatapart * config)
 	return 0;
 }
 
-int b1_loaded(unsigned int base)
+int b1_loaded(avmcard *card)
 {
+	unsigned int base = card->port;
 	unsigned long stop;
 	unsigned char ans;
 	unsigned long tout = 2;
@@ -244,7 +267,8 @@ int b1_loaded(unsigned int base)
 			break;
 	}
 	if (!b1_tx_empty(base)) {
-		printk(KERN_ERR "b1_loaded: tx err, corrupted t4 file ?\n");
+		printk(KERN_ERR "%s: b1_loaded: tx err, corrupted t4 file ?\n",
+				card->name);
 		return 0;
 	}
 	b1_put_byte(base, SEND_POLL);
@@ -253,11 +277,12 @@ int b1_loaded(unsigned int base)
 			if ((ans = b1_get_byte(base)) == RECEIVE_POLL) {
 				return 1;
 			}
-			printk(KERN_ERR "b1_loaded: got 0x%x, firmware not running\n", ans);
+			printk(KERN_ERR "%s: b1_loaded: got 0x%x, firmware not running\n",
+					card->name, ans);
 			return 0;
 		}
 	}
-	printk(KERN_ERR "b1_loaded: firmware not running\n");
+	printk(KERN_ERR "%s: b1_loaded: firmware not running\n", card->name);
 	return 0;
 }
 
@@ -265,14 +290,15 @@ int b1_loaded(unsigned int base)
 
 int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
 {
-	avmcard *card = (avmcard *)(ctrl->driverdata);
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
 	unsigned int port = card->port;
 	unsigned long flags;
 	int retval;
 
 	b1_reset(port);
 
-	if ((retval = b1_load_t4file(port, &data->firmware))) {
+	if ((retval = b1_load_t4file(card, &data->firmware))) {
 		b1_reset(port);
 		printk(KERN_ERR "%s: failed to load t4file!!\n",
 					card->name);
@@ -282,7 +308,7 @@ int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
 	b1_disable_irq(port);
 
 	if (data->configuration.len > 0 && data->configuration.data) {
-		if ((retval = b1_load_config(port, &data->configuration))) {
+		if ((retval = b1_load_config(card, &data->configuration))) {
 			b1_reset(port);
 			printk(KERN_ERR "%s: failed to load config!!\n",
 					card->name);
@@ -290,7 +316,7 @@ int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
 		}
 	}
 
-	if (!b1_loaded(port)) {
+	if (!b1_loaded(card)) {
 		printk(KERN_ERR "%s: failed to load t4file.\n", card->name);
 		return -EIO;
 	}
@@ -309,13 +335,14 @@ int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
 
 void b1_reset_ctr(struct capi_ctr *ctrl)
 {
-	avmcard *card = (avmcard *)(ctrl->driverdata);
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
 	unsigned int port = card->port;
 
 	b1_reset(port);
 	b1_reset(port);
 
-	memset(card->version, 0, sizeof(card->version));
+	memset(cinfo->version, 0, sizeof(cinfo->version));
 	ctrl->reseted(ctrl);
 }
 
@@ -323,7 +350,8 @@ void b1_register_appl(struct capi_ctr *ctrl,
 				__u16 appl,
 				capi_register_params *rp)
 {
-	avmcard *card = (avmcard *)(ctrl->driverdata);
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
 	unsigned int port = card->port;
 	unsigned long flags;
 	int nconn, want = rp->level3cnt;
@@ -347,7 +375,8 @@ void b1_register_appl(struct capi_ctr *ctrl,
 
 void b1_release_appl(struct capi_ctr *ctrl, __u16 appl)
 {
-	avmcard *card = (avmcard *)(ctrl->driverdata);
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
 	unsigned int port = card->port;
 	unsigned long flags;
 
@@ -360,7 +389,8 @@ void b1_release_appl(struct capi_ctr *ctrl, __u16 appl)
 
 void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
 {
-	avmcard *card = (avmcard *)(ctrl->driverdata);
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
 	unsigned int port = card->port;
 	unsigned long flags;
 	__u16 len = CAPIMSG_LEN(skb->data);
@@ -384,25 +414,26 @@ void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
 
 /* ------------------------------------------------------------- */
 
-void b1_parse_version(avmcard *card)
+void b1_parse_version(avmctrl_info *cinfo)
 {
-	struct capi_ctr *ctrl = card->ctrl;
+	struct capi_ctr *ctrl = cinfo->capi_ctrl;
+	avmcard *card = cinfo->card;
 	capi_profile *profp;
 	__u8 *dversion;
 	__u8 flag;
 	int i, j;
 
 	for (j = 0; j < AVM_MAXVERSION; j++)
-		card->version[j] = "\0\0" + 1;
+		cinfo->version[j] = "\0\0" + 1;
 	for (i = 0, j = 0;
-	     j < AVM_MAXVERSION && i < card->versionlen;
-	     j++, i += card->versionbuf[i] + 1)
-		card->version[j] = &card->versionbuf[i + 1];
+	     j < AVM_MAXVERSION && i < cinfo->versionlen;
+	     j++, i += cinfo->versionbuf[i] + 1)
+		cinfo->version[j] = &cinfo->versionbuf[i + 1];
 
-	strncpy(ctrl->serial, card->version[VER_SERIAL], CAPI_SERIAL_LEN);
-	memcpy(&ctrl->profile, card->version[VER_PROFILE],sizeof(capi_profile));
+	strncpy(ctrl->serial, cinfo->version[VER_SERIAL], CAPI_SERIAL_LEN);
+	memcpy(&ctrl->profile, cinfo->version[VER_PROFILE],sizeof(capi_profile));
 	strncpy(ctrl->manu, "AVM GmbH", CAPI_MANUFACTURER_LEN);
-	dversion = card->version[VER_DRIVER];
+	dversion = cinfo->version[VER_DRIVER];
 	ctrl->version.majorversion = 2;
 	ctrl->version.minorversion = 0;
 	ctrl->version.majormanuversion = (((dversion[0] - '0') & 0xf) << 4);
@@ -415,23 +446,24 @@ void b1_parse_version(avmcard *card)
 
 	flag = ((__u8 *)(profp->manu))[1];
 	switch (flag) {
-	case 0: if (card->version[VER_CARDTYPE])
-	           strcpy(card->cardname, card->version[VER_CARDTYPE]);
-	        else strcpy(card->cardname, "B1");
+	case 0: if (cinfo->version[VER_CARDTYPE])
+	           strcpy(cinfo->cardname, cinfo->version[VER_CARDTYPE]);
+	        else strcpy(cinfo->cardname, "B1");
 		break;
-	case 3: strcpy(card->cardname,"PCMCIA B"); break;
-	case 4: strcpy(card->cardname,"PCMCIA M1"); break;
-	case 5: strcpy(card->cardname,"PCMCIA M2"); break;
-	case 6: strcpy(card->cardname,"B1 V3.0"); break;
-	case 7: strcpy(card->cardname,"B1 PCI"); break;
-	default: sprintf(card->cardname, "AVM?%u", (unsigned int)flag); break;
+	case 3: strcpy(cinfo->cardname,"PCMCIA B"); break;
+	case 4: strcpy(cinfo->cardname,"PCMCIA M1"); break;
+	case 5: strcpy(cinfo->cardname,"PCMCIA M2"); break;
+	case 6: strcpy(cinfo->cardname,"B1 V3.0"); break;
+	case 7: strcpy(cinfo->cardname,"B1 PCI"); break;
+	default: sprintf(cinfo->cardname, "AVM?%u", (unsigned int)flag); break;
         }
         printk(KERN_NOTICE "%s: card %d \"%s\" ready.\n",
-				card->name, ctrl->cnr, card->cardname);
+				card->name, ctrl->cnr, cinfo->cardname);
 
         flag = ((__u8 *)(profp->manu))[3];
         if (flag)
-		printk(KERN_NOTICE "b1capi: card %d Protocol:%s%s%s%s%s%s%s\n",
+		printk(KERN_NOTICE "%s: card %d Protocol:%s%s%s%s%s%s%s\n",
+			card->name,
 			ctrl->cnr,
 			(flag & 0x01) ? " DSS1" : "",
 			(flag & 0x02) ? " CT1" : "",
@@ -458,7 +490,8 @@ void b1_parse_version(avmcard *card)
 
 void b1_handle_interrupt(avmcard * card)
 {
-	struct capi_ctr *ctrl = card->ctrl;
+	avmctrl_info *cinfo = &card->ctrlinfo[0];
+	struct capi_ctr *ctrl = cinfo->capi_ctrl;
 	unsigned char b1cmd;
 	struct sk_buff *skb;
 
@@ -481,13 +514,17 @@ void b1_handle_interrupt(avmcard * card)
 		MsgLen = b1_get_slice(card->port, card->msgbuf);
 		DataB3Len = b1_get_slice(card->port, 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);
-			CAPIMSG_SETDATA(skb->data, skb->data + MsgLen);
 			ctrl->handle_capimsg(ctrl, ApplId, skb);
 		}
 		break;
@@ -536,12 +573,12 @@ void b1_handle_interrupt(avmcard * card)
 
 	case RECEIVE_INIT:
 
-		card->versionlen = b1_get_slice(card->port, card->versionbuf);
-		b1_parse_version(card);
+		cinfo->versionlen = b1_get_slice(card->port, cinfo->versionbuf);
+		b1_parse_version(cinfo);
 		printk(KERN_INFO "%s: %s-card (%s) now active\n",
 		       card->name,
-		       card->version[VER_CARDTYPE],
-		       card->version[VER_DRIVER]);
+		       cinfo->version[VER_CARDTYPE],
+		       cinfo->version[VER_DRIVER]);
 		ctrl->ready(ctrl);
 		break;
 
@@ -581,7 +618,8 @@ void b1_handle_interrupt(avmcard * card)
 int b1ctl_read_proc(char *page, char **start, off_t off,
         		int count, int *eof, struct capi_ctr *ctrl)
 {
-	avmcard *card = (avmcard *)(ctrl->driverdata);
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
 	__u8 flag;
 	int len = 0;
 	char *s;
@@ -603,11 +641,11 @@ int b1ctl_read_proc(char *page, char **start, off_t off,
 	len += sprintf(page+len, "%-16s %s\n", "type", s);
 	if (card->cardtype == avm_t1isa)
 	   len += sprintf(page+len, "%-16s %d\n", "cardnr", card->cardnr);
-	if ((s = card->version[VER_DRIVER]) != 0)
+	if ((s = cinfo->version[VER_DRIVER]) != 0)
 	   len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
-	if ((s = card->version[VER_CARDTYPE]) != 0)
+	if ((s = cinfo->version[VER_CARDTYPE]) != 0)
 	   len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
-	if ((s = card->version[VER_SERIAL]) != 0)
+	if ((s = cinfo->version[VER_SERIAL]) != 0)
 	   len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
 
 	if (card->cardtype != avm_m1) {
@@ -635,7 +673,7 @@ int b1ctl_read_proc(char *page, char **start, off_t off,
 			(flag & 0x04) ? " leased line with D-channel" : ""
 			);
 	}
-	len += sprintf(page+len, "%-16s %s\n", "cardname", card->cardname);
+	len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname);
 
 	if (off+count >= len)
 	   *eof = 1;
diff --git a/drivers/isdn/avmb1/b1isa.c b/drivers/isdn/avmb1/b1isa.c
index 9ab1984323eea0b885aa24e5c60f5dcec94d12e7..01972b2d21df5a8dbaf3541cc7bec48428463b17 100644
--- a/drivers/isdn/avmb1/b1isa.c
+++ b/drivers/isdn/avmb1/b1isa.c
@@ -1,11 +1,18 @@
 /*
- * $Id: b1isa.c,v 1.4 1999/08/22 20:26:24 calle Exp $
+ * $Id: b1isa.c,v 1.5 1999/11/05 16:38:01 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.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
+ *   constant string.
+ * - Moved some data from struct avmcard into new struct avmctrl_info.
+ *   Changed all lowlevel capi driver to match the new structur.
+ *
  * Revision 1.4  1999/08/22 20:26:24  calle
  * backported changes from kernel 2.3.14:
  * - several #include "config.h" gone, others come.
@@ -49,13 +56,12 @@
 #include <linux/ioport.h>
 #include <linux/capi.h>
 #include <asm/io.h>
-#include <linux/isdn_compat.h>
 #include "capicmd.h"
 #include "capiutil.h"
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.4 $";
+static char *revision = "$Revision: 1.5 $";
 
 /* ------------------------------------------------------------- */
 
@@ -92,7 +98,8 @@ static void b1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
 
 static void b1isa_remove_ctr(struct capi_ctr *ctrl)
 {
-	avmcard *card = (avmcard *)(ctrl->driverdata);
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
 	unsigned int port = card->port;
 
 	b1_reset(port);
@@ -101,6 +108,7 @@ static void b1isa_remove_ctr(struct capi_ctr *ctrl)
 	di->detach_ctr(ctrl);
 	free_irq(card->irq, card);
 	release_region(card->port, AVMB1_PORTLEN);
+	kfree(card->ctrlinfo);
 	kfree(card);
 
 	MOD_DEC_USE_COUNT;
@@ -110,6 +118,7 @@ static void b1isa_remove_ctr(struct capi_ctr *ctrl)
 
 static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
 {
+	avmctrl_info *cinfo;
 	avmcard *card;
 	int retval;
 
@@ -120,6 +129,15 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
 		return -ENOMEM;
 	}
 	memset(card, 0, sizeof(avmcard));
+        cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC);
+	if (!cinfo) {
+		printk(KERN_WARNING "b1isa: no memory.\n");
+		kfree(card);
+		return -ENOMEM;
+	}
+	memset(cinfo, 0, sizeof(avmctrl_info));
+	card->ctrlinfo = cinfo;
+	cinfo->card = card;
 	sprintf(card->name, "b1isa-%x", p->port);
 	card->port = p->port;
 	card->irq = p->irq;
@@ -129,17 +147,20 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
 		printk(KERN_WARNING
 		       "b1isa: ports 0x%03x-0x%03x in use.\n",
 		       card->port, card->port + AVMB1_PORTLEN);
+	        kfree(card->ctrlinfo);
 		kfree(card);
 		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);
 		return -EINVAL;
 	}
 	if (   card->port != 0x150 && card->port != 0x250
 	    && card->port != 0x300 && card->port != 0x340) {
 		printk(KERN_WARNING "b1isa: illegal port 0x%x.\n", card->port);
+	        kfree(card->ctrlinfo);
 		kfree(card);
 		return -EINVAL;
 	}
@@ -147,6 +168,7 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
 	if ((retval = b1_detect(card->port, card->cardtype)) != 0) {
 		printk(KERN_NOTICE "b1isa: NO card at 0x%x (%d)\n",
 					card->port, retval);
+	        kfree(card->ctrlinfo);
 		kfree(card);
 		return -EIO;
 	}
@@ -158,15 +180,17 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
 	if (retval) {
 		printk(KERN_ERR "b1isa: unable to get IRQ %d.\n", card->irq);
 		release_region(card->port, AVMB1_PORTLEN);
+	        kfree(card->ctrlinfo);
 		kfree(card);
 		return -EBUSY;
 	}
 
-	card->ctrl = di->attach_ctr(driver, card->name, card);
-	if (!card->ctrl) {
+	cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo);
+	if (!cinfo->capi_ctrl) {
 		printk(KERN_ERR "b1isa: attach controller failed.\n");
 		free_irq(card->irq, card);
 		release_region(card->port, AVMB1_PORTLEN);
+	        kfree(card->ctrlinfo);
 		kfree(card);
 		return -EBUSY;
 	}
@@ -177,15 +201,17 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
 
 static char *b1isa_procinfo(struct capi_ctr *ctrl)
 {
-	avmcard *card = (avmcard *)(ctrl->driverdata);
-	if (!card)
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+
+	if (!cinfo)
 		return "";
-	sprintf(card->infobuf, "%s %s 0x%x %d",
-		card->cardname[0] ? card->cardname : "-",
-		card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-",
-		card->port, card->irq
+	sprintf(cinfo->infobuf, "%s %s 0x%x %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
 		);
-	return card->infobuf;
+	return cinfo->infobuf;
 }
 
 /* ------------------------------------------------------------- */
diff --git a/drivers/isdn/avmb1/b1pci.c b/drivers/isdn/avmb1/b1pci.c
index 8c0006a78bf59f7eb23750cc9db657f2871487d9..f4e87b12fd029459e7a1d0ac1a71145a133516ed 100644
--- a/drivers/isdn/avmb1/b1pci.c
+++ b/drivers/isdn/avmb1/b1pci.c
@@ -1,11 +1,21 @@
 /*
- * $Id: b1pci.c,v 1.16 1999/08/11 21:01:07 keil Exp $
+ * $Id: b1pci.c,v 1.18 1999/11/05 16:38:01 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.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
+ *   constant string.
+ * - Moved some data from struct avmcard into new struct avmctrl_info.
+ *   Changed all lowlevel capi driver to match the new structur.
+ *
+ * Revision 1.17  1999/10/05 06:50:07  calle
+ * Forgot SA_SHIRQ as argument to request_irq.
+ *
  * Revision 1.16  1999/08/11 21:01:07  keil
  * new PCI codefix
  *
@@ -51,13 +61,12 @@
 #include <linux/pci.h>
 #include <linux/capi.h>
 #include <asm/io.h>
-#include <linux/isdn_compat.h>
 #include "capicmd.h"
 #include "capiutil.h"
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.16 $";
+static char *revision = "$Revision: 1.18 $";
 
 /* ------------------------------------------------------------- */
 
@@ -86,11 +95,11 @@ static void b1pci_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
 	card = (avmcard *) devptr;
 
 	if (!card) {
-		printk(KERN_WARNING "b1_interrupt: wrong device\n");
+		printk(KERN_WARNING "b1pci: interrupt: wrong device\n");
 		return;
 	}
 	if (card->interrupt) {
-		printk(KERN_ERR "b1_interrupt: reentering interrupt hander (%s)\n", card->name);
+		printk(KERN_ERR "%s: reentering interrupt hander.\n", card->name);
 		return;
 	}
 
@@ -104,7 +113,8 @@ static void b1pci_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
 
 static void b1pci_remove_ctr(struct capi_ctr *ctrl)
 {
-	avmcard *card = (avmcard *)(ctrl->driverdata);
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
 	unsigned int port = card->port;
 
 	b1_reset(port);
@@ -114,6 +124,7 @@ static void b1pci_remove_ctr(struct capi_ctr *ctrl)
 	free_irq(card->irq, card);
 	release_region(card->port, AVMB1_PORTLEN);
 	ctrl->driverdata = 0;
+	kfree(card->ctrlinfo);
 	kfree(card);
 
 	MOD_DEC_USE_COUNT;
@@ -123,15 +134,17 @@ static void b1pci_remove_ctr(struct capi_ctr *ctrl)
 
 static char *b1pci_procinfo(struct capi_ctr *ctrl)
 {
-	avmcard *card = (avmcard *)(ctrl->driverdata);
-	if (!card)
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+
+	if (!cinfo)
 		return "";
-	sprintf(card->infobuf, "%s %s 0x%x %d",
-		card->cardname[0] ? card->cardname : "-",
-		card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-",
-		card->port, card->irq
+	sprintf(cinfo->infobuf, "%s %s 0x%x %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
 		);
-	return card->infobuf;
+	return cinfo->infobuf;
 }
 
 /* ------------------------------------------------------------- */
@@ -139,15 +152,25 @@ static char *b1pci_procinfo(struct capi_ctr *ctrl)
 static int b1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
 {
 	avmcard *card;
+	avmctrl_info *cinfo;
 	int retval;
 
 	card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
 
 	if (!card) {
-		printk(KERN_WARNING "b1pci: no memory.\n");
+		printk(KERN_WARNING "%s: no memory.\n", driver->name);
 		return -ENOMEM;
 	}
 	memset(card, 0, sizeof(avmcard));
+        cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC);
+	if (!cinfo) {
+		printk(KERN_WARNING "%s: no memory.\n", driver->name);
+		kfree(card);
+		return -ENOMEM;
+	}
+	memset(cinfo, 0, sizeof(avmctrl_info));
+	card->ctrlinfo = cinfo;
+	cinfo->card = card;
 	sprintf(card->name, "b1pci-%x", p->port);
 	card->port = p->port;
 	card->irq = p->irq;
@@ -155,15 +178,17 @@ static int b1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
 
 	if (check_region(card->port, AVMB1_PORTLEN)) {
 		printk(KERN_WARNING
-		       "b1pci: ports 0x%03x-0x%03x in use.\n",
-		       card->port, card->port + AVMB1_PORTLEN);
+		       "%s: ports 0x%03x-0x%03x in use.\n",
+		       driver->name, card->port, card->port + AVMB1_PORTLEN);
+	        kfree(card->ctrlinfo);
 		kfree(card);
 		return -EBUSY;
 	}
 	b1_reset(card->port);
 	if ((retval = b1_detect(card->port, card->cardtype)) != 0) {
-		printk(KERN_NOTICE "b1pci: NO card at 0x%x (%d)\n",
-					card->port, retval);
+		printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
+					driver->name, card->port, retval);
+	        kfree(card->ctrlinfo);
 		kfree(card);
 		return -EIO;
 	}
@@ -171,19 +196,23 @@ static int b1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
 
 	request_region(p->port, AVMB1_PORTLEN, card->name);
 
-	retval = request_irq(card->irq, b1pci_interrupt, 0, card->name, card);
+	retval = request_irq(card->irq, b1pci_interrupt, SA_SHIRQ, card->name, card);
 	if (retval) {
-		printk(KERN_ERR "b1pci: unable to get IRQ %d.\n", card->irq);
+		printk(KERN_ERR "%s: unable to get IRQ %d.\n",
+				driver->name, card->irq);
 		release_region(card->port, AVMB1_PORTLEN);
+	        kfree(card->ctrlinfo);
 		kfree(card);
 		return -EBUSY;
 	}
 
-	card->ctrl = di->attach_ctr(driver, card->name, card);
-	if (!card->ctrl) {
-		printk(KERN_ERR "b1pci: attach controller failed.\n");
+	cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo);
+	if (!cinfo->capi_ctrl) {
+		printk(KERN_ERR "%s: attach controller failed.\n",
+				driver->name);
 		free_irq(card->irq, card);
 		release_region(card->port, AVMB1_PORTLEN);
+	        kfree(card->ctrlinfo);
 		kfree(card);
 		return -EBUSY;
 	}
@@ -252,7 +281,7 @@ int b1pci_init(void)
 	while ((dev = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, dev))) {
 		struct capicardparams param;
 
-		param.port = get_pcibase(dev, 1) & PCI_BASE_ADDRESS_IO_MASK;
+		param.port = dev->resource[ 1].start & 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",
@@ -277,7 +306,7 @@ int b1pci_init(void)
 	printk(KERN_ERR "%s: NO B1-PCI card detected\n", driver->name);
 	return -ESRCH;
 #else
-	printk(KERN_ERR "b1pci: kernel not compiled with PCI.\n");
+	printk(KERN_ERR "%s: kernel not compiled with PCI.\n", driver->name);
 	return -EIO;
 #endif
 }
diff --git a/drivers/isdn/avmb1/b1pcmcia.c b/drivers/isdn/avmb1/b1pcmcia.c
index d6acda9d9e08e1b546c714b6036de2a98cd4621d..79e34316481adec4deb2182a0bb8fbdced68f3c3 100644
--- a/drivers/isdn/avmb1/b1pcmcia.c
+++ b/drivers/isdn/avmb1/b1pcmcia.c
@@ -1,11 +1,18 @@
 /*
- * $Id: b1pcmcia.c,v 1.4 1999/08/22 20:26:26 calle Exp $
+ * $Id: b1pcmcia.c,v 1.5 1999/11/05 16:38:01 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.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
+ *   constant string.
+ * - Moved some data from struct avmcard into new struct avmctrl_info.
+ *   Changed all lowlevel capi driver to match the new structur.
+ *
  * Revision 1.4  1999/08/22 20:26:26  calle
  * backported changes from kernel 2.3.14:
  * - several #include "config.h" gone, others come.
@@ -50,13 +57,12 @@
 #include <asm/io.h>
 #include <linux/capi.h>
 #include <linux/b1pcmcia.h>
-#include <linux/isdn_compat.h>
 #include "capicmd.h"
 #include "capiutil.h"
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.4 $";
+static char *revision = "$Revision: 1.5 $";
 
 /* ------------------------------------------------------------- */
 
@@ -75,11 +81,12 @@ static void b1pcmcia_interrupt(int interrupt, void *devptr, struct pt_regs *regs
 	card = (avmcard *) devptr;
 
 	if (!card) {
-		printk(KERN_WARNING "b1_interrupt: wrong device\n");
+		printk(KERN_WARNING "b1pcmcia: interrupt: wrong device\n");
 		return;
 	}
 	if (card->interrupt) {
-		printk(KERN_ERR "b1_interrupt: reentering interrupt hander (%s)\n", card->name);
+		printk(KERN_ERR "%s: reentering interrupt hander.\n",
+			card->name);
 		return;
 	}
 
@@ -93,7 +100,8 @@ static void b1pcmcia_interrupt(int interrupt, void *devptr, struct pt_regs *regs
 
 static void b1pcmcia_remove_ctr(struct capi_ctr *ctrl)
 {
-	avmcard *card = (avmcard *)(ctrl->driverdata);
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
 	unsigned int port = card->port;
 
 	b1_reset(port);
@@ -116,16 +124,26 @@ static int b1pcmcia_add_card(struct capi_driver *driver,
 				unsigned irq,
 				enum avmcardtype cardtype)
 {
+	avmctrl_info *cinfo;
 	avmcard *card;
 	int retval;
 
 	card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
 
 	if (!card) {
-		printk(KERN_WARNING "b1pcmcia: no memory.\n");
+		printk(KERN_WARNING "%s: no memory.\n", driver->name);
 		return -ENOMEM;
 	}
 	memset(card, 0, sizeof(avmcard));
+        cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC);
+	if (!cinfo) {
+		printk(KERN_WARNING "%s: no memory.\n", driver->name);
+		kfree(card);
+		return -ENOMEM;
+	}
+	memset(cinfo, 0, sizeof(avmctrl_info));
+	card->ctrlinfo = cinfo;
+	cinfo->card = card;
 	switch (cardtype) {
 		case avm_m1: sprintf(card->name, "m1-%x", port); break;
 		case avm_m2: sprintf(card->name, "m2-%x", port); break;
@@ -137,8 +155,9 @@ static int b1pcmcia_add_card(struct capi_driver *driver,
 
 	b1_reset(card->port);
 	if ((retval = b1_detect(card->port, card->cardtype)) != 0) {
-		printk(KERN_NOTICE "b1pcmcia: NO card at 0x%x (%d)\n",
-					card->port, retval);
+		printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
+					driver->name, card->port, retval);
+	        kfree(card->ctrlinfo);
 		kfree(card);
 		return -EIO;
 	}
@@ -146,36 +165,42 @@ static int b1pcmcia_add_card(struct capi_driver *driver,
 
 	retval = request_irq(card->irq, b1pcmcia_interrupt, 0, card->name, card);
 	if (retval) {
-		printk(KERN_ERR "b1pcmcia: unable to get IRQ %d.\n", card->irq);
+		printk(KERN_ERR "%s: unable to get IRQ %d.\n",
+				driver->name, card->irq);
+	        kfree(card->ctrlinfo);
 		kfree(card);
 		return -EBUSY;
 	}
 
-	card->ctrl = di->attach_ctr(driver, card->name, card);
-	if (!card->ctrl) {
-		printk(KERN_ERR "b1pcmcia: attach controller failed.\n");
+	cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo);
+	if (!cinfo->capi_ctrl) {
+		printk(KERN_ERR "%s: attach controller failed.\n",
+				driver->name);
 		free_irq(card->irq, card);
+	        kfree(card->ctrlinfo);
 		kfree(card);
 		return -EBUSY;
 	}
 
 	MOD_INC_USE_COUNT;
-	return card->ctrl->cnr;
+	return cinfo->capi_ctrl->cnr;
 }
 
 /* ------------------------------------------------------------- */
 
 static char *b1pcmcia_procinfo(struct capi_ctr *ctrl)
 {
-	avmcard *card = (avmcard *)(ctrl->driverdata);
-	if (!card)
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+
+	if (!cinfo)
 		return "";
-	sprintf(card->infobuf, "%s %s 0x%x %d",
-		card->cardname[0] ? card->cardname : "-",
-		card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-",
-		card->port, card->irq
+	sprintf(cinfo->infobuf, "%s %s 0x%x %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
 		);
-	return card->infobuf;
+	return cinfo->infobuf;
 }
 
 /* ------------------------------------------------------------- */
@@ -220,7 +245,7 @@ int b1pcmcia_delcard(unsigned int port, unsigned irq)
 	avmcard *card;
 
 	for (ctrl = b1pcmcia_driver.controller; ctrl; ctrl = ctrl->next) {
-		card = (avmcard *)(ctrl->driverdata);
+		card = ((avmctrl_info *)(ctrl->driverdata))->card;
 		if (card->port == port && card->irq == irq) {
 			b1pcmcia_remove_ctr(ctrl);
 			return 0;
diff --git a/drivers/isdn/avmb1/capi.c b/drivers/isdn/avmb1/capi.c
index c8cab69193e0f4bfa8dc589a8b6b76c5b650be09..6d1159d5617a260f4b139ddad080034ce0842aec 100644
--- a/drivers/isdn/avmb1/capi.c
+++ b/drivers/isdn/avmb1/capi.c
@@ -1,11 +1,20 @@
 /*
- * $Id: capi.c,v 1.19 1999/07/09 15:05:42 keil Exp $
+ * $Id: capi.c,v 1.21 1999/09/10 17:24:18 calle Exp $
  *
  * CAPI 2.0 Interface for Linux
  *
  * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: capi.c,v $
+ * Revision 1.21  1999/09/10 17:24:18  calle
+ * Changes for proposed standard for CAPI2.0:
+ * - AK148 "Linux Exention"
+ *
+ * Revision 1.20  1999/09/07 09:02:53  calle
+ * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and
+ * DATA_B3_IND is always directly after the CAPI message. The "Data" member
+ * ist never used inside the kernel.
+ *
  * Revision 1.19  1999/07/09 15:05:42  keil
  * compat.h is now isdn_compat.h
  *
@@ -117,7 +126,6 @@
 #include <linux/capi.h>
 #include <linux/kernelcapi.h>
 
-#include <linux/isdn_compat.h>
 #include "capiutil.h"
 #include "capicmd.h"
 #include "capidev.h"
@@ -201,9 +209,6 @@ static ssize_t capi_read(struct file *file, char *buf,
 		skb_queue_head(&cdev->recv_queue, skb);
 		return -EMSGSIZE;
 	}
-	if (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
-	    && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND)
-		CAPIMSG_SETDATA(skb->data, buf + CAPIMSG_LEN(skb->data));
 	retval = copy_to_user(buf, skb->data, skb->len);
 	if (retval) {
 		skb_queue_head(&cdev->recv_queue, skb);
@@ -429,7 +434,7 @@ static int capi_ioctl(struct inode *inode, struct file *file,
 		return data.errcode;
 
 	case CAPI_INSTALLED:
-		if ((*capifuncs->capi_installed) ())
+		if ((*capifuncs->capi_isinstalled)() == CAPI_NOERROR)
 			return 0;
 		return -ENXIO;
 
@@ -615,16 +620,12 @@ static struct capi_interface_user cuser = {
 
 int capi_init(void)
 {
-#ifdef COMPAT_HAS_NEW_WAITQ
 	int j;
-#endif
 	
 	memset(capidevs, 0, sizeof(capidevs));
-#ifdef COMPAT_HAS_NEW_WAITQ
 	for ( j = 0; j < CAPI_MAXMINOR+1; j++ ) {
 		init_waitqueue_head(&capidevs[j].recv_wait);
 	}
-#endif
 
 	if (register_chrdev(capi_major, "capi20", &capi_fops)) {
 		printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);
diff --git a/drivers/isdn/avmb1/capidev.h b/drivers/isdn/avmb1/capidev.h
index c66554a2979ed101f3a5666d8d09ef22bec552f2..96e37c1f47ecb4a0c4a30a70daaca0e28fcc2ce6 100644
--- a/drivers/isdn/avmb1/capidev.h
+++ b/drivers/isdn/avmb1/capidev.h
@@ -44,11 +44,7 @@ struct capidev {
 	int is_registered;
 	__u16 applid;
 	struct sk_buff_head recv_queue;
-#ifdef COMPAT_HAS_NEW_WAITQ
 	wait_queue_head_t recv_wait;
-#else
-	struct wait_queue *recv_wait;
-#endif
 	__u16 errcode;
 	/* Statistic */
 	unsigned long nopen;
diff --git a/drivers/isdn/avmb1/capidrv.c b/drivers/isdn/avmb1/capidrv.c
index fb83e52a6e066e3a1c37152053b5f0eb675b5f93..6db170e42486117f4814c7c4ab8015348b31c4bf 100644
--- a/drivers/isdn/avmb1/capidrv.c
+++ b/drivers/isdn/avmb1/capidrv.c
@@ -1,11 +1,17 @@
 /*
- * $Id: capidrv.c,v 1.26 1999/08/06 07:41:16 calle Exp $
+ * $Id: capidrv.c,v 1.28 1999/11/05 16:22:37 calle Exp $
  *
  * ISDN4Linux Driver, using capi20 interface (kernelcapi)
  *
  * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: capidrv.c,v $
+ * Revision 1.28  1999/11/05 16:22:37  calle
+ * Bugfix: Missing break in switch on ISDN_CMD_HANGUP.
+ *
+ * Revision 1.27  1999/09/16 15:13:04  calle
+ * forgot to change paramter type of contr for lower_callback ...
+ *
  * Revision 1.26  1999/08/06 07:41:16  calle
  * Added the "vbox patch". if (si1 == 1) si2 = 0;
  *
@@ -158,12 +164,11 @@
 #include <linux/ctype.h>
 #include <asm/segment.h>
 
-#include <linux/isdn_compat.h>
 #include "capiutil.h"
 #include "capicmd.h"
 #include "capidrv.h"
 
-static char *revision = "$Revision: 1.26 $";
+static char *revision = "$Revision: 1.28 $";
 int debugmode = 0;
 
 MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
@@ -714,8 +719,6 @@ static struct plcistatechange plcitable[] =
   /* P-0.1 */
   {ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0},
   {ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, 0},
-  {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
-  {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
   /* P-1 */
   {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},
   {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
@@ -1855,14 +1858,19 @@ static int capidrv_command(isdn_ctrl * c, capidrv_contr * card)
 			);
 			ncci_change_state(card, bchan->nccip, EV_NCCI_DISCONNECT_B3_REQ);
 			send_message(card, &cmdcmsg);
+			return 0;
 		} else if (bchan->plcip) {
-			bchan->disconnecting = 1;
 			if (bchan->plcip->state == ST_PLCI_INCOMING) {
-				/* just ignore, we a called from isdn_status_callback(),
-				 * which will return 0 or 2, this is handled by the
-				 * CONNECT_IND handler
+				/*
+				 * just ignore, we a called from
+				 * isdn_status_callback(),
+				 * which will return 0 or 2, this is handled
+				 * by the CONNECT_IND handler
 				 */
-			} else {
+				bchan->disconnecting = 1;
+				return 0;
+			} else if (bchan->plcip->plci) {
+				bchan->disconnecting = 1;
 				capi_fill_DISCONNECT_REQ(&cmdcmsg,
 							 global.appid,
 							 card->msgid++,
@@ -1874,8 +1882,18 @@ static int capidrv_command(isdn_ctrl * c, capidrv_contr * card)
 				);
 				plci_change_state(card, bchan->plcip, EV_PLCI_DISCONNECT_REQ);
 				send_message(card, &cmdcmsg);
+				return 0;
+			} else {
+				printk(KERN_ERR "capidrv-%d: chan %ld disconnect request while waiting for CONNECT_CONF\n",
+				       card->contrnr,
+				       c->arg);
+				return -EINVAL;
 			}
 		}
+		printk(KERN_ERR "capidrv-%d: chan %ld disconnect request on free channel\n",
+				       card->contrnr,
+				       c->arg);
+		return -EINVAL;
 /* ready */
 
 	case ISDN_CMD_SETL2:
@@ -2022,10 +2040,8 @@ static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb)
 		        (void)capidrv_del_ack(nccip, datahandle);
 			return 0;
 		}
-#if 1
 		printk(KERN_DEBUG "capidrv-%d: only %d bytes headroom, need %d\n",
 		       card->contrnr, skb_headroom(skb), msglen);
-#endif
 		memcpy(skb_push(nskb, msglen), sendcmsg.buf, msglen);
 		errcode = (*capifuncs->capi_put_message) (global.appid, nskb);
 		if (errcode == CAPI_NOERROR) {
@@ -2211,10 +2227,6 @@ static int capidrv_addcontr(__u16 contr, struct capi_profile *profp)
 	    ISDN_FEATURE_L2_V11096 |
 	    ISDN_FEATURE_L2_V11019 |
 	    ISDN_FEATURE_L2_V11038 |
-#if 0
-	    ISDN_FEATURE_L2_FAX |
-	    ISDN_FEATURE_L3_FAX |
-#endif
 	    ISDN_FEATURE_P_UNKNOWN;
 	card->interface.hl_hdrlen = 22; /* len of DATA_B3_REQ */
 	strncpy(card->interface.id, id, sizeof(card->interface.id) - 1);
@@ -2309,7 +2321,7 @@ static int capidrv_delcontr(__u16 contr)
 }
 
 
-static void lower_callback(unsigned int cmd, __u16 contr, void *data)
+static void lower_callback(unsigned int cmd, __u32 contr, void *data)
 {
 
 	switch (cmd) {
diff --git a/drivers/isdn/avmb1/capiutil.c b/drivers/isdn/avmb1/capiutil.c
index 7f1a9f1adfa50fcfeede6fe8a8ce95176c9675fd..3482f2a97cbdbc62694379c026fb32e37646b971 100644
--- a/drivers/isdn/avmb1/capiutil.c
+++ b/drivers/isdn/avmb1/capiutil.c
@@ -1,5 +1,5 @@
 /*
- * $Id: capiutil.c,v 1.9 1999/07/09 15:05:46 keil Exp $
+ * $Id: capiutil.c,v 1.10 1999/08/31 11:19:54 paul Exp $
  *
  * CAPI 2.0 convert capi message to capi message struct
  *
@@ -7,6 +7,9 @@
  * Rewritten for Linux 1996 by Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: capiutil.c,v $
+ * Revision 1.10  1999/08/31 11:19:54  paul
+ * various spelling corrections (new checksums may be needed, Karsten!)
+ *
  * Revision 1.9  1999/07/09 15:05:46  keil
  * compat.h is now isdn_compat.h
  *
@@ -70,7 +73,6 @@
 #include <asm/segment.h>
 #include <linux/config.h>
 
-#include <linux/isdn_compat.h>
 #include "capiutil.h"
 
 /* from CAPI2.0 DDK AVM Berlin GmbH */
@@ -97,7 +99,7 @@ char *capi_info2str(__u16 reason)
 	case 0x1001:
 	   return "Too many applications";
 	case 0x1002:
-	   return "Logical block size to small, must be at least 128 Bytes";
+	   return "Logical block size too small, must be at least 128 Bytes";
 	case 0x1003:
 	   return "Buffer exceeds 64 kByte";
 	case 0x1004:
diff --git a/drivers/isdn/avmb1/capiutil.h b/drivers/isdn/avmb1/capiutil.h
index 38209212dbd91512cb3744ab5afce6eef0d678e1..3825ac3083786d175396cec5cca2db6df76e0ac6 100644
--- a/drivers/isdn/avmb1/capiutil.h
+++ b/drivers/isdn/avmb1/capiutil.h
@@ -1,5 +1,5 @@
 /*
- * $Id: capiutil.h,v 1.2 1997/05/18 09:24:19 calle Exp $
+ * $Id: capiutil.h,v 1.4 1999/09/15 08:16:03 calle Exp $
  * 
  * CAPI 2.0 defines & types
  * 
@@ -7,6 +7,14 @@
  * Rewritten for Linux 1996 by Carsten Paeth (calle@calle.in-berlin.de)
  * 
  * $Log: capiutil.h,v $
+ * Revision 1.4  1999/09/15 08:16:03  calle
+ * Implementation of 64Bit extention complete.
+ *
+ * Revision 1.3  1999/09/07 09:02:53  calle
+ * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and
+ * DATA_B3_IND is always directly after the CAPI message. The "Data" member
+ * ist never used inside the kernel.
+ *
  * Revision 1.2  1997/05/18 09:24:19  calle
  * added verbose disconnect reason reporting to avmb1.
  * some fixes in capi20 interface.
@@ -45,12 +53,10 @@
 		((__u8 *)m)[3] = ((__u16)(applid) >> 8) & 0xff; \
 	} while (0)
 
-#define	CAPIMSG_SETDATA(m, data) \
+#define	CAPIMSG_SETLEN(m, len) \
 	do { \
-		((__u8 *)m)[12] = (__u32)(data) & 0xff; \
-		((__u8 *)m)[13] = ((__u32)(data) >> 8) & 0xff; \
-		((__u8 *)m)[14] = ((__u32)(data) >> 16) & 0xff; \
-		((__u8 *)m)[15] = ((__u32)(data) >> 24) & 0xff; \
+		((__u8 *)m)[0] = (__u16)(len) & 0xff; \
+		((__u8 *)m)[1] = ((__u16)(len) >> 8) & 0xff; \
 	} while (0)
 
 /*----- basic-type definitions -----*/
diff --git a/drivers/isdn/avmb1/kcapi.c b/drivers/isdn/avmb1/kcapi.c
index fc58f12415cb0e3e3915c02f55c78fec3ddf43da..75d3f01c23e076174c4c342eced1b0c9d13a17c5 100644
--- a/drivers/isdn/avmb1/kcapi.c
+++ b/drivers/isdn/avmb1/kcapi.c
@@ -1,11 +1,25 @@
 /*
- * $Id: kcapi.c,v 1.6 1999/07/20 06:41:49 calle Exp $
+ * $Id: kcapi.c,v 1.10 1999/10/26 15:30:32 calle Exp $
  * 
  * Kernel CAPI 2.0 Module
  * 
  * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
  * 
  * $Log: kcapi.c,v $
+ * Revision 1.10  1999/10/26 15:30:32  calle
+ * Generate error message if user want to add card, but driver module is
+ * not loaded.
+ *
+ * Revision 1.9  1999/10/11 22:04:12  keil
+ * COMPAT_NEED_UACCESS (no include in isdn_compat.h)
+ *
+ * Revision 1.8  1999/09/10 17:24:18  calle
+ * Changes for proposed standard for CAPI2.0:
+ * - AK148 "Linux Exention"
+ *
+ * Revision 1.7  1999/09/04 06:20:05  keil
+ * Changes from kernel set_current_state()
+ *
  * Revision 1.6  1999/07/20 06:41:49  calle
  * Bugfix: After the redesign of the AVM B1 driver, the driver didn't even
  *         compile, if not selected as modules.
@@ -57,7 +71,7 @@
 #include <linux/tqueue.h>
 #include <linux/capi.h>
 #include <linux/kernelcapi.h>
-#include <linux/isdn_compat.h>
+#include <asm/uaccess.h>
 #include "capicmd.h"
 #include "capiutil.h"
 #include "capilli.h"
@@ -65,7 +79,7 @@
 #include <linux/b1lli.h>
 #endif
 
-static char *revision = "$Revision: 1.6 $";
+static char *revision = "$Revision: 1.10 $";
 
 /* ------------------------------------------------------------- */
 
@@ -119,7 +133,7 @@ struct capi_appl {
 /* ------------------------------------------------------------- */
 
 static struct capi_version driver_version = {2, 0, 1, 1<<4};
-static char driver_serial[CAPI_SERIAL_LEN] = "4711";
+static char driver_serial[CAPI_SERIAL_LEN] = "0004711";
 static char capi_manufakturer[64] = "AVM Berlin";
 
 #define APPL(a)		   (&applications[(a)-1])
@@ -719,7 +733,7 @@ static void controllercb_handle_capimsg(struct capi_ctr * card,
 
 /* -------- Notifier ------------------------------------------ */
 
-static void notify_up(__u16 contr)
+static void notify_up(__u32 contr)
 {
 	struct capi_interface_user *p;
 
@@ -730,7 +744,7 @@ static void notify_up(__u16 contr)
 	}
 }
 
-static void notify_down(__u16 contr)
+static void notify_down(__u32 contr)
 {
 	struct capi_interface_user *p;
         printk(KERN_NOTICE "kcapi: notify down contr %d\n", contr);
@@ -742,7 +756,7 @@ static void notify_down(__u16 contr)
 
 static void notify_handler(void *dummy)
 {
-	__u16 contr;
+	__u32 contr;
 
 	for (contr=1; VALID_CARD(contr); contr++)
 		 if (test_and_clear_bit(contr, &notify_up_set))
@@ -984,14 +998,14 @@ void detach_capi_driver(struct capi_driver *driver)
 /* -------- CAPI2.0 Interface ---------------------------------- */
 /* ------------------------------------------------------------- */
 
-static int capi_installed(void)
+static __u16 capi_isinstalled(void)
 {
 	int i;
 	for (i = 0; i < CAPI_MAXCONTR; i++) {
 		if (cards[i].cardstate == CARD_RUNNING)
-			return 1;
+			return CAPI_NOERROR;
 	}
-	return 0;
+	return CAPI_REGNOTINSTALLED;
 }
 
 static __u16 capi_register(capi_register_params * rparam, __u16 * applidp)
@@ -1053,7 +1067,7 @@ static __u16 capi_release(__u16 applid)
 static __u16 capi_put_message(__u16 applid, struct sk_buff *skb)
 {
 	struct capi_ncci *np;
-	int contr;
+	__u32 contr;
 	int showctl = 0;
 	__u8 cmd, subcmd;
 
@@ -1131,53 +1145,53 @@ static __u16 capi_set_signal(__u16 applid,
 	return CAPI_NOERROR;
 }
 
-static __u16 capi_get_manufacturer(__u16 contr, __u8 buf[CAPI_MANUFACTURER_LEN])
+static __u16 capi_get_manufacturer(__u32 contr, __u8 buf[CAPI_MANUFACTURER_LEN])
 {
 	if (contr == 0) {
 		strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
 		return CAPI_NOERROR;
 	}
 	if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) 
-		return 0x2002;
+		return CAPI_REGNOTINSTALLED;
 
 	strncpy(buf, CARD(contr)->manu, CAPI_MANUFACTURER_LEN);
 	return CAPI_NOERROR;
 }
 
-static __u16 capi_get_version(__u16 contr, struct capi_version *verp)
+static __u16 capi_get_version(__u32 contr, struct capi_version *verp)
 {
 	if (contr == 0) {
 		*verp = driver_version;
 		return CAPI_NOERROR;
 	}
 	if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) 
-		return 0x2002;
+		return CAPI_REGNOTINSTALLED;
 
 	memcpy((void *) verp, &CARD(contr)->version, sizeof(capi_version));
 	return CAPI_NOERROR;
 }
 
-static __u16 capi_get_serial(__u16 contr, __u8 serial[CAPI_SERIAL_LEN])
+static __u16 capi_get_serial(__u32 contr, __u8 serial[CAPI_SERIAL_LEN])
 {
 	if (contr == 0) {
 		strncpy(serial, driver_serial, CAPI_SERIAL_LEN);
 		return CAPI_NOERROR;
 	}
 	if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) 
-		return 0x2002;
+		return CAPI_REGNOTINSTALLED;
 
 	strncpy((void *) serial, CARD(contr)->serial, CAPI_SERIAL_LEN);
 	return CAPI_NOERROR;
 }
 
-static __u16 capi_get_profile(__u16 contr, struct capi_profile *profp)
+static __u16 capi_get_profile(__u32 contr, struct capi_profile *profp)
 {
 	if (contr == 0) {
 		profp->ncontroller = ncards;
 		return CAPI_NOERROR;
 	}
 	if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) 
-		return 0x2002;
+		return CAPI_REGNOTINSTALLED;
 
 	memcpy((void *) profp, &CARD(contr)->profile,
 			sizeof(struct capi_profile));
@@ -1219,7 +1233,12 @@ static int old_capi_manufacturer(unsigned int cmd, void *data)
 			case AVM_CARDTYPE_T1: driver = t1isa_driver; break;
 			default: driver = 0;
 		}
-		if (!driver || !driver->add_card) {
+		if (!driver) {
+			printk(KERN_ERR "kcapi: driver not loaded.\n");
+			return -EIO;
+		}
+		if (!driver->add_card) {
+			printk(KERN_ERR "kcapi: driver has no add card function.\n");
 			return -EIO;
 		}
 
@@ -1277,7 +1296,7 @@ static int old_capi_manufacturer(unsigned int cmd, void *data)
 
 		while (card->cardstate != CARD_RUNNING) {
 
-			current->state = TASK_INTERRUPTIBLE;
+			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout(HZ/10);	/* 0.1 sec */
 
 			if (signal_pending(current))
@@ -1302,7 +1321,7 @@ static int old_capi_manufacturer(unsigned int cmd, void *data)
 
 		while (card->cardstate > CARD_DETECTED) {
 
-			current->state = TASK_INTERRUPTIBLE;
+			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout(HZ/10);	/* 0.1 sec */
 
 			if (signal_pending(current))
@@ -1355,7 +1374,7 @@ static int old_capi_manufacturer(unsigned int cmd, void *data)
 
 		while (card->cardstate != CARD_FREE) {
 
-			current->state = TASK_INTERRUPTIBLE;
+			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout(HZ/10);	/* 0.1 sec */
 
 			if (signal_pending(current))
@@ -1404,7 +1423,7 @@ static int capi_manufacturer(unsigned int cmd, void *data)
 
 struct capi_interface avmb1_interface =
 {
-	capi_installed,
+	capi_isinstalled,
 	capi_register,
 	capi_release,
 	capi_put_message,
@@ -1479,6 +1498,12 @@ extern int t1isa_init(void);
 #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
 extern int b1pcmcia_init(void);
 #endif
+#ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI
+extern int t1pci_init(void);
+#endif
+#ifdef CONFIG_ISDN_DRV_AVMB1_C4
+extern int c4_init(void);
+#endif
 #endif
 
 /*
@@ -1528,6 +1553,12 @@ int kcapi_init(void)
 #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
 	(void)b1pcmcia_init();
 #endif
+#ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI
+	(void)t1pci_init();
+#endif
+#ifdef CONFIG_ISDN_DRV_AVMB1_C4
+	(void)c4_init();
+#endif
 #endif
 	return 0;
 }
diff --git a/drivers/isdn/avmb1/t1isa.c b/drivers/isdn/avmb1/t1isa.c
index 3546e10610f3744b81e1644b7035140a3dd95a5b..22a07f2ade758a0eebb8e2a5cbf0cc4d7d06ce2b 100644
--- a/drivers/isdn/avmb1/t1isa.c
+++ b/drivers/isdn/avmb1/t1isa.c
@@ -1,11 +1,26 @@
 /*
- * $Id: t1isa.c,v 1.5 1999/08/22 20:26:28 calle Exp $
+ * $Id: t1isa.c,v 1.8 1999/11/05 16:38:01 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.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
+ *   constant string.
+ * - Moved some data from struct avmcard into new struct avmctrl_info.
+ *   Changed all lowlevel capi driver to match the new structur.
+ *
+ * Revision 1.7  1999/09/15 08:16:03  calle
+ * Implementation of 64Bit extention complete.
+ *
+ * Revision 1.6  1999/09/07 09:02:53  calle
+ * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and
+ * DATA_B3_IND is always directly after the CAPI message. The "Data" member
+ * ist never used inside the kernel.
+ *
  * Revision 1.5  1999/08/22 20:26:28  calle
  * backported changes from kernel 2.3.14:
  * - several #include "config.h" gone, others come.
@@ -53,13 +68,12 @@
 #include <linux/ioport.h>
 #include <linux/capi.h>
 #include <asm/io.h>
-#include <linux/isdn_compat.h>
 #include "capicmd.h"
 #include "capiutil.h"
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.5 $";
+static char *revision = "$Revision: 1.8 $";
 
 /* ------------------------------------------------------------- */
 
@@ -162,7 +176,8 @@ static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr)
 
 static void t1_handle_interrupt(avmcard * card)
 {
-	struct capi_ctr *ctrl = card->ctrl;
+	avmctrl_info *cinfo = &card->ctrlinfo[0];
+	struct capi_ctr *ctrl = cinfo->capi_ctrl;
 	unsigned char b1cmd;
 	struct sk_buff *skb;
 
@@ -184,12 +199,17 @@ static void t1_handle_interrupt(avmcard * card)
 			MsgLen = t1_get_slice(card->port, card->msgbuf);
 			DataB3Len = t1_get_slice(card->port, 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 "t1isa: incoming packet dropped\n");
+				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);
-				CAPIMSG_SETDATA(skb->data, skb->data + MsgLen);
 				ctrl->handle_capimsg(ctrl, ApplId, skb);
 			}
 			break;
@@ -199,7 +219,8 @@ static void t1_handle_interrupt(avmcard * card)
 			ApplId = (unsigned) b1_get_word(card->port);
 			MsgLen = t1_get_slice(card->port, card->msgbuf);
 			if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
-				printk(KERN_ERR "t1isa: incoming packet dropped\n");
+				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);
@@ -237,12 +258,12 @@ static void t1_handle_interrupt(avmcard * card)
 
 		case RECEIVE_INIT:
 
-			card->versionlen = t1_get_slice(card->port, card->versionbuf);
-			b1_parse_version(card);
+			cinfo->versionlen = t1_get_slice(card->port, cinfo->versionbuf);
+			b1_parse_version(cinfo);
 			printk(KERN_INFO "%s: %s-card (%s) now active\n",
 			       card->name,
-			       card->version[VER_CARDTYPE],
-			       card->version[VER_DRIVER]);
+			       cinfo->version[VER_CARDTYPE],
+			       cinfo->version[VER_DRIVER]);
 			ctrl->ready(ctrl);
 			break;
 
@@ -288,11 +309,12 @@ static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
 	card = (avmcard *) devptr;
 
 	if (!card) {
-		printk(KERN_WARNING "t1_interrupt: wrong device\n");
+		printk(KERN_WARNING "t1isa: interrupt: wrong device\n");
 		return;
 	}
 	if (card->interrupt) {
-		printk(KERN_ERR "t1_interrupt: reentering interrupt hander (%s)\n", card->name);
+		printk(KERN_ERR "%s: reentering interrupt hander.\n",
+				 card->name);
 		return;
 	}
 
@@ -306,7 +328,8 @@ static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
 
 static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
 {
-	avmcard *card = (avmcard *)(ctrl->driverdata);
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
 	unsigned int port = card->port;
 	unsigned long flags;
 	int retval;
@@ -314,7 +337,7 @@ static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
 	t1_disable_irq(port);
 	b1_reset(port);
 
-	if ((retval = b1_load_t4file(port, &data->firmware))) {
+	if ((retval = b1_load_t4file(card, &data->firmware))) {
 		b1_reset(port);
 		printk(KERN_ERR "%s: failed to load t4file!!\n",
 					card->name);
@@ -322,7 +345,7 @@ static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
 	}
 
 	if (data->configuration.len > 0 && data->configuration.data) {
-		if ((retval = b1_load_config(port, &data->configuration))) {
+		if ((retval = b1_load_config(card, &data->configuration))) {
 			b1_reset(port);
 			printk(KERN_ERR "%s: failed to load config!!\n",
 					card->name);
@@ -330,7 +353,7 @@ static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
 		}
 	}
 
-	if (!b1_loaded(port)) {
+	if (!b1_loaded(card)) {
 		printk(KERN_ERR "%s: failed to load t4file.\n", card->name);
 		return -EIO;
 	}
@@ -349,20 +372,22 @@ static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
 
 void t1isa_reset_ctr(struct capi_ctr *ctrl)
 {
-	avmcard *card = (avmcard *)(ctrl->driverdata);
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
 	unsigned int port = card->port;
 
 	t1_disable_irq(port);
 	b1_reset(port);
 	b1_reset(port);
 
-	memset(card->version, 0, sizeof(card->version));
+	memset(cinfo->version, 0, sizeof(cinfo->version));
 	ctrl->reseted(ctrl);
 }
 
 static void t1isa_remove_ctr(struct capi_ctr *ctrl)
 {
-	avmcard *card = (avmcard *)(ctrl->driverdata);
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
 	unsigned int port = card->port;
 
 	t1_disable_irq(port);
@@ -373,6 +398,7 @@ static void t1isa_remove_ctr(struct capi_ctr *ctrl)
 	di->detach_ctr(ctrl);
 	free_irq(card->irq, card);
 	release_region(card->port, AVMB1_PORTLEN);
+	kfree(card->ctrlinfo);
 	kfree(card);
 
 	MOD_DEC_USE_COUNT;
@@ -383,16 +409,26 @@ static void t1isa_remove_ctr(struct capi_ctr *ctrl)
 static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
 {
 	struct capi_ctr *ctrl;
+	avmctrl_info *cinfo;
 	avmcard *card;
 	int retval;
 
 	card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
 
 	if (!card) {
-		printk(KERN_WARNING "t1isa: no memory.\n");
+		printk(KERN_WARNING "%s: no memory.\n", driver->name);
 		return -ENOMEM;
 	}
 	memset(card, 0, sizeof(avmcard));
+        cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC);
+	if (!cinfo) {
+		printk(KERN_WARNING "%s: no memory.\n", driver->name);
+		kfree(card);
+		return -ENOMEM;
+	}
+	memset(cinfo, 0, sizeof(avmctrl_info));
+	card->ctrlinfo = cinfo;
+	cinfo->card = card;
 	sprintf(card->name, "t1isa-%x", p->port);
 	card->port = p->port;
 	card->irq = p->irq;
@@ -400,33 +436,42 @@ static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
 	card->cardnr = p->cardnr;
 
 	if (!(((card->port & 0x7) == 0) && ((card->port & 0x30) != 0x30))) {
-		printk(KERN_WARNING "t1isa: illegal port 0x%x.\n", card->port);
+		printk(KERN_WARNING "%s: illegal port 0x%x.\n",
+				driver->name, card->port);
+	        kfree(card->ctrlinfo);
 		kfree(card);
 		return -EINVAL;
         }
 
 	if (check_region(card->port, AVMB1_PORTLEN)) {
 		printk(KERN_WARNING
-		       "t1isa: ports 0x%03x-0x%03x in use.\n",
-		       card->port, card->port + AVMB1_PORTLEN);
+		       "%s: ports 0x%03x-0x%03x in use.\n",
+		       driver->name, card->port, card->port + AVMB1_PORTLEN);
+	        kfree(card->ctrlinfo);
 		kfree(card);
 		return -EBUSY;
 	}
 	if (hema_irq_table[card->irq & 0xf] == 0) {
-		printk(KERN_WARNING "t1isa: irq %d not valid.\n", card->irq);
+		printk(KERN_WARNING "%s: irq %d not valid.\n",
+				driver->name, card->irq);
+	        kfree(card->ctrlinfo);
 		kfree(card);
 		return -EINVAL;
 	}
 	for (ctrl = driver->controller; ctrl; ctrl = ctrl->next) {
-		if (((avmcard *)(ctrl->driverdata))->cardnr == card->cardnr) {
-			printk(KERN_WARNING "t1isa: card with number %d already installed.\n", card->cardnr);
+	        avmcard *cardp = ((avmctrl_info *)(ctrl->driverdata))->card;
+		if (cardp->cardnr == card->cardnr) {
+			printk(KERN_WARNING "%s: card with number %d already installed at 0x%x.\n",
+					driver->name, card->cardnr, cardp->port);
+	                kfree(card->ctrlinfo);
 			kfree(card);
 			return -EBUSY;
 		}
 	}
         if ((retval = t1_detectandinit(card->port, card->irq, card->cardnr)) != 0) {
-		printk(KERN_NOTICE "t1isa: NO card at 0x%x (%d)\n",
-					card->port, retval);
+		printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
+					driver->name, card->port, retval);
+	        kfree(card->ctrlinfo);
 		kfree(card);
 		return -EIO;
 	}
@@ -437,17 +482,21 @@ static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
 
 	retval = request_irq(card->irq, t1isa_interrupt, 0, card->name, card);
 	if (retval) {
-		printk(KERN_ERR "t1isa: unable to get IRQ %d.\n", card->irq);
+		printk(KERN_ERR "%s: unable to get IRQ %d.\n",
+				driver->name, card->irq);
 		release_region(card->port, AVMB1_PORTLEN);
+	        kfree(card->ctrlinfo);
 		kfree(card);
 		return -EBUSY;
 	}
 
-	card->ctrl = di->attach_ctr(driver, card->name, card);
-	if (!card->ctrl) {
-		printk(KERN_ERR "t1isa: attach controller failed.\n");
+	cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo);
+	if (!cinfo->capi_ctrl) {
+		printk(KERN_ERR "%s: attach controller failed.\n",
+				driver->name);
 		free_irq(card->irq, card);
 		release_region(card->port, AVMB1_PORTLEN);
+	        kfree(card->ctrlinfo);
 		kfree(card);
 		return -EBUSY;
 	}
@@ -458,7 +507,8 @@ static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
 
 static void t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
 {
-	avmcard *card = (avmcard *)(ctrl->driverdata);
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
 	unsigned int port = card->port;
 	unsigned long flags;
 	__u16 len = CAPIMSG_LEN(skb->data);
@@ -483,15 +533,18 @@ static void t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
 
 static char *t1isa_procinfo(struct capi_ctr *ctrl)
 {
-	avmcard *card = (avmcard *)(ctrl->driverdata);
-	if (!card)
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+
+	if (!cinfo)
 		return "";
-	sprintf(card->infobuf, "%s %s 0x%x %d %d",
-		card->cardname[0] ? card->cardname : "-",
-		card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-",
-		card->port, card->irq, card->cardnr
+	sprintf(cinfo->infobuf, "%s %s 0x%x %d %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->cardnr : 0
 		);
-	return card->infobuf;
+	return cinfo->infobuf;
 }
 
 
diff --git a/drivers/isdn/avmb1/t1pci.c b/drivers/isdn/avmb1/t1pci.c
new file mode 100644
index 0000000000000000000000000000000000000000..ad73e71cde045b51be156be71c10b190b96c8b22
--- /dev/null
+++ b/drivers/isdn/avmb1/t1pci.c
@@ -0,0 +1,1164 @@
+/*
+ * $Id: t1pci.c,v 1.2 1999/11/05 16:38:02 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.2  1999/11/05 16:38:02  calle
+ * Cleanups before kernel 2.4:
+ * - Changed all messages to use card->name or driver->name instead of
+ *   constant string.
+ * - Moved some data from struct avmcard into new struct avmctrl_info.
+ *   Changed all lowlevel capi driver to match the new structur.
+ *
+ * Revision 1.1  1999/10/26 15:31:42  calle
+ * Added driver for T1-PCI card.
+ *
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/capi.h>
+#include <asm/io.h>
+#include "compat.h"
+#include "capicmd.h"
+#include "capiutil.h"
+#include "capilli.h"
+#include "avmcard.h"
+
+static char *revision = "$Revision: 1.2 $";
+
+#undef CONFIG_T1PCI_DEBUG
+#undef CONFIG_T1PCI_POLLDEBUG
+
+/* ------------------------------------------------------------- */
+
+#ifndef PCI_VENDOR_ID_AVM
+#define PCI_VENDOR_ID_AVM	0x1244
+#endif
+
+#ifndef PCI_DEVICE_ID_AVM_T1
+#define PCI_DEVICE_ID_AVM_T1	0x1200
+#endif
+
+/* ------------------------------------------------------------- */
+
+int suppress_pollack = 0;
+
+MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
+
+MODULE_PARM(suppress_pollack, "0-1i");
+
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver_interface *di;
+
+/* ------------------------------------------------------------- */
+
+static void 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, &reg, 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, &reg, 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);
+
+	di->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;
+}
+
+/* ------------------------------------------------------------- */
+
+
+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;
+	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, "t1pci-%x", p->port);
+	card->port = p->port;
+	card->irq = p->irq;
+	card->membase = p->membase;
+	card->cardtype = avm_t1pci;
+
+	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);
+
+	t1pci_reset(card);
+
+	if ((retval = t1pci_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;
+	}
+	t1pci_reset(card);
+
+	request_region(p->port, AVMB1_PORTLEN, card->name);
+
+	retval = request_irq(card->irq, t1pci_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 = di->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);
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver t1pci_driver = {
+    "t1pci",
+    "0.0",
+    t1pci_load_firmware,
+    t1pci_reset_ctr,
+    t1pci_remove_ctr,
+    t1pci_register_appl,
+    t1pci_release_appl,
+    t1pci_send_message,
+
+    t1pci_procinfo,
+    t1pci_read_proc,
+    0,	/* use standard driver_read_proc */
+
+    0, /* no add_card function */
+};
+
+#ifdef MODULE
+#define t1pci_init init_module
+void cleanup_module(void);
+#endif
+
+static int ncards = 0;
+
+int t1pci_init(void)
+{
+	struct capi_driver *driver = &t1pci_driver;
+	struct pci_dev *dev = NULL;
+	char *p;
+	int retval;
+
+	if ((p = strchr(revision, ':'))) {
+		strncpy(driver->revision, p + 1, sizeof(driver->revision));
+		p = strchr(driver->revision, '$');
+		*p = 0;
+	}
+
+	printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
+
+        di = attach_capi_driver(driver);
+
+	if (!di) {
+		printk(KERN_ERR "%s: failed to attach capi_driver\n",
+				driver->name);
+		return -EIO;
+	}
+
+#ifdef CONFIG_PCI
+	if (!pci_present()) {
+		printk(KERN_ERR "%s: no PCI bus present\n", driver->name);
+    		detach_capi_driver(driver);
+		return -EIO;
+	}
+
+	while ((dev = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, dev))) {
+		struct capicardparams param;
+
+		param.port = dev->resource[ 1].start & PCI_BASE_ADDRESS_IO_MASK;
+		param.irq = dev->irq;
+		param.membase = dev->resource[ 0].start & PCI_BASE_ADDRESS_MEM_MASK;
+
+		printk(KERN_INFO
+			"%s: PCI BIOS reports AVM-T1-PCI at i/o %#x, irq %d, mem %#x\n",
+			driver->name, param.port, param.irq, param.membase);
+		retval = t1pci_add_card(driver, &param);
+		if (retval != 0) {
+		        printk(KERN_ERR
+			"%s: no AVM-T1-PCI at i/o %#x, irq %d detected, mem %#x\n",
+			driver->name, param.port, param.irq, param.membase);
+#ifdef MODULE
+			cleanup_module();
+#endif
+			return retval;
+		}
+		ncards++;
+	}
+	if (ncards) {
+		printk(KERN_INFO "%s: %d T1-PCI card(s) detected\n",
+				driver->name, ncards);
+		return 0;
+	}
+	printk(KERN_ERR "%s: NO T1-PCI card detected\n", driver->name);
+	return -ESRCH;
+#else
+	printk(KERN_ERR "%s: kernel not compiled with PCI.\n", driver->name);
+	return -EIO;
+#endif
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+    detach_capi_driver(&t1pci_driver);
+}
+#endif
diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c
index 035aa363613a808e1d9868703edb32e785f4f1c3..58a47bcd8e1f320e2337775da8432fc41a13ff71 100644
--- a/drivers/isdn/divert/divert_procfs.c
+++ b/drivers/isdn/divert/divert_procfs.c
@@ -1,5 +1,5 @@
 /* 
- * $Id: divert_procfs.c,v 1.4 1999/08/06 07:42:48 calle Exp $
+ * $Id: divert_procfs.c,v 1.5 1999/09/14 20:31:01 werner Exp $
  *
  * Filesystem handling for the diversion supplementary services.
  *
@@ -20,6 +20,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: divert_procfs.c,v $
+ * Revision 1.5  1999/09/14 20:31:01  werner
+ *
+ * Removed obsoleted functions for proc fs and synced with new ones.
+ *
  * Revision 1.4  1999/08/06 07:42:48  calle
  * Added COMPAT_HAS_NEW_WAITQ for rd_queue for newer kernels.
  *
@@ -38,16 +42,13 @@
 #define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/version.h>
-#if (LINUX_VERSION_CODE >= 0x020117) 
 #include <linux/poll.h>
-#endif
 #ifdef CONFIG_PROC_FS
   #include <linux/proc_fs.h>
 #else
   #include <linux/fs.h>
 #endif
 #include <linux/isdnif.h>
-#include <linux/isdn_compat.h>
 #include "isdn_divert.h"
 
 /*********************************/
@@ -56,11 +57,7 @@
 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 */
-#ifdef COMPAT_HAS_NEW_WAITQ
 static wait_queue_head_t rd_queue;
-#else
-static struct wait_queue *rd_queue = 0; /* Queue IO */
-#endif
 
 /*********************************/
 /* put an info buffer into queue */
@@ -101,11 +98,7 @@ void put_info_buffer(char *cp)
 /**********************************/
 /* deflection device read routine */
 /**********************************/
-#if (LINUX_VERSION_CODE < 0x020117)
-static int isdn_divert_read(struct inode *inode, struct file *file, char *buf, RWARG count)
-#else
 static ssize_t isdn_divert_read(struct file *file, char *buf, size_t count, loff_t *off)
-#endif
 { struct divert_info *inf;
   int len;
 	
@@ -130,11 +123,7 @@ static ssize_t isdn_divert_read(struct file *file, char *buf, size_t count, loff
 /**********************************/
 /* deflection device write routine */
 /**********************************/
-#if (LINUX_VERSION_CODE < 0x020117)
-static int isdn_divert_write(struct inode *inode, struct file *file, const char *buf, RWARG count)
-#else
 static ssize_t isdn_divert_write(struct file *file, const char *buf, size_t count, loff_t *off)
-#endif
 {
   return(-ENODEV);
 } /* isdn_divert_write */
@@ -143,17 +132,6 @@ static ssize_t isdn_divert_write(struct file *file, const char *buf, size_t coun
 /***************************************/
 /* select routines for various kernels */
 /***************************************/
-#if (LINUX_VERSION_CODE < 0x020117)
-static int isdn_divert_select(struct inode *inode, struct file *file, int type, select_table * st)
-{
-  if (*((struct divert_info **)file->private_data))
-    return 1;
-  else 
-    { if (st) select_wait(&(rd_queue), st);
-      return 0;
-    }
-} /* isdn_divert_select */
-#else
 static unsigned int isdn_divert_poll(struct file *file, poll_table * wait)
 { unsigned int mask = 0;
 
@@ -164,7 +142,6 @@ static unsigned int isdn_divert_poll(struct file *file, poll_table * wait)
     }
   return mask;
 } /* isdn_divert_poll */
-#endif
 
 /****************/
 /* Open routine */
@@ -188,11 +165,7 @@ static int isdn_divert_open(struct inode *ino, struct file *filep)
 /*******************/
 /* close routine   */
 /*******************/
-#if (LINUX_VERSION_CODE < 0x020117)
-static void isdn_divert_close(struct inode *ino, struct file *filep)
-#else
 static int isdn_divert_close(struct inode *ino, struct file *filep)
-#endif
 { struct divert_info *inf; 
   int flags;
 
@@ -212,10 +185,7 @@ static int isdn_divert_close(struct inode *ino, struct file *filep)
       kfree(inf);
     }
   MOD_DEC_USE_COUNT;
-#if (LINUX_VERSION_CODE < 0x020117)
-#else
   return(0);
-#endif
 } /* isdn_divert_close */
 
 /*********/
@@ -301,34 +271,12 @@ static int isdn_divert_ioctl(struct inode *inode, struct file *file,
 
 
 #ifdef CONFIG_PROC_FS
-#if (LINUX_VERSION_CODE < 0x020117)
-static LSTYPE
-isdn_divert_lseek(struct inode *inode, struct file *file, LSARG offset, int orig)
-#else
 static loff_t
 isdn_divert_lseek(struct file *file, loff_t offset, int orig)
-#endif
 {
 	return -ESPIPE;
 }
 
-#if (LINUX_VERSION_CODE < 0x020117)
-static struct file_operations isdn_fops =
-{
-	isdn_divert_lseek,
-	isdn_divert_read,
-	isdn_divert_write,
-	NULL,                          /* isdn_readdir */
-	isdn_divert_select,            /* isdn_select */
-	isdn_divert_ioctl,             /* isdn_ioctl */
-	NULL,                          /* isdn_mmap */
-	isdn_divert_open,
-	isdn_divert_close,
-	NULL                           /* fsync */
-};
-
-#else
-
 static struct file_operations isdn_fops =
 {
 	isdn_divert_lseek,
@@ -343,51 +291,33 @@ static struct file_operations isdn_fops =
 	isdn_divert_close,
 	NULL                           /* fsync */
 };
-#endif  /* kernel >= 2.1 */
-
 
-/*
- * proc directories can do almost nothing..
- */
-struct inode_operations proc_isdn_inode_ops = {
-	&isdn_fops,	        /* isdn divert special 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 */
+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  */
 };
 
+
 /****************************/
 /* isdn subdir in /proc/net */
 /****************************/
-static struct proc_dir_entry isdn_proc_entry = 
-  { 0, 4, "isdn", S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, 0, 
-    &proc_dir_inode_operations,NULL,NULL,NULL,NULL,NULL
-  };
-
-static struct proc_dir_entry isdn_divert_entry =
-{ 0, 6, "divert",S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_isdn_inode_ops,
-   NULL
-  }; 
-
-/*****************************************************************/
-/* variables used for automatic determining existence of proc fs */
-/*****************************************************************/
-static int (*proc_reg_dynamic)(struct proc_dir_entry *, struct proc_dir_entry *) = NULL;
-static int (*proc_unreg)(struct proc_dir_entry *, int) = NULL;
-
+static struct proc_dir_entry *isdn_proc_entry = NULL;
+static struct proc_dir_entry *isdn_divert_entry = NULL;
 #endif CONFIG_PROC_FS
 
 /***************************************************************************/
@@ -396,36 +326,19 @@ static int (*proc_unreg)(struct proc_dir_entry *, int) = NULL;
 int divert_dev_init(void)
 { int i;
 
-#ifdef COMPAT_HAS_NEW_WAITQ
 	init_waitqueue_head(&rd_queue);
-#endif
 
 #ifdef CONFIG_PROC_FS
-#if (LINUX_VERSION_CODE < 0x020117)
-  (void *) proc_reg_dynamic = get_module_symbol("","proc_register_dynamic");
-  (void *) proc_unreg = get_module_symbol("","proc_unregister");
-  if (proc_unreg)
-   { i = proc_reg_dynamic(&proc_net,&isdn_proc_entry);  
-     if (i) return(i);
-     i = proc_reg_dynamic(&isdn_proc_entry,&isdn_divert_entry);
-     if (i) 
-      { proc_unreg(&proc_net,isdn_proc_entry.low_ino);
-        return(i);
-      }
-   } /* proc exists */
-#else
-  (void *) proc_reg_dynamic = get_module_symbol("","proc_register");
-  (void *) proc_unreg = get_module_symbol("","proc_unregister");
-  if (proc_unreg)
-   { i = proc_reg_dynamic(proc_net,&isdn_proc_entry);  
-     if (i) return(i);
-     i = proc_reg_dynamic(&isdn_proc_entry,&isdn_divert_entry);
-     if (i) 
-      { proc_unreg(proc_net,isdn_proc_entry.low_ino);
-        return(i);
-      }
-   } /* proc exists */
-#endif
+  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);
@@ -439,16 +352,8 @@ int divert_dev_deinit(void)
 { int i;
 
 #ifdef CONFIG_PROC_FS
-  if (proc_unreg)
-   { i = proc_unreg(&isdn_proc_entry,isdn_divert_entry.low_ino);
-     if (i) return(i);
-#if (LINUX_VERSION_CODE < 0x020117)
-     i = proc_unreg(&proc_net,isdn_proc_entry.low_ino);  
-#else
-     i = proc_unreg(proc_net,isdn_proc_entry.low_ino);  
-#endif
-     if (i) return(i);
-   } /* proc exists */
+  remove_proc_entry("divert",isdn_proc_entry);
+  remove_proc_entry("isdn",proc_net);
 #endif CONFIG_PROC_FS
 
   return(0);
diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c
index f10ea18b26f83ded6174c61ae71f41da5cf94c1f..7079232e7dcfd73adb288a7fdec7b6f73fc81dd2 100644
--- a/drivers/isdn/divert/isdn_divert.c
+++ b/drivers/isdn/divert/isdn_divert.c
@@ -1,5 +1,5 @@
 /* 
- * $Id: isdn_divert.c,v 1.4 1999/08/25 20:02:21 werner Exp $
+ * $Id: isdn_divert.c,v 1.5 1999/08/31 11:20:04 paul Exp $
  *
  * DSS1 main diversion supplementary handling for i4l.
  *
@@ -20,6 +20,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn_divert.c,v $
+ * Revision 1.5  1999/08/31 11:20:04  paul
+ * various spelling corrections (new checksums may be needed, Karsten!)
+ *
  * Revision 1.4  1999/08/25 20:02:21  werner
  * Changed return values for stat_icall(w) from 3->4 and 4->5 because of conflicts
  * with existing software definitions. (PtP incomplete called party number)
@@ -513,7 +516,7 @@ int isdn_divert_icall(isdn_ctrl *ic)
            if (cs->akt_state == DEFLECT_ALERT)
              { strcpy(cs->deflect_dest,dv->rule.to_nr);
                if (!cs->timer.expires)
-		 { strcpy(ic->parm.setup.eazmsn,"Testtext direkt");
+		 { strcpy(ic->parm.setup.eazmsn,"Testtext direct");
                    ic->parm.setup.screen = dv->rule.screen;
                    strcpy(ic->parm.setup.phone,dv->rule.to_nr);
                    cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
@@ -769,18 +772,6 @@ int prot_stat_callback(isdn_ctrl *ic)
                       } 
 
 
-#if 0
-  sprintf(st, "0x%lx 0x%lx",ic->arg, ic->parm.dss1_io.ll_id);
-  p = st + strlen(st);
-  p1 = ic->parm.dss1_io.data;
-  i = ic->parm.dss1_io.datalen;
-  while ((i > 0) && (p - st < 530))
-   { p += sprintf(p," %02x",(*p1++) & 0xFF);
-     i--;
-   }
-  sprintf(p, "\n");
-  put_info_buffer(st);
-#endif
                    break;
  
 		   default:
diff --git a/drivers/isdn/divert/isdn_divert.h b/drivers/isdn/divert/isdn_divert.h
index 1d329c0fb7491108e823c770553f2444905a7310..6ab119ed9527f05e3bd19f337a6217dd037393f1 100644
--- a/drivers/isdn/divert/isdn_divert.h
+++ b/drivers/isdn/divert/isdn_divert.h
@@ -1,5 +1,5 @@
 /* 
- * $Id: isdn_divert.h,v 1.3 1999/08/22 20:26:37 calle Exp $
+ * $Id: isdn_divert.h,v 1.4 1999/09/02 13:24:12 paul Exp $
  *
  * Header for the diversion supplementary ioctl interface.
  *
@@ -20,6 +20,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn_divert.h,v $
+ * Revision 1.4  1999/09/02 13:24:12  paul
+ * cosmetics; text following #endif is not ANSI C
+ *
  * Revision 1.3  1999/08/22 20:26:37  calle
  * backported changes from kernel 2.3.14:
  * - several #include "config.h" gone, others come.
@@ -29,12 +32,9 @@
  * Revision 1.2  1999/07/04 21:37:33  werner
  * Ported from kernel version 2.0
  *
- *
- *
  */
 
 
-
 #include <linux/ioctl.h>
 #include <linux/types.h>
 
@@ -94,12 +94,12 @@ typedef struct
 typedef union
  { int drv_version; /* return of driver version */
    struct 
-   { int drvid; /* id of driver */
-     char drvnam[30]; /* name of driver */
+   { int drvid;		/* id of driver */
+     char drvnam[30];	/* name of driver */
    } getid;
    struct
-   { int ruleidx; /* index of rule */
-     divert_rule rule; /* rule parms */ 
+   { int ruleidx;	/* index of rule */
+     divert_rule rule;	/* rule parms */ 
    } getsetrule;
    struct
    { u_char subcmd;  /* 0 = hangup/reject,
@@ -125,7 +125,7 @@ typedef union
 #include <linux/isdnif.h>
 #include <linux/isdn_divertif.h>
 
-#define AUTODEL_TIME 30 /* timeout in s to delete internal entrys */
+#define AUTODEL_TIME 30 /* timeout in s to delete internal entries */
 
 /**************************************************/
 /* structure keeping ascii info for device output */
@@ -153,12 +153,4 @@ extern void deleteprocs(void);
 extern int deflect_extern_action(u_char, ulong, char *);
 extern int cf_command(int, int, u_char, char *, u_char, char *, ulong *);
 
-#endif __KERNEL__
-
-
-
-
-
-
-
-
+#endif /* __KERNEL__ */
diff --git a/drivers/isdn/eicon/eicon.h b/drivers/isdn/eicon/eicon.h
index beee023dccd123d004d872cf2bb72367d2c9c770..88af10416c4855678c900cd14b9b97da21771815 100644
--- a/drivers/isdn/eicon/eicon.h
+++ b/drivers/isdn/eicon/eicon.h
@@ -1,8 +1,8 @@
-/* $Id: eicon.h,v 1.11 1999/08/29 17:23:44 armin Exp $
+/* $Id: eicon.h,v 1.17 1999/10/26 21:15:33 armin Exp $
  *
  * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
  *
- * Copyright 1998    by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1998    by Fritz Elfert (fritz@isdn4linux.de)
  * Copyright 1998,99 by Armin Schindler (mac@melware.de) 
  * Copyright 1999    Cytronics & Melware (info@melware.de)
  *
@@ -21,6 +21,26 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon.h,v $
+ * Revision 1.17  1999/10/26 21:15:33  armin
+ * using define for checking phone number len to avoid buffer overflow.
+ *
+ * Revision 1.16  1999/10/08 22:09:33  armin
+ * Some fixes of cards interface handling.
+ * Bugfix of NULL pointer occurence.
+ * Changed a few log outputs.
+ *
+ * Revision 1.15  1999/09/26 14:17:53  armin
+ * Improved debug and log via readstat()
+ *
+ * Revision 1.14  1999/09/08 20:17:31  armin
+ * Added microchannel patch from Erik Weber.
+ *
+ * Revision 1.13  1999/09/06 07:29:35  fritz
+ * Changed my mail-address.
+ *
+ * Revision 1.12  1999/09/04 06:20:05  keil
+ * Changes from kernel set_current_state()
+ *
  * Revision 1.11  1999/08/29 17:23:44  armin
  * New setup compat.
  * Bugfix if compile as not module.
@@ -117,6 +137,7 @@
 
 #define MAX_HEADER_LEN 10
 
+#define MAX_STATUS_BUFFER	150
 
 /* Struct for adding new cards */
 typedef struct eicon_cdef {
@@ -224,9 +245,9 @@ typedef struct {
 #include <linux/delay.h>
 #include <linux/ctype.h>
 
+#include <linux/isdn.h>
 #include <linux/isdnif.h>
 
-#include <linux/isdn_compat.h>
 
 typedef struct {
   __u16 length __attribute__ ((packed)); /* length of data/parameter field */
@@ -237,7 +258,7 @@ typedef struct {
 
 /* Macro for delay via schedule() */
 #define SLEEP(j) {                     \
-  current->state = TASK_INTERRUPTIBLE; \
+  set_current_state(TASK_INTERRUPTIBLE); \
   schedule_timeout(j);                 \
 }
 
@@ -472,7 +493,6 @@ typedef struct {
 
 typedef struct {
 	int	       No;		 /* Channel Number	        */
-	unsigned short callref;          /* Call Reference              */
 	unsigned short fsm_state;        /* Current D-Channel state     */
 	unsigned short eazmask;          /* EAZ-Mask for this Channel   */
 	int		queued;          /* User-Data Bytes in TX queue */
@@ -489,9 +509,13 @@ typedef struct {
 	entity		e;		 /* Entity  			*/
 	char		cpn[32];	 /* remember cpn		*/
 	char		oad[32];	 /* remember oad		*/
+	char		dsa[32];	 /* remember dsa		*/
+	char		osa[32];	 /* remember osa		*/
 	unsigned char   cause[2];	 /* Last Cause			*/
 	unsigned char	si1;
 	unsigned char	si2;
+	unsigned char	plan;
+	unsigned char	screen;
 } eicon_chan;
 
 typedef struct {
@@ -527,7 +551,7 @@ typedef struct {
 #define EICON_STATE_LISTEN  15
 #define EICON_STATE_WMCONN  16
 
-#define EICON_MAX_QUEUED  8000 /* 2 * maxbuff */
+#define EICON_MAX_QUEUE  2138
 
 #define EICON_LOCK_TX 0
 #define EICON_LOCK_RX 1
@@ -581,6 +605,8 @@ typedef struct eicon_card {
 	struct sk_buff_head sndq;        /* Send-Message queue               */
 	struct sk_buff_head rackq;       /* Req-Ack-Message queue            */
 	struct sk_buff_head sackq;       /* Data-Ack-Message queue           */
+	struct sk_buff_head statq;       /* Status-Message queue             */
+	int statq_entries;
 	u_char *ack_msg;                 /* Ptr to User Data in User skb     */
 	__u16 need_b3ack;                /* Flag: Need ACK for current skb   */
 	struct sk_buff *sbuf;            /* skb which is currently sent      */
@@ -602,8 +628,9 @@ typedef struct eicon_card {
         isdn_if interface;               /* Interface to upper layer         */
         char regname[35];                /* Name used for request_region     */
 #ifdef CONFIG_MCA
-        int  mca_slot;                   /* # of cards MCA slot              */
-#endif
+        int	mca_slot;	 	 /* # of cards MCA slot              */
+	int	mca_io;			 /* MCA cards IO port		     */
+#endif /* CONFIG_MCA */
 } eicon_card;
 
 /* -----------------------------------------------------------**
@@ -668,6 +695,7 @@ extern int eicon_info(char *, int , void *);
 #endif /* CONFIG_MCA */
 
 extern ulong DebugVar;
+extern void eicon_log(eicon_card * card, int level, const char *fmt, ...);
 
 #endif  /* __KERNEL__ */
 
diff --git a/drivers/isdn/eicon/eicon_idi.c b/drivers/isdn/eicon/eicon_idi.c
index af9c3048398e307b04b56d200c1e4418f43a325f..d8634bdbe587649c4b01a3da7b9fa4a87b7108c4 100644
--- a/drivers/isdn/eicon/eicon_idi.c
+++ b/drivers/isdn/eicon/eicon_idi.c
@@ -1,4 +1,4 @@
-/* $Id: eicon_idi.c,v 1.15 1999/08/28 21:32:50 armin Exp $
+/* $Id: eicon_idi.c,v 1.24 1999/10/26 21:15:33 armin Exp $
  *
  * ISDN lowlevel-module for Eicon.Diehl active cards.
  *        IDI interface 
@@ -6,6 +6,11 @@
  * Copyright 1998,99 by Armin Schindler (mac@melware.de)
  * Copyright 1999    Cytronics & Melware (info@melware.de)
  *
+ * Thanks to	Deutsche Mailbox Saar-Lor-Lux GmbH
+ *		for sponsoring and testing fax
+ *		capabilities with Diva Server cards.
+ *		(dor@deutschemailbox.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)
@@ -21,6 +26,35 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_idi.c,v $
+ * Revision 1.24  1999/10/26 21:15:33  armin
+ * using define for checking phone number len to avoid buffer overflow.
+ *
+ * Revision 1.23  1999/10/11 18:13:25  armin
+ * Added fax capabilities for Eicon Diva Server cards.
+ *
+ * Revision 1.22  1999/10/08 22:09:33  armin
+ * Some fixes of cards interface handling.
+ * Bugfix of NULL pointer occurence.
+ * Changed a few log outputs.
+ *
+ * Revision 1.21  1999/09/26 14:17:53  armin
+ * Improved debug and log via readstat()
+ *
+ * Revision 1.20  1999/09/21 20:35:43  armin
+ * added more error checking.
+ *
+ * Revision 1.19  1999/09/21 20:06:40  armin
+ * Added pointer checks.
+ *
+ * Revision 1.18  1999/09/07 12:48:05  armin
+ * Prepared for sub-address usage.
+ *
+ * Revision 1.17  1999/09/07 12:35:39  armin
+ * Better checking and channel Id handling.
+ *
+ * Revision 1.16  1999/09/04 13:44:19  armin
+ * Fix of V.42 analog Modem negotiation handling.
+ *
  * Revision 1.15  1999/08/28 21:32:50  armin
  * Prepared for fax related functions.
  * Now compilable without errors/warnings.
@@ -96,7 +130,7 @@
 
 #undef EICON_FULL_SERVICE_OKTETT
 
-char *eicon_idi_revision = "$Revision: 1.15 $";
+char *eicon_idi_revision = "$Revision: 1.24 $";
 
 eicon_manifbuf *manbuf;
 
@@ -162,9 +196,14 @@ idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan)
 			reqbuf->XBuffer.P[l++] = 5; 
 			break;
 		case ISDN_PROTO_L2_TRANS:
-		case ISDN_PROTO_L2_MODEM:
 			reqbuf->XBuffer.P[l++] = 2;
 			break;
+		case ISDN_PROTO_L2_MODEM:
+  			if (chan->fsm_state == EICON_STATE_IWAIT)
+				reqbuf->XBuffer.P[l++] = 9; /* V.42 incoming */
+			else
+				reqbuf->XBuffer.P[l++] = 10; /* V.42 */
+			break;
 		case ISDN_PROTO_L2_FAX:
   			if (chan->fsm_state == EICON_STATE_IWAIT)
 				reqbuf->XBuffer.P[l++] = 3; /* autoconnect on incoming */
@@ -275,8 +314,7 @@ idi_call_res_req(eicon_REQ *reqbuf, eicon_chan *chan)
 	reqbuf->XBuffer.P[8] = 0;
 	reqbuf->XBuffer.length = l;
 	reqbuf->Reference = 0; /* Sig Entity */
-	if (DebugVar & 8)
-		printk(KERN_DEBUG"idi_req: Ch%d: Call_Res\n", chan->No);
+	eicon_log(NULL, 8, "idi_req: Ch%d: Call_Res\n", chan->No);
    return(0);
 }
 
@@ -292,8 +330,7 @@ idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer)
         skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
 
         if ((!skb) || (!skb2)) {
-		if (DebugVar & 1)
-                	printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed in do_req()\n", chan->No);
+               	eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in do_req()\n", chan->No);
 		if (skb) 
 			dev_kfree_skb(skb);
 		if (skb2) 
@@ -305,8 +342,7 @@ idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer)
 	chan2->ptr = chan;
 
 	reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ));
-	if (DebugVar & 8)
-		printk(KERN_DEBUG "idi_req: Ch%d: req %x (%s)\n", chan->No, cmd, (layer)?"Net":"Sig");
+	eicon_log(card, 8, "idi_req: Ch%d: req %x (%s)\n", chan->No, cmd, (layer)?"Net":"Sig");
 	if (layer) cmd |= 0x700;
 	switch(cmd) {
 		case ASSIGN:
@@ -345,8 +381,7 @@ idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer)
 			idi_put_req(reqbuf, IDI_N_DISC_ACK, 1);
 			break;
 		default:
-			if (DebugVar & 1)
-				printk(KERN_ERR "idi_req: Ch%d: Unknown request\n", chan->No);
+			eicon_log(card, 1, "idi_req: Ch%d: Unknown request\n", chan->No);
 			dev_kfree_skb(skb);
 			dev_kfree_skb(skb2);
 			return(-1);
@@ -361,8 +396,10 @@ idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer)
 int
 eicon_idi_listen_req(eicon_card *card, eicon_chan *chan)
 {
-	if (DebugVar & 16)
-		printk(KERN_DEBUG"idi_req: Ch%d: Listen_Req eazmask=0x%x\n",chan->No, chan->eazmask);
+	if ((!card) || (!chan))
+		return 1;
+
+	eicon_log(card, 16, "idi_req: Ch%d: Listen_Req eazmask=0x%x\n",chan->No, chan->eazmask);
 	if (!chan->e.D3Id) {
 		idi_do_req(card, chan, ASSIGN, 0); 
 	}
@@ -416,15 +453,19 @@ idi_si2bc(int si1, int si2, char *bc, char *hlc)
 int
 idi_hangup(eicon_card *card, eicon_chan *chan)
 {
+	if ((!card) || (!chan))
+		return 1;
+
 	if ((chan->fsm_state == EICON_STATE_ACTIVE) ||
 	    (chan->fsm_state == EICON_STATE_WMCONN)) {
   		if (chan->e.B2Id) idi_do_req(card, chan, IDI_N_DISC, 1);
 	}
 	if (chan->e.B2Id) idi_do_req(card, chan, REMOVE, 1);
-	idi_do_req(card, chan, HANGUP, 0);
-	chan->fsm_state = EICON_STATE_NULL;
-	if (DebugVar & 8)
-		printk(KERN_DEBUG"idi_req: Ch%d: Hangup\n", chan->No);
+	if (chan->fsm_state != EICON_STATE_NULL) {
+		idi_do_req(card, chan, HANGUP, 0);
+		chan->fsm_state = EICON_STATE_NULL;
+	}
+	eicon_log(card, 8, "idi_req: Ch%d: Hangup\n", chan->No);
 #ifdef CONFIG_ISDN_TTY_FAX
 	chan->fax = 0;
 #endif
@@ -434,10 +475,21 @@ idi_hangup(eicon_card *card, eicon_chan *chan)
 int
 idi_connect_res(eicon_card *card, eicon_chan *chan)
 {
-  chan->fsm_state = EICON_STATE_IWAIT;
-  idi_do_req(card, chan, CALL_RES, 0);
-  idi_do_req(card, chan, ASSIGN, 1);
-  return(0);
+	if ((!card) || (!chan))
+		return 1;
+
+	chan->fsm_state = EICON_STATE_IWAIT;
+	idi_do_req(card, chan, CALL_RES, 0);
+	
+	/* check if old NetID has been removed */
+	if (chan->e.B2Id) {
+		eicon_log(card, 1, "eicon: Ch%d: old net_id %x still exist, removing.\n",
+			chan->No, chan->e.B2Id);
+		idi_do_req(card, chan, REMOVE, 1);
+	}
+
+	idi_do_req(card, chan, ASSIGN, 1);
+	return(0);
 }
 
 int
@@ -447,6 +499,7 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone,
 	int l = 0;
 	int i;
 	unsigned char tmp;
+	unsigned char *sub, *sp;
 	unsigned char bc[5];
 	unsigned char hlc[5];
         struct sk_buff *skb;
@@ -454,12 +507,14 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone,
 	eicon_REQ *reqbuf;
 	eicon_chan_ptr *chan2;
 
+	if ((!card) || (!chan))
+		return 1;
+
         skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC);
         skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
 
         if ((!skb) || (!skb2)) {
-		if (DebugVar & 1)
-                	printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed in connect_req()\n", chan->No);
+               	eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in connect_req()\n", chan->No);
 		if (skb) 
 			dev_kfree_skb(skb);
 		if (skb2) 
@@ -475,18 +530,52 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone,
 	reqbuf->ReqCh = 0;
 	reqbuf->ReqId = 1;
 
+	sub = NULL;
+	sp = phone;
+	while (*sp) {
+		if (*sp == '.') {
+			sub = sp + 1;
+			*sp = 0;
+		} else
+			sp++;
+	}
 	reqbuf->XBuffer.P[l++] = CPN;
 	reqbuf->XBuffer.P[l++] = strlen(phone) + 1;
 	reqbuf->XBuffer.P[l++] = 0x81;
 	for(i=0; i<strlen(phone);i++) 
-		reqbuf->XBuffer.P[l++] = phone[i];
+		reqbuf->XBuffer.P[l++] = phone[i] & 0x7f;
+	if (sub) {
+		reqbuf->XBuffer.P[l++] = DSA;
+		reqbuf->XBuffer.P[l++] = strlen(sub) + 2;
+		reqbuf->XBuffer.P[l++] = 0x80; /* NSAP coded */
+		reqbuf->XBuffer.P[l++] = 0x50; /* local IDI format */
+		while (*sub)
+			reqbuf->XBuffer.P[l++] = *sub++ & 0x7f;
+	}
 
+	sub = NULL;
+	sp = eazmsn;
+	while (*sp) {
+		if (*sp == '.') {
+			sub = sp + 1;
+			*sp = 0;
+		} else
+			sp++;
+	}
 	reqbuf->XBuffer.P[l++] = OAD;
 	reqbuf->XBuffer.P[l++] = strlen(eazmsn) + 2;
 	reqbuf->XBuffer.P[l++] = 0x01;
 	reqbuf->XBuffer.P[l++] = 0x80;
 	for(i=0; i<strlen(eazmsn);i++) 
-		reqbuf->XBuffer.P[l++] = eazmsn[i];
+		reqbuf->XBuffer.P[l++] = eazmsn[i] & 0x7f;
+	if (sub) {
+		reqbuf->XBuffer.P[l++] = OSA;
+		reqbuf->XBuffer.P[l++] = strlen(sub) + 2;
+		reqbuf->XBuffer.P[l++] = 0x80; /* NSAP coded */
+		reqbuf->XBuffer.P[l++] = 0x50; /* local IDI format */
+		while (*sub)
+			reqbuf->XBuffer.P[l++] = *sub++ & 0x7f;
+	}
 
 	if ((tmp = idi_si2bc(si1, si2, bc, hlc)) > 0) {
 		reqbuf->XBuffer.P[l++] = BC;
@@ -500,6 +589,7 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone,
 				reqbuf->XBuffer.P[l++] = hlc[i];
 		}
 	}
+
         reqbuf->XBuffer.P[l++] = CAI;
         reqbuf->XBuffer.P[l++] = 6;
         reqbuf->XBuffer.P[l++] = 0x09;
@@ -570,8 +660,7 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone,
 	skb_queue_tail(&card->sndq, skb2); 
 	eicon_schedule_tx(card);
 
-	if (DebugVar & 8)
-  		printk(KERN_DEBUG"idi_req: Ch%d: Conn_Req %s -> %s\n",chan->No, eazmsn, phone);
+	eicon_log(card, 8, "idi_req: Ch%d: Conn_Req %s -> %s\n",chan->No, eazmsn, phone);
    return(0);
 }
 
@@ -588,9 +677,10 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi
 	__u16 code;
 	isdn_ctrl cmd;
 
-  memset(message, 0, sizeof(idi_ind_message));
+	memset(message, 0, sizeof(idi_ind_message));
+
+	if ((!len) || (!buffer[pos])) return;
 
-  if ((!len) || (!buffer[pos])) return;
   while(pos <= len) {
 	w = buffer[pos++];
 	if (!w) return;
@@ -620,8 +710,18 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi
 		else code = w;
 		code |= (codeset<<8);
 
+		if (pos + wlen > len) {
+			eicon_log(ccard, 1, "idi_err: Ch%d: IElen %d of %x exceeds Ind_Length (+%d)\n", chan->No, 
+					wlen, code, (pos + wlen) - len);
+			return;
+		}
+
 		switch(code) {
 			case OAD:
+				if (wlen > sizeof(message->oad)) {
+					pos += wlen;
+					break;
+				}
 				j = 1;
 				if (wlen) {
 					message->plan = buffer[pos++];
@@ -634,11 +734,14 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi
 				}
 				for(i=0; i < wlen-j; i++) 
 					message->oad[i] = buffer[pos++];
-				if (DebugVar & 2)
-					printk(KERN_DEBUG"idi_inf: Ch%d: OAD=(0x%02x,0x%02x) %s\n", chan->No, 
-						message->plan, message->screen, message->oad);
+				eicon_log(ccard, 2, "idi_inf: Ch%d: OAD=(0x%02x,0x%02x) %s\n", chan->No, 
+					message->plan, message->screen, message->oad);
 				break;
 			case RDN:
+				if (wlen > sizeof(message->rdn)) {
+					pos += wlen;
+					break;
+				}
 				j = 1;
 				if (wlen) {
 					if (!(buffer[pos++] & 0x80)) {
@@ -648,92 +751,116 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi
 				}
 				for(i=0; i < wlen-j; i++) 
 					message->rdn[i] = buffer[pos++];
-				if (DebugVar & 2)
-					printk(KERN_DEBUG"idi_inf: Ch%d: RDN= %s\n", chan->No, 
+				eicon_log(ccard, 2, "idi_inf: Ch%d: RDN= %s\n", chan->No, 
 						message->rdn);
 				break;
 			case CPN:
+				if (wlen > sizeof(message->cpn)) {
+					pos += wlen;
+					break;
+				}
 				for(i=0; i < wlen; i++) 
 					message->cpn[i] = buffer[pos++];
-				if (DebugVar & 2)
-					printk(KERN_DEBUG"idi_inf: Ch%d: CPN=(0x%02x) %s\n", chan->No,
-						(__u8)message->cpn[0], message->cpn + 1);
+				eicon_log(ccard, 2, "idi_inf: Ch%d: CPN=(0x%02x) %s\n", chan->No,
+					(__u8)message->cpn[0], message->cpn + 1);
 				break;
 			case DSA:
-				pos++;
-				for(i=0; i < wlen-1; i++) 
+				if (wlen > sizeof(message->dsa)) {
+					pos += wlen;
+					break;
+				}
+				pos += 2;
+				for(i=0; i < wlen-2; i++) 
 					message->dsa[i] = buffer[pos++];
-				if (DebugVar & 2)
-					printk(KERN_DEBUG"idi_inf: Ch%d: DSA=%s\n", chan->No, message->dsa);
+				eicon_log(ccard, 2, "idi_inf: Ch%d: DSA=%s\n", chan->No, message->dsa);
 				break;
 			case OSA:
-				pos++;
-				for(i=0; i < wlen-1; i++) 
+				if (wlen > sizeof(message->osa)) {
+					pos += wlen;
+					break;
+				}
+				pos += 2;
+				for(i=0; i < wlen-2; i++) 
 					message->osa[i] = buffer[pos++];
-				if (DebugVar & 2)
-					printk(KERN_DEBUG"idi_inf: Ch%d: OSA=%s\n", chan->No, message->osa);
+				eicon_log(ccard, 2, "idi_inf: Ch%d: OSA=%s\n", chan->No, message->osa);
 				break;
 			case BC:
+				if (wlen > sizeof(message->bc)) {
+					pos += wlen;
+					break;
+				}
 				for(i=0; i < wlen; i++) 
 					message->bc[i] = buffer[pos++];
-				if (DebugVar & 4)
-					printk(KERN_DEBUG"idi_inf: Ch%d: BC = 0x%02x 0x%02x 0x%02x\n", chan->No,
-						message->bc[0],message->bc[1],message->bc[2]);
+				eicon_log(ccard, 4, "idi_inf: Ch%d: BC = 0x%02x 0x%02x 0x%02x\n", chan->No,
+					message->bc[0],message->bc[1],message->bc[2]);
 				break;
 			case 0x800|BC:
+				if (wlen > sizeof(message->e_bc)) {
+					pos += wlen;
+					break;
+				}
 				for(i=0; i < wlen; i++) 
 					message->e_bc[i] = buffer[pos++];
-				if (DebugVar & 4)
-					printk(KERN_DEBUG"idi_inf: Ch%d: ESC/BC=%d\n", chan->No, message->bc[0]);
+				eicon_log(ccard, 4, "idi_inf: Ch%d: ESC/BC=%d\n", chan->No, message->bc[0]);
 				break;
 			case LLC:
+				if (wlen > sizeof(message->llc)) {
+					pos += wlen;
+					break;
+				}
 				for(i=0; i < wlen; i++) 
 					message->llc[i] = buffer[pos++];
-				if (DebugVar & 4)
-					printk(KERN_DEBUG"idi_inf: Ch%d: LLC=%d %d %d %d\n", chan->No, message->llc[0],
-						message->llc[1],message->llc[2],message->llc[3]);
+				eicon_log(ccard, 4, "idi_inf: Ch%d: LLC=%d %d %d %d\n", chan->No, message->llc[0],
+					message->llc[1],message->llc[2],message->llc[3]);
 				break;
 			case HLC:
+				if (wlen > sizeof(message->hlc)) {
+					pos += wlen;
+					break;
+				}
 				for(i=0; i < wlen; i++) 
 					message->hlc[i] = buffer[pos++];
-				if (DebugVar & 4)
-					printk(KERN_DEBUG"idi_inf: Ch%d: HLC=%x %x %x %x %x\n", chan->No,
-						message->hlc[0], message->hlc[1],
-						message->hlc[2], message->hlc[3], message->hlc[4]);
+				eicon_log(ccard, 4, "idi_inf: Ch%d: HLC=%x %x %x %x %x\n", chan->No,
+					message->hlc[0], message->hlc[1],
+					message->hlc[2], message->hlc[3], message->hlc[4]);
 				break;
 			case DSP:
 			case 0x600|DSP:
+				if (wlen > sizeof(message->display)) {
+					pos += wlen;
+					break;
+				}
 				for(i=0; i < wlen; i++) 
 					message->display[i] = buffer[pos++];
-				if (DebugVar & 4)
-					printk(KERN_DEBUG"idi_inf: Ch%d: Display: %s\n", chan->No,
-						message->display);
+				eicon_log(ccard, 4, "idi_inf: Ch%d: Display: %s\n", chan->No,
+					message->display);
 				break;
 			case 0x600|KEY:
+				if (wlen > sizeof(message->keypad)) {
+					pos += wlen;
+					break;
+				}
 				for(i=0; i < wlen; i++) 
 					message->keypad[i] = buffer[pos++];
-				if (DebugVar & 4)
-					printk(KERN_DEBUG"idi_inf: Ch%d: Keypad: %s\n", chan->No,
-						message->keypad);
+				eicon_log(ccard, 4, "idi_inf: Ch%d: Keypad: %s\n", chan->No,
+					message->keypad);
 				break;
 			case NI:
 			case 0x600|NI:
 				if (wlen) {
-					if (DebugVar & 4) {
-						switch(buffer[pos] & 127) {
-							case 0:
-								printk(KERN_DEBUG"idi_inf: Ch%d: User suspended.\n", chan->No);
-								break;
-							case 1:
-								printk(KERN_DEBUG"idi_inf: Ch%d: User resumed.\n", chan->No);
-								break;
-							case 2:
-								printk(KERN_DEBUG"idi_inf: Ch%d: Bearer service change.\n", chan->No);
-								break;
-							default:
-								printk(KERN_DEBUG"idi_inf: Ch%d: Unknown Notification %x.\n", 
-										chan->No, buffer[pos] & 127);
-						}
+					switch(buffer[pos] & 127) {
+						case 0:
+							eicon_log(ccard, 4, "idi_inf: Ch%d: User suspended.\n", chan->No);
+							break;
+						case 1:
+							eicon_log(ccard, 4, "idi_inf: Ch%d: User resumed.\n", chan->No);
+							break;
+						case 2:
+							eicon_log(ccard, 4, "idi_inf: Ch%d: Bearer service change.\n", chan->No);
+							break;
+						default:
+							eicon_log(ccard, 4, "idi_inf: Ch%d: Unknown Notification %x.\n", 
+									chan->No, buffer[pos] & 127);
 					}
 					pos += wlen;
 				}
@@ -741,80 +868,91 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi
 			case PI:
 			case 0x600|PI:
 				if (wlen > 1) {
-					if (DebugVar & 4) {
-						switch(buffer[pos+1] & 127) {
-							case 1:
-								printk(KERN_DEBUG"idi_inf: Ch%d: Call is not end-to-end ISDN.\n", chan->No);
-								break;
-							case 2:
-								printk(KERN_DEBUG"idi_inf: Ch%d: Destination address is non ISDN.\n", chan->No);
-								break;
-							case 3:
-								printk(KERN_DEBUG"idi_inf: Ch%d: Origination address is non ISDN.\n", chan->No);
-								break;
-							case 4:
-								printk(KERN_DEBUG"idi_inf: Ch%d: Call has returned to the ISDN.\n", chan->No);
-								break;
-							case 5:
-								printk(KERN_DEBUG"idi_inf: Ch%d: Interworking has occurred.\n", chan->No);
-								break;
-							case 8:
-								printk(KERN_DEBUG"idi_inf: Ch%d: In-band information available.\n", chan->No);
-								break;
-							default:
-								printk(KERN_DEBUG"idi_inf: Ch%d: Unknown Progress %x.\n", 
-										chan->No, buffer[pos+1] & 127);
-						}
+					switch(buffer[pos+1] & 127) {
+						case 1:
+							eicon_log(ccard, 4, "idi_inf: Ch%d: Call is not end-to-end ISDN.\n", chan->No);
+							break;
+						case 2:
+							eicon_log(ccard, 4, "idi_inf: Ch%d: Destination address is non ISDN.\n", chan->No);
+							break;
+						case 3:
+							eicon_log(ccard, 4, "idi_inf: Ch%d: Origination address is non ISDN.\n", chan->No);
+							break;
+						case 4:
+							eicon_log(ccard, 4, "idi_inf: Ch%d: Call has returned to the ISDN.\n", chan->No);
+							break;
+						case 5:
+							eicon_log(ccard, 4, "idi_inf: Ch%d: Interworking has occurred.\n", chan->No);
+							break;
+						case 8:
+							eicon_log(ccard, 4, "idi_inf: Ch%d: In-band information available.\n", chan->No);
+							break;
+						default:
+							eicon_log(ccard, 4, "idi_inf: Ch%d: Unknown Progress %x.\n", 
+									chan->No, buffer[pos+1] & 127);
 					}
 				}
 				pos += wlen;
 				break;
 			case CAU:
+				if (wlen > sizeof(message->cau)) {
+					pos += wlen;
+					break;
+				}
 				for(i=0; i < wlen; i++) 
 					message->cau[i] = buffer[pos++];
 				memcpy(&chan->cause, &message->cau, 2);
-				if (DebugVar & 4)
-					printk(KERN_DEBUG"idi_inf: Ch%d: CAU=%d %d\n", chan->No,
-						message->cau[0],message->cau[1]);
+				eicon_log(ccard, 4, "idi_inf: Ch%d: CAU=%d %d\n", chan->No,
+					message->cau[0],message->cau[1]);
 				break;
 			case 0x800|CAU:
+				if (wlen > sizeof(message->e_cau)) {
+					pos += wlen;
+					break;
+				}
 				for(i=0; i < wlen; i++) 
 					message->e_cau[i] = buffer[pos++];
-				if (DebugVar & 4)
-					printk(KERN_DEBUG"idi_inf: Ch%d: ECAU=%d %d\n", chan->No,
-						message->e_cau[0],message->e_cau[1]);
+				eicon_log(ccard, 4, "idi_inf: Ch%d: ECAU=%d %d\n", chan->No,
+					message->e_cau[0],message->e_cau[1]);
 				break;
 			case 0x800|CHI:
+				if (wlen > sizeof(message->e_chi)) {
+					pos += wlen;
+					break;
+				}
 				for(i=0; i < wlen; i++) 
 					message->e_chi[i] = buffer[pos++];
-				if (DebugVar & 4)
-					printk(KERN_DEBUG"idi_inf: Ch%d: ESC/CHI=%d\n", chan->No,
-						message->e_cau[0]);
+				eicon_log(ccard, 4, "idi_inf: Ch%d: ESC/CHI=%d\n", chan->No,
+					message->e_cau[0]);
 				break;
 			case 0x800|0x7a:
 				pos ++;
 				message->e_mt=buffer[pos++];
-				if (DebugVar & 2)
-					printk(KERN_DEBUG"idi_inf: Ch%d: EMT=0x%x\n", chan->No, message->e_mt);
+				eicon_log(ccard, 4, "idi_inf: Ch%d: EMT=0x%x\n", chan->No, message->e_mt);
 				break;
 			case DT:
+				if (wlen > sizeof(message->dt)) {
+					pos += wlen;
+					break;
+				}
 				for(i=0; i < wlen; i++) 
 					message->dt[i] = buffer[pos++];
-				if (DebugVar & 4)
-					printk(KERN_DEBUG"idi_inf: Ch%d: DT: %02d.%02d.%02d %02d:%02d:%02d\n", chan->No,
-						message->dt[2], message->dt[1], message->dt[0],
-						message->dt[3], message->dt[4], message->dt[5]);
+				eicon_log(ccard, 4, "idi_inf: Ch%d: DT: %02d.%02d.%02d %02d:%02d:%02d\n", chan->No,
+					message->dt[2], message->dt[1], message->dt[0],
+					message->dt[3], message->dt[4], message->dt[5]);
 				break;
 			case 0x600|SIN:
+				if (wlen > sizeof(message->sin)) {
+					pos += wlen;
+					break;
+				}
 				for(i=0; i < wlen; i++) 
 					message->sin[i] = buffer[pos++];
-				if (DebugVar & 2)
-					printk(KERN_DEBUG"idi_inf: Ch%d: SIN=%d %d\n", chan->No,
-						message->sin[0],message->sin[1]);
+				eicon_log(ccard, 2, "idi_inf: Ch%d: SIN=%d %d\n", chan->No,
+					message->sin[0],message->sin[1]);
 				break;
 			case 0x600|CPS:
-				if (DebugVar & 2)
-					printk(KERN_DEBUG"idi_inf: Ch%d: Called Party Status in ind\n", chan->No);
+				eicon_log(ccard, 2, "idi_inf: Ch%d: Called Party Status in ind\n", chan->No);
 				pos += wlen;
 				break;
 			case 0x600|CIF:
@@ -822,8 +960,7 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi
 					if (buffer[pos + i] != '0') break;
 				memcpy(&cmd.parm.num, &buffer[pos + i], wlen - i);
 				cmd.parm.num[wlen - i] = 0;
-				if (DebugVar & 2)
-					printk(KERN_DEBUG"idi_inf: Ch%d: CIF=%s\n", chan->No, cmd.parm.num);
+				eicon_log(ccard, 2, "idi_inf: Ch%d: CIF=%s\n", chan->No, cmd.parm.num);
 				pos += wlen;
 				cmd.driver = ccard->myid;
 				cmd.command = ISDN_STAT_CINF;
@@ -831,8 +968,11 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi
 				ccard->interface.statcallb(&cmd);
 				break;
 			case 0x600|DATE:
-				if (DebugVar & 2)
-					printk(KERN_DEBUG"idi_inf: Ch%d: Date in ind\n", chan->No);
+				eicon_log(ccard, 2, "idi_inf: Ch%d: Date in ind\n", chan->No);
+				pos += wlen;
+				break;
+			case 0xa1: 
+				eicon_log(ccard, 2, "idi_inf: Ch%d: Sending Complete in ind.\n", chan->No);
 				pos += wlen;
 				break;
 			case 0xe08: 
@@ -852,8 +992,7 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi
 			case 0x880:
 				/* Managment Information Element */
 				if (!manbuf) {
-					if (DebugVar & 1)
-						printk(KERN_WARNING"idi_err: manbuf not allocated\n");
+					eicon_log(ccard, 1, "idi_err: manbuf not allocated\n");
 				}
 				else {
 					memcpy(&manbuf->data[manbuf->pos], &buffer[pos], wlen);
@@ -865,9 +1004,8 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi
 				break;
 			default:
 				pos += wlen;
-				if (DebugVar & 6)
-					printk(KERN_WARNING"idi_inf: Ch%d: unknown information element 0x%x in ind, len:%x\n", 
-						chan->No, code, wlen);
+				eicon_log(ccard, 6, "idi_inf: Ch%d: unknown information element 0x%x in ind, len:%x\n", 
+					chan->No, code, wlen);
 		}
 	}
   }
@@ -908,110 +1046,1095 @@ idi_bc2si(unsigned char *bc, unsigned char *hlc, unsigned char *si1, unsigned ch
 int
 idi_fill_in_T30(eicon_chan *chan, unsigned char *buffer)
 {
+	eicon_t30_s	*t30 = (eicon_t30_s *) buffer;
 
-	/* TODO , code follows */
+	if (!chan->fax) {
+		eicon_log(NULL, 1,"idi_T30: fill_in with NULL fax struct, ERROR\n");
+		return 0;
+	}
+	memset(t30, 0, sizeof(eicon_t30_s));
+	t30->station_id_len = EICON_FAXID_LEN;
+	memcpy(&t30->station_id[0], &chan->fax->id[0], EICON_FAXID_LEN);
+	t30->resolution = chan->fax->resolution;
+	t30->rate = chan->fax->rate + 1;	/* eicon rate starts with 1 */
+	t30->format = T30_FORMAT_SFF;
+	t30->pages_low = 0;
+	t30->pages_high = 0;
+	t30->atf = 1;				/* optimised for AT+F command set */
+	t30->code = 0;
+	t30->feature_bits_low = 0;
+	t30->feature_bits_high = 0;
+	t30->control_bits_low = 0;
+	t30->control_bits_high = 0;
+
+	if (chan->fax->nbc) {
+		/* set compression by DCC value */
+  	  switch(chan->fax->compression) {
+		case (0):	/* 1-D modified */
+			break;
+		case (1):	/* 2-D modified Read */
+			t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING;
+			t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING;
+			break;
+		case (2):	/* 2-D uncompressed */
+			t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_UNCOMPR;
+			t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING;
+			t30->feature_bits_low |= T30_FEATURE_BIT_UNCOMPR_ENABLED;
+			t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING;
+			break;
+		case (3):	/* 2-D modified Read */
+			t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_T6_CODING;
+			t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING;
+			t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_UNCOMPR;
+			t30->feature_bits_low |= T30_FEATURE_BIT_UNCOMPR_ENABLED;
+			t30->feature_bits_low |= T30_FEATURE_BIT_T6_CODING;
+			t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING;
+			t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM;
+			t30->feature_bits_low |= T30_FEATURE_BIT_ECM;
+			break;
+	  }
+	} else {
+		/* set compression to best */
+		t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_T6_CODING;
+		t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING;
+		t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_UNCOMPR;
+		t30->feature_bits_low |= T30_FEATURE_BIT_UNCOMPR_ENABLED;
+		t30->feature_bits_low |= T30_FEATURE_BIT_T6_CODING;
+		t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING;
+		t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM;
+		t30->feature_bits_low |= T30_FEATURE_BIT_ECM;
+	}
+	switch(chan->fax->ecm) {
+		case (0):	/* disable ECM */
+			break;
+		case (1):
+			t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM;
+			t30->control_bits_low |= T30_CONTROL_BIT_ECM_64_BYTES;
+			t30->feature_bits_low |= T30_FEATURE_BIT_ECM;
+			t30->feature_bits_low |= T30_FEATURE_BIT_ECM_64_BYTES;
+			break;
+		case (2):
+			t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM;
+			t30->feature_bits_low |= T30_FEATURE_BIT_ECM;
+			break;
+	}
 
-	return(0);
+	if (DebugVar & 128) {
+		char st[40];
+		eicon_log(NULL, 128, "sT30:code = %x\n", t30->code);
+		eicon_log(NULL, 128, "sT30:rate = %x\n", t30->rate);
+		eicon_log(NULL, 128, "sT30:res  = %x\n", t30->resolution);
+		eicon_log(NULL, 128, "sT30:format = %x\n", t30->format);
+		eicon_log(NULL, 128, "sT30:pages_low = %x\n", t30->pages_low);
+		eicon_log(NULL, 128, "sT30:pages_high = %x\n", t30->pages_high);
+		eicon_log(NULL, 128, "sT30:atf  = %x\n", t30->atf);
+		eicon_log(NULL, 128, "sT30:control_bits_low = %x\n", t30->control_bits_low);
+		eicon_log(NULL, 128, "sT30:control_bits_high = %x\n", t30->control_bits_high);
+		eicon_log(NULL, 128, "sT30:feature_bits_low = %x\n", t30->feature_bits_low);
+		eicon_log(NULL, 128, "sT30:feature_bits_high = %x\n", t30->feature_bits_high);
+		//eicon_log(NULL, 128, "sT30:universal_5 = %x\n", t30->universal_5);
+		//eicon_log(NULL, 128, "sT30:universal_6 = %x\n", t30->universal_6);
+		//eicon_log(NULL, 128, "sT30:universal_7 = %x\n", t30->universal_7);
+		eicon_log(NULL, 128, "sT30:station_id_len = %x\n", t30->station_id_len);
+		eicon_log(NULL, 128, "sT30:head_line_len = %x\n", t30->head_line_len);
+		strncpy(st, t30->station_id, t30->station_id_len);
+		st[t30->station_id_len] = 0;
+		eicon_log(NULL, 128, "sT30:station_id = <%s>\n", st);
+	}
+	return(sizeof(eicon_t30_s));
 }
 
 /* send fax struct */
 int
 idi_send_edata(eicon_card *card, eicon_chan *chan)
 {
+	struct sk_buff *skb;
+	struct sk_buff *skb2;
+	eicon_REQ *reqbuf;
+	eicon_chan_ptr *chan2;
+
+	if ((chan->fsm_state == EICON_STATE_NULL) || (chan->fsm_state == EICON_STATE_LISTEN)) {
+		eicon_log(card, 1, "idi_snd: Ch%d: send edata on state %d !\n", chan->No, chan->fsm_state);
+		return -ENODEV;
+	}
+	eicon_log(card, 128, "idi_snd: Ch%d: edata (fax)\n", chan->No);
+
+	skb = alloc_skb(sizeof(eicon_REQ) + sizeof(eicon_t30_s), GFP_ATOMIC);
+	skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
+
+	if ((!skb) || (!skb2)) {
+		eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_edata()\n", chan->No);
+		if (skb) 
+			dev_kfree_skb(skb);
+		if (skb2) 
+			dev_kfree_skb(skb2);
+		return -ENOMEM;
+	}
+
+	chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
+	chan2->ptr = chan;
 
-	/* TODO , code follows */
+	reqbuf = (eicon_REQ *)skb_put(skb, sizeof(eicon_t30_s) + sizeof(eicon_REQ));
+
+	reqbuf->Req = IDI_N_EDATA;
+	reqbuf->ReqCh = 0;
+	reqbuf->ReqId = 1;
+
+	reqbuf->XBuffer.length = idi_fill_in_T30(chan, reqbuf->XBuffer.P);
+	reqbuf->Reference = 1; /* Net Entity */
 
+	skb_queue_tail(&chan->e.X, skb);
+	skb_queue_tail(&card->sndq, skb2);
+	eicon_schedule_tx(card);
 	return (0);
 }
 
 void
 idi_parse_edata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int len)
 {
+	eicon_t30_s *p = (eicon_t30_s *)buffer;
+	int i;
 
-	/* TODO , code follows */
+	if (DebugVar & 128) {
+		char st[40];
+		eicon_log(ccard, 128, "rT30:len %d , size %d\n", len, sizeof(eicon_t30_s));
+		eicon_log(ccard, 128, "rT30:code = %x\n", p->code);
+		eicon_log(ccard, 128, "rT30:rate = %x\n", p->rate);
+		eicon_log(ccard, 128, "rT30:res  = %x\n", p->resolution);
+		eicon_log(ccard, 128, "rT30:format = %x\n", p->format);
+		eicon_log(ccard, 128, "rT30:pages_low = %x\n", p->pages_low);
+		eicon_log(ccard, 128, "rT30:pages_high = %x\n", p->pages_high);
+		eicon_log(ccard, 128, "rT30:atf  = %x\n", p->atf);
+		eicon_log(ccard, 128, "rT30:control_bits_low = %x\n", p->control_bits_low);
+		eicon_log(ccard, 128, "rT30:control_bits_high = %x\n", p->control_bits_high);
+		eicon_log(ccard, 128, "rT30:feature_bits_low = %x\n", p->feature_bits_low);
+		eicon_log(ccard, 128, "rT30:feature_bits_high = %x\n", p->feature_bits_high);
+		//eicon_log(ccard, 128, "rT30:universal_5 = %x\n", p->universal_5);
+		//eicon_log(ccard, 128, "rT30:universal_6 = %x\n", p->universal_6);
+		//eicon_log(ccard, 128, "rT30:universal_7 = %x\n", p->universal_7);
+		eicon_log(ccard, 128, "rT30:station_id_len = %x\n", p->station_id_len);
+		eicon_log(ccard, 128, "rT30:head_line_len = %x\n", p->head_line_len);
+		strncpy(st, p->station_id, p->station_id_len);
+		st[p->station_id_len] = 0;
+		eicon_log(ccard, 128, "rT30:station_id = <%s>\n", st);
+	}
+	if (!chan->fax) {
+		eicon_log(ccard, 1, "idi_edata: parse to NULL fax struct, ERROR\n");
+		return;
+	}
+	chan->fax->code = p->code;
+	i = (p->station_id_len < FAXIDLEN) ? p->station_id_len : (FAXIDLEN - 1);
+	memcpy(chan->fax->r_id, p->station_id, i);
+	chan->fax->r_id[i] = 0;
+	chan->fax->r_resolution = p->resolution;
+	chan->fax->r_rate = p->rate - 1;
+	chan->fax->r_binary = 0; /* no binary support */
+	chan->fax->r_width = 0;
+	chan->fax->r_length = 2;
+	chan->fax->r_scantime = 0;
+	chan->fax->r_compression = 0;
+	chan->fax->r_ecm = 0;
+	if (p->feature_bits_low & T30_FEATURE_BIT_2D_CODING) {
+		chan->fax->r_compression = 1;
+		if (p->feature_bits_low & T30_FEATURE_BIT_UNCOMPR_ENABLED) {
+			chan->fax->r_compression = 2;
+		}
+	}
+	if (p->feature_bits_low & T30_FEATURE_BIT_T6_CODING) {
+		chan->fax->r_compression = 3;
+	}
 
+	if (p->feature_bits_low & T30_FEATURE_BIT_ECM) {
+		chan->fax->r_ecm = 2;
+		if (p->feature_bits_low & T30_FEATURE_BIT_ECM_64_BYTES)
+			chan->fax->r_ecm = 1;
+	}
 }
 
 void
 idi_fax_send_header(eicon_card *card, eicon_chan *chan, int header)
 {
+	static __u16 wd2sff[] = {
+		1728, 2048, 2432, 1216, 864
+	};
+	static __u16 ln2sff[2][3] = {
+		{ 1143, 1401, 0 } , { 2287, 2802, 0 }
+	};
+	struct sk_buff *skb;
+	eicon_sff_dochead *doc;
+	eicon_sff_pagehead *page;
+	u_char *docp;
 
-	/* TODO , code follows */
+	if (!chan->fax) {
+		eicon_log(card, 1, "idi_fax: send head with NULL fax struct, ERROR\n");
+		return;
+	}
+	if (header == 2) { /* DocHeader + PageHeader */
+		skb = alloc_skb(sizeof(eicon_sff_dochead) + sizeof(eicon_sff_pagehead), GFP_ATOMIC);
+	} else {
+		skb = alloc_skb(sizeof(eicon_sff_pagehead), GFP_ATOMIC);
+	}
+	if (!skb) {
+		eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in fax_send_header()\n", chan->No);
+		return;
+	}
+
+	if (header == 2) { /* DocHeader + PageHeader */
+		docp = skb_put(skb, sizeof(eicon_sff_dochead) + sizeof(eicon_sff_pagehead));
+		doc = (eicon_sff_dochead *) docp;
+		page = (eicon_sff_pagehead *) (docp + sizeof(eicon_sff_dochead));
+		memset(docp, 0,sizeof(eicon_sff_dochead)  + sizeof(eicon_sff_pagehead));
+		doc->id = 0x66666653;
+		doc->version = 0x01;
+		doc->off1pagehead = sizeof(eicon_sff_dochead);
+	} else {
+		page = (eicon_sff_pagehead *)skb_put(skb, sizeof(eicon_sff_pagehead));
+		memset(page, 0, sizeof(eicon_sff_pagehead));
+	}
 
+	switch(header) {
+		case 1:	/* PageHeaderEnd */
+			page->pageheadid = 254;
+			page->pageheadlen = 0; 
+			break;
+		case 0: /* PageHeader */
+		case 2: /* DocHeader + PageHeader */
+			page->pageheadid = 254;
+			page->pageheadlen = sizeof(eicon_sff_pagehead) - 2;
+			page->resvert = chan->fax->resolution;
+			page->reshoriz = 0; /* always 203 dpi */
+			page->coding = 0; /* always 1D */
+			page->linelength = wd2sff[chan->fax->width];
+			page->pagelength = ln2sff[chan->fax->resolution][chan->fax->length]; 
+			eicon_log(card, 128, "sSFF-Head: linelength = %d\n", page->linelength);
+			eicon_log(card, 128, "sSFF-Head: pagelength = %d\n", page->pagelength);
+			break;
+	}
+	idi_send_data(card, chan, 0, skb, 0);
 }
 
 void
 idi_fax_cmd(eicon_card *card, eicon_chan *chan) 
 {
+	isdn_ctrl cmd;
 
-	/* TODO , code follows */
+	if ((!card) || (!chan))
+		return;
 
+	if (!chan->fax) {
+		eicon_log(card, 1, "idi_fax: cmd with NULL fax struct, ERROR\n");
+		return;
+	}
+	switch (chan->fax->code) {
+		case ISDN_TTY_FAX_DT:
+			if (chan->fax->phase == ISDN_FAX_PHASE_B) {
+				idi_send_edata(card, chan);
+				break;
+			}
+			if (chan->fax->phase == ISDN_FAX_PHASE_D) {
+				idi_send_edata(card, chan);
+				break;
+			}
+			break;
+
+		case ISDN_TTY_FAX_DR:
+			if (chan->fax->phase == ISDN_FAX_PHASE_B) {
+				idi_send_edata(card, chan);
+
+				cmd.driver = card->myid;
+				cmd.command = ISDN_STAT_FAXIND;
+				cmd.arg = chan->No;
+				chan->fax->r_code = ISDN_TTY_FAX_CFR;
+				card->interface.statcallb(&cmd);
+
+				cmd.driver = card->myid;
+				cmd.command = ISDN_STAT_FAXIND;
+				cmd.arg = chan->No;
+				chan->fax->r_code = ISDN_TTY_FAX_RID;
+				card->interface.statcallb(&cmd);
+
+				/* telling 1-D compression */
+				chan->fax->r_compression = 0;
+				cmd.driver = card->myid;
+				cmd.command = ISDN_STAT_FAXIND;
+				cmd.arg = chan->No;
+				chan->fax->r_code = ISDN_TTY_FAX_DCS;
+				card->interface.statcallb(&cmd);
+
+				chan->fax2.NextObject = FAX_OBJECT_DOCU;
+				chan->fax2.PrevObject = FAX_OBJECT_DOCU;
+
+				break;
+			}
+			if (chan->fax->phase == ISDN_FAX_PHASE_D) {
+				idi_send_edata(card, chan);
+				break;
+			}
+			break;
+
+		case ISDN_TTY_FAX_ET:
+				switch(chan->fax->fet) {
+					case 0:
+					case 1:
+						idi_fax_send_header(card, chan, 0);
+						break;
+					case 2:
+						idi_fax_send_header(card, chan, 1);
+						break;
+				}
+			break;
+	}
 }
 
 void
 idi_edata_rcveop(eicon_card *card, eicon_chan *chan)
 {
+	isdn_ctrl cmd;
 
-	/* TODO , code follows */
-
+	if (!chan->fax) {
+		eicon_log(card, 1, "idi_edata: rcveop with NULL fax struct, ERROR\n");
+		return;
+	}
+	cmd.driver = card->myid;
+	cmd.command = ISDN_STAT_FAXIND;
+	cmd.arg = chan->No;
+	chan->fax->r_code = ISDN_TTY_FAX_ET;
+	card->interface.statcallb(&cmd);
 }
 
 void
 idi_reset_fax_stat(eicon_chan *chan)
 {
-
-	/* TODO , code follows */
-
+	chan->fax2.LineLen = 0;
+	chan->fax2.LineData = 0;
+	chan->fax2.LineDataLen = 0;
+	chan->fax2.NullByteExist = 0;
+	chan->fax2.Dle = 0;
+	chan->fax2.PageCount = 0;
+	chan->fax2.Eop = 0;
 }
 
 void
 idi_edata_action(eicon_card *ccard, eicon_chan *chan, char *buffer, int len)
 {
+	isdn_ctrl cmd;
+
+	if (!chan->fax) {
+		eicon_log(ccard, 1, "idi_edata: action with NULL fax struct, ERROR\n");
+		return;
+	}
+	if (chan->fax->direction == ISDN_TTY_FAX_CONN_OUT) {
+		idi_parse_edata(ccard, chan, buffer, len);
+
+		if (chan->fax->phase == ISDN_FAX_PHASE_A) {
+			idi_reset_fax_stat(chan);
+
+			chan->fsm_state = EICON_STATE_ACTIVE;
+			cmd.driver = ccard->myid;
+			cmd.command = ISDN_STAT_BCONN;
+			cmd.arg = chan->No;
+			ccard->interface.statcallb(&cmd);
+
+			cmd.driver = ccard->myid;
+			cmd.command = ISDN_STAT_FAXIND;
+			cmd.arg = chan->No;
+			chan->fax->r_code = ISDN_TTY_FAX_FCON;
+			ccard->interface.statcallb(&cmd);
+
+			cmd.driver = ccard->myid;
+			cmd.command = ISDN_STAT_FAXIND;
+			cmd.arg = chan->No;
+			chan->fax->r_code = ISDN_TTY_FAX_RID;
+			ccard->interface.statcallb(&cmd);
+
+			cmd.driver = ccard->myid;
+			cmd.command = ISDN_STAT_FAXIND;
+			cmd.arg = chan->No;
+			chan->fax->r_code = ISDN_TTY_FAX_DIS;
+			ccard->interface.statcallb(&cmd);
+
+			if (chan->fax->r_compression != 0) {
+			/* telling fake compression in second DIS message */
+				chan->fax->r_compression = 0;
+				cmd.driver = ccard->myid;
+				cmd.command = ISDN_STAT_FAXIND;
+				cmd.arg = chan->No;
+				chan->fax->r_code = ISDN_TTY_FAX_DIS;
+				ccard->interface.statcallb(&cmd);
+			}
+
+			cmd.driver = ccard->myid;
+			cmd.command = ISDN_STAT_FAXIND;
+			cmd.arg = chan->No;
+			chan->fax->r_code = ISDN_TTY_FAX_SENT; /* OK message */
+			ccard->interface.statcallb(&cmd);
+		} else
+		if (chan->fax->phase == ISDN_FAX_PHASE_D) {
+
+			if ((chan->fax->code == EDATA_T30_MCF) &&
+			    (chan->fax->fet != 2)) {
+				cmd.driver = ccard->myid;
+				cmd.command = ISDN_STAT_FAXIND;
+				cmd.arg = chan->No;
+				chan->fax->r_code = ISDN_TTY_FAX_PTS;
+				ccard->interface.statcallb(&cmd);
+			}
+
+			switch(chan->fax->fet) {
+				case 0:	/* new page */
+					/* stay in phase D , wait on cmd +FDT */
+					break;
+				case 1:	/* new document */
+					/* link-level switch to phase B */
+					break;
+				case 2:	/* session end */
+				default:
+					/* idi_send_edata(ccard, chan); */
+					break;
+			}
+		}
+	}
+
+	if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) {
+		idi_parse_edata(ccard, chan, buffer, len);
 
-	/* TODO , code follows */
+		if ((chan->fax->code == EDATA_T30_DCS) &&
+		    (chan->fax->phase == ISDN_FAX_PHASE_A)) {
+			idi_reset_fax_stat(chan);
+
+			cmd.driver = ccard->myid;
+			cmd.command = ISDN_STAT_BCONN;
+			cmd.arg = chan->No;
+			ccard->interface.statcallb(&cmd);
+
+			cmd.driver = ccard->myid;
+			cmd.command = ISDN_STAT_FAXIND;
+			cmd.arg = chan->No;
+			chan->fax->r_code = ISDN_TTY_FAX_FCON_I;
+			ccard->interface.statcallb(&cmd);
+		} else
+		if ((chan->fax->code == EDATA_T30_TRAIN_OK) &&
+		    (chan->fax->phase == ISDN_FAX_PHASE_A)) {
+			cmd.driver = ccard->myid;
+			cmd.command = ISDN_STAT_FAXIND;
+			cmd.arg = chan->No;
+			chan->fax->r_code = ISDN_TTY_FAX_RID;
+			ccard->interface.statcallb(&cmd);
 
+			cmd.driver = ccard->myid;
+			cmd.command = ISDN_STAT_FAXIND;
+			cmd.arg = chan->No;
+			chan->fax->r_code = ISDN_TTY_FAX_TRAIN_OK;
+			ccard->interface.statcallb(&cmd);
+		} else
+		if ((chan->fax->code == EDATA_T30_TRAIN_OK) &&
+		    (chan->fax->phase == ISDN_FAX_PHASE_B)) {
+			cmd.driver = ccard->myid;
+			cmd.command = ISDN_STAT_FAXIND;
+			cmd.arg = chan->No;
+			chan->fax->r_code = ISDN_TTY_FAX_TRAIN_OK;
+			ccard->interface.statcallb(&cmd);
+		} else
+		if (chan->fax->phase == ISDN_FAX_PHASE_C) {
+			switch(chan->fax->code) {
+				case EDATA_T30_TRAIN_OK:
+					idi_send_edata(ccard, chan);
+					break;
+				case EDATA_T30_MPS:
+					chan->fax->fet = 0;
+					idi_edata_rcveop(ccard, chan);
+					break;
+				case EDATA_T30_EOM:
+					chan->fax->fet = 1;
+					idi_edata_rcveop(ccard, chan);
+					break;
+				case EDATA_T30_EOP:
+					chan->fax->fet = 2;
+					idi_edata_rcveop(ccard, chan);
+					break;
+			}
+		}
+	}
 }
 
 void
 fax_put_rcv(eicon_card *ccard, eicon_chan *chan, u_char *Data, int len)
 {
-
-	/* TODO , code follows */
-
+	struct sk_buff *skb;
+	
+        skb = alloc_skb(len + MAX_HEADER_LEN, GFP_ATOMIC);
+	if (!skb) {
+		eicon_log(ccard, 1, "idi_err: Ch%d: alloc_skb failed in fax_put_rcv()\n", chan->No);
+		return;
+	}
+	skb_reserve(skb, MAX_HEADER_LEN);
+	memcpy(skb_put(skb, len), Data, len);
+	ccard->interface.rcvcallb_skb(ccard->myid, chan->No, skb);
 }
 
 void
 idi_faxdata_rcv(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb)
 {
+	eicon_OBJBUFFER InBuf;
+	eicon_OBJBUFFER LineBuf;
+	unsigned int Length = 0;
+	unsigned int aLength = 0;
+	unsigned int ObjectSize = 0;
+	unsigned int ObjHeadLen = 0;
+	unsigned int ObjDataLen = 0;
+	__u8 Recordtype;
+	__u8 PageHeaderLen;	
+	__u8 Event;
+	eicon_sff_pagehead *ob_page;
+
+	__u16 Cl2Eol = 0x8000;
+
+#	define EVENT_NONE	0
+#	define EVENT_NEEDDATA	1
+
+	if (!chan->fax) {
+		eicon_log(ccard, 1, "idi_fax: rcvdata with NULL fax struct, ERROR\n");
+		return;
+	}
+
+
+	
+	if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) {
+		InBuf.Data = skb->data;
+		InBuf.Size = skb->len;
+		InBuf.Len  = 0;
+		InBuf.Next = InBuf.Data;
+		LineBuf.Data = chan->fax2.abLine;
+		LineBuf.Size = sizeof(chan->fax2.abLine);
+		LineBuf.Len  = chan->fax2.LineLen;
+		LineBuf.Next = LineBuf.Data + LineBuf.Len;
+
+		Event = EVENT_NONE;
+		while (Event == EVENT_NONE) {
+			switch(chan->fax2.NextObject) {
+				case FAX_OBJECT_DOCU:
+						Length = LineBuf.Len + (InBuf.Size - InBuf.Len);
+						if (Length < sizeof(eicon_sff_dochead)) {
+							Event = EVENT_NEEDDATA;
+							break;
+						}
+						ObjectSize = sizeof(eicon_sff_dochead);
+						Length = ObjectSize;
+						if (LineBuf.Len < Length) {
+							Length -= LineBuf.Len;
+							LineBuf.Len = 0;
+							LineBuf.Next = LineBuf.Data;
+							InBuf.Len += Length;
+							InBuf.Next += Length;
+						} else {
+							LineBuf.Len -= Length;
+							LineBuf.Next = LineBuf.Data + LineBuf.Len;
+							memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len);
+						}
+						chan->fax2.PrevObject = FAX_OBJECT_DOCU;
+						chan->fax2.NextObject = FAX_OBJECT_PAGE;
+					break;
+
+				case FAX_OBJECT_PAGE:
+						Length = LineBuf.Len + (InBuf.Size - InBuf.Len);
+						if (Length < 2) {
+							Event = EVENT_NEEDDATA;
+							break;
+						}
+						if (LineBuf.Len == 0) {
+							*LineBuf.Next++ = *InBuf.Next++;
+							LineBuf.Len++;
+							InBuf.Len++;
+						}
+						if (LineBuf.Len == 1) {
+							*LineBuf.Next++ = *InBuf.Next++;
+							LineBuf.Len++;
+							InBuf.Len++;
+						}
+						PageHeaderLen = *(LineBuf.Data + 1);
+						ObjectSize = (PageHeaderLen == 0) ? 2 : sizeof(eicon_sff_pagehead);
+						if (Length < ObjectSize) {
+							Event = EVENT_NEEDDATA;
+							break;
+						}
+						Length = ObjectSize;
+						/* extract page dimensions */
+						if (LineBuf.Len < Length) {
+							aLength = Length - LineBuf.Len;
+							memcpy(LineBuf.Next, InBuf.Next, aLength);
+							LineBuf.Next += aLength;
+							InBuf.Next += aLength;
+							LineBuf.Len += aLength;
+							InBuf.Len += aLength;
+						}
+						if (Length > 2) {
+							ob_page = (eicon_sff_pagehead *)LineBuf.Data;
+							switch(ob_page->linelength) {
+								case 2048:
+									chan->fax->r_width = 1;
+									break;
+								case 2432:
+									chan->fax->r_width = 2;
+									break;
+								case 1216:
+									chan->fax->r_width = 3;
+									break;
+								case 864:
+									chan->fax->r_width = 4;
+									break;
+								case 1728:
+								default:
+									chan->fax->r_width = 0;
+							}
+							switch(ob_page->pagelength) {
+								case 1143:
+								case 2287:
+									chan->fax->r_length = 0;
+									break;
+								case 1401:
+								case 2802:
+									chan->fax->r_length = 1;
+									break;
+								default:
+									chan->fax->r_length = 2;
+							}
+							eicon_log(ccard, 128, "rSFF-Head: linelength = %d\n", ob_page->linelength);
+							eicon_log(ccard, 128, "rSFF-Head: pagelength = %d\n", ob_page->pagelength);
+						}
+						LineBuf.Len -= Length;
+						LineBuf.Next = LineBuf.Data + LineBuf.Len;
+						memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len);
+
+						chan->fax2.PrevObject = FAX_OBJECT_PAGE;
+						chan->fax2.NextObject = FAX_OBJECT_LINE;
+					break;
+
+				case FAX_OBJECT_LINE:
+						Length = LineBuf.Len + (InBuf.Size - InBuf.Len);
+						if (Length < 1) {
+							Event = EVENT_NEEDDATA;
+							break;
+						}
+						if (LineBuf.Len == 0) {
+							*LineBuf.Next++ = *InBuf.Next++;
+							LineBuf.Len++;
+							InBuf.Len++;
+						}
+						Recordtype = *LineBuf.Data;
+						if (Recordtype == 0) {
+							/* recordtype pixel row (2 byte length) */
+							ObjHeadLen = 3;
+							if (Length < ObjHeadLen) {
+								Event = EVENT_NEEDDATA;
+								break;
+							}
+							while (LineBuf.Len < ObjHeadLen) {
+								*LineBuf.Next++ = *InBuf.Next++;
+								LineBuf.Len++;
+								InBuf.Len++;
+							}
+							ObjDataLen = *((__u16*) (LineBuf.Data + 1));
+							ObjectSize = ObjHeadLen + ObjDataLen;
+							if (Length < ObjectSize) {
+								Event = EVENT_NEEDDATA;
+								break;
+							}
+						} else
+						if ((Recordtype >= 1) && (Recordtype <= 216)) {
+							/* recordtype pixel row (1 byte length) */
+							ObjHeadLen = 1;
+							ObjDataLen = Recordtype;
+							ObjectSize = ObjHeadLen + ObjDataLen;
+							if (Length < ObjectSize) {
+								Event = EVENT_NEEDDATA;
+								break;
+							}
+						} else
+						if ((Recordtype >= 217) && (Recordtype <= 253)) {
+							/* recordtype empty lines */
+							ObjHeadLen = 1;
+							ObjDataLen = 0;
+							ObjectSize = ObjHeadLen + ObjDataLen;
+							LineBuf.Len--;
+							LineBuf.Next = LineBuf.Data + LineBuf.Len;
+							memmove(LineBuf.Data, LineBuf.Data + 1, LineBuf.Len);
+							break;
+						} else
+						if (Recordtype == 254) {
+							/* recordtype page header */
+							chan->fax2.PrevObject = FAX_OBJECT_LINE;
+							chan->fax2.NextObject = FAX_OBJECT_PAGE;
+							break;
+						} else {
+							/* recordtype user information */
+							ObjHeadLen = 2;
+							if (Length < ObjHeadLen) {
+								Event = EVENT_NEEDDATA;
+								break;
+							}
+							while (LineBuf.Len < ObjHeadLen) {
+								*LineBuf.Next++ = *InBuf.Next++;
+								LineBuf.Len++;
+								InBuf.Len++;
+							}
+							ObjDataLen = *(LineBuf.Data + 1);
+							ObjectSize = ObjHeadLen + ObjDataLen;
+							if (ObjDataLen == 0) {
+								/* illegal line coding */
+								LineBuf.Len -= ObjHeadLen;
+								LineBuf.Next = LineBuf.Data + LineBuf.Len;
+								memmove(LineBuf.Data, LineBuf.Data + ObjHeadLen, LineBuf.Len);
+								break;
+							} else {
+								/* user information */
+								if (Length < ObjectSize) {
+									Event = EVENT_NEEDDATA;
+									break;
+								}
+								Length = ObjectSize;
+								if (LineBuf.Len < Length) {
+									Length -= LineBuf.Len;
+									LineBuf.Len = 0;
+									LineBuf.Next = LineBuf.Data;
+									InBuf.Len += Length;
+									InBuf.Next += Length;
+								} else {
+									LineBuf.Len -= Length;
+									LineBuf.Next = LineBuf.Data + LineBuf.Len;
+									memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len);
+								}
+							}
+							break;	
+						}
+						Length = ObjectSize;
+						if (LineBuf.Len > ObjHeadLen) {
+							fax_put_rcv(ccard, chan, LineBuf.Data + ObjHeadLen,
+									(LineBuf.Len - ObjHeadLen));
+						}
+						Length -= LineBuf.Len;
+						LineBuf.Len = 0;
+						LineBuf.Next = LineBuf.Data;
+						if (Length > 0) {
+							fax_put_rcv(ccard, chan, InBuf.Next, Length);
+							InBuf.Len += Length;
+							InBuf.Next += Length;
+						}
+						fax_put_rcv(ccard, chan, (__u8 *)&Cl2Eol, sizeof(Cl2Eol));
+					break;
+			} /* end of switch (chan->fax2.NextObject) */
+		} /* end of while (Event==EVENT_NONE) */
+		if (InBuf.Len < InBuf.Size) {
+			Length = InBuf.Size - InBuf.Len;
+			if ((LineBuf.Len + Length) > LineBuf.Size) {
+				eicon_log(ccard, 1, "idi_fax: Ch%d: %d bytes dropping, small buffer\n", chan->No,
+					Length);
+				} else {
+					memcpy(LineBuf.Next, InBuf.Next, Length);
+					LineBuf.Len += Length;
+				}
+		}
+		chan->fax2.LineLen = LineBuf.Len;
+	} else { /* CONN_OUT */
+		/* On CONN_OUT we do not need incoming data, drop it */
+		/* maybe later for polling */
+	}
 
-	/* TODO , code follows */
+#	undef EVENT_NONE
+#	undef EVENT_NEEDDATA
 
+	return;
 }
 
 int
 idi_fax_send_outbuf(eicon_card *ccard, eicon_chan *chan, eicon_OBJBUFFER *OutBuf)
 {
+	struct sk_buff *skb;
 
-	/* TODO , code follows */
+	skb = alloc_skb(OutBuf->Len, GFP_ATOMIC);
+	if (!skb) {
+		eicon_log(ccard, 1, "idi_err: Ch%d: alloc_skb failed in fax_send_outbuf()\n", chan->No);
+		return(-1);
+	}
+	memcpy(skb_put(skb, OutBuf->Len), OutBuf->Data, OutBuf->Len);
 
-	return(0);
+	OutBuf->Len = 0;
+	OutBuf->Next = OutBuf->Data;
+
+	return(idi_send_data(ccard, chan, 0, skb, 1));
 }
 
 int
 idi_faxdata_send(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb)
 {
+	isdn_ctrl cmd;
+	eicon_OBJBUFFER InBuf;
+	__u8 InData;
+	__u8 InMask;
+	eicon_OBJBUFFER OutBuf;
+	eicon_OBJBUFFER LineBuf;
+	__u32 LineData;
+	unsigned int LineDataLen;
+	__u8 Byte;
+	__u8 Event;
+	int ret = 1;
+
+#	define EVENT_NONE	0
+#	define EVENT_EOD	1
+#	define EVENT_EOL 	2
+#	define EVENT_EOP 	3
+
+	if ((!ccard) || (!chan))
+		return -1;
 
-	/* TODO , code follows */
+	if (!chan->fax) {
+		eicon_log(ccard, 1, "idi_fax: senddata with NULL fax struct, ERROR\n");
+		return -1;
+	}
 
-	return(0);
+	if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) {
+		/* Simply ignore any data written in data mode when receiving a fax.    */
+		/* This is not completely correct because only XON's should come here.  */
+        	dev_kfree_skb(skb);
+		return 1;
+	}
+
+	if (chan->fax->phase != ISDN_FAX_PHASE_C) {
+        	dev_kfree_skb(skb);
+		return 1;
+	}
+
+        if (chan->queued + skb->len > 1200)
+                return 0;
+
+	InBuf.Data = skb->data;
+	InBuf.Size = skb->len;
+	InBuf.Len  = 0;
+	InBuf.Next = InBuf.Data;
+	InData = 0;
+	InMask = 0;
+
+	LineBuf.Data = chan->fax2.abLine;
+	LineBuf.Size = sizeof(chan->fax2.abLine);
+	LineBuf.Len  = chan->fax2.LineLen;
+	LineBuf.Next = LineBuf.Data + LineBuf.Len;
+	LineData = chan->fax2.LineData;
+	LineDataLen = chan->fax2.LineDataLen;
+
+	OutBuf.Data = chan->fax2.abFrame;
+	OutBuf.Size = sizeof(chan->fax2.abFrame);
+	OutBuf.Len = 0;
+	OutBuf.Next = OutBuf.Data;
+
+	Event = EVENT_NONE;
+
+	chan->fax2.Eop = 0;
+
+	for (;;) {
+	  for (;;) {
+		if (InMask == 0) {
+			if (InBuf.Len >= InBuf.Size) {
+				Event = EVENT_EOD;
+				break;
+			}
+			if ((chan->fax2.Dle != _DLE_) && *InBuf.Next == _DLE_) {
+				chan->fax2.Dle = _DLE_;
+				InBuf.Next++;
+				InBuf.Len++;
+				if (InBuf.Len >= InBuf.Size) {
+					Event = EVENT_EOD;
+					break;
+				}
+			}
+			if (chan->fax2.Dle == _DLE_) {
+				chan->fax2.Dle = 0;
+				if (*InBuf.Next == _ETX_) {
+					Event = EVENT_EOP;
+					break;
+				} else
+				if (*InBuf.Next == _DLE_) {
+					/* do nothing */
+				} else {
+					eicon_log(ccard, 1,
+						"idi_err: Ch%d: unknown DLE escape %02x found\n",
+							chan->No, *InBuf.Next);
+					InBuf.Next++;
+					InBuf.Len++;
+					if (InBuf.Len >= InBuf.Size) {
+						Event = EVENT_EOD;
+						break;
+					}
+				}
+			}
+			InBuf.Len++;
+			InData = *InBuf.Next++;
+			InMask = (chan->fax->bor) ? 0x80 : 0x01;
+		}
+		while (InMask) {
+			LineData >>= 1;
+			LineDataLen++;
+			if (InData & InMask)
+				LineData |= 0x80000000;
+			if (chan->fax->bor)
+				InMask >>= 1;
+			else
+				InMask <<= 1;
+
+			if ((LineDataLen >= T4_EOL_BITSIZE) &&
+			   ((LineData & T4_EOL_MASK_DWORD) == T4_EOL_DWORD)) {
+				Event = EVENT_EOL;
+				if (LineDataLen > T4_EOL_BITSIZE) {
+					Byte = (__u8)
+						((LineData & ~T4_EOL_MASK_DWORD) >>
+						(32 - LineDataLen));
+					if (Byte == 0) {
+						if (! chan->fax2.NullByteExist) {
+							chan->fax2.NullBytesPos = LineBuf.Len;
+							chan->fax2.NullByteExist = 1;
+						}
+					} else {
+						chan->fax2.NullByteExist = 0;
+					}
+					if (LineBuf.Len < LineBuf.Size) {
+						*LineBuf.Next++  = Byte;
+						LineBuf.Len++;
+					}
+				}
+				LineDataLen = 0;
+				break;
+			}
+			if (LineDataLen >= T4_EOL_BITSIZE + 8) {
+				Byte = (__u8)
+					((LineData & ~T4_EOL_MASK_DWORD) >>
+					(32 - T4_EOL_BITSIZE - 8));
+				LineData &= T4_EOL_MASK_DWORD;
+				LineDataLen = T4_EOL_BITSIZE;
+				if (Byte == 0) {
+					if (! chan->fax2.NullByteExist) {
+						chan->fax2.NullBytesPos = LineBuf.Len;
+						chan->fax2.NullByteExist = 1;
+					}
+				} else {
+					chan->fax2.NullByteExist = 0;
+				}
+				if (LineBuf.Len < LineBuf.Size) {
+					*LineBuf.Next++  = Byte; 
+					LineBuf.Len++;
+				}
+			}
+		}
+		if (Event != EVENT_NONE)
+			break;
+	  }
+
+		if ((Event != EVENT_EOL) && (Event != EVENT_EOP))
+			break;
+
+		if ((Event == EVENT_EOP) && (LineDataLen > 0)) {
+			LineData >>= 32 - LineDataLen;
+			LineDataLen = 0;
+			while (LineData != 0) {
+				Byte = (__u8) LineData;
+				LineData >>= 8;
+				if (Byte == 0) {
+					if (! chan->fax2.NullByteExist) {
+						chan->fax2.NullBytesPos = LineBuf.Len;
+						chan->fax2.NullByteExist = 1;
+					}
+				} else {
+					chan->fax2.NullByteExist = 0;
+				}
+				if (LineBuf.Len < LineBuf.Size) {
+					*LineBuf.Next++  = Byte;
+					LineBuf.Len++;
+				}
+				
+			}
+		}
+		if (chan->fax2.NullByteExist) {
+			if (chan->fax2.NullBytesPos == 0) {
+				LineBuf.Len = 0;
+			} else {
+				LineBuf.Len = chan->fax2.NullBytesPos + 1;
+			}
+		}
+		if (LineBuf.Len > 0) {
+			if (OutBuf.Len + LineBuf.Len + SFF_LEN_FLD_SIZE > OutBuf.Size) {
+				ret = idi_fax_send_outbuf(ccard, chan, &OutBuf);
+			}
+			if (LineBuf.Len <= 216) {
+				*OutBuf.Next++ = (__u8) LineBuf.Len;
+				OutBuf.Len++;
+			} else {
+				*OutBuf.Next++ = 0;
+				*((__u16 *) OutBuf.Next)++ = (__u16) LineBuf.Len;
+				OutBuf.Len += 3;
+			}
+			memcpy(OutBuf.Next, LineBuf.Data, LineBuf.Len);
+			OutBuf.Next += LineBuf.Len;
+			OutBuf.Len  += LineBuf.Len;
+		}
+		LineBuf.Len = 0;
+		LineBuf.Next = LineBuf.Data;
+		chan->fax2.NullByteExist = 0;
+		if (Event == EVENT_EOP)
+			break;
+
+		Event = EVENT_NONE;
+	}
+
+	if (Event == EVENT_EOP) {
+		chan->fax2.Eop = 1;
+		chan->fax2.PageCount++;
+		cmd.driver = ccard->myid;
+		cmd.command = ISDN_STAT_FAXIND;
+		cmd.arg = chan->No;
+		chan->fax->r_code = ISDN_TTY_FAX_EOP;
+		ccard->interface.statcallb(&cmd);
+	}
+	if (OutBuf.Len > 0) {
+		ret = idi_fax_send_outbuf(ccard, chan, &OutBuf);
+	}
+
+	chan->fax2.LineLen = LineBuf.Len;
+	chan->fax2.LineData = LineData;
+	chan->fax2.LineDataLen = LineDataLen;
+
+#	undef EVENT_NONE
+#	undef EVENT_EOD
+#	undef EVENT_EOL
+#	undef EVENT_EOP
+
+	if (ret >= 0)
+	        dev_kfree_skb(skb);
+	if (ret == 0)
+		ret = 1;
+	return(ret);
 }
 
 void
 idi_fax_hangup(eicon_card *ccard, eicon_chan *chan)
 {
+	isdn_ctrl cmd;
 
-	/* TODO , code follows */
-
+	if (!chan->fax) {
+		eicon_log(ccard, 1, "idi_fax: hangup with NULL fax struct, ERROR\n");
+		return;
+	}
+	if ((chan->fax->direction == ISDN_TTY_FAX_CONN_OUT) &&
+	    (chan->fax->code == 0)) {
+		cmd.driver = ccard->myid;
+		cmd.command = ISDN_STAT_FAXIND;
+		cmd.arg = chan->No;
+		chan->fax->r_code = ISDN_TTY_FAX_PTS;
+		ccard->interface.statcallb(&cmd);
+	}
+	if ((chan->fax->code > 1) && (chan->fax->code < 120))
+		chan->fax->code += 120;
+	chan->fax->r_code = ISDN_TTY_FAX_HNG;
+	cmd.driver = ccard->myid;
+	cmd.command = ISDN_STAT_FAXIND;
+	cmd.arg = chan->No;
+	ccard->interface.statcallb(&cmd);
 }
 
 #endif	/******** FAX ********/
@@ -1025,20 +2148,17 @@ idi_send_udata(eicon_card *card, eicon_chan *chan, int UReq, u_char *buffer, int
 	eicon_chan_ptr *chan2;
 
 	if ((chan->fsm_state == EICON_STATE_NULL) || (chan->fsm_state == EICON_STATE_LISTEN)) {
-		if (DebugVar & 1)
-			printk(KERN_DEBUG"idi_snd: Ch%d: send udata on state %d !\n", chan->No, chan->fsm_state);
+		eicon_log(card, 1, "idi_snd: Ch%d: send udata on state %d !\n", chan->No, chan->fsm_state);
 		return -ENODEV;
 	}
-	if (DebugVar & 8)
-		printk(KERN_DEBUG"idi_snd: Ch%d: udata 0x%x: %d %d %d %d\n", chan->No,
-				UReq, buffer[0], buffer[1], buffer[2], buffer[3]);
+	eicon_log(card, 8, "idi_snd: Ch%d: udata 0x%x: %d %d %d %d\n", chan->No,
+			UReq, buffer[0], buffer[1], buffer[2], buffer[3]);
 
 	skb = alloc_skb(sizeof(eicon_REQ) + len + 1, GFP_ATOMIC);
 	skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
 
 	if ((!skb) || (!skb2)) {
-		if (DebugVar & 1)
-			printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed in send_udata()\n", chan->No);
+		eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_udata()\n", chan->No);
 		if (skb) 
 			dev_kfree_skb(skb);
 		if (skb2) 
@@ -1072,6 +2192,9 @@ idi_audio_cmd(eicon_card *ccard, eicon_chan *chan, int cmd, u_char *value)
 	u_char buf[6];
 	struct enable_dtmf_s *dtmf_buf = (struct enable_dtmf_s *)buf;
 
+	if ((!ccard) || (!chan))
+		return;
+
 	memset(buf, 0, 6);
 	switch(cmd) {
 		case ISDN_AUDIO_SETDD:
@@ -1103,14 +2226,15 @@ idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int
 	'1','4','7','*','2','5','8','0','3','6','9','#','A','B','C','D'
 	};
 
+	if ((!ccard) || (!chan))
+		return;
+
 	switch (buffer[0]) {
 		case DSP_UDATA_INDICATION_SYNC:
-			if (DebugVar & 16)
-  				printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_SYNC time %d\n", chan->No, p->time);
+			eicon_log(ccard, 16, "idi_ind: Ch%d: UDATA_SYNC time %d\n", chan->No, p->time);
 			break;
 		case DSP_UDATA_INDICATION_DCD_OFF:
-			if (DebugVar & 8)
-  				printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DCD_OFF time %d\n", chan->No, p->time);
+			eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DCD_OFF time %d\n", chan->No, p->time);
 			break;
 		case DSP_UDATA_INDICATION_DCD_ON:
 			if ((chan->l2prot == ISDN_PROTO_L2_MODEM) &&
@@ -1122,31 +2246,24 @@ idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int
 				sprintf(cmd.parm.num, "%d/%s", p->speed, connmsg[p->norm]);
 				ccard->interface.statcallb(&cmd);
 			}
-			if (DebugVar & 8) {
-  				printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DCD_ON time %d\n", chan->No, p->time);
-				printk(KERN_DEBUG"idi_ind: Ch%d: %d %d %d %d\n", chan->No,
-					    p->norm, p->options, p->speed, p->delay); 
-			    }
+			eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DCD_ON time %d\n", chan->No, p->time);
+			eicon_log(ccard, 8, "idi_ind: Ch%d: %d %d %d %d\n", chan->No,
+				p->norm, p->options, p->speed, p->delay); 
 			break;
 		case DSP_UDATA_INDICATION_CTS_OFF:
-			if (DebugVar & 8)
-  				printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_CTS_OFF time %d\n", chan->No, p->time);
+			eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_CTS_OFF time %d\n", chan->No, p->time);
 			break;
 		case DSP_UDATA_INDICATION_CTS_ON:
-			if (DebugVar & 8) {
-  				printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_CTS_ON time %d\n", chan->No, p->time);
-				printk(KERN_DEBUG"idi_ind: Ch%d: %d %d %d %d\n", chan->No,
-					    p->norm, p->options, p->speed, p->delay); 
-			}
+			eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_CTS_ON time %d\n", chan->No, p->time);
+			eicon_log(ccard, 8, "idi_ind: Ch%d: %d %d %d %d\n", chan->No,
+				p->norm, p->options, p->speed, p->delay); 
 			break;
 		case DSP_UDATA_INDICATION_DISCONNECT:
-			if (DebugVar & 8)
-  				printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DISCONNECT cause %d\n", chan->No, buffer[1]);
+			eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DISCONNECT cause %d\n", chan->No, buffer[1]);
 			break;
 		case DSP_UDATA_INDICATION_DTMF_DIGITS_RECEIVED:
-			if (DebugVar & 8)
-  				printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DTMF_REC '%c'\n", chan->No,
-					dtmf_code[buffer[1]]);
+			eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DTMF_REC '%c'\n", chan->No,
+				dtmf_code[buffer[1]]);
 			cmd.driver = ccard->myid;
 			cmd.command = ISDN_STAT_AUDIO;
 			cmd.parm.num[0] = ISDN_AUDIO_DTMF;
@@ -1155,8 +2272,7 @@ idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int
 			ccard->interface.statcallb(&cmd);
 			break;
 		default:
-			if (DebugVar & 8)
-				printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED UDATA Indication 0x%02x\n", chan->No, buffer[0]);
+			eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED UDATA Indication 0x%02x\n", chan->No, buffer[0]);
 	}
 }
 
@@ -1164,23 +2280,35 @@ void
 idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
 {
 	int tmp;
+	char tnum[64];
+	int dlev;
 	int free_buff;
+	ulong flags;
 	struct sk_buff *skb2;
         eicon_IND *ind = (eicon_IND *)skb->data;
 	eicon_chan *chan;
 	idi_ind_message message;
 	isdn_ctrl cmd;
 
+	if (!ccard) {
+		eicon_log(ccard, 1, "idi_err: Ch??: null card in handle_ind\n");
+  		dev_kfree_skb(skb);
+		return;
+	}
+
 	if ((chan = ccard->IdTable[ind->IndId]) == NULL) {
+		eicon_log(ccard, 1, "idi_err: Ch??: null chan in handle_ind\n");
   		dev_kfree_skb(skb);
 		return;
 	}
 	
-	if ((DebugVar & 128) || 
-	   ((DebugVar & 16) && (ind->Ind != 8))) {
-        	printk(KERN_DEBUG "idi_hdl: Ch%d: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", chan->No,
-		        ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length);
-	}
+	if (ind->Ind != 8)
+		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,
+	        ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length);
 
 	free_buff = 1;
 	/* Signal Layer */
@@ -1188,16 +2316,16 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
 		idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length);
 		switch(ind->Ind) {
 			case HANGUP:
-				if (DebugVar & 8)
-  					printk(KERN_DEBUG"idi_ind: Ch%d: Hangup\n", chan->No);
+				eicon_log(ccard, 8, "idi_ind: Ch%d: Hangup\n", chan->No);
 		                while((skb2 = skb_dequeue(&chan->e.X))) {
 					dev_kfree_skb(skb2);
 				}
-				chan->e.busy = 0;
+				save_flags(flags);
+				cli();
 				chan->queued = 0;
 				chan->waitq = 0;
 				chan->waitpq = 0;
-				chan->fsm_state = EICON_STATE_NULL;
+				restore_flags(flags);
 				if (message.e_cau[0] & 0x7f) {
 					cmd.driver = ccard->myid;
 					cmd.arg = chan->No;
@@ -1207,58 +2335,83 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
 					ccard->interface.statcallb(&cmd);
 				}
 				chan->cause[0] = 0; 
-				cmd.driver = ccard->myid;
-				cmd.arg = chan->No;
-				cmd.command = ISDN_STAT_DHUP;
-				ccard->interface.statcallb(&cmd);
-				eicon_idi_listen_req(ccard, chan);
 #ifdef CONFIG_ISDN_TTY_FAX
 				if (!chan->e.B2Id)
 					chan->fax = 0;
 #endif
+				if (((chan->fsm_state == EICON_STATE_ACTIVE) ||
+				    (chan->fsm_state == EICON_STATE_WMCONN)) ||
+				    ((chan->l2prot == ISDN_PROTO_L2_FAX) &&
+				    (chan->fsm_state == EICON_STATE_OBWAIT))) {
+					chan->fsm_state = EICON_STATE_NULL;
+				} else {
+					if (chan->e.B2Id)
+						idi_do_req(ccard, chan, REMOVE, 1);
+					chan->fsm_state = EICON_STATE_NULL;
+					cmd.driver = ccard->myid;
+					cmd.arg = chan->No;
+					cmd.command = ISDN_STAT_DHUP;
+					ccard->interface.statcallb(&cmd);
+					eicon_idi_listen_req(ccard, chan);
+				}
 				break;
 			case INDICATE_IND:
-				if (DebugVar & 8)
-  					printk(KERN_DEBUG"idi_ind: Ch%d: Indicate_Ind\n", chan->No);
+				eicon_log(ccard, 8, "idi_ind: Ch%d: Indicate_Ind\n", chan->No);
+				if (chan->fsm_state != EICON_STATE_LISTEN) {
+					eicon_log(ccard, 1, "idi_err: Ch%d: Incoming call on wrong state (%d).\n",
+						chan->No, chan->fsm_state);
+					idi_do_req(ccard, chan, HANGUP, 0);
+					break;
+				}
 				chan->fsm_state = EICON_STATE_ICALL;
 				idi_bc2si(message.bc, message.hlc, &chan->si1, &chan->si2);
 				strcpy(chan->cpn, message.cpn + 1);
-				if (strlen(message.dsa)) {
-					strcat(chan->cpn, ".");
-					strcat(chan->cpn, message.dsa);
-				}
 				strcpy(chan->oad, message.oad);
+				strcpy(chan->dsa, message.dsa);
+				strcpy(chan->osa, message.osa);
+				chan->plan = message.plan;
+				chan->screen = message.screen;
 				try_stat_icall_again: 
 				cmd.driver = ccard->myid;
 				cmd.command = ISDN_STAT_ICALL;
 				cmd.arg = chan->No;
 				cmd.parm.setup.si1 = chan->si1;
 				cmd.parm.setup.si2 = chan->si2;
-				strcpy(cmd.parm.setup.eazmsn, chan->cpn);
-				strcpy(cmd.parm.setup.phone, chan->oad);
-				cmd.parm.setup.plan = message.plan;
-				cmd.parm.setup.screen = message.screen;
+				strcpy(tnum, chan->cpn);
+				if (strlen(chan->dsa)) {
+					strcat(tnum, ".");
+					strcat(tnum, chan->dsa);
+				}
+				tnum[ISDN_MSNLEN - 1] = 0;
+				strcpy(cmd.parm.setup.eazmsn, tnum);
+				strcpy(tnum, chan->oad);
+				if (strlen(chan->osa)) {
+					strcat(tnum, ".");
+					strcat(tnum, chan->osa);
+				}
+				tnum[ISDN_MSNLEN - 1] = 0;
+				strcpy(cmd.parm.setup.phone, tnum);
+				cmd.parm.setup.plan = chan->plan;
+				cmd.parm.setup.screen = chan->screen;
 				tmp = ccard->interface.statcallb(&cmd);
 				switch(tmp) {
 					case 0: /* no user responding */
 						idi_do_req(ccard, chan, HANGUP, 0);
+						chan->fsm_state = EICON_STATE_NULL;
 						break;
 					case 1: /* alert */
-						if (DebugVar & 8)
-  							printk(KERN_DEBUG"idi_req: Ch%d: Call Alert\n", chan->No);
+						eicon_log(ccard, 8, "idi_req: Ch%d: Call Alert\n", chan->No);
 						if ((chan->fsm_state == EICON_STATE_ICALL) || (chan->fsm_state == EICON_STATE_ICALLW)) {
 							chan->fsm_state = EICON_STATE_ICALL;
 							idi_do_req(ccard, chan, CALL_ALERT, 0);
 						}
 						break;
 					case 2: /* reject */
-						if (DebugVar & 8)
-  							printk(KERN_DEBUG"idi_req: Ch%d: Call Reject\n", chan->No);
+						eicon_log(ccard, 8, "idi_req: Ch%d: Call Reject\n", chan->No);
 						idi_do_req(ccard, chan, REJECT, 0);
 						break;
 					case 3: /* incomplete number */
-						if (DebugVar & 8)
-  							printk(KERN_DEBUG"idi_req: Ch%d: Incomplete Number\n", chan->No);
+						eicon_log(ccard, 8, "idi_req: Ch%d: Incomplete Number\n", chan->No);
 					        switch(ccard->type) {
 					                case EICON_CTYPE_MAESTRAP:
 					                case EICON_CTYPE_S2M:
@@ -1272,8 +2425,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
 				}
 				break;
 			case INFO_IND:
-				if (DebugVar & 8)
-  					printk(KERN_DEBUG"idi_ind: Ch%d: Info_Ind\n", chan->No);
+				eicon_log(ccard, 8, "idi_ind: Ch%d: Info_Ind\n", chan->No);
 				if ((chan->fsm_state == EICON_STATE_ICALLW) &&
 				    (message.cpn[0])) {
 					strcat(chan->cpn, message.cpn + 1);
@@ -1281,35 +2433,45 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
 				}
 				break;
 			case CALL_IND:
-				if (DebugVar & 8)
-  					printk(KERN_DEBUG"idi_ind: Ch%d: Call_Ind\n", chan->No);
+				eicon_log(ccard, 8, "idi_ind: Ch%d: Call_Ind\n", chan->No);
 				if ((chan->fsm_state == EICON_STATE_ICALL) || (chan->fsm_state == EICON_STATE_IWAIT)) {
 					chan->fsm_state = EICON_STATE_IBWAIT;
 					cmd.driver = ccard->myid;
 					cmd.command = ISDN_STAT_DCONN;
 					cmd.arg = chan->No;
 					ccard->interface.statcallb(&cmd);
-					if (chan->l2prot != ISDN_PROTO_L2_FAX) {
-						idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
-					}
+					switch(chan->l2prot) {
+						case ISDN_PROTO_L2_FAX:
 #ifdef CONFIG_ISDN_TTY_FAX
-					else {
-						if (chan->fax)
-							chan->fax->phase = ISDN_FAX_PHASE_A;
-					}
+							if (chan->fax)
+								chan->fax->phase = ISDN_FAX_PHASE_A;
 #endif
+							break;
+						case ISDN_PROTO_L2_MODEM:
+							/* do nothing, wait for connect */
+							break;
+						default:
+							idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
+					}
 				} else
 					idi_hangup(ccard, chan);
 				break;
 			case CALL_CON:
-				if (DebugVar & 8)
-  					printk(KERN_DEBUG"idi_ind: Ch%d: Call_Con\n", chan->No);
+				eicon_log(ccard, 8, "idi_ind: Ch%d: Call_Con\n", chan->No);
 				if (chan->fsm_state == EICON_STATE_OCALL) {
 					chan->fsm_state = EICON_STATE_OBWAIT;
 					cmd.driver = ccard->myid;
 					cmd.command = ISDN_STAT_DCONN;
 					cmd.arg = chan->No;
 					ccard->interface.statcallb(&cmd);
+
+					/* check if old NetID has been removed */
+					if (chan->e.B2Id) {
+						eicon_log(ccard, 1, "eicon: Ch%d: old net_id %x still exist, removing.\n",
+							chan->No, chan->e.B2Id);
+						idi_do_req(ccard, chan, REMOVE, 1);
+					}
+
 					idi_do_req(ccard, chan, ASSIGN, 1); 
 					idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
 #ifdef CONFIG_ISDN_TTY_FAX
@@ -1322,12 +2484,10 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
 				idi_hangup(ccard, chan);
 				break;
 			case AOC_IND:
-				if (DebugVar & 8)
-  					printk(KERN_DEBUG"idi_ind: Ch%d: Advice of Charge\n", chan->No);
+				eicon_log(ccard, 8, "idi_ind: Ch%d: Advice of Charge\n", chan->No);
 				break;
 			default:
-				if (DebugVar & 8)
-					printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED SigIndication 0x%02x\n", chan->No, ind->Ind);
+				eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED SigIndication 0x%02x\n", chan->No, ind->Ind);
 		}
 	}
 	/* Network Layer */
@@ -1341,8 +2501,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
 		else
 		switch(ind->Ind) {
 			case IDI_N_CONNECT_ACK:
-				if (DebugVar & 16)
-  					printk(KERN_DEBUG"idi_ind: Ch%d: N_Connect_Ack\n", chan->No);
+				eicon_log(ccard, 16, "idi_ind: Ch%d: N_Connect_Ack\n", chan->No);
 				if (chan->l2prot == ISDN_PROTO_L2_MODEM) {
 					chan->fsm_state = EICON_STATE_WMCONN;
 					break;
@@ -1362,8 +2521,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
 						}
 					}
 					else {
-						if (DebugVar & 1)
-							printk(KERN_DEBUG "idi_ind: N_CONNECT_ACK with NULL fax struct, ERROR\n");
+						eicon_log(ccard, 1, "idi_ind: N_CONNECT_ACK with NULL fax struct, ERROR\n");
 					}
 #endif
 					break;
@@ -1375,8 +2533,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
 				ccard->interface.statcallb(&cmd);
 				break; 
 			case IDI_N_CONNECT:
-				if (DebugVar & 16)
-  					printk(KERN_DEBUG"idi_ind: Ch%d: N_Connect\n", chan->No);
+				eicon_log(ccard, 16,"idi_ind: Ch%d: N_Connect\n", chan->No);
 				if (chan->e.B2Id) idi_do_req(ccard, chan, IDI_N_CONNECT_ACK, 1);
 				if (chan->l2prot == ISDN_PROTO_L2_FAX) {
 					break;
@@ -1392,9 +2549,11 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
 				ccard->interface.statcallb(&cmd);
 				break; 
 			case IDI_N_DISC:
-				if (DebugVar & 16)
-  					printk(KERN_DEBUG"idi_ind: Ch%d: N_DISC\n", chan->No);
+				eicon_log(ccard, 16, "idi_ind: Ch%d: N_DISC\n", chan->No);
 				if (chan->e.B2Id) {
+		                	while((skb2 = skb_dequeue(&chan->e.X))) {
+						dev_kfree_skb(skb2);
+					}
 					idi_do_req(ccard, chan, IDI_N_DISC_ACK, 1);
 					idi_do_req(ccard, chan, REMOVE, 1);
 				}
@@ -1404,23 +2563,26 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
 					idi_fax_hangup(ccard, chan);
 				}
 #endif
+				save_flags(flags);
+				cli();
 				chan->queued = 0;
 				chan->waitq = 0;
 				chan->waitpq = 0;
+				restore_flags(flags);
 				idi_do_req(ccard, chan, HANGUP, 0);
 				if (chan->fsm_state == EICON_STATE_ACTIVE) {
 					cmd.driver = ccard->myid;
 					cmd.command = ISDN_STAT_BHUP;
 					cmd.arg = chan->No;
 					ccard->interface.statcallb(&cmd);
+					chan->fsm_state = EICON_STATE_NULL;
 				}
 #ifdef CONFIG_ISDN_TTY_FAX
 				chan->fax = 0;
 #endif
 				break; 
 			case IDI_N_DISC_ACK:
-				if (DebugVar & 16)
-  					printk(KERN_DEBUG"idi_ind: Ch%d: N_DISC_ACK\n", chan->No);
+				eicon_log(ccard, 16, "idi_ind: Ch%d: N_DISC_ACK\n", chan->No);
 #ifdef CONFIG_ISDN_TTY_FAX
 				if (chan->l2prot == ISDN_PROTO_L2_FAX) {
 					idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
@@ -1429,13 +2591,11 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
 #endif
 				break; 
 			case IDI_N_DATA_ACK:
-				if (DebugVar & 16)
-  					printk(KERN_DEBUG"idi_ind: Ch%d: N_DATA_ACK\n", chan->No);
+				eicon_log(ccard, 16, "idi_ind: Ch%d: N_DATA_ACK\n", chan->No);
 				break;
 			case IDI_N_DATA:
 				skb_pull(skb, sizeof(eicon_IND) - 1);
-				if (DebugVar & 128)
-					printk(KERN_DEBUG"idi_rcv: Ch%d: %d bytes\n", chan->No, skb->len);
+				eicon_log(ccard, 128, "idi_rcv: Ch%d: %d bytes\n", chan->No, skb->len);
 				if (chan->l2prot == ISDN_PROTO_L2_FAX) {
 #ifdef CONFIG_ISDN_TTY_FAX
 					idi_faxdata_rcv(ccard, chan, skb);
@@ -1454,27 +2614,26 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
 				break; 
 #endif
 			default:
-				if (DebugVar & 8)
-					printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED NetIndication 0x%02x\n", chan->No, ind->Ind);
+				eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED NetIndication 0x%02x\n", chan->No, ind->Ind);
 		}
 	}
 	else {
-		if (DebugVar & 1)
-			printk(KERN_ERR "idi_ind: Ch%d: Ind is neither SIG nor NET !\n", chan->No);
+		eicon_log(ccard, 1, "idi_ind: Ch%d: Ind is neither SIG nor NET !\n", chan->No);
 	}
-   if (free_buff) dev_kfree_skb(skb);
+   if (free_buff)
+	dev_kfree_skb(skb);
 }
 
 int
 idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
 {
+	ulong flags;
 	isdn_ctrl cmd;
 
 	if (ack->RcId != ((chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id)) {
 		/* I dont know why this happens, just ignoring this RC */
-		if (DebugVar & 16)
-			printk(KERN_DEBUG "idi_ack: Ch%d: RcId %d not equal to last %d\n", chan->No, 
-				ack->RcId, (chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id);
+		eicon_log(ccard, 16, "idi_ack: Ch%d: RcId %d not equal to last %d\n", chan->No, 
+			ack->RcId, (chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id);
 		return 1;
 	}
 
@@ -1488,27 +2647,27 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
 	/* Remove an Id */
 	if (chan->e.Req == REMOVE) {
 		if (ack->Reference != chan->e.ref) {
-			if (DebugVar & 16)
-				printk(KERN_DEBUG "idi_ack: Ch%d: Rc-Ref %d not equal to stored %d\n", chan->No,
-					ack->Reference, chan->e.ref);
+			eicon_log(ccard, 16, "idi_ack: Ch%d: Rc-Ref %d not equal to stored %d\n", chan->No,
+				ack->Reference, chan->e.ref);
 			return 0;
 		}
+		save_flags(flags);
+		cli();
 		ccard->IdTable[ack->RcId] = NULL;
-		if (DebugVar & 16)
-			printk(KERN_DEBUG "idi_ack: Ch%d: Removed : Id=%x Ch=%d (%s)\n", chan->No,
-				ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig");
+		eicon_log(ccard, 16, "idi_ack: Ch%d: Removed : Id=%x Ch=%d (%s)\n", chan->No,
+			ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig");
 		if (!chan->e.ReqCh) 
 			chan->e.D3Id = 0;
 		else
 			chan->e.B2Id = 0;
+		restore_flags(flags);
 		return 1;
 	}
 
 	/* Signal layer */
 	if (!chan->e.ReqCh) {
-		if (DebugVar & 16)
-			printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No,
-				ack->RcId, ack->RcCh, ack->Reference);
+		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);
 	} else {
 	/* Network layer */
 		switch(chan->e.Req & 0x0f) {
@@ -1522,7 +2681,10 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
 						cmd.parm.length = chan->waitpq;
 						ccard->interface.statcallb(&cmd);
 					}
+					save_flags(flags);
+					cli();
 					chan->waitpq = 0;
+					restore_flags(flags);
 #ifdef CONFIG_ISDN_TTY_FAX
 					if (chan->l2prot == ISDN_PROTO_L2_FAX) {
 						if (((chan->queued - chan->waitq) < 1) &&
@@ -1536,20 +2698,21 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
 								ccard->interface.statcallb(&cmd);
 							}
 							else {
-								if (DebugVar & 1)
-									printk(KERN_DEBUG "idi_ack: Sent with NULL fax struct, ERROR\n");
+								eicon_log(ccard, 1, "idi_ack: Sent with NULL fax struct, ERROR\n");
 							}
 						}
 					}
 #endif
 				}
+				save_flags(flags);
+				cli();
 				chan->queued -= chan->waitq;
 				if (chan->queued < 0) chan->queued = 0;
+				restore_flags(flags);
 				break;
 			default:
-				if (DebugVar & 16)
-					printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No,
-						ack->RcId, ack->RcCh, ack->Reference);
+				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);
 		}
 	}
 	return 1;
@@ -1559,22 +2722,30 @@ void
 idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
 {
 	int j;
+	ulong flags;
         eicon_RC *ack = (eicon_RC *)skb->data;
 	eicon_chan *chan;
 	isdn_ctrl cmd;
 	int dCh = -1;
 
+	if (!ccard) {
+		eicon_log(ccard, 1, "idi_err: Ch??: null card in handle_ack\n");
+		dev_kfree_skb(skb);
+		return;
+	}
+
+	save_flags(flags);
+	cli();
 	if ((chan = ccard->IdTable[ack->RcId]) != NULL)
 		dCh = chan->No;
-	
+	restore_flags(flags);
 
 	switch (ack->Rc) {
 		case OK_FC:
 		case N_FLOW_CONTROL:
 		case ASSIGN_RC:
-			if (DebugVar & 1)
-				printk(KERN_ERR "idi_ack: Ch%d: unhandled RC 0x%x\n",
-					dCh, ack->Rc);
+			eicon_log(ccard, 1, "idi_ack: Ch%d: unhandled RC 0x%x\n",
+				dCh, ack->Rc);
 			break;
 		case READY_INT:
 		case TIMER_INT:
@@ -1583,8 +2754,7 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
 
 		case OK:
 			if (!chan) {
-				if (DebugVar & 1)
-					printk(KERN_ERR "idi_ack: Ch%d: OK on chan without Id\n", dCh);
+				eicon_log(ccard, 1, "idi_ack: Ch%d: OK on chan without Id\n", dCh);
 				break;
 			}
 			if (!idi_handle_ack_ok(ccard, chan, ack))
@@ -1593,29 +2763,29 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
 
 		case ASSIGN_OK:
 			if (chan) {
-				if (DebugVar & 1)
-					printk(KERN_ERR "idi_ack: Ch%d: ASSIGN-OK on chan already assigned (%x,%x)\n",
-						chan->No, chan->e.D3Id, chan->e.B2Id);
+				eicon_log(ccard, 1, "idi_ack: Ch%d: ASSIGN-OK on chan already assigned (%x,%x)\n",
+					chan->No, chan->e.D3Id, chan->e.B2Id);
 			}
+			save_flags(flags);
+			cli();
 			for(j = 0; j < ccard->nchannels + 1; j++) {
-				if (ccard->bch[j].e.ref == ack->Reference) {
+				if ((ccard->bch[j].e.ref == ack->Reference) &&
+					(ccard->bch[j].e.Req == ASSIGN)) {
 					if (!ccard->bch[j].e.ReqCh) 
 						ccard->bch[j].e.D3Id  = ack->RcId;
 					else
 						ccard->bch[j].e.B2Id  = ack->RcId;
 					ccard->IdTable[ack->RcId] = &ccard->bch[j];
-					ccard->bch[j].e.busy = 0;
-					ccard->bch[j].e.ref = 0;
-					if (DebugVar & 16)
-						printk(KERN_DEBUG"idi_ack: Ch%d: Id %x assigned (%s)\n", j, 
-							ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig");
+					chan = &ccard->bch[j];
+					eicon_log(ccard, 16, "idi_ack: Ch%d: Id %x assigned (%s)\n", j, 
+						ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig");
 					break;
 				}
 			}		
+			restore_flags(flags);
 			if (j > ccard->nchannels) {
-				if (DebugVar & 24)
-					printk(KERN_DEBUG"idi_ack: Ch??: ref %d not found for Id %d\n", 
-						ack->Reference, ack->RcId);
+				eicon_log(ccard, 24, "idi_ack: Ch??: ref %d not found for Id %d\n", 
+					ack->Reference, ack->RcId);
 			}
 			break;
 
@@ -1627,9 +2797,19 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
 		case UNKNOWN_IE:
 		case WRONG_IE:
 		default:
-			if (DebugVar & 1)
-				printk(KERN_ERR "eicon_ack: Ch%d: Not OK !!: Rc=%d Id=%x Ch=%d\n", dCh, 
-					ack->Rc, ack->RcId, ack->RcCh);
+			if (!chan) {
+				eicon_log(ccard, 1, "idi_ack: Ch%d: Not OK !! on chan without Id\n", dCh);
+				break;
+			} else
+			switch (chan->e.Req) {
+				case 12:	/* Alert */
+					eicon_log(ccard, 2, "eicon_err: Ch%d: Alert Not OK : Rc=%d Id=%x Ch=%d\n",
+						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) { /* Management */
 				chan->fsm_state = 2;
 			} else if (dCh >= 0) {
@@ -1642,8 +2822,13 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
 				ccard->interface.statcallb(&cmd);
 			}
 	}
-	if (chan)
+	save_flags(flags);
+	cli();
+	if (chan) {
+		chan->e.ref = 0;
 		chan->e.busy = 0;
+	}
+	restore_flags(flags);
 	dev_kfree_skb(skb);
 	eicon_schedule_tx(ccard);
 }
@@ -1658,21 +2843,25 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb,
         int len, plen = 0, offset = 0;
 	unsigned long flags;
 
+	if ((!card) || (!chan)) {
+		eicon_log(card, 1, "idi_err: Ch??: null card/chan in send_data\n");
+		return -1;
+	}
+
         if (chan->fsm_state != EICON_STATE_ACTIVE) {
-		if (DebugVar & 1)
-			printk(KERN_DEBUG"idi_snd: Ch%d: send bytes on state %d !\n", chan->No, chan->fsm_state);
+		eicon_log(card, 1, "idi_snd: Ch%d: send bytes on state %d !\n", chan->No, chan->fsm_state);
                 return -ENODEV;
 	}
 
         len = skb->len;
-	if (len > 2138)	/* too much for the shared memory */
+	if (len > EICON_MAX_QUEUE)	/* too much for the shared memory */
 		return -1;
         if (!len)
                 return 0;
-	if (chan->queued + len > ((chan->l2prot == ISDN_PROTO_L2_TRANS) ? 4000 : EICON_MAX_QUEUED))
+	if (chan->queued + len > EICON_MAX_QUEUE)
 		return 0;
-	if (DebugVar & 128)
-		printk(KERN_DEBUG"idi_snd: Ch%d: %d bytes\n", chan->No, len);
+
+	eicon_log(card, 128, "idi_snd: Ch%d: %d bytes\n", chan->No, len);
 
 	save_flags(flags);
 	cli();
@@ -1685,8 +2874,7 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb,
 
 	        if ((!xmit_skb) || (!skb2)) {
 			restore_flags(flags);
-			if (DebugVar & 1)
-	        	        printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed in send_data()\n", chan->No);
+        	        eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_data()\n", chan->No);
 			if (xmit_skb) 
 				dev_kfree_skb(skb);
 			if (skb2) 
@@ -1740,8 +2928,7 @@ eicon_idi_manage_assign(eicon_card *card)
         skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
 
         if ((!skb) || (!skb2)) {
-		if (DebugVar & 1)
-			printk(KERN_WARNING "idi_err: alloc_skb failed in manage_assign()\n");
+		eicon_log(card, 1, "idi_err: alloc_skb failed in manage_assign()\n");
 		if (skb) 
 			dev_kfree_skb(skb);
 		if (skb2) 
@@ -1783,8 +2970,7 @@ eicon_idi_manage_remove(eicon_card *card)
         skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
 
         if ((!skb) || (!skb2)) {
-		if (DebugVar & 1)
-                	printk(KERN_WARNING "idi_err: alloc_skb failed in manage_remove()\n");
+               	eicon_log(card, 1, "idi_err: alloc_skb failed in manage_remove()\n");
 		if (skb) 
 			dev_kfree_skb(skb);
 		if (skb2) 
@@ -1850,8 +3036,7 @@ eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb)
 	chan->fsm_state = 0;
 
 	if (!(manbuf = kmalloc(sizeof(eicon_manifbuf), GFP_KERNEL))) {
-		if (DebugVar & 1)
-                	printk(KERN_WARNING "idi_err: alloc_manifbuf failed\n");
+               	eicon_log(card, 1, "idi_err: alloc_manifbuf failed\n");
 		chan->e.D3Id = 0;
 		return -ENOMEM;
 	}
@@ -1865,8 +3050,7 @@ eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb)
         skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
 
         if ((!skb) || (!skb2)) {
-		if (DebugVar & 1)
-                	printk(KERN_WARNING "idi_err_manif: alloc_skb failed in manage()\n");
+               	eicon_log(card, 1, "idi_err_manif: alloc_skb failed in manage()\n");
 		if (skb) 
 			dev_kfree_skb(skb);
 		if (skb2) 
diff --git a/drivers/isdn/eicon/eicon_io.c b/drivers/isdn/eicon/eicon_io.c
index 60b5b4818495e75fefc2651f0bde6feb4a5883f9..779f241e0a9c550eb70b345b339c55e6e94ef5cf 100644
--- a/drivers/isdn/eicon/eicon_io.c
+++ b/drivers/isdn/eicon/eicon_io.c
@@ -1,4 +1,4 @@
-/* $Id: eicon_io.c,v 1.4 1999/08/22 20:26:47 calle Exp $
+/* $Id: eicon_io.c,v 1.8 1999/10/08 22:09:34 armin Exp $
  *
  * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
  * Code for communicating with hardware.
@@ -24,6 +24,20 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_io.c,v $
+ * Revision 1.8  1999/10/08 22:09:34  armin
+ * Some fixes of cards interface handling.
+ * Bugfix of NULL pointer occurence.
+ * Changed a few log outputs.
+ *
+ * Revision 1.7  1999/09/26 14:17:53  armin
+ * Improved debug and log via readstat()
+ *
+ * Revision 1.6  1999/09/21 20:35:43  armin
+ * added more error checking.
+ *
+ * Revision 1.5  1999/08/31 11:20:11  paul
+ * various spelling corrections (new checksums may be needed, Karsten!)
+ *
  * Revision 1.4  1999/08/22 20:26:47  calle
  * backported changes from kernel 2.3.14:
  * - several #include "config.h" gone, others come.
@@ -51,19 +65,21 @@
 
 void
 eicon_io_rcv_dispatch(eicon_card *ccard) {
+	ulong flags;
         struct sk_buff *skb, *skb2, *skb_new;
         eicon_IND *ind, *ind2, *ind_new;
         eicon_chan *chan;
 
         if (!ccard) {
-		if (DebugVar & 1)
-	                printk(KERN_WARNING "eicon_io_rcv_dispatch: NULL card!\n");
+	        eicon_log(ccard, 1, "eicon_err: NULL card in rcv_dispatch !\n");
                 return;
         }
 
 	while((skb = skb_dequeue(&ccard->rcvq))) {
         	ind = (eicon_IND *)skb->data;
 
+		save_flags(flags);
+		cli();
         	if ((chan = ccard->IdTable[ind->IndId]) == NULL) {
 			if (DebugVar & 1) {
 				switch(ind->Ind) {
@@ -71,14 +87,16 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
 						/* doesn't matter if this happens */ 
 						break;
 					default: 
-						printk(KERN_ERR "idi: Indication for unknown channel Ind=%d Id=%x\n", ind->Ind, ind->IndId);
-						printk(KERN_DEBUG "idi_hdl: Ch??: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n",
+						eicon_log(ccard, 1, "idi: Indication for unknown channel Ind=%d Id=%x\n", ind->Ind, ind->IndId);
+						eicon_log(ccard, 1, "idi_hdl: Ch??: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n",
 							ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length);
 				}
 			}
+			restore_flags(flags);
 	                dev_kfree_skb(skb);
 	                continue;
 	        }
+		restore_flags(flags);
 
 		if (chan->e.complete) { /* check for rec-buffer chaining */
 			if (ind->MLength == ind->RBuffer.length) {
@@ -94,10 +112,12 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
 			}
 		}
 		else {
+			save_flags(flags);
+			cli();
 			if (!(skb2 = skb_dequeue(&chan->e.R))) {
 				chan->e.complete = 1;
-				if (DebugVar & 1)
-	                		printk(KERN_ERR "eicon: buffer incomplete, but 0 in queue\n");
+                		eicon_log(ccard, 1, "eicon: buffer incomplete, but 0 in queue\n");
+				restore_flags(flags);
 	                	dev_kfree_skb(skb);
 				continue;	
 			}
@@ -105,8 +125,8 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
 			skb_new = alloc_skb(((sizeof(eicon_IND)-1)+ind->RBuffer.length+ind2->RBuffer.length),
 					GFP_ATOMIC);
 			if (!skb_new) {
-				if (DebugVar & 1)
-	                		printk(KERN_ERR "eicon_io: skb_alloc failed in rcv_dispatch()\n");
+                		eicon_log(ccard, 1, "eicon_io: skb_alloc failed in rcv_dispatch()\n");
+				restore_flags(flags);
 	                	dev_kfree_skb(skb);
 	                	dev_kfree_skb(skb2);
 				continue;	
@@ -125,12 +145,14 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
                 	dev_kfree_skb(skb2);
 			if (ind->MLength == ind->RBuffer.length) {
 				chan->e.complete = 2;
+				restore_flags(flags);
 				idi_handle_ind(ccard, skb_new);
 				continue;
 			}
 			else {
 				chan->e.complete = 0;
 				skb_queue_tail(&chan->e.R, skb_new);
+				restore_flags(flags);
 				continue;
 			}
 		}
@@ -142,8 +164,7 @@ eicon_io_ack_dispatch(eicon_card *ccard) {
         struct sk_buff *skb;
 
         if (!ccard) {
-		if (DebugVar & 1)
-			printk(KERN_WARNING "eicon_io_ack_dispatch: NULL card!\n");
+		eicon_log(ccard, 1, "eicon_err: NULL card in ack_dispatch!\n");
                 return;
         }
 	while((skb = skb_dequeue(&ccard->rackq))) {
@@ -399,13 +420,13 @@ eicon_io_transmit(eicon_card *ccard) {
 	int scom = 0;
 	int tmp = 0;
 	int quloop = 1;
+	int dlev = 0;
 
 	pci_card = &ccard->hwif.pci;
 	isa_card = &ccard->hwif.isa;
 
         if (!ccard) {
-		if (DebugVar & 1)
-                	printk(KERN_WARNING "eicon_transmit: NULL card!\n");
+               	eicon_log(ccard, 1, "eicon_transmit: NULL card!\n");
                 return;
         }
 
@@ -438,7 +459,7 @@ eicon_io_transmit(eicon_card *ccard) {
 			prram = 0;
 			break;
 		default:
-                	printk(KERN_WARNING "eicon_transmit: unsupported card-type!\n");
+                	eicon_log(ccard, 1, "eicon_transmit: unsupported card-type!\n");
 			return;
 	}
 
@@ -457,16 +478,14 @@ eicon_io_transmit(eicon_card *ccard) {
 				}
         	                restore_flags(flags);
                 	        skb_queue_head(&ccard->sndq, skb2);
-				if (DebugVar & 32)
-        	                	printk(KERN_INFO "eicon: transmit: Card not ready\n");
+       	                	eicon_log(ccard, 32, "eicon: transmit: Card not ready\n");
 	                        return;
 			}
 		} else {
 	                if (!(ram_inb(ccard, &prram->ReqOutput) - ram_inb(ccard, &prram->ReqInput))) {
         	                restore_flags(flags);
                 	        skb_queue_head(&ccard->sndq, skb2);
-				if (DebugVar & 32)
-        	                	printk(KERN_INFO "eicon: transmit: Card not ready\n");
+       	                	eicon_log(ccard, 32, "eicon: transmit: Card not ready\n");
 	                        return;
         	        }
 		}
@@ -479,8 +498,7 @@ eicon_io_transmit(eicon_card *ccard) {
 		  cli();
 		  reqbuf = (eicon_REQ *)skb->data;
 		  if ((reqbuf->Reference) && (chan->e.B2Id == 0) && (reqbuf->ReqId & 0x1f)) {
-			if (DebugVar & 16)
-				printk(KERN_WARNING "eicon: transmit: error Id=0 on %d (Net)\n", chan->No); 
+			eicon_log(ccard, 16, "eicon: transmit: error Id=0 on %d (Net)\n", chan->No); 
 		  } else {
 			if (scom) {
 				ram_outw(ccard, &com->XBuffer.length, reqbuf->XBuffer.length);
@@ -495,7 +513,7 @@ eicon_io_transmit(eicon_card *ccard) {
 				ram_outb(ccard, &ReqOut->ReqCh, reqbuf->ReqCh);
 				ram_outb(ccard, &ReqOut->Req, reqbuf->Req); 
 			}
-
+			dlev = 160;
 			if (reqbuf->ReqId & 0x1f) { /* if this is no ASSIGN */
 
 				if (!reqbuf->Reference) { /* Signal Layer */
@@ -517,6 +535,7 @@ eicon_io_transmit(eicon_card *ccard) {
 					   ((reqbuf->Req & 0x0f) == 0x01)) { /* Send Data */
 						chan->waitq = reqbuf->XBuffer.length;
 						chan->waitpq += reqbuf->XBuffer.length;
+						dlev = 128;
 					}
 				}
 
@@ -544,13 +563,12 @@ eicon_io_transmit(eicon_card *ccard) {
 			else
 				ram_outw(ccard, &prram->NextReq, ram_inw(ccard, &ReqOut->next)); 
 
-			chan->e.busy = 1; 
-			if (DebugVar & 32)
-	                	printk(KERN_DEBUG "eicon: Req=%d Id=%x Ch=%d Len=%d Ref=%d\n", 
-							reqbuf->Req, 
-							ram_inb(ccard, &ReqOut->ReqId),
-							reqbuf->ReqCh, reqbuf->XBuffer.length,
-							chan->e.ref); 
+			chan->e.busy = 1;
+	               	eicon_log(ccard, dlev, "eicon: Req=%d Id=%x Ch=%d Len=%d Ref=%d\n", 
+					reqbuf->Req, 
+					ram_inb(ccard, &ReqOut->ReqId),
+					reqbuf->ReqCh, reqbuf->XBuffer.length,
+					chan->e.ref); 
 		  }
 		  restore_flags(flags);
 		  dev_kfree_skb(skb);
@@ -559,8 +577,7 @@ eicon_io_transmit(eicon_card *ccard) {
 		} 
 		else {
 		skb_queue_tail(&ccard->sackq, skb2);
-		if (DebugVar & 32)
-                	printk(KERN_INFO "eicon: transmit: busy chan %d\n", chan->No); 
+               	eicon_log(ccard, 128, "eicon: transmit: busy chan %d\n", chan->No); 
 		}
 
 		if (scom)
@@ -601,10 +618,11 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
 	unsigned char *irqprobe = 0;
 	int scom = 0;
 	int tmp = 0;
+	int dlev = 0;
 
 
         if (!ccard) {
-                printk(KERN_WARNING "eicon_irq: spurious interrupt %d\n", irq);
+                eicon_log(ccard, 1, "eicon_irq: spurious interrupt %d\n", irq);
                 return;
         }
 
@@ -656,7 +674,7 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
 			prram = 0;
 			break;
 		default:
-                	printk(KERN_WARNING "eicon_irq: unsupported card-type!\n");
+                	eicon_log(ccard, 1, "eicon_irq: unsupported card-type!\n");
 			return;
 	}
 
@@ -706,24 +724,21 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
 		case EICON_CTYPE_QUADRO:
 		case EICON_CTYPE_S2M:
 			if (!(readb(isa_card->intack))) { /* card did not interrupt */
-				if (DebugVar & 1)
-					printk(KERN_DEBUG "eicon: IRQ: card tells no interrupt!\n");
+				eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n");
 				return;
 			} 
 			break;
 #endif
 		case EICON_CTYPE_MAESTRAP:
 			if (!(readb(&ram[0x3fe]))) { /* card did not interrupt */
-				if (DebugVar & 1)
-					printk(KERN_DEBUG "eicon: IRQ: card tells no interrupt!\n");
+				eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n");
 				return;
 			} 
 			break;
 		case EICON_CTYPE_MAESTRA:
 			outw(0x3fe, pci_card->PCIreg + M_ADDR);
 			if (!(inb(pci_card->PCIreg + M_DATA))) { /* card did not interrupt */
-				if (DebugVar & 1)
-					printk(KERN_DEBUG "eicon: IRQ: card tells no interrupt!\n");
+				eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n");
 				return;
 			} 
 			break;
@@ -735,8 +750,7 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
 	if ((tmp = ram_inb(ccard, &com->Rc))) {
 		eicon_RC *ack;
 		if (tmp == READY_INT) {
-			if (DebugVar & 64)
-                        	printk(KERN_INFO "eicon: IRQ Rc=READY_INT\n");
+                       	eicon_log(ccard, 64, "eicon: IRQ Rc=READY_INT\n");
 			if (ccard->ReadyInt) {
 				ccard->ReadyInt--;
 				ram_outb(ccard, &com->Rc, 0);
@@ -744,17 +758,15 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
 		} else {
 			skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC);
 			if (!skb) {
-				if (DebugVar & 1)
-	                		printk(KERN_ERR "eicon_io: skb_alloc failed in _irq()\n");
+                		eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n");
 			} else {
 				ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC));
 				ack->Rc = tmp;
 				ack->RcId = ram_inb(ccard, &com->RcId);
 				ack->RcCh = ram_inb(ccard, &com->RcCh);
 				ack->Reference = ccard->ref_in++;
-				if (DebugVar & 64)
-                	        	printk(KERN_INFO "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n",
-						tmp,ack->RcId,ack->RcCh,ack->Reference);
+               	        	eicon_log(ccard, 128, "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n",
+					tmp,ack->RcId,ack->RcCh,ack->Reference);
 				skb_queue_tail(&ccard->rackq, skb);
 				eicon_schedule_ack(ccard);
 			}
@@ -770,8 +782,7 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
 			int len = ram_inw(ccard, &com->RBuffer.length);
 			skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC);
 			if (!skb) {
-				if (DebugVar & 1)
-	                		printk(KERN_ERR "eicon_io: skb_alloc failed in _irq()\n");
+                		eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n");
 			} else {
 				ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1));
 				ind->Ind = tmp;
@@ -779,9 +790,12 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
 				ind->IndCh = ram_inb(ccard, &com->IndCh);
 				ind->MInd  = ram_inb(ccard, &com->MInd);
 				ind->MLength = ram_inw(ccard, &com->MLength);
-				ind->RBuffer.length = len; 
-				if (DebugVar & 64)
-                        		printk(KERN_INFO "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n",
+				ind->RBuffer.length = len;
+				if ((tmp == 1) || (tmp == 8))
+					dlev = 128;
+				else
+					dlev = 192;
+                       		eicon_log(ccard, dlev, "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n",
 					tmp,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len);
 				ram_copyfromcard(ccard, &ind->RBuffer.P, &com->RBuffer.P, len);
 				skb_queue_tail(&ccard->rcvq, skb);
@@ -804,17 +818,15 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
                         if((Rc=ram_inb(ccard, &RcIn->Rc))) {
 				skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC);
 				if (!skb) {
-					if (DebugVar & 1)
-	                			printk(KERN_ERR "eicon_io: skb_alloc failed in _irq()\n");
+                			eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n");
 				} else {
 					ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC));
 					ack->Rc = Rc;
 					ack->RcId = ram_inb(ccard, &RcIn->RcId);
 					ack->RcCh = ram_inb(ccard, &RcIn->RcCh);
 					ack->Reference = ram_inw(ccard, &RcIn->Reference);
-					if (DebugVar & 64)
-	        	                	printk(KERN_INFO "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n",
-							Rc,ack->RcId,ack->RcCh,ack->Reference);
+        	                	eicon_log(ccard, 128, "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n",
+						Rc,ack->RcId,ack->RcCh,ack->Reference);
 					skb_queue_tail(&ccard->rackq, skb);
 					eicon_schedule_ack(ccard);
 				}
@@ -839,8 +851,7 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
 				int len = ram_inw(ccard, &IndIn->RBuffer.length);
 				skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC);
 				if (!skb) {
-					if (DebugVar & 1)
-	                			printk(KERN_ERR "eicon_io: skb_alloc failed in _irq()\n");
+                			eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n");
 				} else {
 					ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1));
 					ind->Ind = Ind;
@@ -849,8 +860,11 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
 					ind->MInd  = ram_inb(ccard, &IndIn->MInd);
 					ind->MLength = ram_inw(ccard, &IndIn->MLength);
 					ind->RBuffer.length = len;
-					if (DebugVar & 64)
-	                	        	printk(KERN_INFO "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n",
+					if ((Ind == 1) || (Ind == 8))
+						dlev = 128;
+					else
+						dlev = 192;
+                	        	eicon_log(ccard, dlev, "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n",
 						Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len);
 	                                ram_copyfromcard(ccard, &ind->RBuffer.P, &IndIn->RBuffer.P, len);
 					skb_queue_tail(&ccard->rcvq, skb);
diff --git a/drivers/isdn/eicon/eicon_isa.c b/drivers/isdn/eicon/eicon_isa.c
index 75122559ce9eabe4725dff76df5ec51d5ab143d5..a89d18b1212814592458640072ecd946ccd2c75e 100644
--- a/drivers/isdn/eicon/eicon_isa.c
+++ b/drivers/isdn/eicon/eicon_isa.c
@@ -1,9 +1,9 @@
-/* $Id: eicon_isa.c,v 1.7 1999/08/22 20:26:48 calle Exp $
+/* $Id: eicon_isa.c,v 1.9 1999/09/08 20:17:31 armin Exp $
  *
  * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
  * Hardware-specific code for old ISA cards.
  *
- * Copyright 1998    by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1998    by Fritz Elfert (fritz@isdn4linux.de)
  * Copyright 1998,99 by Armin Schindler (mac@melware.de)
  * Copyright 1999    Cytronics & Melware (info@melware.de)
  *
@@ -22,6 +22,12 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_isa.c,v $
+ * Revision 1.9  1999/09/08 20:17:31  armin
+ * Added microchannel patch from Erik Weber.
+ *
+ * Revision 1.8  1999/09/06 07:29:35  fritz
+ * Changed my mail-address.
+ *
  * Revision 1.7  1999/08/22 20:26:48  calle
  * backported changes from kernel 2.3.14:
  * - several #include "config.h" gone, others come.
@@ -64,7 +70,9 @@
 #define release_shmem release_region
 #define request_shmem request_region
 
-char *eicon_isa_revision = "$Revision: 1.7 $";
+char *eicon_isa_revision = "$Revision: 1.9 $";
+
+#undef EICON_MCA_DEBUG
 
 #ifdef CONFIG_ISDN_DRV_EICON_ISA
 
@@ -107,7 +115,7 @@ eicon_isa_printpar(eicon_isa_card *card) {
 		case EICON_CTYPE_SCOM:
 		case EICON_CTYPE_QUADRO:
 		case EICON_CTYPE_S2M:
-			printk(KERN_INFO "Eicon %s at 0x%lx, irq %d\n",
+			printk(KERN_INFO "Eicon %s at 0x%lx, irq %d.\n",
 			       eicon_ctype_name[card->type],
 			       (unsigned long)card->shmem,
 			       card->irq);
@@ -210,12 +218,30 @@ eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) {
 		return -EBUSY;
 	}
 	request_shmem((unsigned long)card->shmem, card->ramsize, "Eicon ISA ISDN");
+#ifdef EICON_MCA_DEBUG
+	printk(KERN_INFO "eicon_isa_boot: card->ramsize = %d.\n", card->ramsize);
+#endif
 	card->mvalid = 1;
 
 	/* clear any pending irq's */
 	readb(card->intack);
+#ifdef CONFIG_MCA
+	if (card->type == EICON_CTYPE_SCOM) {
+		outb_p(0,card->io+1);
+	}
+	else {
+		printk(KERN_WARNING "eicon_isa_boot: Card type yet not supported.\n");
+		return -EINVAL;
+	};
+
+#ifdef EICON_MCA_DEBUG
+	printk(KERN_INFO "eicon_isa_boot: card->io      = %x.\n", card->io);
+	printk(KERN_INFO "eicon_isa_boot: card->irq     = %d.\n", (int)card->irq);
+#endif
+#else
 	/* set reset-line active */
 	writeb(0, card->stopcpu); 
+#endif  /* CONFIG_MCA */
 	/* clear irq-requests */
 	writeb(0, card->intack);
 	readb(card->intack);
@@ -242,7 +268,11 @@ eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) {
 
 	/* Start CPU */
 	writeb(cbuf.boot_opt, &boot->ctrl);
+#ifdef CONFIG_MCA
+	outb_p(0, card->io);
+#else 
 	writeb(0, card->startcpu); 
+#endif /* CONFIG_MCA */
 
 	/* Delay 0.2 sec. */
 	SLEEP(20);
@@ -254,7 +284,11 @@ eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) {
 		SLEEP(10);
 	}
 	if (readb(&boot->ctrl) != 0) {
-		printk(KERN_WARNING "eicon_isa_boot: CPU test failed\n");
+		printk(KERN_WARNING "eicon_isa_boot: CPU test failed.\n");
+#ifdef EICON_MCA_DEBUG
+		printk(KERN_INFO "eicon_isa_boot: &boot->ctrl = %d.\n",
+			readb(&boot->ctrl));
+#endif
 		eicon_isa_release_shmem(card);
 		return -EIO;
 	}
@@ -307,7 +341,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) {
 		return -EFAULT;
 
 	if (!(code = kmalloc(cbuf.firmware_len, GFP_KERNEL))) {
-		printk(KERN_WARNING "eicon_isa_boot: Couldn't allocate code buffer\n");
+		printk(KERN_WARNING "eicon_isa_load: Couldn't allocate code buffer\n");
 		return -ENOMEM;
 	}
 
@@ -323,7 +357,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) {
 		/* Check for valid IRQ */
 		if ((card->irq < 0) || (card->irq > 15) || 
 		    (!((1 << card->irq) & eicon_isa_valid_irq[card->type & 0x0f]))) {
-			printk(KERN_WARNING "eicon_isa_boot: illegal irq: %d\n", card->irq);
+			printk(KERN_WARNING "eicon_isa_load: illegal irq: %d\n", card->irq);
 			eicon_isa_release_shmem(card);
 			kfree(code);
 			return -EINVAL;
@@ -332,7 +366,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) {
 		if (!request_irq(card->irq, &eicon_irq, 0, "Eicon ISA ISDN", card))
 			card->ivalid = 1;
 		else {
-			printk(KERN_WARNING "eicon_isa_boot: irq %d already in use.\n",
+			printk(KERN_WARNING "eicon_isa_load: irq %d already in use.\n",
 			       card->irq);
 			eicon_isa_release_shmem(card);
 			kfree(code);
@@ -343,7 +377,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) {
         tmp = readb(&boot->msize);
         if (tmp != 8 && tmp != 16 && tmp != 24 &&
             tmp != 32 && tmp != 48 && tmp != 60) {
-                printk(KERN_WARNING "eicon_isa_boot: invalid memsize\n");
+                printk(KERN_WARNING "eicon_isa_load: invalid memsize\n");
 		eicon_isa_release_shmem(card);
                 return -EIO;
         }
@@ -366,7 +400,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) {
 			SLEEP(2);
 		}
 		if (readb(&boot->ctrl)) {
-			printk(KERN_WARNING "eicon_isa_boot: download timeout at 0x%x\n", p-code);
+			printk(KERN_WARNING "eicon_isa_load: download timeout at 0x%x\n", p-code);
 			eicon_isa_release(card);
 			kfree(code);
 			return -EIO;
@@ -389,7 +423,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) {
 		SLEEP(2);
 	}
 	if (readw(&boot->signature) != 0x4447) {
-		printk(KERN_WARNING "eicon_isa_boot: firmware selftest failed %04x\n",
+		printk(KERN_WARNING "eicon_isa_load: firmware selftest failed %04x\n",
 		       readw(&boot->signature));
 		eicon_isa_release(card);
 		return -EIO;
@@ -414,11 +448,15 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) {
 			SLEEP(2);
 		}
 		if (card->irqprobe == 1) {
-			printk(KERN_WARNING "eicon_isa_boot: IRQ test failed\n");
+			printk(KERN_WARNING "eicon_isa_load: IRQ # %d test failed\n", card->irq);
 			eicon_isa_release(card);
 			return -EIO;
 		}
 	}
+#ifdef EICON_MCA_DEBUG
+	printk(KERN_INFO "eicon_isa_load: IRQ # %d test succeeded.\n", card->irq);
+#endif
+
 	writeb(card->irq, &card->shmem->com.Int);
 
 	/* initializing some variables */
diff --git a/drivers/isdn/eicon/eicon_isa.h b/drivers/isdn/eicon/eicon_isa.h
index 5b0dc1a6a60fd7d5c06553ef6dd656c9bdc5d074..7f86bd9ff4efcc1755d12bc63ea463e984af64b8 100644
--- a/drivers/isdn/eicon/eicon_isa.h
+++ b/drivers/isdn/eicon/eicon_isa.h
@@ -1,8 +1,8 @@
-/* $Id: eicon_isa.h,v 1.3 1999/03/29 11:19:47 armin Exp $
+/* $Id: eicon_isa.h,v 1.5 1999/09/08 20:17:31 armin Exp $
  *
  * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
  *
- * Copyright 1998    by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1998    by Fritz Elfert (fritz@isdn4linux.de)
  * Copyright 1998,99 by Armin Schindler (mac@melware.de)
  * Copyright 1999    Cytronics & Melware (info@melware.de)
  *
@@ -21,6 +21,12 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_isa.h,v $
+ * Revision 1.5  1999/09/08 20:17:31  armin
+ * Added microchannel patch from Erik Weber.
+ *
+ * Revision 1.4  1999/09/06 07:29:35  fritz
+ * Changed my mail-address.
+ *
  * Revision 1.3  1999/03/29 11:19:47  armin
  * I/O stuff now in seperate file (eicon_io.c)
  * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
@@ -106,6 +112,9 @@ typedef union {
 typedef struct {
 	int               ramsize;
 	int               irq;	    /* IRQ                        */
+#ifdef CONFIG_MCA
+	int		  io;	    /* IO-port for MCA brand      */
+#endif /* CONFIG_MCA */
 	void*             card;
 	eicon_isa_shmem*  shmem;    /* Shared-memory area         */
 	unsigned char*    intack;   /* Int-Acknowledge            */
diff --git a/drivers/isdn/eicon/eicon_mod.c b/drivers/isdn/eicon/eicon_mod.c
index 1ac22aa80e0f70e247f3ea424107665c74362561..2cad8a504a5f3d36914987299f928e70ba1b9189 100644
--- a/drivers/isdn/eicon/eicon_mod.c
+++ b/drivers/isdn/eicon/eicon_mod.c
@@ -1,8 +1,8 @@
-/* $Id: eicon_mod.c,v 1.11 1999/08/29 17:23:45 armin Exp $
+/* $Id: eicon_mod.c,v 1.18 1999/10/11 18:13:25 armin Exp $
  *
  * ISDN lowlevel-module for Eicon.Diehl active cards.
  * 
- * Copyright 1997    by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1997    by Fritz Elfert (fritz@isdn4linux.de)
  * Copyright 1998,99 by Armin Schindler (mac@melware.de) 
  * Copyright 1999    Cytronics & Melware (info@melware.de)
  * 
@@ -11,6 +11,11 @@
  *
  *              Deutsche Telekom AG for S2M support.
  *
+ *		Deutsche Mailbox Saar-Lor-Lux GmbH
+ *		for sponsoring and testing fax
+ *		capabilities with Diva Server cards.
+ *		(dor@deutschemailbox.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)
@@ -26,6 +31,30 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_mod.c,v $
+ * Revision 1.18  1999/10/11 18:13:25  armin
+ * Added fax capabilities for Eicon Diva Server cards.
+ *
+ * Revision 1.17  1999/10/08 22:09:34  armin
+ * Some fixes of cards interface handling.
+ * Bugfix of NULL pointer occurence.
+ * Changed a few log outputs.
+ *
+ * Revision 1.16  1999/09/26 14:17:53  armin
+ * Improved debug and log via readstat()
+ *
+ * Revision 1.15  1999/09/08 20:17:31  armin
+ * Added microchannel patch from Erik Weber.
+ *
+ * Revision 1.14  1999/09/06 07:29:35  fritz
+ * Changed my mail-address.
+ *
+ * Revision 1.13  1999/09/04 17:37:59  armin
+ * Removed not used define, did not work and caused error
+ * in 2.3.16
+ *
+ * Revision 1.12  1999/08/31 11:20:14  paul
+ * various spelling corrections (new checksums may be needed, Karsten!)
+ *
  * Revision 1.11  1999/08/29 17:23:45  armin
  * New setup compat.
  * Bugfix if compile as not module.
@@ -82,7 +111,7 @@
 #include <linux/init.h>
 #ifdef CONFIG_MCA
 #include <linux/mca.h>
-#endif
+#endif /* CONFIG_MCA */
 
 #include "eicon.h"
 
@@ -91,7 +120,7 @@
 static eicon_card *cards = (eicon_card *) NULL;   /* glob. var , contains
                                                      start of card-list   */
 
-static char *eicon_revision = "$Revision: 1.11 $";
+static char *eicon_revision = "$Revision: 1.18 $";
 
 extern char *eicon_pci_revision;
 extern char *eicon_isa_revision;
@@ -172,8 +201,7 @@ find_channel(eicon_card *card, int channel)
 {
 	if ((channel >= 0) && (channel < card->nchannels))
         	return &(card->bch[channel]);
-	if (DebugVar & 1)
-		printk(KERN_WARNING "eicon: Invalid channel %d\n", channel);
+	eicon_log(card, 1, "eicon: Invalid channel %d\n", channel);
 	return NULL;
 }
 
@@ -239,87 +267,6 @@ eicon_find_eaz(eicon_card *card, char eaz)
 	return("\0");
 }
 
-#if 0
-/*
- * Add or delete an MSN to the MSN list
- *
- * First character of msneaz is EAZ, rest is MSN.
- * If length of eazmsn is 1, delete that entry.
- */
-static int
-eicon_set_msn(eicon_card *card, char *eazmsn)
-{
-        struct msn_entry *p = card->msn_list;
-        struct msn_entry *q = NULL;
-	unsigned long flags;
-	int i;
-	
-	if (!strlen(eazmsn))
-		return 0;
-	if (strlen(eazmsn) > 16)
-		return -EINVAL;
-	for (i = 0; i < strlen(eazmsn); i++)
-		if (!isdigit(eazmsn[i]))
-			return -EINVAL;
-        if (strlen(eazmsn) == 1) {
-		/* Delete a single MSN */
-		while (p) {
-			if (p->eaz == eazmsn[0]) {
-				save_flags(flags);
-				cli();
-				if (q)
-					q->next = p->next;
-				else
-					card->msn_list = p->next;
-				restore_flags(flags);
-				kfree(p);
-				if (DebugVar & 8)
-					printk(KERN_DEBUG
-					       "Mapping for EAZ %c deleted\n",
-					       eazmsn[0]);
-				return 0;
-			}
-			q = p;
-			p = p->next;
-		}
-		return 0;
-        }
-	/* Add a single MSN */
-	while (p) {
-		/* Found in list, replace MSN */
-		if (p->eaz == eazmsn[0]) {
-			save_flags(flags);
-			cli();
-			strcpy(p->msn, &eazmsn[1]);
-			restore_flags(flags);
-			if (DebugVar & 8)
-				printk(KERN_DEBUG
-				       "Mapping for EAZ %c changed to %s\n",
-				       eazmsn[0],
-				       &eazmsn[1]);
-			return 0;
-		}
-		p = p->next;
-	}
-	/* Not found in list, add new entry */
-	p = kmalloc(sizeof(msn_entry), GFP_KERNEL);
-	if (!p)
-		return -ENOMEM;
-	p->eaz = eazmsn[0];
-	strcpy(p->msn, &eazmsn[1]);
-	p->next = card->msn_list;
-	save_flags(flags);
-	cli();
-	card->msn_list = p;
-	restore_flags(flags);
-	if (DebugVar & 8)
-		printk(KERN_DEBUG
-		       "Mapping %c -> %s added\n",
-		       eazmsn[0],
-		       &eazmsn[1]);
-	return 0;
-}
-#endif
 
 static void
 eicon_rcv_dispatch(struct eicon_card *card)
@@ -331,9 +278,8 @@ eicon_rcv_dispatch(struct eicon_card *card)
 			eicon_io_rcv_dispatch(card);
 			break;
 		default:
-			if (DebugVar & 1)
-				printk(KERN_WARNING
-				       "eicon_ack_dispatch: Illegal bustype %d\n", card->bus);
+			eicon_log(card, 1,
+			       "eicon_ack_dispatch: Illegal bustype %d\n", card->bus);
 	}
 }
 
@@ -347,9 +293,8 @@ eicon_ack_dispatch(struct eicon_card *card)
 			eicon_io_ack_dispatch(card);
 			break;
 		default:
-			if (DebugVar & 1)
-				printk(KERN_WARNING
-			       		"eicon_ack_dispatch: Illegal bustype %d\n", card->bus);
+			eicon_log(card, 1,
+		       		"eicon_ack_dispatch: Illegal bustype %d\n", card->bus);
 	}
 }
 
@@ -363,9 +308,8 @@ eicon_transmit(struct eicon_card *card)
 			eicon_io_transmit(card);
 			break;
 		default:
-			if (DebugVar & 1)
-				printk(KERN_WARNING
-				       "eicon_transmit: Illegal bustype %d\n", card->bus);
+			eicon_log(card, 1,
+			       "eicon_transmit: Illegal bustype %d\n", card->bus);
 	}
 }
 
@@ -375,8 +319,7 @@ static int eicon_xlog(eicon_card *card, xlogreq_t *xlogreq)
 	int ret_val;
 
 	if (!(xlr = kmalloc(sizeof(xlogreq_t), GFP_KERNEL))) {
-		if (DebugVar & 1)
-			printk(KERN_WARNING "idi_err: alloc_xlogreq_t failed\n");
+		eicon_log(card, 1, "idi_err: alloc_xlogreq_t failed\n");
 		return -ENOMEM;
 	}
 	if (copy_from_user(xlr, xlogreq, sizeof(xlogreq_t))) {
@@ -406,9 +349,8 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
 	int ret = 0;
 	unsigned long flags;
  
-	if (DebugVar & 16)
-		printk(KERN_WARNING "eicon_cmd 0x%x with arg 0x%lx (0x%lx)\n",
-			c->command, c->arg, (ulong) *c->parm.num);
+	eicon_log(card, 16, "eicon_cmd 0x%x with arg 0x%lx (0x%lx)\n",
+		c->command, c->arg, (ulong) *c->parm.num);
 
         switch (c->command) {
 		case ISDN_CMD_IOCTL:
@@ -428,9 +370,8 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
 							return card->hwif.pci.PCIram;
 #endif
 						default:
-							if (DebugVar & 1)
-								printk(KERN_WARNING
-								       "eicon: Illegal BUS type %d\n",
+							eicon_log(card, 1,
+							       "eicon: Illegal BUS type %d\n",
 							       card->bus);
 							ret = -ENODEV;
 					}
@@ -440,17 +381,25 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
 						return -EBUSY;
 					switch (card->bus) {
 						case EICON_BUS_ISA:
-						case EICON_BUS_MCA:
 							if (eicon_isa_find_card(a,
 								card->hwif.isa.irq,
 								card->regname) < 0)
 								return -EFAULT;
 							card->hwif.isa.shmem = (eicon_isa_shmem *)a;
 							return 0;
+						case EICON_BUS_MCA:
+#if CONFIG_MCA
+							if (eicon_mca_find_card(
+								0, a,
+								card->hwif.isa.irq,
+								card->regname) < 0)
+								return -EFAULT;
+							card->hwif.isa.shmem = (eicon_isa_shmem *)a;
+							return 0;
+#endif /* CONFIG_MCA */
 						default:
-							if (DebugVar & 1)
-								printk(KERN_WARNING
-							      		"eicon: Illegal BUS type %d\n",
+							eicon_log(card, 1,
+						      		"eicon: Illegal BUS type %d\n",
 							       card->bus);
 							ret = -ENODEV;
 					}					
@@ -465,9 +414,8 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
 							return card->hwif.pci.irq;
 #endif
 						default:
-							if (DebugVar & 1)
-								printk(KERN_WARNING
-								       "eicon: Illegal BUS type %d\n",
+							eicon_log(card, 1,
+							       "eicon: Illegal BUS type %d\n",
 							       card->bus);
 							ret = -ENODEV;
 					}
@@ -482,9 +430,8 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
 							card->hwif.isa.irq = a;
 							return 0;
 						default:
-							if (DebugVar & 1)
-								printk(KERN_WARNING
-							      		"eicon: Illegal BUS type %d\n",
+							eicon_log(card, 1,
+						      		"eicon: Illegal BUS type %d\n",
 							       card->bus);
 							ret = -ENODEV;
 					}					
@@ -500,9 +447,8 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
 								&(((eicon_codebuf *)a)->isa));
 							break;
 						default:
-							if (DebugVar & 1)
-								printk(KERN_WARNING
-								       "eicon: Illegal BUS type %d\n",
+							eicon_log(card, 1,
+							       "eicon: Illegal BUS type %d\n",
 							       card->bus);
 							ret = -ENODEV;
 					}
@@ -534,9 +480,8 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
 							}
 							break;
 						default:
-							if (DebugVar & 1)
-								printk(KERN_WARNING
-								       "eicon: Illegal BUS type %d\n",
+							eicon_log(card, 1,
+							       "eicon: Illegal BUS type %d\n",
 							       card->bus);
 							ret = -ENODEV;
 					}
@@ -591,18 +536,6 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
 							} 
                                                         return ret;
 						} else return -ENODEV;
-#endif
-#if 0
-				case EICON_IOCTL_SETMSN:
-					if ((ret = copy_from_user(tmp, (char *)a, sizeof(tmp))))
-						return -EFAULT;
-					if ((ret = eicon_set_msn(card, tmp)))
-						return ret;
-#if 0
-					if (card->flags & EICON_FLAGS_RUNNING)
-						return(eicon_capi_manufacturer_req_msn(card));
-#endif
-					return 0;
 #endif
 				case EICON_IOCTL_ADDCARD:
 					if ((ret = copy_from_user(&cdef, (char *)a, sizeof(cdef))))
@@ -612,7 +545,7 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
 					return 0;
 				case EICON_IOCTL_DEBUGVAR:
 					DebugVar = a;
-					printk(KERN_DEBUG"Eicon: Debug Value set to %ld\n", DebugVar);
+					eicon_log(card, 1, "Eicon: Debug Value set to %ld\n", DebugVar);
 					return 0;
 #ifdef MODULE
 				case EICON_IOCTL_FREEIT:
@@ -633,8 +566,7 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
 			cli();
 			if ((chan->fsm_state != EICON_STATE_NULL) && (chan->fsm_state != EICON_STATE_LISTEN)) {
 				restore_flags(flags);
-				if (DebugVar & 1)
-					printk(KERN_WARNING "Dial on channel %d with state %d\n",
+				eicon_log(card, 1, "Dial on channel %d with state %d\n",
 					chan->No, chan->fsm_state);
 				return -EBUSY;
 			}
@@ -643,7 +575,6 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
 			else
 				tmp[0] = c->parm.setup.eazmsn[0];
 			chan->fsm_state = EICON_STATE_OCALL;
-			chan->callref = 0xffff;
 			restore_flags(flags);
 			
 			ret = idi_connect_req(card, chan, c->parm.setup.phone,
@@ -738,20 +669,17 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
 		case ISDN_CMD_GETEAZ:
 			if (!card->flags & EICON_FLAGS_RUNNING)
 				return -ENODEV;
-			if (DebugVar & 1)
-				printk(KERN_DEBUG "eicon CMD_GETEAZ not implemented\n");
+			eicon_log(card, 1, "eicon CMD_GETEAZ not implemented\n");
 			return 0;
 		case ISDN_CMD_SETSIL:
 			if (!card->flags & EICON_FLAGS_RUNNING)
 				return -ENODEV;
-			if (DebugVar & 1)
-				printk(KERN_DEBUG "eicon CMD_SETSIL not implemented\n");
+			eicon_log(card, 1, "eicon CMD_SETSIL not implemented\n");
 			return 0;
 		case ISDN_CMD_GETSIL:
 			if (!card->flags & EICON_FLAGS_RUNNING)
 				return -ENODEV;
-			if (DebugVar & 1)
-				printk(KERN_DEBUG "eicon CMD_GETSIL not implemented\n");
+			eicon_log(card, 1, "eicon CMD_GETSIL not implemented\n");
 			return 0;
 		case ISDN_CMD_LOCK:
 			MOD_INC_USE_COUNT;
@@ -817,36 +745,58 @@ if_command(isdn_ctrl * c)
 static int
 if_writecmd(const u_char * buf, int len, int user, int id, int channel)
 {
-#if 0
-	/* Not yet used */
-        eicon_card *card = eicon_findcard(id);
-
-        if (card) {
-                if (!card->flags & EICON_FLAGS_RUNNING)
-                        return (len);
-                return (len);
-        }
-        printk(KERN_ERR
-               "eicon: if_writecmd called with invalid driverId!\n");
-#endif
         return (len);
 }
 
 static int
 if_readstatus(u_char * buf, int len, int user, int id, int channel)
 {
-#if 0
-	/* Not yet used */
+	int count = 0;
+	int cnt = 0;
+	ulong flags = 0;
+	u_char *p = buf;
+	struct sk_buff *skb;
+
         eicon_card *card = eicon_findcard(id);
 	
         if (card) {
                 if (!card->flags & EICON_FLAGS_RUNNING)
                         return -ENODEV;
-                return (eicon_readstatus(buf, len, user, card));
+	
+		save_flags(flags);
+		cli();
+		while((skb = skb_dequeue(&card->statq))) {
+
+			if ((skb->len + count) > len)
+				cnt = len - count;
+			else
+				cnt = skb->len;
+
+			if (user)
+				copy_to_user(p, skb->data, cnt);
+			else
+				memcpy(p, skb->data, cnt);
+
+			count += cnt;
+			p += cnt;
+
+			if (cnt == skb->len) {
+				dev_kfree_skb(skb);
+				if (card->statq_entries > 0)
+					card->statq_entries--;
+			} else {
+				skb_pull(skb, cnt);
+				skb_queue_head(&card->statq, skb);
+				restore_flags(flags);
+				return count;
+			}
+		}
+		card->statq_entries = 0;
+		restore_flags(flags);
+		return count;
         }
         printk(KERN_ERR
                "eicon: if_readstatus called with invalid driverId!\n");
-#endif
         return 0;
 }
 
@@ -861,14 +811,11 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb)
 	len = skb->len;
 	
         if (card) {
-                if (!card->flags & EICON_FLAGS_RUNNING) {
-			dev_kfree_skb(skb);
+                if (!card->flags & EICON_FLAGS_RUNNING)
                         return -ENODEV;
-		}
-        	if (!(chan = find_channel(card, channel))) {
-			dev_kfree_skb(skb);
+        	if (!(chan = find_channel(card, channel)))
 			return -ENODEV;
-		}
+
 		if (chan->fsm_state == EICON_STATE_ACTIVE) {
 #ifdef CONFIG_ISDN_TTY_FAX
 			if (chan->l2prot == ISDN_PROTO_L2_FAX) {
@@ -880,16 +827,115 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb)
 				ret = idi_send_data(card, chan, ack, skb, 1);
 			return (ret);
 		} else {
-			dev_kfree_skb(skb);
 			return -ENODEV;
 		}
         }
         printk(KERN_ERR
                "eicon: if_sendbuf called with invalid driverId!\n");
-	dev_kfree_skb(skb);
         return -ENODEV;
 }
 
+/* jiftime() copied from HiSax */
+inline int
+jiftime(char *s, long mark)
+{
+        s += 8;
+
+        *s-- = '\0';
+        *s-- = mark % 10 + '0';
+        mark /= 10;
+        *s-- = mark % 10 + '0';
+        mark /= 10;
+        *s-- = '.';
+        *s-- = mark % 10 + '0';
+        mark /= 10;
+        *s-- = mark % 6 + '0';
+        mark /= 6;
+        *s-- = ':';
+        *s-- = mark % 10 + '0';
+        mark /= 10;
+        *s-- = mark % 10 + '0';
+        return(8);
+}
+
+void
+eicon_putstatus(eicon_card * card, char * buf)
+{
+	ulong flags;
+	int count;
+	isdn_ctrl cmd;
+	u_char *p;
+	struct sk_buff *skb;
+
+	if (!card)
+		return;
+
+	save_flags(flags);
+	cli();
+	count = strlen(buf);
+	skb = alloc_skb(count, GFP_ATOMIC);
+	if (!skb) {
+		restore_flags(flags);
+		printk(KERN_ERR "eicon: could not alloc skb in putstatus\n");
+		return;
+	}
+	p = skb_put(skb, count);
+	memcpy(p, buf, count);
+
+	skb_queue_tail(&card->statq, skb);
+
+	if (card->statq_entries >= MAX_STATUS_BUFFER) {
+		if ((skb = skb_dequeue(&card->statq))) {
+			count -= skb->len;
+			dev_kfree_skb(skb);
+		} else
+			count = 0;
+	} else
+		card->statq_entries++;
+
+	restore_flags(flags);
+        if (count) {
+                cmd.command = ISDN_STAT_STAVAIL;
+                cmd.driver = card->myid;
+                cmd.arg = count;
+		card->interface.statcallb(&cmd);
+        }
+}
+
+/*
+ * Debug and Log 
+ */
+void
+eicon_log(eicon_card * card, int level, const char *fmt, ...)
+{
+	va_list args;
+	char Line[160];
+	u_char *p;
+
+
+	if ((DebugVar & level) || (DebugVar & 256)) {
+		va_start(args, fmt);
+
+		if (DebugVar & level) {
+			if (DebugVar & 256) {
+				/* log-buffer */
+				p = Line;
+				p += jiftime(p, jiffies);
+				*p++ = 32;
+				p += vsprintf(p, fmt, args);
+				*p = 0;	
+				eicon_putstatus(card, Line);
+			} else {
+				/* printk, syslogd */
+				vsprintf(Line, fmt, args);
+				printk(KERN_DEBUG "%s", Line);
+			}
+		}
+
+		va_end(args);
+	}
+}
+
 
 /*
  * Allocate a new card-struct, initialize it
@@ -912,7 +958,7 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
 	qloop = (Type == EICON_CTYPE_QUADRO)?2:0;
 	for (i = 0; i <= qloop; i++) {
 		if (!(card = (eicon_card *) kmalloc(sizeof(eicon_card), GFP_KERNEL))) {
-			printk(KERN_WARNING
+			eicon_log(card, 1,
 			       "eicon: (%s) Could not allocate card-struct.\n", id);
 			return;
 		}
@@ -921,6 +967,8 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
 		skb_queue_head_init(&card->rcvq);
 		skb_queue_head_init(&card->rackq);
 		skb_queue_head_init(&card->sackq);
+		skb_queue_head_init(&card->statq);
+		card->statq_entries = 0;
 		card->snd_tq.routine = (void *) (void *) eicon_transmit;
 		card->snd_tq.data = card;
 		card->rcv_tq.routine = (void *) (void *) eicon_rcv_dispatch;
@@ -992,7 +1040,7 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
 						p = p->next;
 					}
 					if (!p) {
-						printk(KERN_WARNING "eicon_alloccard: Quadro Master not found.\n");
+						eicon_log(card, 1, "eicon_alloccard: Quadro Master not found.\n");
 						kfree(card);
 						return;
 					}
@@ -1014,7 +1062,7 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
 					ISDN_FEATURE_L2_V11019 |
 					ISDN_FEATURE_L2_V11038 |
 					ISDN_FEATURE_L2_MODEM |
-					/* ISDN_FEATURE_L2_FAX | */ 
+					ISDN_FEATURE_L2_FAX | 
 					ISDN_FEATURE_L3_TRANSDSP |
 					ISDN_FEATURE_L3_FAX;
                                 card->hwif.pci.card = (void *)card;
@@ -1038,7 +1086,7 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
 					ISDN_FEATURE_L2_V11019 |
 					ISDN_FEATURE_L2_V11038 |
 					ISDN_FEATURE_L2_MODEM |
-					/* ISDN_FEATURE_L2_FAX | */
+					ISDN_FEATURE_L2_FAX |
 					ISDN_FEATURE_L3_TRANSDSP |
 					ISDN_FEATURE_L3_FAX;
                                 card->hwif.pci.card = (void *)card;
@@ -1087,13 +1135,13 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
 				break;
 #endif
 			default:
-				printk(KERN_WARNING "eicon_alloccard: Invalid type %d\n", Type);
+				eicon_log(card, 1, "eicon_alloccard: Invalid type %d\n", Type);
 				kfree(card);
 				return;
 		}
 		if (!(card->bch = (eicon_chan *) kmalloc(sizeof(eicon_chan) * (card->nchannels + 1)
 							 , GFP_KERNEL))) {
-			printk(KERN_WARNING
+			eicon_log(card, 1,
 			       "eicon: (%s) Could not allocate bch-struct.\n", id);
 			kfree(card);
 			return;
@@ -1131,7 +1179,7 @@ eicon_registercard(eicon_card * card)
 		case EICON_BUS_MCA:
 			eicon_isa_printpar(&card->hwif.isa);
 			break;
-#endif
+#endif /* CONFIG_MCA */
 #endif
 		case EICON_BUS_PCI:
 #if CONFIG_PCI
@@ -1139,9 +1187,8 @@ eicon_registercard(eicon_card * card)
 			break;
 #endif
 		default:
-			if (DebugVar & 1)
-				printk(KERN_WARNING
-				       "eicon_registercard: Illegal BUS type %d\n",
+			eicon_log(card, 1,
+			       "eicon_registercard: Illegal BUS type %d\n",
 			       card->bus);
 			return -1;
         }
@@ -1170,7 +1217,7 @@ unregister_card(eicon_card * card)
 		case EICON_BUS_ISA:
 #ifdef CONFIG_MCA
 		case EICON_BUS_MCA:
-#endif
+#endif /* CONFIG_MCA */
 			eicon_isa_release(&card->hwif.isa);
 			break;
 #endif
@@ -1180,9 +1227,8 @@ unregister_card(eicon_card * card)
 			break;
 #endif
 		default:
-			if (DebugVar & 1)
-				printk(KERN_WARNING
-				       "eicon: Invalid BUS type %d\n",
+			eicon_log(card, 1,
+			       "eicon: Invalid BUS type %d\n",
 			       card->bus);
 			break;
         }
@@ -1191,6 +1237,26 @@ unregister_card(eicon_card * card)
 
 static void
 eicon_freecard(eicon_card *card) {
+	int i;
+	struct sk_buff *skb;
+
+	for(i = 0; i < (card->nchannels + 1); i++) {
+		while((skb = skb_dequeue(&card->bch[i].e.X)))
+			dev_kfree_skb(skb);
+		while((skb = skb_dequeue(&card->bch[i].e.R)))
+			dev_kfree_skb(skb);
+	}
+	while((skb = skb_dequeue(&card->sndq)))
+		dev_kfree_skb(skb);
+	while((skb = skb_dequeue(&card->rcvq)))
+		dev_kfree_skb(skb);
+	while((skb = skb_dequeue(&card->rackq)))
+		dev_kfree_skb(skb);
+	while((skb = skb_dequeue(&card->sackq)))
+		dev_kfree_skb(skb);
+	while((skb = skb_dequeue(&card->statq)))
+		dev_kfree_skb(skb);
+
 	eicon_clear_msn(card);
 	kfree(card->bch);
 	kfree(card);
@@ -1236,9 +1302,8 @@ eicon_addcard(int Type, int membase, int irq, char *id)
 					break;
 #endif
 				default:
-					if (DebugVar & 1)
-						printk(KERN_WARNING
-						       "eicon: addcard: Invalid BUS type %d\n",
+					printk(KERN_ERR
+					       "eicon: addcard: Invalid BUS type %d\n",
 					       p->bus);
 			}
 		} else
@@ -1250,7 +1315,7 @@ eicon_addcard(int Type, int membase, int irq, char *id)
                         p = p->next;
                 } else {
                         /* registering failed, remove card from list, free memory */
-                        printk(KERN_WARNING
+                        printk(KERN_ERR
                                "eicon: Initialization of %s failed\n",
                                p->interface.id);
                         if (q) {
@@ -1275,7 +1340,7 @@ eicon_addcard(int Type, int membase, int irq, char *id)
 #define eicon_init init_module
 #endif
 
-int __init
+int
 eicon_init(void)
 {
 	int card_count = 0;
@@ -1317,10 +1382,9 @@ eicon_init(void)
                 printk(KERN_INFO
                         "eicon: No MCA bus, ISDN-interfaces  not probed.\n");
         } else {
-		if (DebugVar & 8)
-               		printk(KERN_DEBUG
-			       "eicon_mca_find_card, irq=%d.\n", 
-                                irq);
+		eicon_log(card, 8,
+			"eicon_mca_find_card, irq=%d.\n", 
+				irq);
                	if (!eicon_mca_find_card(0, membase, irq, id))
                        card_count++;
         };
@@ -1361,12 +1425,14 @@ cleanup_module(void)
         eicon_card *card = cards;
         eicon_card *last;
         while (card) {
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 #ifdef CONFIG_MCA
         	if (MCA_bus)
                         {
                         mca_mark_as_unused (card->mca_slot);
                         mca_set_adapter_procfn(card->mca_slot, NULL, NULL);
                         };
+#endif /* CONFIG_MCA */
 #endif
                 unregister_card(card); 
                 card = card->next;
@@ -1382,7 +1448,6 @@ cleanup_module(void)
 
 #else /* no module */
 
-#ifdef COMPAT_HAS_NEW_SETUP
 static int __init
 eicon_setup(char *line)
 {
@@ -1391,12 +1456,6 @@ eicon_setup(char *line)
 	char *str;
 
 	str = get_options(line, 4, ints);
-#else
-void __init
-eicon_setup(char *str, int *ints)
-{
-        int i, argc;
-#endif
 
         argc = ints[0];
         i = 1;
@@ -1424,13 +1483,9 @@ eicon_setup(char *str, int *ints)
 #else
 	printk(KERN_INFO "Eicon ISDN active driver setup\n");
 #endif
-#ifdef COMPAT_HAS_NEW_SETUP
 	return(1);
 }
 __setup("eicon=", eicon_setup);
-#else
-}
-#endif
 
 #endif /* MODULE */
 
@@ -1456,10 +1511,9 @@ int eicon_mca_find_card(int type,          /* type-idx of eicon-card          */
 {
 	int j, curr_slot = 0;
 
-	if (DebugVar & 8)
-        	printk(KERN_DEBUG
-                       "eicon_mca_find_card type: %d, membase: %#x, irq %d \n",
-                       type, membase, irq);
+       	eicon_log(card, 8,
+		"eicon_mca_find_card type: %d, membase: %#x, irq %d \n",
+		type, membase, irq);
 	/* find a no-driver-assigned eicon card                               */
 	for (j=0; eicon_mca_adapters[j].adf_id != 0; j++) 
 		{
@@ -1524,11 +1578,10 @@ int eicon_mca_probe(int slot,  /* slot-nr where the card was detected         */
 	int irq_array1[]={3,4,0,0,2,10,11,12};
 
         adf_pos0 = mca_read_stored_pos(slot,2);
-	if (DebugVar & 8)
-		printk(KERN_DEBUG
-                       "eicon_mca_probe irq=%d, membase=%d\n", 
-                        irq,
-                        membase);
+	eicon_log(card, 8,
+		"eicon_mca_probe irq=%d, membase=%d\n", 
+		irq,
+		membase);
 	switch (a_idx) {
 		case 0:                /* P/2-Adapter (== PRI/S2M ? )         */
 			cards_membase= 0xC0000+((adf_pos0>>4)*0x4000);
@@ -1542,7 +1595,7 @@ int eicon_mca_probe(int slot,  /* slot-nr where the card was detected         */
 			if (irq == -1) { 
 				irq = cards_irq;
 			} else {
-				if (irq != irq)
+				if (irq != cards_irq)
 					return ENODEV;
 			};
 			cards_io= 0xC00 + ((adf_pos0>>4)*0x10);
@@ -1575,7 +1628,7 @@ int eicon_mca_probe(int slot,  /* slot-nr where the card was detected         */
 			if (irq == -1) { 
 				irq = cards_irq;
 			} else {
-				if (irq != irq)
+				if (irq != cards_irq)
 					return ENODEV;
 			};
 			type = 0; 
@@ -1591,8 +1644,12 @@ int eicon_mca_probe(int slot,  /* slot-nr where the card was detected         */
         	mca_mark_as_used(slot);
 		cards->mca_slot = slot; 
 		/* card->io noch setzen  oder ?? */
-		if (DebugVar & 8)
-			printk("eicon_addcard: erfolgreich fuer slot: %d.\n", 
+		cards->mca_io = cards_io;
+		cards->hwif.isa.io = cards_io;
+		/* reset card */
+		outb_p(0,cards_io+1);
+
+		eicon_log(card, 8, "eicon_addcard: successful for slot # %d.\n", 
 			cards->mca_slot+1);
 		return  0 ; /* eicon_addcard hat eine Karte zugefuegt */
 	} else {
diff --git a/drivers/isdn/eicon/eicon_pci.c b/drivers/isdn/eicon/eicon_pci.c
index c1919e9f810c4f432259c3da3a1f81de14148905..5c96302cb80e2795bc2c114b6aa813d534a386ad 100644
--- a/drivers/isdn/eicon/eicon_pci.c
+++ b/drivers/isdn/eicon/eicon_pci.c
@@ -152,8 +152,8 @@ int eicon_pci_find_card(char *ID)
           aparms->type = EICON_CTYPE_MAESTRA;
 
           aparms->irq = pdev->irq;
-          preg = get_pcibase(pdev, 2) & 0xfffffffc;
-          pcfg = get_pcibase(pdev, 1) & 0xffffff80;
+          preg = pdev->resource[ 2].start & 0xfffffffc;
+          pcfg = pdev->resource[ 1].start & 0xffffff80;
 
 #ifdef EICON_PCI_DEBUG
           printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq);
@@ -174,9 +174,9 @@ int eicon_pci_find_card(char *ID)
          printk(KERN_INFO "Eicon: DIVA Server PRI/PCI detected !\n");
           aparms->type = EICON_CTYPE_MAESTRAP; /*includes 9M,30M*/
           aparms->irq = pdev->irq;
-          pram = get_pcibase(pdev, 0) & 0xfffff000;
-          preg = get_pcibase(pdev, 2) & 0xfffff000;
-          pcfg = get_pcibase(pdev, 4) & 0xfffff000;
+          pram = pdev->resource[ 0].start & 0xfffff000;
+          preg = pdev->resource[ 2].start & 0xfffff000;
+          pcfg = pdev->resource[ 4].start & 0xfffff000;
 
 #ifdef EICON_PCI_DEBUG
           printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq);
diff --git a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile
index 051df618271607af5843551450818571a2982c69..e37d9c404d2d53ac92c52396d060c8da6601047e 100644
--- a/drivers/isdn/hisax/Makefile
+++ b/drivers/isdn/hisax/Makefile
@@ -30,6 +30,8 @@ ISAR_OBJ :=
 HFC_OBJ :=
 HFC_2BDS0 :=
 JADE_OBJ :=
+W6692_OBJ :=
+
 ifeq ($(CONFIG_HISAX_16_0),y)
 	 O_OBJS += teles0.o
 	 ISAC_OBJ := isac.o
@@ -170,6 +172,10 @@ ifeq ($(CONFIG_HISAX_GAZEL),y)
 	 HSCX_OBJ := hscx.o
 endif
 
+ifeq ($(CONFIG_HISAX_W6692),y)
+	W6692_OBJ := w6692.o
+endif
+
 # ifeq ($(CONFIG_HISAX_TESTEMU),y)
 #	 O_OBJS += testemu.o
 # endif
@@ -179,7 +185,7 @@ ifeq ($(ISAC_OBJ), isac.o)
 endif
 
 O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(ISAR_OBJ) $(JADE_OBJ)
-O_OBJS += $(HFC_OBJ) $(HFC_2BDS0)
+O_OBJS += $(HFC_OBJ) $(HFC_2BDS0) $(W6692_OBJ)
 OX_OBJS += config.o
 
 O_TARGET :=
diff --git a/drivers/isdn/hisax/amd7930.c b/drivers/isdn/hisax/amd7930.c
index 7bcc8827c08265c7038bd9afb2134bac20081271..2770aa65e1f045fc356cc3206583f6dc2bd2b1d7 100644
--- a/drivers/isdn/hisax/amd7930.c
+++ b/drivers/isdn/hisax/amd7930.c
@@ -749,8 +749,8 @@ amd7930_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 	return(0);
 }
 
-int __init
-setup_amd7930(struct IsdnCard *card)
+__initfunc(int
+setup_amd7930(struct IsdnCard *card))
 {
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
diff --git a/drivers/isdn/hisax/arcofi.c b/drivers/isdn/hisax/arcofi.c
index 9e582641d30e8f5938133675754521e7c5597c98..e8abc9de2d0add37f959974e6729794f8e352b99 100644
--- a/drivers/isdn/hisax/arcofi.c
+++ b/drivers/isdn/hisax/arcofi.c
@@ -154,8 +154,6 @@ init_arcofi(struct IsdnCardState *cs) {
 	cs->dc.isac.arcofitimer.function = (void *) arcofi_timer;
 	cs->dc.isac.arcofitimer.data = (long) cs;
 	init_timer(&cs->dc.isac.arcofitimer);
-#ifdef COMPAT_HAS_NEW_WAITQ
 	init_waitqueue_head(&cs->dc.isac.arcofi_wait);
-#endif
 	test_and_set_bit(HW_ARCOFI, &cs->HW_Flags);
 }
diff --git a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c
index 06d8b59d059ab5ac50da5112174c7506a3f47dbc..10657ad63afe23d467b5ff7c26e6876608d9d9b0 100644
--- a/drivers/isdn/hisax/asuscom.c
+++ b/drivers/isdn/hisax/asuscom.c
@@ -1,4 +1,4 @@
-/* $Id: asuscom.c,v 1.7 1999/07/12 21:04:53 keil Exp $
+/* $Id: asuscom.c,v 1.8 1999/09/04 06:20:05 keil Exp $
 
  * asuscom.c     low level stuff for ASUSCOM NETWORK INC. ISDNLink cards
  *
@@ -8,6 +8,9 @@
  *
  *
  * $Log: asuscom.c,v $
+ * Revision 1.8  1999/09/04 06:20:05  keil
+ * Changes from kernel set_current_state()
+ *
  * Revision 1.7  1999/07/12 21:04:53  keil
  * fix race in IRQ handling
  * added watchdog for lost IRQs
@@ -39,7 +42,7 @@
 
 extern const char *CardType[];
 
-const char *Asuscom_revision = "$Revision: 1.7 $";
+const char *Asuscom_revision = "$Revision: 1.8 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -288,13 +291,13 @@ reset_asuscom(struct IsdnCardState *cs)
 		byteout(cs->hw.asus.adr, ASUS_RESET);	/* Reset On */
 	save_flags(flags);
 	sti();
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((10*HZ)/1000);
 	if (cs->subtyp == ASUS_IPAC)
 		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x0);
 	else
 		byteout(cs->hw.asus.adr, 0);	/* Reset Off */
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((10*HZ)/1000);
 	if (cs->subtyp == ASUS_IPAC) {
 		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_CONF, 0x0);
@@ -326,8 +329,8 @@ Asus_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 	return(0);
 }
 
-int __init
-setup_asuscom(struct IsdnCard *card)
+__initfunc(int
+setup_asuscom(struct IsdnCard *card))
 {
 	int bytecnt;
 	struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c
index f96db367510374b26738a42d8519d3308cd23df3..55df36f0f73827aa06adb76a5463f78c3871ccfd 100644
--- a/drivers/isdn/hisax/avm_a1.c
+++ b/drivers/isdn/hisax/avm_a1.c
@@ -227,8 +227,8 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 	return(0);
 }
 
-int __init
-setup_avm_a1(struct IsdnCard *card)
+__initfunc(int
+setup_avm_a1(struct IsdnCard *card))
 {
 	u_char val;
 	struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/avm_a1p.c b/drivers/isdn/hisax/avm_a1p.c
index 862829ab3bdf83f287ea398a4dd279e4982c2003..76382c3722b755341940133d865edba191c7b016 100644
--- a/drivers/isdn/hisax/avm_a1p.c
+++ b/drivers/isdn/hisax/avm_a1p.c
@@ -1,4 +1,4 @@
-/* $Id: avm_a1p.c,v 2.4 1999/07/12 21:04:55 keil Exp $
+/* $Id: avm_a1p.c,v 2.5 1999/09/01 08:26:34 calle Exp $
  *
  * avm_a1p.c    low level stuff for the following AVM cards:
  *              A1 PCMCIA
@@ -8,6 +8,9 @@
  * Author       Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: avm_a1p.c,v $
+ * Revision 2.5  1999/09/01 08:26:34  calle
+ * Patch from Daniel Beichl <dani@ecomag.net> to make A1 PCMCIA work again.
+ *
  * Revision 2.4  1999/07/12 21:04:55  keil
  * fix race in IRQ handling
  * added watchdog for lost IRQs
@@ -71,7 +74,7 @@
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
 
-static const char *avm_revision = "$Revision: 2.4 $";
+static const char *avm_revision = "$Revision: 2.5 $";
 
 static inline u_char
 ReadISAC(struct IsdnCardState *cs, u_char offset)
@@ -245,6 +248,7 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 			return 0;
 
 		case CARD_INIT:
+			byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE);
 			clear_pending_isac_ints(cs);
 			clear_pending_hscx_ints(cs);
 			inithscxisac(cs, 1);
@@ -262,8 +266,8 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 	return 0;
 }
 
-int __init
-setup_avm_a1_pcmcia(struct IsdnCard *card)
+__initfunc(int
+setup_avm_a1_pcmcia(struct IsdnCard *card))
 {
 	u_char model, vers;
 	struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
index cd293f1473050f91cca643c279494c4718afa4f7..f343bfb5ae24146cc3ad96611b7427ca06fb3010 100644
--- a/drivers/isdn/hisax/avm_pci.c
+++ b/drivers/isdn/hisax/avm_pci.c
@@ -1,4 +1,4 @@
-/* $Id: avm_pci.c,v 1.11 1999/08/11 21:01:18 keil Exp $
+/* $Id: avm_pci.c,v 1.12 1999/09/04 06:20:05 keil Exp $
 
  * avm_pci.c    low level stuff for AVM Fritz!PCI and ISA PnP isdn cards
  *              Thanks to AVM, Berlin for informations
@@ -7,6 +7,9 @@
  *
  *
  * $Log: avm_pci.c,v $
+ * Revision 1.12  1999/09/04 06:20:05  keil
+ * Changes from kernel set_current_state()
+ *
  * Revision 1.11  1999/08/11 21:01:18  keil
  * new PCI codefix
  *
@@ -50,13 +53,10 @@
 #include "isac.h"
 #include "isdnl1.h"
 #include <linux/pci.h>
-#ifndef COMPAT_HAS_NEW_PCI
-#include <linux/bios32.h>
-#endif
 #include <linux/interrupt.h>
 
 extern const char *CardType[];
-static const char *avm_pci_rev = "$Revision: 1.11 $";
+static const char *avm_pci_rev = "$Revision: 1.12 $";
 
 #define  AVM_FRITZ_PCI		1
 #define  AVM_FRITZ_PNP		2
@@ -482,7 +482,7 @@ HDLC_irq(struct BCState *bcs, u_int stat) {
 				if (bcs->st->lli.l1writewakeup &&
 					(PACKET_NOACK != bcs->tx_skb->pkt_type))
 					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hdlc.count);
-				idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+				dev_kfree_skb(bcs->tx_skb);
 				bcs->hw.hdlc.count = 0;
 				bcs->tx_skb = NULL;
 			}
@@ -609,7 +609,7 @@ close_hdlcstate(struct BCState *bcs)
 		discard_queue(&bcs->rqueue);
 		discard_queue(&bcs->squeue);
 		if (bcs->tx_skb) {
-			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			dev_kfree_skb(bcs->tx_skb);
 			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		}
@@ -734,11 +734,11 @@ reset_avmpcipnp(struct IsdnCardState *cs)
 	save_flags(flags);
 	sti();
 	outb(AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER, cs->hw.avm.cfg_reg + 2);
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
 	outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2);
 	outb(AVM_STATUS1_ENA_IOM | cs->irq, cs->hw.avm.cfg_reg + 3);
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
 	printk(KERN_INFO "AVM PCI/PnP: S1 %x\n", inb(cs->hw.avm.cfg_reg + 3));
 }
@@ -773,14 +773,10 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 	return(0);
 }
 
-#ifdef COMPAT_HAS_NEW_PCI
 static 	struct pci_dev *dev_avm __initdata = NULL;
-#else
-static  int pci_index __initdata = 0;
-#endif
 
-int __init
-setup_avm_pcipnp(struct IsdnCard *card)
+__initfunc(int
+setup_avm_pcipnp(struct IsdnCard *card))
 {
 	u_int val, ver;
 	struct IsdnCardState *cs = card->cs;
@@ -796,7 +792,6 @@ setup_avm_pcipnp(struct IsdnCard *card)
 		cs->subtyp = AVM_FRITZ_PNP;
 	} else {
 #if CONFIG_PCI
-#ifdef COMPAT_HAS_NEW_PCI
 		if (!pci_present()) {
 			printk(KERN_ERR "FritzPCI: no PCI bus present\n");
 			return(0);
@@ -808,7 +803,7 @@ setup_avm_pcipnp(struct IsdnCard *card)
 				printk(KERN_WARNING "FritzPCI: No IRQ for PCI card found\n");
 				return(0);
 			}
-			cs->hw.avm.cfg_reg = get_pcibase(dev_avm, 1) &
+			cs->hw.avm.cfg_reg = dev_avm->resource[ 1].start &
 				PCI_BASE_ADDRESS_IO_MASK; 
 			if (!cs->hw.avm.cfg_reg) {
 				printk(KERN_WARNING "FritzPCI: No IO-Adr for PCI card found\n");
@@ -819,36 +814,6 @@ setup_avm_pcipnp(struct IsdnCard *card)
 			printk(KERN_WARNING "FritzPCI: No PCI card found\n");
 			return(0);
 		}
-#else
-		for (; pci_index < 255; pci_index++) {
-			unsigned char pci_bus, pci_device_fn;
-			unsigned int ioaddr;
-			unsigned char irq;
-
-			if (pcibios_find_device (PCI_VENDOR_AVM,
-				PCI_FRITZPCI_ID, pci_index,
-				&pci_bus, &pci_device_fn) != 0) {
-				continue;
-			}
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-				PCI_INTERRUPT_LINE, &irq);
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-				PCI_BASE_ADDRESS_1, &ioaddr);
-			cs->irq = irq;
-			cs->hw.avm.cfg_reg = ioaddr & PCI_BASE_ADDRESS_IO_MASK;
-			if (!cs->hw.avm.cfg_reg) {
-				printk(KERN_WARNING "FritzPCI: No IO-Adr for PCI card found\n");
-				return(0);
-			}
-			cs->subtyp = AVM_FRITZ_PCI;
-			break;
-		}
-		if (pci_index == 255) {
-			printk(KERN_WARNING "FritzPCI: No PCI card found\n");
-			return(0);
-		}
-		pci_index++;
-#endif /* COMPAT_HAS_NEW_PCI */
 		cs->irq_flags |= SA_SHIRQ;
 #else
 		printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n");
diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
index 57d99b43669c33e527f5bde421201552c9810e5d..cb999972cc2a56583f10f1dab0b82404fc559561 100644
--- a/drivers/isdn/hisax/bkm_a4t.c
+++ b/drivers/isdn/hisax/bkm_a4t.c
@@ -1,4 +1,4 @@
-/* $Id: bkm_a4t.c,v 1.7 1999/08/22 20:26:55 calle Exp $
+/* $Id: bkm_a4t.c,v 1.8 1999/09/04 06:20:05 keil Exp $
  * bkm_a4t.c    low level stuff for T-Berkom A4T
  *              derived from the original file sedlbauer.c
  *              derived from the original file niccy.c
@@ -7,6 +7,9 @@
  * Author       Roland Klabunde (R.Klabunde@Berkom.de)
  *
  * $Log: bkm_a4t.c,v $
+ * Revision 1.8  1999/09/04 06:20:05  keil
+ * Changes from kernel set_current_state()
+ *
  * Revision 1.7  1999/08/22 20:26:55  calle
  * backported changes from kernel 2.3.14:
  * - several #include "config.h" gone, others come.
@@ -42,13 +45,10 @@
 #include "isdnl1.h"
 #include "bkm_ax.h"
 #include <linux/pci.h>
-#ifndef COMPAT_HAS_NEW_PCI
-#include <linux/bios32.h>
-#endif
 
 extern const char *CardType[];
 
-const char *bkm_a4t_revision = "$Revision: 1.7 $";
+const char *bkm_a4t_revision = "$Revision: 1.8 $";
 
 
 static inline u_char
@@ -231,11 +231,11 @@ reset_bkm(struct IsdnCardState *cs)
 		sti();
 		/* Issue the I20 soft reset     */
 		pI20_Regs->i20SysControl = 0xFF;	/* all in */
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout((10 * HZ) / 1000);
 		/* Remove the soft reset */
 		pI20_Regs->i20SysControl = sysRESET | 0xFF;
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout((10 * HZ) / 1000);
 		/* Set our configuration */
 		pI20_Regs->i20SysControl = sysRESET | sysCFG;
@@ -246,14 +246,14 @@ reset_bkm(struct IsdnCardState *cs)
 		    g_A4T_ISAC_RES |
 		    g_A4T_JADE_BOOTR |
 		    g_A4T_ISAR_BOOTR;
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout((10 * HZ) / 1000);
 
 		/* Remove RESET state from ISDN */
 		pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES |
 						g_A4T_JADE_RES |
 						g_A4T_ISAR_RES);
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout((10 * HZ) / 1000);
 		restore_flags(flags);
 	}
@@ -288,23 +288,16 @@ BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 	return (0);
 }
 
-#ifdef COMPAT_HAS_NEW_PCI
 static struct pci_dev *dev_a4t __initdata = NULL;
-#else
-static int pci_index __initdata = 0;
-#endif
 
-int __init
-	   setup_bkm_a4t(struct IsdnCard *card)
+__initfunc(int
+	   setup_bkm_a4t(struct IsdnCard *card))
 {
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 	u_int pci_memaddr = 0, found = 0;
 	I20_REGISTER_FILE *pI20_Regs;
 #if CONFIG_PCI
-#ifndef COMPAT_HAS_NEW_PCI
-	u_char pci_bus, pci_device_fn, pci_irq = 0;
-#endif
 #endif
 
 	strcpy(tmp, bkm_a4t_revision);
@@ -315,7 +308,6 @@ int __init
 		return (0);
 
 #if CONFIG_PCI
-#ifdef COMPAT_HAS_NEW_PCI
 	if (!pci_present()) {
 		printk(KERN_ERR "bkm_a4t: no PCI bus present\n");
 		return (0);
@@ -327,40 +319,14 @@ int __init
 			&sub_sys_id);
 		if (sub_sys_id == ((A4T_SUBSYS_ID << 16) | A4T_SUBVEN_ID)) {
 			found = 1;
-			pci_memaddr = get_pcibase(dev_a4t, 0);
+			pci_memaddr = dev_a4t->resource[ 0].start;
 			cs->irq = dev_a4t->irq;
 		}
 	}
-#else
-	for (; pci_index < 0xff; pci_index++) {
-		if (pcibios_find_device(I20_VENDOR_ID,
-				I20_DEVICE_ID,
-				pci_index,
-				&pci_bus,
-				&pci_device_fn) == PCIBIOS_SUCCESSFUL) {
-			u_int sub_sys_id = 0;
-
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-				PCI_SUBSYSTEM_VENDOR_ID, &sub_sys_id);
-			if (sub_sys_id == ((A4T_SUBSYS_ID << 16) | A4T_SUBVEN_ID)) {
-				found = 1;
-				pcibios_read_config_byte(pci_bus, pci_device_fn,
-					   PCI_INTERRUPT_LINE, &pci_irq);
-				cs->irq = pci_irq;
-				pcibios_read_config_dword(pci_bus, pci_device_fn,
-				       PCI_BASE_ADDRESS_0, &pci_memaddr);
-				break;
-			}
-		}
-	}
-#endif				/* COMPAT_HAS_NEW_PCI */
 	if (!found) {
 		printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
 		return (0);
 	}
-#ifndef COMPAT_HAS_NEW_PCI
-	pci_index++;
-#endif
 	if (!cs->irq) {		/* IRQ range check ?? */
 		printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]);
 		return (0);
diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c
index e32c4544a65f3583a227acf550e4b058aa524bc3..fda6c213c0fb602c2cb8bcc0d829c4077631cd4d 100644
--- a/drivers/isdn/hisax/bkm_a8.c
+++ b/drivers/isdn/hisax/bkm_a8.c
@@ -1,4 +1,4 @@
-/* $Id: bkm_a8.c,v 1.7 1999/08/22 20:26:58 calle Exp $
+/* $Id: bkm_a8.c,v 1.8 1999/09/04 06:20:05 keil Exp $
  * bkm_a8.c     low level stuff for Scitel Quadro (4*S0, passive)
  *              derived from the original file sedlbauer.c
  *              derived from the original file niccy.c
@@ -7,6 +7,9 @@
  * Author       Roland Klabunde (R.Klabunde@Berkom.de)
  *
  * $Log: bkm_a8.c,v $
+ * Revision 1.8  1999/09/04 06:20:05  keil
+ * Changes from kernel set_current_state()
+ *
  * Revision 1.7  1999/08/22 20:26:58  calle
  * backported changes from kernel 2.3.14:
  * - several #include "config.h" gone, others come.
@@ -41,15 +44,12 @@
 #include "isdnl1.h"
 #include "bkm_ax.h"
 #include <linux/pci.h>
-#ifndef COMPAT_HAS_NEW_PCI
-#include <linux/bios32.h>
-#endif
 
 #define	ATTEMPT_PCI_REMAPPING	/* Required for PLX rev 1 */
 
 extern const char *CardType[];
 
-const char sct_quadro_revision[] = "$Revision: 1.7 $";
+const char sct_quadro_revision[] = "$Revision: 1.8 $";
 
 /* To survive the startup phase */
 typedef struct {
@@ -298,13 +298,13 @@ reset_bkm(struct IsdnCardState *cs)
 
 			save_flags(flags);
 			sti();
-			current->state = TASK_INTERRUPTIBLE;
+			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout((10 * HZ) / 1000);
 
 			/* Remove the soft reset */
 			wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) | 4));
 
-			current->state = TASK_INTERRUPTIBLE;
+			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout((10 * HZ) / 1000);
 			restore_flags(flags);
 		}
@@ -341,14 +341,10 @@ BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 	return (0);
 }
 
-#ifdef COMPAT_HAS_NEW_PCI
 static struct pci_dev *dev_a8 __initdata = NULL;
-#else
-static int pci_index __initdata = 0;
-#endif
 
-int __init
-	   setup_sct_quadro(struct IsdnCard *card)
+__initfunc(int
+	   setup_sct_quadro(struct IsdnCard *card))
 {
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
@@ -372,7 +368,6 @@ int __init
 		printk(KERN_WARNING "HiSax: %s: Invalid subcontroller in configuration, default to 1\n",
 		       CardType[card->typ]);
 #if CONFIG_PCI
-#ifdef COMPAT_HAS_NEW_PCI
 	if (!pci_present()) {
 		printk(KERN_ERR "bkm_a4t: no PCI bus present\n");
 		return (0);
@@ -384,46 +379,18 @@ int __init
 			&sub_sys_id);
 		if (sub_sys_id == ((SCT_SUBSYS_ID << 16) | SCT_SUBVEN_ID)) {
 			found = 1;
-			pci_ioaddr1 = get_pcibase(dev_a8, 1);
+			pci_ioaddr1 = dev_a8->resource[ 1].start;
 			pci_irq = dev_a8->irq;
 			pci_bus = dev_a8->bus->number;
 			pci_device_fn = dev_a8->devfn;
 		}
 	}
-#else
-	for (; pci_index < 0xff; pci_index++) {
-		if (pcibios_find_device(
-				PLX_VENDOR_ID,
-				PLX_DEVICE_ID,
-				pci_index,
-				&pci_bus,
-				&pci_device_fn) == PCIBIOS_SUCCESSFUL) {
-			
-			u_int sub_sys_id = 0;
-
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-				PCI_SUBSYSTEM_VENDOR_ID, &sub_sys_id);
-			if (sub_sys_id == ((SCT_SUBSYS_ID << 16) | SCT_SUBVEN_ID)) {
-				found = 1;
-				pcibios_read_config_byte(pci_bus, pci_device_fn,
-					PCI_INTERRUPT_LINE, &pci_irq);
-				pcibios_read_config_dword(pci_bus, pci_device_fn,
-					PCI_BASE_ADDRESS_1, &pci_ioaddr1);
-				cs->irq = pci_irq;
-				break;
-			}
-		}
-	}
-#endif /* COMPAT_HAS_NEW_PCI */
 	if (!found) {
 		printk(KERN_WARNING "HiSax: %s (%s): Card not found\n",
 		       CardType[card->typ],
 		       sct_quadro_subtypes[cs->subtyp]);
 		return (0);
 	}
-#ifndef COMPAT_HAS_NEW_PCI
-	pci_index++; /* need for more as one card */
-#endif
 	if (!pci_irq) {		/* IRQ range check ?? */
 		printk(KERN_WARNING "HiSax: %s (%s): No IRQ\n",
 		       CardType[card->typ],
@@ -445,9 +412,7 @@ int __init
 		pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK;
 		pcibios_write_config_dword(pci_bus, pci_device_fn,
 			PCI_BASE_ADDRESS_1, pci_ioaddr1);
-#ifdef COMPAT_HAS_NEW_PCI
-		get_pcibase(dev_a8, 1) = pci_ioaddr1;
-#endif /* COMPAT_HAS_NEW_PCI */
+		dev_a8->resource[ 1].start = pci_ioaddr1;
 	}
 /* End HACK */
 #endif
diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c
index ce0428a46eaa295a4f0a31a2e19797f9a66b5b77..e4c26d9debd2c3a08aaf68b52d0f5c8c81333997 100644
--- a/drivers/isdn/hisax/callc.c
+++ b/drivers/isdn/hisax/callc.c
@@ -1,4 +1,4 @@
-/* $Id: callc.c,v 2.34 1999/08/25 20:02:34 werner Exp $
+/* $Id: callc.c,v 2.39 1999/10/14 20:25:28 keil Exp $
 
  * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
@@ -11,6 +11,21 @@
  *              Fritz Elfert
  *
  * $Log: callc.c,v $
+ * Revision 2.39  1999/10/14 20:25:28  keil
+ * add a statistic for error monitoring
+ *
+ * Revision 2.38  1999/10/11 22:16:27  keil
+ * Suspend/Resume is possible without explicit ID too
+ *
+ * Revision 2.37  1999/09/20 19:49:47  keil
+ * Fix wrong init of PStack
+ *
+ * Revision 2.36  1999/09/20 12:13:13  keil
+ * Fix hang if no protocol was selected
+ *
+ * Revision 2.35  1999/09/04 06:20:05  keil
+ * Changes from kernel set_current_state()
+ *
  * Revision 2.34  1999/08/25 20:02:34  werner
  * Changed return values for stat_icall(w) from 3->4 and 4->5 because of conflicts
  * with existing software definitions. (PtP incomplete called party number)
@@ -145,15 +160,10 @@
 #include "../avmb1/capicmd.h"  /* this should be moved in a common place */
 
 #ifdef MODULE
-#ifdef COMPAT_HAS_NEW_SYMTAB
 #define MOD_USE_COUNT ( GET_USE_COUNT (&__this_module))
-#else
-extern long mod_use_count_;
-#define MOD_USE_COUNT mod_use_count_
-#endif /* COMPAT_HAS_NEW_SYMTAB */
 #endif	/* MODULE */
 
-const char *lli_revision = "$Revision: 2.34 $";
+const char *lli_revision = "$Revision: 2.39 $";
 
 extern struct IsdnCard cards[];
 extern int nrcards;
@@ -209,7 +219,7 @@ discard_queue(struct sk_buff_head *q)
 	int ret=0;
 
 	while ((skb = skb_dequeue(q))) {
-		idev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb(skb);
 		ret++;
 	}
 	return(ret);
@@ -1121,13 +1131,38 @@ dchan_l3l4(struct PStack *st, int pr, void *arg)
 	}
 }
 
+static void
+dummy_pstack(struct PStack *st, int pr, void *arg) {
+	printk(KERN_WARNING"call to dummy_pstack pr=%04x arg %lx\n", pr, (long)arg);
+}
+
+static void
+init_PStack(struct PStack **stp) {
+	*stp = kmalloc(sizeof(struct PStack), GFP_ATOMIC);
+	(*stp)->next = NULL;
+	(*stp)->l1.l1l2 = dummy_pstack;
+	(*stp)->l1.l1hw = dummy_pstack;
+	(*stp)->l1.l1tei = dummy_pstack;
+	(*stp)->l2.l2tei = dummy_pstack;
+	(*stp)->l2.l2l1 = dummy_pstack;
+	(*stp)->l2.l2l3 = dummy_pstack;
+	(*stp)->l3.l3l2 = dummy_pstack;
+        (*stp)->l3.l3ml3 = dummy_pstack;
+	(*stp)->l3.l3l4 = dummy_pstack;
+	(*stp)->lli.l4l3 = dummy_pstack;
+	(*stp)->ma.layer = dummy_pstack;
+}
+
 static void
 init_d_st(struct Channel *chanp)
 {
-	struct PStack *st = chanp->d_st;
+	struct PStack *st;
 	struct IsdnCardState *cs = chanp->cs;
 	char tmp[16];
 
+	init_PStack(&chanp->d_st);
+	st = chanp->d_st;
+	st->next = NULL;
 	HiSax_addlist(cs, st);
 	setstack_HiSax(st, cs);
 	st->l2.sap = 0;
@@ -1165,28 +1200,6 @@ callc_debug(struct FsmInst *fi, char *fmt, ...)
 	va_end(args);
 }
 
-static void
-dummy_pstack(struct PStack *st, int pr, void *arg) {
-	printk(KERN_WARNING"call to dummy_pstack pr=%04x arg %lx\n", pr, (long)arg);
-}
-
-static void
-init_PStack(struct PStack **stp) {
-	*stp = kmalloc(sizeof(struct PStack), GFP_ATOMIC);
-	(*stp)->next = NULL;
-	(*stp)->l1.l1l2 = dummy_pstack;
-	(*stp)->l1.l1hw = dummy_pstack;
-	(*stp)->l1.l1tei = dummy_pstack;
-	(*stp)->l2.l2tei = dummy_pstack;
-	(*stp)->l2.l2l1 = dummy_pstack;
-	(*stp)->l2.l2l3 = dummy_pstack;
-	(*stp)->l3.l3l2 = dummy_pstack;
-        (*stp)->l3.l3ml3 = dummy_pstack;
-	(*stp)->l3.l3l4 = dummy_pstack;
-	(*stp)->lli.l4l3 = dummy_pstack;
-	(*stp)->ma.layer = dummy_pstack;
-}
-
 static void
 init_chan(int chan, struct IsdnCardState *csta)
 {
@@ -1209,10 +1222,6 @@ init_chan(int chan, struct IsdnCardState *csta)
 	FsmInitTimer(&chanp->fi, &chanp->dial_timer);
 	FsmInitTimer(&chanp->fi, &chanp->drel_timer);
 	if (!chan || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) {
-		init_PStack(&chanp->d_st);
-		if (chan)
-			csta->channel->d_st->next = chanp->d_st;
-		chanp->d_st->next = NULL;
 		init_d_st(chanp);
 	} else {
 		chanp->d_st = csta->channel->d_st;
@@ -1289,7 +1298,7 @@ lldata_handler(struct PStack *st, int pr, void *arg)
 			if (chanp->data_open)
 				chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb);
 			else {
-				idev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb(skb);
 			}
 			break;
 		case (DL_ESTABLISH | INDICATION):
@@ -1319,7 +1328,7 @@ lltrans_handler(struct PStack *st, int pr, void *arg)
 				chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb);
 			else {
 				link_debug(chanp, 0, "channel not open");
-				idev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb(skb);
 			}
 			break;
 		case (PH_ACTIVATE | INDICATION):
@@ -1426,7 +1435,7 @@ leased_l4l3(struct PStack *st, int pr, void *arg)
 	switch (pr) {
 		case (DL_DATA | REQUEST):
 			link_debug(chanp, 0, "leased line d-channel DATA");
-			idev_kfree_skb(skb, FREE_READ);
+			dev_kfree_skb(skb);
 			break;
 		case (DL_ESTABLISH | REQUEST):
 			st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL);
@@ -1450,7 +1459,7 @@ leased_l1l2(struct PStack *st, int pr, void *arg)
 	switch (pr) {
 		case (PH_DATA | INDICATION):
 			link_debug(chanp, 0, "leased line d-channel DATA");
-			idev_kfree_skb(skb, FREE_READ);
+			dev_kfree_skb(skb);
 			break;
 		case (PH_ACTIVATE | INDICATION):
 		case (PH_ACTIVATE | CONFIRM):
@@ -1474,11 +1483,6 @@ leased_l1l2(struct PStack *st, int pr, void *arg)
 	}
 }
 
-static void
-channel_report(struct Channel *chanp)
-{
-}
-
 static void
 distr_debug(struct IsdnCardState *csta, int debugflags)
 {
@@ -1512,7 +1516,6 @@ capi_debug(struct Channel *chanp, capi_msg *cm)
 {
 	char *t = tmpbuf;
 
-	t += sprintf(tmpbuf, "%d CAPIMSG", chanp->chan);
 	t += QuickHex(t, (u_char *)cm, (cm->Length>50)? 50: cm->Length);
 	t--;
 	*t= 0;
@@ -1529,20 +1532,16 @@ lli_got_fac_req(struct Channel *chanp, capi_msg *cm) {
 		return;
 	switch(cm->para[3]) {
 		case 4: /* Suspend */
-			if (cm->para[5]) {
-				strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1);
-				FsmEvent(&chanp->fi, EV_SUSPEND, cm);
-			}
+			strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1);
+			FsmEvent(&chanp->fi, EV_SUSPEND, cm);
 			break;
 		case 5: /* Resume */
-			if (cm->para[5]) {
-				strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1);
-				if (chanp->fi.state == ST_NULL) {
-					FsmEvent(&chanp->fi, EV_RESUME, cm);
-				} else {
-					FsmDelTimer(&chanp->dial_timer, 72);
-					FsmAddTimer(&chanp->dial_timer, 80, EV_RESUME, cm, 73);
-				}
+			strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1);
+			if (chanp->fi.state == ST_NULL) {
+				FsmEvent(&chanp->fi, EV_RESUME, cm);
+			} else {
+				FsmDelTimer(&chanp->dial_timer, 72);
+				FsmAddTimer(&chanp->dial_timer, 80, EV_RESUME, cm, 73);
 			}
 			break;
 	}
@@ -1694,9 +1693,8 @@ HiSax_command(isdn_ctrl * ic)
 		case (ISDN_CMD_IOCTL):
 			switch (ic->arg) {
 				case (0):
-					HiSax_reportcard(csta->cardnr);
-					for (i = 0; i < 2; i++)
-						channel_report(&csta->channel[i]);
+					num = *(unsigned int *) ic->parm.num;
+					HiSax_reportcard(csta->cardnr, num);
 					break;
 				case (1):
 					num = *(unsigned int *) ic->parm.num;
@@ -1904,7 +1902,7 @@ HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb)
 				chanp->bcs->tx_cnt += len;
 				st->l2.l2l1(st, PH_DATA | REQUEST, nskb);
 			}
-			idev_kfree_skb(skb, FREE_WRITE);
+			dev_kfree_skb(skb);
 		} else
 			len = 0;
 		restore_flags(flags);
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index dc0fa46a00a593ccb5268bdccce0799243d240d6..a75810f026ace717519b873de53b8ec4f7f3919d 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -1,10 +1,32 @@
-/* $Id: config.c,v 2.33 1999/08/30 11:57:52 keil Exp $
+/* $Id: config.c,v 2.40 1999/10/30 13:09:45 keil Exp $
 
  * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
  *
  *
  * $Log: config.c,v $
+ * Revision 2.40  1999/10/30 13:09:45  keil
+ * Version 3.3c
+ *
+ * Revision 2.39  1999/10/16 14:44:45  keil
+ * Fix module parm if only NICCY was selected
+ *
+ * Revision 2.38  1999/10/14 20:25:28  keil
+ * add a statistic for error monitoring
+ *
+ * Revision 2.37  1999/09/20 12:11:08  keil
+ * Fix hang if no protocol was selected
+ *
+ * Revision 2.36  1999/09/07 05:43:58  werner
+ *
+ * Added io as parameter 0 for HFC-PCI cards, if manual selection needed.
+ *
+ * Revision 2.35  1999/09/04 06:35:09  keil
+ * Winbond W6692 support
+ *
+ * Revision 2.34  1999/09/04 06:20:06  keil
+ * Changes from kernel set_current_state()
+ *
  * Revision 2.33  1999/08/30 11:57:52  keil
  * Fix broken avm pcmcia
  *
@@ -126,10 +148,7 @@
 #include <linux/stddef.h>
 #include <linux/timer.h>
 #include <linux/config.h>
-#include <linux/isdn_compat.h>
-#ifdef COMPAT_HAS_NEW_SETUP
 #include <linux/init.h>
-#endif
 #include "hisax.h"
 #include <linux/module.h>
 #include <linux/kernel_stat.h>
@@ -182,6 +201,8 @@
  *   33 Scitel Quadro		p0=subcontroller (4*S0, subctrl 1...4)
  *   34	Gazel ISDN cards
  *   35 HFC 2BDS0 PCI           none
+ *   36 Winbond 6692 PCI        none
+ *
  * protocol can be either ISDN_PTYPE_EURO or ISDN_PTYPE_1TR6 or ISDN_PTYPE_NI1
  *
  *
@@ -195,7 +216,7 @@ const char *CardType[] =
  "Compaq ISA", "NETjet", "Teles PCI", "Sedlbauer Speed Star (PCMCIA)",
  "AMD 7930", "NICCY", "S0Box", "AVM A1 (PCMCIA)", "AVM Fritz PnP/PCI",
  "Sedlbauer Speed Fax +", "Siemens I-Surf", "Acer P10", "HST Saphir",
- "Telekom A4T", "Scitel Quadro", "Gazel", "HFC 2BDS0 PCI",
+ "Telekom A4T", "Scitel Quadro", "Gazel", "HFC 2BDS0 PCI", "Winbond 6692",
 };
 
 void HiSax_closecard(int cardnr);
@@ -204,15 +225,7 @@ void HiSax_closecard(int cardnr);
 #define DEFAULT_CARD ISDN_CTYPE_ELSA
 #define DEFAULT_CFG {0,0,0,0}
 int elsa_init_pcmcia(void*, int, int*, int);
-#ifdef COMPAT_HAS_NEW_SYMTAB
 EXPORT_SYMBOL(elsa_init_pcmcia);
-#else
-static struct symbol_table hisax_syms_elsa = {
-#include <linux/symtab_begin.h>
-	X(elsa_init_pcmcia),
-#include <linux/symtab_end.h>
-};
-#endif /* COMPAT_HAS_NEW_SYMTAB */
 #endif /* CONFIG_HISAX_ELSA */
 
 #ifdef CONFIG_HISAX_AVM_A1
@@ -228,17 +241,8 @@ static struct symbol_table hisax_syms_elsa = {
 #define DEFAULT_CARD ISDN_CTYPE_A1_PCMCIA
 #define DEFAULT_CFG {11,0x170,0,0}
 int avm_a1_init_pcmcia(void*, int, int*, int);
-#ifdef COMPAT_HAS_NEW_SYMTAB
 EXPORT_SYMBOL(avm_a1_init_pcmcia);
 EXPORT_SYMBOL(HiSax_closecard);
-#else
-static struct symbol_table hisax_syms_avm_a1= {
-#include <linux/symtab_begin.h>
-	X(avm_a1_init_pcmcia),
-	X(HiSax_closecard),
-#include <linux/symtab_end.h>
-};
-#endif /* COMPAT_HAS_NEW_SYMTAB */
 #endif /* CONFIG_HISAX_AVM_A1_PCMCIA */
 
 #ifdef CONFIG_HISAX_FRITZPCI
@@ -310,15 +314,7 @@ static struct symbol_table hisax_syms_avm_a1= {
 #define DEFAULT_CARD ISDN_CTYPE_SEDLBAUER
 #define DEFAULT_CFG {11,0x270,0,0}
 int sedl_init_pcmcia(void*, int, int*, int);
-#ifdef COMPAT_HAS_NEW_SYMTAB
 EXPORT_SYMBOL(sedl_init_pcmcia);
-#else
-static struct symbol_table hisax_syms_sedl= {
-#include <linux/symtab_begin.h>
-	X(sedl_init_pcmcia),
-#include <linux/symtab_end.h>
-};
-#endif /* COMPAT_HAS_NEW_SYMTAB */
 #endif /* CONFIG_HISAX_SEDLBAUER */
 
 #ifdef CONFIG_HISAX_SPORTSTER
@@ -406,6 +402,13 @@ static struct symbol_table hisax_syms_sedl= {
 #define DEFAULT_CFG {15,0x180,0,0}
 #endif
 
+#ifdef CONFIG_HISAX_W6692
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_W6692
+#define DEFAULT_CFG {0,0,0,0}
+#endif
+
 #ifdef CONFIG_HISAX_1TR6
 #define DEFAULT_PROTO ISDN_PTYPE_1TR6
 #define DEFAULT_PROTO_NAME "1TR6"
@@ -483,7 +486,6 @@ static int mem[] HISAX_INITDATA =
 {0, 0, 0, 0, 0, 0, 0, 0};
 static char *id HISAX_INITDATA = HiSaxID;
 
-#ifdef COMPAT_HAS_NEW_SYMTAB
 MODULE_AUTHOR("Karsten Keil");
 MODULE_PARM(type, "1-8i");
 MODULE_PARM(protocol, "1-8i");
@@ -491,11 +493,10 @@ MODULE_PARM(io, "1-8i");
 MODULE_PARM(irq, "1-8i");
 MODULE_PARM(mem, "1-8i");
 MODULE_PARM(id, "s");
-#ifdef CONFIG_HISAX_16_3	/* For Creatix/Teles PnP */
+#ifdef IO0_IO1
 MODULE_PARM(io0, "1-8i");
 MODULE_PARM(io1, "1-8i");
-#endif /* CONFIG_HISAX_16_3 */
-#endif /* COMPAT_HAS_NEW_SYMTAB */
+#endif /* IO0_IO1 */
 #endif /* MODULE */
 
 int nrcards;
@@ -528,9 +529,9 @@ HiSaxVersion(void))
 
 	printk(KERN_INFO "HiSax: Linux Driver for passive ISDN cards\n");
 #ifdef MODULE
-	printk(KERN_INFO "HiSax: Version 3.3a (module)\n");
+	printk(KERN_INFO "HiSax: Version 3.3c (module)\n");
 #else
-	printk(KERN_INFO "HiSax: Version 3.3a (kernel)\n");
+	printk(KERN_INFO "HiSax: Version 3.3c (kernel)\n");
 #endif
 	strcpy(tmp, l1_revision);
 	printk(KERN_INFO "HiSax: Layer1 Revision %s\n", HiSax_getrev(tmp));
@@ -560,7 +561,6 @@ HiSax_mod_inc_use_count(void)
 #ifdef MODULE
 #define HiSax_init init_module
 #else
-#ifdef COMPAT_HAS_NEW_SETUP
 #define MAX_ARG	(HISAX_MAX_CARDS*5)
 static int __init
 HiSax_setup(char *line)
@@ -570,12 +570,6 @@ HiSax_setup(char *line)
 	char *str;
 
 	str = get_options(line, MAX_ARG, ints);
-#else
-void __init
-HiSax_setup(char *str, int *ints)
-{
-	int i, j, argc;
-#endif        
 	argc = ints[0];
 	printk(KERN_DEBUG"HiSax_setup: argc(%d) str(%s)\n", argc, str);
 	i = 0;
@@ -615,14 +609,10 @@ HiSax_setup(char *str, int *ints)
 		strcpy(HiSaxID, "HiSax");
 		HiSax_id = HiSaxID;
 	}
-#ifdef COMPAT_HAS_NEW_SETUP
 	return(1);
 }
 
 __setup("hisax=", HiSax_setup);
-#else
-}
-#endif /* COMPAT_HAS_NEW_SETUP */
 #endif /* MODULES */
 
 #if CARD_TELES0
@@ -717,11 +707,11 @@ extern int setup_saphir(struct IsdnCard *card);
 extern int setup_testemu(struct IsdnCard *card);
 #endif
 
-#if	CARD_BKM_A4T
+#if CARD_BKM_A4T
 extern int setup_bkm_a4t(struct IsdnCard *card);
 #endif
 
-#if	CARD_SCT_QUADRO
+#if CARD_SCT_QUADRO
 extern int setup_sct_quadro(struct IsdnCard *card);
 #endif
 
@@ -729,6 +719,10 @@ extern int setup_sct_quadro(struct IsdnCard *card);
 extern int setup_gazel(struct IsdnCard *card);
 #endif
 
+#if CARD_W6692
+extern int setup_w6692(struct IsdnCard *card);
+#endif
+
 /*
  * Find card with given driverId
  */
@@ -967,7 +961,7 @@ closecard(int cardnr)
 		csta->rcvbuf = NULL;
 	}
 	if (csta->tx_skb) {
-		idev_kfree_skb(csta->tx_skb, FREE_WRITE);
+		dev_kfree_skb(csta->tx_skb);
 		csta->tx_skb = NULL;
 	}
 	if (csta->DC_Close != NULL) {
@@ -1000,7 +994,7 @@ HISAX_INITFUNC(static int init_card(struct IsdnCardState *cs))
 	while (cnt) {
 		cs->cardmsg(cs, CARD_INIT, NULL);
 		sti();
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		/* Timeout 10ms */
 		schedule_timeout((10*HZ)/1000);
 		restore_flags(flags);
@@ -1253,6 +1247,11 @@ checkcard(int cardnr, char *id, int *busy_flag))
  		case ISDN_CTYPE_GAZEL:
  			ret = setup_gazel(card);
  			break;
+#endif
+#if CARD_W6692
+		case ISDN_CTYPE_W6692:
+			ret = setup_w6692(card);
+			break;
 #endif
 		default:
 			printk(KERN_WARNING
@@ -1357,6 +1356,7 @@ HiSax_inithardware(int *busy_flag))
 				kfree((void *) cards[i].cs);
 			cards[i].cs = NULL;
 			HiSax_shiftcards(i);
+			nrcards--;
 		}
 	}
 	return foundcards;
@@ -1387,12 +1387,9 @@ HiSax_closecard(int cardnr)
 }
 
 void
-HiSax_reportcard(int cardnr)
+HiSax_reportcard(int cardnr, int sel)
 {
 	struct IsdnCardState *cs = cards[cardnr].cs;
-	struct PStack *stptr;
-	struct l3_process *pc;
-	int j, i = 1;
 
 	printk(KERN_DEBUG "HiSax: reportcard No %d\n", cardnr + 1);
 	printk(KERN_DEBUG "HiSax: Type %s\n", CardType[cs->typ]);
@@ -1400,50 +1397,38 @@ HiSax_reportcard(int cardnr)
 	printk(KERN_DEBUG "HiSax: HiSax_reportcard address 0x%lX\n",
 		(ulong) & HiSax_reportcard);
 	printk(KERN_DEBUG "HiSax: cs 0x%lX\n", (ulong) cs);
-	printk(KERN_DEBUG "HiSax: HW_Flags %x bc0 flg %x bc0 flg %x\n",
+	printk(KERN_DEBUG "HiSax: HW_Flags %x bc0 flg %x bc1 flg %x\n",
 		cs->HW_Flags, cs->bcs[0].Flag, cs->bcs[1].Flag);
 	printk(KERN_DEBUG "HiSax: bcs 0 mode %d ch%d\n",
 		cs->bcs[0].mode, cs->bcs[0].channel);
 	printk(KERN_DEBUG "HiSax: bcs 1 mode %d ch%d\n",
 		cs->bcs[1].mode, cs->bcs[1].channel);
-	printk(KERN_DEBUG "HiSax: cs setstack_d 0x%lX\n", (ulong) cs->setstack_d);
-	printk(KERN_DEBUG "HiSax: cs stl 0x%lX\n", (ulong) & (cs->stlist));
-	stptr = cs->stlist;
-	while (stptr != NULL) {
-		printk(KERN_DEBUG "HiSax: dst%d 0x%lX\n", i, (ulong) stptr);
-		printk(KERN_DEBUG "HiSax: dst%d stp 0x%lX\n", i, (ulong) stptr->l1.stlistp);
-		printk(KERN_DEBUG "HiSax: dst%d l1.l1hw 0x%lX\n", i, (ulong) stptr->l1.l1hw);
-		printk(KERN_DEBUG "HiSax:   tei %d sapi %d\n",
-		       stptr->l2.tei, stptr->l2.sap);
-		printk(KERN_DEBUG "HiSax:      man 0x%lX\n", (ulong) stptr->ma.layer);
-		pc = stptr->l3.proc;
-		while (pc) {
-			printk(KERN_DEBUG "HiSax: l3proc %x 0x%lX\n", pc->callref,
-			       (ulong) pc);
-			printk(KERN_DEBUG "HiSax:    state %d  st 0x%lX chan 0x%lX\n",
-			    pc->state, (ulong) pc->st, (ulong) pc->chan);
-			pc = pc->next;
-		}
-		stptr = stptr->next;
-		i++;
-	}
-	for (j = 0; j < 2; j++) {
-		printk(KERN_DEBUG "HiSax: ch%d 0x%lX\n", j,
-		       (ulong) & cs->channel[j]);
-		stptr = cs->channel[j].b_st;
-		i = 1;
-		while (stptr != NULL) {
-			printk(KERN_DEBUG "HiSax:  b_st%d 0x%lX\n", i, (ulong) stptr);
-			printk(KERN_DEBUG "HiSax:    man 0x%lX\n", (ulong) stptr->ma.layer);
-			stptr = stptr->next;
-			i++;
-		}
+#ifdef ERROR_STATISTIC
+	printk(KERN_DEBUG "HiSax: dc errors(rx,crc,tx) %d,%d,%d\n",
+		cs->err_rx, cs->err_crc, cs->err_tx);
+	printk(KERN_DEBUG "HiSax: bc0 errors(inv,rdo,crc,tx) %d,%d,%d,%d\n",
+		cs->bcs[0].err_inv, cs->bcs[0].err_rdo, cs->bcs[0].err_crc, cs->bcs[0].err_tx);
+	printk(KERN_DEBUG "HiSax: bc1 errors(inv,rdo,crc,tx) %d,%d,%d,%d\n",
+		cs->bcs[1].err_inv, cs->bcs[1].err_rdo, cs->bcs[1].err_crc, cs->bcs[1].err_tx);
+	if (sel == 99) {
+		cs->err_rx  = 0;
+		cs->err_crc = 0;
+		cs->err_tx  = 0;
+		cs->bcs[0].err_inv = 0;
+		cs->bcs[0].err_rdo = 0;
+		cs->bcs[0].err_crc = 0;
+		cs->bcs[0].err_tx  = 0;
+		cs->bcs[1].err_inv = 0;
+		cs->bcs[1].err_rdo = 0;
+		cs->bcs[1].err_crc = 0;
+		cs->bcs[1].err_tx  = 0;
 	}
+#endif
 }
 
 
-int __init
-HiSax_init(void)
+__initfunc(int
+HiSax_init(void))
 {
 	int i;
 
@@ -1452,27 +1437,18 @@ HiSax_init(void)
 #ifdef CONFIG_HISAX_ELSA
 	if (type[0] == ISDN_CTYPE_ELSA_PCMCIA) {
 		/* we have exported  and return in this case */
-#ifndef COMPAT_HAS_NEW_SYMTAB
-		register_symtab(&hisax_syms_elsa);
-#endif
 		return 0;
 	}
 #endif
 #ifdef CONFIG_HISAX_SEDLBAUER
 	if (type[0] == ISDN_CTYPE_SEDLBAUER_PCMCIA) {
 		/* we have to export  and return in this case */
-#ifndef COMPAT_HAS_NEW_SYMTAB
-		register_symtab(&hisax_syms_sedl);
-#endif
 		return 0;
 	}
 #endif
 #ifdef CONFIG_HISAX_AVM_A1_PCMCIA
 	if (type[0] == ISDN_CTYPE_A1_PCMCIA) {
 		/* we have to export  and return in this case */
-#ifndef COMPAT_HAS_NEW_SYMTAB
-		register_symtab(&hisax_syms_avm_a1);
-#endif
 		return 0;
 	}
 #endif
@@ -1515,6 +1491,7 @@ HiSax_init(void)
 				break;
 #endif
 			case ISDN_CTYPE_ELSA:
+			case ISDN_CTYPE_HFC_PCI:
 				cards[i].para[0] = io[i];
 				break;
 			case ISDN_CTYPE_16_3:
@@ -1550,6 +1527,7 @@ HiSax_init(void)
 			case ISDN_CTYPE_NETJET:
 			case ISDN_CTYPE_AMD7930:
 			case ISDN_CTYPE_TELESPCI:
+			case ISDN_CTYPE_W6692:
 				break;
 			case ISDN_CTYPE_BKM_A4T:
 	  		   	break;
@@ -1582,11 +1560,6 @@ HiSax_init(void)
 	if (HiSax_inithardware(NULL)) {
 		/* Install only, if at least one card found */
 #ifdef MODULE
-#ifndef COMPAT_HAS_NEW_SYMTAB
-		/* No symbols to export, hide all symbols */
-		register_symtab(NULL);
-		printk(KERN_INFO "HiSax: module installed\n");
-#endif /* COMPAT_HAS_NEW_SYMTAB */
 #endif /* MODULE */
 		return (0);
 	} else {
@@ -1629,9 +1602,7 @@ int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
 
 	nrcards = 0;
 	HiSaxVersion();
-	if (id)			/* If id= string used */
-		HiSax_id = id;
-	/* Initialize all 8 structs, even though we only accept
+	/* Initialize all structs, even though we only accept
 	   two pcmcia cards
 	   */
 	for (i = 0; i < HISAX_MAX_CARDS; i++) {
@@ -1680,9 +1651,7 @@ int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
 
 	nrcards = 0;
 	HiSaxVersion();
-	if (id)			/* If id= string used */
-		HiSax_id = id;
-	/* Initialize all 8 structs, even though we only accept
+	/* Initialize all structs, even though we only accept
 	   two pcmcia cards
 	   */
 	for (i = 0; i < HISAX_MAX_CARDS; i++) {
@@ -1731,12 +1700,10 @@ int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
 
 	nrcards = 0;
 	HiSaxVersion();
-	if (id)			/* If id= string used */
-		HiSax_id = id;
-	/* Initialize all 16 structs, even though we only accept
+	/* Initialize all structs, even though we only accept
 	   two pcmcia cards
 	   */
-	for (i = 0; i < 16; i++) {
+	for (i = 0; i < HISAX_MAX_CARDS; i++) {
 		cards[i].para[0] = irq[i];
 		cards[i].para[1] = io[i];
 		cards[i].typ = type[i];
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
index 8ec1a536c8ed0de3c1533932df4fa780a15e125b..f1161e63de6a3d20a30e54f1ae56f27f2b5165ed 100644
--- a/drivers/isdn/hisax/diva.c
+++ b/drivers/isdn/hisax/diva.c
@@ -1,4 +1,4 @@
-/* $Id: diva.c,v 1.16 1999/08/11 21:01:25 keil Exp $
+/* $Id: diva.c,v 1.17 1999/09/04 06:20:06 keil Exp $
 
  * diva.c     low level stuff for Eicon.Diehl Diva Family ISDN cards
  *
@@ -12,6 +12,9 @@
  *
  *
  * $Log: diva.c,v $
+ * Revision 1.17  1999/09/04 06:20:06  keil
+ * Changes from kernel set_current_state()
+ *
  * Revision 1.16  1999/08/11 21:01:25  keil
  * new PCI codefix
  *
@@ -74,13 +77,10 @@
 #include "ipac.h"
 #include "isdnl1.h"
 #include <linux/pci.h>
-#ifndef COMPAT_HAS_NEW_PCI
-#include <linux/bios32.h>
-#endif
 
 extern const char *CardType[];
 
-const char *Diva_revision = "$Revision: 1.16 $";
+const char *Diva_revision = "$Revision: 1.17 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -550,7 +550,6 @@ Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
 				if (!(skb = dev_alloc_skb(count)))
 					printk(KERN_WARNING "HSCX: receive out of memory\n");
 				else {
-					SET_SKB_FREE(skb);
 					memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
 					skb_queue_tail(&bcs->rqueue, skb);
 				}
@@ -566,7 +565,6 @@ Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
 			if (!(skb = dev_alloc_skb(fifo_size)))
 				printk(KERN_WARNING "HiSax: receive out of memory\n");
 			else {
-				SET_SKB_FREE(skb);
 				memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
 				skb_queue_tail(&bcs->rqueue, skb);
 			}
@@ -583,7 +581,7 @@ Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
 				if (bcs->st->lli.l1writewakeup &&
 					(PACKET_NOACK != bcs->tx_skb->pkt_type))
 					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count);
-				idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+				dev_kfree_skb(bcs->tx_skb);
 				bcs->hw.hscx.count = 0; 
 				bcs->tx_skb = NULL;
 			}
@@ -752,30 +750,30 @@ reset_diva(struct IsdnCardState *cs)
 	sti();
 	if (cs->subtyp == DIVA_IPAC_ISA) {
 		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20);
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout((10*HZ)/1000);
 		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00);
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout((10*HZ)/1000);
 		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0);
 	} else if (cs->subtyp == DIVA_IPAC_PCI) {
 		unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg +
 					PITA_MISC_REG);
 		*ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE;
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout((10*HZ)/1000);
 		*ireg = PITA_PARA_MPX_MODE;
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout((10*HZ)/1000);
 		memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0);
 	} else { /* DIVA 2.0 */
 		cs->hw.diva.ctrl_reg = 0;        /* Reset On */
 		byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout((10*HZ)/1000);
 		cs->hw.diva.ctrl_reg |= DIVA_RESET;  /* Reset Off */
 		byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout((10*HZ)/1000);
 		if (cs->subtyp == DIVA_ISA)
 			cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A;
@@ -880,16 +878,12 @@ Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 	return(0);
 }
 
-#ifdef COMPAT_HAS_NEW_PCI
 static 	struct pci_dev *dev_diva __initdata = NULL;
 static 	struct pci_dev *dev_diva_u __initdata = NULL;
 static 	struct pci_dev *dev_diva201 __initdata = NULL;
-#else
-static  int pci_index __initdata = 0;
-#endif
 
-int __init
-setup_diva(struct IsdnCard *card)
+__initfunc(int
+setup_diva(struct IsdnCard *card))
 {
 	int bytecnt;
 	u_char val;
@@ -927,7 +921,6 @@ setup_diva(struct IsdnCard *card)
 		bytecnt = 8;
 	} else {
 #if CONFIG_PCI
-#ifdef COMPAT_HAS_NEW_PCI
 		if (!pci_present()) {
 			printk(KERN_ERR "Diva: no PCI bus present\n");
 			return(0);
@@ -938,23 +931,23 @@ setup_diva(struct IsdnCard *card)
 			PCI_DIVA20_ID, dev_diva))) {
 			cs->subtyp = DIVA_PCI;
 			cs->irq = dev_diva->irq;
-			cs->hw.diva.cfg_reg = get_pcibase(dev_diva, 2)
+			cs->hw.diva.cfg_reg = dev_diva->resource[ 2].start
 				& PCI_BASE_ADDRESS_IO_MASK;
 		} else if ((dev_diva_u = pci_find_device(PCI_VENDOR_EICON_DIEHL,
 			PCI_DIVA20_U_ID, dev_diva_u))) {
 			cs->subtyp = DIVA_PCI;
 			cs->irq = dev_diva_u->irq;
-			cs->hw.diva.cfg_reg = get_pcibase(dev_diva_u, 2)
+			cs->hw.diva.cfg_reg = dev_diva_u->resource[ 2].start
 				& PCI_BASE_ADDRESS_IO_MASK;
 		} else if ((dev_diva201 = pci_find_device(PCI_VENDOR_EICON_DIEHL,
 			PCI_DIVA_201, dev_diva201))) {
 			cs->subtyp = DIVA_IPAC_PCI;
 			cs->irq = dev_diva201->irq;
 			cs->hw.diva.pci_cfg =
-				(ulong) ioremap((get_pcibase(dev_diva201, 0)
+				(ulong) ioremap((dev_diva201->resource[ 0].start
 					& PCI_BASE_ADDRESS_IO_MASK), 4096);
 			cs->hw.diva.cfg_reg =
-				(ulong) ioremap((get_pcibase(dev_diva201, 1)
+				(ulong) ioremap((dev_diva201->resource[ 1].start
 					& PCI_BASE_ADDRESS_IO_MASK), 4096);
 		} else {
 			printk(KERN_WARNING "Diva: No PCI card found\n");
@@ -970,66 +963,6 @@ setup_diva(struct IsdnCard *card)
 			printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n");
 			return(0);
 		}
-#else
-		u_char pci_bus, pci_device_fn, pci_irq;
-		u_int pci_ioaddr;
-
-		cs->subtyp = 0;
-		for (; pci_index < 0xff; pci_index++) {
-			if (pcibios_find_device(PCI_VENDOR_EICON_DIEHL,
-			   PCI_DIVA20_ID, pci_index, &pci_bus, &pci_device_fn)
-			   == PCIBIOS_SUCCESSFUL)
-				cs->subtyp = DIVA_PCI;
-			else if (pcibios_find_device(PCI_VENDOR_EICON_DIEHL,
-			   PCI_DIVA20_U_ID, pci_index, &pci_bus, &pci_device_fn)
-			   == PCIBIOS_SUCCESSFUL)
-			   	cs->subtyp = DIVA_PCI;
-			else if (pcibios_find_device(PCI_VENDOR_EICON_DIEHL,
-			   PCI_DIVA_201, pci_index, &pci_bus, &pci_device_fn)
-			   == PCIBIOS_SUCCESSFUL)
-			   	cs->subtyp = DIVA_IPAC_PCI;
-			else
-				break;
-			/* get IRQ */
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-				PCI_INTERRUPT_LINE, &pci_irq);
-
-			/* get IO address */
-			if (cs->subtyp == DIVA_IPAC_PCI) {
-				pcibios_read_config_dword(pci_bus, pci_device_fn,
-					PCI_BASE_ADDRESS_0, &pci_ioaddr);
-				cs->hw.diva.pci_cfg = (ulong) ioremap(pci_ioaddr,
-					4096);
-				pcibios_read_config_dword(pci_bus, pci_device_fn,
-					PCI_BASE_ADDRESS_1, &pci_ioaddr);
-				cs->hw.diva.cfg_reg = (ulong) ioremap(pci_ioaddr,
-					4096);
-			} else {
-				pcibios_read_config_dword(pci_bus, pci_device_fn,
-					PCI_BASE_ADDRESS_1, &pci_ioaddr);
-				cs->hw.diva.pci_cfg = pci_ioaddr & ~3;
-				pcibios_read_config_dword(pci_bus, pci_device_fn,
-					PCI_BASE_ADDRESS_2, &pci_ioaddr);
-				cs->hw.diva.cfg_reg = pci_ioaddr & ~3;
-			}
-			if (cs->subtyp)
-				break;
-		}
-		if (!cs->subtyp) {
-			printk(KERN_WARNING "Diva: No PCI card found\n");
-			return(0);
-		}
-		pci_index++;
-		if (!pci_irq) {
-			printk(KERN_WARNING "Diva: No IRQ for PCI card found\n");
-			return(0);
-		}
-		if (!pci_ioaddr) {
-			printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n");
-			return(0);
-		}
-		cs->irq = pci_irq;
-#endif /* COMPAT_HAS_NEW_PCI */
 		cs->irq_flags |= SA_SHIRQ;
 #else
 		printk(KERN_WARNING "Diva: cfgreg 0 and NO_PCI_BIOS\n");
diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
index c2d6cf2d385272d18518e7d67f9a90fd822444e3..4dbe40c38462044cdd0555207ccea55bd2938be0 100644
--- a/drivers/isdn/hisax/elsa.c
+++ b/drivers/isdn/hisax/elsa.c
@@ -1,4 +1,4 @@
-/* $Id: elsa.c,v 2.18 1999/08/25 16:50:54 keil Exp $
+/* $Id: elsa.c,v 2.19 1999/09/04 06:20:06 keil Exp $
 
  * elsa.c     low level stuff for Elsa isdn cards
  *
@@ -14,6 +14,9 @@
  *              for ELSA PCMCIA support
  *
  * $Log: elsa.c,v $
+ * Revision 2.19  1999/09/04 06:20:06  keil
+ * Changes from kernel set_current_state()
+ *
  * Revision 2.18  1999/08/25 16:50:54  keil
  * Fix bugs which cause 2.3.14 hangs (waitqueue init)
  *
@@ -91,15 +94,12 @@
 #include "hscx.h"
 #include "isdnl1.h"
 #include <linux/pci.h>
-#ifndef COMPAT_HAS_NEW_PCI
-#include <linux/bios32.h>
-#endif
 #include <linux/serial.h>
 #include <linux/serial_reg.h>
 
 extern const char *CardType[];
 
-const char *Elsa_revision = "$Revision: 2.18 $";
+const char *Elsa_revision = "$Revision: 2.19 $";
 const char *Elsa_Types[] =
 {"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro",
  "PCMCIA", "QS 1000", "QS 3000", "QS 1000 PCI", "QS 3000 PCI", 
@@ -578,10 +578,10 @@ reset_elsa(struct IsdnCardState *cs)
 		save_flags(flags);
 		sti();
 		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x20);
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
 		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x00);
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xc0);
 		schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
 		restore_flags(flags);
@@ -785,7 +785,7 @@ Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 				cs->hw.elsa.status |= ELSA_TIMER_AKTIV;
 				byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
 				byteout(cs->hw.elsa.timer, 0);
-				current->state = TASK_INTERRUPTIBLE;
+				set_current_state(TASK_INTERRUPTIBLE);
 				schedule_timeout((110*HZ)/1000);
 				restore_flags(flags);
 				cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT;
@@ -928,12 +928,8 @@ probe_elsa(struct IsdnCardState *cs)
 	return (CARD_portlist[i]);
 }
 
-#ifdef COMPAT_HAS_NEW_PCI
 static 	struct pci_dev *dev_qs1000 __initdata = NULL;
 static 	struct pci_dev *dev_qs3000 __initdata = NULL;
-#else
-static 	int pci_index __initdata = 0;
-#endif
 
 int
 setup_elsa(struct IsdnCard *card)
@@ -1051,7 +1047,6 @@ setup_elsa(struct IsdnCard *card)
 		       cs->irq);
 	} else if (cs->typ == ISDN_CTYPE_ELSA_PCI) {
 #if CONFIG_PCI
-#ifdef COMPAT_HAS_NEW_PCI
 		if (!pci_present()) {
 			printk(KERN_ERR "Elsa: no PCI bus present\n");
 			return(0);
@@ -1061,17 +1056,17 @@ setup_elsa(struct IsdnCard *card)
 			 dev_qs1000))) {
 				cs->subtyp = ELSA_QS1000PCI;
 			cs->irq = dev_qs1000->irq;
-			cs->hw.elsa.cfg = get_pcibase(dev_qs1000, 1) & 
+			cs->hw.elsa.cfg = dev_qs1000->resource[ 1].start & 
 				PCI_BASE_ADDRESS_IO_MASK;
-			cs->hw.elsa.base = get_pcibase(dev_qs1000, 3) & 
+			cs->hw.elsa.base = dev_qs1000->resource[ 3].start & 
 				PCI_BASE_ADDRESS_IO_MASK;
 		} else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ELSA,
 			PCI_QS3000_ID, dev_qs3000))) {
 			cs->subtyp = ELSA_QS3000PCI;
 			cs->irq = dev_qs3000->irq;
-			cs->hw.elsa.cfg = get_pcibase(dev_qs3000, 1) & 
+			cs->hw.elsa.cfg = dev_qs3000->resource[ 1].start & 
 				PCI_BASE_ADDRESS_IO_MASK;
-			cs->hw.elsa.base = get_pcibase(dev_qs3000, 3) & 
+			cs->hw.elsa.base = dev_qs3000->resource[ 3].start & 
 				PCI_BASE_ADDRESS_IO_MASK;
 		} else {
 			printk(KERN_WARNING "Elsa: No PCI card found\n");
@@ -1096,54 +1091,6 @@ setup_elsa(struct IsdnCard *card)
 			HZDELAY(500);	/* wait 500*10 ms */
 			restore_flags(flags);
 		}
-#else
-		u_char pci_bus, pci_device_fn, pci_irq;
-		u_int pci_ioaddr;
-
-		cs->subtyp = 0;
-		for (; pci_index < 0xff; pci_index++) {
-			if (pcibios_find_device(PCI_VENDOR_ELSA,
-			   PCI_QS1000_ID, pci_index, &pci_bus, &pci_device_fn)
-			   == PCIBIOS_SUCCESSFUL)
-				cs->subtyp = ELSA_QS1000PCI;
-			else if (pcibios_find_device(PCI_VENDOR_ELSA,
-			   PCI_QS3000_ID, pci_index, &pci_bus, &pci_device_fn)
-			   == PCIBIOS_SUCCESSFUL)
-				cs->subtyp = ELSA_QS3000PCI;
-			else
-				break;
-			/* get IRQ */
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-				PCI_INTERRUPT_LINE, &pci_irq);
-
-			/* get IO address */
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-				PCI_BASE_ADDRESS_1, &pci_ioaddr);
-			pci_ioaddr &= ~3; /* remove io/mem flag */
-			cs->hw.elsa.cfg = pci_ioaddr;
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-				PCI_BASE_ADDRESS_3, &pci_ioaddr);
-			if (cs->subtyp)
-				break;
-		}
-		if (!cs->subtyp) {
-			printk(KERN_WARNING "Elsa: No PCI card found\n");
-			return(0);
-		}
-		pci_index++;
-		if (!pci_irq) {
-			printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n");
-			return(0);
-		}
-
-		if (!pci_ioaddr) {
-			printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n");
-			return(0);
-		}
-		pci_ioaddr &= ~3; /* remove io/mem flag */
-		cs->hw.elsa.base = pci_ioaddr;
-		cs->irq = pci_irq;
-#endif /* COMPAT_HAS_NEW_PCI */
 		cs->hw.elsa.ale  = cs->hw.elsa.base;
 		cs->hw.elsa.isac = cs->hw.elsa.base +1;
 		cs->hw.elsa.hscx = cs->hw.elsa.base +1; 
diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c
index e4b35e50290098e98a01132d150c070225861e75..529a748151698d9b20da88a8c5108c0b87a0c85f 100644
--- a/drivers/isdn/hisax/elsa_ser.c
+++ b/drivers/isdn/hisax/elsa_ser.c
@@ -298,7 +298,7 @@ modem_fill(struct BCState *bcs) {
 				(PACKET_NOACK != bcs->tx_skb->pkt_type))
 					bcs->st->lli.l1writewakeup(bcs->st,
 						bcs->hw.hscx.count);
-			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			dev_kfree_skb(bcs->tx_skb);
 			bcs->tx_skb = NULL;
 		}
 	}
@@ -389,74 +389,6 @@ static inline void transmit_chars(struct IsdnCardState *cs, int *intr_done)
 	}
 }
 
-#if 0
-static inline void check_modem_status(struct IsdnCardState *cs)
-{
-	int	status;
-	struct async_struct *info = cs->hw.elsa.info;
-	struct	async_icount *icount;
-	
-	status = serial_inp(info, UART_MSR);
-
-	if (status & UART_MSR_ANY_DELTA) {
-		icount = &info->state->icount;
-		/* update input line counters */
-		if (status & UART_MSR_TERI)
-			icount->rng++;
-		if (status & UART_MSR_DDSR)
-			icount->dsr++;
-		if (status & UART_MSR_DDCD) {
-			icount->dcd++;
-		}
-		if (status & UART_MSR_DCTS)
-			icount->cts++;
-//		wake_up_interruptible(&info->delta_msr_wait);
-	}
-
-	if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
-#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
-		printk("ttys%d CD now %s...", info->line,
-		       (status & UART_MSR_DCD) ? "on" : "off");
-#endif		
-		if (status & UART_MSR_DCD)
-//			wake_up_interruptible(&info->open_wait);
-;
-		else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
-			   (info->flags & ASYNC_CALLOUT_NOHUP))) {
-#ifdef SERIAL_DEBUG_OPEN
-			printk("doing serial hangup...");
-#endif
-			if (info->tty)
-				tty_hangup(info->tty);
-		}
-	}
-#if 0
-	if (info->flags & ASYNC_CTS_FLOW) {
-		if (info->tty->hw_stopped) {
-			if (status & UART_MSR_CTS) {
-#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
-				printk("CTS tx start...");
-#endif
-				info->tty->hw_stopped = 0;
-				info->IER |= UART_IER_THRI;
-				serial_outp(info, UART_IER, info->IER);
-//				rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
-				return;
-			}
-		} else {
-			if (!(status & UART_MSR_CTS)) {
-#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
-				printk("CTS tx stop...");
-#endif
-				info->tty->hw_stopped = 1;
-				info->IER &= ~UART_IER_THRI;
-				serial_outp(info, UART_IER, info->IER);
-			}
-		}
-	}
-#endif 0
-}
-#endif
 
 static void rs_interrupt_elsa(int irq, struct IsdnCardState *cs)
 {
@@ -510,13 +442,13 @@ close_elsastate(struct BCState *bcs)
 			bcs->hw.hscx.rcvbuf = NULL;
 		}
 		while ((skb = skb_dequeue(&bcs->rqueue))) {
-			idev_kfree_skb(skb, FREE_READ);
+			dev_kfree_skb(skb);
 		}
 		while ((skb = skb_dequeue(&bcs->squeue))) {
-			idev_kfree_skb(skb, FREE_WRITE);
+			dev_kfree_skb(skb);
 		}
 		if (bcs->tx_skb) {
-			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			dev_kfree_skb(bcs->tx_skb);
 			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		}
diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
index ef64a4702dff4a4ceb27a2ef52c991314e2479cb..c104253c7ca08fc90c30fe11ad9b9a144fcec255 100644
--- a/drivers/isdn/hisax/gazel.c
+++ b/drivers/isdn/hisax/gazel.c
@@ -37,9 +37,6 @@
 #include "isdnl1.h"
 #include "ipac.h"
 #include <linux/pci.h>
-#ifndef COMPAT_HAS_NEW_PCI
-#include <linux/bios32.h>
-#endif
 
 extern const char *CardType[];
 const char *gazel_revision = "$Revision: 2.6 $";
@@ -573,11 +570,7 @@ setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
 	return (0);
 }
 
-#ifdef COMPAT_HAS_NEW_PCI
 static struct pci_dev *dev_tel __initdata = NULL;
-#else
-static  int pci_index __initdata = 0;
-#endif
 
 static int
 setup_gazelpci(struct IsdnCardState *cs)
@@ -589,42 +582,19 @@ setup_gazelpci(struct IsdnCardState *cs)
 	printk(KERN_WARNING "Gazel: PCI card automatic recognition\n");
 
 	found = 0;
-#ifdef COMPAT_HAS_NEW_PCI
 	if (!pci_present()) {
 		printk(KERN_WARNING "Gazel: No PCI bus present\n");
 		return 1;
 	}
-#endif
 	seekcard = GAZEL_R685;
 	for (nbseek = 0; nbseek < 3; nbseek++) {
-#ifdef COMPAT_HAS_NEW_PCI
 		if ((dev_tel = pci_find_device(GAZEL_MANUFACTURER, seekcard, dev_tel))) {
 
 			pci_irq = dev_tel->irq;
-			pci_ioaddr0 = get_pcibase(dev_tel, 1);
-			pci_ioaddr1 = get_pcibase(dev_tel, 2);
+			pci_ioaddr0 = dev_tel->resource[ 1].start;
+			pci_ioaddr1 = dev_tel->resource[ 2].start;
 			found = 1;
 		}
-#else
-		for (; pci_index < 0xff; pci_index++) {
-			u_char pci_bus, pci_device_fn;
-			
-			if (pcibios_find_device(GAZEL_MANUFACTURER, seekcard,
-				pci_index, &pci_bus, &pci_device_fn)
-				!= PCIBIOS_SUCCESSFUL)
-				break;
-			/* get IRQ */
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-				PCI_INTERRUPT_LINE, &pci_irq);
-			/* get IO address */
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-				PCI_BASE_ADDRESS_1, &pci_ioaddr0);
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-				PCI_BASE_ADDRESS_2, &pci_ioaddr1);
-			found = 1;
-			break;
-		}
-#endif /* COMPAT_HAS_NEW_PCI */
 		if (found)
 			break;
 		else {
@@ -636,9 +606,6 @@ setup_gazelpci(struct IsdnCardState *cs)
 					seekcard = GAZEL_DJINN_ITOO;
 					break;
 			}
-#ifndef COMPAT_HAS_NEW_PCI
-			pci_index = 0;
-#endif
 		}
 	}
 	if (!found) {
@@ -690,8 +657,8 @@ setup_gazelpci(struct IsdnCardState *cs)
 	return (0);
 }
 
-int __init
-	   setup_gazel(struct IsdnCard *card)
+__initfunc(int
+	   setup_gazel(struct IsdnCard *card))
 {
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c
index 266916c39af4d4bab5db7a72c39841a043d63ab0..bb388c5c28c742795d6c1b6d4eda5df3efdcb054 100644
--- a/drivers/isdn/hisax/hfc_2bds0.c
+++ b/drivers/isdn/hisax/hfc_2bds0.c
@@ -1,4 +1,4 @@
-/* $Id: hfc_2bds0.c,v 1.9 1999/07/01 08:11:35 keil Exp $
+/* $Id: hfc_2bds0.c,v 1.10 1999/10/14 20:25:28 keil Exp $
  *
  *  specific routines for CCD's HFC 2BDS0
  *
@@ -6,6 +6,9 @@
  *
  *
  * $Log: hfc_2bds0.c,v $
+ * Revision 1.10  1999/10/14 20:25:28  keil
+ * add a statistic for error monitoring
+ *
  * Revision 1.9  1999/07/01 08:11:35  keil
  * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
  *
@@ -260,6 +263,9 @@ static struct sk_buff
 		if (cs->debug & L1_DEB_WARN)
 			debugl1(cs, "hfc_empty_fifo: incoming packet too small");
 		cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel);
+#ifdef ERROR_STATISTIC
+		bcs->err_inv++;
+#endif
 		cli();
 		while ((idx++ < count) && WaitNoBusy(cs))
 			ReadReg(cs, HFCD_DATA_NODEB, cip);
@@ -267,7 +273,6 @@ static struct sk_buff
 	} else if (!(skb = dev_alloc_skb(count - 3)))
 		printk(KERN_WARNING "HFC: receive out of memory\n");
 	else {
-		SET_SKB_FREE(skb);
 		ptr = skb_put(skb, count - 3);
 		idx = 0;
 		cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel);
@@ -285,7 +290,7 @@ static struct sk_buff
 			sti();
 			debugl1(cs, "RFIFO BUSY error");
 			printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel);
-			idev_kfree_skb(skb, FREE_READ);
+			dev_kfree_skb(skb);
 			skb = NULL;
 		} else {
 			cli();
@@ -301,8 +306,11 @@ static struct sk_buff
 					bcs->channel, chksum, stat);
 			if (stat) {
 				debugl1(cs, "FIFO CRC error");
-				idev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb(skb);
 				skb = NULL;
+#ifdef ERROR_STATISTIC
+				bcs->err_crc++;
+#endif
 			}
 		}
 	}
@@ -390,7 +398,7 @@ hfc_fill_fifo(struct BCState *bcs)
 		if (bcs->st->lli.l1writewakeup &&
 			(PACKET_NOACK != bcs->tx_skb->pkt_type))
 			bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
-		idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+		dev_kfree_skb(bcs->tx_skb);
 		bcs->tx_skb = NULL;
 	}
 	WaitForBusy(cs);
@@ -592,7 +600,7 @@ close_2bs0(struct BCState *bcs)
 		discard_queue(&bcs->rqueue);
 		discard_queue(&bcs->squeue);
 		if (bcs->tx_skb) {
-			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			dev_kfree_skb(bcs->tx_skb);
 			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		}
@@ -634,17 +642,6 @@ hfcd_bh(struct IsdnCardState *cs)
 */
 	if (!cs)
 		return;
-#if 0	
-	if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
-		if (cs->debug)
-			debugl1(cs, "D-Channel Busy cleared");
-		stptr = cs->stlist;
-		while (stptr != NULL) {
-			stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
-			stptr = stptr->next;
-		}
-	}
-#endif
 	if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
 		switch (cs->dc.hfcd.ph_state) {
 			case (0):
@@ -737,7 +734,6 @@ int receive_dmsg(struct IsdnCardState *cs)
 			while ((idx++ < rcnt) && WaitNoBusy(cs))
 				ReadReg(cs, HFCD_DATA_NODEB, cip);
 		} else if ((skb = dev_alloc_skb(rcnt - 3))) {
-			SET_SKB_FREE(skb);
 			ptr = skb_put(skb, rcnt - 3);
 			while (idx < (rcnt - 3)) {
 				cli();
@@ -752,8 +748,11 @@ int receive_dmsg(struct IsdnCardState *cs)
 				sti();
 				debugl1(cs, "RFIFO D BUSY error");
 				printk(KERN_WARNING "HFC DFIFO channel BUSY Error\n");
-				idev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb(skb);
 				skb = NULL;
+#ifdef ERROR_STATISTIC
+				cs->err_rx++;
+#endif
 			} else {
 				cli();
 				WaitNoBusy(cs);
@@ -768,8 +767,11 @@ int receive_dmsg(struct IsdnCardState *cs)
 						chksum, stat);
 				if (stat) {
 					debugl1(cs, "FIFO CRC error");
-					idev_kfree_skb(skb, FREE_READ);
+					dev_kfree_skb(skb);
 					skb = NULL;
+#ifdef ERROR_STATISTIC
+					cs->err_crc++;
+#endif
 				} else {
 					skb_queue_tail(&cs->rq, skb);
 					sched_event_D(cs, D_RCVBUFREADY);
@@ -865,7 +867,7 @@ hfc_fill_dfifo(struct IsdnCardState *cs)
 	cli();
 	WaitNoBusy(cs);
 	ReadReg(cs, HFCD_DATA, HFCD_FIFO | HFCD_F1_INC | HFCD_SEND);
-	idev_kfree_skb(cs->tx_skb, FREE_WRITE);
+	dev_kfree_skb(cs->tx_skb);
 	cs->tx_skb = NULL;
 	sti();
 	WaitForBusy(cs);
@@ -999,7 +1001,7 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val)
 					}
 					goto afterXPR;
 				} else {
-					idev_kfree_skb(cs->tx_skb, FREE_WRITE);
+					dev_kfree_skb(cs->tx_skb);
 					cs->tx_cnt = 0;
 					cs->tx_skb = NULL;
 				}
@@ -1114,32 +1116,6 @@ HFCD_l1hw(struct PStack *st, int pr, void *arg)
 			cs->hw.hfcD.mst_m |= HFCD_MASTER;
 			cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
 			break;
-#if 0
-		case (HW_TESTLOOP | REQUEST):
-			u_char val = 0;
-			if (1 & (int) arg)
-				val |= 0x0c;
-			if (2 & (int) arg)
-				val |= 0x3;
-			if (test_bit(HW_IOM1, &cs->HW_Flags)) {
-				/* IOM 1 Mode */
-				if (!val) {
-					cs->writeisac(cs, ISAC_SPCR, 0xa);
-					cs->writeisac(cs, ISAC_ADF1, 0x2);
-				} else {
-					cs->writeisac(cs, ISAC_SPCR, val);
-					cs->writeisac(cs, ISAC_ADF1, 0xa);
-				}
-			} else {
-				/* IOM 2 Mode */
-				cs->writeisac(cs, ISAC_SPCR, val);
-				if (val)
-					cs->writeisac(cs, ISAC_ADF1, 0x8);
-				else
-					cs->writeisac(cs, ISAC_ADF1, 0x0);
-			}
-			break;
-#endif
 		default:
 			if (cs->debug & L1_DEB_WARN)
 				debugl1(cs, "hfcd_l1hw unknown pr %4x", pr);
@@ -1156,24 +1132,10 @@ setstack_hfcd(struct PStack *st, struct IsdnCardState *cs)
 static void
 hfc_dbusy_timer(struct IsdnCardState *cs)
 {
-#if 0
-	struct PStack *stptr;
-	if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
-		if (cs->debug)
-			debugl1(cs, "D-Channel Busy");
-		test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
-		stptr = cs->stlist;
-		
-		while (stptr != NULL) {
-			stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
-			stptr = stptr->next;
-		}
-	}
-#endif
 }
 
-unsigned int * __init
-init_send_hfcd(int cnt)
+__initfunc(unsigned int
+*init_send_hfcd(int cnt))
 {
 	int i, *send;
 
@@ -1187,8 +1149,8 @@ init_send_hfcd(int cnt)
 	return(send);
 }
 
-void __init
-init2bds0(struct IsdnCardState *cs)
+__initfunc(void
+init2bds0(struct IsdnCardState *cs))
 {
 	cs->setstack_d = setstack_hfcd;
 	cs->dbusytimer.function = (void *) hfc_dbusy_timer;
diff --git a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c
index 71767c888d58c1deb3ca184731cf2ef98223f27a..6620b90ecee3db4bb9bc19d903358fa475242fbb 100644
--- a/drivers/isdn/hisax/hfc_2bs0.c
+++ b/drivers/isdn/hisax/hfc_2bs0.c
@@ -1,4 +1,4 @@
-/* $Id: hfc_2bs0.c,v 1.9 1999/07/01 08:11:36 keil Exp $
+/* $Id: hfc_2bs0.c,v 1.10 1999/10/14 20:25:28 keil Exp $
 
  *  specific routines for CCD's HFC 2BS0
  *
@@ -6,6 +6,9 @@
  *
  *
  * $Log: hfc_2bs0.c,v $
+ * Revision 1.10  1999/10/14 20:25:28  keil
+ * add a statistic for error monitoring
+ *
  * Revision 1.9  1999/07/01 08:11:36  keil
  * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
  *
@@ -217,12 +220,14 @@ hfc_empty_fifo(struct BCState *bcs, int count)
 		stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
 				       HFC_CHANNEL(bcs->channel));
 		WaitForBusy(cs);
+#ifdef ERROR_STATISTIC
+		bcs->err_inv++;
+#endif
 		return (NULL);
 	}
 	if (!(skb = dev_alloc_skb(count - 3)))
 		printk(KERN_WARNING "HFC: receive out of memory\n");
 	else {
-		SET_SKB_FREE(skb);
 		ptr = skb_put(skb, count - 3);
 		idx = 0;
 		cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
@@ -233,7 +238,7 @@ hfc_empty_fifo(struct BCState *bcs, int count)
 		if (idx != count - 3) {
 			debugl1(cs, "RFIFO BUSY error");
 			printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel);
-			idev_kfree_skb(skb, FREE_READ);
+			dev_kfree_skb(skb);
 			WaitNoBusy(cs);
 			stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
 					       HFC_CHANNEL(bcs->channel));
@@ -251,8 +256,11 @@ hfc_empty_fifo(struct BCState *bcs, int count)
 				bcs->channel, chksum, stat);
 		if (stat) {
 			debugl1(cs, "FIFO CRC error");
-			idev_kfree_skb(skb, FREE_READ);
+			dev_kfree_skb(skb);
 			skb = NULL;
+#ifdef ERROR_STATISTIC
+			bcs->err_crc++;
+#endif
 		}
 		WaitNoBusy(cs);
 		stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
@@ -325,7 +333,7 @@ hfc_fill_fifo(struct BCState *bcs)
 		bcs->tx_cnt -= count;
 		if (PACKET_NOACK == bcs->tx_skb->pkt_type)
 			count = -1;
-		idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+		dev_kfree_skb(bcs->tx_skb);
 		bcs->tx_skb = NULL;
 		WaitForBusy(cs);
 		WaitNoBusy(cs);
@@ -523,7 +531,7 @@ close_hfcstate(struct BCState *bcs)
 		discard_queue(&bcs->rqueue);
 		discard_queue(&bcs->squeue);
 		if (bcs->tx_skb) {
-			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			dev_kfree_skb(bcs->tx_skb);
 			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		}
@@ -559,8 +567,8 @@ setstack_hfc(struct PStack *st, struct BCState *bcs)
 	return (0);
 }
 
-void __init
-init_send(struct BCState *bcs)
+__initfunc(void
+init_send(struct BCState *bcs))
 {
 	int i;
 
@@ -573,8 +581,8 @@ init_send(struct BCState *bcs)
 		bcs->hw.hfc.send[i] = 0x1fff;
 }
 
-void __init
-inithfc(struct IsdnCardState *cs)
+__initfunc(void
+inithfc(struct IsdnCardState *cs))
 {
 	init_send(&cs->bcs[0]);
 	init_send(&cs->bcs[1]);
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index 9d8968e988dc6a95ff22effcbd943e95cc846270..518c1670aec750b74178fec28ca7ce4d5d1a9c06 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -1,4 +1,4 @@
-/* $Id: hfc_pci.c,v 1.18 1999/08/29 17:05:44 werner Exp $
+/* $Id: hfc_pci.c,v 1.23 1999/11/07 17:01:55 keil Exp $
 
  * hfc_pci.c     low level driver for CCD´s hfc-pci based cards
  *
@@ -23,6 +23,25 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: hfc_pci.c,v $
+ * Revision 1.23  1999/11/07 17:01:55  keil
+ * fix for 2.3 pci structs
+ *
+ * Revision 1.22  1999/10/10 20:14:27  werner
+ *
+ * Correct B2-chan usage in conjuntion with echo mode. First implementation of NT-leased line mode.
+ *
+ * Revision 1.21  1999/10/02 17:47:49  werner
+ *
+ * Changed init order, added correction for page alignment with shared mem
+ *
+ * Revision 1.20  1999/09/07 06:18:55  werner
+ *
+ * Added io parameter for HFC-PCI based cards. Needed only with multiple cards
+ * when initialisation/selection order needs to be set.
+ *
+ * Revision 1.19  1999/09/04 06:20:06  keil
+ * Changes from kernel set_current_state()
+ *
  * Revision 1.18  1999/08/29 17:05:44  werner
  * corrected tx_lo line setup. Datasheet is not correct.
  *
@@ -91,40 +110,40 @@
 #include "hfc_pci.h"
 #include "isdnl1.h"
 #include <linux/pci.h>
-#ifndef COMPAT_HAS_NEW_PCI
-#include <linux/bios32.h>
-#endif
 #include <linux/interrupt.h>
 
 extern const char *CardType[];
 
-static const char *hfcpci_revision = "$Revision: 1.18 $";
+static const char *hfcpci_revision = "$Revision: 1.23 $";
 
 /* table entry in the PCI devices list */
 typedef struct {
-  int vendor_id; 
-  int device_id;
-  char *vendor_name;
-  char *card_name;
-  } PCI_ENTRY;
-
-static const PCI_ENTRY id_list[] = {
-  {0x1397,0x2BD0,"CCD/Billion/Asuscom","2BD0"},
-  {0x1397,0xB000,"Billion","B000"},
-  {0x1397,0xB006,"Billion","B006"},
-  {0x1397,0xB007,"Billion","B007"},
-  {0x1397,0xB008,"Billion","B008"},
-  {0x1397,0xB009,"Billion","B009"},
-  {0x1397,0xB00A,"Billion","B00A"},
-  {0x1397,0xB00B,"Billion","B00B"},
-  {0x1397,0xB00C,"Billion","B00C"},
-  {0x1043,0x0675,"Asuscom/Askey","675"},
-  {0x0871,0xFFA2,"German telekom","T-Concept"},
-  {0x0871,0xFFA1,"German telekom","A1T"},
-  {0x1051,0x0100,"Motorola MC145575","MC145575"},
-  {0x1397,0xB100,"Seyeon","B100"},
-  {0x15B0,0x2BD0,"Zoltrix","2BD0"},
-  {0,0,NULL,NULL},      
+	int vendor_id;
+	int device_id;
+	char *vendor_name;
+	char *card_name;
+} PCI_ENTRY;
+
+#define NT_T1_COUNT 20		/* number of 3.125ms interrupts for G2 timeout */
+
+static const PCI_ENTRY id_list[] =
+{
+	{0x1397, 0x2BD0, "CCD/Billion/Asuscom", "2BD0"},
+	{0x1397, 0xB000, "Billion", "B000"},
+	{0x1397, 0xB006, "Billion", "B006"},
+	{0x1397, 0xB007, "Billion", "B007"},
+	{0x1397, 0xB008, "Billion", "B008"},
+	{0x1397, 0xB009, "Billion", "B009"},
+	{0x1397, 0xB00A, "Billion", "B00A"},
+	{0x1397, 0xB00B, "Billion", "B00B"},
+	{0x1397, 0xB00C, "Billion", "B00C"},
+	{0x1043, 0x0675, "Asuscom/Askey", "675"},
+	{0x0871, 0xFFA2, "German telekom", "T-Concept"},
+	{0x0871, 0xFFA1, "German telekom", "A1T"},
+	{0x1051, 0x0100, "Motorola MC145575", "MC145575"},
+	{0x1397, 0xB100, "Seyeon", "B100"},
+	{0x15B0, 0x2BD0, "Zoltrix", "2BD0"},
+	{0, 0, NULL, NULL},
 };
 
 
@@ -151,9 +170,21 @@ releasehfcpci(struct IsdnCardState *cs)
 void
 release_io_hfcpci(struct IsdnCardState *cs)
 {
+	int flags;
+
+	save_flags(flags);
+	cli();
+	cs->hw.hfcpci.int_m2 = 0;	/* interrupt output off ! */
+	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
+	restore_flags(flags);
+	Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET);	/* Reset On */
+	sti();
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout((30 * HZ) / 1000);	/* Timeout 30ms */
+	Write_hfc(cs, HFCPCI_CIRM, 0);	/* Reset Off */
 #if CONFIG_PCI
-	pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, 0);	/* disabe memory mapped ports + busmaster */
-#endif	/* CONFIG_PCI */
+	pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, 0);	/* disable memory mapped ports + busmaster */
+#endif				/* CONFIG_PCI */
 	releasehfcpci(cs);
 	del_timer(&cs->hw.hfcpci.timer);
 	kfree(cs->hw.hfcpci.share_start);
@@ -170,16 +201,20 @@ reset_hfcpci(struct IsdnCardState *cs)
 {
 	long flags;
 
+	save_flags(flags);
+	cli();
 	pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO);	/* enable memory mapped ports, disable busmaster */
+	cs->hw.hfcpci.int_m2 = 0;	/* interrupt output off ! */
+	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
+
 	printk(KERN_INFO "HFC_PCI: resetting card\n");
 	pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO + PCI_ENA_MASTER);	/* enable memory ports + busmaster */
 	Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET);	/* Reset On */
-	save_flags(flags);
 	sti();
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((30 * HZ) / 1000);	/* Timeout 30ms */
 	Write_hfc(cs, HFCPCI_CIRM, 0);	/* Reset Off */
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((20 * HZ) / 1000);	/* Timeout 20ms */
 	if (Read_hfc(cs, HFCPCI_STATUS) & 2)
 		printk(KERN_WARNING "HFC-PCI init bit busy\n");
@@ -187,25 +222,23 @@ reset_hfcpci(struct IsdnCardState *cs)
 	cs->hw.hfcpci.fifo_en = 0x30;	/* only D fifos enabled */
 	Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
 
-	cs->hw.hfcpci.trm = 0 + HFCPCI_BTRANS_THRESMASK; /* no echo connect , threshold */
+	cs->hw.hfcpci.trm = 0 + HFCPCI_BTRANS_THRESMASK;	/* no echo connect , threshold */
 	Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
 
 	Write_hfc(cs, HFCPCI_CLKDEL, 0x0e);	/* ST-Bit delay for TE-Mode */
 	cs->hw.hfcpci.sctrl_e = HFCPCI_AUTO_AWAKE;
 	Write_hfc(cs, HFCPCI_SCTRL_E, cs->hw.hfcpci.sctrl_e);	/* S/T Auto awake */
-	cs->hw.hfcpci.bswapped = 0; /* no exchange */
+	cs->hw.hfcpci.bswapped = 0;	/* no exchange */
+	cs->hw.hfcpci.nt_mode = 0;	/* we are in TE mode */
 	cs->hw.hfcpci.ctmt = HFCPCI_TIM3_125 | HFCPCI_AUTO_TIMER;
 	Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt);
 
-	cs->hw.hfcpci.int_m2 = HFCPCI_IRQ_ENABLE;
-	cs->hw.hfcpci.int_m1 = HFCPCI_INTS_DTRANS | HFCPCI_INTS_DREC | 
-	                       HFCPCI_INTS_L1STATE | HFCPCI_CLTIMER;
+	cs->hw.hfcpci.int_m1 = HFCPCI_INTS_DTRANS | HFCPCI_INTS_DREC |
+	    HFCPCI_INTS_L1STATE | HFCPCI_INTS_TIMER;
 	Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
-	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
 
 	/* Clear already pending ints */
 	if (Read_hfc(cs, HFCPCI_INT_S1));
-	if (Read_hfc(cs, HFCPCI_INT_S2));
 
 	Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 2);	/* HFC ST 2 */
 	udelay(10);
@@ -213,24 +246,29 @@ reset_hfcpci(struct IsdnCardState *cs)
 	cs->hw.hfcpci.mst_m = HFCPCI_MASTER;	/* HFC Master Mode */
 
 	Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
-	cs->hw.hfcpci.sctrl = 0x40; /* set tx_lo mode, error in datasheet ! */
+	cs->hw.hfcpci.sctrl = 0x40;	/* set tx_lo mode, error in datasheet ! */
 	Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);
 	cs->hw.hfcpci.sctrl_r = 0;
 	Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r);
 
-        /* Init GCI/IOM2 in master mode */
+	/* Init GCI/IOM2 in master mode */
 	/* Slots 0 and 1 are set for B-chan 1 and 2 */
 	/* D- and monitor/CI channel are not enabled */
 	/* STIO1 is used as output for data, B1+B2 from ST->IOM+HFC */
-	/* STIO2 is used as data input, B1+B2 from IOM->ST */ 
+	/* STIO2 is used as data input, B1+B2 from IOM->ST */
 	/* ST B-channel send disabled -> continous 1s */
 	/* The IOM slots are always enabled */
-	cs->hw.hfcpci.conn = 0x36; /* set data flow directions */
+	cs->hw.hfcpci.conn = 0x36;	/* set data flow directions */
 	Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
-	Write_hfc(cs, HFCPCI_B1_SSL, 0x80); /* B1-Slot 0 STIO1 out enabled */
-	Write_hfc(cs, HFCPCI_B2_SSL, 0x81); /* B2-Slot 1 STIO1 out enabled */
-	Write_hfc(cs, HFCPCI_B1_RSL, 0x80); /* B1-Slot 0 STIO2 in enabled */
-	Write_hfc(cs, HFCPCI_B2_RSL, 0x81); /* B2-Slot 1 STIO2 in enabled */
+	Write_hfc(cs, HFCPCI_B1_SSL, 0x80);	/* B1-Slot 0 STIO1 out enabled */
+	Write_hfc(cs, HFCPCI_B2_SSL, 0x81);	/* B2-Slot 1 STIO1 out enabled */
+	Write_hfc(cs, HFCPCI_B1_RSL, 0x80);	/* B1-Slot 0 STIO2 in enabled */
+	Write_hfc(cs, HFCPCI_B2_RSL, 0x81);	/* B2-Slot 1 STIO2 in enabled */
+
+	/* Finally enable IRQ output */
+	cs->hw.hfcpci.int_m2 = HFCPCI_IRQ_ENABLE;
+	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
+	if (Read_hfc(cs, HFCPCI_INT_S2));
 	restore_flags(flags);
 }
 
@@ -317,12 +355,11 @@ hfcpci_empty_fifo(struct BCState *bcs, bzfifo_type * bz, u_char * bdata, int cou
 	} else if (!(skb = dev_alloc_skb(count - 3)))
 		printk(KERN_WARNING "HFCPCI: receive out of memory\n");
 	else {
-		SET_SKB_FREE(skb);
 		total = count;
 		count -= 3;
 		ptr = skb_put(skb, count);
 
- 		if (zp->z2 + count <= B_FIFO_SIZE + B_SUB_VAL)
+		if (zp->z2 + count <= B_FIFO_SIZE + B_SUB_VAL)
 			maxlen = count;		/* complete transfer */
 		else
 			maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2;	/* maximum */
@@ -381,7 +418,6 @@ receive_dmsg(struct IsdnCardState *cs)
 			df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1);	/* next buffer */
 			df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + rcnt) & (D_FIFO_SIZE - 1);
 		} else if ((skb = dev_alloc_skb(rcnt - 3))) {
-			SET_SKB_FREE(skb);
 			total = rcnt;
 			rcnt -= 3;
 			ptr = skb_put(skb, rcnt);
@@ -415,55 +451,56 @@ receive_dmsg(struct IsdnCardState *cs)
 /*******************************************************************************/
 /* check for transparent receive data and read max one threshold size if avail */
 /*******************************************************************************/
-int hfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type *bz, u_char *bdata)
-{ unsigned short *z1r, *z2r;
-  int new_z2, fcnt, maxlen;
-  struct sk_buff *skb;
-  u_char *ptr, *ptr1;
+int
+hfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type * bz, u_char * bdata)
+{
+	unsigned short *z1r, *z2r;
+	int new_z2, fcnt, maxlen;
+	struct sk_buff *skb;
+	u_char *ptr, *ptr1;
 
-  z1r = &bz->za[MAX_B_FRAMES].z1; /* pointer to z reg */
-  z2r = z1r + 1; 
+	z1r = &bz->za[MAX_B_FRAMES].z1;		/* pointer to z reg */
+	z2r = z1r + 1;
 
-  if (!(fcnt = *z1r - *z2r)) 
-    return(0); /* no data avail */
+	if (!(fcnt = *z1r - *z2r))
+		return (0);	/* no data avail */
 
-  if (fcnt <= 0) 
-    fcnt += B_FIFO_SIZE; /* bytes actually buffered */  
-  if (fcnt > HFCPCI_BTRANS_THRESHOLD)
-    fcnt = HFCPCI_BTRANS_THRESHOLD; /* limit size */
+	if (fcnt <= 0)
+		fcnt += B_FIFO_SIZE;	/* bytes actually buffered */
+	if (fcnt > HFCPCI_BTRANS_THRESHOLD)
+		fcnt = HFCPCI_BTRANS_THRESHOLD;		/* limit size */
 
-  new_z2 = *z2r + fcnt;	/* new position in fifo */
-  if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
-    new_z2 -= B_FIFO_SIZE;	/* buffer wrap */
+	new_z2 = *z2r + fcnt;	/* new position in fifo */
+	if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
+		new_z2 -= B_FIFO_SIZE;	/* buffer wrap */
 
-  if (!(skb = dev_alloc_skb(fcnt)))
+	if (!(skb = dev_alloc_skb(fcnt)))
 		printk(KERN_WARNING "HFCPCI: receive out of memory\n");
-  else {
-    SET_SKB_FREE(skb);
-    ptr = skb_put(skb, fcnt);
-    if (*z2r + fcnt <= B_FIFO_SIZE + B_SUB_VAL)
-      maxlen = fcnt; /* complete transfer */
-    else
-      maxlen = B_FIFO_SIZE + B_SUB_VAL - *z2r;	/* maximum */
-
-    ptr1 = bdata + (*z2r - B_SUB_VAL);	/* start of data */
-    memcpy(ptr, ptr1, maxlen);	/* copy data */
-    fcnt -= maxlen;
-
-    if (fcnt) {	/* rest remaining */
-      ptr += maxlen;
-      ptr1 = bdata;	/* start of buffer */
-      memcpy(ptr, ptr1, fcnt);	/* rest */
-    }
-    cli();
-    skb_queue_tail(&bcs->rqueue, skb);
-    sti();
-    hfcpci_sched_event(bcs, B_RCVBUFREADY); 
-  }
-  
-  *z2r = new_z2; /* new position */
-  return(1);
-} /* hfcpci_empty_fifo_trans */ 
+	else {
+		ptr = skb_put(skb, fcnt);
+		if (*z2r + fcnt <= B_FIFO_SIZE + B_SUB_VAL)
+			maxlen = fcnt;	/* complete transfer */
+		else
+			maxlen = B_FIFO_SIZE + B_SUB_VAL - *z2r;	/* maximum */
+
+		ptr1 = bdata + (*z2r - B_SUB_VAL);	/* start of data */
+		memcpy(ptr, ptr1, maxlen);	/* copy data */
+		fcnt -= maxlen;
+
+		if (fcnt) {	/* rest remaining */
+			ptr += maxlen;
+			ptr1 = bdata;	/* start of buffer */
+			memcpy(ptr, ptr1, fcnt);	/* rest */
+		}
+		cli();
+		skb_queue_tail(&bcs->rqueue, skb);
+		sti();
+		hfcpci_sched_event(bcs, B_RCVBUFREADY);
+	}
+
+	*z2r = new_z2;		/* new position */
+	return (1);
+}				/* hfcpci_empty_fifo_trans */
 
 /**********************************/
 /* B-channel main receive routine */
@@ -524,11 +561,10 @@ main_rec_hfcpci(struct BCState *bcs)
 			receive = 1;
 		else
 			receive = 0;
-	} else 
-	  if (bcs->mode == L1_MODE_TRANS)
-	    receive = hfcpci_empty_fifo_trans(bcs, bz, bdata);
-	  else
-	    receive = 0;
+	} else if (bcs->mode == L1_MODE_TRANS)
+		receive = hfcpci_empty_fifo_trans(bcs, bz, bdata);
+	else
+		receive = 0;
 	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 	if (count && receive)
 		goto Begin;
@@ -603,7 +639,7 @@ hfcpci_fill_dfifo(struct IsdnCardState *cs)
 	df->f1 = new_f1;	/* next frame */
 	restore_flags(flags);
 
-	idev_kfree_skb(cs->tx_skb, FREE_WRITE);
+	dev_kfree_skb(cs->tx_skb);
 	cs->tx_skb = NULL;
 	return;
 }
@@ -620,7 +656,7 @@ hfcpci_fill_fifo(struct BCState *bcs)
 	bzfifo_type *bz;
 	u_char *bdata;
 	u_char new_f1, *src, *dst;
-        unsigned short *z1t, *z2t;
+	unsigned short *z1t, *z2t;
 
 	if (!bcs->tx_skb)
 		return;
@@ -639,57 +675,53 @@ hfcpci_fill_fifo(struct BCState *bcs)
 	}
 
 	if (bcs->mode == L1_MODE_TRANS) {
-	  z1t = &bz->za[MAX_B_FRAMES].z1;
-	  z2t = z1t + 1;
-	  if (cs->debug & L1_DEB_HSCX)
-	          debugl1(cs, "hfcpci_fill_fifo_trans %d z1(%x) z2(%x)",
-		  bcs->channel, *z1t, *z2t);
-	  fcnt = *z2t - *z1t;
-	  if (fcnt <= 0)
-	          fcnt += B_FIFO_SIZE;	/* fcnt contains available bytes in fifo */
-	  fcnt = B_FIFO_SIZE - fcnt; /* remaining bytes to send */
-
-	  while ((fcnt < 2 * HFCPCI_BTRANS_THRESHOLD) && (bcs->tx_skb)) {
-	    if (bcs->tx_skb->len < B_FIFO_SIZE - fcnt) { 
-	      /* data is suitable for fifo */
-	      count = bcs->tx_skb->len;
-
-	      new_z1 = *z1t + count;	/* new buffer Position */
-	      if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
-		new_z1 -= B_FIFO_SIZE;	/* buffer wrap */
-	      src = bcs->tx_skb->data;	/* source pointer */
-	      dst = bdata + (*z1t - B_SUB_VAL);
-	      maxlen = (B_FIFO_SIZE + B_SUB_VAL) - *z1t; /* end of fifo */
-	      if (maxlen > count)
-		maxlen = count;	/* limit size */
-	      memcpy(dst, src, maxlen);	/* first copy */
-
-	      count -= maxlen;	/* remaining bytes */
-	      if (count) {
-		dst = bdata;	/* start of buffer */
-		src += maxlen;	/* new position */
-		memcpy(dst, src, count);
-	      }
-	      bcs->tx_cnt -= bcs->tx_skb->len;
-	      fcnt += bcs->tx_skb->len;
-	      *z1t = new_z1; /* now send data */
-	    }
-            else 
-	      if (cs->debug & L1_DEB_HSCX)
-		debugl1(cs, "hfcpci_fill_fifo_trans %d frame length %d discarded",
-			bcs->channel, bcs->tx_skb->len);
-
-	    idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
-            cli();
-            bcs->tx_skb = skb_dequeue(&bcs->squeue); /* fetch next data */
-            sti();
-	  }  
-	  test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-	  restore_flags(flags);
-	  return;
+		z1t = &bz->za[MAX_B_FRAMES].z1;
+		z2t = z1t + 1;
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfcpci_fill_fifo_trans %d z1(%x) z2(%x)",
+				bcs->channel, *z1t, *z2t);
+		fcnt = *z2t - *z1t;
+		if (fcnt <= 0)
+			fcnt += B_FIFO_SIZE;	/* fcnt contains available bytes in fifo */
+		fcnt = B_FIFO_SIZE - fcnt;	/* remaining bytes to send */
+
+		while ((fcnt < 2 * HFCPCI_BTRANS_THRESHOLD) && (bcs->tx_skb)) {
+			if (bcs->tx_skb->len < B_FIFO_SIZE - fcnt) {
+				/* data is suitable for fifo */
+				count = bcs->tx_skb->len;
+
+				new_z1 = *z1t + count;	/* new buffer Position */
+				if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
+					new_z1 -= B_FIFO_SIZE;	/* buffer wrap */
+				src = bcs->tx_skb->data;	/* source pointer */
+				dst = bdata + (*z1t - B_SUB_VAL);
+				maxlen = (B_FIFO_SIZE + B_SUB_VAL) - *z1t;	/* end of fifo */
+				if (maxlen > count)
+					maxlen = count;		/* limit size */
+				memcpy(dst, src, maxlen);	/* first copy */
+
+				count -= maxlen;	/* remaining bytes */
+				if (count) {
+					dst = bdata;	/* start of buffer */
+					src += maxlen;	/* new position */
+					memcpy(dst, src, count);
+				}
+				bcs->tx_cnt -= bcs->tx_skb->len;
+				fcnt += bcs->tx_skb->len;
+				*z1t = new_z1;	/* now send data */
+			} else if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "hfcpci_fill_fifo_trans %d frame length %d discarded",
+					bcs->channel, bcs->tx_skb->len);
+
+			dev_kfree_skb(bcs->tx_skb);
+			cli();
+			bcs->tx_skb = skb_dequeue(&bcs->squeue);	/* fetch next data */
+			sti();
+		}
+		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+		restore_flags(flags);
+		return;
 	}
-
-
 	if (cs->debug & L1_DEB_HSCX)
 		debugl1(cs, "hfcpci_fill_fifo_hdlc %d f1(%d) f2(%d) z1(f1)(%x)",
 			bcs->channel, bz->f1, bz->f2,
@@ -749,57 +781,113 @@ hfcpci_fill_fifo(struct BCState *bcs)
 	bz->f1 = new_f1;	/* next frame */
 	restore_flags(flags);
 
-	idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+	dev_kfree_skb(bcs->tx_skb);
 	bcs->tx_skb = NULL;
 	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 	return;
 }
 
+/**********************************************/
+/* D-channel l1 state call for leased NT-mode */
+/**********************************************/
+static void
+dch_nt_l2l1(struct PStack *st, int pr, void *arg)
+{
+	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
+
+	switch (pr) {
+		case (PH_DATA | REQUEST):
+		case (PH_PULL | REQUEST):
+		case (PH_PULL | INDICATION):
+			st->l1.l1hw(st, pr, arg);
+			break;
+		case (PH_ACTIVATE | REQUEST):
+			st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
+			break;
+		case (PH_TESTLOOP | REQUEST):
+			if (1 & (long) arg)
+				debugl1(cs, "PH_TEST_LOOP B1");
+			if (2 & (long) arg)
+				debugl1(cs, "PH_TEST_LOOP B2");
+			if (!(3 & (long) arg))
+				debugl1(cs, "PH_TEST_LOOP DISABLED");
+			st->l1.l1hw(st, HW_TESTLOOP | REQUEST, arg);
+			break;
+		default:
+			if (cs->debug)
+				debugl1(cs, "dch_nt_l2l1 msg %04X unhandled", pr);
+			break;
+	}
+}
+
+
+
 /***********************/
 /* set/reset echo mode */
-/***********************/ 
+/***********************/
 static int
-hfcpci_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic)
+hfcpci_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic)
 {
-  int flags;
-  int i = *(unsigned int *) ic->parm.num;
-  
-  if (cs->chanlimit > 1)
-    return(-EINVAL);
-
-  save_flags(flags);
-  cli();
-  if (i) {
-    cs->logecho = 1;
-    cs->hw.hfcpci.trm |= 0x20; /* enable echo chan */
-    cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_B2REC;
-    cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2RX;
-  }
-  else {
-    cs->logecho = 0;
-    cs->hw.hfcpci.trm &= ~0x20; /* enable echo chan */
-    cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_B2REC;
-    cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2RX;
-  }
-    cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA;
-    cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA;
-    cs->hw.hfcpci.conn |= 0x10; /* B2-IOM -> B2-ST */ 
-    cs->hw.hfcpci.ctmt &= ~2;
-  Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt);
-  Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r);
-  Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);
-  Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
-  Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
-  Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
-  Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
-  restore_flags(flags);
-  return(0);
-} /* hfcpci_auxcmd */ 
+	int flags;
+	int i = *(unsigned int *) ic->parm.num;
+
+	if ((ic->arg == 98) &&
+	    (!(cs->hw.hfcpci.int_m1 & (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC + HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC)))) {
+		save_flags(flags);
+		cli();
+		Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 0);	/* HFC ST G0 */
+		udelay(10);
+		cs->hw.hfcpci.sctrl |= SCTRL_MODE_NT;
+		Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);	/* set NT-mode */
+		udelay(10);
+		Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 1);	/* HFC ST G1 */
+		udelay(10);
+		Write_hfc(cs, HFCPCI_STATES, 1 | HFCPCI_ACTIVATE | HFCPCI_DO_ACTION);
+		cs->dc.hfcpci.ph_state = 1;
+		cs->hw.hfcpci.nt_mode = 1;
+		cs->hw.hfcpci.nt_timer = 0;
+		cs->stlist->l2.l2l1 = dch_nt_l2l1;
+		restore_flags(flags);
+		debugl1(cs, "NT mode activated");
+		return (0);
+	}
+	if ((cs->chanlimit > 1) || (cs->hw.hfcpci.bswapped) ||
+	    (cs->hw.hfcpci.nt_mode) || (ic->arg != 12))
+		return (-EINVAL);
+
+	save_flags(flags);
+	cli();
+	if (i) {
+		cs->logecho = 1;
+		cs->hw.hfcpci.trm |= 0x20;	/* enable echo chan */
+		cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_B2REC;
+		cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2RX;
+	} else {
+		cs->logecho = 0;
+		cs->hw.hfcpci.trm &= ~0x20;	/* disable echo chan */
+		cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_B2REC;
+		cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2RX;
+	}
+	cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA;
+	cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA;
+	cs->hw.hfcpci.conn |= 0x10;	/* B2-IOM -> B2-ST */
+	cs->hw.hfcpci.ctmt &= ~2;
+	Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt);
+	Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r);
+	Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);
+	Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
+	Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
+	Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
+	Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+	restore_flags(flags);
+	return (0);
+}				/* hfcpci_auxcmd */
 
 /*****************************/
 /* E-channel receive routine */
 /*****************************/
-static void receive_emsg(struct IsdnCardState *cs)
+static void
+receive_emsg(struct IsdnCardState *cs)
 {
 	long flags;
 	int rcnt;
@@ -836,55 +924,54 @@ static void receive_emsg(struct IsdnCardState *cs)
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "hfcpci e_rec z1(%x) z2(%x) cnt(%d)",
 				zp->z1, zp->z2, rcnt);
-                new_z2 = zp->z2 + rcnt; /* new position in fifo */
+		new_z2 = zp->z2 + rcnt;		/* new position in fifo */
 		if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
-		  new_z2 -= B_FIFO_SIZE; /* buffer wrap */
+			new_z2 -= B_FIFO_SIZE;	/* buffer wrap */
 		new_f2 = (bz->f2 + 1) & MAX_B_FRAMES;
-	        if ((rcnt > 256 + 3) || (count < 4) ||
+		if ((rcnt > 256 + 3) || (count < 4) ||
 		    (*(bdata + (zp->z1 - B_SUB_VAL)))) {
-		  if (cs->debug & L1_DEB_WARN)
-			debugl1(cs, "hfcpci_empty_echan: incoming packet invalid length %d or crc", rcnt);
-		  bz->za[new_f2].z2 = new_z2;
-		  bz->f2 = new_f2;	/* next buffer */
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "hfcpci_empty_echan: incoming packet invalid length %d or crc", rcnt);
+			bz->za[new_f2].z2 = new_z2;
+			bz->f2 = new_f2;	/* next buffer */
 		} else {
-		    total = rcnt;
-		    rcnt -= 3;
-		    ptr = e_buffer;
-
-		    if (zp->z2 <= B_FIFO_SIZE + B_SUB_VAL)
-			maxlen = rcnt;		/* complete transfer */
-		    else
-			maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2;	/* maximum */
+			total = rcnt;
+			rcnt -= 3;
+			ptr = e_buffer;
 
-		    ptr1 = bdata + (zp->z2 - B_SUB_VAL);	/* start of data */
-		    memcpy(ptr, ptr1, maxlen);	/* copy data */
-		    rcnt -= maxlen;
+			if (zp->z2 <= B_FIFO_SIZE + B_SUB_VAL)
+				maxlen = rcnt;	/* complete transfer */
+			else
+				maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2;	/* maximum */
 
-		    if (rcnt) {	/* rest remaining */
-			ptr += maxlen;
-			ptr1 = bdata;	/* start of buffer */
-			memcpy(ptr, ptr1, rcnt);	/* rest */
-		    }
-		    bz->za[new_f2].z2 = new_z2;
-		    bz->f2 = new_f2;	/* next buffer */
-		    if (cs->debug & DEB_DLOG_HEX) {
-		      	ptr = cs->dlog;
-			if ((total - 3) < MAX_DLOG_SPACE / 3 - 10) {
-			  *ptr++ = 'E';
-			  *ptr++ = 'C';
-			  *ptr++ = 'H';
-			  *ptr++ = 'O';
-			  *ptr++ = ':';
-			  ptr += QuickHex(ptr, e_buffer, total - 3);
-			  ptr--;
-			  *ptr++ = '\n';
-			  *ptr = 0;
-			  HiSax_putstatus(cs, NULL, cs->dlog);
-			} else
-			  HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", total - 3);
-		    }
+			ptr1 = bdata + (zp->z2 - B_SUB_VAL);	/* start of data */
+			memcpy(ptr, ptr1, maxlen);	/* copy data */
+			rcnt -= maxlen;
 
-	}
+			if (rcnt) {	/* rest remaining */
+				ptr += maxlen;
+				ptr1 = bdata;	/* start of buffer */
+				memcpy(ptr, ptr1, rcnt);	/* rest */
+			}
+			bz->za[new_f2].z2 = new_z2;
+			bz->f2 = new_f2;	/* next buffer */
+			if (cs->debug & DEB_DLOG_HEX) {
+				ptr = cs->dlog;
+				if ((total - 3) < MAX_DLOG_SPACE / 3 - 10) {
+					*ptr++ = 'E';
+					*ptr++ = 'C';
+					*ptr++ = 'H';
+					*ptr++ = 'O';
+					*ptr++ = ':';
+					ptr += QuickHex(ptr, e_buffer, total - 3);
+					ptr--;
+					*ptr++ = '\n';
+					*ptr = 0;
+					HiSax_putstatus(cs, NULL, cs->dlog);
+				} else
+					HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", total - 3);
+			}
+		}
 
 		rcnt = bz->f1 - bz->f2;
 		if (rcnt < 0)
@@ -900,7 +987,7 @@ static void receive_emsg(struct IsdnCardState *cs)
 		goto Begin;
 	restore_flags(flags);
 	return;
-} /* receive_emsg */
+}				/* receive_emsg */
 
 /*********************/
 /* Interrupt handler */
@@ -919,6 +1006,9 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 		printk(KERN_WARNING "HFC-PCI: Spurious interrupt!\n");
 		return;
 	}
+	if (!(cs->hw.hfcpci.int_m2 & 0x08))
+		return;		/* not initialised */
+
 	if (HFCPCI_ANYINT & (stat = Read_hfc(cs, HFCPCI_STATUS))) {
 		val = Read_hfc(cs, HFCPCI_INT_S1);
 		if (cs->debug & L1_DEB_ISAC)
@@ -931,7 +1021,7 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 			test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
 			"locked" : "unlocked");
 	val &= cs->hw.hfcpci.int_m1;
-	if (val & 0x40) {	/* TE state machine irq */
+	if (val & 0x40) {	/* state machine irq */
 		exval = Read_hfc(cs, HFCPCI_STATES) & 0xf;
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcpci.ph_state,
@@ -940,6 +1030,14 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 		sched_event_D_pci(cs, D_L1STATECHANGE);
 		val &= ~0x40;
 	}
+	if (val & 0x80) {	/* timer irq */
+		if (cs->hw.hfcpci.nt_mode) {
+			if ((--cs->hw.hfcpci.nt_timer) < 0)
+				sched_event_D_pci(cs, D_L1STATECHANGE);
+		}
+		val &= ~0x80;
+		Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER);
+	}
 	while (val) {
 		save_flags(flags);
 		cli();
@@ -954,24 +1052,23 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 			cs->hw.hfcpci.int_s1 = exval;
 		}
 		if (val & 0x08) {
-			if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1:0))) {
+			if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1 : 0))) {
 				if (cs->debug)
 					debugl1(cs, "hfcpci spurious 0x08 IRQ");
 			} else
 				main_rec_hfcpci(bcs);
 		}
-		if (val & 0x10) { 
-		        if (cs->logecho)
-			  receive_emsg(cs);
-			else    
-			if (!(bcs = Sel_BCS(cs, 1))) {
+		if (val & 0x10) {
+			if (cs->logecho)
+				receive_emsg(cs);
+			else if (!(bcs = Sel_BCS(cs, 1))) {
 				if (cs->debug)
 					debugl1(cs, "hfcpci spurious 0x10 IRQ");
 			} else
 				main_rec_hfcpci(bcs);
 		}
 		if (val & 0x01) {
-			if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1:0))) {
+			if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1 : 0))) {
 				if (cs->debug)
 					debugl1(cs, "hfcpci spurious 0x01 IRQ");
 			} else {
@@ -1036,7 +1133,7 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 					}
 					goto afterXPR;
 				} else {
-					idev_kfree_skb(cs->tx_skb, FREE_WRITE);
+					dev_kfree_skb(cs->tx_skb);
 					cs->tx_cnt = 0;
 					cs->tx_skb = NULL;
 				}
@@ -1070,20 +1167,6 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 static void
 hfcpci_dbusy_timer(struct IsdnCardState *cs)
 {
-#if 0
-	struct PStack *stptr;
-	if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
-		if (cs->debug)
-			debugl1(cs, "D-Channel Busy");
-		test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
-		stptr = cs->stlist;
-
-		while (stptr != NULL) {
-			stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
-			stptr = stptr->next;
-		}
-	}
-#endif
 }
 
 /*************************************/
@@ -1094,6 +1177,7 @@ HFCPCI_l1hw(struct PStack *st, int pr, void *arg)
 {
 	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
 	struct sk_buff *skb = arg;
+	int flags;
 
 	switch (pr) {
 		case (PH_DATA | REQUEST):
@@ -1169,39 +1253,46 @@ HFCPCI_l1hw(struct PStack *st, int pr, void *arg)
 			Write_hfc(cs, HFCPCI_STATES, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION);
 			break;
 		case (HW_DEACTIVATE | REQUEST):
-      			cs->hw.hfcpci.mst_m &= ~HFCPCI_MASTER;
+			cs->hw.hfcpci.mst_m &= ~HFCPCI_MASTER;
 			Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
 			break;
 		case (HW_INFO3 | REQUEST):
 			cs->hw.hfcpci.mst_m |= HFCPCI_MASTER;
 			Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
 			break;
-#if 0
 		case (HW_TESTLOOP | REQUEST):
-			u_char val = 0;
-			if (1 & (int) arg)
-				val |= 0x0c;
-			if (2 & (int) arg)
-				val |= 0x3;
-			if (test_bit(HW_IOM1, &cs->HW_Flags)) {
-				/* IOM 1 Mode */
-				if (!val) {
-					cs->writeisac(cs, ISAC_SPCR, 0xa);
-					cs->writeisac(cs, ISAC_ADF1, 0x2);
-				} else {
-					cs->writeisac(cs, ISAC_SPCR, val);
-					cs->writeisac(cs, ISAC_ADF1, 0xa);
-				}
-			} else {
-				/* IOM 2 Mode */
-				cs->writeisac(cs, ISAC_SPCR, val);
-				if (val)
-					cs->writeisac(cs, ISAC_ADF1, 0x8);
-				else
-					cs->writeisac(cs, ISAC_ADF1, 0x0);
+			switch ((int) arg) {
+				case (1):
+					Write_hfc(cs, HFCPCI_B1_SSL, 0x80);	/* tx slot */
+					Write_hfc(cs, HFCPCI_B1_RSL, 0x80);	/* rx slot */
+					save_flags(flags);
+					cli();
+					cs->hw.hfcpci.conn = (cs->hw.hfcpci.conn & ~7) | 1;
+					Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
+					restore_flags(flags);
+					break;
+
+				case (2):
+					Write_hfc(cs, HFCPCI_B2_SSL, 0x81);	/* tx slot */
+					Write_hfc(cs, HFCPCI_B2_RSL, 0x81);	/* rx slot */
+					save_flags(flags);
+					cli();
+					cs->hw.hfcpci.conn = (cs->hw.hfcpci.conn & ~0x38) | 0x08;
+					Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
+					restore_flags(flags);
+					break;
+
+				default:
+					if (cs->debug & L1_DEB_WARN)
+						debugl1(cs, "hfcpci_l1hw loop invalid %4x", (int) arg);
+					return;
 			}
+			save_flags(flags);
+			cli();
+			cs->hw.hfcpci.trm |= 0x80;	/* enable IOM-loop */
+			Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
+			restore_flags(flags);
 			break;
-#endif
 		default:
 			if (cs->debug & L1_DEB_WARN)
 				debugl1(cs, "hfcpci_l1hw unknown pr %4x", pr);
@@ -1241,113 +1332,127 @@ mode_hfcpci(struct BCState *bcs, int mode, int bc)
 {
 	struct IsdnCardState *cs = bcs->cs;
 	bzfifo_type *bzr, *bzt;
-	int flags;
+	int flags, fifo2;
 
 	if (cs->debug & L1_DEB_HSCX)
 		debugl1(cs, "HFCPCI bchannel mode %d bchan %d/%d",
 			mode, bc, bcs->channel);
 	bcs->mode = mode;
 	bcs->channel = bc;
-	if (cs->chanlimit > 1) { 
-	  cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */
-	  cs->hw.hfcpci.sctrl_e &= ~0x80; 
-	}
-	else {
-	  if (bc) {
-	    cs->hw.hfcpci.bswapped = 1; /* B1 and B2 exchanged */
-	    cs->hw.hfcpci.sctrl_e |= 0x80;
-	    bc = 0; /* B1 controller used */
-	  }
-	  else {
-	    cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */
-	    cs->hw.hfcpci.sctrl_e &= ~0x80; 
-	  }  
-	}  
+	fifo2 = bc;
 	save_flags(flags);
 	cli();
+	if (cs->chanlimit > 1) {
+		cs->hw.hfcpci.bswapped = 0;	/* B1 and B2 normal mode */
+		cs->hw.hfcpci.sctrl_e &= ~0x80;
+	} else {
+		if (bc) {
+			if (mode != L1_MODE_NULL) {
+				cs->hw.hfcpci.bswapped = 1;	/* B1 and B2 exchanged */
+				cs->hw.hfcpci.sctrl_e |= 0x80;
+			} else {
+				cs->hw.hfcpci.bswapped = 0;	/* B1 and B2 normal mode */
+				cs->hw.hfcpci.sctrl_e &= ~0x80;
+			}
+			fifo2 = 0;
+		} else {
+			cs->hw.hfcpci.bswapped = 0;	/* B1 and B2 normal mode */
+			cs->hw.hfcpci.sctrl_e &= ~0x80;
+		}
+	}
 	switch (mode) {
 		case (L1_MODE_NULL):
 			if (bc) {
 				cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA;
 				cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA;
-				cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2;
-				cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC);
 			} else {
 				cs->hw.hfcpci.sctrl &= ~SCTRL_B1_ENA;
 				cs->hw.hfcpci.sctrl_r &= ~SCTRL_B1_ENA;
+			}
+			if (fifo2) {
+				cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2;
+				cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
+			} else {
 				cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B1;
-				cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC);
+				cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
 			}
 			break;
 		case (L1_MODE_TRANS):
 			if (bc) {
-				cs->hw.hfcpci.ctmt |= 2;
-				cs->hw.hfcpci.conn &= ~0x18;
 				cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA;
 				cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA;
-				cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2;
-				cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC);
-		                bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2;
-		                bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b2;
 			} else {
-				cs->hw.hfcpci.ctmt |= 1;
-				cs->hw.hfcpci.conn &= ~0x03;
 				cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA;
 				cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA;
+			}
+			if (fifo2) {
+				cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2;
+				cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
+				cs->hw.hfcpci.ctmt |= 2;
+				cs->hw.hfcpci.conn &= ~0x18;
+				bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2;
+				bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b2;
+			} else {
 				cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1;
-				cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC);
-		                bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b1;
-		                bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b1;
+				cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
+				cs->hw.hfcpci.ctmt |= 1;
+				cs->hw.hfcpci.conn &= ~0x03;
+				bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b1;
+				bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b1;
 			}
 			bzr->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1;
-                        bzr->za[MAX_B_FRAMES].z2 = bzr->za[MAX_B_FRAMES].z1; 
+			bzr->za[MAX_B_FRAMES].z2 = bzr->za[MAX_B_FRAMES].z1;
 			bzr->f1 = MAX_B_FRAMES;
-			bzr->f2 = bzr->f1; /* init F pointers to remain constant */
+			bzr->f2 = bzr->f1;	/* init F pointers to remain constant */
 			bzt->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1;
-                        bzt->za[MAX_B_FRAMES].z2 = bzt->za[MAX_B_FRAMES].z1; 
+			bzt->za[MAX_B_FRAMES].z2 = bzt->za[MAX_B_FRAMES].z1;
 			bzt->f1 = MAX_B_FRAMES;
-			bzt->f2 = bzt->f1; /* init F pointers to remain constant */
+			bzt->f2 = bzt->f1;	/* init F pointers to remain constant */
 			break;
 		case (L1_MODE_HDLC):
 			if (bc) {
-				cs->hw.hfcpci.ctmt &= ~2;
-				cs->hw.hfcpci.conn &= ~0x18;
 				cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA;
 				cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA;
-				cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2;
-				cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC);
 			} else {
-				cs->hw.hfcpci.ctmt &= ~1;
-				cs->hw.hfcpci.conn &= ~0x3;
 				cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA;
 				cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA;
+			}
+			if (fifo2) {
+				cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2;
+				cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
+				cs->hw.hfcpci.ctmt &= ~2;
+				cs->hw.hfcpci.conn &= ~0x18;
+			} else {
 				cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1;
-				cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC);
+				cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
+				cs->hw.hfcpci.ctmt &= ~1;
+				cs->hw.hfcpci.conn &= ~0x03;
 			}
 			break;
 		case (L1_MODE_EXTRN):
 			if (bc) {
-			        cs->hw.hfcpci.conn |= 0x10;
+				cs->hw.hfcpci.conn |= 0x10;
 				cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA;
 				cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA;
 				cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2;
-				cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC);
+				cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
 			} else {
-			        cs->hw.hfcpci.conn |= 0x02;
+				cs->hw.hfcpci.conn |= 0x02;
 				cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA;
 				cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA;
 				cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B1;
-				cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC);
+				cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
 			}
 			break;
 	}
+	Write_hfc(cs, HFCPCI_SCTRL_E, cs->hw.hfcpci.sctrl_e);
 	Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
-	restore_flags(flags);
 	Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
 	Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);
 	Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r);
 	Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt);
 	Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
+	restore_flags(flags);
 }
 
 /******************************/
@@ -1420,7 +1525,7 @@ close_hfcpci(struct BCState *bcs)
 		discard_queue(&bcs->rqueue);
 		discard_queue(&bcs->squeue);
 		if (bcs->tx_skb) {
-			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			dev_kfree_skb(bcs->tx_skb);
 			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		}
@@ -1467,40 +1572,72 @@ setstack_2b(struct PStack *st, struct BCState *bcs)
 static void
 hfcpci_bh(struct IsdnCardState *cs)
 {
+	int flags;
 /*      struct PStack *stptr;
  */
 	if (!cs)
 		return;
-#if 0
-	if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
-		if (cs->debug)
-			debugl1(cs, "D-Channel Busy cleared");
-		stptr = cs->stlist;
-		while (stptr != NULL) {
-			stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
-			stptr = stptr->next;
-		}
-	}
-#endif
 	if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
-		switch (cs->dc.hfcpci.ph_state) {
-			case (0):
-				l1_msg(cs, HW_RESET | INDICATION, NULL);
-				break;
-			case (3):
-				l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
-				break;
-			case (8):
-				l1_msg(cs, HW_RSYNC | INDICATION, NULL);
-				break;
-			case (6):
-				l1_msg(cs, HW_INFO2 | INDICATION, NULL);
-				break;
-			case (7):
-				l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
-				break;
-			default:
-				break;
+		if (!cs->hw.hfcpci.nt_mode)
+			switch (cs->dc.hfcpci.ph_state) {
+				case (0):
+					l1_msg(cs, HW_RESET | INDICATION, NULL);
+					break;
+				case (3):
+					l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
+					break;
+				case (8):
+					l1_msg(cs, HW_RSYNC | INDICATION, NULL);
+					break;
+				case (6):
+					l1_msg(cs, HW_INFO2 | INDICATION, NULL);
+					break;
+				case (7):
+					l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
+					break;
+				default:
+					break;
+		} else {
+			switch (cs->dc.hfcpci.ph_state) {
+				case (2):
+					save_flags(flags);
+					cli();
+					if (cs->hw.hfcpci.nt_timer < 0) {
+						cs->hw.hfcpci.nt_timer = 0;
+						cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
+						Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+						/* Clear already pending ints */
+						if (Read_hfc(cs, HFCPCI_INT_S1));
+
+						Write_hfc(cs, HFCPCI_STATES, 4 | HFCPCI_LOAD_STATE);
+						udelay(10);
+						Write_hfc(cs, HFCPCI_STATES, 4);
+						cs->dc.hfcpci.ph_state = 4;
+					} else {
+						cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_TIMER;
+						Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+						cs->hw.hfcpci.ctmt &= ~HFCPCI_AUTO_TIMER;
+						cs->hw.hfcpci.ctmt |= HFCPCI_TIM3_125;
+						Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER);
+						Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER);
+						cs->hw.hfcpci.nt_timer = NT_T1_COUNT;
+						Write_hfc(cs, HFCPCI_STATES, 2 | HFCPCI_NT_G2_G3);	/* allow G2 -> G3 transition */
+					}
+					restore_flags(flags);
+					break;
+				case (1):
+				case (3):
+				case (4):
+					save_flags(flags);
+					cli();
+					cs->hw.hfcpci.nt_timer = 0;
+					cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
+					Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+					restore_flags(flags);
+					break;
+				default:
+					break;
+			}
 		}
 	}
 	if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
@@ -1513,8 +1650,8 @@ hfcpci_bh(struct IsdnCardState *cs)
 /*************************************/
 /* Alloc memory send data for queues */
 /*************************************/
-unsigned int * __init 
-	init_send_hfcpci(int cnt)
+__initfunc(unsigned int
+	   *init_send_hfcpci(int cnt))
 {
 	int i, *send;
 
@@ -1531,18 +1668,14 @@ unsigned int * __init
 /********************************/
 /* called for card init message */
 /********************************/
-void __init
-	inithfcpci(struct IsdnCardState *cs)
+__initfunc(void
+	   inithfcpci(struct IsdnCardState *cs))
 {
 	cs->setstack_d = setstack_hfcpci;
 	cs->dbusytimer.function = (void *) hfcpci_dbusy_timer;
 	cs->dbusytimer.data = (long) cs;
 	init_timer(&cs->dbusytimer);
 	cs->tqueue.routine = (void *) (void *) hfcpci_bh;
-#if 0
-	if (!cs->hw.hfcpci.send)
-		cs->hw.hfcpci.send = init_send_hfcpci(16);
-#endif
 	if (!cs->bcs[0].hw.hfc.send)
 		cs->bcs[0].hw.hfc.send = init_send_hfcpci(32);
 	if (!cs->bcs[1].hw.hfc.send)
@@ -1579,7 +1712,7 @@ hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 			inithfcpci(cs);
 			save_flags(flags);
 			sti();
-			current->state = TASK_INTERRUPTIBLE;
+			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout((80 * HZ) / 1000);	/* Timeout 80ms */
 			/* now switch timer interrupt off */
 			cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
@@ -1596,52 +1729,49 @@ hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 
 
 /* this variable is used as card index when more than one cards are present */
-#ifdef COMPAT_HAS_NEW_PCI
 static struct pci_dev *dev_hfcpci __initdata = NULL;
-#else
-static int pci_index __initdata = 0;
-#endif
 
 #endif				/* CONFIG_PCI */
 
-int __init
-	setup_hfcpci(struct IsdnCard *card)
+__initfunc(int
+	   setup_hfcpci(struct IsdnCard *card))
 {
 	struct IsdnCardState *cs = card->cs;
+	unsigned short cmd;
 	char tmp[64];
 	int i;
-#ifdef COMPAT_HAS_NEW_PCI
-        struct pci_dev *tmp_hfcpci = NULL;
-#endif
+	struct pci_dev *tmp_hfcpci = NULL;
 
 	strcpy(tmp, hfcpci_revision);
 	printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
 #if CONFIG_PCI
 	cs->hw.hfcpci.int_s1 = 0;
-#if 0
-	cs->hw.hfcpci.send = NULL;
-#endif
 	cs->bcs[0].hw.hfc.send = NULL;
 	cs->bcs[1].hw.hfc.send = NULL;
 	cs->dc.hfcpci.ph_state = 0;
 	cs->hw.hfcpci.fifo = 255;
 	if (cs->typ == ISDN_CTYPE_HFC_PCI) {
-#ifdef COMPAT_HAS_NEW_PCI
 		if (!pci_present()) {
 			printk(KERN_ERR "HFC-PCI: no PCI bus present\n");
 			return (0);
 		}
 		i = 0;
-                while (id_list[i].vendor_id) {
-		  tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
-					       id_list[i].device_id,
-					       dev_hfcpci);
-		  if (tmp_hfcpci) break;
-		  i++;
-		}  
-					      
+		while (id_list[i].vendor_id) {
+			tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
+						     id_list[i].device_id,
+						     dev_hfcpci);
+			i++;
+			if (tmp_hfcpci) {
+				if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK)))
+					continue;
+				else
+					break;
+			}
+		}
+
 		if (tmp_hfcpci) {
-		        dev_hfcpci = tmp_hfcpci; /* old device */
+			i--;
+			dev_hfcpci = tmp_hfcpci;	/* old device */
 			cs->hw.hfcpci.pci_bus = dev_hfcpci->bus->number;
 			cs->hw.hfcpci.pci_device_fn = dev_hfcpci->devfn;
 			cs->irq = dev_hfcpci->irq;
@@ -1649,43 +1779,45 @@ int __init
 				printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
 				return (0);
 			}
-			cs->hw.hfcpci.pci_io = (char *) get_pcibase(dev_hfcpci, 1);
-			printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n",id_list[i].vendor_name,id_list[i].card_name);
+			cs->hw.hfcpci.pci_io = (char *) dev_hfcpci->resource[ 1].start;
+			printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name);
 		} else {
 			printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
 			return (0);
 		}
-#else
-		for (; pci_index < 255; pci_index++) {
-			unsigned char irq;
-
-			i = 0;
-                        while (id_list[i].vendor_id) {
-			  if (pcibios_find_device(id_list[i].vendor_id,
-						  id_list[i].device_id, pci_index,
-						  &cs->hw.hfcpci.pci_bus, &cs->hw.hfcpci.pci_device_fn) == 0) 
-			    break;
-			  i++;
-			}
-			if (!id_list[i].vendor_id) 
-			  continue;
-
-			pcibios_read_config_byte(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn,
-					       PCI_INTERRUPT_LINE, &irq);
-			cs->irq = irq;
-
+		if (((int) cs->hw.hfcpci.pci_io & (PAGE_SIZE - 1))) {
+			printk(KERN_WARNING "HFC-PCI shared mem address will be corrected\n");
+			pcibios_write_config_word(cs->hw.hfcpci.pci_bus,
+					     cs->hw.hfcpci.pci_device_fn,
+						  PCI_COMMAND,
+						  0x0103);	/* set SERR */
+			pcibios_read_config_word(cs->hw.hfcpci.pci_bus,
+					     cs->hw.hfcpci.pci_device_fn,
+						 PCI_COMMAND,
+						 &cmd);
+			pcibios_write_config_word(cs->hw.hfcpci.pci_bus,
+					     cs->hw.hfcpci.pci_device_fn,
+						  PCI_COMMAND,
+						  cmd & ~2);
+			(int) cs->hw.hfcpci.pci_io &= ~(PAGE_SIZE - 1);
+			pcibios_write_config_dword(cs->hw.hfcpci.pci_bus,
+					     cs->hw.hfcpci.pci_device_fn,
+						   PCI_BASE_ADDRESS_1,
+					     (int) cs->hw.hfcpci.pci_io);
+			pcibios_write_config_word(cs->hw.hfcpci.pci_bus,
+					     cs->hw.hfcpci.pci_device_fn,
+						  PCI_COMMAND,
+						  cmd);
 			pcibios_read_config_dword(cs->hw.hfcpci.pci_bus,
-				cs->hw.hfcpci.pci_device_fn, PCI_BASE_ADDRESS_1,
-				(void *) &cs->hw.hfcpci.pci_io);
-			printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n",id_list[i].vendor_name,id_list[i].card_name);
-			break;
-		}
-		if (pci_index == 255) {
-			printk(KERN_WARNING "HFC-PCI: No card found\n");
-			return (0);
+					     cs->hw.hfcpci.pci_device_fn,
+						  PCI_BASE_ADDRESS_1,
+					 (void *) &cs->hw.hfcpci.pci_io);
+			if (((int) cs->hw.hfcpci.pci_io & (PAGE_SIZE - 1))) {
+				printk(KERN_WARNING "HFC-PCI unable to align address %x\n", (unsigned) cs->hw.hfcpci.pci_io);
+				return (0);
+			}
+			dev_hfcpci->resource[1].start = (int) cs->hw.hfcpci.pci_io;
 		}
-		pci_index++;
-#endif				/* COMPAT_HAS_NEW_PCI */
 		if (!cs->hw.hfcpci.pci_io) {
 			printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
 			return (0);
@@ -1701,16 +1833,16 @@ int __init
 		    (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000;
 		pcibios_write_config_dword(cs->hw.hfcpci.pci_bus,
 				       cs->hw.hfcpci.pci_device_fn, 0x80,
-					   (u_int) virt_to_bus(cs->hw.hfcpci.fifos));
+			       (u_int) virt_to_bus(cs->hw.hfcpci.fifos));
 		cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256);
 		printk(KERN_INFO
-		 "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
+		       "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
 		       (u_int) cs->hw.hfcpci.pci_io,
 		       (u_int) cs->hw.hfcpci.fifos,
 		       (u_int) virt_to_bus(cs->hw.hfcpci.fifos),
 		       cs->irq, HZ);
 		pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO);	/* enable memory mapped ports, disable busmaster */
-		cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */
+		cs->hw.hfcpci.int_m2 = 0;	/* disable alle interrupts */
 		cs->hw.hfcpci.int_m1 = 0;
 		Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
 		Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
@@ -1735,7 +1867,7 @@ int __init
 
 	reset_hfcpci(cs);
 	cs->cardmsg = &hfcpci_card_msg;
-	cs->auxcmd  = &hfcpci_auxcmd;
+	cs->auxcmd = &hfcpci_auxcmd;
 	return (1);
 #else
 	printk(KERN_WARNING "HFC-PCI: NO_PCI_BIOS\n");
diff --git a/drivers/isdn/hisax/hfc_pci.h b/drivers/isdn/hisax/hfc_pci.h
index ae04d3d16af9734bf8f7f243b56595c5b9c575ba..e8597d73049ed1aeaa41733e25f9faf0d0cb487c 100644
--- a/drivers/isdn/hisax/hfc_pci.h
+++ b/drivers/isdn/hisax/hfc_pci.h
@@ -1,4 +1,4 @@
-/* $Id: hfc_pci.h,v 1.6 1999/08/28 21:04:29 werner Exp $
+/* $Id: hfc_pci.h,v 1.7 1999/10/10 20:13:06 werner Exp $
 
  *  specific defines for CCD's HFC 2BDS0 PCI chips
  *
@@ -21,6 +21,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: hfc_pci.h,v $
+ * Revision 1.7  1999/10/10 20:13:06  werner
+ *
+ * Corrected timer constant
+ *
  * Revision 1.6  1999/08/28 21:04:29  werner
  * Implemented full audio support (transparent mode)
  *
@@ -129,7 +133,7 @@
 
 /* bits in CTMT (Write) */
 #define HFCPCI_CLTIMER    0x80
-#define HFCPCI_TIM3_125   0x00
+#define HFCPCI_TIM3_125   0x04
 #define HFCPCI_TIM25      0x10
 #define HFCPCI_TIM50      0x14
 #define HFCPCI_TIM400     0x18
diff --git a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c
index 05735e150e5f4123df5eabe5e956c89ec15f7af0..8654857fdef612beadc41bf6aa3e2dcdc66b407b 100644
--- a/drivers/isdn/hisax/hfcscard.c
+++ b/drivers/isdn/hisax/hfcscard.c
@@ -1,4 +1,4 @@
-/* $Id: hfcscard.c,v 1.4 1999/08/09 18:59:59 keil Exp $
+/* $Id: hfcscard.c,v 1.5 1999/09/04 06:20:06 keil Exp $
 
  * hfcscard.c     low level stuff for hfcs based cards (Teles3c, ACER P10)
  *
@@ -6,6 +6,9 @@
  *
  *
  * $Log: hfcscard.c,v $
+ * Revision 1.5  1999/09/04 06:20:06  keil
+ * Changes from kernel set_current_state()
+ *
  * Revision 1.4  1999/08/09 18:59:59  keil
  * Fix S0 init - Thanks to Stefan Gybas
  *
@@ -27,7 +30,7 @@
 
 extern const char *CardType[];
 
-static const char *hfcs_revision = "$Revision: 1.4 $";
+static const char *hfcs_revision = "$Revision: 1.5 $";
 
 static void
 hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs)
@@ -82,13 +85,13 @@ reset_hfcs(struct IsdnCardState *cs)
 	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm);	/* Reset On */
 	save_flags(flags);
 	sti();
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((30*HZ)/1000);
 	cs->hw.hfcD.cirm = 0;
 	if (cs->typ == ISDN_CTYPE_TELES3C)
 		cs->hw.hfcD.cirm |= HFCD_MEM8K;
 	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm);	/* Reset Off */
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((10*HZ)/1000);
 	if (cs->typ == ISDN_CTYPE_TELES3C)
 		cs->hw.hfcD.cirm |= HFCD_INTB;
@@ -135,7 +138,7 @@ hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 			init2bds0(cs);
 			save_flags(flags);
 			sti();
-			current->state = TASK_INTERRUPTIBLE;
+			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout((80*HZ)/1000);
 			cs->hw.hfcD.ctmt |= HFCD_TIM800;
 			cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); 
@@ -148,8 +151,8 @@ hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 	return(0);
 }
 
-int __init
-setup_hfcs(struct IsdnCard *card)
+__initfunc(int
+setup_hfcs(struct IsdnCard *card))
 {
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 0fdf65a409ea6294846b741b477f93001b9755aa..230628486bbc088759c57654280822125ddc5a5a 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -1,8 +1,18 @@
-/* $Id: hisax.h,v 2.34 1999/08/25 17:00:04 keil Exp $
+/* $Id: hisax.h,v 2.37 1999/10/14 20:25:28 keil Exp $
 
  *   Basic declarations, defines and prototypes
  *
  * $Log: hisax.h,v $
+ * Revision 2.37  1999/10/14 20:25:28  keil
+ * add a statistic for error monitoring
+ *
+ * Revision 2.36  1999/10/10 20:16:15  werner
+ *
+ * Added variable to hfcpci union.
+ *
+ * Revision 2.35  1999/09/04 06:35:09  keil
+ * Winbond W6692 support
+ *
  * Revision 2.34  1999/08/25 17:00:04  keil
  * Make ISAR V32bis modem running
  * Make LL->HL interface open for additional commands
@@ -137,6 +147,8 @@
 #include <linux/tty.h>
 #include <linux/serial_reg.h>
 
+#undef ERROR_STATISTIC
+
 #define REQUEST		0
 #define CONFIRM		1
 #define INDICATION	2
@@ -447,6 +459,13 @@ struct hscx_hw {
 	u_char tsaxr1;
 };
 
+struct w6692B_hw {
+	int bchan;
+	int rcvidx;
+	int count;              /* Current skb sent count */
+	u_char *rcvbuf;         /* B-Channel receive Buffer */
+};
+
 struct isar_reg {
 	unsigned int Flags;
 	volatile u_char bstat;
@@ -571,6 +590,12 @@ struct BCState {
 	int event;
 	int  (*BC_SetStack) (struct PStack *, struct BCState *);
 	void (*BC_Close) (struct BCState *);
+#ifdef ERROR_STATISTIC
+	int err_crc;
+	int err_tx;
+	int err_rdo;
+	int err_inv;
+#endif
 	union {
 		struct hscx_hw hscx;
 		struct hdlc_hw hdlc;
@@ -578,6 +603,7 @@ struct BCState {
 		struct hfcB_hw hfc;
 		struct tiger_hw tiger;
 		struct amd7930_hw  amd7930;
+		struct w6692B_hw w6692;
 	} hw;
 };
 
@@ -744,7 +770,8 @@ struct hfcPCI_hw {
 	unsigned char fifo;
         unsigned char fifo_en;
         unsigned char bswapped;
-  /*	unsigned int *send; */
+        unsigned char nt_mode;
+        int nt_timer;
 	unsigned char pci_bus;
         unsigned char pci_device_fn;
         unsigned char *pci_io; /* start of PCI IO memory */
@@ -813,6 +840,11 @@ struct gazel_hw {
 	unsigned char iom2;
 };
 
+struct w6692_hw {
+	unsigned int iobase;
+	struct timer_list timer;
+};
+
 #ifdef  CONFIG_HISAX_TESTEMU
 struct te_hw {
 	unsigned char *sfifo;
@@ -821,13 +853,8 @@ struct te_hw {
 	unsigned char *sfifo_e;
 	int sfifo_cnt;
 	unsigned int stat;
-#ifdef COMPAT_HAS_NEW_WAITQ
 	wait_queue_head_t rwaitq;
 	wait_queue_head_t swaitq;
-#else
-	struct wait_queue *rwaitq;
-	struct wait_queue *swaitq;
-#endif
 };
 #endif
 
@@ -847,11 +874,7 @@ struct isac_chip {
 	int mon_rxp;
 	struct arcofi_msg *arcofi_list;
 	struct timer_list arcofitimer;
-#ifdef COMPAT_HAS_NEW_WAITQ
 	wait_queue_head_t arcofi_wait;
-#else
-	struct wait_queue *arcofi_wait;
-#endif
 	u_char arcofi_bc;
 	u_char arcofi_state;
 	u_char mocr;
@@ -866,6 +889,10 @@ struct hfcpci_chip {
 	int ph_state;
 };
 
+struct w6692_chip {
+	int ph_state;
+};
+
 #define HW_IOM1			0
 #define HW_IPAC			1
 #define HW_ISAR			2
@@ -910,6 +937,7 @@ struct IsdnCardState {
 #endif
 		struct bkm_hw ax;
 		struct gazel_hw gazel;
+		struct w6692_hw w6692;
 	} hw;
 	int myid;
 	isdn_if iif;
@@ -940,6 +968,7 @@ struct IsdnCardState {
 		struct isac_chip isac;
 		struct hfcd_chip hfcd;
 		struct hfcpci_chip hfcpci;
+		struct w6692_chip w6692;
 	} dc;
 	u_char *rcvbuf;
 	int rcvidx;
@@ -948,6 +977,11 @@ struct IsdnCardState {
 	int event;
 	struct tq_struct tqueue;
 	struct timer_list dbusytimer;
+#ifdef ERROR_STATISTIC
+	int err_crc;
+	int err_tx;
+	int err_rx;
+#endif
 };
 
 #define  MON0_RX	1
@@ -992,7 +1026,8 @@ struct IsdnCardState {
 #define	 ISDN_CTYPE_SCT_QUADRO	33
 #define  ISDN_CTYPE_GAZEL	34
 #define  ISDN_CTYPE_HFC_PCI	35
-#define  ISDN_CTYPE_COUNT	35
+#define  ISDN_CTYPE_W6692	36
+#define  ISDN_CTYPE_COUNT	36
 
 
 #ifdef ISDN_CHIP_ISAC
@@ -1007,10 +1042,6 @@ struct IsdnCardState {
 #define __initdata
 #endif
 
-#ifndef __init
-#define __init
-#endif
-
 #define HISAX_INITFUNC(__arginit) __initfunc(__arginit)
 #define HISAX_INITDATA __initdata
 
@@ -1243,6 +1274,15 @@ struct IsdnCardState {
 #define  CARD_GAZEL  0
 #endif
 
+#ifdef	CONFIG_HISAX_W6692
+#define	CARD_W6692	1
+#ifndef	ISDN_CHIP_W6692
+#define	ISDN_CHIP_W6692	1
+#endif
+#else
+#define	CARD_W6692	0
+#endif
+
 #define TEI_PER_CARD 0
 
 #ifdef CONFIG_HISAX_1TR6
@@ -1336,7 +1376,7 @@ int HiSax_command(isdn_ctrl * ic);
 int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
 void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
 void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args);
-void HiSax_reportcard(int cardnr);
+void HiSax_reportcard(int cardnr, int sel);
 int QuickHex(char *txt, u_char * p, int cnt);
 void LogFrame(struct IsdnCardState *cs, u_char * p, int size);
 void dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir);
diff --git a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c
index 290c89f5059b63217ba861fd55a8ee89db1c5a44..1c57cd3f1c432f5e837373a845e6301da1accd06 100644
--- a/drivers/isdn/hisax/hscx.c
+++ b/drivers/isdn/hisax/hscx.c
@@ -219,7 +219,7 @@ close_hscxstate(struct BCState *bcs)
 		discard_queue(&bcs->rqueue);
 		discard_queue(&bcs->squeue);
 		if (bcs->tx_skb) {
-			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			dev_kfree_skb(bcs->tx_skb);
 			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		}
diff --git a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c
index ecc1e825e52a0ded8b0626ea6f8f33f118a192b6..655508f704e99e0e23b22a67e4ece78dcce35b4f 100644
--- a/drivers/isdn/hisax/hscx_irq.c
+++ b/drivers/isdn/hisax/hscx_irq.c
@@ -1,4 +1,4 @@
-/* $Id: hscx_irq.c,v 1.12 1999/07/01 08:11:42 keil Exp $
+/* $Id: hscx_irq.c,v 1.13 1999/10/14 20:25:28 keil Exp $
 
  * hscx_irq.c     low level b-channel stuff for Siemens HSCX
  *
@@ -7,6 +7,9 @@
  * This is an include file for fast inline IRQ stuff
  *
  * $Log: hscx_irq.c,v $
+ * Revision 1.13  1999/10/14 20:25:28  keil
+ * add a statistic for error monitoring
+ *
  * Revision 1.12  1999/07/01 08:11:42  keil
  * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
  *
@@ -181,16 +184,28 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
 	if (val & 0x80) {	/* RME */
 		r = READHSCX(cs, hscx, HSCX_RSTA);
 		if ((r & 0xf0) != 0xa0) {
-			if (!(r & 0x80))
+			if (!(r & 0x80)) {
 				if (cs->debug & L1_DEB_WARN)
 					debugl1(cs, "HSCX invalid frame");
-			if ((r & 0x40) && bcs->mode)
+#ifdef ERROR_STATISTIC
+				bcs->err_inv++;
+#endif
+			}
+			if ((r & 0x40) && bcs->mode) {
 				if (cs->debug & L1_DEB_WARN)
 					debugl1(cs, "HSCX RDO mode=%d",
 						bcs->mode);
-			if (!(r & 0x20))
+#ifdef ERROR_STATISTIC
+				bcs->err_rdo++;
+#endif
+			}
+			if (!(r & 0x20)) {
 				if (cs->debug & L1_DEB_WARN)
 					debugl1(cs, "HSCX CRC error");
+#ifdef ERROR_STATISTIC
+				bcs->err_crc++;
+#endif
+			}
 			WriteHSCXCMDR(cs, hscx, 0x80);
 		} else {
 			count = READHSCX(cs, hscx, HSCX_RBCL) & (
@@ -204,7 +219,6 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
 				if (!(skb = dev_alloc_skb(count)))
 					printk(KERN_WARNING "HSCX: receive out of memory\n");
 				else {
-					SET_SKB_FREE(skb);
 					memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
 					skb_queue_tail(&bcs->rqueue, skb);
 				}
@@ -220,7 +234,6 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
 			if (!(skb = dev_alloc_skb(fifo_size)))
 				printk(KERN_WARNING "HiSax: receive out of memory\n");
 			else {
-				SET_SKB_FREE(skb);
 				memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
 				skb_queue_tail(&bcs->rqueue, skb);
 			}
@@ -237,7 +250,7 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
 				if (bcs->st->lli.l1writewakeup &&
 					(PACKET_NOACK != bcs->tx_skb->pkt_type))
 					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count);
-				idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+				dev_kfree_skb(bcs->tx_skb);
 				bcs->hw.hscx.count = 0; 
 				bcs->tx_skb = NULL;
 			}
@@ -267,6 +280,9 @@ hscx_int_main(struct IsdnCardState *cs, u_char val)
 			if (bcs->mode == 1)
 				hscx_fill_fifo(bcs);
 			else {
+#ifdef ERROR_STATISTIC
+				bcs->err_tx++;
+#endif
 				/* Here we lost an TX interrupt, so
 				   * restart transmitting the whole frame.
 				 */
@@ -297,6 +313,9 @@ hscx_int_main(struct IsdnCardState *cs, u_char val)
 				/* Here we lost an TX interrupt, so
 				   * restart transmitting the whole frame.
 				 */
+#ifdef ERROR_STATISTIC
+				bcs->err_tx++;
+#endif
 				if (bcs->tx_skb) {
 					skb_push(bcs->tx_skb, bcs->hw.hscx.count);
 					bcs->tx_cnt += bcs->hw.hscx.count;
diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c
index 46d5daef0071e9e78108656702a63289ccbb6c87..a992f76c48ee092347666e182912789edb2e743c 100644
--- a/drivers/isdn/hisax/isac.c
+++ b/drivers/isdn/hisax/isac.c
@@ -1,4 +1,4 @@
-/* $Id: isac.c,v 1.23 1999/08/25 16:50:52 keil Exp $
+/* $Id: isac.c,v 1.24 1999/10/14 20:25:28 keil Exp $
 
  * isac.c   ISAC specific routines
  *
@@ -9,6 +9,9 @@
  *		../../../Documentation/isdn/HiSax.cert
  *
  * $Log: isac.c,v $
+ * Revision 1.24  1999/10/14 20:25:28  keil
+ * add a statistic for error monitoring
+ *
  * Revision 1.23  1999/08/25 16:50:52  keil
  * Fix bugs which cause 2.3.14 hangs (waitqueue init)
  *
@@ -281,12 +284,20 @@ isac_interrupt(struct IsdnCardState *cs, u_char val)
 	if (val & 0x80) {	/* RME */
 		exval = cs->readisac(cs, ISAC_RSTA);
 		if ((exval & 0x70) != 0x20) {
-			if (exval & 0x40)
+			if (exval & 0x40) {
 				if (cs->debug & L1_DEB_WARN)
 					debugl1(cs, "ISAC RDO");
-			if (!(exval & 0x20))
+#ifdef ERROR_STATISTIC
+				cs->err_rx++;
+#endif
+			}
+			if (!(exval & 0x20)) {
 				if (cs->debug & L1_DEB_WARN)
 					debugl1(cs, "ISAC CRC error");
+#ifdef ERROR_STATISTIC
+				cs->err_crc++;
+#endif
+			}
 			cs->writeisac(cs, ISAC_CMDR, 0x80);
 		} else {
 			count = cs->readisac(cs, ISAC_RBCL) & 0x1f;
@@ -300,7 +311,6 @@ isac_interrupt(struct IsdnCardState *cs, u_char val)
 				if (!(skb = alloc_skb(count, GFP_ATOMIC)))
 					printk(KERN_WARNING "HiSax: D receive out of memory\n");
 				else {
-					SET_SKB_FREE(skb);
 					memcpy(skb_put(skb, count), cs->rcvbuf, count);
 					skb_queue_tail(&cs->rq, skb);
 				}
@@ -328,7 +338,7 @@ isac_interrupt(struct IsdnCardState *cs, u_char val)
 				isac_fill_fifo(cs);
 				goto afterXPR;
 			} else {
-				idev_kfree_skb(cs->tx_skb, FREE_WRITE);
+				dev_kfree_skb(cs->tx_skb);
 				cs->tx_cnt = 0;
 				cs->tx_skb = NULL;
 			}
@@ -372,6 +382,9 @@ isac_interrupt(struct IsdnCardState *cs, u_char val)
 		if (exval & 0x40) {  /* XDU */
 			debugl1(cs, "ISAC XDU");
 			printk(KERN_WARNING "HiSax: ISAC XDU\n");
+#ifdef ERROR_STATISTIC
+			cs->err_tx++;
+#endif
 			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
 				del_timer(&cs->dbusytimer);
 			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
@@ -614,7 +627,7 @@ ISAC_l1hw(struct PStack *st, int pr, void *arg)
 			discard_queue(&cs->rq);
 			discard_queue(&cs->sq);
 			if (cs->tx_skb) {
-				idev_kfree_skb(cs->tx_skb, FREE_WRITE);
+				dev_kfree_skb(cs->tx_skb);
 				cs->tx_skb = NULL;
 			}
 			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
@@ -670,7 +683,7 @@ dbusy_timer_handler(struct IsdnCardState *cs)
 			/* discard frame; reset transceiver */
 			test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags);
 			if (cs->tx_skb) {
-				idev_kfree_skb(cs->tx_skb, FREE_WRITE);
+				dev_kfree_skb(cs->tx_skb);
 				cs->tx_cnt = 0;
 				cs->tx_skb = NULL;
 			} else {
diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c
index 96442ff7d4ddc302d1d5f365dbc328691ea5a2e7..417f2157dbdeb0f5a67e326eb32927aa40cb6445 100644
--- a/drivers/isdn/hisax/isar.c
+++ b/drivers/isdn/hisax/isar.c
@@ -1,4 +1,4 @@
-/* $Id: isar.c,v 1.5 1999/08/25 16:59:55 keil Exp $
+/* $Id: isar.c,v 1.7 1999/10/14 20:25:29 keil Exp $
 
  * isar.c   ISAR (Siemens PSB 7110) specific routines
  *
@@ -6,6 +6,12 @@
  *
  *
  * $Log: isar.c,v $
+ * Revision 1.7  1999/10/14 20:25:29  keil
+ * add a statistic for error monitoring
+ *
+ * Revision 1.6  1999/08/31 11:20:20  paul
+ * various spelling corrections (new checksums may be needed, Karsten!)
+ *
  * Revision 1.5  1999/08/25 16:59:55  keil
  * Make ISAR V32bis modem running
  * Make LL->HL interface open for additional commands
@@ -459,7 +465,6 @@ isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs)
 	case L1_MODE_TRANS:
 	case L1_MODE_V32:
 		if ((skb = dev_alloc_skb(ireg->clsb))) {
-			SET_SKB_FREE(skb);
 			rcv_mbox(cs, ireg, (u_char *)skb_put(skb, ireg->clsb));
 			skb_queue_tail(&bcs->rqueue, skb);
 			isar_sched_event(bcs, B_RCVBUFREADY);
@@ -478,6 +483,12 @@ isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs)
 			if (cs->debug & L1_DEB_WARN)
 				debugl1(cs, "isar frame error %x len %d",
 					ireg->cmsb, ireg->clsb);
+#ifdef ERROR_STATISTIC
+			if (ireg->cmsb & HDLC_ERR_RER)
+				bcs->err_inv++;
+			if (ireg->cmsb & HDLC_ERR_CER)
+				bcs->err_crc++;
+#endif
 			bcs->hw.isar.rcvidx = 0;
 			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
 		} else {
@@ -493,7 +504,6 @@ isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs)
 				} else if (!(skb = dev_alloc_skb(bcs->hw.isar.rcvidx-2))) {
 					printk(KERN_WARNING "ISAR: receive out of memory\n");
 				} else {
-					SET_SKB_FREE(skb);
 					memcpy(skb_put(skb, bcs->hw.isar.rcvidx-2),
 						bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx-2);
 					skb_queue_tail(&bcs->rqueue, skb);
@@ -593,7 +603,7 @@ send_frames(struct BCState *bcs)
 			if (bcs->st->lli.l1writewakeup &&
 				(PACKET_NOACK != bcs->tx_skb->pkt_type))
 					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.isar.txcnt);
-			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			dev_kfree_skb(bcs->tx_skb);
 			bcs->hw.isar.txcnt = 0; 
 			bcs->tx_skb = NULL;
 		}
@@ -789,10 +799,19 @@ isar_int_main(struct IsdnCardState *cs)
 			check_send(cs, ireg->cmsb);
 			break;
 		case ISAR_IIS_BSTEV:
-			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+#ifdef ERROR_STATISTIC
+			if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) {
+				if (ireg->cmsb == BSTEV_TBO)
+					bcs->err_tx++;
+				if (ireg->cmsb == BSTEV_RBO)
+					bcs->err_rdo++;
+			}
+#endif
 			if (cs->debug & L1_DEB_WARN)
 				debugl1(cs, "Buffer STEV dpath%d msb(%x)",
 					ireg->iis>>6, ireg->cmsb);
+			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+			break;
 		case ISAR_IIS_PSTEV:
 			if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) {
 				rcv_mbox(cs, ireg, (u_char *)ireg->par);
@@ -1022,8 +1041,8 @@ modeisar(struct BCState *bcs, int mode, int bc)
 					&bcs->hw.isar.reg->Flags))
 					bcs->hw.isar.dpath = 1;
 				else {
-					printk(KERN_WARNING"isar modeisar analog funktions only with DP1\n");
-					debugl1(cs, "isar modeisar analog funktions only with DP1");
+					printk(KERN_WARNING"isar modeisar analog works only with DP1\n");
+					debugl1(cs, "isar modeisar analog works only with DP1");
 					return(1);
 				}
 				break;
@@ -1159,7 +1178,7 @@ close_isarstate(struct BCState *bcs)
 		discard_queue(&bcs->rqueue);
 		discard_queue(&bcs->squeue);
 		if (bcs->tx_skb) {
-			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			dev_kfree_skb(bcs->tx_skb);
 			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 			if (bcs->cs->debug & L1_DEB_HSCX)
@@ -1223,7 +1242,7 @@ isar_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) {
 						ll_run(cs, features);
 					break;
 				default:
-					printk(KERN_DEBUG "HiSax: invalid ioclt %d\n",
+					printk(KERN_DEBUG "HiSax: invalid ioctl %d\n",
 					       (int) ic->arg);
 					return(-EINVAL);
 			}
diff --git a/drivers/isdn/hisax/isar.h b/drivers/isdn/hisax/isar.h
index c6ac6532b231e17ff6ec4f1f10332f152888f656..f2bc4820a92d1ca9bd87173aea94ff1069ed3545 100644
--- a/drivers/isdn/hisax/isar.h
+++ b/drivers/isdn/hisax/isar.h
@@ -1,10 +1,13 @@
-/* $Id: isar.h,v 1.5 1999/08/25 16:59:59 keil Exp $
+/* $Id: isar.h,v 1.6 1999/10/14 20:25:29 keil Exp $
  * isar.h   ISAR (Siemens PSB 7110) specific defines
  *
  * Author Karsten Keil (keil@isdn4linux.de)
  *
  *
  * $Log: isar.h,v $
+ * Revision 1.6  1999/10/14 20:25:29  keil
+ * add a statistic for error monitoring
+ *
  * Revision 1.5  1999/08/25 16:59:59  keil
  * Make ISAR V32bis modem running
  * Make LL->HL interface open for additional commands
@@ -178,12 +181,17 @@
 #define HDLC_FSD	0x20
 #define HDLC_FST	0x20
 #define HDLC_ERROR	0x1c
+#define HDLC_ERR_FAD	0x10
+#define HDLC_ERR_RER	0x08
+#define HDLC_ERR_CER	0x01
 #define SART_NMD	0x01
 
 #define BSTAT_RDM0	0x1
 #define BSTAT_RDM1	0x2
 #define BSTAT_RDM2	0x4
 #define BSTAT_RDM3	0x8
+#define BSTEV_TBO	0x1f
+#define BSTEV_RBO	0x2f
 
 extern int ISARVersion(struct IsdnCardState *cs, char *s);
 extern void isar_int_main(struct IsdnCardState *cs);
diff --git a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c
index c819c4811b5822255c4c6e74cc6e94be73bddcb8..7682170253e7637a661b52167ca8ce064c3ae1f1 100644
--- a/drivers/isdn/hisax/isdnl1.c
+++ b/drivers/isdn/hisax/isdnl1.c
@@ -318,12 +318,12 @@ DChannel_proc_rcv(struct IsdnCardState *cs)
 		stptr = cs->stlist;
 		if (skb->len<3) {
 			debugl1(cs, "D-channel frame too short(%d)",skb->len);
-			idev_kfree_skb(skb, FREE_READ);
+			dev_kfree_skb(skb);
 			return;
 		}
 		if ((skb->data[0] & 1) || !(skb->data[1] &1)) {
 			debugl1(cs, "D-channel frame wrong EA0/EA1");
-			idev_kfree_skb(skb, FREE_READ);
+			dev_kfree_skb(skb);
 			return;
 		}
 		sapi = skb->data[0] >> 2;
@@ -350,7 +350,7 @@ DChannel_proc_rcv(struct IsdnCardState *cs)
 					stptr = stptr->next;
 				}
 			}
-			idev_kfree_skb(skb, FREE_READ);
+			dev_kfree_skb(skb);
 		} else if (sapi == CTRL_SAPI) { /* sapi 0 */
 			found = 0;
 			while (stptr != NULL)
@@ -361,7 +361,7 @@ DChannel_proc_rcv(struct IsdnCardState *cs)
 				} else
 					stptr = stptr->next;
 			if (!found)
-				idev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb(skb);
 		}
 	}
 }
diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c
index ca721ea864b5810d87e5c0f79ca59546310b2f10..69e320262ccd0eec6e534f90b2580c3de4fb8e1f 100644
--- a/drivers/isdn/hisax/isdnl2.c
+++ b/drivers/isdn/hisax/isdnl2.c
@@ -201,7 +201,7 @@ freewin1(struct Layer2 *l2)
 	for (i = 0; i < MAX_WINDOW; i++) {
 		if (l2->windowar[i]) {
 			cnt++;
-			idev_kfree_skb(l2->windowar[i], FREE_WRITE);
+			dev_kfree_skb(l2->windowar[i]);
 			l2->windowar[i] = NULL;
 		}
 	}
@@ -480,7 +480,7 @@ setva(struct PStack *st, unsigned int nr)
 		len = l2->windowar[l2->sow]->len;
 		if (PACKET_NOACK == l2->windowar[l2->sow]->pkt_type)
 			len = -1;
-		idev_kfree_skb(l2->windowar[l2->sow], FREE_WRITE);
+		dev_kfree_skb(l2->windowar[l2->sow]);
 		l2->windowar[l2->sow] = NULL;
 		l2->sow = (l2->sow + 1) % l2->window;
 		if (st->lli.l2writewakeup && (len >=0))
@@ -501,7 +501,6 @@ send_uframe(struct PStack *st, u_char cmd, u_char cr)
 		printk(KERN_WARNING "isdl2 can't alloc sbbuff for send_uframe\n");
 		return;
 	}
-	SET_SKB_FREE(skb);
 	memcpy(skb_put(skb, i), tmp, i);
 	enqueue_super(st, skb);
 }
@@ -515,7 +514,7 @@ get_PollFlag(struct PStack * st, struct sk_buff * skb)
 inline void
 FreeSkb(struct sk_buff *skb)
 {
-	idev_kfree_skb(skb, FREE_READ);
+	dev_kfree_skb(skb);
 }
 
 
@@ -970,7 +969,6 @@ enquiry_cr(struct PStack *st, u_char typ, u_char cr, u_char pf)
 		printk(KERN_WARNING "isdl2 can't alloc sbbuff for enquiry_cr\n");
 		return;
 	}
-	SET_SKB_FREE(skb);
 	memcpy(skb_put(skb, i), tmp, i);
 	enqueue_super(st, skb);
 }
@@ -1343,7 +1341,7 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
 	if (l2->windowar[p1]) {
 		printk(KERN_WARNING "isdnl2 try overwrite ack queue entry %d\n",
 		       p1);
-		idev_kfree_skb(l2->windowar[p1], FREE_WRITE);
+		dev_kfree_skb(l2->windowar[p1]);
 	}
 	l2->windowar[p1] = skb_clone(skb, GFP_ATOMIC);
 
@@ -1367,7 +1365,6 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
 		"isdl2 pull_iqueue skb header(%d/%d) too short\n", i, p1);
 		oskb = skb;
 		skb = alloc_skb(oskb->len + i, GFP_ATOMIC);
-		SET_SKB_FREE(skb);
 		memcpy(skb_put(skb, i), header, i);
 		memcpy(skb_put(skb, oskb->len), oskb->data, oskb->len);
 		FreeSkb(oskb);
@@ -1788,12 +1785,12 @@ isdnl2_l3l2(struct PStack *st, int pr, void *arg)
 	switch (pr) {
 		case (DL_DATA | REQUEST):
 			if (FsmEvent(&st->l2.l2m, EV_L2_DL_DATA, arg)) {
-				idev_kfree_skb((struct sk_buff *) arg, FREE_READ);
+				dev_kfree_skb((struct sk_buff *) arg);
 			}
 			break;
 		case (DL_UNIT_DATA | REQUEST):
 			if (FsmEvent(&st->l2.l2m, EV_L2_DL_UNIT_DATA, arg)) {
-				idev_kfree_skb((struct sk_buff *) arg, FREE_READ);
+				dev_kfree_skb((struct sk_buff *) arg);
 			}
 			break;
 		case (DL_ESTABLISH | REQUEST):
diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c
index 458afe920984e0b9dd123941e08cd36492558ebc..6dc8bd9d06c8417ab97d9bed4b0d662b4096b22e 100644
--- a/drivers/isdn/hisax/isdnl3.c
+++ b/drivers/isdn/hisax/isdnl3.c
@@ -260,7 +260,6 @@ l3_alloc_skb(int len)
 		printk(KERN_WARNING "HiSax: No skb for D-channel\n");
 		return (NULL);
 	}
-	SET_SKB_FREE(skb);
 	skb_reserve(skb, MAX_HEADER_LEN);
 	return (skb);
 }
@@ -272,7 +271,7 @@ no_l3_proto(struct PStack *st, int pr, void *arg)
 
 	HiSax_putstatus(st->l1.hardware, "L3", "no D protocol");
 	if (skb) {
-		idev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb(skb);
 	}
 }
 
diff --git a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c
index dd713921a6c04af6b3465cd1b1532cbbb2684cda..245b40bc083a3ab60286471161cd568ca1e168d7 100644
--- a/drivers/isdn/hisax/isurf.c
+++ b/drivers/isdn/hisax/isurf.c
@@ -1,10 +1,13 @@
-/* $Id: isurf.c,v 1.5 1999/08/25 17:00:02 keil Exp $
+/* $Id: isurf.c,v 1.6 1999/09/04 06:20:06 keil Exp $
 
  * isurf.c  low level stuff for Siemens I-Surf/I-Talk cards
  *
  * Author     Karsten Keil (keil@isdn4linux.de)
  *
  * $Log: isurf.c,v $
+ * Revision 1.6  1999/09/04 06:20:06  keil
+ * Changes from kernel set_current_state()
+ *
  * Revision 1.5  1999/08/25 17:00:02  keil
  * Make ISAR V32bis modem running
  * Make LL->HL interface open for additional commands
@@ -34,7 +37,7 @@
 
 extern const char *CardType[];
 
-static const char *ISurf_revision = "$Revision: 1.5 $";
+static const char *ISurf_revision = "$Revision: 1.6 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -154,10 +157,10 @@ reset_isurf(struct IsdnCardState *cs, u_char chips)
 	byteout(cs->hw.isurf.reset, chips); /* Reset On */
 	save_flags(flags);
 	sti();
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((10*HZ)/1000);
 	byteout(cs->hw.isurf.reset, ISURF_ISAR_EA); /* Reset Off */
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((10*HZ)/1000);
 	restore_flags(flags);
 }
@@ -206,8 +209,8 @@ isurf_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) {
 	return(isar_auxcmd(cs, ic));
 }
 
-int __init
-setup_isurf(struct IsdnCard *card)
+__initfunc(int
+setup_isurf(struct IsdnCard *card))
 {
 	int ver;
 	struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c
index 389d043a342be409bae118179c71c3fbfcce584e..cb94d5bb392c3373434634886960c1a33df2ec26 100644
--- a/drivers/isdn/hisax/ix1_micro.c
+++ b/drivers/isdn/hisax/ix1_micro.c
@@ -282,8 +282,8 @@ ix1_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 }
 
 
-int __init
-setup_ix1micro(struct IsdnCard *card)
+__initfunc(int
+setup_ix1micro(struct IsdnCard *card))
 {
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
diff --git a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c
index 5699f28a76dd51abb2c0aa47ced3b03568d7ef63..4f07eed875a921bea83024c5816f0105ddfd68d0 100644
--- a/drivers/isdn/hisax/jade.c
+++ b/drivers/isdn/hisax/jade.c
@@ -214,7 +214,7 @@ close_jadestate(struct BCState *bcs)
 	discard_queue(&bcs->rqueue);
 	discard_queue(&bcs->squeue);
 	if (bcs->tx_skb) {
-		idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+		dev_kfree_skb(bcs->tx_skb);
 		bcs->tx_skb = NULL;
 		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 	}
diff --git a/drivers/isdn/hisax/jade_irq.c b/drivers/isdn/hisax/jade_irq.c
index 9cfcc7d6db91fb7eff8a38f90df1195829080581..e54c80c1a082d7978961c9a7e48df70a0e95da86 100644
--- a/drivers/isdn/hisax/jade_irq.c
+++ b/drivers/isdn/hisax/jade_irq.c
@@ -161,7 +161,6 @@ jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade)
 				if (!(skb = dev_alloc_skb(count)))
 					printk(KERN_WARNING "JADE %s receive out of memory\n", (jade ? "B":"A"));
 				else {
-					SET_SKB_FREE(skb);
 					memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
 					skb_queue_tail(&bcs->rqueue, skb);
 				}
@@ -177,7 +176,6 @@ jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade)
 			if (!(skb = dev_alloc_skb(fifo_size)))
 				printk(KERN_WARNING "HiSax: receive out of memory\n");
 			else {
-				SET_SKB_FREE(skb);
 				memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
 				skb_queue_tail(&bcs->rqueue, skb);
 			}
@@ -194,7 +192,7 @@ jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade)
 				if (bcs->st->lli.l1writewakeup &&
 					(PACKET_NOACK != bcs->tx_skb->pkt_type))
 					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count);
-				idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+				dev_kfree_skb(bcs->tx_skb);
 				bcs->hw.hscx.count = 0;
 				bcs->tx_skb = NULL;
 			}
diff --git a/drivers/isdn/hisax/l3_1tr6.c b/drivers/isdn/hisax/l3_1tr6.c
index ba8d95dbdb77ff20c18fe79196ad42226bc3ee97..31b25acdfc28b41244367be2ccf5f4ac8566b9bd 100644
--- a/drivers/isdn/hisax/l3_1tr6.c
+++ b/drivers/isdn/hisax/l3_1tr6.c
@@ -94,14 +94,14 @@ l3_1tr6_invalid(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 
-	idev_kfree_skb(skb, FREE_READ);
+	dev_kfree_skb(skb);
 	l3_1tr6_release_req(pc, 0, NULL);
 }
 
 static void
 l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb)
 {
-	idev_kfree_skb(skb, FREE_READ);
+	dev_kfree_skb(skb);
 	if (pc->st->l3.debug & L3_DEB_WARN)
 		l3_debug(pc->st, msg);
 	l3_1tr6_release_req(pc, 0, NULL);
@@ -251,7 +251,7 @@ l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg)
 		if ((FAC_SPV == p[3]) || (FAC_Activate == p[3]))
 			pc->para.spv = 1;
 	}
-	idev_kfree_skb(skb, FREE_READ);
+	dev_kfree_skb(skb);
 
 	/* Signal all services, linklevel takes care of Service-Indicator */
 	if (bcfound) {
@@ -290,7 +290,7 @@ l3_1tr6_setup_ack(struct l3_process *pc, u_char pr, void *arg)
 		l3_1tr6_error(pc, "missing setup_ack WE0_chanID", skb);
 		return;
 	}
-	idev_kfree_skb(skb, FREE_READ);
+	dev_kfree_skb(skb);
 	L3AddTimer(&pc->timer, T304, CC_T304);
 	pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
 }
@@ -321,7 +321,7 @@ l3_1tr6_call_sent(struct l3_process *pc, u_char pr, void *arg)
 		l3_1tr6_error(pc, "missing call sent WE0_chanID", skb);
 		return;
 	}
-	idev_kfree_skb(skb, FREE_READ);
+	dev_kfree_skb(skb);
 	L3AddTimer(&pc->timer, T310, CC_T310);
 	newl3state(pc, 3);
 	pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
@@ -332,7 +332,7 @@ l3_1tr6_alert(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 
-	idev_kfree_skb(skb, FREE_READ);
+	dev_kfree_skb(skb);
 	L3DelTimer(&pc->timer);	/* T304 */
 	newl3state(pc, 4);
 	pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
@@ -363,7 +363,7 @@ l3_1tr6_info(struct l3_process *pc, u_char pr, void *arg)
 		}
 	} else if (pc->st->l3.debug & L3_DEB_CHARGE)
 		l3_debug(pc->st, "charging info not found");
-	idev_kfree_skb(skb, FREE_READ);
+	dev_kfree_skb(skb);
 
 }
 
@@ -372,7 +372,7 @@ l3_1tr6_info_s2(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 
-	idev_kfree_skb(skb, FREE_READ);
+	dev_kfree_skb(skb);
 }
 
 static void
@@ -386,7 +386,7 @@ l3_1tr6_connect(struct l3_process *pc, u_char pr, void *arg)
 		return;
 	}
 	newl3state(pc, 10);
-	idev_kfree_skb(skb, FREE_READ);
+	dev_kfree_skb(skb);
 	pc->para.chargeinfo = 0;
 	pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
 }
@@ -414,7 +414,7 @@ l3_1tr6_rel(struct l3_process *pc, u_char pr, void *arg)
 		l3_1tr6_error(pc, "missing REL cause", skb);
 		return;
 	}
-	idev_kfree_skb(skb, FREE_READ);
+	dev_kfree_skb(skb);
 	StopAllL3Timer(pc);
 	newl3state(pc, 0);
 	l3_1TR6_message(pc, MT_N1_REL_ACK, PROTO_DIS_N1);
@@ -427,7 +427,7 @@ l3_1tr6_rel_ack(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 
-	idev_kfree_skb(skb, FREE_READ);
+	dev_kfree_skb(skb);
 	StopAllL3Timer(pc);
 	newl3state(pc, 0);
 	pc->para.cause = NO_CAUSE;
@@ -484,7 +484,7 @@ l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg)
 		l3_1tr6_error(pc, "missing connack date", skb);
 		return;
 	}
-	idev_kfree_skb(skb, FREE_READ);
+	dev_kfree_skb(skb);
 	newl3state(pc, 12);
 	pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
 }
@@ -499,7 +499,7 @@ l3_1tr6_connect_ack(struct l3_process *pc, u_char pr, void *arg)
 		l3_1tr6_error(pc, "missing connack date", skb);
 		return;
 	}
-	idev_kfree_skb(skb, FREE_READ);
+	dev_kfree_skb(skb);
 	newl3state(pc, 10);
 	pc->para.chargeinfo = 0;
 	L3DelTimer(&pc->timer);
@@ -814,7 +814,7 @@ up1tr6(struct PStack *st, int pr, void *arg)
 			sprintf(tmp, "up1tr6 len only %d", skb->len);
 			l3_debug(st, tmp);
 		}
-		idev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb(skb);
 		return;
 	}
 	if ((skb->data[0] & 0xfe) != PROTO_DIS_N0) {
@@ -824,7 +824,7 @@ up1tr6(struct PStack *st, int pr, void *arg)
 				skb->data[0], skb->len);
 			l3_debug(st, tmp);
 		}
-		idev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb(skb);
 		return;
 	}
 	if (skb->data[1] != 1) {
@@ -832,13 +832,13 @@ up1tr6(struct PStack *st, int pr, void *arg)
 			sprintf(tmp, "up1tr6 CR len not 1");
 			l3_debug(st, tmp);
 		}
-		idev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb(skb);
 		return;
 	}
 	cr = skb->data[2];
 	mt = skb->data[3];
 	if (skb->data[0] == PROTO_DIS_N0) {
-		idev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb(skb);
 		if (st->l3.debug & L3_DEB_STATE) {
 			sprintf(tmp, "up1tr6%s N0 mt %x unhandled",
 			     (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", mt);
@@ -853,11 +853,11 @@ up1tr6(struct PStack *st, int pr, void *arg)
 							sprintf(tmp, "up1tr6 no roc mem");
 							l3_debug(st, tmp);
 						}
-						idev_kfree_skb(skb, FREE_READ);
+						dev_kfree_skb(skb);
 						return;
 					}
 				} else {
-					idev_kfree_skb(skb, FREE_READ);
+					dev_kfree_skb(skb);
 					return;
 				}
 			} else if ((mt == MT_N1_REL) || (mt == MT_N1_REL_ACK) ||
@@ -865,7 +865,7 @@ up1tr6(struct PStack *st, int pr, void *arg)
 				(mt == MT_N1_REG_ACK) || (mt == MT_N1_REG_REJ) ||
 				(mt == MT_N1_SUSP_ACK) || (mt == MT_N1_RES_REJ) ||
 				(mt == MT_N1_INFO)) {
-				idev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb(skb);
 				return;
 			} else {
 				if (!(proc = new_l3_process(st, cr))) {
@@ -873,7 +873,7 @@ up1tr6(struct PStack *st, int pr, void *arg)
 						sprintf(tmp, "up1tr6 no roc mem");
 						l3_debug(st, tmp);
 					}
-					idev_kfree_skb(skb, FREE_READ);
+					dev_kfree_skb(skb);
 					return;
 				}
 				mt = MT_N1_INVALID;
@@ -884,7 +884,7 @@ up1tr6(struct PStack *st, int pr, void *arg)
 			    ((1 << proc->state) & datastln1[i].state))
 				break;
 		if (i == DATASTLN1_LEN) {
-			idev_kfree_skb(skb, FREE_READ);
+			dev_kfree_skb(skb);
 			if (st->l3.debug & L3_DEB_STATE) {
 				sprintf(tmp, "up1tr6%sstate %d mt %x unhandled",
 				  (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
diff --git a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c
index 22a5de9fa7ba783200d626a35663ee52658a0208..035ee54ca32d5798794271caedaf633ec93cbfa8 100644
--- a/drivers/isdn/hisax/l3dss1.c
+++ b/drivers/isdn/hisax/l3dss1.c
@@ -1,4 +1,4 @@
-/* $Id: l3dss1.c,v 2.19 1999/08/25 16:55:23 keil Exp $
+/* $Id: l3dss1.c,v 2.20 1999/10/11 22:16:27 keil Exp $
 
  * EURO/DSS1 D-channel protocol
  *
@@ -13,6 +13,9 @@
  *              Fritz Elfert
  *
  * $Log: l3dss1.c,v $
+ * Revision 2.20  1999/10/11 22:16:27  keil
+ * Suspend/Resume is possible without explicit ID too
+ *
  * Revision 2.19  1999/08/25 16:55:23  keil
  * Fix for test case TC10011
  *
@@ -90,7 +93,7 @@
 #include <linux/ctype.h>
 
 extern char *HiSax_getrev(const char *revision);
-const char *dss1_revision = "$Revision: 2.19 $";
+const char *dss1_revision = "$Revision: 2.20 $";
 
 #define EXT_BEARER_CAPS 1
 
@@ -2520,14 +2523,13 @@ l3dss1_suspend_req(struct l3_process *pc, u_char pr, void *arg)
 	u_char *msg = pc->chan->setup.phone;
 
 	MsgHead(p, pc->callref, MT_SUSPEND);
-
-	*p++ = IE_CALL_ID;
 	l = *msg++;
 	if (l && (l <= 10)) {	/* Max length 10 octets */
+		*p++ = IE_CALL_ID;
 		*p++ = l;
 		for (i = 0; i < l; i++)
 			*p++ = *msg++;
-	} else {
+	} else if (l) {
 		l3_debug(pc->st, "SUS wrong CALL_ID len %d", l);
 		return;
 	}
@@ -2596,13 +2598,13 @@ l3dss1_resume_req(struct l3_process *pc, u_char pr, void *arg)
 
 	MsgHead(p, pc->callref, MT_RESUME);
 
-	*p++ = IE_CALL_ID;
 	l = *msg++;
 	if (l && (l <= 10)) {	/* Max length 10 octets */
+		*p++ = IE_CALL_ID;
 		*p++ = l;
 		for (i = 0; i < l; i++)
 			*p++ = *msg++;
-	} else {
+	} else if (l) {
 		l3_debug(pc->st, "RES wrong CALL_ID len %d", l);
 		return;
 	}
@@ -2976,7 +2978,7 @@ dss1up(struct PStack *st, int pr, void *arg)
 	}
 	if (skb->len < 3) {
 		l3_debug(st, "dss1up frame too short(%d)", skb->len);
-		idev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb(skb);
 		return;
 	}
 
@@ -2986,13 +2988,13 @@ dss1up(struct PStack *st, int pr, void *arg)
 				 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
 				 skb->data[0], skb->len);
 		}
-		idev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb(skb);
 		return;
 	}
 	cr = getcallref(skb->data);
 	if (skb->len < ((skb->data[1] & 0x0f) + 3)) {
 		l3_debug(st, "dss1up frame too short(%d)", skb->len);
-		idev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb(skb);
 		return;
 	}
 	mt = skb->data[skb->data[1] + 2];
@@ -3001,26 +3003,26 @@ dss1up(struct PStack *st, int pr, void *arg)
 	if (cr == -2) {  /* wrong Callref */
 		if (st->l3.debug & L3_DEB_WARN)
 			l3_debug(st, "dss1up wrong Callref");
-		idev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb(skb);
 		return;
 	} else if (cr == -1) {	/* Dummy Callref */
 		if (mt == MT_FACILITY)
 			if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) {
 				l3dss1_parse_facility(st, NULL, 
 					(pr == (DL_DATA | INDICATION)) ? -1 : -2, p); 
-				idev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb(skb);
 				return;  
 			}
 		if (st->l3.debug & L3_DEB_WARN)
 			l3_debug(st, "dss1up dummy Callref (no facility msg or ie)");
-		idev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb(skb);
 		return;
 	} else if ((((skb->data[1] & 0x0f) == 1) && (0==(cr & 0x7f))) ||
 		(((skb->data[1] & 0x0f) == 2) && (0==(cr & 0x7fff)))) {	/* Global CallRef */
 		if (st->l3.debug & L3_DEB_STATE)
 			l3_debug(st, "dss1up Global CallRef");
 		global_handler(st, mt, skb);
-		idev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb(skb);
 		return;
 	} else if (!(proc = getl3proc(st, cr))) {
 		/* No transaction process exist, that means no call with
@@ -3032,7 +3034,7 @@ dss1up(struct PStack *st, int pr, void *arg)
 				/* Setup with wrong CREF flag */
 				if (st->l3.debug & L3_DEB_STATE)
 					l3_debug(st, "dss1up wrong CRef flag");
-				idev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb(skb);
 				return;
 			}
 			if (!(proc = dss1_new_l3_process(st, cr))) {
@@ -3040,7 +3042,7 @@ dss1up(struct PStack *st, int pr, void *arg)
 				 * CAUSE 0x2f "Resource unavailable", but this
 				 * need a new_l3_process too ... arghh
 				 */
-				idev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb(skb);
 				return;
 			}
 		} else if (mt == MT_STATUS) {
@@ -3074,17 +3076,17 @@ dss1up(struct PStack *st, int pr, void *arg)
 					l3dss1_msg_without_setup(proc, 0, NULL);
 				}
 			}
-			idev_kfree_skb(skb, FREE_READ);
+			dev_kfree_skb(skb);
 			return;
 		} else if (mt == MT_RELEASE_COMPLETE) {
-			idev_kfree_skb(skb, FREE_READ);
+			dev_kfree_skb(skb);
 			return;
 		} else {
 			/* ETS 300-104 part 2
 			 * if setup has not been made and a message type
 			 * (except MT_SETUP and RELEASE_COMPLETE) is received,
 			 * we must send MT_RELEASE_COMPLETE cause 81 */
-			idev_kfree_skb(skb, FREE_READ);
+			dev_kfree_skb(skb);
 			if ((proc = dss1_new_l3_process(st, cr))) {
 				proc->para.cause = 81;
 				l3dss1_msg_without_setup(proc, 0, NULL);
@@ -3093,7 +3095,7 @@ dss1up(struct PStack *st, int pr, void *arg)
 		}
 	}
 	if (l3dss1_check_messagetype_validity(proc, mt, skb)) {
-		idev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb(skb);
 		return;
 	}
 	if ((p = findie(skb->data, skb->len, IE_DISPLAY, 0)) != NULL) 
@@ -3120,7 +3122,7 @@ dss1up(struct PStack *st, int pr, void *arg)
 		}
 		datastatelist[i].rout(proc, pr, skb);
 	}
-	idev_kfree_skb(skb, FREE_READ);
+	dev_kfree_skb(skb);
 	return;
 }
 
diff --git a/drivers/isdn/hisax/md5sums.asc b/drivers/isdn/hisax/md5sums.asc
index 481a7dc720ea628853dafacfd267654bea1a1dbe..985bd4cb416c336ff40087b28ce0a2bad18b629c 100644
--- a/drivers/isdn/hisax/md5sums.asc
+++ b/drivers/isdn/hisax/md5sums.asc
@@ -6,26 +6,26 @@
 # Eicon Technology Diva 2.01 PCI cards in the moment.
 # Read ../../../Documentation/isdn/HiSax.cert for more informations.
 # 
-0cc164fadd4ec0e2983ec9735e209cbd  isac.c
-5fe8cb5526c78c91f61b0a94a423ea5d  isdnl1.c
-3b9522e8bf9e1c3e7848d729fc3dc05d  isdnl2.c
-f4184a50e35e5b568608e6cb7a693319  isdnl3.c
-ef70f4269fdc2ca15100f9b776afaa0d  tei.c
-65be616dd9d0e06c788d4fdd0fe5fe0a  callc.c
+3c2b1c96274cba97a8261d1cecc662b8  isac.c
+a9a15d069dbacb383cc24c238cb5ebbe  isdnl1.c
+bb51bd223040b511c18f091da5ab6456  isdnl2.c
+b7aa7f97b2374967a4aca7c52991142c  isdnl3.c
+a23fbf8879c1432b04640b8b04bdf419  tei.c
+d7072dbbeeb7c4c45f3810ed13cf5545  callc.c
 bf9605b36429898f7be6630034e83230  cert.c
-97c5e31c2739665b9c2976a30ce0b357  l3dss1.c
-b674eee9314a7cc413971c84003cf1d2  l3_1tr6.c
-51b2ef1efb221bb09fd08ab28bd2c565  elsa.c
-24cda374da44b57f6a1bb215424267b5  diva.c
+0e500813968adacaea2ef22c9cdd89eb  l3dss1.c
+2d748ced0eea375b21fe7ea91ca7917c  l3_1tr6.c
+d45fde1c90dda636ab134f2a51db435e  elsa.c
+0b5fb429f5bfe188fd42a5be01abbb14  diva.c
 # end of md5sums
 
 -----BEGIN PGP SIGNATURE-----
 Version: 2.6.3i
 Charset: noconv
 
-iQCVAwUBN8RgFjpxHvX/mS9tAQFzFQP/dOgnppDIm5ug1hnlWjQ/0BVurKEEJ64r
-DYDHwkcog+0gVE/EB1A7WUDqpFEnj52OZeoVinCfdVuVjP8IkrAJ8dCONsnXjBXz
-pzM+FunP1LFxuv2TVM0f642j98JxS8rObGWH8ZwY36P2QfNp47zorO2F9WvdCkuz
-sxJUtMUOlQ8=
-=8uEP
+iQCVAwUBOCYF6jpxHvX/mS9tAQFnxQP/dpHyNjbo5BhFEZ8qIgpPJzoCgV+b2pB+
+h9Z/Q1jg8l23L/lP9dW00ogrKnKziVUUJqg+wWVEAA7BnNVr3aeyQKFTVuOnK5MC
+Oy0Z98p530vgOBiZ47elNfpefjhfD3duSSYNA4R9fEHVZB/atKFYvB5GDGmrwjIZ
+2f3g3kBP5Os=
+=zNnO
 -----END PGP SIGNATURE-----
diff --git a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c
index fa85bbd27a7846a469f265ce457d4391e1f7151b..be65f1101ca09adda2addcc7cd08fdd0a76136b1 100644
--- a/drivers/isdn/hisax/mic.c
+++ b/drivers/isdn/hisax/mic.c
@@ -224,8 +224,8 @@ mic_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 	return(0);
 }
 
-int __init
-setup_mic(struct IsdnCard *card)
+__initfunc(int
+setup_mic(struct IsdnCard *card))
 {
 	int bytecnt;
 	struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c
index d88442e377d3e17ec44b5fc0b21f59c98c2c4527..3b502f7dbe4eefe943e97027f41fb29898705054 100644
--- a/drivers/isdn/hisax/netjet.c
+++ b/drivers/isdn/hisax/netjet.c
@@ -1,4 +1,4 @@
-/* $Id: netjet.c,v 1.13 1999/08/11 21:01:31 keil Exp $
+/* $Id: netjet.c,v 1.16 1999/10/14 20:25:29 keil Exp $
 
  * netjet.c     low level stuff for Traverse Technologie NETJet ISDN cards
  *
@@ -7,6 +7,15 @@
  * Thanks to Traverse Technologie Australia for documents and informations
  *
  * $Log: netjet.c,v $
+ * Revision 1.16  1999/10/14 20:25:29  keil
+ * add a statistic for error monitoring
+ *
+ * Revision 1.15  1999/09/04 06:20:06  keil
+ * Changes from kernel set_current_state()
+ *
+ * Revision 1.14  1999/08/31 11:20:25  paul
+ * various spelling corrections (new checksums may be needed, Karsten!)
+ *
  * Revision 1.13  1999/08/11 21:01:31  keil
  * new PCI codefix
  *
@@ -59,9 +68,6 @@
 #include "hscx.h"
 #include "isdnl1.h"
 #include <linux/pci.h>
-#ifndef COMPAT_HAS_NEW_PCI
-#include <linux/bios32.h>
-#endif
 #include <linux/interrupt.h>
 #include <linux/ppp_defs.h>
 
@@ -75,7 +81,7 @@
 
 extern const char *CardType[];
 
-const char *NETjet_revision = "$Revision: 1.13 $";
+const char *NETjet_revision = "$Revision: 1.16 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -406,7 +412,6 @@ static void got_frame(struct BCState *bcs, int count) {
 	if (!(skb = dev_alloc_skb(count)))
 		printk(KERN_WARNING "TIGER: receive out of memory\n");
 	else {
-		SET_SKB_FREE(skb);
 		memcpy(skb_put(skb, count), bcs->hw.tiger.rcvbuf, count);
 		skb_queue_tail(&bcs->rqueue, skb);
 	}
@@ -526,19 +531,26 @@ static void read_raw(struct BCState *bcs, u_int *buf, int cnt){
 							debugl1(bcs->cs, "tiger: frame not byte aligned");
 							state=HDLC_FLAG_SEARCH;
 							bcs->hw.tiger.r_err++;
+#ifdef ERROR_STATISTIC
+							bcs->err_inv++;
+#endif
 						} else {
 							if (bcs->cs->debug & L1_DEB_HSCX)
 								debugl1(bcs->cs,"tiger frame end(%d,%d): fcs(%x) i %x",
 									i,j,bcs->hw.tiger.r_fcs, bcs->cs->hw.njet.irqstat0);
 							if (bcs->hw.tiger.r_fcs == PPP_GOODFCS) {
 								got_frame(bcs, (bitcnt>>3)-3);
-							} else
+							} else {
 								if (bcs->cs->debug) {
 									debugl1(bcs->cs, "tiger FCS error");
 									printframe(bcs->cs, bcs->hw.tiger.rcvbuf,
 										(bitcnt>>3)-1, "rec");
 									bcs->hw.tiger.r_err++;
 								}
+#ifdef ERROR_STATISTIC
+							bcs->err_crc++;
+#endif
+							}
 							state=HDLC_FLAG_FOUND;
 						}
 						bitcnt=0;
@@ -556,10 +568,13 @@ static void read_raw(struct BCState *bcs, u_int *buf, int cnt){
 				if ((state == HDLC_FRAME_FOUND) &&
 					!(bitcnt & 7)) {
 					if ((bitcnt>>3)>=HSCX_BUFMAX) {
-						debugl1(bcs->cs, "tiger: frame to big");
+						debugl1(bcs->cs, "tiger: frame too big");
 						r_val=0; 
 						state=HDLC_FLAG_SEARCH;
 						bcs->hw.tiger.r_err++;
+#ifdef ERROR_STATISTIC
+						bcs->err_inv++;
+#endif
 					} else {
 						bcs->hw.tiger.rcvbuf[(bitcnt>>3)-1] = r_val;
 						bcs->hw.tiger.r_fcs = 
@@ -584,6 +599,12 @@ static void read_tiger(struct IsdnCardState *cs) {
 	if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_READ) {
 		debugl1(cs,"tiger warn read double dma %x/%x",
 			cs->hw.njet.irqstat0, cs->hw.njet.last_is0);
+#ifdef ERROR_STATISTIC
+		if (cs->bcs[0].mode)
+			cs->bcs[0].err_rdo++;
+		if (cs->bcs[1].mode)
+			cs->bcs[1].err_rdo++;
+#endif
 		return;
 	} else {
 		cs->hw.njet.last_is0 &= ~NETJET_IRQM0_READ;
@@ -705,7 +726,7 @@ static void write_raw(struct BCState *bcs, u_int *buf, int cnt) {
 				if (bcs->st->lli.l1writewakeup &&
 					(PACKET_NOACK != bcs->tx_skb->pkt_type))
 					bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
-				idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+				dev_kfree_skb(bcs->tx_skb);
 				bcs->tx_skb = NULL;
 			}
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
@@ -755,6 +776,12 @@ static void write_tiger(struct IsdnCardState *cs) {
 	if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_WRITE) {
 		debugl1(cs,"tiger warn write double dma %x/%x",
 			cs->hw.njet.irqstat0, cs->hw.njet.last_is0);
+#ifdef ERROR_STATISTIC
+		if (cs->bcs[0].mode)
+			cs->bcs[0].err_tx++;
+		if (cs->bcs[1].mode)
+			cs->bcs[1].err_tx++;
+#endif
 		return;
 	} else {
 		cs->hw.njet.last_is0 &= ~NETJET_IRQM0_WRITE;
@@ -842,7 +869,7 @@ close_tigerstate(struct BCState *bcs)
 		discard_queue(&bcs->rqueue);
 		discard_queue(&bcs->squeue);
 		if (bcs->tx_skb) {
-			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			dev_kfree_skb(bcs->tx_skb);
 			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		}
@@ -889,8 +916,8 @@ setstack_tiger(struct PStack *st, struct BCState *bcs)
 }
 
  
-void __init
-inittiger(struct IsdnCardState *cs)
+__initfunc(void
+inittiger(struct IsdnCardState *cs))
 {
 	if (!(cs->bcs[0].hw.tiger.send = kmalloc(NETJET_DMA_TXSIZE * sizeof(unsigned int),
 		GFP_KERNEL | GFP_DMA))) {
@@ -1027,11 +1054,11 @@ reset_netjet(struct IsdnCardState *cs)
 	sti();
 	cs->hw.njet.ctrl_reg = 0xff;  /* Reset On */
 	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
 	cs->hw.njet.ctrl_reg = 0x00;  /* Reset Off and status read clear */
 	byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
 	restore_flags(flags);
 	cs->hw.njet.auxd = 0;
@@ -1074,23 +1101,15 @@ NETjet_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 	return(0);
 }
 
-#ifdef COMPAT_HAS_NEW_PCI
 static 	struct pci_dev *dev_netjet __initdata = NULL;
-#else
-static  int pci_index __initdata = 0;
-#endif
 
-int __init
-setup_netjet(struct IsdnCard *card)
+__initfunc(int
+setup_netjet(struct IsdnCard *card))
 {
 	int bytecnt;
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 #if CONFIG_PCI
-#ifndef COMPAT_HAS_NEW_PCI
-	u_char pci_bus, pci_device_fn, pci_irq;
-	u_int pci_ioaddr, found;
-#endif
 #endif
 	strcpy(tmp, NETjet_revision);
 	printk(KERN_INFO "HiSax: Traverse Tech. NETjet driver Rev. %s\n", HiSax_getrev(tmp));
@@ -1098,7 +1117,6 @@ setup_netjet(struct IsdnCard *card)
 		return(0);
 	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 #if CONFIG_PCI
-#ifdef COMPAT_HAS_NEW_PCI
 	if (!pci_present()) {
 		printk(KERN_ERR "Netjet: no PCI bus present\n");
 		return(0);
@@ -1110,7 +1128,7 @@ setup_netjet(struct IsdnCard *card)
 			printk(KERN_WARNING "NETjet: No IRQ for PCI card found\n");
 			return(0);
 		}
-		cs->hw.njet.base = get_pcibase(dev_netjet, 0)
+		cs->hw.njet.base = dev_netjet->resource[ 0].start
 			& PCI_BASE_ADDRESS_IO_MASK; 
 		if (!cs->hw.njet.base) {
 			printk(KERN_WARNING "NETjet: No IO-Adr for PCI card found\n");
@@ -1120,41 +1138,6 @@ setup_netjet(struct IsdnCard *card)
 		printk(KERN_WARNING "NETjet: No PCI card found\n");
 		return(0);
 	}
-#else
-	found = 0;
-	for (; pci_index < 0xff; pci_index++) {
-		if (pcibios_find_device(PCI_VENDOR_TRAVERSE_TECH,
-			PCI_NETJET_ID, pci_index, &pci_bus, &pci_device_fn)
-			== PCIBIOS_SUCCESSFUL)
-			found = 1;
-		else
-			continue;
-		/* get IRQ */
-		pcibios_read_config_byte(pci_bus, pci_device_fn,
-			PCI_INTERRUPT_LINE, &pci_irq);
-
-		/* get IO address */
-		pcibios_read_config_dword(pci_bus, pci_device_fn,
-			PCI_BASE_ADDRESS_0, &pci_ioaddr);
-		if (found)
-			break;
-	}
-	if (!found) {
-		printk(KERN_WARNING "NETjet: No PCI card found\n");
-		return(0);
-	}
-	pci_index++;
-	if (!pci_irq) {
-		printk(KERN_WARNING "NETjet: No IRQ for PCI card found\n");
-		return(0);
-	}
-	if (!pci_ioaddr) {
-		printk(KERN_WARNING "NETjet: No IO-Adr for PCI card found\n");
-		return(0);
-	}
-	cs->hw.njet.base = pci_ioaddr & PCI_BASE_ADDRESS_IO_MASK; 
-	cs->irq = pci_irq;
-#endif /* COMPAT_HAS_NEW_PCI */
 	cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
 	cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
 	bytecnt = 256;
diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
index 7574a8e8fb64a5cfc24dc57e5a1120ad27b85263..4198bb5e0fa3f9822380f0098bcb84b0b0438f7e 100644
--- a/drivers/isdn/hisax/niccy.c
+++ b/drivers/isdn/hisax/niccy.c
@@ -40,9 +40,6 @@
 #include "hscx.h"
 #include "isdnl1.h"
 #include <linux/pci.h>
-#ifndef COMPAT_HAS_NEW_PCI
-#include <linux/bios32.h>
-#endif
 
 extern const char *CardType[];
 const char *niccy_revision = "$Revision: 1.8 $";
@@ -259,14 +256,10 @@ niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 	return(0);
 }
 
-#ifdef COMPAT_HAS_NEW_PCI
 static 	struct pci_dev *niccy_dev __initdata = NULL;
-#else
-static  int pci_index __initdata = 0;
-#endif
 
-int __init
-setup_niccy(struct IsdnCard *card)
+__initfunc(int
+setup_niccy(struct IsdnCard *card))
 {
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
@@ -306,7 +299,6 @@ setup_niccy(struct IsdnCard *card)
 	} else {
 #if CONFIG_PCI
 		u_int pci_ioaddr;
-#ifdef COMPAT_HAS_NEW_PCI
 		if (!pci_present()) {
 			printk(KERN_ERR "Niccy: no PCI bus present\n");
 			return(0);
@@ -320,66 +312,21 @@ setup_niccy(struct IsdnCard *card)
 				return(0);
 			}
 			cs->irq = niccy_dev->irq;
-			if (!get_pcibase(niccy_dev, 0)) {
+			if (!niccy_dev->resource[ 0].start) {
 				printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n");
 				return(0);
 			}
-			cs->hw.niccy.cfg_reg = get_pcibase(niccy_dev, 0) & PCI_BASE_ADDRESS_IO_MASK;
-			if (!get_pcibase(niccy_dev, 1)) {
+			cs->hw.niccy.cfg_reg = niccy_dev->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK;
+			if (!niccy_dev->resource[ 1].start) {
 				printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n");
 				return(0);
 			}
-			pci_ioaddr = get_pcibase(niccy_dev, 1) & PCI_BASE_ADDRESS_IO_MASK;
+			pci_ioaddr = niccy_dev->resource[ 1].start & PCI_BASE_ADDRESS_IO_MASK;
 			cs->subtyp = NICCY_PCI;
 		} else {
 			printk(KERN_WARNING "Niccy: No PCI card found\n");
 			return(0);
 		}
-#else
-		u_char pci_bus, pci_device_fn, pci_irq;
-
-		cs->subtyp = 0;
-		for (; pci_index < 0xff; pci_index++) {
-			if (pcibios_find_device(PCI_VENDOR_DR_NEUHAUS,
-			   PCI_NICCY_ID, pci_index, &pci_bus, &pci_device_fn)
-			   == PCIBIOS_SUCCESSFUL)
-				cs->subtyp = NICCY_PCI;
-			else
-				continue;
-			/* get IRQ */
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-				PCI_INTERRUPT_LINE, &pci_irq);
-
-			/* get IO pci AMCC address */
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-				PCI_BASE_ADDRESS_0, &pci_ioaddr);
-			if (!pci_ioaddr) {
-				printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n");
-				return(0);
-			}
-			cs->hw.niccy.cfg_reg = pci_ioaddr & ~3 ;
-			/* get IO address */
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-				PCI_BASE_ADDRESS_1, &pci_ioaddr);
-			if (cs->subtyp)
-				break;
-		}
-		if (!cs->subtyp) {
-			printk(KERN_WARNING "Niccy: No PCI card found\n");
-			return(0);
-		}
-		pci_index++;
-		if (!pci_irq) {
-			printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n");
-			return(0);
-		}
-		if (!pci_ioaddr) {
-			printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n");
-			return(0);
-		}
-		pci_ioaddr &= ~3; /* remove io/mem flag */
-		cs->irq = pci_irq;
-#endif /* COMPAT_HAS_NEW_PCI */
 		cs->irq_flags |= SA_SHIRQ;
 		cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA;
 		cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR;
diff --git a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c
index d8dfb2ee3f0606fa60ca47d37dab6b97942c3de8..51bc116584160cc5563b262f7be7249bc2aee536 100644
--- a/drivers/isdn/hisax/s0box.c
+++ b/drivers/isdn/hisax/s0box.c
@@ -212,8 +212,8 @@ S0Box_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 	return(0);
 }
 
-int __init
-setup_s0box(struct IsdnCard *card)
+__initfunc(int
+setup_s0box(struct IsdnCard *card))
 {
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
diff --git a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c
index 0d524faa869bc35d388d887dac9a139f765807c8..955a9a4de400ee136a4b1ee3be657ec4f093b16d 100644
--- a/drivers/isdn/hisax/saphir.c
+++ b/drivers/isdn/hisax/saphir.c
@@ -1,4 +1,4 @@
-/* $Id: saphir.c,v 1.3 1999/07/12 21:05:26 keil Exp $
+/* $Id: saphir.c,v 1.4 1999/09/04 06:20:06 keil Exp $
 
  * saphir.c low level stuff for HST Saphir 1
  *
@@ -8,6 +8,9 @@
  *
  *
  * $Log: saphir.c,v $
+ * Revision 1.4  1999/09/04 06:20:06  keil
+ * Changes from kernel set_current_state()
+ *
  * Revision 1.3  1999/07/12 21:05:26  keil
  * fix race in IRQ handling
  * added watchdog for lost IRQs
@@ -26,7 +29,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-static char *saphir_rev = "$Revision: 1.3 $";
+static char *saphir_rev = "$Revision: 1.4 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -234,10 +237,10 @@ saphir_reset(struct IsdnCardState *cs)
 	save_flags(flags);
 	sti();
 	byteout(cs->hw.saphir.cfg_reg + RESET_REG, 1);
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((30*HZ)/1000);	/* Timeout 30ms */
 	byteout(cs->hw.saphir.cfg_reg + RESET_REG, 0);
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((30*HZ)/1000);	/* Timeout 30ms */
 	restore_flags(flags);
 	byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val);
@@ -265,8 +268,8 @@ saphir_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 }
 
 
-int __init
-setup_saphir(struct IsdnCard *card)
+__initfunc(int
+setup_saphir(struct IsdnCard *card))
 {
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
index 2640555b2d374f49e0ee91cc10b819320f0ae74f..daa7953d9033c3b8b095cd7bae49fe2e47f5252e 100644
--- a/drivers/isdn/hisax/sedlbauer.c
+++ b/drivers/isdn/hisax/sedlbauer.c
@@ -1,4 +1,4 @@
-/* $Id: sedlbauer.c,v 1.16 1999/08/29 18:23:01 niemann Exp $
+/* $Id: sedlbauer.c,v 1.17 1999/09/04 06:20:06 keil Exp $
 
  * sedlbauer.c  low level stuff for Sedlbauer cards
  *              includes support for the Sedlbauer speed star (speed star II),
@@ -17,6 +17,9 @@
  *            Edgar Toernig
  *
  * $Log: sedlbauer.c,v $
+ * Revision 1.17  1999/09/04 06:20:06  keil
+ * Changes from kernel set_current_state()
+ *
  * Revision 1.16  1999/08/29 18:23:01  niemann
  * Fixed typo in errormsg
  *
@@ -100,13 +103,10 @@
 #include "isar.h"
 #include "isdnl1.h"
 #include <linux/pci.h>
-#ifndef COMPAT_HAS_NEW_PCI
-#include <linux/bios32.h>
-#endif
 
 extern const char *CardType[];
 
-const char *Sedlbauer_revision = "$Revision: 1.16 $";
+const char *Sedlbauer_revision = "$Revision: 1.17 $";
 
 const char *Sedlbauer_Types[] =
 	{"None", "speed card/win", "speed star", "speed fax+", 
@@ -474,10 +474,10 @@ reset_sedlbauer(struct IsdnCardState *cs)
 			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x20);
 			save_flags(flags);
 			sti();
-			current->state = TASK_INTERRUPTIBLE;
+			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout((10*HZ)/1000);
 			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x0);
-			current->state = TASK_INTERRUPTIBLE;
+			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout((10*HZ)/1000);
 			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_CONF, 0x0);
 			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ACFG, 0xff);
@@ -489,10 +489,10 @@ reset_sedlbauer(struct IsdnCardState *cs)
 			byteout(cs->hw.sedl.reset_on, SEDL_RESET);	/* Reset On */
 			save_flags(flags);
 			sti();
-			current->state = TASK_INTERRUPTIBLE;
+			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout((10*HZ)/1000);
 			byteout(cs->hw.sedl.reset_off, 0);	/* Reset Off */
-			current->state = TASK_INTERRUPTIBLE;
+			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout((10*HZ)/1000);
 			restore_flags(flags);
 		}
@@ -542,15 +542,11 @@ Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 }
 
 #ifdef SEDLBAUER_PCI
-#ifdef COMPAT_HAS_NEW_PCI
 static 	struct pci_dev *dev_sedl __initdata = NULL;
-#else
-static  int pci_index __initdata = 0;
-#endif
 #endif
 
-int __init
-setup_sedlbauer(struct IsdnCard *card)
+__initfunc(int
+setup_sedlbauer(struct IsdnCard *card))
 {
 	int bytecnt, ver, val;
 	struct IsdnCardState *cs = card->cs;
@@ -585,7 +581,6 @@ setup_sedlbauer(struct IsdnCard *card)
 /* Probe for Sedlbauer speed pci */
 #if SEDLBAUER_PCI
 #if CONFIG_PCI
-#ifdef COMPAT_HAS_NEW_PCI
 		if (!pci_present()) {
 			printk(KERN_ERR "Sedlbauer: no PCI bus present\n");
 			return(0);
@@ -597,41 +592,12 @@ setup_sedlbauer(struct IsdnCard *card)
 				printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n");
 				return(0);
 			}
-			cs->hw.sedl.cfg_reg = get_pcibase(dev_sedl, 0) &
+			cs->hw.sedl.cfg_reg = dev_sedl->resource[ 0].start &
 				PCI_BASE_ADDRESS_IO_MASK; 
 		} else {
 			printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
 			return(0);
 		}
-#else
-		for (; pci_index < 255; pci_index++) {
-			unsigned char pci_bus, pci_device_fn;
-			unsigned int ioaddr;
-			unsigned char irq;
-
-			if (pcibios_find_device (PCI_VENDOR_SEDLBAUER,
-						PCI_SPEEDPCI_ID, pci_index,
-						&pci_bus, &pci_device_fn) != 0) {
-				continue;
-			}
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-					PCI_INTERRUPT_LINE, &irq);
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-					PCI_BASE_ADDRESS_0, &ioaddr);
-			cs->irq = irq;
-			cs->hw.sedl.cfg_reg = ioaddr & PCI_BASE_ADDRESS_IO_MASK; 
-			if (!cs->hw.sedl.cfg_reg) {
-				printk(KERN_WARNING "Sedlbauer: No IO-Adr for PCI card found\n");
-				return(0);
-			}
-			break;
-		}	
-		if (pci_index == 255) {
-			printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
-			return(0);
-		}
-		pci_index++;
-#endif /* COMPAT_HAS_NEW_PCI */
 		 cs->irq_flags |= SA_SHIRQ;
 		cs->hw.sedl.bus = SEDL_BUS_PCI;
 		cs->hw.sedl.chip = SEDL_CHIP_IPAC;
diff --git a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c
index 29fae02f7c39d5afca279aee25f32df405d1aa0b..91a6a6ae18da5c4f2375342d26d5e0573c198c8c 100644
--- a/drivers/isdn/hisax/sportster.c
+++ b/drivers/isdn/hisax/sportster.c
@@ -1,4 +1,4 @@
-/* $Id: sportster.c,v 1.9 1999/07/12 21:05:29 keil Exp $
+/* $Id: sportster.c,v 1.10 1999/09/04 06:20:06 keil Exp $
 
  * sportster.c     low level stuff for USR Sportster internal TA
  *
@@ -7,6 +7,9 @@
  * Thanks to Christian "naddy" Weisgerber (3Com, US Robotics) for documentation
  *
  * $Log: sportster.c,v $
+ * Revision 1.10  1999/09/04 06:20:06  keil
+ * Changes from kernel set_current_state()
+ *
  * Revision 1.9  1999/07/12 21:05:29  keil
  * fix race in IRQ handling
  * added watchdog for lost IRQs
@@ -43,7 +46,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-const char *sportster_revision = "$Revision: 1.9 $";
+const char *sportster_revision = "$Revision: 1.10 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -177,11 +180,11 @@ reset_sportster(struct IsdnCardState *cs)
 	byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
 	save_flags(flags);
 	sti();
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((10*HZ)/1000);
 	cs->hw.spt.res_irq &= ~SPORTSTER_RESET; /* Reset Off */
 	byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((10*HZ)/1000);
 	restore_flags(flags);
 }
@@ -208,8 +211,8 @@ Sportster_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 	return(0);
 }
 
-int __init
-get_io_range(struct IsdnCardState *cs)
+__initfunc(int
+get_io_range(struct IsdnCardState *cs))
 {
 	int i, j, adr;
 	
@@ -234,8 +237,8 @@ get_io_range(struct IsdnCardState *cs)
 	}
 }
 
-int __init
-setup_sportster(struct IsdnCard *card)
+__initfunc(int
+setup_sportster(struct IsdnCard *card))
 {
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
diff --git a/drivers/isdn/hisax/tei.c b/drivers/isdn/hisax/tei.c
index f21284bece2c2a9a99a0f69af2e2467d38bc2ca2..8454f1554ac5e0bb2daf7f3fe6a480115aafcf3b 100644
--- a/drivers/isdn/hisax/tei.c
+++ b/drivers/isdn/hisax/tei.c
@@ -169,7 +169,6 @@ put_tei_msg(struct PStack *st, u_char m_id, unsigned int ri, u_char tei)
 		printk(KERN_WARNING "HiSax: No skb for TEI manager\n");
 		return;
 	}
-	SET_SKB_FREE(skb);
 	bp = skb_put(skb, 3);
 	bp[0] = (TEI_SAPI << 2);
 	bp[1] = (GROUP_TEI << 1) | 0x1;
@@ -371,7 +370,7 @@ tei_l1l2(struct PStack *st, int pr, void *arg)
 	int mt;
 
 	if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
-		idev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb(skb);
 		return;
 	}
 
@@ -417,7 +416,7 @@ tei_l1l2(struct PStack *st, int pr, void *arg)
 		st->ma.tei_m.printdebug(&st->ma.tei_m,
 			"tei handler wrong pr %x\n", pr);
 	}
-	idev_kfree_skb(skb, FREE_READ);
+	dev_kfree_skb(skb);
 }
 
 static void
diff --git a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c
index 430ea2768f99eb757dd8d7c54ea062b302e9f370..c34dc5613b2ba58eb037c7be6dff5e83f5715d82 100644
--- a/drivers/isdn/hisax/teleint.c
+++ b/drivers/isdn/hisax/teleint.c
@@ -1,4 +1,4 @@
-/* $Id: teleint.c,v 1.9 1999/07/12 21:05:30 keil Exp $
+/* $Id: teleint.c,v 1.11 1999/09/04 06:20:06 keil Exp $
 
  * teleint.c     low level stuff for TeleInt isdn cards
  *
@@ -6,6 +6,12 @@
  *
  *
  * $Log: teleint.c,v $
+ * Revision 1.11  1999/09/04 06:20:06  keil
+ * Changes from kernel set_current_state()
+ *
+ * Revision 1.10  1999/08/31 11:20:27  paul
+ * various spelling corrections (new checksums may be needed, Karsten!)
+ *
  * Revision 1.9  1999/07/12 21:05:30  keil
  * fix race in IRQ handling
  * added watchdog for lost IRQs
@@ -45,7 +51,7 @@
 
 extern const char *CardType[];
 
-const char *TeleInt_revision = "$Revision: 1.9 $";
+const char *TeleInt_revision = "$Revision: 1.11 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -64,7 +70,7 @@ readreg(unsigned int ale, unsigned int adr, u_char off)
 	while (ret && --max_delay)
 		ret = HFC_BUSY & bytein(ale);
 	if (!max_delay) {
-		printk(KERN_WARNING "TeleInt Busy not inaktive\n");
+		printk(KERN_WARNING "TeleInt Busy not inactive\n");
 		restore_flags(flags);
 		return (0);
 	}
@@ -86,7 +92,7 @@ readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size
 		while (ret && --max_delay)
 			ret = HFC_BUSY & bytein(ale);
 		if (!max_delay) {
-			printk(KERN_WARNING "TeleInt Busy not inaktive\n");
+			printk(KERN_WARNING "TeleInt Busy not inactive\n");
 			return;
 		}
 		data[i] = bytein(adr);
@@ -108,7 +114,7 @@ writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
 	while (ret && --max_delay)
 		ret = HFC_BUSY & bytein(ale);
 	if (!max_delay) {
-		printk(KERN_WARNING "TeleInt Busy not inaktive\n");
+		printk(KERN_WARNING "TeleInt Busy not inactive\n");
 		restore_flags(flags);
 		return;
 	}
@@ -130,7 +136,7 @@ writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int siz
 		while (ret && --max_delay)
 			ret = HFC_BUSY & bytein(ale);
 		if (!max_delay) {
-			printk(KERN_WARNING "TeleInt Busy not inaktive\n");
+			printk(KERN_WARNING "TeleInt Busy not inactive\n");
 			return;
 		}
 		byteout(adr, data[i]);
@@ -254,11 +260,11 @@ reset_TeleInt(struct IsdnCardState *cs)
 	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm);	/* Reset On */
 	save_flags(flags);
 	sti();
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((30*HZ)/1000);
 	cs->hw.hfc.cirm &= ~HFC_RESET;
 	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm);	/* Reset Off */
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((10*HZ)/1000);
 	restore_flags(flags);
 }
@@ -289,8 +295,8 @@ TeleInt_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 	return(0);
 }
 
-int __init
-setup_TeleInt(struct IsdnCard *card)
+__initfunc(int
+setup_TeleInt(struct IsdnCard *card))
 {
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
diff --git a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c
index 4046c4357d25ee8a75c670eaff958a729b6d0a89..866e8dac5effc29f1b5f4d2f02aaa885b0d5f290 100644
--- a/drivers/isdn/hisax/teles0.c
+++ b/drivers/isdn/hisax/teles0.c
@@ -295,8 +295,8 @@ Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 	return(0);
 }
 
-int __init
-setup_teles0(struct IsdnCard *card)
+__initfunc(int
+setup_teles0(struct IsdnCard *card))
 {
 	u_char val;
 	struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c
index 3210a6af68a1adea9b291c84be9d369e1e0ab5d4..0db245abcfc860b28ef83761d8eade039cfd1e8b 100644
--- a/drivers/isdn/hisax/teles3.c
+++ b/drivers/isdn/hisax/teles3.c
@@ -321,8 +321,8 @@ Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 	return(0);
 }
 
-int __init
-setup_teles3(struct IsdnCard *card)
+__initfunc(int
+setup_teles3(struct IsdnCard *card))
 {
 	u_char val;
 	struct IsdnCardState *cs = card->cs;
diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c
index 9ffe99918bb8cd9b7b42bdac10c63f8eae971c5d..eee4ba322b56b5a7476e8c7c53c1de1ad4bdcad4 100644
--- a/drivers/isdn/hisax/telespci.c
+++ b/drivers/isdn/hisax/telespci.c
@@ -42,9 +42,6 @@
 #include "hscx.h"
 #include "isdnl1.h"
 #include <linux/pci.h>
-#ifndef COMPAT_HAS_NEW_PCI
-#include <linux/bios32.h>
-#endif
 
 extern const char *CardType[];
 const char *telespci_revision = "$Revision: 2.9 $";
@@ -304,29 +301,19 @@ TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 	return(0);
 }
 
-#ifdef COMPAT_HAS_NEW_PCI
 static 	struct pci_dev *dev_tel __initdata = NULL;
-#else
-static 	int pci_index __initdata = 0;
-#endif
 
-int __init
-setup_telespci(struct IsdnCard *card)
+__initfunc(int
+setup_telespci(struct IsdnCard *card))
 {
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
-#ifndef COMPAT_HAS_NEW_PCI
-	u_char pci_bus, pci_device_fn, pci_irq;
-	u_int pci_memaddr;
-	u_char found = 0;
-#endif
 
 	strcpy(tmp, telespci_revision);
 	printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
 	if (cs->typ != ISDN_CTYPE_TELESPCI)
 		return (0);
 #if CONFIG_PCI
-#ifdef COMPAT_HAS_NEW_PCI
 	if (!pci_present()) {
 		printk(KERN_ERR "TelesPCI: no PCI bus present\n");
 		return(0);
@@ -337,40 +324,14 @@ setup_telespci(struct IsdnCard *card)
 			printk(KERN_WARNING "Teles: No IRQ for PCI card found\n");
 			return(0);
 		}
-		cs->hw.teles0.membase = (u_int) ioremap(get_pcibase(dev_tel, 0),
+		cs->hw.teles0.membase = (u_int) ioremap(dev_tel->resource[ 0].start,
 			PAGE_SIZE);
 		printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n",
-			get_pcibase(dev_tel, 0), dev_tel->irq);
+			dev_tel->resource[ 0].start, dev_tel->irq);
 	} else {
 		printk(KERN_WARNING "TelesPCI: No PCI card found\n");
 		return(0);
 	}
-#else
-	for (; pci_index < 0xff; pci_index++) {
-		if (pcibios_find_device (0x11DE, 0x6120,
-			pci_index, &pci_bus, &pci_device_fn)
-			== PCIBIOS_SUCCESSFUL) {
-			found = 1;
-		} else {
-			break;
-		}
-		pcibios_read_config_dword(pci_bus, pci_device_fn,
-				PCI_BASE_ADDRESS_0, &pci_memaddr);
-		pcibios_read_config_byte(pci_bus, pci_device_fn,
-				PCI_INTERRUPT_LINE, &pci_irq);
-
-		printk(KERN_INFO "Found: Zoran, base-address: 0x%x,"
-			" irq: 0x%x\n", pci_memaddr, pci_irq);
-		break;
-	}
-	if (!found) {
-		printk(KERN_WARNING "TelesPCI: No PCI card found\n");
-		return(0);
-	}
-	pci_index++;
-	cs->irq = pci_irq;
-	cs->hw.teles0.membase = (u_int) vremap(pci_memaddr, PAGE_SIZE);
-#endif /* COMPAT_HAS_NEW_PCI */
 #else
 	printk(KERN_WARNING "HiSax: Teles/PCI and NO_PCI_BIOS\n");
 	printk(KERN_WARNING "HiSax: Teles/PCI unable to config\n");
diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
new file mode 100644
index 0000000000000000000000000000000000000000..724ce52c9913d7f0e9ffbf6cd4f538c10561f48e
--- /dev/null
+++ b/drivers/isdn/hisax/w6692.c
@@ -0,0 +1,1063 @@
+/* $Id: w6692.c,v 1.1 1999/09/04 06:28:58 keil Exp $
+
+ * w6692.c   Winbond W6692 specific routines
+ *
+ * Author       Petr Novak <petr.novak@i.cz>
+ *              (based on HiSax driver by Karsten Keil)
+ *
+ *              This file is (c) under GNU PUBLIC LICENSE
+ *
+ * $Log: w6692.c,v $
+ * Revision 1.1  1999/09/04 06:28:58  keil
+ * first revision
+ *
+ *
+ *
+ */
+
+#include <linux/config.h>
+#define __NO_VERSION__
+#include "hisax.h"
+#include "w6692.h"
+#include "isdnl1.h"
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+
+#define	PCI_VEND_ASUSCOM	0x675
+#define	PCI_DEV_ASUSCOMPCI1	0x1702
+#ifndef PCI_VENDOR_ID_WINBOND2
+#define PCI_VENDOR_ID_WINBOND2	0x1050
+#endif
+#define	PCI_DEVICE_W6692	0x6692
+
+/* table entry in the PCI devices list */
+typedef struct {
+	int vendor_id;
+	int device_id;
+	char *vendor_name;
+	char *card_name;
+} PCI_ENTRY;
+
+static const PCI_ENTRY id_list[] =
+{
+	{PCI_VEND_ASUSCOM, PCI_DEV_ASUSCOMPCI1, "AsusCom", "TA XXX"},
+	{PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_W6692, "Winbond", "W6692"},
+	{0, 0, NULL, NULL}
+};
+
+extern const char *CardType[];
+
+const char *w6692_revision = "$Revision: 1.1 $";
+
+#define DBUSY_TIMER_VALUE 80
+
+static char *W6692Ver[] HISAX_INITDATA =
+{"W6692 V00", "W6692 V01", "W6692 V10",
+ "W6692 V11"};
+
+static void
+W6692Version(struct IsdnCardState *cs, char *s)
+{
+	int val;
+
+	val = cs->readW6692(cs, W_D_RBCH);
+	printk(KERN_INFO "%s Winbond W6692 version (%x): %s\n", s, val, W6692Ver[(val >> 6) & 3]);
+}
+
+static void
+ph_command(struct IsdnCardState *cs, unsigned int command)
+{
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "ph_command %x", command);
+	cs->writeisac(cs, W_CIX, command);
+}
+
+
+static void
+W6692_new_ph(struct IsdnCardState *cs)
+{
+	switch (cs->dc.w6692.ph_state) {
+		case (W_L1CMD_RST):
+			ph_command(cs, W_L1CMD_DRC);
+			l1_msg(cs, HW_RESET | INDICATION, NULL);
+			/* fallthru */
+		case (W_L1IND_CD):
+			l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL);
+			break;
+		case (W_L1IND_DRD):
+			l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
+			break;
+		case (W_L1IND_CE):
+			l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
+			break;
+		case (W_L1IND_LD):
+			l1_msg(cs, HW_RSYNC | INDICATION, NULL);
+			break;
+		case (W_L1IND_ARD):
+			l1_msg(cs, HW_INFO2 | INDICATION, NULL);
+			break;
+		case (W_L1IND_AI8):
+			l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
+			break;
+		case (W_L1IND_AI10):
+			l1_msg(cs, HW_INFO4_P10 | INDICATION, NULL);
+			break;
+		default:
+			break;
+	}
+}
+
+static void
+W6692_bh(struct IsdnCardState *cs)
+{
+	struct PStack *stptr;
+
+	if (!cs)
+		return;
+	if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
+		if (cs->debug)
+			debugl1(cs, "D-Channel Busy cleared");
+		stptr = cs->stlist;
+		while (stptr != NULL) {
+			stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
+			stptr = stptr->next;
+		}
+	}
+	if (test_and_clear_bit(D_L1STATECHANGE, &cs->event))
+		W6692_new_ph(cs);
+	if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
+		DChannel_proc_rcv(cs);
+	if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
+		DChannel_proc_xmt(cs);
+/*
+   if (test_and_clear_bit(D_RX_MON1, &cs->event))
+   arcofi_fsm(cs, ARCOFI_RX_END, NULL);
+   if (test_and_clear_bit(D_TX_MON1, &cs->event))
+   arcofi_fsm(cs, ARCOFI_TX_END, NULL);
+ */
+}
+
+void
+W6692_sched_event(struct IsdnCardState *cs, int event)
+{
+	test_and_set_bit(event, &cs->event);
+	queue_task(&cs->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+}
+
+static void
+W6692B_sched_event(struct BCState *bcs, int event)
+{
+	bcs->event |= 1 << event;
+	queue_task(&bcs->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+}
+
+static void
+W6692_empty_fifo(struct IsdnCardState *cs, int count)
+{
+	u_char *ptr;
+	long flags;
+
+	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
+		debugl1(cs, "W6692_empty_fifo");
+
+	if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "W6692_empty_fifo overrun %d",
+				cs->rcvidx + count);
+		cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK);
+		cs->rcvidx = 0;
+		return;
+	}
+	ptr = cs->rcvbuf + cs->rcvidx;
+	cs->rcvidx += count;
+	save_flags(flags);
+	cli();
+	cs->readW6692fifo(cs, ptr, count);
+	cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK);
+	restore_flags(flags);
+	if (cs->debug & L1_DEB_ISAC_FIFO) {
+		char *t = cs->dlog;
+
+		t += sprintf(t, "W6692_empty_fifo cnt %d", count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, cs->dlog);
+	}
+}
+
+static void
+W6692_fill_fifo(struct IsdnCardState *cs)
+{
+	int count, more;
+	u_char *ptr;
+	long flags;
+
+	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
+		debugl1(cs, "W6692_fill_fifo");
+
+	if (!cs->tx_skb)
+		return;
+
+	count = cs->tx_skb->len;
+	if (count <= 0)
+		return;
+
+	more = 0;
+	if (count > W_D_FIFO_THRESH) {
+		more = !0;
+		count = W_D_FIFO_THRESH;
+	}
+	save_flags(flags);
+	cli();
+	ptr = cs->tx_skb->data;
+	skb_pull(cs->tx_skb, count);
+	cs->tx_cnt += count;
+	cs->writeW6692fifo(cs, ptr, count);
+	cs->writeW6692(cs, W_D_CMDR, more ? W_D_CMDR_XMS : (W_D_CMDR_XMS | W_D_CMDR_XME));
+	restore_flags(flags);
+	if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
+		debugl1(cs, "W6692_fill_fifo dbusytimer running");
+		del_timer(&cs->dbusytimer);
+	}
+	init_timer(&cs->dbusytimer);
+	cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000);
+	add_timer(&cs->dbusytimer);
+	if (cs->debug & L1_DEB_ISAC_FIFO) {
+		char *t = cs->dlog;
+
+		t += sprintf(t, "W6692_fill_fifo cnt %d", count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, cs->dlog);
+	}
+}
+
+static void
+W6692B_empty_fifo(struct BCState *bcs, int count)
+{
+	u_char *ptr;
+	struct IsdnCardState *cs = bcs->cs;
+	long flags;
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "W6692B_empty_fifo");
+
+	if (bcs->hw.w6692.rcvidx + count > HSCX_BUFMAX) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "W6692B_empty_fifo: incoming packet too large");
+		cs->BC_Write_Reg(cs, bcs->hw.w6692.bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
+		bcs->hw.w6692.rcvidx = 0;
+		return;
+	}
+	ptr = bcs->hw.w6692.rcvbuf + bcs->hw.w6692.rcvidx;
+	bcs->hw.w6692.rcvidx += count;
+	save_flags(flags);
+	cli();
+	READW6692BFIFO(cs, bcs->hw.w6692.bchan, ptr, count);
+	cs->BC_Write_Reg(cs, bcs->hw.w6692.bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
+	restore_flags(flags);
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "W6692B_empty_fifo %c cnt %d",
+			     bcs->hw.w6692.bchan ? 'B' : 'A', count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
+	}
+}
+
+static void
+W6692B_fill_fifo(struct BCState *bcs)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	int more, count;
+	u_char *ptr;
+	long flags;
+
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "W6692B_fill_fifo");
+
+	if (!bcs->tx_skb)
+		return;
+	if (bcs->tx_skb->len <= 0)
+		return;
+
+	more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
+	if (bcs->tx_skb->len > W_B_FIFO_THRESH) {
+		more = !0;
+		count = W_B_FIFO_THRESH;
+	} else
+		count = bcs->tx_skb->len;
+
+	save_flags(flags);
+	cli();
+	ptr = bcs->tx_skb->data;
+	skb_pull(bcs->tx_skb, count);
+	bcs->tx_cnt -= count;
+	bcs->hw.w6692.count += count;
+	WRITEW6692BFIFO(cs, bcs->hw.w6692.bchan, ptr, count);
+	cs->BC_Write_Reg(cs, bcs->hw.w6692.bchan, W_B_CMDR, W_B_CMDR_RACT | W_B_CMDR_XMS | (more ? 0 : W_B_CMDR_XME));
+	restore_flags(flags);
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "W6692B_fill_fifo %c cnt %d",
+			     bcs->hw.w6692.bchan ? 'B' : 'A', count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
+	}
+}
+
+static void
+W6692B_interrupt(struct IsdnCardState *cs, u_char bchan)
+{
+	u_char val;
+	u_char r;
+	struct BCState *bcs = cs->bcs + bchan;
+	struct sk_buff *skb;
+	int count;
+
+	val = cs->BC_Read_Reg(cs, bchan, W_B_EXIR);
+	debugl1(cs, "W6692B chan %d B_EXIR 0x%02X", bchan, val);
+
+	if (!test_bit(BC_FLG_INIT, &bcs->Flag)) {
+		debugl1(cs, "W6692B not INIT yet");
+		return;
+	}
+	if (val & W_B_EXI_RME) {	/* RME */
+		r = cs->BC_Read_Reg(cs, bchan, W_B_STAR);
+		if (r & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB | W_B_STAR_XDOW)) {
+			if ((r & W_B_STAR_RDOV) && bcs->mode)
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "W6692 B RDOV mode=%d",
+						bcs->mode);
+			if (r & W_B_STAR_CRCE)
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "W6692 B CRC error");
+			cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT);
+		} else {
+			count = cs->BC_Read_Reg(cs, bchan, W_B_RBCL) & (W_B_FIFO_THRESH - 1);
+			if (count == 0)
+				count = W_B_FIFO_THRESH;
+			W6692B_empty_fifo(bcs, count);
+			if ((count = bcs->hw.w6692.rcvidx) > 0) {
+				if (cs->debug & L1_DEB_HSCX_FIFO)
+					debugl1(cs, "W6692 Bchan Frame %d", count);
+				if (!(skb = dev_alloc_skb(count)))
+					printk(KERN_WARNING "W6692: Bchan receive out of memory\n");
+				else {
+					memcpy(skb_put(skb, count), bcs->hw.w6692.rcvbuf, count);
+					skb_queue_tail(&bcs->rqueue, skb);
+				}
+			}
+		}
+		bcs->hw.w6692.rcvidx = 0;
+		W6692B_sched_event(bcs, B_RCVBUFREADY);
+	}
+	if (val & W_B_EXI_RMR) {	/* RMR */
+		W6692B_empty_fifo(bcs, W_B_FIFO_THRESH);
+		if (bcs->mode == L1_MODE_TRANS) {
+			/* receive audio data */
+			if (!(skb = dev_alloc_skb(W_B_FIFO_THRESH)))
+				printk(KERN_WARNING "HiSax: receive out of memory\n");
+			else {
+				memcpy(skb_put(skb, W_B_FIFO_THRESH), bcs->hw.w6692.rcvbuf, W_B_FIFO_THRESH);
+				skb_queue_tail(&bcs->rqueue, skb);
+			}
+			bcs->hw.w6692.rcvidx = 0;
+			W6692B_sched_event(bcs, B_RCVBUFREADY);
+		}
+	}
+	if (val & W_B_EXI_XFR) {	/* XFR */
+		if (bcs->tx_skb) {
+			if (bcs->tx_skb->len) {
+				W6692B_fill_fifo(bcs);
+				return;
+			} else {
+				if (bcs->st->lli.l1writewakeup &&
+				 (PACKET_NOACK != bcs->tx_skb->pkt_type))
+					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.w6692.count);
+				dev_kfree_skb(bcs->tx_skb);
+				bcs->hw.w6692.count = 0;
+				bcs->tx_skb = NULL;
+			}
+		}
+		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+			bcs->hw.w6692.count = 0;
+			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+			W6692B_fill_fifo(bcs);
+		} else {
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			W6692B_sched_event(bcs, B_XMTBUFREADY);
+		}
+	}
+	if (val & W_B_EXI_XDUN) {	/* XDUN */
+		if (bcs->mode == 1)
+			W6692B_fill_fifo(bcs);
+		else {
+			/* Here we lost an TX interrupt, so
+			   * restart transmitting the whole frame.
+			 */
+			if (bcs->tx_skb) {
+				skb_push(bcs->tx_skb, bcs->hw.w6692.count);
+				bcs->tx_cnt += bcs->hw.w6692.count;
+				bcs->hw.w6692.count = 0;
+			}
+			cs->BC_Write_Reg(cs, bcs->hw.w6692.bchan, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "W6692 B EXIR %x Lost TX", val);
+		}
+	}
+}
+
+static void
+W6692_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char val, exval, v1;
+	struct sk_buff *skb;
+	unsigned int count;
+	long flags;
+	int icnt = 5;
+
+	if (!cs) {
+		printk(KERN_WARNING "W6692: Spurious interrupt!\n");
+		return;
+	}
+	val = cs->readW6692(cs, W_ISTA);
+
+      StartW6692:
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "W6692 ISTA %x", val);
+
+	if (val & W_INT_D_RME) {	/* RME */
+		exval = cs->readW6692(cs, W_D_RSTA);
+		if (exval & (W_D_RSTA_RDOV | W_D_RSTA_CRCE | W_D_RSTA_RMB)) {
+			if (exval & W_D_RSTA_RDOV)
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "W6692 RDOV");
+			if (exval & W_D_RSTA_CRCE)
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "W6692 D-channel CRC error");
+			if (exval & W_D_RSTA_RMB)
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "W6692 D-channel ABORT");
+			cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST);
+		} else {
+			count = cs->readW6692(cs, W_D_RBCL) & (W_D_FIFO_THRESH - 1);
+			if (count == 0)
+				count = W_D_FIFO_THRESH;
+			W6692_empty_fifo(cs, count);
+			save_flags(flags);
+			cli();
+			if ((count = cs->rcvidx) > 0) {
+				cs->rcvidx = 0;
+				if (!(skb = alloc_skb(count, GFP_ATOMIC)))
+					printk(KERN_WARNING "HiSax: D receive out of memory\n");
+				else {
+					memcpy(skb_put(skb, count), cs->rcvbuf, count);
+					skb_queue_tail(&cs->rq, skb);
+				}
+			}
+			restore_flags(flags);
+		}
+		cs->rcvidx = 0;
+		W6692_sched_event(cs, D_RCVBUFREADY);
+	}
+	if (val & W_INT_D_RMR) {	/* RMR */
+		W6692_empty_fifo(cs, W_D_FIFO_THRESH);
+	}
+	if (val & W_INT_D_XFR) {	/* XFR */
+		if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+			del_timer(&cs->dbusytimer);
+		if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+			W6692_sched_event(cs, D_CLEARBUSY);
+		if (cs->tx_skb) {
+			if (cs->tx_skb->len) {
+				W6692_fill_fifo(cs);
+				goto afterXFR;
+			} else {
+				dev_kfree_skb(cs->tx_skb);
+				cs->tx_cnt = 0;
+				cs->tx_skb = NULL;
+			}
+		}
+		if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
+			cs->tx_cnt = 0;
+			W6692_fill_fifo(cs);
+		} else
+			W6692_sched_event(cs, D_XMTBUFREADY);
+	}
+      afterXFR:
+	if (val & (W_INT_XINT0 | W_INT_XINT1)) {	/* XINT0/1 - never */
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "W6692 spurious XINT!");
+	}
+	if (val & W_INT_D_EXI) {	/* EXI */
+		exval = cs->readW6692(cs, W_D_EXIR);
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "W6692 D_EXIR %02x", exval);
+		if (exval & (W_D_EXI_XDUN | W_D_EXI_XCOL)) {	/* Transmit underrun/collision */
+			debugl1(cs, "W6692 D-chan underrun/collision");
+			printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL\n");
+			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+				del_timer(&cs->dbusytimer);
+			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+				W6692_sched_event(cs, D_CLEARBUSY);
+			if (cs->tx_skb) {	/* Restart frame */
+				skb_push(cs->tx_skb, cs->tx_cnt);
+				cs->tx_cnt = 0;
+				W6692_fill_fifo(cs);
+			} else {
+				printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL no skb\n");
+				debugl1(cs, "W6692 XDUN/XCOL no skb");
+				cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST);
+			}
+		}
+		if (exval & W_D_EXI_RDOV) {	/* RDOV */
+			debugl1(cs, "W6692 D-channel RDOV");
+			printk(KERN_WARNING "HiSax: W6692 D-RDOV\n");
+			cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST);
+		}
+		if (exval & W_D_EXI_TIN2) {	/* TIN2 - never */
+			debugl1(cs, "W6692 spurious TIN2 interrupt");
+		}
+		if (exval & W_D_EXI_MOC) {	/* MOC - not supported */
+			debugl1(cs, "W6692 spurious MOC interrupt");
+			v1 = cs->readW6692(cs, W_MOSR);
+			debugl1(cs, "W6692 MOSR %02x", v1);
+		}
+		if (exval & W_D_EXI_ISC) {	/* ISC - Level1 change */
+			v1 = cs->readW6692(cs, W_CIR);
+			if (cs->debug & L1_DEB_ISAC)
+				debugl1(cs, "W6692 ISC CIR=0x%02X", v1);
+			if (v1 & W_CIR_ICC) {
+				cs->dc.w6692.ph_state = v1 & W_CIR_COD_MASK;
+				if (cs->debug & L1_DEB_ISAC)
+					debugl1(cs, "ph_state_change %x", cs->dc.w6692.ph_state);
+				W6692_sched_event(cs, D_L1STATECHANGE);
+			}
+			if (v1 & W_CIR_SCC) {
+				v1 = cs->readW6692(cs, W_SQR);
+				debugl1(cs, "W6692 SCC SQR=0x%02X", v1);
+			}
+		}
+		if (exval & W_D_EXI_WEXP) {
+			debugl1(cs, "W6692 spurious WEXP interrupt!");
+		}
+		if (exval & W_D_EXI_TEXP) {
+			debugl1(cs, "W6692 spurious TEXP interrupt!");
+		}
+	}
+	if (val & W_INT_B1_EXI) {
+		debugl1(cs, "W6692 B channel 1 interrupt");
+		W6692B_interrupt(cs, 0);
+	}
+	if (val & W_INT_B2_EXI) {
+		debugl1(cs, "W6692 B channel 2 interrupt");
+		W6692B_interrupt(cs, 1);
+	}
+	val = cs->readW6692(cs, W_ISTA);
+	if (val && icnt) {
+		icnt--;
+		goto StartW6692;
+	}
+	if (!icnt) {
+		printk(KERN_WARNING "W6692 IRQ LOOP\n");
+		cs->writeW6692(cs, W_IMASK, 0xff);
+	}
+}
+
+static void
+W6692_l1hw(struct PStack *st, int pr, void *arg)
+{
+	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
+	struct sk_buff *skb = arg;
+	int val;
+
+	switch (pr) {
+		case (PH_DATA | REQUEST):
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
+			if (cs->tx_skb) {
+				skb_queue_tail(&cs->sq, skb);
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
+#endif
+			} else {
+				cs->tx_skb = skb;
+				cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA", 0);
+#endif
+				W6692_fill_fifo(cs);
+			}
+			break;
+		case (PH_PULL | INDICATION):
+			if (cs->tx_skb) {
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
+				skb_queue_tail(&cs->sq, skb);
+				break;
+			}
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
+			cs->tx_skb = skb;
+			cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+			if (cs->debug & L1_DEB_LAPD)
+				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
+#endif
+			W6692_fill_fifo(cs);
+			break;
+		case (PH_PULL | REQUEST):
+#ifdef L2FRAME_DEBUG		/* psa */
+			if (cs->debug & L1_DEB_LAPD)
+				debugl1(cs, "-> PH_REQUEST_PULL");
+#endif
+			if (!cs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			break;
+		case (HW_RESET | REQUEST):
+			if ((cs->dc.w6692.ph_state == W_L1IND_DRD))
+				ph_command(cs, W_L1CMD_ECK);
+			else {
+				ph_command(cs, W_L1CMD_RST);
+				cs->dc.w6692.ph_state = W_L1CMD_RST;
+				W6692_new_ph(cs);
+			}
+			break;
+		case (HW_ENABLE | REQUEST):
+			ph_command(cs, W_L1CMD_ECK);
+			break;
+		case (HW_INFO3 | REQUEST):
+			ph_command(cs, W_L1CMD_AR8);
+			break;
+		case (HW_TESTLOOP | REQUEST):
+			val = 0;
+			if (1 & (long) arg)
+				val |= 0x0c;
+			if (2 & (long) arg)
+				val |= 0x3;
+			/* !!! not implemented yet */
+			break;
+		case (HW_DEACTIVATE | RESPONSE):
+			discard_queue(&cs->rq);
+			discard_queue(&cs->sq);
+			if (cs->tx_skb) {
+				dev_kfree_skb(cs->tx_skb);
+				cs->tx_skb = NULL;
+			}
+			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+				del_timer(&cs->dbusytimer);
+			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+				W6692_sched_event(cs, D_CLEARBUSY);
+			break;
+		default:
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "W6692_l1hw unknown %04x", pr);
+			break;
+	}
+}
+
+static void
+setstack_W6692(struct PStack *st, struct IsdnCardState *cs)
+{
+	st->l1.l1hw = W6692_l1hw;
+}
+
+static void
+DC_Close_W6692(struct IsdnCardState *cs)
+{
+}
+
+static void
+dbusy_timer_handler(struct IsdnCardState *cs)
+{
+	struct PStack *stptr;
+	int rbch, star;
+
+	if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
+		rbch = cs->readW6692(cs, W_D_RBCH);
+		star = cs->readW6692(cs, W_D_STAR);
+		if (cs->debug)
+			debugl1(cs, "D-Channel Busy D_RBCH %02x D_STAR %02x",
+				rbch, star);
+		if (star & W_D_STAR_XBZ) {	/* D-Channel Busy */
+			test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
+			stptr = cs->stlist;
+			while (stptr != NULL) {
+				stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
+				stptr = stptr->next;
+			}
+		} else {
+			/* discard frame; reset transceiver */
+			test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags);
+			if (cs->tx_skb) {
+				dev_kfree_skb(cs->tx_skb);
+				cs->tx_cnt = 0;
+				cs->tx_skb = NULL;
+			} else {
+				printk(KERN_WARNING "HiSax: W6692 D-Channel Busy no skb\n");
+				debugl1(cs, "D-Channel Busy no skb");
+			}
+			cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST);	/* Transmitter reset */
+			cs->irq_func(cs->irq, cs, NULL);
+		}
+	}
+}
+
+static void
+W6692Bmode(struct BCState *bcs, int mode, int bc)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	int bchan = bcs->hw.w6692.bchan;
+
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "w6692 %c mode %d ichan %d",
+			'1' + bchan, mode, bc);
+	bcs->mode = mode;
+	bcs->channel = bc;
+
+	switch (mode) {
+		case (L1_MODE_NULL):
+			cs->BC_Write_Reg(cs, bchan, W_B_MODE, 0);
+			break;
+		case (L1_MODE_TRANS):
+			cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_MMS);
+			break;
+		case (L1_MODE_HDLC):
+			cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_ITF);
+			cs->BC_Write_Reg(cs, bchan, W_B_ADM1, 0xff);
+			cs->BC_Write_Reg(cs, bchan, W_B_ADM2, 0xff);
+			break;
+	}
+	if (mode)
+		cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RRST |
+				 W_B_CMDR_RACT | W_B_CMDR_XRST);
+	cs->BC_Write_Reg(cs, bchan, W_B_EXIM, 0x00);
+}
+
+static void
+W6692_l2l1(struct PStack *st, int pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+	long flags;
+
+	switch (pr) {
+		case (PH_DATA | REQUEST):
+			save_flags(flags);
+			cli();
+			if (st->l1.bcs->tx_skb) {
+				skb_queue_tail(&st->l1.bcs->squeue, skb);
+				restore_flags(flags);
+			} else {
+				st->l1.bcs->tx_skb = skb;
+				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+				st->l1.bcs->hw.w6692.count = 0;
+				restore_flags(flags);
+				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+			}
+			break;
+		case (PH_PULL | INDICATION):
+			if (st->l1.bcs->tx_skb) {
+				printk(KERN_WARNING "W6692_l2l1: this shouldn't happen\n");
+				break;
+			}
+			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+			st->l1.bcs->tx_skb = skb;
+			st->l1.bcs->hw.w6692.count = 0;
+			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+			break;
+		case (PH_PULL | REQUEST):
+			if (!st->l1.bcs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			break;
+		case (PH_ACTIVATE | REQUEST):
+			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			W6692Bmode(st->l1.bcs, st->l1.mode, st->l1.bc);
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | REQUEST):
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | CONFIRM):
+			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+			W6692Bmode(st->l1.bcs, 0, st->l1.bc);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			break;
+	}
+}
+
+static void
+close_w6692state(struct BCState *bcs)
+{
+	W6692Bmode(bcs, 0, bcs->channel);
+	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
+		if (bcs->hw.w6692.rcvbuf) {
+			kfree(bcs->hw.w6692.rcvbuf);
+			bcs->hw.w6692.rcvbuf = NULL;
+		}
+		if (bcs->blog) {
+			kfree(bcs->blog);
+			bcs->blog = NULL;
+		}
+		discard_queue(&bcs->rqueue);
+		discard_queue(&bcs->squeue);
+		if (bcs->tx_skb) {
+			dev_kfree_skb(bcs->tx_skb);
+			bcs->tx_skb = NULL;
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+		}
+	}
+}
+
+static int
+open_w6692state(struct IsdnCardState *cs, struct BCState *bcs)
+{
+	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
+		if (!(bcs->hw.w6692.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+			       "HiSax: No memory for w6692.rcvbuf\n");
+			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
+			return (1);
+		}
+		if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+			       "HiSax: No memory for bcs->blog\n");
+			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
+			kfree(bcs->hw.w6692.rcvbuf);
+			bcs->hw.w6692.rcvbuf = NULL;
+			return (2);
+		}
+		skb_queue_head_init(&bcs->rqueue);
+		skb_queue_head_init(&bcs->squeue);
+	}
+	bcs->tx_skb = NULL;
+	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	bcs->event = 0;
+	bcs->hw.w6692.rcvidx = 0;
+	bcs->tx_cnt = 0;
+	return (0);
+}
+
+static int
+setstack_w6692(struct PStack *st, struct BCState *bcs)
+{
+	bcs->channel = st->l1.bc;
+	if (open_w6692state(st->l1.hardware, bcs))
+		return (-1);
+	st->l1.bcs = bcs;
+	st->l2.l2l1 = W6692_l2l1;
+	setstack_manager(st);
+	bcs->st = st;
+	setstack_l1_B(st);
+	return (0);
+}
+
+HISAX_INITFUNC(void initW6692(struct IsdnCardState *cs, int part))
+{
+	if (part & 1) {
+		cs->tqueue.routine = (void *) (void *) W6692_bh;
+		cs->setstack_d = setstack_W6692;
+		cs->DC_Close = DC_Close_W6692;
+		cs->dbusytimer.function = (void *) dbusy_timer_handler;
+		cs->dbusytimer.data = (long) cs;
+		init_timer(&cs->dbusytimer);
+
+		cs->writeW6692(cs, W_D_CTL, W_D_CTL_SRST);
+		cs->writeW6692(cs, W_D_CTL, 0x00);
+		cs->writeW6692(cs, W_IMASK, 0xff);
+		cs->writeW6692(cs, W_D_SAM, 0xff);
+		cs->writeW6692(cs, W_D_TAM, 0xff);
+		cs->writeW6692(cs, W_D_EXIM, 0x00);
+		cs->writeW6692(cs, W_D_MODE, W_D_MODE_RACT);
+		cs->writeW6692(cs, W_IMASK, 0x18);
+		ph_command(cs, W_L1CMD_RST);
+		cs->dc.w6692.ph_state = W_L1CMD_RST;
+		W6692_new_ph(cs);
+		ph_command(cs, W_L1CMD_ECK);
+
+		cs->bcs[0].BC_SetStack = setstack_w6692;
+		cs->bcs[1].BC_SetStack = setstack_w6692;
+		cs->bcs[0].BC_Close = close_w6692state;
+		cs->bcs[1].BC_Close = close_w6692state;
+		cs->bcs[0].hw.w6692.bchan = 0;
+		cs->bcs[1].hw.w6692.bchan = 1;
+		W6692Bmode(cs->bcs, 0, 0);
+		W6692Bmode(cs->bcs + 1, 0, 0);
+	}
+	if (part & 2) {
+		/* Reenable all IRQ */
+		cs->writeW6692(cs, W_IMASK, 0x18);
+		cs->writeW6692(cs, W_D_EXIM, 0x00);
+		cs->BC_Write_Reg(cs, 0, W_B_EXIM, 0x00);
+		cs->BC_Write_Reg(cs, 1, W_B_EXIM, 0x00);
+		/* Reset D-chan receiver and transmitter */
+		cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST);
+	}
+}
+
+/* Interface functions */
+
+static u_char
+ReadW6692(struct IsdnCardState *cs, u_char offset)
+{
+	return (inb(cs->hw.w6692.iobase + offset));
+}
+
+static void
+WriteW6692(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	outb(value, cs->hw.w6692.iobase + offset);
+}
+
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	insb(cs->hw.w6692.iobase + W_D_RFIFO, data, size);
+}
+
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	outsb(cs->hw.w6692.iobase + W_D_XFIFO, data, size);
+}
+
+static u_char
+ReadW6692B(struct IsdnCardState *cs, int bchan, u_char offset)
+{
+	return (inb(cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset));
+}
+
+static void
+WriteW6692B(struct IsdnCardState *cs, int bchan, u_char offset, u_char value)
+{
+	outb(value, cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset);
+}
+
+static int
+w6692_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	switch (mt) {
+		case CARD_RESET:
+			return (0);
+		case CARD_RELEASE:
+			release_region(cs->hw.w6692.iobase, 256);
+			return (0);
+		case CARD_INIT:
+			initW6692(cs, 3);
+			return (0);
+		case CARD_TEST:
+			return (0);
+	}
+	return (0);
+}
+
+static int id_idx = 0;
+
+static struct pci_dev *dev_w6692 __initdata = NULL;
+
+__initfunc(int setup_w6692(struct IsdnCard *card))
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+	u_char found = 0;
+	u_char pci_irq = 0;
+	u_int pci_ioaddr = 0;
+
+	strcpy(tmp, w6692_revision);
+	printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_W6692)
+		return (0);
+#if CONFIG_PCI
+	if (!pci_present()) {
+		printk(KERN_ERR "W6692: no PCI bus present\n");
+		return (0);
+	}
+	while (id_list[id_idx].vendor_id) {
+		dev_w6692 = pci_find_device(id_list[id_idx].vendor_id,
+					    id_list[id_idx].device_id,
+					    dev_w6692);
+		if (dev_w6692)
+			break;
+		id_idx++;
+	}
+	if (dev_w6692) {
+		found = 1;
+		pci_irq = dev_w6692->irq;
+		/* I think address 0 is allways the configuration area */
+		/* and address 1 is the real IO space KKe 03.09.99 */
+		pci_ioaddr = dev_w6692->resource[ 1].start;
+	}
+	if (!found) {
+		printk(KERN_WARNING "W6692: No PCI card found\n");
+		return (0);
+	}
+	cs->irq = pci_irq;
+	if (!cs->irq) {
+		printk(KERN_WARNING "W6692: No IRQ for PCI card found\n");
+		return (0);
+	}
+	pci_ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
+	if (!pci_ioaddr) {
+		printk(KERN_WARNING "W6692: NO I/O Base Address found\n");
+		return (0);
+	}
+	cs->hw.w6692.iobase = pci_ioaddr;
+	printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n",
+	       id_list[id_idx].vendor_name, id_list[id_idx].card_name,
+	       pci_ioaddr, dev_w6692->irq);
+	if (check_region((cs->hw.w6692.iobase), 256)) {
+		printk(KERN_WARNING
+		       "HiSax: %s I/O ports %x-%x already in use\n",
+		       id_list[id_idx].card_name,
+		       cs->hw.w6692.iobase,
+		       cs->hw.w6692.iobase + 255);
+		return (0);
+	} else {
+		request_region(cs->hw.w6692.iobase, 256,
+			       id_list[id_idx].card_name);
+	}
+#else
+	printk(KERN_WARNING "HiSax: W6692 and NO_PCI_BIOS\n");
+	printk(KERN_WARNING "HiSax: W6692 unable to config\n");
+	return (0);
+#endif				/* CONFIG_PCI */
+
+	printk(KERN_INFO
+	       "HiSax: %s config irq:%d I/O:%x\n",
+	       id_list[id_idx].card_name, cs->irq,
+	       cs->hw.w6692.iobase);
+
+	cs->readW6692 = &ReadW6692;
+	cs->writeW6692 = &WriteW6692;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadW6692B;
+	cs->BC_Write_Reg = &WriteW6692B;
+	cs->BC_Send_Data = &W6692B_fill_fifo;
+	cs->cardmsg = &w6692_card_msg;
+	cs->irq_func = &W6692_interrupt;
+	W6692Version(cs, "W6692:");
+	printk(KERN_INFO "W6692 ISTA=0x%X\n", ReadW6692(cs, W_ISTA));
+	printk(KERN_INFO "W6692 IMASK=0x%X\n", ReadW6692(cs, W_IMASK));
+	printk(KERN_INFO "W6692 D_EXIR=0x%X\n", ReadW6692(cs, W_D_EXIR));
+	printk(KERN_INFO "W6692 D_EXIM=0x%X\n", ReadW6692(cs, W_D_EXIM));
+	printk(KERN_INFO "W6692 D_RSTA=0x%X\n", ReadW6692(cs, W_D_RSTA));
+	return (1);
+}
diff --git a/drivers/isdn/hisax/w6692.h b/drivers/isdn/hisax/w6692.h
new file mode 100644
index 0000000000000000000000000000000000000000..4990b008263a34a13f8e696baf84f104a5eca1d0
--- /dev/null
+++ b/drivers/isdn/hisax/w6692.h
@@ -0,0 +1,190 @@
+/* $Id: w6692.h,v 1.1 1999/09/04 06:28:58 keil Exp $
+
+ * w6692.h   Winbond W6692 specific defines
+ *
+ * Author       Petr Novak <petr.novak@i.cz>
+ *
+ *
+ * $Log: w6692.h,v $
+ * Revision 1.1  1999/09/04 06:28:58  keil
+ * first revision
+ *
+ *
+ * Revision 1.0  1999/08/28 21:58:00 pnovak
+ * first version
+ *
+ *
+ */
+
+/* map W6692 functions to ISAC functions */
+#define readW6692	readisac
+#define writeW6692	writeisac
+#define	readW6692fifo	readisacfifo
+#define	writeW6692fifo	writeisacfifo
+
+/* B-channel FIFO read/write routines */
+
+#define READW6692BFIFO(cs,bchan,ptr,count) \
+	insb(cs->hw.w6692.iobase+W_B_RFIFO+(bchan?0x40:0),ptr,count)
+
+#define WRITEW6692BFIFO(cs,bchan,ptr,count) \
+	outsb(cs->hw.w6692.iobase+W_B_XFIFO+(bchan?0x40:0),ptr,count)
+
+/* Specifications of W6692 registers */
+
+#define W_D_RFIFO	0x00	/* R */
+#define W_D_XFIFO	0x04	/* W */
+#define W_D_CMDR	0x08	/* W */
+#define W_D_MODE	0x0c	/* R/W */
+#define W_D_TIMR	0x10	/* R/W */
+#define W_ISTA		0x14	/* R_clr */
+#define W_IMASK		0x18	/* R/W */
+#define W_D_EXIR	0x1c	/* R_clr */
+#define W_D_EXIM	0x20	/* R/W */
+#define W_D_STAR	0x24	/* R */
+#define W_D_RSTA	0x28	/* R */
+#define W_D_SAM		0x2c	/* R/W */
+#define W_D_SAP1	0x30	/* R/W */
+#define W_D_SAP2	0x34	/* R/W */
+#define W_D_TAM		0x38	/* R/W */
+#define W_D_TEI1	0x3c	/* R/W */
+#define W_D_TEI2	0x40	/* R/W */
+#define W_D_RBCH	0x44	/* R */
+#define W_D_RBCL	0x48	/* R */
+#define W_TIMR2		0x4c	/* W */
+#define W_L1_RC		0x50	/* R/W */
+#define W_D_CTL		0x54	/* R/W */
+#define W_CIR		0x58	/* R */
+#define W_CIX		0x5c	/* W */
+#define W_SQR		0x60	/* R */
+#define W_SQX		0x64	/* W */
+#define W_PCTL		0x68	/* R/W */
+#define W_MOR		0x6c	/* R */
+#define W_MOX		0x70	/* R/W */
+#define W_MOSR		0x74	/* R_clr */
+#define W_MOCR		0x78	/* R/W */
+#define W_GCR		0x7c	/* R/W */
+
+#define	W_B_RFIFO	0x80	/* R */
+#define	W_B_XFIFO	0x84	/* W */
+#define	W_B_CMDR	0x88	/* W */
+#define	W_B_MODE	0x8c	/* R/W */
+#define	W_B_EXIR	0x90	/* R_clr */
+#define	W_B_EXIM	0x94	/* R/W */
+#define	W_B_STAR	0x98	/* R */
+#define	W_B_ADM1	0x9c	/* R/W */
+#define	W_B_ADM2	0xa0	/* R/W */
+#define	W_B_ADR1	0xa4	/* R/W */
+#define	W_B_ADR2	0xa8	/* R/W */
+#define	W_B_RBCL	0xac	/* R */
+#define	W_B_RBCH	0xb0	/* R */
+
+#define W_XADDR		0xf4	/* R/W */
+#define W_XDATA		0xf8	/* R/W */
+#define W_EPCTL		0xfc	/* W */
+
+/* W6692 register bits */
+
+#define	W_D_CMDR_XRST	0x01
+#define	W_D_CMDR_XME	0x02
+#define	W_D_CMDR_XMS	0x08
+#define	W_D_CMDR_STT	0x10
+#define	W_D_CMDR_RRST	0x40
+#define	W_D_CMDR_RACK	0x80
+
+#define	W_D_MODE_RLP	0x01
+#define	W_D_MODE_DLP	0x02
+#define	W_D_MODE_MFD	0x04
+#define	W_D_MODE_TEE	0x08
+#define	W_D_MODE_TMS	0x10
+#define	W_D_MODE_RACT	0x40
+#define	W_D_MODE_MMS	0x80
+
+#define W_INT_B2_EXI	0x01
+#define W_INT_B1_EXI	0x02
+#define W_INT_D_EXI	0x04
+#define W_INT_XINT0	0x08
+#define W_INT_XINT1	0x10
+#define W_INT_D_XFR	0x20
+#define W_INT_D_RME	0x40
+#define W_INT_D_RMR	0x80
+
+#define W_D_EXI_WEXP	0x01
+#define W_D_EXI_TEXP	0x02
+#define W_D_EXI_ISC	0x04
+#define W_D_EXI_MOC	0x08
+#define W_D_EXI_TIN2	0x10
+#define W_D_EXI_XCOL	0x20
+#define W_D_EXI_XDUN	0x40
+#define W_D_EXI_RDOV	0x80
+
+#define	W_D_STAR_DRDY	0x10
+#define	W_D_STAR_XBZ	0x20
+#define	W_D_STAR_XDOW	0x80
+
+#define W_D_RSTA_RMB	0x10
+#define W_D_RSTA_CRCE	0x20
+#define W_D_RSTA_RDOV	0x40
+
+#define W_D_CTL_SRST	0x20
+
+#define W_CIR_SCC	0x80
+#define W_CIR_ICC	0x40
+#define W_CIR_COD_MASK	0x0f
+
+#define	W_B_CMDR_XRST	0x01
+#define	W_B_CMDR_XME	0x02
+#define	W_B_CMDR_XMS	0x04
+#define	W_B_CMDR_RACT	0x20
+#define	W_B_CMDR_RRST	0x40
+#define	W_B_CMDR_RACK	0x80
+
+#define	W_B_MODE_FTS0	0x01
+#define	W_B_MODE_FTS1	0x02
+#define	W_B_MODE_SW56	0x04
+#define	W_B_MODE_BSW0	0x08
+#define	W_B_MODE_BSW1	0x10
+#define	W_B_MODE_EPCM	0x20
+#define	W_B_MODE_ITF	0x40
+#define	W_B_MODE_MMS	0x80
+
+#define	W_B_EXI_XDUN	0x01
+#define	W_B_EXI_XFR	0x02
+#define	W_B_EXI_RDOV	0x10
+#define	W_B_EXI_RME	0x20
+#define	W_B_EXI_RMR	0x40
+
+#define	W_B_STAR_XBZ	0x01
+#define	W_B_STAR_XDOW	0x04
+#define	W_B_STAR_RMB	0x10
+#define	W_B_STAR_CRCE	0x20
+#define	W_B_STAR_RDOV	0x40
+
+#define	W_B_RBCH_LOV	0x20
+
+/* W6692 Layer1 commands */
+
+#define	W_L1CMD_ECK	0x00
+#define W_L1CMD_RST	0x01
+#define W_L1CMD_SCP	0x04
+#define W_L1CMD_SSP	0x02
+#define W_L1CMD_AR8	0x08
+#define W_L1CMD_AR10	0x09
+#define W_L1CMD_EAL	0x0a
+#define W_L1CMD_DRC	0x0f
+
+/* W6692 Layer1 indications */
+
+#define W_L1IND_CE	0x07
+#define W_L1IND_DRD	0x00
+#define W_L1IND_LD	0x04
+#define W_L1IND_ARD	0x08
+#define W_L1IND_TI	0x0a
+#define W_L1IND_ATI	0x0b
+#define W_L1IND_AI8	0x0c
+#define W_L1IND_AI10	0x0d
+#define W_L1IND_CD	0x0f
+
+/* FIFO thresholds */
+#define W_D_FIFO_THRESH	64
+#define W_B_FIFO_THRESH	64
diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c
index 26ac3502df0500de2fc4ad67e0652911a75b0d84..92ee95a2e47931b6cd248b9c8da980b28e121b0e 100644
--- a/drivers/isdn/icn/icn.c
+++ b/drivers/isdn/icn/icn.c
@@ -1,8 +1,8 @@
-/* $Id: icn.c,v 1.59 1999/08/28 22:10:55 keil Exp $
+/* $Id: icn.c,v 1.62 1999/09/06 07:29:35 fritz Exp $
 
  * ISDN low-level module for the ICN active ISDN-Card.
  *
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,6 +19,15 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: icn.c,v $
+ * Revision 1.62  1999/09/06 07:29:35  fritz
+ * Changed my mail-address.
+ *
+ * Revision 1.61  1999/09/03 14:06:58  fritz
+ * Fixed a memory leak.
+ *
+ * Revision 1.60  1999/08/31 11:20:32  paul
+ * various spelling corrections (new checksums may be needed, Karsten!)
+ *
  * Revision 1.59  1999/08/28 22:10:55  keil
  * __setup function should be static
  *
@@ -238,7 +247,7 @@
 #undef MAP_DEBUG
 
 static char
-*revision = "$Revision: 1.59 $";
+*revision = "$Revision: 1.62 $";
 
 static int icn_addcard(int, char *, char *);
 
@@ -467,7 +476,7 @@ icn_pollbchan_receive(int channel, icn_card * card)
 			if (!eflag) {
 				if ((cnt = card->rcvidx[channel])) {
 					if (!(skb = dev_alloc_skb(cnt))) {
-						printk(KERN_WARNING "ïcn: receive out of memory\n");
+						printk(KERN_WARNING "icn: receive out of memory\n");
 						break;
 					}
 					memcpy(skb_put(skb, cnt), card->rcvbuf[channel], cnt);
@@ -545,12 +554,10 @@ icn_pollbchan_send(int channel, icn_card * card)
 			if (!skb->len) {
 				save_flags(flags);
 				cli();
-				if (card->xskb[channel]) {
+				if (card->xskb[channel])
 					card->xskb[channel] = NULL;
-					restore_flags(flags);
-					dev_kfree_skb(skb);
-				} else
-					restore_flags(flags);
+				restore_flags(flags);
+				dev_kfree_skb(skb);
 				if (card->xlen[channel]) {
 					cmd.command = ISDN_STAT_BSENT;
 					cmd.driver = card->myid;
@@ -1852,7 +1859,6 @@ icn_addcard(int port, char *id1, char *id2)
 #ifdef MODULE
 #define icn_init init_module
 #else
-#ifdef COMPAT_HAS_NEW_SETUP
 #include <linux/init.h>
 static int __init
 icn_setup(char *line)
@@ -1863,14 +1869,6 @@ icn_setup(char *line)
 	static char sid2[20];
 
 	str = get_options(line, 2, ints);
-#else
-void
-icn_setup(char *str, int *ints)
-{
-	char *p;
-	static char sid[20];
-	static char sid2[20];
-#endif
 	if (ints[0])
 		portbase = ints[1];
 	if (ints[0] > 1)
@@ -1884,13 +1882,9 @@ icn_setup(char *str, int *ints)
 			icn_id2 = sid2;
 		}
 	}
-#ifdef COMPAT_HAS_NEW_SETUP
 	return(1);
 }
 __setup("icn=", icn_setup);
-#else
-}
-#endif
 #endif /* MODULES */
 
 int
diff --git a/drivers/isdn/icn/icn.h b/drivers/isdn/icn/icn.h
index 3bd2819cedb85b3d97c9f6acf81e795027a33aa5..6d40a695c434ce472b176321ffd55c67219dacfb 100644
--- a/drivers/isdn/icn/icn.h
+++ b/drivers/isdn/icn/icn.h
@@ -1,8 +1,8 @@
-/* $Id: icn.h,v 1.28 1997/10/10 15:56:18 fritz Exp $
+/* $Id: icn.h,v 1.29 1999/09/06 07:29:35 fritz Exp $
 
  * ISDN lowlevel-module for the ICN active ISDN-Card.
  *
- * Copyright 1994 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994 by Fritz Elfert (fritz@isdn4linux.de)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,6 +19,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: icn.h,v $
+ * Revision 1.29  1999/09/06 07:29:35  fritz
+ * Changed my mail-address.
+ *
  * Revision 1.28  1997/10/10 15:56:18  fritz
  * New HL<->LL interface:
  *   New BSENT callback with nr. of bytes included.
diff --git a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c
index 10414ee945cdab70c05b7a147282624d29f1a47b..ba890846d1b081f9210fc9ea7b92c4111121c2ad 100644
--- a/drivers/isdn/isdn_common.c
+++ b/drivers/isdn/isdn_common.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.c,v 1.86 1999/07/31 12:59:42 armin Exp $
+/* $Id: isdn_common.c,v 1.93 1999/11/04 13:11:36 keil Exp $
 
  * Linux ISDN subsystem, common used functions (linklevel).
  *
@@ -21,6 +21,40 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_common.c,v $
+ * Revision 1.93  1999/11/04 13:11:36  keil
+ * Reinit of v110 structs
+ *
+ * Revision 1.92  1999/10/31 15:59:50  he
+ * more skb headroom checks
+ *
+ * Revision 1.91  1999/10/28 22:48:45  armin
+ * Bugfix: isdn_free_channel() now frees the channel,
+ * even when the usage of the ttyI has changed.
+ *
+ * Revision 1.90  1999/10/27 21:21:17  detabc
+ * Added support for building logically-bind-group's per interface.
+ * usefull for outgoing call's with more then one isdn-card.
+ *
+ * Switchable support to dont reset the hangup-timeout for
+ * receive frames. Most part's of the timru-rules for receiving frames
+ * are now obsolete. If the input- or forwarding-firewall deny
+ * the frame, the line will be not hold open.
+ *
+ * Revision 1.89  1999/10/16 14:46:47  keil
+ * replace kmalloc with vmalloc for the big dev struct
+ *
+ * Revision 1.88  1999/10/02 00:39:26  he
+ * Fixed a 2.3.x wait queue initialization (was causing panics)
+ *
+ * Revision 1.87  1999/09/12 16:19:39  detabc
+ * added abc features
+ * low cost routing for net-interfaces (only the HL side).
+ * need more implementation in the isdnlog-utility
+ * udp info support (first part).
+ * different EAZ on outgoing call's.
+ * more checks on D-Channel callbacks (double use of channels).
+ * tested and running with kernel 2.3.17
+ *
  * Revision 1.86  1999/07/31 12:59:42  armin
  * Added tty fax capabilities.
  *
@@ -362,6 +396,7 @@
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/poll.h>
+#include <linux/vmalloc.h>
 #include <linux/isdn.h>
 #include "isdn_common.h"
 #include "isdn_tty.h"
@@ -381,7 +416,7 @@
 
 isdn_dev *dev = (isdn_dev *) 0;
 
-static char *isdn_revision = "$Revision: 1.86 $";
+static char *isdn_revision = "$Revision: 1.93 $";
 
 extern char *isdn_net_revision;
 extern char *isdn_tty_revision;
@@ -1039,9 +1074,6 @@ isdn_status_callback(isdn_ctrl * c)
 				isdn_free_queue(&dev->drv[di]->rpqueue[i]);
 			kfree(dev->drv[di]->rpqueue);
 			kfree(dev->drv[di]->rcv_waitq);
-#ifndef COMPAT_HAS_NEW_WAITQ
-			kfree(dev->drv[di]->snd_waitq);
-#endif
 			kfree(dev->drv[di]);
 			dev->drv[di] = NULL;
 			dev->drvid[di][0] = '\0';
@@ -1103,11 +1135,7 @@ isdn_getnum(char **p)
  * of the mapping (di,ch)<->minor, happen during the sleep? --he 
  */
 int
-#ifdef COMPAT_HAS_NEW_WAITQ
 isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_queue_head_t *sleep)
-#else
-isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, struct wait_queue **sleep)
-#endif
 {
 	int left;
 	int count;
@@ -1535,6 +1563,9 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
  * are serialized by means of a semaphore.
  */
 		switch (cmd) {
+			case IIOCNETLCR:
+				printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");
+				return -ENODEV;
 #ifdef CONFIG_NETDEVICES
 			case IIOCNETAIF:
 				/* Add a network-interface */
@@ -2092,13 +2123,19 @@ isdn_free_channel(int di, int ch, int usage)
 	save_flags(flags);
 	cli();
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-		if (((dev->usage[i] & ISDN_USAGE_MASK) == usage) &&
+		if (((!usage) || ((dev->usage[i] & ISDN_USAGE_MASK) == usage)) &&
 		    (dev->drvmap[i] == di) &&
 		    (dev->chanmap[i] == ch)) {
 			dev->usage[i] &= (ISDN_USAGE_NONE | ISDN_USAGE_EXCLUSIVE);
 			strcpy(dev->num[i], "???");
 			dev->ibytes[i] = 0;
 			dev->obytes[i] = 0;
+// 20.10.99 JIM, try to reinitialize v110 !
+			dev->v110emu[i] = 0;
+			atomic_set(&(dev->v110use[i]), 0);
+			isdn_v110_close(dev->v110[i]);
+			dev->v110[i] = NULL;
+// 20.10.99 JIM, try to reinitialize v110 !
 			isdn_info_update();
 			isdn_free_queue(&dev->drv[di]->rpqueue[ch]);
 		}
@@ -2180,8 +2217,33 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
 		/* V.110 must always be acknowledged */
 		ack = 1;
 		ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, nskb);
-	} else
-		ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb);
+	} else {
+		int hl = dev->drv[drvidx]->interface->hl_hdrlen;
+
+		if( skb_headroom(skb) < hl ){
+			/* 
+			 * This should only occur when new HL driver with
+			 * increased hl_hdrlen was loaded after netdevice
+			 * was created and connected to the new driver.
+			 *
+			 * The V.110 branch (re-allocates on its own) does
+			 * not need this
+			 */
+			struct sk_buff * skb_tmp;
+
+			skb_tmp = skb_realloc_headroom(skb, hl);
+			printk(KERN_DEBUG "isdn_writebuf_skb_stub: reallocating headroom%s\n", skb_tmp ? "" : " failed");
+			if (!skb_tmp) return -ENOMEM; /* 0 better? */
+			ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb_tmp);
+			if( ret > 0 ){
+				dev_kfree_skb(skb);
+			} else {
+				dev_kfree_skb(skb_tmp);
+			}
+		} else {
+			ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb);
+		}
+	}
 	if (ret > 0) {
 		dev->obytes[idx] += ret;
 		if (dev->v110[idx]) {
@@ -2202,43 +2264,11 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
 
 int
 register_isdn_module(isdn_module *m) {
-#if 0
-	isdn_module_list **pp = &dev->modules;
-	isdn_module *new = kmalloc(sizeof(isdn_module_list), GFP_KERNEL);
-
-	if (!new) {
-		printk(KERN_WARNING "isdn: Out of memory in register_isdn_module\n");
-		return -1;
-	}
-	while (*pp && (*pp)->orig != m)
-		pp = &(*pp)->next;
-	if (*pp != NULL) {
-		printk(KERN_WARNING "isdn: Module %s already registered\n", m->name);
-		return -1;
-	}
-	while (*pp && ((*pp)->module.priority < m->priority))
-		pp = &(*pp)->next;
-	new->next = *pp;
-	new->orig = m;
-	new->module = *m;
- 
-	*pp = new;
-#endif
 	return 0;
 }
 
 int
 unregister_isdn_module(isdn_module *m) {
-#if 0
-	isdn_module_list **pp = &dev->modules;
-
-	while (*pp && *pp != m)
-		pp = &(*pp)->next;
-	if (*pp == NULL) {
-		printk(KERN_WARNING "isdn: Module %s not found\n", m->name);
-		return -1;
-	}
-#endif
 	return 0;
 }
 
@@ -2248,9 +2278,7 @@ isdn_add_channels(driver *d, int drvidx, int n, int adding)
 	int j, k, m;
 	ulong flags;
 
-#ifdef COMPAT_HAS_NEW_WAITQ
 	init_waitqueue_head(&d->st_waitq);
-#endif
 	if (d->flags & DRV_FLAG_RUNNING)
 		return -1;
        	if (n < 1) return 0;
@@ -2300,14 +2328,9 @@ isdn_add_channels(driver *d, int drvidx, int n, int adding)
 
 	if ((adding) && (d->rcv_waitq))
 		kfree(d->rcv_waitq);
-#ifdef COMPAT_HAS_NEW_WAITQ
 	d->rcv_waitq = (wait_queue_head_t *)
 		kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_KERNEL);
 	if (!d->rcv_waitq) {
-#else
-	if (!(d->rcv_waitq = (struct wait_queue **)
-	      kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL))) {
-#endif
 		printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n");
 		if (!adding) {
 			kfree(d->rpqueue);
@@ -2316,30 +2339,11 @@ isdn_add_channels(driver *d, int drvidx, int n, int adding)
 		}
 		return -1;
 	}
-#ifdef COMPAT_HAS_NEW_WAITQ
 	d->snd_waitq = d->rcv_waitq + m;
 	for (j = 0; j < m; j++) {
 		init_waitqueue_head(&d->rcv_waitq[j]);
 		init_waitqueue_head(&d->snd_waitq[j]);
 	}
-#else
-	memset((char *) d->rcv_waitq, 0, sizeof(struct wait_queue *) * m);
-
-	if ((adding) && (d->snd_waitq))
-		kfree(d->snd_waitq);
-	if (!(d->snd_waitq = (struct wait_queue **)
-	      kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL))) {
-		printk(KERN_WARNING "register_isdn: Could not alloc snd_waitq\n");
-		if (!adding) {
-			kfree(d->rcv_waitq);
-			kfree(d->rpqueue);
-			kfree(d->rcvcount);
-			kfree(d->rcverr);
-		}
-		return -1;
-	}
-	memset((char *) d->snd_waitq, 0, sizeof(struct wait_queue *) * m);
-#endif
 
 	dev->channels += n;
 	save_flags(flags);
@@ -2513,33 +2517,26 @@ isdn_init(void)
 	int i;
 	char tmprev[50];
 
-	sti();
-	if (!(dev = (isdn_dev *) kmalloc(sizeof(isdn_dev), GFP_KERNEL))) {
+	if (!(dev = (isdn_dev *) vmalloc(sizeof(isdn_dev)))) {
 		printk(KERN_WARNING "isdn: Could not allocate device-struct.\n");
 		return -EIO;
 	}
 	memset((char *) dev, 0, sizeof(isdn_dev));
 	init_timer(&dev->timer);
 	dev->timer.function = isdn_timer_funct;
-#ifdef COMPAT_HAS_NEW_WAITQ
 	init_MUTEX(&dev->sem);
 	init_waitqueue_head(&dev->info_waitq);
-#else
-	dev->sem = MUTEX;
-#endif
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
 		dev->drvmap[i] = -1;
 		dev->chanmap[i] = -1;
 		dev->m_idx[i] = -1;
 		strcpy(dev->num[i], "???");
-#ifdef COMPAT_HAS_NEW_WAITQ
 		init_waitqueue_head(&dev->mdm.info[i].open_wait);
 		init_waitqueue_head(&dev->mdm.info[i].close_wait);
-#endif
 	}
 	if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) {
 		printk(KERN_WARNING "isdn: Could not register control devices\n");
-		kfree(dev);
+		vfree(dev);
 		return -EIO;
 	}
 	if ((i = isdn_tty_modem_init()) < 0) {
@@ -2548,7 +2545,7 @@ isdn_init(void)
 			tty_unregister_driver(&dev->mdm.cua_modem);
 		if (i <= -2)
 			tty_unregister_driver(&dev->mdm.tty_modem);
-		kfree(dev);
+		vfree(dev);
 		unregister_chrdev(ISDN_MAJOR, "isdn");
 		return -EIO;
 	}
@@ -2560,7 +2557,7 @@ isdn_init(void)
 		for (i = 0; i < ISDN_MAX_CHANNELS; i++)
 			kfree(dev->mdm.info[i].xmit_buf - 4);
 		unregister_chrdev(ISDN_MAJOR, "isdn");
-		kfree(dev);
+		vfree(dev);
 		return -EIO;
 	}
 #endif                          /* CONFIG_ISDN_PPP */
@@ -2629,7 +2626,7 @@ cleanup_module(void)
 		printk(KERN_WARNING "isdn: controldevice busy, remove cancelled\n");
 	} else {
 		del_timer(&dev->timer);
-		kfree(dev);
+		vfree(dev);
 		printk(KERN_NOTICE "ISDN-subsystem unloaded\n");
 	}
 	restore_flags(flags);
diff --git a/drivers/isdn/isdn_common.h b/drivers/isdn/isdn_common.h
index e6fb122f6669accf4d3a952371cf3043338666ec..3c60d7c8076ac4866dc26574de7110faf9a30329 100644
--- a/drivers/isdn/isdn_common.h
+++ b/drivers/isdn/isdn_common.h
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.h,v 1.16 1999/07/01 08:29:54 keil Exp $
+/* $Id: isdn_common.h,v 1.17 1999/10/27 21:21:17 detabc Exp $
 
  * header for Linux ISDN subsystem, common used functions and debugging-switches (linklevel).
  *
@@ -21,6 +21,15 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_common.h,v $
+ * Revision 1.17  1999/10/27 21:21:17  detabc
+ * Added support for building logically-bind-group's per interface.
+ * usefull for outgoing call's with more then one isdn-card.
+ *
+ * Switchable support to dont reset the hangup-timeout for
+ * receive frames. Most part's of the timru-rules for receiving frames
+ * are now obsolete. If the input- or forwarding-firewall deny
+ * the frame, the line will be not hold open.
+ *
  * Revision 1.16  1999/07/01 08:29:54  keil
  * compatibility to 2.3 kernel
  *
@@ -118,11 +127,7 @@ extern char *isdn_map_eaz2msn(char *msn, int di);
 extern void isdn_timer_ctrl(int tf, int onoff);
 extern void isdn_unexclusive_channel(int di, int ch);
 extern int isdn_getnum(char **);
-#ifdef COMPAT_HAS_NEW_WAITQ
 extern int isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *);
-#else
-extern int isdn_readbchan(int, int, u_char *, u_char *, int, struct wait_queue**);
-#endif
 extern int isdn_get_free_channel(int, int, int, int, int);
 extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
 extern int register_isdn(isdn_if * i);
diff --git a/drivers/isdn/isdn_net.c b/drivers/isdn/isdn_net.c
index 9d54f01274e82df77965a8cdd0a5135b892f7ee5..e1c7cb75d4834959326f1c8b2f8a2d1caac24a43 100644
--- a/drivers/isdn/isdn_net.c
+++ b/drivers/isdn/isdn_net.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_net.c,v 1.89 1999/08/22 20:26:03 calle Exp $
+/* $Id: isdn_net.c,v 1.95 1999/10/27 21:21:17 detabc Exp $
 
  * Linux ISDN subsystem, network interfaces and related functions (linklevel).
  *
@@ -21,6 +21,38 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_net.c,v $
+ * Revision 1.95  1999/10/27 21:21:17  detabc
+ * Added support for building logically-bind-group's per interface.
+ * usefull for outgoing call's with more then one isdn-card.
+ *
+ * Switchable support to dont reset the hangup-timeout for
+ * receive frames. Most part's of the timru-rules for receiving frames
+ * are now obsolete. If the input- or forwarding-firewall deny
+ * the frame, the line will be not hold open.
+ *
+ * Revision 1.94  1999/10/02 11:07:02  he
+ * Changed tbusy logic in indn_net.c
+ *
+ * Revision 1.93  1999/09/23 22:22:41  detabc
+ * added tcp-keepalive-detect with local response (ipv4 only)
+ * added host-only-interface support
+ * (source ipaddr == interface ipaddr) (ipv4 only)
+ * ok with kernel 2.3.18 and 2.2.12
+ *
+ * Revision 1.92  1999/09/13 23:25:17  he
+ * serialized xmitting frames from isdn_ppp and BSENT statcallb
+ *
+ * Revision 1.91  1999/09/12 16:19:39  detabc
+ * added abc features
+ * low cost routing for net-interfaces (only the HL side).
+ * need more implementation in the isdnlog-utility
+ * udp info support (first part).
+ * different EAZ on outgoing call's.
+ * more checks on D-Channel callbacks (double use of channels).
+ * tested and running with kernel 2.3.17
+ *
+ * Revision 1.90  1999/09/04 22:21:39  detabc
+ *
  * Revision 1.89  1999/08/22 20:26:03  calle
  * backported changes from kernel 2.3.14:
  * - several #include "config.h" gone, others come.
@@ -360,13 +392,58 @@
 #include "isdn_concap.h"
 #endif
 
+
+#ifndef ISDN_NEW_TBUSY
+#define ISDN_NEW_TBUSY
+#endif
+#ifdef ISDN_NEW_TBUSY
+/*
+ * Outline of new tbusy handling: 
+ *
+ * Old method, roughly spoken, consisted of setting tbusy when entering
+ * isdn_net_start_xmit() and at several other locations and clearing
+ * it from isdn_net_start_xmit() thread when sending was successful.
+ *
+ * With 2.3.x multithreaded network core, to prevent problems, tbusy should
+ * only be set by the isdn_net_start_xmit() thread and only when a tx-busy
+ * condition is detected. Other threads (in particular isdn_net_stat_callb())
+ * are only allowed to clear tbusy.
+ *
+ * -HE
+ */
+
+/*
+ * Tell upper layers that the network device is ready to xmit more frames.
+ */
+static void __inline__ isdn_net_dev_xon(struct net_device * dev)
+{
+	dev->tbusy = 0;
+	mark_bh(NET_BH);
+}
+
+static void __inline__ isdn_net_lp_xon(isdn_net_local * lp)
+{
+	lp->netdev->dev.tbusy = 0;
+	if(lp->master) lp->master->tbusy = 0;
+	mark_bh(NET_BH);
+}
+
+/*
+ * Ask upper layers to temporarily cease passing us more xmit frames.
+ */
+static void __inline__ isdn_net_dev_xoff(struct net_device * dev)
+{
+	dev->tbusy = 1;
+}
+#endif
+
 /* Prototypes */
 
 int isdn_net_force_dial_lp(isdn_net_local *);
 static int isdn_net_start_xmit(struct sk_buff *, struct net_device *);
 static int isdn_net_xmit(struct net_device *, isdn_net_local *, struct sk_buff *);
 
-char *isdn_net_revision = "$Revision: 1.89 $";
+char *isdn_net_revision = "$Revision: 1.95 $";
 
  /*
   * Code for raw-networking over ISDN
@@ -408,7 +485,11 @@ isdn_net_reset(struct net_device *dev)
 	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 );
@@ -607,6 +688,13 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
 				    (!lp->dialstate)) {
 					lp->stats.tx_packets++;
 					lp->stats.tx_bytes += c->parm.length;
+					/* some HL drivers deliver 
+					   ISDN_STAT_BSENT from hw interrupt.
+					   Output routines in isdn_ppp are now
+					   called with irq disabled such that
+					   dequeueing the sav_skb while another
+					   frame is sent will not occur.
+					*/
 					if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP && lp->sav_skb) {
 						struct net_device *mdev;
 						if (lp->master)
@@ -615,13 +703,19 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
 							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:
@@ -704,7 +798,6 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
 						lp->dialstarted = 0;
 						lp->dialwait_timer = 0;
 
-						/* Immediately send first skb to speed up arp */
 #ifdef CONFIG_ISDN_PPP
 						if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
 							isdn_ppp_wakeup_daemon(lp);
@@ -715,11 +808,15 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
 							if( pops->connect_ind)
 								pops->connect_ind(cprot);
 #endif /* CONFIG_ISDN_X25 */
+						/* Immediately send first skb to speed up arp */
 						if (lp->first_skb) {
 
 							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).
@@ -728,6 +825,7 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
 							lp->netdev->dev.tbusy = 0;
 							mark_bh(NET_BH);
 						}
+#endif /* ISDN_NEW_TBUSY */
 						return 1;
 				}
 				break;
@@ -1162,6 +1260,7 @@ isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp)
 					break;
 			}
 			printk(KERN_INFO "OPEN: %d.%d.%d.%d -> %d.%d.%d.%d%s\n",
+
 			       p[12], p[13], p[14], p[15],
 			       p[16], p[17], p[18], p[19],
 			       addinfo);
@@ -1180,8 +1279,12 @@ isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp)
  * standard send-routine, else send directly.
  *
  * 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(struct net_device *ndev, isdn_net_local * lp,
 		  struct sk_buff *skb)
@@ -1192,13 +1295,17 @@ isdn_net_send_skb(struct net_device *ndev, isdn_net_local * lp,
 	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;
@@ -1244,7 +1351,11 @@ isdn_net_xmit(struct net_device *ndev, isdn_net_local * lp, struct sk_buff *skb)
 			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)))
@@ -1298,15 +1409,19 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 #ifdef CONFIG_ISDN_X25
 	struct concap_proto * cprot = lp -> netdev -> cprot;
 #endif
-
 	if (ndev->tbusy) {
 		if (jiffies - ndev->trans_start < (2 * HZ))
 			return 1;
 		if (!lp->dialstate)
 			lp->stats.tx_errors++;
 		ndev->trans_start = jiffies;
+#ifdef ISDN_NEW_TBUSY
+		isdn_net_dev_xon(ndev);
+#endif
 	}
+#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).
@@ -1320,7 +1435,11 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
    when a dl_establish request is received from the upper layer.
 */
 	if( cprot ) {
-		return  cprot -> pops -> encap_and_xmit ( cprot , skb);
+		int ret = cprot -> pops -> encap_and_xmit ( cprot , skb);
+#ifdef ISDN_NEW_TBUSY
+		if(ret) isdn_net_dev_xoff(ndev);
+#endif
+		return ret;
 	} else
 #endif
 	/* auto-dialing xmit function */
@@ -1339,7 +1458,9 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 			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]) {
@@ -1355,7 +1476,9 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 					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
@@ -1364,22 +1487,28 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 
 				/* Grab a free ISDN-Channel */
 				if (((chi =
-				     isdn_get_free_channel(ISDN_USAGE_NET,
-							   lp->l2_proto,
-							   lp->l3_proto,
-							   lp->pre_device,
-						 lp->pre_channel)) < 0) &&
+				     isdn_get_free_channel(
+					 		ISDN_USAGE_NET,
+							lp->l2_proto,
+							lp->l3_proto,
+							lp->pre_device,
+						 	lp->pre_channel)
+							) < 0) &&
 					((chi =
-				     isdn_get_free_channel(ISDN_USAGE_NET,
-							   lp->l2_proto,
-							   lp->l3_proto,
-							   lp->pre_device,
-						 lp->pre_channel^1)) < 0)) {
+				     isdn_get_free_channel(
+					 		ISDN_USAGE_NET,
+							lp->l2_proto,
+							lp->l3_proto,
+							lp->pre_device,
+						    lp->pre_channel^1)
+							) < 0)) {
 					restore_flags(flags);
 					isdn_net_unreachable(ndev, skb,
 							   "No channel");
 					dev_kfree_skb(skb);
+#ifndef ISDN_NEW_TBUSY
 					ndev->tbusy = 0;
+#endif
 					return 0;
 				}
 				/* Log packet, which triggered dialing */
@@ -1399,6 +1528,9 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 					}
 					restore_flags(flags);
 					isdn_net_dial();	/* Initiate dialing */
+#ifdef ISDN_NEW_TBUSY
+					isdn_net_dev_xoff(ndev);
+#endif
 					return 1;	/* let upper layer requeue skb packet */
 				}
 #endif
@@ -1412,7 +1544,9 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 				}
 				lp->first_skb = skb;
 				/* Initiate dialing */
+#ifndef ISDN_NEW_TBUSY
 				ndev->tbusy = 0;
+#endif
 				restore_flags(flags);
 				isdn_net_dial();
 				return 0;
@@ -1420,21 +1554,37 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 				isdn_net_unreachable(ndev, skb,
 						     "No phone number");
 				dev_kfree_skb(skb);
+#ifndef ISDN_NEW_TBUSY
 				ndev->tbusy = 0;
+#endif
 				return 0;
 			}
 		} else {
-			/* Connection is established, try sending */
+			/* Device is connected to an ISDN channel */ 
 			ndev->trans_start = jiffies;
 			if (!lp->dialstate) {
+				/* ISDN connection is established, try sending */
+				int ret;
 				if (lp->first_skb) {
-					if (isdn_net_xmit(ndev, lp, lp->first_skb))
+					if (isdn_net_xmit(ndev, lp, lp->first_skb)){
+#ifdef ISDN_NEW_TBUSY
+						isdn_net_dev_xoff(ndev);
+#endif
 						return 1;
+}
 					lp->first_skb = NULL;
 				}
-				return (isdn_net_xmit(ndev, lp, skb));
+				ret = (isdn_net_xmit(ndev, lp, skb));
+#ifdef ISDN_NEW_TBUSY
+				if(ret) isdn_net_dev_xoff(ndev);
+#endif
+				return ret;
 			} else
+#ifdef ISDN_NEW_TBUSY
+				isdn_net_dev_xoff(ndev);
+#else
 				ndev->tbusy = 1;
+#endif
 		}
 	}
 	return 1;
@@ -1915,7 +2065,7 @@ isdn_net_rebuild_header(struct sk_buff *skb)
 }
 
 /*
- * Interface-setup. (called just after registering a new interface)
+ * Interface-setup. (just after registering a new interface)
  */
 static int
 isdn_net_init(struct net_device *ndev)
@@ -2046,7 +2196,6 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm setup)
 	isdn_net_phone *n;
 	ulong flags;
 	char nr[32];
-
 	/* Search name in netdev-chain */
 	save_flags(flags);
 	cli();
@@ -2258,10 +2407,15 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm setup)
 					       lp->name, nr, eaz);
 					if (lp->phone[1]) {
 						/* Grab a free ISDN-Channel */
-						if ((chi = isdn_get_free_channel(ISDN_USAGE_NET, lp->l2_proto,
+						if ((chi = 
+							isdn_get_free_channel(
+								ISDN_USAGE_NET,
+								lp->l2_proto,
 							    lp->l3_proto,
-							  lp->pre_device,
-						 lp->pre_channel)) < 0) {
+							  	lp->pre_device,
+						 		lp->pre_channel)
+								) < 0) {
+
 							printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n", lp->name);
 							restore_flags(flags);
 							return 0;
@@ -2368,10 +2522,14 @@ isdn_net_force_dial_lp(isdn_net_local * lp)
 			cli();
 
 			/* Grab a free ISDN-Channel */
-			if ((chi = isdn_get_free_channel(ISDN_USAGE_NET, lp->l2_proto,
-							 lp->l3_proto,
-							 lp->pre_device,
-						 lp->pre_channel)) < 0) {
+			if ((chi = 
+						isdn_get_free_channel(
+							ISDN_USAGE_NET,
+							lp->l2_proto,
+							lp->l3_proto,
+							lp->pre_device,
+						 	lp->pre_channel)
+							) < 0) {
 				printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name);
 				restore_flags(flags);
 				return -EAGAIN;
@@ -3076,7 +3234,6 @@ isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
 	if (dev->netdev == NULL)
 		isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
 	restore_flags(flags);
-
 	kfree(p->local);
 	kfree(p);
 
diff --git a/drivers/isdn/isdn_ppp.c b/drivers/isdn/isdn_ppp.c
index 78c71c7fe48814036bb954c7f823ce857304318d..06c2d83addd7f5e01525cb4861c48c132252f9c6 100644
--- a/drivers/isdn/isdn_ppp.c
+++ b/drivers/isdn/isdn_ppp.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.c,v 1.52 1999/08/22 20:26:07 calle Exp $
+/* $Id: isdn_ppp.c,v 1.60 1999/11/04 20:29:55 he Exp $
  *
  * Linux ISDN subsystem, functions for synchronous PPP (linklevel).
  *
@@ -19,6 +19,34 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_ppp.c,v $
+ * Revision 1.60  1999/11/04 20:29:55  he
+ * applied Andre Beck's reset_free fix
+ *
+ * Revision 1.59  1999/10/31 15:59:50  he
+ * more skb headroom checks
+ *
+ * Revision 1.58  1999/10/30 13:13:01  keil
+ * Henners isdn_ppp_skb_push:under fix
+ *
+ * Revision 1.57  1999/10/05 22:47:17  he
+ * Removed dead ISDN_SYNCPPP_READDRESS code (obsoleted by sysctl_ip_dynaddr
+ * and network address translation)
+ *
+ * Revision 1.56  1999/09/29 16:01:06  he
+ * replaced dev_alloc_skb() for downstream skbs by equivalent alloc_skb()
+ *
+ * Revision 1.55  1999/09/23 22:07:51  detabc
+ *
+ * make ipc_head common usable (for use compressor with raw-ip)
+ * add function before netif_rx(). needed for ipv4-tcp-keepalive-detect.
+ * ~
+ *
+ * Revision 1.54  1999/09/13 23:25:17  he
+ * serialized xmitting frames from isdn_ppp and BSENT statcallb
+ *
+ * Revision 1.53  1999/08/31 11:18:14  paul
+ * various spelling corrections (new checksums may be needed, Karsten!)
+ *
  * Revision 1.52  1999/08/22 20:26:07  calle
  * backported changes from kernel 2.3.14:
  * - several #include "config.h" gone, others come.
@@ -212,10 +240,6 @@
 
 /* TODO: right tbusy handling when using MP */
 
-/*
- * experimental for dynamic addressing: readdress IP frames
- */
-#undef ISDN_SYNCPPP_READDRESS
 #define CONFIG_ISDN_CCP 1
 
 #include <linux/config.h>
@@ -258,6 +282,7 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
 				    unsigned char code, unsigned char id,
 				    unsigned char *data, int len);
 static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is);
+static void isdn_ppp_ccp_reset_free(struct ippp_struct *is);
 static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
 					  unsigned char id);
 static void isdn_ppp_ccp_timer_callback(unsigned long closure);
@@ -281,9 +306,10 @@ static int isdn_ppp_fill_mpqueue(isdn_net_dev *, struct sk_buff **skb,
 static void isdn_ppp_free_mpqueue(isdn_net_dev *);
 #endif
 
-char *isdn_ppp_revision = "$Revision: 1.52 $";
+char *isdn_ppp_revision = "$Revision: 1.60 $";
 
 static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
+
 static struct isdn_ppp_compressor *ipc_head = NULL;
 
 /*
@@ -354,10 +380,6 @@ isdn_ppp_free(isdn_net_local * lp)
 		printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_slot, (long) lp, (long) is->lp);
 
 	is->lp = NULL;          /* link is down .. set lp to NULL */
-#ifdef ISDN_SYNCPPP_READDRESS
-	is->old_pa_addr = 0x0;
-	is->old_pa_dstaddr = 0x0;
-#endif
 	lp->ppp_slot = -1;      /* is this OK ?? */
 	restore_flags(flags);
 
@@ -450,9 +472,6 @@ isdn_ppp_wakeup_daemon(isdn_net_local * lp)
 
 	ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
 
-#ifndef COMPAT_HAS_NEW_WAITQ
-	if (ippp_table[lp->ppp_slot]->wq)
-#endif
 		wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
 }
 
@@ -470,11 +489,7 @@ isdn_ppp_closewait(int slot)
 		return 0;
 	is = ippp_table[slot];
 
-#ifdef COMPAT_HAS_NEW_WAITQ
 	if (is->state)
-#else
-	if (is->state && is->wq)
-#endif
 		wake_up_interruptible(&is->wq);
 
 	is->state = IPPP_CLOSEWAIT;
@@ -515,9 +530,6 @@ isdn_ppp_open(int min, struct file *file)
 	}
 	is = file->private_data = ippp_table[slot];
 
-#if 0
-	if (is->debug & 0x1)
-#endif
 		printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n", slot, min, is->state);
 
 	/* compression stuff */
@@ -539,11 +551,7 @@ isdn_ppp_open(int min, struct file *file)
 	is->mru = 1524;         /* MRU, default 1524 */
 	is->maxcid = 16;        /* VJ: maxcid */
 	is->tk = current;
-#ifdef COMPAT_HAS_NEW_WAITQ
 	init_waitqueue_head(&is->wq);
-#else
-	is->wq = NULL;          /* read() wait queue */
-#endif
 	is->first = is->rq + NUM_RCV_BUFFS - 1;	/* receive queue */
 	is->last = is->rq;
 	is->minor = min;
@@ -615,9 +623,9 @@ isdn_ppp_release(int min, struct file *file)
 	is->comp_stat    = is->link_comp_stat    = NULL;
         is->decomp_stat  = is->link_decomp_stat  = NULL;
 
+	/* Clean up if necessary */
 	if(is->reset)
-		kfree(is->reset);
-	is->reset = NULL;
+		isdn_ppp_ccp_reset_free(is);
 
 	/* this slot is ready for new connections */
 	is->state = 0;
@@ -719,10 +727,6 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
 			}
 			is->pppcfg = val;
 			break;
-#if 0
-		case PPPIOCGSTAT:	/* read PPP statistic information */
-			break;
-#endif
 		case PPPIOCGIDLE:	/* get idle time information */
 			if (lp) {
 				struct ppp_idle pidle;
@@ -911,9 +915,6 @@ isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot)
 	is->last = bl->next;
 	restore_flags(flags);
 
-#ifndef COMPAT_HAS_NEW_WAITQ
-	if (is->wq)
-#endif
 		wake_up_interruptible(&is->wq);
 
 	return len;
@@ -1004,6 +1005,7 @@ isdn_ppp_write(int min, struct file *file, const char *buf, int count)
 			lp->dialstate == 0 &&
 		    (lp->flags & ISDN_NET_CONNECTED)) {
 			unsigned short hl;
+			unsigned long flags;
 			int cnt;
 			struct sk_buff *skb;
 			/*
@@ -1027,6 +1029,8 @@ isdn_ppp_write(int min, struct file *file, const char *buf, int count)
 
 			isdn_ppp_send_ccp(lp->netdev,lp,skb); /* keeps CCP/compression states in sync */
 
+			save_flags(flags);
+			cli();
 			if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb)) != count) {
 				if (lp->sav_skb) {
 					dev_kfree_skb(lp->sav_skb);
@@ -1035,6 +1039,7 @@ isdn_ppp_write(int min, struct file *file, const char *buf, int count)
 					printk(KERN_INFO "isdn_ppp_write: Can't write PPP frame to LL (%d,%d)!\n", cnt, count);
 				lp->sav_skb = skb;
 			}
+			restore_flags(flags);
 		}
 	}
 	return count;
@@ -1115,7 +1120,7 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
 		isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
 	}
 	if (net_dev->local->master) {
-		printk(KERN_WARNING "isdn_ppp_receice: net_dev != master\n");
+		printk(KERN_WARNING "isdn_ppp_receive: net_dev != master\n");
 		net_dev = ((isdn_net_local *) net_dev->local->master->priv)->netdev;
 	}
 	if (skb->data[0] == 0xff && skb->data[1] == 0x03)
@@ -1459,6 +1464,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
 	isdn_net_dev *nd;
 	unsigned int proto = PPP_IP;     /* 0x21 */
 	struct ippp_struct *ipt,*ipts;
+	unsigned long flags;
 
 	if (mdev)
 		mlp = (isdn_net_local *) (mdev->priv);
@@ -1470,12 +1476,6 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
 	ipts = ippp_table[mlp->ppp_slot];
 
 	if (!(ipts->pppcfg & SC_ENABLE_IP)) {	/* PPP connected ? */
-#ifdef ISDN_SYNCPPP_READDRESS
-		if (!ipts->old_pa_addr)
-			ipts->old_pa_addr = mdev->pa_addr;
-		if (!ipts->old_pa_dstaddr)
-			ipts->old_pa_dstaddr = mdev->pa_dstaddr;
-#endif
 		if (ipts->debug & 0x1)
 			printk(KERN_INFO "%s: IP frame delayed.\n", netdev->name);
 		return 1;
@@ -1484,21 +1484,6 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
 	switch (ntohs(skb->protocol)) {
 		case ETH_P_IP:
 			proto = PPP_IP;
-#ifdef ISDN_SYNCPPP_READDRESS
-			if (ipts->old_pa_addr != mdev->pa_addr) {
-				struct iphdr *ipfr;
-				ipfr = (struct iphdr *) skb->data;
-				if(ipts->debug & 0x4)
-					printk(KERN_DEBUG "IF-address changed from %lx to %lx\n", ipts->old_pa_addr, mdev->pa_addr);
-				if (ipfr->version == 4) {
-					if (ipfr->saddr == ipts->old_pa_addr) {
-						printk(KERN_DEBUG "readdressing %lx to %lx\n", ipfr->saddr, mdev->pa_addr);
-						ipfr->saddr = mdev->pa_addr;
-					}
-				}
-			}
-			/* dstaddr change not so important */
-#endif
 			break;
 		case ETH_P_IPX:
 			proto = PPP_IPX;	/* untested */
@@ -1529,8 +1514,6 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
 
 	/* Pull off the fake header we stuck on earlier to keep
      * the fragemntation code happy.
-     * this will break the ISDN_SYNCPPP_READDRESS hack a few lines
-     * above. So, enabling this is no longer allowed
      */
 	skb_pull(skb,IPPP_MAX_HEADER);
 
@@ -1548,7 +1531,13 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
 		 * sk_buff. old call to dev_alloc_skb only reserved
 		 * 16 bytes, now we are looking what the driver want.
 		 */
-		hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
+		hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen + IPPP_MAX_HEADER;
+		/* 
+		 * Note: hl might still be insufficient because the method
+		 * above does not account for a possibible MPPP slave channel
+		 * which had larger HL header space requirements than the
+		 * master.
+		 */
 		new_skb = alloc_skb(hl+skb->len, GFP_ATOMIC);
 		if (new_skb) {
 			u_char *buf;
@@ -1654,13 +1643,16 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
 		printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len);
 		isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,ipt->unit,lp->ppp_slot);
 	}
+	save_flags(flags);
+	cli();
 	if (isdn_net_send_skb(netdev, lp, skb)) {
-		if (lp->sav_skb) {	/* whole sav_skb processing with disabled IRQs ?? */
+		if (lp->sav_skb) {	/* should never happen as sav_skb are sent with disabled IRQs) */
 			printk(KERN_ERR "%s: whoops .. there is another stored skb!\n", netdev->name);
 			dev_kfree_skb(skb);
 		} else
 			lp->sav_skb = skb;
 	}
+	restore_flags(flags);
 	return 0;
 }
 
@@ -1744,12 +1736,6 @@ isdn_ppp_bundle(struct ippp_struct *is, int unit)
 
 	ippp_table[nlp->ppp_slot]->mpppcfg |= ippp_table[lp->ppp_slot]->mpppcfg &
 	    (SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ);
-#if 0
-	if (ippp_table[nlp->ppp_slot]->mpppcfg != ippp_table[lp->ppp_slot]->mpppcfg) {
-		printk(KERN_WARNING "isdn_ppp_bundle: different MP options %04x and %04x\n",
-		       ippp_table[nlp->ppp_slot]->mpppcfg, ippp_table[lp->ppp_slot]->mpppcfg);
-	}
-#endif
 
 	restore_flags(flags);
 	return 0;
@@ -2075,9 +2061,6 @@ isdn_ppp_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	int len;
 	isdn_net_local *lp = (isdn_net_local *) dev->priv;
 
-#if 0
-	printk(KERN_DEBUG "ippp, dev_ioctl: cmd %#08x , %d \n", cmd, lp->ppp_slot);
-#endif
 
 	if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
 		return -EINVAL;
@@ -2241,17 +2224,20 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
 {
 	struct sk_buff *skb;
 	unsigned char *p;
-	int count;
+	int count, hl;
+	unsigned long flags;
 	int cnt = 0;
 	isdn_net_local *lp = is->lp;
 
 	/* Alloc large enough skb */
-	skb = dev_alloc_skb(len + 16);
+	hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
+	skb = alloc_skb(len + hl + 16,GFP_ATOMIC);
 	if(!skb) {
 		printk(KERN_WARNING
 		       "ippp: CCP cannot send reset - out of memory\n");
 		return;
 	}
+	skb_reserve(skb, hl);
 
 	/* We may need to stuff an address and control field first */
 	if(!(is->pppcfg & SC_COMP_AC)) {
@@ -2284,6 +2270,8 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
 	   especially dunno what the sav_skb stuff is good for. */
 
 	count = skb->len;
+	save_flags(flags);
+	cli();
 	if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel,
 					  1, skb)) != count) {
 		if (lp->sav_skb) {
@@ -2297,21 +2285,41 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
 			       cnt, count);
 		lp->sav_skb = skb;
 	}
+	restore_flags(flags);
 }
 
 /* Allocate the reset state vector */
 static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is)
 {
 	struct ippp_ccp_reset *r;
-	printk(KERN_DEBUG "ippp_ccp: allocating reset data structure\n");
 	r = kmalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL);
-	if(!r)
+	if(!r) {
+		printk(KERN_ERR "ippp_ccp: failed to allocate reset data"
+		       " structure - no mem\n");
 		return NULL;
+	}
 	memset(r, 0, sizeof(struct ippp_ccp_reset));
+	printk(KERN_DEBUG "ippp_ccp: allocated reset data structure %p\n", r);
 	is->reset = r;
 	return r;
 }
 
+/* Destroy the reset state vector. Kill all pending timers first. */
+static void isdn_ppp_ccp_reset_free(struct ippp_struct *is)
+{
+	unsigned int id;
+
+	printk(KERN_DEBUG "ippp_ccp: freeing reset data structure %p\n",
+	       is->reset);
+	for(id = 0; id < 256; id++) {
+		if(is->reset->rs[id]) {
+			isdn_ppp_ccp_reset_free_state(is, (unsigned char)id);
+		}
+	}
+	kfree(is->reset);
+	is->reset = NULL;
+}
+
 /* Free a given state and clear everything up for later reallocation */
 static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
 					  unsigned char id)
@@ -2653,13 +2661,7 @@ static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
     }
 
 	if(type) { /* type=1 => Link compression */
-#if 0
-		compressor = is->link_compressor;
-		stat = is->link_comp_stat;
-		new_proto = PPP_LINK_COMP;
-#else
 		return skb_in;
-#endif
 	}
 	else {
 		if(!master) {
@@ -2683,9 +2685,11 @@ static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
 	}
 
 	/* Allow for at least 150 % expansion (for now) */
-	skb_out = dev_alloc_skb(skb_in->len + skb_in->len/2 + 32);
+	skb_out = alloc_skb(skb_in->len + skb_in->len/2 + 32 +
+		skb_headroom(skb_in), GFP_ATOMIC);
 	if(!skb_out)
 		return skb_in;
+	skb_reserve(skb_out, skb_headroom(skb_in));
 
 	ret = (compressor->compress)(stat,skb_in,skb_out,*proto);
 	if(!ret) {
@@ -2914,7 +2918,6 @@ static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct
 	}
 }
 
-
 int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc)
 {
 	ipc->next = ipc_head;
@@ -2949,6 +2952,16 @@ static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_
 		printk(KERN_DEBUG "[%d] Set %s type %d\n",is->unit,
 			(data->flags&IPPP_COMP_FLAG_XMIT)?"compressor":"decompressor",num);
 
+	/* If is has no valid reset state vector, we cannot allocate a
+	   decompressor. The decompressor would cause reset transactions
+	   sooner or later, and they need that vector. */
+
+	if(!(data->flags & IPPP_COMP_FLAG_XMIT) && !is->reset) {
+		printk(KERN_ERR "ippp_ccp: no reset data structure - can't"
+		       " allow decompression.\n");
+		return -ENOMEM;
+	}
+
 	while(ipc) {
 		if(ipc->num == num) {
 			stat = ipc->alloc(data);
@@ -3000,5 +3013,3 @@ static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_
 	}
 	return -EINVAL;
 }
-
-
diff --git a/drivers/isdn/isdn_tty.c b/drivers/isdn/isdn_tty.c
index e502f90dadb3c90cdc70133239eb4eafd5d461c8..5b301adb9db8ec773764e8ccf35f053c92edaecc 100644
--- a/drivers/isdn/isdn_tty.c
+++ b/drivers/isdn/isdn_tty.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.c,v 1.73 1999/08/28 21:56:27 keil Exp $
+/* $Id: isdn_tty.c,v 1.80 1999/11/07 13:34:30 armin Exp $
 
  * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
  *
@@ -20,6 +20,30 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_tty.c,v $
+ * Revision 1.80  1999/11/07 13:34:30  armin
+ * Fixed AT command line editor
+ *
+ * Revision 1.79  1999/10/29 18:35:08  armin
+ * Check number len in isdn_get_msnstr() to avoid buffer overflow.
+ *
+ * Revision 1.78  1999/10/28 23:03:51  armin
+ * Bugfix: now freeing channel on modem_hup() even when
+ * usage on ttyI has changed and error-report for
+ * AT-commands on wrong channel-state.
+ *
+ * Revision 1.77  1999/10/26 21:13:14  armin
+ * using define for checking phone number len in isdn_tty_getdial()
+ *
+ * Revision 1.76  1999/10/11 22:16:26  keil
+ * Suspend/Resume is possible without explicit ID too
+ *
+ * Revision 1.75  1999/10/08 18:59:32  armin
+ * Bugfix of too small MSN buffer and checking phone number
+ * in isdn_tty_getdial()
+ *
+ * Revision 1.74  1999/09/04 06:20:04  keil
+ * Changes from kernel set_current_state()
+ *
  * Revision 1.73  1999/08/28 21:56:27  keil
  * misplaced #endif caused ttyI crash in 2.3.X
  *
@@ -348,7 +372,7 @@ static int bit2si[8] =
 static int si2bit[8] =
 {4, 1, 4, 4, 4, 4, 4, 4};
 
-char *isdn_tty_revision = "$Revision: 1.73 $";
+char *isdn_tty_revision = "$Revision: 1.80 $";
 
 
 /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
@@ -1014,7 +1038,6 @@ void
 isdn_tty_modem_hup(modem_info * info, int local)
 {
 	isdn_ctrl cmd;
-	int usage;
 
 	if (!info)
 		return;
@@ -1068,10 +1091,7 @@ isdn_tty_modem_hup(modem_info * info, int local)
 		}
 		isdn_all_eaz(info->isdn_driver, info->isdn_channel);
 		info->emu.mdmreg[REG_RINGCNT] = 0;
-		usage = isdn_calc_usage(info->emu.mdmreg[REG_SI1I],
-					info->emu.mdmreg[REG_L2PROT]);
-		isdn_free_channel(info->isdn_driver, info->isdn_channel,
-				  usage);
+		isdn_free_channel(info->isdn_driver, info->isdn_channel, 0);
 	}
 	info->isdn_driver = -1;
 	info->isdn_channel = -1;
@@ -1108,8 +1128,8 @@ isdn_tty_suspend(char *id, modem_info * info, atemu * m)
 	printk(KERN_DEBUG "Msusp ttyI%d\n", info->line);
 #endif
 	l = strlen(id);
-	if ((info->isdn_driver >= 0) && l) {
-		cmd.parm.cmsg.Length = l+17;
+	if ((info->isdn_driver >= 0)) {
+		cmd.parm.cmsg.Length = l+18;
 		cmd.parm.cmsg.Command = CAPI_FACILITY;
 		cmd.parm.cmsg.Subcommand = CAPI_REQ;
 		cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
@@ -1147,10 +1167,6 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m)
 	int l;
 
 	l = strlen(id);
-	if (!l) {
-		isdn_tty_modem_result(4, info);
-		return;
-	}
 	for (j = 7; j >= 0; j--)
 		if (m->mdmreg[REG_SI1] & (1 << j)) {
 			si = bit2si[j];
@@ -1204,7 +1220,7 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m)
 		isdn_command(&cmd);
 		cmd.driver = info->isdn_driver;
 		cmd.arg = info->isdn_channel;
-		cmd.parm.cmsg.Length = l+17;
+		cmd.parm.cmsg.Length = l+18;
 		cmd.parm.cmsg.Command = CAPI_FACILITY;
 		cmd.parm.cmsg.Subcommand = CAPI_REQ;
 		cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
@@ -1901,12 +1917,7 @@ isdn_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
 static int
 isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * info)
 {
-#ifdef COMPAT_HAS_NEW_WAITQ
 	DECLARE_WAITQUEUE(wait, NULL);
-#else
-	struct wait_queue wait =
-	{current, NULL};
-#endif
 	int do_clocal = 0;
 	unsigned long flags;
 	int retval;
@@ -2157,7 +2168,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
 		 */
 		timeout = jiffies + HZ;
 		while (!(info->lsr & UART_LSR_TEMT)) {
-			current->state = TASK_INTERRUPTIBLE;
+			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout(20);
 			if (time_after(jiffies,timeout))
 				break;
@@ -2173,7 +2184,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
 	info->ncarrier = 0;
 	tty->closing = 0;
 	if (info->blocked_open) {
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(50);
 		wake_up_interruptible(&info->open_wait);
 	}
@@ -2375,11 +2386,7 @@ isdn_tty_modem_init(void)
 			return -3;
 		}
 #endif
-#ifdef COMPAT_HAS_NEW_WAITQ
 		init_MUTEX(&info->write_sem);
-#else
-		info->write_sem = MUTEX;
-#endif
 		sprintf(info->last_cause, "0000");
 		sprintf(info->last_num, "none");
 		info->last_dir = 0;
@@ -2396,13 +2403,8 @@ isdn_tty_modem_init(void)
 		info->blocked_open = 0;
 		info->callout_termios = m->cua_modem.init_termios;
 		info->normal_termios = m->tty_modem.init_termios;
-#ifdef COMPAT_HAS_NEW_WAITQ
 		init_waitqueue_head(&info->open_wait);
 		init_waitqueue_head(&info->close_wait);
-#else
-		info->open_wait = 0;
-		info->close_wait = 0;
-#endif
 		info->isdn_driver = -1;
 		info->isdn_channel = -1;
 		info->drv_index = -1;
@@ -3101,9 +3103,12 @@ isdn_tty_show_profile(int ridx, modem_info * info)
 static void
 isdn_tty_get_msnstr(char *n, char **p)
 {
-	while ((*p[0] >= '0' && *p[0] <= '9') ||
+	int limit = ISDN_MSNLEN - 1;
+
+	while (((*p[0] >= '0' && *p[0] <= '9') ||
 	       /* Why a comma ??? */
-	       (*p[0] == ','))
+	       (*p[0] == ',')) &&
+		(limit--))
 		*n++ = *p[0]++;
 	*n = '\0';
 }
@@ -3115,16 +3120,18 @@ static void
 isdn_tty_getdial(char *p, char *q,int cnt)
 {
 	int first = 1;
-	int limit=39;	/* MUST match the size in isdn_tty_parse to avoid
-				buffer overflow */
+	int limit = ISDN_MSNLEN - 1;	/* MUST match the size of interface var to avoid
+					buffer overflow */
 
 	while (strchr(" 0123456789,#.*WPTS-", *p) && *p && --cnt>0) {
 		if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first) ||
-		    (*p == '*') || (*p == '#'))
+		    (*p == '*') || (*p == '#')) {
 			*q++ = *p;
-		p++;
-		if(!--limit)
+			limit--;
+		}
+		if(!limit)
 			break;
+		p++;
 		first = 0;
 	}
 	*q = 0;
@@ -3268,6 +3275,8 @@ isdn_tty_cmd_ATand(char **p, modem_info * info)
 		case 'F':
 			/* &F -Set Factory-Defaults */
 			p[0]++;
+			if (info->msr & UART_MSR_DCD)
+				PARSE_ERROR1;
 			isdn_tty_reset_profile(m);
 			isdn_tty_modem_reset_regs(info, 1);
 			break;
@@ -3919,6 +3928,12 @@ isdn_tty_parse_at(modem_info * info)
 				break;
 			case 'D':
 				/* D - Dial */
+				if (info->msr & UART_MSR_DCD)
+					PARSE_ERROR;
+				if (info->msr & UART_MSR_RI) {
+					isdn_tty_modem_result(3, info);
+					return;
+				}
 				isdn_tty_getdial(++p, ds, sizeof ds);
 				p += strlen(p);
 				if (!strlen(m->msn))
@@ -4113,7 +4128,7 @@ isdn_tty_edit_at(const char *p, int count, modem_info * info, int user)
 			c = *p;
 		total++;
 		if (c == m->mdmreg[REG_CR] || c == m->mdmreg[REG_LF]) {
-			/* Separator (CR oder LF) */
+			/* Separator (CR or LF) */
 			m->mdmcmd[m->mdmcmdl] = 0;
 			if (m->mdmreg[REG_ECHO] & BIT_ECHO) {
 				eb[0] = c;
@@ -4126,7 +4141,7 @@ isdn_tty_edit_at(const char *p, int count, modem_info * info, int user)
 			continue;
 		}
 		if (c == m->mdmreg[REG_BS] && m->mdmreg[REG_BS] < 128) {
-			/* Backspace-Funktion */
+			/* Backspace-Function */
 			if ((m->mdmcmdl > 2) || (!m->mdmcmdl)) {
 				if (m->mdmcmdl)
 					m->mdmcmdl--;
@@ -4144,18 +4159,24 @@ isdn_tty_edit_at(const char *p, int count, modem_info * info, int user)
 			if (m->mdmcmdl < 255) {
 				c = my_toupper(c);
 				switch (m->mdmcmdl) {
-					case 0:
-						if (c == 'A')
-							m->mdmcmd[m->mdmcmdl] = c;
-						break;
 					case 1:
-						if (c == 'T')
+						if (c == 'T') {
 							m->mdmcmd[m->mdmcmdl] = c;
+							m->mdmcmd[++m->mdmcmdl] = 0;
+							break;
+						} else
+							m->mdmcmdl = 0;
+						/* Fall through, check for 'A' */
+					case 0:
+						if (c == 'A') {
+							m->mdmcmd[m->mdmcmdl] = c;
+							m->mdmcmd[++m->mdmcmdl] = 0;
+						}
 						break;
 					default:
 						m->mdmcmd[m->mdmcmdl] = c;
+						m->mdmcmd[++m->mdmcmdl] = 0;
 				}
-				m->mdmcmd[++m->mdmcmdl] = 0;
 			}
 		}
 	}
diff --git a/drivers/isdn/isdn_tty.h b/drivers/isdn/isdn_tty.h
index 87acd7be2fd384864f81c84a257a5889391d7e26..1c27b83009c986129596e035aa961ac071f9476e 100644
--- a/drivers/isdn/isdn_tty.h
+++ b/drivers/isdn/isdn_tty.h
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.h,v 1.16 1999/08/22 20:26:10 calle Exp $
+/* $Id: isdn_tty.h,v 1.17 1999/09/21 19:00:35 armin Exp $
 
  * header for Linux ISDN subsystem, tty related functions (linklevel).
  *
@@ -20,6 +20,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_tty.h,v $
+ * Revision 1.17  1999/09/21 19:00:35  armin
+ * Extended FCON message with added CPN
+ * can now be activated with Bit 1 of Reg 23.
+ *
  * Revision 1.16  1999/08/22 20:26:10  calle
  * backported changes from kernel 2.3.14:
  * - several #include "config.h" gone, others come.
@@ -154,6 +158,7 @@
 
 #define REG_CPN      23
 #define BIT_CPN       1
+#define BIT_CPNFCON   2
 
 extern void isdn_tty_modem_escape(void);
 extern void isdn_tty_modem_ring(void);
diff --git a/drivers/isdn/isdn_ttyfax.c b/drivers/isdn/isdn_ttyfax.c
index 7665aa812c266cd6da310a1a40e0fbcd6446b648..9b7268b32c5ccd8a6a36936e61e7e3da9fbacb3c 100644
--- a/drivers/isdn/isdn_ttyfax.c
+++ b/drivers/isdn/isdn_ttyfax.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_ttyfax.c,v 1.3 1999/08/22 20:26:12 calle Exp $
+/* $Id: isdn_ttyfax.c,v 1.4 1999/09/21 19:00:35 armin Exp $
  * Linux ISDN subsystem, tty_fax AT-command emulator (linklevel).
  *
  * Copyright 1999    by Armin Schindler (mac@melware.de)
@@ -20,6 +20,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_ttyfax.c,v $
+ * Revision 1.4  1999/09/21 19:00:35  armin
+ * Extended FCON message with added CPN
+ * can now be activated with Bit 1 of Reg 23.
+ *
  * Revision 1.3  1999/08/22 20:26:12  calle
  * backported changes from kernel 2.3.14:
  * - several #include "config.h" gone, others come.
@@ -46,7 +50,7 @@
 #include "isdn_ttyfax.h"
 
 
-static char *isdn_tty_fax_revision = "$Revision: 1.3 $";
+static char *isdn_tty_fax_revision = "$Revision: 1.4 $";
 
 #define PARSE_ERROR1 { isdn_tty_fax_modem_result(1, info); return 1; }
 
@@ -98,7 +102,7 @@ static void isdn_tty_fax_modem_result(int code, modem_info * info)
 			break;
 		case 2:	/* +FCON */
 			/* Append CPN, if enabled */
-			if ((m->mdmreg[REG_CPN] & BIT_CPN) &&
+			if ((m->mdmreg[REG_CPN] & BIT_CPNFCON) &&
 				(!(dev->usage[info->isdn_channel] & ISDN_USAGE_OUTGOING))) {
 				sprintf(rs, "/%s", m->cpn);
 				isdn_tty_at_cout(rs, info);
@@ -907,76 +911,6 @@ int isdn_tty_cmd_PLUSF_FAX(char **p, modem_info * info)
                 return 0;
         }
 
-#if 0
-	/* LO=n - Flow control opts */
-        if (!strncmp(p[0], "LO", 2)) { /* TODO */
-                p[0] += 2;
-		switch (*p[0]) {
-			case '?':
-				p[0]++;
-                                sprintf(rs, "\r\n%d",f->lo);
-                                isdn_tty_at_cout(rs, info);
-				break;
-			case '=':
-                                p[0]++;
-                                if (*p[0] == '?')
-                                    {
-                                     p[0]++;
-                                     sprintf(rs, "\r\n0,1,2");
-                       		     isdn_tty_at_cout(rs, info);
-                                    }
-                                    else
-                                    {
-                                        par = isdn_getnum(p);
-                                        if ((par < 0) || (par > 2))
-                                            PARSE_ERROR1;
-                                        f->lo = par;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                                        printk(KERN_DEBUG "isdn_tty: Fax FLO=%d\n", par);
-#endif
-                                    }
-                                    break;
-			default:
-				PARSE_ERROR1;
-		}
-                return 0;
-        }
-#endif
-#if 0
-	/* LPL=n - Doc for polling cmd  */
-        if (!strncmp(p[0], "LPL", 3)) { /* TODO */
-                p[0] += 3;
-		switch (*p[0]) {
-			case '?':
-				p[0]++;
-                                sprintf(rs, "\r\n%d",f->lpl);
-                                isdn_tty_at_cout(rs, info);
-				break;
-			case '=':
-                                p[0]++;
-                                if (*p[0] == '?')
-                                    {
-                                     p[0]++;
-                                     sprintf(rs, "\r\n0,1");
-                       		     isdn_tty_at_cout(rs, info);
-                                    }
-                                    else
-                                    {
-                                        par = isdn_getnum(p);
-                                        if ((par < 0) || (par > 1))
-                                            PARSE_ERROR1;
-                                        f->lpl = par;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                                        printk(KERN_DEBUG "isdn_tty: Fax FLPL=%d\n", par);
-#endif
-                                    }
-                                    break;
-			default:
-				PARSE_ERROR1;
-		}
-                return 0;
-        }
-#endif
 
 	/* MDL? - DCE Model       */
         if (!strncmp(p[0], "MDL?", 4)) {
@@ -1066,41 +1000,6 @@ int isdn_tty_cmd_PLUSF_FAX(char **p, modem_info * info)
                 return 0;
         }
 
-#if 0
-	/* PTS=n - Page transfer status       */
-        if (!strncmp(p[0], "PTS", 3)) { /* TODO */
-                p[0] += 3;
-		switch (*p[0]) {
-			case '?':
-				p[0]++;
-                                sprintf(rs, "\r\n%d",f->pts);
-                                isdn_tty_at_cout(rs, info);
-				break;
-			case '=':
-                                p[0]++;
-                                if (*p[0] == '?')
-                                    {
-                                     p[0]++;
-                                     sprintf(rs, "\r\n0-5");
-                       		     isdn_tty_at_cout(rs, info);
-                                    }
-                                    else
-                                    {
-                                        par = isdn_getnum(p);
-                                        if ((par < 0) || (par > 5))
-                                            PARSE_ERROR1;
-                                        f->pts = par;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                                        printk(KERN_DEBUG "isdn_tty: Fax FPTS=%d\n", par);
-#endif
-                                    }
-                                    break;
-			default:
-				PARSE_ERROR1;
-		}
-                return 0;
-        }
-#endif
 
 	/* REL=n - Phase C received EOL alignment */
         if (!strncmp(p[0], "REL", 3)) {
@@ -1148,41 +1047,6 @@ int isdn_tty_cmd_PLUSF_FAX(char **p, modem_info * info)
                 return 0;
         }
 
-#if 0
-	/* SPL=n - Enable polling */
-        if (!strncmp(p[0], "SPL", 3)) { /* TODO */
-                p[0] += 3;
-		switch (*p[0]) {
-			case '?':
-				p[0]++;
-                                sprintf(rs, "\r\n%d", f->spl);
-                                isdn_tty_at_cout(rs, info);
-				break;
-			case '=':
-                                p[0]++;
-                                if (*p[0] == '?')
-                                    {
-                                     p[0]++;
-                                     sprintf(rs, "\r\n0,1");
-                       		     isdn_tty_at_cout(rs, info);
-                                    }
-                                    else
-                                    {
-                                        par = isdn_getnum(p);
-                                        if ((par < 0) || (par > 1))
-                                            PARSE_ERROR1;
-                                        f->spl = par;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                                        printk(KERN_DEBUG "isdn_tty: Fax FSPL=%d\n", par);
-#endif
-                                    }
-                                    break;
-			default:
-				PARSE_ERROR1;
-		}
-                return 0;
-        }
-#endif
 
 	/* Phase C Transmit Data Block Size */
 	if (!strncmp(p[0], "TBC=", 4)) { /* dummy, not used */
diff --git a/drivers/isdn/isdn_v110.c b/drivers/isdn/isdn_v110.c
index ae62378b875751b4b742a031730562db27ed0723..a3ac19caf09bd2918e09465a2d96186db2bd1396 100644
--- a/drivers/isdn/isdn_v110.c
+++ b/drivers/isdn/isdn_v110.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_v110.c,v 1.2 1998/02/22 19:44:25 fritz Exp $
+/* $Id: isdn_v110.c,v 1.3 1999/10/30 09:49:28 keil Exp $
 
  * Linux ISDN subsystem, V.110 related functions (linklevel).
  *
@@ -19,6 +19,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_v110.c,v $
+ * Revision 1.3  1999/10/30 09:49:28  keil
+ * Reinit of v110 structs
+ *
  * Revision 1.2  1998/02/22 19:44:25  fritz
  * Bugfixes and improvements regarding V.110, V.110 now running.
  *
@@ -36,7 +39,7 @@
 
 #undef ISDN_V110_DEBUG
 
-char *isdn_v110_revision = "$Revision: 1.2 $";
+char *isdn_v110_revision = "$Revision: 1.3 $";
 
 #define V110_38400 255
 #define V110_19200  15
@@ -148,21 +151,13 @@ isdn_v110_open(unsigned char key, int hdrlen, int maxsize)
 }
 
 /* isdn_v110_close frees private V.110 data structures */
-static void
+void
 isdn_v110_close(isdn_v110_stream * v)
 {
 	if (v == NULL)
 		return;
 #ifdef ISDN_V110_DEBUG
 	printk(KERN_DEBUG "v110 close\n");
-#if 0
-	printk(KERN_DEBUG "isdn_v110_close: nbytes=%d\n", v->nbytes);
-	printk(KERN_DEBUG "isdn_v110_close: nbits=%d\n", v->nbits);
-	printk(KERN_DEBUG "isdn_v110_close: key=%d\n", v->key);
-	printk(KERN_DEBUG "isdn_v110_close: SyncInit=%d\n", v->SyncInit);
-	printk(KERN_DEBUG "isdn_v110:close: decodelen=%d\n", v->decodelen);
-	printk(KERN_DEBUG "isdn_v110_close: framelen=%d\n", v->framelen);
-#endif
 #endif
 	kfree(v->encodebuf);
 	kfree(v);
diff --git a/drivers/isdn/isdn_v110.h b/drivers/isdn/isdn_v110.h
index 9ab5a93f36181518866927c9f9cf85ee19fd59ac..4bb6948498430d2f151fbac55c5d34af196770fa 100644
--- a/drivers/isdn/isdn_v110.h
+++ b/drivers/isdn/isdn_v110.h
@@ -1,4 +1,4 @@
-/* $Id: isdn_v110.h,v 1.1 1998/02/20 17:32:11 fritz Exp $
+/* $Id: isdn_v110.h,v 1.2 1999/10/30 09:49:28 keil Exp $
 
  * Linux ISDN subsystem, V.110 related functions (linklevel).
  *
@@ -19,6 +19,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_v110.h,v $
+ * Revision 1.2  1999/10/30 09:49:28  keil
+ * Reinit of v110 structs
+ *
  * Revision 1.1  1998/02/20 17:32:11  fritz
  * First checkin (not yet completely functionable).
  *
@@ -41,5 +44,6 @@ extern struct sk_buff *isdn_v110_encode(isdn_v110_stream *, struct sk_buff *);
 extern struct sk_buff *isdn_v110_decode(isdn_v110_stream *, struct sk_buff *);
 
 extern int isdn_v110_stat_callback(int, isdn_ctrl *);
+extern void isdn_v110_close(isdn_v110_stream * v);
 
 #endif
diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c
index 2e580e1c7a611784cf5e3cbd8d3204612b99de79..9168aca8cbba3c10d9387f5d8f2a18965b96b228 100644
--- a/drivers/isdn/isdnloop/isdnloop.c
+++ b/drivers/isdn/isdnloop/isdnloop.c
@@ -1,8 +1,8 @@
-/* $Id: isdnloop.c,v 1.8 1998/11/18 18:59:43 armin Exp $
+/* $Id: isdnloop.c,v 1.9 1999/09/06 07:29:36 fritz Exp $
 
  * ISDN low-level module implementing a dummy loop driver.
  *
- * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1997 by Fritz Elfert (fritz@isdn4linux.de)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,6 +19,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdnloop.c,v $
+ * Revision 1.9  1999/09/06 07:29:36  fritz
+ * Changed my mail-address.
+ *
  * Revision 1.8  1998/11/18 18:59:43  armin
  * changes for 2.1.127
  *
@@ -56,7 +59,7 @@
 #include "isdnloop.h"
 
 static char
-*revision = "$Revision: 1.8 $";
+*revision = "$Revision: 1.9 $";
 
 static int isdnloop_addcard(char *);
 
diff --git a/drivers/isdn/isdnloop/isdnloop.h b/drivers/isdn/isdnloop/isdnloop.h
index 42906c143ee3e833b46b4b9d94810336c0799362..82266edbe3938b8d33cdae4a005c2a1808fefa23 100644
--- a/drivers/isdn/isdnloop/isdnloop.h
+++ b/drivers/isdn/isdnloop/isdnloop.h
@@ -1,8 +1,8 @@
-/* $Id: isdnloop.h,v 1.3 1998/04/14 20:59:35 he Exp $
+/* $Id: isdnloop.h,v 1.4 1999/09/06 07:29:36 fritz Exp $
 
  * Loopback lowlevel module for testing of linklevel.
  *
- * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1997 by Fritz Elfert (fritz@isdn4linux.de)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,6 +19,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdnloop.h,v $
+ * Revision 1.4  1999/09/06 07:29:36  fritz
+ * Changed my mail-address.
+ *
  * Revision 1.3  1998/04/14 20:59:35  he
  * merged 2.1.94 changes
  *
diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c
index 77f0ed45f7d9afa028cfde2d4322077a23ade85c..679aaddeb46ecc36b6e6704718f4fd809abaa1c4 100644
--- a/drivers/isdn/pcbit/drv.c
+++ b/drivers/isdn/pcbit/drv.c
@@ -86,9 +86,7 @@ int pcbit_init_dev(int board, int mem_base, int irq)
 
 	dev_pcbit[board] = dev;
 	memset(dev, 0, sizeof(struct pcbit_dev));
-#ifdef COMPAT_HAS_NEW_WAITQ
 	init_waitqueue_head(&dev->set_running_wq);
-#endif
 
 	if (mem_base >= 0xA0000 && mem_base <= 0xFFFFF )
 		dev->sh_mem = (unsigned char*) mem_base;
@@ -593,20 +591,6 @@ void pcbit_l3_receive(struct pcbit_dev * dev, ulong msg,
 		       dev->b1->s_refnum, 
 		       dev->b2->s_refnum);
 #endif
-#if 0	
-		if (dev->b1->s_refnum == refnum)
-			chan = dev->b1;
-		else { 
-		   
-			if (dev->b2->s_refnum == refnum)
-				chan = dev->b2;
-			else {
-				chan = NULL;
-				printk(KERN_WARNING "Connection Confirm - refnum doesn't match chan\n");
-				break;
-			}
-		}
-#else
 		/* We just try to find a channel in the right state */
 
 		if (dev->b1->fsm_state == ST_CALL_INIT)
@@ -620,7 +604,6 @@ void pcbit_l3_receive(struct pcbit_dev * dev, ulong msg,
 				break;
 			}
 		}
-#endif
 		if (capi_decode_conn_conf(chan, skb, &complete)) {
 			printk(KERN_DEBUG "conn_conf indicates error\n");
 			pcbit_fsm_event(dev, chan, EV_ERROR, NULL);
diff --git a/drivers/isdn/pcbit/layer2.c b/drivers/isdn/pcbit/layer2.c
index bc1b079a2d123b73ad0cf23065ecf8bbf6ff8a40..36bd6f8aad9ecb7337ec49bb1d2df150881b55a5 100644
--- a/drivers/isdn/pcbit/layer2.c
+++ b/drivers/isdn/pcbit/layer2.c
@@ -375,16 +375,11 @@ pcbit_receive(struct pcbit_dev *dev)
 
 		if (dev->read_frame) {
 			printk(KERN_DEBUG "pcbit_receive: Type 0 frame and read_frame != NULL\n");
-#if 0
-			pcbit_l2_error(dev);
-			return;
-#else
 			/* discard previous queued frame */
 			if (dev->read_frame->skb)
 				kfree_skb(dev->read_frame->skb);
 			kfree(dev->read_frame);
 			dev->read_frame = NULL;
-#endif
 		}
 		frame = kmalloc(sizeof(struct frame_buf), GFP_ATOMIC);
 
@@ -460,14 +455,10 @@ pcbit_receive(struct pcbit_dev *dev)
 
 		if (!(frame = dev->read_frame)) {
 			printk("Type 1 frame and no frame queued\n");
-#if 1
 			/* usually after an error: toss frame */
 			dev->readptr += tt;
 			if (dev->readptr > dev->sh_mem + BANK2 + BANKLEN)
 				dev->readptr -= BANKLEN;
-#else
-			pcbit_l2_error(dev);
-#endif
 			return;
 
 		}
diff --git a/drivers/isdn/pcbit/module.c b/drivers/isdn/pcbit/module.c
index 7995520194ad2b90be6accf5242c25ac588581fe..9d3aa8007ddb82daf174191e4044aac91c887ac3 100644
--- a/drivers/isdn/pcbit/module.c
+++ b/drivers/isdn/pcbit/module.c
@@ -102,7 +102,6 @@ void cleanup_module(void)
 }
 
 #else
-#ifdef COMPAT_HAS_NEW_SETUP
 #define MAX_PARA	(MAX_PCBIT_CARDS * 2)
 #include <linux/init.h>
 static int __init pcbit_setup(char *line)
@@ -112,11 +111,6 @@ static int __init pcbit_setup(char *line)
 	int ints[MAX_PARA+1];
 
 	str = get_options(line, MAX_PARA, ints);
-#else
-void pcbit_setup(char *str, int *ints)
-{
-	int i, j, argc;
-#endif
 	argc = ints[0];
 	i = 0;
 	j = 1;
@@ -135,13 +129,9 @@ void pcbit_setup(char *str, int *ints)
 
 		i++;
 	}
-#ifdef COMPAT_HAS_NEW_SETUP
 	return(1);
 }
 __setup("pcbit=", pcbit_setup);
-#else
-}
-#endif
 #endif
 
 
diff --git a/drivers/isdn/pcbit/pcbit.h b/drivers/isdn/pcbit/pcbit.h
index 45c68871dd5b55fb8f47b95c464abeae37ce0321..d284cc70f0d540b1cb8e3a140dec8950fef64705 100644
--- a/drivers/isdn/pcbit/pcbit.h
+++ b/drivers/isdn/pcbit/pcbit.h
@@ -68,11 +68,7 @@ struct pcbit_dev {
 	struct frame_buf *write_queue;
 
 	/* Protocol start */
-#ifdef COMPAT_HAS_NEW_WAITQ
 	wait_queue_head_t set_running_wq;
-#else
-	struct wait_queue *set_running_wq;
-#endif
 	struct timer_list set_running_timer;
 
 	struct timer_list error_recover_timer;
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c
index 788950eebf5aa2e01747079f631840681ab0233a..e455c074e6f64dc590b4eb5e596078ad2c7bf2c5 100644
--- a/drivers/isdn/sc/init.c
+++ b/drivers/isdn/sc/init.c
@@ -164,7 +164,7 @@ int init_sc(void)
 		if(do_reset) {
 			pr_debug("Doing a SAFE probe reset\n");
 			outb(0xFF, io[b] + RESET_OFFSET);
-			current->state = TASK_INTERRUPTIBLE;
+			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout(milliseconds(10000));
 		}
 		pr_debug("RAM Base for board %d is 0x%x, %s probe\n", b, ram[b],
@@ -512,19 +512,10 @@ int identify_board(unsigned long rambase, unsigned int iobase)
 	 * Try to identify a PRI card
 	 */
 	outb(PRI_BASEPG_VAL, pgport);
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout(HZ);
 	sig = readl(rambase + SIG_OFFSET);
 	pr_debug("Looking for a signature, got 0x%x\n", sig);
-#if 0
-/*
- * For Gary: 
- * If it's a timing problem, it should be gone with the above schedule()
- * Another possible reason may be the missing volatile in the original
- * code. readl() does this for us.
- */
-	printk("");	/* Hack! Doesn't work without this !!!??? */
-#endif
 	if(sig == SIGNATURE)
 		return PRI_BOARD;
 
@@ -532,13 +523,10 @@ int identify_board(unsigned long rambase, unsigned int iobase)
 	 * Try to identify a PRI card
 	 */
 	outb(BRI_BASEPG_VAL, pgport);
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout(HZ);
 	sig = readl(rambase + SIG_OFFSET);
 	pr_debug("Looking for a signature, got 0x%x\n", sig);
-#if 0
-	printk("");	/* Hack! Doesn't work without this !!!??? */
-#endif
 	if(sig == SIGNATURE)
 		return BRI_BOARD;
 
@@ -567,7 +555,7 @@ int identify_board(unsigned long rambase, unsigned int iobase)
 	 */
 	x = 0;
 	while((inb(iobase + FIFOSTAT_OFFSET) & RF_HAS_DATA) && x < 100) {
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(1);
 		x++;
 	}
diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c
index 9915cb0d8cacc07ae974159596312f9d37f195d4..141d5254dbeae762a66777cd785a9b9d2eafad5e 100644
--- a/drivers/isdn/sc/ioctl.c
+++ b/drivers/isdn/sc/ioctl.c
@@ -15,9 +15,6 @@ extern int send_and_receive(int, unsigned int, unsigned char,unsigned char,
 
 extern board *adapter[];
 
-#if 0
-static char *ChannelStates[] = { "Idle", "Ready", "Connecting", "Connected", "Disconnecting" };
-#endif
 
 int GetStatus(int card, boardInfo *);
 
@@ -42,7 +39,7 @@ int sc_ioctl(int card, scs_ioctl *data)
 
 		pr_debug("%s: SCIOLOAD: ioctl received\n", adapter[card]->devicename);
 		if(adapter[card]->EngineUp) {
-			pr_debug("%s: SCIOCLOAD: Command Failed, LoadProc while engine running.\n",
+			pr_debug("%s: SCIOCLOAD: command failed, LoadProc while engine running.\n",
 				adapter[card]->devicename);
 			return -1;
 		}
@@ -56,12 +53,12 @@ int sc_ioctl(int card, scs_ioctl *data)
 		status = send_and_receive(card, CMPID, cmReqType2, cmReqClass0, cmReqLoadProc,
 				0, sizeof(srec), srec, &rcvmsg, SAR_TIMEOUT);
 		if(status) {
-			pr_debug("%s: SCIOCLOAD: Command Failed, status = %d\n", 
+			pr_debug("%s: SCIOCLOAD: command failed, status = %d\n", 
 				adapter[card]->devicename, status);
 			return -1;
 		}
 		else {
-			pr_debug("%s: SCIOCLOAD: Command Sucessful\n", adapter[card]->devicename);
+			pr_debug("%s: SCIOCLOAD: command successful\n", adapter[card]->devicename);
 			return 0;
 		}
 	}
@@ -70,7 +67,7 @@ int sc_ioctl(int card, scs_ioctl *data)
 	{
 		pr_debug("%s: SCIOSTART: ioctl received\n", adapter[card]->devicename);
 		if(adapter[card]->EngineUp) {
-			pr_debug("%s: SCIOCSTART: Command Failed, Engine already running.\n",
+			pr_debug("%s: SCIOCSTART: command failed, engine already running.\n",
 				adapter[card]->devicename);
 			return -1;
 		}
@@ -94,16 +91,16 @@ int sc_ioctl(int card, scs_ioctl *data)
 		if ((err = copy_from_user(&switchtype, (char *) data->dataptr, sizeof(char))))
 			return err;
 
-		pr_debug("%s: SCIOCSETSWITCH: Setting switch type to %d\n", adapter[card]->devicename,
+		pr_debug("%s: SCIOCSETSWITCH: setting switch type to %d\n", adapter[card]->devicename,
 			switchtype);
 		status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallSetSwitchType,
 						0, sizeof(char),&switchtype,&rcvmsg, SAR_TIMEOUT);
 		if(!status && !rcvmsg.rsp_status) {
-			pr_debug("%s: SCIOCSETSWITCH: Command Successful\n", adapter[card]->devicename);
+			pr_debug("%s: SCIOCSETSWITCH: command successful\n", adapter[card]->devicename);
 			return 0;
 		}
 		else {
-			pr_debug("%s: SCIOCSETSWITCH: Command Failed (status = %d)\n",
+			pr_debug("%s: SCIOCSETSWITCH: command failed (status = %d)\n",
 				adapter[card]->devicename, status);
 			return status;
 		}
@@ -123,10 +120,10 @@ int sc_ioctl(int card, scs_ioctl *data)
 		status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, 
 			ceReqCallGetSwitchType, 0, 0, 0, &rcvmsg, SAR_TIMEOUT);
 		if (!status && !rcvmsg.rsp_status) {
-			pr_debug("%s: SCIOCGETSWITCH: Command Sucessful\n", adapter[card]->devicename);
+			pr_debug("%s: SCIOCGETSWITCH: command successful\n", adapter[card]->devicename);
 		}
 		else {
-			pr_debug("%s: SCIOCGETSWITCH: Command Failed (status = %d)\n",
+			pr_debug("%s: SCIOCGETSWITCH: command failed (status = %d)\n",
 				adapter[card]->devicename, status);
 			return status;
 		}
@@ -156,10 +153,10 @@ int sc_ioctl(int card, scs_ioctl *data)
 		status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetSPID,
 					data->channel, 0, 0, &rcvmsg, SAR_TIMEOUT);
 		if (!status) {
-			pr_debug("%s: SCIOCGETSPID: Command Sucessful\n", adapter[card]->devicename);
+			pr_debug("%s: SCIOCGETSPID: command successful\n", adapter[card]->devicename);
 		}
 		else {
-			pr_debug("%s: SCIOCGETSPID: Command Failed (status = %d)\n",
+			pr_debug("%s: SCIOCGETSPID: command failed (status = %d)\n",
 				adapter[card]->devicename, status);
 			return status;
 		}
@@ -188,18 +185,18 @@ int sc_ioctl(int card, scs_ioctl *data)
 		if ((err = copy_from_user(spid, (char *) data->dataptr, sizeof(spid))))
 			return err;
 
-		pr_debug("%s: SCIOCSETSPID: Setting channel %d spid to %s\n", 
+		pr_debug("%s: SCIOCSETSPID: setting channel %d spid to %s\n", 
 			adapter[card]->devicename, data->channel, spid);
 		status = send_and_receive(card, CEPID, ceReqTypeCall, 
 			ceReqClass0, ceReqCallSetSPID, data->channel, 
 			strlen(spid), spid, &rcvmsg, SAR_TIMEOUT);
 		if(!status && !rcvmsg.rsp_status) {
-			pr_debug("%s: SCIOCSETSPID: Command Successful\n", 
+			pr_debug("%s: SCIOCSETSPID: command successful\n", 
 				adapter[card]->devicename);
 			return 0;
 		}
 		else {
-			pr_debug("%s: SCIOCSETSPID: Command Failed (status = %d)\n",
+			pr_debug("%s: SCIOCSETSPID: command failed (status = %d)\n",
 				adapter[card]->devicename, status);
 			return status;
 		}
@@ -219,10 +216,10 @@ int sc_ioctl(int card, scs_ioctl *data)
 		status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetMyNumber,
 					data->channel, 0, 0, &rcvmsg, SAR_TIMEOUT);
 		if (!status) {
-			pr_debug("%s: SCIOCGETDN: Command Sucessful\n", adapter[card]->devicename);
+			pr_debug("%s: SCIOCGETDN: command successful\n", adapter[card]->devicename);
 		}
 		else {
-			pr_debug("%s: SCIOCGETDN: Command Failed (status = %d)\n",
+			pr_debug("%s: SCIOCGETDN: command failed (status = %d)\n",
 				adapter[card]->devicename, status);
 			return status;
 		}
@@ -252,18 +249,18 @@ int sc_ioctl(int card, scs_ioctl *data)
 		if ((err = copy_from_user(dn, (char *) data->dataptr, sizeof(dn))))
 			return err;
 
-		pr_debug("%s: SCIOCSETDN: Setting channel %d dn to %s\n", 
+		pr_debug("%s: SCIOCSETDN: setting channel %d dn to %s\n", 
 			adapter[card]->devicename, data->channel, dn);
 		status = send_and_receive(card, CEPID, ceReqTypeCall, 
 			ceReqClass0, ceReqCallSetMyNumber, data->channel, 
 			strlen(dn),dn,&rcvmsg, SAR_TIMEOUT);
 		if(!status && !rcvmsg.rsp_status) {
-			pr_debug("%s: SCIOCSETDN: Command Successful\n", 
+			pr_debug("%s: SCIOCSETDN: command successful\n", 
 				adapter[card]->devicename);
 			return 0;
 		}
 		else {
-			pr_debug("%s: SCIOCSETDN: Command Failed (status = %d)\n",
+			pr_debug("%s: SCIOCSETDN: command failed (status = %d)\n",
 				adapter[card]->devicename, status);
 			return status;
 		}
@@ -273,7 +270,7 @@ int sc_ioctl(int card, scs_ioctl *data)
 
 		pr_debug("%s: SCIOTRACE: ioctl received\n", adapter[card]->devicename);
 /*		adapter[card]->trace = !adapter[card]->trace; 
-		pr_debug("%s: SCIOCTRACE: Tracing turned %s\n", adapter[card]->devicename,
+		pr_debug("%s: SCIOCTRACE: tracing turned %s\n", adapter[card]->devicename,
 			adapter[card]->trace ? "ON" : "OFF"); */
 		break;
 
@@ -305,11 +302,11 @@ int sc_ioctl(int card, scs_ioctl *data)
 		status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, 
 			ceReqCallGetCallType, data->channel, 0, 0, &rcvmsg, SAR_TIMEOUT);
 		if (!status && !rcvmsg.rsp_status) {
-			pr_debug("%s: SCIOCGETSPEED: Command Sucessful\n",
+			pr_debug("%s: SCIOCGETSPEED: command successful\n",
 				adapter[card]->devicename);
 		}
 		else {
-			pr_debug("%s: SCIOCGETSPEED: Command Failed (status = %d)\n",
+			pr_debug("%s: SCIOCGETSPEED: command failed (status = %d)\n",
 				adapter[card]->devicename, status);
 			return status;
 		}
diff --git a/drivers/isdn/sc/message.c b/drivers/isdn/sc/message.c
index 4d4765f792470ad1e817c78095f586d9441df2c3..871a696434799daf6da206ed4af8f8a9fa6706ff 100644
--- a/drivers/isdn/sc/message.c
+++ b/drivers/isdn/sc/message.c
@@ -1,5 +1,5 @@
 /*
- *  $Id: message.c,v 1.4 1999/01/05 18:29:47 he Exp $
+ *  $Id: message.c,v 1.5 1999/09/04 06:20:07 keil Exp $
  *  Copyright (C) 1996  SpellCaster Telecommunications Inc.
  *
  *  message.c - functions for sending and receiving control messages
@@ -266,7 +266,7 @@ int send_and_receive(int card,
 	tries = 0;
 	/* wait for the response */
 	while (tries < timeout) {
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(1);
 		
 		pr_debug("SAR waiting..\n");
diff --git a/drivers/isdn/sc/packet.c b/drivers/isdn/sc/packet.c
index d75cb04d7f7b4fb43d11a57a68b1e50470d4ce7e..31e562c57b046e5470eed56d8bfeff74bef6584e 100644
--- a/drivers/isdn/sc/packet.c
+++ b/drivers/isdn/sc/packet.c
@@ -1,5 +1,5 @@
 /*
- *  $Id: packet.c,v 1.4 1998/02/12 23:08:50 keil Exp $
+ *  $Id: packet.c,v 1.5 1999/08/31 11:20:41 paul Exp $
  *  Copyright (C) 1996  SpellCaster Telecommunications Inc.
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -52,11 +52,11 @@ int sndpkt(int devId, int channel, struct sk_buff *data)
 	card = get_card_from_id(devId);
 
 	if(!IS_VALID_CARD(card)) {
-		pr_debug("Invalid param: %d is not a valid card id\n", card);
+		pr_debug("invalid param: %d is not a valid card id\n", card);
 		return -ENODEV;
 	}
 
-	pr_debug("%s: Send Packet: frst = 0x%x nxt = %d  f = %d n = %d\n",
+	pr_debug("%s: sndpkt: frst = 0x%x nxt = %d  f = %d n = %d\n",
 		adapter[card]->devicename,
 		adapter[card]->channel[channel].first_sendbuf,
 		adapter[card]->channel[channel].next_sendbuf,
@@ -64,26 +64,26 @@ int sndpkt(int devId, int channel, struct sk_buff *data)
 		adapter[card]->channel[channel].num_sendbufs);
 
 	if(!adapter[card]->channel[channel].free_sendbufs) {
-		pr_debug("%s: Out out TX buffers\n", adapter[card]->devicename);
+		pr_debug("%s: out of TX buffers\n", adapter[card]->devicename);
 		return -EINVAL;
 	}
 
 	if(data->len > BUFFER_SIZE) {
-		pr_debug("%s: Data overflows buffer size (data > buffer)\n", adapter[card]->devicename);
+		pr_debug("%s: data overflows buffer size (data > buffer)\n", adapter[card]->devicename);
 		return -EINVAL;
 	}
 
 	ReqLnkWrite.buff_offset = adapter[card]->channel[channel].next_sendbuf *
 		BUFFER_SIZE + adapter[card]->channel[channel].first_sendbuf;
 	ReqLnkWrite.msg_len = data->len; /* sk_buff size */
-	pr_debug("%s: Writing %d bytes to buffer offset 0x%x\n", adapter[card]->devicename,
+	pr_debug("%s: writing %d bytes to buffer offset 0x%x\n", adapter[card]->devicename,
 			ReqLnkWrite.msg_len, ReqLnkWrite.buff_offset);
 	memcpy_toshmem(card, (char *)ReqLnkWrite.buff_offset, data->data, ReqLnkWrite.msg_len);
 
 	/*
 	 * sendmessage
 	 */
-	pr_debug("%s: Send Packet size=%d, buf_offset=0x%x buf_indx=%d\n",
+	pr_debug("%s: sndpkt size=%d, buf_offset=0x%x buf_indx=%d\n",
 		adapter[card]->devicename,
 		ReqLnkWrite.msg_len, ReqLnkWrite.buff_offset,
 		adapter[card]->channel[channel].next_sendbuf);
@@ -92,7 +92,7 @@ int sndpkt(int devId, int channel, struct sk_buff *data)
 				channel+1, sizeof(LLData), (unsigned int*)&ReqLnkWrite);
 	len = data->len;
 	if(status) {
-		pr_debug("%s: Failed to send packet, status = %d\n", adapter[card]->devicename, status);
+		pr_debug("%s: failed to send packet, status = %d\n", adapter[card]->devicename, status);
 		return -1;
 	}
 	else {
@@ -101,7 +101,7 @@ int sndpkt(int devId, int channel, struct sk_buff *data)
 			++adapter[card]->channel[channel].next_sendbuf ==
 			adapter[card]->channel[channel].num_sendbufs ? 0 :
 			adapter[card]->channel[channel].next_sendbuf;
-			pr_debug("%s: Packet sent successfully\n", adapter[card]->devicename);
+			pr_debug("%s: packet sent successfully\n", adapter[card]->devicename);
 		dev_kfree_skb(data);
 		indicate_status(card,ISDN_STAT_BSENT,channel, (char *)&len);
 	}
@@ -114,7 +114,7 @@ void rcvpkt(int card, RspMessage *rcvmsg)
 	struct sk_buff *skb;
 
 	if(!IS_VALID_CARD(card)) {
-		pr_debug("Invalid param: %d is not a valid card id\n", card);
+		pr_debug("invalid param: %d is not a valid card id\n", card);
 		return;
 	}
 
@@ -122,7 +122,7 @@ void rcvpkt(int card, RspMessage *rcvmsg)
 	case 0x01:
 	case 0x02:
 	case 0x70:
-		pr_debug("%s: Error status code: 0x%x\n", adapter[card]->devicename, rcvmsg->rsp_status);
+		pr_debug("%s: error status code: 0x%x\n", adapter[card]->devicename, rcvmsg->rsp_status);
 		return;
 	case 0x00: 
 	    if (!(skb = dev_alloc_skb(rcvmsg->msg_data.response.msg_len))) {
@@ -144,7 +144,7 @@ void rcvpkt(int card, RspMessage *rcvmsg)
 		/*
 	 	 * Recycle the buffer
 	 	 */
-		pr_debug("%s: Buffer size : %d\n", adapter[card]->devicename, BUFFER_SIZE);
+		pr_debug("%s: buffer size : %d\n", adapter[card]->devicename, BUFFER_SIZE);
 /*		memset_shmem(card, rcvmsg->msg_data.response.buff_offset, 0, BUFFER_SIZE); */
 		newll.buff_offset = rcvmsg->msg_data.response.buff_offset;
 		newll.msg_len = BUFFER_SIZE;
@@ -163,30 +163,30 @@ int setup_buffers(int card, int c)
 	LLData	RcvBuffOffset;
 
 	if(!IS_VALID_CARD(card)) {
-		pr_debug("Invalid param: %d is not a valid card id\n", card);
+		pr_debug("invalid param: %d is not a valid card id\n", card);
 		return -ENODEV;
 	}
 
 	/*
 	 * Calculate the buffer offsets (send/recv/send/recv)
 	 */
-	pr_debug("%s: Seting up channel buffer space in shared RAM\n", adapter[card]->devicename);
+	pr_debug("%s: setting up channel buffer space in shared RAM\n", adapter[card]->devicename);
 	buffer_size = BUFFER_SIZE;
 	nBuffers = ((adapter[card]->ramsize - BUFFER_BASE) / buffer_size) / 2;
 	nBuffers = nBuffers > BUFFERS_MAX ? BUFFERS_MAX : nBuffers;
-	pr_debug("%s: Calculating buffer space: %d buffers, %d big\n", adapter[card]->devicename,
+	pr_debug("%s: calculating buffer space: %d buffers, %d big\n", adapter[card]->devicename,
 		nBuffers, buffer_size);
 	if(nBuffers < 2) {
-		pr_debug("%s: Not enough buffer space\n", adapter[card]->devicename);
+		pr_debug("%s: not enough buffer space\n", adapter[card]->devicename);
 		return -1;
 	}
 	cBase = (nBuffers * buffer_size) * (c - 1);
-	pr_debug("%s: Channel buffer offset from Shared RAM: 0x%x\n", adapter[card]->devicename, cBase);
+	pr_debug("%s: channel buffer offset from shared RAM: 0x%x\n", adapter[card]->devicename, cBase);
 	adapter[card]->channel[c-1].first_sendbuf = BUFFER_BASE + cBase;
 	adapter[card]->channel[c-1].num_sendbufs = nBuffers / 2;
 	adapter[card]->channel[c-1].free_sendbufs = nBuffers / 2;
 	adapter[card]->channel[c-1].next_sendbuf = 0;
-	pr_debug("%s: Send buffer setup complete: first=0x%x n=%d f=%d, nxt=%d\n",
+	pr_debug("%s: send buffer setup complete: first=0x%x n=%d f=%d, nxt=%d\n",
 				adapter[card]->devicename,
 				adapter[card]->channel[c-1].first_sendbuf,
 				adapter[card]->channel[c-1].num_sendbufs,
@@ -196,13 +196,13 @@ int setup_buffers(int card, int c)
 	/*
 	 * Prep the receive buffers
 	 */
-	pr_debug("%s: Adding %d RecvBuffers:\n", adapter[card]->devicename, nBuffers /2);
+	pr_debug("%s: adding %d RecvBuffers:\n", adapter[card]->devicename, nBuffers /2);
 	for (i = 0 ; i < nBuffers / 2; i++) {
 		RcvBuffOffset.buff_offset = 
 			((adapter[card]->channel[c-1].first_sendbuf +
 			(nBuffers / 2) * buffer_size) + (buffer_size * i));
 		RcvBuffOffset.msg_len = buffer_size;
-		pr_debug("%s: Adding RcvBuffer #%d offset=0x%x sz=%d buffsz:%d\n",
+		pr_debug("%s: adding RcvBuffer #%d offset=0x%x sz=%d bufsz:%d\n",
 				adapter[card]->devicename,
 				i + 1, RcvBuffOffset.buff_offset, 
 				RcvBuffOffset.msg_len,buffer_size);
diff --git a/drivers/misc/acpi.c b/drivers/misc/acpi.c
index 3538155a581582c2b295f40cf106ef6db26ca64d..3fd6bcc3c8ae4b67209627c63f3f8145a0e10998 100644
--- a/drivers/misc/acpi.c
+++ b/drivers/misc/acpi.c
@@ -917,7 +917,7 @@ static int __init acpi_init(void)
 			   acpi_irq,
 			   SA_INTERRUPT | SA_SHIRQ,
 			   "acpi",
-			   NULL)) {
+			   acpi_facp)) {
 		printk(KERN_ERR "ACPI: SCI (IRQ%d) allocation failed\n",
 		       acpi_facp->sci_int);
 		acpi_destroy_tables();
@@ -956,7 +956,7 @@ static void __exit acpi_exit(void)
 	acpi_release_ioports(acpi_facp);
 
 	if (acpi_facp->sci_int)
-		free_irq(acpi_facp->sci_int, NULL);
+		free_irq(acpi_facp->sci_int, acpi_facp);
 
 	acpi_destroy_tables();
 }
diff --git a/drivers/net/82596.c b/drivers/net/82596.c
index f3e1839041ebbf2471f49acc5f096f06a8873a42..0b8a9723b73cd3bacd176252e70e09dce6031e69 100644
--- a/drivers/net/82596.c
+++ b/drivers/net/82596.c
@@ -11,10 +11,15 @@
    by Richard Hirst <richard@sleepie.demon.co.uk>
    Renamed to be 82596.c
 
-   *** Untested on Apricot hardware, and may require some hacking
-   *** to make it work.  The old 82596.c reported hasn't worked
-   *** since 1.3.xx anyway.  I have been unable to find any users
-   *** of Apricot hardware to test this on.
+   980825:  Changed to receive directly in to sk_buffs which are
+   allocated at open() time.  Eliminates copy on incoming frames
+   (small ones are still copied).  Shared data now held in a
+   non-cached page, so we can run on 68060 in copyback mode.
+
+   TBD:
+   * look at deferring rx frames rather than discarding (as per tulip)
+   * handle tx ring full as per tulip
+   * performace test to tune rx_copybreak
 
    Most of my modifications relate to the braindead big-endian
    implementation by Intel.  When the i596 is operating in
@@ -57,12 +62,22 @@ static const char *version = "82596.c:v1.0 15/07/98\n";
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#include <asm/pgtable.h>	/*?? */
+#include <asm/pgtable.h>
+
+#if defined(CONFIG_MVME16x_NET) || defined(CONFIG_MVME16x_NET_MODULE)
+#define ENABLE_MVME16x_NET
+#endif
+#if defined(CONFIG_BVME6000_NET) || defined(CONFIG_BVME6000_NET_MODULE)
+#define ENABLE_BVME6000_NET
+#endif
+#if defined(CONFIG_APRICOT) || defined(CONFIG_APRICOT_MODULE)
+#define ENABLE_APRICOT
+#endif
 
-#ifdef CONFIG_MVME16x_NET
+#ifdef ENABLE_MVME16x_NET
 #include <asm/mvme16xhw.h>
 #endif
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
 #include <asm/bvme6000hw.h>
 #endif
 
@@ -83,11 +98,12 @@ static const char *version = "82596.c:v1.0 15/07/98\n";
 #define MACH_IS_APRICOT	0
 #else
 #define WSWAPrfd(x)	x
+#define WSWAPrbd(x)	((struct i596_rbd *)(x))
 #define WSWAPiscp(x)	((struct i596_iscp *)(x))
 #define WSWAPscb(x)	((struct i596_scb *)(x))
 #define WSWAPcmd(x)	x
 #define WSWAPtbd(x)	x
-#define WSWAPchar(x)	x
+#define WSWAPchar(x)	((char *)(x))
 #define ISCP_BUSY	0x0001
 #define MACH_IS_APRICOT	1
 #endif
@@ -103,19 +119,22 @@ static const char *version = "82596.c:v1.0 15/07/98\n";
 #define PORT_ALTSCP		0x02	/* alternate SCB address */
 #define PORT_ALTDUMP		0x03	/* Alternate DUMP address */
 
-#ifndef HAVE_ALLOC_SKB
-#define alloc_skb(size, priority) (struct sk_buff *) kmalloc(size,priority)
-#define kfree_skbmem(buff, size) kfree_s(buff,size)
-#endif
+#define I82596_DEBUG 1
 
-#define APRICOT_DEBUG 2
-
-#ifdef APRICOT_DEBUG
-int i596_debug = APRICOT_DEBUG;
+#ifdef I82596_DEBUG
+int i596_debug = I82596_DEBUG;
 #else
 int i596_debug = 1;
 #endif
 
+/* Copy frames shorter than rx_copybreak, otherwise pass on up in
+ * a full sized sk_buff.  Value of 100 stolen from tulip.c (!alpha).
+ */
+static int rx_copybreak = 100;
+
+#define PKT_BUF_SZ	1536
+#define MAX_MC_CNT	64
+
 #define I596_TOTAL_SIZE 17
 
 #define I596_NULL -1
@@ -179,12 +198,22 @@ struct i596_rfd {
 	unsigned short stat;
 	unsigned short cmd;
 	struct i596_rfd *next;
-	long rbd;
+	struct i596_rbd *rbd;
 	unsigned short count;
 	unsigned short size;
-	char data[1532];
 };
 
+struct i596_rbd {
+    unsigned short count;
+    unsigned short zero1;
+    struct i596_rbd *next;
+    char *data;
+    unsigned short size;
+    unsigned short zero2;
+    struct sk_buff *skb;
+};
+
+#define TX_RING_SIZE 16
 #define RX_RING_SIZE 16
 
 struct i596_scb {
@@ -222,6 +251,9 @@ struct i596_private {
 	struct i596_cmd set_conf;
 	char i596_config[16];
 	struct i596_cmd tdr;
+	struct i596_cmd mc_cmd;		/* Keep these three together!!! */
+	short mc_cnt;			/* Keep these three together!!! */
+	char mc_addrs[MAX_MC_CNT*6];	/* Keep these three together!!! */
 	unsigned long stat;
 	int last_restart __attribute__((aligned(4)));
 	struct i596_rfd *rx_tail;
@@ -230,6 +262,11 @@ struct i596_private {
 	int cmd_backlog;
 	unsigned long last_cmd;
 	struct net_device_stats stats;
+	struct i596_rfd rfds[RX_RING_SIZE];
+	struct i596_rbd rbds[RX_RING_SIZE];
+	struct tx_cmd tx_cmds[TX_RING_SIZE];
+	struct i596_tbd tbds[TX_RING_SIZE];
+	int next_tx_cmd;
 };
 
 char init_setup[] =
@@ -262,23 +299,24 @@ static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
 static void print_eth(char *);
 static void set_multicast_list(struct net_device *dev);
 
+static int rx_ring_size = RX_RING_SIZE;
 static int ticks_limit = 25;
 static int max_cmd_backlog = 16;
 
 
 static inline void CA(struct net_device *dev)
 {
-#ifdef CONFIG_MVME16x_NET
+#ifdef ENABLE_MVME16x_NET
 	if (MACH_IS_MVME16x) {
 		((struct i596_reg *) dev->base_addr)->ca = 1;
 	}
 #endif
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
 	if (MACH_IS_BVME6000) {
 		volatile u32 i = *(volatile u32 *) (dev->base_addr);
 	}
 #endif
-#ifdef CONFIG_APRICOT_i596
+#ifdef ENABLE_APRICOT
 	if (MACH_IS_APRICOT) {
 		outw(0, (short) (dev->base_addr) + 4);
 	}
@@ -288,14 +326,14 @@ static inline void CA(struct net_device *dev)
 
 static inline void MPU_PORT(struct net_device *dev, int c, volatile void *x)
 {
-#ifdef CONFIG_MVME16x_NET
+#ifdef ENABLE_MVME16x_NET
 	if (MACH_IS_MVME16x) {
 		struct i596_reg *p = (struct i596_reg *) (dev->base_addr);
 		p->porthi = ((c) | (u32) (x)) & 0xffff;
 		p->portlo = ((c) | (u32) (x)) >> 16;
 	}
 #endif
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
 	if (MACH_IS_BVME6000) {
 		u32 v = (u32) (c) | (u32) (x);
 		v = ((u32) (v) << 16) | ((u32) (v) >> 16);
@@ -307,7 +345,7 @@ static inline void MPU_PORT(struct net_device *dev, int c, volatile void *x)
 }
 
 
-#if defined(CONFIG_MVME16x_NET) || defined(CONFIG_BVME6000_NET)
+#if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET)
 static void i596_error(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_id;
@@ -333,77 +371,88 @@ static void i596_error(int irq, void *dev_id, struct pt_regs *regs)
 }
 #endif
 
-static inline int init_rx_bufs(struct net_device *dev, int num)
+static inline void init_rx_bufs(struct net_device *dev)
 {
-	struct i596_private *lp = (struct i596_private *) dev->priv;
+	struct i596_private *lp = (struct i596_private *)dev->priv;
 	int i;
 	struct i596_rfd *rfd;
-
-	lp->scb.rfd = (struct i596_rfd *) I596_NULL;
+	struct i596_rbd *rbd;
 
 	if (i596_debug > 1)
-		printk("%s: init_rx_bufs %d.\n", dev->name, num);
+		printk ("%s: init_rx_bufs %d.\n", dev->name, rx_ring_size);
 
-	for (i = 0; i < num; i++) {
-		if (!(rfd = (struct i596_rfd *) kmalloc(sizeof(struct i596_rfd), GFP_KERNEL)))
-			 break;
+	/* First build the Receive Buffer Descriptor List */
 
-		rfd->stat = 0x0000;
-		rfd->rbd = I596_NULL;
-		rfd->count = 0;
-		rfd->size = 1532;
-		if (i == 0) {
-			rfd->cmd = CMD_EOL;
-			lp->rx_tail = rfd;
-		} else
-			rfd->cmd = 0x0000;
-
-		rfd->next = lp->scb.rfd;
-		lp->scb.rfd = WSWAPrfd(rfd);
+	for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
+		struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ);
+
+		if (skb == NULL)
+			panic("82596: alloc_skb() failed");
+		skb->dev = dev;
+		rbd->next = WSWAPrbd(rbd+1);
+		rbd->skb = skb;
+		rbd->data = WSWAPchar(skb->tail);
+		rbd->size = PKT_BUF_SZ;
+#ifdef __mc68000__
+		cache_clear(virt_to_phys(skb->tail), PKT_BUF_SZ);
+#endif
 	}
+	lp->rbds[rx_ring_size-1].next = WSWAPrbd(lp->rbds);
 
-	if (i != 0)
-		lp->rx_tail->next = lp->scb.rfd;
+	/* Now build the Receive Frame Descriptor List */
 
-	return (i);
+	for (i = 0, rfd = lp->rfds; i < rx_ring_size; i++, rfd++) {
+		rfd->rbd = (struct i596_rbd *)I596_NULL;
+		rfd->next = WSWAPrfd(rfd+1);
+		rfd->cmd = CMD_FLEX;
+	}
+	lp->scb.rfd = WSWAPrfd(lp->rfds);
+	lp->rfds[0].rbd = WSWAPrbd(lp->rbds);
+	rfd = lp->rfds + rx_ring_size - 1;
+	lp->rx_tail = rfd;
+	rfd->next = WSWAPrfd(lp->rfds);
+	rfd->cmd = CMD_EOL|CMD_FLEX;
 }
 
 static inline void remove_rx_bufs(struct net_device *dev)
 {
-	struct i596_private *lp = (struct i596_private *) dev->priv;
-	struct i596_rfd *rfd = WSWAPrfd(lp->scb.rfd);
-
-	lp->rx_tail->next = (struct i596_rfd *) I596_NULL;
+	struct i596_private *lp = (struct i596_private *)dev->priv;
+	struct i596_rbd *rbd;
+	int i;
 
-	do {
-		lp->scb.rfd = rfd->next;
-		kfree(rfd);
-		rfd = WSWAPrfd(lp->scb.rfd);
+	for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
+		if (rbd->skb == NULL)
+			break;
+		dev_kfree_skb(rbd->skb);
 	}
-	while (rfd != lp->rx_tail);
 }
 
 static inline void init_i596_mem(struct net_device *dev)
 {
 	struct i596_private *lp = (struct i596_private *) dev->priv;
-#if !defined(CONFIG_MVME16x_NET) && !defined(CONFIG_BVME6000_NET)
+#if !defined(ENABLE_MVME16x_NET) && !defined(ENABLE_BVME6000_NET)
 	short ioaddr = dev->base_addr;
 #endif
 	int boguscnt = 100000;
 	unsigned long flags;
+	int i;
 
-#if defined(CONFIG_MVME16x_NET) || defined(CONFIG_BVME6000_NET)
-#ifdef CONFIG_MVME16x_NET
+#if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET)
+#ifdef ENABLE_MVME16x_NET
 	if (MACH_IS_MVME16x) {
 		volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
 
 		/* Disable all ints for now */
 		pcc2[0x28] = 1;
 		pcc2[0x2a] = 0x40;
-		pcc2[0x2b] = 0x40;	/* Set snooping bits now! */
+		/* Following disables snooping.  Snooping is not required
+		 * as we make appropriate use of non-cached pages for
+		 * shared data, and cache_push/cache_clear.
+		 */
+		pcc2[0x2b] = 0x00;
 	}
 #endif
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
 	if (MACH_IS_BVME6000) {
 		volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG;
 
@@ -419,7 +468,7 @@ static inline void init_i596_mem(struct net_device *dev)
 
 	MPU_PORT(dev, PORT_ALTSCP, &lp->scp);
 
-#else
+#elif defined(ENABLE_APRICOT)
 
 	/* change the scp address */
 	outw(0, ioaddr);
@@ -431,15 +480,15 @@ static inline void init_i596_mem(struct net_device *dev)
 
 	lp->last_cmd = jiffies;
 
-#ifdef CONFIG_MVME16x_NET
+#ifdef ENABLE_MVME16x_NET
 	if (MACH_IS_MVME16x)
 		lp->scp.sysbus = 0x00000054;
 #endif
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
 	if (MACH_IS_BVME6000)
 		lp->scp.sysbus = 0x0000004c;
 #endif
-#ifdef CONFIG_APRICOT_i596
+#ifdef ENABLE_APRICOT
 	if (MACH_IS_APRICOT)
 		lp->scp.sysbus = 0x00440000;
 #endif
@@ -454,7 +503,7 @@ static inline void init_i596_mem(struct net_device *dev)
 	if (i596_debug > 1)
 		printk("%s: starting i82596.\n", dev->name);
 
-#if !defined(CONFIG_MVME16x_NET) && !defined(CONFIG_BVME6000_NET)
+#if defined(ENABLE_APRICOT)
 	(void) inb(ioaddr + 0x10);
 	outb(4, ioaddr + 0xf);
 #endif
@@ -466,9 +515,22 @@ static inline void init_i596_mem(struct net_device *dev)
 			     dev->name, lp->scb.status, lp->scb.command);
 			break;
 		}
+
+	/* Ensure rx frame/buffer descriptors are tidy */
+	/* Bit naff doing this here as well as in init_rx_bufs() */
+
+	for (i = 0; i < rx_ring_size; i++) {
+		lp->rfds[i].rbd = (struct i596_rbd *)I596_NULL;
+		lp->rfds[i].cmd = CMD_FLEX;
+	}
+	lp->rfds[rx_ring_size-1].cmd = CMD_EOL|CMD_FLEX;
+	lp->scb.rfd = WSWAPrfd(lp->rfds);
+	lp->rfds[0].rbd = WSWAPrbd(lp->rbds);
+	lp->rx_tail = lp->rfds + rx_ring_size - 1;
+
 	lp->scb.command = 0;
 
-#ifdef CONFIG_MVME16x_NET
+#ifdef ENABLE_MVME16x_NET
 	if (MACH_IS_MVME16x) {
 		volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
 
@@ -478,7 +540,7 @@ static inline void init_i596_mem(struct net_device *dev)
 		pcc2[0x2b] = 0x55;
 	}
 #endif
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
 	if (MACH_IS_BVME6000) {
 		volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG;
 
@@ -525,38 +587,88 @@ static inline void init_i596_mem(struct net_device *dev)
 
 static inline int i596_rx(struct net_device *dev)
 {
-	struct i596_private *lp = (struct i596_private *) dev->priv;
+	struct i596_private *lp = (struct i596_private *)dev->priv;
 	struct i596_rfd *rfd;
+	struct i596_rbd *rbd;
 	int frames = 0;
 
 	if (i596_debug > 3)
-		printk("i596_rx()\n");
+		printk ("i596_rx()\n");
 
-	rfd = WSWAPrfd(lp->scb.rfd);	/* Reference next frame descriptor to check */
+	rfd = WSWAPrfd(lp->scb.rfd);		/* Ref next frame to check */
 
-	while ((rfd->stat) & STAT_C) {	/* Loop while we have complete frames */
-		if (i596_debug > 2)
-			print_eth(rfd->data);
+	while ((rfd->stat) & STAT_C) {		/* Loop while complete frames */
+		rbd = WSWAPrbd(rfd->rbd);       /* Ref associated buffer desc */
+
+		if (i596_debug >2)
+			print_eth(WSWAPchar(rbd->data));
 
 		if ((rfd->stat) & STAT_OK) {
 			/* a good frame */
-			int pkt_len = rfd->count & 0x3fff;
-			struct sk_buff *skb = dev_alloc_skb(pkt_len);
+			int pkt_len = rbd->count & 0x3fff;
+			struct sk_buff *skb = rbd->skb;
+			int rx_in_place = 0;
 
 			frames++;
 
+			/* Check if the packet is long enough to just accept
+			 * without copying to a properly sized skbuff.
+			 */
+
+			if (pkt_len > rx_copybreak) {
+				struct sk_buff *newskb;
+				char *temp;
+
+				/* Get fresh skbuff to replace filled one. */
+				newskb = dev_alloc_skb(PKT_BUF_SZ);
+				if (newskb == NULL) {
+					skb = NULL;	/* drop pkt */
+					goto memory_squeeze;
+				}
+				/* Pass up the skb already on the Rx ring. */
+				temp = skb_put(skb, pkt_len);
+				if (WSWAPchar(rbd->data) != temp)
+					printk(KERN_ERR "%s: Internal consistency error "
+						"-- the skbuff addresses do not match"
+						" in i596_rx: %p vs. %p / %p.\n", dev->name,
+						WSWAPchar(rbd->data),
+						skb->head, temp);
+				rx_in_place = 1;
+				rbd->skb = newskb;
+				newskb->dev = dev;
+				rbd->data = WSWAPchar(newskb->tail);
+#ifdef __mc68000__
+				cache_clear(virt_to_phys(newskb->tail), PKT_BUF_SZ);
+#endif
+			}
+			else
+				skb = dev_alloc_skb(pkt_len + 2);
+memory_squeeze:
 			if (skb == NULL) {
-				printk("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name);
+				/* XXX tulip.c can defer packets here!! */
+				printk ("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name);
 				lp->stats.rx_dropped++;
-			} else {
+			}
+			else {
 				skb->dev = dev;
-				memcpy(skb_put(skb, pkt_len), rfd->data, pkt_len);
-				skb->protocol = eth_type_trans(skb, dev);
+				if (!rx_in_place) {
+					/* 16 byte align the data fields */
+					skb_reserve(skb, 2);
+					memcpy(skb_put(skb,pkt_len),
+						WSWAPchar(rbd->data), pkt_len);
+				}
+				skb->protocol=eth_type_trans(skb,dev);
+				skb->len = pkt_len;
+#ifdef __mc68000__
+				cache_clear(virt_to_phys(rbd->skb->tail),
+						pkt_len);
+#endif
 				netif_rx(skb);
 				lp->stats.rx_packets++;
-				lp->stats.rx_bytes += pkt_len;
+				lp->stats.rx_bytes+=pkt_len;
 			}
-		} else {
+		}
+		else {
 			lp->stats.rx_errors++;
 			if ((rfd->stat) & 0x0001)
 				lp->stats.collisions++;
@@ -576,21 +688,40 @@ static inline int i596_rx(struct net_device *dev)
 
 		/* Clear the buffer descriptor count and EOF + F flags */
 
+		if (rbd != (struct i596_rbd *)I596_NULL)
+			rbd->count=0;
+		else
+			printk("%s: Null rbd - oops!\n", dev->name);
+
+		/* Tidy the frame descriptor, marking it as end of list */
+
+		rfd->rbd = (struct i596_rbd *)I596_NULL;
 		rfd->stat = 0;
+		rfd->cmd = CMD_EOL|CMD_FLEX;
 		rfd->count = 0;
-		rfd->cmd = CMD_EOL;
-		lp->rx_tail->cmd = 0;
+
+		/* Remove end-of-list from old end descriptor */
+
+		lp->rx_tail->cmd = CMD_FLEX;
+
+		/* Update last frame descriptor to reference the one just
+		 * processed */
+
 		lp->rx_tail = rfd;
+
+		/* Update record of next frame descriptor to process */
+
 		lp->scb.rfd = rfd->next;
-		rfd = WSWAPrfd(lp->scb.rfd);	/* Next frame descriptor to check */
+		rfd = WSWAPrfd(lp->scb.rfd);	/* Next frame desc. to check */
 	}
 
 	if (i596_debug > 3)
-		printk("frames %d\n", frames);
+		printk ("frames %d\n", frames);
 
 	return 0;
 }
 
+
 static inline void i596_cleanup_cmd(struct i596_private *lp)
 {
 	struct i596_cmd *ptr;
@@ -617,13 +748,12 @@ static inline void i596_cleanup_cmd(struct i596_private *lp)
 				lp->stats.tx_aborted_errors++;
 
 				ptr->next = (struct i596_cmd *) I596_NULL;
-				kfree(tx_cmd);
+				tx_cmd->cmd.command = 0;  /* Mark as free */
 				break;
 			}
 		case CmdMulticastList:
 			{
 				ptr->next = (struct i596_cmd *) I596_NULL;
-				kfree(ptr);
 				break;
 			}
 		default:
@@ -743,26 +873,19 @@ static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
 
 static int i596_open(struct net_device *dev)
 {
-	int i;
-
 	if (i596_debug > 1)
 		printk("%s: i596_open() irq %d.\n", dev->name, dev->irq);
 
-	if (request_irq(dev->irq, &i596_interrupt, 0, "apricot", dev))
+	if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev))
 		return -EAGAIN;
-#ifdef CONFIG_MVME16x_NET
+#ifdef ENABLE_MVME16x_NET
 	if (MACH_IS_MVME16x) {
-		if (request_irq(0x56, &i596_error, 0, "apricot_error", dev))
+		if (request_irq(0x56, &i596_error, 0, "i82596_error", dev))
 			return -EAGAIN;
 	}
 #endif
-	if ((i = init_rx_bufs(dev, RX_RING_SIZE)) < RX_RING_SIZE)
-		printk("%s: only able to allocate %d receive buffers\n", dev->name, i);
+	init_rx_bufs(dev);
 
-	if (i < 4) {
-		free_irq(dev->irq, dev);
-		return -EAGAIN;
-	}
 	dev->tbusy = 0;
 	dev->interrupt = 0;
 	dev->start = 1;
@@ -779,6 +902,7 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct i596_private *lp = (struct i596_private *) dev->priv;
 	int ioaddr = dev->base_addr;
 	struct tx_cmd *tx_cmd;
+	struct i596_tbd *tbd;
 
 	if (i596_debug > 2)
 		printk("%s: 82596 start xmit\n", dev->name);
@@ -810,7 +934,8 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		dev->trans_start = jiffies;
 	}
 	if (i596_debug > 3)
-		printk("%s: i596_start_xmit() called\n", dev->name);
+		printk("%s: i596_start_xmit(%x,%x) called\n", dev->name,
+				skb->len, (unsigned int)skb->data);
 
 	/* Block a timer-based transmit from overlapping.  This could better be
 	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
@@ -820,14 +945,18 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 		dev->trans_start = jiffies;
 
-		tx_cmd = (struct tx_cmd *) kmalloc((sizeof(struct tx_cmd) + sizeof(struct i596_tbd)), GFP_ATOMIC);
-		if (tx_cmd == NULL) {
-			printk("%s: i596_xmit Memory squeeze, dropping packet.\n", dev->name);
+		tx_cmd = lp->tx_cmds + lp->next_tx_cmd;
+		tbd = lp->tbds + lp->next_tx_cmd;
+
+		if (tx_cmd->cmd.command) {
+			printk ("%s: xmit ring full, dropping packet.\n",
+					dev->name);
 			lp->stats.tx_dropped++;
 
 			dev_kfree_skb(skb);
 		} else {
-			struct i596_tbd *tbd = (struct i596_tbd *) (tx_cmd + 1);
+			if (++lp->next_tx_cmd == TX_RING_SIZE)
+				lp->next_tx_cmd = 0;
 			tx_cmd->tbd = WSWAPtbd(tbd);
 			tbd->next = (struct i596_tbd *) I596_NULL;
 
@@ -841,6 +970,9 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 			tbd->data = WSWAPchar(skb->data);
 
+#ifdef __mc68000__
+			cache_push(virt_to_phys(skb->data), length);
+#endif
 			if (i596_debug > 3)
 				print_eth(skb->data);
 			i596_add_cmd(dev, (struct i596_cmd *) tx_cmd);
@@ -854,7 +986,6 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	return 0;
 }
-
 
 static void print_eth(char *add)
 {
@@ -879,14 +1010,15 @@ int __init i82596_probe(struct net_device *dev)
 	struct i596_private *lp;
 	char eth_addr[6];
 
-#ifdef CONFIG_MVME16x_NET
+#ifdef ENABLE_MVME16x_NET
 	if (MACH_IS_MVME16x) {
 		static int probed = 0;
-
+#ifdef XXX_FIXME
 		if (mvme16x_config & MVME16x_CONFIG_NO_ETHERNET) {
 			printk("Ethernet probe disabled - chip not present\n");
 			return ENODEV;
 		}
+#endif
 		if (probed)
 			return ENODEV;
 		probed++;
@@ -895,7 +1027,7 @@ int __init i82596_probe(struct net_device *dev)
 		dev->irq = (unsigned) MVME16x_IRQ_I596;
 	}
 #endif
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
 	if (MACH_IS_BVME6000) {
 		volatile unsigned char *rtc = (unsigned char *) BVME_RTC_BASE;
 		unsigned char msr = rtc[3];
@@ -909,7 +1041,7 @@ int __init i82596_probe(struct net_device *dev)
 		dev->irq = (unsigned) BVME_IRQ_I596;
 	}
 #endif
-#ifdef CONFIG_APRICOT_INTEL
+#ifdef ENABLE_APRICOT
 	int checksum = 0;
 	int ioaddr = 0x300;
 
@@ -953,22 +1085,28 @@ int __init i82596_probe(struct net_device *dev)
 	if (i596_debug > 0)
 		printk(version);
 
-	/* The APRICOT-specific entries in the device structure. */
+	/* The 82596-specific entries in the device structure. */
 	dev->open = &i596_open;
 	dev->stop = &i596_close;
 	dev->hard_start_xmit = &i596_start_xmit;
 	dev->get_stats = &i596_get_stats;
 	dev->set_multicast_list = &set_multicast_list;
 
-	dev->mem_start = (int) kmalloc(sizeof(struct i596_private) + 0x0f, GFP_KERNEL);
-	/* align for scp */
-	dev->priv = (void *) ((dev->mem_start + 0xf) & 0xfffffff0);
+	dev->mem_start = (int)__get_free_pages(GFP_ATOMIC, 0);
+	dev->priv = (void *)(dev->mem_start);
 
 	lp = (struct i596_private *) dev->priv;
 	if (i596_debug)
-		printk("%s: lp at 0x%08lx, lp->scb at 0x%08lx\n"
-		,dev->name, (unsigned long) lp, (unsigned long) &lp->scb);
+		printk ("%s: lp at 0x%08lx (%d bytes), lp->scb at 0x%08lx\n",
+			dev->name, (unsigned long)lp,
+			sizeof(struct i596_private), (unsigned long)&lp->scb);
 	memset((void *) lp, 0, sizeof(struct i596_private));
+
+#ifdef __mc68000__
+	cache_push(virt_to_phys((void *)(dev->mem_start)), 4096);
+	cache_clear(virt_to_phys((void *)(dev->mem_start)), 4096);
+	kernel_set_cachemode((void *)(dev->mem_start), 4096, IOMAP_NOCACHE_SER);
+#endif
 	lp->scb.command = 0;
 	lp->scb.cmd = (struct i596_cmd *) I596_NULL;
 	lp->scb.rfd = (struct i596_rfd *) I596_NULL;
@@ -984,7 +1122,7 @@ static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 	int boguscnt = 2000;
 	unsigned short status, ack_cmd = 0;
 
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
 	if (MACH_IS_BVME6000) {
 		if (*(char *) BVME_LOCAL_IRQ_STAT & BVME_ETHERR) {
 			i596_error(BVME_IRQ_I596, NULL, NULL);
@@ -1063,13 +1201,12 @@ static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 					dev_kfree_skb(skb);
 
 					ptr->next = (struct i596_cmd *) I596_NULL;
-					kfree(tx_cmd);
+					tx_cmd->cmd.command = 0; /* Mark free */
 					break;
 				}
 			case CmdMulticastList:
 				{
 					ptr->next = (struct i596_cmd *) I596_NULL;
-					kfree(ptr);
 					break;
 				}
 			case CmdTDR:
@@ -1141,7 +1278,7 @@ static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 		}
 	lp->scb.command = ack_cmd;
 
-#ifdef CONFIG_MVME16x_NET
+#ifdef ENABLE_MVME16x_NET
 	if (MACH_IS_MVME16x) {
 		/* Ack the interrupt */
 
@@ -1150,7 +1287,7 @@ static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 		pcc2[0x2a] |= 0x08;
 	}
 #endif
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
 	if (MACH_IS_BVME6000) {
 		volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG;
 
@@ -1158,7 +1295,7 @@ static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 		*ethirq = 3;
 	}
 #endif
-#ifdef CONFIG_APRICOT_INTEL
+#ifdef ENABLE_APRICOT
 	(void) inb(ioaddr + 0x10);
 	outb(4, ioaddr + 0xf);
 #endif
@@ -1208,7 +1345,7 @@ static int i596_close(struct net_device *dev)
 
 	i596_cleanup_cmd(lp);
 
-#ifdef CONFIG_MVME16x_NET
+#ifdef ENABLE_MVME16x_NET
 	if (MACH_IS_MVME16x) {
 		volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
 
@@ -1218,7 +1355,7 @@ static int i596_close(struct net_device *dev)
 		pcc2[0x2b] = 0x40;	/* Set snooping bits now! */
 	}
 #endif
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
 	if (MACH_IS_BVME6000) {
 		volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG;
 
@@ -1249,7 +1386,7 @@ static void set_multicast_list(struct net_device *dev)
 {
 	struct i596_private *lp = (struct i596_private *) dev->priv;
 	struct i596_cmd *cmd;
-	int config = 0;
+	int config = 0, cnt;
 
 	if (i596_debug > 1)
 		printk("%s: set multicast list, %d entries, promisc %s, allmulti %s\n", dev->name, dev->mc_count, dev->flags & IFF_PROMISC ? "ON" : "OFF", dev->flags & IFF_ALLMULTI ? "ON" : "OFF");
@@ -1279,18 +1416,24 @@ static void set_multicast_list(struct net_device *dev)
 			i596_add_cmd(dev, &lp->set_conf);
 		}
 	}
+
+	cnt = dev->mc_count;
+	if (cnt > MAX_MC_CNT)
+	{
+		cnt = MAX_MC_CNT;
+		printk("%s: Only %d multicast addresses supported",
+			dev->name, cnt);
+	}
+	
 	if (dev->mc_count > 0) {
 		struct dev_mc_list *dmi;
 		unsigned char *cp;
-		cmd = (struct i596_cmd *) kmalloc(sizeof(struct i596_cmd) + 2 + dev->mc_count * 6, GFP_ATOMIC);
-		if (cmd == NULL) {
-			printk("%s: set_multicast Memory squeeze.\n", dev->name);
-			return;
-		}
+
+		cmd = &lp->mc_cmd;
 		cmd->command = CmdMulticastList;
 		*((unsigned short *) (cmd + 1)) = dev->mc_count * 6;
 		cp = ((unsigned char *) (cmd + 1)) + 2;
-		for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) {
+		for(dmi=dev->mc_list;cnt && dmi!=NULL;dmi=dmi->next,cnt--) {
 			memcpy(cp, dmi->dmi_addr, 6);
 			if (i596_debug > 1)
 				printk("%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, *(cp + 0), *(cp + 1), *(cp + 2), *(cp + 3), *(cp + 4), *(cp + 5));
@@ -1306,40 +1449,58 @@ static void set_multicast_list(struct net_device *dev)
 static unsigned int i596_portlist[] __initdata =
 {0x300, 0};
 struct netdev_entry i596_drv =
-{"apricot", i82596_probe, I596_TOTAL_SIZE, apricot_portlist};
+{"i82596", i82596_probe, I596_TOTAL_SIZE, i596_portlist};
 #endif
 
 #ifdef MODULE
 static char devicename[9] =
 {0,};
-static struct net_device dev_apricot =
+static struct net_device dev_82596 =
 {
-	devicename,		/* device name inserted by /linux/drivers/net/net_init.c */
+	devicename,	/* device name inserted by drivers/net/net_init.c */
 	0, 0, 0, 0,
-	0x300, 10,
+	0, 0,		/* base, irq */
 	0, 0, 0, NULL, i82596_probe};
 
+#ifdef ENABLE_APRICOT
 static int io = 0x300;
 static int irq = 10;
 MODULE_PARM(irq, "i");
+#endif
+
+MODULE_PARM(debug, "i");
+static int debug = -1;
 
 int init_module(void)
 {
-	dev_apricot.base_addr = io;
-	dev_apricot.irq = irq;
-	if (register_netdev(&dev_apricot) != 0)
+#ifdef ENABLE_APRICOT
+	dev_82596.base_addr = io;
+	dev_82596.irq = irq;
+#endif
+	if (debug >= 0)
+		i596_debug = debug;
+	if (register_netdev(&dev_82596) != 0)
 		return -EIO;
 	return 0;
 }
 
 void cleanup_module(void)
 {
-	unregister_netdev(&dev_apricot);
-	kfree((void *) dev_apricot.mem_start);
-	dev_apricot.priv = NULL;
+	unregister_netdev(&dev_82596);
+#ifdef __mc68000__
+	/* XXX This assumes default cache mode to be IOMAP_FULL_CACHING,
+	 * XXX which may be invalid (CONFIG_060_WRITETHROUGH)
+	 */
 
+	kernel_set_cachemode((u32)(dev_82596.mem_start), 4096,
+			IOMAP_FULL_CACHING);
+#endif
+	free_page ((u32)(dev_82596.mem_start));
+	dev_82596.priv = NULL;
+#ifdef ENABLE_APRICOT
 	/* If we don't do this, we can't re-insmod it later. */
-	release_region(dev_apricot.base_addr, I596_TOTAL_SIZE);
+	release_region(dev_82596.base_addr, I596_TOTAL_SIZE);
+#endif
 }
 
 #endif				/* MODULE */
diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c
index ba7fc1610fced5bf5565ccf19fa4a5d79bf189e3..8db17e5c90d5413d5f70c977f1cc8b24aa1a95b2 100644
--- a/drivers/parport/ieee1284.c
+++ b/drivers/parport/ieee1284.c
@@ -80,19 +80,42 @@ int parport_wait_event (struct parport *port, signed long timeout)
  * are able to eat the time up to 40ms.
  */ 
 
+int parport_poll_peripheral(struct parport *port,
+			    unsigned char mask,
+			    unsigned char result,
+			    int usec)
+{
+	/* Zero return code is success, >0 is timeout. */
+	int counter = usec / 5;
+	unsigned char status;
+	for (; counter > 0; counter--) {
+		status = parport_read_status (port);
+		if ((status & mask) == result)
+			return 0;
+		if (signal_pending (current))
+			return -EINTR;
+		if (current->need_resched)
+			break;
+		udelay (5);
+	}
+
+	return 1;
+}
+
 int parport_wait_peripheral(struct parport *port,
 			    unsigned char mask, 
 			    unsigned char result)
 {
-	int counter;
+	int ret;
+	int usec;
 	long deadline;
 	unsigned char status;
 
-	counter = port->physport->spintime; /* usecs of fast polling */
+	usec = port->physport->spintime; /* usecs of fast polling */
 	if (!port->physport->cad->timeout)
 		/* A zero timeout is "special": busy wait for the
 		   entire 35ms. */
-		counter = 35000;
+		usec = 35000;
 
 	/* Fast polling.
 	 *
@@ -100,16 +123,9 @@ int parport_wait_peripheral(struct parport *port,
 	 * How about making a note (in the device structure) of how long
 	 * it takes, so we know for next time?
 	 */
-	for (counter /= 5; counter > 0; counter--) {
-		status = parport_read_status (port);
-		if ((status & mask) == result)
-			return 0;
-		if (signal_pending (current))
-			return -EINTR;
-		if (current->need_resched)
-			break;
-		udelay(5);
-	}
+	ret = parport_poll_peripheral (port, mask, result, usec);
+	if (ret != 1)
+		return ret;
 
 	if (!port->physport->cad->timeout)
 		/* We may be in an interrupt handler, so we can't poll
@@ -137,7 +153,7 @@ int parport_wait_peripheral(struct parport *port,
 			/* parport_wait_event didn't time out, but the
 			 * peripheral wasn't actually ready either.
 			 * Wait for another 10ms. */
-			current->state = TASK_INTERRUPTIBLE;
+			__set_current_state (TASK_INTERRUPTIBLE);
 			schedule_timeout ((HZ+ 99) / 100);
 		}
 	}
@@ -369,8 +385,17 @@ int parport_negotiate (struct parport *port, int mode)
 				      PARPORT_CONTROL_STROBE,
 				      PARPORT_CONTROL_STROBE);
 
+		/* Event 52: nAck goes low */
+		if (parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0)) {
+			/* This peripheral is _very_ slow. */
+			DPRINTK (KERN_DEBUG
+				 "%s: Event 52 didn't happen\n",
+				 port->name);
+			parport_ieee1284_terminate (port);
+			return 1;
+		}
+
 		/* Event 53: Set nStrobe high */
-		udelay (5);
 		parport_frob_control (port,
 				      PARPORT_CONTROL_STROBE,
 				      0);
diff --git a/drivers/parport/ieee1284_ops.c b/drivers/parport/ieee1284_ops.c
index 4d460a58d6f95fb9c8c35142e491f5f6289da4c5..3d77776b515d53cbd2f61c06f021f98dfea9d5f6 100644
--- a/drivers/parport/ieee1284_ops.c
+++ b/drivers/parport/ieee1284_ops.c
@@ -95,7 +95,7 @@ size_t parport_ieee1284_write_compat (struct parport *port,
                            our interrupt handler called. */
 			if (count && no_irq) {
 				parport_release (dev);
-				current->state = TASK_INTERRUPTIBLE;
+				set_current_state (TASK_INTERRUPTIBLE);
 				schedule_timeout (wait);
 				parport_claim_or_block (dev);
 			}
@@ -525,7 +525,7 @@ size_t parport_ieee1284_ecp_read_data (struct parport *port,
 			/* Yield the port for a while. */
 			if (count && dev->port->irq != PARPORT_IRQ_NONE) {
 				parport_release (dev);
-				current->state = TASK_INTERRUPTIBLE;
+				set_current_state (TASK_INTERRUPTIBLE);
 				schedule_timeout ((HZ + 24) / 25);
 				parport_claim_or_block (dev);
 			}
diff --git a/drivers/parport/init.c b/drivers/parport/init.c
index 432fede95faf8c1297de45571309494e51b882ce..b2f4d4b06c16dc7d553999c4011c697fd77af380 100644
--- a/drivers/parport/init.c
+++ b/drivers/parport/init.c
@@ -181,6 +181,7 @@ EXPORT_SYMBOL(parport_write);
 EXPORT_SYMBOL(parport_read);
 EXPORT_SYMBOL(parport_ieee1284_wakeup);
 EXPORT_SYMBOL(parport_wait_peripheral);
+EXPORT_SYMBOL(parport_poll_peripheral);
 EXPORT_SYMBOL(parport_wait_event);
 EXPORT_SYMBOL(parport_set_timeout);
 EXPORT_SYMBOL(parport_ieee1284_interrupt);
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 587a6a2b0bc74aa5e8867af5e040a9db4e0eddc1..72d8dc15203e819d247239c2e78921429f04b9b8 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -122,7 +122,7 @@ static int change_mode(struct parport *p, int m)
 				if (time_after_eq (jiffies, expire))
 					/* The FIFO is stuck. */
 					return -EBUSY;
-				current->state = TASK_INTERRUPTIBLE;
+				__set_current_state (TASK_INTERRUPTIBLE);
 				schedule_timeout ((HZ + 99) / 100);
 				if (signal_pending (current))
 					break;
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 0503f4af1caeb6875809a41b5c6af6b3959d6477..2913461938ad919650a28aaf75a46df48c877cfa 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -32,3 +32,11 @@ L_OBJS   += syscall.o setup.o
 endif
 
 include $(TOPDIR)/Rules.make
+
+names.o: names.c devlist.h
+
+devlist.h: pci.ids gen-devlist
+	./gen-devlist <pci.ids >devlist.h
+
+gen-devlist: gen-devlist.c
+	$(HOSTCC) $(HOSTCFLAGS) -o gen-devlist gen-devlist.c
diff --git a/drivers/pci/devlist.h b/drivers/pci/devlist.h
deleted file mode 100644
index f0482b7d3c3171a676912a4017f880ce76f633d1..0000000000000000000000000000000000000000
--- a/drivers/pci/devlist.h
+++ /dev/null
@@ -1,1016 +0,0 @@
-VENDOR( COMPAQ, "Compaq" )
-	DEVICE( COMPAQ,		COMPAQ_TOKENRING, "Token Ring 4/16")
-	DEVICE( COMPAQ,		COMPAQ_1280,	"QVision 1280/p")
-	DEVICE( COMPAQ,		COMPAQ_SMART2P,	"Smart-2/P RAID Controller")
-	DEVICE( COMPAQ,		COMPAQ_NETEL100,"Netelligent 10/100")
-	DEVICE( COMPAQ,		COMPAQ_NETEL10,	"Netelligent 10")
-	DEVICE( COMPAQ,		COMPAQ_NETFLEX3I,"NetFlex 3")
-	DEVICE( COMPAQ,		COMPAQ_NETEL100D,"Netelligent 10/100 Dual")
-	DEVICE( COMPAQ,		COMPAQ_NETEL100PI,"Netelligent 10/100 ProLiant")
-	DEVICE( COMPAQ,		COMPAQ_NETEL100I,"Netelligent 10/100 Integrated")
-	DEVICE( COMPAQ,		COMPAQ_THUNDER,	"ThunderLAN")
-	DEVICE( COMPAQ,		COMPAQ_NETFLEX3B,"NetFlex 3 BNC")
-ENDVENDOR()
-
-VENDOR( NCR, "NCR" )
-	DEVICE( NCR,		NCR_53C810,	"53c810")
-	DEVICE( NCR,		NCR_53C820,	"53c820")
-	DEVICE( NCR,		NCR_53C825,	"53c825")
-	DEVICE( NCR,		NCR_53C815,	"53c815")
-	DEVICE( NCR,		NCR_53C860,	"53c860")
-	DEVICE( NCR,		NCR_53C896,	"53c896")
-	DEVICE( NCR,		NCR_53C895,	"53c895")
-	DEVICE( NCR,		NCR_53C885,	"53c885")
-	DEVICE( NCR,		NCR_53C875,	"53c875")
-	DEVICE( NCR,		NCR_53C875J,	"53c875J")
-ENDVENDOR()
-
-VENDOR( ATI, "ATI" )
-	DEVICE( ATI,		ATI_68800,      "68800AX")
-	DEVICE( ATI,		ATI_215CT222,   "215CT222")
-	DEVICE( ATI,		ATI_210888CX,   "210888CX")
-	DEVICE( ATI,		ATI_215GB,	"Mach64 GB")
-	DEVICE( ATI,		ATI_215GD,	"Mach64 GD (Rage Pro)")
-	DEVICE( ATI,		ATI_215GI,	"Mach64 GI (Rage Pro)")
-	DEVICE( ATI,		ATI_215GP,	"Mach64 GP (Rage Pro)")
-	DEVICE( ATI,		ATI_215GQ,	"Mach64 GQ (Rage Pro)")
-	DEVICE( ATI,		ATI_215GT,	"Mach64 GT (Rage II)")
-	DEVICE( ATI,		ATI_215GTB,	"Mach64 GTB (Rage II)")
-	DEVICE( ATI,		ATI_210888GX,   "210888GX")
-	DEVICE( ATI,		ATI_215LG,	"Mach64 LG (Rage Pro)")
-	DEVICE( ATI,		ATI_264LT,	"Mach64 LT")
-	DEVICE( ATI,		ATI_264VT,	"Mach64 VT")
-ENDVENDOR()
-
-VENDOR( VLSI, "VLSI" )
-	DEVICE( VLSI,		VLSI_82C592,	"82C592-FC1")
-	DEVICE( VLSI,		VLSI_82C593,	"82C593-FC1")
-	DEVICE( VLSI,		VLSI_82C594,	"82C594-AFC2")
-	DEVICE( VLSI,		VLSI_82C597,	"82C597-AFC2")
-	DEVICE( VLSI,		VLSI_82C541,	"82C541 Lynx")
-	DEVICE( VLSI,		VLSI_82C543,	"82C543 Lynx ISA")
-	DEVICE( VLSI,		VLSI_82C532,	"82C532")
-	DEVICE( VLSI,		VLSI_82C534,	"82C534")
-	DEVICE( VLSI,		VLSI_82C535,	"82C535")
-	DEVICE( VLSI,		VLSI_82C147,	"82C147")
-	DEVICE( VLSI,		VLSI_VAS96011,	"VAS96011 (Golden Gate II)")
-ENDVENDOR()
-
-VENDOR( ADL, "Avance Logic" )
-	DEVICE( ADL,		ADL_2301,	"2301")
-ENDVENDOR()
-
-VENDOR( NS, "NS" )
-	DEVICE( NS,		NS_87415,	"87415")
-	DEVICE( NS,		NS_87410,	"87410")
-ENDVENDOR()
-
-VENDOR( TSENG, "Tseng'Lab" )
-	DEVICE( TSENG,		TSENG_W32P_2,	"ET4000W32P")
-	DEVICE( TSENG,		TSENG_W32P_b,	"ET4000W32P rev B")
-	DEVICE( TSENG,		TSENG_W32P_c,	"ET4000W32P rev C")
-	DEVICE( TSENG,		TSENG_W32P_d,	"ET4000W32P rev D")
-	DEVICE( TSENG,		TSENG_ET6000,	"ET6000")
-ENDVENDOR()
-
-VENDOR( WEITEK, "Weitek" )
-	DEVICE( WEITEK,		WEITEK_P9000,	"P9000")
-	DEVICE( WEITEK,		WEITEK_P9100,	"P9100")
-ENDVENDOR()
-
-VENDOR( DEC, "DEC" )
-	DEVICE( DEC,		DEC_BRD,	"DC21050")
-	DEVICE( DEC,		DEC_TULIP,	"DC21040")
-	DEVICE( DEC,		DEC_TGA,	"TGA")
-	DEVICE( DEC,		DEC_TULIP_FAST,	"DC21140")
-	DEVICE( DEC,		DEC_TGA2,	"TGA2")
-	DEVICE( DEC,		DEC_FDDI,	"DEFPA")
-	DEVICE( DEC,		DEC_TULIP_PLUS,	"DC21041")
-	DEVICE( DEC,		DEC_21142,	"DC21142")
-	DEVICE( DEC,		DEC_21052,	"DC21052")
-	DEVICE( DEC,		DEC_21150,	"DC21150")
-	DEVICE( DEC,		DEC_21152,	"DC21152")
-	DEVICE( DEC,		DEC_21153,	"DC21153")
-	DEVICE( DEC,		DEC_21154,	"DC21154")
-ENDVENDOR()
-
-VENDOR( CIRRUS, "Cirrus Logic" )
-	DEVICE( CIRRUS,		CIRRUS_7548,	"GD 7548")
-	DEVICE( CIRRUS,		CIRRUS_5430,	"GD 5430")
-	DEVICE( CIRRUS,		CIRRUS_5434_4,	"GD 5434")
-	DEVICE( CIRRUS,		CIRRUS_5434_8,	"GD 5434")
-	DEVICE( CIRRUS,		CIRRUS_5436,	"GD 5436")
-	DEVICE( CIRRUS,		CIRRUS_5446,	"GD 5446")
-	DEVICE( CIRRUS,		CIRRUS_5480,	"GD 5480")
-	DEVICE( CIRRUS,		CIRRUS_5462,	"Laguna")
-	DEVICE( CIRRUS,		CIRRUS_5464,	"Laguna 3D")
-	DEVICE( CIRRUS,		CIRRUS_5465,	"Laguna 3DA")
-	DEVICE( CIRRUS,		CIRRUS_6729,	"CL 6729")
-	DEVICE( CIRRUS,		CIRRUS_6832,	"PD 6832")
-	DEVICE( CIRRUS,		CIRRUS_7542,	"CL 7542")
-	DEVICE( CIRRUS,		CIRRUS_7543,	"CL 7543")
-	DEVICE( CIRRUS,		CIRRUS_7541,	"CL 7541")
-ENDVENDOR()
-
-VENDOR( IBM, "IBM" )
-	DEVICE( IBM,		IBM_FIRE_CORAL,	"Fire Coral")
-	DEVICE( IBM,		IBM_TR,		"Token Ring")
-	DEVICE( IBM,		IBM_82G2675,	"82G2675")
-	DEVICE( IBM,		IBM_MCA,	"MicroChannel")
-	DEVICE( IBM,		IBM_82351,	"82351")
-	DEVICE( IBM,		IBM_PYTHON,	"Python")
-	DEVICE( IBM,		IBM_SERVERAID,	"ServeRAID")
-	DEVICE( IBM,		IBM_TR_WAKE,	"Wake On LAN Token Ring")
-	DEVICE( IBM,		IBM_MPIC,	"MPIC-2 Interrupt Controller")
-	DEVICE( IBM,		IBM_3780IDSP,	"MWave DSP")
-	DEVICE( IBM,		IBM_MPIC_2,	"MPIC-2 ASIC Interrupt Controller")
-ENDVENDOR()
-
-VENDOR( WD, "Western Digital" )
-	DEVICE( WD,		WD_7197,	"WD 7197")
-ENDVENDOR()
-
-VENDOR( AMD, "AMD" )
-	DEVICE( AMD,		AMD_LANCE,	"79C970")
-	DEVICE( AMD,		AMD_SCSI,	"53C974")
-ENDVENDOR()
-
-VENDOR( TRIDENT, "Trident" )
-	DEVICE( TRIDENT,	TRIDENT_9320,	"Cyber9320")
-	DEVICE( TRIDENT,	TRIDENT_9388,	"Cyber9388")
-	DEVICE( TRIDENT,	TRIDENT_9397,	"Cyber9397")
-	DEVICE( TRIDENT,	TRIDENT_939A,	"Cyber939a")
-	DEVICE( TRIDENT,	TRIDENT_9520,	"Cyber9520")
-	DEVICE( TRIDENT,	TRIDENT_9525,	"Cyber9525")
-	DEVICE( TRIDENT,	TRIDENT_9420,	"TGUI 9420")
-	DEVICE( TRIDENT,	TRIDENT_9440,	"TGUI 9440")
-	DEVICE( TRIDENT,	TRIDENT_9660,	"TGUI 9660 / Cyber9385")
-	DEVICE( TRIDENT,	TRIDENT_9750,	"3DImage 975")
-	DEVICE( TRIDENT,	TRIDENT_9850,	"3DImage 985")
-	DEVICE( TRIDENT,	TRIDENT_9880,	"Blade 3D")
-	DEVICE( TRIDENT,	TRIDENT_8400,	"CyberBlade/i7")
-	DEVICE( TRIDENT,	TRIDENT_8420,	"CyberBlade/i7d")
-	DEVICE( TRIDENT,	TRIDENT_8500,	"CyberBlade/i1")
-ENDVENDOR()
-
-VENDOR( AI, "Acer Incorporated" )
-	DEVICE( AI,		AI_M1435,	"M1435")
-ENDVENDOR()
-
-VENDOR( MATROX, "Matrox" )
-	DEVICE( MATROX,		MATROX_MGA_2,	"Atlas PX2085")
-	DEVICE( MATROX,		MATROX_MIL,	"Millennium")
-	DEVICE( MATROX,		MATROX_MYS,	"Mystique")
-	DEVICE( MATROX,		MATROX_MIL_2,	"Millennium II")
-	DEVICE( MATROX,		MATROX_MIL_2_AGP,"Millennium II AGP")
-	DEVICE( MATROX,		MATROX_MGA_IMP,	"MGA Impression")
-	DEVICE( MATROX,         MATROX_G100_MM, "G100 multi monitor")
-	DEVICE( MATROX,         MATROX_G100_AGP,"G100 AGP")
-	DEVICE( MATROX,         MATROX_G200_PCI,"G200 PCI")
-	DEVICE( MATROX,         MATROX_G200_AGP,"G200 AGP")
-	DEVICE( MATROX,		MATROX_G400,	"G400")
-	DEVICE( MATROX,		MATROX_VIA,	"Corona / Meteor-II")
-ENDVENDOR()
-
-VENDOR( CT, "Chips & Technologies" )
-	DEVICE( CT,		CT_65545,	"65545")
-	DEVICE( CT,		CT_65548,	"65548")
-	DEVICE(	CT,		CT_65550,	"65550")
-	DEVICE( CT,		CT_65554,	"65554")
-	DEVICE( CT,		CT_65555,	"65555")
-ENDVENDOR()
-
-VENDOR( MIRO, "Miro" )
-	DEVICE( MIRO,		MIRO_36050,	"ZR36050")
-ENDVENDOR()
-
-VENDOR( NEC, "NEC" )
-	DEVICE( NEC,		NEC_PCX2,	"PowerVR PCX2")
-ENDVENDOR()
-
-VENDOR( FD, "Future Domain" )
-	DEVICE( FD,		FD_36C70,	"TMC-18C30")
-ENDVENDOR()
-
-VENDOR( SI, "Silicon Integrated Systems" )
-	DEVICE( SI,		SI_5591_AGP,	"5591/5592 AGP")
-	DEVICE( SI,		SI_6202,	"6202")
-	DEVICE( SI,		SI_503,		"85C503")
-	DEVICE( SI,		SI_ACPI,	"ACPI")
-	DEVICE( SI,		SI_5597_VGA,	"5597/5598 VGA")
-	DEVICE( SI,		SI_6205,	"6205")
-	DEVICE( SI,		SI_496,		"85C496")
-	DEVICE(	SI,		SI_501,		"85C501")
-	DEVICE(	SI,		SI_530,		"530 Host")
-	DEVICE( SI,		SI_601,		"85C601")
-	DEVICE(	SI,		SI_620,		"620 Host")
-	DEVICE( SI,		SI_5107,	"5107")
-	DEVICE( SI,		SI_5511,       	"85C5511")
-	DEVICE( SI,		SI_5513,	"85C5513 IDE")
-	DEVICE( SI,		SI_5571,	"5571")
-	DEVICE( SI,		SI_5591,	"5591/5592 Host")
-	DEVICE( SI,		SI_5597,	"5597/5598 Host")
-	DEVICE(	SI,		SI_5600,	"5600 Host")
-	DEVICE(	SI,		SI_6306,	"3D-AGP 6306 VGA")
-	DEVICE(	SI,		SI_6326,	"3D-AGP 6326 VGA")
-	DEVICE( SI,		SI_7001,	"7001 USB")
-ENDVENDOR()
-
-VENDOR( HP, "Hewlett Packard" )
-	DEVICE( HP,		HP_J2585A,	"J2585A")
-	DEVICE( HP,		HP_J2585B,	"J2585B (Lassen)")
-ENDVENDOR()
-
-VENDOR( PCTECH, "PCTECH" )
-	DEVICE( PCTECH,		PCTECH_RZ1000,  "RZ1000 (buggy)")
-	DEVICE( PCTECH,		PCTECH_RZ1001,  "RZ1001 (buggy?)")
-	DEVICE( PCTECH,		PCTECH_SAMURAI_0,"Samurai 0")
-	DEVICE( PCTECH,		PCTECH_SAMURAI_1,"Samurai 1")
-	DEVICE( PCTECH,		PCTECH_SAMURAI_IDE,"Samurai IDE")
-ENDVENDOR()
-
-VENDOR( DPT, "DPT" )
-	DEVICE( DPT,		DPT,		"SmartCache/Raid")
-ENDVENDOR()
-
-VENDOR( OPTI, "OPTi" )
-	DEVICE( OPTI,		OPTI_92C178,	"92C178")
-	DEVICE( OPTI,		OPTI_82C557,	"82C557 Viper-M")
-	DEVICE( OPTI,		OPTI_82C558,	"82C558 Viper-M ISA+IDE")
-	DEVICE( OPTI,		OPTI_82C621,	"82C621")
-	DEVICE( OPTI,		OPTI_82C700,	"82C700")
-	DEVICE( OPTI,		OPTI_82C701,	"82C701 FireStar Plus")
-	DEVICE( OPTI,		OPTI_82C814,	"82C814 Firebridge 1")
-	DEVICE( OPTI,		OPTI_82C822,	"82C822")
-	DEVICE( OPTI,		OPTI_82C825,	"82C825 Firebridge 2")
-ENDVENDOR()
-
-VENDOR( SGS, "SGS Thomson" )
-	DEVICE( SGS,		SGS_2000,	"STG 2000X")
-	DEVICE( SGS,		SGS_1764,	"STG 1764X")
-ENDVENDOR()
-
-VENDOR( BUSLOGIC, "BusLogic" )
-	DEVICE( BUSLOGIC,	BUSLOGIC_MULTIMASTER_NC, "MultiMaster NC")
-	DEVICE( BUSLOGIC,	BUSLOGIC_MULTIMASTER,    "MultiMaster")
-	DEVICE( BUSLOGIC,	BUSLOGIC_FLASHPOINT,     "FlashPoint")
-ENDVENDOR()
-
-VENDOR( TI, "Texas Instruments" )
-	DEVICE( TI,		TI_TVP4010,	"TVP4010 Permedia")
-	DEVICE( TI,		TI_TVP4020,	"TVP4020 Permedia 2")
-	DEVICE( TI,		TI_PCI1130,	"PCI1130")
-	DEVICE( TI,		TI_PCI1131,	"PCI1131")
-	DEVICE( TI,		TI_PCI1250,	"PCI1250")
-ENDVENDOR()
-
-VENDOR( OAK, "OAK" )
-	DEVICE( OAK,		OAK_OTI107,	"OTI107")
-ENDVENDOR()
-
-VENDOR( WINBOND2, "Winbond" )
-	DEVICE( WINBOND2,	WINBOND2_89C940,"NE2000-PCI")
-	DEVICE( WINBOND2,	WINBOND2_89C940F, "W89C940F")
-ENDVENDOR()
-
-VENDOR( MOTOROLA, "Motorola" )
-	DEVICE( MOTOROLA,	MOTOROLA_MPC105,"MPC105 Eagle")
-	DEVICE( MOTOROLA,	MOTOROLA_MPC106,"MPC106 Grackle")
-	DEVICE( MOTOROLA,	MOTOROLA_RAVEN,	"Raven")
-	DEVICE( MOTOROLA,	MOTOROLA_FALCON,"Falcon")
-	DEVICE( MOTOROLA,	MOTOROLA_CPX8216,"CPX8216")
-ENDVENDOR()
-
-VENDOR( PROMISE, "Promise Technology" )
-	DEVICE( PROMISE,        PROMISE_20246,	"IDE UltraDMA/33")
-	DEVICE(	PROMISE,	PROMISE_20262,	"IDE UltraDMA/66")
-	DEVICE( PROMISE,	PROMISE_5300,	"DC5030")
-ENDVENDOR()
-
-VENDOR( N9, "Number Nine" )
-	DEVICE( N9,		N9_I128,	"Imagine 128")
-	DEVICE( N9,		N9_I128_2,	"Imagine 128v2")
-	DEVICE( N9,		N9_I128_T2R,	"Revolution 3D")
-ENDVENDOR()
-
-VENDOR( UMC, "UMC" )
-	DEVICE( UMC,		UMC_UM8673F,	"UM8673F")
-	DEVICE( UMC,		UMC_UM8891A,	"UM8891A")
-	DEVICE( UMC,		UMC_UM8886BF,	"UM8886BF")
-	DEVICE( UMC,		UMC_UM8886A,	"UM8886A")
-	DEVICE( UMC,		UMC_UM8881F,	"UM8881F")
-	DEVICE( UMC,		UMC_UM8886F,	"UM8886F")
-	DEVICE( UMC,		UMC_UM9017F,	"UM9017F")
-	DEVICE( UMC,		UMC_UM8886N,	"UM8886N")
-	DEVICE( UMC,		UMC_UM8891N,	"UM8891N")
-ENDVENDOR()
-
-VENDOR( X, "X Technology" )
-	DEVICE( X,		X_AGX016,	"ITT AGX016")
-ENDVENDOR()
-
-VENDOR( PICOP, "PicoPower" )
-	DEVICE( PICOP,		PICOP_PT86C52X,	"PT86C52x Vesuvius")
-	DEVICE( PICOP,		PICOP_PT80C524,	"PT80C524 Nile")
-ENDVENDOR()
-
-VENDOR( APPLE, "Apple" )
-	DEVICE( APPLE,		APPLE_BANDIT,	"Bandit")
-	DEVICE( APPLE,		APPLE_GC,	"Grand Central")
-	DEVICE( APPLE,		APPLE_HYDRA,	"Hydra")
-ENDVENDOR()
-
-VENDOR( NEXGEN, "Nexgen" )
-	DEVICE( NEXGEN,		NEXGEN_82C501,	"82C501")
-ENDVENDOR()
-
-VENDOR( QLOGIC, "Q Logic" )
-	DEVICE( QLOGIC,		QLOGIC_ISP1020,	"ISP1020")
-	DEVICE( QLOGIC,		QLOGIC_ISP1022,	"ISP1022")
-ENDVENDOR()
-
-VENDOR( CYRIX, "Cyrix" )
-	DEVICE( CYRIX,		CYRIX_5510,	"5510")
-	DEVICE( CYRIX,		CYRIX_PCI_MASTER,"PCI Master")
-	DEVICE( CYRIX,		CYRIX_5520,	"5520")
-	DEVICE( CYRIX,		CYRIX_5530_LEGACY,"5530 Kahlua Legacy")
-	DEVICE( CYRIX,		CYRIX_5530_SMI,	"5530 Kahlua SMI")
-	DEVICE( CYRIX,		CYRIX_5530_IDE,	"5530 Kahlua IDE")
-	DEVICE( CYRIX,		CYRIX_5530_AUDIO,"5530 Kahlua Audio")
-	DEVICE( CYRIX,		CYRIX_5530_VIDEO,"5530 Kahlua Video")
-ENDVENDOR()
-
-VENDOR( LEADTEK, "Leadtek Research" )
-	DEVICE( LEADTEK,	LEADTEK_805,	"S3 805")
-ENDVENDOR()
-
-VENDOR( CONTAQ, "Contaq" )
-	DEVICE( CONTAQ,		CONTAQ_82C599,	"82C599")
-	DEVICE( CONTAQ,		CONTAQ_82C693,	"82C693")
-ENDVENDOR()
-
-VENDOR( FOREX, "Forex" )
-ENDVENDOR()
-
-VENDOR( OLICOM, "Olicom" )
-	DEVICE( OLICOM,		OLICOM_OC3136,	"OC-3136/3137")
-	DEVICE( OLICOM,		OLICOM_OC2315,	"OC-2315")
-	DEVICE( OLICOM,		OLICOM_OC2325,	"OC-2325")
-	DEVICE( OLICOM,		OLICOM_OC2183,	"OC-2183/2185")
-	DEVICE( OLICOM,		OLICOM_OC2326,	"OC-2326")
-	DEVICE( OLICOM,		OLICOM_OC6151,	"OC-6151/6152")
-ENDVENDOR()
-
-VENDOR( SUN, "Sun Microsystems" )
-	DEVICE( SUN,		SUN_EBUS,	"PCI-EBus Bridge")
-	DEVICE( SUN,		SUN_HAPPYMEAL,	"Happy Meal Ethernet")
-	DEVICE( SUN,		SUN_SIMBA,	"Advanced PCI Bridge")
-	DEVICE( SUN,		SUN_PBM,	"PCI Bus Module")
-	DEVICE( SUN,		SUN_SABRE,	"Ultra IIi PCI")
-ENDVENDOR()
-
-VENDOR( CMD, "CMD" )
-	DEVICE( CMD,		CMD_640,	"640 (buggy)")
-	DEVICE( CMD,		CMD_643,	"643")
-	DEVICE( CMD,		CMD_646,	"646")
-	DEVICE( CMD,		CMD_670,	"670")
-ENDVENDOR()
-
-VENDOR( VISION, "Vision" )
-	DEVICE( VISION,		VISION_QD8500,	"QD-8500")
-	DEVICE( VISION,		VISION_QD8580,	"QD-8580")
-ENDVENDOR()
-
-VENDOR( BROOKTREE, "Brooktree" )
-	DEVICE( BROOKTREE,	BROOKTREE_848,	"Bt848")
-	DEVICE( BROOKTREE,	BROOKTREE_849A,	"Bt849")
-	DEVICE( BROOKTREE,      BROOKTREE_878_1,"Bt878 2nd Contr. (?)")
-	DEVICE( BROOKTREE,      BROOKTREE_878,  "Bt878")
-	DEVICE( BROOKTREE,	BROOKTREE_8474,	"Bt8474")
-ENDVENDOR()
-
-VENDOR( SIERRA, "Sierra" )
-	DEVICE( SIERRA,		SIERRA_STB,	"STB Horizon 64")
-ENDVENDOR()
-
-VENDOR( SGI, "Silicon Graphics Inc" )
-	DEVICE( SGI,		SGI_IOC3,	"IOC3")
-ENDVENDOR()
-
-VENDOR( ACC, "ACC MICROELECTRONICS" )
-	DEVICE( ACC,		ACC_2056,	"2056")
-ENDVENDOR()
-
-VENDOR( WINBOND, "Winbond" )
-	DEVICE( WINBOND,	WINBOND_83769,	"W83769F")
-	DEVICE( WINBOND,	WINBOND_82C105,	"SL82C105")
-	DEVICE( WINBOND,	WINBOND_83C553,	"W83C553")
-ENDVENDOR()
-
-VENDOR( DATABOOK, "Databook" )
-	DEVICE( DATABOOK,      	DATABOOK_87144,	"DB87144")
-ENDVENDOR()
-
-VENDOR( PLX, "PLX" )
-	DEVICE(	PLX,		PLX_9050,	"PCI9050 I2O")
-	DEVICE( PLX,		PLX_9080,	"PCI9080 I2O")
-ENDVENDOR()
-
-VENDOR( MADGE, "Madge Networks" )
-	DEVICE( MADGE,		MADGE_MK2,	"Smart 16/4 BM Mk2 Ringnode")
-	DEVICE( MADGE,		MADGE_C155S,	"Collage 155 Server")
-ENDVENDOR()
-
-VENDOR( 3COM, "3Com" )
-	DEVICE( 3COM,		3COM_3C339,	"3C339 TokenRing")
-	DEVICE( 3COM,		3COM_3C590,	"3C590 10bT")
-	DEVICE( 3COM,		3COM_3C595TX,	"3C595 100bTX")
-	DEVICE( 3COM,		3COM_3C595T4,	"3C595 100bT4")
-	DEVICE( 3COM,		3COM_3C595MII,	"3C595 100b-MII")
-	DEVICE( 3COM,		3COM_3C900TPO,	"3C900 10bTPO")
-	DEVICE( 3COM,		3COM_3C900COMBO,"3C900 10b Combo")
-	DEVICE( 3COM,		3COM_3C905TX,	"3C905 100bTX")
-	DEVICE( 3COM,		3COM_3C905T4,	"3C905 100bT4")
-	DEVICE( 3COM,		3COM_3C905B_TX,	"3C905B 100bTX")
-ENDVENDOR()
-
-VENDOR( SMC, "SMC" )
-	DEVICE( SMC,		SMC_EPIC100,	"9432 TX")
-ENDVENDOR()
-
-VENDOR( AL, "Acer Labs" )
-	DEVICE( AL,		AL_M1445,	"M1445")
-	DEVICE( AL,		AL_M1449,	"M1449")
-	DEVICE( AL,		AL_M1451,	"M1451")
-	DEVICE( AL,		AL_M1461,	"M1461")
-	DEVICE( AL,		AL_M1489,	"M1489")
-	DEVICE( AL,		AL_M1511,	"M1511")
-	DEVICE( AL,		AL_M1513,	"M1513")
-	DEVICE( AL,		AL_M1521,	"M1521")
-	DEVICE( AL,		AL_M1523,	"M1523")
-	DEVICE( AL,		AL_M1531,	"M1531 Aladdin IV")
-	DEVICE( AL,		AL_M1533,	"M1533 Aladdin IV")
-	DEVICE(	AL,		AL_M1541,	"M1541 Aladdin V")
-	DEVICE(	AL,		AL_M1543,	"M1543 Aladdin V")
-	DEVICE( AL,		AL_M3307,	"M3307 MPEG-1 decoder")
-	DEVICE( AL,		AL_M4803,	"M4803")
-	DEVICE( AL,		AL_M5219,	"M5219")
-	DEVICE( AL,		AL_M5229,	"M5229 TXpro")
-	DEVICE( AL,		AL_M5237,	"M5237 USB")
-	DEVICE(	AL,		AL_M5243,	"M5243 AGP")
-	DEVICE(	AL,		AL_M7101,	"M7101 PMU")
-ENDVENDOR()
-
-VENDOR( MITSUBISHI, "Mitsubishi" )
-ENDVENDOR()
-
-VENDOR( SURECOM, "Surecom" )
-	DEVICE( SURECOM,	SURECOM_NE34,	"NE-34PCI LAN")
-ENDVENDOR()
-
-VENDOR( NEOMAGIC, "Neomagic" )
-	DEVICE( NEOMAGIC,       NEOMAGIC_MAGICGRAPH_NM2070,     "Magicgraph NM2070")
-	DEVICE( NEOMAGIC,	NEOMAGIC_MAGICGRAPH_128V, "MagicGraph 128V")
-	DEVICE( NEOMAGIC,	NEOMAGIC_MAGICGRAPH_128ZV, "MagicGraph 128ZV")
-	DEVICE( NEOMAGIC,	NEOMAGIC_MAGICGRAPH_NM2160, "MagicGraph NM2160")
-	DEVICE( NEOMAGIC,	NEOMAGIC_MAGICGRAPH_128ZVPLUS, "MagicGraph 128ZV+")
-ENDVENDOR()
-
-VENDOR( ASP, "Advanced System Products" )
-	DEVICE( ASP,		ASP_ABP940,	"ABP940")
-	DEVICE( ASP,		ASP_ABP940U,	"ABP940U")
-	DEVICE( ASP,		ASP_ABP940UW,	"ABP940UW")
-ENDVENDOR()
-
-VENDOR( MACRONIX, "Macronix" )
-	DEVICE( MACRONIX,	MACRONIX_MX98713,"MX98713")
-	DEVICE( MACRONIX,	MACRONIX_MX987x5,"MX98715 / MX98725")
-ENDVENDOR()
-
-VENDOR( TCONRAD, "Thomas-Conrad" )
-	DEVICE( TCONRAD,	TCONRAD_TOKENRING, "Token Ring 4/16")
-ENDVENDOR()
-
-VENDOR( CERN, "CERN" )
-	DEVICE( CERN,		CERN_SPSB_PMC,	"STAR/RD24 SCI-PCI (PMC)")
-	DEVICE( CERN,		CERN_SPSB_PCI,	"STAR/RD24 SCI-PCI (PMC)")
-	DEVICE( CERN,		CERN_HIPPI_DST,	"HIPPI destination")
-	DEVICE( CERN,		CERN_HIPPI_SRC,	"HIPPI source")
-ENDVENDOR()
-
-VENDOR( NVIDIA, "NVidia" )
-	DEVICE( NVIDIA,		NVIDIA_TNT,	"Riva TNT")
-	DEVICE( NVIDIA,		NVIDIA_TNT2,	"Riva TNT2")
-	DEVICE( NVIDIA,		NVIDIA_UTNT2,	"Riva TNT2 (Ultra)")
-	DEVICE( NVIDIA,		NVIDIA_VTNT2,	"Riva TNT2 (Vanta)")
-	DEVICE( NVIDIA,		NVIDIA_UVTNT2,	"Riva TNT2 (Ultra Vanta)")
-	DEVICE( NVIDIA,		NVIDIA_ITNT2,	"Riva TNT2 (Integrated)")
-ENDVENDOR()
-
-VENDOR( IMS, "IMS" )
-	DEVICE( IMS,		IMS_8849,	"8849")
-ENDVENDOR()
-
-VENDOR( TEKRAM2, "Tekram" )
-	DEVICE( TEKRAM2,	TEKRAM2_690c,	"DC690c")
-ENDVENDOR()
-
-VENDOR( TUNDRA, "Tundra" )
-	DEVICE( TUNDRA,		TUNDRA_CA91C042,"CA91C042 Universe")
-ENDVENDOR()
-
-VENDOR( AMCC, "AMCC" )
-	DEVICE( AMCC,		AMCC_MYRINET,	"Myrinet PCI (M2-PCI-32)")
-	DEVICE( AMCC,		AMCC_PARASTATION,"ParaStation Interface")
-	DEVICE( AMCC,		AMCC_S5933,	"S5933 PCI44")
-	DEVICE( AMCC,		AMCC_S5933_HEPC3,"S5933 Traquair HEPC3")
-ENDVENDOR()
-
-VENDOR( INTERG, "Intergraphics" )
-	DEVICE( INTERG,		INTERG_1680,	"IGA-1680")
-	DEVICE( INTERG,         INTERG_1682,    "IGA-1682")
-	DEVICE( INTERG,		INTERG_2000,	"CyberPro 2000")
-ENDVENDOR()
-
-VENDOR( REALTEK, "Realtek" )
-	DEVICE( REALTEK,	REALTEK_8029,	"8029")
-	DEVICE( REALTEK,	REALTEK_8129,	"8129")
-	DEVICE( REALTEK,	REALTEK_8139,	"8139")
-ENDVENDOR()
-
-VENDOR( TRUEVISION, "Truevision" )
-	DEVICE( TRUEVISION,	TRUEVISION_T1000,"TARGA 1000")
-ENDVENDOR()
-
-VENDOR( INIT, "Initio Corp" )
-	DEVICE( INIT,		INIT_320P,	"320 P")
-	DEVICE( INIT,		INIT_360P,	"360 P")
-ENDVENDOR()
-
-VENDOR( TTI, "Triones Technologies, Inc." )
-	DEVICE(	TTI,		TTI_HPT343,	"HPT343 IDE UltraDMA/33")
-	DEVICE(	TTI,		TTI_HPT366,	"HPT366 IDE UltraDMA/66")
-ENDVENDOR()
-
-VENDOR( VIA, "VIA Technologies" )
-	DEVICE( VIA,		VIA_8501_0,	"VT 8501")
-	DEVICE( VIA,		VIA_82C505,	"VT 82C505")
-	DEVICE( VIA,		VIA_82C561,	"VT 82C561")
-	DEVICE( VIA,		VIA_82C586_1,	"VT 82C586 Apollo IDE")
-	DEVICE( VIA,		VIA_82C576,	"VT 82C576 3V")
-	DEVICE( VIA,		VIA_82C585,	"VT 82C585 Apollo VP1/VPX")
-	DEVICE( VIA,		VIA_82C586_0,	"VT 82C586 Apollo ISA")
-	DEVICE( VIA,		VIA_82C595,	"VT 82C595 Apollo VP2")
-	DEVICE(	VIA,		VIA_82C596,	"VT 82C596 Apollo Mobile")
-	DEVICE( VIA,		VIA_82C597_0,	"VT 82C597 Apollo VP3")
-	DEVICE( VIA,		VIA_82C598_0,	"VT 82C598 Apollo MVP3")
-	DEVICE(	VIA,		VIA_82C680,	"VT 82C680 Apollo P6")
-	DEVICE(	VIA,		VIA_82C686,	"VT 82C686 Apollo Super")
-	DEVICE(	VIA,		VIA_82C691,	"VT 82C691 Apollo Pro")
-	DEVICE(	VIA,		VIA_82C693,	"VT 82C693 Apollo Pro Plus")
-	DEVICE( VIA,		VIA_82C926,	"VT 82C926 Amazon")
-	DEVICE( VIA,		VIA_82C416,	"VT 82C416MV")
-	DEVICE( VIA,		VIA_82C595_97,	"VT 82C595 Apollo VP2/97")
-	DEVICE( VIA,		VIA_82C586_2,	"VT 82C586 Apollo USB")
-	DEVICE( VIA,		VIA_82C586_3,	"VT 82C586B Apollo ACPI")
-	DEVICE(	VIA,		VIA_82C686_4,	"VT 82C686 Apollo Super ACPI")
-	DEVICE(	VIA,		VIA_82C686_5,	"VT 82C686 Apollo Super AC97/Audio")
-	DEVICE(	VIA,		VIA_82C686_6,	"VT 82C686 Apollo Super AC97/Modem")
-	DEVICE( VIA,		VIA_86C100A,	"VT 86C100A")
-	DEVICE( VIA,		VIA_8501_1,	"VT 8501 PCI Bridge")
-	DEVICE( VIA,		VIA_82C597_1,	"VT 82C597 Apollo VP3 AGP")
-	DEVICE( VIA,		VIA_82C598_1,	"VT 82C598 Apollo MVP3 AGP")
-ENDVENDOR()
-
-VENDOR( SMC2, "SMC" )
-	DEVICE( SMC2,		SMC2_1211TX,	"1211 TX")
-ENDVENDOR()
-
-VENDOR( VORTEX, "VORTEX" )
-	DEVICE( VORTEX,		VORTEX_GDT60x0,	"GDT 60x0")
-	DEVICE( VORTEX,		VORTEX_GDT6000B,"GDT 6000b")
-	DEVICE( VORTEX,		VORTEX_GDT6x10,	"GDT 6110/6510")
-	DEVICE( VORTEX,		VORTEX_GDT6x20,	"GDT 6120/6520")
-	DEVICE( VORTEX,		VORTEX_GDT6530,	"GDT 6530")
-	DEVICE( VORTEX,		VORTEX_GDT6550,	"GDT 6550")
-	DEVICE( VORTEX,		VORTEX_GDT6x17,	"GDT 6117/6517")
-	DEVICE( VORTEX,		VORTEX_GDT6x27,	"GDT 6127/6527")
-	DEVICE( VORTEX,		VORTEX_GDT6537,	"GDT 6537")
-	DEVICE( VORTEX,		VORTEX_GDT6557,	"GDT 6557")
-	DEVICE( VORTEX,		VORTEX_GDT6x15,	"GDT 6115/6515")
-	DEVICE( VORTEX,		VORTEX_GDT6x25,	"GDT 6125/6525")
-	DEVICE( VORTEX,		VORTEX_GDT6535,	"GDT 6535")
-	DEVICE( VORTEX,		VORTEX_GDT6555,	"GDT 6555")
-	DEVICE( VORTEX,		VORTEX_GDT6x17RP,"GDT 6117RP/6517RP")
-	DEVICE( VORTEX,		VORTEX_GDT6x27RP,"GDT 6127RP/6527RP")
-	DEVICE( VORTEX,		VORTEX_GDT6537RP,"GDT 6537RP")
-	DEVICE( VORTEX,		VORTEX_GDT6557RP,"GDT 6557RP")
-	DEVICE( VORTEX,		VORTEX_GDT6x11RP,"GDT 6111RP/6511RP")
-	DEVICE( VORTEX,		VORTEX_GDT6x21RP,"GDT 6121RP/6521RP")
-	DEVICE( VORTEX,		VORTEX_GDT6x17RP1,"GDT 6117RP1/6517RP1")
-	DEVICE( VORTEX,		VORTEX_GDT6x27RP1,"GDT 6127RP1/6527RP1")
-	DEVICE( VORTEX,		VORTEX_GDT6537RP1,"GDT 6537RP1")
-	DEVICE( VORTEX,		VORTEX_GDT6557RP1,"GDT 6557RP1")
-	DEVICE( VORTEX,		VORTEX_GDT6x11RP1,"GDT 6111RP1/6511RP1")
-	DEVICE( VORTEX,		VORTEX_GDT6x21RP1,"GDT 6121RP1/6521RP1")
-	DEVICE( VORTEX,		VORTEX_GDT6x17RP2,"GDT 6117RP2/6517RP2")
-	DEVICE( VORTEX,		VORTEX_GDT6x27RP2,"GDT 6127RP2/6527RP2")
-	DEVICE( VORTEX,		VORTEX_GDT6537RP2,"GDT 6537RP2")
-	DEVICE( VORTEX,		VORTEX_GDT6557RP2,"GDT 6557RP2")
-	DEVICE( VORTEX,		VORTEX_GDT6x11RP2,"GDT 6111RP2/6511RP2")
-	DEVICE( VORTEX,		VORTEX_GDT6x21RP2,"GDT 6121RP2/6521RP2")
-ENDVENDOR()
-
-VENDOR( EF, "Efficient Networks" )
-	DEVICE( EF,		EF_ATM_FPGA,   	"155P-MF1 (FPGA)")
-	DEVICE( EF,		EF_ATM_ASIC,    "155P-MF1 (ASIC)")
-ENDVENDOR()
-
-VENDOR( FORE, "Fore Systems" )
-	DEVICE( FORE,		FORE_PCA200PC,  "PCA-200PC")
-	DEVICE( FORE,		FORE_PCA200E,	 "PCA-200E")
-ENDVENDOR()
-
-VENDOR( IMAGINGTECH, "Imaging Technology" )
-	DEVICE( IMAGINGTECH,	IMAGINGTECH_ICPCI, "MVC IC-PCI")
-ENDVENDOR()
-
-VENDOR( PHILIPS, "Philips" )
-	DEVICE( PHILIPS,	PHILIPS_SAA7145,"SAA7145")
-	DEVICE( PHILIPS,	PHILIPS_SAA7146,"SAA7146")
-ENDVENDOR()
-
-VENDOR( CYCLONE, "Cyclone" )
-	DEVICE( CYCLONE,	CYCLONE_SDK,	"SDK")
-ENDVENDOR()
-
-VENDOR( ALLIANCE, "Alliance" )
-	DEVICE( ALLIANCE,	ALLIANCE_PROMOTIO, "Promotion-6410")
-	DEVICE( ALLIANCE,	ALLIANCE_PROVIDEO, "Provideo")
-	DEVICE( ALLIANCE,	ALLIANCE_AT24,	"AT24")
-	DEVICE( ALLIANCE,	ALLIANCE_AT3D,	"AT3D")
-ENDVENDOR()
-
-VENDOR( VMIC, "VMIC" )
-	DEVICE( VMIC,		VMIC_VME,	"VMIVME-7587")
-ENDVENDOR()
-
-VENDOR( DIGI, "Digi Intl." )
-	DEVICE( DIGI,		DIGI_EPC,	"AccelPort EPC")
-	DEVICE( DIGI,		DIGI_RIGHTSWITCH, "RightSwitch SE-6")
-	DEVICE( DIGI,		DIGI_XEM,	"AccelPort Xem")
-	DEVICE( DIGI,		DIGI_XR,	"AccelPort Xr")
-	DEVICE( DIGI,		DIGI_CX,	"AccelPort C/X")
-	DEVICE( DIGI,		DIGI_XRJ,	"AccelPort Xr/J")
-	DEVICE( DIGI,		DIGI_EPCJ,	"AccelPort EPC/J")
-	DEVICE( DIGI,		DIGI_XR_920,	"AccelPort Xr 920")
-ENDVENDOR()
-
-VENDOR( MUTECH, "Mutech" )
-	DEVICE( MUTECH,		MUTECH_MV1000,	"MV-1000")
-ENDVENDOR()
-
-VENDOR( RENDITION, "Rendition" )
-	DEVICE( RENDITION,	RENDITION_VERITE,"Verite 1000")
-	DEVICE( RENDITION,	RENDITION_VERITE2100,"Verite 2100")
-ENDVENDOR()
-
-VENDOR( TOSHIBA, "Toshiba" )
-	DEVICE( TOSHIBA,	TOSHIBA_601,	"Laptop")
-	DEVICE( TOSHIBA,	TOSHIBA_TOPIC95,"ToPIC95")
-	DEVICE( TOSHIBA,	TOSHIBA_TOPIC97,"ToPIC97")
-ENDVENDOR()
-
-VENDOR( RICOH, "Ricoh" )
-	DEVICE( RICOH,		RICOH_RL5C466,	"RL5C466")
-ENDVENDOR()
-
-VENDOR( ARTOP, "Artop Electronics" )
-	DEVICE(	ARTOP,		ARTOP_ATP8400,	"ATP8400")
-	DEVICE( ARTOP,		ARTOP_ATP850UF,	"ATP850UF")
-ENDVENDOR()
-
-VENDOR( ZEITNET, "ZeitNet" )
-	DEVICE( ZEITNET,	ZEITNET_1221,	"1221")
-	DEVICE( ZEITNET,	ZEITNET_1225,	"1225")
-ENDVENDOR()
-
-VENDOR( OMEGA, "Omega Micro" )
-	DEVICE( OMEGA,		OMEGA_82C092G,	"82C092G")
-ENDVENDOR()
-
-VENDOR( LITEON, "LiteOn" )
-	DEVICE( LITEON,		LITEON_LNE100TX,"LNE100TX")
-ENDVENDOR()
-
-VENDOR( NP, "Network Peripherals" )
-	DEVICE( NP,		NP_PCI_FDDI,	"NP-PCI")
-ENDVENDOR()
-
-VENDOR( ATT, "Lucent Microelectronics" )
-	DEVICE( ATT,		ATT_L56XMF,	"L56xMF")
-ENDVENDOR()
-
-VENDOR( SPECIALIX, "Specialix" )
-	DEVICE( SPECIALIX,	SPECIALIX_IO8,	"IO8+/PCI")
-	DEVICE( SPECIALIX,	SPECIALIX_XIO,	"XIO/SIO host")
-	DEVICE( SPECIALIX,	SPECIALIX_RIO,	"RIO host")
-ENDVENDOR()
-
-VENDOR( AURAVISION, "Auravision" )
-	DEVICE( AURAVISION,	AURAVISION_VXP524,"VXP524")
-ENDVENDOR()
-
-VENDOR( IKON, "Ikon" )
-	DEVICE( IKON,		IKON_10115,	"10115 Greensheet")
-	DEVICE( IKON,		IKON_10117,	"10117 Greensheet")
-ENDVENDOR()
-
-VENDOR( ZORAN, "Zoran" )
-	DEVICE( ZORAN,		ZORAN_36057,	"ZR36057")
-	DEVICE( ZORAN,		ZORAN_36120,	"ZR36120")
-ENDVENDOR()
-
-VENDOR( KINETIC, "Kinetic" )
-	DEVICE( KINETIC,	KINETIC_2915,	"2915 CAMAC")
-ENDVENDOR()
-
-VENDOR( COMPEX, "Compex" )
-	DEVICE( COMPEX,		COMPEX_ENET100VG4, "Readylink ENET100-VG4")
-	DEVICE( COMPEX,		COMPEX_RL2000,	"ReadyLink 2000")
-ENDVENDOR()
-
-VENDOR( RP, "Comtrol" )
-	DEVICE( RP,             RP32INTF,       "RocketPort 32 Intf")
-	DEVICE( RP,             RP8INTF,        "RocketPort 8 Intf")
-	DEVICE( RP,             RP16INTF,       "RocketPort 16 Intf")
-	DEVICE( RP, 		RP4QUAD,	"Rocketport 4 Quad")
-	DEVICE( RP,             RP8OCTA,        "RocketPort 8 Oct")
-	DEVICE( RP,             RP8J,	        "RocketPort 8 J")
-	DEVICE( RP,             RPP4,	        "RocketPort Plus 4 Quad")
-	DEVICE( RP,             RPP8,	        "RocketPort Plus 8 Oct")
-	DEVICE( RP,             RP8M,	        "RocketModem 8 J")
-ENDVENDOR()
-
-VENDOR( CYCLADES, "Cyclades" )
-	DEVICE( CYCLADES,	CYCLOM_Y_Lo,	"Cyclom-Y below 1Mbyte")
-	DEVICE( CYCLADES,	CYCLOM_Y_Hi,	"Cyclom-Y above 1Mbyte")
-	DEVICE( CYCLADES,	CYCLOM_4Y_Lo,	"Cyclom-4Y below 1Mbyte")
-	DEVICE( CYCLADES,	CYCLOM_4Y_Hi,	"Cyclom-4Y above 1Mbyte")
-	DEVICE( CYCLADES,	CYCLOM_8Y_Lo,	"Cyclom-8Y below 1Mbyte")
-	DEVICE( CYCLADES,	CYCLOM_8Y_Hi,	"Cyclom-8Y above 1Mbyte")
-	DEVICE( CYCLADES,	CYCLOM_Z_Lo,	"Cyclades-Z below 1Mbyte")
-	DEVICE( CYCLADES,	CYCLOM_Z_Hi,	"Cyclades-Z above 1Mbyte")
-ENDVENDOR()
-
-VENDOR( ESSENTIAL, "Essential Communications" )
-	DEVICE( ESSENTIAL,	ESSENTIAL_ROADRUNNER,"Roadrunner serial HIPPI")
-ENDVENDOR()
-
-VENDOR( O2, "O2 Micro" )
-	DEVICE( O2,		O2_6832,	"6832")
-ENDVENDOR()
-
-VENDOR( 3DFX, "3Dfx" )
-	DEVICE( 3DFX,		3DFX_VOODOO,	"Voodoo")
-	DEVICE( 3DFX,		3DFX_VOODOO2,	"Voodoo2")
-	DEVICE( 3DFX,           3DFX_BANSHEE,   "Banshee")
-	DEVICE( 3DFX,           3DFX_VOODOO3,   "Voodoo3")
-ENDVENDOR()
-
-VENDOR( SIGMADES, "Sigma Designs" )
-	DEVICE( SIGMADES,	SIGMADES_6425,	"REALmagic64/GX")
-ENDVENDOR()
-
-VENDOR( AVM, "AVM" )
-	DEVICE( AVM,		AVM_A1,		"A1 (Fritz)")
-ENDVENDOR()
-
-VENDOR( CCUBE, "C-Cube" )
-ENDVENDOR()
-
-VENDOR( DIPIX, "Dipix" )
-ENDVENDOR()
-
-VENDOR( STALLION, "Stallion" )
-	DEVICE( STALLION,	STALLION_ECHPCI832,"EasyConnection 8/32")
-	DEVICE( STALLION,	STALLION_ECHPCI864,"EasyConnection 8/64")
-	DEVICE( STALLION,	STALLION_EIOPCI,"EasyIO")
-ENDVENDOR()
-
-VENDOR( OPTIBASE, "Optibase" )
-	DEVICE( OPTIBASE,	OPTIBASE_FORGE,	"MPEG Forge")
-	DEVICE( OPTIBASE,	OPTIBASE_FUSION,"MPEG Fusion")
-	DEVICE( OPTIBASE,	OPTIBASE_VPLEX,	"VideoPlex")
-	DEVICE( OPTIBASE,	OPTIBASE_VPLEXCC,"VideoPlex CC")
-	DEVICE( OPTIBASE,	OPTIBASE_VQUEST,"VideoQuest")
-ENDVENDOR()
-
-VENDOR(	ESS, "ESS Technologies" )
-	DEVICE(	ESS,		ESS_AUDIOPCI,	"3D Audio 1969")
-ENDVENDOR()
-
-VENDOR( SATSAGEM, "SatSagem" )
-	DEVICE( SATSAGEM,	SATSAGEM_PCR2101,"PCR2101 DVB receiver")
-	DEVICE( SATSAGEM,	SATSAGEM_TELSATTURBO,"Telsat Turbo DVB")
-ENDVENDOR()
-
-VENDOR( HUGHES, "Hughes" )
-	DEVICE( HUGHES,		HUGHES_DIRECPC,	"DirecPC")
-ENDVENDOR()
-
-VENDOR( ENSONIQ, "Ensoniq" )
-	DEVICE( ENSONIQ,	ENSONIQ_ES1371,	"ES1371")
-	DEVICE( ENSONIQ,	ENSONIQ_AUDIOPCI,"AudioPCI")
-ENDVENDOR()
-
-VENDOR( ALTEON, "Alteon" )
-	DEVICE( ALTEON,		ALTEON_ACENIC,  "AceNIC")
-ENDVENDOR()
-
-VENDOR( PICTUREL, "Picture Elements" )
-	DEVICE( PICTUREL,	PICTUREL_PCIVST,"PCIVST")
-ENDVENDOR()
-
-VENDOR( NVIDIA_SGS, "NVidia/SGS Thomson" )
-	DEVICE( NVIDIA_SGS,	NVIDIA_SGS_RIVA128,	"Riva 128")
-ENDVENDOR()
-
-VENDOR( CBOARDS, "ComputerBoards" )
-	DEVICE( CBOARDS,	CBOARDS_DAS1602_16,"DAS1602/16")
-ENDVENDOR()
-
-VENDOR( MOTOROLA_OOPS, "Motorola" )
-	DEVICE( MOTOROLA_OOPS,	MOTOROLA_FALCON,"Falcon")
-ENDVENDOR()
-
-VENDOR( LAVA, "Lava Computer MFG" )
-	DEVICE( LAVA,		LAVA_PARALLEL,	"Lava Parallel")
-	DEVICE( LAVA,		LAVA_DUAL_PAR_A,"Lava Dual Parallel (A)")
-	DEVICE( LAVA,		LAVA_DUAL_PAR_B,"Lava Dual Parallel (B)")
-	DEVICE( LAVA,		LAVA_BOCA_IOPPAR,"BOCA Research IOPPAR")
-ENDVENDOR()
-
-VENDOR( SYMPHONY, "Symphony" )
-	DEVICE( SYMPHONY,	SYMPHONY_101,	"82C101")
-ENDVENDOR()
-
-VENDOR( TEKRAM, "Tekram" )
-	DEVICE( TEKRAM,		TEKRAM_DC290,	"DC-290")
-ENDVENDOR()
-
-VENDOR( 3DLABS, "3Dlabs" )
-	DEVICE( 3DLABS,		3DLABS_300SX,	"GLINT 300SX")
-	DEVICE( 3DLABS,		3DLABS_500TX,	"GLINT 500TX")
-	DEVICE( 3DLABS,		3DLABS_DELTA,	"GLINT Delta")
-	DEVICE( 3DLABS,		3DLABS_PERMEDIA,"PERMEDIA")
-	DEVICE( 3DLABS,		3DLABS_MX,	"GLINT MX")
-ENDVENDOR()
-
-VENDOR( AVANCE, "Avance" )
-	DEVICE( AVANCE,		AVANCE_ALG2064,	"ALG2064i")
-	DEVICE( AVANCE,		AVANCE_2302,	"ALG-2302")
-ENDVENDOR()
-
-VENDOR( NETVIN, "NetVin" )
-	DEVICE( NETVIN,		NETVIN_NV5000SC,"NV5000")
-ENDVENDOR()
-
-VENDOR( S3, "S3 Inc." )
-	DEVICE( S3,		S3_PLATO_PXS,	"PLATO/PX (system)")
-	DEVICE( S3,		S3_ViRGE,	"ViRGE")
-	DEVICE( S3,		S3_TRIO,	"Trio32/Trio64")
-	DEVICE( S3,		S3_AURORA64VP,	"Aurora64V+")
-	DEVICE( S3,		S3_TRIO64UVP,	"Trio64UV+")
-	DEVICE( S3,		S3_ViRGE_VX,	"ViRGE/VX")
-	DEVICE( S3,		S3_868,	        "Vision 868")
-	DEVICE( S3,		S3_928,		"Vision 928-P")
-	DEVICE( S3,		S3_864_1,	"Vision 864-P")
-	DEVICE( S3,		S3_864_2,	"Vision 864-P")
-	DEVICE( S3,		S3_964_1,	"Vision 964-P")
-	DEVICE( S3,		S3_964_2,	"Vision 964-P")
-	DEVICE( S3,		S3_968,		"Vision 968")
-	DEVICE( S3,		S3_TRIO64V2,	"Trio64V2/DX or /GX")
-	DEVICE( S3,		S3_PLATO_PXG,	"PLATO/PX (graphics)")
-	DEVICE( S3,		S3_ViRGE_DXGX,	"ViRGE/DX or /GX")
-	DEVICE( S3,		S3_ViRGE_GX2,	"ViRGE/GX2")
-	DEVICE( S3,		S3_ViRGE_MX,	"ViRGE/MX")
-	DEVICE( S3,		S3_ViRGE_MXP,	"ViRGE/MX+")
-	DEVICE( S3,		S3_ViRGE_MXPMV,	"ViRGE/MX+MV")
-	DEVICE( S3,		S3_SONICVIBES,	"SonicVibes")
-ENDVENDOR()
-
-VENDOR( DCI, "Decision Computer Int." )
-	DEVICE( DCI,		DCI_PCCOM4,	"PC COM PCI Bus 4 port serial Adapter")
-ENDVENDOR()
-
-VENDOR( GENROCO, "Genroco" )
-	DEVICE( GENROCO,	GENROCO_HFP832,	"TURBOstor HFP832")
-ENDVENDOR()
-
-VENDOR( INTEL, "Intel" )
-	DEVICE( INTEL,		INTEL_82375,	"82375EB")
-	DEVICE( INTEL,		INTEL_82424,	"82424ZX Saturn")
-	DEVICE( INTEL,		INTEL_82378,	"82378IB")
-	DEVICE( INTEL,		INTEL_82430,	"82430ZX Aries")
-	DEVICE( INTEL,		INTEL_82434,	"82434LX Mercury/Neptune")
-	DEVICE( INTEL,		INTEL_82092AA_0,"82092AA PCMCIA bridge")
-	DEVICE( INTEL,		INTEL_82092AA_1,"82092AA EIDE")
-	DEVICE( INTEL,		INTEL_7116,	"SAA7116")
-	DEVICE( INTEL,		INTEL_82596,	"82596")
-	DEVICE( INTEL,		INTEL_82865,	"82865")
-	DEVICE( INTEL,		INTEL_82557,	"EtherExpress Pro100")
-	DEVICE( INTEL,		INTEL_82559ER,	"82559ER")
-	DEVICE( INTEL,		INTEL_82437,	"82437")
-	DEVICE( INTEL,		INTEL_82371FB_0,"82371FB PIIX ISA")
-	DEVICE( INTEL,		INTEL_82371FB_1,"82371FB PIIX IDE")
-	DEVICE( INTEL,		INTEL_82371MX,	"430MX - 82371MX MPIIX")
-	DEVICE( INTEL,		INTEL_82437MX,	"430MX - 82437MX MTSC")
-	DEVICE( INTEL,		INTEL_82441,	"82441FX Natoma")
-	DEVICE( INTEL,		INTEL_82380FB,	"82380FB Mobile")
-	DEVICE( INTEL,		INTEL_82439,	"82439HX Triton II")
-	DEVICE(	INTEL,		INTEL_82371SB_0,"82371SB PIIX3 ISA")
-	DEVICE(	INTEL,		INTEL_82371SB_1,"82371SB PIIX3 IDE")
-	DEVICE( INTEL,		INTEL_82371SB_2,"82371SB PIIX3 USB")
-	DEVICE( INTEL,		INTEL_82437VX,	"82437VX Triton II")
-	DEVICE( INTEL,		INTEL_82439TX,	"82439TX")
-	DEVICE( INTEL,		INTEL_82371AB_0,"82371AB PIIX4 ISA")
-	DEVICE( INTEL,		INTEL_82371AB,	"82371AB PIIX4 IDE")
-	DEVICE( INTEL,		INTEL_82371AB_2,"82371AB PIIX4 USB")
-	DEVICE( INTEL,		INTEL_82371AB_3,"82371AB PIIX4 ACPI")
-	DEVICE( INTEL,		INTEL_82443LX_0,"440LX - 82443LX PAC Host")
-	DEVICE( INTEL,		INTEL_82443LX_1,"440LX - 82443LX PAC AGP")
-	DEVICE( INTEL,		INTEL_82443BX_0,"440BX - 82443BX Host")
-	DEVICE( INTEL,		INTEL_82443BX_1,"440BX - 82443BX AGP")
-	DEVICE( INTEL,		INTEL_82443BX_2,"440BX - 82443BX Host (no AGP)")
-	DEVICE( INTEL,		INTEL_P6,	"Orion P6")
-	DEVICE( INTEL,		INTEL_82450GX,	"82450GX Orion P6")
-ENDVENDOR()
-
-VENDOR( KTI, "KTI" )
-	DEVICE(	KTI,		KTI_ET32P2,	"ET32P2")
-ENDVENDOR()
-
-VENDOR( ADAPTEC, "Adaptec" )
-	DEVICE( ADAPTEC,	ADAPTEC_7810,	"AIC-7810 RAID")
-	DEVICE( ADAPTEC,	ADAPTEC_7821,	"AIC-7860")
-	DEVICE( ADAPTEC,	ADAPTEC_38602,	"AIC-7860")
-	DEVICE( ADAPTEC,	ADAPTEC_7850,	"AIC-7850")
-	DEVICE( ADAPTEC,	ADAPTEC_7855,	"AIC-7855")
-	DEVICE( ADAPTEC,	ADAPTEC_5800,	"AIC-5800")
-	DEVICE( ADAPTEC,	ADAPTEC_3860,	"AIC-7860")
-	DEVICE( ADAPTEC,	ADAPTEC_7860,	"AIC-7860")
-	DEVICE( ADAPTEC,	ADAPTEC_7861,	"AIC-7861")
-	DEVICE( ADAPTEC,	ADAPTEC_7870,	"AIC-7870")
-	DEVICE( ADAPTEC,	ADAPTEC_7871,	"AIC-7871")
-	DEVICE( ADAPTEC,	ADAPTEC_7872,	"AIC-7872")
-	DEVICE( ADAPTEC,	ADAPTEC_7873,	"AIC-7873")
-	DEVICE( ADAPTEC,	ADAPTEC_7874,	"AIC-7874")
-	DEVICE( ADAPTEC,	ADAPTEC_7895,	"AIC-7895U")
-	DEVICE( ADAPTEC,	ADAPTEC_7880,	"AIC-7880U")
-	DEVICE( ADAPTEC,	ADAPTEC_7881,	"AIC-7881U")
-	DEVICE( ADAPTEC,	ADAPTEC_7882,	"AIC-7882U")
-	DEVICE( ADAPTEC,	ADAPTEC_7883,	"AIC-7883U")
-	DEVICE( ADAPTEC,	ADAPTEC_7884,	"AIC-7884U")
-	DEVICE( ADAPTEC,	ADAPTEC_7885,	"AIC-7885U")
-	DEVICE( ADAPTEC,	ADAPTEC_7886,	"AIC-7886U")
-	DEVICE( ADAPTEC,	ADAPTEC_7887,	"AIC-7887U")
-	DEVICE( ADAPTEC,	ADAPTEC_7888,	"AIC-7888U")
-	DEVICE( ADAPTEC,	ADAPTEC_1030,	"ABA-1030 DVB receiver")
-ENDVENDOR()
-
-VENDOR( ADAPTEC2, "Adaptec" )
-	DEVICE( ADAPTEC2,	ADAPTEC2_2940U2,"AHA-2940U2")
-	DEVICE( ADAPTEC2,	ADAPTEC2_2930U2,"AHA-2930U2")
-	DEVICE( ADAPTEC2,	ADAPTEC2_7890B,	"AIC-7890/1")
-	DEVICE( ADAPTEC2,	ADAPTEC2_7890,	"AIC-7890/1")
-	DEVICE( ADAPTEC2,	ADAPTEC2_3940U2,"AHA-3940U2")
-	DEVICE( ADAPTEC2,	ADAPTEC2_3950U2D,"AHA-3950U2D")
-	DEVICE( ADAPTEC2,	ADAPTEC2_7896,	"AIC-7896/7")
-	DEVICE( ADAPTEC2,	ADAPTEC2_7892A,	"AIC-7892")
-	DEVICE( ADAPTEC2,	ADAPTEC2_7892B,	"AIC-7892")
-	DEVICE( ADAPTEC2,	ADAPTEC2_7892D,	"AIC-7892")
-	DEVICE( ADAPTEC2,	ADAPTEC2_7892P,	"AIC-7892")
-	DEVICE( ADAPTEC2,	ADAPTEC2_7899A,	"AIC-7899")
-	DEVICE( ADAPTEC2,	ADAPTEC2_7899B,	"AIC-7899")
-	DEVICE( ADAPTEC2,	ADAPTEC2_7899D,	"AIC-7899")
-	DEVICE( ADAPTEC2,	ADAPTEC2_7899P,	"AIC-7899")
-ENDVENDOR()
-
-VENDOR( ATRONICS, "Atronics" )
-	DEVICE( ATRONICS,	ATRONICS_2015,	"IDE-2015PL")
-ENDVENDOR()
-
-VENDOR( TIGERJET, "TigerJet" )
-	DEVICE( TIGERJET,	TIGERJET_300,	"Tiger300 ISDN")
-ENDVENDOR()
-
-VENDOR( ARK, "ARK" )
-	DEVICE( ARK,		ARK_STING,	"Stingray")
-	DEVICE( ARK,		ARK_STINGARK,	"Stingray ARK 2000PV")
-	DEVICE( ARK,		ARK_2000MT,	"2000MT")
-ENDVENDOR()
-
-#undef VENDOR
-#undef ENDVENDOR
-#undef DEVICE
diff --git a/drivers/pci/gen-devlist.c b/drivers/pci/gen-devlist.c
new file mode 100644
index 0000000000000000000000000000000000000000..b9809f744d55f05c968a91d09052454a6c28d136
--- /dev/null
+++ b/drivers/pci/gen-devlist.c
@@ -0,0 +1,66 @@
+/*
+ *	Generate devlist.h from the PCI ID file.
+ *
+ *	(c) 1999 Martin Mares <mj@ucw.cz>
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+static void
+pq(char *c)
+{
+	while (*c) {
+		if (*c == '"')
+			printf("\\\"");
+		else
+			putchar(*c);
+		c++;
+	}
+}
+
+int
+main(void)
+{
+	char line[1024], *c, vend[8];
+	int vendors = 0;
+
+	while (fgets(line, sizeof(line)-1, stdin)) {
+		if ((c = strchr(line, '\n')))
+			*c = 0;
+		if (!line[0] || line[0] == '#')
+			continue;
+		if (line[1] == ' ') {
+			vend[0] = 0;
+			continue;
+		}
+		if (line[0] == '\t') {
+			if (vend[0] && strlen(line) > 5 && line[5] == ' ') {
+				c = line + 5;
+				while (*c == ' ')
+					*c++ = 0;
+				printf("\tDEVICE(%s,%s,\"", vend, line+1);
+				pq(c);
+				puts("\")");
+			}
+		} else if (strlen(line) > 4 && line[4] == ' ') {
+			c = line + 4;
+			while (*c == ' ')
+				*c++ = 0;
+			if (vendors)
+				puts("ENDVENDOR()\n");
+			vendors++;
+			strcpy(vend, line);
+			printf("VENDOR(%s,\"", vend);
+			pq(c);
+			puts("\")");
+		}
+	}
+	puts("ENDVENDOR()\n\
+\n\
+#undef VENDOR\n\
+#undef DEVICE\n\
+#undef ENDVENDOR");
+
+	return 0;
+}
diff --git a/drivers/pci/names.c b/drivers/pci/names.c
index 52d0492368fb4c226679af1ed583dc5e8f6879f5..81dafad61c96585de257eccd4ec5550dc47459ea 100644
--- a/drivers/pci/names.c
+++ b/drivers/pci/names.c
@@ -39,11 +39,11 @@ struct pci_vendor_info {
 
 #define VENDOR( vendor, name )		static struct pci_device_info __devices_##vendor[] __initdata = {
 #define ENDVENDOR()			};
-#define DEVICE( vendor, device, name )	{ PCI_DEVICE_ID_##device, 0, __devicestr_##vendor##device },
+#define DEVICE( vendor, device, name )	{ 0x##device, 0, __devicestr_##vendor##device },
 #include "devlist.h"
 
 static const struct pci_vendor_info __initdata pci_vendor_list[] = {
-#define VENDOR( vendor, name )		{ PCI_VENDOR_ID_##vendor, sizeof(__devices_##vendor) / sizeof(struct pci_device_info), __vendorstr_##vendor, __devices_##vendor },
+#define VENDOR( vendor, name )		{ 0x##vendor, sizeof(__devices_##vendor) / sizeof(struct pci_device_info), __vendorstr_##vendor, __devices_##vendor },
 #define ENDVENDOR()
 #define DEVICE( vendor, device, name )
 #include "devlist.h"
diff --git a/drivers/pci/pci.ids b/drivers/pci/pci.ids
new file mode 100644
index 0000000000000000000000000000000000000000..d9b44d1e009c4859c5367b998081b669cc2c312c
--- /dev/null
+++ b/drivers/pci/pci.ids
@@ -0,0 +1,3640 @@
+#
+#	List of PCI ID's
+#
+#	Maintained by Martin Mares <pci-ids@ucw.cz>
+#	If you have any new entries, send them to the maintainer.
+#
+#	$Id: pci.ids,v 1.41 1999/10/30 09:25:10 mj Exp $
+#
+
+# Vendors, devices and subsystems. Please keep sorted.
+
+# Syntax:
+# vendor  vendor_name
+#	device  device_name				<-- single tab
+#		subvendor subdevice  subsystem_name	<-- two tabs
+
+0000  Gammagraphx, Inc.
+001a  Ascend Communications, Inc.
+0033  Paradyne corp.
+003d  Lockheed Martin-Marietta Corp
+0070  Hauppage computer works Inc.
+0675  Dynalink
+	1700  IS64PH ISDN Adapter
+	1702  IS64PH ISDN Adapter
+0a89  BREA Technologies Inc
+0e11  Compaq Computer Corporation
+	0001  PCI to EISA Bridge
+	0002  PCI to ISA Bridge
+	0508  Netelligent 4/16 Token Ring
+	1000  Triflex/Pentium Bridge, Model 1000
+	2000  Triflex/Pentium Bridge, Model 2000
+	3032  QVision 1280/p
+	3033  QVision 1280/p
+	3034  QVision 1280/p
+	4000  4000 [Triflex]
+	6010  HotPlug PCI Bridge 6010
+	a0f3  Triflex PCI to ISA Bridge
+	ae10  Smart-2/P RAID Controller
+		0e11 4030  Smart-2/P Array Controller
+		0e11 4031  Smart-2SL Array Controller
+		0e11 4032  Smart Array Controller
+		0e11 4033  Smart 3100ES Array Controller
+	ae29  MIS-L
+	ae2a  MPC
+	ae2b  MIS-E
+	ae32  Netelligent 10/100
+	ae34  Netelligent 10
+	ae35  Integrated NetFlex-3/P
+	ae40  Netelligent 10/100 Dual
+	ae43  ProLiant Integrated Netelligent 10/100
+	ae69  CETUS-L
+	ae6c  Northstar
+	b011  Integrated Netelligent 10/100
+	b012  Netelligent 10 T/2
+	b030  Netelligent WS 5100
+	b04a  10/100TX WOL UTP Controller
+	b0c6  10/100TX Embedded WOL UTP Controller
+	b0d7  NC3121 (Rev A & B)
+	f130  NetFlex-3/P ThunderLAN 1.0
+	f150  NetFlex-3/P ThunderLAN 2.3
+1000  Symbios Logic Inc. (formerly NCR)
+	0001  53c810
+		1000 1000  8100S
+	0002  53c820
+	0003  53c825
+	0004  53c815
+	0005  53c810AP
+	0006  53c860
+	000b  53c896
+	000c  53c895
+	000d  53c885
+	000f  53c875
+		0e11 7004  Embedded Ultra Wide SCSI Controller
+		1092 8760  FirePort 40 Dual SCSI Controller
+		1de1 3904  DC390F Ultra Wide SCSI Controller
+	0012  53c895a
+	008f  53c875J
+		1092 8000  FirePort 40 SCSI Controller
+		1092 8760  FirePort 40 Dual SCSI Host Adapter
+	0701  83C885
+	0702  Yellowfin G-NIC gigabit ethernet
+		1318 0000  PEI100X
+	0901  61C102
+	1000  63C815
+1001  Initio
+	9100  INI-9100/9100W SCSI Host
+1002  ATI Technologies Inc
+	4158  68800AX [Mach32]
+	4354  215CT [Mach64 CT]
+	4358  210888CX [Mach64 CX]
+	4554  210888ET [Mach64 ET]
+	4742  3D Rage Pro AGP 1X/2X
+	4744  3D Rage Pro AGP 1X
+	4747  3D Rage Pro
+	4749  3D Rage Pro
+	474c  Rage XC
+	474d  Rage XL AGP
+	474e  Rage XC AGP
+	474f  Rage XL
+	4750  3D Rage Pro 215GP
+	4751  3D Rage Pro 215GQ
+	4753  Rage XC
+	4754  3D Rage I/II 215GT [Mach64 GT]
+	4755  3D Rage II+ 215GTB [Mach64 GTB]
+	4756  3D Rage IIC 215IIC [Mach64 GT IIC]
+	4757  3D Rage IIC AGP
+	4758  210888GX [Mach64 GX]
+	4759  3D Rage IIC
+	475a  3D Rage IIC AGP
+	4c42  3D Rage LT Pro AGP-133
+		0e11 b10e  3D Rage LT Pro (Compaq Armada 1750)
+	4c44  3D Rage LT Pro AGP-66
+	4c47  3D Rage LT-G 215LG
+	4c49  3D Rage LT Pro
+	4c4d  3D Rage P/M Mobility AGP 2x
+	4c4e  3D Rage L Mobility AGP 2x
+	4c50  3D Rage LT Pro
+	4c51  3D Rage LT Pro
+	4c52  3D Rage P/M Mobility
+	4c53  3D Rage L Mobility
+	4c54  264LT [Mach64 LT]
+	5041  Rage 128 PA
+	5042  Rage 128 PB
+	5043  Rage 128 PC
+	5044  Rage 128 PD
+	5045  Rage 128 PE
+	5046  Rage 128 PF
+	5047  Rage 128 PG
+	5048  Rage 128 PH
+	5049  Rage 128 PI
+	504A  Rage 128 PJ
+	504B  Rage 128 PK
+	504C  Rage 128 PL
+	504D  Rage 128 PM
+	504E  Rage 128 PN
+	504F  Rage 128 PO
+	5050  Rage 128 PP
+	5051  Rage 128 PQ
+	5052  Rage 128 PR
+	5053  Rage 128 PS
+	5054  Rage 128 PT
+	5055  Rage 128 PU
+	5056  Rage 128 PV
+	5057  Rage 128 PW
+	5058  Rage 128 PX
+	5245  Rage 128 RE
+	5246  Rage 128 RF
+	524b  Rage 128 RK
+	524c  Rage 128 RL
+	5345  Rage 128 SE
+	5346  Rage 128 SF
+	5347  Rage 128 SG
+	534B  Rage 128 SK
+	534C  Rage 128 SL
+	534D  Rage 128 SM
+	5354  Mach 64 VT
+		1002 5654  Mach 64 reference
+	5654  264VT [Mach64 VT]
+	5655  264VT3 [Mach64 VT3]
+	5656  264VT4 [Mach64 VT4]
+1003  ULSI Systems
+	0201  US201
+1004  VLSI Technology Inc
+	0005  82C592-FC1
+	0006  82C593-FC1
+	0007  82C594-AFC2
+	0008  82C596/7 [Wildcat]
+	0009  82C597-AFC2
+	000c  82C541 [Lynx]
+	000d  82C543 [Lynx]
+	0101  82C532
+	0102  82C534
+	0103  82C538
+	0104  82C535
+	0105  82C147
+	0200  82C975
+	0280  82C925
+	0702  VAS96011 [Golden Gate II]
+1005  Avance Logic Inc. [ALI]
+	2064  ALG2032/2064
+	2128  ALG2364A
+	2301  ALG2301
+	2302  ALG2302
+	2364  ALG2364
+	2464  ALG2364A
+	2501  ALG2564A/25128A
+1006  Reply Group
+1007  NetFrame Systems Inc
+1008  Epson
+100a  Phoenix Technologies
+100b  National Semiconductor Corporation
+	0001  DP83810
+	0002  87415
+	d001  87410
+100c  Tseng Labs Inc
+	3202  ET4000/W32p rev A
+	3205  ET4000/W32p rev B
+	3206  ET4000/W32p rev C
+	3207  ET4000/W32p rev D
+	3208  ET6000
+	4702  ET6300
+100d  AST Research Inc
+100e  Weitek
+	9000  P9000
+	9001  P9000
+	9100  P9100
+1010  Video Logic, Ltd.
+1011  Digital Equipment Corporation
+	0001  DECchip 21050
+	0002  DECchip 21040 [Tulip]
+	0004  DECchip 21030 [TGA]
+	0007  NVRAM [Zephyr NVRAM]
+	0008  KZPSA [KZPSA]
+	0009  DECchip 21140 [FasterNet]
+		10b8 2001  SMC9332BDT EtherPower 10/100
+		10b8 2002  SMC9332BVT EtherPower T4 10/100
+		10b8 2003  SMC9334BDT EtherPower 10/100 (1-port)
+		1112 2300  RNS2300 Fast Ethernet
+		1112 2320  RNS2320 Fast Ethernet
+		1112 2340  RNS2340 Fast Ethernet
+		1113 1207  EN-1207-TX Fast Ethernet
+		1109 2400  ANA-6944A/TX Fast Ethernet
+		1186 1100  DFE-500TX Fast Ethernet
+		1282 9100  AEF-380TXD Fast Ethernet
+		2646 0001  KNE100TX Fast Ethernet
+	000a  21230 Video Codec
+	000d  PBXGB [TGA2]
+	000f  DEFPA
+	0014  DECchip 21041 [Tulip Pass 3]
+		1186 0100  DE-530+
+	0016  DGLPB [OPPO]
+	0019  DECchip 21142/43
+		1011 500b  DE500 Fast Ethernet
+		1014 0001  10/100 EtherJet Cardbus
+		1025 0315  ALN315 Fast Ethernet
+		108d 0016  Rapidfire 2327 10/100 Ethernet
+		10b8 2005  SMC8032DT Extreme Ethernet 10/100
+		10ef 8169  Cardbus Fast Ethernet
+		1109 2a00  ANA-6911A/TX Fast Ethernet
+		1109 2b00  ANA-6911A/TXC Fast Ethernet
+		1109 3000  ANA-6922/TX Fast Ethernet
+		1113 1207  Cheetah Fast Ethernet
+		1113 2220  Cardbus Fast Ethernet
+		115d 0002  Cardbus Ethernet 10/100
+		1179 0203  Fast Ethernet
+		1179 0204  Cardbus Fast Ethernet
+		1186 1101  DFE-500TX Fast Ethernet
+		1186 1102  DFE-500TX Fast Ethernet
+		1266 0004  Eagle Fast EtherMAX
+		12af 0019  NetFlyer Cardbus Fast Ethernet
+		1395 0001  10/100 Ethernet CardBus PC Card
+		8086 0001  EtherExpress PRO/100 Mobile CardBus 32
+	0021  DECchip 21052
+	0022  DECchip 21150
+	0024  DECchip 21152
+	0025  DECchip 21153
+	0026  DECchip 21154
+	0045  DECchip 21553
+	0046  DECchip 21554
+1012  Micronics Computers Inc
+1013  Cirrus Logic
+	0038  GD 7548
+	0040  GD 7555 Flat Panel GUI Accelerator
+	004c  GD 7556 Video/Graphics LCD/CRT Ctrlr
+	00a0  GD 5430/40 [Alpine]
+	00a2  GD 5432 [Alpine]
+	00a4  GD 5434-4 [Alpine]
+	00a8  GD 5434-8 [Alpine]
+	00ac  GD 5436 [Alpine]
+	00b0  GD 5440
+	00b8  GD 5446
+	00bc  GD 5480
+	00d0  GD 5462
+	00d2  GD 5462 [Laguna I]
+	00d4  GD 5464 [Laguna]
+	00d6  GD 5465 [Laguna]
+	00e8  GD 5436U
+	1100  CL 6729
+	1110  PD 6832
+	1112  PD 6834 PCMCIA/CardBus Ctrlr
+	1113  PD 6833 PCMCIA/CardBus Ctrlr
+	1200  GD 7542 [Nordic]
+	1202  GD 7543 [Viking]
+	1204  GD 7541 [Nordic Light]
+	4400  CD 4400
+	6001  CS 4610/11 [CrystalClear SoundFusion Audio Accelerator]
+	6003  CS 4614/22/24 [CrystalClear SoundFusion Audio Accelerator]
+1014  IBM
+	0002  PCI to MCA Bridge
+	0005  Alta Lite
+	0007  Alta MP
+	000a  Fire Coral
+	0018  TR Auto LANstreamer
+	001b  GXT-150P
+	001d  82G2675
+	0020  MCA
+	0022  IBM27-82351
+	002d  Python
+	002e  ServeRAID controller
+	0036  Miami
+	003e  16/4 Token ring UTP/STP controller
+		1014 003E  Token-Ring Adapter
+		1014 00CD  Token-Ring Adapter + Wake-On-LAN
+		1014 00CE  16/4 Token-Ring Adapter 2
+		1014 00CF  16/4 Token-Ring Adapter Special
+		1014 00E4  High-Speed 100/16/4 Token-Ring Adapter
+		1014 00E5  16/4 Token-Ring Adapter 2 + Wake-On-LAN
+	0046  MPIC interrupt controller
+	0053  25 MBit ATM Controller
+	0057  MPEG PCI Bridge
+	005C  i82557B 10/100
+	007d  3780IDSP [MWave]
+	0095  20H2999 PCI Docking Bridge
+	00b7  256-bit Graphics Rasterizer [Fire GL1]
+	ffff  MPIC-2 interrupt controller
+1015  LSI Logic Corp of Canada
+1016  ICL Personal Systems
+1017  SPEA Software AG
+	5343  SPEA 3D Accelerator
+1018  Unisys Systems
+1019  Elitegroup Computer Systems
+101a  AT&T GIS (NCR)
+	0005  100VG ethernet
+101b  Vitesse Semiconductor
+101c  Western Digital
+	0193  33C193A
+	0196  33C196A
+	0197  33C197A
+	0296  33C296A
+	3193  7193
+	3197  7197
+	3296  33C296A
+	4296  34C296
+	9710  Pipeline 9710
+	9712  Pipeline 9712
+	c24a  90C
+101e  American Megatrends Inc.
+	9010  MegaRAID
+	9060  MegaRAID
+101f  PictureTel
+1020  Hitachi Computer Products
+1021  OKI Electric Industry Co. Ltd.
+1022  Advanced Micro Devices [AMD]
+	2000  79c970 [PCnet LANCE]
+		103c 104c  Ethernet with LAN remote power Adapter
+		103c 1064  Ethernet with LAN remote power Adapter
+		103c 1065  Ethernet with LAN remote power Adapter
+		103c 106c  Ethernet with LAN remote power Adapter
+		103c 106e  Ethernet with LAN remote power Adapter
+		103c 10ea  Ethernet with LAN remote power Adapter
+		1113 1220  EN1220 10/100 Fast Ethernet
+		1259 2450  AT-2450 10/100 Fast Ethernet
+		1259 2700  AT-2700TX 10/100 Fast Ethernet
+		1259 2701  AT-2700FX 100Mb Ethernet
+	2001  79c978 [HomePNA]
+	2020  53c974 [PCscsi]
+	2040  79c974
+1023  Trident Microsystems
+	0194  82C194
+	2000  4DWave DX
+	2001  4DWave NX
+	8400  CyberBlade/i7
+	8420  CyberBlade/i7d
+	8500  CyberBlade/i1
+	9320  TGUI 9320
+	9382  Cyber 9382 [Reference design]
+	9383  Cyber 9383 [Reference design]
+	9385  Cyber 9385 [Reference design]
+	9386  Cyber 9386
+	9388  Cyber 9388
+	9397  Cyber 9397
+	939a  Cyber 9397DVD
+	9420  TGUI 9420
+	9430  TGUI 9430
+	9440  TGUI 9440
+	9460  TGUI 9460
+	9470  TGUI 9470
+	9520  Cyber 9520
+	9525  Cyber 9525
+	9660  TGUI 9660/968x/968x
+	9680  TGUI 9680
+	9682  TGUI 9682
+	9683  TGUI 9683
+	9685  ProVIDIA 9685
+	9750  3DIm`age 975
+	9753  TGUI 9753
+	9754  TGUI 9754
+	9759  TGUI 975
+	9783  TGUI 9783
+	9785  TGUI 9785
+	9850  3DImage 9850
+	9880  Blade 3D PCI/AGP
+1024  Zenith Data Systems
+1025  Acer Incorporated [ALI]
+	1435  M1435
+	1445  M1445
+	1449  M1449
+	1451  M1451
+	1461  M1461
+	1489  M1489
+	1511  M1511
+	1513  M1513
+	1531  M1531
+	1533  M1533
+	3141  M3141
+	3143  M3143
+	3145  M3145
+	3147  M3147
+	3149  M3149
+	3151  M3151
+	5217  M5217H
+	5219  M5219
+	5225  M5225
+	5229  M5229
+	5235  M5235
+1028  Dell Computer Corporation
+1029  Siemens Nixdorf IS
+102a  LSI Logic
+	0000  HYDRA
+	0010  ASPEN
+102b  Matrox Graphics, Inc.
+#DJ: I've a suspicion that 0010 is a duplicate of 0d10.
+	0010  MGA-I [Impression?]
+	0518  MGA-II [Athena]
+	0519  MGA 2064W [Millennium]
+	051a  MGA 1064SG [Mystique]
+		1100 102b  MGA-1084SG Mystique
+	051b  MGA 2164W [Millennium II]
+	051e  MGA 1064SG [Mystique] AGP
+	051f  MGA 2164W [Millennium II] AGP
+	0520  MGA G200
+		102b dbc2  G200 Multi-Monitor
+		102b dbc8  G200 Multi-Monitor
+		102b dbe2  G200 Multi-Monitor
+		102b dbe8  G200 Multi-Monitor
+		102b ff03  Millennium G200 SD
+		102b ff04  Marvel G200
+	0521  MGA G200 AGP
+		1014 ff03  Millennium G200 AGP
+		102b 48e9  Mystique G200 AGP
+		102b 48f8  Millennium G200 SD AGP
+		102b 4a60  Millennium G200 LE AGP
+		102b 4a64  Millennium G200 AGP
+		102b c93c  Millennium G200 AGP
+		102b c9b0  Millennium G200 AGP
+		102b c9bc  Millennium G200 AGP
+		102b ca60  Millennium G250 LE AGP
+		102b ca6c  Millennium G250 AGP
+		102b dbbc  Millennium G200 AGP
+		102b f806  Mystique G200 Video AGP
+		102b ff02  Mystique G200 AGP
+		102b ff03  Millennium G200 AGP
+		102b ff04  Marvel G200 AGP
+	0525  MGA G400 AGP
+		0e11 b16f  Matrox MGA-G400 AGP
+		102b 0328  Millennium G400 16Mb SDRAM
+		102b 0338  Millennium G400 16Mb SDRAM
+		102b 19d8  Millennium G400 16Mb SGRAM
+		102b 19f8  Millennium G400 32Mb SGRAM
+		102b 2159  Millennium G400 Dual Head 16Mb
+		102b 2179  Millennium G400 MAX/Dual Head 32Mb
+		102b 217d  Millennium G400 Dual Head Max
+		102b 2f58  Millennium G400
+		102b 2f78  Millennium G400
+		102b 3693  Marvel G400 AGP
+		b16f 0e11  Matrox MGA-G400 AGP
+	0d10  MGA Ultima/Impression
+	1000  MGA G100 [Productiva]
+		102b ff01  Productiva G100
+		102b ff05  Productiva G100 Multi-Monitor
+	1001  MGA G100 [Productiva] AGP
+		102b ff05  MGA-G100 Productiva AGP Multi-Monitor
+	2007  MGA Mistral
+	4536  VIA Framegrabber
+102c  Chips and Technologies
+	00b8  F64310
+	00c0  F69000 HiQVideo
+	00d0  F65545
+	00d8  F65545
+	00dc  F65548
+	00e0  F65550
+	00e4  F65554
+	00e5  F65555 HiQVPro
+		0e11 b049  Armada 1700 Laptop Display Controller
+	00f0  F68554
+	00f4  F68554 HiQVision
+	00f5  F68555
+102d  Wyse Technology Inc.
+	50dc  3328 Audio
+102e  Olivetti Advanced Technology
+102f  Toshiba America
+	0009  r4x00
+	0020  ATM Meteor 155
+1030  TMC Research
+1031  Miro Computer Products AG
+	5601  DC20 ASIC
+	5607  Video I/O & motion JPEG compressor
+	5631  Media 3D
+	6057  MiroVideo DC10/DC30+
+1032  Compaq
+1033  NEC Corporation
+	0001  PCI to 486-like bus Bridge
+	0002  PCI to VL98 Bridge
+	0003  ATM Controller
+	0004  R4000 PCI Bridge
+	0005  PCI to 486-like bus Bridge
+	0007  PCI to UX-Bus Bridge
+	001a  [Nile II]
+	0021  Vrc4373 [Nile I]
+	0029  PowerVR PCX1
+	002a  PowerVR 3D
+	0035  USB
+	0046  PowerVR PCX2 [midas]
+	005a  Vrc5074 [Nile 4]
+	0063  Firewarden
+	0067  PowerVR Neon 250 Chipset
+		1010 0020  PowerVR Neon 250 AGP 32Mb
+		1010 0080  PowerVR Neon 250 AGP 16Mb
+		1010 0088  PowerVR Neon 250 16Mb
+		1010 0090  PowerVR Neon 250 AGP 16Mb
+		1010 0098  PowerVR Neon 250 16Mb
+		1010 00a0  PowerVR Neon 250 AGP 32Mb
+		1010 00a8  PowerVR Neon 250 32Mb
+		1010 0120  PowerVR Neon 250 AGP 32Mb
+	0074  56k Voice Modem
+		1033 8014  RCV56ACF 56k Voice Modem
+	009b  Vrc5476
+1034  Framatome Connectors USA Inc.
+1035  Comp. & Comm. Research Lab
+1036  Future Domain Corp.
+	0000  TMC-18C30 [36C70]
+1037  Hitachi Micro Systems
+1038  AMP, Inc
+1039  Silicon Integrated Systems [SiS]
+	0001  5591/5592 AGP
+	0002  SG86C202
+	0006  85C501/2/3
+	0008  85C503/5513
+	0009  ACPI
+	0200  5597/5598 VGA
+	0204  82C204
+	0205  SG86C205
+	0406  85C501/2
+	0496  85C496
+	0530  530 Host
+	0597  5513C
+	0601  85C601
+	0620  620 Host
+	0900  SiS900 10/100 Ethernet
+	3602  83C602
+	5107  5107
+	5511  5511/5512
+	5513  5513
+	5517  5517
+	5571  5571
+	5591  5591/5592 Host
+	5597  5597 [SiS5582]
+	5600  5600 Host
+	6204  Video decoder & MPEG interface
+	6236  6236 3D-AGP
+	6306  6306 3D-AGP
+	6326  86C326
+		1092 0a50  SpeedStar A50
+		1092 0a70  SpeedStar A70
+		1092 4910  SpeedStar A70 
+		1092 4920  SpeedStar A70 
+	7001  7001
+	7007  OHCI Compliant FireWire Controller
+103a  Seiko Epson Corporation
+103b  Tatung Co. of America
+103c  Hewlett-Packard Company
+	1030  J2585A
+	1031  J2585B
+	1040  J2973A DeskDirect 10BaseT NIC
+	1041  J2585B DeskDirect 10/100 NIC
+	1042  J2970A DeskDirect 10BaseT/2 NIC
+	1064  79C970 PCnet Ethernet Controller
+	2910  E2910A
+	2925  E2925A
+103e  Solliday Engineering
+103f  Synopsys/Logic Modeling Group
+1040  Accelgraphics Inc.
+1041  Computrend
+1042  Micron
+	1000  FDC 37C665
+	1001  37C922
+	3000  Samurai_0
+	3010  Samurai_1
+	3020  Samurai_IDE
+1043  Asustek Computer, Inc.
+1044  Distributed Processing Technology
+	1012  Domino RAID Engine
+	a400  SmartCache/Raid I-IV Controller
+	a500  PCI Bridge
+	a501  SmartRAID V Controller
+1045  OPTi Inc.
+	a0f8  82C750 [Vendetta] USB Controller
+	c101  92C264
+	c178  92C178
+	c556  82X556 [Viper]
+	c557  82C557 [Viper-M]
+	c558  82C558 [Viper-M ISA+IDE]
+	c567  82C750 [Vendetta], device 0
+	c568  82C750 [Vendetta], device 1
+	c569  82C579 [Viper XPress+ Chipset]
+	c621  82C621
+	c700  82C700
+	c701  82C701 [FireStar Plus]
+	c814  82C814 [Firebridge 1]
+	c822  82C822
+	c824  82C824
+	c825  82C825 [Firebridge 2]
+	c861  82C861
+	c895  82C895
+	d568  82C825 [Firebridge 2]
+1046  IPC Corporation, Ltd.
+1047  Genoa Systems Corp
+1048  Elsa AG
+	1000  QuickStep 1000
+	3000  QuickStep 3000
+1049  Fountain Technologies, Inc.
+104a  SGS Thomson Microelectronics
+	0008  STG 2000X
+	0009  STG 1764X
+	1746  STG 1764X
+	3520  MPEG-II decoder card
+104b  BusLogic
+	0140  BT-946C (old) [multimaster  01]
+	1040  BT-946C (BA80C30) [MultiMaster 10]
+	8130  Flashpoint LT
+104c  Texas Instruments
+	0500  100 MBit LAN Controller
+	0508  TMS380C2X Compressor Interface
+	1000  Eagle i/f AS
+	3d04  TVP4010 [Permedia]
+	3d07  TVP4020 [Permedia 2]
+		1092 0127  FIRE GL 1000 PRO
+		1092 0136  FIRE GL 1000 PRO
+		1092 0141  FIRE GL 1000 PRO
+		1092 0146  FIRE GL 1000 PRO
+		1092 0148  FIRE GL 1000 PRO
+		1092 0149  FIRE GL 1000 PRO
+		1092 0152  FIRE GL 1000 PRO
+		1092 0154  FIRE GL 1000 PRO
+		1092 0155  FIRE GL 1000 PRO
+		1092 0156  FIRE GL 1000 PRO
+		1092 0157  FIRE GL 1000 PRO
+		1097 3d01  Jeronimo Pro
+		3d3d 0100  Reference Permedia 2 3D
+	8000  LYNX FireWire Host Controller
+	8009  OHCI Compliant FireWire Controller
+	8019  TSB12LV23 OHCI Compliant IEEE-1394 Controller
+	a001  TDC1570
+	a100  TDC1561
+	ac10  PCI1050
+	ac11  PCI1053
+	ac12  PCI1130
+	ac13  PCI1031
+	ac15  PCI1131
+	ac16  PCI1250
+	ac17  PCI1220
+	ac18  PCI1260
+	ac19  PCI1221
+	ac1a  PCI1210
+	ac1b  PCI1221
+	ac1c  PCI1225
+	ac1d  PCI1251
+	ac20  TI 2030
+	fe00  FireWire Host Controller
+	fe03  12C01A FireWire Host Controller
+104d  Sony Corporation
+104e  Oak Technology, Inc
+	0017  OTI-64017
+	0107  OTI-107 [Spitfire]
+	0111  OTI-64111 [Spitfire]
+	0217  OTI-64217
+	0317  OTI-64317
+104f  Co-time Computer Ltd
+1050  Winbond Electronics Corp
+	0000  NE2000
+	0001  W83769F
+	0105  W82C105
+	0840  W89C840
+	0940  W89C940
+	5a5a  W89C940F
+	9970  W9970CF
+1051  Anigma, Inc.
+1053  Young Micro Systems
+1054  Hitachi, Ltd
+1055  EFAR Microsystems
+1056  ICL
+# Motorola made a mistake and used this value, please duplicate Moto
+# entries here -- Cort
+1507  Motorola Computer Group
+	0001  MPC105 [Eagle]
+	0002  MPC106 [Grackle]
+	0100  MC145575 [HFC-PCI]
+	0431  KTI829c 100VG
+	4801  Raven
+	4802  Falcon
+	4803  Hawk
+	4806  CPX8216
+1057  Motorola Computer Group
+	0001  MPC105 [Eagle]
+	0002  MPC106 [Grackle]
+	0100  MC145575 [HFC-PCI]
+	0431  KTI829c 100VG
+	4801  Raven
+	4802  Falcon
+	4803  Hawk
+	4806  CPX8216
+1058  Electronics & Telecommunications RSH
+1059  Teknor Industrial Computers Inc
+105a  Promise Technology, Inc.
+	4d33  20246
+	4d38  20262
+	5300  DC5300
+105b  Foxconn International, Inc.
+105c  Wipro Infotech Limited
+105d  Number 9 Computer Company
+	2309  Imagine 128
+	2339  Imagine 128-II
+		105d 0000  Imagine 128 series 2 4Mb VRAM
+		105d 0001  Imagine 128 series 2 4Mb VRAM
+		105d 0002  Imagine 128 series 2 4Mb VRAM
+		105d 0003  Imagine 128 series 2 4Mb VRAM
+		105d 0004  Imagine 128 series 2 4Mb VRAM
+		105d 0005  Imagine 128 series 2 4Mb VRAM
+		105d 0006  Imagine 128 series 2 4Mb VRAM
+		105d 0007  Imagine 128 series 2 4Mb VRAM
+		105d 0008  Imagine 128 series 2e 4Mb DRAM
+		105d 0009  Imagine 128 series 2e 4Mb DRAM
+		105d 000a  Imagine 128 series 2 8Mb VRAM
+		105d 000b  Imagine 128 series 2 8Mb H-VRAM
+	493d  Imagine 128 T2R [Ticket to Ride]
+	5348  Revolution 4
+105e  Vtech Computers Ltd
+105f  Infotronic America Inc
+1060  United Microelectronics [UMC]
+	0001  UM82C881
+	0002  UM82C886
+	0101  UM8673F
+	0881  UM8881
+	0886  UM8886F
+	0891  UM8891A
+	1001  UM886A
+	673a  UM8886BF
+	8710  UM8710
+	886a  UM8886A
+	8881  UM8881F
+	8886  UM8886F
+	888a  UM8886A
+	8891  UM8891A
+	9017  UM9017F
+	9018  UM9018
+	9026  UM9026
+	e881  UM8881N
+	e886  UM8886N
+	e891  UM8891N
+1061  I.I.T.
+	0001  AGX016
+	0002  IIT3204/3501
+1062  Maspar Computer Corp
+1063  Ocean Office Automation
+1064  Alcatel
+1065  Texas Microsystems
+1066  PicoPower Technology
+	0000  PT80C826
+	0001  PT86C52x [Vesuvius]
+	0002  PT80C524 [Nile]
+	0005  National PC87550 System Controller
+	8002  PT80C524 [Nile]
+1067  Mitsubishi Electronics
+1068  Diversified Technology
+1069  Mylex Corporation
+	0001  DAC960P
+	0002  DAC960PD
+	0010  DAC960PX
+	ba55  eXtremeRAID support Device
+106a  Aten Research Inc
+106b  Apple Computer Inc.
+	0001  Bandit PowerPC host bridge
+	0002  Grand Central I/O
+	0003  Control Video
+	0004  PlanB Video-In
+	0007  O'Hare I/O
+	000e  Hydra Mac I/O
+	0010  Heathrow Mac I/O
+	0017  Paddington Mac I/O
+106c  Hyundai Electronics America
+	8803  Dual Window Graphics Accelerator
+	8804  LAN Controller
+	8805  100-BaseT LAN
+106d  Sequent Computer Systems
+106e  DFI, Inc
+106f  City Gate Development Ltd
+1070  Daewoo Telecom Ltd
+1071  Mitac
+1072  GIT Co Ltd
+1073  Yamaha Corporation
+	0002  YGV615 [RPA3 3D-Graphics Controller]
+	0003  YMF-740
+	0004  YMF-724
+	000C  YMF-740C [DS-1L Audio Controller]
+	000D  YMF-724F [DS-1 Audio Controller]
+	0010  YMF-744B [DS-1S Audio Controller]
+	0012  YMF-754 [DS-1E Audio Controller]
+1074  NexGen Microsystems
+	4e78  82c500/1
+1075  Advanced Integrations Research
+1076  Chaintech Computer Co. Ltd
+1077  Q Logic
+	1020  ISP1020
+	1022  ISP1022
+	1080  ISP1080
+	1240  ISP1240
+	2020  ISP2020A
+	2100  ISP2100
+1078  Cyrix Corporation
+	0000  5510 [Grappa]
+	0001  PCI Master
+	0002  5520 [Cognac]
+	0100  5530 Legacy [Kahlua]
+	0101  5530 SMI [Kahlua]
+	0102  5530 IDE [Kahlua]
+	0103  5530 Audio [Kahlua]
+	0104  5530 Video [Kahlua]
+1079  I-Bus
+107a  NetWorth
+107b  Gateway 2000
+107c  LG Electronics [Lucky Goldstar Co. Ltd]
+107d  LeadTek Research Inc.
+	0000  P86C850
+107e  Interphase Corporation
+	0001  ATM Interface Card
+	0002  100 VG AnyLan Controller
+	0008  155 Mbit ATM Controller
+107f  Data Technology Corporation
+	0802  SL82C105
+1080  Contaq Microsystems
+	0600  82C599
+	c691  Cypress CY82C691
+	c693  82c693
+1081  Supermac Technology
+	0d47  Radius PCI to NuBUS Bridge
+1082  EFA Corporation of America
+1083  Forex Computer Corporation
+	0001  FR710
+1084  Parador
+1085  Tulip Computers Int.B.V.
+1086  J. Bond Computer Systems
+1087  Cache Computer
+1088  Microcomputer Systems (M) Son
+1089  Data General Corporation
+108a  Bit3 Computer Corp.
+	0001  VME Bridge Model 617
+	0010  VME Bridge Model 618
+	3000  VME Bridge Model 2706
+108c  Oakleigh Systems Inc.
+108d  Olicom
+	0001  OC-3136/3137
+	0002  16/4 Token Ring
+	0004  OC-3139/3140 RapidFire Token-Ring 16/4
+	0005  OC-3250 GoCard Token-Ring 16/4
+	0006  OC-3530 RapidFire Token-Ring 100
+	0007  OC-3141 RapidFire Token-Ring 16/4
+	0011  OC-2315
+	0012  OC-2325
+	0013  OC-2183/2185
+	0014  OC-2326
+	0021  OC-6151/6152 [RapidFire ATM 155]
+	0022  ATM Adapter
+108e  Sun Microsystems Computer Corp.
+	0001  EBUS
+	1000  EBUS
+	1001  Happy Meal
+	5000  Simba Advanced PCI Bridge
+	8000  PCI Bus Module
+	a000  Ultra IIi
+108f  Systemsoft
+1090  Encore Computer Corporation
+1091  Intergraph Corporation
+	0020  3D graphics processor
+	0021  3D graphics processor w/Texturing
+	0040  3D graphics frame buffer
+	0041  3D graphics frame buffer
+	0060  Proprietary bus bridge
+	00E4  Powerstorm 4D50T
+	0720  Motion JPEG codec
+1092  Diamond Multimedia Systems
+	00a0  Speedstar Pro SE
+	00a8  Speedstar 64
+	08d4  Supra 2260 Modem
+	1092  Viper V330
+	6120  Maximum DVD
+	8810  Stealth SE
+	8811  Stealth 64/SE
+	8880  Stealth
+	8881  Stealth
+	88b0  Stealth 64
+	88b1  Stealth 64
+	88c0  Stealth 64
+	88c1  Stealth 64
+	88d0  Stealth 64
+	88d1  Stealth 64
+	88f0  Stealth 64
+	88f1  Stealth 64
+	9999  DMD-I0928-1 "Monster sound" sound chip
+1093  National Instruments
+	0160  PCI-DIO-96
+	0162  PCI-MIO-16XE-50
+	1170  PCI-MIO-16XE-10
+	1180  PCI-MIO-16E-1
+	1190  PCI-MIO-16E-4
+	1330  PCI-6031E
+	1350  PCI-6071E
+	2a60  PCI-6023E
+	c801  PCI-GPIB
+1094  First International Computers [FIC]
+1095  CMD Technology Inc
+	0640  PCI0640
+	0643  PCI0643
+	0646  PCI0646
+	0650  PBC0650A
+	0647  PCI0647
+	0670  USB0670
+	0673  USB0673
+1096  Alacron
+1097  Appian Technology
+1098  Quantum Designs (H.K.) Ltd
+	0001  QD-8500
+	0002  QD-8580
+1099  Samsung Electronics Co., Ltd
+109a  Packard Bell
+109b  Gemlight Computer Ltd.
+109c  Megachips Corporation
+109d  Zida Technologies Ltd.
+109e  Brooktree Corporation
+	0350  Bt848 TV with DMA push
+	0351  Bt849A Video capture
+	036e  Bt878
+		1851 1850  FlyVideo'98 - Video
+		1851 1851  FlyVideo II
+		1852 1852  FlyVideo'98 - Video (with FM Tuner)
+	036f  Bt879
+		1851 1850  FlyVideo'98 - Video	
+		1851 1851  FlyVideo II
+		1852 1852  FlyVideo'98 - Video (with FM Tuner)
+	0878  Bt878
+	2115  BtV 2115 Mediastream controller
+	2125  BtV 2125 Mediastream controller
+	2164  BtV 2164
+	2165  BtV 2165
+	8230  Bt8230 ATM Segment/Reassembly Ctrlr (SRC)
+	8472  Bt8472
+	8474  Bt8474
+109f  Trigem Computer Inc.
+10a0  Meidensha Corporation
+10a1  Juko Electronics Ind. Co. Ltd
+10a2  Quantum Corporation
+10a3  Everex Systems Inc
+10a4  Globe Manufacturing Sales
+10a5  Racal Interlan
+10a6  Informtech Industrial Ltd.
+10a7  Benchmarq Microelectronics
+10a8  Sierra Semiconductor
+	0000  STB Horizon 64
+10a9  Silicon Graphics
+	0003  IOC3
+	0005  RAD Audio
+	0009  Alteon Gigabit Ethernet
+10aa  ACC Microelectronics
+	0000  ACCM 2188
+10ab  Digicom
+10ac  Honeywell IAC
+10ad  Symphony Labs
+	0001  W83769F
+	0003  SL82C103
+	0005  SL82C105
+	0103  SL82c103
+	0105  SL82c105
+	0565  W83C553
+10ae  Cornerstone Technology
+10af  Micro Computer Systems Inc
+10b0  CardExpert Technology
+10b1  Cabletron Systems Inc
+10b2  Raytheon Company
+10b3  Databook Inc
+	3106  DB87144
+	b106  DB87144
+10b4  STB Systems Inc
+	1b1d  Velocity 128 3D
+		10b4 237e  Velocity 4400
+10b5  PLX Technology, Inc.
+	0001  i960 PCI bus interface
+	1076  VScom 800 8 port serial adaptor
+	1077  VScom 400 4 port serial adaptor
+	9036  9036
+	9050  PCI <-> IOBus Bridge
+	9060  9060
+	906d  9060SD
+		125c 0640  Aries 16000P
+	906e  9060ES
+	9080  9080
+		10b5 9080  9080 [real subsystem ID not set]
+10b6  Madge Networks
+	0001  Smart 16/4 Ringnode
+	0002  Smart 16/4 BM Mk2 Ringnode
+	0003  Smart 16/4 Ringnode
+		0e11 b0fd  NC4621 4/16 Token-Ring Adapter + WOL
+		10b6 0003  Smart 16/4 Ringnode Mk3
+		10b6 0007  Presto Mk2
+	0004  Smart 16/4 Ringnode (BM)
+	0006  16/4 Cardbus Adapter
+	0007  Presto
+	1000  Collage 25 ATM adaptor
+	1001  Collage 155 Server
+10b7  3Com Corporation
+	0001  3c985 1000BaseSX
+	3390  Token Link Velocity
+	3590  3c359 TokenLink Velocity XL
+	5057  3c575 [Megahertz] 10/100 LAN CardBus
+	5157  3c575 [Megahertz] 10/100 LAN CardBus
+	5900  3c590 10BaseT [Vortex]
+	5950  3c595 100BaseTX [Vortex]
+	5951  3c595 100BaseT4 [Vortex]
+	5952  3c595 100Base-MII [Vortex]
+	8811  Token ring
+	9000  3c900 10BaseT [Boomerang]
+	9001  3c900 Combo [Boomerang]
+	9004  3c900B-TPO [Etherlink XL TPO]
+	9005  3c900B-Combo [Etherlink XL Combo]
+	9006  3c900B-TPC [Etherlink XL TPC]
+	900A  3c900B-FL [Etherlink XL FL]
+	9050  3c905 100BaseTX [Boomerang]
+	9051  3c905 100BaseT4
+	9055  3c905B 100BaseTX [Cyclone]
+	9058  3c905B-Combo [Deluxe Etherlink XL 10/100]
+	905A  3c905B-FX [Fast Etherlink XL FX 10/100]
+	9200  3c905C-TX [Fast Etherlink]
+	9800  3c980-TX [Fast Etherlink XL Server Adapter]
+10b8  Standard Microsystems Corp [SMC]
+	0005  83C170QF
+		1055 e000  LANEPIC
+		1055 e002  LANEPIC
+		10b8 a011  EtherPower II 10/100
+		10b8 a014  EtherPower II 10/100
+		10b8 a015  EtherPower II 10/100
+		10b8 a016  EtherPower II 10/100
+		10b8 a017  EtherPower II 10/100
+	0006  LANEPIC
+	1000  FDC 37c665
+	1001  FDC 37C922
+	a011  83C170QF
+	b106  SMC34C90
+10b9  Acer Laboratories Inc. [ALi]
+	1435  M1435
+	1445  M1445
+	1449  M1449
+	1451  M1451
+	1461  M1461
+	1489  M1489
+	1511  M1511 [Aladdin]
+	1512  M1512 [Aladdin]
+	1513  M1513 [Aladdin]
+	1521  M1521 [Aladdin III]
+	1523  M1523
+	1531  M1531 [Aladdin IV]
+	1533  M1533 PCI to ISA Bridge [Aladdin IV]
+	1541  M1541
+	1543  M1543
+	1621  M1621
+	3141  M3141
+	3143  M3143
+	3145  M3145
+	3147  M3147
+	3149  M3149
+	3151  M3151
+	3307  M3307
+	3309  M3309
+	5212  M4803
+	5215  MS4803
+	5217  M5217H
+	5219  M5219
+	5225  M5225
+	5229  M5229 IDE
+	5235  M5225
+	5237  M5237 USB
+	5243  M5243
+	5247  M5247
+	7101  M7101 PMU
+10ba  Mitsubishi Electric Corp.
+	0301  AccelGraphics AccelECLIPSE
+10bb  Dapha Electronics Corporation
+10bc  Advanced Logic Research
+10bd  Surecom Technology
+	0e34  NE-34
+10be  Tseng Labs International Co.
+10bf  Most Inc
+10c0  Boca Research Inc.
+10c1  ICM Co., Ltd.
+10c2  Auspex Systems Inc.
+10c3  Samsung Semiconductors, Inc.
+	1100  Smartether100 SC1100 LAN Adapter (i82557B)
+10c4  Award Software International Inc.
+10c5  Xerox Corporation
+10c6  Rambus Inc.
+10c7  Media Vision
+10c8  Neomagic Corporation
+	0001  NM2070 [MagicGraph NM2070]
+	0002  NM2090 [MagicGraph 128V]
+	0003  NM2093 [MagicGraph 128ZV]
+	0004  NM2160 [MagicGraph 128XD]
+	0005  [MagicGraph 256AV]
+	0006  [MagicGraph 256ZX]
+	0083  [MagicGraph 128ZV Plus]
+	8005  [MagicMedia 256AV]
+10c9  Dataexpert Corporation
+10ca  Fujitsu Microelectr., Inc.
+10cb  Omron Corporation
+10cc  Mentor ARC Inc
+10cd  Advanced System Products, Inc
+	1100  ASC1100
+	1200  ASC1200 [(abp940) Fast SCSI-II]
+	1300  ABP940-U / ABP960-U
+	2300  ABP940-UW
+10ce  Radius
+10cf  Citicorp TTI
+	2001  mb86605
+10d0  Fujitsu Limited
+10d1  FuturePlus Systems Corp.
+10d2  Molex Incorporated
+10d3  Jabil Circuit Inc
+10d4  Hualon Microelectronics
+10d5  Autologic Inc.
+10d6  Cetia
+10d7  BCM Advanced Research
+10d8  Advanced Peripherals Labs
+10d9  Macronix, Inc. [MXIC]
+	0512  MX98713
+	0531  MX987x5
+	8625  MX86250
+	8888  MX86200
+10da  Compaq IPG-Austin
+	0508  TC4048 Token Ring 4/16
+	3390  Tl3c3x9
+10db  Rohm LSI Systems, Inc.
+10dc  CERN/ECP/EDU
+	0001  STAR/RD24 SCI-PCI (PMC)
+	0002  TAR/RD24 SCI-PCI (PMC) [ATT 2C15-3 (FPGA)  SCI bridge on PCI 5 Volt card]
+	0021  HIPPI destination
+	0022  HIPPI source
+	10dc  ATT2C15-3 FPGA
+10dd  Evans & Sutherland
+10de  nVidia Corporation
+	0008  NV1 EDGE 3D
+	0009  NV1 EDGE 3D
+	0020  Riva TNT 128
+		1043 0200  V3400 TNT
+		1092 0550  Viper V550
+		1092 0552  Viper V550
+		1102 1015  Graphics Blaster CT6710
+		1092 4804  Viper V550 
+		1092 4808  Viper V550 
+		1092 4810  Viper V550
+		1092 4812  Viper V550
+		1092 4815  Viper V550
+		1092 4820  Viper V550 with TV out
+		1092 4822  Viper V550
+		1092 4904  Viper V550 
+		1092 4914  Viper V550 
+		1092 8225  Viper V550
+	0028  Riva TNT2
+		1043 0200  AGP-V3800 SGRAM
+		1092 4804  Viper V770
+		1092 4a00  Viper V770
+		1092 4a02  Viper V770 Ultra
+		1092 6a02  Viper V770 Ultra
+		1092 7a02  Viper V770 Ultra
+		1102 1020  3D Blaster RIVA TNT2
+		14af 5810  Maxi Gamer Xentor
+	0029  Riva TNT2 Ultra
+		1043 0200  AGP-V3800 Deluxe
+		1102 1021  3D Blaster RIVA TNT2 Ultra
+		14af 5820  Maxi Gamer Xentor 32
+	002c  Vanta
+		1043 0200  AGP-V3800 Combat SDRAM
+		1092 6820  Viper V730
+		14af 5008  Maxi Gamer Phoenix 2
+	002d  Riva TNT2 Model 64
+		1043 0200  AGP-V3800M
+	00a0  Riva TNT2
+		14af 5810  Maxi Gamer Xentor
+10df  Emulex Corporation
+	10df  Light Pulse Fibre Channel Adapter
+	1ae5  LP6000 Fibre Channel Host Adapter
+	f700  LP7000 Fibre Channel Host Adapter
+10e0  Integrated Micro Solutions Inc.
+	5026  IMS5026/27/28
+	5027  IMS5027
+	5028  IMS5028
+	8849  IMS8849
+	8853  IMS8853
+	9128  IMS9129 [Twin turbo 128]
+10e1  Tekram Technology Co.,Ltd.
+	0391  TRM-S1040
+	690c  DC-690c
+	dc29  DC-290
+10e2  Aptix Corporation
+10e3  Tundra Semiconductor Corp.
+	0000  CA91C042 [Universe]
+	0860  CA91C860 [QSpan]
+10e4  Tandem Computers
+10e5  Micro Industries Corporation
+10e6  Gainbery Computer Products Inc.
+10e7  Vadem
+10e8  Applied Micro Circuits Corporation
+	2011  Q-Motion Video Capture/Edit board
+	4750  S5930 [Matchmaker]
+	5920  S5920
+	8043  LANai4.x [Myrinet LANai interface chip]
+	8062  S5933_PARASTATION
+	807d  S5933 [Matchmaker]
+	8088  Kingsberg Spacetec Format Synchronizer
+	8089  Kingsberg Spacetec Serial Output Board
+	809c  S5933_HEPC3
+	811a  PCI-IEEE1355-DS-DE Interface
+	8170  S5933 "Matchmaker" PCI Chipset Development Tool
+10e9  Alps Electric Co., Ltd.
+10ea  Intergraphics Systems
+	1680  IGA-1680
+	1682  IGA-1682
+	1683  IGA-1683
+	2000  CyberPro 2000
+	2010  CyberPro 2000A
+10eb  Artists Graphics
+	0101  3GA
+	8111  Twist3 Frame Grabber
+10ec  Realtek Semiconductor Co., Ltd.
+	8029  RT8029(AS)
+		10b8 2011  EZ-Card
+		10ec 8029  RT8029(AS)
+		1113 1208  EN1208
+		1186 0300  DE-528
+		1259 2400  AT-2400
+	8129  RT8129
+	8139  RT8139
+		1025 8920  ALN-325
+		1025 8921  ALN-325
+		10bd 0320  EP-320X-R
+		10ec 8139  RT8139
+		1186 1320  SN5200
+		1259 2500  AT-2500TX
+		1429 d010  ND010
+		1432 9130  EN-9130TX
+		1436 8139  RT8139
+		146c 1439  FE-1439TX
+		1489 6001  GF100TXRII
+		1489 6002  GF100TXRA
+		149c 139a  LFE-8139ATX
+		149c 8139  LFE-8139TX
+		2646 0001  EtheRx
+		8e2e 7000  KF-230TX
+		8e2e 7100  KF-230TX/2
+10ed  Ascii Corporation
+	7310  V7310
+10ee  Xilinx, Inc.
+10ef  Racore Computer Products, Inc.
+	8154  M815x Token Ring Adapter
+10f0  Peritek Corporation
+10f1  Tyan Computer
+10f2  Achme Computer, Inc.
+10f3  Alaris, Inc.
+10f4  S-MOS Systems, Inc.
+10f5  NKK Corporation
+	a001  NDR4000 [NR4600 Bridge]
+10f6  Creative Electronic Systems SA
+10f7  Matsushita Electric Industrial Co., Ltd.
+10f8  Altos India Ltd
+10f9  PC Direct
+10fa  Truevision
+	000c  TARGA 1000
+10fb  Thesys Gesellschaft für Mikroelektronik mbH
+10fc  I-O Data Device, Inc.
+10fd  Soyo Computer, Inc
+10fe  Fast Multimedia AG
+10ff  NCube
+1100  Jazz Multimedia
+1101  Initio Corporation
+	9100  INI-9100/9100W
+	9400  INI-940
+	9401  INI-950
+	9500  360P
+1102  Creative Labs
+	0002  SB Live! EMU10000
+		1102 0020  CT4850 SBLive! Value
+		1102 0021  CT4620 SBLive!
+		1102 002f  SBLive! mainboard implementation 
+		1102 8022  CT4780 SBLive! Value
+		1102 8024  CT4760 SBLive!
+		1102 8026  CT4830 SBLive! Value
+		1102 8027  CT4832 SBLive! Value
+		1102 8031  CT4831 SBLive! Value
+		1102 8040  CT4760 SBLive!
+	7002  SB Live!
+		1102 0020  Gameport Joystick
+1103  Triones Technologies, Inc.
+	0003  HPT343
+	0004  HPT366
+1104  RasterOps Corp.
+1105  Sigma Designs, Inc.
+	8300  REALmagic Hollywood Plus DVD Decoder
+1106  VIA Technologies, Inc.
+	0501  VT8501
+	0505  VT82C505
+	0561  VT82C561
+	0571  VT82C586 IDE [Apollo]
+	0576  VT82C576 3V [Apollo Master]
+	0585  VT82C585VP [Apollo VP1/VPX]
+	0586  VT82C586/A/B PCI-to-ISA [Apollo VP]
+		1106 0000  MVP3 ISA Bridge
+	0595  VT82C595 [Apollo VP2]
+	0596  VT82C596 ISA [Apollo PRO]
+	0597  VT82C597 [Apollo VP3]
+	0598  VT82C598 [Apollo MVP3]
+	0680  VT82C680 [Apollo P6]
+	0686  VT82C686 [Apollo Super]
+	0691  VT82C691 [Apollo PRO]
+	0693  VT82C693 [Apollo Pro Plus]
+	0926  VT82C926 [Amazon]
+	1000  VT82C570MV
+	1106  VT82C570MV
+	1571  VT82C416MV
+	1595  VT82C595/97 [Apollo VP2/97]
+	3038  VT82C586B USB
+		1234 0925  MVP3 USB Controller
+	3040  VT82C586B ACPI
+	3043  VT86C100A [Rhine 10/100]
+		1106 0100  VT86C100A
+		1186 1400  DFE-530TX
+	3057  VT82C686 [Apollo Super ACPI]
+	3058  VT82C686 [Apollo Super AC97/Audio]
+	3068  VT82C686 [Apollo Super AC97/Modem]
+	5030  VT82C596 ACPI [Apollo PRO]
+	6100  VT85C100A [Rhine II]
+	8501  VT8501
+	8596  VT82C596 [Apollo PRO AGP]
+	8597  VT82C597 [Apollo VP3 AGP]
+	8598  VT82C598 [Apollo MVP3 AGP]
+	8691  VT82C691 [Apollo Pro]
+1107  Stratus Computers
+	0576  VIA VT82C570MV [Apollo] (Wrong vendor ID!)
+1108  Proteon, Inc.
+	0100  p1690plus_AA
+	0101  p1690plus_AB
+	0105  P1690Plus
+	0108  P1690Plus
+	0138  P1690Plus
+	0139  P1690Plus
+	013C  P1690Plus
+	013D  P1690Plus
+1109  Cogent Data Technologies, Inc.
+	1400  EM110TX [EX110TX]
+110a  Siemens Nixdorf AG
+	0002  Pirahna 2-port
+	0005  Tulip controller, power management, switch extender
+	4942  FPGA I-Bus Tracer for MBD
+	6120  SZB6120
+110b  Chromatic Research Inc.
+	0001  Mpact Media Processor
+110c  Mini-Max Technology, Inc.
+110d  Znyx Advanced Systems
+110e  CPU Technology
+110f  Ross Technology
+1110  Powerhouse Systems
+	6037  Firepower Powerized SMP I/O ASIC
+	6073  Firepower Powerized SMP I/O ASIC
+1111  Santa Cruz Operation
+# DJ- Some people say that 0x1112 is Rockwell International ?
+1112  RNS - Div. of Meret Communications Inc
+	2200  FDDI Adapter
+	2340  4 Port Fast Ethernet Adapter
+	2400  ATM Adapter
+1113  Accton Technology Corporation
+	1211  SMC2-1211TX
+	1217  EN-1217 Ethernet Adapter
+	5105  10Mbps Network card
+	9211  EN-1207D Fast Ethernet Adapter
+1114  Atmel Corporation
+1115  3D Labs
+1116  Data Translation
+	0022  DT3001
+	0023  DT3002
+	0024  DT3003
+	0028  DT3003-PGL
+	0025  DT3004
+	0026  DT3005
+	0027  DT3001-PGL
+1117  Datacube, Inc
+	9500  Max-1C SVGA card
+	9501  Max-1C image processing
+1118  Berg Electronics
+1119  ICP Vortex Computersysteme GmbH
+	0000  GDT 6000/6020/6050
+	0001  GDT 6000b/6010
+	0002  GDT 6110/6510
+	0003  GDT 6120/6520
+	0004  GDT 6530
+	0005  GDT 6550
+	0006  GDT 6x17
+	0007  GDT 6x27
+	0008  GDT 6537
+	0009  GDT 5557
+	000a  GDT 6x15
+	000b  GDT 6x25
+	000c  GDT 6535
+	000d  GDT 6555
+	0100  GDT 6117RP/6517RP
+	0101  GDT 6127RP/6527RP
+	0102  GDT 6537RP
+	0103  GDT 6557RP
+	0104  GDT 6111RP/6511RP
+	0105  GDT 6121RP/6521RP
+	0110  GDT 6117RP1/6517RP1
+	0111  GDT 6127RP1/6527RP1
+	0112  GDT 6537RP1
+	0113  GDT 6557RP1
+	0114  GDT 6111RP1/6511RP1
+	0115  GDT 6121RP1/6521RP1
+	0118  GDT 6x18RD
+	0119  GDT 6x28RD
+	011A  GDT 6x38RD
+	011B  GDT 6x58RD
+	0120  GDT 6117RP2/6517RP2
+	0121  GDT 6127RP2/6527RP2
+	0122  GDT 6537RP2
+	0123  GDT 6557RP2
+	0124  GDT 6111RP2/6511RP2
+	0125  GDT 6121RP2/6521RP2
+	0168  GDT 7x18RN
+	0169  GDT 7x28RN
+	016A  GDT 7x38RN
+	016B  GDT 7x58RN
+	0210  GDT 6x19RD
+	0211  GDT 6x29RD
+	0260  GDT 7x19RN
+	0261  GDT 7x29RN
+111a  Efficient Networks, Inc
+	0000  155P-MF1 (FPGA)
+	0002  155P-MF1 (ASIC)
+	0003  ENI-25P ATM Adapter
+	0005  ENI-25P ATM Adapter
+111b  Teledyne Electronic Systems
+111c  Tricord Systems Inc.
+	0001  Powerbis Bridge
+111d  Integrated Device Tech
+	0001  IDT77211 ATM Adapter
+111e  Eldec
+111f  Precision Digital Images
+	4a47  Precision MX Video engine interface
+	5243  Frame capture bus interface
+1120  EMC Corporation
+1121  Zilog
+1122  Multi-tech Systems, Inc.
+1123  Excellent Design, Inc.
+1124  Leutron Vision AG
+1125  Eurocore
+1127  FORE Systems Inc
+	0200  ForeRunner PCA-200 ATM
+	0210  PCA-200PC
+	0250  ATM
+	0300  PCA-200E
+	0310  ATM
+	0400  ForeRunnerHE ATM Adapter
+1129  Firmworks
+112a  Hermes Electronics Company, Ltd.
+112b  Linotype - Hell AG
+112c  Zenith Data Systems
+112d  Ravicad
+112e  Infomedia Microelectronics Inc.
+112f  Imaging Technology Inc
+	0000  MVC IC-PCI
+	0001  Video frame grabber/processor
+1130  Computervision
+1131  Philips Semiconductors
+	7145  SAA7145
+	7146  SAA7146
+1132  Mitel Corp.
+1133  Eicon Technology Corporation
+	7901  EiconCard S90
+	7902  EiconCard S90
+	7911  EiconCard S91
+	7912  EiconCard S91
+	7941  EiconCard S94
+	7942  EiconCard S94
+	b921  EiconCard P92
+	b922  EiconCard P92
+	e001  DIVA 20PRO
+	e002  DIVA 20
+	e003  DIVA 20PRO_U
+	e004  DIVA 20_U
+	e010  DIVA Server BRI-2M
+	e014  DIVA Server PRO-30M
+1134  Mercury Computer Systems
+	0001  Raceway Bridge
+1135  Fuji Xerox Co Ltd
+	0001  Printer controller
+1136  Momentum Data Systems
+1137  Cisco Systems Inc
+1138  Ziatech Corporation
+	8905  8905 [STD 32 Bridge]
+1139  Dynamic Pictures, Inc
+113a  FWB Inc
+113b  Network Computing Devices
+113c  Cyclone Microsystems, Inc.
+	0000  PCI-9060 i960 Bridge
+	0001  PCI-SDK [PCI i960 Evaluation Platform]
+	0911  PCI-911 [PCI-based i960Jx Intelligent I/O Controller]
+	0912  PCI-912 [i960CF-based Intelligent I/O Controller]
+	0913  PCI-913
+	0914  PCI-914 [I/O Controller w/ secondary PCI bus]
+113d  Leading Edge Products Inc
+113e  Sanyo Electric Co - Computer Engineering Dept
+113f  Equinox Systems, Inc.
+	0808  SST-64P Adapter
+	1010  SST-128P Adapter
+	80C0  SST-16P Adapter
+	80C4  SST-16P Adapter
+	80C8  SST-16P Adapter
+	8888  SST-4P Adapter
+	9090  SST-8P Adapter
+1140  Intervoice Inc
+1141  Crest Microsystem Inc
+1142  Alliance Semiconductor Corporation
+	3210  AP6410
+	6422  ProVideo 6422
+	6424  ProVideo 6424
+	6425  ProMotion AT25
+	643d  ProMotion AT3D
+1143  NetPower, Inc
+1144  Cincinnati Milacron
+	0001  Noservo controller
+1145  Workbit Corporation
+1146  Force Computers
+1147  Interface Corp
+1148  Syskonnect (Schneider & Koch)
+	4000  FDDI Adapter
+		0e11 b03b  Netelligent 100 FDDI DAS Fibre SC
+		0e11 b03c  Netelligent 100 FDDI SAS Fibre SC
+		0e11 b03d  Netelligent 100 FDDI DAS UTP
+		0e11 b03e  Netelligent 100 FDDI SAS UTP
+		0e11 b03f  Netelligent 100 FDDI SAS Fibre MIC
+		1148 5521  FDDI SK-5521 (SK-NET FDDI-UP)
+		1148 5522  FDDI SK-5522 (SK-NET FDDI-UP DAS)
+		1148 5541  FDDI SK-5541 (SK-NET FDDI-FP)
+		1148 5543  FDDI SK-5543 (SK-NET FDDI-LP)
+		1148 5544  FDDI SK-5544 (SK-NET FDDI-LP DAS)
+		1148 5821  FDDI SK-5821 (SK-NET FDDI-UP64)
+		1148 5822  FDDI SK-5822 (SK-NET FDDI-UP64 DAS)
+		1148 5841  FDDI SK-5841 (SK-NET FDDI-FP64)
+		1148 5843  FDDI SK-5843 (SK-NET FDDI-LP64)
+		1148 5844  FDDI SK-5844 (SK-NET FDDI-LP64 DAS)
+	4200  Token ring adaptor
+	4300  GE
+1149  Win System Corporation
+114a  VMIC
+	7587  VMIVME-7587
+114b  Canopus Co., Ltd
+114c  Annabooks
+114d  IC Corporation
+114e  Nikon Systems Inc
+114f  Digi International
+	0002  AccelePort EPC
+	0003  RightSwitch SE-6
+	0004  AccelePort Xem
+	0005  AccelePort Xr
+	0006  AccelePort Xr,C/X
+	0009  AccelePort Xr/J
+	000a  AccelePort EPC/J
+	000C  DataFirePRIme T1 (1-port)
+	000D  SyncPort 2-Port (x.25/FR)
+	0011  AccelePort 8r EIA-232 (IBM)
+	0012  AccelePort 8r EIA-422
+	0013  AccelePort Xr
+	0014  AccelePort 8r EIA-422
+	0015  AccelePort Xem
+	0016  AccelePort EPC/X
+	0017  AccelePort C/X
+	001A  DataFirePRIme E1 (1-port)
+	001B  AccelePort C/X (IBM)
+	001D  DataFire RAS T1/E1/PRI
+	0023  AccelePort RAS
+	0024  DataFire RAS B4 ST/U
+	0026  AccelePort 4r 920
+	0027  AccelePort Xr 920
+	0034  AccelePort 2r 920
+	0035  DataFire DSP T1/E1/PRI cPCI
+	6001  Avanstar
+1150  Thinking Machines Corp
+1151  JAE Electronics Inc.
+1152  Megatek
+1153  Land Win Electronic Corp
+1154  Melco Inc
+1155  Pine Technology Ltd
+1156  Periscope Engineering
+1157  Avsys Corporation
+1158  Voarx R & D Inc
+	3011  Tokenet/vg 1001/10m anylan
+	9050  Lanfleet/Truevalue
+	9051  Lanfleet/Truevalue
+1159  Mutech Corp
+	0001  MV-1000
+115a  Harlequin Ltd
+115b  Parallax Graphics
+115c  Photron Ltd.
+115d  Xircom
+	0003  Cardbus Ethernet 10/100
+		1014 0181  10/100 EtherJet Cardbus Adapter
+		1014 1181  10/100 EtherJet Cardbus Adapter
+		115d 0181  Cardbus Ethernet 10/100
+		115d 1181  Cardbus Ethernet 10/100
+		8086 8181  EtherExpress PRO/100 Mobile CardBus 32 Adapter
+		8086 9181  EtherExpress PRO/100 Mobile CardBus 32 Adapter
+	0005  Cardbus Ethernet 10/100
+		1014 0182  10/100 EtherJet Cardbus Adapter
+		1014 1182  10/100 EtherJet Cardbus Adapter
+		115d 0182  Cardbus Ethernet 10/100
+		115d 1182  Cardbus Ethernet 10/100
+	0007  Cardbus Ethernet 10/100
+		1014 0182  10/100 EtherJet Cardbus Adapter
+		1014 1182  10/100 EtherJet Cardbus Adapter
+		115d 0182  Cardbus Ethernet 10/100
+		115d 1182  Cardbus Ethernet 10/100
+	000b  Cardbus Ethernet 10/100
+		1014 0183  10/100 EtherJet Cardbus Adapter
+		115d 0183  Cardbus Ethernet 10/100
+	000f  Cardbus Ethernet 10/100
+		1014 0183  10/100 EtherJet Cardbus Adapter
+		115d 0183  Cardbus Ethernet 10/100
+	0101  Cardbus 56k modem
+	0103  Cardbus Ethernet + 56k Modem
+		115d 1181  CBEM56G-100 Ethernet + 56k Modem
+		8086 9181  PRO/100 LAN + Modem56 CardBus
+115e  Peer Protocols Inc
+115f  Maxtor Corporation
+1160  Megasoft Inc
+1161  PFU Limited
+1162  OA Laboratory Co Ltd
+1163  Rendition
+	0001  Verite 1000
+	2000  Verite V2000/V2100/V2200
+1164  Advanced Peripherals Technologies
+1165  Imagraph Corporation
+	0001  Motion TPEG Recorder/Player with audio
+1166  Relience Computer
+	0008  CNB20HE
+	0009  CNB20HE
+1167  Mutoh Industries Inc
+1168  Thine Electronics Inc
+1169  Centre for Development of Advanced Computing
+116a  Polaris Communications
+	6100  Bus/Tag Channel
+	6800  Escon Channel
+	7100  Bus/Tag Channel
+	7800  Escon Channel
+116b  Connectware Inc
+116c  Intelligent Resources Integrated Systems
+116d  Martin-Marietta
+116e  Electronics for Imaging
+116f  Workstation Technology
+1170  Inventec Corporation
+1171  Loughborough Sound Images Plc
+1172  Altera Corporation
+1173  Adobe Systems, Inc
+1174  Bridgeport Machines
+1175  Mitron Computer Inc.
+1176  SBE Incorporated
+1177  Silicon Engineering
+1178  Alfa, Inc.
+1179  Toshiba America Info Systems
+	0404  DVD Decoder card
+	0406  Tecra Video Capture device
+	0407  DVD Decoder card (Version 2)
+	0601  601
+	0603  ToPIC95 PCI to CardBus Bridge for Notebooks
+	060a  ToPIC95
+	060f  ToPIC97
+	0701  FIR Port
+# This is apparently incorrect. Does anyone know the correct ID?
+#	0701  Lucent DSP1645 [Mars]
+117b  L G Electronics, Inc.
+117c  Atto Technology
+117d  Becton & Dickinson
+117e  T/R Systems
+117f  Integrated Circuit Systems
+1180  Ricoh Co Ltd
+	0465  RL5c465
+	0466  RL5c466
+	0475  RL5c475
+	0476  RL5c476 II
+	0477  RL5c477
+	0478  RL5c478
+1181  Telmatics International
+1183  Fujikura Ltd
+1184  Forks Inc
+1185  Dataworld International Ltd
+1186  D-Link System Inc
+	0100  DC21041
+1187  Advanced Technology Laboratories, Inc.
+1188  Shima Seiki Manufacturing Ltd.
+1189  Matsushita Electronics Co Ltd
+118a  Hilevel Technology
+118b  Hypertec Pty Limited
+118c  Corollary, Inc
+	0014  PCIB [C-bus II to PCI bus host bridge chip]
+118d  BitFlow Inc
+	0001  Raptor-PCI framegrabber
+	0012  Model 12 Road Runner Frame Grabber
+	0014  Model 14 Road Runner Frame Grabber
+	0024  Model 24 Road Runner Frame Grabber
+	0044  Model 44 Road Runner Frame Grabber
+	0112  Model 12 Road Runner Frame Grabber
+	0114  Model 14 Road Runner Frame Grabber
+	0124  Model 24 Road Runner Frame Grabber
+	0144  Model 44 Road Runner Frame Grabber
+	0212  Model 12 Road Runner Frame Grabber
+	0214  Model 14 Road Runner Frame Grabber
+	0224  Model 24 Road Runner Frame Grabber
+	0244  Model 44 Road Runner Frame Grabber
+	0312  Model 12 Road Runner Frame Grabber
+	0314  Model 14 Road Runner Frame Grabber
+	0324  Model 24 Road Runner Frame Grabber
+	0344  Model 44 Road Runner Frame Grabber
+118e  Hermstedt GmbH
+118f  Green Logic
+1190  Tripace
+1191  Artop Electronic Corp
+	0004  ATP8400
+	0005  ATP850UF
+	8002  AEC6710 SCSI-2 Host Adapter
+	8010  AEC6712UW SCSI
+	8020  AEC6712U SCSI
+	8030  AEC6712S SCSI
+	8040  AEC6712D SCSI
+	8050  AEC6712SUW SCSI
+1192  Densan Company Ltd
+1193  Zeitnet Inc.
+	0001  1221
+	0002  1225
+1194  Toucan Technology
+1195  Ratoc System Inc
+1196  Hytec Electronics Ltd
+1197  Gage Applied Sciences, Inc.
+1198  Lambda Systems Inc
+1199  Attachmate Corporation
+119a  Mind Share, Inc.
+119b  Omega Micro Inc.
+	1221  82C092G
+119c  Information Technology Inst.
+119d  Bug, Inc. Sapporo Japan
+119e  Fujitsu Microelectronics Ltd.
+119f  Bull HN Information Systems
+11a0  Convex Computer Corporation
+11a1  Hamamatsu Photonics K.K.
+11a2  Sierra Research and Technology
+11a3  Deuretzbacher GmbH & Co. Eng. KG
+11a4  Barco Graphics NV
+11a5  Microunity Systems Eng. Inc
+11a6  Pure Data Ltd.
+11a7  Power Computing Corp.
+11a8  Systech Corp.
+11a9  InnoSys Inc.
+	4240  AMCC S933Q Intelligent Serial Card
+11aa  Actel
+11ab  Galileo Technology Ltd.
+	0146  GT-64010
+	4801  GT-48001
+	f003  GT-64010 Primary Image Piranha Image Generator
+11ac  Canon Information Systems Research Aust.
+11ad  Lite-On Communications Inc
+	0002  LNE100TX
+		11ad 0002  LNE100TX
+		11ad 0003  LNE100TX
+		11ad f003  LNE100TX
+		11ad ffff  LNE100TX
+		1385 f004  FA310TX
+11ae  Aztech System Ltd
+11af  Avid Technology Inc.
+11b0  V3 Semiconductor Inc.
+	0292  V292PBC [Am29030/40 Bridge]
+	0960  V96xPBC
+	c960  V96DPC
+11b1  Apricot Computers
+11b2  Eastman Kodak
+11b3  Barr Systems Inc.
+11b4  Leitch Technology International
+11b5  Radstone Technology Plc
+11b6  United Video Corp
+11b8  XPoint Technologies, Inc
+	0001  Quad PeerMaster
+11b9  Pathlight Technology Inc.
+	c0ed  SSA Controller
+11ba  Videotron Corp
+11bb  Pyramid Technology
+11bc  Network Peripherals Inc
+	0001  NP-PCI
+11bd  Pinnacle Systems Inc.
+11be  International Microcircuits Inc
+11bf  Astrodesign, Inc.
+11c0  Hewlett Packard
+11c1  Lucent Microelectronics
+	0440  56k WinModem
+		0001 0440  LT WinModem 56k Data+Fax+Voice+Dsvd
+		1033 8015  LT WinModem 56k Data+Fax+Voice+Dsvd 
+		1033 804f  LT WinModem 56k Data+Fax+Voice+Dsvd 
+		10cf 102c  LB LT Modem V.90 56k
+		10cf 104a  BIBLO LT Modem 56k
+		10cf 105f  LB2 LT Modem V.90 56k
+		1179 0001  Internal V.90 Modem
+		11c1 0440  LT WinModem 56k Data+Fax+Voice+Dsvd
+		122d 4101  MDP7800-U Modem
+		13e0 0040  LT WinModem 56k Data+Fax+Voice+Dsvd
+		13e0 0440  LT WinModem 56k Data+Fax+Voice+Dsvd
+		13e0 0441  LT WinModem 56k Data+Fax+Voice+Dsvd
+		13e0 f100  LT WinModem 56k Data+Fax+Voice+Dsvd 
+		13e0 f101  LT WinModem 56k Data+Fax+Voice+Dsvd 
+		144d 2101  LT56PV Modem
+		149f 0440  LT WinModem 56k Data+Fax+Voice+Dsvd
+	0441  56k WinModem
+		1033 804d  LT WinModem 56k Data+Fax
+		1092 0440  Supra 56i
+		1179 0001  Internal V.90 Modem
+		11c1 0440  LT WinModem 56k Data+Fax
+		11c1 0441  LT WinModem 56k Data+Fax 
+		122d 4100  MDP7800-U Modem
+		13e0 0040  LT WinModem 56k Data+Fax 
+		13e0 0100  LT WinModem 56k Data+Fax 
+		13e0 0410  LT WinModem 56k Data+Fax 
+		13e0 0420  TelePath Internet 56k WinModem
+		13e0 0443  LT WinModem 56k Data+Fax 
+		1416 9804  CommWave 56k Modem
+		141d 0440  LT WinModem 56k Data+Fax 
+		144f 0441  Lucent 56k V.90 DF Modem
+		1468 0441  Presario 56k V.90 DF Modem
+	0442  56k WinModem
+		0001 0440  LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
+		11c1 0440  LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
+		11c1 0442  LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
+		13e0 0412  LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
+		13e0 0442  LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
+		13fc 2471  LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
+		144d 2104  LT56PT Modem
+		149f 0440  LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
+		1668 0440  LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
+	0448  WinModem 56k
+		13e0 0040  LT WinModem 56k Data+Fax+Voice+Dsvd
+	0449  WinModem 56k
+		0e11 b14d  56k V.90 Modem
+		13e0 0020  LT WinModem 56k Data+Fax
+		13e0 0041  TelePath Internet 56k WinModem
+		144f 0449  Lucent 56k V.90 DFi Modem
+		1468 0449  Presario 56k V.90 DFi Modem
+	044A  F-1156IV WinModem (V90, 56KFlex)
+		13e0 0012  LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
+		13e0 0042  LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
+		144f 1005  LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd
+	0480  Venus WinModem (V90, 56KFlex)
+11c2  Sand Microelectronics
+11c4  Document Technologies, Inc
+11c5  Shiva Corporation
+11c6  Dainippon Screen Mfg. Co. Ltd
+11c7  D.C.M. Data Systems
+11c8  Dolphin Interconnect Solutions AS
+	0658  PSB32 SCI-Adapter D31x
+	d665  PSB64 SCI-Adapter D32x
+	d667  PSB66 SCI-Adapter D33x
+11c9  Magma
+	0010  16-line serial port w/- DMA
+	0011  4-line serial port w/- DMA
+11ca  LSI Systems, Inc
+11cb  Specialix Research Ltd.
+	2000  PCI_9050
+		11cb 0200  SX
+		11cb b008  I/O8+
+	4000  SUPI_1
+	8000  T225
+11cc  Michels & Kleberhoff Computer GmbH
+11cd  HAL Computer Systems, Inc.
+11ce  Netaccess
+11cf  Pioneer Electronic Corporation
+11d0  Lockheed Martin Federal Systems-Manassas
+11d1  Auravision
+	01f7  VxP524
+11d2  Intercom Inc.
+11d3  Trancell Systems Inc
+11d4  Analog Devices
+11d5  Ikon Corporation
+	0115  10115
+	0117  10117
+11d6  Tekelec Telecom
+11d7  Trenton Technology, Inc.
+11d8  Image Technologies Development
+11d9  TEC Corporation
+11da  Novell
+11db  Sega Enterprises Ltd
+11dc  Questra Corporation
+11dd  Crosfield Electronics Limited
+11de  Zoran Corporation
+	6057  ZR36057PQC Video cutting chipset
+		1031 7efe  DC10 Plus
+		1031 fc00  MiroVIDEO DC50, Motion JPEG Capture/CODEC Board
+		13ca 4231  JPEG/TV Card
+	6120  ZR36120
+		1328 f001  Cinemaster C DVD Decoder
+11df  New Wave PDG
+11e0  Cray Communications A/S
+11e1  GEC Plessey Semi Inc.
+11e2  Samsung Information Systems America
+11e3  Quicklogic Corporation
+11e4  Second Wave Inc
+11e5  IIX Consulting
+11e6  Mitsui-Zosen System Research
+11e7  Toshiba America, Elec. Company
+11e8  Digital Processing Systems Inc.
+11e9  Highwater Designs Ltd.
+11ea  Elsag Bailey
+11eb  Formation Inc.
+11ec  Coreco Inc
+11ed  Mediamatics
+11ee  Dome Imaging Systems Inc
+11ef  Nicolet Technologies B.V.
+11f0  Compu-Shack
+	4231  FDDI
+	4232  FASTline UTP Quattro
+	4233  FASTline FO
+	4234  FASTline UTP
+	4235  FASTline-II UTP
+	4236  FASTline-II FO
+	4731  GIGAline
+11f1  Symbios Logic Inc
+11f2  Picture Tel Japan K.K.
+11f3  Keithley Metrabyte
+11f4  Kinetic Systems Corporation
+	2915  CAMAC controller
+11f5  Computing Devices International
+11f6  Compex
+	0112  ENet100VG4
+	1401  ReadyLink 2000
+	2011  RL100-ATX 10/100
+	2201  ReadyLink 100TX (Winbond W89C840)
+	9881  RL100TX
+11f7  Scientific Atlanta
+11f8  PMC-Sierra Inc.
+	7375  PM7375 [LASAR-155 ATM SAR]
+11f9  I-Cube Inc
+11fa  Kasan Electronics Company, Ltd.
+11fb  Datel Inc
+11fc  Silicon Magic
+11fd  High Street Consultants
+11fe  Comtrol Corporation
+	0001  RocketPort 8 Oct
+	0002  RocketPort 8 Intf
+	0003  RocketPort 16 Intf
+	0004  RocketPort 32 Intf
+	0005  RocketPort Octacable
+	0006  RocketPort 8J
+	0008  RocketPort 8-port
+	0009  RocketPort 16-port
+	000A  RocketPort Plus Quadcable
+	000B  RocketPort Plus Octacable
+	000C  RocketPort 8-port Modem
+11ff  Scion Corporation
+1200  CSS Corporation
+1201  Vista Controls Corp
+1202  Network General Corp.
+1203  Bayer Corporation, Agfa Division
+1204  Lattice Semiconductor Corporation
+1205  Array Corporation
+1206  Amdahl Corporation
+1208  Parsytec GmbH
+	4853  HS-Link Device
+1209  SCI Systems Inc
+120a  Synaptel
+120b  Adaptive Solutions
+120c  Technical Corp.
+120d  Compression Labs, Inc.
+120e  Cyclades Corporation
+	0100  Cyclom_Y below first megabyte
+	0101  Cyclom_Y above first megabyte
+	0102  Cyclom_4Y below first megabyte
+	0103  Cyclom_4Y above first megabyte
+	0104  Cyclom_8Y below first megabyte
+	0105  Cyclom_8Y above first megabyte
+	0200  Cyclom_Z below first megabyte
+	0201  Cyclom_Z above first megabyte
+120f  Essential Communications
+	0001  Roadrunner serial HIPPI
+1210  Hyperparallel Technologies
+1211  Braintech Inc
+1212  Kingston Technology Corp.
+1213  Applied Intelligent Systems, Inc.
+1214  Performance Technologies, Inc.
+1215  Interware Co., Ltd
+1216  Purup Prepress A/S
+1217  O2 Micro, Inc.
+	6729  6729
+	673a  6730
+	6832  6832
+	6836  6836
+1218  Hybricon Corp.
+1219  First Virtual Corporation
+121a  3Dfx Interactive, Inc.
+	0001  Voodoo
+	0002  Voodoo 2
+	0003  Voodoo Banshee
+		1092 0003  Monster Fusion
+		1092 4000  Monster Fusion
+		1092 4002  Monster Fusion
+		1092 4801  Monster Fusion AGP
+		1092 4803  Monster Fusion AGP
+		1092 8030  Monster Fusion
+		1092 8035  Monster Fusion AGP
+		121a 0001  Voodoo Banshee AGP
+		121a 0003  Voodoo Banshee AGP SGRAM
+		121a 0004  Voodoo Banshee
+		3030 3030  Skywell Magic TwinPower
+	0005  Voodoo 3
+		121a 0004  Voodoo3 AGP
+		121a 0030  Voodoo3 AGP
+		121a 0031  Voodoo3 AGP
+		121a 0034  Voodoo3 AGP
+		121a 0036  Voodoo3
+		121a 0037  Voodoo3 AGP
+		121a 0038  Voodoo3 AGP
+		121a 003a  Voodoo3 AGP
+		121a 0044  Voodoo3
+		121a 004b  Velocity 100
+		121a 004c  Velocity 200
+		121a 004d  Voodoo3 AGP
+		121a 004e  Voodoo3 AGP
+		121a 0051  Voodoo3 AGP
+		121a 0052  Voodoo3 AGP
+		121a 0060  Voodoo3 3500 TV (NTSC)
+		121a 0061  Voodoo3 3500 TV (PAL)
+		121a 0062  Voodoo3 3500 TV (SECAM)
+121b  Advanced Telecommunications Modules
+121c  Nippon Texaco., Ltd
+121d  Lippert Automationstechnik GmbH
+121e  CSPI
+121f  Arcus Technology, Inc.
+1220  Ariel Corporation
+	1220  AMCC 5933 TMS320C80 DSP/Imaging board
+1221  Contec Co., Ltd
+1222  Ancor Communications, Inc.
+1223  Heurikon/Computer Products
+1224  Interactive Images
+1225  Power I/O, Inc.
+1227  Tech-Source
+1228  Norsk Elektro Optikk A/S
+1229  Data Kinesis Inc.
+122a  Integrated Telecom
+122b  LG Industrial Systems Co., Ltd
+122c  Sican GmbH
+122d  Aztech System Ltd
+	1206  368DSP
+	50dc  3328 Audio
+	80da  3328 Audio
+122e  Xyratex
+122f  Andrew Corporation
+1230  Fishcamp Engineering
+1231  Woodward McCoach, Inc.
+1232  GPT Limited
+1233  Bus-Tech, Inc.
+1234  Technical Corp.
+1235  Risq Modular Systems, Inc.
+1236  Sigma Designs Corporation
+	0000  RealMagic64/GX
+	6401  REALmagic 64/GX (SD 6425)
+1237  Alta Technology Corporation
+1238  Adtran
+1239  3DO Company
+123a  Visicom Laboratories, Inc.
+123b  Seeq Technology, Inc.
+123c  Century Systems, Inc.
+123d  Engineering Design Team, Inc.
+	0000  EasyConnect 8/32
+	0002  EasyConnect 8/64
+	0003  EasyIO
+123e  Simutech, Inc.
+123f  C-Cube Microsystems
+	00e4  MPEG
+	8888  Cinemaster C 3.0 DVD Decoder
+1240  Marathon Technologies Corp.
+1241  DSC Communications
+1243  Delphax
+1244  AVM Audiovisuelles MKTG & Computer System GmbH
+	0700  B1 ISDN
+	0a00  A1 ISDN [Fritz]
+1245  A.P.D., S.A.
+1246  Dipix Technologies, Inc.
+1247  Xylon Research, Inc.
+1248  Central Data Corporation
+1249  Samsung Electronics Co., Ltd.
+124a  AEG Electrocom GmbH
+124b  SBS/Greenspring Modular I/O
+124c  Solitron Technologies, Inc.
+124d  Stallion Technologies, Inc.
+	0000  EasyConnection 8/32
+	0002  EasyConnection 8/64
+	0003  EasyIO
+124e  Cylink
+124f  Infotrend Technology, Inc.
+	0041  IFT-2000 Series RAID Controller
+1250  Hitachi Microcomputer System Ltd
+1251  VLSI Solutions Oy
+1253  Guzik Technical Enterprises
+1254  Linear Systems Ltd.
+1255  Optibase Ltd
+	1110  MPEG Forge
+	1210  MPEG Fusion
+	2110  VideoPlex
+	2120  VideoPlex CC
+	2130  VideoQuest
+1256  Perceptive Solutions, Inc.
+1257  Vertex Networks, Inc.
+1258  Gilbarco, Inc.
+1259  Allied Telesyn International
+	2560  AT-2560 Fast Ethernet Adapter (i82557B)
+125a  ABB Power Systems
+125b  Asix Electronics Corporation
+125c  Aurora Technologies, Inc.
+125d  ESS Technology
+	0000  ES336H Fax Modem (Early Model)
+	1948  Solo?
+	1968  ES1968 Maestro 2
+	1969  ES1969 Solo-1 Audiodrive
+	1978  ES1978 Maestro Audiodrive
+	2808  ES336H Fax Modem (Later Model)
+	2898  ES2898 Modem
+125e  Specialvideo Engineering SRL
+125f  Concurrent Technologies, Inc.
+1260  Harris Semiconductor
+	8130  HMP8130 NTSC/PAL Video Decoder
+	8131  HMP8131 NTSC/PAL Video Decoder
+1261  Matsushita-Kotobuki Electronics Industries, Ltd.
+1262  ES Computer Company, Ltd.
+1263  Sonic Solutions
+1264  Aval Nagasaki Corporation
+1265  Casio Computer Co., Ltd.
+1266  Microdyne Corporation
+	0001  NE10/100 Adapter (i82557B)
+	1910  NE2000Plus (RT8029) Ethernet Adapter
+1267  S. A. Telecommunications
+	5352  PCR2101
+	5a4b  Telsat Turbo
+1268  Tektronix
+1269  Thomson-CSF/TTM
+126a  Lexmark International, Inc.
+126b  Adax, Inc.
+126c  Northern Telecom
+126d  Splash Technology, Inc.
+126e  Sumitomo Metal Industries, Ltd.
+126f  Silicon Motion, Inc.
+	0910  SM910
+1270  Olympus Optical Co., Ltd.
+1271  GW Instruments
+1272  Telematics International
+1273  Hughes Network Systems
+	0002  DirecPC
+1274  Ensoniq
+	1371  ES1371 [AudioPCI-97]
+	5000  ES1370 [AudioPCI]
+1275  Network Appliance Corporation
+1276  Switched Network Technologies, Inc.
+1277  Comstream
+1278  Transtech Parallel Systems Ltd.
+1279  Transmeta Corporation
+127a  Rockwell International
+	1002  HCF 56k V90 FaxModem
+	1003  HCF 56k V90 FaxModem
+	1004  HCF 56k V90 FaxModem
+	1005  HCF 56k V90 FaxModem
+		122d 4008  MDP3858SP-A SVD Modem
+		127a 1005  PCI56RVP Modem 
+		13df 1005  PCI56RVP Modem 
+		1436 1005  WS-5614PS3G
+	8234  RapidFire 616X ATM155 Adapter
+127b  Pixera Corporation
+127c  Crosspoint Solutions, Inc.
+127d  Vela Research
+127e  Winnov, L.P.
+127f  Fujifilm
+1280  Photoscript Group Ltd.
+1281  Yokogawa Electric Corporation
+1282  Davicom Semiconductor, Inc.
+1283  Integrated Technology Express, Inc.
+	673a  IT8330G
+	8330  IT8330G
+	e886  IT8330G
+1284  Sahara Networks, Inc.
+1285  Platform Technologies, Inc.
+	0100  PT-201C-O-P AGOGO-XP sound chip
+1286  Mazet GmbH
+1287  M-Pact, Inc.
+	001e  LS220D DVD Decoder
+	001f  LS220C DVD Decoder
+1288  Timestep Corporation
+1289  AVC Technology, Inc.
+128a  Asante Technologies, Inc.
+128b  Transwitch Corporation
+128c  Retix Corporation
+128d  G2 Networks, Inc.
+	0021  ATM155 Adapter
+128e  Hoontech Corporation/Samho Multi Tech Ltd.
+	0008  ST128 WSS/SB
+	0009  ST128 SAM9407
+	000a  ST128 Game Port
+	000b  ST128 MPU Port
+	000c  ST128 Ctrl Port
+128f  Tateno Dennou, Inc.
+1290  Sord Computer Corporation
+1291  NCS Computer Italia
+1292  Tritech Microelectronics Inc
+1293  Media Reality Technology
+1294  Rhetorex, Inc.
+1295  Imagenation Corporation
+1296  Kofax Image Products
+1297  Holco Enterprise Co, Ltd/Shuttle Computer
+1298  Spellcaster Telecommunications Inc.
+1299  Knowledge Technology Lab.
+129a  VMetro, inc.
+129b  Image Access
+129c  Jaycor
+129d  Compcore Multimedia, Inc.
+129e  Victor Company of Japan, Ltd.
+129f  OEC Medical Systems, Inc.
+12a0  Allen-Bradley Company
+12a1  Simpact Associates, Inc.
+12a2  Newgen Systems Corporation
+12a3  Lucent Technologies
+12a4  NTT Electronics Technology Company
+12a5  Vision Dynamics Ltd.
+12a6  Scalable Networks, Inc.
+12a7  AMO GmbH
+12a8  News Datacom
+12a9  Xiotech Corporation
+12aa  SDL Communications, Inc.
+12ab  Yuan Yuan Enterprise Co., Ltd.
+12ac  Measurex Corporation
+12ad  Multidata GmbH
+12ae  Alteon Networks Inc.
+	0001  AceNIC Gigabit Ethernet
+12af  TDK USA Corp
+12b0  Jorge Scientific Corp
+12b1  GammaLink
+12b2  General Signal Networks
+12b3  Inter-Face Co Ltd
+12b4  FutureTel Inc
+12b5  Granite Systems Inc.
+12b6  Natural Microsystems
+12b7  Cognex Modular Vision Systems Div. - Acumen Inc.
+12b8  Korg
+12b9  US Robotics/3Com
+	1006  WinModem
+12ba  PMC Sierra
+12bb  Nippon Unisoft Corporation
+12bc  Array Microsystems
+12bd  Computerm Corp.
+12be  Anchor Chips Inc.
+	3041  AN3041Q CO-MEM
+	3042  AN3042Q CO-MEM Lite
+12bf  Fujifilm Microdevices
+12c0  Infimed
+12c1  GMM Research Corp
+12c2  Mentec Limited
+12c3  Holtek Microelectronics Inc
+12c4  Connect Tech Inc
+12c5  Picture Elements Incorporated
+	0081  PCIVST [Grayscale Thresholding Engine]
+12c6  Mitani Corporation
+12c7  Dialogic Corp
+12c8  G Force Co, Ltd
+12c9  Gigi Operations
+12ca  Integrated Computing Engines
+12cb  Antex Electronics Corporation
+12cc  Pluto Technologies International
+12cd  Aims Lab
+12ce  Netspeed Inc.
+12cf  Prophet Systems, Inc.
+12d0  GDE Systems, Inc.
+12d1  PSITech
+12d2  NVidia / SGS Thomson (Joint Venture)
+	0008  NV1
+	0009  DAC64
+	0018  Riva128
+		107b 8030  STB Velocity 128
+		1092 0350  Viper V330
+		1092 1092  Viper V330
+		10b4 1b1b  STB Velocity 128
+		10b4 1b20  STB Velocity 128
+		10b4 1b21  STB Velocity 128
+		10b4 1b22  STB Velocity 128 AGP, NTSC TV-Out
+		10b4 1b23  STB Velocity 128 AGP, PAL TV-Out
+		10b4 1b27  STB Velocity 128 DVD
+		10b4 222a  STB Velocity 128 AGP
+		10b4 2230  STB Velocity 128
+		10b4 2235  STB Velocity 128 AGP
+	0019  Riva128ZX
+	0020  TNT
+	0028  TNT2
+	0029  UTNT2
+	002C  VTNT2
+	00A0  ITNT2
+12d3  Vingmed Sound A/S
+12d4  DGM&S
+12d5  Equator Technologies
+12d6  Analogic Corp
+12d7  Biotronic SRL
+12d8  Pericom Semiconductor
+12d9  Aculab PLC
+12da  True Time Inc.
+12db  Annapolis Micro Systems, Inc
+12dc  Symicron Computer Communication Ltd.
+12dd  Management Graphics
+12de  Rainbow Technologies
+12df  SBS Technologies Inc
+12e0  Chase Research
+	0010  ST16C654 Quad UART
+	0020  ST16C654 Quad UART
+	0030  ST16C654 Quad UART
+12e1  Nintendo Co, Ltd
+12e2  Datum Inc. Bancomm-Timing Division
+12e3  Imation Corp - Medical Imaging Systems
+12e4  Brooktrout Technology Inc
+12e5  Apex Semiconductor Inc
+12e6  Cirel Systems
+12e7  Sunsgroup Corporation
+12e8  Crisc Corp
+12e9  GE Spacenet
+12ea  Zuken
+12eb  Aureal Semiconductor
+	0001  Vortex 1
+	0002  Vortex 2
+12ec  3A International, Inc.
+12ed  Optivision Inc.
+12ee  Orange Micro
+12ef  Vienna Systems
+12f0  Pentek
+12f1  Sorenson Vision Inc
+12f2  Gammagraphx, Inc.
+12f3  Radstone Technology
+12f4  Megatel
+12f5  Forks
+12f6  Dawson France
+12f7  Cognex
+12f8  Electronic Design GmbH
+	0002  VideoMaker
+12f9  Four Fold Ltd
+12fb  Spectrum Signal Processing
+12fc  Capital Equipment Corp
+12fd  I2S
+12fe  ESD Electronic System Design GmbH
+12ff  Lexicon
+1300  Harman International Industries Inc
+1302  Computer Sciences Corp
+1303  Innovative Integration
+1304  Juniper Networks
+1305  Netphone, Inc
+1306  Duet Technologies
+1307  Computer Boards
+	0001  PCI-DAS1602/16
+	000C  PCI-PDISO8
+	000D  PCI-PDISO16
+	000B  PCI-DIO48H
+	000F  PCI-DAS1200
+	0010  PCI-DAS1602/12
+	0014  PCI-DIO24H
+	0015  PCI-DIO24H/CTR3
+	0016  PCI-DIO48H/CTR15
+	0017  PCI-DIO96H
+	0018  PCI-CTR05
+	0019  PCI-DAS1200/JR
+	001A  PCI-DAS1001
+	001B  PCI-DAS1002
+	001C  PCI-DAS1602JR/16
+	001D  PCI-DAS6402/16
+	001E  PCI-DAS6402/12
+	001F  PCI-DAS16/M1
+	0020  PCI-DDA02/12
+	0021  PCI-DDA04/12
+	0022  PCI-DDA08/12
+	0023  PCI-DDA02/16
+	0024  PCI-DDA04/16
+	0025  PCI-DDA08/16
+	0026  PCI-DAC04/12-HS
+	0027  PCI-DAC04/16-HS
+	0028  PCI-DIO24
+	0029  PCI-DAS08
+	002C  PCI-INT32
+	0033  PCI-DUAL-AC5
+	0034  PCI-DAS-TC
+	0035  PCI-DAS64/M1/16
+	0036  PCI-DAS64/M2/16
+	0037  PCI-DAS64/M3/16
+	004C  PCI-DAS1000
+1308  Jato Technologies Inc.
+	0001  NetCelerator Adapter
+1309  AB Semiconductor Ltd
+130a  Mitsubishi Electric Microcomputer
+130b  Colorgraphic Communications Corp
+130c  Ambex Technologies, Inc
+130d  Accelerix Inc
+130e  Yamatake-Honeywell Co. Ltd
+130f  Advanet Inc
+1310  Gespac
+1311  Videoserver, Inc
+1312  Acuity Imaging, Inc
+1313  Yaskawa Electric Co.
+1316  Teradyne Inc
+1317  Bridgecom, Inc
+1318  Packet Engines Inc.
+1319  Fortemedia, Inc
+	0801  Xwave QS3000A [FM801]
+	0802  Xwave QS3000A [FM801 game port]
+131a  Finisar Corp.
+131c  Nippon Electro-Sensory Devices Corp
+131d  Sysmic, Inc.
+131e  Xinex Networks Inc
+131f  Siig Inc
+	1010  Duet 1S(16550)+1P
+	1011  Duet 1S(16650)+1P
+	1012  Duet 1S(16850)+1P
+	1020  CyberParallel (1-port)
+	1021  CyberParallel (2-port)
+	1034  Trio 2S(16550)+1P
+	1035  Trio 2S(16650)+1P
+	1036  Trio 2S(16850)+1P
+	2010  Duet 1S(16550)+1P
+	2011  Duet 1S(16650)+1P
+	2012  Duet 1S(16850)+1P
+	2020  CyberParallel (1-port)
+	2021  CyberParallel (2-port)
+	2040  Trio 1S(16550)+2P
+	2041  Trio 1S(16650)+2P
+	2042  Trio 1S(16850)+2P
+	2060  Trio 2S(16550)+1P
+	2061  Trio 2S(16650)+1P
+	2062  Trio 2S(16850)+1P
+1320  Crypto AG
+1321  Arcobel Graphics BV
+1322  MTT Co., Ltd
+1323  Dome Inc
+1324  Sphere Communications
+1325  Salix Technologies, Inc
+1326  Seachange international
+1327  Voss scientific
+1328  quadrant international
+1329  Productivity Enhancement
+132a  Microcom Inc.
+132b  Broadband Technologies
+132c  Micrel Inc
+132d  Integrated Silicon Solution, Inc.
+1330  MMC Networks
+1331  Radisys Corp.
+1332  Micro Memory
+1334  Redcreek Communications, Inc
+1335  Videomail, Inc
+1337  Third Planet Publishing
+1338  BT Electronics
+133a  Vtel Corp
+133b  Softcom Microsystems
+133c  Holontech Corp
+133d  SS Technologies
+133e  Virtual Computer Corp
+133f  SCM Microsystems
+1340  Atalla Corp
+1341  Kyoto Microcomputer Co
+1342  Promax Systems Inc
+1343  Phylon Communications Inc
+1344  Crucial Technology
+1345  Arescom Inc
+1347  Odetics
+1349  Sumitomo Electric Industries, Ltd.
+134a  DTC Technology Corp.
+	0001  Domex 536
+134b  ARK Research Corp.
+134c  Chori Joho System Co. Ltd
+134d  PCTel Inc
+134e  CSTI
+134f  Algo System Co Ltd
+1350  Systec Co. Ltd
+1351  Sonix Inc
+1353  Dassault A.T.
+1354  Dwave System Inc
+1355  Kratos Analytical Ltd
+1356  The Logical Co
+1359  Prisa Networks
+135a  Brain Boxes
+135b  Giganet Inc
+135c  Quatech Inc
+135d  ABB Network Partner AB
+135e  Sealevel Systems Inc
+	7101  Single Port RS-232/422/485/530
+	7201  Dual Port RS-232/422/485 Interface
+	7202  Dual Port RS-232 Interface
+	7401  Four Port RS-232 Interface
+	7402  Four Port RS-422/485 Interface
+	7801  Eight Port RS-232 Interface
+	8001  8001 Digital I/O Adapter
+1360  Meinberg Funkuhren
+1361  Soliton Systems K.K.
+1362  Fujifacom Corporation
+1363  Phoenix Technology Ltd
+1364  ATM Communications Inc
+1365  Hypercope GmbH
+1366  Teijin Seiki Co. Ltd
+1367  Hitachi Zosen Corporation
+1368  Skyware Corporation
+1369  Digigram
+136a  High Soft Tech
+136b  Kawasaki Steel Corporation
+136c  Adtek System Science Co Ltd
+136d  Gigalabs Inc
+136f  Applied Magic Inc
+1370  ATL Products
+1371  CNet Technology Inc
+1373  Silicon Vision Inc
+1374  Silicom Ltd
+1375  Argosystems Inc
+1376  LMC
+1377  Electronic Equipment Production & Distribution GmbH
+1378  Telemann Co. Ltd
+1379  Asahi Kasei Microsystems Co Ltd
+137a  Mark of the Unicorn Inc
+137b  PPT Vision
+137c  Iwatsu Electric Co Ltd
+137d  Dynachip Corporation
+137e  Patriot Scientific Corporation
+137f  Japan Satellite Systems Inc
+1380  Sanritz Automation Co Ltd
+1381  Brains Co. Ltd
+1382  Marian - Electronic & Software
+1383  Controlnet Inc
+1384  Reality Simulation Systems Inc
+1385  Netgear
+	620a  GA620
+1386  Video Domain Technologies
+1387  Systran Corp
+1388  Hitachi Information Technology Co Ltd
+1389  Applicom International
+	0001  PCI1500PFB [Intelligent fieldbus adaptor]
+138a  Fusion Micromedia Corp
+138b  Tokimec Inc
+138c  Silicon Reality
+138d  Future Techno Designs pte Ltd
+138e  Basler GmbH
+138f  Patapsco Designs Inc
+1390  Concept Development Inc
+1391  Development Concepts Inc
+1392  Medialight Inc
+1393  Moxa Technologies Co Ltd
+1394  Level One Communications
+1395  Ambicom Inc
+1396  Cipher Systems Inc
+1397  Cologne Chip Designs GmbH
+	2bd0  ISDN network controller
+1398  Clarion co. Ltd
+1399  Rios systems Co Ltd
+139a  Alacritech Inc
+139b  Mediasonic Multimedia Systems Ltd
+139c  Quantum 3d Inc
+139d  EPL limited
+139e  Media4
+139f  Aethra s.r.l.
+13a0  Crystal Group Inc
+13a1  Kawasaki Heavy Industries Ltd
+13a2  Ositech Communications Inc
+13a3  Hi-Fn
+13a4  Rascom Inc
+13a5  Audio Digital Imaging Inc
+13a6  Videonics Inc
+13a7  Teles AG
+13a8  Exar Corp.
+13a9  Siemens Medical Systems, Ultrasound Group
+13aa  Broadband Networks Inc
+13ab  Arcom Control Systems Ltd
+13ac  Motion Media Technology Ltd
+13ad  Nexus Inc
+13ae  ALD Technology Ltd
+13af  T.Sqware
+13b0  Maxspeed Corp
+13b1  Tamura corporation
+13b2  Techno Chips Co. Ltd
+13b3  Lanart Corporation
+13b4  Wellbean Co Inc
+13b5  ARM
+13b6  Dlog GmbH
+13b7  Logic Devices Inc
+13b8  Nokia Telecommunications oy
+13b9  Elecom Co Ltd
+13ba  Oxford Instruments
+13bb  Sanyo Technosound Co Ltd
+13bc  Bitran Corporation
+13bd  Sharp corporation
+13be  Miroku Jyoho Service Co. Ltd
+13bf  Sharewave Inc
+13c0  Microgate Corporation
+	0010  SyncLink WAN Adapter
+13c1  3ware Inc
+13c2  Technotrend Systemtechnik GmbH
+13c3  Janz Computer AG
+13c4  Phase Metrics
+13c5  Alphi Technology Corp
+13c6  Condor Engineering Inc
+13c7  Blue Chip Technology Ltd
+13c8  Apptech Inc
+13c9  Eaton Corporation
+13ca  Iomega Corporation
+13cb  Yano Electric Co Ltd
+13cc  Metheus Corporation
+13cd  Compatible Systems Corporation
+13ce  Cocom A/S
+13cf  Studio Audio & Video Ltd
+13d0  Techsan Electronics Co Ltd
+13d1  Abocom Systems Inc
+13d2  Shark Multimedia Inc
+13d3  IMC Networks
+13d4  Graphics Microsystems Inc
+13d5  Media 100 Inc
+13d6  K.I. Technology Co Ltd
+13d7  Toshiba Engineering Corporation
+13d8  Phobos corporation
+13d9  Apex PC Solutions Inc
+13da  Intresource Systems pte Ltd
+13db  Janich & Klass Computertechnik GmbH
+13dc  Netboost Corporation
+13dd  Multimedia Bundle Inc
+13de  ABB Robotics Products AB
+13df  E-Tech Inc
+	0001  PCI56RVP Modem
+13e0  GVC Corporation
+13e1  Silicom Multimedia Systems Inc
+13e2  Dynamics Research Corporation
+13e3  Nest Inc
+13e4  Calculex Inc
+13e5  Telesoft Design Ltd
+13e6  Argosy research Inc
+13e7  NAC Incorporated
+13e8  Chip Express Corporation
+13e9  Chip Express Corporation
+13ea  Dallas Semiconductor
+13eb  Hauppauge Computer Works Inc
+13ec  Zydacron Inc
+13ed  Raytheion E-Systems
+13ee  Hayes Microcomputer Products Inc
+13ef  Coppercom Inc
+13f0  Sundance technology Inc
+13f1  Oce' - Technologies B.V.
+13f2  Ford Microelectronics Inc
+13f3  Mcdata Corporation
+13f4  Troika Design Inc
+13f5  Kansai Electric Co. Ltd
+13f6  C-Media Electronics Inc
+	0100  CM8338A
+	0101  CM8338B
+	0111  CM8738
+13f7  Wildfire Communications
+13f8  Ad Lib Multimedia Inc
+13f9  NTT Advanced Technology Corp.
+13fa  Pentland Systems Ltd
+13fb  Aydin Corp
+13fc  Computer Peripherals International
+13fd  Micro Science Inc
+13fe  Advantech Co. Ltd
+13ff  Silicon Spice Inc
+1400  Artx Inc
+1401  CR-Systems A/S
+1402  Meilhaus Electronic GmbH
+1403  Ascor Inc
+1404  Fundamental Software Inc
+1405  Excalibur Systems Inc
+1406  Oce' Printing Systems GmbH
+1407  Lava Computer mfg Inc
+	8000  Lava Parallel
+	8002  Lava Dual Parallel port A
+	8003  Lava Dual Parallel port B
+	8800  BOCA Research IOPPAR
+1408  Aloka Co. Ltd
+1409  Timedia Technology Co Ltd
+140a  DSP Research Inc
+140b  Ramix Inc
+140c  Elmic Systems Inc
+140d  Matsushita Electric Works Ltd
+140e  Goepel Electronic GmbH
+140f  Salient Systems Corp
+1410  Midas lab Inc
+1411  Ikos Systems Inc
+1412  IC Ensemble Inc
+1413  Addonics
+1414  Microsoft Corporation
+1415  Oxford Semiconductor Ltd
+1416  Multiwave Innovation pte Ltd
+1417  Convergenet Technologies Inc
+1418  Kyushu electronics systems Inc
+1419  Excel Switching Corp
+141a  Apache Micro Peripherals Inc
+141b  Zoom Telephonics Inc
+141d  Digitan Systems Inc
+141e  Fanuc Ltd
+141f  Visiontech Ltd
+1420  Psion Dacom plc
+1421  Ads Technologies Inc
+1422  Ygrec Systems Co Ltd
+1423  Custom Technology Corp.
+1424  Videoserver Connections
+1425  ASIC Designers Inc
+1426  Storage Technology Corp.
+1427  Better On-Line Solutions
+1428  Edec Co Ltd
+1429  Unex Technology Corp.
+142a  Kingmax Technology Inc
+142b  Radiolan
+142c  Minton Optic Industry Co Ltd
+142d  Pix stream Inc
+142e  Vitec Multimedia
+142f  Radicom Research Inc
+1430  ITT Aerospace/Communications Division
+1431  Gilat Satellite Networks
+1432  Edimax Computer Co.
+1433  Eltec Elektronik GmbH
+1435  Real Time Devices US Inc.
+1436  CIS Technology Inc
+1437  Nissin Inc Co
+1438  Atmel-dream
+1439  Outsource Engineering & Mfg. Inc
+143a  Stargate Solutions Inc
+143b  Canon Research Center, America
+143c  Amlogic Inc
+143d  Tamarack Microelectronics Inc
+143e  Jones Futurex Inc
+143f  Lightwell Co Ltd - Zax Division
+1440  ALGOL Corp.
+1441  AGIE Ltd
+1442  Phoenix Contact GmbH & Co.
+1443  Unibrain S.A.
+1444  TRW
+1445  Logical DO Ltd
+1446  Graphin Co Ltd
+1447  AIM GmBH
+1448  Alesis Studio Electronics
+1449  TUT Systems Inc
+144a  Adlink Technology
+144b  Loronix Information Systems Inc
+144c  Catalina Research Inc
+144d  Samsung Electronics Co Ltd
+144e  OLITEC
+144f  Askey Computer Corp.
+1450  Octave Communications Ind.
+1451  SP3D Chip Design GmBH
+1453  MYCOM Inc
+1454  Altiga Networks
+1455  Logic Plus Plus Inc
+1456  Advanced Hardware Architectures
+1457  Nuera Communications Inc
+1458  Giga-byte Technology
+1459  DOOIN Electronics
+145a  Escalate Networks Inc
+145b  PRAIM SRL
+145c  Cryptek
+145d  Gallant Computer Inc
+145e  Aashima Technology B.V.
+145f  Baldor Electric Company
+1460  DYNARC INC
+1461  Avermedia Technologies Inc
+1462  Micro-star International Co Ltd
+1463  Fast Corporation
+1464  Interactive Circuits & Systems Ltd
+1465  GN NETTEST Telecom DIV.
+1466  Designpro Inc.
+1467  DIGICOM SPA
+1468  AMBIT Microsystem Corp.
+1469  Cleveland Motion Controls
+146a  IFR
+146b  Parascan Technologies Ltd
+146c  Ruby Tech Corp.
+146d  Tachyon, INC.
+146e  Williams Electronics Games, Inc.
+146f  Multi Dimensional Consulting Inc
+1470  Bay Networks
+1471  Integrated Telecom Express Inc
+1472  DAIKIN Industries, Ltd
+1473  ZAPEX Technologies Inc
+1474  Doug Carson & Associates
+1475  PICAZO Communications
+1476  MORTARA Instrument Inc
+1477  Net Insight
+1478  DIATREND Corporation
+1479  TORAY Industries Inc
+147a  FORMOSA Industrial Computing
+147b  ABIT Computer Corp.
+147c  AWARE, Inc.
+147d  Interworks Computer Products
+147e  Matsushita Graphic Communication Systems, Inc.
+147f  NIHON UNISYS, Ltd.
+1480  SCII Telecom
+1481  BIOPAC Systems Inc
+1482  ISYTEC - Integrierte Systemtechnik GmBH
+1483  LABWAY Corporation
+1484  Logic Corporation
+1485  ERMA - Electronic GmBH
+1486  L3 Communications Telemetry & Instrumentation
+1487  MARQUETTE Medical Systems
+1488  KONTRON Electronik GmBH
+1489  KYE Systems Corporation
+148a  OPTO
+148b  INNOMEDIALOGIC Inc.
+148c  C.P. Technology Co. Ltd
+148d  DIGICOM Systems, Inc.
+148e  OSI Plus Corporation
+148f  Plant Equipment, Inc.
+1490  Stone Microsystems PTY Ltd.
+1491  ZEAL Corporation
+1492  Time Logic Corporation
+1493  MAKER Communications
+1494  WINTOP Technology, Inc.
+1495  TOKAI Communications Industry Co. Ltd
+1496  JOYTECH Computer Co., Ltd.
+1497  SMA Regelsysteme GmBH
+1498  TEWS Datentechnik GmBH
+1499  EMTEC CO., Ltd
+149a  ANDOR Technology Ltd
+149b  SEIKO Instruments Inc
+149c  OVISLINK Corp.
+149D  NEWTEK Inc
+149e  Mapletree Networks Inc.
+149f  LECTRON Co Ltd
+14a0  SOFTING GmBH
+14a1  Systembase Co Ltd
+14a2  Millennium Engineering Inc
+14a3  Maverick Networks
+14a4  GVC/BCM Advanced Research
+14a5  XIONICS Document Technologies Inc
+14a6  INOVA Computers GmBH & Co KG
+14a7  MYTHOS Systems Inc
+14a8  FEATRON Technologies Corporation
+14a9  HIVERTEC Inc
+14aa  Advanced MOS Technology Inc
+14ab  Mentor Graphics Corp.
+14ac  Novaweb Technologies Inc
+14ad  Time Space Radio AB
+14ae  CTI, Inc
+14af  Guillemot Corporation
+14b0  BST Communication Technology Ltd
+14b1  Nextcom K.K.
+14b2  ENNOVATE Networks Inc
+14b3  XPEED Inc
+14b4  PHILIPS Business Electronics B.V.
+14b5  Creamware GmBH
+14b6  Quantum Data Corp.
+14b7  PROXIM Inc
+	0001  Symphony 4110
+14b8  Techsoft Technology Co Ltd
+14b9  AIRONET Wireless Communications
+	0001  PC4800
+14ba  INTERNIX Inc.
+14bb  SEMTECH Corporation
+14bc  Globespan Semiconductor Inc.
+14bd  CARDIO Control N.V.
+14be  L3 Communications
+14bf  SPIDER Communications Inc.
+14c0  COMPAL Electronics Inc
+14c1  MYRICOM Inc.
+14c2  DTK Computer
+14c3  MEDIATEK Corp.
+14c4  IWASAKI Information Systems Co Ltd
+14c5  Automation Products AB
+14c6  Data Race Inc
+14c7  Modular Technology Holdings Ltd
+14c8  Turbocomm Tech. Inc.
+14c9  ODIN Telesystems Inc
+14ca  PE Logic Corp.
+14cb  Billionton Systems Inc
+14cc  NAKAYO Telecommunications Inc
+14cd  Universal Scientific Ind.
+14ce  Whistle Communications
+14cf  TEK Microsystems Inc.
+14d0  Ericsson Axe R & D
+14d1  Computer Hi-Tech Co Ltd
+14d2  Titan Electronics Inc
+14d3  CIRTECH (UK) Ltd
+14d4  Panacom Technology Corp
+14d5  Nitsuko Corporation
+14d6  Accusys Inc
+14d7  Hirakawa Hewtech Corp
+14d8  HOPF Elektronik GmBH
+14d9  Alpha Processor Inc
+14da  National Aerospace Laboratories
+14db  AFAVLAB Technology Inc
+14dc  Amplicon Liveline Ltd
+14dd  Boulder Design Labs Inc
+14de  Applied Integration Corporation
+14df  ASIC Communications Corp
+14e1  INVERTEX
+14e2  INFOLIBRIA
+14e3  AMTELCO
+14e4  BROADCOM Corporation
+14e5  Pixelfusion Ltd
+14e6  SHINING Technology Inc
+14e7  3CX
+14e8  RAYCER Inc
+14e9  GARNETS System CO Ltd
+14ea  PLANEX COMMUNICATIONS Inc
+14eb  SEIKO EPSON Corp
+14ec  ACQIRIS
+14ed  DATAKINETICS Ltd
+14ee  MASPRO KENKOH Corp
+14ef  CARRY Computer ENG. CO Ltd
+14f0  CANON RESEACH CENTRE FRANCE
+14f1  CONEXANT
+	2013  HSP MicroModem 56K
+14f2  MOBILITY Electronics
+14f3  BROADLOGIC
+14f4  TOKYO Electronic Industry CO Ltd
+14f5  SOPAC Ltd
+14f6  COYOTE Technologies LLC
+14f7  WOLF Technology Inc
+14f8  AUDIOCODES Inc
+14f9  AG COMMUNICATIONS
+14fa  WANDEL & GOCHERMANN
+14fb  TRANSAS MARINE (UK) Ltd
+14fc  QUADRICS Supercomputers World
+14fd  JAPAN Computer Industry Inc
+14fe  ARCHTEK TELECOM Corp
+14ff  TWINHEAD INTERNATIONAL Corp
+1500  DELTA Electronics, Inc
+1501  BANKSOFT CANADA Ltd
+1502  MITSUBISHI ELECTRIC LOGISTICS SUPPORT Co Ltd
+1503  KAWASAKI LSI USA Inc
+1504  KAISER Electronics
+1505  ITA INGENIEURBURO FUR TESTAUFGABEN GmbH
+1506  CHAMELEON Systems Inc
+# 1507  HTEC Ltd
+# Commented out because there are no known HTEC chips and 1507 is already
+# used by mistake by Motorola (see vendor ID 1057)
+1508  HONDA CONNECTORS/MHOTRONICS Inc
+1509  FIRST INTERNATIONAL Computer Inc
+150a  FORVUS RESEARCH Inc
+150b  YAMASHITA Systems Corp
+150c  KYOPAL CO Ltd
+150d  WARPSPPED Inc
+150e  C-PORT Corp
+150f  INTEC GmbH
+1510  BEHAVIOR TECH Computer Corp
+1511  CENTILLIUM Technology Corp
+1512  ROSUN Technologies Inc
+1513  Raychem
+1514  TFL LAN Inc
+1515  Advent design
+1516  MYSON Technology Inc
+1517  ECHOTEK Corp
+1518  PEP MODULAR Computers GmbH
+1519  TELEFON AKTIEBOLAGET LM Ericsson
+151a  GLOBETEK Inc
+151b  COMBOX Ltd
+151c  DIGITAL AUDIO LABS Inc
+151d  Fujitsu Computer Products Of America
+151e  MATRIX Corp
+151f  TOPIC SEMICONDUCTOR Corp
+1520  CHAPLET System Inc
+1521  BELL Corp
+1522  MainPine Ltd
+1523  MUSIC Semiconductors
+1524  ENE Technology Inc
+1525  IMPACT Technologies
+1526  ISS, Inc
+1527  SOLECTRON
+1528  ACKSYS
+1529  AMERICAN MICROSystems Inc
+152a  QUICKTURN DESIGN Systems
+152b  FLYTECH Technology CO Ltd
+152c  MACRAIGOR Systems LLC
+152d  QUANTA Computer Inc
+152e  MELEC Inc
+152f  PHILIPS - CRYPTO
+1530  ACQIS Technology Inc
+1531  CHRYON Corp
+1532  ECHELON Corp
+1533  BALTIMORE
+1534  ROAD Corp
+1535  EVERGREEN Technologies Inc
+1537  DATALEX COMMUNCATIONS
+1538  ARALION Inc
+1539  ATELIER INFORMATIQUES et ELECTRONIQUE ETUDES S.A.
+153a  ONO SOKKI
+153b  TERRATEC Electronic GmbH
+153c  ANTAL Electronic
+153d  FILANET Corp
+153e  TECHWELL Inc
+153f  MIPS DENMARK
+1540  PROVIDEO MULTIMEDIA Co Ltd
+1541  MACHONE Communications
+1542  VIVID Technology Inc
+1543  SILICON Laboratories
+1544  DCM DATA Systems
+1545  VISIONTEK
+1546  IOI Technology Corp
+1547  MITUTOYO Corp
+1548  JET PROPULSION Laboratory
+1549  INTERCONNECT Systems Solutions
+154a  MAX Technologies Inc
+154b  COMPUTEX Co Ltd
+154c  VISUAL Technology Inc
+154d  PAN INTERNATIONAL Industrial Corp
+154e  SERVOTEST Ltd
+154f  STRATABEAM Technology
+1550  OPEN NETWORK Co Ltd
+1551  SMART Electronic DEVELOPMENT GmBH
+1552  RACAL AIRTECH Ltd
+1553  CHICONY Electronics Co Ltd
+1554  PROLINK Microsystems Corp
+1555  GESYTEC GmBH
+1556  PLD APPLICATIONS
+1557  MEDIASTAR Co Ltd
+1558  CLEVO/KAPOK Computer
+1559  SI LOGIC Ltd
+155a  INNOMEDIA Inc
+155b  PROTAC INTERNATIONAL Corp
+1668  Action Tec Electronics Inc
+1a08  Sierra semiconductor
+	0000  SC15064
+1b13  Jaton Corp
+1c1c  Symphony
+	0001  82C101
+1d44  DPT
+	a400  PM2x24/PM3224
+1de1  Tekram Technology Co.,Ltd.
+	2020  DC-390
+	690c  690c
+	dc29  DC290
+2001  Temporal Research Ltd
+21c3  21st Century Computer Corp.
+2348  Racore
+	2010  8142 100VG/AnyLAN
+2646  Kingston Technologies
+270b  Xantel Corporation
+270f  Chaintech Computer Co. Ltd
+2711  AVID Technology Inc.
+3000  Hansol Electronics Inc.
+3142  Post Impression Systems.
+3388  Hint Corp
+	8011  VXPro II Chipset
+	8012  VXPro II Chipset
+	8013  VXPro II Chipset
+3513  ARCOM Control Systems Ltd
+3d3d  3DLabs
+	0001  GLINT 300SX
+	0002  GLINT 500TX
+	0003  GLINT Delta
+	0004  Permedia
+	0005  Permedia
+	0006  GLINT MX
+	0007  3D Extreme
+	0009  Permedia II 2D+3D
+		3d3d 0100  AccelStar II 3D Accelerator
+		3d3d 0111  Permedia 3:16
+		3d3d 0114  Santa Ana
+		3d3d 0116  Oxygen GVX1
+		3d3d 0119  Scirocco
+		3d3d 0120  Santa Ana PCL
+		3d3d 0125  Oxygen VX1
+		3d3d 0127  Permedia3 Create!
+	0100  Permedia II 2D+3D
+	1004  Permedia
+	3d04  Permedia
+	ffff  Glint VGA
+4005  Avance Logic Inc.
+	1064  ALG-2064
+	2064  ALG-2064i
+	2128  ALG-2364A GUI Accelerator
+	2301  ALG-2301
+	2302  ALG-2302
+	2303  AVG-2302 GUI Accelerator
+	2364  ALG-2364A
+	2464  ALG-2464
+	2501  ALG-2564A/25128A
+4033  Addtron Technology Co, Inc.
+4444  Internext Compression Inc
+4468  Bridgeport machines
+4594  Cogetec Informatique Inc
+45fb  Baldor Electric Company
+4680  Umax Computer Corp
+4843  Hercules Computer Technology Inc
+4943  Growth Networks
+4978  Axil Computer Inc
+4a14  NetVin
+	5000  NV5000SC
+4b10  Buslogic Inc.
+4c48  LUNG HWA Electronics
+4d51  MEDIAQ Inc.
+	0200  MQ-200
+4ddc  ILC Data Device Corp
+5053  Voyetra Technologies
+	2010  Daytona Audio Adapter
+5136  S S Technologies
+5143  Qualcomm Inc
+5145  Ensoniq (Old)
+	3031  Concert AudioPCI
+5301  Alliance Semiconductor Corp.
+	0001  ProMotion aT3D
+5333  S3 Inc.
+	0551  Plato/PX (system)
+	5631  86c325 [ViRGE]
+	8800  86c866 [Vision 866]
+	8801  86c964 [Vision 964]
+	8810  86c764_0 [Trio 32 vers 0]
+	8811  86c764/765 [Trio32/64/64V+]
+	8812  86cM65 [Aurora64V+]
+	8813  86c764_3 [Trio 32/64 vers 3]
+	8814  86c767 [Trio 64UV+]
+	8815  86cM65 [Aurora 128]
+	883d  86c988 [ViRGE/VX]
+	8870  FireGL
+	8880  86c868 [Vision 868 VRAM] vers 0
+	8881  86c868 [Vision 868 VRAM] vers 1
+	8882  86c868 [Vision 868 VRAM] vers 2
+	8883  86c868 [Vision 868 VRAM] vers 3
+	88b0  86c928 [Vision 928 VRAM] vers 0
+	88b1  86c928 [Vision 928 VRAM] vers 1
+	88b2  86c928 [Vision 928 VRAM] vers 2
+	88b3  86c928 [Vision 928 VRAM] vers 3
+	88c0  86c864 [Vision 864 DRAM] vers 0
+	88c1  86c864 [Vision 864 DRAM] vers 1
+	88c2  86c864 [Vision 864-P DRAM] vers 2
+	88c3  86c864 [Vision 864-P DRAM] vers 3
+	88d0  86c964 [Vision 964 VRAM] vers 0
+	88d1  86c964 [Vision 964 VRAM] vers 1
+	88d2  86c964 [Vision 964-P VRAM] vers 2
+	88d3  86c964 [Vision 964-P VRAM] vers 3
+	88f0  86c968 [Vision 968 VRAM] rev 0
+	88f1  86c968 [Vision 968 VRAM] rev 1
+	88f2  86c968 [Vision 968 VRAM] rev 2
+	88f3  86c968 [Vision 968 VRAM] rev 3
+	8900  86c755 [Trio 64V2/DX]
+	8901  Trio 64V2/DX or /GX
+	8902  Plato/PX
+	8903  Trio 3D business multimedia
+	8904  Trio 64 3D
+		1014 00db  Integrated Trio3D
+		5333 8904  86C365 Trio3D AGP
+	8905  Trio 64V+ family
+	8906  Trio 64V+ family
+	8907  Trio 64V+ family
+	8908  Trio 64V+ family
+	8909  Trio 64V+ family
+	890a  Trio 64V+ family
+	890b  Trio 64V+ family
+	890c  Trio 64V+ family
+	890d  Trio 64V+ family
+	890e  Trio 64V+ family
+	890f  Trio 64V+ family
+	8a01  ViRGE/DX or /GX
+		0e11 b032  ViRGE/GX
+		10b4 1617  Nitro 3D
+		10b4 1717  Nitro 3D
+		5333 8a01  ViRGE/DX
+	8a10  ViRGE/GX2
+		1092 8a10  Stealth 3D 4000
+	8a13  86c368 [Trio 3D/2X]
+		5333 8a13  Trio3D/2X
+	8a20  86c794 [Savage 3D]
+	8a21  86c795 [Savage 3D/MV]
+	8a22  Savage 4
+		105d 0018  SR9 8Mb SDRAM
+		105d 002a  SR9 Pro 16Mb SDRAM
+		105d 003a  SR9 Pro 32Mb SDRAM
+		105d 092f  SR9 Pro+ 16Mb SGRAM
+		1092 4207  Stealth III S540
+		1092 4800  Stealth III S540
+		1092 4808  Stealth III S540
+		1092 480e  Stealth III S540
+		1092 4904  Stealth III S520
+		1092 4a09  Stealth III S540
+		1092 4a0b  Stealth III S540 Xtreme
+		1092 4a0f  Stealth III S540
+		1092 4e01  Stealth III S540
+		1102 101d  3d Blaster Savage 4
+		1102 101e  3d Blaster Savage 4
+	8a23  Savage 4
+	8c00  ViRGE/M3
+	8c01  ViRGE/MX
+	8c02  ViRGE/MX+
+	8c03  ViRGE/MX+MV
+	ca00  SonicVibes
+544c  Teralogic Inc
+5455  Technische University Berlin
+	4458  S5933
+5519  Cnet Technologies, Inc.
+5555  Genroco, Inc
+	0003  TURBOstor HFP-832 [HiPPI NIC]
+5700  Netpower
+6356  UltraStor
+6374  c't Magazin für Computertechnik
+	6773  GPPCI
+6409  Logitec Corp.
+6666  Decision Computer International Co.
+	0001  PCCOM4
+	0002  PCCOM8
+7604  O.N. Electronic Co Ltd.
+7bde  MIDAC Corporation
+7fed  PowerTV
+8008  Quancom Electronic GmbH
+	0010  WDOG1 [PCI-Watchdog 1]
+	0011  PWDOG2 [PCI-Watchdog 2]
+8086  Intel Corporation
+	0007  82379AB
+	0039  21145
+	0122  82437FX
+	0482  82375EB
+	0483  82424ZX [Saturn]
+	0484  82378IB [SIO ISA Bridge]
+	0486  82430ZX [Aries]
+	04a3  82434LX [Mercury/Neptune]
+	04d0  82437FX [Triton FX]
+	0960  80960RP [i960 RP Microprocessor/Bridge]
+	1000  82542 Gigabit Ethernet Adapter
+		0e11 b0df  NC1632 Gigabit Ethernet Adapter
+		0e11 b0e0  NC1633 Gigabit Ethernet Adapter
+		0e11 b123  NC1634 Gigabit Ethernet Adapter
+		1014 0119  Netfinity Gigabit Ethernet SX Adapter
+		8086 1000  EtherExpress PRO/1000 Gigabit Server Adapter
+	1209  82559ER
+	1221  82092AA_0
+	1222  82092AA_1
+	1223  SAA7116
+	1225  82452KX/GX [Orion]
+	1226  82596
+	1227  82865 [Ether Express Pro 100]
+	1228  82556 [Ether Express Pro 100 Smart]
+	1229  82557 [Ethernet Pro 100]
+		0e11 b01e  NC3120
+		0e11 b01f  NC3122
+		0e11 b02f  NC1120
+		0e11 b04a  Netelligent 10/100TX NIC with Wake on LAN
+		0e11 b0c6  Embedded NC3120 with Wake on LAN
+		0e11 b0c7  Embedded NC3121
+		0e11 b0d7  NC3121 with Wake on LAN
+		0e11 b0dd  NC3131
+		0e11 b0de  NC3132
+		0e11 b0e1  NC3133
+		1014 005c  Ethernet Pro 10/100
+		1014 105c  Netfinity 10/100
+		1033 8000  PC-9821X-B06
+		1033 8016  PK-UG-X006
+		1033 801f  PK-UG-X006
+		103c 10C0  Ethernet Pro 10/100TX
+		103c 10C3  Ethernet Pro 10/100TX
+		103c 1200  Ethernet Pro 10/100TX
+		10c3 1100  SmartEther100 SC1100
+		1259 2560  AT-2560 100 
+		1259 2561  AT-2560 100 FX Ethernet Adapter
+		1266 0001  NE10/100 Adapter
+		8086 0001  EtherExpress PRO/100B (TX)
+		8086 0002  EtherExpress PRO/100B (T4)
+		8086 0003  EtherExpress PRO/10+
+		8086 0004  EtherExpress PRO/100 WfM
+		8086 0005  82557 10/100
+		8086 0006  82557 10/100 with Wake on LAN
+		8086 0007  82558 10/100 Adapter
+		8086 0008  82558 10/100 with Wake on LAN
+		8086 0009  EtherExpress PRO/100+
+		8086 000a  EtherExpress PRO/100+ Management Adapter
+		8086 000b  EtherExpress PRO/100+
+		8086 000c  EtherExpress PRO/100+ Management Adapter
+		8086 000d  EtherExpress PRO/100+ Alert On LAN II* Adapter
+		8086 000e  EtherExpress PRO/100+ Management Adapter with Alert On LAN*
+		8086 1009  EtherExpress PRO/100+ Server Adapter
+		8086 100C  EtherExpress PRO/100+ Server Adapter (PILA8470B)
+		8086 10f0  EtherExpress PRO/100+ Dual Port Adapter
+		8086 200d  EtherExpress PRO/100 Cardbus
+		8086 200e  EtherExpress PRO/100 LAN+V90 Cardbus Modem
+		8086 3000  82559 Fast Ethernet LAN on Motherboard
+		8086 3001  82559 Fast Ethernet LOM with Basic Alert on LAN*
+		8086 3002  82559 Fast Ethernet LOM with Alert on LAN II*
+	122d  430FX - 82437FX TSC [Triton I]
+	122e  82371FB PIIX ISA [Triton I]
+	1230  82371FB PIIX IDE [Triton I]
+	1231  DSVD Modem
+	1234  430MX - 82371MX MPIIX [430MX PCIset - 82371MX Mobile PCI I/O IDE Xcelerator (MPIIX)]
+	1235  430MX - 82437MX MTSC [430MX PCIset - 82437MX Mobile System Controller (MTSC) and 82438MX Mobile Data Path (MTDP)]
+	1237  440FX - 82441FX PMC [Natoma]
+	1239  82371FB
+	123b  82380PB
+	123c  82380AB
+	1240  752 AGP
+	124b  82380FB
+	1250  430HX - 82439HX TXC [Triton II]
+	1960  80960RP [i960RP Microprocessor]
+		101e 0438  MegaRaid 438
+		101e 0466  MegaRaid 466
+		103c 10C6  MegaRaid 438
+		103c 10C7  MegaRaid T5
+		1111 1111  MegaRaid 466
+		113c 03A2  MegaRaid
+	5200  EtherExpress PRO/100
+	5201  EtherExpress PRO/100
+	7000  82371SB PIIX3 ISA [Natoma/Triton II]
+	7010  82371SB PIIX3 IDE [Natoma/Triton II]
+	7020  82371SB PIIX3 USB [Natoma/Triton II]
+	7030  430VX - 82437VX TVX [Triton VX]
+	7100  430TX - 82439TX MTXC
+	7110  82371AB PIIX4 ISA
+	7111  82371AB PIIX4 IDE
+	7112  82371AB PIIX4 USB
+	7113  82371AB PIIX4 ACPI
+	7120  82810 GMCH [Graphics Memory Controller Hub]
+	7121  82810 CGC [Chipset Graphics Controller]
+	7122  82810-DC100 GMCH [Graphics Memory Controller Hub]
+	7123  82810-DC100 CGC [Chipset Graphics Controller]
+	7180  440LX/EX - 82443LX/EX Host bridge
+	7181  440LX/EX - 82443LX/EX AGP bridge
+	7190  440BX/ZX - 82443BX/ZX Host bridge
+		0e11 0500  Armada 1750 Laptop System Chipset
+	7191  440BX/ZX - 82443BX/ZX AGP bridge
+	7192  440BX/ZX - 82443BX/ZX Host bridge (AGP disabled)
+		0e11 0460  Armada 1700 Laptop System Chipset
+	71a0  440GX - 82443GX Host bridge
+	71a1  440GX - 82443GX AGP bridge
+	71a2  440GX - 82443GX Host bridge (AGP disabled)
+	7602  82372FB [PCI-to-USB UHCI]
+	7800  i740
+		1092 0100  Stealth II G460
+		8086 0100  Intel740 Graphics Accelerator
+	84c4  450KX/GX [Orion] - 82454KX/GX PCI bridge
+	84c5  450KX/GX [Orion] - 82453KX/GX Memory controller
+	84ca  450NX - 82451NX Memory & I/O Controller
+	84cb  450NX - 82454NX PCI Expander Bridge
+	ffff  450NX/GX [Orion] - 82453KX/GX Memory controller [BUG]
+8800  Trigem Computer Inc.
+	2008  Video assistent component
+8866  T-Square Design Inc.
+8888  Silicon Magic
+8e0e  Computone Corporation
+8e2e  KTI
+	3000  ET32P2
+9004  Adaptec
+# FIXME: [dj] In one document I have, lot of these AIC's are actually AHA's
+	1078  AIC-7810
+	1160  AIC-1160 [Family Fiber Channel Adapter]
+	2178  AIC-7821
+	3860  AHA-2930CU
+	3b78  AHA-4844W/4844UW
+	5075  AIC-755x
+	5078  AHA-7850
+	5175  AIC-755x
+	5178  AIC-7851
+	5275  AIC-755x
+	5278  AIC-7852
+	5375  AIC-755x
+	5378  AIC-7850
+	5475  AIC-2930
+	5478  AIC-7850
+	5575  AVA-2930
+	5578  AIC-7855
+	5675  AIC-755x
+	5678  AIC-7850
+	5775  AIC-755x
+	5778  AIC-7850
+	5800  AIC-5800
+	5900  ANA-5910/5930/5940 ATM155 & 25 LAN Adapter
+	5905  ANA-5910A/5930A/5940A ATM Adapter
+	6038  AIC-3860
+# FIXME: This is a cardbus card.  The declaration may be duplicative.
+	6075  AIC-1480 / APA-1480
+	6078  AIC-7860
+	6178  AIC-7861
+	6278  AIC-7860
+	6378  AIC-7860
+	6478  AIC-786
+	6578  AIC-786x
+	6678  AIC-786
+	6778  AIC-786x
+	6915  ANA620xx/ANA69011A
+		9004 0008  ANA69011A/TX 10/100
+		9004 0009  ANA69011A/TX 10/100
+		9004 0010  ANA62022 2-port 10/100
+		9004 0018  ANA62044 4-port 10/100
+		9004 0020  ANA62022 2-port 10/100
+		9004 0028  ANA69011A/TX 10/100
+		9004 8008  ANA69011A/TX 64 bit 10/100
+		9004 8009  ANA69011A/TX 64 bit 10/100
+		9004 8010  ANA62022 2-port 64 bit 10/100
+		9004 8018  ANA62044 4-port 64 bit 10/100
+		9004 8020  ANA62022 2-port 64 bit 10/100
+		9004 8028  ANA69011A/TX 64 bit 10/100
+	7078  AHA-294x / AIC-7870
+	7178  AHA-294x / AIC-7871
+	7278  AHA-3940 / AIC-7872
+	7378  AHA-3985 / AIC-7873
+	7478  AHA-2944 / AIC-7874
+# FIXME: [dj] Where did the 3rd number come from in 0x7578 & 0x7678 ?
+	7578  AHA-3944 / AHA-3944W / 7875
+	7678  AHA-4944W/UW / 7876
+	7778  AIC-787x
+	7810  AIC-7810
+	7850  AIC-7850
+	7855  AHA-2930
+	7860  AIC-7860
+	7870  AIC-7870
+	7871  AHA-2940
+	7872  AHA-3940
+	7873  AHA-3980
+	7874  AHA-2944
+	7880  AIC-7880P
+	7890  AIC-7890
+	7891  AIC-789x
+	7892  AIC-789x
+	7893  AIC-789x
+	7894  AIC-789x
+	7895  AHA-2940U/UW / AHA-39xx / AIC-7895
+	7896  AIC-789x
+	7897  AIC-789x
+	8078  AIC-7880U
+	8178  AIC-7881U
+	8278  AHA-3940U/UW / AIC-7882U
+	8378  AHA-3940U/UW / AIC-7883U
+	8478  AHA-294x / AIC-7884U
+	8578  AHA-3944U / AHA-3944UWD / 7885
+	8678  AHA-4944UW / 7886
+	8778  AIC-788x
+	8878  7888
+	8b78  ABA-1030
+	ec78  AHA-4944W/UW
+9005  Adaptec
+	0010  AHA-2940U2/W
+	0011  2930U2
+	0013  78902
+	001f  AHA-2940U2/W / 7890
+	0020  AIC-7890
+	002f  AIC-7890
+	0030  AIC-7890
+	003f  AIC-7890
+	0050  3940U2
+	0051  3950U2D
+	005f  7896
+	0080  7892A
+	0081  7892B
+	0083  7892D
+	008f  7892P
+	00c0  7899A
+	00c1  7899B
+	00c3  7899D
+	00cf  7899P
+907f  Atronics
+	2015  IDE-2015PL
+9412  Holtek
+	6565  6565
+a0a0  AOPEN Inc.
+a0f1  UNISYS Corporation
+a200  NEC Corporation
+a259  Hewlett Packard
+a25b  Hewlett Packard GmbH PL24-MKT
+a304  Sony
+a727  3Com Corporation
+aa42  Scitex Digital Video
+b1b3  Shiva Europe Limited
+c001  TSI Telsys
+c0a9  Micron/Crucial Technology
+c0de  Motorola
+c0fe  Motion Engineering, Inc.
+cafe  Chrysalis-ITS
+cccc  Catapult Communications
+d4d4  Dy4 Systems Inc
+e000  Winbond
+	e000  W89C940
+e159  Tiger Jet Network Inc.
+	0001  Model 300 128k
+		0059 0001  128k ISDN-S/T Adapter
+		0059 0003  128k ISDN-U Adapter
+eabb  Aashima Technology B.V.
+ecc0  Echo Corporation
+edd8  ARK Logic Inc
+	a091  1000PV [Stingray]
+	a099  2000PV [Stingray]
+	a0a1  2000MT
+	a0a9  2000MI
+feda  Epigram Inc
+fffe  VMWare Inc
+	0710  Virtual SVGA
+ffff  Illegal Vendor ID
+
+
+# List of known device classes, subclasses and programming interfaces
+
+# Syntax:
+# C class  class_name
+#	subclass  subclass_name			<-- single tab
+#		prog-if  prog-if_name		<-- two tabs
+
+C 00  Unclassified device
+	00  Non-VGA unclassified device
+	01  VGA compatible unclassified device
+C 01  Mass storage controller
+	00  SCSI storage controller
+	01  IDE interface
+	02  Floppy disk controller
+	03  IPI bus controller
+	04  RAID bus controller
+	80  Unknown mass storage controller
+C 02  Network controller
+	00  Ethernet controller
+	01  Token ring network controller
+	02  FDDI network controller
+	03  ATM network controller
+	80  Network controller
+C 03  Display controller
+	00  VGA compatible controller
+		00  VGA
+		01  8514
+	01  XGA compatible controller
+	02  3D controller
+	80  Display controller
+C 04  Multimedia controller
+	00  Multimedia video controller
+	01  Multimedia audio controller
+	02  Computer telephony device
+	80  Multimedia controller
+C 05  Memory controller
+	00  RAM memory
+	01  FLASH memory
+	80  Memory controller
+C 06  Bridge
+	00  Host bridge
+	01  ISA bridge
+	02  EISA bridge
+	03  MicroChannel bridge
+	04  PCI bridge
+		00  Normal decode
+		01  Subtractive decode
+	05  PCMCIA bridge
+	06  NuBus bridge
+	07  CardBus bridge
+	08  RACEway bridge
+		00  Transparent mode
+		01  Endpoint mode
+	80  Bridge
+C 07  Communication controller
+	00  Serial controller
+		00  8250
+		01  16450
+		02  16550
+		03  16650
+		04  16750
+		05  16850
+		06  16950
+	01  Parallel controller
+		00  SPP
+		01  BiDir
+		02  ECP
+		03  IEEE1284
+		FE  IEEE1284 Target
+	02  Multiport serial controller
+	03  Modem
+		00  Generic
+		01  Hayes/16450
+		02  Hayes/16550
+		03  Hayes/16650
+		04  Hayes/16750
+	80  Communication controller
+C 08  Generic system peripheral
+	00  PIC
+		00  8259
+		01  ISA PIC
+		02  EISA PIC
+		10  IO-APIC
+		20  IO(X)-APIC
+	01  DMA controller
+		00  8237
+		01  ISA DMA
+		02  EISA DMA
+	02  Timer
+		00  8254
+		01  ISA Timer
+		02  EISA Timers
+	03  RTC
+		00  Generic
+		01  ISA RTC
+	04  PCI Hot-plug controller
+	80  System peripheral
+C 09  Input device controller
+	00  Keyboard controller
+	01  Digitizer Pen
+	02  Mouse controller
+	03  Scanner controller
+	04  Gameport controller
+		00  Generic
+		10  Extended
+	80  Input device controller
+C 0A  Docking station
+	00  Generic Docking Station
+	80  Docking Station
+C 0B  Processor
+	00  386
+	01  486
+	02  Pentium
+	10  Alpha
+	20  Power PC
+	30  MIPS
+	40  Co-processor
+C 0C  Serial bus controller
+	00  FireWire (IEEE 1394)
+		00  Generic
+		10  OHCI
+	01  ACCESS Bus
+	02  SSA
+	03  USB Controller
+		00  UHCI
+		10  OHCI
+		80  Unspecified
+		FE  USB Device
+	04  Fiber Channel
+	05  SMBus
+C 0D  Wireless controller
+	00  IRDA controller
+	01  Consumer IR controller
+	10  RF controller
+	80  Wireless controller
+C 0E  Intelligent controller
+	00  I2O
+C 0F  Satellite communications controller
+	00  Satellite TV controller
+	01  Satellite audio communication controller
+	03  Satellite voice communication controller
+	04  Satellite data communication controller
+C 10  Encryption controller
+	00  Network and computing encryption device
+	01  Entertainment encryption device
+	80  Encryption controller
+C 11  Signal processing controller
+	00  DPIO module
+	80  Signal processing controller
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 323e077caeb0af49d9033ea103d616edb1fc1d44..2056501c2b20bdd2c007d6f93d5627da596d7715 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -265,14 +265,22 @@ else
   endif
 endif
 
-ifeq ($(CONFIG_MAC_SCSI_OLD),y)
+ifeq ($(CONFIG_MAC_SCSI),y)
 L_OBJS += mac_scsi.o
 else
-  ifeq ($(CONFIG_MAC_SCSI_OLD),m)
+  ifeq ($(CONFIG_MAC_SCSI),m)
   M_OBJS += mac_scsi.o
   endif
 endif
 
+ifeq ($(CONFIG_SUN3_SCSI),y)
+L_OBJS += sun3_scsi.o
+else
+  ifeq ($(CONFIG_SUN3_SCSI),m)
+  M_OBJS += sun3_scsi.o
+  endif
+endif
+
 ifeq ($(CONFIG_SCSI_MAC_ESP),y)
 L_OBJS += mac_esp.o NCR53C9x.o
 else
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 46b8045331f96821834fdfc60babdf527c5b12dc..93d084cbfe9324c2999bc22b1ec7c1cd107228d1 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -111,8 +111,12 @@
 #include "mac_scsi.h"
 #endif
 
+#ifdef CONFIG_SUN3_SCSI
+#include "sun3_scsi.h"
+#endif
+
 #ifdef CONFIG_MAC_SCSI
-#include "mac_scsinew.h"
+#include "mac_scsi.h"
 #endif
 
 #ifdef CONFIG_SCSI_MAC_ESP
@@ -445,6 +449,10 @@ static Scsi_Host_Template builtin_scsi_hosts[] =
 #endif
 #endif
 
+#ifdef CONFIG_SUN3_SCSI
+	SUN3_NCR5380,
+#endif
+
 #ifdef CONFIG_MVME16x_SCSI
 	MVME16x_SCSI,
 #endif
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c
index 726bf4107db64d708896182229355cb3e14f32b8..036ffdf2c49dd67c854bc524cea08add73aeec20 100644
--- a/drivers/scsi/mac_esp.c
+++ b/drivers/scsi/mac_esp.c
@@ -22,25 +22,28 @@
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
+#include <linux/init.h>
 
 #include "scsi.h"
 #include "hosts.h"
 #include "NCR53C9x.h"
 #include "mac_esp.h"
 
-#include "../../arch/m68k/mac/via6522.h"  /* huh? */
-
 #include <asm/io.h>
 
 #include <asm/setup.h>
 #include <asm/irq.h>
 #include <asm/macints.h>
 #include <asm/machw.h>
+#include <asm/mac_via.h>
 
 #include <asm/pgtable.h>
 
 #include <asm/macintosh.h>
 
+#define mac_turnon_irq(x)	mac_enable_irq(x)
+#define mac_turnoff_irq(x)	mac_disable_irq(x)
+
 extern inline void esp_handle(struct NCR_ESP *esp);
 extern void mac_esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
 
@@ -236,6 +239,8 @@ void mac_esp_setup(char *str, int *ints) {
 #endif
 }
 
+__setup("mac53c9x=", mac_esp_setup);
+
 /*
  * ESP address 'detection'
  */
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index 79009810706d83b3075b80f3a263c0c804441c96..3832fa2665411eccea1688e153dfa4776e4c31a5 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -1,95 +1,104 @@
 /*
- * mac_scsi.c   -- Device dependent functions for the Macintosh NCR5380 SCSI 
- *		   port (MacII style machines, no DMA).
+ * Generic Macintosh NCR5380 driver
  *
- * based on:
+ * Copyright 1998, Michael Schmitz <mschmitz@lbl.gov>
+ *
+ * derived in part from:
  */
-
 /*
- * atari_scsi.c -- Device dependent functions for the Atari generic SCSI port
+ * Generic Generic NCR5380 driver
+ *
+ * Copyright 1995, Russell King
  *
- * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ * ALPHA RELEASE 1.
  *
- *   Loosely based on the work of Robert De Vries' team and added:
- *    - working real DMA
- *    - Falcon support (untested yet!)   ++bjoern fixed and now it works
- *    - lots of extensions and bug fixes.
+ * For more information, please consult
  *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
+ * NCR 5380 Family
+ * SCSI Protocol Controller
+ * Databook
  *
+ * NCR Microelectronics
+ * 1635 Aeroplaza Drive
+ * Colorado Springs, CO 80916
+ * 1+ (719) 578-3400
+ * 1+ (800) 334-5454
  */
 
 
-#include <linux/config.h>
-#include <linux/module.h>
-
-#define NDEBUG_ABORT	0x800000
-#define NDEBUG_TAGS	0x1000000
-#define NDEBUG_MERGING	0x2000000
-
-#define NDEBUG (0)
-
-#define AUTOSENSE
-/* MSch: Tested the pseudo-DMA code on Atari for the Mac68k port ... */
-/* Defining neither PSEUDO_DMA nor REAL_DMA -> PIO transfer, sloooow ! */
-/*#define	REAL_DMA*/ /* never supported on NCR5380 Macs */
 /*
- * Usage: define PSEUDO_DMA to use hardware-handshaked PIO mode (TBI)
- *        undef  PSEUDO_DMA to use pure PIO mode
+ * Options :
+ *
+ * PARITY - enable parity checking.  Not supported.
+ *
+ * SCSI2 - enable support for SCSI-II tagged queueing.  Untested.
+ *
+ * USLEEP - enable support for devices that don't disconnect.  Untested.
  */
 
-/*#define PSEUDO_DMA*/	/* currently gives trouble on some Macs */
+/*
+ * $Log: mac_NCR5380.c,v $
+ */
 
-#ifdef PSEUDO_DMA
-#define EMULATE_PSEUDO_DMA
-#define DMA_WORKS_RIGHT
-#define UNSAFE
+#define AUTOSENSE
+#if 0
+#define PSEUDO_DMA
 #endif
 
-/* Support tagged queuing? (on devices that are able to... :-) */
-#define	SUPPORT_TAGS
-#define	MAX_TAGS 32
-
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <linux/ctype.h>
 #include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/blk.h>
+
+#include <linux/module.h>
+#include <linux/signal.h>
 #include <linux/sched.h>
-#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/blk.h>
 
-#include <asm/setup.h>
-#include <asm/machw.h>
-#include <asm/macints.h>
-#include <asm/macintosh.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
+#include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/traps.h>
-#include <asm/bitops.h>
+#include <asm/system.h>
+
+#include <asm/macintosh.h>
+#include <asm/macints.h>
+#include <asm/machw.h>
+#include <asm/mac_via.h>
 
 #include "scsi.h"
 #include "hosts.h"
 #include "mac_scsi.h"
 #include "NCR5380.h"
 #include "constants.h"
-#include <asm/io.h>
 
-#include <linux/stat.h>
+#if 0
+#define NDEBUG (NDEBUG_INTR | NDEBUG_PSEUDO_DMA | NDEBUG_ARBITRATION | NDEBUG_SELECTION | NDEBUG_RESELECTION)
+#else
+#define NDEBUG (NDEBUG_ABORT)
+#endif
 
-struct proc_dir_entry proc_scsi_mac = {
-    PROC_SCSI_MAC, 8, "mac_5380",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
+#define USE_WRAPPER
+#define RESET_BOOT
+#define DRIVER_SETUP
 
 /*
- * Define RBV_HACK to run the SCSI driver on RBV Macs; undefine to
- * try getting better interrupt latency
+ * BUG can be used to trigger a strange code-size related hang on 2.1 kernels
+ */
+#ifdef BUG
+#undef RESET_BOOT
+#undef DRIVER_SETUP
+#endif
+
+/* 
+ * Need to define this to make SCSI work on RBV machines; leave undefined
+ * to enable interrupts a bit more on other machines 
+ * Changes method of SCSI interrupt disable from software mask to VIA IER!
+ * (don't know if that's essential)
+ *
+ * 990502 (jmt) - not needed (and won't work) on new irq architecture
  */
-#define RBV_HACK
+/* #define RBV_HACK */
 
 #ifdef RBV_HACK
 #define	ENABLE_IRQ()	mac_turnon_irq( IRQ_MAC_SCSI ); 
@@ -99,83 +108,18 @@ struct proc_dir_entry proc_scsi_mac = {
 #define	DISABLE_IRQ()	mac_disable_irq( IRQ_MAC_SCSI );
 #endif
 
-#define HOSTDATA_DMALEN		(((struct NCR5380_hostdata *) \
-				(mac_scsi_host->hostdata))->dma_len)
-
-/* Time (in jiffies) to wait after a reset; the SCSI standard calls for 250ms,
- * we usually do 0.5s to be on the safe side. But Toshiba CD-ROMs once more
- * need ten times the standard value... */
-#ifndef CONFIG_MAC_SCSI_TOSHIBA_DELAY
-#define	AFTER_RESET_DELAY	(HZ/2)
-#else
-#define	AFTER_RESET_DELAY	(5*HZ/2)
-#endif
-
-/***************************** Prototypes *****************************/
-
-#ifdef REAL_DMA
-static int scsi_dma_is_ignored_buserr( unsigned char dma_stat );
-static void mac_scsi_fetch_restbytes( void );
-static long mac_scsi_dma_residual( struct Scsi_Host *instance );
-static int mac_classify_cmd( Scsi_Cmnd *cmd );
-static unsigned long mac_dma_xfer_len( unsigned long wanted_len,
-                                       Scsi_Cmnd *cmd, int write_flag );
-#endif
-#ifdef PSEUDO_DMA
-static int mac_pdma_read(struct Scsi_Host *instance, unsigned char *dst,
-			   int len);
-static int mac_pdma_write(struct Scsi_Host *instance, unsigned char *src,
-			   int len);
-static unsigned long mac_dma_xfer_len( unsigned long wanted_len,
-                                         Scsi_Cmnd *cmd, int write_flag );
-#endif
-static void scsi_mac_intr( int irq, void *dummy, struct pt_regs *fp);
-static void mac_scsi_reset_boot( void );
-static unsigned char mac_scsi_reg_read( unsigned char reg );
-static void mac_scsi_reg_write( unsigned char reg, unsigned char value);
-
-/************************* End of Prototypes **************************/
+#define mac_turnon_irq(x) mac_enable_irq(x)
+#define mac_turnoff_irq(x) mac_disable_irq(x)
 
+extern void via_scsi_clear(void);
 
-static struct Scsi_Host *mac_scsi_host = NULL;
-#if 0
-static unsigned char (*mac_scsi_reg_read)( unsigned char reg );
-static void (*mac_scsi_reg_write)( unsigned char reg, unsigned char value );
+static void scsi_mac_intr(int irq, void *dummy, struct pt_regs *fp);
+#ifdef RESET_BOOT
+static void mac_scsi_reset_boot(struct Scsi_Host *instance);
 #endif
+static char macscsi_read(struct Scsi_Host *instance, int reg);
+static void macscsi_write(struct Scsi_Host *instance, int reg, int value);
 
-#ifdef REAL_DMA
-static unsigned long	mac_dma_residual, mac_dma_startaddr;
-static short		mac_dma_active;
-/* pointer to the dribble buffer */
-static char		*mac_dma_buffer = NULL;
-/* precalculated physical address of the dribble buffer */
-static unsigned long	mac_dma_phys_buffer;
-/* != 0 tells the int handler to copy data from the dribble buffer */
-static char		*mac_dma_orig_addr;
-/* size of the dribble buffer; 4k seems enough, since the Falcon cannot use
- * scatter-gather anyway, so most transfers are 1024 byte only. In the rare
- * cases where requests to physical contiguous buffers have been merged, this
- * request is <= 4k (one page). So I don't think we have to split transfers
- * just due to this buffer size...
- */
-#define	MAC_BUFFER_SIZE	(4096)
-#if 1  /* FIXME: is that an issue for Macs?? */
-/* mask for address bits that can't be used with the ST-DMA */
-static unsigned long	mac_dma_stram_mask;
-#define STRAM_ADDR(a)	(((a) & mac_dma_stram_mask) == 0)
-#endif
-/* number of bytes to cut from a transfer to handle NCR overruns */
-static int mac_read_overruns = 0;
-#endif
-#ifdef PSEUDO_DMA
-static unsigned long	mac_pdma_residual, mac_pdma_startaddr, mac_pdma_current;
-static short		mac_pdma_active;
-/* FIXME: is that an issue for Macs?? */
-/* mask for address bits that can't be used with the ST-DMA */
-static unsigned long	mac_dma_stram_mask;
-#define STRAM_ADDR(a)	(((a) & mac_dma_stram_mask) == 0)
-static int mac_read_overruns = 0;
-#endif
 static int setup_can_queue = -1;
 static int setup_cmd_per_lun = -1;
 static int setup_sg_tablesize = -1;
@@ -184,371 +128,39 @@ static int setup_use_tagged_queuing = -1;
 #endif
 static int setup_hostid = -1;
 
-
-#if defined(REAL_DMA)
-
-#if 0  /* FIXME */
-static int scsi_dma_is_ignored_buserr( unsigned char dma_stat )
-{
-	int i;
-	unsigned long	addr = SCSI_DMA_READ_P( dma_addr ), end_addr;
-
-	if (dma_stat & 0x01) {
-
-		/* A bus error happens when DMA-ing from the last page of a
-		 * physical memory chunk (DMA prefetch!), but that doesn't hurt.
-		 * Check for this case:
-		 */
-		
-		for( i = 0; i < boot_info.num_memory; ++i ) {
-			end_addr = boot_info.memory[i].addr +
-				boot_info.memory[i].size;
-			if (end_addr <= addr && addr <= end_addr + 4)
-				return( 1 );
-		}
-	}
-	return( 0 );
-}
-
-
-/* Dead code... wasn't called anyway :-) and causes some trouble, because at
- * end-of-DMA, both SCSI ints are triggered simultaneously, so the NCR int has
- * to clear the DMA int pending bit before it allows other level 6 interrupts.
- */
-static void scsi_dma_buserr (int irq, void *dummy, struct pt_regs *fp)
-{
-	unsigned char	dma_stat = tt_scsi_dma.dma_ctrl;
-
-	/* Don't do anything if a NCR interrupt is pending. Probably it's just
-	 * masked... */
-	if (mac_irq_pending( IRQ_MAC_SCSI ))
-		return;
-	
-	printk("Bad SCSI DMA interrupt! dma_addr=0x%08lx dma_stat=%02x dma_cnt=%08lx\n",
-	       SCSI_DMA_READ_P(dma_addr), dma_stat, SCSI_DMA_READ_P(dma_cnt));
-	if (dma_stat & 0x80) {
-		if (!scsi_dma_is_ignored_buserr( dma_stat ))
-			printk( "SCSI DMA bus error -- bad DMA programming!\n" );
-	}
-	else {
-		/* Under normal circumstances we never should get to this point,
-		 * since both interrupts are triggered simultaneously and the 5380
-		 * int has higher priority. When this irq is handled, that DMA
-		 * interrupt is cleared. So a warning message is printed here.
-		 */
-		printk( "SCSI DMA intr ?? -- this shouldn't happen!\n" );
-	}
-}
-#endif
-
-#endif
-
-void restore_irq(struct pt_regs *regs)
-{
-	unsigned long flags;
-
-	save_flags(flags);
-	flags = (flags & ~0x0700) | (regs->sr & 0x0700);
-	restore_flags(flags);
-}
-
 static int polled_scsi_on = 0;
-static unsigned char *mac_scsi_regp = NULL;
-
-void scsi_mac_polled (void)
-{
-	if (polled_scsi_on)
-	{
-		if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ)
-		{
-			printk("SCSI poll\n");
-			scsi_mac_intr(IRQ_MAC_SCSI, NULL, NULL);
-		}
-	}
-}
-
-static void scsi_mac_intr (int irq, void *dummy, struct pt_regs *fp)
-{
-	unsigned long flags;
-#ifdef REAL_DMA
-	int dma_stat;
-
-	dma_stat = mac_scsi_dma.dma_ctrl;
-
-	INT_PRINTK("scsi%d: NCR5380 interrupt, DMA status = %02x\n",
-		   mac_scsi_host->host_no, dma_stat & 0xff);
-
-	/* Look if it was the DMA that has interrupted: First possibility
-	 * is that a bus error occurred...
-	 */
-	if (dma_stat & 0x80) {
-		if (!scsi_dma_is_ignored_buserr( dma_stat )) {
-			printk(KERN_ERR "SCSI DMA caused bus error near 0x%08lx\n",
-			       SCSI_DMA_READ_P(dma_addr));
-			printk(KERN_CRIT "SCSI DMA bus error -- bad DMA programming!");
-		}
-	}
-
-	/* If the DMA is active but not finished, we have the the case
-	 * that some other 5380 interrupt occurred within the DMA transfer.
-	 * This means we have residual bytes, if the desired end address
-	 * is not yet reached. Maybe we have to fetch some bytes from the
-	 * rest data register, too. The residual must be calculated from
-	 * the address pointer, not the counter register, because only the
-	 * addr reg counts bytes not yet written and pending in the rest
-	 * data reg!
-	 */
-	if ((dma_stat & 0x02) && !(dma_stat & 0x40)) {
-		mac_dma_residual = HOSTDATA_DMALEN - (SCSI_DMA_READ_P( dma_addr ) -
-												mac_dma_startaddr);
-
-		DMA_PRINTK("SCSI DMA: There are %ld residual bytes.\n",
-			   mac_dma_residual);
-
-		if ((signed int)mac_dma_residual < 0)
-			mac_dma_residual = 0;
-		if ((dma_stat & 1) == 0) {
-			/* After read operations, we maybe have to
-			   transport some rest bytes */
-			mac_scsi_fetch_restbytes();
-		}
-		else {
-			/* There seems to be a nasty bug in some SCSI-DMA/NCR
-			   combinations: If a target disconnects while a write
-			   operation is going on, the address register of the
-			   DMA may be a few bytes farer than it actually read.
-			   This is probably due to DMA prefetching and a delay
-			   between DMA and NCR.  Experiments showed that the
-			   dma_addr is 9 bytes to high, but this could vary.
-			   The problem is, that the residual is thus calculated
-			   wrong and the next transfer will start behind where
-			   it should.  So we round up the residual to the next
-			   multiple of a sector size, if it isn't already a
-			   multiple and the originally expected transfer size
-			   was.  The latter condition is there to ensure that
-			   the correction is taken only for "real" data
-			   transfers and not for, e.g., the parameters of some
-			   other command.  These shouldn't disconnect anyway.
-			   */
-			if (mac_dma_residual & 0x1ff) {
-				DMA_PRINTK("SCSI DMA: DMA bug corrected, "
-					   "difference %ld bytes\n",
-					   512 - (mac_dma_residual & 0x1ff));
-				mac_dma_residual = (mac_dma_residual + 511) & ~0x1ff;
-			}
-		}
-		mac_scsi_dma.dma_ctrl = 0;
-	}
-
-	/* If the DMA is finished, fetch the rest bytes and turn it off */
-	if (dma_stat & 0x40) {
-		atari_dma_residual = 0;
-		if ((dma_stat & 1) == 0)
-			atari_scsi_fetch_restbytes();
-		tt_scsi_dma.dma_ctrl = 0;
-	}
-
-#endif /* REAL_DMA */
-
-#ifdef PSEUDO_DMA
-	/* determine if there is any residual for the current transfer */
-	if (mac_pdma_active) {
-	  /* probably EOP interrupt, signaling i.e. target disconnect.
-	   * We must figure out the residual from the source/destination
-	   * pointers here ... */
-	  /* Should check bus status here to make sure it wasn't reselect or reset */
-	  mac_pdma_residual = HOSTDATA_DMALEN - (mac_pdma_current - mac_pdma_startaddr);
-	  mac_pdma_active = 0;
-	}
-#endif
-
-#ifdef RBV_HACK
-	mac_turnoff_irq( IRQ_MAC_SCSI );
-#else
-	mac_disable_irq( IRQ_MAC_SCSI );
-#endif
-
-	save_flags(flags);
-#ifndef RBV_HACK	/* interferes with level triggered RBV IRQs ?? */
-	restore_irq(fp);
-#endif
-
-	if ( irq == IRQ_IDX(IRQ_MAC_SCSI) )
-		NCR5380_intr (irq, dummy, fp);
-
-	restore_flags(flags);
-
-	/* To be sure the int is not masked */
-#ifdef RBV_HACK
-	mac_turnon_irq( IRQ_MAC_SCSI );
-#else
-	mac_enable_irq( IRQ_MAC_SCSI );
-#endif
-
-	/* Clear the IRQ */
-	via_scsi_clear();
-}
-
-
-#ifdef REAL_DMA
-static void mac_scsi_fetch_restbytes( void )
-{
-	int nr;
-	char	*src, *dst;
-
-	/* fetch rest bytes in the DMA register */
-	dst = (char *)SCSI_DMA_READ_P( dma_addr );
-	if ((nr = ((long)dst & 3))) {
-		/* there are 'nr' bytes left for the last long address before the
-		   DMA pointer */
-		dst = (char *)( (unsigned long)dst & ~3 );
-		DMA_PRINTK("SCSI DMA: there are %d rest bytes for phys addr 0x%08lx",
-			   nr, (long)dst);
-		dst = (char *)PTOV(dst);  /* The content of the DMA pointer
-					   * is a physical address! */
-		DMA_PRINTK(" = virt addr 0x%08lx\n", (long)dst);
-		for( src = (char *)&mac_scsi_dma.dma_restdata; nr > 0; --nr )
-			*dst++ = *src++;
-	}
-}
-#endif /* REAL_DMA */
-
-#if 0  /* FIXME : how is the host ID determined on a Mac? */
-#define	RTC_READ(reg)				\
-    ({	unsigned char	__val;			\
-		outb(reg,&tt_rtc.regsel);	\
-		__val = tt_rtc.data;		\
-		__val;				\
-	})
-
-#define	RTC_WRITE(reg,val)			\
-    do {					\
-		outb(reg,&tt_rtc.regsel);	\
-		tt_rtc.data = (val);		\
-	} while(0)
-#endif
-				   
-int mac_scsi_detect (Scsi_Host_Template *host)
-{
-	static int called = 0;
-	struct Scsi_Host *instance;
-
-	if (!MACH_IS_MAC || called)
-		return( 0 );
-
-	if (macintosh_config->scsi_type != MAC_SCSI_OLD)
-		return( 0 );
-
-	host->proc_dir = &proc_scsi_mac;
-
-	/* testing: IIfx SCSI without IOP ?? */
-	if (macintosh_config->ident == MAC_MODEL_IIFX)
-		mac_scsi_regp = via1_regp+0x8000;
-	else
-		mac_scsi_regp = via1_regp+0x10000;
-
-#if 0  /* maybe if different SCSI versions show up ? */
-	mac_scsi_reg_read  = IS_A_TT() ? atari_scsi_tt_reg_read :
-					   atari_scsi_falcon_reg_read;
-	mac_scsi_reg_write = IS_A_TT() ? atari_scsi_tt_reg_write :
-#endif					   atari_scsi_falcon_reg_write;
-
-	/* setup variables */
-	host->can_queue =
-		(setup_can_queue > 0) ? setup_can_queue :
-		MAC_SCSI_CAN_QUEUE;
-	host->cmd_per_lun =
-		(setup_cmd_per_lun > 0) ? setup_cmd_per_lun :
-		MAC_SCSI_CMD_PER_LUN;
-	host->sg_tablesize =
-		(setup_sg_tablesize >= 0) ? setup_sg_tablesize : MAC_SCSI_SG_TABLESIZE;
-
-	if (setup_hostid >= 0)
-		host->this_id = setup_hostid;
-	else {
-		/* use 7 as default */
-		host->this_id = 7;
-	}
-
-#ifdef SUPPORT_TAGS
-	if (setup_use_tagged_queuing < 0)
-		setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING;
-#endif
 
-	instance = scsi_register (host, sizeof (struct NCR5380_hostdata));
-	mac_scsi_host = instance;
+/* Time (in jiffies) to wait after a reset; the SCSI standard calls for 250ms,
+ * we usually do 0.5s to be on the safe side. But Toshiba CD-ROMs once more
+ * need ten times the standard value... */
+#define TOSHIBA_DELAY
 
-	/* truncation of machspec bit not critical as instance->irq never used */
-#if 0	/* Might work; problem was only with Falcon lock */
-	instance->irq = IRQ_MAC_SCSI;
+#ifdef TOSHIBA_DELAY
+#define	AFTER_RESET_DELAY	(5*HZ/2)
 #else
-	instance->irq = 0;
-#endif
-	mac_scsi_reset_boot();
-	NCR5380_init (instance, 0);
-
-       	/* This int is actually "pseudo-slow", i.e. it acts like a slow
-	 * interrupt after having cleared the pending flag for the DMA
-	 * interrupt. */
-	request_irq(IRQ_MAC_SCSI, scsi_mac_intr, IRQ_TYPE_SLOW,
-	            "SCSI NCR5380", scsi_mac_intr);
-#ifdef REAL_DMA
-	tt_scsi_dma.dma_ctrl = 0;
-	atari_dma_residual = 0;
-
-	if (is_brokenscsi) {
-		/* While the read overruns (described by Drew Eckhardt in
-		 * NCR5380.c) never happened on TTs, they do in fact on the Medusa
-		 * (This was the cause why SCSI didn't work right for so long
-		 * there.) Since handling the overruns slows down a bit, I turned
-		 * the #ifdef's into a runtime condition.
-		 *
-		 * In principle it should be sufficient to do max. 1 byte with
-		 * PIO, but there is another problem on the Medusa with the DMA
-		 * rest data register. So 'atari_read_overruns' is currently set
-		 * to 4 to avoid having transfers that aren't a multiple of 4. If
-		 * the rest data bug is fixed, this can be lowered to 1.
-		 */
-		mac_read_overruns = 4;
-	}
-#endif /* REAL_DMA */
-
-#ifdef PSEUDO_DMA
-	mac_pdma_residual = 0;
-	mac_pdma_active   = 0;
+#define	AFTER_RESET_DELAY	(HZ/2)
 #endif
 
-	printk(KERN_INFO "scsi%d: options CAN_QUEUE=%d CMD_PER_LUN=%d SCAT-GAT=%d "
-#ifdef SUPPORT_TAGS
-			"TAGGED-QUEUING=%s "
-#endif
-			"HOSTID=%d",
-			instance->host_no, instance->hostt->can_queue,
-			instance->hostt->cmd_per_lun,
-			instance->hostt->sg_tablesize,
-#ifdef SUPPORT_TAGS
-			setup_use_tagged_queuing ? "yes" : "no",
-#endif
-			instance->hostt->this_id );
-	NCR5380_print_options (instance);
-	printk ("\n");
+static struct proc_dir_entry proc_scsi_mac5380 = {
+	PROC_SCSI_MAC, 13, "Mac 5380 SCSI", S_IFDIR | S_IRUGO, S_IXUGO, 2
+};
 
-	called = 1;
-	return( 1 );
-}
+static volatile unsigned char *mac_scsi_regp = NULL;
+static volatile unsigned char *mac_scsi_drq  = NULL;
+static volatile unsigned char *mac_scsi_nodrq = NULL;
 
-#ifdef MODULE
-int mac_scsi_release (struct Scsi_Host *sh)
-{
-       	free_irq(IRQ_MAC_SCSI, scsi_mac_intr);
-	if (mac_dma_buffer)
-		scsi_init_free (mac_dma_buffer, MAC_BUFFER_SIZE);
-	return 1;
-}
-#endif
+/*
+ * Function : mac_scsi_setup(char *str, int *ints)
+ *
+ * Purpose : booter command line initialization of the overrides array,
+ *
+ * Inputs : str - unused, ints - array of integer parameters with ints[0]
+ *	equal to the number of ints.
+ *
+ */
 
-void mac_scsi_setup( char *str, int *ints )
-{
+void mac_scsi_setup(char *str, int *ints) {
+#ifdef DRIVER_SETUP
 	/* Format of mac5380 parameter is:
 	 *   mac5380=<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
 	 * Negative values mean don't change.
@@ -606,39 +218,145 @@ void mac_scsi_setup( char *str, int *ints )
 			setup_use_tagged_queuing = !!ints[5];
 	}
 #endif
+#endif
 }
 
-int mac_scsi_reset( Scsi_Cmnd *cmd, unsigned int reset_flags)
+__setup("mac5380=", mac_scsi_setup);
+
+#if 0
+#define MAC_ADDRESS(card) (ecard_address((card), ECARD_IOC, ECARD_SLOW) + 0x800)
+#define MAC_IRQ(card)     ((card)->irq)
+#endif
+
+/*
+ * XXX: status debug
+ */
+static struct Scsi_Host *default_instance;
+
+/*
+ * Function : int macscsi_detect(Scsi_Host_Template * tpnt)
+ *
+ * Purpose : initializes mac NCR5380 driver based on the
+ *	command line / compile time port and irq definitions.
+ *
+ * Inputs : tpnt - template for this SCSI adapter.
+ *
+ * Returns : 1 if a host adapter was found, 0 if not.
+ *
+ */
+ 
+int macscsi_detect(Scsi_Host_Template * tpnt)
 {
-	int		rv;
-	struct NCR5380_hostdata *hostdata =
-		(struct NCR5380_hostdata *)cmd->host->hostdata;
+    int count = 0;
+    static int called = 0;
+    struct Scsi_Host *instance;
 
-	/* For doing the reset, SCSI interrupts must be disabled first,
-	 * since the 5380 raises its IRQ line while _RST is active and we
-	 * can't disable interrupts completely, since we need the timer.
-	 */
-	/* And abort a maybe active DMA transfer */
-       	mac_turnoff_irq( IRQ_MAC_SCSI );
-#ifdef REAL_DMA
-       	mac_scsi_dma.dma_ctrl = 0;
-#endif /* REAL_DMA */
-#ifdef PSEUDO_DMA
-	mac_pdma_active = 0;
+    if (!MACH_IS_MAC || called)
+	return( 0 );
+
+    if (macintosh_config->scsi_type != MAC_SCSI_OLD)
+	 return( 0 );
+
+    tpnt->proc_dir = &proc_scsi_mac5380;
+
+    /* setup variables */
+    tpnt->can_queue =
+      (setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE;
+    tpnt->cmd_per_lun =
+      (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN;
+    tpnt->sg_tablesize = 
+      (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE;
+
+    if (setup_hostid >= 0)
+      tpnt->this_id = setup_hostid;
+    else {
+      /* use 7 as default */
+      tpnt->this_id = 7;
+    }
+
+#ifdef SUPPORT_TAGS
+	if (setup_use_tagged_queuing < 0)
+		setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING;
 #endif
 
-	rv = NCR5380_reset(cmd, reset_flags);
+#if 0	/* loop over multiple adapters (Powerbooks ??) */
+    for (count = 0; count < mac_num_scsi; count++) {
+#endif
+        instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
+	default_instance = instance;
 
-	/* Re-enable ints */
-       	mac_turnon_irq( IRQ_MAC_SCSI );
+	if (macintosh_config->ident == MAC_MODEL_IIFX) {
+		mac_scsi_regp  = via1+0x8000;
+		mac_scsi_drq   = via1+0xE000;
+		mac_scsi_nodrq = via1+0xC000;
+	} else {
+		mac_scsi_regp  = via1+0x10000;
+		mac_scsi_drq   = via1+0x6000;
+		mac_scsi_nodrq = via1+0x12000;
+	}
+
+
+        instance->io_port = (unsigned long) mac_scsi_regp;
+	instance->irq = IRQ_MAC_SCSI;
+
+#ifdef RESET_BOOT
+	mac_scsi_reset_boot(instance);
+#endif
+
+	NCR5380_init(instance, 0);
+
+	instance->n_io_port = 255;
+
+        ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
+
+	if (instance->irq != IRQ_NONE)
+#ifdef USE_WRAPPER
+	    if (request_irq(instance->irq, scsi_mac_intr, IRQ_FLG_SLOW, "MacSCSI-5380", NULL)) {
+#else
+	    if (request_irq(instance->irq, macscsi_intr, IRQ_FLG_SLOW, "MacSCSI-5380", NULL)) {
+#endif
+		printk("scsi%d: IRQ%d not free, interrupts disabled\n",
+		    instance->host_no, instance->irq);
+		instance->irq = IRQ_NONE;
+	    }
+
+	printk("scsi%d: generic 5380 at port %lX irq", instance->host_no, instance->io_port);
+	if (instance->irq == IRQ_NONE)
+	    printk ("s disabled");
+	else
+	    printk (" %d", instance->irq);
+	printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
+	    instance->can_queue, instance->cmd_per_lun, MACSCSI_PUBLIC_RELEASE);
+	printk("\nscsi%d:", instance->host_no);
+	NCR5380_print_options(instance);
+	printk("\n");
+#if 0	/* multiple adapters */
+    }
+#endif
+    called = 1;
+    return 1;
 
-	return( rv );
 }
 
-	
-static void mac_scsi_reset_boot( void )
+int macscsi_release (struct Scsi_Host *shpnt)
+{
+	if (shpnt->irq != IRQ_NONE)
+		free_irq (shpnt->irq, NULL);
+
+	return 0;
+}
+
+#ifdef RESET_BOOT
+/*
+ * Our 'bus reset on boot' function
+ */
+
+static void mac_scsi_reset_boot(struct Scsi_Host *instance)
 {
 	unsigned long end;
+
+	NCR5380_local_declare();
+	NCR5380_setup(instance);
 	
 	/*
 	 * Do a SCSI reset to clean up the bus during initialization. No messing
@@ -662,7 +380,7 @@ static void mac_scsi_reset_boot( void )
 	NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
 	NCR5380_read( RESET_PARITY_INTERRUPT_REG );
 
-	for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
+	for( end = jiffies + AFTER_RESET_DELAY; jiffies < end; )
 		barrier();
 
 	/* switch on SCSI IRQ again */
@@ -670,438 +388,359 @@ static void mac_scsi_reset_boot( void )
 
 	printk( " done\n" );
 }
+#endif
 
+const char * macscsi_info (struct Scsi_Host *spnt) {
+    return "";
+}
 
-const char * mac_scsi_info (struct Scsi_Host *host)
+void restore_irq(struct pt_regs *regs)
 {
-	/* mac_scsi_detect() is verbose enough... */
-	static const char string[] = "Macintosh NCR5380 SCSI";
-	return string;
-}
+	unsigned long flags;
 
+	save_flags(flags);
+	flags = (flags & ~0x0700) | (regs->sr & 0x0700);
+	restore_flags(flags);
+}
 
-#if defined(REAL_DMA)
+#ifdef USE_WRAPPER
+/*
+ * SCSI interrupt wrapper - just to make sure it's the proper irq, and 
+ * that we leave the handler in a clean state
+ */
 
-unsigned long mac_scsi_dma_setup( struct Scsi_Host *instance, void *data,
-				   unsigned long count, int dir )
+static void scsi_mac_intr (int irq, void *dev_id, struct pt_regs *fp)
 {
-	unsigned long addr = virt_to_phys( data );
-
-	DMA_PRINTK("scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, "
-		   "dir = %d\n", instance->host_no, data, addr, count, dir);
-
-	if (!STRAM_ADDR(addr)) {
-		/* If we have a non-DMAable address on a Falcon, use the dribble
-		 * buffer; 'orig_addr' != 0 in the read case tells the interrupt
-		 * handler to copy data from the dribble buffer to the originally
-		 * wanted address.
-		 */
-		if (dir)
-			memcpy( mac_dma_buffer, data, count );
-		else
-			mac_dma_orig_addr = data;
-		addr = mac_dma_phys_buffer;
-	}
-	
-	mac_dma_startaddr = addr;	/* Needed for calculating residual later. */
-  
-	/* Cache cleanup stuff: On writes, push any dirty cache out before sending
-	 * it to the peripheral. (Must be done before DMA setup, since at least
-	 * the ST-DMA begins to fill internal buffers right after setup. For
-	 * reads, invalidate any cache, may be altered after DMA without CPU
-	 * knowledge.
-	 * 
-	 * ++roman: For the Medusa, there's no need at all for that cache stuff,
-	 * because the hardware does bus snooping (fine!).
-	 */
-	dma_cache_maintenance( addr, count, dir );
+#ifndef RBV_HACK
+	unsigned long flags;
+#endif
+
+#ifdef RBV_HACK
+	mac_turnoff_irq( IRQ_MAC_SCSI );
+#else
+	mac_disable_irq( IRQ_MAC_SCSI );
+#endif
 
-	if (count == 0)
-		printk(KERN_NOTICE "SCSI warning: DMA programmed for 0 bytes !\n");
+	if ( irq == IRQ_MAC_SCSI ) {
+#ifndef RBV_HACK
+		save_flags(flags);
+		restore_irq(fp);
+#endif
+		NCR5380_intr (irq, dev_id, fp);
+#ifndef RBV_HACK
+		restore_flags(flags);
+#endif
+	}
 
-	mac_scsi_dma.dma_ctrl = dir;
-	SCSI_DMA_WRITE_P( dma_addr, addr );
-	SCSI_DMA_WRITE_P( dma_cnt, count );
-	mac_scsi_dma.dma_ctrl = dir | 2;
+	/* To be sure the int is not masked */
+#ifdef RBV_HACK
+	mac_turnon_irq( IRQ_MAC_SCSI );
+#else
+	mac_enable_irq( IRQ_MAC_SCSI );
+#endif
 
-	return( count );
+#if 1	/* ??? 0 worked */
+	/* Clear the IRQ */
+	via_scsi_clear();
+#endif
 }
+#endif
 
+/*
+ * pseudo-DMA transfer functions, copied and modified from Russel King's
+ * ARM 5380 driver (cumana_1)
+ *
+ * Work in progress (sort of), didn't work last time I checked, don't use!
+ */
 
-static long mac_scsi_dma_residual( struct Scsi_Host *instance )
-{
-	return( mac_dma_residual );
-}
+#ifdef NOT_EFFICIENT
+#define CTRL(p,v)     outb(*ctrl = (v), (p) - 577)
+#define STAT(p)       inb((p)+1)
+#define IN(p)         inb((p))
+#define OUT(v,p)      outb((v), (p))
+#else
+#if 0
+#define CTRL(p,v)	(p[-2308] = (*ctrl = (v)))
+#else
+#define CTRL(p,v)	(*ctrl = (v))
+#endif
+#define STAT(p)		(p[1<<4])
+#define IN(p)		(*(p))
+#define IN2(p)		((unsigned short)(*(volatile unsigned long *)(p)))
+#define OUT(v,p)	(*(p) = (v))
+#define OUT2(v,p)	(*((volatile unsigned long *)(p)) = (v))
+#endif
+#define L(v)		(((v)<<16)|((v) & 0x0000ffff))
+#define H(v)		(((v)>>16)|((v) & 0xffff0000))
+#define ioaddr(v)	(v)
 
+static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr,
+              int len)
+{
+  int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
+  int oldctrl = *ctrl;
+  unsigned long *laddr;
+#ifdef NOT_EFFICIENT
+  int iobase = instance->io_port;
+  int dma_io = mac_scsi_nodrq;
+#else
+  volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port);
+  volatile unsigned char *dma_io = (unsigned char *)(mac_scsi_nodrq);
+#endif
+
+  if(!len) return 0;
+
+  CTRL(iobase, 0x02);
+  laddr = (unsigned long *)addr;
+  while(len >= 32)
+  {
+    int status;
+    unsigned long v;
+    status = STAT(iobase);
+    if(status & 0x80)
+      goto end;
+    if(!(status & 0x40))
+      continue;
+    v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
+    v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
+    v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
+    v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
+    v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
+    v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
+    v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
+    v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
+    len -= 32;
+    if(len == 0)
+      break;
+  }
+
+  addr = (unsigned char *)laddr;
+  CTRL(iobase, 0x12);
+  while(len > 0)
+  {
+    int status;
+    status = STAT(iobase);
+    if(status & 0x80)
+      goto end;
+    if(status & 0x40)
+    {
+      OUT(*addr++, dma_io);
+      if(--len == 0)
+        break;
+    }
 
-#define	CMD_SURELY_BLOCK_MODE	0
-#define	CMD_SURELY_BYTE_MODE	1
-#define	CMD_MODE_UNKNOWN		2
+    status = STAT(iobase);
+    if(status & 0x80)
+      goto end;
+    if(status & 0x40)
+    {
+      OUT(*addr++, dma_io);
+      if(--len == 0)
+        break;
+    }
+  }
+end:
+  CTRL(iobase, oldctrl|0x40);
+  return len;
+}
 
-static int mac_classify_cmd( Scsi_Cmnd *cmd )
+static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr,
+              int len)
 {
-	unsigned char opcode = cmd->cmnd[0];
-	
-	if (opcode == READ_DEFECT_DATA || opcode == READ_LONG ||
-		opcode == READ_BUFFER)
-		return( CMD_SURELY_BYTE_MODE );
-	else if (opcode == READ_6 || opcode == READ_10 ||
-		 opcode == 0xa8 /* READ_12 */ || opcode == READ_REVERSE ||
-		 opcode == RECOVER_BUFFERED_DATA) {
-		/* In case of a sequential-access target (tape), special care is
-		 * needed here: The transfer is block-mode only if the 'fixed' bit is
-		 * set! */
-		if (cmd->device->type == TYPE_TAPE && !(cmd->cmnd[1] & 1))
-			return( CMD_SURELY_BYTE_MODE );
-		else
-			return( CMD_SURELY_BLOCK_MODE );
-	}
-	else
-		return( CMD_MODE_UNKNOWN );
+  int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
+  int oldctrl = *ctrl;
+  unsigned long *laddr;
+#ifdef NOT_EFFICIENT
+  int iobase = instance->io_port;
+  int dma_io = mac_scsi_nodrq;
+#else
+  volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port);
+  volatile unsigned char *dma_io = (unsigned char *)((int)mac_scsi_nodrq);
+#endif
+
+  if(!len) return 0;
+
+  CTRL(iobase, 0x00);
+  laddr = (unsigned long *)addr;
+  while(len >= 32)
+  {
+    int status;
+    status = STAT(iobase);
+    if(status & 0x80)
+      goto end;
+    if(!(status & 0x40))
+      continue;
+    *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
+    *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
+    *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
+    *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
+    *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
+    *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
+    *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
+    *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
+    len -= 32;
+    if(len == 0)
+      break;
+  }
+
+  addr = (unsigned char *)laddr;
+  CTRL(iobase, 0x10);
+  while(len > 0)
+  {
+    int status;
+    status = STAT(iobase);
+    if(status & 0x80)
+      goto end;
+    if(status & 0x40)
+    {
+      *addr++ = IN(dma_io);
+      if(--len == 0)
+        break;
+    }
+
+    status = STAT(iobase);
+    if(status & 0x80)
+      goto end;
+    if(status & 0x40)
+    {
+      *addr++ = IN(dma_io);
+      if(--len == 0)
+        break;
+    }
+  }
+end:
+  CTRL(iobase, oldctrl|0x40);
+  return len;
 }
 
-#endif	/* REAL_DMA */
+#undef STAT
+#undef CTRL
+#undef IN
+#undef OUT
 
-#if defined(REAL_DMA) || defined(PSEUDO_DMA)
-/* This function calculates the number of bytes that can be transferred via
- * DMA. On the TT, this is arbitrary, but on the Falcon we have to use the
- * ST-DMA chip. There are only multiples of 512 bytes possible and max.
- * 255*512 bytes :-( This means also, that defining READ_OVERRUNS is not
- * possible on the Falcon, since that would require to program the DMA for
- * n*512 - atari_read_overrun bytes. But it seems that the Falcon doesn't have
- * the overrun problem, so this question is academic :-)
+/*
+ * NCR 5380 register access functions
  */
 
-static unsigned long mac_dma_xfer_len( unsigned long wanted_len,
-					Scsi_Cmnd *cmd,
-					int write_flag )
+#ifdef ORIG
+#if 0
+#define CTRL(p,v) outb(*ctrl = (v), (p) - 577)
+#else
+#define CTRL(p,v) (*ctrl = (v))
+#endif
+
+static char macscsi_read(struct Scsi_Host *instance, int reg)
 {
-	unsigned long	possible_len, limit;
-
-#if defined(REAL_DMA)
-	if (IS_A_TT())
-		/* TT SCSI DMA can transfer arbitrary #bytes */
-		return( wanted_len );
-
-	/* ST DMA chip is stupid -- only multiples of 512 bytes! (and max.
-	 * 255*512 bytes, but this should be enough)
-	 *
-	 * ++roman: Aaargl! Another Falcon-SCSI problem... There are some commands
-	 * that return a number of bytes which cannot be known beforehand. In this
-	 * case, the given transfer length is an "allocation length". Now it
-	 * can happen that this allocation length is a multiple of 512 bytes and
-	 * the DMA is used. But if not n*512 bytes really arrive, some input data
-	 * will be lost in the ST-DMA's FIFO :-( Thus, we have to distinguish
-	 * between commands that do block transfers and those that do byte
-	 * transfers. But this isn't easy... there are lots of vendor specific
-	 * commands, and the user can issue any command via the
-	 * SCSI_IOCTL_SEND_COMMAND.
-	 *
-	 * The solution: We classify SCSI commands in 1) surely block-mode cmd.s,
-	 * 2) surely byte-mode cmd.s and 3) cmd.s with unknown mode. In case 1)
-	 * and 3), the thing to do is obvious: allow any number of blocks via DMA
-	 * or none. In case 2), we apply some heuristic: Byte mode is assumed if
-	 * the transfer (allocation) length is < 1024, hoping that no cmd. not
-	 * explicitly known as byte mode have such big allocation lengths...
-	 * BTW, all the discussion above applies only to reads. DMA writes are
-	 * unproblematic anyways, since the targets aborts the transfer after
-	 * receiving a sufficient number of bytes.
-	 *
-	 * Another point: If the transfer is from/to an non-ST-RAM address, we
-	 * use the dribble buffer and thus can do only STRAM_BUFFER_SIZE bytes.
-	 */
+  int iobase = instance->io_port;
+  int i;
+  int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
 
-	if (write_flag) {
-		/* Write operation can always use the DMA, but the transfer size must
-		 * be rounded up to the next multiple of 512 (atari_dma_setup() does
-		 * this).
-		 */
-		possible_len = wanted_len;
-	}
-	else {
-		/* Read operations: if the wanted transfer length is not a multiple of
-		 * 512, we cannot use DMA, since the ST-DMA cannot split transfers
-		 * (no interrupt on DMA finished!)
-		 */
-		if (wanted_len & 0x1ff)
-			possible_len = 0;
-		else {
-			/* Now classify the command (see above) and decide whether it is
-			 * allowed to do DMA at all */
-			switch( falcon_classify_cmd( cmd )) {
-			  case CMD_SURELY_BLOCK_MODE:
-				possible_len = wanted_len;
-				break;
-			  case CMD_SURELY_BYTE_MODE:
-				possible_len = 0; /* DMA prohibited */
-				break;
-			  case CMD_MODE_UNKNOWN:
-			  default:
-				/* For unknown commands assume block transfers if the transfer
-				 * size/allocation length is >= 1024 */
-				possible_len = (wanted_len < 1024) ? 0 : wanted_len;
-				break;
-			}
-		}
-	}
+  CTRL(iobase, 0);
+#if 0
+  i = inb(iobase + 64 + reg);
+#else
+  i = inb(iobase + reg<<4);
+#endif
+  CTRL(iobase, 0x40);
 
-	/* Last step: apply the hard limit on DMA transfers */
-	limit = (atari_dma_buffer && !STRAM_ADDR( virt_to_phys(cmd->SCp.ptr) )) ?
-		    STRAM_BUFFER_SIZE : 255*512;
-	if (possible_len > limit)
-		possible_len = limit;
+  return i;
+}
 
-	if (possible_len != wanted_len)
-		DMA_PRINTK("Sorry, must cut DMA transfer size to %ld bytes "
-			   "instead of %ld\n", possible_len, wanted_len);
+static void macscsi_write(struct Scsi_Host *instance, int reg, int value)
+{
+  int iobase = instance->io_port;
+  int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
 
-#else /* REAL_DMA */
-	possible_len = wanted_len;
+  CTRL(iobase, 0);
+#if 0
+  outb(value, iobase + 64 + reg);
+#else
+  outb(value, iobase + reg<<4);
 #endif
-	
-	return( possible_len );
+  CTRL(iobase, 0x40);
 }
-#endif	/* REAL_DMA || PSEUDO_DMA */
-
-
-/* 
- * FIXME !!!
- */
 
-/* NCR5380 register access functions
- */
+#undef CTRL
 
-static unsigned char mac_scsi_reg_read( unsigned char reg )
+#else
+static char macscsi_read(struct Scsi_Host *instance, int reg)
 {
 	return( mac_scsi_regp[reg << 4] );
 }
 
-static void mac_scsi_reg_write( unsigned char reg, unsigned char value )
+static void macscsi_write(struct Scsi_Host *instance, int reg, int value)
 {
 	mac_scsi_regp[reg << 4] = value;
 }
 
-#include "mac_NCR5380.c"
+#endif
 
-#ifdef PSEUDO_DMA
+#include "NCR5380.c"
 
 /*
- * slightly optimized PIO transfer routines, experimental!
- * command may time out if interrupts are left enabled
+ * Debug stuff - to be called on NMI, or sysrq key. Use at your own risk; 
+ * reentering NCR5380_print_status seems to have ugly side effects
  */
 
-static inline int mac_pdma_read (struct Scsi_Host *instance, unsigned char *dst,    int len)
+void scsi_mac_debug (void)
 {
-    register unsigned char *d = dst;
-    register i = len;
-    register unsigned char p, tmp;
-
-#if (NDEBUG & NDEBUG_PSEUDO_DMA)
-    printk("pdma_read: reading %d bytes to %p\n", len, dst);
-#endif
-
-    mac_pdma_residual = len;
-    if (mac_pdma_active) {
-      printk("pseudo-DMA already active in pread!\n");
-      return -1;
-    }
-    mac_pdma_active = 1;
-    mac_pdma_startaddr = (unsigned long) dst;
-    mac_pdma_current   = (unsigned long) dst;
-
-    /* 
-     * Get the phase from the bus (sanity check) 
-     * Hopefully, the phase bits are valid here ...
-     */
-    p = NCR5380_read(STATUS_REG) & PHASE_MASK;
-    if (!(p & SR_IO)) {
-      PDMA_PRINTK("NCR5380_pread: initial phase mismatch!\n");
-      NCR_PRINT_PHASE(NDEBUG_ANY);
-      return -1;
-    }
-
-    /* 
-     * The NCR5380 chip will only drive the SCSI bus when the 
-     * phase specified in the appropriate bits of the TARGET COMMAND
-     * REGISTER match the STATUS REGISTER
-     */
+	unsigned long flags;
+	NCR5380_local_declare();
 
-#if 0	/* done in transfer_dma */
-    p = PHASE_DATAIN;
-    NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
+	if (default_instance) {
+#if 0
+		NCR5380_setup(default_instance);
+		if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ)
 #endif
-
-    for (; i; --i) {
-	HSH_PRINTK(" read %d ..", i);
-        /* check if we were interrupted ... */
-        if (!mac_pdma_active) {
-	  printk("pwrite: interrupt detected!\n");
-	  break;
-        }
-
-	/* 
-	 * Wait for assertion of REQ, after which the phase bits will be 
-	 * valid 
-	 */
-	while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ))
-		barrier();
-
-	HSH_PRINTK(" REQ ..");
-
-	/* Check for phase mismatch */	
-	if ((tmp & PHASE_MASK) != p) {
-            if (!mac_pdma_active) 
-	    	printk("scsi%d : phase mismatch after interrupt\n", instance->host_no);
-	    else
-	    	printk("scsi%d : phase mismatch w/o interrupt\n", instance->host_no);
-	    NCR_PRINT_PHASE(NDEBUG_ANY);
-	    break;
+			save_flags(flags);
+			cli();
+			NCR5380_print_status(default_instance);
+			restore_flags(flags);
 	}
-
-	/* Do actual transfer from SCSI bus to memory */
-	*d = NCR5380_read(CURRENT_SCSI_DATA_REG);
-
-	d++;
-	
-	/* Handshake ... */
-
-	/* Assert ACK */
-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
-	HSH_PRINTK(" ACK ..");
-
-	/* Wait for REQ to be dropped */
-	while (NCR5380_read(STATUS_REG) & SR_REQ)
-		barrier();
-	HSH_PRINTK(" /REQ ..");
-
-	/* Drop ACK */
-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-	HSH_PRINTK(" /ACK !\n");
-
-	mac_pdma_current = (unsigned long) d;
-	mac_pdma_residual--;
-    }
-
-#if (NDEBUG & NDEBUG_PSEUDO_DMA)
-    printk("pdma_read: read at %d bytes to %p\n", i, dst);
-#endif
-
-    if (mac_pdma_residual)
-      printk("pread: leaving with residual %ld of %ld\n", 
-      		mac_pdma_residual, len);
-    mac_pdma_active = 0;
-
-    /* ?? */
 #if 0
-    NCR5380_write(MODE_REG, MR_BASE);
-    NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+	polled_scsi_on = 1;
 #endif
-    return 0;
 }
-		
-static inline int mac_pdma_write (struct Scsi_Host *instance, unsigned char *src,    int len)
-{
-    register unsigned char *s = src;
-    register i = len;
-    register unsigned char p, tmp;
+/*
+ * Helper function for interrupt trouble. More ugly side effects here.
+ */
 
-#if (NDEBUG & NDEBUG_PSEUDO_DMA)
-    printk("pdma_write: writing %d bytes from %p\n", len, src);
+void scsi_mac_polled (void)
+{
+	unsigned long flags;
+	NCR5380_local_declare();
+	struct Scsi_Host *instance;
+	
+#if 0
+	for (instance = first_instance; instance && (instance->hostt == 
+	    the_template); instance = instance->next)
+	    if (instance->irq == IRQ_MAC_SCSI && polled_scsi_on) {
+#else
+		instance = default_instance;
 #endif
-
-    mac_pdma_residual = len;
-    if (mac_pdma_active) {
-      printk("pseudo-DMA already active in pwrite!\n");
-      return -1;
-    }
-    mac_pdma_active = 1;
-    mac_pdma_startaddr = (unsigned long) src;
-    mac_pdma_current   = (unsigned long) src;
-
-    /* 
-     * Get the phase from the bus (sanity check) 
-     */
-    p = NCR5380_read(STATUS_REG) & PHASE_MASK;
-    if (p & SR_IO) {
-      printk("NCR5380_pwrite: initial phase mismatch!\n");
-      NCR_PRINT_PHASE(NDEBUG_ANY);
-      return -1;
-    }
-
-    /* 
-     * The NCR5380 chip will only drive the SCSI bus when the 
-     * phase specified in the appropriate bits of the TARGET COMMAND
-     * REGISTER match the STATUS REGISTER
-     */
-
-#if 0	/* already done in transfer_dma */ 
-    p = PHASE_DATAOUT;
-    NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
+		NCR5380_setup(instance);
+		if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ)
+		{
+			printk("SCSI poll\n");
+			save_flags(flags);
+			cli();
+#ifdef USE_WRAPPER
+			scsi_mac_intr(IRQ_MAC_SCSI, instance, NULL);
+#else
+			macscsi_intr(IRQ_MAC_SCSI, instance, NULL);
 #endif
-
-    for (; i; --i) {
-        /* check if we were interrupted ... */
-        if (!mac_pdma_active) {
-	  printk("pwrite: interrupt detected!\n");
-	  break;
-        }
-
-       	/* 
-	 * Wait for assertion of REQ, after which the phase bits will be 
-	 * valid 
-	 */
-	while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ));
-
-	/* Check for phase mismatch */	
-	if ((tmp & PHASE_MASK) != p) {
-            if (!mac_pdma_active) 
-	    	printk("scsi%d : phase mismatch after interrupt\n", instance->host_no);
-	    else
-	    	printk("scsi%d : phase mismatch w/o interrupt\n", instance->host_no);
-	    NCR_PRINT_PHASE(NDEBUG_ANY);
-	    /* should we signal an error here?? */
-	    break;
-	}
-
-	/* Do actual transfer to SCSI bus from memory */
-
-	NCR5380_write(OUTPUT_DATA_REG, *s);
-
-	s++;
-	
-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
-		      ICR_ASSERT_DATA);
-
-	/* Handshake ... assert ACK */
-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
-		      ICR_ASSERT_DATA | ICR_ASSERT_ACK);
-
-	/* ... wait for REQ to be dropped */
-	while (NCR5380_read(STATUS_REG) & SR_REQ);
-
-	/* and drop ACK (and DATA) ! */
-	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
-	mac_pdma_current = (unsigned long) s;
-	mac_pdma_residual--;
-    }
-
-#if (NDEBUG & NDEBUG_PSEUDO_DMA)
-    printk("pdma_write: write at %d bytes from %p\n", i, src);
+			restore_flags(flags);
+		}
+#if 0
+	    }
 #endif
+}
 
-    if (mac_pdma_residual)
-      printk("pwrite: leaving with residual %ld of len %ld \n", 
-      		mac_pdma_residual, len);
-    mac_pdma_active = 0;
 
-    return 0;
-
-}
-#endif /* PSEUDO_DMA */
 
 #ifdef MODULE
-Scsi_Host_Template driver_template = MAC_SCSI;
+
+Scsi_Host_Template driver_template = MAC_NCR5380;
 
 #include "scsi_module.c"
 #endif
diff --git a/drivers/scsi/mac_scsi.h b/drivers/scsi/mac_scsi.h
index da186f9d406b3b7af60c1d3656a8d92292d66da4..49a90965c34b3eeb28d4faa5b2029309adf02484 100644
--- a/drivers/scsi/mac_scsi.h
+++ b/drivers/scsi/mac_scsi.h
@@ -1,286 +1,110 @@
 /*
- * mac_scsi.h -- Header file for the Macintosh native SCSI driver
+ * Cumana Generic NCR5380 driver defines
  *
- * based on Roman Hodeks atari_scsi.h
- */
-
-/*
- * atari_scsi.h -- Header file for the Atari native SCSI driver
+ * Copyright 1993, Drew Eckhardt
+ *	Visionary Computing
+ *	(Unix and Linux consulting and custom programming)
+ *	drew@colorado.edu
+ *      +1 (303) 440-4894
  *
- * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ * ALPHA RELEASE 1.
  *
- * (Loosely based on the work of Robert De Vries' team)
+ * For more information, please consult
  *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
+ * NCR 5380 Family
+ * SCSI Protocol Controller
+ * Databook
  *
+ * NCR Microelectronics
+ * 1635 Aeroplaza Drive
+ * Colorado Springs, CO 80916
+ * 1+ (719) 578-3400
+ * 1+ (800) 334-5454
  */
 
+/*
+ * $Log: cumana_NCR5380.h,v $
+ */
 
-#ifndef MAC_SCSI_H
-#define MAC_SCSI_H
-
-/* (I_HAVE_OVERRUNS stuff removed) */
-
-#ifndef ASM
-int mac_scsi_abort (Scsi_Cmnd *);
-int mac_scsi_detect (Scsi_Host_Template *);
-const char * mac_scsi_info (struct Scsi_Host *host);
-int mac_scsi_queue_command (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
-int mac_scsi_reset (Scsi_Cmnd *, unsigned int);
-int mac_scsi_proc_info (char *, char **, off_t, int, int, int);
-#ifdef MODULE
-int mac_scsi_release (struct Scsi_Host *);
-#else
-#define mac_scsi_release NULL
-#endif
-
-/* The values for CMD_PER_LUN and CAN_QUEUE are somehow arbitrary. Higher
- * values should work, too; try it! (but cmd_per_lun costs memory!) */
-
-/* But there seems to be a bug somewhere that requires CAN_QUEUE to be
- * 2*CMD_PER_LUN. At least on a TT, no spurious timeouts seen since
- * changed CMD_PER_LUN... */
-
-/* Note: The Falcon currently uses 8/1 setting due to unsolved problems with
- * cmd_per_lun != 1 */
-
-#define MAC_SCSI_CAN_QUEUE		        16
-#define MAC_SCSI_CMD_PER_LUN		        8
-#define MAC_SCSI_SG_TABLESIZE		SG_ALL
-
-#define	DEFAULT_USE_TAGGED_QUEUING	0
+#ifndef MAC_NCR5380_H
+#define MAC_NCR5380_H
 
+#define MACSCSI_PUBLIC_RELEASE 1
 
-#if defined (HOSTS_C) || defined (MODULE)
 
-#define MAC_SCSI { NULL, NULL, NULL,				\
-  mac_scsi_proc_info,						\
-  "Macintosh NCR5380 SCSI",					\
-  mac_scsi_detect,						\
-  mac_scsi_release,						\
-  mac_scsi_info,						\
-  /* command */ NULL,						\
-  mac_scsi_queue_command,					\
-  mac_scsi_abort,						\
-  mac_scsi_reset,						\
-  /* slave_attach */	NULL,					\
-  /* bios_param */	NULL,					\
-  /* can queue */	0, /* initialized at run-time */	\
-  /* host_id */		0, /* initialized at run-time */	\
-  /* scatter gather */	0, /* initialized at run-time */	\
-  /* cmd per lun */	0, /* initialized at run-time */	\
-  /* present */		0,					\
-  /* unchecked ISA DMA */ 0,					\
-  /* use_clustering */	DISABLE_CLUSTERING }
+#ifndef ASM
+int macscsi_abort (Scsi_Cmnd *);
+int macscsi_detect (Scsi_Host_Template *);
+int macscsi_release (struct Scsi_Host *);
+const char *macscsi_info (struct Scsi_Host *);
+int macscsi_reset(Scsi_Cmnd *, unsigned int);
+int macscsi_queue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+int macscsi_proc_info (char *buffer, char **start, off_t offset,
+			int length, int hostno, int inout);
 
+#ifndef NULL
+#define NULL 0
 #endif
 
-#ifndef HOSTS_C
+#ifndef CMD_PER_LUN
+#define CMD_PER_LUN 2
+#endif
 
-#define	NCR5380_implementation_fields	/* none */
+#ifndef CAN_QUEUE
+#define CAN_QUEUE 16
+#endif
 
-#define NCR5380_read(reg)		  mac_scsi_reg_read( reg )
-#define NCR5380_write(reg, value) mac_scsi_reg_write( reg, value )
+#ifndef SG_TABLESIZE
+#define SG_TABLESIZE SG_NONE
+#endif
 
-#define NCR5380_intr mac_scsi_intr
-#define NCR5380_queue_command mac_scsi_queue_command
-#define NCR5380_abort mac_scsi_abort
-#define NCR5380_proc_info mac_scsi_proc_info
-#define NCR5380_dma_read_setup(inst,d,c) mac_scsi_dma_setup (inst, d, c, 0)
-#define NCR5380_dma_write_setup(inst,d,c) mac_scsi_dma_setup (inst, d, c, 1)
-#define NCR5380_dma_residual(inst) mac_scsi_dma_residual( inst )
-#define	NCR5380_dma_xfer_len(i,cmd,phase) \
-	mac_dma_xfer_len(cmd->SCp.this_residual,cmd,((phase) & SR_IO) ? 0 : 1)
-#ifdef PSEUDO_DMA
-#define NCR5380_pread(inst,d,l) mac_pdma_read (inst, d, l)
-#define NCR5380_pwrite(inst,d,l) mac_pdma_write (inst, d, l)
+#ifndef USE_TAGGED_QUEUING
+#define	USE_TAGGED_QUEUING 0
 #endif
 
-/* Debugging printk definitions:
- *
- *  ARB  -> arbitration
- *  ASEN -> auto-sense
- *  DMA  -> DMA
- *  HSH  -> PIO handshake
- *  INF  -> information transfer
- *  INI  -> initialization
- *  INT  -> interrupt
- *  LNK  -> linked commands
- *  MAIN -> NCR5380_main() control flow
- *  NDAT -> no data-out phase
- *  NWR  -> no write commands
- *  PIO  -> PIO transfers
- *  PDMA -> pseudo DMA (unused on MAC)
- *  QU   -> queues
- *  RSL  -> reselections
- *  SEL  -> selections
- *  USL  -> usleep cpde (unused on MAC)
- *  LBS  -> last byte sent (unused on MAC)
- *  RSS  -> restarting of selections
- *  EXT  -> extended messages
- *  ABRT -> aborting and resetting
- *  TAG  -> queue tag handling
- *  MER  -> merging of consec. buffers
- *
- */
+#include <scsi/scsicam.h>
 
-#if NDEBUG & NDEBUG_ARBITRATION
-#define ARB_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define ARB_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_AUTOSENSE
-#define ASEN_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define ASEN_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_DMA
-#define DMA_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define DMA_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_HANDSHAKE
-#define HSH_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define HSH_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_INFORMATION
-#define INF_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define INF_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_INIT
-#define INI_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define INI_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_INTR
-#define INT_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define INT_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_LINKED
-#define LNK_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define LNK_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_MAIN
-#define MAIN_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define MAIN_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_NO_DATAOUT
-#define NDAT_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define NDAT_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_NO_WRITE
-#define NWR_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define NWR_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_PIO
-#define PIO_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define PIO_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_PSEUDO_DMA
-#define PDMA_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define PDMA_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_QUEUES
-#define QU_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define QU_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_RESELECTION
-#define RSL_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define RSL_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_SELECTION
-#define SEL_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define SEL_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_USLEEP
-#define USL_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define USL_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_LAST_BYTE_SENT
-#define LBS_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define LBS_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_RESTART_SELECT
-#define RSS_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define RSS_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_EXTENDED
-#define EXT_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define EXT_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_ABORT
-#define ABRT_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define ABRT_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_TAGS
-#define TAG_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define TAG_PRINTK(format, args...)
-#endif
-#if NDEBUG & NDEBUG_MERGING
-#define MER_PRINTK(format, args...) \
-	printk(KERN_DEBUG format , ## args)
-#else
-#define MER_PRINTK(format, args...)
-#endif
+#define MAC_NCR5380 {						\
+name:			"Macintosh NCR5380 SCSI",			\
+detect:			macscsi_detect,					\
+release:		macscsi_release,	/* Release */		\
+info:			macscsi_info,					\
+queuecommand:		macscsi_queue_command,				\
+abort:			macscsi_abort,			 		\
+reset:			macscsi_reset,					\
+bios_param:		scsicam_bios_param,	/* biosparam */		\
+can_queue:		CAN_QUEUE,		/* can queue */		\
+this_id:		7,			/* id */		\
+sg_tablesize:		SG_ALL,			/* sg_tablesize */	\
+cmd_per_lun:		CMD_PER_LUN,		/* cmd per lun */	\
+unchecked_isa_dma:	0,			/* unchecked_isa_dma */	\
+use_clustering:		DISABLE_CLUSTERING				\
+	}
 
-/* conditional macros for NCR5380_print_{,phase,status} */
+#ifndef HOSTS_C
 
-#define NCR_PRINT(mask)	\
-	((NDEBUG & (mask)) ? NCR5380_print(instance) : (void)0)
+#define NCR5380_implementation_fields \
+    int port, ctrl
 
-#define NCR_PRINT_PHASE(mask) \
-	((NDEBUG & (mask)) ? NCR5380_print_phase(instance) : (void)0)
+#define NCR5380_local_declare() \
+        struct Scsi_Host *_instance
 
-#define NCR_PRINT_STATUS(mask) \
-	((NDEBUG & (mask)) ? NCR5380_print_status(instance) : (void)0)
+#define NCR5380_setup(instance) \
+        _instance = instance
 
-#define NDEBUG_ANY	0xffffffff
+#define NCR5380_read(reg) macscsi_read(_instance, reg)
+#define NCR5380_write(reg, value) macscsi_write(_instance, reg, value)
 
+#define NCR5380_intr macscsi_intr
+#define NCR5380_queue_command macscsi_queue_command
+#define NCR5380_abort macscsi_abort
+#define NCR5380_reset macscsi_reset
+#define NCR5380_proc_info macscsi_proc_info
 
-#endif /* else def HOSTS_C */
-#endif /* ndef ASM */
-#endif /* MAC_SCSI_H */
+#define BOARD_NORMAL	0
+#define BOARD_NCR53C400	1
 
+#endif /* ndef HOSTS_C */
+#endif /* ndef ASM */
+#endif /* MAC_NCR5380_H */
 
diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c
new file mode 100644
index 0000000000000000000000000000000000000000..76930a9e055dd7f49e586a005ef89c44f868b0d7
--- /dev/null
+++ b/drivers/scsi/sun3_scsi.c
@@ -0,0 +1,420 @@
+/*
+ * Sun3 SCSI stuff by Erik Verbruggen (erik@bigmama.xtdnet.nl)
+ *
+ * Adapted from mac_scsinew.c:
+ */
+/*
+ * Generic Macintosh NCR5380 driver
+ *
+ * Copyright 1998, Michael Schmitz <mschmitz@lbl.gov>
+ *
+ * derived in part from:
+ */
+/*
+ * Generic Generic NCR5380 driver
+ *
+ * Copyright 1995, Russell King
+ *
+ * ALPHA RELEASE 1.
+ *
+ * For more information, please consult
+ *
+ * NCR 5380 Family
+ * SCSI Protocol Controller
+ * Databook
+ *
+ * NCR Microelectronics
+ * 1635 Aeroplaza Drive
+ * Colorado Springs, CO 80916
+ * 1+ (719) 578-3400
+ * 1+ (800) 334-5454
+ */
+
+
+/*
+ * This is from mac_scsi.h, but hey, maybe this is usefull for Sun3 too! :)
+ *
+ * Options :
+ *
+ * PARITY - enable parity checking.  Not supported.
+ *
+ * SCSI2 - enable support for SCSI-II tagged queueing.  Untested.
+ *
+ * USLEEP - enable support for devices that don't disconnect.  Untested.
+ */
+
+/*
+ * $Log: mac_NCR5380.c,v $
+ */
+
+#define AUTOSENSE
+#if 0
+#define PSEUDO_DMA
+#endif
+
+#include <linux/types.h>
+#include <linux/stddef.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/blk.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include <asm/sun3ints.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "sun3_scsi.h"
+#include "NCR5380.h"
+#include "constants.h"
+
+#if 0
+#define NDEBUG (NDEBUG_INTR | NDEBUG_PSEUDO_DMA | NDEBUG_ARBITRATION | NDEBUG_SELECTION | NDEBUG_RESELECTION)
+#define NCR_TIMEOUT 100
+#else
+#define NDEBUG (NDEBUG_ABORT)
+#endif
+
+#define USE_WRAPPER
+#define RESET_BOOT
+#define DRIVER_SETUP
+
+/*
+ * BUG can be used to trigger a strange code-size related hang on 2.1 kernels
+ */
+#ifdef BUG
+#undef RESET_BOOT
+#undef DRIVER_SETUP
+#endif
+
+#define	ENABLE_IRQ()	sun3_enable_irq( IRQ_SUN3_SCSI ); 
+#define	DISABLE_IRQ()	sun3_enable_irq( IRQ_SUN3_SCSI );
+
+/* extern void via_scsi_clear(void); */
+
+static void scsi_sun3_intr(int irq, void *dummy, struct pt_regs *fp);
+static char sun3scsi_read(struct Scsi_Host *instance, int reg);
+static void sun3scsi_write(struct Scsi_Host *instance, int reg, int value);
+
+static int setup_can_queue = -1;
+static int setup_cmd_per_lun = -1;
+static int setup_sg_tablesize = -1;
+#ifdef SUPPORT_TAGS
+static int setup_use_tagged_queuing = -1;
+#endif
+static int setup_hostid = -1;
+
+static int polled_scsi_on = 0;
+
+#define	AFTER_RESET_DELAY	(HZ/2)
+
+static struct proc_dir_entry proc_scsi_sun3_5380 = {
+	PROC_SCSI_MAC, 13, "Sun3 5380 SCSI", S_IFDIR | S_IRUGO, S_IXUGO, 2
+};
+
+static volatile unsigned char *sun3_scsi_regp = IOBASE_SUN3_SCSI;
+/*
+static volatile unsigned char *sun3_scsi_drq  = NULL;
+static volatile unsigned char *sun3_scsi_nodrq = NULL;
+*/
+
+/*
+ * Function : sun3_scsi_setup(char *str, int *ints)
+ *
+ * Purpose : booter command line initialization of the overrides array,
+ *
+ * Inputs : str - unused, ints - array of integer parameters with ints[0]
+ *	equal to the number of ints.
+ *
+ * TODO: make it actually work!
+ *
+ */
+
+void sun3_scsi_setup(char *str, int *ints) {
+	printk("sun3_scsi_setup() called\n");
+	setup_can_queue = -1;
+	setup_cmd_per_lun = -1;
+	setup_sg_tablesize = -1;
+	setup_hostid = -1;
+#ifdef SUPPORT_TAGS
+	setup_use_tagged_queuing = -1;
+#endif
+	printk("sun3_scsi_setup() done\n");
+}
+
+/*
+ * XXX: status debug
+ */
+static struct Scsi_Host *default_instance;
+
+/*
+ * Function : int sun3scsi_detect(Scsi_Host_Template * tpnt)
+ *
+ * Purpose : initializes mac NCR5380 driver based on the
+ *	command line / compile time port and irq definitions.
+ *
+ * Inputs : tpnt - template for this SCSI adapter.
+ *
+ * Returns : 1 if a host adapter was found, 0 if not.
+ *
+ */
+ 
+int sun3scsi_detect(Scsi_Host_Template * tpnt)
+{
+	unsigned long ioaddr, iopte;
+	unsigned short *ioptr;
+	int count = 0;
+	static int called = 0;
+	struct Scsi_Host *instance;
+
+	if(called)
+		return 0;
+
+printk("sun3scsi_detect(0x%p)\n",tpnt);
+
+	tpnt->proc_dir = &proc_scsi_sun3_5380;
+
+	/* setup variables */
+	tpnt->can_queue =
+		(setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE;
+	tpnt->cmd_per_lun =
+		(setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN;
+	tpnt->sg_tablesize = 
+		(setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE;
+
+	if (setup_hostid >= 0)
+		tpnt->this_id = setup_hostid;
+	else {
+		/* use 7 as default */
+		tpnt->this_id = 7;
+	}
+
+	/* Taken from Sammy's lance driver: */
+        /* IOBASE_SUN3_SCSI can be found within the IO pmeg with some effort */
+        for(ioaddr = 0xfe00000; ioaddr < (0xfe00000 + SUN3_PMEG_SIZE);
+            ioaddr += SUN3_PTE_SIZE) {
+
+                iopte = sun3_get_pte(ioaddr);
+                if(!(iopte & SUN3_PAGE_TYPE_IO)) /* this an io page? */
+                        continue;
+
+                if(((iopte & SUN3_PAGE_PGNUM_MASK) << PAGE_SHIFT) ==
+                   IOBASE_SUN3_SCSI) {
+                        count = 1;
+printk("Found ioaddr in pmeg\n");
+                        break;
+                }
+        }
+
+	if(!count) {
+		printk("No Sun3 NCR5380 found!\n");
+		return 0;
+	}
+
+	sun3_scsi_regp = ioaddr;
+
+	/* doing some stuff like resetting DVMA: */
+	ioptr = ioaddr;
+        *(ioptr+8) = 0;
+	udelay(10);
+        *(ioptr+9) = 0;
+	udelay(10);
+        *(ioptr+12) = 0;
+	udelay(10);
+        *(ioptr+12) = 0x7;
+	udelay(10);
+	printk("SCSI status reg = %x\n", *(ioptr+12));
+	udelay(10);
+        *(ioptr+13) = 0;
+	udelay(10);
+
+#ifdef SUPPORT_TAGS
+	if (setup_use_tagged_queuing < 0)
+		setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING;
+#endif
+
+	instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
+	default_instance = instance;
+
+/*
+	if (macintosh_config->ident == MAC_MODEL_IIFX) {
+		mac_scsi_regp  = via1_regp+0x8000;
+		mac_scsi_drq   = via1_regp+0x6000;
+		mac_scsi_nodrq = via1_regp+0x12000;
+	} else {
+		mac_scsi_regp  = via1_regp+0x10000;
+		mac_scsi_drq   = via1_regp+0x6000;
+		mac_scsi_nodrq = via1_regp+0x12000;
+	}
+*/
+
+        instance->io_port = (unsigned long) ioaddr;
+	instance->irq = IRQ_SUN3_SCSI;
+
+	NCR5380_init(instance, 0);
+
+	instance->n_io_port = 32;
+
+        ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
+
+	if (instance->irq != IRQ_NONE)
+		if (sun3_request_irq(instance->irq, sun3scsi_intr,
+		                0, "Sun3SCSI-5380", NULL)) {
+			printk("scsi%d: IRQ%d not free, interrupts disabled\n",
+			       instance->host_no, instance->irq);
+			instance->irq = IRQ_NONE;
+		}
+
+	printk("scsi%d: generic 5380 at port %lX irq", instance->host_no, instance->io_port);
+	if (instance->irq == IRQ_NONE)
+		printk ("s disabled");
+	else
+		printk (" %d", instance->irq);
+	printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
+	       instance->can_queue, instance->cmd_per_lun,
+	       SUN3SCSI_PUBLIC_RELEASE);
+	printk("\nscsi%d:", instance->host_no);
+	NCR5380_print_options(instance);
+	printk("\n");
+
+	called = 1;
+	return 1;
+}
+
+int sun3scsi_release (struct Scsi_Host *shpnt)
+{
+	if (shpnt->irq != IRQ_NONE)
+		free_irq (shpnt->irq, NULL);
+
+	return 0;
+}
+
+#ifdef RESET_BOOT
+/*
+ * Our 'bus reset on boot' function
+ */
+
+static void sun3_scsi_reset_boot(struct Scsi_Host *instance)
+{
+	unsigned long end;
+
+	NCR5380_local_declare();
+	NCR5380_setup(instance);
+	
+	/*
+	 * Do a SCSI reset to clean up the bus during initialization. No
+	 * messing with the queues, interrupts, or locks necessary here.
+	 */
+
+	printk( "Sun3 SCSI: resetting the SCSI bus..." );
+
+	/* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */
+       	sun3_disable_irq( IRQ_SUN3_SCSI );
+
+	/* get in phase */
+	NCR5380_write( TARGET_COMMAND_REG,
+		      PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
+
+	/* assert RST */
+	NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
+
+	/* The min. reset hold time is 25us, so 40us should be enough */
+	udelay( 50 );
+
+	/* reset RST and interrupt */
+	NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
+	NCR5380_read( RESET_PARITY_INTERRUPT_REG );
+
+	for( end = jiffies + AFTER_RESET_DELAY; jiffies < end; )
+		barrier();
+
+	/* switch on SCSI IRQ again */
+       	sun3_enable_irq( IRQ_SUN3_SCSI );
+
+	printk( " done\n" );
+}
+#endif
+
+const char * sun3scsi_info (struct Scsi_Host *spnt) {
+    return "";
+}
+
+
+/*
+ * NCR 5380 register access functions
+ */
+
+static char sun3scsi_read(struct Scsi_Host *instance, int reg)
+{
+/*
+printk("sun3scsi_read(instance=0x%p, reg=0x%x): @0x%p= %d\n",instance,reg,sun3_scsi_regp,sun3_scsi_regp[reg]);
+*/
+	return( sun3_scsi_regp[reg] );
+}
+
+static void sun3scsi_write(struct Scsi_Host *instance, int reg, int value)
+{
+/*
+	printk("sun3scsi_write(instance=0x%p, reg=0x%x, value=0x%x)\n", instance, reg, value);
+*/
+	sun3_scsi_regp[reg] = value;
+}
+
+#include "NCR5380.c"
+
+/*
+ * Debug stuff - to be called on NMI, or sysrq key. Use at your own risk; 
+ * reentering NCR5380_print_status seems to have ugly side effects
+ */
+
+void sun3_sun3_debug (void)
+{
+	unsigned long flags;
+	NCR5380_local_declare();
+
+	if (default_instance) {
+			save_flags(flags);
+			cli();
+			NCR5380_print_status(default_instance);
+			restore_flags(flags);
+	}
+#if 0
+	polled_scsi_on = 1;
+#endif
+}
+/*
+ * Helper function for interrupt trouble. More ugly side effects here.
+ */
+
+void scsi_sun3_polled (void)
+{
+	unsigned long flags;
+	NCR5380_local_declare();
+	struct Scsi_Host *instance;
+	
+	instance = default_instance;
+	NCR5380_setup(instance);
+	if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ)
+	{
+		printk("SCSI poll\n");
+		save_flags(flags);
+		cli();
+		sun3scsi_intr(IRQ_SUN3_SCSI, instance, NULL);
+		restore_flags(flags);
+	}
+}
+
+
+#ifdef MODULE
+
+Scsi_Host_Template driver_template = SUN3_NCR5380;
+
+#include "scsi_module.c"
+#endif
diff --git a/drivers/scsi/sun3_scsi.h b/drivers/scsi/sun3_scsi.h
new file mode 100644
index 0000000000000000000000000000000000000000..c677bfbf614bd84b18b81d52be5b037f931b2c44
--- /dev/null
+++ b/drivers/scsi/sun3_scsi.h
@@ -0,0 +1,119 @@
+/*
+ * Sun3 SCSI stuff by Erik Verbruggen (erik@bigmama.xtdnet.nl)
+ *
+ * Adapted from mac_scsinew.h:
+ */
+/*
+ * Cumana Generic NCR5380 driver defines
+ *
+ * Copyright 1993, Drew Eckhardt
+ *	Visionary Computing
+ *	(Unix and Linux consulting and custom programming)
+ *	drew@colorado.edu
+ *      +1 (303) 440-4894
+ *
+ * ALPHA RELEASE 1.
+ *
+ * For more information, please consult
+ *
+ * NCR 5380 Family
+ * SCSI Protocol Controller
+ * Databook
+ *
+ * NCR Microelectronics
+ * 1635 Aeroplaza Drive
+ * Colorado Springs, CO 80916
+ * 1+ (719) 578-3400
+ * 1+ (800) 334-5454
+ */
+
+/*
+ * $Log: cumana_NCR5380.h,v $
+ */
+
+#ifndef SUN3_NCR5380_H
+#define SUN3_NCR5380_H
+
+#define SUN3SCSI_PUBLIC_RELEASE 1
+
+/*
+ * Int: level 2 autovector
+ * IO: type 1, base 0x00140000, 5 bits phys space: A<4..0>
+ */
+#define IRQ_SUN3_SCSI 2
+#define IOBASE_SUN3_SCSI 0x00140000
+
+int sun3scsi_abort (Scsi_Cmnd *);
+int sun3scsi_detect (Scsi_Host_Template *);
+int sun3scsi_release (struct Scsi_Host *);
+const char *sun3scsi_info (struct Scsi_Host *);
+int sun3scsi_reset(Scsi_Cmnd *, unsigned int);
+int sun3scsi_queue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+int sun3scsi_proc_info (char *buffer, char **start, off_t offset,
+			int length, int hostno, int inout);
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef CMD_PER_LUN
+#define CMD_PER_LUN 2
+#endif
+
+#ifndef CAN_QUEUE
+#define CAN_QUEUE 16
+#endif
+
+#ifndef SG_TABLESIZE
+#define SG_TABLESIZE SG_NONE
+#endif
+
+#ifndef USE_TAGGED_QUEUING
+#define	USE_TAGGED_QUEUING 0
+#endif
+
+#include <scsi/scsicam.h>
+
+#define SUN3_NCR5380 {							\
+name:			"Sun3 NCR5380 SCSI",				\
+detect:			sun3scsi_detect,				\
+release:		sun3scsi_release,	/* Release */		\
+info:			sun3scsi_info,					\
+queuecommand:		sun3scsi_queue_command,				\
+abort:			sun3scsi_abort,			 		\
+reset:			sun3scsi_reset,					\
+bios_param:		scsicam_bios_param,	/* biosparam */		\
+can_queue:		CAN_QUEUE,		/* can queue */		\
+this_id:		7,			/* id */		\
+sg_tablesize:		SG_ALL,			/* sg_tablesize */	\
+cmd_per_lun:		CMD_PER_LUN,		/* cmd per lun */	\
+unchecked_isa_dma:	0,			/* unchecked_isa_dma */	\
+use_clustering:		DISABLE_CLUSTERING				\
+	}
+
+#ifndef HOSTS_C
+
+#define NCR5380_implementation_fields \
+    int port, ctrl
+
+#define NCR5380_local_declare() \
+        struct Scsi_Host *_instance
+
+#define NCR5380_setup(instance) \
+        _instance = instance
+
+#define NCR5380_read(reg) sun3scsi_read(_instance, reg)
+#define NCR5380_write(reg, value) sun3scsi_write(_instance, reg, value)
+
+#define NCR5380_intr sun3scsi_intr
+#define NCR5380_queue_command sun3scsi_queue_command
+#define NCR5380_abort sun3scsi_abort
+#define NCR5380_reset sun3scsi_reset
+#define NCR5380_proc_info sun3scsi_proc_info
+
+#define BOARD_NORMAL	0
+#define BOARD_NCR53C400	1
+
+#endif /* ndef HOSTS_C */
+#endif /* SUN3_NCR5380_H */
+
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index 8f163cd8ca75c2cc2d05bbe8480d309673e8b941..51d1cb05ed797aac7de61970a5cc1acfd2cc52e5 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -464,7 +464,7 @@ static int tt_encode_fix( struct fb_fix_screeninfo *fix,
 	int mode;
 
 	strcpy(fix->id,"Atari Builtin");
-	fix->smem_start = real_screen_base;
+	fix->smem_start = (unsigned long)real_screen_base;
 	fix->smem_len = screen_len;
 	fix->type=FB_TYPE_INTERLEAVED_PLANES;
 	fix->type_aux=2;
@@ -797,7 +797,7 @@ static int falcon_encode_fix( struct fb_fix_screeninfo *fix,
 							  struct atafb_par *par )
 {
 	strcpy(fix->id, "Atari Builtin");
-	fix->smem_start = real_screen_base;
+	fix->smem_start = (unsigned long)real_screen_base;
 	fix->smem_len = screen_len;
 	fix->type = FB_TYPE_INTERLEAVED_PLANES;
 	fix->type_aux = 2;
@@ -1760,7 +1760,7 @@ static int stste_encode_fix( struct fb_fix_screeninfo *fix,
 	int mode;
 
 	strcpy(fix->id,"Atari Builtin");
-	fix->smem_start = real_screen_base;
+	fix->smem_start = (unsigned long)real_screen_base;
 	fix->smem_len = screen_len;
 	fix->type = FB_TYPE_INTERLEAVED_PLANES;
 	fix->type_aux = 2;
@@ -2104,7 +2104,7 @@ static int ext_encode_fix( struct fb_fix_screeninfo *fix,
 
 {
 	strcpy(fix->id,"Unknown Extern");
-	fix->smem_start=external_addr;
+	fix->smem_start = (unsigned long)external_addr;
 	fix->smem_len = PAGE_ALIGN(external_len);
 	if (external_depth == 1) {
 		fix->type = FB_TYPE_PACKED_PIXELS;
@@ -2488,7 +2488,7 @@ atafb_set_disp(int con, struct fb_info *info)
 	atafb_get_var(&var, con, info);
 	if (con == -1)
 		con=0;
-	display->screen_base = fix.smem_start;
+	display->screen_base = (void *)fix.smem_start;
 	display->visual = fix.visual;
 	display->type = fix.type;
 	display->type_aux = fix.type_aux;
diff --git a/fs/exec.c b/fs/exec.c
index 44a43b356f90179917ce6430f0726edd39cdaedc..d94f55e5f4b986d896bb308d03f3d85a4c323c83 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -462,6 +462,7 @@ int flush_old_exec(struct linux_binprm * bprm)
 	/*
 	 * Make sure we have a private signal table
 	 */
+	task_lock(current);
 	oldsig = current->sig;
 	retval = make_private_signals();
 	if (retval) goto flush_failed;
@@ -500,6 +501,7 @@ int flush_old_exec(struct linux_binprm * bprm)
 			
 	flush_signal_handlers(current);
 	flush_old_files(current->files);
+	task_unlock(current);
 
 	return 0;
 
@@ -508,6 +510,7 @@ int flush_old_exec(struct linux_binprm * bprm)
 		kfree(current->sig);
 flush_failed:
 	current->sig = oldsig;
+	task_unlock(current);
 	return retval;
 }
 
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
index 356286fb2f277db8eb0b98fa4573a2de021f3594..a582fd5459ae3fd08dc07f00de54063f97b7de8e 100644
--- a/fs/ext2/ioctl.c
+++ b/fs/ext2/ioctl.c
@@ -23,7 +23,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
 	switch (cmd) {
 	case EXT2_IOC_GETFLAGS:
 		flags = inode->u.ext2_i.i_flags & EXT2_FL_USER_VISIBLE;
-		return put_user(inode->u.ext2_i.i_flags, (int *) arg);
+		return put_user(flags, (int *) arg);
 	case EXT2_IOC_SETFLAGS: {
 		unsigned int oldflags;
 
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index 38b59aed767f2bf30b9736e29f45525acafe4dba..28ff91997c612fe933831eb3d94c0bba70dfdd83 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -8,7 +8,7 @@
 # Note 2! The CFLAGS definitions are now in the main makefile.
 
 O_TARGET := proc.o
-O_OBJS   := inode.o root.o base.o generic.o mem.o link.o fd.o array.o \
+O_OBJS   := inode.o root.o base.o generic.o array.o \
 		kmsg.o scsi.o proc_tty.o sysvipc.o proc_misc.o kcore.o
 ifdef CONFIG_OMIRR
 O_OBJS   := $(O_OBJS) omirr.o
diff --git a/fs/proc/array.c b/fs/proc/array.c
index e72203cfae956c1feaf2cd63bd98efe1056819b2..03802b89230edde40cc5155a895d8a6973c9500b 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -70,401 +70,7 @@
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
-
-
-static int open_kcore(struct inode * inode, struct file * filp)
-{
-	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
-}
-
-extern ssize_t read_kcore(struct file *, char *, size_t, loff_t *);
-
-static struct file_operations proc_kcore_operations = {
-	NULL,           /* lseek */
-	read_kcore,
-	NULL,		/* write */
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	NULL,		/* ioctl */
-	NULL,		/* mmap */
-	open_kcore
-};
-
-struct inode_operations proc_kcore_inode_operations = {
-	&proc_kcore_operations,
-};
-
-/*
- * This function accesses profiling information. The returned data is
- * binary: the sampling step and the actual contents of the profile
- * buffer. Use of the program readprofile is recommended in order to
- * get meaningful info out of these data.
- */
-static ssize_t read_profile(struct file *file, char *buf,
-			    size_t count, loff_t *ppos)
-{
-	unsigned long p = *ppos;
-	ssize_t read;
-	char * pnt;
-	unsigned int sample_step = 1 << prof_shift;
-
-	if (p >= (prof_len+1)*sizeof(unsigned int))
-		return 0;
-	if (count > (prof_len+1)*sizeof(unsigned int) - p)
-		count = (prof_len+1)*sizeof(unsigned int) - p;
-	read = 0;
-
-	while (p < sizeof(unsigned int) && count > 0) {
-		put_user(*((char *)(&sample_step)+p),buf);
-		buf++; p++; count--; read++;
-	}
-	pnt = (char *)prof_buffer + p - sizeof(unsigned int);
-	copy_to_user(buf,(void *)pnt,count);
-	read += count;
-	*ppos += read;
-	return read;
-}
-
-/*
- * Writing to /proc/profile resets the counters
- *
- * Writing a 'profiling multiplier' value into it also re-sets the profiling
- * interrupt frequency, on architectures that support this.
- */
-static ssize_t write_profile(struct file * file, const char * buf,
-			     size_t count, loff_t *ppos)
-{
-#ifdef __SMP__
-	extern int setup_profiling_timer (unsigned int multiplier);
-
-	if (count==sizeof(int)) {
-		unsigned int multiplier;
-
-		if (copy_from_user(&multiplier, buf, sizeof(int)))
-			return -EFAULT;
-
-		if (setup_profiling_timer(multiplier))
-			return -EINVAL;
-	}
-#endif
-
-	memset(prof_buffer, 0, prof_len * sizeof(*prof_buffer));
-	return count;
-}
-
-static struct file_operations proc_profile_operations = {
-	NULL,           /* lseek */
-	read_profile,
-	write_profile,
-};
-
-struct inode_operations proc_profile_inode_operations = {
-	&proc_profile_operations,
-};
-
-static struct page * get_phys_addr(struct mm_struct * mm, unsigned long ptr)
-{
-	pgd_t *pgd;
-	pmd_t *pmd;
-	pte_t pte;
-
-	if (ptr >= TASK_SIZE)
-		return 0;
-	pgd = pgd_offset(mm,ptr);
-	if (pgd_none(*pgd))
-		return 0;
-	if (pgd_bad(*pgd)) {
-		pgd_ERROR(*pgd);
-		pgd_clear(pgd);
-		return 0;
-	}
-	pmd = pmd_offset(pgd,ptr);
-	if (pmd_none(*pmd))
-		return 0;
-	if (pmd_bad(*pmd)) {
-		pmd_ERROR(*pmd);
-		pmd_clear(pmd);
-		return 0;
-	}
-	pte = *pte_offset(pmd,ptr);
-	if (!pte_present(pte))
-		return 0;
-	return pte_page(pte);
-}
-
-static int get_array(struct mm_struct *mm, unsigned long start, unsigned long end, char * buffer)
-{
-	struct page *page;
-	unsigned long kaddr;
-	int size = 0, result = 0;
-	char c;
-
-	if (start >= end)
-		return result;
-	for (;;) {
-		page = get_phys_addr(mm, start);
-		if (!page)
-			return result;
-		kaddr = kmap(page, KM_READ) + (start & ~PAGE_MASK);
-		do {
-			c = *(char *) kaddr;
-			if (!c)
-				result = size;
-			if (size < PAGE_SIZE)
-				buffer[size++] = c;
-			else {
-				kunmap(kaddr, KM_READ);
-				return result;
-			}
-			kaddr++;
-			start++;
-			if (!c && start >= end) {
-				kunmap(kaddr, KM_READ);
-				return result;
-			}
-		} while (kaddr & ~PAGE_MASK);
-		kunmap(kaddr, KM_READ);
-	}
-	return result;
-}
-
-static struct mm_struct *get_mm(int pid)
-{
-	struct task_struct *p;
-	struct mm_struct *mm = NULL;
-	
-	read_lock(&tasklist_lock);
-	p = find_task_by_pid(pid);
-	if (p)
-		mm = p->mm;
-	if (mm)
-		atomic_inc(&mm->mm_users);
-	read_unlock(&tasklist_lock);
-	return mm;
-}
-
-
-static int get_env(int pid, char * buffer)
-{
-	struct mm_struct *mm = get_mm(pid);
-	int res = 0;
-	if (mm) {
-		res = get_array(mm, mm->env_start, mm->env_end, buffer);
-		mmput(mm);
-	}
-	return res;
-}
-
-static int get_arg(int pid, char * buffer)
-{
-	struct mm_struct *mm = get_mm(pid);
-	int res = 0;
-	if (mm) {
-		res = get_array(mm, mm->arg_start, mm->arg_end, buffer);
-		mmput(mm);
-	}
-	return res;
-}
-
-/*
- * These bracket the sleeping functions..
- */
-extern void scheduling_functions_start_here(void);
-extern void scheduling_functions_end_here(void);
-#define first_sched	((unsigned long) scheduling_functions_start_here)
-#define last_sched	((unsigned long) scheduling_functions_end_here)
-
-static unsigned long get_wchan(struct task_struct *p)
-{
-	if (!p || p == current || p->state == TASK_RUNNING)
-		return 0;
-#if defined(__i386__)
-	{
-		unsigned long ebp, esp, eip;
-		unsigned long stack_page;
-		int count = 0;
-
-		stack_page = (unsigned long)p;
-		esp = p->thread.esp;
-		if (!stack_page || esp < stack_page || esp > 8188+stack_page)
-			return 0;
-		/* include/asm-i386/system.h:switch_to() pushes ebp last. */
-		ebp = *(unsigned long *) esp;
-		do {
-			if (ebp < stack_page || ebp > 8184+stack_page)
-				return 0;
-			eip = *(unsigned long *) (ebp+4);
-			if (eip < first_sched || eip >= last_sched)
-				return eip;
-			ebp = *(unsigned long *) ebp;
-		} while (count++ < 16);
-	}
-#elif defined(__alpha__)
-	/*
-	 * This one depends on the frame size of schedule().  Do a
-	 * "disass schedule" in gdb to find the frame size.  Also, the
-	 * code assumes that sleep_on() follows immediately after
-	 * interruptible_sleep_on() and that add_timer() follows
-	 * immediately after interruptible_sleep().  Ugly, isn't it?
-	 * Maybe adding a wchan field to task_struct would be better,
-	 * after all...
-	 */
-	{
-	    unsigned long schedule_frame;
-	    unsigned long pc;
-
-	    pc = thread_saved_pc(&p->thread);
-	    if (pc >= first_sched && pc < last_sched) {
-		schedule_frame = ((unsigned long *)p->thread.ksp)[6];
-		return ((unsigned long *)schedule_frame)[12];
-	    }
-	    return pc;
-	}
-#elif defined(__mips__)
-	/*
-	 * The same comment as on the Alpha applies here, too ...
-	 */
-	{
-		unsigned long schedule_frame;
-		unsigned long pc;
-
-		pc = thread_saved_pc(&p->tss);
-		if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
-			schedule_frame = ((unsigned long *)(long)p->tss.reg30)[16];
-			return (unsigned long)((unsigned long *)schedule_frame)[11];
-		}
-		return pc;
-	}
-#elif defined(__mc68000__)
-	{
-	    unsigned long fp, pc;
-	    unsigned long stack_page;
-	    int count = 0;
-
-	    stack_page = (unsigned long)p;
-	    fp = ((struct switch_stack *)p->thread.ksp)->a6;
-	    do {
-		    if (fp < stack_page+sizeof(struct task_struct) ||
-			fp >= 8184+stack_page)
-			    return 0;
-		    pc = ((unsigned long *)fp)[1];
-		/* FIXME: This depends on the order of these functions. */
-		    if (pc < first_sched || pc >= last_sched)
-		      return pc;
-		    fp = *(unsigned long *) fp;
-	    } while (count++ < 16);
-	}
-#elif defined(__powerpc__)
-	{
-		unsigned long ip, sp;
-		unsigned long stack_page = (unsigned long) p;
-		int count = 0;
-
-		sp = p->thread.ksp;
-		do {
-			sp = *(unsigned long *)sp;
-			if (sp < stack_page || sp >= stack_page + 8188)
-				return 0;
-			if (count > 0) {
-				ip = *(unsigned long *)(sp + 4);
-				if (ip < first_sched || ip >= last_sched)
-					return ip;
-			}
-		} while (count++ < 16);
-	}
-#elif defined(__arm__)
-	{
-		unsigned long fp, lr;
-		unsigned long stack_page;
-		int count = 0;
-
-		stack_page = 4096 + (unsigned long)p;
-		fp = get_css_fp(&p->thread);
-		do {
-			if (fp < stack_page || fp > 4092+stack_page)
-				return 0;
-			lr = pc_pointer (((unsigned long *)fp)[-1]);
-			if (lr < first_sched || lr > last_sched)
-				return lr;
-			fp = *(unsigned long *) (fp - 12);
-		} while (count ++ < 16);
-	}
-#elif defined (__sparc__)
-	{
-		unsigned long pc, fp, bias = 0;
-		unsigned long task_base = (unsigned long) p;
-		struct reg_window *rw;
-		int count = 0;
-
-#ifdef __sparc_v9__
-		bias = STACK_BIAS;
-#endif
-		fp = p->thread.ksp + bias;
-		do {
-			/* Bogus frame pointer? */
-			if (fp < (task_base + sizeof(struct task_struct)) ||
-			    fp >= (task_base + (2 * PAGE_SIZE)))
-				break;
-			rw = (struct reg_window *) fp;
-			pc = rw->ins[7];
-			if (pc < first_sched || pc >= last_sched)
-				return pc;
-			fp = rw->ins[6] + bias;
-		} while (++count < 16);
-	}
-#endif
-
-	return 0;
-}
-
-#if defined(__i386__)
-# define KSTK_EIP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1019])
-# define KSTK_ESP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
-#elif defined(__alpha__)
-  /*
-   * See arch/alpha/kernel/ptrace.c for details.
-   */
-# define PT_REG(reg)		(PAGE_SIZE - sizeof(struct pt_regs)	\
-				 + (long)&((struct pt_regs *)0)->reg)
-# define KSTK_EIP(tsk) \
-    (*(unsigned long *)(PT_REG(pc) + PAGE_SIZE + (unsigned long)(tsk)))
-# define KSTK_ESP(tsk)	((tsk) == current ? rdusp() : (tsk)->thread.usp)
-#elif defined(__arm__)
-# ifdef CONFIG_CPU_26
-#  define KSTK_EIP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
-#  define KSTK_ESP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1020])
-# else
-#  define KSTK_EIP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1021])
-#  define KSTK_ESP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1019])
-# endif
-#elif defined(__mc68000__)
-#define	KSTK_EIP(tsk)	\
-    ({			\
-	unsigned long eip = 0;	 \
-	if ((tsk)->thread.esp0 > PAGE_SIZE && \
-	    MAP_NR((tsk)->thread.esp0) < max_mapnr) \
-	      eip = ((struct pt_regs *) (tsk)->thread.esp0)->pc; \
-	eip; })
-#define	KSTK_ESP(tsk)	((tsk) == current ? rdusp() : (tsk)->thread.usp)
-#elif defined(__powerpc__)
-#define KSTK_EIP(tsk)	((tsk)->thread.regs->nip)
-#define KSTK_ESP(tsk)	((tsk)->thread.regs->gpr[1])
-#elif defined (__sparc_v9__)
-# define KSTK_EIP(tsk)  ((tsk)->thread.kregs->tpc)
-# define KSTK_ESP(tsk)  ((tsk)->thread.kregs->u_regs[UREG_FP])
-#elif defined(__sparc__)
-# define KSTK_EIP(tsk)  ((tsk)->thread.kregs->pc)
-# define KSTK_ESP(tsk)  ((tsk)->thread.kregs->u_regs[UREG_FP])
-#elif defined(__mips__)
-# define PT_REG(reg)		((long)&((struct pt_regs *)0)->reg \
-				 - sizeof(struct pt_regs))
-#define KSTK_TOS(tsk) ((unsigned long)(tsk) + KERNEL_STACK_SIZE - 32)
-# define KSTK_EIP(tsk)	(*(unsigned long *)(KSTK_TOS(tsk) + PT_REG(cp0_epc)))
-# define KSTK_ESP(tsk)	(*(unsigned long *)(KSTK_TOS(tsk) + PT_REG(regs[29])))
-#elif defined(__sh__)
-# define KSTK_EIP(tsk)  ((tsk)->thread.pc)
-# define KSTK_ESP(tsk)  ((tsk)->thread.sp)
-#endif
+#include <asm/processor.h>
 
 /* Gcc optimizes away "strlen(x)" for constant x */
 #define ADDBUF(buffer, string) \
@@ -654,36 +260,27 @@ extern inline char *task_cap(struct task_struct *p, char *buffer)
 }
 
 
-static int get_status(int pid, char * buffer)
+/* task is locked, so we are safe here */
+
+int proc_pid_status(struct task_struct *task, char * buffer)
 {
 	char * orig = buffer;
-	struct task_struct *tsk;
-	struct mm_struct *mm = NULL;
+	struct mm_struct *mm = task->mm;
 
-	read_lock(&tasklist_lock);
-	tsk = find_task_by_pid(pid);
-	if (tsk)
-		mm = tsk->mm;
-	if (mm)
-		atomic_inc(&mm->mm_users);
-	read_unlock(&tasklist_lock);	/* FIXME!! This should be done after the last use */
-	if (!tsk)
-		return 0;
-	buffer = task_name(tsk, buffer);
-	buffer = task_state(tsk, buffer);
+	buffer = task_name(task, buffer);
+	buffer = task_state(task, buffer);
 	if (mm)
 		buffer = task_mem(mm, buffer);
-	buffer = task_sig(tsk, buffer);
-	buffer = task_cap(tsk, buffer);
-	if (mm)
-		mmput(mm);
+	buffer = task_sig(task, buffer);
+	buffer = task_cap(task, buffer);
 	return buffer - orig;
 }
 
-static int get_stat(int pid, char * buffer)
+/* task is locked, so we are safe here */
+
+int proc_pid_stat(struct task_struct *task, char * buffer)
 {
-	struct task_struct *tsk;
-	struct mm_struct *mm = NULL;
+	struct mm_struct *mm = task->mm;
 	unsigned long vsize, eip, esp, wchan;
 	long priority, nice;
 	int tty_pgrp;
@@ -691,16 +288,7 @@ static int get_stat(int pid, char * buffer)
 	char state;
 	int res;
 
-	read_lock(&tasklist_lock);
-	tsk = find_task_by_pid(pid);
-	if (tsk)
-		mm = tsk->mm;
-	if (mm)
-		atomic_inc(&mm->mm_users);
-	read_unlock(&tasklist_lock);	/* FIXME!! This should be done after the last use */
-	if (!tsk)
-		return 0;
-	state = *get_task_state(tsk);
+	state = *get_task_state(task);
 	vsize = eip = esp = 0;
 	if (mm) {
 		struct vm_area_struct *vma;
@@ -710,55 +298,55 @@ static int get_stat(int pid, char * buffer)
 			vsize += vma->vm_end - vma->vm_start;
 			vma = vma->vm_next;
 		}
-		eip = KSTK_EIP(tsk);
-		esp = KSTK_ESP(tsk);
+		eip = KSTK_EIP(task);
+		esp = KSTK_ESP(task);
 		up(&mm->mmap_sem);
 	}
 
-	wchan = get_wchan(tsk);
+	wchan = get_wchan(task);
 
-	collect_sigign_sigcatch(tsk, &sigign, &sigcatch);
+	collect_sigign_sigcatch(task, &sigign, &sigcatch);
 
-	if (tsk->tty)
-		tty_pgrp = tsk->tty->pgrp;
+	if (task->tty)
+		tty_pgrp = task->tty->pgrp;
 	else
 		tty_pgrp = -1;
 
 	/* scale priority and nice values from timeslices to -20..20 */
 	/* to make it look like a "normal" Unix priority/nice value  */
-	priority = tsk->counter;
+	priority = task->counter;
 	priority = 20 - (priority * 10 + DEF_PRIORITY / 2) / DEF_PRIORITY;
-	nice = tsk->priority;
+	nice = task->priority;
 	nice = 20 - (nice * 20 + DEF_PRIORITY / 2) / DEF_PRIORITY;
 
 	res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
 %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu \
 %lu %lu %lu %lu %lu %lu %lu %lu %d %d\n",
-		pid,
-		tsk->comm,
+		task->pid,
+		task->comm,
 		state,
-		tsk->p_pptr->pid,
-		tsk->pgrp,
-		tsk->session,
-	        tsk->tty ? kdev_t_to_nr(tsk->tty->device) : 0,
+		task->p_pptr->pid,
+		task->pgrp,
+		task->session,
+	        task->tty ? kdev_t_to_nr(task->tty->device) : 0,
 		tty_pgrp,
-		tsk->flags,
-		tsk->min_flt,
-		tsk->cmin_flt,
-		tsk->maj_flt,
-		tsk->cmaj_flt,
-		tsk->times.tms_utime,
-		tsk->times.tms_stime,
-		tsk->times.tms_cutime,
-		tsk->times.tms_cstime,
+		task->flags,
+		task->min_flt,
+		task->cmin_flt,
+		task->maj_flt,
+		task->cmaj_flt,
+		task->times.tms_utime,
+		task->times.tms_stime,
+		task->times.tms_cutime,
+		task->times.tms_cstime,
 		priority,
 		nice,
 		0UL /* removed */,
-		tsk->it_real_value,
-		tsk->start_time,
+		task->it_real_value,
+		task->start_time,
 		vsize,
 		mm ? mm->rss : 0, /* you might want to shift this left 3 */
-		tsk->rlim ? tsk->rlim[RLIMIT_RSS].rlim_cur : 0,
+		task->rlim ? task->rlim[RLIMIT_RSS].rlim_cur : 0,
 		mm ? mm->start_code : 0,
 		mm ? mm->end_code : 0,
 		mm ? mm->start_stack : 0,
@@ -768,17 +356,15 @@ static int get_stat(int pid, char * buffer)
 		 * It must be decimal for Linux 2.0 compatibility.
 		 * Use /proc/#/status for real-time signals.
 		 */
-		tsk->signal .sig[0] & 0x7fffffffUL,
-		tsk->blocked.sig[0] & 0x7fffffffUL,
+		task->signal .sig[0] & 0x7fffffffUL,
+		task->blocked.sig[0] & 0x7fffffffUL,
 		sigign      .sig[0] & 0x7fffffffUL,
 		sigcatch    .sig[0] & 0x7fffffffUL,
 		wchan,
-		tsk->nswap,
-		tsk->cnswap,
-		tsk->exit_signal,
-		tsk->processor);
-	if (mm)
-		mmput(mm);
+		task->nswap,
+		task->cnswap,
+		task->exit_signal,
+		task->processor);
 	return res;
 }
 		
@@ -855,9 +441,9 @@ static void statm_pgd_range(pgd_t * pgd, unsigned long address, unsigned long en
 	}
 }
 
-static int get_statm(int pid, char * buffer)
+int proc_pid_statm(struct task_struct *task, char * buffer)
 {
-	struct mm_struct *mm = get_mm(pid);
+	struct mm_struct *mm = task->mm;
 	int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
 
 	if (mm) {
@@ -884,7 +470,6 @@ static int get_statm(int pid, char * buffer)
 			vma = vma->vm_next;
 		}
 		up(&mm->mmap_sem);
-		mmput(mm);
 	}
 	return sprintf(buffer,"%d %d %d %d %d %d %d\n",
 		       size, resident, share, trs, lrs, drs, dt);
@@ -923,10 +508,10 @@ static int get_statm(int pid, char * buffer)
 #define MAPS_LINE_MAX	MAPS_LINE_MAX8
 
 
-static ssize_t read_maps (int pid, struct file * file, char * buf,
+ssize_t proc_pid_read_maps (struct task_struct *task, struct file * file, char * buf,
 			  size_t count, loff_t *ppos)
 {
-	struct task_struct *p;
+	struct mm_struct *mm = task->mm;
 	struct vm_area_struct * map, * next;
 	char * destptr = buf, * buffer;
 	loff_t lineno;
@@ -942,25 +527,19 @@ static ssize_t read_maps (int pid, struct file * file, char * buf,
 	if (!buffer)
 		goto out;
 
-	retval = -EINVAL;
-	read_lock(&tasklist_lock);
-	p = find_task_by_pid(pid);
-	read_unlock(&tasklist_lock);	/* FIXME!! This should be done after the last use */
-	if (!p)
-		goto freepage_out;
-
-	if (!p->mm || count == 0)
+	if (!mm || count == 0)
 		goto getlen_out;
 
 	/* Check whether the mmaps could change if we sleep */
-	volatile_task = (p != current || atomic_read(&p->mm->mm_users) > 1);
+	volatile_task = (task != current || atomic_read(&mm->mm_users) > 1);
 
 	/* decode f_pos */
 	lineno = *ppos >> MAPS_LINE_SHIFT;
 	column = *ppos & (MAPS_LINE_LENGTH-1);
 
 	/* quickly go to line lineno */
-	for (map = p->mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++)
+	down(&mm->mmap_sem);
+	for (map = mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++)
 		continue;
 
 	for ( ; map ; map = next ) {
@@ -1019,7 +598,9 @@ static ssize_t read_maps (int pid, struct file * file, char * buf,
 		i = len-column;
 		if (i > count)
 			i = count;
+		up(&mm->mmap_sem);
 		copy_to_user(destptr, line+column, i); /* may have slept */
+		down(&mm->mmap_sem);
 		destptr += i;
 		count   -= i;
 		column  += i;
@@ -1038,246 +619,34 @@ static ssize_t read_maps (int pid, struct file * file, char * buf,
 		if (volatile_task)
 			break;
 	}
+	up(&mm->mmap_sem);
 
 	/* encode f_pos */
 	*ppos = (lineno << MAPS_LINE_SHIFT) + column;
 
 getlen_out:
 	retval = destptr - buf;
-
-freepage_out:
 	free_page((unsigned long)buffer);
 out:
 	return retval;
 }
 
 #ifdef __SMP__
-static int get_pidcpu(int pid, char * buffer)
+int proc_pid_cpu(struct task_struct *task, char * buffer)
 {
-	struct task_struct * tsk = current ;
 	int i, len;
 
-	read_lock(&tasklist_lock);
-	if (pid != tsk->pid)
-		tsk = find_task_by_pid(pid);
-	read_unlock(&tasklist_lock);	/* FIXME!! This should be done after the last use */
-
-	if (tsk == NULL)
-		return 0;
-
 	len = sprintf(buffer,
 		"cpu  %lu %lu\n",
-		tsk->times.tms_utime,
-		tsk->times.tms_stime);
+		task->times.tms_utime,
+		task->times.tms_stime);
 		
 	for (i = 0 ; i < smp_num_cpus; i++)
 		len += sprintf(buffer + len, "cpu%d %lu %lu\n",
 			i,
-			tsk->per_cpu_utime[cpu_logical_map(i)],
-			tsk->per_cpu_stime[cpu_logical_map(i)]);
+			task->per_cpu_utime[cpu_logical_map(i)],
+			task->per_cpu_stime[cpu_logical_map(i)]);
 
 	return len;
 }
 #endif
-
-static int process_unauthorized(int type, int pid)
-{
-	struct task_struct *p;
-	uid_t euid=0;	/* Save the euid keep the lock short */
-	int ok = 0;
-		
-	read_lock(&tasklist_lock);
-	
-	/*
-	 *	Grab the lock, find the task, save the uid and
-	 *	check it has an mm still (ie its not dead)
-	 */
-	
-	p = find_task_by_pid(pid);
-	if (p) {
-		euid=p->euid;
-		ok = p->dumpable;
-		if(!cap_issubset(p->cap_permitted, current->cap_permitted))
-			ok=0;			
-	}
-		
-	read_unlock(&tasklist_lock);
-
-	if (!p)
-		return 1;
-
-	switch(type) {
-		case PROC_PID_STATUS:
-		case PROC_PID_STATM:
-		case PROC_PID_STAT:
-		case PROC_PID_MAPS:
-		case PROC_PID_CMDLINE:
-		case PROC_PID_CPU:
-			return 0;	
-	}
-	if(capable(CAP_DAC_OVERRIDE) || (current->fsuid == euid && ok))
-		return 0;
-	return 1;
-}
-
-
-static inline int get_process_array(char * page, int pid, int type)
-{
-	switch (type) {
-		case PROC_PID_STATUS:
-			return get_status(pid, page);
-		case PROC_PID_ENVIRON:
-			return get_env(pid, page);
-		case PROC_PID_CMDLINE:
-			return get_arg(pid, page);
-		case PROC_PID_STAT:
-			return get_stat(pid, page);
-		case PROC_PID_STATM:
-			return get_statm(pid, page);
-#ifdef __SMP__
-		case PROC_PID_CPU:
-			return get_pidcpu(pid, page);
-#endif
-	}
-	return -EBADF;
-}
-
-#define PROC_BLOCK_SIZE	(3*1024)		/* 4K page size but our output routines use some slack for overruns */
-
-static ssize_t array_read(struct file * file, char * buf,
-			  size_t count, loff_t *ppos)
-{
-	struct inode * inode = file->f_dentry->d_inode;
-	unsigned long page;
-	char *start;
-	ssize_t length;
-	ssize_t end;
-	unsigned int type, pid;
-	struct proc_dir_entry *dp;
-
-	if (count > PROC_BLOCK_SIZE)
-		count = PROC_BLOCK_SIZE;
-	if (!(page = __get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
-	type = inode->i_ino;
-	pid = type >> 16;
-	type &= 0x0000ffff;
-	start = NULL;
-	dp = (struct proc_dir_entry *) inode->u.generic_ip;
-
-	if (!pid) {	/* can't happen */
-		free_page(page);
-		return -EBADF;
-	}
-	
-	if (process_unauthorized(type, pid)) {
-		free_page(page);
-		return -EIO;
-	}
-	
-	length = get_process_array((char *) page, pid, type);
-	if (length < 0) {
-		free_page(page);
-		return length;
-	}
-	/* Static 4kB (or whatever) block capacity */
-	if (*ppos >= length) {
-		free_page(page);
-		return 0;
-	}
-	if (count + *ppos > length)
-		count = length - *ppos;
-	end = count + *ppos;
-	copy_to_user(buf, (char *) page + *ppos, count);
-	*ppos = end;
-	free_page(page);
-	return count;
-}
-
-static struct file_operations proc_array_operations = {
-	NULL,		/* array_lseek */
-	array_read,
-	NULL,		/* array_write */
-	NULL,		/* array_readdir */
-	NULL,		/* array_poll */
-	NULL,		/* array_ioctl */
-	NULL,		/* mmap */
-	NULL,		/* no special open code */
-	NULL,		/* flush */
-	NULL,		/* no special release code */
-	NULL		/* can't fsync */
-};
-
-struct inode_operations proc_array_inode_operations = {
-	&proc_array_operations,	/* default base directory 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,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* flushpage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL,			/* smap */
-	NULL			/* revalidate */
-};
-
-static ssize_t arraylong_read(struct file * file, char * buf,
-			      size_t count, loff_t *ppos)
-{
-	struct inode * inode = file->f_dentry->d_inode;
-	unsigned int pid = inode->i_ino >> 16;
-	unsigned int type = inode->i_ino & 0x0000ffff;
-
-	switch (type) {
-		case PROC_PID_MAPS:
-			return read_maps(pid, file, buf, count, ppos);
-	}
-	return -EINVAL;
-}
-
-static struct file_operations proc_arraylong_operations = {
-	NULL,		/* array_lseek */
-	arraylong_read,
-	NULL,		/* array_write */
-	NULL,		/* array_readdir */
-	NULL,		/* array_poll */
-	NULL,		/* array_ioctl */
-	NULL,		/* mmap */
-	NULL,		/* no special open code */
-	NULL,		/* flush */
-	NULL,		/* no special release code */
-	NULL		/* can't fsync */
-};
-
-struct inode_operations proc_arraylong_inode_operations = {
-	&proc_arraylong_operations,	/* default base directory 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,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* flushpage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL,			/* smap */
-	NULL			/* revalidate */
-};
diff --git a/fs/proc/base.c b/fs/proc/base.c
index f0a0febf8860eb170128251ea2a1250e57817ad4..658da356237b1b23502c8dcae2098c31587a16d1 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -14,28 +14,328 @@
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/init.h>
+#include <linux/file.h>
 
-static struct file_operations proc_base_operations = {
-	NULL,			/* lseek - default */
-	NULL,			/* read - bad */
-	NULL,			/* write - bad */
-	proc_readdir,		/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	NULL			/* can't fsync */
+#define fake_ino(pid,ino) (((pid)<<16)|(ino))
+
+ssize_t proc_pid_read_maps(struct task_struct*,struct file*,char*,size_t,loff_t*);
+int proc_pid_stat(struct task_struct*,char*);
+int proc_pid_status(struct task_struct*,char*);
+int proc_pid_statm(struct task_struct*,char*);
+int proc_pid_cpu(struct task_struct*,char*);
+
+static struct dentry *proc_fd_link(struct inode *inode)
+{
+	if (inode->u.proc_i.file)
+		return dget(inode->u.proc_i.file->f_dentry);
+	return NULL;
+}
+
+static struct dentry *proc_exe_link(struct inode *inode)
+{
+	struct mm_struct * mm;
+	struct vm_area_struct * vma;
+	struct dentry *result = NULL;
+	struct task_struct *task = inode->u.proc_i.task;
+
+	if (!task_lock(task))
+		return NULL;
+	mm = task->mm;
+	if (!mm)
+		goto out;
+	down(&mm->mmap_sem);
+	vma = mm->mmap;
+	while (vma) {
+		if ((vma->vm_flags & VM_EXECUTABLE) && 
+		    vma->vm_file) {
+			result = dget(vma->vm_file->f_dentry);
+			break;
+		}
+		vma = vma->vm_next;
+	}
+	up(&mm->mmap_sem);
+out:
+	task_unlock(task);
+	return result;
+}
+
+static struct dentry *proc_cwd_link(struct inode *inode)
+{
+	struct dentry *result = NULL;
+	if (task_lock(inode->u.proc_i.task)) {
+		struct fs_struct *fs = inode->u.proc_i.task->fs;
+		if (fs)
+			result = dget(fs->pwd);
+		task_unlock(inode->u.proc_i.task);
+	}
+	return result;
+}
+
+static struct dentry *proc_root_link(struct inode *inode)
+{
+	struct dentry *result = NULL;
+	if (task_lock(inode->u.proc_i.task)) {
+		struct fs_struct *fs = inode->u.proc_i.task->fs;
+		if (fs)
+			result = dget(fs->root);
+		task_unlock(inode->u.proc_i.task);
+	}
+	return result;
+}
+
+/* task is locked and can't drop mm, so we are safe */
+
+static int proc_pid_environ(struct task_struct *task, char * buffer)
+{
+	struct mm_struct *mm = task->mm;
+	int res = 0;
+	if (mm)
+		res = access_process_vm(task, mm->env_start, buffer,
+					mm->env_end - mm->env_start, 0);
+	return res;
+}
+
+/* task is locked and can't drop mm, so we are safe */
+
+static int proc_pid_cmdline(struct task_struct *task, char * buffer)
+{
+	struct mm_struct *mm = task->mm;
+	int res = 0;
+	if (mm)
+		res = access_process_vm(task, mm->arg_start, buffer,
+					mm->arg_end - mm->arg_start, 0);
+	return res;
+}
+
+/************************************************************************/
+/*                       Here the fs part begins                        */
+/************************************************************************/
+
+/* permission checks */
+
+static int standard_permission(struct inode *inode, int mask)
+{
+	int mode = inode->i_mode;
+
+	if ((mask & S_IWOTH) && IS_RDONLY(inode) &&
+	    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+		return -EROFS; /* Nobody gets write access to a read-only fs */
+	else if ((mask & S_IWOTH) && IS_IMMUTABLE(inode))
+		return -EACCES; /* Nobody gets write access to an immutable file */
+	else if (current->fsuid == inode->i_uid)
+		mode >>= 6;
+	else if (in_group_p(inode->i_gid))
+		mode >>= 3;
+	if (((mode & mask & S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE))
+		return 0;
+	/* read and search access */
+	if ((mask == S_IROTH) ||
+	    (S_ISDIR(mode)  && !(mask & ~(S_IROTH | S_IXOTH))))
+		if (capable(CAP_DAC_READ_SEARCH))
+			return 0;
+	return -EACCES;
+}
+
+static int proc_permission(struct inode *inode, int mask)
+{
+	struct dentry *de, *base, *root;
+	struct super_block *our_sb, *sb, *below;
+
+	if (standard_permission(inode, mask) != 0)
+		return -EACCES;
+
+	base = current->fs->root;
+	de = root = proc_root_link(inode); /* Ewww... */
+
+	if (!de)
+		return -ENOENT;
+
+	our_sb = base->d_inode->i_sb;
+	sb = de->d_inode->i_sb;
+	while (sb != our_sb) {
+		de = sb->s_root->d_covers;
+		below = de->d_inode->i_sb;
+		if (sb == below)
+			goto out;
+		sb = below;
+	}
+
+	if (!is_subdir(de, base))
+		goto out;
+
+	dput(root);
+	return 0;
+out:
+	dput(root);
+	return -EACCES;
+}
+
+static ssize_t pid_maps_read(struct file * file, char * buf,
+			      size_t count, loff_t *ppos)
+{
+	struct inode * inode = file->f_dentry->d_inode;
+	struct task_struct *task = inode->u.proc_i.task;
+	ssize_t res;
+
+	if (!task_lock(task))
+		return -EIO;
+	res = proc_pid_read_maps(task, file, buf, count, ppos);
+	task_unlock(task);
+	return res;
+}
+
+static struct file_operations proc_maps_operations = {
+	NULL,		/* array_lseek */
+	pid_maps_read,
 };
 
-/*
- * proc directories can do almost nothing..
- */
-static struct inode_operations proc_base_inode_operations = {
-	&proc_base_operations,	/* default base directory file-ops */
+struct inode_operations proc_maps_inode_operations = {
+	&proc_maps_operations,	/* default base directory file-ops */
+};
+
+#define PROC_BLOCK_SIZE	(3*1024)		/* 4K page size but our output routines use some slack for overruns */
+
+static ssize_t proc_info_read(struct file * file, char * buf,
+			  size_t count, loff_t *ppos)
+{
+	struct inode * inode = file->f_dentry->d_inode;
+	unsigned long page;
+	ssize_t length;
+	ssize_t end;
+	struct task_struct *task = inode->u.proc_i.task;
+
+	if (count > PROC_BLOCK_SIZE)
+		count = PROC_BLOCK_SIZE;
+	if (!(page = __get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+
+	if (!task_lock(task)) {
+		free_page(page);
+		return -EIO;
+	}
+	
+	length = inode->u.proc_i.op.proc_read(task, (char*)page);
+
+	task_unlock(task);
+
+	if (length < 0) {
+		free_page(page);
+		return length;
+	}
+	/* Static 4kB (or whatever) block capacity */
+	if (*ppos >= length) {
+		free_page(page);
+		return 0;
+	}
+	if (count + *ppos > length)
+		count = length - *ppos;
+	end = count + *ppos;
+	copy_to_user(buf, (char *) page + *ppos, count);
+	*ppos = end;
+	free_page(page);
+	return count;
+}
+
+static struct file_operations proc_info_file_operations = {
+    NULL,			/* lseek   */
+    proc_info_read,		/* read	   */
+};
+
+struct inode_operations proc_info_inode_operations = {
+	&proc_info_file_operations,  /* default proc file-ops */
+};
+
+#define MAY_PTRACE(p) \
+(p==current||(p->p_pptr==current&&(p->flags&PF_PTRACED)&&p->state==TASK_STOPPED))
+
+static ssize_t mem_read(struct file * file, char * buf,
+			size_t count, loff_t *ppos)
+{
+	struct task_struct *task = file->f_dentry->d_inode->u.proc_i.task;
+	char *page;
+	unsigned long src = *ppos;
+	int copied = 0;
+
+	if (!MAY_PTRACE(task))
+		return -ESRCH;
+
+	page = (char *)__get_free_page(GFP_USER);
+	if (!page)
+		return -ENOMEM;
+
+	while (count > 0) {
+		int this_len, retval;
+
+		this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+		retval = access_process_vm(task, src, page, this_len, 0);
+		if (!retval) {
+			if (!copied)
+				copied = -EIO;
+			break;
+		}
+		if (copy_to_user(buf, page, retval)) {
+			copied = -EFAULT;
+			break;
+		}
+		copied += retval;
+		src += retval;
+		buf += retval;
+		count -= retval;
+	}
+	*ppos = src;
+	free_page((unsigned long) page);
+	return copied;
+}
+
+static ssize_t mem_write(struct file * file, const char * buf,
+			 size_t count, loff_t *ppos)
+{
+	int copied = 0;
+	char *page;
+	struct task_struct *task = file->f_dentry->d_inode->u.proc_i.task;
+	unsigned long dst = *ppos;
+
+	if (!MAY_PTRACE(task))
+		return -ESRCH;
+
+	page = (char *)__get_free_page(GFP_USER);
+	if (!page)
+		return -ENOMEM;
+
+	while (count > 0) {
+		int this_len, retval;
+
+		this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+		if (copy_from_user(page, buf, this_len)) {
+			copied = -EFAULT;
+			break;
+		}
+		retval = access_process_vm(task, dst, page, this_len, 1);
+		if (!retval) {
+			if (!copied)
+				copied = -EIO;
+			break;
+		}
+		copied += retval;
+		buf += retval;
+		dst += retval;
+		count -= retval;			
+	}
+	*ppos = dst;
+	free_page((unsigned long) page);
+	return copied;
+}
+
+static struct file_operations proc_mem_operations = {
+	NULL,		/* lseek - default */
+	mem_read,
+	mem_write,
+};
+
+static struct inode_operations proc_mem_inode_operations = {
+	&proc_mem_operations,	/* default base directory file-ops */
 	NULL,			/* create */
-	proc_lookup,		/* lookup */
+	NULL,			/* lookup */
 	NULL,			/* link */
 	NULL,			/* unlink */
 	NULL,			/* symlink */
@@ -50,161 +350,576 @@ static struct inode_operations proc_base_inode_operations = {
 	NULL,			/* writepage */
 	NULL,			/* flushpage */
 	NULL,			/* truncate */
-	NULL,			/* permission */
+	proc_permission,	/* permission */
 	NULL,			/* smap */
 	NULL			/* revalidate */
 };
 
-/*
- * The fill argument is non-zero when the inode is being filled ...
- * we don't need to do anything when it's being deleted.
- */
-static void proc_pid_fill_inode(struct inode * inode, int fill)
+static struct dentry * proc_pid_follow_link(struct dentry *dentry,
+					struct dentry *base,
+					unsigned int follow)
 {
-	struct task_struct *p;
-	int pid = inode->i_ino >> 16;
-	int ino = inode->i_ino & 0xffff;
+	struct inode *inode = dentry->d_inode;
+	struct dentry * result;
+	int error;
 
-	read_lock(&tasklist_lock);
-	if (fill && (p = find_task_by_pid(pid)) != NULL) {
-		uid_t uid = 0;
-		gid_t gid = 0;
-		if (p->dumpable || ino == PROC_PID_INO) {
-			uid = p->euid;
-			gid = p->egid;
-		}
-		inode->i_uid = uid;
-		inode->i_gid = gid;
+	/* We don't need a base pointer in the /proc filesystem */
+	dput(base);
+
+	error = proc_permission(inode, MAY_EXEC);
+	result = ERR_PTR(error);
+	if (error)
+		goto out;
+
+	result = inode->u.proc_i.op.proc_get_link(inode);
+out:
+	if (!result)
+		result = ERR_PTR(-ENOENT);
+	return result;
+}
+
+static int do_proc_readlink(struct dentry *dentry, char * buffer, int buflen)
+{
+	struct inode * inode;
+	char * tmp = (char*)__get_free_page(GFP_KERNEL), *path, *pattern;
+	int len;
+
+	if (!tmp)
+		return -ENOMEM;
+		
+	/* Check for special dentries.. */
+	pattern = NULL;
+	inode = dentry->d_inode;
+	if (inode && IS_ROOT(dentry)) {
+		if (S_ISSOCK(inode->i_mode))
+			pattern = "socket:[%lu]";
+		if (S_ISFIFO(inode->i_mode))
+			pattern = "pipe:[%lu]";
 	}
-	read_unlock(&tasklist_lock);
+	
+	if (pattern) {
+		len = sprintf(tmp, pattern, inode->i_ino);
+		path = tmp;
+	} else {
+		path = d_path(dentry, tmp, PAGE_SIZE);
+		len = tmp + PAGE_SIZE - 1 - path;
+	}
+
+	if (len < buflen)
+		buflen = len;
+	copy_to_user(buffer, path, buflen);
+	free_page((unsigned long)tmp);
+	return buflen;
 }
 
-/*
- * This is really a pseudo-entry, and only links
- * backwards to the parent with no link from the
- * root directory to this. This way we can have just
- * one entry for every /proc/<pid>/ directory.
- */
-struct proc_dir_entry proc_pid = {
-	PROC_PID_INO, 5, "<pid>",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
-	0, &proc_base_inode_operations,
-	NULL, proc_pid_fill_inode,
-	NULL, &proc_root, NULL
-};
-
-static struct proc_dir_entry proc_pid_status = {
-	PROC_PID_STATUS, 6, "status",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations,
-	NULL, proc_pid_fill_inode,
-};
-static struct proc_dir_entry proc_pid_mem = {
-	PROC_PID_MEM, 3, "mem",
-	S_IFREG | S_IRUSR | S_IWUSR, 1, 0, 0,
-	0, &proc_mem_inode_operations,
-	NULL, proc_pid_fill_inode,
-};
-static struct proc_dir_entry proc_pid_cwd = {
-	PROC_PID_CWD, 3, "cwd",
-	S_IFLNK | S_IRWXU, 1, 0, 0,
-	0, &proc_link_inode_operations,
-	NULL, proc_pid_fill_inode,
-};
-static struct proc_dir_entry proc_pid_root = {
-	PROC_PID_ROOT, 4, "root",
-	S_IFLNK | S_IRWXU, 1, 0, 0,
-	0, &proc_link_inode_operations,
-	NULL, proc_pid_fill_inode,
-};
-static struct proc_dir_entry proc_pid_exe = {
-	PROC_PID_EXE, 3, "exe",
-	S_IFLNK | S_IRWXU, 1, 0, 0,
-	0, &proc_link_inode_operations,
-	NULL, proc_pid_fill_inode,
-};
-static struct proc_dir_entry proc_pid_fd = {
-	PROC_PID_FD, 2, "fd",
-	S_IFDIR | S_IRUSR | S_IXUSR, 2, 0, 0,
-	0, &proc_fd_inode_operations,
-	NULL, proc_pid_fill_inode,
-};
-static struct proc_dir_entry proc_pid_environ = {
-	PROC_PID_ENVIRON, 7, "environ",
-	S_IFREG | S_IRUSR, 1, 0, 0,
-	0, &proc_array_inode_operations,
-	NULL, proc_pid_fill_inode,
-};
-static struct proc_dir_entry proc_pid_cmdline = {
-	PROC_PID_CMDLINE, 7, "cmdline",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations,
-	NULL, proc_pid_fill_inode,
-};
-static struct proc_dir_entry proc_pid_stat = {
-	PROC_PID_STAT, 4, "stat",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations,
-	NULL, proc_pid_fill_inode,
-};
-static struct proc_dir_entry proc_pid_statm = {
-	PROC_PID_STATM, 5, "statm",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations,
-	NULL, proc_pid_fill_inode,
-};
-static struct proc_dir_entry proc_pid_maps = {
-	PROC_PID_MAPS, 4, "maps",
-	S_IFIFO | S_IRUGO, 1, 0, 0,
-	0, &proc_arraylong_inode_operations,
-	NULL, proc_pid_fill_inode,
+static int proc_pid_readlink(struct dentry * dentry, char * buffer, int buflen)
+{
+	int error;
+	struct inode *inode = dentry->d_inode;
+
+	error = proc_permission(inode, MAY_EXEC);
+	if (error)
+		goto out;
+
+	dentry = inode->u.proc_i.op.proc_get_link(inode);
+	error = -ENOENT;
+	if (!dentry)
+		goto out;
+
+	error = PTR_ERR(dentry);
+	if (IS_ERR(dentry))
+		goto out;
+
+	error = do_proc_readlink(dentry, buffer, buflen);
+	dput(dentry);
+out:
+	return error;
+}
+
+static struct inode_operations proc_pid_link_inode_operations = {
+	NULL,			/* file-operations */
+	NULL,			/* create */
+	NULL,			/* lookup */
+	NULL,			/* link */
+	NULL,			/* unlink */
+	NULL,			/* symlink */
+	NULL,			/* mkdir */
+	NULL,			/* rmdir */
+	NULL,			/* mknod */
+	NULL,			/* rename */
+	proc_pid_readlink,	/* readlink */
+	proc_pid_follow_link,	/* follow_link */
 };
 
-#if CONFIG_AP1000
-static struct proc_dir_entry proc_pid_ringbuf = {
-	PROC_PID_RINGBUF, 7, "ringbuf",
-	S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
-	0, &proc_ringbuf_inode_operations,
-	NULL, proc_pid_fill_inode,
+/* reading from directory - bad */
+
+static ssize_t proc_dir_read (struct file * filp, char * buf,
+			      size_t count, loff_t *ppos)
+{
+	return -EISDIR;
+}
+
+struct pid_entry {
+	int type;
+	int len;
+	char *name;
+	mode_t mode;
 };
+
+#define E(type,name,mode) {(type),sizeof(name)-1,(name),(mode)}
+static struct pid_entry base_stuff[] = {
+  E(PROC_PID_FD,	"fd",		S_IFDIR|S_IRUSR|S_IXUSR),
+  E(PROC_PID_ENVIRON,	"environ",	S_IFREG|S_IRUSR),
+  E(PROC_PID_STATUS,	"status",	S_IFREG|S_IRUGO),
+  E(PROC_PID_CMDLINE,	"cmdline",	S_IFREG|S_IRUGO),
+  E(PROC_PID_STAT,	"stat",		S_IFREG|S_IRUGO),
+  E(PROC_PID_STATM,	"statm",	S_IFREG|S_IRUGO),
+#ifdef SMP
+  E(PROC_PID_CPU,	"cpu",		S_IFREG|S_IRUGO),
 #endif
+#if CONFIG_AP1000
+  E(PROC_PID_RINGBUF,	"ringbuf",	S_IFREG|S_IRUGO|S_IWUSR),
+#endif
+  E(PROC_PID_MAPS,	"maps",		S_IFREG|S_IRUGO),
+  E(PROC_PID_MEM,	"mem",		S_IFREG|S_IRUSR|S_IWUSR),
+  E(PROC_PID_CWD,	"cwd",		S_IFLNK|S_IRWXUGO),
+  E(PROC_PID_ROOT,	"root",		S_IFLNK|S_IRWXUGO),
+  E(PROC_PID_EXE,	"exe",		S_IFLNK|S_IRWXUGO),
+  {0,0,NULL,0}
+};
+#undef E
 
-#ifdef __SMP__
-static struct proc_dir_entry proc_pid_cpu = {
-	PROC_PID_CPU, 3, "cpu",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations,
-	NULL, proc_pid_fill_inode,
+#define NUMBUF 10
+
+static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
+{
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct task_struct *p = inode->u.proc_i.task;
+	unsigned int fd, pid, ino;
+	int retval;
+	char buf[NUMBUF];
+
+	retval = 0;
+	pid = p->pid;
+
+	fd = filp->f_pos;
+	switch (fd) {
+		case 0:
+			if (filldir(dirent, ".", 1, 0, inode->i_ino) < 0)
+				goto out;
+			filp->f_pos++;
+		case 1:
+			ino = fake_ino(pid, PROC_PID_INO);
+			if (filldir(dirent, "..", 2, 1, ino) < 0)
+				goto out;
+			filp->f_pos++;
+		default:
+			for (fd = filp->f_pos-2;
+			     p->p_pptr && p->files && fd < p->files->max_fds;
+			     fd++, filp->f_pos++) {
+				unsigned int i,j;
+
+				if (!fcheck_task(p, fd))
+					continue;
+
+				j = NUMBUF;
+				i = fd;
+				do {
+					j--;
+					buf[j] = '0' + (i % 10);
+					i /= 10;
+				} while (i);
+
+				ino = fake_ino(pid, PROC_PID_FD_DIR + fd);
+				if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino) < 0)
+					break;
+
+			}
+	}
+out:
+	return retval;
+}
+
+static int proc_base_readdir(struct file * filp,
+	void * dirent, filldir_t filldir)
+{
+	int i;
+	int pid;
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct pid_entry *p;
+
+	pid = inode->u.proc_i.task->pid;
+	if (!inode->u.proc_i.task->p_pptr)
+		return -ENOENT;
+	i = filp->f_pos;
+	switch (i) {
+		case 0:
+			if (filldir(dirent, ".", 1, i, inode->i_ino) < 0)
+				return 0;
+			i++;
+			filp->f_pos++;
+			/* fall through */
+		case 1:
+			if (filldir(dirent, "..", 2, i, PROC_ROOT_INO) < 0)
+				return 0;
+			i++;
+			filp->f_pos++;
+			/* fall through */
+		default:
+			i -= 2;
+			if (i>=sizeof(base_stuff)/sizeof(base_stuff[0]))
+				return 1;
+			p = base_stuff + i;
+			while (p->name) {
+				if (filldir(dirent, p->name, p->len, filp->f_pos, fake_ino(pid, p->type)) < 0)
+					return 0;
+				filp->f_pos++;
+				p++;
+			}
+	}
+	return 1;
+}
+
+/* building an inode */
+
+static struct inode *proc_pid_get_inode(struct super_block * sb, struct task_struct *task, int ino)
+{
+	struct inode * inode;
+
+	/* We need a new inode */
+	
+	inode = get_empty_inode();
+	if (!inode)
+		goto out;
+
+	/* Common stuff */
+
+	inode->i_sb = sb;
+	inode->i_dev = sb->s_dev;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+	inode->i_ino = fake_ino(task->pid, ino);
+
+	inode->u.proc_i.file = NULL;
+	/*
+	 * grab the reference to task.
+	 */
+	inode->u.proc_i.task = task;
+	atomic_inc(&mem_map[MAP_NR(task)].count);
+	if (!task->p_pptr)
+		goto out_unlock;
+
+	inode->i_uid = 0;
+	inode->i_gid = 0;
+	if (ino == PROC_PID_INO || task->dumpable) {
+		inode->i_uid = task->euid;
+		inode->i_gid = task->egid;
+	}
+
+out:
+	return inode;
+
+out_unlock:
+	iput(inode);
+	return NULL;
+}
+
+/* dentry stuff */
+
+static int pid_fd_revalidate(struct dentry * dentry, int flags)
+{
+	return 0;
+}
+
+static int pid_base_revalidate(struct dentry * dentry, int flags)
+{
+	if (dentry->d_inode->u.proc_i.task->p_pptr)
+		return 1;
+	d_drop(dentry);
+	return 0;
+}
+
+static void pid_delete_dentry(struct dentry * dentry)
+{
+	d_drop(dentry);
+}
+
+static struct dentry_operations pid_fd_dentry_operations =
+{
+	pid_fd_revalidate,	/* revalidate */
+	NULL,			/* d_hash */
+	NULL,			/* d_compare */
+	pid_delete_dentry	/* d_delete(struct dentry *) */
+};
+
+static struct dentry_operations pid_dentry_operations =
+{
+	NULL,			/* revalidate */
+	NULL,			/* d_hash */
+	NULL,			/* d_compare */
+	pid_delete_dentry	/* d_delete(struct dentry *) */
+};
+
+static struct dentry_operations pid_base_dentry_operations =
+{
+	pid_base_revalidate,	/* revalidate */
+	NULL,			/* d_hash */
+	NULL,			/* d_compare */
+	pid_delete_dentry	/* d_delete(struct dentry *) */
 };
-#endif
 
-void __init proc_base_init(void)
+/* Lookups */
+
+static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry)
 {
+	unsigned int fd, c;
+	struct task_struct *task = dir->u.proc_i.task;
+	struct file * file;
+	struct files_struct * files;
+	struct inode *inode;
+	const char *name;
+	int len;
+
+	fd = 0;
+	len = dentry->d_name.len;
+	name = dentry->d_name.name;
+	if (len > 1 && *name == '0') goto out;
+	while (len-- > 0) {
+		c = *name - '0';
+		name++;
+		if (c > 9)
+			goto out;
+		fd *= 10;
+		fd += c;
+		if (fd & 0xffff8000)
+			goto out;
+	}
+
+	inode = proc_pid_get_inode(dir->i_sb, task, PROC_PID_FD_DIR+fd);
+	if (!inode)
+		goto out;
+	/* FIXME */
+	files = task->files;
+	if (!files)	/* can we ever get here if that's the case? */
+		goto out_unlock;
+	read_lock(&files->file_lock);
+	file = inode->u.proc_i.file = fcheck_task(task, fd);
+	if (!file)
+		goto out_unlock2;
+	get_file(file);
+	read_unlock(&files->file_lock);
+	inode->i_op = &proc_pid_link_inode_operations;
+	inode->i_size = 64;
+	inode->i_mode = S_IFLNK;
+	inode->u.proc_i.op.proc_get_link = proc_fd_link;
+	if (file->f_mode & 1)
+		inode->i_mode |= S_IRUSR | S_IXUSR;
+	if (file->f_mode & 2)
+		inode->i_mode |= S_IWUSR | S_IXUSR;
+	dentry->d_op = &pid_fd_dentry_operations;
+	d_add(dentry, inode);
+	return NULL;
+
+out_unlock2:
+	read_unlock(&files->file_lock);
+out_unlock:
+	iput(inode);
+out:
+	return ERR_PTR(-ENOENT);
+}
+
+static struct file_operations proc_fd_operations = {
+	NULL,			/* lseek - default */
+	proc_dir_read,		/* read - bad */
+	NULL,			/* write - bad */
+	proc_readfd,		/* readdir */
+};
+
+/*
+ * proc directories can do almost nothing..
+ */
+static struct inode_operations proc_fd_inode_operations = {
+	&proc_fd_operations,	/* default base directory file-ops */
+	NULL,			/* create */
+	proc_lookupfd,		/* lookup */
+	NULL,			/* link */
+	NULL,			/* unlink */
+	NULL,			/* symlink */
+	NULL,			/* mkdir */
+	NULL,			/* rmdir */
+	NULL,			/* mknod */
+	NULL,			/* rename */
+	NULL,			/* readlink */
+	NULL,			/* follow_link */
+	NULL,			/* get_block */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
+	NULL,			/* flushpage */
+	NULL,			/* truncate */
+	proc_permission,	/* permission */
+};
+
+static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry)
+{
+	struct inode *inode;
+	int error;
+	struct task_struct *task = dir->u.proc_i.task;
+	struct pid_entry *p;
+
+	error = -ENOENT;
+	inode = NULL;
+
+	for (p = base_stuff; p->name; p++) {
+		if (p->len != dentry->d_name.len)
+			continue;
+		if (!memcmp(dentry->d_name.name, p->name, p->len))
+			break;
+	}
+	if (!p->name)
+		goto out;
+
+	error = -EINVAL;
+	inode = proc_pid_get_inode(dir->i_sb, task, p->type);
+	if (!inode)
+		goto out;
+
+	inode->i_mode = p->mode;
+	/*
+	 * Yes, it does not scale. And it should not. Don't add
+	 * new entries into /proc/<pid>/ without very good reasons.
+	 */
+	switch(p->type) {
+		case PROC_PID_FD:
+			inode->i_nlink = 2;
+			inode->i_op = &proc_fd_inode_operations;
+			break;
+		case PROC_PID_EXE:
+			inode->i_op = &proc_pid_link_inode_operations;
+			inode->u.proc_i.op.proc_get_link = proc_exe_link;
+			break;
+		case PROC_PID_CWD:
+			inode->i_op = &proc_pid_link_inode_operations;
+			inode->u.proc_i.op.proc_get_link = proc_cwd_link;
+			break;
+		case PROC_PID_ROOT:
+			inode->i_op = &proc_pid_link_inode_operations;
+			inode->u.proc_i.op.proc_get_link = proc_root_link;
+			break;
+		case PROC_PID_ENVIRON:
+			inode->i_op = &proc_info_inode_operations;
+			inode->u.proc_i.op.proc_read = proc_pid_environ;
+			break;
+		case PROC_PID_STATUS:
+			inode->i_op = &proc_info_inode_operations;
+			inode->u.proc_i.op.proc_read = proc_pid_status;
+			break;
+		case PROC_PID_STAT:
+			inode->i_op = &proc_info_inode_operations;
+			inode->u.proc_i.op.proc_read = proc_pid_stat;
+			break;
+		case PROC_PID_CMDLINE:
+			inode->i_op = &proc_info_inode_operations;
+			inode->u.proc_i.op.proc_read = proc_pid_cmdline;
+			break;
+		case PROC_PID_STATM:
+			inode->i_op = &proc_info_inode_operations;
+			inode->u.proc_i.op.proc_read = proc_pid_statm;
+			break;
+		case PROC_PID_MAPS:
+			inode->i_op = &proc_maps_inode_operations;
+			break;
+#ifdef SMP
+		case PROC_PID_CPU:
+			inode->i_op = &proc_info_inode_operations;
+			inode->u.proc_i.op.proc_read = proc_pid_cpu;
+			break;
+#endif
 #if CONFIG_AP1000
-	proc_register(&proc_pid, &proc_pid_ringbuf);
+		case PROC_PID_RINGBUF:
+			inode->i_op = &proc_ringbuf_inode_operations;
+			break;
 #endif
-	proc_register(&proc_pid, &proc_pid_status);
-	proc_register(&proc_pid, &proc_pid_mem);
-	proc_register(&proc_pid, &proc_pid_cwd);
-	proc_register(&proc_pid, &proc_pid_root);
-	proc_register(&proc_pid, &proc_pid_exe);
-	proc_register(&proc_pid, &proc_pid_fd);
-	proc_register(&proc_pid, &proc_pid_environ);
-	proc_register(&proc_pid, &proc_pid_cmdline);
-	proc_register(&proc_pid, &proc_pid_stat);
-	proc_register(&proc_pid, &proc_pid_statm);
-	proc_register(&proc_pid, &proc_pid_maps);
-#ifdef __SMP__	
-	proc_register(&proc_pid, &proc_pid_cpu);
-#endif	
-};
+		case PROC_PID_MEM:
+			inode->i_op = &proc_mem_inode_operations;
+			break;
+		default:
+			printk("procfs: impossible type (%d)",p->type);
+			iput(inode);
+			return ERR_PTR(-EINVAL);
+	}
+	dentry->d_op = &pid_dentry_operations;
+	d_add(dentry, inode);
+	return NULL;
 
+out:
+	return ERR_PTR(error);
+}
 
+static struct file_operations proc_base_operations = {
+	NULL,			/* lseek - default */
+	proc_dir_read,		/* read - bad */
+	NULL,			/* write - bad */
+	proc_base_readdir,	/* readdir */
+};
+
+static struct inode_operations proc_base_inode_operations = {
+	&proc_base_operations,	/* default base directory file-ops */
+	NULL,			/* create */
+	proc_base_lookup,	/* lookup */
+};
 
+struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry)
+{
+	unsigned int pid, c;
+	struct task_struct *task;
+	const char *name;
+	struct inode *inode;
+	int len;
 
+	pid = 0;
+	name = dentry->d_name.name;
+	len = dentry->d_name.len;
+	while (len-- > 0) {
+		c = *name - '0';
+		name++;
+		if (c > 9)
+			goto out;
+		pid *= 10;
+		pid += c;
+		if (!pid)
+			goto out;
+		if (pid & 0xffff0000)
+			goto out;
+	}
 
+	read_lock(&tasklist_lock);
+	task = find_task_by_pid(pid);
+	if (task)
+		atomic_inc(&mem_map[MAP_NR(task)].count);
+	read_unlock(&tasklist_lock);
+	if (!task)
+		goto out;
 
+	inode = proc_pid_get_inode(dir->i_sb, task, PROC_PID_INO);
 
+	free_task_struct(task);
 
+	if (!inode)
+		goto out;
+	inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
+	inode->i_op = &proc_base_inode_operations;
+	inode->i_nlink = 3;
+	inode->i_flags|=S_IMMUTABLE;
 
+	dentry->d_op = &pid_base_dentry_operations;
+	d_add(dentry, inode);
+	return NULL;
+out:
+	return ERR_PTR(-ENOENT);
+}
 
+void proc_pid_delete_inode(struct inode *inode)
+{
+	if (inode->u.proc_i.file)
+		fput(inode->u.proc_i.file);
+	free_task_struct(inode->u.proc_i.task);
+}
diff --git a/fs/proc/fd.c b/fs/proc/fd.c
deleted file mode 100644
index 1862f6f5fd1f6c512d5536d30a2f0bf13907f35b..0000000000000000000000000000000000000000
--- a/fs/proc/fd.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- *  linux/fs/proc/fd.c
- *
- *  Copyright (C) 1991, 1992 Linus Torvalds
- *
- *  proc fd directory handling functions
- *
- *  01-May-98 Edgar Toernig <froese@gmx.de>
- *	Added support for more than 256 fds.
- *	Limit raised to 32768.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/file.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-
-#include <asm/uaccess.h>
-
-static int proc_readfd(struct file *, void *, filldir_t);
-static struct dentry *proc_lookupfd(struct inode *, struct dentry *);
-
-static struct file_operations proc_fd_operations = {
-	NULL,			/* lseek - default */
-	NULL,			/* read - bad */
-	NULL,			/* write - bad */
-	proc_readfd,		/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	NULL			/* can't fsync */
-};
-
-/*
- * proc directories can do almost nothing..
- */
-struct inode_operations proc_fd_inode_operations = {
-	&proc_fd_operations,	/* default base directory file-ops */
-	NULL,			/* create */
-	proc_lookupfd,		/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* flushpage */
-	NULL,			/* truncate */
-	proc_permission,	/* permission */
-	NULL,			/* smap */
-	NULL			/* revalidate */
-};
-
-/*
- * NOTE! Normally we'd indicate that a file does not
- * exist by creating a negative dentry and returning
- * a successful return code. However, for this case
- * we do not want to create negative dentries, because
- * the state of the world can change behind our backs.
- *
- * Thus just return -ENOENT instead.
- */
-static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry)
-{
-	unsigned int ino, pid, fd, c;
-	struct task_struct * p;
-	struct file * file;
-	struct inode *inode;
-	const char *name;
-	int len, err;
-
-	err = -ENOENT;
-	ino = dir->i_ino;
-	pid = ino >> 16;
-	ino &= 0x0000ffff;
-
-	if (!pid || ino != PROC_PID_FD)
-		goto out;
-
-	fd = 0;
-	len = dentry->d_name.len;
-	name = dentry->d_name.name;
-	if (len > 1 && *name == '0') goto out;
-	while (len-- > 0) {
-		c = *name - '0';
-		name++;
-		if (c > 9)
-			goto out;
-		fd *= 10;
-		fd += c;
-		if (fd & 0xffff8000)
-			goto out;
-	}
-
-	read_lock(&tasklist_lock);
-	file = NULL;
-	p = find_task_by_pid(pid);
-	if (p && p->files)
-		file = fcheck_task(p, fd);
-	read_unlock(&tasklist_lock);
-
-	/*
-	 *	File handle is invalid if it is out of range, if the process
-	 *	has no files (Zombie) if the file is closed, or if its inode
-	 *	is NULL
-	 */
-
-	if (!file)
-		goto out;
-
-	ino = (pid << 16) + PROC_PID_FD_DIR + fd;
-	inode = proc_get_inode(dir->i_sb, ino, NULL);
-	if (inode) {
-		dentry->d_op = &proc_dentry_operations;
-		d_add(dentry, inode);
-		return NULL;
-	}
-out:
-	return ERR_PTR(err);
-}
-
-#define NUMBUF 10
-
-static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
-{
-	struct inode *inode = filp->f_dentry->d_inode;
-	struct task_struct *p, *tmp;
-	unsigned int fd, pid, ino;
-	int retval;
-	char buf[NUMBUF];
-
-	retval = 0;
-	ino = inode->i_ino;
-	pid = ino >> 16;
-	ino &= 0x0000ffff;
-	if (ino != PROC_PID_FD)
-		goto out;
-
-	for (fd = filp->f_pos; fd < 2; fd++, filp->f_pos++) {
-		ino = inode->i_ino;
-		if (fd)
-			ino = (ino & 0xffff0000) | PROC_PID_INO;
-		if (filldir(dirent, "..", fd+1, fd, ino) < 0)
-			goto out;
-	}
-
-	read_lock(&tasklist_lock);
-	p = find_task_by_pid(pid);
-	if (!p)
-		goto out_unlock;
-
-	for (fd -= 2 ; p->files && fd < p->files->max_fds; fd++, filp->f_pos++)
-	{
-		unsigned int i,j;
-
-		if (!fcheck_task(p, fd))
-			continue;
-
-		j = NUMBUF;
-		i = fd;
-		do {
-			j--;
-			buf[j] = '0' + (i % 10);
-			i /= 10;
-		} while (i);
-
-		/* Drop the task lock, as the filldir function may block */
-		read_unlock(&tasklist_lock);
-
-		ino = (pid << 16) + PROC_PID_FD_DIR + fd;
-		if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino) < 0)
-			goto out;
-
-		read_lock(&tasklist_lock);
-		/*
-		 * filldir() might have slept, so we must
-		 * re-validate "p". This is fast enough due
-		 * to the pidhash
-		 */
-		tmp = find_task_by_pid(pid);
-		if (p != tmp)
-			break;
-	}
-out_unlock:
-	read_unlock(&tasklist_lock);
-
-out:
-	return retval;
-}
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index a5596e4ee404ed9e8b17afb7edeff8e66458e147..205f83fc45cbbd24e9174ad62392042ec2ef55c0 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -51,9 +51,7 @@ void de_put(struct proc_dir_entry *de)
 static void proc_put_inode(struct inode *inode)
 {
 #ifdef CONFIG_SUN_OPENPROMFS_MODULE
-	if ((inode->i_ino >= PROC_OPENPROM_FIRST) &&
-	    (inode->i_ino <  PROC_OPENPROM_FIRST + PROC_NOPENPROM) &&
-	    proc_openprom_use)
+	if (PROC_INODE_OPENPROM(inode) && proc_openprom_use)
 		(*proc_openprom_use)(inode, 0);
 #endif	
 	/*
@@ -71,11 +69,12 @@ static void proc_delete_inode(struct inode *inode)
 {
 	struct proc_dir_entry *de = inode->u.generic_ip;
 
-#if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
-	if ((inode->i_ino >= PROC_OPENPROM_FIRST) &&
-	    (inode->i_ino <  PROC_OPENPROM_FIRST + PROC_NOPENPROM))
+	if (PROC_INODE_PROPER(inode)) {
+		proc_pid_delete_inode(inode);
+		return;
+	}
+	if (PROC_INODE_OPENPROM(inode))
 		return;
-#endif	
 
 	if (de) {
 		/*
@@ -142,113 +141,6 @@ static int parse_options(char *options,uid_t *uid,gid_t *gid)
 	return 1;
 }
 
-/*
- * The standard rules, copied from fs/namei.c:permission().
- */
-static int standard_permission(struct inode *inode, int mask)
-{
-	int mode = inode->i_mode;
-
-	if ((mask & S_IWOTH) && IS_RDONLY(inode) &&
-	    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
-		return -EROFS; /* Nobody gets write access to a read-only fs */
-	else if ((mask & S_IWOTH) && IS_IMMUTABLE(inode))
-		return -EACCES; /* Nobody gets write access to an immutable file */
-	else if (current->fsuid == inode->i_uid)
-		mode >>= 6;
-	else if (in_group_p(inode->i_gid))
-		mode >>= 3;
-	if (((mode & mask & S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE))
-		return 0;
-	/* read and search access */
-	if ((mask == S_IROTH) ||
-	    (S_ISDIR(mode)  && !(mask & ~(S_IROTH | S_IXOTH))))
-		if (capable(CAP_DAC_READ_SEARCH))
-			return 0;
-	return -EACCES;
-}
-
-/* 
- * Set up permission rules for processes looking at other processes.
- * You're not allowed to see a process unless it has the same or more
- * restricted root than your own.  This prevents a chrooted processes
- * from escaping through the /proc entries of less restricted
- * processes, and thus allows /proc to be safely mounted in a chrooted
- * area.
- *
- * Note that root (uid 0) doesn't get permission for this either,
- * since chroot is stronger than root.
- *
- * XXX TODO: use the dentry mechanism to make off-limits procs simply
- * invisible rather than denied?  Does each namespace root get its own
- * dentry tree?
- *
- * This also applies the default permissions checks, as it only adds
- * restrictions.
- *
- * Jeremy Fitzhardinge <jeremy@zip.com.au>
- */
-int proc_permission(struct inode *inode, int mask)
-{
-	struct task_struct *p;
-	unsigned long ino = inode->i_ino;
-	unsigned long pid;
-	struct dentry *de, *base;
-
-	if (standard_permission(inode, mask) != 0)
-		return -EACCES;
-
-	/* 
-	 * Find the root of the processes being examined (if any).
-	 * XXX Surely there's a better way of doing this?
-	 */
-	if (ino >= PROC_OPENPROM_FIRST && 
-	    ino <  PROC_OPENPROM_FIRST + PROC_NOPENPROM)
-		return 0;		/* already allowed */
-
-	pid = ino >> 16;
-	if (pid == 0)
-		return 0;		/* already allowed */
-	
-	de = NULL;
-	base = current->fs->root;
-
-	read_lock(&tasklist_lock);
-	p = find_task_by_pid(pid);
-
-	if (p && p->fs)
-		de = p->fs->root;
-	read_unlock(&tasklist_lock);	/* FIXME! */
-
-	if (p == NULL)
-		return -EACCES;		/* ENOENT? */
-
-	if (de == NULL)
-	{
-		/* kswapd and bdflush don't have proper root or cwd... */
-		return -EACCES;
-	}
-	
-	/* XXX locking? */
-	for(;;)
-	{
-		struct dentry *parent;
-
-		if (de == base)
-			return 0;	/* already allowed */
-
-		de = de->d_covers;
-		parent = de->d_parent;
-
-		if (de == parent)
-			break;
-
-		de = parent;
-	}
-
-	return -EACCES;			/* incompatible roots */
-}
-
 struct inode * proc_get_inode(struct super_block * sb, int ino,
 				struct proc_dir_entry * de)
 {
@@ -269,14 +161,9 @@ printk("proc_iget: using deleted entry %s, count=%d\n", de->name, de->count);
 		goto out_fail;
 	
 #ifdef CONFIG_SUN_OPENPROMFS_MODULE
-	if ((inode->i_ino >= PROC_OPENPROM_FIRST)
-	    && (inode->i_ino < PROC_OPENPROM_FIRST + PROC_NOPENPROM)
-	    && proc_openprom_use)
+	if (PROC_INODE_OPENPROM(inode) && proc_openprom_use)
 		(*proc_openprom_use)(inode, 1);
 #endif	
-	/* N.B. How can this test ever fail?? */
-	if (inode->i_sb != sb)
-		printk("proc_get_inode: inode fubar\n");
 
 	inode->u.generic_ip = (void *) de;
 	if (de) {
@@ -366,63 +253,7 @@ int proc_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
 
 void proc_read_inode(struct inode * inode)
 {
-	unsigned long ino, pid;
-	struct task_struct * p;
-	
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-	inode->i_blocks = 0;
-	inode->i_blksize = 1024;
-	ino = inode->i_ino;
-	if (ino >= PROC_OPENPROM_FIRST && 
-	    ino <  PROC_OPENPROM_FIRST + PROC_NOPENPROM)
-		goto out;
-	inode->i_op = NULL;
-	inode->i_mode = 0;
-	inode->i_uid = 0;
-	inode->i_gid = 0;
-	inode->i_nlink = 1;
-	inode->i_size = 0;
-
-	pid = ino >> 16;
-	if (!pid)
-		goto out;
-
-	read_lock(&tasklist_lock);
-	p = find_task_by_pid(pid);
-	if (!p)
-		goto out_unlock;
-
-	ino &= 0x0000ffff;
-	if (ino == PROC_PID_INO || p->dumpable) {
-		inode->i_uid = p->euid;
-		inode->i_gid = p->egid;
-	}
-	if (ino & PROC_PID_FD_DIR) {
-		struct file * file;
-		ino &= 0x7fff;
-		if (!p->files)	/* can we ever get here if that's the case? */
-			goto out_unlock;
-		read_lock(&p->files->file_lock);
-		file = fcheck_task(p, ino);
-		if (!file)
-			goto out_unlock2;
-
-		inode->i_op = &proc_link_inode_operations;
-		inode->i_size = 64;
-		inode->i_mode = S_IFLNK;
-		if (file->f_mode & 1)
-			inode->i_mode |= S_IRUSR | S_IXUSR;
-		if (file->f_mode & 2)
-			inode->i_mode |= S_IWUSR | S_IXUSR;
-out_unlock2:
-		read_unlock(&p->files->file_lock);
-	}
-out_unlock:
-	/* Defer unlocking until we're done with the task */
-	read_unlock(&tasklist_lock);
-
-out:
-	return;
 }
 
 void proc_write_inode(struct inode * inode)
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index d58914e7d6185395c1b576e7daae06d1245a12ba..107f86e16333af04dee1969f79ee653547b27cd4 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -5,6 +5,7 @@
  *	Jeremy Fitzhardinge <jeremy@sw.oz.au>
  *	Implemented by David Howells <David.Howells@nexor.co.uk>
  *	Modified and incorporated into 2.3.x by Tigran Aivazian <tigran@sco.com>
+ *	Support to dump module's data structures (ELF only), Tigran Aivazian <tigran@sco.com>
  */
 
 #include <linux/config.h>
@@ -14,6 +15,8 @@
 #include <linux/a.out.h>
 #include <linux/elf.h>
 #include <linux/elfcore.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
 #include <asm/uaccess.h>
 
 #ifdef CONFIG_KCORE_AOUT
@@ -262,7 +265,7 @@ ssize_t read_kcore(struct file *file, char *buffer, size_t buflen,
 	char *page;
 
 	/* work out how much file we allow to be read */
-	size = ((size_t)high_memory - PAGE_OFFSET) + PAGE_SIZE;
+	proc_root_kcore.size = size = get_kcore_size();
 	acc = 0;
 
 	/* see if file pointer already beyond EOF */
diff --git a/fs/proc/link.c b/fs/proc/link.c
deleted file mode 100644
index 69d435600505983a3fb91f5083796476803f98a3..0000000000000000000000000000000000000000
--- a/fs/proc/link.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- *  linux/fs/proc/link.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *
- *  /proc link-file handling code
- */
-
-#include <asm/uaccess.h>
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-
-static int proc_readlink(struct dentry *, char *, int);
-static struct dentry * proc_follow_link(struct dentry *, struct dentry *, unsigned int);
-
-/*
- * links can't do much...
- */
-static struct file_operations proc_fd_link_operations = {
-	NULL,			/* lseek - default */
-	NULL,			/* read - bad */
-	NULL,			/* write - bad */
-	NULL,			/* readdir - bad */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* very special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	NULL			/* can't fsync */
-};
-
-struct inode_operations proc_link_inode_operations = {
-	&proc_fd_link_operations,/* file-operations */
-	NULL,			/* create */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	proc_readlink,		/* readlink */
-	proc_follow_link,	/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* flushpage */
-	NULL,			/* truncate */
-	proc_permission,	/* permission */
-	NULL,			/* smap */
-	NULL			/* revalidate */
-};
-
-static struct dentry * proc_follow_link(struct dentry *dentry,
-					struct dentry *base,
-					unsigned int follow)
-{
-	struct inode *inode = dentry->d_inode;
-	struct task_struct *p;
-	struct dentry * result;
-	int ino, pid;
-	int error;
-
-	/* We don't need a base pointer in the /proc filesystem */
-	dput(base);
-
-	error = permission(inode, MAY_EXEC);
-	result = ERR_PTR(error);
-	if (error)
-		goto out;
-
-	ino = inode->i_ino;
-	pid = ino >> 16;
-	ino &= 0x0000ffff;
-
-	result = ERR_PTR(-ENOENT);
-
-	switch (ino) {
-		case PROC_PID_CWD:
-			read_lock(&tasklist_lock);
-			p = find_task_by_pid(pid);
-			if (p && p->fs && p->fs->pwd)
-				result = dget(p->fs->pwd);
-			read_unlock(&tasklist_lock);
-			break;
-
-		case PROC_PID_ROOT:
-			read_lock(&tasklist_lock);
-			p = find_task_by_pid(pid);
-			if (p && p->fs && p->fs->root)
-				result = dget(p->fs->root);
-			read_unlock(&tasklist_lock);
-			break;
-
-		case PROC_PID_EXE: {
-			struct mm_struct *mm = NULL;
-			struct vm_area_struct * vma;
-			read_lock(&tasklist_lock);
-			p = find_task_by_pid(pid);
-			if (p)
-				mm = p->mm;
-			if (mm)
-				atomic_inc(&mm->mm_users);
-			read_unlock(&tasklist_lock);
-			if (!mm)
-				break;
-			down(&mm->mmap_sem);
-			vma = mm->mmap;
-			while (vma) {
-				if ((vma->vm_flags & VM_EXECUTABLE) && 
-				    vma->vm_file) {
-					result = dget(vma->vm_file->f_dentry);
-					break;
-				}
-				vma = vma->vm_next;
-			}
-			up(&mm->mmap_sem);
-			mmput(mm);
-			break;
-		}
-		default:
-			if (ino & PROC_PID_FD_DIR) {
-				struct file * file;
-				struct files_struct *files = NULL;
-				read_lock(&tasklist_lock);
-				p = find_task_by_pid(pid);
-				if (p)
-					files = p->files;
-				read_unlock(&tasklist_lock);
-				if (!files)
-					break;
-				ino &= 0x7fff;
-				read_lock(&files->file_lock);
-				/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
-				if (ino < files->max_fds &&
-				    (file = files->fd[ino]) && file->f_dentry)
-					result = dget(file->f_dentry);
-				read_unlock(&p->files->file_lock);
-			}
-	}
-out:
-	return result;
-}
-
-/*
- * This pretty-prints the pathname of a dentry,
- * clarifying sockets etc.
- */
-static int do_proc_readlink(struct dentry *dentry, char * buffer, int buflen)
-{
-	struct inode * inode;
-	char * tmp = (char*)__get_free_page(GFP_KERNEL), *path, *pattern;
-	int len;
-
-	if(tmp==NULL)
-		return -ENOMEM;
-		
-	/* Check for special dentries.. */
-	pattern = NULL;
-	inode = dentry->d_inode;
-	if (inode && IS_ROOT(dentry)) {
-		if (S_ISSOCK(inode->i_mode))
-			pattern = "socket:[%lu]";
-		if (S_ISFIFO(inode->i_mode))
-			pattern = "pipe:[%lu]";
-	}
-	
-	if (pattern) {
-		len = sprintf(tmp, pattern, inode->i_ino);
-		path = tmp;
-	} else {
-		path = d_path(dentry, tmp, PAGE_SIZE);
-		len = tmp + PAGE_SIZE - 1 - path;
-	}
-
-	if (len < buflen)
-		buflen = len;
-	dput(dentry);
-	copy_to_user(buffer, path, buflen);
-	free_page((unsigned long)tmp);
-	return buflen;
-}
-
-static int proc_readlink(struct dentry * dentry, char * buffer, int buflen)
-{
-	int error;
-
-	dentry = proc_follow_link(dentry, NULL, 1);
-	error = PTR_ERR(dentry);
-	if (!IS_ERR(dentry)) {
-		error = -ENOENT;
-		if (dentry) {
-			error = do_proc_readlink(dentry, buffer, buflen);
-		}
-	}
-	return error;
-}
diff --git a/fs/proc/mem.c b/fs/proc/mem.c
deleted file mode 100644
index 410ea32f02537e290a5694c79f4d505f6352a2a8..0000000000000000000000000000000000000000
--- a/fs/proc/mem.c
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- *  linux/fs/proc/mem.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/proc_fs.h>
-#include <linux/highmem.h>
-
-#include <asm/page.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-
-/*
- * mem_write isn't really a good idea right now. It needs
- * to check a lot more: if the process we try to write to 
- * dies in the middle right now, mem_write will overwrite
- * kernel memory.. This disables it altogether.
- */
-#define mem_write NULL
-
-static int check_range(struct mm_struct * mm, unsigned long addr, int count)
-{
-	struct vm_area_struct *vma;
-	int retval;
-
-	vma = find_vma(mm, addr);
-	if (!vma)
-		return -EACCES;
-	if (vma->vm_start > addr)
-		return -EACCES;
-	if (!(vma->vm_flags & VM_READ))
-		return -EACCES;
-	while ((retval = vma->vm_end - addr) < count) {
-		struct vm_area_struct *next = vma->vm_next;
-		if (!next)
-			break;
-		if (vma->vm_end != next->vm_start)
-			break;
-		if (!(next->vm_flags & VM_READ))
-			break;
-		vma = next;
-	}
-	if (retval > count)
-		retval = count;
-	return retval;
-}
-
-static struct task_struct * get_task(int pid)
-{
-	struct task_struct * tsk = current;
-
-	if (pid != tsk->pid) {
-		tsk = find_task_by_pid(pid);
-
-		/* Allow accesses only under the same circumstances
-		 * that we would allow ptrace to work.
-		 */
-		if (tsk) {
-			if (!(tsk->flags & PF_PTRACED)
-			    || tsk->state != TASK_STOPPED
-			    || tsk->p_pptr != current)
-				tsk = NULL;
-		}
-	}
-	return tsk;
-}
-
-static ssize_t mem_read(struct file * file, char * buf,
-			size_t count, loff_t *ppos)
-{
-	struct inode * inode = file->f_dentry->d_inode;
-	pgd_t *page_dir;
-	pmd_t *page_middle;
-	pte_t pte;
-	struct page * page;
-	struct task_struct * tsk;
-	unsigned long addr;
-	unsigned long maddr; /* temporary mapped address */
-	char *tmp;
-	ssize_t scount, i;
-
-	read_lock(&tasklist_lock);
-	tsk = get_task(inode->i_ino >> 16);
-	read_unlock(&tasklist_lock);	/* FIXME: This should really be done only afetr not using tsk any more!!! */
-	if (!tsk)
-		return -ESRCH;
-	addr = *ppos;
-	scount = check_range(tsk->mm, addr, count);
-	if (scount < 0)
-		return scount;
-	tmp = buf;
-	while (scount > 0) {
-		if (signal_pending(current))
-			break;
-		page_dir = pgd_offset(tsk->mm,addr);
-		if (pgd_none(*page_dir))
-			break;
-		if (pgd_bad(*page_dir)) {
-			pgd_ERROR(*page_dir);
-			pgd_clear(page_dir);
-			break;
-		}
-		page_middle = pmd_offset(page_dir,addr);
-		if (pmd_none(*page_middle))
-			break;
-		if (pmd_bad(*page_middle)) {
-			pmd_ERROR(*page_middle);
-			pmd_clear(page_middle);
-			break;
-		}
-		pte = *pte_offset(page_middle,addr);
-		if (!pte_present(pte))
-			break;
-		page = pte_page(pte);
-		i = PAGE_SIZE-(addr & ~PAGE_MASK);
-		if (i > scount)
-			i = scount;
-		maddr = kmap(page, KM_READ);
-		copy_to_user(tmp, (char *)maddr + (addr & ~PAGE_MASK), i);
-		kunmap(maddr, KM_READ);
-		addr += i;
-		tmp += i;
-		scount -= i;
-	}
-	*ppos = addr;
-	return tmp-buf;
-}
-
-#ifndef mem_write
-
-static ssize_t mem_write(struct file * file, char * buf,
-			 size_t count, loff_t *ppos)
-{
-	struct inode * inode = file->f_dentry->d_inode;
-	pgd_t *page_dir;
-	pmd_t *page_middle;
-	pte_t pte;
-	struct page * page;
-	struct task_struct * tsk;
-	unsigned long addr;
-	unsigned long maddr; /* temporary mapped address */
-	char *tmp;
-	long i;
-
-	addr = *ppos;
-	tsk = get_task(inode->i_ino >> 16);
-	if (!tsk)
-		return -ESRCH;
-	tmp = buf;
-	while (count > 0) {
-		if (signal_pending(current))
-			break;
-		page_dir = pgd_offset(tsk,addr);
-		if (pgd_none(*page_dir))
-			break;
-		if (pgd_bad(*page_dir)) {
-			pgd_ERROR(*page_dir);
-			pgd_clear(page_dir);
-			break;
-		}
-		page_middle = pmd_offset(page_dir,addr);
-		if (pmd_none(*page_middle))
-			break;
-		if (pmd_bad(*page_middle)) {
-			pmd_ERROR(*page_middle);
-			pmd_clear(page_middle);
-			break;
-		}
-		pte = *pte_offset(page_middle,addr);
-		if (!pte_present(pte))
-			break;
-		if (!pte_write(pte))
-			break;
-		page = pte_page(pte);
-		i = PAGE_SIZE-(addr & ~PAGE_MASK);
-		if (i > count)
-			i = count;
-		maddr = kmap(page, KM_WRITE);
-		copy_from_user((char *)maddr + (addr & ~PAGE_MASK), tmp, i);
-		kunmap(maddr, KM_WRITE);
-		addr += i;
-		tmp += i;
-		count -= i;
-	}
-	*ppos = addr;
-	if (tmp != buf)
-		return tmp-buf;
-	if (signal_pending(current))
-		return -ERESTARTSYS;
-	return 0;
-}
-
-#endif
-
-static long long mem_lseek(struct file * file, long long offset, int orig)
-{
-	switch (orig) {
-		case 0:
-			file->f_pos = offset;
-			return file->f_pos;
-		case 1:
-			file->f_pos += offset;
-			return file->f_pos;
-		default:
-			return -EINVAL;
-	}
-}
-
-/*
- * This isn't really reliable by any means..
- */
-int mem_mmap(struct file * file, struct vm_area_struct * vma)
-{
-	struct task_struct *tsk;
-	pgd_t *src_dir, *dest_dir;
-	pmd_t *src_middle, *dest_middle;
-	pte_t *src_table, *dest_table;
-	unsigned long stmp, etmp, dtmp, mapnr;
-	struct vm_area_struct *src_vma = NULL;
-	struct inode *inode = file->f_dentry->d_inode;
-	
-	/* Get the source's task information */
-
-	tsk = get_task(inode->i_ino >> 16);
-
-	if (!tsk)
-		return -ESRCH;
-
-	/* Ensure that we have a valid source area.  (Has to be mmap'ed and
-	 have valid page information.)  We can't map shared memory at the
-	 moment because working out the vm_area_struct & nattach stuff isn't
-	 worth it. */
-
-	src_vma = tsk->mm->mmap;
-	stmp = vma->vm_pgoff << PAGE_SHIFT;
-	etmp = stmp + vma->vm_end - vma->vm_start;
-	while (stmp < etmp) {
-		while (src_vma && stmp > src_vma->vm_end)
-			src_vma = src_vma->vm_next;
-		if (!src_vma || (src_vma->vm_flags & VM_SHM))
-			return -EINVAL;
-
-		src_dir = pgd_offset(tsk->mm, stmp);
-		if (pgd_none(*src_dir))
-			return -EINVAL;
-		if (pgd_bad(*src_dir)) {
-			pgd_ERROR(*src_dir);
-			return -EINVAL;
-		}
-		src_middle = pmd_offset(src_dir, stmp);
-		if (pmd_none(*src_middle))
-			return -EINVAL;
-		if (pmd_bad(*src_middle)) {
-			pmd_ERROR(*src_middle);
-			return -EINVAL;
-		}
-		src_table = pte_offset(src_middle, stmp);
-		if (pte_none(*src_table))
-			return -EINVAL;
-
-		if (stmp < src_vma->vm_start) {
-			if (!(src_vma->vm_flags & VM_GROWSDOWN))
-				return -EINVAL;
-			if (src_vma->vm_end - stmp > current->rlim[RLIMIT_STACK].rlim_cur)
-				return -EINVAL;
-		}
-		stmp += PAGE_SIZE;
-	}
-
-	src_vma = tsk->mm->mmap;
-	stmp    = vma->vm_pgoff << PAGE_SHIFT;
-	dtmp    = vma->vm_start;
-
-	flush_cache_range(vma->vm_mm, vma->vm_start, vma->vm_end);
-	flush_cache_range(src_vma->vm_mm, src_vma->vm_start, src_vma->vm_end);
-	while (dtmp < vma->vm_end) {
-		while (src_vma && stmp > src_vma->vm_end)
-			src_vma = src_vma->vm_next;
-
-		src_dir = pgd_offset(tsk->mm, stmp);
-		src_middle = pmd_offset(src_dir, stmp);
-		src_table = pte_offset(src_middle, stmp);
-
-		dest_dir = pgd_offset(current->mm, dtmp);
-		dest_middle = pmd_alloc(dest_dir, dtmp);
-		if (!dest_middle)
-			return -ENOMEM;
-		dest_table = pte_alloc(dest_middle, dtmp);
-		if (!dest_table)
-			return -ENOMEM;
-
-		if (!pte_present(*src_table))
-			handle_mm_fault(tsk, src_vma, stmp, 1);
-
-		if ((vma->vm_flags & VM_WRITE) && !pte_write(*src_table))
-			handle_mm_fault(tsk, src_vma, stmp, 1);
-
-		set_pte(src_table, pte_mkdirty(*src_table));
-		set_pte(dest_table, *src_table);
-		mapnr = pte_pagenr(*src_table);
-		if (mapnr < max_mapnr)
-			get_page(mem_map + pte_pagenr(*src_table));
-
-		stmp += PAGE_SIZE;
-		dtmp += PAGE_SIZE;
-	}
-
-	flush_tlb_range(vma->vm_mm, vma->vm_start, vma->vm_end);
-	flush_tlb_range(src_vma->vm_mm, src_vma->vm_start, src_vma->vm_end);
-	return 0;
-}
-
-static struct file_operations proc_mem_operations = {
-	mem_lseek,
-	mem_read,
-	mem_write,
-	NULL,		/* mem_readdir */
-	NULL,		/* mem_poll */
-	NULL,		/* mem_ioctl */
-	mem_mmap,	/* mmap */
-	NULL,		/* no special open code */
-	NULL,		/* flush */
-	NULL,		/* no special release code */
-	NULL		/* can't fsync */
-};
-
-struct inode_operations proc_mem_inode_operations = {
-	&proc_mem_operations,	/* default base directory 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,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* flushpage */
-	NULL,			/* truncate */
-	proc_permission,	/* permission */
-	NULL,			/* smap */
-	NULL			/* revalidate */
-};
diff --git a/fs/proc/net.c b/fs/proc/net.c
deleted file mode 100644
index b4e18bc499b5940c88bf8774f504a3d5c11f1f63..0000000000000000000000000000000000000000
--- a/fs/proc/net.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- *  linux/fs/proc/net.c
- *
- *  Copyright (C) 1991, 1992 Linus Torvalds
- *
- *  gjh 3/'93 heim@peanuts.informatik.uni-tuebingen.de (Gerald J. Heim)
- *            most of this file is stolen from base.c
- *            it works, but you shouldn't use it as a guideline
- *            for new proc-fs entries. once i'll make it better.
- * fvk 3/'93  waltje@uwalt.nl.mugnet.org (Fred N. van Kempen)
- *	      cleaned up the whole thing, moved "net" specific code to
- *	      the NET kernel layer (where it belonged in the first place).
- * Michael K. Johnson (johnsonm@stolaf.edu) 3/93
- *            Added support from my previous inet.c.  Cleaned things up
- *            quite a bit, modularized the code.
- * fvk 4/'93  waltje@uwalt.nl.mugnet.org (Fred N. van Kempen)
- *	      Renamed "route_get_info()" to "rt_get_info()" for consistency.
- * Alan Cox (gw4pts@gw4pts.ampr.org) 4/94
- *	      Dusted off the code and added IPX. Fixed the 4K limit.
- * Erik Schoenfelder (schoenfr@ibr.cs.tu-bs.de)
- *	      /proc/net/snmp.
- * Alan Cox (gw4pts@gw4pts.ampr.org) 1/95
- *	      Added AppleTalk slots
- *
- *  proc net directory handling functions
- */
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/mm.h>
-
-#include <asm/uaccess.h>
-
-#define PROC_BLOCK_SIZE	(3*1024)		/* 4K page size but our output routines use some slack for overruns */
-
-static long proc_readnet(struct inode * inode, struct file * file,
-			char * buf, unsigned long count)
-{
-	char * page;
-	int bytes=count;
-	int copied=0;
-	char *start;
-	struct proc_dir_entry * dp;
-
-	if (count < 0)
-		return -EINVAL;
-	dp = (struct proc_dir_entry *) inode->u.generic_ip;
-	if (!(page = (char*) __get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
-
-	while (bytes>0)
-	{
-		int length, thistime=bytes;
-		if (bytes > PROC_BLOCK_SIZE)
-			thistime=PROC_BLOCK_SIZE;
-
-		length = dp->get_info(page, &start,
-				      file->f_pos,
-				      thistime,
-				      (file->f_flags & O_ACCMODE) == O_RDWR);
-
-		/*
- 		 *	We have been given a non page aligned block of
-		 *	the data we asked for + a bit. We have been given
- 		 *	the start pointer and we know the length.. 
-		 */
-
-		if (length <= 0)
-			break;
-		/*
- 		 *	Copy the bytes
-		 */
-		copy_to_user(buf+copied, start, length);
-		file->f_pos += length;	/* Move down the file */
-		bytes  -= length;
-		copied += length;
-		if (length<thistime)
-			break;	/* End of file */
-	}
-	free_page((unsigned long) page);
-	return copied;
-}
-
-static struct file_operations proc_net_operations = {
-	NULL,			/* lseek - default */
-	proc_readnet,		/* read - bad */
-	NULL,			/* write - bad */
-	NULL,			/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	NULL			/* can't fsync */
-};
-
-/*
- * proc directories can do almost nothing..
- */
-struct inode_operations proc_net_inode_operations = {
-	&proc_net_operations,	/* default net 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,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* flushpage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL,			/* smap */
-	NULL			/* revalidate */
-};
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 7826d9fa913de4750c6614dbb38e3ff2ec54b5c6..bd3a0842fbe2f76f5add39d9a25f63bf287eab26 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -30,6 +30,7 @@
 #include <linux/slab.h>
 #include <linux/smp.h>
 #include <linux/signal.h>
+#include <linux/module.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -545,12 +546,102 @@ static int memory_read_proc(char *page, char **start, off_t off,
 	return len;
 }
 
+static int open_kcore(struct inode * inode, struct file * filp)
+{
+	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
+}
+
+extern ssize_t read_kcore(struct file *, char *, size_t, loff_t *);
+
+static struct file_operations proc_kcore_operations = {
+	NULL,           /* lseek */
+	read_kcore,
+	NULL,		/* write */
+	NULL,		/* readdir */
+	NULL,		/* poll */
+	NULL,		/* ioctl */
+	NULL,		/* mmap */
+	open_kcore
+};
+
+static struct inode_operations proc_kcore_inode_operations = {
+	&proc_kcore_operations,
+};
+
+/*
+ * This function accesses profiling information. The returned data is
+ * binary: the sampling step and the actual contents of the profile
+ * buffer. Use of the program readprofile is recommended in order to
+ * get meaningful info out of these data.
+ */
+static ssize_t read_profile(struct file *file, char *buf,
+			    size_t count, loff_t *ppos)
+{
+	unsigned long p = *ppos;
+	ssize_t read;
+	char * pnt;
+	unsigned int sample_step = 1 << prof_shift;
+
+	if (p >= (prof_len+1)*sizeof(unsigned int))
+		return 0;
+	if (count > (prof_len+1)*sizeof(unsigned int) - p)
+		count = (prof_len+1)*sizeof(unsigned int) - p;
+	read = 0;
+
+	while (p < sizeof(unsigned int) && count > 0) {
+		put_user(*((char *)(&sample_step)+p),buf);
+		buf++; p++; count--; read++;
+	}
+	pnt = (char *)prof_buffer + p - sizeof(unsigned int);
+	copy_to_user(buf,(void *)pnt,count);
+	read += count;
+	*ppos += read;
+	return read;
+}
+
+/*
+ * Writing to /proc/profile resets the counters
+ *
+ * Writing a 'profiling multiplier' value into it also re-sets the profiling
+ * interrupt frequency, on architectures that support this.
+ */
+static ssize_t write_profile(struct file * file, const char * buf,
+			     size_t count, loff_t *ppos)
+{
+#ifdef __SMP__
+	extern int setup_profiling_timer (unsigned int multiplier);
+
+	if (count==sizeof(int)) {
+		unsigned int multiplier;
+
+		if (copy_from_user(&multiplier, buf, sizeof(int)))
+			return -EFAULT;
+
+		if (setup_profiling_timer(multiplier))
+			return -EINVAL;
+	}
+#endif
+
+	memset(prof_buffer, 0, prof_len * sizeof(*prof_buffer));
+	return count;
+}
+
+static struct file_operations proc_profile_operations = {
+	NULL,           /* lseek */
+	read_profile,
+	write_profile,
+};
+
+static struct inode_operations proc_profile_inode_operations = {
+	&proc_profile_operations,
+};
+
 static struct proc_dir_entry proc_root_kmsg = {
 	0, 4, "kmsg",
 	S_IFREG | S_IRUSR, 1, 0, 0,
 	0, &proc_kmsg_inode_operations
 };
-static struct proc_dir_entry proc_root_kcore = {
+struct proc_dir_entry proc_root_kcore = {
 	0, 5, "kcore",
 	S_IFREG | S_IRUSR, 1, 0, 0,
 	0, &proc_kcore_inode_operations
@@ -613,7 +704,7 @@ void proc_misc_init(void)
 	/* And now for trickier ones */
 	proc_register(&proc_root, &proc_root_kmsg);
 	proc_register(&proc_root, &proc_root_kcore);
-	proc_root_kcore.size = (MAP_NR(high_memory) << PAGE_SHIFT) + PAGE_SIZE;
+	proc_root_kcore.size = get_kcore_size();
 	if (prof_shift) {
 		proc_register(&proc_root, &proc_root_profile);
 		proc_root_profile.size = (1+prof_len) * sizeof(unsigned int);
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 082b419fdc392d625c9924d195a8fc0a97643bb1..545e7cfada3d5bd9739634acd87a898f652ffd4f 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -541,7 +541,6 @@ static struct proc_dir_entry proc_root_ppc_htab = {
 
 void __init proc_root_init(void)
 {
-	proc_base_init();
 	proc_misc_init();
 	proc_register(&proc_root, &proc_root_self);
 	proc_net = create_proc_entry("net", S_IFDIR, 0);
@@ -631,11 +630,7 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry)
 
 static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry)
 {
-	unsigned int pid, c;
 	struct task_struct *p;
-	const char *name;
-	struct inode *inode;
-	int len;
 
 	if (dir->i_ino == PROC_ROOT_INO) { /* check for safety... */
 		extern unsigned long total_forks;
@@ -666,40 +661,7 @@ static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentr
 	if (!proc_lookup(dir, dentry))
 		return NULL;
 	
-	pid = 0;
-	name = dentry->d_name.name;
-	len = dentry->d_name.len;
-	while (len-- > 0) {
-		c = *name - '0';
-		name++;
-		if (c > 9) {
-			pid = 0;
-			break;
-		}
-		pid *= 10;
-		pid += c;
-		if (!pid)
-			break;
-		if (pid & 0xffff0000) {
-			pid = 0;
-			break;
-		}
-	}
-	read_lock(&tasklist_lock);
-	p = find_task_by_pid(pid);
-	read_unlock(&tasklist_lock);
-	inode = NULL;
-	if (pid && p) {
-		unsigned long ino = (pid << 16) + PROC_PID_INO;
-		inode = proc_get_inode(dir->i_sb, ino, &proc_pid);
-		if (!inode)
-			return ERR_PTR(-EINVAL);
-		inode->i_flags|=S_IMMUTABLE;
-	}
-
-	dentry->d_op = &proc_dentry_operations;
-	d_add(dentry, inode);
-	return NULL;
+	return proc_pid_lookup(dir, dentry);
 }
 
 /*
diff --git a/include/asm-alpha/processor.h b/include/asm-alpha/processor.h
index 92654cd8328947cd3d341f56cb94c7e13e1056ee..f986d1c14b43c4ab3f94857def3761e2c9cfddeb 100644
--- a/include/asm-alpha/processor.h
+++ b/include/asm-alpha/processor.h
@@ -126,6 +126,49 @@ extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
 #define release_segments(mm)		do { } while (0)
 #define forget_segments()		do { } while (0)
 
+/*
+ * These bracket the sleeping functions..
+ */
+extern void scheduling_functions_start_here(void);
+extern void scheduling_functions_end_here(void);
+#define first_sched	((unsigned long) scheduling_functions_start_here)
+#define last_sched	((unsigned long) scheduling_functions_end_here)
+
+static inline unsigned long get_wchan(struct task_struct *p)
+{
+	unsigned long schedule_frame;
+	unsigned long pc;
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+	/*
+	 * This one depends on the frame size of schedule().  Do a
+	 * "disass schedule" in gdb to find the frame size.  Also, the
+	 * code assumes that sleep_on() follows immediately after
+	 * interruptible_sleep_on() and that add_timer() follows
+	 * immediately after interruptible_sleep().  Ugly, isn't it?
+	 * Maybe adding a wchan field to task_struct would be better,
+	 * after all...
+	 */
+
+	pc = thread_saved_pc(&p->thread);
+	if (pc >= first_sched && pc < last_sched) {
+		schedule_frame = ((unsigned long *)p->thread.ksp)[6];
+		return ((unsigned long *)schedule_frame)[12];
+	}
+	return pc;
+}
+#undef last_sched
+#undef first_sched
+
+/*
+* See arch/alpha/kernel/ptrace.c for details.
+*/
+#define PT_REG(reg)		(PAGE_SIZE - sizeof(struct pt_regs)	\
+				 + (long)&((struct pt_regs *)0)->reg)
+#define KSTK_EIP(tsk) \
+    (*(unsigned long *)(PT_REG(pc) + PAGE_SIZE + (unsigned long)(tsk)))
+#define KSTK_ESP(tsk)	((tsk) == current ? rdusp() : (tsk)->thread.usp)
+
 /* NOTE: The task struct and the stack go together!  */
 #define alloc_task_struct() \
         ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
diff --git a/include/asm-arm/processor.h b/include/asm-arm/processor.h
index 33b98efa16d8f17d226d5805c21722643aa957d4..02cd7202906d613d022b6222cbed123b8f25cd9f 100644
--- a/include/asm-arm/processor.h
+++ b/include/asm-arm/processor.h
@@ -107,6 +107,45 @@ extern void release_thread(struct task_struct *);
 #define release_segments(mm)		do { } while (0)
 #define forget_segments()		do { } while (0)
 
+/*
+ * These bracket the sleeping functions..
+ */
+extern void scheduling_functions_start_here(void);
+extern void scheduling_functions_end_here(void);
+#define first_sched	((unsigned long) scheduling_functions_start_here)
+#define last_sched	((unsigned long) scheduling_functions_end_here)
+
+static inline unsigned long get_wchan(struct task_struct *p)
+{
+	unsigned long fp, lr;
+	unsigned long stack_page;
+	int count = 0;
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+
+	stack_page = 4096 + (unsigned long)p;
+	fp = get_css_fp(&p->thread);
+	do {
+		if (fp < stack_page || fp > 4092+stack_page)
+			return 0;
+		lr = pc_pointer (((unsigned long *)fp)[-1]);
+		if (lr < first_sched || lr > last_sched)
+			return lr;
+		fp = *(unsigned long *) (fp - 12);
+	} while (count ++ < 16);
+	return 0;
+}
+#undef last_sched
+#undef first_sched
+
+#ifdef CONFIG_CPU_26
+# define KSTK_EIP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
+# define KSTK_ESP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1020])
+#else
+# define KSTK_EIP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1021])
+# define KSTK_ESP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1019])
+#endif
+
 extern struct task_struct *alloc_task_struct(void);
 extern void free_task_struct(struct task_struct *);
 
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index ddd5e165e224f517c947aac522b9a57cf1f788ab..878c637f7cea012afaf58309add49a65086efbbe 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -406,6 +406,10 @@ extern inline unsigned long thread_saved_pc(struct thread_struct *t)
 	return ((unsigned long *)t->esp)[3];
 }
 
+unsigned long get_wchan(struct task_struct *p);
+#define KSTK_EIP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1019])
+#define KSTK_ESP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
+
 #define THREAD_SIZE (2*PAGE_SIZE)
 #define alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
 #define free_task_struct(p) free_pages((unsigned long) (p), 1)
diff --git a/include/asm-m68k/processor.h b/include/asm-m68k/processor.h
index 7b6564813d3cc0ab45f86fc4a590c8641a57ed0c..545673d7c041052fc9db15f3c771efda6d0d535e 100644
--- a/include/asm-m68k/processor.h
+++ b/include/asm-m68k/processor.h
@@ -134,6 +134,48 @@ extern inline unsigned long thread_saved_pc(struct thread_struct *t)
 		return sw->retpc;
 }
 
+/*
+ * These bracket the sleeping functions..
+ */
+extern void scheduling_functions_start_here(void);
+extern void scheduling_functions_end_here(void);
+#define first_sched	((unsigned long) scheduling_functions_start_here)
+#define last_sched	((unsigned long) scheduling_functions_end_here)
+
+static inline unsigned long get_wchan(struct task_struct *p)
+{
+	unsigned long fp, pc;
+	unsigned long stack_page;
+	int count = 0;
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+
+	stack_page = (unsigned long)p;
+	fp = ((struct switch_stack *)p->thread.ksp)->a6;
+	do {
+		if (fp < stack_page+sizeof(struct task_struct) ||
+		    fp >= 8184+stack_page)
+			return 0;
+		pc = ((unsigned long *)fp)[1];
+		/* FIXME: This depends on the order of these functions. */
+		if (pc < first_sched || pc >= last_sched)
+			return pc;
+		fp = *(unsigned long *) fp;
+	} while (count++ < 16);
+	return 0;
+}
+#undef last_sched
+#undef first_sched
+
+#define	KSTK_EIP(tsk)	\
+    ({			\
+	unsigned long eip = 0;	 \
+	if ((tsk)->thread.esp0 > PAGE_SIZE && \
+	    MAP_NR((tsk)->thread.esp0) < max_mapnr) \
+	      eip = ((struct pt_regs *) (tsk)->thread.esp0)->pc; \
+	eip; })
+#define	KSTK_ESP(tsk)	((tsk) == current ? rdusp() : (tsk)->thread.usp)
+
 #define THREAD_SIZE (2*PAGE_SIZE)
 
 /* Allocation and freeing of basic task resources. */
diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h
index a264617a3f0fafdeb801fa53b9071e53f449e93f..4f277148ae7a53512e7fe7f6b810b5806dea7054 100644
--- a/include/asm-mips/processor.h
+++ b/include/asm-mips/processor.h
@@ -206,6 +206,39 @@ extern inline unsigned long thread_saved_pc(struct thread_struct *t)
  */
 extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp);
 
+/*
+ * These bracket the sleeping functions..
+ */
+extern void scheduling_functions_start_here(void);
+extern void scheduling_functions_end_here(void);
+#define first_sched	((unsigned long) scheduling_functions_start_here)
+#define last_sched	((unsigned long) scheduling_functions_end_here)
+
+static inline unsigned long get_wchan(struct task_struct *p)
+{
+	unsigned long schedule_frame;
+	unsigned long pc;
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+	/*
+	 * The same comment as on the Alpha applies here, too ...
+	 */
+	pc = thread_saved_pc(&p->tss);
+	if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
+		schedule_frame = ((unsigned long *)(long)p->tss.reg30)[16];
+		return (unsigned long)((unsigned long *)schedule_frame)[11];
+	}
+	return pc;
+}
+#undef last_sched
+#undef first_sched
+
+#define PT_REG(reg)		((long)&((struct pt_regs *)0)->reg \
+				 - sizeof(struct pt_regs))
+#define KSTK_TOS(tsk) ((unsigned long)(tsk) + KERNEL_STACK_SIZE - 32)
+#define KSTK_EIP(tsk)	(*(unsigned long *)(KSTK_TOS(tsk) + PT_REG(cp0_epc)))
+#define KSTK_ESP(tsk)	(*(unsigned long *)(KSTK_TOS(tsk) + PT_REG(regs[29])))
+
 /* Allocation and freeing of basic task resources. */
 /*
  * NOTE! The task struct and the stack go together
diff --git a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h
index 6e425b60b58bbf308aea5df760e158491aeade5d..167debde713b4bff2557d59e0d273afc980ae1ac 100644
--- a/include/asm-ppc/processor.h
+++ b/include/asm-ppc/processor.h
@@ -316,6 +316,40 @@ static inline unsigned long thread_saved_pc(struct thread_struct *t)
 #define release_segments(mm)		do { } while (0)
 #define forget_segments()		do { } while (0)
 
+/*
+ * These bracket the sleeping functions..
+ */
+extern void scheduling_functions_start_here(void);
+extern void scheduling_functions_end_here(void);
+#define first_sched	((unsigned long) scheduling_functions_start_here)
+#define last_sched	((unsigned long) scheduling_functions_end_here)
+
+static inline unsigned long get_wchan(struct task_struct *p)
+{
+	unsigned long ip, sp;
+	unsigned long stack_page = (unsigned long) p;
+	int count = 0;
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+	sp = p->thread.ksp;
+	do {
+		sp = *(unsigned long *)sp;
+		if (sp < stack_page || sp >= stack_page + 8188)
+			return 0;
+		if (count > 0) {
+			ip = *(unsigned long *)(sp + 4);
+			if (ip < first_sched || ip >= last_sched)
+				return ip;
+		}
+	} while (count++ < 16);
+	return 0;
+}
+#undef last_sched
+#undef first_sched
+
+#define KSTK_EIP(tsk)	((tsk)->thread.regs->nip)
+#define KSTK_ESP(tsk)	((tsk)->thread.regs->gpr[1])
+
 /*
  * NOTE! The task struct and the stack go together
  */
diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h
index 07175eff5c5e85c4373ed8d623720a5198176e08..ae8b036c227d1541b6913b19c541b78d97a57642 100644
--- a/include/asm-sh/processor.h
+++ b/include/asm-sh/processor.h
@@ -189,6 +189,17 @@ extern __inline__ unsigned long thread_saved_pc(struct thread_struct *t)
 	return t->pc;
 }
 
+static inline unsigned long get_wchan(struct task_struct *p)
+{
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+	/* FIXME: here the actual wchan calculation should sit */
+	return 0;
+}
+
+#define KSTK_EIP(tsk)  ((tsk)->thread.pc)
+#define KSTK_ESP(tsk)  ((tsk)->thread.sp)
+
 #define THREAD_SIZE (2*PAGE_SIZE)
 extern struct task_struct * alloc_task_struct(void);
 extern void free_task_struct(struct task_struct *);
diff --git a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h
index 81739b0a528bde1e20d38b390c3caa4c2888983a..662a8119f42ddc406f4042bb2d9586632afdfbd4 100644
--- a/include/asm-sparc/processor.h
+++ b/include/asm-sparc/processor.h
@@ -161,6 +161,43 @@ extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 #define release_segments(mm)		do { } while (0)
 #define forget_segments()		do { } while (0)
 
+/*
+ * These bracket the sleeping functions..
+ */
+extern void scheduling_functions_start_here(void);
+extern void scheduling_functions_end_here(void);
+#define first_sched	((unsigned long) scheduling_functions_start_here)
+#define last_sched	((unsigned long) scheduling_functions_end_here)
+
+static inline unsigned long get_wchan(struct task_struct *p)
+{
+	unsigned long pc, fp, bias = 0;
+	unsigned long task_base = (unsigned long) p;
+	struct reg_window *rw;
+	int count = 0;
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+
+	fp = p->thread.ksp + bias;
+	do {
+		/* Bogus frame pointer? */
+		if (fp < (task_base + sizeof(struct task_struct)) ||
+		    fp >= (task_base + (2 * PAGE_SIZE)))
+			break;
+		rw = (struct reg_window *) fp;
+		pc = rw->ins[7];
+		if (pc < first_sched || pc >= last_sched)
+			return pc;
+		fp = rw->ins[6] + bias;
+	} while (++count < 16);
+	return 0;
+}
+#undef last_sched
+#undef first_sched
+
+#define KSTK_EIP(tsk)  ((tsk)->thread.kregs->pc)
+#define KSTK_ESP(tsk)  ((tsk)->thread.kregs->u_regs[UREG_FP])
+
 #ifdef __KERNEL__
 #define THREAD_SIZE (2*PAGE_SIZE)
 
diff --git a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h
index d5074144dd0c84367565bd569f1a9bc760c8c987..56a116279dd9f7c32ed30da2939112608f096b95 100644
--- a/include/asm-sparc64/processor.h
+++ b/include/asm-sparc64/processor.h
@@ -209,6 +209,43 @@ extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 #define release_segments(mm)		do { } while (0)
 #define forget_segments()		do { } while (0)
 
+/*
+ * These bracket the sleeping functions..
+ */
+extern void scheduling_functions_start_here(void);
+extern void scheduling_functions_end_here(void);
+#define first_sched	((unsigned long) scheduling_functions_start_here)
+#define last_sched	((unsigned long) scheduling_functions_end_here)
+
+static inline unsigned long get_wchan(struct task_struct *p)
+{
+	unsigned long pc, fp, bias = 0;
+	unsigned long task_base = (unsigned long) p;
+	struct reg_window *rw;
+	int count = 0;
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+	bias = STACK_BIAS;
+	fp = p->thread.ksp + bias;
+	do {
+		/* Bogus frame pointer? */
+		if (fp < (task_base + sizeof(struct task_struct)) ||
+		    fp >= (task_base + (2 * PAGE_SIZE)))
+			break;
+		rw = (struct reg_window *) fp;
+		pc = rw->ins[7];
+		if (pc < first_sched || pc >= last_sched)
+			return pc;
+		fp = rw->ins[6] + bias;
+	} while (++count < 16);
+	return 0;
+}
+#undef last_sched
+#undef first_sched
+
+#define KSTK_EIP(tsk)  ((tsk)->thread.kregs->tpc)
+#define KSTK_ESP(tsk)  ((tsk)->thread.kregs->u_regs[UREG_FP])
+
 #ifdef __KERNEL__
 #define THREAD_SIZE (2*PAGE_SIZE)
 /* Allocation and freeing of task_struct and kernel stack. */
diff --git a/include/linux/concap.h b/include/linux/concap.h
index a0743ec146b8e98b5b257115277dbfd80c4f01db..79d642288891259b767dddc0e93fa6804fcc6d7f 100644
--- a/include/linux/concap.h
+++ b/include/linux/concap.h
@@ -5,7 +5,6 @@
 #ifdef __KERNEL__
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
-#include <linux/isdn_compat.h>
 
 /* Stuff to support encapsulation protocols genericly. The encapsulation
    protocol is processed at the uppermost layer of the network interface.
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 4b1fadbf996ae21080cc0f1e7a27cf6efde39e8b..a7efa4ea0b79161925c42a75c53664959915cabb 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -271,6 +271,7 @@ void init_buffer(struct buffer_head *, bh_end_io_t *, void *);
 #include <linux/bfs_fs_i.h>
 #include <linux/udf_fs_i.h>
 #include <linux/ncp_fs_i.h>
+#include <linux/proc_fs_i.h>
 
 /*
  * Attribute flags.  These should be or-ed together to figure out what
@@ -395,6 +396,7 @@ struct inode {
 		struct bfs_inode_info		bfs_i;
 		struct udf_inode_info		udf_i;
 		struct ncp_inode_info		ncpfs_i;
+		struct proc_inode_info		proc_i;
 		struct socket			socket_i;
 		void				*generic_ip;
 	} u;
diff --git a/include/linux/isdn.h b/include/linux/isdn.h
index d1d7350b1cc6481ffb404f939110521c32b2b555..b73358b68240a9c88b06b441572d012c25b168e1 100644
--- a/include/linux/isdn.h
+++ b/include/linux/isdn.h
@@ -1,8 +1,8 @@
-/* $Id: isdn.h,v 1.71 1999/08/23 15:54:22 keil Exp $
+/* $Id: isdn.h,v 1.81 1999/10/27 21:21:18 detabc Exp $
  *
  * Main header for the Linux ISDN subsystem (linklevel).
  *
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de)
  * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
  * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
  * 
@@ -21,6 +21,51 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn.h,v $
+ * Revision 1.81  1999/10/27 21:21:18  detabc
+ * Added support for building logically-bind-group's per interface.
+ * usefull for outgoing call's with more then one isdn-card.
+ *
+ * Switchable support to dont reset the hangup-timeout for
+ * receive frames. Most part's of the timru-rules for receiving frames
+ * are now obsolete. If the input- or forwarding-firewall deny
+ * the frame, the line will be not hold open.
+ *
+ * Revision 1.80  1999/10/26 21:09:29  armin
+ * New bufferlen for phonenumber only with kernel 2.3.x
+ *
+ * Revision 1.79  1999/10/16 17:52:38  keil
+ * Changing the MSN length need new data versions
+ *
+ * Revision 1.78  1999/10/08 18:59:33  armin
+ * Bugfix of too small MSN buffer and checking phone number
+ * in isdn_tty_getdial()
+ *
+ * Revision 1.77  1999/09/23 22:22:42  detabc
+ * added tcp-keepalive-detect with local response (ipv4 only)
+ * added host-only-interface support
+ * (source ipaddr == interface ipaddr) (ipv4 only)
+ * ok with kernel 2.3.18 and 2.2.12
+ *
+ * Revision 1.76  1999/09/14 10:16:21  keil
+ * change ABC include
+ *
+ * Revision 1.75  1999/09/13 23:25:17  he
+ * serialized xmitting frames from isdn_ppp and BSENT statcallb
+ *
+ * Revision 1.74  1999/09/12 16:19:39  detabc
+ * added abc features
+ * low cost routing for net-interfaces (only the HL side).
+ * need more implementation in the isdnlog-utility
+ * udp info support (first part).
+ * different EAZ on outgoing call's.
+ * more checks on D-Channel callbacks (double use of channels).
+ * tested and running with kernel 2.3.17
+ *
+ * Revision 1.73  1999/09/06 07:29:36  fritz
+ * Changed my mail-address.
+ *
+ * Revision 1.72  1999/09/04 22:20:19  detabc
+ *
  * Revision 1.71  1999/08/23 15:54:22  keil
  * more backported changes from kernel 2.3.14
  *
@@ -250,7 +295,6 @@
 #ifndef isdn_h
 #define isdn_h
 
-#include <linux/isdn_compat.h>
 #include <linux/config.h>
 #include <linux/ioctl.h>
 
@@ -279,6 +323,18 @@
 #define ISDN_MINOR_PPPMAX   (128 + (ISDN_MAX_CHANNELS-1))
 #define ISDN_MINOR_STATUS   255
 
+#undef CONFIG_ISDN_WITH_ABC_CALLB
+#undef CONFIG_ISDN_WITH_ABC_UDP_CHECK
+#undef CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP
+#undef CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL
+#undef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
+#undef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
+#undef CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE
+#undef CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR
+#undef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
+#undef CONFIG_ISDN_WITH_ABC_ICALL_BIND
+
+
 /* New ioctl-codes */
 #define IIOCNETAIF  _IO('I',1)
 #define IIOCNETDIF  _IO('I',2)
@@ -302,6 +358,7 @@
 #define IIOCNETDIL  _IO('I',20)
 #define IIOCGETCPS  _IO('I',21)
 #define IIOCGETDVR  _IO('I',22)
+#define IIOCNETLCR  _IO('I',23) /* dwabc ioctl for LCR from isdnlog */
 
 #define IIOCNETALN  _IO('I',32)
 #define IIOCNETDLN  _IO('I',33)
@@ -335,10 +392,15 @@
 #define ISDN_USAGE_OUTGOING 128 /* This bit is set, if channel is outgoing  */
 
 #define ISDN_MODEM_ANZREG    24        /* Number of Modem-Registers        */
-#define ISDN_MSNLEN          20
 #define ISDN_LMSNLEN         255 /* Length of tty's Listen-MSN string */
 #define ISDN_CMSGLEN	     50	 /* Length of CONNECT-Message to add for Modem */
 
+#define ISDN_MSNLEN          32
+#define NET_DV 0x06  /* Data version for isdn_net_ioctl_cfg   */
+#define TTY_DV 0x06  /* Data version for iprofd etc.          */
+
+#define INF_DV 0x01  /* Data version for /dev/isdninfo        */
+
 typedef struct {
   char drvid[25];
   unsigned long arg;
@@ -356,10 +418,6 @@ typedef struct {
   int  outgoing;
 } isdn_net_ioctl_phone;
 
-#define NET_DV 0x05  /* Data version for isdn_net_ioctl_cfg   */
-#define TTY_DV 0x05  /* Data version for iprofd etc.          */
-#define INF_DV 0x01  /* Data version for /dev/isdninfo        */
-
 typedef struct {
   char name[10];     /* Name of interface                     */
   char master[10];   /* Name of Master for Bundling           */
@@ -438,7 +496,6 @@ typedef struct {
 
 #include <linux/isdnif.h>
 
-
 #define ISDN_DRVIOCTL_MASK       0x7f  /* Mask for Device-ioctl */
 
 /* Until now unused */
@@ -504,12 +561,6 @@ typedef struct {
 #define ISDN_NET_CALLBACK   0x04       /* activate callback                 */
 #define ISDN_NET_CBHUP      0x08       /* hangup before callback            */
 #define ISDN_NET_CBOUT      0x10       /* remote machine does callback      */
-#if 0
-/* Unused??? */
-#define ISDN_NET_CLONE      0x08       /* clone a tmp interface when called */
-#define ISDN_NET_TMP        0x10       /* tmp interface until getting an IP */
-#define ISDN_NET_DYNAMIC    0x20       /* this link is dynamically allocated */
-#endif
 
 #define ISDN_NET_MAGIC      0x49344C02 /* for paranoia-checking             */
 
@@ -591,7 +642,7 @@ typedef struct isdn_net_local_s {
   struct isdn_net_local_s *last;       /* Ptr to last link in bundle       */
   struct isdn_net_dev_s  *netdev;      /* Ptr to netdev                    */
   struct sk_buff         *first_skb;   /* Ptr to skb that triggers dialing */
-  struct sk_buff         *sav_skb;     /* Ptr to skb, rejected by LL-driver*/
+  struct sk_buff *volatile sav_skb;    /* Ptr to skb, rejected by LL-driver*/
                                        /* Ptr to orig. hard_header_cache   */
   int                    (*org_hhc)(
 				    struct neighbour *neigh,
@@ -743,12 +794,7 @@ typedef struct modem_info {
   atemu                 emu;             /* AT-emulator data               */
   struct termios	normal_termios;  /* For saving termios structs     */
   struct termios	callout_termios;
-#ifdef COMPAT_HAS_NEW_WAITQ
   wait_queue_head_t	open_wait, close_wait;
-#else
-  struct wait_queue	*open_wait;
-  struct wait_queue	*close_wait;
-#endif
   struct semaphore      write_sem;
 } modem_info;
 
@@ -826,11 +872,7 @@ typedef struct {
 	ulong               flags;            /* Misc driver Flags                */
 	int                 locks;            /* Number of locks for this driver  */
 	int                 channels;         /* Number of channels               */
-#ifdef COMPAT_HAS_NEW_WAITQ
 	wait_queue_head_t   st_waitq;         /* Wait-Queue for status-read's     */
-#else
-	struct wait_queue  *st_waitq;         /* Wait-Queue for status-read's     */
-#endif
 	int                 maxbufsize;       /* Maximum Buffersize supported     */
 	unsigned long       pktcount;         /* Until now: unused                */
 	int                 stavail;          /* Chars avail on Status-device     */
@@ -841,13 +883,8 @@ typedef struct {
 	unsigned long      DLEflag;           /* Flags: Insert DLE at next read   */
 #endif
 	struct sk_buff_head *rpqueue;         /* Pointers to start of Rcv-Queue   */
-#ifdef COMPAT_HAS_NEW_WAITQ
 	wait_queue_head_t  *rcv_waitq;       /* Wait-Queues for B-Channel-Reads  */
 	wait_queue_head_t  *snd_waitq;       /* Wait-Queue for B-Channel-Send's  */
-#else
-	struct wait_queue  **rcv_waitq;       /* Wait-Queues for B-Channel-Reads  */
-	struct wait_queue  **snd_waitq;       /* Wait-Queue for B-Channel-Send's  */
-#endif
 	char               msn2eaz[10][ISDN_MSNLEN];  /* Mapping-Table MSN->EAZ   */
 } driver;
 
@@ -863,11 +900,7 @@ typedef struct isdn_devt {
 	/*  see ISDN_TIMER_..defines  */
 	int               global_flags;
 	infostruct        *infochain;                /* List of open info-devs.    */
-#ifdef COMPAT_HAS_NEW_WAITQ
 	wait_queue_head_t info_waitq;               /* Wait-Queue for isdninfo    */
-#else
-	struct wait_queue *info_waitq;               /* Wait-Queue for isdninfo    */
-#endif
 	struct timer_list timer;		       /* Misc.-function Timer       */
 	int               chanmap[ISDN_MAX_CHANNELS];/* Map minor->device-channel  */
 	int               drvmap[ISDN_MAX_CHANNELS]; /* Map minor->driver-index    */
@@ -894,6 +927,7 @@ typedef struct isdn_devt {
 extern isdn_dev *dev;
 
 
+
 /* Utility-Macros */
 #define MIN(a,b) ((a<b)?a:b)
 #define MAX(a,b) ((a>b)?a:b)
diff --git a/include/linux/isdn_compat.h b/include/linux/isdn_compat.h
deleted file mode 100644
index 7750f63037eadb557880110bbc742ca6bc6cfbd2..0000000000000000000000000000000000000000
--- a/include/linux/isdn_compat.h
+++ /dev/null
@@ -1,116 +0,0 @@
-#ifdef __KERNEL__
-/* Compatibility for various Linux kernel versions */
-
-#ifndef _LINUX_ISDN_COMPAT_H
-#define _LINUX_ISDN_COMPAT_H
-
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
-
-#ifndef KERNEL_VERSION
-#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
-#include <linux/mm.h>
-
-#define ioremap vremap
-#define ioremap_nocache vremap
-#define iounmap vfree
-
-static inline unsigned long copy_from_user(void *to, const void *from, unsigned long n)
-{
-	int i;
-	if ((i = verify_area(VERIFY_READ, from, n)) != 0)
-		return i;
-	memcpy_fromfs(to, from, n);
-	return 0;
-}
-
-static inline unsigned long copy_to_user(void *to, const void *from, unsigned long n)
-{
-	int i;
-	if ((i = verify_area(VERIFY_WRITE, to, n)) != 0)
-		return i;
-	memcpy_tofs(to, from, n);
-	return 0;
-}
-
-#define GET_USER(x, addr) ( x = get_user(addr) )
-#ifdef __alpha__ /* needed for 2.0.x with alpha-patches */
-#define RWTYPE long
-#define LSTYPE long
-#define RWARG unsigned long
-#else
-#define RWTYPE int
-#define LSTYPE int
-#define RWARG int
-#endif
-#define LSARG off_t
-#else
-#include <asm/uaccess.h>
-#define GET_USER get_user
-#define PUT_USER put_user
-#define RWTYPE long
-#define LSTYPE long long
-#define RWARG unsigned long
-#define LSARG long long
-#endif /* LINUX_VERSION_CODE */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,15)
-#define SET_SKB_FREE(x) ( x->free = 1 )
-#define idev_kfree_skb(a,b) dev_kfree_skb(a,b)
-#else
-#define SET_SKB_FREE(x)
-#define idev_kfree_skb(a,b) dev_kfree_skb(a)
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,18)
-#define COMPAT_HAS_NEW_SYMTAB
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,31)
-#define CLOSETYPE void
-#define CLOSEVAL
-#else
-#define CLOSETYPE int
-#define CLOSEVAL (0)
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,37)
-#define test_and_clear_bit clear_bit
-#define test_and_set_bit set_bit
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,81)
-#define kstat_irqs( PAR ) kstat.interrupts[PAR]
-#endif
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,91)
-#define COMPAT_HAS_NEW_PCI
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
-#define get_pcibase(ps, nr) ps->base_address[nr]
-#else
-#define get_pcibase(ps, nr) ps->resource[nr].start
-#endif
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,127)
-#define schedule_timeout(a) current->timeout = jiffies + (a); schedule ();
-#endif
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)
-#define COMPAT_HAS_NEW_WAITQ
-#endif
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,12)
-#define COMPAT_HAS_NEW_SETUP
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,14)
-#define net_device device
-#endif
-
-#endif /* __KERNEL__ */
-#endif /* _LINUX_ISDN_COMPAT_H */
diff --git a/include/linux/isdn_ppp.h b/include/linux/isdn_ppp.h
index 9ca7dc7cde3210a0b8031e977bbaeb65aa523b8d..6ba3086abda995cbc69b2fe0959783e4b6f745e4 100644
--- a/include/linux/isdn_ppp.h
+++ b/include/linux/isdn_ppp.h
@@ -4,7 +4,6 @@
 #define _LINUX_ISDN_PPP_H
 
 #include <linux/config.h>
-#include <linux/isdn_compat.h>
 
 #define CALLTYPE_INCOMING 0x1
 #define CALLTYPE_OUTGOING 0x2
@@ -207,11 +206,7 @@ struct ippp_struct {
   struct ippp_buf_queue rq[NUM_RCV_BUFFS]; /* packet queue for isdn_ppp_read() */
   struct ippp_buf_queue *first;  /* pointer to (current) first packet */
   struct ippp_buf_queue *last;   /* pointer to (current) last used packet in queue */
-#ifdef COMPAT_HAS_NEW_WAITQ
   wait_queue_head_t wq;
-#else
-  struct wait_queue *wq;
-#endif
   struct task_struct *tk;
   unsigned int mpppcfg;
   unsigned int pppcfg;
diff --git a/include/linux/isdnif.h b/include/linux/isdnif.h
index 06206eb916d684e663dfaea812c99fce5146ca62..07e3b826df910b34e4345b51d8d97c3b20337099 100644
--- a/include/linux/isdnif.h
+++ b/include/linux/isdnif.h
@@ -1,10 +1,10 @@
-/* $Id: isdnif.h,v 1.30 1999/08/23 15:54:29 keil Exp $
+/* $Id: isdnif.h,v 1.32 1999/10/11 22:03:00 keil Exp $
  *
  * Linux ISDN subsystem
  *
  * Definition of the interface between the subsystem and its low-level drivers.
  *
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de)
  * Copyright 1995,96    Thinking Objects Software GmbH Wuerzburg
  * 
  * This program is free software; you can redistribute it and/or modify
@@ -22,6 +22,12 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdnif.h,v $
+ * Revision 1.32  1999/10/11 22:03:00  keil
+ * COMPAT_NEED_UACCESS (no include in isdn_compat.h)
+ *
+ * Revision 1.31  1999/09/06 07:29:36  fritz
+ * Changed my mail-address.
+ *
  * Revision 1.30  1999/08/23 15:54:29  keil
  * more backported changes from kernel 2.3.14
  *
@@ -138,7 +144,6 @@
 #define isdnif_h
 
 #include <linux/config.h>
-#include <linux/isdn_compat.h>
 
 /*
  * Values for general protocol-selection
diff --git a/include/linux/kernelcapi.h b/include/linux/kernelcapi.h
index 7b212be059557509dcdf5ee23f02d32edbe0acfe..5778d2ebb97f1b2438c12a470813de1fed62d152 100644
--- a/include/linux/kernelcapi.h
+++ b/include/linux/kernelcapi.h
@@ -1,11 +1,15 @@
 /*
- * $Id: kernelcapi.h,v 1.3 1999/07/01 15:26:56 calle Exp $
+ * $Id: kernelcapi.h,v 1.4 1999/09/10 17:24:19 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.4  1999/09/10 17:24:19  calle
+ * Changes for proposed standard for CAPI2.0:
+ * - AK148 "Linux Exention"
+ *
  * Revision 1.3  1999/07/01 15:26:56  calle
  * complete new version (I love it):
  * + new hardware independed "capi_driver" interface that will make it easy to:
@@ -70,19 +74,19 @@ typedef struct kcapi_flagdef {
 #ifdef __KERNEL__
 
 struct capi_interface {
-	int (*capi_installed) (void);
+	__u16 (*capi_isinstalled) (void);
 
-	 __u16(*capi_register) (capi_register_params * rparam, __u16 * applidp);
-	 __u16(*capi_release) (__u16 applid);
-	 __u16(*capi_put_message) (__u16 applid, struct sk_buff * msg);
-	 __u16(*capi_get_message) (__u16 applid, struct sk_buff ** msgp);
-	 __u16(*capi_set_signal) (__u16 applid,
+	__u16 (*capi_register) (capi_register_params * rparam, __u16 * applidp);
+	__u16 (*capi_release) (__u16 applid);
+	__u16 (*capi_put_message) (__u16 applid, struct sk_buff * msg);
+	__u16 (*capi_get_message) (__u16 applid, struct sk_buff ** msgp);
+	__u16 (*capi_set_signal) (__u16 applid,
 			      void (*signal) (__u16 applid, __u32 param),
 				  __u32 param);
-	 __u16(*capi_get_manufacturer) (__u16 contr, __u8 buf[CAPI_MANUFACTURER_LEN]);
-	 __u16(*capi_get_version) (__u16 contr, struct capi_version * verp);
-	 __u16(*capi_get_serial) (__u16 contr, __u8 serial[CAPI_SERIAL_LEN]);
-	 __u16(*capi_get_profile) (__u16 contr, struct capi_profile * profp);
+	__u16 (*capi_get_manufacturer) (__u32 contr, __u8 buf[CAPI_MANUFACTURER_LEN]);
+	__u16 (*capi_get_version) (__u32 contr, struct capi_version * verp);
+	 __u16(*capi_get_serial) (__u32 contr, __u8 serial[CAPI_SERIAL_LEN]);
+	 __u16(*capi_get_profile) (__u32 contr, struct capi_profile * profp);
 
 	/*
 	 * to init controllers, data is always in user memory
@@ -96,7 +100,7 @@ struct capi_interface {
 
 struct capi_interface_user {
 	char name[20];
-	void (*callback) (unsigned int cmd, __u16 contr, void *data);
+	void (*callback) (unsigned int cmd, __u32 contr, void *data);
 	/* internal */
 	struct capi_interface_user *next;
 };
diff --git a/include/linux/module.h b/include/linux/module.h
index e0b655aab82cb91eac95321b7a8e739d07bbdc6c..88c260f658b01022318a007ff98a34ecdaac1869 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -286,4 +286,5 @@ __attribute__((section("__ksymtab"))) =			\
 #define EXPORT_NO_SYMBOLS
 #endif /* MODULE */
 
+extern unsigned long get_kcore_size(void);
 #endif /* _LINUX_MODULE_H */
diff --git a/include/linux/parport.h b/include/linux/parport.h
index b663548f6972115ba0c9fc81ce8b51c8325d552c..8a1e97501633ed0803eafce21afc661d92774cf0 100644
--- a/include/linux/parport.h
+++ b/include/linux/parport.h
@@ -422,6 +422,10 @@ extern int parport_wait_event (struct parport *, long timeout);
 extern int parport_wait_peripheral (struct parport *port,
 				    unsigned char mask,
 				    unsigned char val);
+extern int parport_poll_peripheral (struct parport *port,
+				    unsigned char mask,
+				    unsigned char val,
+				    int usec);
 
 /* For architectural drivers */
 extern void parport_ieee1284_wakeup (struct parport *port);
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 69f55ff2aca77aa62fd5dae112821feab9961a30..a76f96bb726057241e972eeeba0bfd8fcdb5bd50 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -179,6 +179,11 @@ struct proc_dir_entry {
 extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
 				off_t offset, int length, int inout);
 
+#define PROC_INODE_PROPER(inode) ((inode)->i_ino & ~0xffff)
+#define PROC_INODE_OPENPROM(inode) \
+	((inode->i_ino >= PROC_OPENPROM_FIRST) \
+	    && (inode->i_ino < PROC_OPENPROM_FIRST + PROC_NOPENPROM))
+
 #ifdef CONFIG_PROC_FS
 
 extern struct proc_dir_entry proc_root;
@@ -193,6 +198,7 @@ extern struct proc_dir_entry *proc_mca;
 extern struct proc_dir_entry *proc_bus;
 extern struct proc_dir_entry *proc_sysvipc;
 extern struct proc_dir_entry *proc_root_driver;
+extern struct proc_dir_entry proc_root_kcore;
 
 extern struct inode_operations proc_scsi_inode_operations;
 
@@ -292,7 +298,6 @@ extern struct inode * proc_get_inode(struct super_block *, int, struct proc_dir_
 extern int proc_statfs(struct super_block *, struct statfs *, int);
 extern void proc_read_inode(struct inode *);
 extern void proc_write_inode(struct inode *);
-extern int proc_permission(struct inode *, int);
 
 extern int proc_match(int, const char *,struct proc_dir_entry *);
 
diff --git a/include/linux/proc_fs_i.h b/include/linux/proc_fs_i.h
new file mode 100644
index 0000000000000000000000000000000000000000..5060d08fc4c9e057d910ae7b718e1fee6ee4d9d6
--- /dev/null
+++ b/include/linux/proc_fs_i.h
@@ -0,0 +1,9 @@
+struct proc_inode_info {
+	struct task_struct *task;
+	int type;
+	union {
+		struct dentry *(*proc_get_link)(struct inode *);
+		int (*proc_read)(struct task_struct *task, char *page);
+	} op;
+	struct file *file;
+};
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 81ec83c273bbf87aca6a9738feb4d95ce74282bf..191de76af9af8cd71f53f4c6f69342c39b46546f 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -361,6 +361,8 @@ struct task_struct {
 /* Thread group tracking */
    	u32 parent_exec_id;
    	u32 self_exec_id;
+/* Protection of fields allocatio/deallocation */
+	struct semaphore exit_sem;
 };
 
 /*
@@ -427,6 +429,7 @@ struct task_struct {
 /* mm */	NULL, &init_mm, \
 /* signals */	SPIN_LOCK_UNLOCKED, &init_signals, {{0}}, {{0}}, NULL, &init_task.sigqueue, 0, 0, \
 /* exec cts */	0,0, \
+/* exit_sem */	__MUTEX_INITIALIZER(name.exit_sem),	\
 }
 
 #ifndef INIT_TASK_SIZE
@@ -837,6 +840,21 @@ extern inline void unhash_process(struct task_struct *p)
 	write_unlock_irq(&tasklist_lock);
 }
 
+static inline int task_lock(struct task_struct *p)
+{
+	down(&p->exit_sem);
+	if (p->p_pptr)
+		return 1;
+	/* He's dead, Jim. You take his wallet, I'll take tricoder... */
+	up(&p->exit_sem);
+	return 0;
+}
+
+static inline void task_unlock(struct task_struct *p)
+{
+	up(&p->exit_sem);
+}
+
 #endif /* __KERNEL__ */
 
 #endif
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index c5ba9895f445fcdfb356371bdebfeeb1e9b3273a..0e1e65a70aedb4065e4c3ddadd93cd71866d7715 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -103,7 +103,8 @@ enum
 	KERN_MSGPOOL=37,        /* int: Maximum system message pool size */
 	KERN_SYSRQ=38,		/* int: Sysreq enable */
 	KERN_MAX_THREADS=39,    /* int: Maximum nr of threads in the system */
- 	KERN_RANDOM=40		/* Random driver */
+ 	KERN_RANDOM=40,		/* Random driver */
+ 	KERN_SHMALL=41		/* int: Maximum size of shared memory */
 };
 
 
diff --git a/ipc/shm.c b/ipc/shm.c
index 58b41189a9a83655fbeec1fb2519347111871cc4..34ec74877cc85add2e53a9bd821fee7f74d96690 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -50,7 +50,7 @@ static int shm_swapout(struct page *, struct file *);
 static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
 #endif
 
-unsigned int shm_prm[3] = {SHMMAX, SHMALL, SHMMNI};
+size_t shm_prm[3] = {SHMMAX, SHMALL, SHMMNI};
 
 static int shm_tot = 0; /* total number of shared memory pages */
 static int shm_rss = 0; /* number of shared memory pages that are in memory */
diff --git a/kernel/exit.c b/kernel/exit.c
index db0d1f1fa83f7e0906b42b0c8a0ed40ce2336916..399cb98998896da8dba92f1655438e5474446af9 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -402,6 +402,7 @@ NORET_TYPE void do_exit(long code)
 #ifdef CONFIG_BSD_PROCESS_ACCT
 	acct_process(code);
 #endif
+	task_lock(tsk);
 	sem_exit();
 	__exit_mm(tsk);
 #if CONFIG_AP1000
@@ -414,6 +415,7 @@ NORET_TYPE void do_exit(long code)
 	tsk->state = TASK_ZOMBIE;
 	tsk->exit_code = code;
 	exit_notify();
+	task_unlock(tsk);
 #ifdef DEBUG_PROC_TREE
 	audit_ptree();
 #endif
diff --git a/kernel/fork.c b/kernel/fork.c
index 2cce575fc6891dbd8f347a44c929a85aa9427c9e..a90a6bc470ffbc07370c48e7d40f380e869b400a 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -650,6 +650,7 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs)
 	p->p_cptr = NULL;
 	init_waitqueue_head(&p->wait_chldexit);
 	p->vfork_sem = NULL;
+	sema_init(&p->exit_sem, 1);
 
 	p->sigpending = 0;
 	sigemptyset(&p->signal);
diff --git a/kernel/module.c b/kernel/module.c
index 6f4ad977d846789645eedfed5160da3705085716..fd80b8c42b415a6afc96b203ebb029bfe8698506 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -53,6 +53,26 @@ static struct module *find_module(const char *name);
 static void free_module(struct module *, int tag_freed);
 
 
+/* needed for /proc/kcore, here because kernel_module is static (TA) */
+unsigned long get_kcore_size(void)
+{
+	unsigned long try, size = 0;
+	struct module * m;
+
+	if (module_list == &kernel_module)
+		return ((size_t)high_memory - PAGE_OFFSET + PAGE_SIZE);
+
+	/* shouldn't we have a rw spinlock for module_list? */
+	lock_kernel();
+	for (m=module_list; m; m=m->next) {
+		try = (unsigned long)m + m->size;
+		if (try > size)
+			size = try;
+	}
+	unlock_kernel();
+	return (size - PAGE_OFFSET + PAGE_SIZE);
+}
+
 /*
  * Called at boot time
  */
@@ -969,6 +989,13 @@ get_module_symbol(char *modname, char *symname)
 
 #else		/* CONFIG_MODULES */
 
+/* no MODULES so high_memory is good enough for /proc/kcore (TA) */
+unsigned long get_kcore_size(void)
+{
+	return ((size_t)high_memory - PAGE_OFFSET + PAGE_SIZE);
+}
+
+
 /* Dummy syscalls for people who don't want modules */
 
 asmlinkage unsigned long