diff -u --recursive --new-file v2.3.26/linux/CREDITS linux/CREDITS
--- v2.3.26/linux/CREDITS	Sun Nov  7 16:37:33 1999
+++ linux/CREDITS	Wed Nov 10 10:55:31 1999
@@ -508,8 +508,8 @@
 S: Belgium
 
 N: Cort Dougan
-E: cort@cs.nmt.edu
-W: http://www.cs.nmt.edu/~cort/
+E: cort@ppc.kernel.org
+W: http://www.ppc.kernel.org/~cort/
 D: PowerPC
 S: Computer Science Department
 S: New Mexico Tech
diff -u --recursive --new-file v2.3.26/linux/Documentation/Changes linux/Documentation/Changes
--- v2.3.26/linux/Documentation/Changes	Sun Nov  7 16:37:33 1999
+++ linux/Documentation/Changes	Sun Nov  7 16:34:00 1999
@@ -63,6 +63,7 @@
 - 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 @@
    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 @@
 
    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
 **********************
 
@@ -774,6 +781,11 @@
 
 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 -u --recursive --new-file v2.3.26/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.3.26/linux/Documentation/Configure.help	Sun Nov  7 16:37:33 1999
+++ linux/Documentation/Configure.help	Thu Nov 11 16:03:36 1999
@@ -1680,6 +1680,29 @@
   Say Y here to enable support in the dumb serial driver to support
   the HUB6 card.
 
+PCMCIA serial device support
+CONFIG_PCMCIA_SERIAL_CS
+  Say Y here to enable support for 16-bit PCMCIA serial devices,
+  including serial port cards, modems, and the modem functions of
+  multifunction ethernet/modem cards.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called serial_cs.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt. If unsure,
+  say N.
+
+CardBus serial device support
+CONFIG_PCMCIA_SERIAL_CB
+  Say Y here to enable support for CardBus serial devices, including
+  the modem functions of multifunction ethernet/modem devices.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called serial_cb.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt. If unsure,
+  say N.
+
 PCI support
 CONFIG_PCI
   Find out whether you have a PCI motherboard. PCI is the name of a
@@ -5607,6 +5630,36 @@
   module, say M here and read Documentation/modules.txt. If unsure,
   say N.
 
+3Com 3c575 CardBus support
+CONFIG_PCMCIA_3C575
+  This driver supports the 3Com 3c575 series of CardBus Fast Ethernet
+  adapters.
+
+  This driver can only be compiled as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called 3c575_cb.o. If you want to do that, say M
+  here and read Documentation/modules.txt.  If unsure, say N.
+
+DEC Tulip CardBus support
+CONFIG_PCMCIA_TULIP
+  This driver supports CardBus Fast Ethernet adapters based on DEC
+  Tulip and compatible chipsets.
+
+  This driver can only be compiled as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called tulip_cb.o. If you want to do that, say M
+  here and read Documentation/modules.txt.  If unsure, say N.
+
+SMC EPIC CardBus support
+CONFIG_PCMCIA_EPIC100
+  This driver supports CardBus Fast Ethernet adapters based on the SMC
+  EPIC chipset.
+
+  This driver can only be compiled as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called epic100_cb.o. If you want to do that, say
+  M here and read Documentation/modules.txt.  If unsure, say N.
+
 Aviator/Raytheon 2.4MHz wireless support
 CONFIG_PCMCIA_RAYCS
   Say Y here if you intend to attach an Aviator/Raytheon PCMCIA
@@ -7919,23 +7972,11 @@
   Note that you must say Y to "/proc filesystem support" below for
   this to work.
 
-Generic ACPI support
+ACPI support
 CONFIG_ACPI
   Advanced Configuration and Power Interface (ACPI) is an interface
   specification to support power management of peripherals. If your
   system supports it, say Y here.
-
-  This code is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module will be called acpi.o. If you want to compile it as a
-  module, say M here and read Documentation/modules.txt.
-  
-PIIX4 ACPI support
-CONFIG_PIIX4_ACPI
-  If you have a PIIX4 based motherboard (PCI ISA IDE Xcelerator
-  (PIIX4) is a multi-function PCI device) and you want support for
-  Advanced Configuration and Power Interface (ACPI) to support power
-  management of peripherals, say Y here.
 
 Minix fs support
 CONFIG_MINIX_FS
diff -u --recursive --new-file v2.3.26/linux/Documentation/acpi.txt linux/Documentation/acpi.txt
--- v2.3.26/linux/Documentation/acpi.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/acpi.txt	Wed Nov 10 20:01:03 1999
@@ -0,0 +1,125 @@
+ACPI Driver Interface
+---------------------
+
+Overview:
+1) Register each instance of a device with "acpi_register"
+2) Call "acpi_access" before accessing the hardware.
+   (this will ensure that the hardware is awake and ready)
+3) "acpi_transition" callback is called before entering D1-D3
+   or after entering D0
+4) Call "acpi_dev_idle" when the device is not being used
+   (not required by will improve idle detection)
+5) When unloaded, unregister the device with "acpi_unregister"
+
+/*
+ * Description: Register a device with the ACPI subsystem
+ *
+ * Parameters:
+ *   info - static device information
+ *     type - device type
+ *     hid - PnP identifier (or 0 if unknown)
+ *     trans - device state transition callback
+ *   adr - bus number and address or unique id
+ *
+ * Returns: Registered ACPI device or NULL on error
+ *
+ * Details: The device type, bus number, and bus address should be
+ *          enough information to reconstruct the device tree and
+ *          identify device dependencies
+ *
+ * Examples:
+ *   struct acpi_dev_info info = {ACPI_SYS_DEV, ACPI_VGA_HID, vga_trans};
+ *   dev = acpi_register(&info, 0);
+ *
+ *   struct pci_dev *pci_dev = pci_find_dev(...);
+ *   struct acpi_dev_info info = {ACPI_PCI_DEV, 0, trans};
+ *   dev = acpi_register(&info, ACPI_PCI_ADR(pci_dev));
+ */
+struct acpi_dev *acpi_register(struct acpi_dev_info *info, unsigned long adr);
+
+/*
+ * Description: Unregister a device with ACPI
+ *
+ * Parameters:
+ *   dev - ACPI device previously returned from acpi_register
+ */
+void acpi_unregister(struct acpi_dev *dev);
+
+/*
+ * Device idle/use detection
+ *
+ * In general, drivers for all devices should call "acpi_access"
+ * before accessing the hardware (ie. before reading or modifying
+ * a hardware register).  Request or packet-driven drivers should
+ * additionally call "acpi_idle" when a device is not being used.
+ *
+ * Examples:
+ * 1) A keyboard driver would call acpi_access whenever a key is pressed
+ * 2) A network driver would call acpi_access before submitting
+ *    a packet for transmit or receive and acpi_idle when its
+ *    transfer and receive queues are empty.
+ * 3) A VGA driver would call acpi_access before it accesses any
+ *    of the video controller registers
+ *
+ * Ultimately, the ACPI policy manager uses the access and idle
+ * information to decide when to transition devices between
+ * device states.
+ */
+
+/*
+ * Description: Update device access time and wake up device, if necessary
+ *
+ * Parameters:
+ *   dev - ACPI device previously returned from acpi_register
+ *
+ * Details: If called from an interrupt handler acpi_access updates
+ *          access time but should never need to wake up the device
+ *          (if device is generating interrupts, it should be awake
+ *          already)  This is important as we can not wake up
+ *          devices (run AML, etc.) from an interrupt handler.
+ */
+void acpi_access(struct acpi_dev *dev);
+
+/*
+ * Description: Identify device as currently being idle
+ *
+ * Parameters:
+ *   dev - ACPI device previously returned from acpi_register
+ *
+ * Details: A call to acpi_idle might signal to the policy manager
+ *          to put a device to sleep.  If a new device request arrives
+ *          between the call to acpi_idle and the acpi_transition
+ *          callback, the driver should fail the acpi_transition request.
+ */
+void acpi_dev_idle(struct acpi_dev *dev);
+
+/*
+ * Transition function
+ *
+ * Parameters:
+ *   dev - ACPI device previously returned from acpi_register
+ *   state - the device state being entered
+ *
+ * Returns: 0 if the state transition is possible and context saved
+ *          EINVAL if the requested device state is not supported
+ *          EBUSY if the device is now busy and can not transition
+ *          ENOMEM if the device was unable to save context (out of memory)
+ *          
+ * Details: The device state transition function will be called
+ *          before the device is transitioned into the D1-D3 states
+ *          or after the device is transitioned into the D0 state.
+ *          The device driver should save (D1-D3) or restore (D0)
+ *          device context when the transition function is called.
+ *
+ *          For system devices, the ACPI subsystem will perform
+ *          the actual hardware state transition itself.  For bus
+ *          devices, after the driver's acpi_transition function
+ *          is called, the bus driver's acpi_transition function
+ *          is called to perform the actual hardware state transition.
+ *
+ *          Once a driver returns 0 (success) from a transition
+ *          to D1-3 request, it should not process any further
+ *          requests or access the device hardware until a
+ *          call to "acpi_access" is made.
+ */
+typedef int (*acpi_transition)(struct acpi_dev *dev, acpi_dstate_t state);
diff -u --recursive --new-file v2.3.26/linux/Documentation/isdn/00-INDEX linux/Documentation/isdn/00-INDEX
--- v2.3.26/linux/Documentation/isdn/00-INDEX	Wed Apr  1 16:20:56 1998
+++ linux/Documentation/isdn/00-INDEX	Sun Nov  7 16:34:00 1999
@@ -6,12 +6,18 @@
 	- 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 @@
 	- 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 -u --recursive --new-file v2.3.26/linux/Documentation/isdn/CREDITS linux/Documentation/isdn/CREDITS
--- v2.3.26/linux/Documentation/isdn/CREDITS	Thu Aug 12 09:42:32 1999
+++ linux/Documentation/isdn/CREDITS	Sun Nov  7 16:34:00 1999
@@ -15,8 +15,11 @@
   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 -u --recursive --new-file v2.3.26/linux/Documentation/isdn/README linux/Documentation/isdn/README
--- v2.3.26/linux/Documentation/isdn/README	Thu Aug 12 09:42:33 1999
+++ linux/Documentation/isdn/README	Sun Nov  7 16:34:00 1999
@@ -11,7 +11,7 @@
   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 @@
    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 @@
              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 @@
    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 -u --recursive --new-file v2.3.26/linux/Documentation/isdn/README.FAQ linux/Documentation/isdn/README.FAQ
--- v2.3.26/linux/Documentation/isdn/README.FAQ	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/isdn/README.FAQ	Sun Nov  7 16:34:00 1999
@@ -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 -u --recursive --new-file v2.3.26/linux/Documentation/isdn/README.HiSax linux/Documentation/isdn/README.HiSax
--- v2.3.26/linux/Documentation/isdn/README.HiSax	Thu Aug 26 13:05:34 1999
+++ linux/Documentation/isdn/README.HiSax	Sun Nov  7 16:34:00 1999
@@ -63,6 +63,7 @@
 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 @@
    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 @@
    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 @@
 	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 -u --recursive --new-file v2.3.26/linux/Documentation/isdn/README.avmb1 linux/Documentation/isdn/README.avmb1
--- v2.3.26/linux/Documentation/isdn/README.avmb1	Thu Aug 12 09:42:33 1999
+++ linux/Documentation/isdn/README.avmb1	Sun Nov  7 16:34:00 1999
@@ -169,7 +169,7 @@
 
 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 -u --recursive --new-file v2.3.26/linux/Documentation/isdn/README.eicon linux/Documentation/isdn/README.eicon
--- v2.3.26/linux/Documentation/isdn/README.eicon	Thu Aug 12 09:42:33 1999
+++ linux/Documentation/isdn/README.eicon	Sun Nov  7 16:34:00 1999
@@ -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 @@
 
 
 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 @@
 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 -u --recursive --new-file v2.3.26/linux/Documentation/isdn/README.fax linux/Documentation/isdn/README.fax
--- v2.3.26/linux/Documentation/isdn/README.fax	Thu Aug 12 09:42:33 1999
+++ linux/Documentation/isdn/README.fax	Sun Nov  7 16:34:00 1999
@@ -9,7 +9,7 @@
 
 - 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 @@
 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 -u --recursive --new-file v2.3.26/linux/Documentation/isdn/README.hfc-pci linux/Documentation/isdn/README.hfc-pci
--- v2.3.26/linux/Documentation/isdn/README.hfc-pci	Thu Aug 12 09:42:33 1999
+++ linux/Documentation/isdn/README.hfc-pci	Sun Nov  7 16:34:00 1999
@@ -20,6 +20,21 @@
 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 -u --recursive --new-file v2.3.26/linux/Documentation/isdn/README.pcbit linux/Documentation/isdn/README.pcbit
--- v2.3.26/linux/Documentation/isdn/README.pcbit	Tue Apr 28 14:22:04 1998
+++ linux/Documentation/isdn/README.pcbit	Sun Nov  7 16:34:00 1999
@@ -32,7 +32,7 @@
 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 -u --recursive --new-file v2.3.26/linux/Documentation/oops-tracing.txt linux/Documentation/oops-tracing.txt
--- v2.3.26/linux/Documentation/oops-tracing.txt	Mon Oct  4 15:49:29 1999
+++ linux/Documentation/oops-tracing.txt	Mon Nov  8 10:29:52 1999
@@ -16,6 +16,37 @@
 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 -u --recursive --new-file v2.3.26/linux/MAINTAINERS linux/MAINTAINERS
--- v2.3.26/linux/MAINTAINERS	Sun Nov  7 16:37:33 1999
+++ linux/MAINTAINERS	Wed Nov 10 10:55:31 1999
@@ -482,10 +482,18 @@
 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
@@ -514,10 +522,10 @@
 L:	linux-x25@vger.rutgers.edu
 S:	Maintained
 
-LINUX FOR POWERPC (PREP)
+LINUX FOR POWERPC
 P:	Cort Dougan
-M:	cort@cs.nmt.edu
-W:	http://linuxppc.cs.nmt.edu/
+M:	cort@ppc.kernel.org
+W:	http://www.ppc.kernel.org/
 S:	Maintained
 
 LINUX FOR POWER MACINTOSH
diff -u --recursive --new-file v2.3.26/linux/Makefile linux/Makefile
--- v2.3.26/linux/Makefile	Sun Nov  7 16:37:33 1999
+++ linux/Makefile	Thu Nov 11 16:03:36 1999
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 3
-SUBLEVEL = 26
+SUBLEVEL = 27
 EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
@@ -166,6 +166,10 @@
 DRIVERS := $(DRIVERS) drivers/net/pcmcia/pcmcia_net.o
 endif
 
+ifeq ($(CONFIG_PCMCIA_CHRDEV),y)
+DRIVERS := $(DRIVERS) drivers/char/pcmcia/pcmcia_char.o
+endif
+
 ifdef CONFIG_DIO
 DRIVERS := $(DRIVERS) drivers/dio/dio.a
 endif
@@ -329,7 +333,7 @@
 modules: $(patsubst %, _mod_%, $(SUBDIRS))
 
 modules/MARKER:
-	mkdir modules
+	mkdir -p modules
 	touch modules/MARKER
 
 $(patsubst %, _mod_%, $(SUBDIRS)) : include/linux/version.h include/config/MARKER modules/MARKER
@@ -362,6 +366,8 @@
 	if [ -f IRDA_MODULES  ]; then inst_mod IRDA_MODULES  net;   fi; \
 	if [ -f USB_MODULES   ]; then inst_mod USB_MODULES   usb;   fi; \
 	if [ -f PCMCIA_MODULES ]; then inst_mod PCMCIA_MODULES pcmcia; fi; \
+	if [ -f PCMCIA_NET_MODULES ]; then inst_mod PCMCIA_NET_MODULES pcmcia; fi; \
+	if [ -f PCMCIA_CHAR_MODULES ]; then inst_mod PCMCIA_CHAR_MODULES pcmcia; fi; \
 	\
 	ls *.o > $$MODLIB/.allmods; \
 	echo $$MODULES | tr ' ' '\n' | sort | comm -23 $$MODLIB/.allmods - > $$MODLIB/.misc; \
@@ -390,6 +396,7 @@
 	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 -u --recursive --new-file v2.3.26/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c
--- v2.3.26/linux/arch/alpha/kernel/alpha_ksyms.c	Mon Oct 11 15:38:14 1999
+++ linux/arch/alpha/kernel/alpha_ksyms.c	Mon Nov  8 14:28:34 1999
@@ -206,3 +206,5 @@
 EXPORT_SYMBOL_NOVERS(__remqu);
 EXPORT_SYMBOL_NOVERS(memcpy);
 EXPORT_SYMBOL_NOVERS(memset);
+
+EXPORT_SYMBOL(get_wchan);
diff -u --recursive --new-file v2.3.26/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- v2.3.26/linux/arch/alpha/kernel/process.c	Tue Aug 31 17:29:12 1999
+++ linux/arch/alpha/kernel/process.c	Mon Nov  8 14:28:34 1999
@@ -406,3 +406,35 @@
 	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 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;
+}
diff -u --recursive --new-file v2.3.26/linux/arch/arm/kernel/armksyms.c linux/arch/arm/kernel/armksyms.c
--- v2.3.26/linux/arch/arm/kernel/armksyms.c	Mon Nov  1 13:56:26 1999
+++ linux/arch/arm/kernel/armksyms.c	Mon Nov  8 14:28:34 1999
@@ -237,3 +237,5 @@
 EXPORT_SYMBOL_NOVERS(__down_interruptible_failed);
 EXPORT_SYMBOL_NOVERS(__down_trylock_failed);
 EXPORT_SYMBOL_NOVERS(__up_wakeup);
+
+EXPORT_SYMBOL(get_wchan);
diff -u --recursive --new-file v2.3.26/linux/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c
--- v2.3.26/linux/arch/arm/kernel/process.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/kernel/process.c	Mon Nov  8 14:28:34 1999
@@ -337,3 +337,31 @@
 	return __ret;
 }
 
+/*
+ * 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 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;
+}
diff -u --recursive --new-file v2.3.26/linux/arch/arm/mm/small_page.c linux/arch/arm/mm/small_page.c
--- v2.3.26/linux/arch/arm/mm/small_page.c	Mon Nov  1 13:56:26 1999
+++ linux/arch/arm/mm/small_page.c	Thu Nov 11 10:33:42 1999
@@ -33,7 +33,7 @@
  *  second level page tables on 32-bit ARMs.
  *
  * Theory:
- *  We "misuse" the Linux memory management system.  We use __get_pages
+ *  We "misuse" the Linux memory management system.  We use alloc_page
  *  to allocate a page and then mark it as reserved.  The Linux memory
  *  management system will then ignore the "offset", "next_hash" and
  *  "pprev_hash" entries in the mem_map for this page.
@@ -119,7 +119,7 @@
 	return page_address(page) + (offset << order->shift);
 
 need_new_page:
-	page = __get_pages(priority, 0);
+	page = alloc_page(priority);
 	if (!order->queue) {
 		if (!page)
 			goto no_page;
diff -u --recursive --new-file v2.3.26/linux/arch/i386/boot/compressed/misc.c linux/arch/i386/boot/compressed/misc.c
--- v2.3.26/linux/arch/i386/boot/compressed/misc.c	Thu Aug 26 13:05:34 1999
+++ linux/arch/i386/boot/compressed/misc.c	Thu Nov 11 10:33:42 1999
@@ -9,6 +9,7 @@
  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  */
 
+#include <linux/mm.h>
 #include <asm/segment.h>
 #include <asm/io.h>
 
diff -u --recursive --new-file v2.3.26/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.3.26/linux/arch/i386/defconfig	Sun Nov  7 16:37:33 1999
+++ linux/arch/i386/defconfig	Thu Nov 11 16:39:48 1999
@@ -299,6 +299,9 @@
 # CONFIG_PCMCIA_NMCLAN is not set
 # CONFIG_PCMCIA_SMC91C92 is not set
 # CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_PCMCIA_3C575 is not set
+# CONFIG_PCMCIA_TULIP is not set
+# CONFIG_PCMCIA_EPIC100 is not set
 CONFIG_PCMCIA_RAYCS=y
 # CONFIG_PCMCIA_NETWAVE is not set
 # CONFIG_PCMCIA_WAVELAN is not set
@@ -345,6 +348,10 @@
 # CONFIG_82C710_MOUSE is not set
 # CONFIG_PC110_PAD is not set
 # CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
 # CONFIG_WATCHDOG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
@@ -366,6 +373,12 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
+
+#
+# PCMCIA character device support
+#
+# CONFIG_PCMCIA_SERIAL_CS is not set
+# CONFIG_PCMCIA_SERIAL_CB is not set
 
 #
 # USB drivers - not for the faint of heart
diff -u --recursive --new-file v2.3.26/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile
--- v2.3.26/linux/arch/i386/kernel/Makefile	Sat Oct  9 11:47:50 1999
+++ linux/arch/i386/kernel/Makefile	Thu Nov 11 11:39:13 1999
@@ -59,7 +59,4 @@
 O_OBJS += visws_apic.o
 endif
 
-head.o: head.S
-	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $*.S -o $*.o
-
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.26/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- v2.3.26/linux/arch/i386/kernel/apm.c	Sun Nov  7 16:37:34 1999
+++ linux/arch/i386/kernel/apm.c	Mon Nov  8 10:18:45 1999
@@ -1367,8 +1367,10 @@
 	/* 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 -u --recursive --new-file v2.3.26/linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S
--- v2.3.26/linux/arch/i386/kernel/head.S	Fri Oct 22 13:21:45 1999
+++ linux/arch/i386/kernel/head.S	Thu Nov 11 10:33:42 1999
@@ -8,6 +8,7 @@
  */
 
 .text
+#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/linkage.h>
 #include <asm/segment.h>
diff -u --recursive --new-file v2.3.26/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.3.26/linux/arch/i386/kernel/i386_ksyms.c	Mon Nov  1 13:56:26 1999
+++ linux/arch/i386/kernel/i386_ksyms.c	Mon Nov  8 10:19:19 1999
@@ -129,3 +129,4 @@
 EXPORT_SYMBOL(screen_info);
 #endif
 
+EXPORT_SYMBOL(get_wchan);
diff -u --recursive --new-file v2.3.26/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.3.26/linux/arch/i386/kernel/irq.c	Fri Oct 22 13:21:45 1999
+++ linux/arch/i386/kernel/irq.c	Mon Nov  8 10:47:28 1999
@@ -650,6 +650,19 @@
 	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 -u --recursive --new-file v2.3.26/linux/arch/i386/kernel/mca.c linux/arch/i386/kernel/mca.c
--- v2.3.26/linux/arch/i386/kernel/mca.c	Mon Nov  1 13:56:26 1999
+++ linux/arch/i386/kernel/mca.c	Tue Nov  9 11:56:37 1999
@@ -29,6 +29,9 @@
  *	David Weinehall March 24th, 1999
  *	- Fixed the output of 'Driver Installed' in /proc/mca/pos
  *	- Made the Integrated Video & SCSI show up even if they have id 0000
+ *
+ *	AV November 9th, 1999
+ *	- switched to regular procfs methods.
  */
 
 #include <linux/types.h>
@@ -105,52 +108,7 @@
 /*--------------------------------------------------------------------*/
 
 #ifdef CONFIG_PROC_FS
-
 static void mca_do_proc_init(void);
-static int mca_default_procfn(char* buf, int slot);
-
-static ssize_t proc_mca_read(struct file*, char*, size_t, loff_t *);
-
-static struct file_operations proc_mca_operations = {
-	NULL,			/* llseek */
-	proc_mca_read,		/* read */
-	NULL,			/* write */
-	NULL,			/* readdir */
-	NULL,			/* poll */
-	NULL,			/* ioctl */
-	NULL,			/* mmap */
-	NULL,			/* open */
-	NULL,			/* flush */
-	NULL,			/* release */
-	NULL,			/* fsync */
-	NULL,			/* fascync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
-	NULL			/* lock */
-};
-
-static struct inode_operations proc_mca_inode_operations = {
-	&proc_mca_operations,	/* default 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 */
-};
 #endif
 
 /*--------------------------------------------------------------------*/
@@ -657,7 +615,8 @@
 
 #ifdef CONFIG_PROC_FS
 
-int get_mca_info(char *buf) 
+int get_mca_info(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
 {
 	int i, j, len = 0;
 
@@ -667,101 +626,45 @@
 
 		for(i=0; i<MCA_MAX_SLOT_NR; i++) 
 		{
-			len += sprintf(buf+len, "Slot %d: ", i+1);
+			len += sprintf(page+len, "Slot %d: ", i+1);
 			for(j=0; j<8; j++) 
-				len += sprintf(buf+len, "%02x ", mca_info->slot[i].pos[j]);
-			len += sprintf(buf+len, " %s\n", mca_info->slot[i].name);
+				len += sprintf(page+len, "%02x ", mca_info->slot[i].pos[j]);
+			len += sprintf(page+len, " %s\n", mca_info->slot[i].name);
 		}
 
 		/* Format POS registers of integrated video subsystem */
 
-		len += sprintf(buf+len, "Video : ");
+		len += sprintf(page+len, "Video : ");
 		for(j=0; j<8; j++) 
-			len += sprintf(buf+len, "%02x ", mca_info->slot[MCA_INTEGVIDEO].pos[j]);
-		len += sprintf(buf+len, " %s\n", mca_info->slot[MCA_INTEGVIDEO].name);
+			len += sprintf(page+len, "%02x ", mca_info->slot[MCA_INTEGVIDEO].pos[j]);
+		len += sprintf(page+len, " %s\n", mca_info->slot[MCA_INTEGVIDEO].name);
 
 		/* Format POS registers of integrated SCSI subsystem */
 	
-		len += sprintf(buf+len, "SCSI  : ");
+		len += sprintf(page+len, "SCSI  : ");
 		for(j=0; j<8; j++)
-			len += sprintf(buf+len, "%02x ", mca_info->slot[MCA_INTEGSCSI].pos[j]);
-		len += sprintf(buf+len, " %s\n", mca_info->slot[MCA_INTEGSCSI].name);
+			len += sprintf(page+len, "%02x ", mca_info->slot[MCA_INTEGSCSI].pos[j]);
+		len += sprintf(page+len, " %s\n", mca_info->slot[MCA_INTEGSCSI].name);
 	} else {
 		/* Leave it empty if MCA not detected - this should *never*
 		 * happen! 
 		 */
 	}
 
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
 	return len;
 }
 
-
-/*--------------------------------------------------------------------*/
-
-void __init mca_do_proc_init(void)
-{
-	int i;
-	struct proc_dir_entry* node = NULL;
-
-	if(mca_info == NULL) return;	/* Should never happen */
-
-	proc_register(proc_mca, &(struct proc_dir_entry) {
-		PROC_MCA_REGISTERS, 3, "pos", S_IFREG|S_IRUGO,
-		1, 0, 0, 0, &proc_mca_inode_operations,});
-
-	proc_register(proc_mca, &(struct proc_dir_entry) {
-		PROC_MCA_MACHINE, 7, "machine", S_IFREG|S_IRUGO,
-		1, 0, 0, 0, &proc_mca_inode_operations,});
-
-	/* Initialize /proc/mca entries for existing adapters */
-
-	for(i = 0; i < MCA_NUMADAPTERS; i++) {
-		mca_info->slot[i].procfn = 0;
-		mca_info->slot[i].dev = 0;
-
-		if(!mca_isadapter(i)) continue;
-
-		node = (struct proc_dir_entry *)kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL);
-
-		if(node == NULL) {
-			printk("Failed to allocate memory for MCA proc-entries!");
-			return;
-		}
-		memset(node, 0, sizeof(struct proc_dir_entry));
-
-		if(i < MCA_MAX_SLOT_NR) {
-			node->low_ino = PROC_MCA_SLOT + i;
-			node->namelen = sprintf(mca_info->slot[i].procname,
-				"slot%d", i+1);
-		} else if(i == MCA_INTEGVIDEO) {
-			node->low_ino = PROC_MCA_VIDEO;
-			node->namelen = sprintf(mca_info->slot[i].procname,
-				"video");
-		} else if(i == MCA_INTEGSCSI) {
-			node->low_ino = PROC_MCA_SCSI;
-			node->namelen = sprintf(mca_info->slot[i].procname,
-				"scsi");
-		}
-		node->name = mca_info->slot[i].procname;
-		node->mode = S_IFREG | S_IRUGO;
-		node->ops = &proc_mca_inode_operations;
-		proc_register(proc_mca, node);
-	}
-
-} /* mca_do_proc_init() */
-
 /*--------------------------------------------------------------------*/
 
-int mca_default_procfn(char* buf, int slot) 
+static int mca_default_procfn(char* buf, struct MCA_adapter *p)
 {
 	int len = 0, i;
-
-	/* This really shouldn't happen... */
-
-	if(mca_info == NULL) {
-		*buf = 0;
-		return 0;
-	}
+	int slot = p - mca_info->slot;
 
 	/* Print out the basic information */
 
@@ -772,21 +675,21 @@
 	} else if(slot == MCA_INTEGVIDEO) {
 		len += sprintf(buf+len, "Integrated Video Adapter\n");
 	}
-	if(mca_info->slot[slot].name[0]) {
+	if(p->name[0]) {
 
 		/* Drivers might register a name without /proc handler... */
 
 		len += sprintf(buf+len, "Adapter Name: %s\n",
-			mca_info->slot[slot].name);
+			p->name);
 	} else {
 		len += sprintf(buf+len, "Adapter Name: Unknown\n");
 	}
 	len += sprintf(buf+len, "Id: %02x%02x\n",
-		mca_info->slot[slot].pos[1], mca_info->slot[slot].pos[0]);
+		p->pos[1], p->pos[0]);
 	len += sprintf(buf+len, "Enabled: %s\nPOS: ",
 		mca_isenabled(slot) ? "Yes" : "No");
 	for(i=0; i<8; i++) {
-		len += sprintf(buf+len, "%02x ", mca_info->slot[slot].pos[i]);
+		len += sprintf(buf+len, "%02x ", p->pos[i]);
 	}
 	len += sprintf(buf+len, "\nDriver Installed: %s",
 		mca_is_adapter_used(slot) ? "Yes" : "No");
@@ -796,111 +699,80 @@
 	return len;
 } /* mca_default_procfn() */
 
-static int get_mca_machine_info(char* buf) 
+static int get_mca_machine_info(char* page, char **start, off_t off,
+				 int count, int *eof, void *data)
 {
 	int len = 0;
 
-	len += sprintf(buf+len, "Model Id: 0x%x\n", machine_id);
-	len += sprintf(buf+len, "Submodel Id: 0x%x\n", machine_submodel_id);
-	len += sprintf(buf+len, "BIOS Revision: 0x%x\n", BIOS_revision);
-
+	len += sprintf(page+len, "Model Id: 0x%x\n", machine_id);
+	len += sprintf(page+len, "Submodel Id: 0x%x\n", machine_submodel_id);
+	len += sprintf(page+len, "BIOS Revision: 0x%x\n", BIOS_revision);
+
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
 	return len;
 }
 
-static int mca_fill(char* page, int pid, int type, char** start,
-	loff_t *offset, int length)
+static int mca_read_proc(char *page, char **start, off_t off,
+				 int count, int *eof, void *data)
 {
+	struct MCA_adapter *p = (struct MCA_adapter *)data;
 	int len = 0;
-	int slot = 0;
-
-	switch(type) {
-		case PROC_MCA_REGISTERS:
-			return get_mca_info(page);
-		case PROC_MCA_MACHINE:
-			return get_mca_machine_info(page);
-		case PROC_MCA_VIDEO:
-			slot = MCA_INTEGVIDEO;
-			break;
-		case PROC_MCA_SCSI:
-			slot = MCA_INTEGSCSI;
-			break;
-		default:
-			if(type < PROC_MCA_SLOT || type >= PROC_MCA_LAST) {
-				return -EBADF;
-			}
-			slot = type - PROC_MCA_SLOT;
-			break;
-	}
-
-	/* If we made it here, we better have a valid slot */
 
 	/* Get the standard info */
 
-	len = mca_default_procfn(page, slot);
+	len = mca_default_procfn(page, p);
 
 	/* Do any device-specific processing, if there is any */
 
-	if(mca_info->slot[slot].procfn) {
-		len += mca_info->slot[slot].procfn(page+len, slot,
-			mca_info->slot[slot].dev);
+	if(p->procfn) {
+		len += p->procfn(page+len, p-mca_info->slot, p->dev);
 	}
-
+	if (len <= off+count) *eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len>count) len = count;
+	if (len<0) len = 0;
 	return len;
-} /* mca_fill() */
-
-/* Blatantly stolen from fs/proc/array.c, and thus is probably overkill */ 
+} /* mca_read_proc() */
 
-#define PROC_BLOCK_SIZE	(3*1024)
+/*--------------------------------------------------------------------*/
 
-static ssize_t proc_mca_read(struct file* file,
-	char* buf, size_t count, loff_t *ppos)
+void __init mca_do_proc_init(void)
 {
-	unsigned long page;
-	char *start;
-	int length;
-	int end;
-	unsigned int type, pid;
-	struct proc_dir_entry *dp;
-	struct inode *inode = file->f_dentry->d_inode;
-
-	if(count < 0)
-		return -EINVAL;
-	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;
-	length = mca_fill((char *) page, pid, type,
-			  &start, ppos, count);
-	if(length < 0) {
-		free_page(page);
-		return length;
-	}
-	if(start != NULL) {
-		/* We have had block-adjusting processing! */
-
-		copy_to_user(buf, start, length);
-		*ppos += length;
-		count = length;
-	} else {
-		/* Static 4kB (or whatever) block capacity */
+	int i;
+	struct proc_dir_entry* node = NULL;
+	struct MCA_adapter *p;
+
+	if(mca_info == NULL) return;	/* Should never happen */
+
+	create_proc_read_entry("pos",0,proc_mca,get_mca_info,NULL);
+	create_proc_read_entry("machine",0,proc_mca,get_mca_machine_info,NULL);
+
+	/* Initialize /proc/mca entries for existing adapters */
+
+	for(i = 0; i < MCA_NUMADAPTERS; i++) {
+		p = &mca_info->slot[i];
+		p->procfn = 0;
+
+		if(i < MCA_MAX_SLOT_NR) sprintf(p->procname,"slot%d", i+1);
+		else if(i == MCA_INTEGVIDEO) sprintf(p->procname,"video");
+		else if(i == MCA_INTEGSCSI) sprintf(p->procname,"scsi");
+
+		if(!mca_isadapter(i)) continue;
 
-		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;
-} /* proc_mca_read() */
+		node = create_proc_read_entry(p->procname, 0, proc_mca,
+						mca_read_proc, (void *)p);
+
+		if(node == NULL) {
+			printk("Failed to allocate memory for MCA proc-entries!");
+			return;
+		}
+	}
+
+} /* mca_do_proc_init() */
 
 #endif
diff -u --recursive --new-file v2.3.26/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
--- v2.3.26/linux/arch/i386/kernel/mtrr.c	Mon Nov  1 13:56:26 1999
+++ linux/arch/i386/kernel/mtrr.c	Thu Nov 11 09:33:36 1999
@@ -1204,7 +1204,7 @@
     i = (*get_free_region) (base, size);
     if (i < 0)
     {
-	spin_unlock (&main_lock);
+	up(&main_lock);
 	printk ("mtrr: no more MTRRs available\n");
 	return i;
     }
diff -u --recursive --new-file v2.3.26/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.3.26/linux/arch/i386/kernel/process.c	Mon Nov  1 13:56:26 1999
+++ linux/arch/i386/kernel/process.c	Mon Nov  8 10:19:19 1999
@@ -685,3 +685,37 @@
 	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 -u --recursive --new-file v2.3.26/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.3.26/linux/arch/i386/kernel/setup.c	Wed Oct 27 16:34:12 1999
+++ linux/arch/i386/kernel/setup.c	Mon Nov  8 22:10:43 1999
@@ -583,6 +583,7 @@
 #define VMALLOC_RESERVE	(unsigned long)(128 << 20)
 #define MAXMEM		(unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE)
 #define MAXMEM_PFN	PFN_DOWN(MAXMEM)
+#define MAX_NONPAE_PFN	(1 << 20)
 
 	/*
 	 * partially used pages are not usable - thus
@@ -608,8 +609,26 @@
 	 * Determine low and high memory ranges:
 	 */
 	max_low_pfn = max_pfn;
-	if (max_low_pfn > MAXMEM_PFN)
+	if (max_low_pfn > MAXMEM_PFN) {
 		max_low_pfn = MAXMEM_PFN;
+#ifndef CONFIG_HIGHMEM
+		/* Maximum memory usable is what is directly addressable */
+		printk(KERN_WARNING "Warning only %ldMB will be used.\n",
+					MAXMEM>>20);
+		if (max_pfn > MAX_NONPAE_PFN)
+			printk(KERN_WARNING "Use a PAE enabled kernel.\n");
+		else
+			printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
+#else /* !CONFIG_HIGHMEM */
+#ifndef CONFIG_X86_PAE
+		if (max_pfn > MAX_NONPAE_PFN) {
+			max_pfn = MAX_NONPAE_PFN;
+			printk(KERN_WARNING "Warning only 4GB will be used.\n");
+			printk(KERN_WARNING "Use a PAE enabled kernel.\n");
+		}
+#endif /* !CONFIG_X86_PAE */
+#endif /* !CONFIG_HIGHMEM */
+	}
 
 #ifdef CONFIG_HIGHMEM
 	highstart_pfn = highend_pfn = max_pfn;
diff -u --recursive --new-file v2.3.26/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v2.3.26/linux/arch/i386/mm/init.c	Sun Nov  7 16:37:34 1999
+++ linux/arch/i386/mm/init.c	Thu Nov 11 10:33:42 1999
@@ -171,9 +171,11 @@
 	return freed;
 }
 
-/* NOTE: fixmap_init alloc all the fixmap pagetables contigous on the
-   physical space so we can cache the place of the first one and move
-   around without checking the pgd every time. */
+/*
+ * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the
+ * physical space so we can cache the place of the first one and move
+ * around without checking the pgd every time.
+ */
 
 #if CONFIG_HIGHMEM
 pte_t *kmap_pte;
@@ -268,6 +270,44 @@
 	set_pte_phys (address,phys);
 }
 
+static void __init fixrange_init (unsigned long start, unsigned long end, pgd_t *pgd_base)
+{
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+	int i, j;
+
+	i = __pgd_offset(start);
+	j = __pmd_offset(start);
+	pgd = pgd_base + i;
+
+	for ( ; (i < PTRS_PER_PGD) && (start != end); pgd++, i++) {
+#if CONFIG_X86_PAE
+		if (pgd_none(*pgd)) {
+			pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+			memset((void*)pmd, 0, PAGE_SIZE);
+			pgd_val(*pgd) = __pa(pmd) + 0x1;
+			if (pmd != pmd_offset(pgd, start))
+				BUG();
+		}
+		pmd = pmd_offset(pgd, start);
+#else
+		pmd = (pmd_t *)pgd;
+#endif
+		for (; (j < PTRS_PER_PMD) && start; pmd++, j++) {
+			if (pmd_none(*pmd)) {
+				pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+				memset((void*)pte, 0, PAGE_SIZE);
+				pmd_val(*pmd) = _KERNPG_TABLE + __pa(pte);
+				if (pte != pte_offset(pmd, 0))
+					BUG();
+			}
+			start += PMD_SIZE;
+		}
+		j = 0;
+	}
+}
+
 static void __init pagetable_init(void)
 {
 	pgd_t *pgd, *pgd_base;
@@ -331,37 +371,21 @@
 	 * Fixed mappings, only the page table structure has to be
 	 * created - mappings will be set by set_fixmap():
 	 */
-
 	vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
-	i = __pgd_offset(vaddr);
-	j = __pmd_offset(vaddr);
-	pgd = pgd_base + i;
+	fixrange_init(vaddr, 0, pgd_base);
 
-	for ( ; (i < PTRS_PER_PGD) && vaddr; pgd++, i++) {
-#if CONFIG_X86_PAE
-		if (pgd_none(*pgd)) {
-			pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-			memset((void*)pmd, 0, PAGE_SIZE);
-			pgd_val(*pgd) = __pa(pmd) + 0x1;
-			if (pmd != pmd_offset(pgd, vaddr))
-				BUG();
-		}
-		pmd = pmd_offset(pgd, vaddr);
-#else
-		pmd = (pmd_t *)pgd;
+#if CONFIG_HIGHMEM
+	/*
+	 * Permanent kmaps:
+	 */
+	vaddr = PKMAP_BASE;
+	fixrange_init(vaddr, vaddr + 4*1024*1024, pgd_base);
+
+	pgd = swapper_pg_dir + __pgd_offset(vaddr);
+	pmd = pmd_offset(pgd, vaddr);
+	pte = pte_offset(pmd, vaddr);
+	pkmap_page_table = pte;
 #endif
-		for (; (j < PTRS_PER_PMD) && vaddr; pmd++, j++) {
-			if (pmd_none(*pmd)) {
-				pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-				memset((void*)pte, 0, PAGE_SIZE);
-				pmd_val(*pmd) = _KERNPG_TABLE + __pa(pte);
-				if (pte != pte_offset(pmd, 0))
-					BUG();
-			}
-			vaddr += PMD_SIZE;
-		}
-		j = 0;
-	}
 
 #if CONFIG_X86_PAE
 	/*
@@ -389,6 +413,7 @@
 	 */
 	for (i = 0; i < USER_PTRS_PER_PGD; i++)
 		pgd_val(swapper_pg_dir[i]) = 0;
+	flush_tlb_all();
 }
 
 /*
@@ -420,13 +445,18 @@
 #endif
 
 #ifdef CONFIG_HIGHMEM
-	kmap_init(); /* run after fixmap_init */
-#endif
-#ifdef CONFIG_HIGHMEM
-	free_area_init(highend_pfn);
-#else
-	free_area_init(max_low_pfn);
+	kmap_init();
 #endif
+	{
+		unsigned int zones_size[3];
+
+		zones_size[0] = virt_to_phys((char *)MAX_DMA_ADDRESS)
+					 >> PAGE_SHIFT;
+		zones_size[1] = max_low_pfn - zones_size[0];
+		zones_size[2] = highend_pfn - zones_size[0] - zones_size[1];
+
+		free_area_init(zones_size);
+	}
 	return;
 }
 
@@ -441,7 +471,6 @@
 /*
  * Ok, all PAE-capable CPUs are definitely handling the WP bit right.
  */
-//#ifndef CONFIG_X86_PAE
 	const unsigned long vaddr = PAGE_OFFSET;
 	pgd_t *pgd;
 	pmd_t *pmd;
@@ -478,7 +507,6 @@
 #endif
 	} else
 		printk(".\n");
-//#endif
 }
 
 static inline int page_is_ram (unsigned long pagenr)
@@ -541,7 +569,7 @@
 	totalram_pages += totalhigh_pages;
 #endif
 	printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %ldk highmem)\n",
-		(unsigned long) nr_free_pages << (PAGE_SHIFT-10),
+		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
 		max_mapnr << (PAGE_SHIFT-10),
 		codepages << (PAGE_SHIFT-10),
 		reservedpages << (PAGE_SHIFT-10),
@@ -572,7 +600,7 @@
 void free_initmem(void)
 {
 	unsigned long addr;
-	
+
 	addr = (unsigned long)(&__init_begin);
 	for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
 		ClearPageReserved(mem_map + MAP_NR(addr));
@@ -587,10 +615,10 @@
 {
 	val->totalram = totalram_pages;
 	val->sharedram = 0;
-	val->freeram = nr_free_pages;
+	val->freeram = nr_free_pages();
 	val->bufferram = atomic_read(&buffermem_pages);
 	val->totalhigh = totalhigh_pages;
-	val->freehigh = nr_free_highpages;
+	val->freehigh = nr_free_highpages();
 	val->mem_unit = PAGE_SIZE;
 	return;
 }
diff -u --recursive --new-file v2.3.26/linux/arch/m68k/kernel/m68k_ksyms.c linux/arch/m68k/kernel/m68k_ksyms.c
--- v2.3.26/linux/arch/m68k/kernel/m68k_ksyms.c	Tue Sep  7 12:14:06 1999
+++ linux/arch/m68k/kernel/m68k_ksyms.c	Mon Nov  8 14:28:34 1999
@@ -75,3 +75,5 @@
 EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
 EXPORT_SYMBOL_NOVERS(__down_failed_trylock);
 EXPORT_SYMBOL_NOVERS(__up_wakeup);
+
+EXPORT_SYMBOL(get_wchan);
diff -u --recursive --new-file v2.3.26/linux/arch/m68k/kernel/process.c linux/arch/m68k/kernel/process.c
--- v2.3.26/linux/arch/m68k/kernel/process.c	Sun Nov  7 16:37:34 1999
+++ linux/arch/m68k/kernel/process.c	Mon Nov  8 14:28:34 1999
@@ -346,3 +346,34 @@
 	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 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;
+}
diff -u --recursive --new-file v2.3.26/linux/arch/m68k/math-emu/fp_emu.h linux/arch/m68k/math-emu/fp_emu.h
--- v2.3.26/linux/arch/m68k/math-emu/fp_emu.h	Sun Aug 15 11:47:29 1999
+++ linux/arch/m68k/math-emu/fp_emu.h	Wed Nov 10 10:00:48 1999
@@ -38,10 +38,11 @@
 #ifndef _FP_EMU_H
 #define _FP_EMU_H
 
-#ifndef __ASSEMBLY__
-
+#include "../kernel/m68k_defs.h"
 #include <asm/math-emu.h>
 
+#ifndef __ASSEMBLY__
+
 #define IS_INF(a) ((a)->exp == 0x7fff)
 #define IS_ZERO(a) ((a)->mant.m64 == 0)
 
@@ -113,9 +114,6 @@
 })
 
 #else /* __ASSEMBLY__ */
-
-#include "../kernel/m68k_defs.h"
-#include <asm/math-emu.h>
 
 /*
  * set, reset or clear a bit in the fp status register
diff -u --recursive --new-file v2.3.26/linux/arch/mips/kernel/mips_ksyms.c linux/arch/mips/kernel/mips_ksyms.c
--- v2.3.26/linux/arch/mips/kernel/mips_ksyms.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/kernel/mips_ksyms.c	Mon Nov  8 14:28:34 1999
@@ -122,3 +122,4 @@
 EXPORT_SYMBOL(screen_info);
 #endif
 
+EXPORT_SYMBOL(get_wchan);
diff -u --recursive --new-file v2.3.26/linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c
--- v2.3.26/linux/arch/mips/kernel/process.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/kernel/process.c	Mon Nov  8 14:28:34 1999
@@ -182,3 +182,28 @@
 
 	return retval;
 }
+
+/*
+ * 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 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;
+}
diff -u --recursive --new-file v2.3.26/linux/arch/ppc/amiga/config.c linux/arch/ppc/amiga/config.c
--- v2.3.26/linux/arch/ppc/amiga/config.c	Sun Nov  7 16:37:34 1999
+++ linux/arch/ppc/amiga/config.c	Wed Nov 10 22:18:38 1999
@@ -6,7 +6,6 @@
 void (*mach_kbd_reset_setup) (char *, int) __initdata = 0;
 
 #include <asm/io.h>
-#include <asm/system.h>
 
 /*
  *  linux/arch/m68k/amiga/config.c
diff -u --recursive --new-file v2.3.26/linux/arch/ppc/config.in linux/arch/ppc/config.in
--- v2.3.26/linux/arch/ppc/config.in	Sun Nov  7 16:37:34 1999
+++ linux/arch/ppc/config.in	Tue Nov  9 07:13:17 1999
@@ -44,7 +44,7 @@
 fi
 
 bool 'Symmetric multi-processing support' CONFIG_SMP
-if [ "$CONFIG_6xx" != "y" ];then
+if [ "$CONFIG_6xx" = "y" ];then
   bool 'AltiVec Support' CONFIG_ALTIVEC
 fi
 
diff -u --recursive --new-file v2.3.26/linux/arch/ppc/defconfig linux/arch/ppc/defconfig
--- v2.3.26/linux/arch/ppc/defconfig	Sun Nov  7 16:37:34 1999
+++ linux/arch/ppc/defconfig	Mon Nov  8 12:32:50 1999
@@ -3,6 +3,11 @@
 #
 
 #
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
 # Platform support
 #
 CONFIG_PPC=y
@@ -10,55 +15,55 @@
 # CONFIG_PPC64 is not set
 # CONFIG_82xx is not set
 # CONFIG_8xx is not set
-# CONFIG_MPC821 is not set
-# CONFIG_MPC823 is not set
-# CONFIG_MPC850 is not set
-# CONFIG_MPC855 is not set
-# CONFIG_MPC860 is not set
-# CONFIG_MPC860T is not set
-# CONFIG_RPXLITE is not set
-# CONFIG_RPXCLASSIC is not set
-# CONFIG_BSEIP is not set
-# CONFIG_MBX is not set
-# CONFIG_WINCEPT is not set
 # CONFIG_PMAC is not set
 # CONFIG_PREP is not set
 # CONFIG_CHRP is not set
-# CONFIG_ALL_PPC is not set
-CONFIG_GEMINI=y
+CONFIG_ALL_PPC=y
+# CONFIG_GEMINI is not set
 # CONFIG_APUS is not set
 # CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
 CONFIG_6xx=y
 
 #
-# General setup
+# Loadable module support
 #
-CONFIG_EXPERIMENTAL=y
 CONFIG_MODULES=y
 CONFIG_MODVERSIONS=y
 CONFIG_KMOD=y
+
+#
+# General setup
+#
 CONFIG_PCI=y
 CONFIG_NET=y
 CONFIG_SYSCTL=y
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_KCORE_AOUT is not set
-CONFIG_KCORE_ELF=y
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
 # CONFIG_BINFMT_MISC is not set
+
+#
+# PCMCIA/CardBus support
+#
+# CONFIG_PCMCIA is not set
 # CONFIG_PARPORT is not set
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_FB is not set
-# CONFIG_PMAC_PBOOK is not set
-# CONFIG_MAC_FLOPPY is not set
-# CONFIG_MAC_SERIAL is not set
-# CONFIG_ADB is not set
-# CONFIG_PROC_DEVICETREE is not set
+CONFIG_VGA_CONSOLE=y
+CONFIG_FB=y
+CONFIG_FB_COMPAT_XPMAC=y
+CONFIG_PMAC_PBOOK=y
+CONFIG_MAC_FLOPPY=y
+CONFIG_MAC_SERIAL=y
+CONFIG_ADB=y
+CONFIG_ADB_CUDA=y
+CONFIG_ADB_MACIO=y
+CONFIG_ADB_PMU=y
+CONFIG_ADB_KEYBOARD=y
+CONFIG_PROC_DEVICETREE=y
 # CONFIG_TOTALMP is not set
-# CONFIG_BOOTX_TEXT is not set
+CONFIG_BOOTX_TEXT=y
 # CONFIG_MOTOROLA_HOTSWAP is not set
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Plug and Play configuration
@@ -68,26 +73,48 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_IDE is not set
+CONFIG_BLK_DEV_FD=y
+CONFIG_BLK_DEV_IDE=y
 
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
-# CONFIG_BLK_DEV_HD_ONLY is not set
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+# CONFIG_BLK_DEV_IDESCSI is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+# CONFIG_BLK_DEV_IDEPCI is not set
+CONFIG_BLK_DEV_SL82C105=y
+CONFIG_BLK_DEV_IDE_PMAC=y
+CONFIG_BLK_DEV_IDEDMA_PMAC=y
+CONFIG_IDEDMA_PMAC_AUTO=y
+CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_IDE_CHIPSETS is not set
 # CONFIG_BLK_CPQ_DA is not set
 
 #
 # Additional Block Devices
 #
-# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_MD is not set
-# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_INITRD=y
 # CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_DAC960 is not set
 CONFIG_PARIDE_PARPORT=y
 # CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
+CONFIG_BLK_DEV_IDE_MODES=y
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -124,7 +151,7 @@
 #  
 #
 # CONFIG_IPX is not set
-# CONFIG_ATALK is not set
+CONFIG_ATALK=m
 # CONFIG_DECNET is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
@@ -149,7 +176,7 @@
 # SCSI support type (disk, tape, CD-ROM)
 #
 CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
+CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 # CONFIG_CHR_DEV_SG is not set
@@ -169,7 +196,11 @@
 # CONFIG_SCSI_AHA152X is not set
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
-# CONFIG_SCSI_AIC7XXX is not set
+CONFIG_SCSI_AIC7XXX=y
+# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
+CONFIG_AIC7XXX_PROC_STATS=y
+CONFIG_AIC7XXX_RESET_DELAY=15
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
@@ -183,12 +214,11 @@
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_G_NCR5380_PORT is not set
-# CONFIG_SCSI_G_NCR5380_MEM is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 # CONFIG_SCSI_NCR53C8XX is not set
 CONFIG_SCSI_SYM53C8XX=y
@@ -212,8 +242,9 @@
 # CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_ULTRASTOR is not set
 # CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_MESH is not set
-# CONFIG_SCSI_MAC53C94 is not set
+CONFIG_SCSI_MESH=y
+CONFIG_SCSI_MESH_SYNC_RATE=5
+CONFIG_SCSI_MAC53C94=y
 
 #
 # Network device support
@@ -233,28 +264,63 @@
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-# CONFIG_MACE is not set
-# CONFIG_BMAC is not set
-CONFIG_NCR885E=y
+CONFIG_MACE=y
+CONFIG_BMAC=y
+# CONFIG_NCR885E is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_RTL8139 is not set
 # CONFIG_SIS900 is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_ACENIC is not set
+# CONFIG_DM9102 is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
 # CONFIG_NET_ISA is not set
-# CONFIG_NET_EISA is not set
+CONFIG_NET_EISA=y
+CONFIG_PCNET32=y
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_ACENIC is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+CONFIG_DE4X5=y
+# CONFIG_DEC_ELCP is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEXPRESS_PRO100 is not set
+# CONFIG_LNE390 is not set
+# CONFIG_NE3210 is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_ES3210 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_ZNET is not set
 # CONFIG_NET_POCKET is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+# CONFIG_IPDDP is not set
+CONFIG_PPP=y
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
 # CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
 # CONFIG_NET_RADIO is not set
 
 #
-# Token ring devices
+# Token Ring driver support
 #
 # CONFIG_TR is not set
 # CONFIG_NET_FC is not set
@@ -264,10 +330,7 @@
 #
 # Wan interfaces
 #
-# CONFIG_HOSTESS_SV11 is not set
-# CONFIG_COSA is not set
-# CONFIG_SEALEVEL_4021 is not set
-# CONFIG_DLCI is not set
+# CONFIG_WAN is not set
 
 #
 # Amateur Radio support
@@ -289,12 +352,50 @@
 #
 
 #
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_CLGEN is not set
+# CONFIG_FB_PM2 is not set
+CONFIG_FB_OF=y
+CONFIG_FB_CONTROL=y
+CONFIG_FB_PLATINUM=y
+CONFIG_FB_VALKYRIE=y
+CONFIG_FB_IMSTT=y
+CONFIG_FB_CT65550=y
+# CONFIG_FB_S3TRIO is not set
+# CONFIG_FB_VGA16 is not set
+CONFIG_FB_MATROX=y
+# CONFIG_FB_MATROX_MILLENIUM is not set
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G100=y
+# CONFIG_FB_MATROX_MULTIHEAD is not set
+CONFIG_FB_ATY=y
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+CONFIG_FBCON_CFB32=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+CONFIG_FONT_SUN8x16=y
+CONFIG_FONT_SUN12x22=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
+CONFIG_SERIAL=m
 # CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 CONFIG_UNIX98_PTYS=y
@@ -307,13 +408,14 @@
 # CONFIG_ATIXL_BUSMOUSE is not set
 # CONFIG_LOGIBUSMOUSE is not set
 # CONFIG_MS_BUSMOUSE is not set
+# CONFIG_ADBMOUSE is not set
 CONFIG_MOUSE=y
 CONFIG_PSMOUSE=y
 # CONFIG_82C710_MOUSE is not set
 # CONFIG_PC110_PAD is not set
 # CONFIG_QIC02_TAPE is not set
 # CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
+CONFIG_NVRAM=y
 # CONFIG_RTC is not set
 
 #
@@ -333,14 +435,6 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_FT_NORMAL_DEBUG is not set
-# CONFIG_FT_FULL_DEBUG is not set
-# CONFIG_FT_NO_TRACE is not set
-# CONFIG_FT_NO_TRACE_AT_ALL is not set
-# CONFIG_FT_STD_FDC is not set
-# CONFIG_FT_MACH2 is not set
-# CONFIG_FT_PROBE_FC10 is not set
-# CONFIG_FT_ALT_FDC is not set
 # CONFIG_DRM is not set
 
 #
@@ -352,11 +446,14 @@
 # Filesystems
 #
 # CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS_FS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_FAT_FS is not set
+CONFIG_HFS_FS=y
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_UMSDOS_FS is not set
+CONFIG_VFAT_FS=y
 # CONFIG_EFS_FS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
@@ -369,6 +466,7 @@
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
+# CONFIG_BFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
 
@@ -376,10 +474,11 @@
 # Network File Systems
 #
 # CONFIG_CODA_FS is not set
-# CONFIG_NFS_FS is not set
-# CONFIG_NFSD is not set
-# CONFIG_SUNRPC is not set
-# CONFIG_LOCKD is not set
+CONFIG_NFS_FS=y
+CONFIG_NFSD=y
+# CONFIG_NFSD_SUN is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
 
@@ -394,16 +493,86 @@
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
-# CONFIG_NLS is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
 
 #
 # Sound
 #
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+CONFIG_DMASOUND=y
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+CONFIG_SOUND_OSS=y
+# CONFIG_SOUND_DMAP is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_SGALAXY is not set
+CONFIG_SOUND_CS4232=m
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_NM256 is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_SOFTOSS is not set
+# CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_UART6850 is not set
+
+#
+# Additional low level sound drivers
+#
+# CONFIG_LOWLEVEL_SOUND is not set
 
 #
 # Kernel hacking
 #
-# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_MAGIC_SYSRQ=y
 # CONFIG_KGDB is not set
-# CONFIG_XMON is not set
+CONFIG_XMON=y
diff -u --recursive --new-file v2.3.26/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- v2.3.26/linux/arch/ppc/kernel/chrp_setup.c	Wed Oct 27 16:34:12 1999
+++ linux/arch/ppc/kernel/chrp_setup.c	Wed Nov 10 22:18:38 1999
@@ -11,7 +11,6 @@
  */
 
 #include <linux/config.h>
-#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -576,9 +575,10 @@
 	ppc_md.calibrate_decr = chrp_calibrate_decr;
 
 #ifdef CONFIG_VT
-#ifdef CONFIG_MAC_KEYBOAD
+#ifdef CONFIG_MAC_KEYBOARD
 	if (adb_driver == NULL)
 	{
+#endif /* CONFIG_MAC_KEYBOAD */
 		ppc_md.kbd_setkeycode    = pckbd_setkeycode;
 		ppc_md.kbd_getkeycode    = pckbd_getkeycode;
 		ppc_md.kbd_translate     = pckbd_translate;
@@ -588,7 +588,8 @@
 #ifdef CONFIG_MAGIC_SYSRQ
 		ppc_md.ppc_kbd_sysrq_xlate	 = pckbd_sysrq_xlate;
 		SYSRQ_KEY = 0x54;
-#endif		
+#endif /* CONFIG_MAGIC_SYSRQ */
+#ifdef CONFIG_MAC_KEYBOARD
 	}
 	else
 	{
@@ -601,24 +602,13 @@
 #ifdef CONFIG_MAGIC_SYSRQ
 		ppc_md.ppc_kbd_sysrq_xlate	 = mackbd_sysrq_xlate;
 		SYSRQ_KEY = 0x69;
-#endif		
+#endif /* CONFIG_MAGIC_SYSRQ */
 	}
-#else
-	ppc_md.kbd_setkeycode    = pckbd_setkeycode;
-	ppc_md.kbd_getkeycode    = pckbd_getkeycode;
-	ppc_md.kbd_translate     = pckbd_translate;
-	ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
-	ppc_md.kbd_leds          = pckbd_leds;
-	ppc_md.kbd_init_hw       = pckbd_init_hw;
-#ifdef CONFIG_MAGIC_SYSRQ
-	ppc_md.ppc_kbd_sysrq_xlate	 = pckbd_sysrq_xlate;
-	SYSRQ_KEY = 0x54;
-#endif
+#endif /* CONFIG_MAC_KEYBOARD */
+#endif /* CONFIG_VT */
 	if ( rtas_data )
 		ppc_md.progress = chrp_progress;
-#endif
-#endif
-
+	
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
         ppc_ide_md.insw = chrp_ide_insw;
         ppc_ide_md.outsw = chrp_ide_outsw;
diff -u --recursive --new-file v2.3.26/linux/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S
--- v2.3.26/linux/arch/ppc/kernel/entry.S	Sat Oct  9 11:47:50 1999
+++ linux/arch/ppc/kernel/entry.S	Wed Nov 10 10:55:31 1999
@@ -411,9 +411,9 @@
 	addis	r7,r7,-KERNELBASE@h
 	lis	r8,rtas_entry@ha
 	lwz	r8,rtas_entry@l(r8)
-	addis	r5,r8,-KERNELBASE@h
 	mfmsr	r9
 	stw	r9,8(r1)
+	li	r0,0
 	ori	r0,r0,MSR_EE|MSR_SE|MSR_BE
 	andc	r0,r9,r0
 	andi.	r9,r9,MSR_ME|MSR_RI
diff -u --recursive --new-file v2.3.26/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- v2.3.26/linux/arch/ppc/kernel/head.S	Sun Nov  7 16:37:34 1999
+++ linux/arch/ppc/kernel/head.S	Mon Nov  8 12:32:50 1999
@@ -817,6 +817,15 @@
 	srwi	r4,r4,16
 	cmpi	0,r4,12
 	bnelr
+	
+	/* enable altivec so we can save */
+	mfmsr	r4
+	oris	r4,r4,MSR_VEC@h
+	mtmsr	r4
+
+	/* make sure our tsk pointer is valid */
+	cmpi	0,r3,0
+	beqlr
 
 	/* save altivec regs */
 	addi	r4,r3,THREAD+THREAD_VRSAVE
@@ -830,6 +839,11 @@
 	lis	r6,MSR_VEC@h
 	andi.	r5,r5,r6
 	stw	r5,_MSR(r4)
+
+	/* we've given up the altivec - clear the pointer */
+	li	r3,0
+	lis	r4,last_task_used_altivec@h
+	stw	r3,last_task_used_altivec@l(r4)
 #endif /* CONFIG_ALTIVEC */
 	blr
 	
diff -u --recursive --new-file v2.3.26/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- v2.3.26/linux/arch/ppc/kernel/pmac_setup.c	Sun Nov  7 16:37:34 1999
+++ linux/arch/ppc/kernel/pmac_setup.c	Wed Nov 10 22:18:38 1999
@@ -39,7 +39,6 @@
 #include <linux/ioport.h>
 #include <linux/major.h>
 #include <linux/blk.h>
-#include <linux/ide.h>
 #include <linux/vt_kern.h>
 #include <linux/console.h>
 #include <linux/ide.h>
diff -u --recursive --new-file v2.3.26/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- v2.3.26/linux/arch/ppc/kernel/ppc_ksyms.c	Sun Nov  7 16:37:34 1999
+++ linux/arch/ppc/kernel/ppc_ksyms.c	Mon Nov  8 14:28:34 1999
@@ -268,3 +268,4 @@
 void ppc_irq_dispatch_handler(struct pt_regs *, int);
 EXPORT_SYMBOL(ppc_irq_dispatch_handler);
 EXPORT_SYMBOL(decrementer_count);
+EXPORT_SYMBOL(get_wchan);
diff -u --recursive --new-file v2.3.26/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c
--- v2.3.26/linux/arch/ppc/kernel/prep_setup.c	Fri Oct 22 13:21:45 1999
+++ linux/arch/ppc/kernel/prep_setup.c	Wed Nov 10 22:18:39 1999
@@ -210,7 +210,7 @@
 }
 
 void __init
-prep_setup_arch()
+prep_setup_arch(void)
 {
 	extern char cmd_line[];
 	unsigned char reg;
diff -u --recursive --new-file v2.3.26/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c
--- v2.3.26/linux/arch/ppc/kernel/process.c	Sun Nov  7 16:37:34 1999
+++ linux/arch/ppc/kernel/process.c	Wed Nov 10 10:55:31 1999
@@ -210,6 +210,11 @@
 	prev->last_processor = prev->processor;
 	current_set[smp_processor_id()] = new;
 #endif /* __SMP__ */
+	/* Avoid the trap.  On smp this this never happens since
+	 * we don't set last_task_used_altivec -- Cort
+	 */
+	if ( last_task_used_altivec == new )
+		new->thread.regs->msr |= MSR_VEC;
 	new_thread = &new->thread;
 	old_thread = &current->thread;
 	*last = _switch(old_thread, new_thread);
@@ -574,3 +579,32 @@
 	orig_y = y;
 }
 #endif
+
+/*
+ * 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 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;
+}
diff -u --recursive --new-file v2.3.26/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v2.3.26/linux/arch/ppc/kernel/setup.c	Sun Nov  7 16:37:34 1999
+++ linux/arch/ppc/kernel/setup.c	Wed Nov 10 10:55:31 1999
@@ -389,12 +389,10 @@
 
 	if ( have_of )
 	{
-#ifdef CONFIG_MACH_SPECIFIC
 		/* prom_init has already been called from __start */
 		if (boot_infos)
 			relocate_nodes();
 		finish_device_tree();
-#endif /* CONFIG_MACH_SPECIFIC	*/
 		/*
 		 * If we were booted via quik, r3 points to the physical
 		 * address of the command-line parameters.
@@ -450,7 +448,7 @@
 	int_control.int_cli = __no_use_cli;
 	int_control.int_save_flags = __no_use_save_flags;
 	int_control.int_restore_flags = __no_use_restore_flags;
-	
+
 	switch (_machine)
 	{
 	case _MACH_Pmac:
diff -u --recursive --new-file v2.3.26/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c
--- v2.3.26/linux/arch/ppc/kernel/traps.c	Sun Nov  7 16:37:34 1999
+++ linux/arch/ppc/kernel/traps.c	Mon Nov  8 12:32:50 1999
@@ -149,19 +149,19 @@
 		show_regs(regs);
 		panic("Kernel Used Altivec with MSR_VEC off!\n");
 	}
-#ifdef __SMP__
-	printk("User Mode altivec trap should not happen in SMP!\n");
-#else
+
 	if ( last_task_used_altivec != current )
 	{
 		if ( last_task_used_altivec )
 			giveup_altivec(current);
 		load_up_altivec(current);
+		/* on SMP we always save/restore on switch */
+#ifndef __SMP__		
 		last_task_used_altivec = current;
+#endif		
 	}
 	/* enable altivec for the task on return */
 	regs->msr |= MSR_VEC;
-#endif		
 }
 
 void
diff -u --recursive --new-file v2.3.26/linux/arch/ppc/mm/extable.c linux/arch/ppc/mm/extable.c
--- v2.3.26/linux/arch/ppc/mm/extable.c	Fri Feb 20 18:28:21 1998
+++ linux/arch/ppc/mm/extable.c	Wed Nov 10 22:18:39 1999
@@ -43,13 +43,18 @@
 #else
 	/* The kernel is the last "module" -- no need to treat it special.  */
 	struct module *mp;
+	read_lock(&modlist_lock);
 	for (mp = module_list; mp != NULL; mp = mp->next) {
 		if (mp->ex_table_start == NULL)
 			continue;
 		ret = search_one_table(mp->ex_table_start,
 				       mp->ex_table_end - 1, addr);
-		if (ret) return ret;
+		if (ret) {
+			read_unlock(&modlist_lock);
+			return ret;
+		}
 	}
+	read_unlock(&modlist_lock);
 #endif
 
 	return 0;
diff -u --recursive --new-file v2.3.26/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- v2.3.26/linux/arch/ppc/mm/init.c	Sun Nov  7 16:37:34 1999
+++ linux/arch/ppc/mm/init.c	Wed Nov 10 22:18:39 1999
@@ -348,7 +348,7 @@
 	i = max_mapnr;
 	val->totalram = 0;
 	val->sharedram = 0;
-	val->freeram = nr_free_pages << PAGE_SHIFT;
+	val->freeram = nr_free_pages();
 	val->bufferram = atomic_read(&buffermem_pages);
 	while (i-- > 0)  {
 		if (PageReserved(mem_map+i))
@@ -1215,8 +1215,6 @@
 	 */
 	empty_bad_page = alloc_bootmem_pages(PAGE_SIZE);
 	empty_bad_page_table = alloc_bootmem_pages(PAGE_SIZE);
-
-	free_area_init(max_low_pfn);
 }
 
 void __init mem_init(void)
diff -u --recursive --new-file v2.3.26/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c
--- v2.3.26/linux/arch/sparc/kernel/process.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/kernel/process.c	Mon Nov  8 14:28:34 1999
@@ -702,3 +702,37 @@
 			   "g1", "g2", "g3", "o0", "o1", "memory", "cc");
 	return retval;
 }
+
+/*
+ * 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 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
diff -u --recursive --new-file v2.3.26/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c
--- v2.3.26/linux/arch/sparc/kernel/sparc_ksyms.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc/kernel/sparc_ksyms.c	Mon Nov  8 14:28:34 1999
@@ -279,3 +279,5 @@
 EXPORT_SYMBOL_DOT(umul);
 EXPORT_SYMBOL_DOT(div);
 EXPORT_SYMBOL_DOT(udiv);
+
+EXPORT_SYMBOL(get_wchan);
diff -u --recursive --new-file v2.3.26/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c
--- v2.3.26/linux/arch/sparc64/kernel/process.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc64/kernel/process.c	Mon Nov  8 14:28:34 1999
@@ -802,3 +802,35 @@
 	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 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;
+}
diff -u --recursive --new-file v2.3.26/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c
--- v2.3.26/linux/arch/sparc64/kernel/sparc64_ksyms.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc64/kernel/sparc64_ksyms.c	Mon Nov  8 14:28:34 1999
@@ -311,3 +311,5 @@
 EXPORT_SYMBOL_NOVERS(memcpy);
 EXPORT_SYMBOL_NOVERS(memset);
 EXPORT_SYMBOL_NOVERS(memmove);
+
+EXPORT_SYMBOL(get_wchan);
diff -u --recursive --new-file v2.3.26/linux/drivers/acorn/scsi/acornscsi.c linux/drivers/acorn/scsi/acornscsi.c
--- v2.3.26/linux/drivers/acorn/scsi/acornscsi.c	Mon Aug  2 10:19:52 1999
+++ linux/drivers/acorn/scsi/acornscsi.c	Thu Nov 11 16:57:30 1999
@@ -190,10 +190,6 @@
 unsigned int sdtr_period = SDTR_PERIOD;
 unsigned int sdtr_size   = SDTR_SIZE;
 
-static struct proc_dir_entry proc_scsi_acornscsi = {
-	PROC_SCSI_EATA, 9, "acornscsi", S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 static void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result);
 static int acornscsi_reconnect_finish(AS_Host *host);
 static void acornscsi_dma_cleanup(AS_Host *host);
@@ -2875,7 +2871,7 @@
     struct Scsi_Host *instance;
     AS_Host *host;
 
-    tpnt->proc_dir = &proc_scsi_acornscsi;
+    tpnt->proc_name = "acornscsi";
 
     for (i = 0; i < MAX_ECARDS; i++)
 	ecs[i] = NULL;
diff -u --recursive --new-file v2.3.26/linux/drivers/acorn/scsi/acornscsi.h linux/drivers/acorn/scsi/acornscsi.h
--- v2.3.26/linux/drivers/acorn/scsi/acornscsi.h	Thu Jun 17 01:11:35 1999
+++ linux/drivers/acorn/scsi/acornscsi.h	Thu Nov 11 16:57:30 1999
@@ -23,10 +23,7 @@
 #define CAN_QUEUE 16
 #endif
 
-#ifndef PROC_SCSI_AKA30
 #include "linux/proc_fs.h"
-#define PROC_SCSI_AKA30 PROC_SCSI_EATA
-#endif
 
 #include <scsi/scsicam.h>
 
diff -u --recursive --new-file v2.3.26/linux/drivers/acorn/scsi/arxescsi.c linux/drivers/acorn/scsi/arxescsi.c
--- v2.3.26/linux/drivers/acorn/scsi/arxescsi.c	Thu Jun 17 01:11:35 1999
+++ linux/drivers/acorn/scsi/arxescsi.c	Thu Nov 11 16:57:30 1999
@@ -58,11 +58,6 @@
 
 static struct expansion_card *ecs[MAX_ECARDS];
 
-static struct proc_dir_entry proc_scsi_arxescsi = {
-	PROC_SCSI_QLOGICFAS, 6, "arxescsi",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 /*
  * Function: int arxescsi_dma_setup(host, SCpnt, direction, min_type)
  * Purpose : initialises DMA/PIO
@@ -223,7 +218,7 @@
 	int count = 0;
 	struct Scsi_Host *host;
   
-	tpnt->proc_dir = &proc_scsi_arxescsi;
+	tpnt->proc_name = "arxescsi";
 	memset(ecs, 0, sizeof (ecs));
 
 	ecard_startfind();
diff -u --recursive --new-file v2.3.26/linux/drivers/acorn/scsi/cumana_1.c linux/drivers/acorn/scsi/cumana_1.c
--- v2.3.26/linux/drivers/acorn/scsi/cumana_1.c	Sat Jul 18 11:55:24 1998
+++ linux/drivers/acorn/scsi/cumana_1.c	Thu Nov 11 16:57:30 1999
@@ -69,10 +69,6 @@
 	{ 0xffff, 0xffff }
 };
 
-static struct proc_dir_entry proc_scsi_cumana1 = {
-	PROC_SCSI_T128, 12, "CumanaSCSI-1", S_IFDIR | S_IRUGO, S_IXUGO, 2
-};
-
 /*
  * Function : cumanascsi_setup(char *str, int *ints)
  *
@@ -106,7 +102,7 @@
     int count = 0;
     struct Scsi_Host *instance;
 
-    tpnt->proc_dir = &proc_scsi_cumana1;
+    tpnt->proc_name = "CumanaSCSI-1";
 
     memset (ecs, 0, sizeof (ecs));
 
diff -u --recursive --new-file v2.3.26/linux/drivers/acorn/scsi/cumana_2.c linux/drivers/acorn/scsi/cumana_2.c
--- v2.3.26/linux/drivers/acorn/scsi/cumana_2.c	Thu Jun 17 01:11:35 1999
+++ linux/drivers/acorn/scsi/cumana_2.c	Thu Nov 11 16:57:30 1999
@@ -84,11 +84,6 @@
  */
 int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
 
-static struct proc_dir_entry proc_scsi_cumanascsi_2 = {
-	PROC_SCSI_QLOGICFAS, 6, "cumanascs2",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 /* Prototype: void cumanascsi_2_irqenable(ec, irqnr)
  * Purpose  : Enable interrupts on Cumana SCSI 2 card
  * Params   : ec    - expansion card structure
@@ -329,7 +324,7 @@
 	int count = 0;
 	struct Scsi_Host *host;
   
-	tpnt->proc_dir = &proc_scsi_cumanascsi_2;
+	tpnt->proc_name = "cumanascs2";
 	memset(ecs, 0, sizeof (ecs));
 
 	ecard_startfind();
diff -u --recursive --new-file v2.3.26/linux/drivers/acorn/scsi/ecoscsi.c linux/drivers/acorn/scsi/ecoscsi.c
--- v2.3.26/linux/drivers/acorn/scsi/ecoscsi.c	Sat Jul 18 11:55:24 1998
+++ linux/drivers/acorn/scsi/ecoscsi.c	Thu Nov 11 16:57:30 1999
@@ -57,10 +57,6 @@
 #include "../../scsi/NCR5380.h"
 #include "../../scsi/constants.h"
 
-static struct proc_dir_entry proc_scsi_ecoscsi = {
-	PROC_SCSI_GENERIC_NCR5380, 7, "ecoscsi", S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 static char ecoscsi_read(struct Scsi_Host *instance, int reg)
 {
   int iobase = instance->io_port;
@@ -104,7 +100,7 @@
 {
     struct Scsi_Host *instance;
 
-    tpnt->proc_dir = &proc_scsi_ecoscsi;
+    tpnt->proc_name = "ecoscsi";
 
     instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
     instance->io_port = 0x80ce8000;
diff -u --recursive --new-file v2.3.26/linux/drivers/acorn/scsi/eesox.c linux/drivers/acorn/scsi/eesox.c
--- v2.3.26/linux/drivers/acorn/scsi/eesox.c	Thu Jun 17 01:11:35 1999
+++ linux/drivers/acorn/scsi/eesox.c	Thu Nov 11 16:57:30 1999
@@ -81,11 +81,6 @@
  */
 int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
 
-static struct proc_dir_entry proc_scsi_eesox = {
-	PROC_SCSI_QLOGICISP, 5, "eesox",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 /* Prototype: void eesoxscsi_irqenable(ec, irqnr)
  * Purpose  : Enable interrupts on EESOX SCSI card
  * Params   : ec    - expansion card structure
@@ -334,7 +329,7 @@
 	int count = 0;
 	struct Scsi_Host *host;
   
-	tpnt->proc_dir = &proc_scsi_eesox;
+	tpnt->proc_name = "eesox";
 	memset(ecs, 0, sizeof (ecs));
 
 	ecard_startfind();
diff -u --recursive --new-file v2.3.26/linux/drivers/acorn/scsi/oak.c linux/drivers/acorn/scsi/oak.c
--- v2.3.26/linux/drivers/acorn/scsi/oak.c	Sat Jul 18 11:55:24 1998
+++ linux/drivers/acorn/scsi/oak.c	Thu Nov 11 16:57:30 1999
@@ -71,10 +71,6 @@
 	{ 0xffff, 0xffff }
 };
 
-static struct proc_dir_entry proc_scsi_oakscsi = {
-	PROC_SCSI_PAS16, 7, "oakscsi", S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 #define OAK_ADDRESS(card) (ecard_address((card), ECARD_MEMC, 0))
 #define OAK_IRQ(card)	  (IRQ_NONE)
 /*
@@ -95,7 +91,7 @@
     int count = 0;
     struct Scsi_Host *instance;
 
-    tpnt->proc_dir = &proc_scsi_oakscsi;
+    tpnt->proc_name = "oakscsi";
 
     memset (ecs, 0, sizeof (ecs));
 
diff -u --recursive --new-file v2.3.26/linux/drivers/acorn/scsi/powertec.c linux/drivers/acorn/scsi/powertec.c
--- v2.3.26/linux/drivers/acorn/scsi/powertec.c	Thu Jun 17 01:11:35 1999
+++ linux/drivers/acorn/scsi/powertec.c	Thu Nov 11 16:57:30 1999
@@ -81,11 +81,6 @@
  */
 int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
 
-static struct proc_dir_entry proc_scsi_powertec = {
-	PROC_SCSI_QLOGICISP, 8, "powertec",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 /* Prototype: void powertecscsi_irqenable(ec, irqnr)
  * Purpose  : Enable interrupts on Powertec SCSI card
  * Params   : ec    - expansion card structure
@@ -236,7 +231,7 @@
 	int count = 0;
 	struct Scsi_Host *host;
   
-	tpnt->proc_dir = &proc_scsi_powertec;
+	tpnt->proc_name = "powertec";
 	memset(ecs, 0, sizeof (ecs));
 
 	ecard_startfind();
diff -u --recursive --new-file v2.3.26/linux/drivers/block/amiflop.c linux/drivers/block/amiflop.c
--- v2.3.26/linux/drivers/block/amiflop.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/block/amiflop.c	Mon Nov  8 11:03:20 1999
@@ -1821,13 +1821,13 @@
 		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 -u --recursive --new-file v2.3.26/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.3.26/linux/drivers/block/ide.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/block/ide.c	Thu Nov 11 16:03:36 1999
@@ -307,6 +307,7 @@
 	struct hd_driveid *id = drive->id;
 
 	if (drive->removable && id != NULL) {
+		if (id->config == 0x848a) return 1;	/* CompactFlash */
 		if (!strncmp(id->model, "KODAK ATA_FLASH", 15)	/* Kodak */
 		 || !strncmp(id->model, "Hitachi CV", 10)	/* Hitachi */
 		 || !strncmp(id->model, "SunDisk SDCFB", 13)	/* SunDisk */
diff -u --recursive --new-file v2.3.26/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v2.3.26/linux/drivers/block/ll_rw_blk.c	Mon Nov  1 13:56:26 1999
+++ linux/drivers/block/ll_rw_blk.c	Thu Nov 11 10:33:42 1999
@@ -22,6 +22,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <linux/blk.h>
+#include <linux/highmem.h>
 
 #include <linux/module.h>
 
@@ -491,6 +492,15 @@
 	   won't clear the mapped bit under us. */
 	if (!buffer_mapped(bh))
 		BUG();
+
+	/*
+	 * Temporary solution - in 2.5 this will be done by the lowlevel
+	 * driver. Create a bounce buffer if the buffer data points into
+	 * high memory - keep the original buffer otherwise.
+	 */
+#if CONFIG_HIGHMEM
+	bh = create_bounce(rw, bh);
+#endif
 
 /* look for a free request. */
        /* Loop uses two requests, 1 for loop and 1 for the real device.
diff -u --recursive --new-file v2.3.26/linux/drivers/block/nbd.c linux/drivers/block/nbd.c
--- v2.3.26/linux/drivers/block/nbd.c	Mon Jul  5 20:07:02 1999
+++ linux/drivers/block/nbd.c	Wed Nov 10 12:38:13 1999
@@ -35,6 +35,7 @@
 #include <linux/errno.h>
 #include <linux/file.h>
 #include <linux/ioctl.h>
+#include <net/sock.h>
 
 #include <asm/segment.h>
 #include <asm/uaccess.h>
@@ -105,6 +106,7 @@
 
 
 	do {
+		sock->sk->allocation = GFP_ATOMIC;
 		iov.iov_base = buf;
 		iov.iov_len = size;
 		msg.msg_name = NULL;
diff -u --recursive --new-file v2.3.26/linux/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- v2.3.26/linux/drivers/cdrom/cdrom.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/cdrom/cdrom.c	Thu Nov 11 16:57:30 1999
@@ -2531,23 +2531,6 @@
 
 static struct ctl_table_header *cdrom_sysctl_header;
 
-/*
- * This is called as the fill_inode function when an inode
- * is going into (fill = 1) or out of service (fill = 0).
- * We use it here to manage the module use counts.
- *
- * Note: only the top-level directory needs to do this; if
- * a lower level is referenced, the parent will be as well.
- */
-static void cdrom_procfs_modcount(struct inode *inode, int fill)
-{
-	if (fill) {
-		MOD_INC_USE_COUNT;
-	} else {
-		MOD_DEC_USE_COUNT;
-	}
-}
-
 static void cdrom_sysctl_register(void)
 {
 	static int initialized = 0;
@@ -2556,7 +2539,7 @@
 		return;
 
 	cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 1);
-	cdrom_root_table->child->de->fill_inode = &cdrom_procfs_modcount;
+	cdrom_root_table->child->de->owner = THIS_MODULE;
 
 	/* set the defaults */
 	cdrom_sysctl_settings.autoclose = autoclose;
diff -u --recursive --new-file v2.3.26/linux/drivers/char/Config.in linux/drivers/char/Config.in
--- v2.3.26/linux/drivers/char/Config.in	Mon Nov  1 13:56:26 1999
+++ linux/drivers/char/Config.in	Wed Nov 10 22:23:28 1999
@@ -6,7 +6,7 @@
 
 bool 'Virtual terminal' CONFIG_VT
 if [ "$CONFIG_VT" = "y" ]; then
-  bool 'Support for console on virtual terminal' CONFIG_VT_CONSOLE
+   bool '  Support for console on virtual terminal' CONFIG_VT_CONSOLE
 fi
 tristate 'Standard/generic (dumb) serial support' CONFIG_SERIAL
 if [ "$CONFIG_SERIAL" = "y" ]; then
@@ -22,103 +22,101 @@
 fi
 bool 'Non-standard serial port support' CONFIG_SERIAL_NONSTANDARD
 if [ "$CONFIG_SERIAL_NONSTANDARD" = "y" ]; then
-   tristate 'Comtrol Rocketport support' CONFIG_ROCKETPORT
-   tristate 'Digiboard Intelligent Async Support' CONFIG_DIGIEPCA
+   tristate '  Comtrol Rocketport support' CONFIG_ROCKETPORT
+   tristate '  Digiboard Intelligent Async Support' CONFIG_DIGIEPCA
    if [ "$CONFIG_DIGIEPCA" = "n" ]; then
-      tristate 'Digiboard PC/Xx Support' CONFIG_DIGI
+      tristate '  Digiboard PC/Xx Support' CONFIG_DIGI
    fi
-   tristate 'Cyclades async mux support' CONFIG_CYCLADES
+   tristate '  Cyclades async mux support' CONFIG_CYCLADES
    if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_CYCLADES" != "n" ]; then
-      bool '  Cyclades-Z interrupt mode operation (EXPERIMENTAL)' CONFIG_CYZ_INTR
+      bool '    Cyclades-Z interrupt mode operation (EXPERIMENTAL)' CONFIG_CYZ_INTR
    fi
-   bool 'Stallion multiport serial support' CONFIG_STALDRV
+   bool '  Stallion multiport serial support' CONFIG_STALDRV
    if [ "$CONFIG_STALDRV" = "y" ]; then
-     tristate '  Stallion EasyIO or EC8/32 support' CONFIG_STALLION
-     tristate '  Stallion EC8/64, ONboard, Brumby support' CONFIG_ISTALLION
+     tristate '    Stallion EasyIO or EC8/32 support' CONFIG_STALLION
+     tristate '    Stallion EC8/64, ONboard, Brumby support' CONFIG_ISTALLION
    fi
-   tristate 'SDL RISCom/8 card support' CONFIG_RISCOM8
-   tristate 'Computone IntelliPort Plus serial support' CONFIG_COMPUTONE
-   tristate 'Specialix IO8+ card support' CONFIG_SPECIALIX
+   tristate '  SDL RISCom/8 card support' CONFIG_RISCOM8
+   tristate '  Computone IntelliPort Plus serial support' CONFIG_COMPUTONE
+   tristate '  Specialix IO8+ card support' CONFIG_SPECIALIX
    if [ "$CONFIG_SPECIALIX" != "n" ]; then
-     bool 'Specialix DTR/RTS pin is RTS' CONFIG_SPECIALIX_RTSCTS
+      bool '  Specialix DTR/RTS pin is RTS' CONFIG_SPECIALIX_RTSCTS
    fi 
-   tristate 'Specialix SX (and SI) card support' CONFIG_SX
-   tristate 'Hayes ESP serial port support' CONFIG_ESPSERIAL
+   tristate '  Specialix SX (and SI) card support' CONFIG_SX
+   tristate '  Hayes ESP serial port support' CONFIG_ESPSERIAL
    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-	dep_tristate 'Multi-Tech multiport card support' CONFIG_ISI m
+      dep_tristate '  Multi-Tech multiport card support (EXPERIMENTAL)' CONFIG_ISI m
    fi
-   dep_tristate 'Microgate SyncLink card support' CONFIG_SYNCLINK m
-   dep_tristate 'HDLC line discipline support' CONFIG_N_HDLC m
+   dep_tristate '  Microgate SyncLink card support' CONFIG_SYNCLINK m
+   dep_tristate '  HDLC line discipline support' CONFIG_N_HDLC m
 fi
 bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
 if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
-	int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
+   int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
 fi
 if [ "$CONFIG_PARPORT" != "n" ]; then
-  dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
-  if [ "$CONFIG_PRINTER" != "n" ]; then
-    bool '  Support for console on line printer' CONFIG_LP_CONSOLE
-  fi
-  dep_tristate 'Support for user-space parallel port device drivers' CONFIG_PPDEV $CONFIG_PARPORT
+   dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
+   if [ "$CONFIG_PRINTER" != "n" ]; then
+      bool '  Support for console on line printer' CONFIG_LP_CONSOLE
+   fi
+   dep_tristate 'Support for user-space parallel port device drivers' CONFIG_PPDEV $CONFIG_PARPORT
 fi
 
 mainmenu_option next_comment
 comment 'Mice'
 tristate 'Bus Mouse Support' CONFIG_BUSMOUSE
 if [ "$CONFIG_BUSMOUSE" != "n" ]; then
-  dep_tristate 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE $CONFIG_BUSMOUSE
-  dep_tristate 'Logitech busmouse support' CONFIG_LOGIBUSMOUSE $CONFIG_BUSMOUSE
-  dep_tristate 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE $CONFIG_BUSMOUSE
-  if [ "$CONFIG_ADB" = "y" ]; then
-    dep_tristate 'Apple Desktop Bus mouse support' CONFIG_ADBMOUSE $CONFIG_BUSMOUSE
-  fi
+   dep_tristate '  ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE $CONFIG_BUSMOUSE
+   dep_tristate '  Logitech busmouse support' CONFIG_LOGIBUSMOUSE $CONFIG_BUSMOUSE
+   dep_tristate '  Microsoft busmouse support' CONFIG_MS_BUSMOUSE $CONFIG_BUSMOUSE
+   if [ "$CONFIG_ADB" = "y" ]; then
+      dep_tristate '  Apple Desktop Bus mouse support' CONFIG_ADBMOUSE $CONFIG_BUSMOUSE
+   fi
 fi
 
 tristate 'Mouse Support (not serial and bus mice)' CONFIG_MOUSE
 if [ "$CONFIG_MOUSE" != "n" ]; then
-	bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE
-	tristate 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE
-	tristate 'PC110 digitizer pad support' CONFIG_PC110_PAD
+   bool '  PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE
+   tristate '  C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE
+   tristate '  PC110 digitizer pad support' CONFIG_PC110_PAD
 fi
 endmenu
 
 tristate 'QIC-02 tape support' CONFIG_QIC02_TAPE
 if [ "$CONFIG_QIC02_TAPE" != "n" ]; then
-  bool 'Do you want runtime configuration for QIC-02' CONFIG_QIC02_DYNCONF
-  if [ "$CONFIG_QIC02_DYNCONF" != "y" ]; then
-    comment '  Edit configuration parameters in ./include/linux/tpqic02.h!'
-  else
-    comment '  Setting runtime QIC-02 configuration is done with qic02conf'
-    comment '  from the tpqic02-support package.  It is available at'
-    comment '  metalab.unc.edu or ftp://titus.cfw.com/pub/Linux/util/'
-  fi
-  dep_tristate 'Zoran ZR36057/36060 support' CONFIG_VIDEO_ZORAN $CONFIG_VIDEO_DEV
-  dep_tristate '  Include support for Iomega Buz' CONFIG_VIDEO_BUZ $CONFIG_VIDEO_ZORAN
+   bool '  Do you want runtime configuration for QIC-02' CONFIG_QIC02_DYNCONF
+   if [ "$CONFIG_QIC02_DYNCONF" != "y" ]; then
+      comment '  Edit configuration parameters in ./include/linux/tpqic02.h!'
+   else
+      comment '  Setting runtime QIC-02 configuration is done with qic02conf'
+      comment '  from the tpqic02-support package.  It is available at'
+      comment '  metalab.unc.edu or ftp://titus.cfw.com/pub/Linux/util/'
+   fi
 fi
 
+mainmenu_option next_comment
+comment 'Watchdog Cards'
 bool 'Watchdog Timer Support'	CONFIG_WATCHDOG
 if [ "$CONFIG_WATCHDOG" != "n" ]; then
-  mainmenu_option next_comment
-  comment 'Watchdog Cards'
-  bool '  Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT
-  tristate '  WDT Watchdog timer' CONFIG_WDT
-  if [ "$CONFIG_WDT" != "n" ]; then
-     bool '    WDT501 features' CONFIG_WDT_501
-     if [ "$CONFIG_WDT_501" = "y" ]; then
+   bool '  Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT
+   tristate '  WDT Watchdog timer' CONFIG_WDT
+   if [ "$CONFIG_WDT" != "n" ]; then
+      bool '    WDT501 features' CONFIG_WDT_501
+      if [ "$CONFIG_WDT_501" = "y" ]; then
          bool '      Fan Tachometer' CONFIG_WDT_501_FAN
-     fi
-  fi
-  tristate '  Software Watchdog' CONFIG_SOFT_WATCHDOG
-  tristate '  Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG
-  tristate '  Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT
-  endmenu
+      fi
+   fi
+   tristate '  Software Watchdog' CONFIG_SOFT_WATCHDOG
+   tristate '  Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG
+   tristate '  Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT
 fi
+endmenu
 
 
 tristate '/dev/nvram support' CONFIG_NVRAM
 bool 'Enhanced Real Time Clock Support' CONFIG_RTC
 if [ "$CONFIG_ALPHA_BOOK1" = "y" ]; then
-  bool 'Tadpole ANA H8 Support'  CONFIG_H8
+   bool 'Tadpole ANA H8 Support'  CONFIG_H8
 fi
 
 mainmenu_option next_comment
@@ -126,68 +124,76 @@
 
 tristate 'Video For Linux' CONFIG_VIDEO_DEV
 if [ "$CONFIG_VIDEO_DEV" != "n" ]; then
-  dep_tristate 'ADS Cadet AM/FM Tuner' CONFIG_RADIO_CADET $CONFIG_VIDEO_DEV
-  dep_tristate 'AIMSlab RadioTrack (aka RadioReveal) support' CONFIG_RADIO_RTRACK $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_RADIO_RTRACK" = "y" ]; then
-    hex '  RadioTrack i/o port (0x20f or 0x30f)' CONFIG_RADIO_RTRACK_PORT 20f
-  fi
-  dep_tristate 'AIMSlab RadioTrack II support' CONFIG_RADIO_RTRACK2 $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_RADIO_RTRACK2" = "y" ]; then
-    hex '  RadioTrack II i/o port (0x20c or 0x30c)' CONFIG_RADIO_RTRACK2_PORT 30c
-  fi
-  dep_tristate 'Aztech/Packard Bell Radio' CONFIG_RADIO_AZTECH $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_RADIO_AZTECH" = "y" ]; then
-    hex '  Aztech/Packard Bell I/O port (0x350 or 0x358)' CONFIG_RADIO_AZTECH_PORT 350
-  fi
-  dep_tristate 'GemTek Radio Card support' CONFIG_RADIO_GEMTEK $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_RADIO_GEMTEK" = "y" ]; then
-    hex '  GemTek i/o port (0x20c, 0x30c, 0x24c or 0x34c)' CONFIG_RADIO_GEMTEK_PORT 34c
-  fi
-  dep_tristate 'Miro PCM20 Radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV
-  dep_tristate 'TerraTec ActiveRadio ISA Standalone' CONFIG_RADIO_TERRATEC $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_RADIO_TERRATEC" = "y" ]; then
-    hex '  Terratec i/o port (normally 0x590)' CONFIG_RADIO_TERRATEC_PORT 590
-  fi
-  dep_tristate 'Trust FM radio card' CONFIG_RADIO_TRUST $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_RADIO_TRUST" = "y" ]; then
-    hex '  Trust i/o port (usually 0x350 or 0x358)' CONFIG_RADIO_TRUST_PORT 350
-  fi
-  if [ "$CONFIG_PCI" != "n" ]; then
-    dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV
-  fi
-  if [ "$CONFIG_PARPORT" != "n" ]; then
-    dep_tristate 'Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT
-    dep_tristate 'Colour QuickCam Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT
-  fi
-  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-    if [ "$CONFIG_SGI" = "y" ]; then
-      dep_tristate 'SGI Vino Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_VINO $CONFIG_VIDEO_DEV
-    fi
-  fi
-  dep_tristate 'Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_PMAC" = "y" ]; then
-    dep_tristate 'PlanB Video-In on PowerMac' CONFIG_VIDEO_PLANB $CONFIG_VIDEO_DEV
-  fi
-  dep_tristate 'SAA5249 Teletext processor' CONFIG_VIDEO_SAA5249 $CONFIG_VIDEO_DEV
-  dep_tristate 'SF16FMI Radio' CONFIG_RADIO_SF16FMI $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_RADIO_SF16FMI" = "y" ]; then
-    hex '  SF16FMI I/O port (0x284 or 0x384)' CONFIG_RADIO_SF16FMI_PORT 284
-  fi
-  dep_tristate 'Typhoon Radio (a.k.a. EcoRadio)' CONFIG_RADIO_TYPHOON $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_PROC_FS" = "y" ]; then
+   dep_tristate '  I2C on parallel port' CONFIG_I2C_PARPORT $CONFIG_PARPORT
+   comment 'Radio/Video Adapters'
+   dep_tristate '  ADS Cadet AM/FM Tuner' CONFIG_RADIO_CADET $CONFIG_VIDEO_DEV
+   dep_tristate '  AIMSlab RadioTrack (aka RadioReveal) support' CONFIG_RADIO_RTRACK $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_RADIO_RTRACK" = "y" ]; then
+      hex '  RadioTrack i/o port (0x20f or 0x30f)' CONFIG_RADIO_RTRACK_PORT 20f
+   fi
+   dep_tristate '  AIMSlab RadioTrack II support' CONFIG_RADIO_RTRACK2 $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_RADIO_RTRACK2" = "y" ]; then
+      hex '    RadioTrack II i/o port (0x20c or 0x30c)' CONFIG_RADIO_RTRACK2_PORT 30c
+   fi
+   dep_tristate '  Aztech/Packard Bell Radio' CONFIG_RADIO_AZTECH $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_RADIO_AZTECH" = "y" ]; then
+      hex '    Aztech/Packard Bell I/O port (0x350 or 0x358)' CONFIG_RADIO_AZTECH_PORT 350
+   fi
+   if [ "$CONFIG_PCI" != "n" ]; then
+      dep_tristate '  BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV
+   fi
+   dep_tristate '  GemTek Radio Card support' CONFIG_RADIO_GEMTEK $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_RADIO_GEMTEK" = "y" ]; then
+      hex '    GemTek i/o port (0x20c, 0x30c, 0x24c or 0x34c)' CONFIG_RADIO_GEMTEK_PORT 34c
+   fi
+   dep_tristate '  Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV
+   dep_tristate '  Miro PCM20 Radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_PMAC" = "y" ]; then
+      dep_tristate '  PlanB Video-In on PowerMac' CONFIG_VIDEO_PLANB $CONFIG_VIDEO_DEV
+   fi
+   if [ "$CONFIG_PARPORT" != "n" ]; then
+      dep_tristate '  Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT
+      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+	 dep_tristate '  QuickCam Colour Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT
+      fi
+   fi
+   dep_tristate '  SAA5249 Teletext processor' CONFIG_VIDEO_SAA5249 $CONFIG_VIDEO_DEV
+   dep_tristate '  SF16FMI Radio' CONFIG_RADIO_SF16FMI $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_RADIO_SF16FMI" = "y" ]; then
+      hex '    SF16FMI I/O port (0x284 or 0x384)' CONFIG_RADIO_SF16FMI_PORT 284
+   fi
+   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+      if [ "$CONFIG_SGI" = "y" ]; then
+	 dep_tristate '  SGI Vino Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_VINO $CONFIG_VIDEO_DEV
+      fi
+   fi
+   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+      dep_tristate '  Stradis 4:2:2 MPEG-2 video driver  (EXPERIMENTAL)' CONFIG_VIDEO_STRADIS $CONFIG_VIDEO_DEV
+   fi
+   dep_tristate '  TerraTec ActiveRadio ISA Standalone' CONFIG_RADIO_TERRATEC $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_RADIO_TERRATEC" = "y" ]; then
+      hex '    Terratec i/o port (normally 0x590)' CONFIG_RADIO_TERRATEC_PORT 590
+   fi
+   dep_tristate '  Trust FM radio card' CONFIG_RADIO_TRUST $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_RADIO_TRUST" = "y" ]; then
+      hex '    Trust i/o port (usually 0x350 or 0x358)' CONFIG_RADIO_TRUST_PORT 350
+   fi
+   dep_tristate '  Typhoon Radio (a.k.a. EcoRadio)' CONFIG_RADIO_TYPHOON $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_PROC_FS" = "y" ]; then
       if [ "$CONFIG_RADIO_TYPHOON" != "n" ]; then
-	bool '  Support for /proc/radio-typhoon' CONFIG_RADIO_TYPHOON_PROC_FS
+	 bool '    Support for /proc/radio-typhoon' CONFIG_RADIO_TYPHOON_PROC_FS
       fi
-  fi
-  if [ "$CONFIG_RADIO_TYPHOON" = "y" ]; then
-    hex '  Typhoon I/O port (0x316 or 0x336)' CONFIG_RADIO_TYPHOON_PORT 316
-    int '  Typhoon frequency set when muting the device (kHz)' CONFIG_RADIO_TYPHOON_MUTEFREQ 87500
-  fi
-  dep_tristate 'Zoltrix Radio' CONFIG_RADIO_ZOLTRIX $CONFIG_VIDEO_DEV
-  if [ "$CONFIG_RADIO_ZOLTRIX" = "y" ]; then
-    hex '  ZOLTRIX I/O port (0x20c or 0x30c)' CONFIG_RADIO_ZOLTRIX_PORT 20c
-  fi
-  dep_tristate 'IIC on parallel port' CONFIG_I2C_PARPORT $CONFIG_PARPORT
+   fi
+   if [ "$CONFIG_RADIO_TYPHOON" = "y" ]; then
+      hex '  Typhoon I/O port (0x316 or 0x336)' CONFIG_RADIO_TYPHOON_PORT 316
+      int '  Typhoon frequency set when muting the device (kHz)' CONFIG_RADIO_TYPHOON_MUTEFREQ 87500
+   fi
+   dep_tristate '  Zoltrix Radio' CONFIG_RADIO_ZOLTRIX $CONFIG_VIDEO_DEV
+   if [ "$CONFIG_RADIO_ZOLTRIX" = "y" ]; then
+      hex '    ZOLTRIX I/O port (0x20c or 0x30c)' CONFIG_RADIO_ZOLTRIX_PORT 20c
+   fi
+   dep_tristate '  Zoran ZR36057/36060 support' CONFIG_VIDEO_ZORAN $CONFIG_VIDEO_DEV
+   dep_tristate '    Include support for Iomega Buz' CONFIG_VIDEO_BUZ $CONFIG_VIDEO_ZORAN
 fi
 
 endmenu
@@ -197,7 +203,7 @@
 
 tristate 'Joystick support' CONFIG_JOYSTICK
 if [ "$CONFIG_JOYSTICK" != "n" ]; then
-  source drivers/char/joystick/Config.in
+   source drivers/char/joystick/Config.in
 fi
 endmenu
 
@@ -210,15 +216,19 @@
 comment 'Ftape, the floppy tape device driver'
 tristate 'Ftape (QIC-80/Travan) support' CONFIG_FTAPE
 if [ "$CONFIG_FTAPE" != "n" ]; then
-  source drivers/char/ftape/Config.in
+   source drivers/char/ftape/Config.in
 fi
 endmenu
 
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-  bool 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM
-  if [ "$CONFIG_DRM" = "y" ]; then
-    dep_tristate '   3dlabs GMX 2000' CONFIG_DRM_GAMMA m
-  fi
+   bool 'Direct Rendering Manager (XFree86 DRI support) (EXPERIMENTAL)' CONFIG_DRM
+   if [ "$CONFIG_DRM" = "y" ]; then
+      dep_tristate '  3dlabs GMX 2000' CONFIG_DRM_GAMMA m
+   fi
+fi
+
+if [ "$CONFIG_PCMCIA" != "n" ]; then
+   source drivers/char/pcmcia/Config.in
 fi
 
 endmenu
diff -u --recursive --new-file v2.3.26/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.3.26/linux/drivers/char/Makefile	Sun Nov  7 16:37:34 1999
+++ linux/drivers/char/Makefile	Thu Nov 11 16:03:36 1999
@@ -11,7 +11,7 @@
 
 SUB_DIRS     := 
 MOD_SUB_DIRS := $(SUB_DIRS)
-ALL_SUB_DIRS := $(SUB_DIRS) ftape joystick
+ALL_SUB_DIRS := $(SUB_DIRS) ftape joystick pcmcia
 
 #
 # This file contains the font map for the default (hardware) font
@@ -450,6 +450,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_VIDEO_STRADIS),y)
+O_OBJS += vino.o
+else
+  ifeq ($(CONFIG_VIDEO_STRADIS),m)
+  M_OBJS += stradis.o
+  endif
+endif
+
 ifeq ($(CONFIG_RADIO_AZTECH),y)
 O_OBJS += radio-aztech.o
 else
@@ -581,6 +589,15 @@
 ifeq ($(CONFIG_DRM),y)
   ALL_SUB_DIRS += drm
   MOD_SUB_DIRS += drm
+endif
+
+ifeq ($(CONFIG_PCMCIA),y)
+  SUB_DIRS += pcmcia
+  MOD_IN_SUB_DIRS += pcmcia
+else
+  ifeq ($(CONFIG_PCMCIA),m)
+    MOD_IN_SUB_DIRS += pcmcia
+  endif
 endif
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.26/linux/drivers/char/console.c linux/drivers/char/console.c
--- v2.3.26/linux/drivers/char/console.c	Fri Oct 22 13:21:48 1999
+++ linux/drivers/char/console.c	Wed Nov 10 20:01:03 1999
@@ -95,6 +95,7 @@
 #include <linux/apm_bios.h>
 #endif
 #include <linux/bootmem.h>
+#include <linux/acpi.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -201,6 +202,11 @@
 #define DO_UPDATE IS_VISIBLE
 #endif
 
+static int acpi_con_transition(struct acpi_dev *dev, acpi_dstate_t state);
+static struct acpi_dev_info acpi_con_info
+	= {ACPI_SYS_DEV, ACPI_VGA_HID, acpi_con_transition};
+static struct acpi_dev *acpi_con = NULL;
+
 static inline unsigned short *screenpos(int currcons, int offset, int viewed)
 {
 	unsigned short *p;
@@ -654,6 +660,9 @@
 	    screenbuf = (unsigned short *) q;
 	    kmalloced = 1;
 	    vc_init(currcons, video_num_lines, video_num_columns, 1);
+
+	    if (!acpi_con)
+		    acpi_con = acpi_register(&acpi_con_info, 0);
 	}
 	return 0;
 }
@@ -1991,6 +2000,8 @@
 	if (!printable || test_and_set_bit(0, &printing))
 		return;
 
+	acpi_access(acpi_con);
+
 	if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1))
 		currcons = kmsg_redirect - 1;
 
@@ -2148,6 +2159,7 @@
 {
 	int	retval;
 
+	acpi_access(acpi_con);
 	retval = do_con_write(tty, from_user, buf, count);
 	con_flush_chars(tty);
 
@@ -2156,6 +2168,7 @@
 
 static void con_put_char(struct tty_struct *tty, unsigned char ch)
 {
+	acpi_access(acpi_con);
 	do_con_write(tty, 0, &ch, 1);
 }
 
@@ -2221,6 +2234,7 @@
 {
 	struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
 
+	acpi_access(acpi_con);
 	set_cursor(vt->vc_num);
 }
 
@@ -2806,6 +2820,21 @@
 	}
 }
 
+static int acpi_con_transition(struct acpi_dev *dev, acpi_dstate_t state)
+{
+	switch (state)
+	{
+	case ACPI_D0:
+		unblank_screen();
+		break;
+	case ACPI_D1:
+	case ACPI_D2:
+	case ACPI_D3:
+		do_blank_screen(0);
+		break;
+	}
+	return 0;
+}
 
 /*
  *	Visible symbols for modules
diff -u --recursive --new-file v2.3.26/linux/drivers/char/cs8420.h linux/drivers/char/cs8420.h
--- v2.3.26/linux/drivers/char/cs8420.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/cs8420.h	Wed Nov 10 13:58:46 1999
@@ -0,0 +1,50 @@
+/* cs8420.h - cs8420 initializations
+   Copyright (C) 1999 Nathan Laredo (laredo@gnu.org)
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ */
+#ifndef __CS8420_H__
+#define __CS8420_H__
+
+/* Initialization Sequence */
+	 
+static __u8 init8420[] = {
+	1, 0x01,	2, 0x02,	3, 0x00,	4, 0x46,
+	5, 0x24,	6, 0x84,	18, 0x18,	19, 0x13,
+};
+
+#define INIT8420LEN	(sizeof(init8420)/2)
+
+static __u8 mode8420pro[] = {	/* professional output mode */
+	32, 0xa1,	33, 0x00,	34, 0x00,	35, 0x00,
+	36, 0x00,	37, 0x00,	38, 0x00,	39, 0x00,
+	40, 0x00,	41, 0x00,	42, 0x00,	43, 0x00,
+	44, 0x00,	45, 0x00,	46, 0x00,	47, 0x00,
+	48, 0x00,	49, 0x00,	50, 0x00,	51, 0x00,
+	52, 0x00,	53, 0x00,	54, 0x00,	55, 0x00,
+};
+#define MODE8420LEN	(sizeof(mode8420pro)/2)
+
+static __u8 mode8420con[] = {	/* consumer output mode */
+	32, 0x20,	33, 0x00,	34, 0x00,	35, 0x48,
+	36, 0x00,	37, 0x00,	38, 0x00,	39, 0x00,
+	40, 0x00,	41, 0x00,	42, 0x00,	43, 0x00,
+	44, 0x00,	45, 0x00,	46, 0x00,	47, 0x00,
+	48, 0x00,	49, 0x00,	50, 0x00,	51, 0x00,
+	52, 0x00,	53, 0x00,	54, 0x00,	55, 0x00,
+};
+
+#endif
diff -u --recursive --new-file v2.3.26/linux/drivers/char/dn_keyb.c linux/drivers/char/dn_keyb.c
--- v2.3.26/linux/drivers/char/dn_keyb.c	Mon Oct 11 15:38:14 1999
+++ linux/drivers/char/dn_keyb.c	Mon Nov  8 11:03:20 1999
@@ -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 @@
 #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 @@
 }
 #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 @@
 
 	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 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 @@
 
 }
 
-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 @@
   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 -u --recursive --new-file v2.3.26/linux/drivers/char/drm/sigio.c linux/drivers/char/drm/sigio.c
--- v2.3.26/linux/drivers/char/drm/sigio.c	Fri Sep 10 23:57:29 1999
+++ linux/drivers/char/drm/sigio.c	Wed Nov 10 10:00:48 1999
@@ -35,7 +35,6 @@
 # include "xf86.h"
 # include "xf86drm.h"
 # include "xf86_OSlib.h"
-# include "xf86drm.h"
 #else
 # include <unistd.h>
 # include <signal.h>
diff -u --recursive --new-file v2.3.26/linux/drivers/char/dsp56k.c linux/drivers/char/dsp56k.c
--- v2.3.26/linux/drivers/char/dsp56k.c	Mon Aug  9 12:32:28 1999
+++ linux/drivers/char/dsp56k.c	Mon Nov  8 11:03:20 1999
@@ -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 -u --recursive --new-file v2.3.26/linux/drivers/char/ftape/lowlevel/ftape-proc.c linux/drivers/char/ftape/lowlevel/ftape-proc.c
--- v2.3.26/linux/drivers/char/ftape/lowlevel/ftape-proc.c	Tue Jul  6 19:16:55 1999
+++ linux/drivers/char/ftape/lowlevel/ftape-proc.c	Tue Nov  9 19:39:02 1999
@@ -22,245 +22,25 @@
  *
  *      This file contains the procfs interface for the
  *      QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
+
+ *	Old code removed, switched to dynamic proc entry.
  */
 
 #include <linux/config.h>
 
 #if defined(CONFIG_PROC_FS) && defined(CONFIG_FT_PROC_FS)
 
-/*  adding proc entries from inside a module is REALLY complicated 
- *  for pre-2.1.28 kernels. I don't want to care about it.
- */
-
 #include <linux/proc_fs.h>
 
 #include <linux/ftape.h>
-#if LINUX_VERSION_CODE <= KERNEL_VER(1,2,13) /* bail out */
-#error \
-Please disable CONFIG_FT_PROC_FS in "MCONFIG" or upgrade to a newer kernel!
-#endif
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,16)
 #include <linux/init.h>
-#else
-#define __initdata
-#define __initfunc(__arg) __arg
-#endif
 #include <linux/qic117.h>
 
-
 #include "../lowlevel/ftape-io.h"
 #include "../lowlevel/ftape-ctl.h"
 #include "../lowlevel/ftape-proc.h"
 #include "../lowlevel/ftape-tracing.h"
 
-static int ftape_read_proc(char *page, char **start, off_t off,
-			   int count, int *eof, void *data);
-
-#if LINUX_VERSION_CODE < KERNEL_VER(2,1,28)
-
-#include <asm/segment.h> /* for memcpy_tofs() */
-
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,0)
-static long ftape_proc_read(struct inode* inode, struct file* file,
-			    char* buf, unsigned long count);
-#else
-static int ftape_proc_read(struct inode* inode, struct file* file,
-			   char* buf, int count);
-#endif
-
-#define FT_PROC_REGISTER(parent, child) proc_register_dynamic(parent, child)
-
-/*
- *	Structures for interfacing with the /proc filesystem.
- *	Router creates its own directory /proc/net/router with the folowing
- *	entries:
- *	config		device configuration
- *	status		global device statistics
- *	<device>	entry for each WAN device
- */
-
-/*
- *	Generic /proc/net/ftape/<file> file and inode operations
- */
-
-
-static struct file_operations ftape_proc_fops =
-{
-	NULL,			/* lseek   */
-	ftape_proc_read,	/* read	   */
-	NULL,			/* write   */
-	NULL,			/* readdir */
-	NULL,			/* select  */
-	NULL,			/* ioctl   */
-	NULL,			/* mmap	   */
-	NULL,			/* no special open code	   */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	NULL,			/* can't fsync */
-};
-
-static struct inode_operations ftape_proc_inode_operations =
-{
-	&ftape_proc_fops,
-	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 */
-};
-
-/*
- * Proc filesystem directory entries.
- */
-
-static int ftape_get_info(char *page, char **start, off_t off,
-			  int count, int dummy)
-{
-	int dummy_eof;
-
-	return ftape_read_proc(page, start, off, count, &dummy_eof, NULL);
-}
-
-static struct proc_dir_entry proc_ftape = {
-	0,                            /* low_ino    */
-	sizeof("ftape")-1,            /* namelen    */
-	"ftape",                      /* name       */
-	S_IFREG | S_IRUGO,            /* mode       */
-	1,                            /* nlink      */
-	0,                            /* uid        */
-	0,                            /* gid        */
-	0,                            /* size       */
-	&ftape_proc_inode_operations, /* ops        */
-	ftape_get_info,               /* get_info   */
-	NULL,                         /* fill_inode */
-	NULL,                         /* next       */
-	NULL,                         /* parent     */
-	NULL,                         /* subdir     */
-	NULL                          /* data       */
-};
-
-/*  Read ftape proc directory entry.
- */
-
-#define PROC_BLOCK_SIZE	PAGE_SIZE
-
-#if LINUX_VERSION_CODE >= KERNEL_VER(2,1,0)
-static long ftape_proc_read(struct inode * inode, struct file * file,
-			    char * buf, unsigned long nbytes)
-#else
-static int ftape_proc_read(struct inode * inode, struct file * file,
-			   char * buf, int nbytes)
-#endif
-{
-	char 	*page;
-	int	retval=0;
-	int	eof=0;
-	int	n, count;
-	char	*start;
-	struct proc_dir_entry * dp;
-
-	if (nbytes < 0)
-		return -EINVAL;
-	dp = (struct proc_dir_entry *) inode->u.generic_ip;
-	if (!(page = (char*) __get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
-
-	while ((nbytes > 0) && !eof)
-	{
-		count = PROC_BLOCK_SIZE <= nbytes ? PROC_BLOCK_SIZE : nbytes;
-
-		start = NULL;
-		if (dp->get_info) {
-			/*
-			 * Handle backwards compatibility with the old net
-			 * routines.
-			 * 
-			 * XXX What gives with the file->f_flags & O_ACCMODE
-			 * test?  Seems stupid to me....
-			 */
-			n = dp->get_info(page, &start, file->f_pos, count,
-				 (file->f_flags & O_ACCMODE) == O_RDWR);
-			if (n < count)
-				eof = 1;
-		} else
-			break;
-			
-		if (!start) {
-			/*
-			 * For proc files that are less than 4k
-			 */
-			start = page + file->f_pos;
-			n -= file->f_pos;
-			if (n <= 0)
-				break;
-			if (n > count)
-				n = count;
-		}
-		if (n == 0)
-			break;	/* End of file */
-		if (n < 0) {
-			if (retval == 0)
-				retval = n;
-			break;
-		}
-#if LINUX_VERSION_CODE > KERNEL_VER(2,1,3)
-		copy_to_user(buf, start, n);
-#else
-		memcpy_tofs(buf, start, n);
-#endif
-		file->f_pos += n;	/* Move down the file */
-		nbytes -= n;
-		buf += n;
-		retval += n;
-	}
-	free_page((unsigned long) page);
-	return retval;
-}
-
-#else /* LINUX_VERSION_CODE < KERNEL_VER(2,1,28) */
-
-#define FT_PROC_REGISTER(parent, child) proc_register(parent, child)
-
-/*
- * Proc filesystem directory entries.
- */
-
-static struct proc_dir_entry proc_ftape = {
-	0,                   /* low_ino    */
-	sizeof("ftape")-1,   /* namelen    */
-	"ftape",             /* name       */
-	S_IFREG | S_IRUGO,   /* mode       */
-	1,                   /* nlink      */
-	0,                   /* uid        */
-	0,                   /* gid        */
-	0,                   /* size       */
-	NULL,                /* ops        */
-	NULL,                /* get_info   */
-	NULL,                /* fill_inode */
-	NULL,                /* next       */
-	NULL,                /* parent     */
-	NULL,                /* subdir     */
-	NULL,                /* data       */
-	ftape_read_proc,     /* read_proc  */
-	NULL                 /* write_proc */
-};
-
-#endif
-
 static size_t get_driver_info(char *buf)
 {
 	const char *debug_level[] = { "bugs"  ,
@@ -423,13 +203,14 @@
 
 int __init ftape_proc_init(void)
 {
-	return FT_PROC_REGISTER(&proc_root, &proc_ftape);
+	return create_proc_read_entry("ftape", 0, &proc_root,
+		ftape_read_proc, NULL) != NULL;
 }
 
 #ifdef MODULE
 void ftape_proc_destroy(void)
 {
-	proc_unregister(&proc_root, proc_ftape.low_ino);
+	remove_proc_entry("ftape", &proc_root);
 }
 #endif
 
diff -u --recursive --new-file v2.3.26/linux/drivers/char/ibmmpeg2.h linux/drivers/char/ibmmpeg2.h
--- v2.3.26/linux/drivers/char/ibmmpeg2.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/ibmmpeg2.h	Wed Nov 10 13:58:46 1999
@@ -0,0 +1,94 @@
+/* ibmmpeg2.h - IBM MPEGCD21 definitions */
+
+#ifndef __IBM_MPEG2__
+#define __IBM_MPEG2__
+
+/* Define all MPEG Decoder registers */
+/* Chip Control and Status */
+#define IBM_MP2_CHIP_CONTROL	0x200*2
+#define IBM_MP2_CHIP_MODE	0x201*2
+/* Timer Control and Status */
+#define IBM_MP2_SYNC_STC2	0x202*2
+#define IBM_MP2_SYNC_STC1	0x203*2
+#define IBM_MP2_SYNC_STC0	0x204*2
+#define IBM_MP2_SYNC_PTS2	0x205*2
+#define IBM_MP2_SYNC_PTS1	0x206*2
+#define IBM_MP2_SYNC_PTS0	0x207*2
+/* Video FIFO Control */
+#define IBM_MP2_FIFO		0x208*2
+#define IBM_MP2_FIFOW		0x100*2
+#define IBM_MP2_FIFO_STAT	0x209*2
+#define IBM_MP2_RB_THRESHOLD	0x22b*2
+/* Command buffer */
+#define IBM_MP2_COMMAND		0x20a*2
+#define IBM_MP2_CMD_DATA	0x20b*2
+#define IBM_MP2_CMD_STAT	0x20c*2
+#define IBM_MP2_CMD_ADDR	0x20d*2
+/* Internal Processor Control and Status */
+#define IBM_MP2_PROC_IADDR	0x20e*2
+#define IBM_MP2_PROC_IDATA	0x20f*2
+#define IBM_MP2_WR_PROT		0x235*2
+/* DRAM Access */
+#define IBM_MP2_DRAM_ADDR	0x210*2
+#define IBM_MP2_DRAM_DATA	0x212*2
+#define IBM_MP2_DRAM_CMD_STAT	0x213*2
+#define IBM_MP2_BLOCK_SIZE	0x23b*2
+#define IBM_MP2_SRC_ADDR	0x23c*2
+/* Onscreen Display */
+#define IBM_MP2_OSD_ADDR	0x214*2
+#define IBM_MP2_OSD_DATA	0x215*2
+#define IBM_MP2_OSD_MODE	0x217*2
+#define IBM_MP2_OSD_LINK_ADDR	0x229*2
+#define IBM_MP2_OSD_SIZE	0x22a*2
+/* Interrupt Control */
+#define IBM_MP2_HOST_INT	0x218*2
+#define IBM_MP2_MASK0		0x219*2
+#define IBM_MP2_HOST_INT1	0x23e*2
+#define IBM_MP2_MASK1		0x23f*2
+/* Audio Control */
+#define IBM_MP2_AUD_IADDR	0x21a*2
+#define IBM_MP2_AUD_IDATA	0x21b*2
+#define IBM_MP2_AUD_FIFO	0x21c*2
+#define IBM_MP2_AUD_FIFOW	0x101*2
+#define IBM_MP2_AUD_CTL		0x21d*2
+#define IBM_MP2_BEEP_CTL	0x21e*2
+#define IBM_MP2_FRNT_ATTEN	0x22d*2
+/* Display Control */
+#define IBM_MP2_DISP_MODE	0x220*2
+#define IBM_MP2_DISP_DLY	0x221*2
+#define IBM_MP2_VBI_CTL		0x222*2
+#define IBM_MP2_DISP_LBOR	0x223*2
+#define IBM_MP2_DISP_TBOR	0x224*2
+/* Polarity Control */
+#define IBM_MP2_INFC_CTL	0x22c*2
+
+/* control commands */
+#define IBM_MP2_PLAY		0
+#define IBM_MP2_PAUSE		1
+#define IBM_MP2_SINGLE_FRAME	2
+#define IBM_MP2_FAST_FORWARD	3
+#define IBM_MP2_SLOW_MOTION	4
+#define IBM_MP2_IMED_NORM_PLAY	5
+#define IBM_MP2_RESET_WINDOW	6
+#define IBM_MP2_FREEZE_FRAME	7
+#define IBM_MP2_RESET_VID_RATE	8
+#define IBM_MP2_CONFIG_DECODER	9
+#define IBM_MP2_CHANNEL_SWITCH	10
+#define IBM_MP2_RESET_AUD_RATE	11
+#define IBM_MP2_PRE_OP_CHN_SW	12
+#define IBM_MP2_SET_STILL_MODE	14
+
+/* Define Xilinx FPGA Internal Registers */
+
+/* general control register 0 */
+#define XILINX_CTL0		0x600
+/* genlock delay resister 1 */
+#define XILINX_GLDELAY		0x602
+/* send 16 bits to CS3310 port */
+#define XILINX_CS3310		0x604
+/* send 16 bits to CS3310 and complete */
+#define XILINX_CS3310_CMPLT	0x60c
+/* pulse width modulator control */
+#define XILINX_PWM		0x606
+
+#endif
diff -u --recursive --new-file v2.3.26/linux/drivers/char/ip2main.c linux/drivers/char/ip2main.c
--- v2.3.26/linux/drivers/char/ip2main.c	Tue Aug 31 17:29:13 1999
+++ linux/drivers/char/ip2main.c	Tue Nov  9 19:39:02 1999
@@ -74,16 +74,6 @@
 int ip2_read_procmem(char *, char **, off_t, int, int );
 int ip2_read_proc(char *, char **, off_t, int, int *, void * );
 
-struct proc_dir_entry ip2_proc_entry = {
-   0,
-   6,"ip2mem",
-   S_IFREG | S_IRUGO,
-   1, 0, 0,
-   0,
-   NULL,
-   ip2_read_procmem
-};
-
 /********************/
 /* Type Definitions */
 /********************/
@@ -429,9 +419,7 @@
 	if ( ( err = unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) ) {
 		printk(KERN_ERR "IP2: failed to unregister IPL driver (%d)\n", err);
 	}
-	if ( ( err = proc_unregister( &proc_root, ip2_proc_entry.low_ino ) ) ) {
-		printk(KERN_ERR "IP2: failed to unregister read_procmem (%d)\n", err);
-	}
+	remove_proc_entry("ip2mem", &proc_root);
 
 	// free memory
 	for (i = 0; i < IP2_MAX_BOARDS; i++) {
@@ -673,8 +661,8 @@
 		printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err );
 	} else
 	/* Register the read_procmem thing */
-	if ( ( err = proc_register( &proc_root,  &ip2_proc_entry ) ) ) {
-		printk(KERN_ERR "IP2: failed to register read_procmem (%d)\n", err );
+	if (!create_proc_info_entry("ip2mem",0,&proc_root,ip2_read_procmem)) {
+		printk(KERN_ERR "IP2: failed to register read_procmem\n");
 	} else {
 
 #ifdef IP2DEBUG_TRACE
diff -u --recursive --new-file v2.3.26/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v2.3.26/linux/drivers/char/keyboard.c	Fri Oct 15 15:25:13 1999
+++ linux/drivers/char/keyboard.c	Wed Nov 10 20:01:03 1999
@@ -32,7 +32,6 @@
 #include <linux/string.h>
 #include <linux/random.h>
 #include <linux/init.h>
-#include <linux/module.h>
 
 #include <asm/keyboard.h>
 #include <asm/bitops.h>
@@ -42,6 +41,7 @@
 #include <linux/vt_kern.h>
 #include <linux/kbd_ll.h>
 #include <linux/sysrq.h>
+#include <linux/acpi.h>
 
 #define SIZE(x) (sizeof(x)/sizeof((x)[0]))
 
@@ -159,6 +159,9 @@
 int sysrq_enabled = 1;
 #endif
 
+static struct acpi_dev_info acpi_kbd_info = {ACPI_SYS_DEV, ACPI_KBC_HID, NULL};
+static struct acpi_dev *acpi_kbd = NULL;
+
 /*
  * Many other routines do put_queue, but I think either
  * they produce ASCII, or they produce some user-assigned
@@ -201,6 +204,8 @@
 	char up_flag = down ? 0 : 0200;
 	char raw_mode;
 
+	acpi_access(acpi_kbd);
+
 	do_poke_blanked_console = 1;
 	mark_bh(CONSOLE_BH);
 	add_keyboard_randomness(scancode | up_flag);
@@ -923,5 +928,8 @@
 	kbd_init_hw();
 	init_bh(KEYBOARD_BH, kbd_bh);
 	mark_bh(KEYBOARD_BH);
+	
+	acpi_kbd = acpi_register(&acpi_kbd_info, 0);
+
 	return 0;
 }
diff -u --recursive --new-file v2.3.26/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.3.26/linux/drivers/char/mem.c	Mon Nov  1 13:56:26 1999
+++ linux/drivers/char/mem.c	Wed Nov 10 08:40:04 1999
@@ -56,6 +56,9 @@
 #ifdef CONFIG_USB
 extern void usb_init(void);
 #endif
+#ifdef CONFIG_PPDEV
+extern int pp_init(void);
+#endif
      
 static ssize_t do_write_mem(struct file * file, void *p, unsigned long realp,
 			    const char * buf, size_t count, loff_t *ppos)
@@ -672,6 +675,9 @@
 #endif
 #ifdef CONFIG_VIDEO_DEV
 	videodev_init();
+#endif
+#ifdef CONFIG_PPDEV
+	pp_init();
 #endif
 	return 0;
 }
diff -u --recursive --new-file v2.3.26/linux/drivers/char/n_hdlc.c linux/drivers/char/n_hdlc.c
--- v2.3.26/linux/drivers/char/n_hdlc.c	Mon Oct 11 15:38:14 1999
+++ linux/drivers/char/n_hdlc.c	Wed Nov 10 10:00:48 1999
@@ -105,7 +105,6 @@
 #include <linux/malloc.h>
 #include <linux/tty.h>
 #include <linux/errno.h>
-#include <linux/sched.h>	/* to get the struct task_struct */
 #include <linux/string.h>	/* used in new tty drivers */
 #include <linux/signal.h>	/* used in new tty drivers */
 #include <asm/system.h>
diff -u --recursive --new-file v2.3.26/linux/drivers/char/pcmcia/Config.in linux/drivers/char/pcmcia/Config.in
--- v2.3.26/linux/drivers/char/pcmcia/Config.in	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/pcmcia/Config.in	Thu Nov 11 16:03:36 1999
@@ -0,0 +1,31 @@
+#
+# PCMCIA character device configuration
+#
+
+mainmenu_option next_comment
+comment 'PCMCIA character device support'
+
+if [ "$CONFIG_SERIAL" = "y" ]; then
+   dep_tristate '  PCMCIA serial device support' \
+      CONFIG_PCMCIA_SERIAL_CS $CONFIG_PCMCIA
+   if [ "$CONFIG_CARDBUS" = "y" ]; then
+      dep_tristate '  CardBus serial device support' \
+         CONFIG_PCMCIA_SERIAL_CB $CONFIG_PCMCIA
+   fi
+fi
+
+if [ "$CONFIG_SERIAL" = "m" ]; then
+   dep_tristate '  PCMCIA serial device support' \
+      CONFIG_PCMCIA_SERIAL_CS m
+   if [ "$CONFIG_CARDBUS" = "y" ]; then
+      dep_tristate '  CardBus serial device support' \
+         CONFIG_PCMCIA_SERIAL_CB m
+   fi
+fi
+
+if [ "$CONFIG_PCMCIA_SERIAL_CS" = "y" -o \
+     "$CONFIG_PCMCIA_SERIAL_CB" = "y" ]; then
+   define_bool CONFIG_PCMCIA_CHRDEV y
+fi
+
+endmenu
diff -u --recursive --new-file v2.3.26/linux/drivers/char/pcmcia/Makefile linux/drivers/char/pcmcia/Makefile
--- v2.3.26/linux/drivers/char/pcmcia/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/pcmcia/Makefile	Thu Nov 11 16:03:36 1999
@@ -0,0 +1,27 @@
+#
+# drivers/char/pcmcia/Makefile
+#
+# Makefile for the Linux PCMCIA char device drivers.
+#
+
+SUB_DIRS     := 
+MOD_SUB_DIRS := $(SUB_DIRS)
+ALL_SUB_DIRS := $(SUB_DIRS)
+
+O_TARGET := pcmcia_char.o
+MOD_LIST_NAME := PCMCIA_CHAR_MODULES
+
+obj-y		:=
+obj-m		:=
+obj-n		:=
+obj-		:=
+
+obj-$(CONFIG_PCMCIA_SERIAL_CS)	+= serial_cs.o
+obj-$(CONFIG_PCMCIA_SERIAL_CB)	+= serial_cb.o
+
+O_OBJS		:= $(obj-y)
+OX_OBJS		:=
+M_OBJS		:= $(obj-m)
+MX_OBJS		:=
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.26/linux/drivers/char/pcmcia/serial_cb.c linux/drivers/char/pcmcia/serial_cb.c
--- v2.3.26/linux/drivers/char/pcmcia/serial_cb.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/pcmcia/serial_cb.c	Thu Nov 11 16:03:36 1999
@@ -0,0 +1,150 @@
+/*======================================================================
+
+    A driver for CardBus serial devices
+
+    serial_cb.c 1.14 1999/11/11 02:18:08
+
+    Copyright 1998, 1999 by Donald Becker and David Hinds
+    
+    This software may be used and distributed according to the terms
+    of the GNU Public License, incorporated herein by reference.
+    All other rights reserved.
+    
+    This driver is an activator for CardBus serial cards, as
+    found on multifunction (e.g. Ethernet and Modem) CardBus cards.
+    
+    Donald Becker may be reached as becker@CESDIS.edu, or C/O
+    USRA Center of Excellence in Space Data and Information Sciences
+    Code 930.5, NASA Goddard Space Flight Center, Greenbelt MD 20771
+    David Hinds may be reached at dhinds@pcmcia.sourceforge.org
+    
+======================================================================*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/major.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#include <pcmcia/driver_ops.h>
+
+#ifdef PCMCIA_DEBUG
+static int pc_debug = PCMCIA_DEBUG;
+MODULE_PARM(pc_debug, "i");
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+static char *version =
+"serial_cb.c 1.14 1999/11/11 02:18:08 (David Hinds)";
+#else
+#define DEBUG(n, args...)
+#endif
+
+/*======================================================================
+
+    Card-specific configuration hacks
+
+======================================================================*/
+
+static void device_setup(u_char bus, u_char devfn, u_int ioaddr)
+{
+    u_short a, b;
+
+    pcibios_read_config_word(bus, devfn, PCI_SUBSYSTEM_VENDOR_ID, &a);
+    pcibios_read_config_word(bus, devfn, PCI_SUBSYSTEM_ID, &b);
+    if ((a == 0x13a2) && (b == 0x8007)) {
+	/* Ositech Jack of Spades */
+	DEBUG(0, "  83c175 NVCTL_m = 0x%4.4x.\n", inl(ioaddr+0x80));
+	outl(0x4C00, ioaddr + 0x80);
+	outl(0x4C80, ioaddr + 0x80);
+    }
+    DEBUG(0, "  modem registers are %2.2x %2.2x %2.2x "
+	  "%2.2x %2.2x %2.2x %2.2x %2.2x  %2.2x.\n",
+	  inb(ioaddr + 0), inb(ioaddr + 1), inb(ioaddr + 2),
+	  inb(ioaddr + 3), inb(ioaddr + 4), inb(ioaddr + 5),
+	  inb(ioaddr + 6), inb(ioaddr + 7), inb(ioaddr + 8));
+}
+
+/*======================================================================
+
+    serial_attach() creates a serial device "instance" and registers
+    it with the kernel serial driver, and serial_detach() unregisters
+    an instance.
+
+======================================================================*/
+
+static dev_node_t *serial_attach(dev_locator_t *loc)
+{
+    u_int io;
+    u_char bus, devfn, irq;
+    int line;
+    struct serial_struct serial;
+    
+    if (loc->bus != LOC_PCI) return NULL;
+    bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
+    printk(KERN_INFO "serial_attach(bus %d, fn %d)\n", bus, devfn);
+    pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
+    pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
+    if (io & PCI_BASE_ADDRESS_SPACE_IO) {
+	io &= PCI_BASE_ADDRESS_IO_MASK;
+    } else {
+	printk(KERN_NOTICE "serial_cb: PCI base address 0 is not IO\n");
+	return NULL;
+    }
+    device_setup(bus, devfn, io);
+    memset(&serial, 0, sizeof(serial));
+    serial.port = io; serial.irq = irq;
+    serial.flags = ASYNC_SKIP_TEST | ASYNC_SHARE_IRQ;
+
+    /* Some devices seem to need extra time */
+    __set_current_state(TASK_UNINTERRUPTIBLE);
+    schedule_timeout(HZ/50);
+
+    line = register_serial(&serial);
+    if (line < 0) {
+	printk(KERN_NOTICE "serial_cb: register_serial() at 0x%04x, "
+	       "irq %d failed\n", serial.port, serial.irq);
+	return NULL;
+    } else {
+	dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
+	sprintf(node->dev_name, "ttyS%d", line);
+	node->major = TTY_MAJOR; node->minor = 0x40 + line;
+	node->next = NULL;
+	MOD_INC_USE_COUNT;
+	return node;
+    }
+}
+
+static void serial_detach(dev_node_t *node)
+{
+    DEBUG(0, "serial_detach(tty%02d)\n", node->minor - 0x40);
+    unregister_serial(node->minor - 0x40);
+    kfree(node);
+    MOD_DEC_USE_COUNT;
+}
+
+/*====================================================================*/
+
+struct driver_operations serial_ops = {
+    "serial_cb", serial_attach, NULL, NULL, serial_detach
+};
+
+static int __init init_serial_cb(void)
+{
+    DEBUG(0, "%s\n", version);
+    register_driver(&serial_ops);
+    return 0;
+}
+
+static void __exit exit_serial_cb(void)
+{
+    DEBUG(0, "serial_cb: unloading\n");
+    unregister_driver(&serial_ops);
+}
+
+module_init(init_serial_cb);
+module_exit(exit_serial_cb);
diff -u --recursive --new-file v2.3.26/linux/drivers/char/pcmcia/serial_cs.c linux/drivers/char/pcmcia/serial_cs.c
--- v2.3.26/linux/drivers/char/pcmcia/serial_cs.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/pcmcia/serial_cs.c	Thu Nov 11 16:03:36 1999
@@ -0,0 +1,667 @@
+/*======================================================================
+
+    A driver for PCMCIA serial devices
+
+    serial_cs.c 1.114 1999/11/11 00:54:46
+
+    The contents of this file are subject to the Mozilla Public
+    License Version 1.1 (the "License"); you may not use this file
+    except in compliance with the License. You may obtain a copy of
+    the License at http://www.mozilla.org/MPL/
+
+    Software distributed under the License is distributed on an "AS
+    IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+    implied. See the License for the specific language governing
+    rights and limitations under the License.
+
+    The initial developer of the original code is David A. Hinds
+    <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
+    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
+
+    Alternatively, the contents of this file may be used under the
+    terms of the GNU Public License version 2 (the "GPL"), in which
+    case the provisions of the GPL are applicable instead of the
+    above.  If you wish to allow the use of your version of this file
+    only under the terms of the GPL and not to allow others to use
+    your version of this file under the MPL, indicate your decision
+    by deleting the provisions above and replace them with the notice
+    and other provisions required by the GPL.  If you do not delete
+    the provisions above, a recipient may use your version of this
+    file under either the MPL or the GPL.
+    
+======================================================================*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/major.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ciscode.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/cisreg.h>
+
+#ifdef PCMCIA_DEBUG
+static int pc_debug = PCMCIA_DEBUG;
+MODULE_PARM(pc_debug, "i");
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+static char *version =
+"serial_cs.c 1.114 1999/11/11 00:54:46 (David Hinds)";
+#else
+#define DEBUG(n, args...)
+#endif
+
+/*====================================================================*/
+
+/* Parameters that can be set with 'insmod' */
+
+/* Bit map of interrupts to choose from */
+static u_int irq_mask = 0xdeb8;
+static int irq_list[4] = { -1 };
+
+/* Enable the speaker? */
+static int do_sound = 1;
+
+MODULE_PARM(irq_mask, "i");
+MODULE_PARM(irq_list, "1-4i");
+MODULE_PARM(do_sound, "i");
+
+/*====================================================================*/
+
+/* Table of multi-port card ID's */
+
+typedef struct {
+    u_short	manfid;
+    u_short	prodid;
+    int		multi;		/* 1 = multifunction, > 1 = # ports */
+} multi_id_t;
+
+static multi_id_t multi_id[] = {
+    { MANFID_OMEGA, PRODID_OMEGA_QSP_100, 4 },
+    { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232, 2 },
+    { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232_D1, 2 },
+    { MANFID_QUATECH, PRODID_QUATECH_QUAD_RS232, 4 },
+    { MANFID_SOCKET, PRODID_SOCKET_DUAL_RS232, 2 },
+    { MANFID_INTEL, PRODID_INTEL_DUAL_RS232, 2 },
+    { MANFID_NATINST, PRODID_NATINST_QUAD_RS232, 4 }
+};
+#define MULTI_COUNT (sizeof(multi_id)/sizeof(multi_id_t))
+
+typedef struct serial_info_t {
+    int		ndev;
+    int		multi;
+    int		slave;
+    int		manfid;
+    dev_node_t	node[4];
+    int		line[4];
+} serial_info_t;
+
+static void serial_config(dev_link_t *link);
+static void serial_release(u_long arg);
+static int serial_event(event_t event, int priority,
+			event_callback_args_t *args);
+
+static dev_info_t dev_info = "serial_cs";
+
+static dev_link_t *serial_attach(void);
+static void serial_detach(dev_link_t *);
+
+static dev_link_t *dev_list = NULL;
+
+/*====================================================================*/
+
+static void cs_error(client_handle_t handle, int func, int ret)
+{
+    error_info_t err = { func, ret };
+    CardServices(ReportError, handle, &err);
+}
+
+/*======================================================================
+
+    serial_attach() creates an "instance" of the driver, allocating
+    local data structures for one device.  The device is registered
+    with Card Services.
+
+======================================================================*/
+
+static dev_link_t *serial_attach(void)
+{
+    client_reg_t client_reg;
+    dev_link_t *link;
+    int i, ret;
+    
+    DEBUG(0, "serial_attach()\n");
+
+    /* Create new serial device */
+    link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
+    memset(link, 0, sizeof(struct dev_link_t));
+    link->release.function = &serial_release;
+    link->release.data = (u_long)link;
+    link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+    link->io.NumPorts1 = 8;
+    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+    link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
+    if (irq_list[0] == -1)
+	link->irq.IRQInfo2 = irq_mask;
+    else
+	for (i = 0; i < 4; i++)
+	    link->irq.IRQInfo2 |= 1 << irq_list[i];
+    link->conf.Attributes = CONF_ENABLE_IRQ;
+    link->conf.Vcc = 50;
+    if (do_sound) {
+	link->conf.Attributes |= CONF_ENABLE_SPKR;
+	link->conf.Status = CCSR_AUDIO_ENA;
+    }
+    link->conf.IntType = INT_MEMORY_AND_IO;
+    link->priv = kmalloc(sizeof(struct serial_info_t), GFP_KERNEL);
+    memset(link->priv, 0, sizeof(struct serial_info_t));
+    
+    /* Register with Card Services */
+    link->next = dev_list;
+    dev_list = link;
+    client_reg.dev_info = &dev_info;
+    client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
+    client_reg.EventMask =
+	CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
+	CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
+	CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
+    client_reg.event_handler = &serial_event;
+    client_reg.Version = 0x0210;
+    client_reg.event_callback_args.client_data = link;
+    ret = CardServices(RegisterClient, &link->handle, &client_reg);
+    if (ret != CS_SUCCESS) {
+	cs_error(link->handle, RegisterClient, ret);
+	serial_detach(link);
+	return NULL;
+    }
+    
+    return link;
+} /* serial_attach */
+
+/*======================================================================
+
+    This deletes a driver "instance".  The device is de-registered
+    with Card Services.  If it has been released, all local data
+    structures are freed.  Otherwise, the structures will be freed
+    when the device is released.
+
+======================================================================*/
+
+static void serial_detach(dev_link_t *link)
+{
+    dev_link_t **linkp;
+    long flags;
+    int ret;
+
+    DEBUG(0, "serial_detach(0x%p)\n", link);
+    
+    /* Locate device structure */
+    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+	if (*linkp == link) break;
+    if (*linkp == NULL)
+	return;
+
+    save_flags(flags);
+    cli();
+    if (link->state & DEV_RELEASE_PENDING) {
+	del_timer(&link->release);
+	link->state &= ~DEV_RELEASE_PENDING;
+    }
+    restore_flags(flags);
+    
+    if (link->state & DEV_CONFIG)
+	serial_release((u_long)link);
+    
+    if (link->handle) {
+	ret = CardServices(DeregisterClient, link->handle);
+	if (ret != CS_SUCCESS)
+	    cs_error(link->handle, DeregisterClient, ret);
+    }
+    
+    /* Unlink device structure, free bits */
+    *linkp = link->next;
+    kfree_s(link->priv, sizeof(serial_info_t));
+    kfree_s(link, sizeof(struct dev_link_t));
+    
+} /* serial_detach */
+
+/*====================================================================*/
+
+static int setup_serial(serial_info_t *info, ioaddr_t port, int irq)
+{
+    struct serial_struct serial;
+    int line;
+    
+    memset(&serial, 0, sizeof(serial));
+    serial.port = port;
+    serial.irq = irq;
+    serial.flags = ASYNC_SKIP_TEST;
+    serial.flags |= (info->multi || info->slave) ? ASYNC_SHARE_IRQ : 0;
+    line = register_serial(&serial);
+    if (line < 0) {
+	printk(KERN_NOTICE "serial_cs: register_serial() at 0x%04x, "
+	       "irq %d failed\n", serial.port, serial.irq);
+	return -1;
+    }
+    
+    info->line[info->ndev] = line;
+    sprintf(info->node[info->ndev].dev_name, "ttyS%d", line);
+    info->node[info->ndev].major = TTY_MAJOR;
+    info->node[info->ndev].minor = 0x40+line;
+    if (info->ndev > 0)
+	info->node[info->ndev-1].next = &info->node[info->ndev];
+    info->ndev++;
+    
+    return 0;
+}
+
+/*====================================================================*/
+
+static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple,
+		     cisparse_t *parse)
+{
+    int i;
+    i = CardServices(fn, handle, tuple);
+    if (i != CS_SUCCESS) return CS_NO_MORE_ITEMS;
+    i = CardServices(GetTupleData, handle, tuple);
+    if (i != CS_SUCCESS) return i;
+    return CardServices(ParseTuple, handle, tuple, parse);
+}
+
+#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c)
+#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c)
+
+/*====================================================================*/
+
+static int simple_config(dev_link_t *link)
+{
+    static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+    client_handle_t handle = link->handle;
+    serial_info_t *info = link->priv;
+    tuple_t tuple;
+    u_char buf[256];
+    cisparse_t parse;
+    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+    config_info_t config;
+    int i, j;
+
+    /* If the card is already configured, look up the port and irq */
+    i = CardServices(GetConfigurationInfo, handle, &config);
+    if ((i == CS_SUCCESS) &&
+	(config.Attributes & CONF_VALID_CLIENT)) {
+	ioaddr_t port = 0;
+	if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) {
+	    port = config.BasePort2;
+	    info->slave = 1;
+	} else if ((info->manfid == MANFID_OSITECH) &&
+		   (config.NumPorts1 == 0x40)) {
+	    port = config.BasePort1 + 0x28;
+	    info->slave = 1;
+	}
+	if (info->slave)
+	    return setup_serial(info, port, config.AssignedIRQ);
+    }
+    link->conf.Vcc = config.Vcc;
+    
+    /* First pass: look for a config entry that looks normal. */
+    tuple.TupleData = (cisdata_t *)buf;
+    tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
+    tuple.Attributes = 0;
+    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+    i = first_tuple(handle, &tuple, &parse);
+    while (i != CS_NO_MORE_ITEMS) {
+	if (i != CS_SUCCESS) goto next_entry;
+	if (cf->vpp1.present & (1<<CISTPL_POWER_VNOM))
+	    link->conf.Vpp1 = link->conf.Vpp2 =
+		cf->vpp1.param[CISTPL_POWER_VNOM]/10000;
+	if ((cf->io.nwin > 0) && ((cf->io.win[0].base & 0xf) == 8)) {
+	    link->conf.ConfigIndex = cf->index;
+	    link->io.BasePort1 = cf->io.win[0].base;
+	    link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
+	    i = CardServices(RequestIO, link->handle, &link->io);
+	    if (i == CS_SUCCESS) goto found_port;
+	}
+    next_entry:
+	i = next_tuple(handle, &tuple, &parse);
+    }
+    
+    /* Second pass: try to find an entry that isn't picky about
+       its base address, then try to grab any standard serial port
+       address, and finally try to get any free port. */
+    i = first_tuple(handle, &tuple, &parse);
+    while (i != CS_NO_MORE_ITEMS) {
+	if ((i == CS_SUCCESS) && (cf->io.nwin > 0) &&
+	    ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
+	    link->conf.ConfigIndex = cf->index;
+	    for (j = 0; j < 5; j++) {
+		link->io.BasePort1 = base[j];
+		i = CardServices(RequestIO, link->handle,
+				 &link->io);
+		if (i == CS_SUCCESS) goto found_port;
+	    }
+	}
+	i = next_tuple(handle, &tuple, &parse);
+    }
+
+found_port:
+    if (i != CS_SUCCESS) {
+	cs_error(link->handle, RequestIO, i);
+	return -1;
+    }
+    
+    i = CardServices(RequestIRQ, link->handle, &link->irq);
+    if (i != CS_SUCCESS) {
+	cs_error(link->handle, RequestIRQ, i);
+	link->irq.AssignedIRQ = 0;
+    }
+    if (info->multi && (info->manfid == MANFID_3COM))
+	link->conf.ConfigIndex &= ~(0x08);
+    i = CardServices(RequestConfiguration, link->handle, &link->conf);
+    if (i != CS_SUCCESS) {
+	cs_error(link->handle, RequestConfiguration, i);
+	return -1;
+    }
+
+    return setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ);
+}
+
+static int multi_config(dev_link_t *link)
+{
+    client_handle_t handle = link->handle;
+    serial_info_t *info = link->priv;
+    tuple_t tuple;
+    u_char buf[256];
+    cisparse_t parse;
+    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+    int i, base2 = 0;
+
+    tuple.TupleData = (cisdata_t *)buf;
+    tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
+    tuple.Attributes = 0;
+    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+
+    /* First, look for a generic full-sized window */
+    link->io.NumPorts1 = info->multi * 8;
+    i = first_tuple(handle, &tuple, &parse);
+    while (i != CS_NO_MORE_ITEMS) {
+	/* The quad port cards have bad CIS's, so just look for a
+	   window larger than 8 ports and assume it will be right */
+	if ((i == CS_SUCCESS) && (cf->io.nwin == 1) &&
+	    (cf->io.win[0].len > 8)) {
+	    link->conf.ConfigIndex = cf->index;
+	    link->io.BasePort1 = cf->io.win[0].base;
+	    link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
+	    i = CardServices(RequestIO, link->handle, &link->io);
+	    base2 = link->io.BasePort1 + 8;
+	    if (i == CS_SUCCESS) break;
+	}
+	i = next_tuple(handle, &tuple, &parse);
+    }
+
+    /* If that didn't work, look for two windows */
+    if (i != CS_SUCCESS) {
+	link->io.NumPorts1 = link->io.NumPorts2 = 8;
+	info->multi = 2;
+	i = first_tuple(handle, &tuple, &parse);
+	while (i != CS_NO_MORE_ITEMS) {
+	    if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) {
+		link->conf.ConfigIndex = cf->index;
+		link->io.BasePort1 = cf->io.win[0].base;
+		link->io.BasePort2 = cf->io.win[1].base;
+		link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
+		i = CardServices(RequestIO, link->handle, &link->io);
+		base2 = link->io.BasePort2;
+		if (i == CS_SUCCESS) break;
+	    }
+	    i = next_tuple(handle, &tuple, &parse);
+	}
+    }
+    
+    if (i != CS_SUCCESS) {
+	cs_error(link->handle, RequestIO, i);
+	return -1;
+    }
+    
+    i = CardServices(RequestIRQ, link->handle, &link->irq);
+    if (i != CS_SUCCESS) {
+	cs_error(link->handle, RequestIRQ, i);
+	link->irq.AssignedIRQ = 0;
+    }
+    /* Socket Dual IO: this enables irq's for second port */
+    if (info->multi && (info->manfid == MANFID_SOCKET)) {
+	link->conf.Present |= PRESENT_EXT_STATUS;
+	link->conf.ExtStatus = ESR_REQ_ATTN_ENA;
+    }
+    i = CardServices(RequestConfiguration, link->handle, &link->conf);
+    if (i != CS_SUCCESS) {
+	cs_error(link->handle, RequestConfiguration, i);
+	return -1;
+    }
+    
+    setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ);
+    for (i = 0; i < info->multi-1; i++)
+	setup_serial(info, base2+(8*i), link->irq.AssignedIRQ);
+    
+    return 0;
+}
+
+/*======================================================================
+
+    serial_config() is scheduled to run after a CARD_INSERTION event
+    is received, to configure the PCMCIA socket, and to make the
+    serial device available to the system.
+
+======================================================================*/
+
+#define CS_CHECK(fn, args...) \
+while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
+
+void serial_config(dev_link_t *link)
+{
+    client_handle_t handle;
+    serial_info_t *info;
+    tuple_t tuple;
+    u_short buf[128];
+    cisparse_t parse;
+    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+    int i, last_ret, last_fn;
+
+    sti();
+    handle = link->handle;
+    info = link->priv;
+    
+    DEBUG(0, "serial_config(0x%p)\n", link);
+    
+    tuple.TupleData = (cisdata_t *)buf;
+    tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
+    tuple.Attributes = 0;
+    /* Get configuration register information */
+    tuple.DesiredTuple = CISTPL_CONFIG;
+    last_ret = first_tuple(handle, &tuple, &parse);
+    if (last_ret != CS_SUCCESS) {
+	last_fn = ParseTuple;
+	goto cs_failed;
+    }
+    link->conf.ConfigBase = parse.config.base;
+    link->conf.Present = parse.config.rmask[0];
+    
+    /* Configure card */
+    link->state |= DEV_CONFIG;
+
+    /* Is this a compliant multifunction card? */
+    tuple.DesiredTuple = CISTPL_LONGLINK_MFC;
+    tuple.Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK;
+    info->multi = (first_tuple(handle, &tuple, &parse) == CS_SUCCESS);
+    
+    /* Is this a multiport card? */
+    tuple.DesiredTuple = CISTPL_MANFID;
+    if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) {
+	info->manfid = le16_to_cpu(buf[0]);
+	for (i = 0; i < MULTI_COUNT; i++)
+	    if ((info->manfid == multi_id[i].manfid) &&
+		(le16_to_cpu(buf[1]) == multi_id[i].prodid))
+		break;
+	if (i < MULTI_COUNT)
+	    info->multi = multi_id[i].multi;
+    }
+
+    /* Another check for dual-serial cards: look for either serial or
+       multifunction cards that ask for appropriate IO port ranges */
+    tuple.DesiredTuple = CISTPL_FUNCID;
+    if ((info->multi == 0) &&
+	((first_tuple(handle, &tuple, &parse) != CS_SUCCESS) ||
+	 (parse.funcid.func == CISTPL_FUNCID_MULTI) ||
+	 (parse.funcid.func == CISTPL_FUNCID_SERIAL))) {
+	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+	if ((first_tuple(handle, &tuple, &parse) == CS_SUCCESS) &&
+	    (((cf->io.nwin == 1) && (cf->io.win[0].len == 16)) ||
+	     ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
+	      (cf->io.win[1].len == 8))))
+	    info->multi = 2;
+    }
+    
+    if (info->multi > 1)
+	multi_config(link);
+    else
+	simple_config(link);
+    
+    if (info->ndev == 0)
+	goto failed;
+    
+    if (info->manfid == MANFID_IBM) {
+	conf_reg_t reg = { 0, CS_READ, 0x800, 0 };
+	CS_CHECK(AccessConfigurationRegister, link->handle, &reg);
+	reg.Action = CS_WRITE;
+	reg.Value = reg.Value | 1;
+	CS_CHECK(AccessConfigurationRegister, link->handle, &reg);
+    }
+
+    link->dev = &info->node[0];
+    link->state &= ~DEV_CONFIG_PENDING;
+    return;
+
+cs_failed:
+    cs_error(link->handle, last_fn, last_ret);
+failed:
+    serial_release((u_long)link);
+
+} /* serial_config */
+
+/*======================================================================
+
+    After a card is removed, serial_release() will unregister the net
+    device, and release the PCMCIA configuration.
+    
+======================================================================*/
+
+void serial_release(u_long arg)
+{
+    dev_link_t *link = (dev_link_t *)arg;
+    serial_info_t *info = link->priv;
+    int i;
+    
+    sti();
+    
+    DEBUG(0, "serial_release(0x%p)\n", link);
+
+    for (i = 0; i < info->ndev; i++) {
+	unregister_serial(info->line[i]);
+    }
+    link->dev = NULL;
+
+    if (!info->slave) {
+	CardServices(ReleaseConfiguration, link->handle);
+	CardServices(ReleaseIO, link->handle, &link->io);
+	CardServices(ReleaseIRQ, link->handle, &link->irq);
+    }
+    
+    link->state &= ~DEV_CONFIG;
+
+} /* serial_release */
+
+/*======================================================================
+
+    The card status event handler.  Mostly, this schedules other
+    stuff to run after an event is received.  A CARD_REMOVAL event
+    also sets some flags to discourage the serial drivers from
+    talking to the ports.
+    
+======================================================================*/
+
+static int serial_event(event_t event, int priority,
+			event_callback_args_t *args)
+{
+    dev_link_t *link = args->client_data;
+    serial_info_t *info = link->priv;
+    
+    DEBUG(1, "serial_event(0x%06x)\n", event);
+    
+    switch (event) {
+    case CS_EVENT_CARD_REMOVAL:
+	link->state &= ~DEV_PRESENT;
+	if (link->state & DEV_CONFIG) {
+	    link->release.expires = jiffies + HZ/20;
+	    link->state |= DEV_RELEASE_PENDING;
+	    add_timer(&link->release);
+	}
+	break;
+    case CS_EVENT_CARD_INSERTION:
+	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+	serial_config(link);
+	break;
+    case CS_EVENT_PM_SUSPEND:
+	link->state |= DEV_SUSPEND;
+	/* Fall through... */
+    case CS_EVENT_RESET_PHYSICAL:
+	if ((link->state & DEV_CONFIG) && !info->slave)
+	    CardServices(ReleaseConfiguration, link->handle);
+	break;
+    case CS_EVENT_PM_RESUME:
+	link->state &= ~DEV_SUSPEND;
+	/* Fall through... */
+    case CS_EVENT_CARD_RESET:
+	if (DEV_OK(link) && !info->slave)
+	    CardServices(RequestConfiguration, link->handle, &link->conf);
+	break;
+    }
+    return 0;
+} /* serial_event */
+
+/*====================================================================*/
+
+static int __init init_serial_cs(void)
+{
+    servinfo_t serv;
+    DEBUG(0, "%s\n", version);
+    CardServices(GetCardServicesInfo, &serv);
+    if (serv.Revision != CS_RELEASE_CODE) {
+	printk(KERN_NOTICE "serial_cs: Card Services release "
+	       "does not match!\n");
+	return -1;
+    }
+    register_pccard_driver(&dev_info, &serial_attach, &serial_detach);
+    return 0;
+}
+
+static void __exit exit_serial_cs(void)
+{
+    DEBUG(0, "serial_cs: unloading\n");
+    unregister_pccard_driver(&dev_info);
+    while (dev_list != NULL)
+	serial_detach(dev_list);
+}
+
+module_init(init_serial_cs);
+module_exit(exit_serial_cs);
diff -u --recursive --new-file v2.3.26/linux/drivers/char/pms.c linux/drivers/char/pms.c
--- v2.3.26/linux/drivers/char/pms.c	Sat Oct  9 11:47:50 1999
+++ linux/drivers/char/pms.c	Wed Nov 10 13:39:06 1999
@@ -624,7 +624,7 @@
 {
 	int y;
 	int dw = 2*dev->width;
-	char *src = (char *)bus_to_virt(mem_base);
+	u32 src = mem_base;
 
 	char tmp[dw+32]; /* using a temp buffer is faster than direct  */
 	int cnt = 0;
@@ -639,8 +639,14 @@
   
 	for (y = 0; y < dev->height; y++ ) 
 	{
-		*src = 0;  /* synchronisiert neue Zeile */
-		memcpy(tmp, src, dw+32); /* discard 16 word   */
+		isa_writeb(0, src);  /* synchronisiert neue Zeile */
+		
+		/*
+		 *	This is in truth a fifo, be very careful as if you
+		 *	forgot this odd things will occur 8)
+		 */
+		 
+		isa_memcpy_fromio(tmp, src, dw+32); /* discard 16 word   */
 		cnt -= dev->height;
 		while (cnt <= 0) 
 		{ 
diff -u --recursive --new-file v2.3.26/linux/drivers/char/ppdev.c linux/drivers/char/ppdev.c
--- v2.3.26/linux/drivers/char/ppdev.c	Mon Nov  1 13:56:26 1999
+++ linux/drivers/char/ppdev.c	Tue Nov  9 09:29:52 1999
@@ -505,14 +505,14 @@
 	if (minor >= PARPORT_MAX)
 		return -ENXIO;
 
-	pp = kmalloc (GFP_KERNEL, sizeof (struct pp_struct));
+	pp = kmalloc (sizeof (struct pp_struct), GFP_KERNEL);
 	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 @@
 	}
 
 	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 -u --recursive --new-file v2.3.26/linux/drivers/char/saa7121.h linux/drivers/char/saa7121.h
--- v2.3.26/linux/drivers/char/saa7121.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/saa7121.h	Wed Nov 10 13:58:46 1999
@@ -0,0 +1,132 @@
+/* saa7121.h - saa7121 initializations
+   Copyright (C) 1999 Nathan Laredo (laredo@gnu.org)
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ */
+#ifndef __SAA7121_H__
+#define __SAA7121_H__
+
+#define NTSC_BURST_START	0x19	/* 28 */
+#define NTSC_BURST_END		0x1d	/* 29 */
+#define NTSC_CHROMA_PHASE	0x67	/* 5a */
+#define NTSC_GAINU		0x76	/* 5b */
+#define NTSC_GAINV		0xa5	/* 5c */
+#define NTSC_BLACK_LEVEL	0x2a	/* 5d */
+#define NTSC_BLANKING_LEVEL	0x2e	/* 5e */
+#define NTSC_VBI_BLANKING	0x2e	/* 5f */
+#define NTSC_DAC_CONTROL	0x11	/* 61 */
+#define NTSC_BURST_AMP		0x3f	/* 62 */
+#define NTSC_SUBC3		0x1f	/* 63 */
+#define NTSC_SUBC2		0x7c	/* 64 */
+#define NTSC_SUBC1		0xf0	/* 65 */
+#define NTSC_SUBC0		0x21	/* 66 */
+#define NTSC_HTRIG		0x72	/* 6c */
+#define NTSC_VTRIG		0x00	/* 6c */
+#define NTSC_MULTI		0x30	/* 6e */
+#define NTSC_CCTTX		0x11	/* 6f */
+#define NTSC_FIRST_ACTIVE	0x12	/* 7a */
+#define NTSC_LAST_ACTIVE	0x02	/* 7b */
+#define NTSC_MSB_VERTICAL	0x40	/* 7c */
+
+#define PAL_BURST_START		0x21	/* 28 */
+#define PAL_BURST_END		0x1d	/* 29 */
+#define PAL_CHROMA_PHASE	0x3f	/* 5a */
+#define PAL_GAINU		0x7d	/* 5b */
+#define PAL_GAINV		0xaf	/* 5c */
+#define PAL_BLACK_LEVEL		0x23	/* 5d */
+#define PAL_BLANKING_LEVEL	0x35	/* 5e */
+#define PAL_VBI_BLANKING	0x35	/* 5f */
+#define PAL_DAC_CONTROL		0x02	/* 61 */
+#define PAL_BURST_AMP		0x2f	/* 62 */
+#define PAL_SUBC3		0xcb	/* 63 */
+#define PAL_SUBC2		0x8a	/* 64 */
+#define PAL_SUBC1		0x09	/* 65 */
+#define PAL_SUBC0		0x2a	/* 66 */
+#define PAL_HTRIG		0x86	/* 6c */
+#define PAL_VTRIG		0x04	/* 6d */
+#define PAL_MULTI		0x20	/* 6e */
+#define PAL_CCTTX		0x15	/* 6f */
+#define PAL_FIRST_ACTIVE	0x16	/* 7a */
+#define PAL_LAST_ACTIVE		0x36	/* 7b */
+#define PAL_MSB_VERTICAL	0x40	/* 7c */
+
+/* Initialization Sequence */
+	 
+static __u8 init7121ntsc[] = {
+	0x26, 0x0,	0x27, 0x0,
+	0x28, NTSC_BURST_START,		0x29, NTSC_BURST_END,
+	0x2a, 0x0,	0x2b, 0x0,	0x2c, 0x0,	0x2d, 0x0,
+	0x2e, 0x0,	0x2f, 0x0,	0x30, 0x0,	0x31, 0x0,
+	0x32, 0x0,	0x33, 0x0,	0x34, 0x0,	0x35, 0x0,
+	0x36, 0x0,	0x37, 0x0,	0x38, 0x0,	0x39, 0x0,
+	0x3a, 0x03,	0x3b, 0x0,	0x3c, 0x0,	0x3d, 0x0,
+	0x3e, 0x0,	0x3f, 0x0,	0x40, 0x0,	0x41, 0x0,
+	0x42, 0x0,	0x43, 0x0,	0x44, 0x0,	0x45, 0x0,
+	0x46, 0x0,	0x47, 0x0,	0x48, 0x0,	0x49, 0x0,
+	0x4a, 0x0,	0x4b, 0x0,	0x4c, 0x0,	0x4d, 0x0,
+	0x4e, 0x0,	0x4f, 0x0,	0x50, 0x0,	0x51, 0x0,
+	0x52, 0x0,	0x53, 0x0,	0x54, 0x0,	0x55, 0x0,
+	0x56, 0x0,	0x57, 0x0,	0x58, 0x0,	0x59, 0x0,
+	0x5a, NTSC_CHROMA_PHASE,	0x5b, NTSC_GAINU,
+	0x5c, NTSC_GAINV,		0x5d, NTSC_BLACK_LEVEL,
+	0x5e, NTSC_BLANKING_LEVEL,	0x5f, NTSC_VBI_BLANKING,
+	0x60, 0x0,			0x61, NTSC_DAC_CONTROL,
+	0x62, NTSC_BURST_AMP,		0x63, NTSC_SUBC3,
+	0x64, NTSC_SUBC2,		0x65, NTSC_SUBC1,
+	0x66, NTSC_SUBC0,		0x67, 0x80,	0x68, 0x80,
+	0x69, 0x80,	0x6a, 0x80,	0x6b, 0x29,
+	0x6c, NTSC_HTRIG,		0x6d, NTSC_VTRIG,
+	0x6e, NTSC_MULTI,		0x6f, NTSC_CCTTX,
+	0x70, 0xc9,	0x71, 0x68,	0x72, 0x60,	0x73, 0x0,
+	0x74, 0x0,	0x75, 0x0,	0x76, 0x0,	0x77, 0x0,
+	0x78, 0x0,	0x79, 0x0,	0x7a, NTSC_FIRST_ACTIVE,
+	0x7b, NTSC_LAST_ACTIVE,		0x7c, NTSC_MSB_VERTICAL,
+	0x7d, 0x0,	0x7e, 0x0,	0x7f, 0x0
+}; 
+#define INIT7121LEN	(sizeof(init7121ntsc)/2)
+
+static __u8 init7121pal[] = {
+	0x26, 0x0,	0x27, 0x0,
+	0x28, PAL_BURST_START,		0x29, PAL_BURST_END,
+	0x2a, 0x0,	0x2b, 0x0,	0x2c, 0x0,	0x2d, 0x0,
+	0x2e, 0x0,	0x2f, 0x0,	0x30, 0x0,	0x31, 0x0,
+	0x32, 0x0,	0x33, 0x0,	0x34, 0x0,	0x35, 0x0,
+	0x36, 0x0,	0x37, 0x0,	0x38, 0x0,	0x39, 0x0,
+	0x3a, 0x03,	0x3b, 0x0,	0x3c, 0x0,	0x3d, 0x0,
+	0x3e, 0x0,	0x3f, 0x0,	0x40, 0x0,	0x41, 0x0,
+	0x42, 0x0,	0x43, 0x0,	0x44, 0x0,	0x45, 0x0,
+	0x46, 0x0,	0x47, 0x0,	0x48, 0x0,	0x49, 0x0,
+	0x4a, 0x0,	0x4b, 0x0,	0x4c, 0x0,	0x4d, 0x0,
+	0x4e, 0x0,	0x4f, 0x0,	0x50, 0x0,	0x51, 0x0,
+	0x52, 0x0,	0x53, 0x0,	0x54, 0x0,	0x55, 0x0,
+	0x56, 0x0,	0x57, 0x0,	0x58, 0x0,	0x59, 0x0,
+	0x5a, PAL_CHROMA_PHASE,		0x5b, PAL_GAINU,
+	0x5c, PAL_GAINV,		0x5d, PAL_BLACK_LEVEL,
+	0x5e, PAL_BLANKING_LEVEL,	0x5f, PAL_VBI_BLANKING,
+	0x60, 0x0,			0x61, PAL_DAC_CONTROL,
+	0x62, PAL_BURST_AMP,		0x63, PAL_SUBC3,
+	0x64, PAL_SUBC2,		0x65, PAL_SUBC1,
+	0x66, PAL_SUBC0,		0x67, 0x80,	0x68, 0x80,
+	0x69, 0x80,	0x6a, 0x80,	0x6b, 0x29,
+	0x6c, PAL_HTRIG,		0x6d, PAL_VTRIG,
+	0x6e, PAL_MULTI,		0x6f, PAL_CCTTX,
+	0x70, 0xc9,	0x71, 0x68,	0x72, 0x60,	0x73, 0x0,
+	0x74, 0x0,	0x75, 0x0,	0x76, 0x0,	0x77, 0x0,
+	0x78, 0x0,	0x79, 0x0,	0x7a, PAL_FIRST_ACTIVE,
+	0x7b, PAL_LAST_ACTIVE,		0x7c, PAL_MSB_VERTICAL,
+	0x7d, 0x0,	0x7e, 0x0,	0x7f, 0x0
+}; 
+#endif
diff -u --recursive --new-file v2.3.26/linux/drivers/char/saa7146.h linux/drivers/char/saa7146.h
--- v2.3.26/linux/drivers/char/saa7146.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/saa7146.h	Wed Nov 10 13:58:46 1999
@@ -0,0 +1,117 @@
+/*  
+    saa7146.h - definitions philips saa7146 based cards
+    Copyright (C) 1999 Nathan Laredo (laredo@gnu.org)
+    
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __SAA7146__
+#define __SAA7146__
+
+#define SAA7146_VERSION_CODE 0x000101
+
+#include <linux/types.h>
+#include <linux/wait.h>
+
+#include <linux/i2c.h>
+#include <linux/videodev.h>
+
+#ifndef O_NONCAP  
+#define O_NONCAP	O_TRUNC
+#endif
+
+#define MAX_GBUFFERS	2
+#define FBUF_SIZE	0x190000
+
+#ifdef __KERNEL__
+
+struct saa7146_window 
+{
+	int x, y;
+	ushort width, height;
+	ushort bpp, bpl;
+	ushort swidth, sheight;
+	short cropx, cropy;
+	ushort cropwidth, cropheight;
+	unsigned long vidadr;
+	int color_fmt;
+	ushort depth;
+};
+
+/*  Per-open data for handling multiple opens on one device */
+struct device_open
+{
+	int	     isopen;
+	int	     noncapturing;
+	struct saa7146  *dev;
+};
+#define MAX_OPENS 3
+
+struct saa7146
+{
+	struct video_device video_dev;
+	struct video_picture picture;
+	struct video_audio audio_dev;
+	struct video_info vidinfo;
+	int user;
+	int cap;
+	int capuser;
+	int irqstate;		/* irq routine is state driven */
+	int writemode;
+	int playmode;
+        unsigned int nr;
+	unsigned long irq;          /* IRQ used by SAA7146 card */
+	unsigned short id;
+	struct i2c_bus i2c;
+	struct pci_dev *dev;
+	unsigned char revision;
+	unsigned char boardcfg[64];	/* 64 bytes of config from eeprom */
+	unsigned long saa7146_adr;   /* bus address of IO mem from PCI BIOS */
+	struct saa7146_window win;
+	unsigned char *saa7146_mem; /* pointer to mapped IO memory */
+	struct device_open open_data[MAX_OPENS];
+#define MAX_MARKS 16
+	/* for a/v sync */
+	int endmark[MAX_MARKS], endmarkhead, endmarktail;
+	u32 *dmaRPS1, *pageRPS1, *dmaRPS2, *pageRPS2, *dmavid1, *dmavid2,
+		*dmavid3, *dmaa1in, *dmaa1out, *dmaa2in, *dmaa2out,
+		*pagedebi, *pagevid1, *pagevid2, *pagevid3, *pagea1in,
+		*pagea1out, *pagea2in, *pagea2out;
+	wait_queue_head_t i2cq, debiq, audq, vidq;
+	u8  *vidbuf, *audbuf, *osdbuf, *dmadebi;
+	int audhead, vidhead, osdhead, audtail, vidtail, osdtail;
+	spinlock_t lock;	/* the device lock */
+};
+#endif
+
+#ifdef _ALPHA_SAA7146
+#define saawrite(dat,adr)    writel((dat),(char *) (saa->saa7146_adr+(adr)))
+#define saaread(adr)         readl(saa->saa7146_adr+(adr))
+#else
+#define saawrite(dat,adr)    writel((dat), (char *) (saa->saa7146_mem+(adr)))
+#define saaread(adr)         readl(saa->saa7146_mem+(adr))
+#endif
+
+#define saaand(dat,adr)      saawrite((dat) & saaread(adr), adr)
+#define saaor(dat,adr)       saawrite((dat) | saaread(adr), adr)
+#define saaaor(dat,mask,adr) saawrite((dat) | ((mask) & saaread(adr)), adr)
+
+/* bitmask of attached hardware found */
+#define SAA7146_UNKNOWN		0x00000000
+#define SAA7146_SAA7111		0x00000001
+#define SAA7146_SAA7121		0x00000002
+#define SAA7146_IBMMPEG		0x00000004
+
+#endif
diff -u --recursive --new-file v2.3.26/linux/drivers/char/saa7146reg.h linux/drivers/char/saa7146reg.h
--- v2.3.26/linux/drivers/char/saa7146reg.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/saa7146reg.h	Wed Nov 10 13:58:46 1999
@@ -0,0 +1,283 @@
+/*  
+    saa7146.h - definitions philips saa7146 based cards
+    Copyright (C) 1999 Nathan Laredo (laredo@gnu.org)
+    
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __SAA7146_REG__
+#define __SAA7146_REG__
+#define SAA7146_BASE_ODD1	0x00
+#define SAA7146_BASE_EVEN1	0x04
+#define SAA7146_PROT_ADDR1	0x08
+#define SAA7146_PITCH1		0x0c
+#define SAA7146_PAGE1		0x10
+#define SAA7146_NUM_LINE_BYTE1	0x14
+#define SAA7146_BASE_ODD2	0x18
+#define SAA7146_BASE_EVEN2	0x1c
+#define SAA7146_PROT_ADDR2	0x20
+#define SAA7146_PITCH2		0x24
+#define SAA7146_PAGE2		0x28
+#define SAA7146_NUM_LINE_BYTE2	0x2c
+#define SAA7146_BASE_ODD3	0x30
+#define SAA7146_BASE_EVEN3	0x34
+#define SAA7146_PROT_ADDR3	0x38
+#define SAA7146_PITCH3		0x3c
+#define SAA7146_PAGE3		0x40
+#define SAA7146_NUM_LINE_BYTE3	0x44
+#define SAA7146_PCI_BT_V1	0x48
+#define SAA7146_PCI_BT_V2	0x49
+#define SAA7146_PCI_BT_V3	0x4a
+#define SAA7146_PCI_BT_DEBI	0x4b
+#define SAA7146_PCI_BT_A	0x4c
+#define SAA7146_DD1_INIT	0x50
+#define SAA7146_DD1_STREAM_B	0x54
+#define SAA7146_DD1_STREAM_A	0x56
+#define SAA7146_BRS_CTRL	0x58
+#define SAA7146_HPS_CTRL	0x5c
+#define SAA7146_HPS_V_SCALE	0x60
+#define SAA7146_HPS_V_GAIN	0x64
+#define SAA7146_HPS_H_PRESCALE	0x68
+#define SAA7146_HPS_H_SCALE	0x6c
+#define SAA7146_BCS_CTRL	0x70
+#define SAA7146_CHROMA_KEY_RANGE	0x74
+#define SAA7146_CLIP_FORMAT_CTRL	0x78
+#define SAA7146_DEBI_CONFIG	0x7c
+#define SAA7146_DEBI_COMMAND	0x80
+#define SAA7146_DEBI_PAGE	0x84
+#define SAA7146_DEBI_AD		0x88
+#define SAA7146_I2C_TRANSFER	0x8c
+#define SAA7146_I2C_STATUS	0x90
+#define SAA7146_BASE_A1_IN	0x94
+#define SAA7146_PROT_A1_IN	0x98
+#define SAA7146_PAGE_A1_IN	0x9C
+#define SAA7146_BASE_A1_OUT	0xa0
+#define SAA7146_PROT_A1_OUT	0xa4
+#define SAA7146_PAGE_A1_OUT	0xa8
+#define SAA7146_BASE_A2_IN	0xac
+#define SAA7146_PROT_A2_IN	0xb0
+#define SAA7146_PAGE_A2_IN	0xb4
+#define SAA7146_BASE_A2_OUT	0xb8
+#define SAA7146_PROT_A2_OUT	0xbc
+#define SAA7146_PAGE_A2_OUT	0xc0
+#define SAA7146_RPS_PAGE0	0xc4
+#define SAA7146_RPS_PAGE1	0xc8
+#define SAA7146_RPS_THRESH0	0xcc
+#define SAA7146_RPS_THRESH1	0xd0
+#define SAA7146_RPS_TOV0	0xd4
+#define SAA7146_RPS_TOV1	0xd8
+#define SAA7146_IER		0xdc
+#define SAA7146_GPIO_CTRL	0xe0
+#define SAA7146_EC1SSR		0xe4
+#define SAA7146_EC2SSR		0xe8
+#define SAA7146_ECT1R		0xec
+#define SAA7146_ECT2R		0xf0
+#define SAA7146_ACON1		0xf4
+#define SAA7146_ACON2		0xf8
+#define SAA7146_MC1		0xfc
+#define SAA7146_MC2		0x100
+#define SAA7146_RPS_ADDR0	0x104
+#define SAA7146_RPS_ADDR1	0x108
+#define SAA7146_ISR		0x10c
+#define SAA7146_PSR		0x110
+#define SAA7146_SSR		0x114
+#define SAA7146_EC1R		0x118
+#define SAA7146_EC2R		0x11c
+#define SAA7146_VDP1		0x120
+#define SAA7146_VDP2		0x124
+#define SAA7146_VDP3		0x128
+#define SAA7146_ADP1		0x12c
+#define SAA7146_ADP2		0x130
+#define SAA7146_ADP3		0x134
+#define SAA7146_ADP4		0x138
+#define SAA7146_DDP		0x13c
+#define SAA7146_LEVEL_REP	0x140
+#define SAA7146_FB_BUFFER1	0x144
+#define SAA7146_FB_BUFFER2	0x148
+#define SAA7146_A_TIME_SLOT1	0x180
+#define SAA7146_A_TIME_SLOT2	0x1C0
+
+/* bitfield defines */
+#define MASK_31			0x80000000
+#define MASK_30			0x40000000
+#define MASK_29			0x20000000
+#define MASK_28			0x10000000
+#define MASK_27			0x08000000
+#define MASK_26			0x04000000
+#define MASK_25			0x02000000
+#define MASK_24			0x01000000
+#define MASK_23			0x00800000
+#define MASK_22			0x00400000
+#define MASK_21			0x00200000
+#define MASK_20			0x00100000
+#define MASK_19			0x00080000
+#define MASK_18			0x00040000
+#define MASK_17			0x00020000
+#define MASK_16			0x00010000
+#define MASK_15			0x00008000
+#define MASK_14			0x00004000
+#define MASK_13			0x00002000
+#define MASK_12			0x00001000
+#define MASK_11			0x00000800
+#define MASK_10			0x00000400
+#define MASK_09			0x00000200
+#define MASK_08			0x00000100
+#define MASK_07			0x00000080
+#define MASK_06			0x00000040
+#define MASK_05			0x00000020
+#define MASK_04			0x00000010
+#define MASK_03			0x00000008
+#define MASK_02			0x00000004
+#define MASK_01			0x00000002
+#define MASK_00			0x00000001
+#define MASK_B0			0x000000ff
+#define MASK_B1			0x0000ff00
+#define MASK_B2			0x00ff0000
+#define MASK_B3			0xff000000
+#define MASK_W0			0x0000ffff
+#define MASK_W1			0xffff0000
+#define MASK_PA			0xfffffffc
+#define MASK_PR			0xfffffffe
+#define MASK_ER			0xffffffff
+#define MASK_NONE		0x00000000
+
+#define SAA7146_PAGE_MAP_EN	MASK_11
+/* main control register 1 */
+#define SAA7146_MC1_MRST_N	MASK_15
+#define SAA7146_MC1_ERPS1	MASK_13
+#define SAA7146_MC1_ERPS0	MASK_12
+#define SAA7146_MC1_EDP		MASK_11
+#define SAA7146_MC1_EVP		MASK_10
+#define SAA7146_MC1_EAP		MASK_09
+#define SAA7146_MC1_EI2C	MASK_08
+#define SAA7146_MC1_TR_E_DEBI	MASK_07
+#define SAA7146_MC1_TR_E_1	MASK_06
+#define SAA7146_MC1_TR_E_2	MASK_05
+#define SAA7146_MC1_TR_E_3	MASK_04
+#define SAA7146_MC1_TR_E_A2_OUT	MASK_03
+#define SAA7146_MC1_TR_E_A2_IN	MASK_02
+#define SAA7146_MC1_TR_E_A1_OUT	MASK_01
+#define SAA7146_MC1_TR_E_A1_IN	MASK_00
+/* main control register 2 */
+#define SAA7146_MC2_RPS_SIG4	MASK_15
+#define SAA7146_MC2_RPS_SIG3	MASK_14
+#define SAA7146_MC2_RPS_SIG2	MASK_13
+#define SAA7146_MC2_RPS_SIG1	MASK_12
+#define SAA7146_MC2_RPS_SIG0	MASK_11
+#define SAA7146_MC2_UPLD_D1_B	MASK_10
+#define SAA7146_MC2_UPLD_D1_A	MASK_09
+#define SAA7146_MC2_UPLD_BRS	MASK_08
+#define SAA7146_MC2_UPLD_HPS_H	MASK_06
+#define SAA7146_MC2_UPLD_HPS_V	MASK_05
+#define SAA7146_MC2_UPLD_DMA3	MASK_04
+#define SAA7146_MC2_UPLD_DMA2	MASK_03
+#define SAA7146_MC2_UPLD_DMA1	MASK_02
+#define SAA7146_MC2_UPLD_DEBI	MASK_01
+#define SAA7146_MC2_UPLD_I2C	MASK_00
+/* Primary Status Register and Interrupt Enable/Status Registers */
+#define SAA7146_PSR_PPEF	MASK_31
+#define SAA7146_PSR_PABO	MASK_30
+#define SAA7146_PSR_PPED	MASK_29
+#define SAA7146_PSR_RPS_I1	MASK_28
+#define SAA7146_PSR_RPS_I0	MASK_27
+#define SAA7146_PSR_RPS_LATE1	MASK_26
+#define SAA7146_PSR_RPS_LATE0	MASK_25
+#define SAA7146_PSR_RPS_E1	MASK_24
+#define SAA7146_PSR_RPS_E0	MASK_23
+#define SAA7146_PSR_RPS_TO1	MASK_22
+#define SAA7146_PSR_RPS_TO0	MASK_21
+#define SAA7146_PSR_UPLD	MASK_20
+#define SAA7146_PSR_DEBI_S	MASK_19
+#define SAA7146_PSR_DEBI_E	MASK_18
+#define SAA7146_PSR_I2C_S	MASK_17
+#define SAA7146_PSR_I2C_E	MASK_16
+#define SAA7146_PSR_A2_IN	MASK_15
+#define SAA7146_PSR_A2_OUT	MASK_14
+#define SAA7146_PSR_A1_IN	MASK_13
+#define SAA7146_PSR_A1_OUT	MASK_12
+#define SAA7146_PSR_AFOU	MASK_11
+#define SAA7146_PSR_V_PE	MASK_10
+#define SAA7146_PSR_VFOU	MASK_09
+#define SAA7146_PSR_FIDA	MASK_08
+#define SAA7146_PSR_FIDB	MASK_07
+#define SAA7146_PSR_PIN3	MASK_06
+#define SAA7146_PSR_PIN2	MASK_05
+#define SAA7146_PSR_PIN1	MASK_04
+#define SAA7146_PSR_PIN0	MASK_03
+#define SAA7146_PSR_ECS		MASK_02
+#define SAA7146_PSR_EC3S	MASK_01
+#define SAA7146_PSR_EC0S	MASK_00
+/* Secondary Status Register */
+#define SAA7146_SSR_PRQ		MASK_31
+#define SAA7146_SSR_PMA		MASK_30
+#define SAA7146_SSR_RPS_RE1	MASK_29
+#define SAA7146_SSR_RPS_PE1	MASK_28
+#define SAA7146_SSR_RPS_A1	MASK_27
+#define SAA7146_SSR_RPS_RE0	MASK_26
+#define SAA7146_SSR_RPS_PE0	MASK_25
+#define SAA7146_SSR_RPS_A0	MASK_24
+#define SAA7146_SSR_DEBI_TO	MASK_23
+#define SAA7146_SSR_DEBI_EF	MASK_22
+#define SAA7146_SSR_I2C_EA	MASK_21
+#define SAA7146_SSR_I2C_EW	MASK_20
+#define SAA7146_SSR_I2C_ER	MASK_19
+#define SAA7146_SSR_I2C_EL	MASK_18
+#define SAA7146_SSR_I2C_EF	MASK_17
+#define SAA7146_SSR_V3P		MASK_16
+#define SAA7146_SSR_V2P		MASK_15
+#define SAA7146_SSR_V1P		MASK_14
+#define SAA7146_SSR_VF3		MASK_13
+#define SAA7146_SSR_VF2		MASK_12
+#define SAA7146_SSR_VF1		MASK_11
+#define SAA7146_SSR_AF2_IN	MASK_10
+#define SAA7146_SSR_AF2_OUT	MASK_09
+#define SAA7146_SSR_AF1_IN	MASK_08
+#define SAA7146_SSR_AF1_OUT	MASK_07
+#define SAA7146_SSR_VGT		MASK_05
+#define SAA7146_SSR_LNQG	MASK_04
+#define SAA7146_SSR_EC5S	MASK_03
+#define SAA7146_SSR_EC4S	MASK_02
+#define SAA7146_SSR_EC2S	MASK_01
+#define SAA7146_SSR_EC1S	MASK_00
+/* I2C status register */
+#define SAA7146_I2C_ABORT	MASK_07
+#define SAA7146_I2C_SPERR	MASK_06
+#define SAA7146_I2C_APERR	MASK_05
+#define SAA7146_I2C_DTERR	MASK_04
+#define SAA7146_I2C_DRERR	MASK_03
+#define SAA7146_I2C_AL		MASK_02
+#define SAA7146_I2C_ERR		MASK_01
+#define SAA7146_I2C_BUSY	MASK_00
+/* output formats */
+#define SAA7146_YUV422	0
+#define SAA7146_RGB16	0
+#define SAA7146_YUV444	1
+#define SAA7146_RGB24	1
+#define SAA7146_ARGB32	2
+#define SAA7146_YUV411	3
+#define SAA7146_ARGB15  3
+#define SAA7146_YUV2	4
+#define SAA7146_RGAB15	4
+#define SAA7146_Y8	6
+#define SAA7146_YUV8	7
+#define SAA7146_RGB8	7
+#define SAA7146_YUV444p	8
+#define SAA7146_YUV422p	9
+#define SAA7146_YUV420p	10
+#define SAA7146_YUV1620	11
+#define SAA7146_Y1	13
+#define SAA7146_Y2	14
+#define SAA7146_YUV1	15
+#endif
diff -u --recursive --new-file v2.3.26/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.3.26/linux/drivers/char/serial.c	Mon Nov  1 13:56:26 1999
+++ linux/drivers/char/serial.c	Mon Nov  8 15:04:10 1999
@@ -3457,11 +3457,13 @@
 	}
 	if (state->type == PORT_16550A) {
 		/* Check for Oxford Semiconductor 16C950 */
+		unsigned char scratch4;
+
 		scratch = serial_icr_read(info, UART_ID1);
-		scratch2 = serial_icr_read(info, UART_ID2);
+		scratch4 = serial_icr_read(info, UART_ID2);
 		scratch3 = serial_icr_read(info, UART_ID3);
 		
-		if (scratch == 0x16 && scratch2 == 0xC9 &&
+		if (scratch == 0x16 && scratch4 == 0xC9 &&
 		    (scratch3 == 0x50 || scratch3 == 0x52 ||
 		     scratch3 == 0x54)) {
 			state->type = PORT_16C950;
diff -u --recursive --new-file v2.3.26/linux/drivers/char/stradis.c linux/drivers/char/stradis.c
--- v2.3.26/linux/drivers/char/stradis.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/stradis.c	Thu Nov 11 10:07:21 1999
@@ -0,0 +1,2286 @@
+/* 
+ * stradis.c - stradis 4:2:2 mpeg decoder driver
+ *
+ * Stradis 4:2:2 MPEG-2 Decoder Driver
+ * Copyright (C) 1999 Nathan Laredo <laredo@gnu.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/malloc.h>
+#include <linux/mm.h>
+#include <linux/poll.h>
+#include <linux/pci.h>
+#include <linux/signal.h>
+#include <asm/io.h>
+#include <linux/ioport.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <linux/sched.h>
+#include <asm/segment.h>
+#include <asm/types.h>
+#include <linux/types.h>
+#include <linux/wrapper.h>
+#include <linux/interrupt.h>
+#include <asm/uaccess.h>
+#include <linux/vmalloc.h>
+#include <linux/videodev.h>
+#include <linux/i2c.h>
+
+#include "saa7146.h"
+#include "saa7146reg.h"
+#include "ibmmpeg2.h"
+#include "saa7121.h"
+#include "cs8420.h"
+
+#define DEBUG(x) 		/* debug driver */
+#undef  IDEBUG(x) 		/* debug irq handler */
+#undef  MDEBUG(x) 		/* debug memory management */
+
+#define SAA7146_MAX 6
+
+static struct saa7146 saa7146s[SAA7146_MAX];
+
+static int saa_num = 0;		/* number of SAA7146s in use */
+
+#define nDebNormal	0x00480000
+#define nDebNoInc	0x00480000
+#define nDebVideo	0xd0480000
+#define nDebAudio	0xd0400000
+#define nDebDMA		0x02c80000
+
+#define oDebNormal	0x13c80000
+#define oDebNoInc	0x13c80000
+#define oDebVideo	0xd1080000
+#define oDebAudio	0xd1080000
+#define oDebDMA		0x03080000
+
+#define NewCard		(saa->boardcfg[3])
+#define ChipControl	(saa->boardcfg[1])
+#define NTSCFirstActive	(saa->boardcfg[4])
+#define PALFirstActive	(saa->boardcfg[5])
+#define NTSCLastActive	(saa->boardcfg[54])
+#define PALLastActive	(saa->boardcfg[55])
+#define Have2MB		(saa->boardcfg[18] & 0x40)
+#define HaveCS8420	(saa->boardcfg[18] & 0x04)
+#define IBMMPEGCD20	(saa->boardcfg[18] & 0x20)
+#define HaveCS3310	(saa->boardcfg[18] & 0x01)
+#define CS3310MaxLvl	((saa->boardcfg[30] << 8) | saa->boardcfg[31])
+#define HaveCS4341	(saa->boardcfg[40] == 2)
+#define SDIType		(saa->boardcfg[27])
+#define CurrentMode	(saa->boardcfg[2])
+
+#define debNormal	(NewCard ? nDebNormal : oDebNormal)
+#define debNoInc	(NewCard ? nDebNoInc : oDebNoInc)
+#define debVideo	(NewCard ? nDebVideo : oDebVideo)
+#define debAudio	(NewCard ? nDebAudio : oDebAudio)
+#define debDMA		(NewCard ? nDebDMA : oDebDMA)
+
+#ifdef DEBUG
+int stradis_driver(void)	/* for the benefit of ksymoops */
+{
+	return 1;
+}
+#endif
+
+#ifdef USE_RESCUE_EEPROM_SDM275
+static unsigned char rescue_eeprom[64] = {
+0x00,0x01,0x04,0x13,0x26,0x0f,0x10,0x00,0x00,0x00,0x43,0x63,0x22,0x01,0x29,0x15,0x73,0x00,0x1f, 'd', 'e', 'c', 'x', 'l', 'd', 'v', 'a',0x02,0x00,0x01,0x00,0xcc,0xa4,0x63,0x09,0xe2,0x10,0x00,0x0a,0x00,0x02,0x02, 'd', 'e', 'c', 'x', 'l', 'a',0x00,0x00,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+#endif
+
+/* ----------------------------------------------------------------------- */
+/* Hardware I2C functions */
+static void I2CWipe(struct saa7146 *saa)
+{
+	int i;
+	/* set i2c to ~=100kHz, abort transfer, clear busy */
+	saawrite(0x600 | SAA7146_I2C_ABORT, SAA7146_I2C_STATUS);
+	saawrite((SAA7146_MC2_UPLD_I2C << 16) |
+		 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
+	/* wait for i2c registers to be programmed */
+	for (i = 0; i < 1000 &&
+	     !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
+		schedule();
+	saawrite(0x600, SAA7146_I2C_STATUS);
+	saawrite((SAA7146_MC2_UPLD_I2C << 16) |
+		 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
+	/* wait for i2c registers to be programmed */
+	for (i = 0; i < 1000 &&
+	     !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
+		schedule();
+	saawrite(0x600, SAA7146_I2C_STATUS);
+	saawrite((SAA7146_MC2_UPLD_I2C << 16) |
+		 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
+	/* wait for i2c registers to be programmed */
+	for (i = 0; i < 1000 &&
+	     !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
+		schedule();
+}
+/* read I2C */
+static int I2CRead(struct i2c_bus *bus, unsigned char addr,
+		   unsigned char subaddr, int dosub)
+{
+	struct saa7146 *saa = (struct saa7146 *) bus->data;
+	int i;
+
+
+	if (saaread(SAA7146_I2C_STATUS) & 0x3c)
+		I2CWipe(saa);
+	for (i = 0; i < 1000 &&
+	     (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++)
+		schedule();
+	if (i == 1000)
+		I2CWipe(saa);
+	if (dosub)
+		saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 8) |
+		  ((subaddr & 0xff) << 16) | 0xed, SAA7146_I2C_TRANSFER);
+	else
+		saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 16) |
+			 0xf1, SAA7146_I2C_TRANSFER);
+	saawrite((SAA7146_MC2_UPLD_I2C << 16) |
+		 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
+	/* wait for i2c registers to be programmed */
+	for (i = 0; i < 1000 &&
+	     !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
+		schedule();
+	/* wait for valid data */
+	for (i = 0; i < 1000 &&
+	     (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++)
+		schedule();
+	if (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_ERR)
+		return -1;
+	if (i == 1000) 
+		printk("i2c setup read timeout\n");
+	saawrite(0x41, SAA7146_I2C_TRANSFER);
+	saawrite((SAA7146_MC2_UPLD_I2C << 16) |
+		 SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
+	/* wait for i2c registers to be programmed */
+	for (i = 0; i < 1000 &&
+	     !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
+		schedule();
+	/* wait for valid data */
+	for (i = 0; i < 1000 &&
+	     (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_BUSY); i++)
+		schedule();
+	if (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_ERR)
+		return -1;
+	if (i == 1000) 
+		printk("i2c read timeout\n");
+	return ((saaread(SAA7146_I2C_TRANSFER) >> 24) & 0xff);
+}
+static int I2CReadOld(struct i2c_bus *bus, unsigned char addr)
+{
+	return I2CRead(bus, addr, 0, 0);
+}
+
+/* set both to write both bytes, reset it to write only b1 */
+
+static int I2CWrite(struct i2c_bus *bus, unsigned char addr, unsigned char b1,
+		    unsigned char b2, int both)
+{
+	struct saa7146 *saa = (struct saa7146 *) bus->data;
+	int i;
+	u32 data;
+
+	if (saaread(SAA7146_I2C_STATUS) & 0x3c)
+		I2CWipe(saa);
+	for (i = 0; i < 1000 &&
+	     (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++)
+		schedule();
+	if (i == 1000)
+		I2CWipe(saa);
+	data = ((addr & 0xfe) << 24) | ((b1 & 0xff) << 16);
+	if (both)
+		data |= ((b2 & 0xff) << 8) | 0xe5;
+	else
+		data |= 0xd1;
+	saawrite(data, SAA7146_I2C_TRANSFER);
+	saawrite((SAA7146_MC2_UPLD_I2C << 16) | SAA7146_MC2_UPLD_I2C,
+		 SAA7146_MC2);
+	return 0;
+}
+
+static void attach_inform(struct i2c_bus *bus, int id)
+{
+	struct saa7146 *saa = (struct saa7146 *) bus->data;
+	int i;
+
+	DEBUG(printk(KERN_DEBUG "stradis%d: i2c: device found=%02x\n", saa->nr, id));
+	if (id == 0xa0)	{ /* we have rev2 or later board, fill in info */
+		for (i = 0; i < 64; i++)
+			saa->boardcfg[i] = I2CRead(bus, 0xa0, i, 1);
+#ifdef USE_RESCUE_EEPROM_SDM275
+		if (saa->boardcfg[0] != 0) {
+			printk("stradis%d: WARNING: EEPROM STORED VALUES HAVE BEEN IGNORED\n", saa->nr);
+			for (i = 0; i < 64; i++)
+				saa->boardcfg[i] = rescue_eeprom[i];
+		}
+#endif
+		printk("stradis%d: config =", saa->nr);
+		for (i = 0; i < 51; i++) {
+			printk(" %02x",saa->boardcfg[i]);
+		}
+		printk("\n");
+	}
+}
+
+static void detach_inform(struct i2c_bus *bus, int id)
+{
+	struct saa7146 *saa = (struct saa7146 *) bus->data;
+	int i;
+	i = saa->nr;
+}
+
+static void I2CBusScan(struct i2c_bus *bus)
+{
+	int i;
+	for (i = 0; i < 0xff; i += 2)
+		if ((I2CRead(bus, i, 0, 0)) >= 0)
+			attach_inform(bus, i);
+}
+
+static struct i2c_bus saa7146_i2c_bus_template =
+{
+	"saa7146",
+	I2C_BUSID_BT848,
+	NULL,
+	SPIN_LOCK_UNLOCKED,
+	attach_inform,
+	detach_inform,
+	NULL,
+	NULL,
+	I2CReadOld,
+	I2CWrite,
+};
+
+static int debiwait_maxwait = 0;
+
+static int wait_for_debi_done(struct saa7146 *saa)
+{
+	int i;
+
+	/* wait for registers to be programmed */
+	for (i = 0; i < 100000 &&
+	     !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_DEBI); i++)
+		saaread(SAA7146_MC2);
+	/* wait for transfer to complete */
+	for (i = 0; i < 500000 &&
+	     (saaread(SAA7146_PSR) & SAA7146_PSR_DEBI_S); i++)
+		saaread(SAA7146_MC2);
+	if (i > debiwait_maxwait)
+		printk("wait-for-debi-done maxwait: %d\n",
+			debiwait_maxwait = i);
+	
+	if (i == 500000)
+		return -1;
+	return 0;
+}
+
+static int debiwrite(struct saa7146 *saa, u32 config, int addr,
+		      u32 val, int count)
+{
+	u32 cmd;
+	if (count <= 0 || count > 32764)
+		return -1;
+	if (wait_for_debi_done(saa) < 0)
+		return -1;
+	saawrite(config, SAA7146_DEBI_CONFIG);
+	if (count <= 4)		/* immediate transfer */
+		saawrite(val, SAA7146_DEBI_AD);
+	else			/* block transfer */
+		saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD);
+	saawrite((cmd = (count << 17) | (addr & 0xffff)), SAA7146_DEBI_COMMAND);
+	saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI,
+		 SAA7146_MC2);
+	return 0;
+}
+
+static u32 debiread(struct saa7146 *saa, u32 config, int addr, int count)
+{
+	u32 result = 0;
+
+	if (count > 32764 || count <= 0)
+		return 0;
+	if (wait_for_debi_done(saa) < 0)
+		return 0;
+	saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD);
+	saawrite((count << 17) | 0x10000 | (addr & 0xffff),
+		 SAA7146_DEBI_COMMAND);
+	saawrite(config, SAA7146_DEBI_CONFIG);
+	saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI,
+		 SAA7146_MC2);
+	if (count > 4)		/* not an immediate transfer */
+		return count;
+	wait_for_debi_done(saa);
+	result = saaread(SAA7146_DEBI_AD);
+	if (count == 1)
+		result &= 0xff;
+	if (count == 2)
+		result &= 0xffff;
+	if (count == 3)
+		result &= 0xffffff;
+	return result;
+}
+
+/* MUST be a multiple of 8 bytes and 8-byte aligned and < 32768 bytes */
+/* data copied into saa->dmadebi buffer, caller must re-enable interrupts */
+static void ibm_block_dram_read(struct saa7146 *saa, int address, int bytes)
+{
+	int i, j;
+	u32 *buf;
+	buf = (u32 *) saa->dmadebi;
+	if (bytes > 0x7000)
+		bytes = 0x7000;
+	saawrite(0, SAA7146_IER);	/* disable interrupts */
+	for (i=0; i < 10000 &&
+		(debiread(saa, debNormal, IBM_MP2_DRAM_CMD_STAT, 2)
+		& 0x8000); i++)
+		saaread(SAA7146_MC2);
+	if (i == 10000)
+		printk(KERN_ERR "stradis%d: dram_busy never cleared\n",
+			saa->nr);
+	debiwrite(saa, debNormal, IBM_MP2_SRC_ADDR, (address<<16) |
+		(address>>16), 4);
+	debiwrite(saa, debNormal, IBM_MP2_BLOCK_SIZE, bytes, 2);
+	debiwrite(saa, debNormal, IBM_MP2_CMD_STAT, 0x8a10, 2);
+	for (j = 0; j < bytes/4; j++) {
+		for (i = 0; i < 10000 &&
+			(!(debiread(saa, debNormal, IBM_MP2_DRAM_CMD_STAT, 2)
+			& 0x4000)); i++)
+			saaread(SAA7146_MC2);
+		if (i == 10000)
+			printk(KERN_ERR "stradis%d: dram_ready never set\n",
+				saa->nr);
+		buf[j] = debiread(saa, debNormal, IBM_MP2_DRAM_DATA, 4);
+	}
+}
+
+static void do_irq_send_data(struct saa7146 *saa)
+{
+	int split, audbytes, vidbytes;
+
+	saawrite(SAA7146_PSR_PIN1, SAA7146_IER);
+	/* if special feature mode in effect, disable audio sending */
+	if (saa->playmode != VID_PLAY_NORMAL)
+		saa->audtail = saa->audhead = 0;
+	if (saa->audhead <= saa->audtail)
+		audbytes = saa->audtail - saa->audhead;
+	else
+		audbytes = 65536 - (saa->audhead - saa->audtail);
+	if (saa->vidhead <= saa->vidtail)
+		vidbytes = saa->vidtail - saa->vidhead;
+	else
+		vidbytes = 524288 - (saa->vidhead - saa->vidtail);
+	if (audbytes == 0 && vidbytes == 0 && saa->osdtail == saa->osdhead) {
+		saawrite(0, SAA7146_IER);
+		return;
+	}
+	/* if at least 1 block audio waiting and audio fifo isn't full */
+	if (audbytes >= 2048 && (debiread(saa, debNormal,
+		IBM_MP2_AUD_FIFO, 2) & 0xff) < 60) {
+		if (saa->audhead > saa->audtail)
+			split = 65536 - saa->audhead;
+		else
+			split = 0;
+		audbytes = 2048;
+		if (split > 0 && split < 2048) {
+			memcpy(saa->dmadebi, saa->audbuf + saa->audhead,
+				split);
+			saa->audhead = 0;
+			audbytes -= split;
+		} else
+			split = 0;
+		memcpy(saa->dmadebi + split, saa->audbuf + saa->audhead,
+			audbytes);
+		saa->audhead += audbytes;
+		saa->audhead &= 0xffff;
+		debiwrite(saa, debAudio, (NewCard? IBM_MP2_AUD_FIFO :
+			  IBM_MP2_AUD_FIFOW), 0, 2048);
+		wake_up_interruptible(&saa->audq);
+	/* if at least 1 block video waiting and video fifo isn't full */
+	} else if (vidbytes >= 30720 && (debiread(saa, debNormal,
+		IBM_MP2_FIFO, 2)) < 16384) {
+		if (saa->vidhead > saa->vidtail)
+			split = 524288 - saa->vidhead;
+		else
+			split = 0;
+		vidbytes = 30720;
+		if (split > 0 && split < 30720) {
+			memcpy(saa->dmadebi, saa->vidbuf + saa->vidhead,
+				split);
+			saa->vidhead = 0;
+			vidbytes -= split;
+		} else
+			split = 0;
+		memcpy(saa->dmadebi + split, saa->vidbuf + saa->vidhead,
+			vidbytes);
+		saa->vidhead += vidbytes;
+		saa->vidhead &= 0x7ffff;
+		debiwrite(saa, debVideo, (NewCard ? IBM_MP2_FIFO :
+			  IBM_MP2_FIFOW), 0, 30720);
+		wake_up_interruptible(&saa->vidq);
+	}
+	saawrite(SAA7146_PSR_DEBI_S | SAA7146_PSR_PIN1, SAA7146_IER);
+}
+
+static void send_osd_data(struct saa7146 *saa)
+{
+	int size = saa->osdtail - saa->osdhead;
+	if (size > 30720)
+		size = 30720;
+	/* ensure some multiple of 8 bytes is transferred */
+	size = 8 * ((size + 8)>>3);
+	if (size) {
+		debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR,
+			  (saa->osdhead>>3), 2);
+		memcpy(saa->dmadebi, &saa->osdbuf[saa->osdhead], size);
+		saa->osdhead += size;
+		/* block transfer of next 8 bytes to ~32k bytes */
+		debiwrite(saa, debNormal, IBM_MP2_OSD_DATA, 0, size);
+	}
+	if (saa->osdhead >= saa->osdtail) {
+		saa->osdhead = saa->osdtail = 0;
+		debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2);
+	}
+}
+
+static void saa7146_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct saa7146 *saa = (struct saa7146 *) dev_id;
+	u32 stat, astat;
+	int count;
+
+	count = 0;
+	while (1) {
+		/* get/clear interrupt status bits */
+		stat = saaread(SAA7146_ISR);
+		astat = stat & saaread(SAA7146_IER);
+		if (!astat)
+			return;
+		saawrite(astat, SAA7146_ISR);
+		if (astat & SAA7146_PSR_DEBI_S) {
+			do_irq_send_data(saa);
+		}
+		if (astat & SAA7146_PSR_PIN1) {
+			int istat;
+			/* the following read will trigger DEBI_S */
+			istat = debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
+			if (istat & 1) {
+				saawrite(0, SAA7146_IER);
+				send_osd_data(saa);
+				saawrite(SAA7146_PSR_DEBI_S |
+					 SAA7146_PSR_PIN1, SAA7146_IER);
+			}
+			if (istat & 0x20) {	/* Video Start */
+				saa->vidinfo.frame_count++;
+			}
+			if (istat & 0x400) {	/* Picture Start */
+				/* update temporal reference */
+			}
+			if (istat & 0x200) {	/* Picture Resolution Change */
+				/* read new resolution */
+			}
+			if (istat & 0x100) {	/* New User Data found */
+				/* read new user data */
+			}
+			if (istat & 0x1000) {	/* new GOP/SMPTE */
+				/* read new SMPTE */
+			}
+			if (istat & 0x8000) {	/* Sequence Start Code */
+				/* reset frame counter, load sizes */
+				saa->vidinfo.frame_count = 0;
+				saa->vidinfo.h_size = 704;
+				saa->vidinfo.v_size = 480;
+#if 0
+				if (saa->endmarkhead != saa->endmarktail) {
+					saa->audhead = 
+						saa->endmark[saa->endmarkhead];
+					saa->endmarkhead++;
+					if (saa->endmarkhead >= MAX_MARKS)
+						saa->endmarkhead = 0;
+				}
+#endif
+			}
+			if (istat & 0x4000) {	/* Sequence Error Code */
+				if (saa->endmarkhead != saa->endmarktail) {
+					saa->audhead = 
+						saa->endmark[saa->endmarkhead];
+					saa->endmarkhead++;
+					if (saa->endmarkhead >= MAX_MARKS)
+						saa->endmarkhead = 0;
+				}
+			}
+		}
+#ifdef IDEBUG
+		if (astat & SAA7146_PSR_PPEF) {
+			IDEBUG(printk("stradis%d irq: PPEF\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_PABO) {
+			IDEBUG(printk("stradis%d irq: PABO\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_PPED) {
+			IDEBUG(printk("stradis%d irq: PPED\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_RPS_I1) {
+			IDEBUG(printk("stradis%d irq: RPS_I1\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_RPS_I0) {
+			IDEBUG(printk("stradis%d irq: RPS_I0\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_RPS_LATE1) {
+			IDEBUG(printk("stradis%d irq: RPS_LATE1\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_RPS_LATE0) {
+			IDEBUG(printk("stradis%d irq: RPS_LATE0\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_RPS_E1) {
+			IDEBUG(printk("stradis%d irq: RPS_E1\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_RPS_E0) {
+			IDEBUG(printk("stradis%d irq: RPS_E0\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_RPS_TO1) {
+			IDEBUG(printk("stradis%d irq: RPS_TO1\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_RPS_TO0) {
+			IDEBUG(printk("stradis%d irq: RPS_TO0\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_UPLD) {
+			IDEBUG(printk("stradis%d irq: UPLD\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_DEBI_E) {
+			IDEBUG(printk("stradis%d irq: DEBI_E\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_I2C_S) {
+			IDEBUG(printk("stradis%d irq: I2C_S\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_I2C_E) {
+			IDEBUG(printk("stradis%d irq: I2C_E\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_A2_IN) {
+			IDEBUG(printk("stradis%d irq: A2_IN\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_A2_OUT) {
+			IDEBUG(printk("stradis%d irq: A2_OUT\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_A1_IN) {
+			IDEBUG(printk("stradis%d irq: A1_IN\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_A1_OUT) {
+			IDEBUG(printk("stradis%d irq: A1_OUT\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_AFOU) {
+			IDEBUG(printk("stradis%d irq: AFOU\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_V_PE) {
+			IDEBUG(printk("stradis%d irq: V_PE\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_VFOU) {
+			IDEBUG(printk("stradis%d irq: VFOU\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_FIDA) {
+			IDEBUG(printk("stradis%d irq: FIDA\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_FIDB) {
+			IDEBUG(printk("stradis%d irq: FIDB\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_PIN3) {
+			IDEBUG(printk("stradis%d irq: PIN3\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_PIN2) {
+			IDEBUG(printk("stradis%d irq: PIN2\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_PIN0) {
+			IDEBUG(printk("stradis%d irq: PIN0\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_ECS) {
+			IDEBUG(printk("stradis%d irq: ECS\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_EC3S) {
+			IDEBUG(printk("stradis%d irq: EC3S\n", saa->nr));
+		}
+		if (astat & SAA7146_PSR_EC0S) {
+			IDEBUG(printk("stradis%d irq: EC0S\n", saa->nr));
+		}
+#endif
+		count++;
+		if (count > 15)
+			printk(KERN_WARNING "stradis%d: irq loop %d\n",
+			       saa->nr, count);
+		if (count > 20) {
+			saawrite(0, SAA7146_IER);
+			printk(KERN_ERR
+			       "stradis%d: IRQ loop cleared\n", saa->nr);
+		}
+	}
+}
+
+static int ibm_send_command(struct saa7146 *saa,
+			    int command, int data, int chain)
+{
+	int i;
+
+	if (chain)
+		debiwrite(saa, debNormal, IBM_MP2_COMMAND, (command << 1) | 1, 2);
+	else
+		debiwrite(saa, debNormal, IBM_MP2_COMMAND, command << 1, 2);
+	debiwrite(saa, debNormal, IBM_MP2_CMD_DATA, data, 2);
+	debiwrite(saa, debNormal, IBM_MP2_CMD_STAT, 1, 2);
+	for (i = 0; i < 100 &&
+	     (debiread(saa, debNormal, IBM_MP2_CMD_STAT, 2) & 1); i++)
+		schedule();
+	if (i == 100)
+		return -1;
+	return 0;
+}
+
+static void cs4341_setlevel(struct saa7146 *saa, int left, int right)
+{
+	I2CWrite(&(saa->i2c), 0x22, 0x03,
+		 left > 94 ? 94 : left, 2);
+	I2CWrite(&(saa->i2c), 0x22, 0x04,
+		 right > 94 ? 94 : right, 2);
+}
+
+static void initialize_cs4341(struct saa7146 *saa)
+{
+	int i;
+	for (i = 0; i < 200; i++) {
+		/* auto mute off, power on, no de-emphasis */
+		/* I2S data up to 24-bit 64xFs internal SCLK */
+		I2CWrite(&(saa->i2c), 0x22, 0x01, 0x11, 2);
+		/* ATAPI mixer setings */
+		I2CWrite(&(saa->i2c), 0x22, 0x02, 0x49, 2);
+		/* attenuation left 3db */
+		I2CWrite(&(saa->i2c), 0x22, 0x03, 0x00, 2);
+		/* attenuation right 3db */
+		I2CWrite(&(saa->i2c), 0x22, 0x04, 0x00, 2);
+		I2CWrite(&(saa->i2c), 0x22, 0x01, 0x10, 2);
+		if (I2CRead(&(saa->i2c), 0x22, 0x02, 1) == 0x49)
+			break;
+		schedule();
+	}
+	printk("stradis%d: CS4341 initialized (%d)\n", saa->nr, i);
+	return;
+}
+
+static void initialize_cs8420(struct saa7146 *saa, int pro)
+{
+	int i;
+	u8 *sequence;
+	if (pro)
+		sequence = mode8420pro;
+	else
+		sequence = mode8420con;
+	for (i = 0; i < INIT8420LEN; i++)
+		I2CWrite(&(saa->i2c), 0x20, init8420[i * 2],
+			 init8420[i * 2 + 1], 2);
+	for (i = 0; i < MODE8420LEN; i++)
+		I2CWrite(&(saa->i2c), 0x20, sequence[i * 2],
+			 sequence[i * 2 + 1], 2);
+	printk("stradis%d: CS8420 initialized\n", saa->nr);
+}
+
+static void initialize_saa7121(struct saa7146 *saa, int dopal)
+{
+	int i, mod;
+	u8 *sequence;
+	if (dopal)
+		sequence = init7121pal;
+	else
+		sequence = init7121ntsc;
+	mod = saaread(SAA7146_PSR) & 0x08;
+	/* initialize PAL/NTSC video encoder */
+	for (i = 0; i < INIT7121LEN; i++) {
+		if (NewCard) {	/* handle new card encoder differences */
+			if (sequence[i*2] == 0x3a)
+				I2CWrite(&(saa->i2c), 0x88, 0x3a, 0x13, 2);
+			else if (sequence[i*2] == 0x6b)
+				I2CWrite(&(saa->i2c), 0x88, 0x6b, 0x20, 2);
+			else if (sequence[i*2] == 0x6c)
+				I2CWrite(&(saa->i2c), 0x88, 0x6c,
+					 dopal ? 0x09 : 0xf5, 2);
+			else if (sequence[i*2] == 0x6d)
+				I2CWrite(&(saa->i2c), 0x88, 0x6d,
+					 dopal ? 0x20 : 0x00, 2);
+			else if (sequence[i*2] == 0x7a)
+				I2CWrite(&(saa->i2c), 0x88, 0x7a,
+					 dopal ? (PALFirstActive - 1) :
+					 (NTSCFirstActive - 4), 2);
+			else if (sequence[i*2] == 0x7b)
+				I2CWrite(&(saa->i2c), 0x88, 0x7b,
+					 dopal ? PALLastActive :
+					 NTSCLastActive, 2);
+			else I2CWrite(&(saa->i2c), 0x88, sequence[i * 2],
+				 sequence[i * 2 + 1], 2);
+		} else {
+			if (sequence[i*2] == 0x6b && mod)
+				I2CWrite(&(saa->i2c), 0x88, 0x6b, 
+					(sequence[i * 2 + 1] ^ 0x09), 2);
+			else if (sequence[i*2] == 0x7a)
+				I2CWrite(&(saa->i2c), 0x88, 0x7a,
+					 dopal ? (PALFirstActive - 1) :
+					 (NTSCFirstActive - 4), 2);
+			else if (sequence[i*2] == 0x7b)
+				I2CWrite(&(saa->i2c), 0x88, 0x7b,
+					 dopal ? PALLastActive :
+					 NTSCLastActive, 2);
+			else
+				I2CWrite(&(saa->i2c), 0x88, sequence[i * 2],
+					 sequence[i * 2 + 1], 2);
+		}
+	}
+}
+
+static void set_genlock_offset(struct saa7146 *saa, int noffset)
+{
+	int nCode;
+	int PixelsPerLine = 858;
+	if (CurrentMode == VIDEO_MODE_PAL)
+		PixelsPerLine = 864;
+	if (noffset > 500)
+		noffset = 500;
+	else if (noffset < -500)
+		noffset = -500;
+	nCode = noffset + 0x100;
+	if (nCode == 1)
+		nCode = 0x401;
+	else if (nCode < 1) nCode = 0x400 + PixelsPerLine + nCode;
+	debiwrite(saa, debNormal, XILINX_GLDELAY, nCode, 2);
+}
+
+static void set_out_format(struct saa7146 *saa, int mode)
+{
+	initialize_saa7121(saa, (mode == VIDEO_MODE_NTSC ? 0 : 1));
+	saa->boardcfg[2] = mode;
+	/* do not adjust analog video parameters here, use saa7121 init */
+	/* you will affect the SDI output on the new card */
+	if (mode == VIDEO_MODE_PAL) {		/* PAL */
+		debiwrite(saa, debNormal, XILINX_CTL0, 0x0808, 2);
+		mdelay(50);
+		saawrite(0x012002c0, SAA7146_NUM_LINE_BYTE1);
+		if (NewCard) {
+			debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
+				  0xe100, 2);
+			mdelay(50);
+		}
+		debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
+			  NewCard ? 0xe500: 0x6500, 2);
+		debiwrite(saa, debNormal, IBM_MP2_DISP_DLY,
+			  (1 << 8) |
+			  (NewCard ? PALFirstActive : PALFirstActive-6), 2);
+	} else {		/* NTSC */
+		debiwrite(saa, debNormal, XILINX_CTL0, 0x0800, 2);
+		mdelay(50);
+		saawrite(0x00f002c0, SAA7146_NUM_LINE_BYTE1);
+		debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
+			  NewCard ? 0xe100: 0x6100, 2);
+		debiwrite(saa, debNormal, IBM_MP2_DISP_DLY,
+			  (1 << 8) |
+			  (NewCard ? NTSCFirstActive : NTSCFirstActive-6), 2);
+	}
+}
+
+
+/* Intialize bitmangler to map from a byte value to the mangled word that
+ * must be output to program the Xilinx part through the DEBI port.
+ * Xilinx Data Bit->DEBI Bit: 0->15 1->7 2->6 3->12 4->11 5->2 6->1 7->0
+ * transfer FPGA code, init IBM chip, transfer IBM microcode
+ * rev2 card mangles: 0->7 1->6 2->5 3->4 4->3 5->2 6->1 7->0
+ */
+static u16 bitmangler[256];
+
+static int initialize_fpga(struct video_code *bitdata)
+{
+	int i, num, startindex, failure = 0, loadtwo, loadfile = 0;
+	u16 *dmabuf;
+	u8 *newdma;
+	struct saa7146 *saa;
+
+	/* verify fpga code */
+	for (startindex = 0; startindex < bitdata->datasize; startindex++)
+		if (bitdata->data[startindex] == 255)
+			break;
+	if (startindex == bitdata->datasize) {
+		printk(KERN_INFO "stradis: bad fpga code\n");
+		return -1;
+	}
+	/* initialize all detected cards */
+	for (num = 0; num < saa_num; num++) {
+		saa = &saa7146s[num];
+		if (saa->boardcfg[0] > 20)
+				continue;	/* card was programmed */
+		loadtwo = (saa->boardcfg[18] & 0x10);
+		if (!NewCard)	/* we have an old board */
+			for (i = 0; i < 256; i++)
+			    bitmangler[i] = ((i & 0x01) << 15) |
+				((i & 0x02) << 6) | ((i & 0x04) << 4) |
+				((i & 0x08) << 9) | ((i & 0x10) << 7) |
+				((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
+				((i & 0x80) >> 7);
+		else	/* else we have a new board */
+			for (i = 0; i < 256; i++)
+			    bitmangler[i] = ((i & 0x01) << 7) |
+				((i & 0x02) << 5) | ((i & 0x04) << 3) |
+				((i & 0x08) << 1) | ((i & 0x10) >> 1) |
+				((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
+				((i & 0x80) >> 7);
+
+		dmabuf = (u16 *) saa->dmadebi;
+		newdma = (u8 *) saa->dmadebi;
+		if (NewCard) {	/* SDM2xxx */
+			if (!strncmp(bitdata->loadwhat, "decoder2", 8))
+				continue;	/* fpga not for this card */
+			if (!strncmp(&saa->boardcfg[42],
+				     bitdata->loadwhat, 8)) {
+				loadfile = 1;
+			} else if (loadtwo && !strncmp(&saa->boardcfg[19],
+				   bitdata->loadwhat, 8)) {
+				loadfile = 2;
+			} else if (!saa->boardcfg[42] &&	/* special */
+				   !strncmp("decxl", bitdata->loadwhat, 8)) {
+				loadfile = 1;
+			} else
+				continue;	/* fpga not for this card */
+			if (loadfile != 1 && loadfile != 2) {
+				continue;	/* skip to next card */
+			}
+			if (saa->boardcfg[0] && loadfile == 1 )
+				continue;	/* skip to next card */
+			if (saa->boardcfg[0] != 1 && loadfile == 2)
+				continue;	/* skip to next card */
+			saa->boardcfg[0]++;	/* mark fpga handled */
+			printk("stradis%d: loading %s\n", saa->nr,
+				bitdata->loadwhat);
+			if (loadtwo && loadfile == 2)
+				goto send_fpga_stuff;
+			/* turn on the Audio interface to set PROG low */
+			saawrite(0x00400040, SAA7146_GPIO_CTRL);
+			saaread(SAA7146_PSR);	/* ensure posted write */
+			/* wait for everyone to reset */
+			mdelay(10);
+			saawrite(0x00400000, SAA7146_GPIO_CTRL);
+		} else {	/* original card */
+			if (strncmp(bitdata->loadwhat, "decoder2", 8))
+				continue;	/* fpga not for this card */
+			/* Pull the Xilinx PROG signal WS3 low */
+			saawrite(0x02000200, SAA7146_MC1);
+			/* Turn on the Audio interface so can set PROG low */
+			saawrite(0x000000c0, SAA7146_ACON1);
+			/* Pull the Xilinx INIT signal (GPIO2) low */
+			saawrite(0x00400000, SAA7146_GPIO_CTRL);
+			/* Make sure everybody resets */
+			saaread(SAA7146_PSR);	/* ensure posted write */
+			mdelay(10);
+			/* Release the Xilinx PROG signal */
+			saawrite(0x00000000, SAA7146_ACON1);
+			/* Turn off the Audio interface */
+			saawrite(0x02000000, SAA7146_MC1);
+		}
+		/* Release Xilinx INIT signal (WS2) */
+		saawrite(0x00000000, SAA7146_GPIO_CTRL);
+		/* Wait for the INIT to go High */
+		for (i = 0; i < 10000 &&
+		     !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2); i++)
+			schedule();
+		if (i == 1000) {
+			printk(KERN_INFO "stradis%d: no fpga INIT\n", saa->nr);
+			return -1;
+		}
+send_fpga_stuff:
+		if (NewCard) {
+			for (i = startindex; i < bitdata->datasize; i++)
+				newdma[i - startindex] =
+					bitmangler[bitdata->data[i]];
+			debiwrite(saa, 0x01420000, 0, 0,
+				((bitdata->datasize - startindex) + 5));
+			if (loadtwo) {
+				if (loadfile == 1) {
+					printk("stradis%d: "
+						"awaiting 2nd FPGA bitfile\n",
+						saa->nr);
+					continue;	/* skip to next card */
+				}
+
+			}
+		} else {
+			for (i = startindex; i < bitdata->datasize; i++)
+				dmabuf[i - startindex] =
+					bitmangler[bitdata->data[i]];
+			debiwrite(saa, 0x014a0000, 0, 0,
+				((bitdata->datasize - startindex) + 5) * 2);
+		}
+		for (i = 0; i < 1000 &&
+		     !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2); i++)
+			schedule();
+		if (i == 1000) {
+			printk(KERN_INFO "stradis%d: FPGA load failed\n",
+			       saa->nr);
+			failure++;
+			continue;
+		}
+		if (!NewCard) {
+			/* Pull the Xilinx INIT signal (GPIO2) low */
+			saawrite(0x00400000, SAA7146_GPIO_CTRL);
+			saaread(SAA7146_PSR);	/* ensure posted write */
+			mdelay(2);
+			saawrite(0x00000000, SAA7146_GPIO_CTRL);
+			mdelay(2);
+		}
+		printk(KERN_INFO "stradis%d: FPGA Loaded\n", saa->nr);
+		saa->boardcfg[0] = 26;	/* mark fpga programmed */
+		/* set VXCO to its lowest frequency */
+		debiwrite(saa, debNormal, XILINX_PWM, 0, 2);
+		if (NewCard) {
+			/* mute CS3310 */
+			if (HaveCS3310)
+				debiwrite(saa, debNormal, XILINX_CS3310_CMPLT,
+					  0, 2);
+			/* set VXCO to PWM mode, release reset, blank on */
+			debiwrite(saa, debNormal, XILINX_CTL0, 0xffc4, 2);
+			mdelay(10);
+			/* unmute CS3310 */
+			if (HaveCS3310)
+				debiwrite(saa, debNormal, XILINX_CTL0,
+					  0x2020, 2);
+		}
+		/* set source Black */
+		debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2);
+		saa->boardcfg[4] = 22;	/* set NTSC First Active Line */
+		saa->boardcfg[5] = 23;	/* set PAL First Active Line */
+		saa->boardcfg[54] = 2;	/* set NTSC Last Active Line - 256 */
+		saa->boardcfg[55] = 54;	/* set PAL Last Active Line - 256 */
+		set_out_format(saa, VIDEO_MODE_NTSC);
+		mdelay(50);
+		/* begin IBM chip init */
+		debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2);
+		saaread(SAA7146_PSR);	/* wait for reset */
+		mdelay(5);
+		debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2);
+		debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2);
+		debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0x10, 2);
+		debiwrite(saa, debNormal, IBM_MP2_CMD_ADDR, 0, 2);
+		debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2);
+		if (NewCard) {
+			mdelay(5);
+			/* set i2s rate converter to 48KHz */
+			debiwrite(saa, debNormal, 0x80c0, 6, 2);
+			/* we must init CS8420 first since rev b pulls i2s */
+			/* master clock low and CS4341 needs i2s master to */
+			/* run the i2c port. */
+			if (HaveCS8420) {
+				/* 0=consumer, 1=pro */
+				initialize_cs8420(saa, 0);
+			}
+			mdelay(5);
+			if (HaveCS4341)
+				initialize_cs4341(saa);
+		}
+		debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2);
+		debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2);
+		debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2);
+		debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2);
+		if (NewCard)
+			set_genlock_offset(saa, 0);
+		debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2);
+#if 0
+		/* enable genlock */
+		debiwrite(saa, debNormal, XILINX_CTL0, 0x8000, 2);
+#else
+		/* disable genlock */
+		debiwrite(saa, debNormal, XILINX_CTL0, 0x8080, 2);
+#endif
+	}
+	return failure;
+}
+
+static int do_ibm_reset(struct saa7146 *saa)
+{
+	/* failure if decoder not previously programmed */
+	if (saa->boardcfg[0] < 37)
+		return -EIO;
+	/* mute CS3310 */
+	if (HaveCS3310)
+		debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, 0, 2);
+	/* disable interrupts */
+	saawrite(0, SAA7146_IER);
+	saa->audhead = saa->audtail = 0;
+	saa->vidhead = saa->vidtail = 0;
+	/* tristate debi bus, disable debi transfers */
+	saawrite(0x00880000, SAA7146_MC1);
+	/* ensure posted write */
+	saaread(SAA7146_MC1);
+	mdelay(50);
+	/* re-enable debi transfers */
+	saawrite(0x00880088, SAA7146_MC1);
+	/* set source Black */
+	debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2);
+	/* begin IBM chip init */
+	set_out_format(saa, CurrentMode);
+	debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2);
+	saaread(SAA7146_PSR);	/* wait for reset */
+	mdelay(5);
+	debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2);
+	debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2);
+	debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2);
+	debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2);
+	if (NewCard) {
+		mdelay(5);
+		/* set i2s rate converter to 48KHz */
+		debiwrite(saa, debNormal, 0x80c0, 6, 2);
+		/* we must init CS8420 first since rev b pulls i2s */
+		/* master clock low and CS4341 needs i2s master to */
+		/* run the i2c port. */
+		if (HaveCS8420) {
+			/* 0=consumer, 1=pro */
+			initialize_cs8420(saa, 1);
+		}
+		mdelay(5);
+		if (HaveCS4341)
+			initialize_cs4341(saa);
+	}
+	debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2);
+	debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2);
+	debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2);
+	debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2);
+	if (NewCard)
+		set_genlock_offset(saa, 0);
+	debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2);
+	debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2);
+	debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2);
+	if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER,
+		(ChipControl == 0x43 ? 0xe800 : 0xe000), 1)) {
+		printk(KERN_ERR "stradis%d: IBM config failed\n", saa->nr);
+	}
+	if (HaveCS3310) {
+		int i = CS3310MaxLvl;
+		debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, ((i<<8)|i), 2);
+	}
+	/* start video decoder */
+	debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2);
+	/* 256k vid, 3520 bytes aud */
+	debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, 0x4037, 2);
+	debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2);
+	ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
+	/* enable buffer threshold irq */
+	debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2);
+	/* clear pending interrupts */
+	debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
+	debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2);
+	return 0;
+}
+
+/* load the decoder microcode */
+static int initialize_ibmmpeg2(struct video_code *microcode)
+{
+	int i, num;
+	struct saa7146 *saa;
+
+	for (num = 0; num < saa_num; num++) {
+		saa = &saa7146s[num];
+		/* check that FPGA is loaded */
+		debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0xa55a, 2);
+		if ((i = debiread(saa, debNormal, IBM_MP2_OSD_SIZE, 2)) !=
+		     0xa55a) {
+			printk(KERN_INFO "stradis%d: %04x != 0xa55a\n",
+				saa->nr, i);
+#if 0
+			return -1;
+#endif
+		}
+		if (!strncmp(microcode->loadwhat, "decoder.vid", 11)) {
+			if (saa->boardcfg[0] > 27)
+				continue;	/* skip to next card */
+			/* load video control store */
+			saa->boardcfg[1] = 0x13;  /* no-sync default */
+			debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2);
+			debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2);
+			for (i = 0; i < microcode->datasize / 2; i++)
+				debiwrite(saa, debNormal, IBM_MP2_PROC_IDATA,
+					(microcode->data[i * 2] << 8) |
+					 microcode->data[i * 2 + 1], 2);
+			debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2);
+			debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2);
+			debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
+				  ChipControl, 2);
+			saa->boardcfg[0] = 28;
+		}
+		if (!strncmp(microcode->loadwhat, "decoder.aud", 11)) {
+			if (saa->boardcfg[0] > 35)
+				continue;	/* skip to next card */
+			/* load audio control store */
+			debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2);
+			debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2);
+			for (i = 0; i < microcode->datasize; i++)
+				debiwrite(saa, debNormal, IBM_MP2_AUD_IDATA,
+					microcode->data[i], 1);
+			debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2);
+			debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2);
+			debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2);
+			debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2);
+			if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER,
+			    0xe000, 1)) {
+				printk(KERN_ERR
+				       "stradis%d: IBM config failed\n",
+				       saa->nr);
+				return -1;
+			}
+			/* set PWM to center value */
+			if (NewCard) {
+				debiwrite(saa, debNormal, XILINX_PWM,
+					  saa->boardcfg[14] +
+					  (saa->boardcfg[13]<<8), 2);
+			} else
+				debiwrite(saa, debNormal, XILINX_PWM,
+					  0x46, 2);
+			if (HaveCS3310) {
+				i = CS3310MaxLvl;
+				debiwrite(saa, debNormal,
+					XILINX_CS3310_CMPLT, ((i<<8)|i), 2);
+			}
+			printk(KERN_INFO
+			       "stradis%d: IBM MPEGCD%d Initialized\n",
+			       saa->nr, 18 + (debiread(saa, debNormal,
+			       IBM_MP2_CHIP_CONTROL, 2) >> 12));
+			/* start video decoder */
+			debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
+				ChipControl, 2);
+			debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD,
+				0x4037, 2);	/* 256k vid, 3520 bytes aud */
+			debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2);
+			ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
+			/* enable buffer threshold irq */
+			debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2);
+			debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
+			/* enable gpio irq */
+			saawrite(0x00002000, SAA7146_GPIO_CTRL);
+			/* enable decoder output to HPS */
+			debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2);
+			saa->boardcfg[0] = 37;
+		}
+	}
+	return 0;
+}
+
+static u32 palette2fmt[] =
+{				/* some of these YUV translations are wrong */
+  0xffffffff, 0x86000000, 0x87000000, 0x80000000, 0x8100000, 0x82000000,
+  0x83000000, 0x00000000, 0x03000000, 0x03000000, 0x0a00000, 0x03000000,
+  0x06000000, 0x00000000, 0x03000000, 0x0a000000, 0x0300000
+};
+static int bpp2fmt[4] =
+{
+	VIDEO_PALETTE_HI240, VIDEO_PALETTE_RGB565, VIDEO_PALETTE_RGB24,
+	VIDEO_PALETTE_RGB32
+};
+
+/* I wish I could find a formula to calculate these... */
+static u32 h_prescale[64] =
+{
+  0x10000000, 0x18040202, 0x18080000, 0x380c0606, 0x38100204, 0x38140808,
+  0x38180000, 0x381c0000, 0x3820161c, 0x38242a3b, 0x38281230, 0x382c4460,
+  0x38301040, 0x38340080, 0x38380000, 0x383c0000, 0x3840fefe, 0x3844ee9f,
+  0x3848ee9f, 0x384cee9f, 0x3850ee9f, 0x38542a3b, 0x38581230, 0x385c0000,
+  0x38600000, 0x38640000, 0x38680000, 0x386c0000, 0x38700000, 0x38740000,
+  0x38780000, 0x387c0000, 0x30800000, 0x38840000, 0x38880000, 0x388c0000,
+  0x38900000, 0x38940000, 0x38980000, 0x389c0000, 0x38a00000, 0x38a40000,
+  0x38a80000, 0x38ac0000, 0x38b00000, 0x38b40000, 0x38b80000, 0x38bc0000,
+  0x38c00000, 0x38c40000, 0x38c80000, 0x38cc0000, 0x38d00000, 0x38d40000,
+  0x38d80000, 0x38dc0000, 0x38e00000, 0x38e40000, 0x38e80000, 0x38ec0000,
+  0x38f00000, 0x38f40000, 0x38f80000, 0x38fc0000,
+};
+static u32 v_gain[64] =
+{
+  0x016000ff, 0x016100ff, 0x016100ff, 0x016200ff, 0x016200ff, 0x016200ff,
+  0x016200ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff,
+  0x016300ff, 0x016300ff, 0x016300ff, 0x016400ff, 0x016400ff, 0x016400ff,
+  0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+  0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+  0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+  0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+  0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+  0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+  0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+  0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+};
+
+
+static void saa7146_set_winsize(struct saa7146 *saa)
+{
+	u32 format;
+	int offset, yacl, ysci;
+	saa->win.color_fmt = format =
+	    (saa->win.depth == 15) ? palette2fmt[VIDEO_PALETTE_RGB555] :
+	    palette2fmt[bpp2fmt[(saa->win.bpp - 1) & 3]];
+	offset = saa->win.x * saa->win.bpp + saa->win.y * saa->win.bpl;
+	saawrite(saa->win.vidadr + offset, SAA7146_BASE_EVEN1);
+	saawrite(saa->win.vidadr + offset + saa->win.bpl, SAA7146_BASE_ODD1);
+	saawrite(saa->win.bpl * 2, SAA7146_PITCH1);
+	saawrite(saa->win.vidadr + saa->win.bpl * saa->win.sheight,
+		 SAA7146_PROT_ADDR1);
+	saawrite(0, SAA7146_PAGE1);
+	saawrite(format|0x60, SAA7146_CLIP_FORMAT_CTRL);
+	offset = (704 / (saa->win.width - 1)) & 0x3f;
+	saawrite(h_prescale[offset], SAA7146_HPS_H_PRESCALE);
+	offset = (720896 / saa->win.width) / (offset + 1);
+	saawrite((offset<<12)|0x0c, SAA7146_HPS_H_SCALE);
+	if (CurrentMode == VIDEO_MODE_NTSC) {
+		yacl = /*(480 / saa->win.height - 1) & 0x3f*/ 0;
+		ysci = 1024 - (saa->win.height * 1024 / 480);
+	} else {
+		yacl = /*(576 / saa->win.height - 1) & 0x3f*/ 0;
+		ysci = 1024 - (saa->win.height * 1024 / 576);
+	}
+	saawrite((1<<31)|(ysci<<21)|(yacl<<15), SAA7146_HPS_V_SCALE);
+	saawrite(v_gain[yacl], SAA7146_HPS_V_GAIN);
+	saawrite(((SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_HPS_V |
+		   SAA7146_MC2_UPLD_HPS_H) << 16) | (SAA7146_MC2_UPLD_DMA1 |
+		   SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_HPS_H),
+		   SAA7146_MC2);
+}
+
+/* clip_draw_rectangle(cm,x,y,w,h) -- handle clipping an area
+ * bitmap is fixed width, 128 bytes (1024 pixels represented) 
+ * arranged most-sigificant-bit-left in 32-bit words 
+ * based on saa7146 clipping hardware, it swaps bytes if LE 
+ * much of this makes up for egcs brain damage -- so if you
+ * are wondering "why did he do this?" it is because the C
+ * was adjusted to generate the optimal asm output without
+ * writing non-portable __asm__ directives.
+ */
+
+static void clip_draw_rectangle(u32 *clipmap, int x, int y, int w, int h)
+{
+	register int startword, endword;
+	register u32 bitsleft, bitsright;
+	u32 *temp;
+	if (x < 0) {
+		w += x;
+		x = 0;
+	}
+	if (y < 0) {
+		h += y;
+		y = 0;
+	}
+	if (w <= 0 || h <= 0 || x > 1023 || y > 639)
+		return;		/* throw away bad clips */
+	if (x + w > 1024)
+		w = 1024 - x;
+	if (y + h > 640)
+		h = 640 - y;
+	startword = (x >> 5);
+	endword = ((x + w) >> 5);
+	bitsleft = (0xffffffff >> (x & 31));
+	bitsright = (0xffffffff << (~((x + w) - (endword<<5))));
+	temp = &clipmap[(y<<5) + startword];
+	w = endword - startword;
+	if (!w) {
+		bitsleft |= bitsright;
+		for (y = 0; y < h; y++) {
+			*temp |= bitsleft;
+			temp += 32;
+		}
+	} else {
+		for (y = 0; y < h; y++) {
+			*temp++ |= bitsleft;
+			for (x = 1; x < w; x++)
+				*temp++ = 0xffffffff;
+			*temp |= bitsright;
+			temp += (32 - w);
+		}
+	}
+}
+
+static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr)
+{
+	int i, width, height;
+	u32 *clipmap;
+
+	clipmap = saa->dmavid2;
+	if((width=saa->win.width)>1023)
+		width = 1023;		/* sanity check */
+	if((height=saa->win.height)>640)
+		height = 639;		/* sanity check */
+	if (ncr > 0) {	/* rectangles pased */
+		/* convert rectangular clips to a bitmap */
+		memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */
+		for (i = 0; i < ncr; i++)
+			clip_draw_rectangle(clipmap, cr[i].x, cr[i].y,
+				cr[i].width, cr[i].height);
+	}
+	/* clip against viewing window AND screen 
+	   so we do not have to rely on the user program
+	 */
+	clip_draw_rectangle(clipmap,(saa->win.x+width>saa->win.swidth) ?
+		(saa->win.swidth-saa->win.x) : width, 0, 1024, 768);
+	clip_draw_rectangle(clipmap,0,(saa->win.y+height>saa->win.sheight) ?
+		(saa->win.sheight-saa->win.y) : height,1024,768);
+	if (saa->win.x<0)
+		clip_draw_rectangle(clipmap, 0, 0, -(saa->win.x), 768);
+	if (saa->win.y<0)
+		clip_draw_rectangle(clipmap, 0, 0, 1024, -(saa->win.y));
+}
+
+static int saa_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+	struct saa7146 *saa = (struct saa7146 *) dev;
+	switch (cmd) {
+	case VIDIOCGCAP:
+		{
+			struct video_capability b;
+			strcpy(b.name, saa->video_dev.name);
+			b.type = VID_TYPE_CAPTURE |
+			    VID_TYPE_OVERLAY |
+			    VID_TYPE_CLIPPING |
+			    VID_TYPE_FRAMERAM |
+			    VID_TYPE_SCALES;
+			b.channels = 1;
+			b.audios = 1;
+			b.maxwidth = 768;
+			b.maxheight = 576;
+			b.minwidth = 32;
+			b.minheight = 32;
+			if (copy_to_user(arg, &b, sizeof(b)))
+				return -EFAULT;
+			return 0;
+		}
+	case VIDIOCGPICT:
+		{
+			struct video_picture p = saa->picture;
+			if (saa->win.depth == 8)
+				p.palette = VIDEO_PALETTE_HI240;
+			if (saa->win.depth == 15)
+				p.palette = VIDEO_PALETTE_RGB555;
+			if (saa->win.depth == 16)
+				p.palette = VIDEO_PALETTE_RGB565;
+			if (saa->win.depth == 24)
+				p.palette = VIDEO_PALETTE_RGB24;
+			if (saa->win.depth == 32)
+				p.palette = VIDEO_PALETTE_RGB32;
+			if (copy_to_user(arg, &p, sizeof(p)))
+				return -EFAULT;
+			return 0;
+		}
+	case VIDIOCSPICT:
+		{
+			struct video_picture p;
+			u32 format;
+			if (copy_from_user(&p, arg, sizeof(p)))
+				return -EFAULT;
+			if (p.palette < sizeof(palette2fmt) / sizeof(u32)) {
+				format = palette2fmt[p.palette];
+				saa->win.color_fmt = format;
+				saawrite(format|0x60, SAA7146_CLIP_FORMAT_CTRL);
+			}
+			saawrite(((p.brightness & 0xff00) << 16) |
+				 ((p.contrast & 0xfe00) << 7) |
+			     ((p.colour & 0xfe00) >> 9), SAA7146_BCS_CTRL);
+			saa->picture = p;
+			/* upload changed registers */
+			saawrite(((SAA7146_MC2_UPLD_HPS_H |
+				 SAA7146_MC2_UPLD_HPS_V) << 16) |
+				SAA7146_MC2_UPLD_HPS_H | SAA7146_MC2_UPLD_HPS_V,
+				 SAA7146_MC2);
+			return 0;
+		}
+	case VIDIOCSWIN:
+		{
+			struct video_window vw;
+			struct video_clip *vcp = NULL;
+
+			if (copy_from_user(&vw, arg, sizeof(vw)))
+				return -EFAULT;
+
+			if (vw.flags || vw.width < 16 || vw.height < 16) {	/* stop capture */
+				saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1);
+				return -EINVAL;
+			}
+			if (saa->win.bpp < 4) {		/* 32-bit align start and adjust width */
+				int i = vw.x;
+				vw.x = (vw.x + 3) & ~3;
+				i = vw.x - i;
+				vw.width -= i;
+			}
+			saa->win.x = vw.x;
+			saa->win.y = vw.y;
+			saa->win.width = vw.width;
+			if (saa->win.width > 768)
+				saa->win.width = 768;
+			saa->win.height = vw.height;
+			if (CurrentMode == VIDEO_MODE_NTSC) {
+				if (saa->win.height > 480)
+					saa->win.height = 480;
+			} else {
+				if (saa->win.height > 576)
+					saa->win.height = 576;
+			}
+
+			/* stop capture */
+			saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1);
+			saa7146_set_winsize(saa);
+
+			/*
+			 *    Do any clips.
+			 */
+			if (vw.clipcount < 0) {
+				if (copy_from_user(saa->dmavid2, vw.clips,
+						   VIDEO_CLIPMAP_SIZE))
+					return -EFAULT;
+			} else if (vw.clipcount > 0) {
+				if ((vcp = vmalloc(sizeof(struct video_clip) *
+					        (vw.clipcount))) == NULL)
+					 return -ENOMEM;
+				if (copy_from_user(vcp, vw.clips,
+					      sizeof(struct video_clip) *
+						   vw.clipcount)) {
+					vfree(vcp);
+					return -EFAULT;
+				}
+			} else	/* nothing clipped */
+				memset(saa->dmavid2, 0, VIDEO_CLIPMAP_SIZE);
+			make_clip_tab(saa, vcp, vw.clipcount);
+			if (vw.clipcount > 0)
+				vfree(vcp);
+
+			/* start capture & clip dma if we have an address */
+			if ((saa->cap & 3) && saa->win.vidadr != 0)
+				saawrite(((SAA7146_MC1_TR_E_1 |
+					SAA7146_MC1_TR_E_2) << 16) | 0xffff,
+					SAA7146_MC1);
+			return 0;
+		}
+	case VIDIOCGWIN:
+		{
+			struct video_window vw;
+			vw.x = saa->win.x;
+			vw.y = saa->win.y;
+			vw.width = saa->win.width;
+			vw.height = saa->win.height;
+			vw.chromakey = 0;
+			vw.flags = 0;
+			if (copy_to_user(arg, &vw, sizeof(vw)))
+				return -EFAULT;
+			return 0;
+		}
+	case VIDIOCCAPTURE:
+		{
+			int v;
+			if (copy_from_user(&v, arg, sizeof(v)))
+				return -EFAULT;
+			if (v == 0) {
+				saa->cap &= ~1;
+				saawrite((SAA7146_MC1_TR_E_1 << 16),
+					 SAA7146_MC1);
+			} else {
+				if (saa->win.vidadr == 0 || saa->win.width == 0
+				    || saa->win.height == 0)
+					return -EINVAL;
+				saa->cap |= 1;
+				saawrite((SAA7146_MC1_TR_E_1 << 16) | 0xffff,
+					 SAA7146_MC1);
+			}
+			return 0;
+		}
+	case VIDIOCGFBUF:
+		{
+			struct video_buffer v;
+			v.base = (void *) saa->win.vidadr;
+			v.height = saa->win.sheight;
+			v.width = saa->win.swidth;
+			v.depth = saa->win.depth;
+			v.bytesperline = saa->win.bpl;
+			if (copy_to_user(arg, &v, sizeof(v)))
+				return -EFAULT;
+			return 0;
+
+		}
+	case VIDIOCSFBUF:
+		{
+			struct video_buffer v;
+			if (!capable(CAP_SYS_ADMIN))
+				return -EPERM;
+			if (copy_from_user(&v, arg, sizeof(v)))
+				return -EFAULT;
+			if (v.depth != 8 && v.depth != 15 && v.depth != 16 &&
+			v.depth != 24 && v.depth != 32 && v.width > 16 &&
+			    v.height > 16 && v.bytesperline > 16)
+				return -EINVAL;
+			if (v.base)
+				saa->win.vidadr = (unsigned long) v.base;
+			saa->win.sheight = v.height;
+			saa->win.swidth = v.width;
+			saa->win.bpp = ((v.depth + 7) & 0x38) / 8;
+			saa->win.depth = v.depth;
+			saa->win.bpl = v.bytesperline;
+
+			DEBUG(printk("Display at %p is %d by %d, bytedepth %d, bpl %d\n",
+				     v.base, v.width, v.height, saa->win.bpp, saa->win.bpl));
+			saa7146_set_winsize(saa);
+			return 0;
+		}
+	case VIDIOCKEY:
+		{
+			/* Will be handled higher up .. */
+			return 0;
+		}
+
+	case VIDIOCGAUDIO:
+		{
+			struct video_audio v;
+			v = saa->audio_dev;
+			v.flags &= ~(VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE);
+			v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME;
+			strcpy(v.name, "MPEG");
+			v.mode = VIDEO_SOUND_STEREO;
+			if (copy_to_user(arg, &v, sizeof(v)))
+				return -EFAULT;
+			return 0;
+		}
+	case VIDIOCSAUDIO:
+		{
+			struct video_audio v;
+			int i;
+			if (copy_from_user(&v, arg, sizeof(v)))
+				return -EFAULT;
+			i = (~(v.volume>>8))&0xff;
+			if (!HaveCS4341) {
+				if (v.flags & VIDEO_AUDIO_MUTE) {
+					debiwrite(saa, debNormal,
+						IBM_MP2_FRNT_ATTEN,
+						0xffff, 2);
+				}
+				if (!(v.flags & VIDEO_AUDIO_MUTE))
+					debiwrite(saa, debNormal,
+						IBM_MP2_FRNT_ATTEN,
+						  0x0000, 2);
+				if (v.flags & VIDEO_AUDIO_VOLUME)
+					debiwrite(saa, debNormal,
+						IBM_MP2_FRNT_ATTEN,
+						(i<<8)|i, 2);
+			} else {
+				if (v.flags & VIDEO_AUDIO_MUTE)
+					cs4341_setlevel(saa, 0xff, 0xff);
+				if (!(v.flags & VIDEO_AUDIO_MUTE))
+					cs4341_setlevel(saa, 0, 0);
+				if (v.flags & VIDEO_AUDIO_VOLUME)
+					cs4341_setlevel(saa, i, i);
+			}
+			saa->audio_dev = v;
+			return 0;
+		}
+
+	case VIDIOCGUNIT:
+		{
+			struct video_unit vu;
+			vu.video = saa->video_dev.minor;
+			vu.vbi = VIDEO_NO_UNIT;
+			vu.radio = VIDEO_NO_UNIT;
+			vu.audio = VIDEO_NO_UNIT;
+			vu.teletext = VIDEO_NO_UNIT;
+			if (copy_to_user((void *) arg, (void *) &vu, sizeof(vu)))
+				return -EFAULT;
+			return 0;
+		}
+	case VIDIOCSPLAYMODE:
+		{
+			struct video_play_mode pmode;
+			if (copy_from_user((void *) &pmode, arg,
+				sizeof(struct video_play_mode)))
+				return -EFAULT;
+			switch (pmode.mode) {
+				case VID_PLAY_VID_OUT_MODE:
+					if (pmode.p1 != VIDEO_MODE_NTSC &&
+						pmode.p1 != VIDEO_MODE_PAL)
+						return -EINVAL;
+					set_out_format(saa, pmode.p1);
+					return 0;
+				case VID_PLAY_GENLOCK:
+					debiwrite(saa, debNormal,
+						  XILINX_CTL0,
+						  (pmode.p1 ? 0x8000 : 0x8080),
+						  2);
+					if (NewCard)
+						set_genlock_offset(saa,
+							pmode.p2);
+					return 0;
+				case VID_PLAY_NORMAL:
+					debiwrite(saa, debNormal,
+						IBM_MP2_CHIP_CONTROL,
+						ChipControl, 2);
+					ibm_send_command(saa,
+						IBM_MP2_PLAY, 0, 0);
+					saa->playmode = pmode.mode;
+					return 0;
+				case VID_PLAY_PAUSE:
+					/* IBM removed the PAUSE command */
+					/* they say use SINGLE_FRAME now */
+				case VID_PLAY_SINGLE_FRAME:
+					ibm_send_command(saa,
+							IBM_MP2_SINGLE_FRAME,
+							0, 0);
+					if (saa->playmode == pmode.mode) {
+						debiwrite(saa, debNormal,
+							IBM_MP2_CHIP_CONTROL,
+							ChipControl, 2);
+					}
+					saa->playmode = pmode.mode;
+					return 0;
+				case VID_PLAY_FAST_FORWARD:
+					ibm_send_command(saa,
+						IBM_MP2_FAST_FORWARD, 0, 0);
+					saa->playmode = pmode.mode;
+					return 0;
+				case VID_PLAY_SLOW_MOTION:
+					ibm_send_command(saa,
+						IBM_MP2_SLOW_MOTION,
+						pmode.p1, 0);
+					saa->playmode = pmode.mode;
+					return 0;
+				case VID_PLAY_IMMEDIATE_NORMAL:
+					/* ensure transfers resume */
+					debiwrite(saa, debNormal,
+						IBM_MP2_CHIP_CONTROL,
+						ChipControl, 2);
+					ibm_send_command(saa,
+						IBM_MP2_IMED_NORM_PLAY, 0, 0);
+					saa->playmode = VID_PLAY_NORMAL;
+					return 0;
+				case VID_PLAY_SWITCH_CHANNELS:
+					saa->audhead = saa->audtail = 0;
+					saa->vidhead = saa->vidtail = 0;
+					ibm_send_command(saa,
+						IBM_MP2_FREEZE_FRAME, 0, 1);
+					ibm_send_command(saa,
+						IBM_MP2_RESET_AUD_RATE, 0, 1);
+					debiwrite(saa, debNormal,
+						IBM_MP2_CHIP_CONTROL, 0, 2);
+					ibm_send_command(saa,
+						IBM_MP2_CHANNEL_SWITCH, 0, 1);
+					debiwrite(saa, debNormal,
+						IBM_MP2_CHIP_CONTROL,
+						ChipControl, 2);
+					ibm_send_command(saa,
+						IBM_MP2_PLAY, 0, 0);
+					saa->playmode = VID_PLAY_NORMAL;
+					return 0;
+				case VID_PLAY_FREEZE_FRAME:
+					ibm_send_command(saa,
+						IBM_MP2_FREEZE_FRAME, 0, 0);
+					saa->playmode = pmode.mode;
+					return 0;
+				case VID_PLAY_STILL_MODE:
+					ibm_send_command(saa,
+						IBM_MP2_SET_STILL_MODE, 0, 0);
+					saa->playmode = pmode.mode;
+					return 0;
+				case VID_PLAY_MASTER_MODE:
+					if (pmode.p1 == VID_PLAY_MASTER_NONE)
+						saa->boardcfg[1] = 0x13;
+					else if (pmode.p1 ==
+						VID_PLAY_MASTER_VIDEO)
+						saa->boardcfg[1] = 0x23;
+					else if (pmode.p1 ==
+						VID_PLAY_MASTER_AUDIO)
+						saa->boardcfg[1] = 0x43;
+					else
+						return -EINVAL;
+					debiwrite(saa, debNormal,
+						IBM_MP2_CHIP_CONTROL,
+						ChipControl, 2);
+					return 0;
+				case VID_PLAY_ACTIVE_SCANLINES:
+					if (CurrentMode == VIDEO_MODE_PAL) {
+						if (pmode.p1 < 1 ||
+							pmode.p2 > 625)
+							return -EINVAL;
+						saa->boardcfg[5] = pmode.p1;
+						saa->boardcfg[55] = (pmode.p1 +
+							(pmode.p2/2) - 1) &	
+							0xff;
+					} else {
+						if (pmode.p1 < 4 ||
+							pmode.p2 > 525)
+							return -EINVAL;
+						saa->boardcfg[4] = pmode.p1;
+						saa->boardcfg[54] = (pmode.p1 +
+							(pmode.p2/2) - 4) &
+							0xff;
+					}
+					set_out_format(saa, CurrentMode);
+				case VID_PLAY_RESET:
+					return do_ibm_reset(saa);
+				case VID_PLAY_END_MARK:
+					if (saa->endmarktail <  
+						saa->endmarkhead) {
+						if (saa->endmarkhead -
+							saa->endmarktail < 2)
+							return -ENOSPC;
+					} else if (saa->endmarkhead <=
+						saa->endmarktail) {
+						if (saa->endmarktail -
+							saa->endmarkhead >
+							(MAX_MARKS - 2))
+							return -ENOSPC;
+					} else
+						return -ENOSPC;
+					saa->endmark[saa->endmarktail] =
+						saa->audtail;
+					saa->endmarktail++;
+					if (saa->endmarktail >= MAX_MARKS)
+						saa->endmarktail = 0;
+			}
+			return -EINVAL;
+		}
+	case VIDIOCSWRITEMODE:
+		{
+			int mode;
+			if (copy_from_user((void *) &mode, arg, sizeof(int)))
+				 return -EFAULT;
+			if (mode == VID_WRITE_MPEG_AUD ||
+			    mode == VID_WRITE_MPEG_VID ||
+			    mode == VID_WRITE_CC ||
+			    mode == VID_WRITE_TTX ||
+			    mode == VID_WRITE_OSD) {
+				saa->writemode = mode;
+				return 0;
+			}
+			return -EINVAL;
+		}
+	case VIDIOCSMICROCODE:
+		{
+			struct video_code ucode;
+			__u8 *udata;
+			int i;
+			if (copy_from_user((void *) &ucode, arg,
+			    sizeof(ucode)))
+				return -EFAULT;
+			if (ucode.datasize > 65536 || ucode.datasize < 1024 ||
+			    strncmp(ucode.loadwhat, "dec", 3))
+				return -EINVAL;
+			if ((udata = vmalloc(ucode.datasize)) == NULL)
+				return -ENOMEM;
+			if (copy_from_user((void *) udata, ucode.data,
+			    ucode.datasize)) {
+				vfree(udata);
+				return -EFAULT;
+			}
+			ucode.data = udata;
+			if (!strncmp(ucode.loadwhat, "decoder.aud", 11)
+				|| !strncmp(ucode.loadwhat, "decoder.vid", 11))
+				i = initialize_ibmmpeg2(&ucode);
+			else
+				i = initialize_fpga(&ucode);
+			vfree(udata);
+			if (i)
+				return -EINVAL;
+			return 0;
+
+		}
+	case VIDIOCGCHAN:	/* this makes xawtv happy */
+		{
+			struct video_channel v;
+			if (copy_from_user(&v, arg, sizeof(v)))
+				return -EFAULT;
+			v.flags = VIDEO_VC_AUDIO;
+			v.tuners = 0;
+			v.type = VID_TYPE_MPEG_DECODER;
+			v.norm = CurrentMode;
+			strcpy(v.name, "MPEG2");
+			if (copy_to_user(arg, &v, sizeof(v)))
+				return -EFAULT;
+			return 0;
+		}
+	case VIDIOCSCHAN:	/* this makes xawtv happy */
+		{
+			struct video_channel v;
+			if (copy_from_user(&v, arg, sizeof(v)))
+				return -EFAULT;
+			/* do nothing */
+			return 0;
+		}
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static int saa_init_done(struct video_device *dev)
+{
+	return 0;
+}
+
+static int saa_mmap(struct video_device *dev, const char *adr,
+		    unsigned long size)
+{
+	struct saa7146 *saa = (struct saa7146 *) dev;
+	printk(KERN_DEBUG "stradis%d: saa_mmap called\n", saa->nr);
+	return -EINVAL;
+}
+
+static long saa_read(struct video_device *dev, char *buf,
+		     unsigned long count, int nonblock)
+{
+	return -EINVAL;
+}
+
+static long saa_write(struct video_device *dev, const char *buf,
+		      unsigned long count, int nonblock)
+{
+	struct saa7146 *saa = (struct saa7146 *) dev;
+	unsigned long todo = count;
+	int blocksize, split;
+	unsigned long flags;
+
+	while (todo > 0) {
+		if (saa->writemode == VID_WRITE_MPEG_AUD) {
+			spin_lock_irqsave(&saa->lock, flags);
+			if (saa->audhead <= saa->audtail)
+				blocksize = 65536-(saa->audtail - saa->audhead);
+			else
+				blocksize = saa->audhead - saa->audtail;
+			spin_unlock_irqrestore(&saa->lock, flags);
+			if (blocksize < 16384) {
+				saawrite(SAA7146_PSR_DEBI_S |
+					 SAA7146_PSR_PIN1, SAA7146_IER);
+				saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
+				/* wait for buffer space to open */
+				interruptible_sleep_on(&saa->audq);
+			}
+			spin_lock_irqsave(&saa->lock, flags);
+			if (saa->audhead <= saa->audtail) {
+				blocksize = 65536-(saa->audtail - saa->audhead);
+				split = 65536 - saa->audtail;
+			} else {
+				blocksize = saa->audhead - saa->audtail;
+				split = 65536;
+			}
+			spin_unlock_irqrestore(&saa->lock, flags);
+			blocksize--;
+			if (blocksize > todo)
+				blocksize = todo;
+			/* double check that we really have space */
+			if (!blocksize)
+				return -ENOSPC;
+			if (split < blocksize) {
+				if (copy_from_user(saa->audbuf +
+					saa->audtail, buf, split)) 
+					return -EFAULT;
+				buf += split;
+				todo -= split;
+				blocksize -= split;
+				saa->audtail = 0;
+			}
+			if (copy_from_user(saa->audbuf + saa->audtail, buf,
+				blocksize)) 
+				return -EFAULT;
+			saa->audtail += blocksize;
+			todo -= blocksize;
+			buf += blocksize;
+			saa->audtail &= 0xffff;
+		} else if (saa->writemode == VID_WRITE_MPEG_VID) {
+			spin_lock_irqsave(&saa->lock, flags);
+			if (saa->vidhead <= saa->vidtail)
+				blocksize=524288-(saa->vidtail - saa->vidhead);
+			else
+				blocksize = saa->vidhead - saa->vidtail;
+			spin_unlock_irqrestore(&saa->lock, flags);
+			if (blocksize < 65536) {
+				saawrite(SAA7146_PSR_DEBI_S |
+					 SAA7146_PSR_PIN1, SAA7146_IER);
+				saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
+				/* wait for buffer space to open */
+				interruptible_sleep_on(&saa->vidq);
+			}
+			spin_lock_irqsave(&saa->lock, flags);
+			if (saa->vidhead <= saa->vidtail) {
+				blocksize=524288-(saa->vidtail - saa->vidhead);
+				split = 524288 - saa->vidtail;
+			} else {
+				blocksize = saa->vidhead - saa->vidtail;
+				split = 524288;
+			}
+			spin_unlock_irqrestore(&saa->lock, flags);
+			blocksize--;
+			if (blocksize > todo)
+				blocksize = todo;
+			/* double check that we really have space */
+			if (!blocksize)
+				return -ENOSPC;
+			if (split < blocksize) {
+				if (copy_from_user(saa->vidbuf +
+					saa->vidtail, buf, split)) 
+					return -EFAULT;
+				buf += split;
+				todo -= split;
+				blocksize -= split;
+				saa->vidtail = 0;
+			}
+			if (copy_from_user(saa->vidbuf + saa->vidtail, buf,
+				blocksize)) 
+				return -EFAULT;
+			saa->vidtail += blocksize;
+			todo -= blocksize;
+			buf += blocksize;
+			saa->vidtail &= 0x7ffff;
+		} else if (saa->writemode == VID_WRITE_OSD) {
+			if (count > 131072)
+				return -ENOSPC;
+			if (copy_from_user(saa->osdbuf, buf, count))
+				return -EFAULT;
+			buf += count;
+			saa->osdhead = 0;
+			saa->osdtail = count;
+			debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR, 0, 2);
+			debiwrite(saa, debNormal, IBM_MP2_OSD_LINK_ADDR, 0, 2);
+			debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00d, 2);
+			debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
+				  debiread(saa, debNormal,
+				  IBM_MP2_DISP_MODE, 2) | 1, 2);
+			/* trigger osd data transfer */
+			saawrite(SAA7146_PSR_DEBI_S |
+				 SAA7146_PSR_PIN1, SAA7146_IER);
+			saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
+		}
+	}
+	return count;
+}
+
+static int saa_open(struct video_device *dev, int flags)
+{
+	struct saa7146 *saa = (struct saa7146 *) dev;
+
+	saa->video_dev.busy = 0;
+	saa->user++;
+	if (saa->user > 1)
+		return 0;	/* device open already, don't reset */
+	saa->writemode = VID_WRITE_MPEG_VID;	/* default to video */
+	return 0;
+}
+
+static void saa_close(struct video_device *dev)
+{
+	struct saa7146 *saa = (struct saa7146 *) dev;
+	saa->user--;
+	saa->video_dev.busy = 0;
+	if (saa->user > 0)	/* still someone using device */
+		return;
+	saawrite(0x007f0000, SAA7146_MC1);	/* stop all overlay dma */
+}
+
+/* template for video_device-structure */
+static struct video_device saa_template =
+{
+	"SAA7146A",
+	VID_TYPE_CAPTURE | VID_TYPE_OVERLAY,
+	VID_HARDWARE_SAA7146,
+	saa_open,
+	saa_close,
+	saa_read,
+	saa_write,
+	NULL,			/* poll */
+	saa_ioctl,
+	saa_mmap,
+	saa_init_done,
+	NULL,
+	0,
+	0
+};
+
+static int configure_saa7146(struct pci_dev *dev, int num)
+{
+	int result;
+	struct saa7146 *saa;
+
+	saa = &saa7146s[num];
+	
+	saa->endmarkhead = saa->endmarktail = 0;
+	saa->win.x = saa->win.y = 0;
+	saa->win.width = saa->win.cropwidth = 720;
+	saa->win.height = saa->win.cropheight = 480;
+	saa->win.cropx = saa->win.cropy = 0;
+	saa->win.bpp = 2;
+	saa->win.depth = 16;
+	saa->win.color_fmt = palette2fmt[VIDEO_PALETTE_RGB565];
+	saa->win.bpl = 1024 * saa->win.bpp;
+	saa->win.swidth = 1024;
+	saa->win.sheight = 768;
+	saa->picture.brightness = 32768;
+	saa->picture.contrast = 38768;
+	saa->picture.colour = 32768;
+	saa->cap = 0;
+	saa->dev = dev;
+	saa->nr = num;
+	saa->playmode = VID_PLAY_NORMAL;
+	memset(saa->boardcfg, 0, 64);	/* clear board config area */
+	saa->saa7146_mem = NULL;
+	saa->dmavid1 = saa->dmavid2 = saa->dmavid3 = saa->dmaa1in =
+	    saa->dmaa1out = saa->dmaa2in = saa->dmaa2out =
+	    saa->pagevid1 = saa->pagevid2 = saa->pagevid3 = saa->pagea1in =
+	    saa->pagea1out = saa->pagea2in = saa->pagea2out =
+	    saa->pagedebi = saa->dmaRPS1 = saa->dmaRPS2 = saa->pageRPS1 =
+	    saa->pageRPS2 = NULL;
+	saa->audbuf = saa->vidbuf = saa->osdbuf = saa->dmadebi = NULL;
+	saa->audhead = saa->vidtail = 0;
+
+	init_waitqueue_head(&saa->i2cq);
+	init_waitqueue_head(&saa->audq);
+	init_waitqueue_head(&saa->debiq);
+	init_waitqueue_head(&saa->vidq);
+	spin_lock_init(&saa->lock);
+	
+	saa->id = dev->device;
+	saa->irq = dev->irq;
+	saa->video_dev.minor = -1;
+	saa->saa7146_adr = dev->resource[0].start;
+	pci_read_config_byte(dev, PCI_CLASS_REVISION, &saa->revision);
+	saa->saa7146_mem = ioremap(((saa->saa7146_adr) &
+		PCI_BASE_ADDRESS_MEM_MASK), 0x200);
+	memcpy(&(saa->i2c), &saa7146_i2c_bus_template, sizeof(struct i2c_bus));
+	memcpy(&saa->video_dev, &saa_template, sizeof(saa_template));
+	sprintf(saa->i2c.name, "stradis%d", num);
+	saa->i2c.data = saa;
+	saawrite(0, SAA7146_IER);	/* turn off all interrupts */
+	result = request_irq(saa->irq, saa7146_irq,
+		       SA_SHIRQ | SA_INTERRUPT, "stradis", (void *) saa);
+	if (result == -EINVAL)
+		printk(KERN_ERR "stradis%d: Bad irq number or handler\n",
+		       num);
+	if (result == -EBUSY)
+		printk(KERN_ERR "stradis%d: IRQ %ld busy, change your PnP"
+		       " config in BIOS\n", num, saa->irq);
+	if (result < 0)
+		return result;
+	pci_set_master(dev);
+	if (video_register_device(&saa->video_dev, VFL_TYPE_GRABBER) < 0)
+		return -1;
+#if 0
+	/* i2c generic interface is currently BROKEN */
+	i2c_register_bus(&saa->i2c);
+#endif
+	return 0;
+}
+
+static int init_saa7146(int i)
+{
+	struct saa7146 *saa = &saa7146s[i];
+
+	saa->user = 0;
+	/* reset the saa7146 */
+	saawrite(0xffff0000, SAA7146_MC1);
+	mdelay(5);
+	/* enable debi and i2c transfers and pins */
+	saawrite(((SAA7146_MC1_EDP | SAA7146_MC1_EI2C |
+		   SAA7146_MC1_TR_E_DEBI) << 16) | 0xffff, SAA7146_MC1);
+	/* ensure proper state of chip */
+	saawrite(0x00000000, SAA7146_PAGE1);
+	saawrite(0x00f302c0, SAA7146_NUM_LINE_BYTE1);
+	saawrite(0x00000000, SAA7146_PAGE2);
+	saawrite(0x01400080, SAA7146_NUM_LINE_BYTE2);
+	saawrite(0x00000000, SAA7146_DD1_INIT);
+	saawrite(0x00000000, SAA7146_DD1_STREAM_B);
+	saawrite(0x00000000, SAA7146_DD1_STREAM_A);
+	saawrite(0x00000000, SAA7146_BRS_CTRL);
+	saawrite(0x80400040, SAA7146_BCS_CTRL);
+	saawrite(0x0000e000 /*| (1<<29)*/, SAA7146_HPS_CTRL);
+	saawrite(0x00000060, SAA7146_CLIP_FORMAT_CTRL);
+	saawrite(0x00000000, SAA7146_ACON1);
+	saawrite(0x00000000, SAA7146_ACON2);
+	saawrite(0x00000600, SAA7146_I2C_STATUS);
+	saawrite(((SAA7146_MC2_UPLD_D1_B | SAA7146_MC2_UPLD_D1_A |
+		   SAA7146_MC2_UPLD_BRS | SAA7146_MC2_UPLD_HPS_H |
+		   SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_DMA2 |
+	   SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_I2C) << 16) | 0xffff,
+		 SAA7146_MC2);
+	/* setup arbitration control registers */
+	saawrite(0x1412121a, SAA7146_PCI_BT_V1);
+
+	/* allocate 32k dma buffer + 4k for page table */
+	if ((saa->dmadebi = kmalloc(32768 + 4096, GFP_KERNEL)) == NULL) {
+		printk(KERN_ERR "stradis%d: debi kmalloc failed\n", i);
+		return -1;
+	}
+#if 0
+	saa->pagedebi = saa->dmadebi + 32768;	/* top 4k is for mmu */
+	saawrite(virt_to_bus(saa->pagedebi) /*|0x800 */ , SAA7146_DEBI_PAGE);
+	for (i = 0; i < 12; i++)	/* setup mmu page table */
+		saa->pagedebi[i] = virt_to_bus((saa->dmadebi + i * 4096));
+#endif
+	saa->audhead = saa->vidhead = saa->osdhead = 0;
+	saa->audtail = saa->vidtail = saa->osdtail = 0;
+	if (saa->vidbuf == NULL)
+		if ((saa->vidbuf = vmalloc(524288)) == NULL) {
+			printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr);
+			return -ENOMEM;
+		}
+	if (saa->audbuf == NULL)
+		if ((saa->audbuf = vmalloc(65536)) == NULL) {
+			printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr);
+			vfree(saa->vidbuf);
+			saa->vidbuf = NULL;
+			return -ENOMEM;
+		}
+	if (saa->osdbuf == NULL)
+		if ((saa->osdbuf = vmalloc(131072)) == NULL) {
+			printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr);
+			vfree(saa->vidbuf);
+			vfree(saa->audbuf);
+			saa->vidbuf = saa->audbuf = NULL;
+			return -ENOMEM;
+		}
+	/* allocate 81920 byte buffer for clipping */
+	if ((saa->dmavid2 = kmalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) {
+		printk(KERN_ERR "stradis%d: clip kmalloc failed\n", saa->nr);
+		vfree(saa->vidbuf);
+		vfree(saa->audbuf);
+		vfree(saa->osdbuf);
+		saa->vidbuf = saa->audbuf = saa->osdbuf = NULL;
+		saa->dmavid2 = NULL;
+		return -1;
+	}
+	memset(saa->dmavid2, 0x00, VIDEO_CLIPMAP_SIZE);	/* clip everything */
+	/* setup clipping registers */
+	saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2);
+	saawrite(virt_to_bus(saa->dmavid2) + 128, SAA7146_BASE_ODD2);
+	saawrite(virt_to_bus(saa->dmavid2) + VIDEO_CLIPMAP_SIZE,
+		SAA7146_PROT_ADDR2);
+	saawrite(256, SAA7146_PITCH2);
+	saawrite(4, SAA7146_PAGE2); /* dma direction: read, no byteswap */
+	saawrite(((SAA7146_MC2_UPLD_DMA2) << 16) | SAA7146_MC2_UPLD_DMA2,
+		 SAA7146_MC2);
+	I2CBusScan(&(saa->i2c));
+	return 0;
+}
+
+static void release_saa(void)
+{
+	u8 command;
+	int i;
+	struct saa7146 *saa;
+
+	for (i = 0; i < saa_num; i++) {
+		saa = &saa7146s[i];
+
+		/* turn off all capturing, DMA and IRQs */
+		saawrite(0xffff0000, SAA7146_MC1);	/* reset chip */
+		saawrite(0, SAA7146_MC2);
+		saawrite(0, SAA7146_IER);
+		saawrite(0xffffffffUL, SAA7146_ISR);
+#if 0
+		/* unregister i2c_bus */
+		i2c_unregister_bus((&saa->i2c));
+#endif
+
+		/* disable PCI bus-mastering */
+		pci_read_config_byte(saa->dev, PCI_COMMAND, &command);
+		/* Should this be &=~ ?? */
+		command &= ~PCI_COMMAND_MASTER;
+		pci_write_config_byte(saa->dev, PCI_COMMAND, command);
+		/* unmap and free memory */
+		saa->audhead = saa->audtail = saa->osdhead = 0;
+		saa->vidhead = saa->vidtail = saa->osdtail = 0;
+		if (saa->vidbuf)
+			vfree(saa->vidbuf);
+		if (saa->audbuf)
+			vfree(saa->audbuf);
+		if (saa->osdbuf)
+			vfree(saa->osdbuf);
+		if (saa->dmavid2)
+			kfree((void *) saa->dmavid2);
+		saa->audbuf = saa->vidbuf = saa->osdbuf = NULL;
+		saa->dmavid2 = NULL;
+		if (saa->dmadebi)
+			kfree((void *) saa->dmadebi);
+		if (saa->dmavid1)
+			kfree((void *) saa->dmavid1);
+		if (saa->dmavid2)
+			kfree((void *) saa->dmavid2);
+		if (saa->dmavid3)
+			kfree((void *) saa->dmavid3);
+		if (saa->dmaa1in)
+			kfree((void *) saa->dmaa1in);
+		if (saa->dmaa1out)
+			kfree((void *) saa->dmaa1out);
+		if (saa->dmaa2in)
+			kfree((void *) saa->dmaa2in);
+		if (saa->dmaa2out)
+			kfree((void *) saa->dmaa2out);
+		if (saa->dmaRPS1)
+			kfree((void *) saa->dmaRPS1);
+		if (saa->dmaRPS2)
+			kfree((void *) saa->dmaRPS2);
+		free_irq(saa->irq, saa);
+		if (saa->saa7146_mem)
+			iounmap(saa->saa7146_mem);
+		if (saa->video_dev.minor != -1)
+			video_unregister_device(&saa->video_dev);
+	}
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+#else
+int init_stradis_cards(struct video_init *unused)
+{
+#endif
+	struct pci_dev *dev = pci_devices;
+	int result = 0, i;
+	u32 newcard;
+
+	saa_num = 0;
+
+	while (dev) {
+		if (dev->vendor == PCI_VENDOR_ID_PHILIPS)
+			if (dev->device == PCI_DEVICE_ID_PHILIPS_SAA7146) {
+				pci_read_config_dword(dev,
+					PCI_SUBSYSTEM_VENDOR_ID, &newcard);
+				if (!newcard)
+					printk(KERN_INFO "stradis%d: rev1 decoder\n", saa_num);
+				else
+					printk(KERN_INFO "stradis%d: SDM2xx found\n", saa_num); 
+				result = configure_saa7146(dev, saa_num++);
+			}
+		if (result)
+			return result;
+		dev = dev->next;
+	}
+	if (saa_num)
+		printk(KERN_INFO "stradis: %d card(s) found.\n", saa_num);
+	else
+		return -EINVAL;
+	for (i = 0; i < saa_num; i++)
+		if (init_saa7146(i) < 0) {
+			release_saa();
+			return -EIO;
+		}
+	return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+	release_saa();
+	printk(KERN_INFO "stradis: module cleanup complete\n");
+}
+
+#endif
diff -u --recursive --new-file v2.3.26/linux/drivers/char/videodev.c linux/drivers/char/videodev.c
--- v2.3.26/linux/drivers/char/videodev.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/char/videodev.c	Wed Nov 10 16:09:01 1999
@@ -60,6 +60,9 @@
 	{"i2c-tuner", i2c_tuner_init},
 	{"bttv", init_bttv_cards},
 #endif	
+#ifdef CONFIG_VIDEO_STRADIS
+	{"stradis", init_stradis_cards},
+#endif	
 #ifdef CONFIG_VIDEO_BWQCAM
 	{"bw-qcam", init_bw_qcams},
 #endif	
diff -u --recursive --new-file v2.3.26/linux/drivers/i2o/README linux/drivers/i2o/README
--- v2.3.26/linux/drivers/i2o/README	Mon Oct  4 15:49:29 1999
+++ linux/drivers/i2o/README	Wed Nov 10 09:52:18 1999
@@ -9,13 +9,13 @@
 
 AUTHORS (so far)
 
-Alan Cox, 	Building Number Three Ltd.
+Alan Cox, Building Number Three Ltd.
 	Core code, SCSI and Block OSMs
 
-Steve Ralston,	LSI Logic Corp.
+Steve Ralston, LSI Logic Corp.
 	Debugging SCSI and Block OSM
 
-Deepak Saxena,	Intel Corp.
+Deepak Saxena, Intel Corp.
 	/proc interface, bug fixes
 	Ioctl interfaces for control
 	Debugging LAN OSM
@@ -23,18 +23,21 @@
 Philip Rumpf
 	Fixed assorted dumb SMP locking bugs
 
-Juha Sievanen,  University of Helsinki Finland
+Juha Sievanen, University of Helsinki Finland
 	LAN OSM code
 	/proc interface to LAN class
 	Bug fixes
 	Core code extensions
 
-Auvo Häkkinen,  University of Helsinki Finland
+Auvo Häkkinen, University of Helsinki Finland
 	LAN OSM code
 	/Proc interface to LAN class
 	Bug fixes
 	Core code extensions
 
+Taneli Vähäkangas, University of Helsinki Finland
+	Fixes to i2o_config
+
 CREDITS
 
 	This work was made possible by 
@@ -75,6 +78,7 @@
 o	PCI IOP's without interrupts are not supported yet
 o	Push FAIL handling into the core
 o	DDM control interfaces for module load etc
+o	Event handling
 
 Block:
 o	Real error handler
@@ -87,7 +91,8 @@
 o	Find the right way to associate drives/luns/busses
 
 Lan:	Batch mode sends
-	Fix the "killing interrupt handler" in i2o_set_multicast_list
+	Performance tuning
+	Event handling
 
 Tape:
 o	Anyone seen anything implementing this ?
diff -u --recursive --new-file v2.3.26/linux/drivers/i2o/README.ioctl linux/drivers/i2o/README.ioctl
--- v2.3.26/linux/drivers/i2o/README.ioctl	Mon Oct  4 15:49:29 1999
+++ linux/drivers/i2o/README.ioctl	Wed Nov 10 09:52:18 1999
@@ -208,18 +208,16 @@
 
    DESCRIPTION
 
-   This function downloads the software pointed by sw->buf to the
-   iop identified by sw->iop. The DownloadFlags, SwID, SwType and SwSize 
-   fields of the ExecSwDownload message are filled in with the values of 
-   sw->flags, sw->sw_id, sw->sw_type and *(sw->swlen).
-
-   Once the ioctl() is called and software transfer begins, the 
-   user can read the value *(sw->maxfrag) and *(sw->curfrag) to
-   determine the status of the software transfer. As the IOP
-   is very slow when it comes to SW transfers, this can be
-   used by a separate thread to report status to the user. The
-   user _should not_ write to this memory location until the ioctl()
-   has returned.
+   This function downloads a software fragment pointed by sw->buf
+   to the iop identified by sw->iop. The DownloadFlags, SwID, SwType
+   and SwSize fields of the ExecSwDownload message are filled in with
+   the values of sw->flags, sw->sw_id, sw->sw_type and *(sw->swlen).
+
+   The fragments _must_ be sent in order and be 8K in size. The last
+   fragment _may_ be shorter, however. The kernel will compute its
+   size based on information in the sw->swlen field.
+
+   Please note that SW transfers can take a long time.
 
    RETURNS
 
@@ -234,7 +232,7 @@
 IX. Uploading Software
    
    SYNOPSIS 
- 
+
    ioctl(fd, I2OSWUL, struct i2o_sw_xfer *sw);
 
       struct i2o_sw_xfer
@@ -251,19 +249,17 @@
 
    DESCRIPTION
 
-   This function uploads software from the IOP identified by sw->iop
-   and places it in the buffer pointed to by sw->buf. The length of the
-   buffer is given in *(sw->swlen). The UploadFlags, SwID and SwType
-   fields of the ExecSwUpload message are filled in 
-   with the values of sw->flags, sw->sw_id and sw->sw_type. 
-
-   Once the ioctl() is called and software transfer begins, the 
-   user can read the value *(sw->maxfrag) and *(sw->curfrag) to
-   determine the status of the software transfer.  As the IOP
-   is very slow when it comes to SW transfers, this can be
-   used by a separate thread to report status to the user. The
-   user _should not_ write to this memory location until the ioctl()
-   has returned.
+   This function uploads a software fragment from the IOP identified
+   by sw->iop, sw->sw_type, sw->sw_id and optionally sw->swlen fields.
+   The UploadFlags, SwID, SwType and SwSize fields of the ExecSwUpload
+   message are filled in with the values of sw->flags, sw->sw_id,
+   sw->sw_type and *(sw->swlen).
+
+   The fragments _must_ be requested in order and be 8K in size. The
+   user is responsible for allocating memory pointed by sw->buf. The
+   last fragment _may_ be shorter.
+
+   Please note that SW transfers can take a long time.
 
    RETURNS
 
diff -u --recursive --new-file v2.3.26/linux/drivers/i2o/i2o_config.c linux/drivers/i2o/i2o_config.c
--- v2.3.26/linux/drivers/i2o/i2o_config.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/i2o/i2o_config.c	Wed Nov 10 09:52:18 1999
@@ -11,7 +11,11 @@
  *         - Added software download ioctl (still testing)
  *	Modified 09/10/1999 by Auvo Häkkinen
  *	   - Changes to i2o_cfg_reply(), ioctl_parms()
- *	   - Added ioct_validate() (not yet tested)
+ *	   - Added ioct_validate()
+ *	Modified 09/30/1999 by Taneli Vähäkangas
+ *	   - Fixed ioctl_swdl()
+ *	Modified 10/04/1999 by Taneli Vähäkangas
+ *	   - Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel()
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -33,8 +37,6 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-#include "i2o_proc.h"
-
 static int i2o_cfg_token = 0;
 static int i2o_cfg_context = -1;
 static void *page_buf;
@@ -196,7 +198,7 @@
 	struct i2o_controller *c;
 	struct i2o_cmd_hrtlct *cmd = (struct i2o_cmd_hrtlct*)arg;
 	struct i2o_cmd_hrtlct kcmd;
-	pi2o_hrt hrt;
+	i2o_hrt *hrt;
 	int len;
 	u32 reslen;
 	int ret = 0;
@@ -214,7 +216,7 @@
 	if(!c)
 		return -ENXIO;
 		
-	hrt = (pi2o_hrt)c->hrt;
+	hrt = (i2o_hrt *)c->hrt;
 
 	i2o_unlock_controller(c);
 
@@ -235,7 +237,7 @@
 	struct i2o_controller *c;
 	struct i2o_cmd_hrtlct *cmd = (struct i2o_cmd_hrtlct*)arg;
 	struct i2o_cmd_hrtlct kcmd;
-	pi2o_lct lct;
+	i2o_lct *lct;
 	int len;
 	int ret = 0;
 	u32 reslen;
@@ -253,7 +255,7 @@
 	if(!c)
 		return -ENXIO;
 
-	lct = (pi2o_lct)c->lct;
+	lct = (i2o_lct *)c->lct;
 	i2o_unlock_controller(c);
 
 	len = (unsigned int)lct->table_size << 2;
@@ -317,14 +319,14 @@
 		return -ENOMEM;
 	}
 
-        len = i2o_issue_params(i2o_cmd, c, kcmd.tid,
-        			ops, kcmd.oplen, res, 65536);
+        len = i2o_issue_params(i2o_cmd, c, kcmd.tid, 
+       			ops, kcmd.oplen, res, sizeof(res));
         i2o_unlock_controller(c);
 	kfree(ops);
         
-	if (len) {
+	if (len < 0) {
 		kfree(res);
-		return len; /* -DetailedStatus || -ETIMEDOUT */
+		return len; /* -DetailedStatus */
 	}
 
 	put_user(len, kcmd.reslen);
@@ -414,7 +416,7 @@
 	}
 
 	token = i2o_post_wait(c, msg, 9*4, 10);
-	if(token)
+	if(token != I2O_POST_WAIT_OK)
 	{
 		i2o_unlock_controller(c);
 		kfree(res);
@@ -437,139 +439,175 @@
 
 	return ret;
 }
-
+ 
 int ioctl_swdl(unsigned long arg)
 {
 	struct i2o_sw_xfer kxfer;
 	struct i2o_sw_xfer *pxfer = (struct i2o_sw_xfer *)arg;
-	unsigned char maxfrag = 0, curfrag = 0;
-	unsigned char buffer[8192];
+	unsigned char maxfrag = 0, curfrag = 1;
+	unsigned char *buffer;
 	u32 msg[9];
-	unsigned int token = 0, diff = 0, swlen = 0, swxfer = 0;
+	unsigned int status = 0, swlen = 0, fragsize = 8192;
 	struct i2o_controller *c;
-	int foo = 0;
 
-	printk("*** foo%d ***\n", foo++);
 	if(copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
-	{
-		printk( "i2o_config: can't copy i2o_sw cmd @ %p\n", pxfer);
 		return -EFAULT;
-	}
-	printk("*** foo%d ***\n", foo++);
 
-	printk("Attempting to copy swlen from %p\n", kxfer.swlen);
 	if(get_user(swlen, kxfer.swlen) < 0)
-	{
-		printk( "i2o_config: can't copy swlen\n");
 		return -EFAULT;
-	}
-	printk("*** foo%d ***\n", foo++);
-
-	maxfrag = swlen >> 13;	// Transfer in 8k fragments
 
-	printk("Attempting to write maxfrag @ %p\n", kxfer.maxfrag);
-	if(put_user(maxfrag, kxfer.maxfrag) < 0)
-	{
-		printk( "i2o_config: can't write maxfrag\n");
+	if(get_user(maxfrag, kxfer.maxfrag) < 0)
 		return -EFAULT;
-	}
-	printk("*** foo%d ***\n", foo++);
 
-	printk("Attempting to write curfrag @ %p\n", kxfer.curfrag);
-	if(put_user(curfrag, kxfer.curfrag) < 0)
-	{
-		printk( "i2o_config: can't write curfrag\n");
+	if(get_user(curfrag, kxfer.curfrag) < 0)
 		return -EFAULT;
-	}
-	printk("*** foo%d ***\n", foo++);
 
-	if(!kxfer.buf)
-	{
-		printk( "i2o_config: NULL software buffer\n");
+	if(curfrag==maxfrag) fragsize = swlen-(maxfrag-1)*8192;
+
+	if(!kxfer.buf || !access_ok(VERIFY_READ, kxfer.buf, fragsize))
 		return -EFAULT;
-	}
-	printk("*** foo%d ***\n", foo++);
 	
-	// access_ok doesn't check for NULL...
-	if(!access_ok(VERIFY_READ, kxfer.buf, swlen))
-	{
-                printk( "i2o_config: Cannot read sw buffer\n");
-                return -EFAULT;
-	}
-	printk("*** foo%d ***\n", foo++);
-
 	c = i2o_find_controller(kxfer.iop);
 	if(!c)
 		return -ENXIO;
-	printk("*** foo%d ***\n", foo++);
+
+	buffer=kmalloc(fragsize, GFP_KERNEL);
+	if (buffer==NULL)
+	{
+		i2o_unlock_controller(c);
+		return -ENOMEM;
+	}
+	__copy_from_user(buffer, kxfer.buf, fragsize);
 
 	msg[0]= NINE_WORD_MSG_SIZE | SGL_OFFSET_7;
 	msg[1]= I2O_CMD_SW_DOWNLOAD<<24 | HOST_TID<<12 | ADAPTER_TID;
 	msg[2]= (u32)cfg_handler.context;
 	msg[3]= 0;
-	msg[4]= ((u32)kxfer.flags)<<24|((u32)kxfer.sw_type)<<16|((u32)maxfrag)<<8|((u32)curfrag);
+	msg[4]= (((u32)kxfer.flags)<<24) | (((u32)kxfer.sw_type)<<16) |
+		(((u32)maxfrag)<<8) | (((u32)curfrag));
 	msg[5]= swlen;
 	msg[6]= kxfer.sw_id;
-	msg[7]= (0xD0000000 | 8192);
+	msg[7]= (0xD0000000 | fragsize);
 	msg[8]= virt_to_phys(buffer);
 
-	printk("*** foo%d ***\n", foo++);
+//	printk("i2o_config: swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
+	status = i2o_post_wait(c, msg, sizeof(msg), 60);
 
-	//
-	// Loop through all fragments but last and transfer them...
-	// We already checked memory, so from now we assume it's all good
-	//
-	for(curfrag = 0; curfrag < maxfrag-1; curfrag++)
-	{
-		printk("Transfering fragment %d\n", curfrag);
-
-		msg[4] |= (u32)curfrag;
-
-		__copy_from_user(buffer, kxfer.buf, 8192);
-		swxfer += 8192;
-
-		// Yes...that's one minute, but the spec states that
-		// transfers take a long time, and I've seen just how
-		// long they can take.
-		token = i2o_post_wait(c, msg, sizeof(msg), 60);
-		if (token)	// Something very wrong
-		{
-			i2o_unlock_controller(c);
-			printk("Timeout downloading software");
-			return -ETIMEDOUT;
-		}
-
-		__put_user(curfrag, kxfer.curfrag);
-	}
-
-	// Last frag is special case since it's not exactly 8K
-	diff = swlen - swxfer;
-	msg[4] |= (u32)maxfrag;
-	msg[7] = (0xD0000000 | diff);
-	__copy_from_user(buffer, kxfer.buf, 8192);
-	token = i2o_post_wait(c, msg, sizeof(msg), 60);
-	if(token)	// Something very wrong
+	i2o_unlock_controller(c);
+	kfree(buffer);
+	
+	if (status != I2O_POST_WAIT_OK)
 	{
-		i2o_unlock_controller(c);
-		printk("Timeout downloading software");
+		// it fails if you try and send frags out of order
+		// and for some yet unknown reasons too
+		printk("i2o_config: swdl failed, DetailedStatus = %d\n", status);
 		return -ETIMEDOUT;
 	}
-	__put_user(curfrag, kxfer.curfrag);
-	i2o_unlock_controller(c);
 
 	return 0;
 }
 
-/* To be written */
 int ioctl_swul(unsigned long arg)
 {
-	return -EINVAL;
+	struct i2o_sw_xfer kxfer;
+	struct i2o_sw_xfer *pxfer = (struct i2o_sw_xfer *)arg;
+	unsigned char maxfrag = 0, curfrag = 1;
+	unsigned char *buffer;
+	u32 msg[9];
+	unsigned int status = 0, swlen = 0, fragsize = 8192;
+	struct i2o_controller *c;
+	
+	if(copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
+		return -EFAULT;
+		
+	if(get_user(swlen, kxfer.swlen) < 0)
+		return -EFAULT;
+		
+	if(get_user(maxfrag, kxfer.maxfrag) < 0)
+		return -EFAULT;
+		
+	if(get_user(curfrag, kxfer.curfrag) < 0)
+		return -EFAULT;
+	
+	if(curfrag==maxfrag) fragsize = swlen-(maxfrag-1)*8192;
+	
+	if(!kxfer.buf || !access_ok(VERIFY_WRITE, kxfer.buf, fragsize))
+		return -EFAULT;
+		
+	c = i2o_find_controller(kxfer.iop);
+	if(!c)
+		return -ENXIO;
+		
+	buffer=kmalloc(fragsize, GFP_KERNEL);
+	if (buffer==NULL)
+	{
+		i2o_unlock_controller(c);
+		return -ENOMEM;
+	}
+	
+	msg[0]= NINE_WORD_MSG_SIZE | SGL_OFFSET_7;
+	msg[1]= I2O_CMD_SW_UPLOAD<<24 | HOST_TID<<12 | ADAPTER_TID;
+	msg[2]= (u32)cfg_handler.context;
+	msg[3]= 0;
+	msg[4]= (u32)kxfer.flags<<24|(u32)kxfer.sw_type<<16|(u32)maxfrag<<8|(u32)curfrag;
+	msg[5]= swlen;
+	msg[6]= kxfer.sw_id;
+	msg[7]= (0xD0000000 | fragsize);
+	msg[8]= virt_to_bus(buffer);
+	
+//	printk("i2o_config: swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
+	status = i2o_post_wait(c, msg, sizeof(msg), 60);
+	i2o_unlock_controller(c);
+	
+	if (status != I2O_POST_WAIT_OK)
+	{
+		kfree(buffer);
+		printk("i2o_config: swul failed, DetailedStatus = %d\n", status);
+		return -ETIMEDOUT;
+	}
+	
+	__copy_to_user(kxfer.buf, buffer, fragsize);
+	kfree(buffer);
+	
+	return 0;
 }
 
-/* To be written */
 int ioctl_swdel(unsigned long arg)
 {
-	return -EINVAL;
+	struct i2o_controller *c;
+	struct i2o_sw_xfer kxfer, *pxfer = (struct i2o_sw_xfer *)arg;
+	u32 msg[7];
+	unsigned int swlen;
+	int token;
+	
+	if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
+		return -EFAULT;
+		
+	if (get_user(swlen, kxfer.swlen) < 0)
+		return -EFAULT;
+		
+	c = i2o_find_controller(kxfer.iop);
+	if (!c)
+		return -ENXIO;
+
+	msg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0;
+	msg[1] = I2O_CMD_SW_REMOVE<<24 | HOST_TID<<12 | ADAPTER_TID;
+	msg[2] = (u32)i2o_cfg_context;
+	msg[3] = 0;
+	msg[4] = (u32)kxfer.flags<<24 | (u32)kxfer.sw_type<<16;
+	msg[5] = swlen;
+	msg[6] = kxfer.sw_id;
+
+	token = i2o_post_wait(c, msg, sizeof(msg), 10);
+	i2o_unlock_controller(c);
+	
+	if (token != I2O_POST_WAIT_OK)
+	{
+		printk("i2o_config: swdel failed, DetailedStatus = %d\n", token);
+		return -ETIMEDOUT;
+	}
+	
+	return 0;
 }
 
 int ioctl_validate(unsigned long arg)
@@ -591,7 +629,7 @@
         token = i2o_post_wait(c, msg, sizeof(msg), 10);
         i2o_unlock_controller(c);
 
-        if (token)
+        if (token != I2O_POST_WAIT_OK)
         {
                 printk("Can't validate configuration, ErrorStatus = %d\n",
                 	token);
@@ -644,7 +682,7 @@
 int __init i2o_config_init(void)
 #endif
 {
-	printk(KERN_INFO "i2o configuration manager v 0.02\n");
+	printk(KERN_INFO "i2o configuration manager v 0.03\n");
 	
 	if((page_buf = kmalloc(4096, GFP_KERNEL))==NULL)
 	{
diff -u --recursive --new-file v2.3.26/linux/drivers/i2o/i2o_core.c linux/drivers/i2o/i2o_core.c
--- v2.3.26/linux/drivers/i2o/i2o_core.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/i2o/i2o_core.c	Wed Nov 10 09:52:18 1999
@@ -35,6 +35,7 @@
 
 #include <linux/bitops.h>
 #include <linux/wait.h>
+#include <linux/delay.h>
 #include <linux/timer.h>
 
 #include <asm/io.h>
@@ -927,7 +928,7 @@
 	u32 *p;
 	struct i2o_device *d;
 	char str[22];
-	pi2o_lct lct = c->lct;
+	i2o_lct *lct = c->lct;
 
 	max = lct->table_size;
 	
@@ -1168,6 +1169,9 @@
 
 	/* Wait for a reply */
 	time=jiffies;
+	
+	/* DPT driver claims they need this */
+	mdelay(5);
 
 #ifdef DRIVERDEBUG
 	printk(KERN_INFO "Reset posted, waiting...\n");
@@ -1192,7 +1196,7 @@
 	{
 		/* 
 		 * Once the reset is sent, the IOP goes into the INIT state 
-		 * which is inditerminate.  We need to wait until the IOP 
+		 * which is indeterminate.  We need to wait until the IOP 
 		 * has rebooted before we can let the system talk to 
 		 * it. We read the inbound Free_List until a message is 
 		 * available.  If we can't read one in the given ammount of 
@@ -1230,6 +1234,7 @@
 	u32 m;
 	u32 *msg;
 	u8 *status_block;
+	int i;
 
 #ifdef DRIVERDEBUG
 	printk(KERN_INFO "Getting status block for iop%d\n", c->unit);
@@ -1238,7 +1243,7 @@
 		kfree(c->status_block);
 
 	c->status_block = 
-		(pi2o_status_block)kmalloc(sizeof(i2o_status_block),GFP_KERNEL);
+		(i2o_status_block *)kmalloc(sizeof(i2o_status_block),GFP_KERNEL);
 	if(c->status_block == NULL)
 	{
 #ifdef DRIVERDEBUG
@@ -1248,45 +1253,53 @@
 	}
 
 	status_block = (u8*)c->status_block;
+	
+	for(i=0;i<5;i++)
+	{
+		m=i2o_wait_message(c, "StatusGet");
+		if(m==0xFFFFFFFF)
+			return -ETIMEDOUT;
+		
+		memset(status_block, 0, sizeof(i2o_status_block));
+	
+		msg=(u32 *)(c->mem_offset+m);
 
-	m=i2o_wait_message(c, "StatusGet");
-	if(m==0xFFFFFFFF)
-		return -ETIMEDOUT;
-
-	msg=(u32 *)(c->mem_offset+m);
-
-	msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_0;
-	msg[1]=I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID;
-	msg[2]=core_context;
-	msg[3]=0;
-	msg[4]=0;
-	msg[5]=0;
-	msg[6]=virt_to_phys(c->status_block);
-	msg[7]=0;	/* 64bit host FIXME */
-	msg[8]=88;
-
-	i2o_post_message(c,m);
+		__raw_writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_0, &msg[0]);
+		__raw_writel(I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID, &msg[1]);
+		__raw_writel(0, &msg[2]);
+	 	__raw_writel(0, &msg[3]);
+	 	__raw_writel(0, &msg[4]);
+	 	__raw_writel(0, &msg[5]);
+		__raw_writel(virt_to_bus(c->status_block), &msg[6]);
+		__raw_writel(0, &msg[7]);	/* 64bit host FIXME */
+		__raw_writel(sizeof(i2o_status_block), &msg[8]);
+		
+		printk("SB is %d bytes.\n", sizeof(i2o_status_block));
 
-	/* Wait for a reply */
-	time=jiffies;
+		i2o_post_message(c,m);
+		
+		/* DPT work around */
+		mdelay(5);
 
-	while(status_block[87]!=0xFF)
-	{
-		if((jiffies-time)>=5*HZ)
+		/* Wait for a reply */
+		time=jiffies;
+	
+		while((jiffies-time)<=HZ)
 		{
+			if(status_block[87]!=0)
+			{
+				/* Ok the reply has arrived. Fill in the important stuff */
+				c->inbound_size = (status_block[12]|(status_block[13]<<8))*4;
+				return 0;
+			}
+			schedule();
+			barrier();
+		}
 #ifdef DRIVERDEBUG
-			printk(KERN_ERR "IOP get status timeout.\n");
+		printk(KERN_ERR "IOP get status timeout.\n");
 #endif
-			return -ETIMEDOUT;
-		}
-		schedule();
-		barrier();
 	}
-	
-	/* Ok the reply has arrived. Fill in the important stuff */
-	c->inbound_size = (status_block[12]|(status_block[13]<<8))*4;
-
-	return 0;
+	return 0;//-ETIMEDOUT;
 }
 
 
@@ -1354,7 +1367,7 @@
  */
 static void __init i2o_sys_init()
 {
-	struct i2o_controller *iop;
+	struct i2o_controller *iop, *niop;
 	int ret;
 	u32 m;
 
@@ -1362,18 +1375,30 @@
 	printk(KERN_INFO "This may take a few minutes if there are many devices\n");
 
 	/* Get the status for each IOP */
-	for(iop = i2o_controller_chain; iop; iop = iop->next)
+	for(iop = i2o_controller_chain; iop; iop = niop)
 	{
+		niop = iop->next;
 #ifdef DRIVERDEBUG
 		printk(KERN_INFO "Getting initial status for iop%d\n", iop->unit);
 #endif
-		i2o_status_get(iop);
+		if(i2o_status_get(iop)<0)
+		{
+			printk("Unable to obtain status of IOP, attempting a reset.\n");
+			i2o_reset_controller(iop);
+			if(i2o_status_get(iop)<0)
+			{
+				printk("IOP not responding.\n");
+				i2o_delete_controller(iop);
+				continue;
+			}
+		}
 
 		if(iop->status_block->iop_state == ADAPTER_STATE_FAULTED)
 		{
 			printk(KERN_CRIT "i2o: iop%d has hardware fault\n",
 					iop->unit);
 			i2o_delete_controller(iop);
+			continue;
 		}
 
 		if(iop->status_block->iop_state == ADAPTER_STATE_HOLD ||
@@ -1384,7 +1409,7 @@
 			int msg[256];
 
 #ifdef DRIVERDEBUG
-			printk(KERN_INFO "iop%d already running...trying to reboot",
+			printk(KERN_INFO "iop%d already running...trying to reboot\n",
 					iop->unit);
 #endif
 			i2o_init_outbound_q(iop);
@@ -1396,6 +1421,7 @@
 			{
 				printk(KERN_CRIT "Failed to initialize iop%d\n", iop->unit);
 				i2o_delete_controller(iop);
+				continue;
 			}
 		}
 	}
@@ -1403,9 +1429,11 @@
 	/*
 	 * Now init the outbound queue for each one.
 	 */
-	for(iop = i2o_controller_chain; iop; iop = iop->next)
+	for(iop = i2o_controller_chain; iop; iop = niop)
 	{
 		int i;
+		
+		niop = iop->next;
 
 		if((ret=i2o_init_outbound_q(iop)))
 		{
@@ -1413,6 +1441,7 @@
 				"IOP%d initialization failed: Could not initialize outbound q\n",
 				iop->unit);
 			i2o_delete_controller(iop);
+			continue;
 		}
 		iop->page_frame = kmalloc(MSG_POOL_SIZE, GFP_KERNEL);
 
@@ -1438,18 +1467,20 @@
 	/*
 	 * OK..parse the HRT
 	 */
-	for(iop = i2o_controller_chain; iop; iop = iop->next)
+	for(iop = i2o_controller_chain; iop; iop = niop)
 	{
+		niop = iop->next;
 		if(i2o_hrt_get(iop))
 		{
 			printk(KERN_CRIT "iop%d: Could not get HRT!\n", iop->unit);
 			i2o_delete_controller(iop);
-			break;
+			continue;
 		}
 		if(i2o_parse_hrt(iop))
 		{
 			printk(KERN_CRIT "iop%d: Could not parse HRT!\n", iop->unit);
 			i2o_delete_controller(iop);
+			continue;
 		}
 	}
 
@@ -1466,15 +1497,17 @@
 		return;
 	}
 
-	for(iop = i2o_controller_chain; iop; iop = iop->next)
+	for(iop = i2o_controller_chain; iop; iop = niop)
 #ifdef DRIVERDEBUG
 	{
+		niop = iop->next;
 		printk(KERN_INFO "Sending system table to iop%d\n", iop->unit);
 #endif
 		if(i2o_systab_send(iop))
 		{
 			printk(KERN_CRIT "iop%d: Error sending system table\n", iop->unit);
 			i2o_delete_controller(iop);
+			continue;
 		}
 #ifdef DRIVERDEBUG
 	}
@@ -1483,8 +1516,9 @@
 	/*
 	 * Enable
 	 */
-	for(iop = i2o_controller_chain; iop; iop = iop->next)
+	for(iop = i2o_controller_chain; iop; iop = niop)
 	{
+		niop = iop->next;
 #ifdef DRIVERDEBUG
 		printk(KERN_INFO "Enableing iop%d\n", iop->unit);
 #endif
@@ -1492,14 +1526,16 @@
 		{
 			printk(KERN_ERR "Could not enable iop%d\n", iop->unit);
 			i2o_delete_controller(iop);
+			continue;
 		}
 	}
 
 	/*
 	 * OK..one last thing and we're ready to go!
 	 */
-	for(iop = i2o_controller_chain; iop; iop = iop->next)
+	for(iop = i2o_controller_chain; iop; iop = niop)
 	{
+		niop = iop->next;
 #ifdef DRIVERDEBUG
 		printk(KERN_INFO "Getting LCT for iop%d\n", iop->unit);
 #endif
@@ -1507,6 +1543,7 @@
 		{
 			printk(KERN_ERR "Could not get LCT from iop%d\n", iop->unit);
 			i2o_delete_controller(iop);
+			continue;
 		}
 		else	
 			i2o_parse_lct(iop);
@@ -1667,7 +1704,7 @@
 	msg[4]= 4096;			/* Host page frame size */
 	msg[5]= MSG_FRAME_SIZE<<16|0x80;	/* Outbound msg frame size and Initcode */
 	msg[6]= 0xD0000004;		/* Simple SG LE, EOB */
-	msg[7]= virt_to_phys(workspace);
+	msg[7]= virt_to_bus(workspace);
 	*((u32 *)workspace)=0;
 
 	/*
@@ -1685,7 +1722,6 @@
 		{
 			printk(KERN_ERR "i2o/iop%d: IOP outbound initialise failed.\n",
 						c->unit);
-			kfree(workspace);
 			return -ETIMEDOUT;
 		}
 		schedule();
@@ -2419,7 +2455,7 @@
 	case I2O_CMD_UTIL_DEVICE_RELEASE:
 		printk("UTIL_DEVICE_RELEASE, ");
 		break;
-	case I2O_CMD_UTIL_ACK:
+	case I2O_CMD_UTIL_EVT_ACK:
 		printk("UTIL_EVENT_ACKNOWLEDGE, ");
 		break;
 	case I2O_CMD_UTIL_EVT_REGISTER:
diff -u --recursive --new-file v2.3.26/linux/drivers/i2o/i2o_lan.c linux/drivers/i2o/i2o_lan.c
--- v2.3.26/linux/drivers/i2o/i2o_lan.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/i2o/i2o_lan.c	Wed Nov 10 09:52:18 1999
@@ -1,7 +1,7 @@
 /*
  *	linux/drivers/i2o/i2o_lan.c
  *
- * 	I2O LAN CLASS OSM 	Prototyping, September 17th 1999
+ * 	I2O LAN CLASS OSM 	Prototyping, November 8th 1999
  *
  *	(C) Copyright 1999 	University of Helsinki,
  *				Department of Computer Science
@@ -11,7 +11,7 @@
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
  *	as published by the Free Software Foundation; either version
- *	2 of the License, or (at your option) any later version.    
+ *	2 of the License, or (at your option) any later version.
  *
  *	Authors: 	Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
  *			Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
@@ -20,9 +20,7 @@
  *	Tested:		in FDDI environment (using SysKonnect's DDM)
  *			in Ethernet environment (using Intel 82558 DDM proto)
  *
- *	TODO:		batch mode networking
- *			- we've not been able to test batch replies and 
- *			  batch receives
+ *	TODO:		batch mode sends
  *			error checking / timeouts
  *			code / test for other LAN classes
  */
@@ -39,6 +37,7 @@
 #include <linux/trdevice.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
+#include <linux/tqueue.h>
 #include <asm/io.h>
 
 #include <linux/errno.h>
@@ -46,68 +45,65 @@
 #include <linux/i2o.h>
 #include "i2o_lan.h"
 
-//#define DRIVERDEBUG
+#define DRIVERDEBUG
 #ifdef DRIVERDEBUG
 #define dprintk(s, args...) printk(s, ## args)
 #else
 #define dprintk(s, args...)
 #endif
 
-#define MAX_LAN_CARDS 4
+/* Module params */
+
+static u32 bucketpost   = I2O_BUCKET_COUNT;
+static u32 bucketthresh = I2O_BUCKET_THRESH;
+static u32 rx_copybreak = 200;
+
+#define MAX_LAN_CARDS 16
 static struct net_device *i2o_landevs[MAX_LAN_CARDS+1];
 static int unit = -1; 			/* device unit number */
 
 struct i2o_lan_local {
 	u8 unit;
 	struct i2o_device *i2o_dev;
-	int reply_flag; 		/* needed by scalar/table queries */
-	struct fddi_statistics stats;   /* see also struct net_device_stats */ 
+	struct fddi_statistics stats;   /* see also struct net_device_stats */
 	unsigned short (*type_trans)(struct sk_buff *, struct net_device *);
-	/* 
-	 * Due to way that interrupts can pile up, we need to keep track
- 	 * of buckets ourselves.  Otherwise we'll end up flooding
-	 * the DDM with buckets.
-	 */
-	u32	bucket_count;
-
-   /*
-    * Keep track of no. of outstanding TXes
-    */
-   u32   tx_count;
-   u32   max_tx;
-   u32   tx_full;
-
-   spinlock_t lock;
+	u32 bucket_count;  		/* nbr of buckets sent to DDM */
+	u32 tx_count; 	  		/* nbr of outstanding TXes */
+	u32 max_tx;	   		/* DDM's Tx queue len */
 
+	spinlock_t lock;
 };
 
-/* function prototypes */
+static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop,
+                          struct i2o_message *m); 
+static void i2o_lan_event_reply(struct net_device *dev, u32 *msg); 
 static int i2o_lan_receive_post(struct net_device *dev, u32 count);
 static int i2o_lan_receive_post_reply(struct net_device *dev, u32 *msg);
 static void i2o_lan_release_buckets(struct net_device *dev, u32 *msg);
 
-/*
- * Module params
- */
-static u32 bucketpost = I2O_BUCKET_COUNT;
-static u32 bucketthresh = I2O_BUCKET_THRESH;
-static u32 rx_copybreak = 200;
+static struct i2o_handler i2o_lan_handler = {
+	i2o_lan_reply,
+	"I2O Lan OSM",
+	0,              // context
+	I2O_CLASS_LAN
+};
+static int lan_context;  
 
-static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop, 
+
+static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop,
 			  struct i2o_message *m)
-{  
+{
 	u32 *msg = (u32 *)m;
 	u8 unit  = (u8)(msg[2]>>16); // InitiatorContext
 	struct net_device *dev = i2o_landevs[unit];
 
-    	if (msg[0] & (1<<13)) // Fail bit is set
- 	{
- 		printk(KERN_ERR "IOP failed to process the msg:\n");
+    	if (msg[0] & (1<<13)) { // Fail bit is set
+ 		printk(KERN_ERR "%s: IOP failed to process the msg:\n",dev->name);
 		printk(KERN_ERR "  Cmd = 0x%02X, InitiatorTid = %d, TargetTid = %d\n",
 			(msg[1] >> 24) & 0xFF, (msg[1] >> 12) & 0xFFF, msg[1] & 0xFFF);
 		printk(KERN_ERR "  FailureCode = 0x%02X\n  Severity = 0x%02X\n  "
 			"LowestVersion = 0x%02X\n  HighestVersion = 0x%02X\n",
-			 msg[4] >> 24, (msg[4] >> 16) & 0xFF, 
+			 msg[4] >> 24, (msg[4] >> 16) & 0xFF,
 			(msg[4] >> 8) & 0xFF, msg[4] & 0xFF);
 		printk(KERN_ERR "  FailingHostUnit = 0x%04X\n  FailingIOP = 0x%03X\n",
 			msg[5] >> 16, msg[5] & 0xFFF);
@@ -115,23 +111,21 @@
 	}	
 
 #ifndef DRIVERDEBUG
-	if (msg[4] >> 24) 	/* ReqStatus != SUCCESS */
+	if (msg[4] >> 24)  	/* ReqStatus != SUCCESS */
 #endif
 		i2o_report_status(KERN_INFO, dev->name, msg);
-
+	
 	switch (msg[1] >> 24) {
 	case LAN_RECEIVE_POST: 
 	{
-		if (dev->start)
-		{
-			if(!(msg[4]>>24))
-			{
+		if (dev->start) {
+			if(!(msg[4]>>24)) {
 				i2o_lan_receive_post_reply(dev,msg);
 				break;
 			}
 
 			// Something VERY wrong if this is happening
-			printk( KERN_WARNING "i2olan: Device %s rejected bucket post\n", dev->name);
+			printk( KERN_WARNING "i2olan: Device %s rejected bucket post.\n", dev->name);
 		}
 
 		// Getting unused buckets back
@@ -146,15 +140,16 @@
 		struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;	
 		u8 trl_count  = msg[3] & 0x000000FF; 	
 		
-		do { 	// The HDM has handled the outgoing packet
+		while (trl_count) {	
+	  		// The HDM has handled the outgoing packet
 			dev_kfree_skb((struct sk_buff *)msg[4 + trl_count]);
-			dprintk(KERN_INFO "%s: Request skb freed (trl_count=%d).\n",
+			printk(KERN_INFO "%s: Request skb freed (trl_count=%d).\n",
 				dev->name,trl_count);
 			priv->tx_count--;
-		} while (--trl_count);
+			trl_count--;
+		}
 		
-		if(dev->tbusy)
-		{
+		if (dev->tbusy) {
 			clear_bit(0,(void*)&dev->tbusy);
 			mark_bh(NET_BH); /* inform upper layers */
 		}
@@ -162,45 +157,135 @@
 		break;	
 	}
 
-	default: 
-		if (msg[2] & 0x80000000)  // reply to a UtilParamsGet/Set
-		{	
-	   		int *flag = (int *)msg[3]; // flag for i2o_post_wait
-			if (msg[4] >> 24) // ReqStatus != SUCCESS
-	     	 		*flag = -(msg[4] & 0xFFFF); // DetailedStatus
-	     		else
-	     			*flag = I2O_POST_WAIT_OK;
-	     	}
+	case LAN_RESET:
+	case LAN_SUSPEND:
+		break;
+
+	case I2O_CMD_UTIL_EVT_REGISTER:
+        case I2O_CMD_UTIL_EVT_ACK:
+        	i2o_lan_event_reply(dev, msg);
+        	break;
+
+	default:
+		printk(KERN_ERR "%s: Sorry, no handler for the reply.\n", dev->name);
+		i2o_report_status(KERN_INFO, dev->name, msg);		
 	}
 }
 
+
+static void i2o_lan_event_reply(struct net_device *dev, u32 *msg)
+{
+        struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
+        struct i2o_device *i2o_dev = priv->i2o_dev;
+        struct i2o_controller *iop = i2o_dev->controller;
+        struct i2o_reply {
+                u8  version_offset;
+                u8  msg_flags;
+                u16 msg_size;
+                u32 tid:12;
+                u32 initiator:12;
+                u32 function:8;
+                u32 initiator_context;
+                u32 transaction_context;
+                u32 evt_indicator;
+                u32 evt_data[(iop->inbound_size - 20) / 4];     /* max */
+        } *evt = (struct i2o_reply *)msg;
+
+        int evt_data_len = (evt->msg_size - 5) * 4;             /* real */
+
+        if (evt->function == I2O_CMD_UTIL_EVT_REGISTER) {
+                printk(KERN_INFO "%s: I2O event - ", dev->name);
+
+                switch (evt->evt_indicator) {
+                        case I2O_EVT_IND_STATE_CHANGE:
+                                printk("State chance 0x%08X.\n",
+                                        evt->evt_data[0]);
+                                break;
+                        case I2O_EVT_IND_GENERAL_WARNING:
+                                printk("General warning 0x%02X.\n",
+                                        evt->evt_data[0]);
+                                break;
+                        case I2O_EVT_IND_CONFIGURATION_FLAG:
+                                printk("Configuration requested.\n");
+                                break;
+                        case I2O_EVT_IND_LOCK_RELEASE:
+                                printk("Lock released.\n");
+                                break;
+                        case I2O_EVT_IND_CAPABILITY_CHANGE:
+                                printk("Capability change 0x%02X.\n",
+                                        evt->evt_data[0]);
+                                break;
+                        case I2O_EVT_IND_DEVICE_RESET:
+                                printk("Device reset.\n");
+                                break;                            
+                        case I2O_EVT_IND_EVT_MASK_MODIFIED:
+                                printk("Event mask modified, 0x%08X.\n",
+                                        evt->evt_data[0]);
+                                break;
+                        case I2O_EVT_IND_FIELD_MODIFIED: {
+                                u16 *work16 = (u16 *)evt->evt_data;
+                                printk("Group 0x%04X, field %d changed.\n",
+                                        work16[0], work16[1]);
+                                break;
+                        }
+                        case I2O_EVT_IND_VENDOR_EVT: {
+                                int i;
+                                printk("Vendor event:\n");
+                                for (i = 0; i < evt_data_len / 4; i++)
+                                        printk("   0x%08X\n", evt->evt_data[i]);
+                                break;
+                        }
+                        case I2O_EVT_IND_DEVICE_STATE:
+                                printk("Device state changed 0x%08X.\n",
+                                        evt->evt_data[0]);
+                                break;
+                        case I2O_LAN_EVT_LINK_DOWN:
+                                printk("Link to the physical device is lost.\n");
+                                break;
+                        case I2O_LAN_EVT_LINK_UP:
+                                printk("Link to the physical device is (re)established.\n");
+                                break;
+                        case I2O_LAN_EVT_MEDIA_CHANGE:
+                                printk("Media change.\n");
+                                break;
+                        default:
+                                printk("Event Indicator = 0x%08X.\n",
+                                        evt->evt_indicator);
+                }
+
+                /*
+                 * EventAck necessary only for events that cause the device
+                 * to syncronize with the user
+                 *
+                 *if (i2o_event_ack(iop, i2o_dev->lct_data->tid,
+                 *               priv->unit << 16 | lan_context,
+                 *               evt->evt_indicator,
+                 *               evt->evt_data, evt_data_len) < 0)
+                 *       printk("%s: Event Acknowledge timeout.\n", dev->name);
+                 */
+        }
+
+        /* else evt->function == I2O_CMD_UTIL_EVT_ACK) */
+        /* Do we need to do something here too? */
+}   
+
+
 void i2o_lan_release_buckets(struct net_device *dev, u32 *msg)
 {
 	struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;	
 	u8 trl_count  = (u8)(msg[3] & 0x000000FF); 	
 	u32 *pskb = &msg[6];
-	
-	while (trl_count) 
-	{	
-		dprintk("%s: Releasing unused sk_buff %p\n",dev->name, 
+
+	while (trl_count) {	
+		dprintk("%s: Releasing unused sk_buff %p.\n",dev->name,
 			(struct sk_buff*)(*pskb));
-		dev_kfree_skb((struct sk_buff*)(*pskb)); 
+		dev_kfree_skb((struct sk_buff*)(*pskb));
 		pskb++;
 		priv->bucket_count--;
 		trl_count--;
 	}
 }
 
-static struct i2o_handler i2o_lan_handler =
-{
-	i2o_lan_reply,
-	"I2O Lan OSM",
-	0,		// context
-	I2O_CLASS_LAN
-};
-static int lan_context;
-
-
 static int i2o_lan_receive_post_reply(struct net_device *dev, u32 *msg)
 {
 	struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
@@ -210,25 +295,21 @@
 	u8 trl_count  = msg[3] & 0x000000FF; 	
 	struct sk_buff *skb, *newskb;
 
-static int n_calls = 0;
-n_calls++;
-
 #if 0
 	dprintk(KERN_INFO "TrlFlags = 0x%02X, TrlElementSize = %d, TrlCount = %d\n"
-		"msgsize = %d, buckets_remaining = %d\n", 
+		"msgsize = %d, buckets_remaining = %d\n",
 		msg[3]>>24, msg[3]&0x0000FF00, trl_count, msg[0]>>16, msg[5]);	
 #endif
-
-	while (trl_count--)
-	{
+	while (trl_count--) {
 		skb = (struct sk_buff *)(bucket->context);		
 		packet = (struct i2o_packet_info *)bucket->packet_info;	
 		priv->bucket_count--;
 
+#if 0
 		dprintk(KERN_INFO "Buckets_remaining = %d, bucket_count = %d, trl_count = %d\n",
 			msg[5], priv->bucket_count, trl_count);
-#if 0
-		dprintk(KERN)INFO "flags = 0x%02X, offset = 0x%06X, status = 0x%02X, length = %d\n",
+
+		dprintk(KERN_INFO "flags = 0x%02X, offset = 0x%06X, status = 0x%02X, length = %d\n",
 			packet->flags, packet->offset, packet->status, packet->len);
 #endif
 		if (packet->len < rx_copybreak) {
@@ -241,15 +322,15 @@
 				newskb->protocol = priv->type_trans(newskb, dev);
 
 				netif_rx(newskb);
-				dev_kfree_skb(skb); // FIXME: reuse this skb? 
+				dev_kfree_skb(skb); // FIXME: reuse this skb?
 			}
 			else {
-				printk("I2OLAN-%s: Can't allocate skb.\n", dev->name);
+				printk("%s: Can't allocate skb.\n", dev->name);
 				return -ENOMEM;
 			}
 		} else {
 			skb_put(skb,packet->len);		
-			skb->dev  = dev;		
+			skb->dev = dev;		
 			skb->protocol = priv->type_trans(skb, dev);
 
 			netif_rx(skb);
@@ -260,20 +341,17 @@
 		bucket++; // to next Packet Descriptor Block
 	}
 
-	if (priv->bucket_count < bucketpost - bucketthresh)
-		i2o_lan_receive_post(dev, bucketpost - priv->bucket_count);
-
 	if ((msg[4] & 0x000000FF) == I2O_LAN_DSC_BUCKET_OVERRUN)
-	{
-		printk(KERN_INFO "%s: DDM out of buckets (count = %d)! "
-			 "Number of posts = %d\n", dev->name, msg[5], n_calls);
-		n_calls = 0;
-	}
+		printk(KERN_INFO "%s: DDM out of buckets (count = %d)!\n",
+			 dev->name, msg[5]);
+	
+	if (priv->bucket_count <= bucketpost - bucketthresh)
+		i2o_lan_receive_post(dev, bucketpost - priv->bucket_count);
 
 	return 0;
 }
 
-/* 
+/*
  * i2o_lan_receive_post(): Post buckets to receive packets.
  */
 static int i2o_lan_receive_post(struct net_device *dev, u32 count)
@@ -289,14 +367,12 @@
 	int n_elems = (iop->inbound_size - 16 ) / 12; /* msg header + SGLs */
 	u32 total = 0;
 	int i;
-
-	while (total < count)
-	{
+	
+	while (total < count) {
 		m = I2O_POST_READ32(iop);
 		if (m == 0xFFFFFFFF)
 			return -ETIMEDOUT;		
-		msg = bus_to_virt(iop->mem_offset + m);
-
+		msg = (u32 *)(iop->mem_offset + m);
 		bucket_count = (total + n_elems < count)
 			     ? n_elems
 			     : count - total;
@@ -306,8 +382,7 @@
 		msg[2] = priv->unit << 16 | lan_context; // InitiatorContext	
 		msg[3] = bucket_count;			 // BucketCount
 
-		for (i = 0; i < bucket_count; i++)
-		{
+		for (i = 0; i < bucket_count; i++) {
 			skb = dev_alloc_skb(bucket_len + 2);
 			if (skb == NULL)
 				return -ENOMEM;
@@ -331,11 +406,11 @@
 	return 0;	
 }	
 
-/* 
- * i2o_lan_reset(): Reset the LAN adapter into the operational state and 
+/*
+ * i2o_lan_reset(): Reset the LAN adapter into the operational state and
  * 	restore it to full operation.
  */
-static int i2o_lan_reset(struct net_device *dev) 
+static int i2o_lan_reset(struct net_device *dev)
 {
 	struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;	
 	struct i2o_device *i2o_dev = priv->i2o_dev;
@@ -351,12 +426,12 @@
 	if (i2o_post_this(iop, msg, sizeof(msg)) < 0)
 		return -ETIMEDOUT;		
 
-	return 0; 
+	return 0;
 }
 
-/* 
+/*
  * i2o_lan_suspend(): Put LAN adapter into a safe, non-active state.
- * 	Reply to any LAN class message with status error_no_data_transfer 
+ * 	Reply to any LAN class message with status error_no_data_transfer
  *	/ suspended.
  */
 static int i2o_lan_suspend(struct net_device *dev)
@@ -366,14 +441,14 @@
 	struct i2o_controller *iop = i2o_dev->controller;	
 	u32 msg[5];
 
-	dprintk( "%s: LAN SUSPEND MESSAGE\n", dev->name );
+	dprintk( "%s: LAN SUSPEND MESSAGE.\n", dev->name );
 	msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
 	msg[1] = LAN_SUSPEND<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid;
 	msg[2] = priv->unit << 16 | lan_context; // InitiatorContext
 	msg[3] = 0; 				 // TransactionContext
 	msg[4] = 1 << 16; 			 // return posted buckets
 
-	if (i2o_post_this(iop, msg, sizeof(msg))< 0)
+	if (i2o_post_this(iop, msg, sizeof(msg)) < 0)
 		return -ETIMEDOUT;
 
 	return 0;
@@ -385,9 +460,9 @@
 static void i2o_set_batch_mode(struct net_device *dev)
 {
 
-/* 
+/*
  * NOTE: we have not been able to test batch mode
- * 	 since HDMs we have, don't implement it 
+ * 	 since HDMs we have, don't implement it
  */
 
 	struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;	
@@ -400,11 +475,13 @@
 	// enable batch mode, toggle automatically
 	val = 0x00000000;
 //	val = 0x00000001; // turn off batch mode
-	if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0003, 0, &val, 4) < 0)
-		printk(KERN_WARNING "Unable to enter I2O LAN batch mode.\n");
-	else
+	if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0003, 0, &val, sizeof(val)) <0)
+		printk(KERN_WARNING "%s: Unable to enter I2O LAN batch mode.\n",
+			dev->name);
+	else 
 		dprintk(KERN_INFO "%s: I2O LAN batch mode enabled.\n",dev->name);
 //		dprintk(KERN_INFO "%s: I2O LAN batch mode disabled.\n",dev->name);
+
 	/*
 	 * When PacketOrphanlimit is same as the maximum packet length,
 	 * the packets will never be split into two separate buckets
@@ -413,31 +490,39 @@
 	/* set LAN_OPERATION attributes */
 
 	val = dev->mtu + dev->hard_header_len; // PacketOrphanLimit
-	if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0004, 2, &val, 4))
-		printk(KERN_WARNING "i2o_lan: Unable to set PacketOrphanLimit.\n");
+	if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0004, 2, &val, sizeof(val)) < 0)
+		printk(KERN_WARNING "%s: Unable to set PacketOrphanLimit.\n",
+			dev->name);
 	else
-		dprintk(KERN_INFO "%s: PacketOrphanLimit set to %d\n",
+		dprintk(KERN_INFO "%s: PacketOrphanLimit set to %d.\n",
 			dev->name,val);
-
+	
 	return;	
 }
 
-/* 
- * i2o_lan_open(): Open the device to send/receive packets via 
+/*
+ * i2o_lan_open(): Open the device to send/receive packets via
  * the network device.	
  */
 static int i2o_lan_open(struct net_device *dev)
 {
 	struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;	
-	struct i2o_device *i2o_dev = priv->i2o_dev;	
+	struct i2o_device *i2o_dev = priv->i2o_dev;
+	struct i2o_controller *iop = i2o_dev->controller; 
+	u32 evt_mask =  0xFFC00007; // All generic events, all lan evenst
 
-	if(i2o_claim_device(i2o_dev, &i2o_lan_handler, I2O_CLAIM_PRIMARY))
-	{
+	if (i2o_claim_device(i2o_dev, &i2o_lan_handler, I2O_CLAIM_PRIMARY)) {
 		printk(KERN_WARNING "%s: Unable to claim the I2O LAN device.\n", dev->name);
 		return -EAGAIN;
 	}
-	dprintk(KERN_INFO "%s: I2O LAN device claimed (tid=%d).\n", dev->name, i2o_dev->lct_data->tid);
-
+	dprintk(KERN_INFO "%s: I2O LAN device claimed (tid=%d).\n", 
+		dev->name, i2o_dev->lct_data->tid);
+#if 0
+	if (i2o_event_register(iop, i2o_dev->lct_data->tid,
+				priv->unit << 16 | lan_context, evt_mask) < 0)
+		printk(KERN_WARNING "%s: Unable to set the event mask.\n", 
+			dev->name);
+#endif
 	i2o_lan_reset(dev);
 	
 	dev->tbusy = 0;
@@ -453,19 +538,26 @@
 
 /*
  * i2o_lan_close(): End the transfering.
- */ 
+ */
 static int i2o_lan_close(struct net_device *dev)
 {
 	struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;	
 	struct i2o_device *i2o_dev = priv->i2o_dev;	
+//#if 0
+	struct i2o_controller *iop = i2o_dev->controller; 
 
+	if (i2o_event_register(iop, i2o_dev->lct_data->tid,
+				priv->unit << 16 | lan_context, 0) < 0)
+		printk(KERN_WARNING "%s: Unable to clear the event mask.\n", 
+				dev->name);
+//#endif
 	dev->tbusy = 1;
 	dev->start = 0;
 	i2o_lan_suspend(dev);
 
-	if(i2o_release_device(i2o_dev, &i2o_lan_handler, I2O_CLAIM_PRIMARY))
+	if (i2o_release_device(i2o_dev, &i2o_lan_handler, I2O_CLAIM_PRIMARY))
 		printk(KERN_WARNING "%s: Unable to unclaim I2O LAN device "
-		       "(tid=%d)\n", dev->name, i2o_dev->lct_data->tid);
+		       "(tid=%d).\n", dev->name, i2o_dev->lct_data->tid);
 
 	MOD_DEC_USE_COUNT;
 
@@ -473,9 +565,9 @@
 }
 
 #if 0
-/* 
+/*
  * i2o_lan_sdu_send(): Send a packet, MAC header added by the HDM.
- * Must be supported by Fibre Channel, optional for Ethernet/802.3, 
+ * Must be supported by Fibre Channel, optional for Ethernet/802.3,
  * Token Ring, FDDI
  */
 static int i2o_lan_sdu_send(struct sk_buff *skb, struct net_device *dev)
@@ -484,12 +576,12 @@
 }
 #endif
 
-/* 
+/*
  * i2o_lan_packet_send(): Send a packet as is, including the MAC header.
- * 
- * Must be supported by Ethernet/802.3, Token Ring, FDDI, optional for 
+ *
+ * Must be supported by Ethernet/802.3, Token Ring, FDDI, optional for
  * Fibre Channel
- */ 
+ */
 static int i2o_lan_packet_send(struct sk_buff *skb, struct net_device *dev)
 {
 	struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;	
@@ -498,14 +590,13 @@
 	u32 m, *msg;
 	u32 flags = 0;
 
-	/* 
+	/*
 	 * Keep interrupt from changing dev->tbusy from underneath us
 	 * (Do we really need to do this?)
 	 */
 	spin_lock_irqsave(&priv->lock, flags);
 
-	if(test_and_set_bit(0,(void*)&dev->tbusy) != 0)
-	{
+	if(test_and_set_bit(0,(void*)&dev->tbusy) != 0) {
 		spin_unlock_irqrestore(&priv->lock, flags);
 		return 1;
 	}
@@ -515,9 +606,19 @@
 		spin_unlock_irqrestore(&priv->lock, flags);
 		dev_kfree_skb(skb);
 		return -ETIMEDOUT;
-	}    
-	msg = bus_to_virt(iop->mem_offset + m);
-	
+	}
+	msg = (u32 *)(iop->mem_offset + m);
+
+#if 0
+	__raw_writel(SEVEN_WORD_MSG_SIZE | 1<<12 | SGL_OFFSET_4,&msg[0]);
+	__raw_writel(LAN_PACKET_SEND<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid, &msg[1]);
+	__raw_writel(priv->unit << 16 | lan_context, &msg[2]); // InitiatorContext
+	__raw_writel(1 << 4, &msg[3]); 			// TransmitControlWord
+	__raw_writel(0xD5000000 | skb->len, &msg[4]);	// MAC hdr included
+	__raw_writel((u32)skb, &msg[5]);		// TransactionContext
+	__raw_writel(virt_to_bus(skb->data),&msg[6]);
+#endif
+
 	msg[0] = SEVEN_WORD_MSG_SIZE | 1<<12 | SGL_OFFSET_4;
 	msg[1] = LAN_PACKET_SEND<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid;	
 	msg[2] = priv->unit << 16 | lan_context; // IntiatorContext
@@ -552,8 +653,8 @@
 	u64 val64[16];
 	u64 supported_group[4] = { 0, 0, 0, 0 };
 
-        if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0100, -1, 
-        		 val64, sizeof(val64)) < 0)
+        if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0100, -1, val64, 
+        		     sizeof(val64)) < 0)
         	printk("%s: Unable to query LAN_HISTORICAL_STATS.\n",dev->name);
 	else {
         	dprintk("%s: LAN_HISTORICAL_STATS queried.\n",dev->name);
@@ -566,13 +667,13 @@
 		priv->stats.rx_dropped = val64[6];
 	}
 
-        if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0180, -1, 
+        if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0180, -1,
         		&supported_group, sizeof(supported_group)) < 0)
         	printk("%s: Unable to query LAN_SUPPORTED_OPTIONAL_HISTORICAL_STATS.\n",dev->name);
 
 	if (supported_group[2]) {
-        	if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0183, -1, 
-        	 	val64, sizeof(val64) ) < 0)
+        	if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0183, -1,
+        	 	val64, sizeof(val64)) < 0)
         		printk("%s: Unable to query LAN_OPTIONAL_RX_HISTORICAL_STATS.\n",dev->name);
 		else {
         		dprintk("%s: LAN_OPTIONAL_RX_HISTORICAL_STATS queried.\n",dev->name);
@@ -582,11 +683,10 @@
 		}
 	}
 
-	if (i2o_dev->lct_data->sub_class == I2O_LAN_ETHERNET)
-	{
+	if (i2o_dev->lct_data->sub_class == I2O_LAN_ETHERNET) {
 		u64 supported_stats = 0;		
 
-        	if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0200, -1, 
+        	if (i2o_query_scalar(iop, i2o_dev->lct_data->tid,  0x0200, -1,
         			 val64, sizeof(val64)) < 0)
         		printk("%s: Unable to query LAN_802_3_HISTORICAL_STATS.\n",dev->name);
 		else {
@@ -596,14 +696,15 @@
 			priv->stats.tx_carrier_errors  = val64[6];
 		}
 
-        	if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0280, -1, 
-        			 &supported_stats, 8) < 0)
-        		printk("%s: Unable to query LAN_SUPPORTED_802_3_HISTORICAL_STATS\n", dev->name);
+        	if (i2o_query_scalar(iop, i2o_dev->lct_data->tid,  0x0280, -1,
+        			 &supported_stats, sizeof(supported_stats)) < 0)
+        		printk("%s: Unable to query LAN_SUPPORTED_802_3_HISTORICAL_STATS.\n", dev->name);
 
         	if (supported_stats != 0) {
-        		if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0281, -1, 
+        		if (i2o_query_scalar(iop, i2o_dev->lct_data->tid,  0x0281, -1,
         				 val64, sizeof(val64)) < 0)
-        			printk("%s: Unable to query LAN_OPTIONAL_802_3_HISTORICAL_STATS.\n",dev->name);
+;
+//        			printk("%s: Unable to query LAN_OPTIONAL_802_3_HISTORICAL_STATS.\n",dev->name);
 			else {
         			dprintk("%s: LAN_OPTIONAL_802_3_HISTORICAL_STATS queried.\n",dev->name);
 				if (supported_stats & 0x1)
@@ -616,13 +717,12 @@
 	}
 
 #ifdef CONFIG_TR
-	if (i2o_dev->lct_data->sub_class == I2O_LAN_TR)
-	{
-        	if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0300, -1, 
+	if (i2o_dev->lct_data->sub_class == I2O_LAN_TR) {
+        	if (i2o_query_scalar(iop, i2o_dev->lct_data->tid,  0x0300, -1,
         			 val64, sizeof(val64)) < 0)
         		printk("%s: Unable to query LAN_802_5_HISTORICAL_STATS.\n",dev->name);
 		else {
-			struct tr_statistics *stats = 
+			struct tr_statistics *stats =
 					(struct tr_statistics *)&priv->stats;
 //        		dprintk("%s: LAN_802_5_HISTORICAL_STATS queried.\n",dev->name);
 
@@ -642,9 +742,8 @@
 #endif
 
 #ifdef CONFIG_FDDI
-	if (i2o_dev->lct_data->sub_class == I2O_LAN_FDDI)
-	{
-        	if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0400, -1, 
+	if (i2o_dev->lct_data->sub_class == I2O_LAN_FDDI) {
+        	if (i2o_query_scalar(iop, i2o_dev->lct_data->tid,  0x0400, -1,
         			 val64, sizeof(val64)) < 0)
         		printk("%s: Unable to query LAN_FDDI_HISTORICAL_STATS.\n",dev->name);
 		else {
@@ -666,90 +765,97 @@
 
 	return (struct net_device_stats *)&priv->stats;
 }
- 
+
 /*
- * i2o_lan_set_multicast_list(): Enable a network device to receive packets
- *	not send to the protocol address.
+ * i2o_lan_set_mc_list(): Enable a network device to receive packets
+ *      not send to the protocol address.
  */
-static void i2o_lan_set_multicast_list(struct net_device *dev)
+
+static void i2o_lan_set_mc_list(struct net_device *dev)
 {
-	struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;	
-	struct i2o_device *i2o_dev = priv->i2o_dev;
-	struct i2o_controller *iop = i2o_dev->controller;
-	u32 filter_mask;
-	u32 work32[64];
+        struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
+        struct i2o_device *i2o_dev = priv->i2o_dev;
+        struct i2o_controller *iop = i2o_dev->controller;
+        u32 filter_mask;
+        u32 max_size_mc_table;
+        u32 mc_addr_group[64];
+
+        if (i2o_query_scalar(iop, i2o_dev->lct_data->tid,  0x0001, -1,
+                             &mc_addr_group, sizeof(mc_addr_group)) < 0 ) {
+                printk(KERN_WARNING "%s: Unable to query LAN_MAC_ADDRESS group.\n", dev->name);
+                return;
+        }
 
-	dprintk(KERN_INFO "%s: Entered i2o_lan_set_multicast_list().\n", dev->name);
+        max_size_mc_table = mc_addr_group[8];
 
-return;
+        if (dev->flags & IFF_PROMISC) {
+                filter_mask = 0x00000002;
+                dprintk(KERN_INFO "%s: Enabling promiscuous mode...\n", dev->name);
+        }
 
-/* FIXME: Why does the next call kill the interrupt handler?
- * The same piece of code works fine in function lan_open(), and in i2o_proc.c
- *
- * *because its trying to sleep in an irq - this must be async - Alan
- */
+        else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > max_size_mc_table) {
+                filter_mask = 0x00000004;
+                dprintk(KERN_INFO "%s: Enabling all multicast mode...\n", dev->name);
+        }
 
-	if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0001, -1,
-			     &work32, sizeof(work32)) < 0) 
-	{
-		printk(KERN_WARNING "i2o_lan: Unable to query "
-			" LAN_MAC_ADDRESS table.\n");	
-		return;
-	}
-	printk(KERN_INFO "capab mask = 0x%08X, filter mask = 0x%08X\n",
-		work32[7], work32[6]);
+        else if (dev->mc_count) {
+                struct dev_mc_list *mc;
+		u8 mc_table[2 + 8 * dev->mc_count]; // RowCount, Addresses
+		u64 *work64 = (u64 *)(mc_table + 2);
+
+                filter_mask = 0x00000000;
+                dprintk(KERN_INFO "%s: Enabling multicast mode...\n", dev->name);
+
+                /* Fill multicast addr table */
+
+		memset(mc_table, 0, sizeof(mc_table));
+                memcpy(mc_table, &dev->mc_count, 2);
+                for (mc = dev->mc_list; mc ; mc = mc->next, work64++ )
+                        memcpy(work64, mc->dmi_addr, mc->dmi_addrlen);
+		
+		/* Clear old mc table, copy new table to <iop,tid> */
 
-	filter_mask = work32[6];
+                if (i2o_clear_table(iop, i2o_dev->lct_data->tid,  0x0002) < 0)
+                        printk("%s: Unable to clear LAN_MULTICAST_MAC_ADDRESS table.\n",dev->name);
 
-	if (dev->flags & IFF_PROMISC)
-	{
-		filter_mask |= 0x00000002; 
-		dprintk(KERN_INFO "i2o_lan: Enabling promiscuous mode...\n");
+                if ((i2o_row_add_table(iop, i2o_dev->lct_data->tid,  0x0002, -1,
+                        mc_table, sizeof(mc_table))) < 0)
+                        printk("%s: Unable to set LAN_MULTICAST_MAC_ADDRESS table.\n",dev->name);
         }
-        
- 	else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > work32[5])
- 	{
-		filter_mask |= 0x00000000; 
-		dprintk(KERN_INFO "i2o_lan: Enabling all multicast mode...\n");
-	}
-
-        else if (dev->mc_count)
-	{	
-		struct dev_mc_list *mclist;
-		int i;
-		u8 *work8 = (u8 *)work32;
-
-		dprintk(KERN_INFO "i2o_lan: Enabling multicast mode...\n");
-                filter_mask = 0x00000004; 
-
-		/* Fill the multicast addresses */
-		mclist = dev->mc_list;
-
-		for (i = 0; i < dev->mc_count; i++)
-		{	
-			memcpy(work8, mclist->dmi_addr, mclist->dmi_addrlen);
-			work8 += 8;
-			mclist = mclist->next;
-		} 
-
-		if (i2o_clear_table(iop, i2o_dev->lct_data->tid, 0x0002) < 0)
-			dprintk("%s: Unable to clear LAN_MULTICAST_MAC_ADDRESS table.\n",dev->name);
-
-		if (i2o_row_add_table(iop, i2o_dev->lct_data->tid, 0x0002, -1,
-			work32, dev->mc_count*8) < 0)	
-			dprintk("%s: Unable to set LAN_MULTICAST_MAC_ADDRESS table.\n",dev->name);
-	} 
-	
-	else {
-        	filter_mask |= 0x00000300; // Broadcast, Multicast disabled
-		dprintk(KERN_INFO "i2o_lan: Enabling unicast mode...\n");
+
+        else {	
+                filter_mask = 0x00000300; // Broadcast, Multicast disabled
+                printk(KERN_INFO "%s: Enabling unicast mode...\n",dev->name);
         }
 
-	if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0001, 3,
-			&filter_mask, 4) < 0)
-		printk(KERN_WARNING "i2o_lan: Unable to set MAC FilterMask.\n");
+	/* Finally copy new FilterMask to <iop,tid> */
+
+        if (i2o_set_scalar(iop, i2o_dev->lct_data->tid,  0x0001, 3,
+                        &filter_mask, sizeof(filter_mask)) <0)
+                printk(KERN_WARNING "%s: Unable to set MAC FilterMask.\n",dev->name);
 
-	return;
+        return;
+}
+
+/*
+ * i2o_lan_set_multicast_list():
+ *       Queue routine i2o_lan_set_mc_list() to be called later.
+ *       Needs to be async.
+ */
+
+static void i2o_lan_set_multicast_list(struct net_device *dev)
+{
+        struct tq_struct *task;
+
+        task = (struct tq_struct *)kmalloc(sizeof(struct tq_struct), GFP_KERNEL);
+        if (task == NULL)
+                return;
+
+        task->next = NULL;
+        task->sync = 0;
+        task->routine = (void *)i2o_lan_set_mc_list;
+        task->data = (void *)dev;
+        queue_task(task, &tq_scheduler);
 }
 
 struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
@@ -761,24 +867,21 @@
 	unsigned short (*type_trans)(struct sk_buff *, struct net_device *);
 	void (*unregister_dev)(struct net_device *dev);
 
-	switch (i2o_dev->lct_data->sub_class)
-	{
+	switch (i2o_dev->lct_data->sub_class) {
 	case I2O_LAN_ETHERNET:
-		dev = init_etherdev(NULL, sizeof(struct i2o_lan_local));
+        	dev = init_etherdev(NULL, sizeof(struct i2o_lan_local));
 		if (dev == NULL)
 			return NULL;
 		type_trans = eth_type_trans;
 		unregister_dev = unregister_netdev;
 		break;
 
-
 #ifdef CONFIG_ANYLAN
 	case I2O_LAN_100VG:
-		printk(KERN_ERR "i2o_lan: 100base VG not yet supported\n");
+		printk(KERN_ERR "i2o_lan: 100base VG not yet supported.\n");
 		break;
 #endif
 
-
 #ifdef CONFIG_TR
 	case I2O_LAN_TR:
 		dev = init_trdev(NULL, sizeof(struct i2o_lan_local));
@@ -800,8 +903,7 @@
             	dev->priv = (void *)(dev + 1);
                 dev->name = (char *)(dev + 1) + sizeof(struct i2o_lan_local);
 
-		if (dev_alloc_name(dev,"fddi%d") < 0)
-		{
+		if (dev_alloc_name(dev,"fddi%d") < 0) {
 			printk(KERN_WARNING "i2o_lan: Too many FDDI devices.\n");
 			kfree(dev);
 			return NULL;
@@ -817,13 +919,13 @@
 
 #ifdef CONFIG_FIBRE_CHANNEL
 	case I2O_LAN_FIBRE_CHANNEL:
-		printk(KERN_INFO "i2o_lan: Fibre Channel not yet supported\n");
+		printk(KERN_INFO "i2o_lan: Fibre Channel not yet supported.\n");
 	break;
 #endif
 
 	case I2O_LAN_UNKNOWN:
 	default:
-		printk(KERN_ERR "i2o_lan: LAN type 0x%08X not supported\n",
+		printk(KERN_ERR "i2o_lan: LAN type 0x%08X not supported.\n",
 		       i2o_dev->lct_data->sub_class);
 		return NULL;
 	}
@@ -838,13 +940,12 @@
 	priv->unit = unit;
 
 	if (i2o_query_scalar(i2o_dev->controller, i2o_dev->lct_data->tid,
-			0x0001, 0, &hw_addr, 8) < 0)
-	{
-     	printk(KERN_ERR "%s: Unable to query hardware address.\n", dev->name);
+			     0x0001, 0, &hw_addr, sizeof(hw_addr)) < 0) {
+     		printk(KERN_ERR "%s: Unable to query hardware address.\n", dev->name);
 		unit--;
 		unregister_dev(dev);
 		kfree(dev);
-      		return NULL;  
+      		return NULL;
 	}
 
 	dprintk("%s: hwaddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
@@ -854,18 +955,18 @@
 	dev->addr_len = 6;
 	memcpy(dev->dev_addr, hw_addr, 6);
 
-   if (i2o_query_scalar(i2o_dev->controller, i2o_dev->lct_data->tid,
-         0x0007, 2, &max_tx, 4) < 0)
-   {
-      printk(KERN_ERR "%s: Unable to query max TX queue.\n", dev->name);
-      unit--;
-      unregister_dev(dev);
-      kfree(dev);
-         return NULL;
-   }
-   printk(KERN_INFO "%s: Max TX Outstanding = %d\n", dev->name, max_tx);
-   priv->max_tx = max_tx;
-   priv->tx_count = 0;
+	if (i2o_query_scalar(i2o_dev->controller, i2o_dev->lct_data->tid,
+         	0x0007, 2, &max_tx, sizeof(max_tx)) < 0) 
+	{
+      		printk(KERN_ERR "%s: Unable to query max TX queue.\n", dev->name);
+      		unit--;
+      		unregister_dev(dev);
+      		kfree(dev);
+         	return NULL;
+	}
+   	dprintk(KERN_INFO "%s: Max TX Outstanding = %d.\n", dev->name, max_tx);
+   	priv->max_tx = max_tx;
+   	priv->tx_count = 0;
 
 	priv->lock = SPIN_LOCK_UNLOCKED;
 
@@ -887,43 +988,41 @@
 	struct net_device *dev;
 	int i;
 
-	if (i2o_install_handler(&i2o_lan_handler) < 0)
-	{
- 		printk(KERN_ERR "Unable to register I2O LAN OSM.\n");
+	printk(KERN_INFO "Linux I2O LAN OSM (c) 1999 University of Helsinki.\n");
+ 
+	if (i2o_install_handler(&i2o_lan_handler) < 0) {
+ 		printk(KERN_ERR "i2o_lan: Unable to register I2O LAN OSM.\n");
 		return -EINVAL;
-	}   
+	}
 	lan_context = i2o_lan_handler.context;
 	
 	for(i=0; i <= MAX_LAN_CARDS; i++)
 		i2o_landevs[i] = NULL;
 
-	for (i=0; i < MAX_I2O_CONTROLLERS; i++)
-	{
+	for (i=0; i < MAX_I2O_CONTROLLERS; i++) {
 		struct i2o_controller *iop = i2o_find_controller(i);
 		struct i2o_device *i2o_dev;
 
-		if (iop==NULL)
-			continue;
+		if (iop==NULL) continue;
+
+		for (i2o_dev=iop->devices;i2o_dev != NULL;i2o_dev=i2o_dev->next) {
 
-		for (i2o_dev=iop->devices;i2o_dev != NULL;i2o_dev=i2o_dev->next)
-		{
-			if (i2o_dev->lct_data->class_id != I2O_CLASS_LAN) 
+			if (i2o_dev->lct_data->class_id != I2O_CLASS_LAN)
 				continue;
 
-			if(i2o_dev->lct_data->user_tid != 0xFFF)
+			/* Make sure device not already claimed by an ISM */
+			if (i2o_dev->lct_data->user_tid != 0xFFF)
 				continue;
 
-			if (unit == MAX_LAN_CARDS)
-			{
+			if (unit == MAX_LAN_CARDS) {
 				i2o_unlock_controller(iop);
-				printk(KERN_WARNING "Too many I2O LAN devices.\n");
+				printk(KERN_WARNING "i2o_lan: Too many I2O LAN devices.\n");
 				return -EINVAL;
 			}
 
 			dev = i2o_lan_register_device(i2o_dev);
- 			if (dev == NULL)
-			{
-				printk(KERN_ERR "Unable to register I2O LAN device\n");
+ 			if (dev == NULL) {
+				printk(KERN_ERR "i2o_lan: Unable to register I2O LAN device.\n");
 				continue; // try next one
 			}
 
@@ -947,14 +1046,12 @@
 {
 	int i;
 
-	for (i = 0; i <= unit; i++)
-	{
+	for (i = 0; i <= unit; i++) {
 		struct net_device *dev = i2o_landevs[i];
 		struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;	
 		struct i2o_device *i2o_dev = priv->i2o_dev;	
 
-		switch (i2o_dev->lct_data->sub_class)
-		{
+		switch (i2o_dev->lct_data->sub_class) {
 		case I2O_LAN_ETHERNET:
 			unregister_netdev(dev);
 			kfree(dev);
@@ -976,11 +1073,11 @@
 			       i2o_dev->lct_data->sub_class);
 		}
 
-		dprintk(KERN_INFO "%s: I2O LAN device unregistered.\n", 
+		dprintk(KERN_INFO "%s: I2O LAN device unregistered.\n",
 			dev->name);
 	}
 
-        i2o_remove_handler(&i2o_lan_handler);
+	i2o_remove_handler(&i2o_lan_handler);
 }
 
 EXPORT_NO_SYMBOLS;
@@ -992,4 +1089,4 @@
 MODULE_PARM(bucketthresh, "i"); // Bucket post threshold
 MODULE_PARM(rx_copybreak, "i");
 
-#endif    
+#endif
diff -u --recursive --new-file v2.3.26/linux/drivers/i2o/i2o_lan.h linux/drivers/i2o/i2o_lan.h
--- v2.3.26/linux/drivers/i2o/i2o_lan.h	Mon Oct  4 15:49:29 1999
+++ linux/drivers/i2o/i2o_lan.h	Wed Nov 10 09:52:18 1999
@@ -18,7 +18,7 @@
 /* Tunable parameters first */
 
 #define I2O_BUCKET_COUNT 	256
-#define I2O_BUCKET_THRESH	16
+#define I2O_BUCKET_THRESH	8
 
 /* LAN types */
 #define I2O_LAN_ETHERNET	0x0030
@@ -108,5 +108,11 @@
 	u32 context; 			/* FIXME: 64bit support */
 	struct i2o_packet_info packet_info[1];
 };
+
+/* Event Indicator Mask Flags for LAN OSM */
+
+#define I2O_LAN_EVT_LINK_DOWN		0x01
+#define I2O_LAN_EVT_LINK_UP		0x02
+#define I2O_LAN_EVT_MEDIA_CHANGE 	0x04
  
 #endif /* _I2O_LAN_H */
diff -u --recursive --new-file v2.3.26/linux/drivers/i2o/i2o_pci.c linux/drivers/i2o/i2o_pci.c
--- v2.3.26/linux/drivers/i2o/i2o_pci.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/i2o/i2o_pci.c	Wed Nov 10 09:52:18 1999
@@ -5,11 +5,11 @@
  *	(C) Copyright 1999   Red Hat Software
  *	
  *	Written by Alan Cox, Building Number Three Ltd
- *	Modified by Deepak Saxena <deepak@plexity.net>
+ * 	Modified by Deepak Saxena <deepak@plexity.net>
  *
  *	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
+ * 	as published by the Free Software Foundation; either version
  *	2 of the License, or (at your option) any later version.
  *
  *	TODO:
@@ -120,7 +120,7 @@
 
 	if(c==NULL)
 	{
-		printk(KERN_ERR "i2o_pci: insufficient memory to add controller.\n");
+		printk(KERN_ERR "i2o: Insufficient memory to add controller.\n");
 		return -ENOMEM;
 	}
 	memset(c, 0, sizeof(*c));
@@ -137,7 +137,7 @@
 	
 	if(i==6)
 	{
-		printk(KERN_ERR "i2o_pci: I2O controller has no memory regions defined.\n");
+		printk(KERN_ERR "i2o: I2O controller has no memory regions defined.\n");
 		kfree(c);
 		return -EINVAL;
 	}
@@ -145,11 +145,11 @@
 	size = dev->resource[i].end-dev->resource[i].start+1;	
 	/* Map the I2O controller */
 	
-	printk(KERN_INFO "PCI I2O controller at 0x%08X size=%d\n", memptr, size);
+	printk(KERN_INFO "i2o: PCI I2O controller at 0x%08X size=%d\n", memptr, size);
 	mem = ioremap(memptr, size);
 	if(mem==NULL)
 	{
-		printk(KERN_ERR "i2o_pci: Unable to map controller.\n");
+		printk(KERN_ERR "i2o: Unable to map controller.\n");
 		kfree(c);
 		return -EINVAL;
 	}
@@ -189,7 +189,7 @@
 	
 	if(i<0)
 	{
-		printk(KERN_ERR "i2o: unable to install controller.\n");
+		printk(KERN_ERR "i2o: Unable to install controller.\n");
 		kfree(c);
 		iounmap(mem);
 		return i;
@@ -216,7 +216,7 @@
 		}
 	}
 
-	printk(KERN_INFO "Installed iop%d at IRQ%d\n", c->unit, dev->irq);
+	printk(KERN_INFO "%s: Installed at IRQ%d\n", c->name, dev->irq);
 	I2O_IRQ_WRITE32(c,0x0);
 	c->enabled = 1;
 	return 0;	
@@ -227,7 +227,7 @@
 	struct pci_dev *dev;
 	int count=0;
 	
-	printk(KERN_INFO "Checking for PCI I2O controllers...\n");
+	printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n");
 	
 	for(dev=pci_devices; dev!=NULL; dev=dev->next)
 	{
@@ -235,17 +235,17 @@
 			continue;
 		if((dev->class&0xFF)>1)
 		{
-			printk(KERN_INFO "I2O controller found but does not support I2O 1.5 (skipping).\n");
+			printk(KERN_INFO "i2o: I2O Controller found but does not support I2O 1.5 (skipping).\n");
 			continue;
 		}
-		printk(KERN_INFO "I2O controller on bus %d at %d.\n",
+		printk(KERN_INFO "i2o: I2O controller on bus %d at %d.\n",
 			dev->bus->number, dev->devfn);
 		pci_set_master(dev);
 		if(i2o_pci_install(dev)==0)
 			count++;
 	}
 	if(count)
-		printk(KERN_INFO "%d I2O controller%s found and installed.\n", count,
+		printk(KERN_INFO "i2o: %d I2O controller%s found and installed.\n", count,
 			count==1?"":"s");
 	return count?count:-ENODEV;
 }
@@ -270,7 +270,7 @@
 		if(i2o_activate_controller(c))
 #endif /* MODULE */
 		{
-			printk("I2O: Failed to initialize iop%d\n", c->unit);
+			printk("%s: Failed to initialize.\n", c->name);
 #ifdef MODULE
 			core->unlock(c);
 			core->delete(c);
diff -u --recursive --new-file v2.3.26/linux/drivers/i2o/i2o_proc.c linux/drivers/i2o/i2o_proc.c
--- v2.3.26/linux/drivers/i2o/i2o_proc.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/i2o/i2o_proc.c	Wed Nov 10 09:52:18 1999
@@ -51,9 +51,6 @@
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 
-
-#include "i2o_proc.h"
-
 #include "i2o_lan.h"
 
 /*
@@ -69,24 +66,34 @@
 
 static int proc_context = 0;
 
-
 static int i2o_proc_read_lct(char *, char **, off_t, int, int *, void *);
 static int i2o_proc_read_hrt(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_stat(char *, char **, off_t, int, int *, void *);
+static int i2o_proc_read_status(char *, char **, off_t, int, int *, void *);
+
 static int i2o_proc_read_hw(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_dst(char *, char **, off_t, int, int *, void *);
 static int i2o_proc_read_ddm_table(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_ds(char *, char **, off_t, int, int *, void *);
+static int i2o_proc_read_driver_store(char *, char **, off_t, int, int *, void *);
+static int i2o_proc_read_drivers_stored(char *, char **, off_t, int, int *, void *);
+
 static int i2o_proc_read_groups(char *, char **, off_t, int, int *, void *);
+static int i2o_proc_read_phys_device(char *, char **, off_t, int, int *, void *);
+static int i2o_proc_read_claimed(char *, char **, off_t, int, int *, void *);
+static int i2o_proc_read_users(char *, char **, off_t, int, int *, void *);
 static int i2o_proc_read_priv_msgs(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_dev(char *, char **, off_t, int, int *, void *);
+static int i2o_proc_read_authorized_users(char *, char **, off_t, int, int *, void *);
+
 static int i2o_proc_read_dev_name(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_ddm(char *, char **, off_t, int, int *, void *);
+static int i2o_proc_read_dev_identity(char *, char **, off_t, int, int *, void *);
+static int i2o_proc_read_ddm_identity(char *, char **, off_t, int, int *, void *);
 static int i2o_proc_read_uinfo(char *, char **, off_t, int, int *, void *);
 static int i2o_proc_read_sgl_limits(char *, char **, off_t, int, int *, void *);
+
+static int i2o_proc_read_sensors(char *, char **, off_t, int, int *, void *);
+
 static int print_serial_number(char *, int, u8 *, int);
-static int i2o_proc_create_entries(void *, 
-				   i2o_proc_entry *, struct proc_dir_entry *);
+
+static int i2o_proc_create_entries(void *, i2o_proc_entry *,
+				   struct proc_dir_entry *);
 static void i2o_proc_remove_entries(i2o_proc_entry *, struct proc_dir_entry *);
 static int i2o_proc_add_controller(struct i2o_controller *, 
 				   struct proc_dir_entry * );
@@ -117,18 +124,8 @@
 				     void *);
 static int i2o_proc_read_lan_hist_stats(char *, char **, off_t, int, int *,
 					void *);
-static int i2o_proc_read_lan_supp_opt_stats(char *, char **, off_t, int, int *,
-					    void *);
-static int i2o_proc_read_lan_opt_tx_hist_stats(char *, char **, off_t, int,
-					       int *, void *);
-static int i2o_proc_read_lan_opt_rx_hist_stats(char *, char **, off_t, int,
-					       int *, void *);
 static int i2o_proc_read_lan_eth_stats(char *, char **, off_t, int,
 				       int *, void *);
-static int i2o_proc_read_lan_supp_eth_stats(char *, char **, off_t, int, int *,
-					    void *);
-static int i2o_proc_read_lan_opt_eth_stats(char *, char **, off_t, int, int *,
-					   void *);
 static int i2o_proc_read_lan_tr_stats(char *, char **, off_t, int, int *,
 				      void *);
 static int i2o_proc_read_lan_fddi_stats(char *, char **, off_t, int, int *,
@@ -155,11 +152,11 @@
 {
 	{"hrt", S_IFREG|S_IRUGO, i2o_proc_read_hrt, NULL},
 	{"lct", S_IFREG|S_IRUGO, i2o_proc_read_lct, NULL},
-	{"stat", S_IFREG|S_IRUGO, i2o_proc_read_stat, NULL},
+	{"status", S_IFREG|S_IRUGO, i2o_proc_read_status, NULL},
 	{"hw", S_IFREG|S_IRUGO, i2o_proc_read_hw, NULL},
-	{"dst", S_IFREG|S_IRUGO, i2o_proc_read_dst, NULL},
 	{"ddm_table", S_IFREG|S_IRUGO, i2o_proc_read_ddm_table, NULL},
-	{"ds", S_IFREG|S_IRUGO, i2o_proc_read_ds, NULL},
+	{"driver_store", S_IFREG|S_IRUGO, i2o_proc_read_driver_store, NULL},
+	{"drivers_stored", S_IFREG|S_IRUGO, i2o_proc_read_drivers_stored, NULL},
 	{NULL, 0, NULL, NULL}
 };
 
@@ -169,11 +166,16 @@
 static i2o_proc_entry generic_dev_entries[] = 
 {
 	{"groups", S_IFREG|S_IRUGO, i2o_proc_read_groups, NULL},
+	{"phys_dev", S_IFREG|S_IRUGO, i2o_proc_read_phys_device, NULL},
+	{"claimed", S_IFREG|S_IRUGO, i2o_proc_read_claimed, NULL},
+	{"users", S_IFREG|S_IRUGO, i2o_proc_read_users, NULL},
 	{"priv_msgs", S_IFREG|S_IRUGO, i2o_proc_read_priv_msgs, NULL},
-	{"dev_identity", S_IFREG|S_IRUGO, i2o_proc_read_dev, NULL},
-	{"ddm_identity", S_IFREG|S_IRUGO, i2o_proc_read_ddm, NULL},
-	{"sgl_limits", S_IFREG|S_IRUGO, i2o_proc_read_sgl_limits, NULL},
+	{"authorized_users", S_IFREG|S_IRUGO, i2o_proc_read_authorized_users, NULL},
+	{"dev_identity", S_IFREG|S_IRUGO, i2o_proc_read_dev_identity, NULL},
+	{"ddm_identity", S_IFREG|S_IRUGO, i2o_proc_read_ddm_identity, NULL},
 	{"user_info", S_IFREG|S_IRUGO, i2o_proc_read_uinfo, NULL},
+	{"sgl_limits", S_IFREG|S_IRUGO, i2o_proc_read_sgl_limits, NULL},
+	{"sensors", S_IFREG|S_IRUGO, i2o_proc_read_sensors, NULL},
 	{NULL, 0, NULL, NULL}
 };
 
@@ -187,22 +189,22 @@
 };
 
 #define SCSI_TABLE_SIZE	13
-	static char *scsi_devices[] = 
-		{
-			"Direct-Access Read/Write",
-			"Sequential-Access Storage",
-			"Printer",
-			"Processor",
-			"WORM Device",
-			"CD-ROM Device",
-			"Scanner Device",
-			"Optical Memory Device",
-			"Medium Changer Device",
-			"Communications Device",
-			"Graphics Art Pre-Press Device",
-			"Graphics Art Pre-Press Device",
-			"Array Controller Device"
-		};
+static char *scsi_devices[] = 
+{
+	"Direct-Access Read/Write",
+	"Sequential-Access Storage",
+	"Printer",
+	"Processor",
+	"WORM Device",
+	"CD-ROM Device",
+	"Scanner Device",
+	"Optical Memory Device",
+	"Medium Changer Device",
+	"Communications Device",
+	"Graphics Art Pre-Press Device",
+	"Graphics Art Pre-Press Device",
+	"Array Controller Device"
+};
 
 /* private */
 
@@ -214,7 +216,6 @@
  */
 static i2o_proc_entry lan_entries[] = 
 {
-	/* LAN param groups 0000h-0008h */
 	{"lan_dev_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_dev_info, NULL},
 	{"lan_mac_addr", S_IFREG|S_IRUGO, i2o_proc_read_lan_mac_addr, NULL},
 	{"lan_mcast_addr", S_IFREG|S_IRUGO|S_IWUSR,
@@ -227,56 +228,30 @@
 	{"lan_alt_addr", S_IFREG|S_IRUGO, i2o_proc_read_lan_alt_addr, NULL},
 	{"lan_tx_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_tx_info, NULL},
 	{"lan_rx_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_rx_info, NULL},
-	/* LAN param groups 0100h, 0180h, 0182h, 0183h */
-	{"lan_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_hist_stats, NULL},
-	{"lan_supp_opt_stats", S_IFREG|S_IRUGO,
-	 i2o_proc_read_lan_supp_opt_stats, NULL},
-	{"lan_opt_tx_stats", S_IFREG|S_IRUGO,
-	 i2o_proc_read_lan_opt_tx_hist_stats, NULL},
-	{"lan_opt_rx_stats", S_IFREG|S_IRUGO,
-	 i2o_proc_read_lan_opt_rx_hist_stats, NULL},
-	/* TODO: LAN param group 0184h */
+
+	{"lan_hist_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_hist_stats, NULL},
 	{NULL, 0, NULL, NULL}
 };
 
 /*
- * Ethernet specific LAN entries
+ * Port specific LAN entries
  * 
  */
 static i2o_proc_entry lan_eth_entries[] = 
 {
-	/* LAN param groups 0200h, 0280h, 0281h */
-	{"lan_eth_stat", S_IFREG|S_IRUGO, i2o_proc_read_lan_eth_stats, NULL},
-        {"lan_supp_eth_stats", S_IFREG|S_IRUGO,
-	 i2o_proc_read_lan_supp_eth_stats, NULL},
-        {"lan_opt_eth_stats", S_IFREG|S_IRUGO,
-	 i2o_proc_read_lan_opt_eth_stats, NULL},
+	{"lan_eth_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_eth_stats, NULL},
 	{NULL, 0, NULL, NULL}
 };
 
-/*
- * Token Ring specific LAN entries
- * 
- */
 static i2o_proc_entry lan_tr_entries[] = 
 {
-	/* LAN param group 0300h */
-	{"lan_tr_stats", S_IFREG|S_IRUGO,
-	 i2o_proc_read_lan_tr_stats, NULL},
-	/* TODO: LAN param group 0380h, 0381h */
+	{"lan_tr_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_tr_stats, NULL},
 	{NULL, 0, NULL, NULL}
 };
 
-/*
- * FDDI specific LAN entries
- * 
- */
 static i2o_proc_entry lan_fddi_entries[] = 
 {
-	/* LAN param group 0400h */
-	{"lan_fddi_stats", S_IFREG|S_IRUGO,
-	 i2o_proc_read_lan_fddi_stats, NULL},
-	/* TODO: LAN param group 0480h, 0481h */
+	{"lan_fddi_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_fddi_stats, NULL},
 	{NULL, 0, NULL, NULL}
 };
 
@@ -290,6 +265,22 @@
         return strncat(tmp, (char *)chars, n);
 }
 
+static int i2o_report_query_status(char *buf, int block_status, char *group)
+{
+	switch (block_status)
+	{
+	case -ETIMEDOUT:
+		return sprintf(buf, "Timeout reading group %s.\n",group);
+	case -ENOMEM:
+		return sprintf(buf, "No free memory to read the table.\n");
+	case -I2O_PARAMS_STATUS_INVALID_GROUP_ID:
+		return sprintf(buf, "Group %s not supported.\n", group);
+	default:
+		return sprintf(buf, "Error reading group %s. BlockStatus 0x%02X\n",
+			       group, -block_status);
+	}
+}
+
 static char* bus_strings[] = 
 { 
 	"Local Bus", 
@@ -314,7 +305,7 @@
 		      int *eof, void *data)
 {
 	struct i2o_controller *c = (struct i2o_controller *)data;
-	pi2o_hrt hrt = (pi2o_hrt)c->hrt;
+	i2o_hrt *hrt = (i2o_hrt *)c->hrt;
 	u32 bus;
 	int count;
 	int i;
@@ -342,17 +333,15 @@
 	}
 	
 	len += sprintf(buf+len, "HRT has %d entries of %d bytes each.\n",
-		       count, hrt->entry_len);
+		       count, hrt->entry_len << 2);
 
 	for(i = 0; i < count; i++)
 	{
 		len += sprintf(buf+len, "Entry %d:\n", i);
 		len += sprintf(buf+len, "   Adapter ID: %0#10x\n", 
 					hrt->hrt_entry[i].adapter_id);
-		len += sprintf(buf+len, "   Controlled by: %0#6x\n",
+		len += sprintf(buf+len, "   Controlling tid: %0#6x\n",
 					hrt->hrt_entry[i].parent_tid);
-		len += sprintf(buf+len, "   Bus#%d\n", 
-					hrt->hrt_entry[i].bus_num);
 
 		if(hrt->hrt_entry[i].bus_type != 0x80)
 		{
@@ -425,20 +414,19 @@
 	int *eof, void *data)
 {
 	struct i2o_controller *c = (struct i2o_controller*)data;
-	pi2o_lct lct = (pi2o_lct)c->lct;
+	i2o_lct *lct = (i2o_lct *)c->lct;
 	int entries;
 	int i;
 
 #define BUS_TABLE_SIZE 3
 	static char *bus_ports[] =
-		{
-			"Generic Bus",
-			"SCSI Bus",
-			"Fibre Channel Bus"
-		};
+	{
+		"Generic Bus",
+		"SCSI Bus",
+		"Fibre Channel Bus"
+	};
 
 	spin_lock(&i2o_proc_lock);
-
 	len = 0;
 
 	entries = (lct->table_size - 3)/9;
@@ -451,8 +439,7 @@
 	for(i = 0; i < entries; i++)
 	{
 		len += sprintf(buf+len, "Entry %d\n", i);
-
-		len += sprintf(buf+len, "  %s", i2o_get_class_name(lct->lct_entry[i].class_id));
+		len += sprintf(buf+len, "  Class, SubClass  : %s", i2o_get_class_name(lct->lct_entry[i].class_id));
 	
 		/*
 		 *	Classes which we'll print subclass info for
@@ -463,23 +450,23 @@
 				switch(lct->lct_entry[i].sub_class)
 				{
 					case 0x00:
-						len += sprintf(buf+len, ": Direct-Access Read/Write");
+						len += sprintf(buf+len, ", Direct-Access Read/Write");
 						break;
 
 					case 0x04:
-						len += sprintf(buf+len, ": WORM Drive");
+						len += sprintf(buf+len, ", WORM Drive");
 						break;
 	
 					case 0x05:
-						len += sprintf(buf+len, ": CD-ROM Drive");
+						len += sprintf(buf+len, ", CD-ROM Drive");
 						break;
 
 					case 0x07:
-						len += sprintf(buf+len, ": Optical Memory Device");
+						len += sprintf(buf+len, ", Optical Memory Device");
 						break;
 
 					default:
-						len += sprintf(buf+len, ": Unknown (0x%02x)",
+						len += sprintf(buf+len, ", Unknown (0x%02x)",
 							       lct->lct_entry[i].sub_class);
 						break;
 				}
@@ -489,27 +476,27 @@
 				switch(lct->lct_entry[i].sub_class & 0xFF)
 				{
 					case 0x30:
-						len += sprintf(buf+len, ": Ethernet");
+						len += sprintf(buf+len, ", Ethernet");
 						break;
 
 					case 0x40:
-						len += sprintf(buf+len, ": 100base VG");
+						len += sprintf(buf+len, ", 100base VG");
 						break;
 
 					case 0x50:
-						len += sprintf(buf+len, ": IEEE 802.5/Token-Ring");
+						len += sprintf(buf+len, ", IEEE 802.5/Token-Ring");
 						break;
 
 					case 0x60:
-						len += sprintf(buf+len, ": ANSI X3T9.5 FDDI");
+						len += sprintf(buf+len, ", ANSI X3T9.5 FDDI");
 						break;
 		
 					case 0x70:
-						len += sprintf(buf+len, ": Fibre Channel");
+						len += sprintf(buf+len, ", Fibre Channel");
 						break;
 
 					default:
-						len += sprintf(buf+len, ": Unknown Sub-Class (0x%02x)",
+						len += sprintf(buf+len, ", Unknown Sub-Class (0x%02x)",
 							       lct->lct_entry[i].sub_class & 0xFF);
 						break;
 				}
@@ -517,27 +504,27 @@
 
 			case I2O_CLASS_SCSI_PERIPHERAL:
 				if(lct->lct_entry[i].sub_class < SCSI_TABLE_SIZE)
-					len += sprintf(buf+len, ": %s", 
+					len += sprintf(buf+len, ", %s", 
 								scsi_devices[lct->lct_entry[i].sub_class]);
 				else
-					len += sprintf(buf+len, ": Unknown Device Type");
+					len += sprintf(buf+len, ", Unknown Device Type");
 				break;
 
 			case I2O_CLASS_BUS_ADAPTER_PORT:
 				if(lct->lct_entry[i].sub_class < BUS_TABLE_SIZE)
-					len += sprintf(buf+len, ": %s", 
+					len += sprintf(buf+len, ", %s", 
 								bus_ports[lct->lct_entry[i].sub_class]);
 				else
-					len += sprintf(buf+len, ": Unknown Bus Type");
+					len += sprintf(buf+len, ", Unknown Bus Type");
 				break;
 		}
 		len += sprintf(buf+len, "\n");
 		
-		len += sprintf(buf+len, "  Local TID: 0x%03x\n", lct->lct_entry[i].tid);
-		len += sprintf(buf+len, "  User TID: 0x%03x\n", lct->lct_entry[i].user_tid);
-		len += sprintf(buf+len, "  Parent TID: 0x%03x\n", 
+		len += sprintf(buf+len, "  Local TID        : 0x%03x\n", lct->lct_entry[i].tid);
+		len += sprintf(buf+len, "  User TID         : 0x%03x\n", lct->lct_entry[i].user_tid);
+		len += sprintf(buf+len, "  Parent TID       : 0x%03x\n", 
 					lct->lct_entry[i].parent_tid);
-		len += sprintf(buf+len, "  Identity Tag: 0x%x%x%x%x%x%x%x%x\n",
+		len += sprintf(buf+len, "  Identity Tag     : 0x%x%x%x%x%x%x%x%x\n",
 					lct->lct_entry[i].identity_tag[0],
 					lct->lct_entry[i].identity_tag[1],
 					lct->lct_entry[i].identity_tag[2],
@@ -546,219 +533,211 @@
 					lct->lct_entry[i].identity_tag[5],
 					lct->lct_entry[i].identity_tag[6],
 					lct->lct_entry[i].identity_tag[7]);
-		len += sprintf(buf+len, "  Change Indicator: %0#10x\n", 
+		len += sprintf(buf+len, "  Change Indicator : %0#10x\n", 
 				lct->lct_entry[i].change_ind);
-		len += sprintf(buf+len, "  Device Flags: %0#10x\n", 
+		len += sprintf(buf+len, "  Event Capab Mask : %0#10x\n", 
 				lct->lct_entry[i].device_flags);
 	}
 
 	spin_unlock(&i2o_proc_lock);
-	
 	return len;
 }
 
-int i2o_proc_read_stat(char *buf, char **start, off_t offset, int len, 
-	int *eof, void *data)
+int i2o_proc_read_status(char *buf, char **start, off_t offset, int len, 
+			 int *eof, void *data)
 {
 	struct i2o_controller *c = (struct i2o_controller*)data;
-	u32 *msg;
-	u32 m;
-	u8 *workspace;
-	u16 *work16;
-	u32 *work32;
-	long time;
 	char prodstr[25];
 	int version;
 	
 	spin_lock(&i2o_proc_lock);
-
 	len = 0;
 
-	workspace = (u8*)kmalloc(88, GFP_KERNEL);
-	if(!workspace)
-	{
-		len += sprintf(buf, "No memory for status transfer\n");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-
-	m = I2O_POST_READ32(c);
-	if(m == 0xFFFFFFFF)
-	{
-		len += sprintf(buf, "Could not get inbound message frame from IOP!\n");	
-		kfree(workspace);
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-	
-	msg = (u32 *)(m+c->mem_offset);
-
-	memset(workspace, 0, 88);
-	work32 = (u32*)workspace;
-	work16 = (u16*)workspace;
-
-	msg[0] = NINE_WORD_MSG_SIZE|SGL_OFFSET_0;
-	msg[1] = I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID;
-	msg[2] = msg[3] = msg[4] = msg[5] = 0;
-	msg[6] = virt_to_phys(workspace);
-	msg[7] = 0; /* FIXME: 64-bit */
-	msg[8] = 88;
-
-	/* 
-	 * hmm...i2o_post_message should just take ptr to message, and 
-	 * determine offset on it's own...less work for OSM developers
-	 */
-	i2o_post_message(c, m);
-
-	time = jiffies;
-
-	while(workspace[87] != 0xFF)
-	{
-		if(jiffies-time >= 2*HZ)
-		{
-			len += sprintf(buf, "Timeout waiting for status reply\n");
-			kfree(workspace);
-			spin_unlock(&i2o_proc_lock);
-			return len;
-		}
-		schedule();
-		barrier();
-	}
+	i2o_status_get(c); // reread the status block
 
-	len += sprintf(buf+len, "Organization ID: %0#6x\n", work16[0]);
+	len += sprintf(buf+len,"Organization ID        : %0#6x\n", 
+				c->status_block->org_id);
 
-	version = workspace[9]&0xF0>>4;
-	if(version == 0x02) {
-		len += sprintf(buf+len, "Lowest I2O version supported: ");
+	version = c->status_block->i2o_version;
+	
+/* FIXME for Spec 2.0
+	if (version == 0x02) {
+		len += sprintf(buf+len,"Lowest I2O version supported: ");
 		switch(workspace[2]) {
-		case 0x00:
-			len += sprintf(buf+len, "1.0\n");
-			break;
-		case 0x01:
-			len += sprintf(buf+len, "1.5\n");
-			break;
-		case 0x02:
-			len += sprintf(buf+len, "2.0\n");
-			break;
+			case 0x00:
+				len += sprintf(buf+len,"1.0\n");
+				break;
+			case 0x01:
+				len += sprintf(buf+len,"1.5\n");
+				break;
+			case 0x02:
+				len += sprintf(buf+len,"2.0\n");
+				break;
 		}
 
 		len += sprintf(buf+len, "Highest I2O version supported: ");
 		switch(workspace[3]) {
+			case 0x00:
+				len += sprintf(buf+len,"1.0\n");
+				break;
+			case 0x01:
+				len += sprintf(buf+len,"1.5\n");
+				break;
+			case 0x02:
+				len += sprintf(buf+len,"2.0\n");
+				break;
+		}
+	}
+*/
+	len += sprintf(buf+len,"IOP ID                 : %0#5x\n", 
+				c->status_block->iop_id);
+	len += sprintf(buf+len,"Host Unit ID           : %0#6x\n",
+				c->status_block->host_unit_id);
+	len += sprintf(buf+len,"Segment Number         : %0#5x\n",
+				c->status_block->segment_number);
+
+	len += sprintf(buf+len, "I2O version            : ");
+	switch (version) {
 		case 0x00:
-			len += sprintf(buf+len, "1.0\n");
+			len += sprintf(buf+len,"1.0\n");
 			break;
 		case 0x01:
-			len += sprintf(buf+len, "1.5\n");
+			len += sprintf(buf+len,"1.5\n");
 			break;
 		case 0x02:
-			len += sprintf(buf+len, "2.0\n");
+			len += sprintf(buf+len,"2.0\n");
 			break;
-		}
-	}
-
-	len += sprintf(buf+len, "IOP ID: %0#5x\n", work16[2]&0xFFF);
-	len += sprintf(buf+len, "Host Unit ID: %0#6x\n", work16[3]);
-	len += sprintf(buf+len, "Segment Number: %0#5x\n", work16[4]&0XFFF);
-
-	len += sprintf(buf+len, "I2O version: ");
-	switch(version)
-	{
-	case 0x00:
-		len += sprintf(buf+len, "1.0\n");
-		break;
-	case 0x01:
-		len += sprintf(buf+len, "1.5\n");
-		break;
-	case 0x02:
-		len += sprintf(buf+len, "2.0\n");
-		break;
-	default:
-		len += sprintf(buf+len, "Unknown version\n");
+		default:
+			len += sprintf(buf+len,"Unknown version\n");
 	}
 
-	len += sprintf(buf+len, "IOP State: ");
-	switch(workspace[10])
-	{
+	len += sprintf(buf+len, "IOP State              : ");
+	switch (c->status_block->iop_state) {
 		case 0x01:
-			len += sprintf(buf+len, "Init\n");
+			len += sprintf(buf+len,"INIT\n");
 			break;
 
 		case 0x02:
-			len += sprintf(buf+len, "Reset\n");
+			len += sprintf(buf+len,"RESET\n");
 			break;
 
 		case 0x04:
-			len += sprintf(buf+len, "Hold\n");
+			len += sprintf(buf+len,"HOLD\n");
 			break;
 
 		case 0x05:
-			len += sprintf(buf+len, "Hold\n");
+			len += sprintf(buf+len,"READY\n");
 			break;
 
 		case 0x08:
-			len += sprintf(buf+len, "Operational\n");
+			len += sprintf(buf+len,"OPERATIONAL\n");
 			break;
 
 		case 0x10:
-			len += sprintf(buf+len, "FAILED\n");
+			len += sprintf(buf+len,"FAILED\n");
 			break;
 
 		case 0x11:
-			len += sprintf(buf+len, "FAULTED\n");
+			len += sprintf(buf+len,"FAULTED\n");
 			break;
 
 		default:
-			len += sprintf(buf+len, "Unknown\n");
+			len += sprintf(buf+len,"Unknown\n");
 			break;
 	}
 
-	/* 0x00 is the only type supported w/spec 1.5 */
-	/* Added 2.0 types */
-	len += sprintf(buf+len, "Messenger Type: ");
-	switch (workspace[11])
-	{
-	case 0x00:
-		len += sprintf(buf+len, "Memory mapped\n");
-		break;
-	case 0x01:
-		len += sprintf(buf+len, "Memory mapped only\n");
-		break;
-	case 0x02:
-		len += sprintf(buf+len, "Remote only\n");
-		break;
-	case 0x03:
-		len += sprintf(buf+len, "Memory mapped and remote\n");
-		break;
-	default:
-		len += sprintf(buf+len, "Unknown\n");
-		break;
+	len += sprintf(buf+len,"Messenger Type         : ");
+	switch (c->status_block->msg_type) { 
+		case 0x00:
+			len += sprintf(buf+len,"Memory mapped\n");
+			break;
+		case 0x01:
+			len += sprintf(buf+len,"Memory mapped only\n");
+			break;
+		case 0x02:
+			len += sprintf(buf+len,"Remote only\n");
+			break;
+		case 0x03:
+			len += sprintf(buf+len,"Memory mapped and remote\n");
+			break;
+		default:
+			len += sprintf(buf+len,"Unknown\n");
 	}
-	len += sprintf(buf+len, "Inbound Frame Size: %d bytes\n", work16[6]*4);
-	len += sprintf(buf+len, "Max Inbound Frames: %d\n", work32[4]);
-	len += sprintf(buf+len, "Current Inbound Frames: %d\n", work32[5]);
-	len += sprintf(buf+len, "Max Outbound Frames: %d\n", work32[6]);
+
+	len += sprintf(buf+len,"Inbound Frame Size     : %d bytes\n", 
+				c->status_block->inbound_frame_size<<2);
+	len += sprintf(buf+len,"Max Inbound Frames     : %d\n", 
+				c->status_block->max_inbound_frames);
+	len += sprintf(buf+len,"Current Inbound Frames : %d\n", 
+				c->status_block->cur_inbound_frames);
+	len += sprintf(buf+len,"Max Outbound Frames    : %d\n", 
+				c->status_block->max_outbound_frames);
 
 	/* Spec doesn't say if NULL terminated or not... */
-	memcpy(prodstr, work32+7, 24);
+	memcpy(prodstr, c->status_block->product_id, 24);
 	prodstr[24] = '\0';
-	len += sprintf(buf+len, "Product ID: %s\n", prodstr);
-
-	len += sprintf(buf+len, "LCT Size: %d\n", work32[13]);
-
-	len += sprintf(buf+len, "Desired private memory space: %d kB\n", 
-						work32[15]>>10);
-	len += sprintf(buf+len, "Allocated private memory space: %d kB\n", 
-						work32[16]>>10);
-	len += sprintf(buf+len, "Private memory base address: %0#10x\n", 
-						work32[17]);
-	len += sprintf(buf+len, "Desired private I/O space: %d kB\n", 
-						work32[18]>>10);
-	len += sprintf(buf+len, "Allocated private I/O space: %d kB\n", 
-						work32[19]>>10);
-	len += sprintf(buf+len, "Private I/O base address: %0#10x\n", 
-						work32[20]);
+	len += sprintf(buf+len,"Product ID             : %s\n", prodstr);
+	len += sprintf(buf+len,"Expected LCT Size      : %d bytes\n", 
+				c->status_block->expected_lct_size);
+
+	len += sprintf(buf+len,"IOP Capabilities\n");
+	len += sprintf(buf+len,"   Context Field Size Support : ");
+	switch (c->status_block->iop_capabilities & 0x0000003) {
+		case 0:
+			len += sprintf(buf+len,"Supports only 32-bit context fields\n");
+			break;
+		case 1:
+			len += sprintf(buf+len,"Supports only 64-bit context fields\n");
+			break;
+		case 2:
+			len += sprintf(buf+len,"Supports 32-bit and 64-bit context fields, "
+						"but not concurrently\n");
+			break;
+		case 3:
+			len += sprintf(buf+len,"Supports 32-bit and 64-bit context fields "
+						"concurrently\n");
+			break;
+		default:
+			len += sprintf(buf+len,"0x%08x\n",c->status_block->iop_capabilities);
+	}
+	len += sprintf(buf+len,"   Current Context Field Size : ");
+	switch (c->status_block->iop_capabilities & 0x0000000C) {
+		case 0:
+			len += sprintf(buf+len,"not configured\n");
+			break;
+		case 4:
+			len += sprintf(buf+len,"Supports only 32-bit context fields\n");
+			break;
+		case 8:
+			len += sprintf(buf+len,"Supports only 64-bit context fields\n");
+			break;
+		case 12:
+			len += sprintf(buf+len,"Supports both 32-bit or 64-bit context fields "
+						"concurrently\n");
+			break;
+		default:
+			len += sprintf(buf+len,"\n");
+	}
+	len += sprintf(buf+len,"   Inbound Peer Support       : %s\n",
+			(c->status_block->iop_capabilities & 0x00000010) ? "Supported" : "Not supported");
+	len += sprintf(buf+len,"   Outbound Peer Support      : %s\n",
+			(c->status_block->iop_capabilities & 0x00000020) ? "Supported" : "Not supported");
+	len += sprintf(buf+len,"   Peer to Peer Support       : %s\n",
+			(c->status_block->iop_capabilities & 0x00000040) ? "Supported" : "Not supported");
+
+	len += sprintf(buf+len, "Desired private memory size   : %d kB\n", 
+				c->status_block->desired_mem_size>>10);
+	len += sprintf(buf+len, "Allocated private memory size : %d kB\n", 
+				c->status_block->current_mem_size>>10);
+	len += sprintf(buf+len, "Private memory base address   : %0#10x\n", 
+				c->status_block->current_mem_base);
+	len += sprintf(buf+len, "Desired private I/O size      : %d kB\n", 
+				c->status_block->desired_io_size>>10);
+	len += sprintf(buf+len, "Allocated private I/O size    : %d kB\n", 
+				c->status_block->current_io_size>>10);
+	len += sprintf(buf+len, "Private I/O base address      : %0#10x\n", 
+				c->status_block->current_io_base);
 
-	kfree(workspace);
 	spin_unlock(&i2o_proc_lock);
 
 	return len;
@@ -790,25 +769,25 @@
 
 	len = 0;
 
-	token = i2o_query_scalar(c, ADAPTER_TID,
-					0,		// ParamGroup 0x0000h
-					-1,		// all fields
-					&work32,
-					sizeof(work32));
+	token = i2o_query_scalar(c, ADAPTER_TID, 0x0000, -1, &work32, sizeof(work32));
 
-	if(token < 0)
-	{
-		len += sprintf(buf, "Error waiting for reply from IOP\n");
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0x0000 IOP Hardware");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
 
-	len += sprintf(buf, "IOP Hardware Information Table (group = 0x0000)\n");
-
-	len += sprintf(buf+len, "I2O Vendor ID        : %0#6x\n", work16[0]);
-	len += sprintf(buf+len, "Product ID           : %0#6x\n", work16[1]);
-	len += sprintf(buf+len, "RAM                  : %dkB\n", work32[1]>>10);
-	len += sprintf(buf+len, "Non-Volatile Storage : %dkB\n", work32[2]>>10);
+	len += sprintf(buf+len, "I2O Vendor ID    : %0#6x\n", work16[0]);
+	len += sprintf(buf+len, "Product ID       : %0#6x\n", work16[1]);
+	len += sprintf(buf+len, "CPU              : ");
+	if(work8[16] > 8)
+		len += sprintf(buf+len, "Unknown\n");
+	else
+		len += sprintf(buf+len, "%s\n", cpu_table[work8[16]]);
+	/* Anyone using ProcessorVersion? */
+	
+	len += sprintf(buf+len, "RAM              : %dkB\n", work32[1]>>10);
+	len += sprintf(buf+len, "Non-Volatile Mem : %dkB\n", work32[2]>>10);
 
 	hwcap = work32[3];
 	len += sprintf(buf+len, "Capabilities :\n");
@@ -823,13 +802,6 @@
 	if(hwcap&0x00000010)
 		len += sprintf(buf+len, "   Battery-backed RAM\n");
 
-	len += sprintf(buf+len, "CPU                 : ");
-	if(work8[16] > 8)
-		len += sprintf(buf+len, "Unknown\n");
-	else
-		len += sprintf(buf+len, "%s\n", cpu_table[work8[16]]);
-	/* Anyone using ProcessorVersion? */
-	
 	spin_unlock(&i2o_proc_lock);
 
 	return len;
@@ -850,11 +822,10 @@
 		u8  reserved;
 		u16 i2o_vendor_id;
 		u16 module_id;
-		u8  module_name[24];
-		u8  module_version[4];
+		u8  module_name_version[28];
 		u32 data_size;
 		u32 code_size;
-	} i2o_exec_execute_ddm_table, *pi2o_exec_execute_ddm_table;
+	} i2o_exec_execute_ddm_table;
 
 	struct
 	{
@@ -879,27 +850,13 @@
 				NULL, 0,
 				&result, sizeof(result));
 
-	if (token<0)
-		switch (token)
-		{
-		case -ETIMEDOUT:
-			len += sprintf(buf, "Timeout reading table.\n");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-			break;
-		case -ENOMEM:
-			len += sprintf(buf, "No free memory to read the table.\n");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-			break;
-		default:
-			len += sprintf(buf, "Error reading group. BlockStatus %d\n",
-				       token);
-			spin_unlock(&i2o_proc_lock);
-			return len;
-		}
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0x0003 Executing DDM List");
+		spin_unlock(&i2o_proc_lock);
+		return len;
+	}
 
-	len += sprintf(buf+len, "Tid   Type            Vendor Id     Name                     Vrs  Data_size Code_size\n");
+	len += sprintf(buf+len, "Tid   Module_type     Vendor Mod_id  Module_name             Vrs  Data_size Code_size\n");
 	ddm_table=result.ddm_table[0];
 
 	for(i=0; i < result.row_count; ddm_table=result.ddm_table[++i])
@@ -918,11 +875,10 @@
 			len += sprintf(buf+len, "                ");
 		}
 
-		len += sprintf(buf+len, "%0#7x", ddm_table.i2o_vendor_id);
-		len += sprintf(buf+len, "%0#7x", ddm_table.module_id);
-		len += sprintf(buf+len, "%-25s", chtostr(ddm_table.module_name, 24));
-		len += sprintf(buf+len, "%-6s", chtostr(ddm_table.module_version,4));
-		len += sprintf(buf+len, "%8d  ", ddm_table.data_size);
+		len += sprintf(buf+len, "%-#7x", ddm_table.i2o_vendor_id);
+		len += sprintf(buf+len, "%-#8x", ddm_table.module_id);
+		len += sprintf(buf+len, "%-29s", chtostr(ddm_table.module_name_version, 28));
+		len += sprintf(buf+len, "%9d  ", ddm_table.data_size);
 		len += sprintf(buf+len, "%8d", ddm_table.code_size);
 
 		len += sprintf(buf+len, "\n");
@@ -935,20 +891,20 @@
 
 
 /* Executive group 0004h - Driver Store (scalar) */
-int i2o_proc_read_ds(char *buf, char **start, off_t offset, int len, 
+int i2o_proc_read_driver_store(char *buf, char **start, off_t offset, int len, 
 		     int *eof, void *data)
 {
 	struct i2o_controller *c = (struct i2o_controller*)data;
 	u32 work32[8];
+	int token;
 
 	spin_lock(&i2o_proc_lock);
 
 	len = 0;
 
-	if(i2o_query_scalar(c, ADAPTER_TID, 0x0004, -1, &work32,
-		sizeof(work32)) < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+	token = i2o_query_scalar(c, ADAPTER_TID, 0x0004, -1, &work32, sizeof(work32));
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0x0004 Driver Store");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
@@ -966,8 +922,8 @@
 
 
 /* Executive group 0005h - Driver Store Table (table) */
-int i2o_proc_read_dst(char *buf, char **start, off_t offset, int len, 
-		      int *eof, void *data)
+int i2o_proc_read_drivers_stored(char *buf, char **start, off_t offset,
+				 int len, int *eof, void *data)
 {
 	typedef struct _i2o_driver_store {
 		u16 stored_ddm_index;
@@ -1005,33 +961,17 @@
 	len = 0;
 
 	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				c, ADAPTER_TID,
-				0x0005, -1,
-				NULL, 0,
+				c, ADAPTER_TID, 0x0005, -1, NULL, 0, 
 				&result, sizeof(result));
 
-	if (token<0)
-		switch (token)
-		{
-		case -ETIMEDOUT:
-			len += sprintf(buf, "Timeout reading table.\n");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-			break;
-		case -ENOMEM:
-			len += sprintf(buf, "No free memory to read the table.\n");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-			break;
-		default:
-			len += sprintf(buf, "Error reading group. "
-					"BlockStatus %d\n",token);
-			spin_unlock(&i2o_proc_lock);
-			return len;
-		}
-
-	len += sprintf(buf+len, "#  Type            Vendor Id      Name                    Vrs  Date     Mod_size Par_size Flags\n");	
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0x0005 DRIVER STORE TABLE");
+		spin_unlock(&i2o_proc_lock);
+		return len;
+	}
 
+	len += sprintf(buf+len, "#  Module_type     Vendor Mod_id  Module_name             Vrs"  
+				"Date     Mod_size Par_size Flags\n");
 	for(i=0, dst=result.dst[0]; i < result.row_count; dst=result.dst[++i])
 	{
 		len += sprintf(buf+len, "%-3d", dst.stored_ddm_index);
@@ -1052,8 +992,8 @@
 			len += sprintf(buf+len, "%-d", dst.module_state);
 #endif
 
-		len += sprintf(buf+len, "%#7x", dst.i2o_vendor_id);
-		len += sprintf(buf+len, "%#8x", dst.module_id);
+		len += sprintf(buf+len, "%-#7x", dst.i2o_vendor_id);
+		len += sprintf(buf+len, "%-#8x", dst.module_id);
 		len += sprintf(buf+len, "%-29s", chtostr(dst.module_name_version,28));
 		len += sprintf(buf+len, "%-9s", chtostr(dst.date,8));
 		len += sprintf(buf+len, "%8d ", dst.module_size);
@@ -1077,81 +1017,69 @@
 int i2o_proc_read_groups(char *buf, char **start, off_t offset, int len, 
 			 int *eof, void *data)
 {
-	struct i2o_controller *c = (struct i2o_controller*)data;
+	struct i2o_device *d = (struct i2o_device*)data;
 	int token;
 	int i;
-	int rows;
-	u16 work16[2048];
-	u16 *group=work16;
-	int more;
-	
+	u8 properties;
+
+	typedef struct _i2o_group_info
+	{
+		u16 group_number;
+		u16 field_count;
+		u16 row_count;
+		u8  properties;
+		u8  reserved;
+	} i2o_group_info;
+
+	struct
+	{
+		u16 result_count;
+		u16 pad;
+		u16 block_size;
+		u8  block_status;
+		u8  error_info_size;
+		u16 row_count;
+		u16 more_flag;
+		i2o_group_info group[256];
+	} result;
+
 	spin_lock(&i2o_proc_lock);
 
 	len = 0;
 
 	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				c, ADAPTER_TID,
-				0xF000, -1,
-				NULL, 0,
-				&work16, sizeof(work16));
-
-	if (token<0)
-		switch (token)
-		{
-		case -ETIMEDOUT:
-			len += sprintf(buf, "Timeout reading table.\n");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-			break;
-		case -ENOMEM:
-			len += sprintf(buf, "No free memory to read the table.\n");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-			break;
-		default:
-			len += sprintf(buf, "Error reading table. BlockStatus %d\n",
-				       token);
-			spin_unlock(&i2o_proc_lock);
-			return len;
-		}
+				d->controller, d->lct_data->tid, 0xF000, -1, NULL, 0,
+				&result, sizeof(result));
 
-	rows=work16[4];
-	more=work16[5];
+	if (token < 0) {
+		len = i2o_report_query_status(buf+len, token, "0xF000 Params Descriptor");
+		spin_unlock(&i2o_proc_lock);
+		return len;
+	}
 
-	len += sprintf(buf+len, "\nPARAMS DESCRIPTOR TABLE:\n\n");
 	len += sprintf(buf+len, "#  Group   FieldCount RowCount Type   Add Del Clear\n");
 
-	group+=64;
-
-	for(i=0; i < rows; i++,	group+=16)
+	for (i=0; i < result.row_count; i++)
 	{
 		len += sprintf(buf+len, "%-3d", i);
-
-		len += sprintf(buf+len, "%#6x ", group[0]);
-		len += sprintf(buf+len, "%10d ", group[1]);
-		len += sprintf(buf+len, "%8d ", group[2]);
-
-		if(group[3]&0x1)
-			len += sprintf(buf+len, "Table  ");
-		else
-			len += sprintf(buf+len, "Scalar ");
-		if(group[3]&0x2)
-			len += sprintf(buf+len, "x   ");
-		else
-			len += sprintf(buf+len, "    ");
-		if(group[3]&0x4)
-			len += sprintf(buf+len, "x   ");
-		else
-			len += sprintf(buf+len, "    ");
-		if(group[3]&0x8)
-			len += sprintf(buf+len, "x   ");
-		else
-			len += sprintf(buf+len, "    ");
+		len += sprintf(buf+len, "0x%04X ", result.group[i].group_number);
+		len += sprintf(buf+len, "%10d ", result.group[i].field_count);
+		len += sprintf(buf+len, "%8d ",  result.group[i].row_count);
+
+		properties = result.group[i].properties;
+		if (properties & 0x1)	len += sprintf(buf+len, "Table  ");
+				else	len += sprintf(buf+len, "Scalar ");
+		if (properties & 0x2)	len += sprintf(buf+len, " + ");
+				else	len += sprintf(buf+len, " - ");
+		if (properties & 0x4)	len += sprintf(buf+len, "  + ");
+				else	len += sprintf(buf+len, "  - ");
+		if (properties & 0x8)	len += sprintf(buf+len, "  + ");
+				else	len += sprintf(buf+len, "  - ");
 
 		len += sprintf(buf+len, "\n");
 	}
 
-	if(more)
+	if (result.more_flag)
 		len += sprintf(buf+len, "There is more...\n");
 
 	spin_unlock(&i2o_proc_lock);
@@ -1160,74 +1088,283 @@
 }
 
 
-/* Generic group F005h - Private message extensions (table) */
-int i2o_proc_read_priv_msgs(char *buf, char **start, off_t offset, int len, 
-			    int *eof, void *data)
+/* Generic group F001h - Physical Device Table (table) */
+int i2o_proc_read_phys_device(char *buf, char **start, off_t offset, int len,
+			      int *eof, void *data)
 {
-	struct i2o_controller *c = (struct i2o_controller*)data;
+	struct i2o_device *d = (struct i2o_device*)data;
 	int token;
 	int i;
-	int rows;
-	int more;
-	u16 work16[1024];
-	u16 *field=work16;
 
-	spin_lock(&i2o_proc_lock);
+	struct
+	{
+		u16 result_count;
+		u16 pad;
+		u16 block_size;
+		u8  block_status;
+		u8  error_info_size;
+		u16 row_count;
+		u16 more_flag;
+		u32 adapter_id[64];
+	} result;
 
+	spin_lock(&i2o_proc_lock);
 	len = 0;
 
 	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				c, ADAPTER_TID,
-				0xF000, -1,
-				NULL, 0,
-				&work16, sizeof(work16));
+				d->controller, d->lct_data->tid,
+				0xF001, -1, NULL, 0,
+				&result, sizeof(result));
 
-	if (token<0)
-		switch (token)
-		{
-		case -ETIMEDOUT:
-			len += sprintf(buf, "Timeout reading table.\n");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-			break;
-		case -ENOMEM:
-			len += sprintf(buf, "No free memory to read the table.\n");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-			break;
-		default:
-			len += sprintf(buf, "Error reading field. BlockStatus %d\n",
-				       token);
-			spin_unlock(&i2o_proc_lock);
-			return len;
-		}
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0xF001 Physical Device Table");
+		spin_unlock(&i2o_proc_lock);
+		return len;
+	}
 
-	rows=work16[4];
-	more=work16[5];
-	
-	len += sprintf(buf+len, "Instance#  OrgId  FunctionCode\n");
+	if (result.row_count)
+		len += sprintf(buf+len, "#  AdapterId\n");
 
-	field+=64;
-	for(i=0; i < rows; i++,	field+=16)
+	for (i=0; i < result.row_count; i++)
 	{
-		len += sprintf(buf+len, "%0#9x ", field[0]);
-		len += sprintf(buf+len, "%0#6x ", work16[1]);
-		len += sprintf(buf+len, "%0#6x", work16[2]);
-
-		len += sprintf(buf+len, "\n");
+		len += sprintf(buf+len, "%-2d", i);
+		len += sprintf(buf+len, "%#7x\n", result.adapter_id[i]);
 	}
 
-	if(more)
+	if (result.more_flag)
 		len += sprintf(buf+len, "There is more...\n");
 
 	spin_unlock(&i2o_proc_lock);
-
 	return len;
 }
 
+/* Generic group F002h - Claimed Table (table) */
+int i2o_proc_read_claimed(char *buf, char **start, off_t offset, int len,
+			  int *eof, void *data)
+{
+	struct i2o_device *d = (struct i2o_device*)data;
+	int token;
+	int i;
 
-int i2o_proc_read_dev(char *buf, char **start, off_t offset, int len, 
-		      int *eof, void *data)
+	struct {
+		u16 result_count;
+		u16 pad;
+		u16 block_size;
+		u8  block_status;
+		u8  error_info_size;
+		u16 row_count;
+		u16 more_flag;
+		u16 claimed_tid[64];
+	} result;
+
+	spin_lock(&i2o_proc_lock);
+	len = 0;
+
+	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
+				d->controller, d->lct_data->tid,
+				0xF002, -1, NULL, 0,
+				&result, sizeof(result));
+
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0xF002 Claimed Table");
+		spin_unlock(&i2o_proc_lock);
+		return len;
+	}
+
+	if (result.row_count)
+		len += sprintf(buf+len, "#  ClaimedTid\n");
+
+	for (i=0; i < result.row_count; i++)
+	{
+		len += sprintf(buf+len, "%-2d", i);
+		len += sprintf(buf+len, "%#7x\n", result.claimed_tid[i]);
+	}
+
+	if (result.more_flag)
+		len += sprintf(buf+len, "There is more...\n");
+
+	spin_unlock(&i2o_proc_lock);
+	return len;
+}
+
+/* Generic group F003h - User Table (table) */
+int i2o_proc_read_users(char *buf, char **start, off_t offset, int len,
+			int *eof, void *data)
+{
+	struct i2o_device *d = (struct i2o_device*)data;
+	int token;
+	int i;
+
+	typedef struct _i2o_user_table
+	{
+		u16 instance;
+		u16 user_tid;
+		u8 claim_type;
+		u8  reserved1;
+		u16  reserved2;
+	} i2o_user_table;
+
+	struct
+	{
+		u16 result_count;
+		u16 pad;
+		u16 block_size;
+		u8  block_status;
+		u8  error_info_size;
+		u16 row_count;
+		u16 more_flag;
+		i2o_user_table user[64];
+	} result;
+
+	spin_lock(&i2o_proc_lock);
+	len = 0;
+
+	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
+				d->controller, d->lct_data->tid,
+				0xF003, -1, NULL, 0,
+				&result, sizeof(result));
+
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0xF003 User Table");
+		spin_unlock(&i2o_proc_lock);
+		return len;
+	}
+
+	len += sprintf(buf+len, "#  Instance UserTid ClaimType\n");
+
+	for(i=0; i < result.row_count; i++)
+	{
+		len += sprintf(buf+len, "%-3d", i);
+		len += sprintf(buf+len, "%#8x ", result.user[i].instance);
+		len += sprintf(buf+len, "%#7x ", result.user[i].user_tid);
+		len += sprintf(buf+len, "%#9x\n", result.user[i].claim_type);
+	}
+
+	if (result.more_flag)
+		len += sprintf(buf+len, "There is more...\n");
+
+	spin_unlock(&i2o_proc_lock);
+	return len;
+}
+
+/* Generic group F005h - Private message extensions (table) (optional) */
+int i2o_proc_read_priv_msgs(char *buf, char **start, off_t offset, int len, 
+			    int *eof, void *data)
+{
+	struct i2o_device *d = (struct i2o_device*)data;
+	int token;
+	int i;
+
+	typedef struct _i2o_private
+	{
+		u16 ext_instance;
+		u16 organization_id;
+		u16 x_function_code;
+	} i2o_private;
+
+	struct
+	{
+		u16 result_count;
+		u16 pad;
+		u16 block_size;
+		u8  block_status;
+		u8  error_info_size;
+		u16 row_count;
+		u16 more_flag;
+		i2o_private extension[64];
+	} result;
+
+	spin_lock(&i2o_proc_lock);
+
+	len = 0;
+
+	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
+				d->controller, d->lct_data->tid,
+				0xF000, -1,
+				NULL, 0,
+				&result, sizeof(result));
+
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0xF005 Private Message Extensions (optional)");
+		spin_unlock(&i2o_proc_lock);
+		return len;
+	}
+	
+	len += sprintf(buf+len, "Instance#  OrgId  FunctionCode\n");
+
+	for(i=0; i < result.row_count; i++)
+	{
+		len += sprintf(buf+len, "%0#9x ", result.extension[i].ext_instance);
+		len += sprintf(buf+len, "%0#6x ", result.extension[i].organization_id);
+		len += sprintf(buf+len, "%0#6x",  result.extension[i].x_function_code);
+
+		len += sprintf(buf+len, "\n");
+	}
+
+	if(result.more_flag)
+		len += sprintf(buf+len, "There is more...\n");
+
+	spin_unlock(&i2o_proc_lock);
+
+	return len;
+}
+
+
+/* Generic group F006h - Authorized User Table (table) */
+int i2o_proc_read_authorized_users(char *buf, char **start, off_t offset, int len,
+				   int *eof, void *data)
+{
+	struct i2o_device *d = (struct i2o_device*)data;
+	int token;
+	int i;
+
+	struct
+	{
+		u16 result_count;
+		u16 pad;
+		u16 block_size;
+		u8  block_status;
+		u8  error_info_size;
+		u16 row_count;
+		u16 more_flag;
+		u32 alternate_tid[64];
+	} result;
+
+	spin_lock(&i2o_proc_lock);
+	len = 0;
+
+	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
+				d->controller, d->lct_data->tid,
+				0xF006, -1,
+				NULL, 0,
+				&result, sizeof(result));
+
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0xF006 Autohorized User Table");
+		spin_unlock(&i2o_proc_lock);
+		return len;
+	}
+
+	if (result.row_count)
+		len += sprintf(buf+len, "#  AlternateTid\n");
+
+	for(i=0; i < result.row_count; i++)
+	{
+		len += sprintf(buf+len, "%-2d", i);
+		len += sprintf(buf+len, "%#7x ", result.alternate_tid[i]);
+	}
+
+	if (result.more_flag)
+		len += sprintf(buf+len, "There is more...\n");
+
+	spin_unlock(&i2o_proc_lock);
+	return len;
+}
+
+
+/* Generic group F100h - Device Identity (scalar) */
+int i2o_proc_read_dev_identity(char *buf, char **start, off_t offset, int len, 
+			       int *eof, void *data)
 {
 	struct i2o_device *d = (struct i2o_device*)data;
 	static u32 work32[128];		// allow for "stuff" + up to 256 byte (max) serial number
@@ -1240,14 +1377,11 @@
 	len = 0;
 
 	token = i2o_query_scalar(d->controller, d->lct_data->tid,
-					0xF100,		// ParamGroup F100h (Device Identity)
-					-1,		// all fields
-					&work32,
-					sizeof(work32));
+				0xF100,	-1,
+				&work32, sizeof(work32));
 
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token ,"0xF100 Device Identity");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
@@ -1290,44 +1424,45 @@
 }
 
 
-
-int i2o_proc_read_ddm(char *buf, char **start, off_t offset, int len, 
-		      int *eof, void *data)
+/* Generic group F101h - DDM Identity (scalar) */
+int i2o_proc_read_ddm_identity(char *buf, char **start, off_t offset, int len, 
+			      int *eof, void *data)
 {
 	struct i2o_device *d = (struct i2o_device*)data;
-	static u32 work32[128];
-	static u16 *work16 = (u16*)work32;
 	int token;
 
+	struct
+	{
+		u16 ddm_tid;
+		u8 module_name[24];
+		u8 module_rev[8];
+		u8 sn_format;
+		u8 serial_number[12];
+		u8 pad[256]; // allow up to 256 byte (max) serial number
+	} result;	
+
 	spin_lock(&i2o_proc_lock);
 	
 	len = 0;
 
 	token = i2o_query_scalar(d->controller, d->lct_data->tid, 
-					0xF101,		// ParamGroup F101h (DDM Identity)
-					-1,		// all fields
-					&work32,
-					sizeof(work32));
+				0xF101,	-1,
+				&result, sizeof(result));
 
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0xF101 DDM Identity");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
 
-	len += sprintf(buf,     "Registering DDM TID : 0x%03x\n", work16[0]&0xFFF);
-	len += sprintf(buf+len, "Module name         : %s\n", chtostr((u8 *)(work16+1), 24));
-	len += sprintf(buf+len, "Module revision     : %s\n", chtostr((u8 *)(work16+13), 8));
+	len += sprintf(buf,     "Registering DDM TID : 0x%03x\n", result.ddm_tid);
+	len += sprintf(buf+len, "Module name         : %s\n", chtostr(result.module_name, 24));
+	len += sprintf(buf+len, "Module revision     : %s\n", chtostr(result.module_rev, 8));
 
 	len += sprintf(buf+len, "Serial number       : ");
-	len = print_serial_number(buf, len,
-			(u8*)(work16+17),
-					/* allow for SNLen plus
-					 * possible trailing '\0'
-					 */
-			sizeof(work32)-(17*sizeof(u16))-2
-				);
+	len = print_serial_number(buf, len, result.serial_number, sizeof(result)-36);
+				/* allow for SNLen plus possible trailing '\0' */
+
 	len += sprintf(buf+len, "\n");
 
 	spin_unlock(&i2o_proc_lock);
@@ -1335,41 +1470,44 @@
 	return len;
 }
 
+/* Generic group F102h - User Information (scalar) */
 int i2o_proc_read_uinfo(char *buf, char **start, off_t offset, int len, 
 			int *eof, void *data)
 {
 	struct i2o_device *d = (struct i2o_device*)data;
-	static u32 work32[256];
 	int token;
- 
+
+ 	struct
+	{
+		u8 device_name[64];
+		u8 service_name[64];
+		u8 physical_location[64];
+		u8 instance_number[4];
+	} result;
+
 	spin_lock(&i2o_proc_lock);
-	
 	len = 0;
 
 	token = i2o_query_scalar(d->controller, d->lct_data->tid,
-					0xF102,		// ParamGroup F102h (User Information)
-					-1,		// all fields
-					&work32,
-					sizeof(work32));
+				0xF102,	-1,
+				&result, sizeof(result));
 
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0xF102 User Information");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
 
-	len += sprintf(buf,     "Device name     : %s\n", chtostr((u8 *)work32, 64));
-	len += sprintf(buf+len, "Service name    : %s\n", chtostr((u8 *)(work32+16), 64));
-	len += sprintf(buf+len, "Physical name   : %s\n", chtostr((u8 *)(work32+32), 64));
-	len += sprintf(buf+len, "Instance number : %s\n", chtostr((u8 *)(work32+48), 4));
-        
-	spin_unlock(&i2o_proc_lock);
+	len += sprintf(buf,     "Device name     : %s\n", chtostr(result.device_name, 64));
+	len += sprintf(buf+len, "Service name    : %s\n", chtostr(result.service_name, 64));
+	len += sprintf(buf+len, "Physical name   : %s\n", chtostr(result.physical_location, 64));
+	len += sprintf(buf+len, "Instance number : %s\n", chtostr(result.instance_number, 4));
 
+	spin_unlock(&i2o_proc_lock);
 	return len;
 }
 
-
+/* Generic group F103h - SGL Operating Limits (scalar) */
 int i2o_proc_read_sgl_limits(char *buf, char **start, off_t offset, int len, 
 			     int *eof, void *data)
 {
@@ -1384,14 +1522,11 @@
 	len = 0;
 
 	token = i2o_query_scalar(d->controller, d->lct_data->tid, 
-				 0xF103,	// ParamGroup F103h (SGL Operating Limits)
-				 -1,		// all fields
-				 &work32,
-				 sizeof(work32));
+				 0xF103, -1,
+				 &work32, sizeof(work32));
 
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0xF103 SGL Operating Limits");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
@@ -1424,6 +1559,164 @@
 	return len;
 }
 
+/* Generic group F200h - Sensors (scalar) */
+int i2o_proc_read_sensors(char *buf, char **start, off_t offset, int len,
+			  int *eof, void *data)
+{
+	struct i2o_device *d = (struct i2o_device*)data;
+	int token;
+
+	struct
+	{
+		u16 sensor_instance;
+		u8  component;
+		u16 component_instance;
+		u8  sensor_class;
+		u8  sensor_type;
+		u8  scaling_exponent;
+		u32 actual_reading;
+		u32 minimum_reading;
+		u32 low2lowcat_treshold;
+		u32 lowcat2low_treshold;
+		u32 lowwarn2low_treshold;
+		u32 low2lowwarn_treshold;
+		u32 norm2lowwarn_treshold;
+		u32 lowwarn2norm_treshold;
+		u32 nominal_reading;
+		u32 hiwarn2norm_treshold;
+		u32 norm2hiwarn_treshold;
+		u32 high2hiwarn_treshold;
+		u32 hiwarn2high_treshold;
+		u32 hicat2high_treshold;
+		u32 hi2hicat_treshold;
+		u32 maximum_reading;
+		u8  sensor_state;
+		u16 event_enable;
+	} result;
+	
+	spin_lock(&i2o_proc_lock);	
+	len = 0;
+
+	token = i2o_query_scalar(d->controller, d->lct_data->tid,
+				 0xF200, -1,
+				 &result, sizeof(result));
+
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0xF200 Sensors (optional)");
+		spin_unlock(&i2o_proc_lock);
+		return len;
+	}
+	
+	len += sprintf(buf+len, "Sensor instance       : %d\n", result.sensor_instance);
+
+	len += sprintf(buf+len, "Component             : %d = ", result.component);
+	switch (result.component)
+	{
+	case 0:	len += sprintf(buf+len, "Other");		
+		break;
+	case 1: len += sprintf(buf+len, "Planar logic Board");
+		break;
+	case 2: len += sprintf(buf+len, "CPU");
+		break;
+	case 3: len += sprintf(buf+len, "Chassis");
+		break;
+	case 4: len += sprintf(buf+len, "Power Supply");
+		break;
+	case 5: len += sprintf(buf+len, "Storage");
+		break;
+	case 6: len += sprintf(buf+len, "External");
+		break;
+	}		
+	len += sprintf(buf+len,"\n");
+
+	len += sprintf(buf+len, "Component instance    : %d\n", result.component_instance);
+	len += sprintf(buf+len, "Sensor class          : %s\n",
+				result.sensor_class ? "Analog" : "Digital");
+	
+	len += sprintf(buf+len, "Sensor type           : %d = ",result.sensor_type);
+	switch (result.sensor_type)
+	{
+	case 0:	len += sprintf(buf+len, "Other\n");
+		break;
+	case 1: len += sprintf(buf+len, "Thermal\n");
+		break;
+	case 2: len += sprintf(buf+len, "DC voltage (DC volts)\n");
+		break;
+	case 3: len += sprintf(buf+len, "AC voltage (AC volts)\n");
+		break;
+	case 4: len += sprintf(buf+len, "DC current (DC amps)\n");
+		break;
+	case 5: len += sprintf(buf+len, "AC current (AC volts)\n");
+		break;
+	case 6: len += sprintf(buf+len, "Door open\n");
+		break;
+	case 7: len += sprintf(buf+len, "Fan operational\n");
+		break;
+ 	}			
+
+	len += sprintf(buf+len, "Scaling exponent      : %d\n", result.scaling_exponent);
+	len += sprintf(buf+len, "Actual reading        : %d\n", result.actual_reading);
+	len += sprintf(buf+len, "Minimum reading       : %d\n", result.minimum_reading);
+	len += sprintf(buf+len, "Low2LowCat treshold   : %d\n", result.low2lowcat_treshold);
+	len += sprintf(buf+len, "LowCat2Low treshold   : %d\n", result.lowcat2low_treshold);
+	len += sprintf(buf+len, "LowWarn2Low treshold  : %d\n", result.lowwarn2low_treshold);
+	len += sprintf(buf+len, "Low2LowWarn treshold  : %d\n", result.low2lowwarn_treshold);
+	len += sprintf(buf+len, "Norm2LowWarn treshold : %d\n", result.norm2lowwarn_treshold);
+	len += sprintf(buf+len, "LowWarn2Norm treshold : %d\n", result.lowwarn2norm_treshold);
+	len += sprintf(buf+len, "Nominal reading       : %d\n", result.nominal_reading);
+	len += sprintf(buf+len, "HiWarn2Norm treshold  : %d\n", result.hiwarn2norm_treshold);
+	len += sprintf(buf+len, "Norm2HiWarn treshold  : %d\n", result.norm2hiwarn_treshold);
+	len += sprintf(buf+len, "High2HiWarn treshold  : %d\n", result.high2hiwarn_treshold);
+	len += sprintf(buf+len, "HiWarn2High treshold  : %d\n", result.hiwarn2high_treshold);
+	len += sprintf(buf+len, "HiCat2High treshold   : %d\n", result.hicat2high_treshold);
+	len += sprintf(buf+len, "High2HiCat treshold   : %d\n", result.hi2hicat_treshold);
+	len += sprintf(buf+len, "Maximum reading       : %d\n", result.maximum_reading);
+
+	len += sprintf(buf+len, "Sensor state          : %d = ", result.sensor_state);
+	switch (result.sensor_state)
+	{
+	case 0:	 len += sprintf(buf+len, "Normal\n");
+		 break;
+	case 1:  len += sprintf(buf+len, "Abnormal\n");
+		 break;
+	case 2:  len += sprintf(buf+len, "Unknown\n");
+		 break;
+	case 3:  len += sprintf(buf+len, "Low Catastrophic (LoCat)\n");
+		 break;
+	case 4:  len += sprintf(buf+len, "Low (Low)\n");
+		 break;
+	case 5:  len += sprintf(buf+len, "Low Warning (LoWarn)\n");
+		 break;
+	case 6:  len += sprintf(buf+len, "High Warning (HiWarn)\n");
+		 break;
+	case 7:  len += sprintf(buf+len, "High (High)\n");
+		 break;
+	case 8:  len += sprintf(buf+len, "High Catastrophic (HiCat)\n");
+		 break;
+	}			
+
+	len += sprintf(buf+len, "Event_enable          : 0x%02X\n", result.event_enable);
+	if (result.event_enable & 0x01)
+		len += sprintf(buf+len, "\tOperational state change. \n");
+	if (result.event_enable & 0x02)
+		len += sprintf(buf+len, "\tLow catastrophic. \n");
+	if (result.event_enable & 0x04)
+		len += sprintf(buf+len, "\tLow reading. \n");
+	if (result.event_enable & 0x08)
+		len += sprintf(buf+len, "\tLow warning. \n");
+	if (result.event_enable & 0x10)
+		len += sprintf(buf+len, "\tChange back to normal from out of range state. \n");
+	if (result.event_enable & 0x20)
+		len += sprintf(buf+len, "\tHigh warning. \n");
+	if (result.event_enable & 0x40)
+		len += sprintf(buf+len, "\tHigh reading. \n");
+	if (result.event_enable & 0x80)
+		len += sprintf(buf+len, "\tHigh catastrophic. \n");
+
+	spin_unlock(&i2o_proc_lock);
+	return len;
+}
+
 
 static int print_serial_number(char *buff, int pos, u8 *serialno, int max_len)
 {
@@ -1749,14 +2042,12 @@
 	int token;
 
 	spin_lock(&i2o_proc_lock);
-
 	len = 0;
 
 	token = i2o_query_scalar(d->controller, d->lct_data->tid,
 				 0x0000, -1, &work32, 56*4);
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token, "0x0000 LAN Device Info");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
@@ -1877,9 +2168,8 @@
 
 	token = i2o_query_scalar(d->controller, d->lct_data->tid,
 				 0x0001, -1, &work32, 48*4);
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0x0001 LAN MAC Address");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
@@ -1955,51 +2245,44 @@
 				 int len, int *eof, void *data)
 {
 	struct i2o_device *d = (struct i2o_device*)data;
-	static u32 field32[64];
-	static u8 *field8 = (u8 *)field32;
-	static u16 *field16 = (u16 *)field32;
 	int token;
 	int i;
+	u8 mc_addr[8];
+
+	struct
+	{
+		u16 result_count;
+		u16 pad;
+		u16 block_size;
+		u8  block_status;
+		u8  error_info_size;
+		u16 row_count;
+		u16 more_flag;
+		u8  mc_addr[256][8];
+	} result;	
 
 	spin_lock(&i2o_proc_lock);	
 	len = 0;
 
 	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-			d->controller, d->lct_data->tid, 0x0002, -1, 
-			NULL, 0, &field32, sizeof(field32));
-
-	if (token<0)
-		switch (token) {
-		case -ETIMEDOUT:
-			len += sprintf(buf, "Timeout reading table.\n");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-			break;
-		case -ENOMEM:
-			len += sprintf(buf, "No free memory to read the table.\n");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-			break;
-		default:
-			len += sprintf(buf, "Error reading field. BlockStatus %d\n",
-				       token);
-			spin_unlock(&i2o_proc_lock);
-			return len;
-		}
-
-	len += sprintf(buf, "RowCount=%d, MoreFlag=%d\n", 
-		       field16[0], field16[1]);
+				d->controller, d->lct_data->tid, 0x0002, -1, 
+				NULL, 0, &result, sizeof(result));
 
-	field8=(u8 *)&field16[2];
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0x002 LAN Multicast MAC Address");
+		spin_unlock(&i2o_proc_lock);
+		return len;
+	}
 
-	for(i=0; i<field16[0]; i++, field8+=8)
+	for (i = 0; i < result.row_count; i++)
 	{
+		memcpy(mc_addr, result.mc_addr[i], 8);
+
 		len += sprintf(buf+len, "MC MAC address[%d]: "
 			       "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-			       i,
-			       field8[0], field8[1], field8[2],
-			       field8[3], field8[4], field8[5],
-			       field8[6], field8[7]);
+			       i, mc_addr[0], mc_addr[1], mc_addr[2],
+			       mc_addr[3], mc_addr[4], mc_addr[5],
+			       mc_addr[6], mc_addr[7]);
 	}
 
 	spin_unlock(&i2o_proc_lock);
@@ -2019,9 +2302,8 @@
 
 	token = i2o_query_scalar(d->controller, d->lct_data->tid,
 				 0x0003, -1, &work32, 9*4);
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0x0003 LAN Batch Control");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
@@ -2050,8 +2332,8 @@
 			       work32[4]/10);
 	}
 
-	len += sprintf(buf+len, "Max Rx batch count : %d\n", work32[5]);
-	len += sprintf(buf+len, "Max Rx batch delay : %d\n", work32[6]);
+	len += sprintf(buf+len, "Max Rx batch count     : %d\n", work32[5]);
+	len += sprintf(buf+len, "Max Rx batch delay     : %d\n", work32[6]);
 
 	if(d->i2oversion == 0x00) {
 		len += sprintf(buf+len,
@@ -2079,9 +2361,8 @@
 
 	token = i2o_query_scalar(d->controller, d->lct_data->tid,
 				 0x0004, -1, &work32, 20);
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0x0004 LAN Operation");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
@@ -2090,7 +2371,7 @@
 	len += sprintf(buf+len, "Transmission error reporting  : %s\n",
 		       (work32[1]&1)?"on":"off");
 	len += sprintf(buf+len, "Bad packet handling           : %s\n",
-		       (work32[1]&0x2)?"by host":"by DDM");		      
+				(work32[1]&0x2)?"by host":"by DDM");
 	len += sprintf(buf+len, "Packet orphan limit           : %d\n", work32[2]);
 
 	len += sprintf(buf+len, "Tx modes :\n");
@@ -2134,52 +2415,72 @@
 				      int len, int *eof, void *data)
 {
 	struct i2o_device *d = (struct i2o_device*)data;
-	static u32 work32[9];
-	static u8 *work8 = (u8*)work32;
-        static u64 *work64 = (u64*)work32;
 	int token;
 
+	struct
+	{
+		u32 connector_type;
+		u32 connection_type;
+		u64 current_tx_wire_speed;
+		u64 current_rx_wire_speed;
+		u8  duplex_mode;
+		u8  link_status;
+		u8  reserved;
+		u8  duplex_mode_target;
+		u32 connector_type_target;
+		u32 connection_type_target;
+	} result;	
+
 	spin_lock(&i2o_proc_lock);	
 	len = 0;
 
 	token = i2o_query_scalar(d->controller, d->lct_data->tid,
-				 0x0005, -1, &work32, 36);
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+				 0x0005, -1, &result, sizeof(result));
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token, "0x0005 LAN Media Operation");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
 
 	len += sprintf(buf, "Connector type         : %s\n",
-		       i2o_get_connector_type(work32[0]));
+		       i2o_get_connector_type(result.connector_type));
 	len += sprintf(buf+len, "Connection type        : %s\n",
-		       i2o_get_connection_type(work32[1]));
-
-	len += sprintf(buf+len, "Current Tx wire speed  : %d bps\n", (int)work64[1]);
-	len += sprintf(buf+len, "Current Rx wire speed  : %d bps\n", (int)work64[2]);
+		       i2o_get_connection_type(result.connection_type));
 
-	len += sprintf(buf+len, "Duplex mode            : %s duplex\n", 
-			(work8[24]&1)?"Full":"Half");
+	len += sprintf(buf+len, "Current Tx wire speed  : %d bps\n", (int)result.current_tx_wire_speed);
+	len += sprintf(buf+len, "Current Rx wire speed  : %d bps\n", (int)result.current_rx_wire_speed);
+	len += sprintf(buf+len, "Duplex mode            : %s duplex\n",
+			(result.duplex_mode)?"Full":"Half");
+			
 	len += sprintf(buf+len, "Link status            : ");
-	if(work8[25] == 0x00)
+	switch (result.link_status)
+	{
+	case 0x00:
 		len += sprintf(buf+len, "Unknown\n");
-	else if(work8[25] == 0x01)
+		break;
+	case 0x01:
 		len += sprintf(buf+len, "Normal\n");
-	else if(work8[25] == 0x02)
+		break;
+	case 0x02:
 		len += sprintf(buf+len, "Failure\n");
-	else if(work8[25] == 0x03)
+		break;
+	case 0x03:
 		len += sprintf(buf+len, "Reset\n");
-	else
+		break;
+	default:
 		len += sprintf(buf+len, "Unspecified\n");
-
-	if (d->i2oversion == 0x00) { /* Reserved in 1.53 and 2.0 */
+	}
+	
+	if (d->i2oversion == 0x00) /* Reserved in 1.53 and 2.0 */
+	{
 		len += sprintf(buf+len, "Bad packets handled by : %s\n",
-			       (work8[26] == 0xFF)?"host":"DDM");
+			       (result.reserved == 0xFF)?"host":"DDM");
 	}
-	if (d->i2oversion != 0x00) {
+	else
+	{
 		len += sprintf(buf+len, "Duplex mode target     : ");
-		switch (work8[27]) {
+		switch (result.duplex_mode_target)
+		{
 		case 0:
 			len += sprintf(buf+len, "Half duplex\n");
 			break;
@@ -2188,69 +2489,59 @@
 			break;
 		default:
 			len += sprintf(buf+len, "\n");
-			break;
 		}
 
 		len += sprintf(buf+len, "Connector type target  : %s\n",
-			       i2o_get_connector_type(work32[7]));
+			       i2o_get_connector_type(result.connector_type_target));
 		len += sprintf(buf+len, "Connection type target : %s\n",
-			       i2o_get_connection_type(work32[8]));
+			       i2o_get_connection_type(result.connection_type_target));
 	}
 
 	spin_unlock(&i2o_proc_lock);
 	return len;
 }
 
-/* LAN group 0006h - Alternate address (table) */
+/* LAN group 0006h - Alternate address (table) (optional) */
 int i2o_proc_read_lan_alt_addr(char *buf, char **start, off_t offset, int len,
 			       int *eof, void *data)
 {
 	struct i2o_device *d = (struct i2o_device*)data;
-	static u32 field32[64];
-	static u8 *field8 = (u8 *)field32;
-	static u16 *field16 = (u16 *)field32;
 	int token;
 	int i;
+	u8 alt_addr[8];
+	struct
+	{
+		u16 result_count;
+		u16 pad;
+		u16 block_size;
+		u8  block_status;
+		u8  error_info_size;
+		u16 row_count;
+		u16 more_flag;
+		u8  alt_addr[256][8];
+	} result;	
 
 	spin_lock(&i2o_proc_lock);	
 	len = 0;
 
 	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-			d->controller, d->lct_data->tid, 0x0006, -1, 
-			NULL, 0, &field32, sizeof(field32));
+				d->controller, d->lct_data->tid,
+				0x0006, -1, NULL, 0, &result, sizeof(result));
 
-	if (token<0)
-		switch (token) {
-		case -ETIMEDOUT:
-			len += sprintf(buf, "Timeout reading table.\n");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-			break;
-		case -ENOMEM:
-			len += sprintf(buf, "No free memory to read the table.\n");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-			break;
-		default:
-			len += sprintf(buf, "Error reading field. BlockStatus %d\n",
-				       token);
-			spin_unlock(&i2o_proc_lock);
-			return len;
-		}
-
-	len += sprintf(buf,"RowCount=%d, MoreFlag=%d\n", field16[0],
-		       field16[1]);
-
-	field8=(u8 *)&field16[2];
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token, "0x0006 LAN Alternate Address (optional)");
+		spin_unlock(&i2o_proc_lock);
+		return len;
+	}
 
-	for(i=0; i<field16[0]; i++, field8+=8)
+	for (i=0; i < result.row_count; i++)
 	{
+		memcpy(alt_addr,result.alt_addr[i],8);
 		len += sprintf(buf+len, "Alternate address[%d]: "
 			       "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-			       i,
-			       field8[0], field8[1], field8[2],
-			       field8[3], field8[4], field8[5],
-			       field8[6], field8[7]);
+			       i, alt_addr[0], alt_addr[1], alt_addr[2],
+			       alt_addr[3], alt_addr[4], alt_addr[5],
+			       alt_addr[6], alt_addr[7]);
 	}
 
 	spin_unlock(&i2o_proc_lock);
@@ -2271,9 +2562,8 @@
 
 	token = i2o_query_scalar(d->controller, d->lct_data->tid,
 				 0x0007, -1, &work32, 8*4);
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0x0007 LAN Transmit Info");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
@@ -2304,12 +2594,15 @@
 		len += sprintf(buf+len, "    RSVP checksum\n");
 	if(work32[4]&0x00001000)
 		len += sprintf(buf+len, "    ICMP checksum\n");
-	if (d->i2oversion == 0x00) {
+	if (d->i2oversion == 0x00)
+	{
 		if(work32[4]&0x00008000)
 			len += sprintf(buf+len, "    Loopback enabled\n");
 		if(work32[4]&0x00010000)
 			len += sprintf(buf+len, "    Loopback suppression enabled\n");
-	} else {
+	}
+	else
+	{
 		if(work32[4]&0x00010000)
 			len += sprintf(buf+len, "    Loopback enabled\n");
 		if(work32[4]&0x00020000)
@@ -2333,9 +2626,8 @@
 
 	token = i2o_query_scalar(d->controller, d->lct_data->tid,
 				 0x0008, -1, &work32, 8*4);
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0x0008 LAN Receive Info");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
@@ -2354,288 +2646,345 @@
 	return len;
 }
 
+static int i2o_report_opt_field(char *buf, char *field_name,
+				int field_nbr, int supp_fields, u64 *value)
+{
+	if (supp_fields & (1 << field_nbr))
+		return sprintf(buf, "%-24s : " FMT_U64_HEX "\n", field_name, U64_VAL(value));
+	else	
+		return sprintf(buf, "%-24s : Not supported\n", field_name);	
+}
 
 /* LAN group 0100h - LAN Historical statistics (scalar) */
+/* LAN group 0180h - Supported Optional Historical Statistics (scalar) */
+/* LAN group 0182h - Optional Non Media Specific Transmit Historical Statistics (scalar) */
+/* LAN group 0183h - Optional Non Media Specific Receive Historical Statistics (scalar) */
+
 int i2o_proc_read_lan_hist_stats(char *buf, char **start, off_t offset, int len,
 				 int *eof, void *data)
 {
 	struct i2o_device *d = (struct i2o_device*)data;
-	static u64 work64[9];
 	int token;
 
+	struct
+	{
+		u64 tx_packets;
+		u64 tx_bytes;
+		u64 rx_packets;
+		u64 rx_bytes;
+		u64 tx_errors;
+		u64 rx_errors;
+		u64 rx_dropped;
+		u64 adapter_resets;
+		u64 adapter_suspends;
+	} stats;			// 0x0100
+
+	static u64 supp_groups[4];	// 0x0180
+
+	struct
+	{
+		u64 tx_retries;
+		u64 tx_directed_bytes;
+		u64 tx_directed_packets;
+		u64 tx_multicast_bytes;
+		u64 tx_multicast_packets;
+		u64 tx_broadcast_bytes;
+		u64 tx_broadcast_packets;
+		u64 tx_group_addr_packets;
+		u64 tx_short_packets;
+	} tx_stats;			// 0x0182
+
+	struct
+	{
+		u64 rx_crc_errors;
+		u64 rx_directed_bytes;
+		u64 rx_directed_packets;
+		u64 rx_multicast_bytes;
+		u64 rx_multicast_packets;
+		u64 rx_broadcast_bytes;
+		u64 rx_broadcast_packets;
+		u64 rx_group_addr_packets;
+		u64 rx_short_packets;
+		u64 rx_long_packets;
+		u64 rx_runt_packets;
+	} rx_stats;			// 0x0183
+
+	struct
+	{
+		u64 ipv4_generate;
+		u64 ipv4_validate_success;
+		u64 ipv4_validate_errors;
+		u64 tcp_generate;
+		u64 tcp_validate_success;
+		u64 tcp_validate_errors;
+		u64 udp_generate;
+		u64 udp_validate_success;
+		u64 udp_validate_errors;
+		u64 rsvp_generate;
+		u64 rsvp_validate_success;
+		u64 rsvp_validate_errors;		
+		u64 icmp_generate;
+		u64 icmp_validate_success;
+		u64 icmp_validate_errors;
+	} chksum_stats;			// 0x0184
+
 	spin_lock(&i2o_proc_lock);	
 	len = 0;
 
 	token = i2o_query_scalar(d->controller, d->lct_data->tid,
-				 0x0100, -1, &work64, 9*8);
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+				 0x0100, -1, &stats, sizeof(stats));
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0x100 LAN Statistics");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
 
-	len += sprintf(buf,     "Tx packets       : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[0]));
+	len += sprintf(buf+len, "Tx packets       : " FMT_U64_HEX "\n",
+		       U64_VAL(&stats.tx_packets));
 	len += sprintf(buf+len, "Tx bytes         : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[1]));
+		       U64_VAL(&stats.tx_bytes));
 	len += sprintf(buf+len, "Rx packets       : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[2]));
+		       U64_VAL(&stats.rx_packets));
 	len += sprintf(buf+len, "Rx bytes         : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[3]));
+		       U64_VAL(&stats.rx_bytes));
 	len += sprintf(buf+len, "Tx errors        : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[4]));
+		       U64_VAL(&stats.tx_errors));
 	len += sprintf(buf+len, "Rx errors        : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[5]));
+		       U64_VAL(&stats.rx_errors));
 	len += sprintf(buf+len, "Rx dropped       : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[6]));
+		       U64_VAL(&stats.rx_dropped));
 	len += sprintf(buf+len, "Adapter resets   : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[7]));
+		       U64_VAL(&stats.adapter_resets));
 	len += sprintf(buf+len, "Adapter suspends : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[8]));
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
-
-
-/* LAN group 0180h - Supported Optional Historical Statistics (scalar) */
-int i2o_proc_read_lan_supp_opt_stats(char *buf, char **start, off_t offset,
-				     int len, int *eof, void *data)
-{
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u64 work64[4];
-	int token;
+		       U64_VAL(&stats.adapter_suspends));
 
-	spin_lock(&i2o_proc_lock);	
-
-	len = 0;
+	/* Optional statistics follows */
+	/* Get 0x0180 to see which optional groups/fields are supported */
 
 	token = i2o_query_scalar(d->controller, d->lct_data->tid,
-				 0x0180, -1, &work64, 4*8);
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+				 0x0180, -1, &supp_groups, sizeof(supp_groups));
+	
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token, "0x180 LAN Supported Optional Statistics");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
 
-	if (d->i2oversion == 0x00)
-		len += sprintf(buf, "Supported stats : " FMT_U64_HEX " \n",
-			       U64_VAL(&work64[0]));
-	else
+	if (supp_groups[1]) /* 0x0182 */
 	{
-		len += sprintf(buf, "Supported stats (0182h) : " FMT_U64_HEX " \n",
-			       U64_VAL(&work64[1]));
-		len += sprintf(buf, "Supported stats (0183h) : " FMT_U64_HEX " \n",
-			       U64_VAL(&work64[2]));
-		len += sprintf(buf, "Supported stats (0184h) : " FMT_U64_HEX " \n",
-			       U64_VAL(&work64[3]));
-	}
+		token = i2o_query_scalar(d->controller, d->lct_data->tid,
+				 	0x0182, -1, &tx_stats, sizeof(tx_stats));
 
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
+		if (token < 0) {
+			len += i2o_report_query_status(buf+len, token,"0x182 LAN Optional Tx Historical Statistics");
+			spin_unlock(&i2o_proc_lock);
+			return len;
+		}
 
+		len += sprintf(buf+len, "==== Optional TX statistics (group 0182h)\n");
 
-/* LAN group 0182h - Optional Non Media Specific Transmit Historical Statistics
- * (scalar) */
-int i2o_proc_read_lan_opt_tx_hist_stats(char *buf, char **start, off_t offset,
-					int len, int *eof, void *data)
-{
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u64 work64[9];
-	int token;
-
-	spin_lock(&i2o_proc_lock);	
+		len += i2o_report_opt_field(buf+len, "Tx RetryCount",
+					0, supp_groups[1], &tx_stats.tx_retries);
+		len += i2o_report_opt_field(buf+len, "Tx DirectedBytes",
+					1, supp_groups[1], &tx_stats.tx_directed_bytes);
+		len += i2o_report_opt_field(buf+len, "Tx DirectedPackets",
+					2, supp_groups[1], &tx_stats.tx_directed_packets);
+		len += i2o_report_opt_field(buf+len, "Tx MulticastBytes",
+					3, supp_groups[1], &tx_stats.tx_multicast_bytes);
+		len += i2o_report_opt_field(buf+len, "Tx MulticastPackets",
+					4, supp_groups[1], &tx_stats.tx_multicast_packets);
+		len += i2o_report_opt_field(buf+len, "Tx BroadcastBytes",
+					5, supp_groups[1], &tx_stats.tx_broadcast_bytes);
+		len += i2o_report_opt_field(buf+len, "Tx BroadcastPackets",
+					6, supp_groups[1], &tx_stats.tx_broadcast_packets);
+		len += i2o_report_opt_field(buf+len, "Tx TotalGroupAddrPackets",
+					7, supp_groups[1], &tx_stats.tx_group_addr_packets);
+		len += i2o_report_opt_field(buf+len, "Tx TotalPacketsTooShort",
+					8, supp_groups[1], &tx_stats.tx_short_packets);
+	}
+
+	if (supp_groups[2]) /* 0x0183 */
+	{
+		token = i2o_query_scalar(d->controller, d->lct_data->tid,
+					 0x0183, -1, &rx_stats, sizeof(rx_stats));
+		if (token < 0) {
+			len += i2o_report_query_status(buf+len, token,"0x183 LAN Optional Rx Historical Stats");
+			spin_unlock(&i2o_proc_lock);
+			return len;
+		}
 
-	len = 0;
+		len += sprintf(buf+len, "==== Optional RX statistics (group 0183h)\n");
 
-	token = i2o_query_scalar(d->controller, d->lct_data->tid, 
-				 0x0182, -1, &work64, 9*8);
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		len += i2o_report_opt_field(buf+len, "Rx CRCErrorCount",
+					0, supp_groups[2], &rx_stats.rx_crc_errors);
+		len += i2o_report_opt_field(buf+len, "Rx DirectedBytes",
+					1, supp_groups[2], &rx_stats.rx_directed_bytes);
+		len += i2o_report_opt_field(buf+len, "Rx DirectedPackets",
+					2, supp_groups[2], &rx_stats.rx_directed_packets);
+		len += i2o_report_opt_field(buf+len, "Rx MulticastBytes",
+					3, supp_groups[2], &rx_stats.rx_multicast_bytes);
+		len += i2o_report_opt_field(buf+len, "Rx MulticastPackets",
+					4, supp_groups[2], &rx_stats.rx_multicast_packets);
+		len += i2o_report_opt_field(buf+len, "Rx BroadcastBytes",
+					5, supp_groups[2], &rx_stats.rx_broadcast_bytes);
+		len += i2o_report_opt_field(buf+len, "Rx BroadcastPackets",
+					6, supp_groups[2], &rx_stats.rx_broadcast_packets);
+		len += i2o_report_opt_field(buf+len, "Rx TotalGroupAddrPackets",
+					7, supp_groups[2], &rx_stats.rx_group_addr_packets);
+		len += i2o_report_opt_field(buf+len, "Rx TotalPacketsTooShort",
+					8, supp_groups[2], &rx_stats.rx_short_packets);
+		len += i2o_report_opt_field(buf+len, "Rx TotalPacketsTooLong",
+					9, supp_groups[2], &rx_stats.rx_long_packets);
+		len += i2o_report_opt_field(buf+len, "Rx TotalPacketsRunt",
+					10, supp_groups[2], &rx_stats.rx_runt_packets);
 	}
+	
+	if (supp_groups[3]) /* 0x0184 */
+	{
+		token = i2o_query_scalar(d->controller, d->lct_data->tid,
+				 	0x0184, -1, &chksum_stats, sizeof(chksum_stats));
 
-	len += sprintf(buf,     "TxRetryCount           : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[0]));
-	len += sprintf(buf+len, "DirectedBytesTx        : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[1]));
-	len += sprintf(buf+len, "DirectedPacketsTx      : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[2]));
-	len += sprintf(buf+len, "MulticastBytesTx       : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[3]));
-	len += sprintf(buf+len, "MulticastPacketsTx     : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[4]));
-	len += sprintf(buf+len, "BroadcastBytesTx       : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[5]));
-	len += sprintf(buf+len, "BroadcastPacketsTx     : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[6]));
-	len += sprintf(buf+len, "TotalGroupAddrTxCount  : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[7]));
-	len += sprintf(buf+len, "TotalTxPacketsTooShort : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[8]));
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
-
-/* LAN group 0183h - Optional Non Media Specific Receive Historical Statistics
- * (scalar) */
-int i2o_proc_read_lan_opt_rx_hist_stats(char *buf, char **start, off_t offset,
-					int len, int *eof, void *data)
-{
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u64 work64[11];
-	int token;
-
-	spin_lock(&i2o_proc_lock);	
+		if (token < 0) {
+			len += i2o_report_query_status(buf+len, token,"0x184 LAN Optional Chksum Historical Stats");
+			spin_unlock(&i2o_proc_lock);
+			return len;
+		}
 
-	len = 0;
+		len += sprintf(buf+len, "==== Optional CHKSUM statistics (group 0x0184)\n");
 
-	token = i2o_query_scalar(d->controller, d->lct_data->tid,
-				 0x0183, -1, &work64, 11*8);
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		len += i2o_report_opt_field(buf+len, "IPv4 Generate",
+					0, supp_groups[3], &chksum_stats.ipv4_generate);
+		len += i2o_report_opt_field(buf+len, "IPv4 ValidateSuccess",
+					1, supp_groups[3], &chksum_stats.ipv4_validate_success);
+		len += i2o_report_opt_field(buf+len, "IPv4 ValidateError",
+					2, supp_groups[3], &chksum_stats.ipv4_validate_errors);
+		len += i2o_report_opt_field(buf+len, "TCP  Generate",
+					3, supp_groups[3], &chksum_stats.tcp_generate);
+		len += i2o_report_opt_field(buf+len, "TCP  ValidateSuccess",
+					4, supp_groups[3], &chksum_stats.tcp_validate_success);
+		len += i2o_report_opt_field(buf+len, "TCP  ValidateError",
+					5, supp_groups[3], &chksum_stats.tcp_validate_errors);
+		len += i2o_report_opt_field(buf+len, "UDP  Generate",
+					6, supp_groups[3], &chksum_stats.udp_generate);
+		len += i2o_report_opt_field(buf+len, "UDP  ValidateSuccess",
+					7, supp_groups[3], &chksum_stats.udp_validate_success);
+		len += i2o_report_opt_field(buf+len, "UDP  ValidateError",
+					8, supp_groups[3], &chksum_stats.udp_validate_errors);
+		len += i2o_report_opt_field(buf+len, "RSVP Generate",
+					9, supp_groups[3], &chksum_stats.rsvp_generate);
+		len += i2o_report_opt_field(buf+len, "RSVP ValidateSuccess",
+					10, supp_groups[3], &chksum_stats.rsvp_validate_success);
+		len += i2o_report_opt_field(buf+len, "RSVP ValidateError",
+					11, supp_groups[3], &chksum_stats.rsvp_validate_errors);
+		len += i2o_report_opt_field(buf+len, "ICMP Generate",
+					12, supp_groups[3], &chksum_stats.icmp_generate);
+		len += i2o_report_opt_field(buf+len, "ICMP ValidateSuccess",
+					13, supp_groups[3], &chksum_stats.icmp_validate_success);
+		len += i2o_report_opt_field(buf+len, "ICMP ValidateError",
+					14, supp_groups[3], &chksum_stats.icmp_validate_errors);
 	}
 
-	len += sprintf(buf,     "ReceiveCRCErrorCount     : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[0]));
-	len += sprintf(buf+len, "DirectedBytesRx          : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[1]));
-	len += sprintf(buf+len, "DirectedPacketsRx        : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[2]));
-	len += sprintf(buf+len, "MulticastBytesRx         : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[3]));
-	len += sprintf(buf+len, "MulticastPacketsRx       : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[4]));
-	len += sprintf(buf+len, "BroadcastBytesRx         : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[5]));
-	len += sprintf(buf+len, "BroadcastPacketsRx       : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[6]));
-	len += sprintf(buf+len, "TotalGroupAddrRxCount    : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[7]));
-	len += sprintf(buf+len, "TotalRxPacketsTooShort   : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[8]));
-	len += sprintf(buf+len, "TotalRxPacketsTooLong    : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[9]));
-	len += sprintf(buf+len, "TotalRuntPacketsReceived : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[10]));
-
 	spin_unlock(&i2o_proc_lock);
 	return len;
 }
 
 /* LAN group 0200h - Required Ethernet Statistics (scalar) */
+/* LAN group 0280h - Optional Ethernet Statistics Supported (scalar) */
+/* LAN group 0281h - Optional Ethernet Historical Statistics (scalar) */
 int i2o_proc_read_lan_eth_stats(char *buf, char **start, off_t offset,
 				int len, int *eof, void *data)
 {
 	struct i2o_device *d = (struct i2o_device*)data;
-	static u64 work64[8];
 	int token;
 
+	struct
+	{
+		u64 rx_align_errors;
+		u64 tx_one_collisions;
+		u64 tx_multiple_collisions;
+		u64 tx_deferred;
+		u64 tx_late_collisions;
+		u64 tx_max_collisions;
+		u64 tx_carrier_lost;
+		u64 tx_excessive_deferrals;
+	} stats;	
 
-	spin_lock(&i2o_proc_lock);
-	
+	static u64 supp_fields;
+	struct
+	{
+		u64 rx_overrun;
+		u64 tx_underrun;
+		u64 tx_heartbeat_failure;	
+	} hist_stats;
+
+	spin_lock(&i2o_proc_lock);	
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->lct_data->tid, 
-				 0x0200, -1, &work64, 8*8);
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+	token = i2o_query_scalar(d->controller, d->lct_data->tid,
+				 0x0200, -1, &stats, sizeof(stats));
+
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0x0200 LAN Ethernet Statistics");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
 
-	len += sprintf(buf,     "Rx alignment errors    : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[0]));
+	len += sprintf(buf+len, "Rx alignment errors    : " FMT_U64_HEX "\n",
+		       U64_VAL(&stats.rx_align_errors));
 	len += sprintf(buf+len, "Tx one collisions      : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[1]));
+		       U64_VAL(&stats.tx_one_collisions));
 	len += sprintf(buf+len, "Tx multicollisions     : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[2]));
+		       U64_VAL(&stats.tx_multiple_collisions));
 	len += sprintf(buf+len, "Tx deferred            : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[3]));
+		       U64_VAL(&stats.tx_deferred));
 	len += sprintf(buf+len, "Tx late collisions     : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[4]));
+		       U64_VAL(&stats.tx_late_collisions));
 	len += sprintf(buf+len, "Tx max collisions      : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[5]));
+		       U64_VAL(&stats.tx_max_collisions));
 	len += sprintf(buf+len, "Tx carrier lost        : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[6]));
+		       U64_VAL(&stats.tx_carrier_lost));
 	len += sprintf(buf+len, "Tx excessive deferrals : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[7]));
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
-
-/* LAN group 0280h - Supported Ethernet Historical Statistics (scalar) */
-int i2o_proc_read_lan_supp_eth_stats(char *buf, char **start, off_t offset,
-				     int len, int *eof, void *data)
-{
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u64 work64[1];
-	int token;
+		       U64_VAL(&stats.tx_excessive_deferrals));
 
-	spin_lock(&i2o_proc_lock);	
+	/* Optional Ethernet statistics follows  */
+	/* Get 0x0280 to see which optional fields are supported */
 
-	len = 0;
+	token = i2o_query_scalar(d->controller, d->lct_data->tid,
+				 0x0280, -1, &supp_fields, sizeof(supp_fields));
 
-	token = i2o_query_scalar(d->controller, d->lct_data->tid, 
-				 0x0280, -1, &work64, 8);
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0x0280 LAN Supported Optional Ethernet Statistics");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
 
-	len += sprintf(buf, "Supported stats : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[0]));
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
-
-/* LAN group 0281h - Optional Ethernet Historical Statistics (scalar) */
-int i2o_proc_read_lan_opt_eth_stats(char *buf, char **start, off_t offset,
-				    int len, int *eof, void *data)
-{
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u64 work64[3];
-	int token;
+	if (supp_fields) /* 0x0281 */
+	{
+		token = i2o_query_scalar(d->controller, d->lct_data->tid,
+					 0x0281, -1, &stats, sizeof(stats));
 
-	spin_lock(&i2o_proc_lock);	
+		if (token < 0) {
+			len += i2o_report_query_status(buf+len, token,"0x0281 LAN Optional Ethernet Statistics");
+			spin_unlock(&i2o_proc_lock);
+			return len;
+		}
 
-	len = 0;
+		len += sprintf(buf+len, "==== Optional ETHERNET statistics (group 0x0281)\n");
 
-	token = i2o_query_scalar(d->controller, d->lct_data->tid,
-				 0x0281, -1, &work64, 3*8);
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		len += i2o_report_opt_field(buf+len, "Rx Overrun",
+					0, supp_fields, &hist_stats.rx_overrun);
+		len += i2o_report_opt_field(buf+len, "Tx Underrun",
+					1, supp_fields, &hist_stats.tx_underrun);
+		len += i2o_report_opt_field(buf+len, "Tx HeartbeatFailure",
+					2, supp_fields, &hist_stats.tx_heartbeat_failure);
 	}
 
-	len += sprintf(buf, "Rx overrun           : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[0]));
-	len += sprintf(buf, "Tx underrun          : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[1]));
-	len += sprintf(buf, "Tx heartbeat failure : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[2]));
-
 	spin_unlock(&i2o_proc_lock);
 	return len;
 }
 
 /* LAN group 0300h - Required Token Ring Statistics (scalar) */
+/* LAN group 0380h, 0381h - Optional Statistics not yet defined (TODO) */
 int i2o_proc_read_lan_tr_stats(char *buf, char **start, off_t offset,
 			       int len, int *eof, void *data)
 {
@@ -2663,15 +3012,14 @@
 		"Signal Loss"
 	};
 
-	spin_lock(&i2o_proc_lock);
-	
+	spin_lock(&i2o_proc_lock);	
 	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->lct_data->tid, 
-				 0x0300, -1, &work64, 13*8);
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+	token = i2o_query_scalar(d->controller, d->lct_data->tid,
+				 0x0300, -1, &work64, sizeof(work64));
+
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0x0300 Token Ring Statistics");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
@@ -2707,6 +3055,7 @@
 }
 
 /* LAN group 0400h - Required FDDI Statistics (scalar) */
+/* LAN group 0480h, 0481h - Optional Statistics, not yet defined (TODO) */
 int i2o_proc_read_lan_fddi_stats(char *buf, char **start, off_t offset,
 				 int len, int *eof, void *data)
 {
@@ -2758,19 +3107,18 @@
 	};
 
 	spin_lock(&i2o_proc_lock);
-	
 	len = 0;
 
 	token = i2o_query_scalar(d->controller, d->lct_data->tid,
-				 0x0400, -1, &work64, 11*8);
-	if(token < 0)
-	{
-		len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+				 0x0400, -1, &work64, sizeof(work64));
+
+	if (token < 0) {
+		len += i2o_report_query_status(buf+len, token,"0x0400 FDDI Required Statistics");
 		spin_unlock(&i2o_proc_lock);
 		return len;
 	}
 
-	len += sprintf(buf,     "ConfigurationState : %s\n", conf_state[work64[0]]);
+	len += sprintf(buf+len, "ConfigurationState : %s\n", conf_state[work64[0]]);
 	len += sprintf(buf+len, "UpstreamNode       : " FMT_U64_HEX "\n",
 		       U64_VAL(&work64[1]));
 	len += sprintf(buf+len, "DownStreamNode     : " FMT_U64_HEX "\n",
@@ -2780,7 +3128,7 @@
 	len += sprintf(buf+len, "FramesLost         : " FMT_U64_HEX "\n",
 		       U64_VAL(&work64[4]));
 	len += sprintf(buf+len, "RingMgmtState      : %s\n", ring_state[work64[5]]);
-	len += sprintf(buf+len, "LCTFailures: " FMT_U64_HEX "\n",
+	len += sprintf(buf+len, "LCTFailures        : " FMT_U64_HEX "\n",
 		       U64_VAL(&work64[6]));
 	len += sprintf(buf+len, "LEMRejects         : " FMT_U64_HEX "\n",
 		       U64_VAL(&work64[7]));
diff -u --recursive --new-file v2.3.26/linux/drivers/i2o/i2o_proc.h linux/drivers/i2o/i2o_proc.h
--- v2.3.26/linux/drivers/i2o/i2o_proc.h	Mon Jul  5 20:09:40 1999
+++ linux/drivers/i2o/i2o_proc.h	Wed Dec 31 16:00:00 1969
@@ -1,36 +0,0 @@
-#ifndef i2oproc_h
-#define i2oproc_h
-
-/*
- * Fixme: make this dependent on architecture
- * The official header files to this already...but we can't use them
- */
-#define     I2O_64BIT_CONTEXT          0
-
-typedef struct _i2o_msg {
-	u8 ver_offset;
-	u8 msg_flags;
-	u16 msg_size;
-	u32 target_addr:12;
-	u32 initiator_addr:12;
-	u32 function:8;
-	u32 init_context;	/* FIXME: 64-bit support! */
-} i2o_msg, *pi2o_msg;
-
-typedef struct _i2o_reply_message {
-	i2o_msg msg_frame;
-	u32 tctx;		/* FIXME: 64-bit */
-	u16 detailed_status_code;
-	u8 reserved;
-	u8 req_status;
-} i2o_reply_msg, *pi2o_reply_msg;
-
-typedef struct _i2o_mult_reply_message {
-	i2o_msg msg_frame;
-	u32 tctx;		/* FIXME: 64-bit */
-	u16 detailed_status_code;
-	u8 reserved;
-	u8 req_status;
-} i2o_mult_reply_msg, *pi2o_mult_reply_msg;
-   
-#endif				/* i2oproc_h */
diff -u --recursive --new-file v2.3.26/linux/drivers/i2o/i2o_scsi.c linux/drivers/i2o/i2o_scsi.c
--- v2.3.26/linux/drivers/i2o/i2o_scsi.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/i2o/i2o_scsi.c	Thu Nov 11 16:57:30 1999
@@ -59,10 +59,6 @@
 
 #define MAXHOSTS 32
 
-struct proc_dir_entry proc_scsi_i2o_scsi = {
-	PROC_SCSI_I2O, 8, "i2o_scsi", S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 struct i2o_scsi_host
 {
 	struct i2o_controller *controller;
@@ -587,7 +583,7 @@
 		m = I2O_POST_READ32(c);
 	}
 	while(m==0xFFFFFFFF);
-	msg = c->mem_offset + m;
+	msg = (u32 *)(c->mem_offset + m);
 	
 	/*
 	 *	Put together a scsi execscb message
diff -u --recursive --new-file v2.3.26/linux/drivers/i2o/i2o_scsi.h linux/drivers/i2o/i2o_scsi.h
--- v2.3.26/linux/drivers/i2o/i2o_scsi.h	Tue Sep  7 12:14:06 1999
+++ linux/drivers/i2o/i2o_scsi.h	Thu Nov 11 16:57:30 1999
@@ -14,8 +14,6 @@
 #define I2O_SCSI_CAN_QUEUE 4
 #define I2O_SCSI_CMD_PER_LUN 6
 
-extern struct proc_dir_entry proc_scsi_i2o_scsi;
-
 extern int i2o_scsi_detect(Scsi_Host_Template *);
 extern const char *i2o_scsi_info(struct Scsi_Host *);
 extern int i2o_scsi_command(Scsi_Cmnd *);
@@ -27,7 +25,7 @@
 
 #define I2OSCSI {                                          \
 		  next: NULL,				    \
-                  proc_dir:          &proc_scsi_i2o_scsi,   \
+                  proc_name:         "i2o_scsi",   \
                   name:              "I2O SCSI Layer", 	    \
                   detect:            i2o_scsi_detect,       \
                   release:	     i2o_scsi_release,	    \
diff -u --recursive --new-file v2.3.26/linux/drivers/isdn/Config.in linux/drivers/isdn/Config.in
--- v2.3.26/linux/drivers/isdn/Config.in	Fri Oct 15 15:25:13 1999
+++ linux/drivers/isdn/Config.in	Tue Nov  9 10:09:02 1999
@@ -14,7 +14,7 @@
 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 '  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
@@ -52,26 +52,28 @@
    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
+   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; 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
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; 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
 fi
 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
 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 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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/act2000/act2000_isa.c linux/drivers/isdn/act2000/act2000_isa.c
--- v2.3.26/linux/drivers/isdn/act2000/act2000_isa.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/act2000/act2000_isa.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 @@
  *   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 @@
 }
 
 int
-isa_detect(unsigned short portbase)
+act2000_isa_detect(unsigned short portbase)
 {
         int ret = 0;
         unsigned long flags;
@@ -117,13 +124,13 @@
         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 @@
                 /* 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 @@
 }
 
 static void
-isa_select_irq(act2000_card * card)
+act2000_isa_select_irq(act2000_card * card)
 {
 	unsigned char reg;
 
@@ -183,9 +190,9 @@
 }
 
 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 @@
  * 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 @@
         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 @@
                 }
         } 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 @@
                        "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 @@
 }
 
 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 @@
  * 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 @@
 }
 
 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 @@
 }
 
 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 @@
 }
 
 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 @@
 					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 @@
 				} 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 @@
 }
 
 void
-isa_send(act2000_card * card)
+act2000_isa_send(act2000_card * card)
 {
 	unsigned long flags;
 	struct sk_buff *skb;
@@ -410,11 +417,8 @@
 		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 @@
 		} else
 			dev_kfree_skb(skb);
 		card->sbuf = NULL;
-#if 0
-		printk(KERN_DEBUG "isa_send: %d bytes\n", l);
-#endif
 	}
 }
 
@@ -447,7 +448,7 @@
  * 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 @@
         while (1) {
                 if (count > 510)
                         return -EPROTO;
-                if (isa_readb(card, p++))
+                if (act2000_isa_readb(card, p++))
                         break;
                 count++;
         }
@@ -476,7 +477,7 @@
         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 @@
  * 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 @@
         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 @@
                 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 @@
                 p += l;
         }
         kfree(buf);
-        isa_delay(HZ / 2);
-        return (isa_getid(card));
+        act2000_isa_delay(HZ / 2);
+        return (act2000_isa_getid(card));
 }
diff -u --recursive --new-file v2.3.26/linux/drivers/isdn/act2000/act2000_isa.h linux/drivers/isdn/act2000/act2000_isa.h
--- v2.3.26/linux/drivers/isdn/act2000/act2000_isa.h	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/act2000/act2000_isa.h	Sun Nov  7 16:34:00 1999
@@ -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 @@
 
 /* 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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/act2000/capi.c linux/drivers/isdn/act2000/capi.c
--- v2.3.26/linux/drivers/isdn/act2000/capi.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/act2000/capi.c	Sun Nov  7 16:34:00 1999
@@ -113,10 +113,6 @@
 	{{ 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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/act2000/capi.h linux/drivers/isdn/act2000/capi.h
--- v2.3.26/linux/drivers/isdn/act2000/capi.h	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/act2000/capi.h	Sun Nov  7 16:34:00 1999
@@ -322,19 +322,6 @@
 			__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 @@
 			__u8  controller;
 			__u16 info __attribute__ ((packed));
 		} listen_conf;
-#endif
 		struct data_b3_req {
 			__u16 fakencci;
 			__u16 datalen;
diff -u --recursive --new-file v2.3.26/linux/drivers/isdn/act2000/module.c linux/drivers/isdn/act2000/module.c
--- v2.3.26/linux/drivers/isdn/act2000/module.c	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/act2000/module.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 {
 	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 @@
 {
 	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 @@
 				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 @@
         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 @@
         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 @@
 		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 @@
 			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 @@
 							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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/avmb1/Makefile linux/drivers/isdn/avmb1/Makefile
--- v2.3.26/linux/drivers/isdn/avmb1/Makefile	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/avmb1/Makefile	Sun Nov  7 16:34:00 1999
@@ -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 @@
   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 @@
   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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/avmb1/avmcard.h linux/drivers/isdn/avmb1/avmcard.h
--- v2.3.26/linux/drivers/isdn/avmb1/avmcard.h	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/avmb1/avmcard.h	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	__u8  sendbuf[128+2048];
 } avmcard_dmainfo;
 
+
 typedef struct avmcard {
 	char name[32];
 	unsigned int port;
@@ -81,25 +94,34 @@
 	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 @@
 }
 
 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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/avmb1/b1.c linux/drivers/isdn/avmb1/b1.c
--- v2.3.26/linux/drivers/isdn/avmb1/b1.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/avmb1/b1.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 @@
 		}
 		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 @@
 		}
 		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 @@
 	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 @@
 			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 @@
 			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_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 @@
 	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 @@
 		}
 	}
 
-	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 @@
 
 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 @@
 				__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_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_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_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 @@
 
 	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_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 @@
 		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 @@
 
 	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 @@
 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 @@
 	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 @@
 			(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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/avmb1/b1isa.c linux/drivers/isdn/avmb1/b1isa.c
--- v2.3.26/linux/drivers/isdn/avmb1/b1isa.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/avmb1/b1isa.c	Sun Nov  7 16:34:00 1999
@@ -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_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 @@
 	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 int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
 {
+	avmctrl_info *cinfo;
 	avmcard *card;
 	int retval;
 
@@ -120,6 +129,15 @@
 		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 @@
 		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 @@
 	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 @@
 	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 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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/avmb1/b1pci.c linux/drivers/isdn/avmb1/b1pci.c
--- v2.3.26/linux/drivers/isdn/avmb1/b1pci.c	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/avmb1/b1pci.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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_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 @@
 	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 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 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 @@
 
 	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 @@
 
 	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 @@
 	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 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/avmb1/b1pcmcia.c linux/drivers/isdn/avmb1/b1pcmcia.c
--- v2.3.26/linux/drivers/isdn/avmb1/b1pcmcia.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/avmb1/b1pcmcia.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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_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 @@
 				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 @@
 
 	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 @@
 
 	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 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c
--- v2.3.26/linux/drivers/isdn/avmb1/capi.c	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/avmb1/capi.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 		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 @@
 		return data.errcode;
 
 	case CAPI_INSTALLED:
-		if ((*capifuncs->capi_installed) ())
+		if ((*capifuncs->capi_isinstalled)() == CAPI_NOERROR)
 			return 0;
 		return -ENXIO;
 
@@ -615,16 +620,12 @@
 
 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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/avmb1/capidev.h linux/drivers/isdn/avmb1/capidev.h
--- v2.3.26/linux/drivers/isdn/avmb1/capidev.h	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/avmb1/capidev.h	Sun Nov  7 16:34:00 1999
@@ -44,11 +44,7 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/avmb1/capidrv.c linux/drivers/isdn/avmb1/capidrv.c
--- v2.3.26/linux/drivers/isdn/avmb1/capidrv.c	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/avmb1/capidrv.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
   /* 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 @@
 			);
 			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 @@
 				);
 				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 @@
 		        (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 @@
 	    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 void lower_callback(unsigned int cmd, __u16 contr, void *data)
+static void lower_callback(unsigned int cmd, __u32 contr, void *data)
 {
 
 	switch (cmd) {
diff -u --recursive --new-file v2.3.26/linux/drivers/isdn/avmb1/capiutil.c linux/drivers/isdn/avmb1/capiutil.c
--- v2.3.26/linux/drivers/isdn/avmb1/capiutil.c	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/avmb1/capiutil.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/avmb1/capiutil.h linux/drivers/isdn/avmb1/capiutil.h
--- v2.3.26/linux/drivers/isdn/avmb1/capiutil.h	Thu May 29 21:53:05 1997
+++ linux/drivers/isdn/avmb1/capiutil.h	Sun Nov  7 16:34:00 1999
@@ -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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/avmb1/kcapi.c linux/drivers/isdn/avmb1/kcapi.c
--- v2.3.26/linux/drivers/isdn/avmb1/kcapi.c	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/avmb1/kcapi.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 /* ------------------------------------------------------------- */
 
 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 @@
 
 /* -------- 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_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_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 @@
 /* -------- 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_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 @@
 	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 @@
 			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 @@
 
 		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 @@
 
 		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 @@
 
 		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 @@
 
 struct capi_interface avmb1_interface =
 {
-	capi_installed,
+	capi_isinstalled,
 	capi_register,
 	capi_release,
 	capi_put_message,
@@ -1479,6 +1498,12 @@
 #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
 
 /*
@@ -1527,6 +1552,12 @@
 #endif
 #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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/avmb1/t1isa.c linux/drivers/isdn/avmb1/t1isa.c
--- v2.3.26/linux/drivers/isdn/avmb1/t1isa.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/avmb1/t1isa.c	Sun Nov  7 16:34:00 1999
@@ -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 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 @@
 			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 @@
 			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 @@
 
 		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 @@
 	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 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 @@
 	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 @@
 	}
 
 	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 @@
 		}
 	}
 
-	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 @@
 
 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 @@
 	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 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 @@
 	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 @@
 
 	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 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 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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/avmb1/t1pci.c linux/drivers/isdn/avmb1/t1pci.c
--- v2.3.26/linux/drivers/isdn/avmb1/t1pci.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/avmb1/t1pci.c	Sun Nov  7 16:34:00 1999
@@ -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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/divert/divert_procfs.c linux/drivers/isdn/divert/divert_procfs.c
--- v2.3.26/linux/drivers/isdn/divert/divert_procfs.c	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/divert/divert_procfs.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 /**********************************/
 /* 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 @@
 /**********************************/
 /* 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 @@
 /***************************************/
 /* 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 @@
     }
   return mask;
 } /* isdn_divert_poll */
-#endif
 
 /****************/
 /* Open routine */
@@ -188,11 +165,7 @@
 /*******************/
 /* 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 @@
       kfree(inf);
     }
   MOD_DEC_USE_COUNT;
-#if (LINUX_VERSION_CODE < 0x020117)
-#else
   return(0);
-#endif
 } /* isdn_divert_close */
 
 /*********/
@@ -301,34 +271,12 @@
 
 
 #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 @@
 	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 @@
 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 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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/divert/isdn_divert.c linux/drivers/isdn/divert/isdn_divert.c
--- v2.3.26/linux/drivers/isdn/divert/isdn_divert.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/divert/isdn_divert.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
            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 @@
                       } 
 
 
-#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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/divert/isdn_divert.h linux/drivers/isdn/divert/isdn_divert.h
--- v2.3.26/linux/drivers/isdn/divert/isdn_divert.h	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/divert/isdn_divert.h	Sun Nov  7 16:34:00 1999
@@ -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 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 @@
 #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 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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/eicon/eicon.h linux/drivers/isdn/eicon/eicon.h
--- v2.3.26/linux/drivers/isdn/eicon/eicon.h	Tue Aug 31 17:29:13 1999
+++ linux/drivers/isdn/eicon/eicon.h	Sun Nov  7 16:34:00 1999
@@ -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 @@
 #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 @@
 
 /* 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 {
 	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 @@
 	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 @@
 #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 @@
 	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 @@
         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 @@
 #endif /* CONFIG_MCA */
 
 extern ulong DebugVar;
+extern void eicon_log(eicon_card * card, int level, const char *fmt, ...);
 
 #endif  /* __KERNEL__ */
 
diff -u --recursive --new-file v2.3.26/linux/drivers/isdn/eicon/eicon_idi.c linux/drivers/isdn/eicon/eicon_idi.c
--- v2.3.26/linux/drivers/isdn/eicon/eicon_idi.c	Tue Aug 31 17:29:13 1999
+++ linux/drivers/isdn/eicon/eicon_idi.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 			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 @@
 	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 @@
         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 @@
 	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_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 @@
 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 @@
 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 @@
 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 @@
 	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 @@
 	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 @@
 	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 @@
 				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 @@
 	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 @@
 	__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 @@
 		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 @@
 				}
 				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 @@
 				}
 				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 @@
 			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 @@
 					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 @@
 				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 @@
 			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 @@
 				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 @@
 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);
 
-	/* TODO , code follows */
+	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;
+
+	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;
+
+	if ((!card) || (!chan))
+		return;
 
-	/* TODO , code follows */
+	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) {
 
-	/* TODO , code follows */
+			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);
+
+		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
 
-	/* TODO , code follows */
+	if ((!ccard) || (!chan))
+		return -1;
 
-	return(0);
+	if (!chan->fax) {
+		eicon_log(ccard, 1, "idi_fax: senddata with NULL fax struct, ERROR\n");
+		return -1;
+	}
+
+	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 @@
 	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 @@
 	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 @@
 	'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 @@
 				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 @@
 			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 @@
 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_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 @@
 					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 @@
 				}
 				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 @@
 				}
 				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_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 @@
 		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 @@
 						}
 					}
 					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 @@
 				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 @@
 				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_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 @@
 #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 @@
 				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 @@
 	/* 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 @@
 						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 @@
 								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 @@
 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 @@
 
 		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 @@
 
 		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 @@
 		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 @@
 				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 @@
         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 @@
 
 	        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 @@
         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 @@
         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 @@
 	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 @@
         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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/eicon/eicon_io.c linux/drivers/isdn/eicon/eicon_io.c
--- v2.3.26/linux/drivers/isdn/eicon/eicon_io.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/eicon/eicon_io.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 						/* 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 @@
 			}
 		}
 		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 @@
 			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 @@
                 	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 @@
         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 @@
 	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 @@
 			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 @@
 				}
         	                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 @@
 		  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 @@
 				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 @@
 					   ((reqbuf->Req & 0x0f) == 0x01)) { /* Send Data */
 						chan->waitq = reqbuf->XBuffer.length;
 						chan->waitpq += reqbuf->XBuffer.length;
+						dlev = 128;
 					}
 				}
 
@@ -544,13 +563,12 @@
 			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 @@
 		} 
 		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 @@
 	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 @@
 			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 @@
 		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 @@
 	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 @@
 		} 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 @@
 			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 @@
 				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 @@
                         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 @@
 				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 @@
 					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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/eicon/eicon_isa.c linux/drivers/isdn/eicon/eicon_isa.c
--- v2.3.26/linux/drivers/isdn/eicon/eicon_isa.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/eicon/eicon_isa.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 		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 @@
 		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 @@
 
 	/* 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 @@
 		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 @@
 		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 @@
 		/* 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 @@
 		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 @@
         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 @@
 			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 @@
 		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 @@
 			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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/eicon/eicon_isa.h linux/drivers/isdn/eicon/eicon_isa.h
--- v2.3.26/linux/drivers/isdn/eicon/eicon_isa.h	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/eicon/eicon_isa.h	Sun Nov  7 16:34:00 1999
@@ -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 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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/eicon/eicon_mod.c linux/drivers/isdn/eicon/eicon_mod.c
--- v2.3.26/linux/drivers/isdn/eicon/eicon_mod.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/eicon/eicon_mod.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 {
 	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 @@
 	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_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_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_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 @@
 	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 @@
 	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 @@
 							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 @@
 						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 @@
 							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 @@
 							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_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 @@
 							}
 							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;
 					}
@@ -592,18 +537,6 @@
                                                         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))))
 						return -EFAULT;
@@ -612,7 +545,7 @@
 					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 @@
 			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 @@
 			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 @@
 		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 @@
 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 @@
 	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 @@
 				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 @@
 	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 @@
 		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 @@
 						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 @@
 					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 @@
 					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 @@
 				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 @@
 		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 @@
 			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 @@
 		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 @@
 			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 @@
 
 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 @@
 					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 @@
                         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 @@
 #define eicon_init init_module
 #endif
 
-int __init
+int
 eicon_init(void)
 {
 	int card_count = 0;
@@ -1317,10 +1382,9 @@
                 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 @@
         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 @@
 
 #else /* no module */
 
-#ifdef COMPAT_HAS_NEW_SETUP
 static int __init
 eicon_setup(char *line)
 {
@@ -1391,12 +1456,6 @@
 	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 @@
 #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 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 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 @@
 			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 @@
 			if (irq == -1) { 
 				irq = cards_irq;
 			} else {
-				if (irq != irq)
+				if (irq != cards_irq)
 					return ENODEV;
 			};
 			type = 0; 
@@ -1591,8 +1644,12 @@
         	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/eicon/eicon_pci.c linux/drivers/isdn/eicon/eicon_pci.c
--- v2.3.26/linux/drivers/isdn/eicon/eicon_pci.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/eicon/eicon_pci.c	Sun Nov  7 16:34:00 1999
@@ -152,8 +152,8 @@
           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 @@
          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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/Makefile linux/drivers/isdn/hisax/Makefile
--- v2.3.26/linux/drivers/isdn/hisax/Makefile	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/hisax/Makefile	Sun Nov  7 16:34:00 1999
@@ -30,6 +30,8 @@
 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 @@
 	 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 @@
 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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/amd7930.c linux/drivers/isdn/hisax/amd7930.c
--- v2.3.26/linux/drivers/isdn/hisax/amd7930.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/amd7930.c	Sun Nov  7 16:34:00 1999
@@ -749,8 +749,8 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/arcofi.c linux/drivers/isdn/hisax/arcofi.c
--- v2.3.26/linux/drivers/isdn/hisax/arcofi.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/hisax/arcofi.c	Sun Nov  7 16:34:00 1999
@@ -154,8 +154,6 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/asuscom.c linux/drivers/isdn/hisax/asuscom.c
--- v2.3.26/linux/drivers/isdn/hisax/asuscom.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/asuscom.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 		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 @@
 	return(0);
 }
 
-int __init
-setup_asuscom(struct IsdnCard *card)
+__initfunc(int
+setup_asuscom(struct IsdnCard *card))
 {
 	int bytecnt;
 	struct IsdnCardState *cs = card->cs;
diff -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/avm_a1.c linux/drivers/isdn/hisax/avm_a1.c
--- v2.3.26/linux/drivers/isdn/hisax/avm_a1.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/avm_a1.c	Sun Nov  7 16:34:00 1999
@@ -227,8 +227,8 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/avm_a1p.c linux/drivers/isdn/hisax/avm_a1p.c
--- v2.3.26/linux/drivers/isdn/hisax/avm_a1p.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/avm_a1p.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 			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 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/avm_pci.c linux/drivers/isdn/hisax/avm_pci.c
--- v2.3.26/linux/drivers/isdn/hisax/avm_pci.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/avm_pci.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 				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 @@
 		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 @@
 	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 @@
 	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 @@
 		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 @@
 				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 @@
 			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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/bkm_a4t.c linux/drivers/isdn/hisax/bkm_a4t.c
--- v2.3.26/linux/drivers/isdn/hisax/bkm_a4t.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/bkm_a4t.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 		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 @@
 		    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 @@
 	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 @@
 		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 @@
 			&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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/bkm_a8.c linux/drivers/isdn/hisax/bkm_a8.c
--- v2.3.26/linux/drivers/isdn/hisax/bkm_a8.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/bkm_a8.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 
 			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 @@
 	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 @@
 		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 @@
 			&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 @@
 		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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/callc.c linux/drivers/isdn/hisax/callc.c
--- v2.3.26/linux/drivers/isdn/hisax/callc.c	Tue Aug 31 17:29:13 1999
+++ linux/drivers/isdn/hisax/callc.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	int ret=0;
 
 	while ((skb = skb_dequeue(q))) {
-		idev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb(skb);
 		ret++;
 	}
 	return(ret);
@@ -1122,12 +1132,37 @@
 }
 
 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;
@@ -1166,28 +1201,6 @@
 }
 
 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)
 {
 	struct Channel *chanp = csta->channel + chan;
@@ -1209,10 +1222,6 @@
 	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 @@
 			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 @@
 				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 @@
 	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 @@
 	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):
@@ -1475,11 +1484,6 @@
 }
 
 static void
-channel_report(struct Channel *chanp)
-{
-}
-
-static void
 distr_debug(struct IsdnCardState *csta, int debugflags)
 {
 	int i;
@@ -1512,7 +1516,6 @@
 {
 	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 @@
 		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 @@
 		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 @@
 				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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/config.c linux/drivers/isdn/hisax/config.c
--- v2.3.26/linux/drivers/isdn/hisax/config.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/config.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
  "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 @@
 #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 @@
 #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 @@
 #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 @@
 #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 @@
 {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(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 @@
 
 	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 @@
 #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 @@
 	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 @@
 		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_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_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 @@
 		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 @@
 	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);
@@ -1254,6 +1248,11 @@
  			ret = setup_gazel(card);
  			break;
 #endif
+#if CARD_W6692
+		case ISDN_CTYPE_W6692:
+			ret = setup_w6692(card);
+			break;
+#endif
 		default:
 			printk(KERN_WARNING
 				"HiSax: Support for %s Card not selected\n",
@@ -1357,6 +1356,7 @@
 				kfree((void *) cards[i].cs);
 			cards[i].cs = NULL;
 			HiSax_shiftcards(i);
+			nrcards--;
 		}
 	}
 	return foundcards;
@@ -1387,12 +1387,9 @@
 }
 
 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 @@
 	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 @@
 #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 @@
 				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 @@
 			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 @@
 	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 @@
 
 	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 @@
 
 	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 @@
 
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/diva.c linux/drivers/isdn/hisax/diva.c
--- v2.3.26/linux/drivers/isdn/hisax/diva.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/diva.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 				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 @@
 			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 @@
 				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 @@
 	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 @@
 	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 @@
 		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 @@
 			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 @@
 			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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/elsa.c linux/drivers/isdn/hisax/elsa.c
--- v2.3.26/linux/drivers/isdn/hisax/elsa.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/hisax/elsa.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 		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 @@
 				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 @@
 	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 @@
 		       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 @@
 			 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 @@
 			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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/elsa_ser.c linux/drivers/isdn/hisax/elsa_ser.c
--- v2.3.26/linux/drivers/isdn/hisax/elsa_ser.c	Sun Aug 15 11:49:08 1999
+++ linux/drivers/isdn/hisax/elsa_ser.c	Sun Nov  7 16:34:00 1999
@@ -298,7 +298,7 @@
 				(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 @@
 	}
 }
 
-#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 @@
 			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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/gazel.c linux/drivers/isdn/hisax/gazel.c
--- v2.3.26/linux/drivers/isdn/hisax/gazel.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/gazel.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 @@
 	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 @@
 					seekcard = GAZEL_DJINN_ITOO;
 					break;
 			}
-#ifndef COMPAT_HAS_NEW_PCI
-			pci_index = 0;
-#endif
 		}
 	}
 	if (!found) {
@@ -690,8 +657,8 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/hfc_2bds0.c linux/drivers/isdn/hisax/hfc_2bds0.c
--- v2.3.26/linux/drivers/isdn/hisax/hfc_2bds0.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/hfc_2bds0.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 		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 @@
 	} 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 @@
 			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 @@
 					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 @@
 		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 @@
 		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 @@
 */
 	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 @@
 			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 @@
 				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 @@
 						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 @@
 	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 @@
 					}
 					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 @@
 			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 @@
 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 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/hfc_2bs0.c linux/drivers/isdn/hisax/hfc_2bs0.c
--- v2.3.26/linux/drivers/isdn/hisax/hfc_2bs0.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/hfc_2bs0.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 		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 @@
 		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 @@
 				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 @@
 		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 @@
 		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 @@
 	return (0);
 }
 
-void __init
-init_send(struct BCState *bcs)
+__initfunc(void
+init_send(struct BCState *bcs))
 {
 	int i;
 
@@ -573,8 +581,8 @@
 		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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/hfc_pci.c linux/drivers/isdn/hisax/hfc_pci.c
--- v2.3.26/linux/drivers/isdn/hisax/hfc_pci.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/hfc_pci.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 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 @@
 {
 	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 @@
 	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 @@
 	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 @@
 	} 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 @@
 			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 @@
 /*******************************************************************************/
 /* 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;
-
-  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 <= 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 */
+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;
+
+	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 */
+
+	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 @@
 			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 @@
 	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 @@
 	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 @@
 	}
 
 	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 */
+		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);
 
-	      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;
+			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 @@
 	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 @@
 		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 @@
 		goto Begin;
 	restore_flags(flags);
 	return;
-} /* receive_emsg */
+}				/* receive_emsg */
 
 /*********************/
 /* Interrupt handler */
@@ -919,6 +1006,9 @@
 		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 @@
 			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 @@
 		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 @@
 			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 @@
 					}
 					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 @@
 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 @@
 {
 	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 @@
 			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 @@
 {
 	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 @@
 		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 @@
 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 @@
 /*************************************/
 /* 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 @@
 /********************************/
 /* 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 @@
 			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 @@
 
 
 /* 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 @@
 				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 @@
 		    (((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 @@
 
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/hfc_pci.h linux/drivers/isdn/hisax/hfc_pci.h
--- v2.3.26/linux/drivers/isdn/hisax/hfc_pci.h	Tue Aug 31 17:29:13 1999
+++ linux/drivers/isdn/hisax/hfc_pci.h	Sun Nov  7 16:34:00 1999
@@ -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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/hfcscard.c linux/drivers/isdn/hisax/hfcscard.c
--- v2.3.26/linux/drivers/isdn/hisax/hfcscard.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/hfcscard.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 @@
 			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 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/hisax.h linux/drivers/isdn/hisax/hisax.h
--- v2.3.26/linux/drivers/isdn/hisax/hisax.h	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/hisax.h	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 @@
 	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 hfcB_hw hfc;
 		struct tiger_hw tiger;
 		struct amd7930_hw  amd7930;
+		struct w6692B_hw w6692;
 	} hw;
 };
 
@@ -744,7 +770,8 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 #endif
 		struct bkm_hw ax;
 		struct gazel_hw gazel;
+		struct w6692_hw w6692;
 	} hw;
 	int myid;
 	isdn_if iif;
@@ -940,6 +968,7 @@
 		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 @@
 	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 @@
 #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 @@
 #define __initdata
 #endif
 
-#ifndef __init
-#define __init
-#endif
-
 #define HISAX_INITFUNC(__arginit) __initfunc(__arginit)
 #define HISAX_INITDATA __initdata
 
@@ -1243,6 +1274,15 @@
 #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_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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/hscx.c linux/drivers/isdn/hisax/hscx.c
--- v2.3.26/linux/drivers/isdn/hisax/hscx.c	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/hisax/hscx.c	Sun Nov  7 16:34:00 1999
@@ -219,7 +219,7 @@
 		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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/hscx_irq.c linux/drivers/isdn/hisax/hscx_irq.c
--- v2.3.26/linux/drivers/isdn/hisax/hscx_irq.c	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/hisax/hscx_irq.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 @@
 				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 @@
 			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 @@
 				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 @@
 			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 @@
 				/* 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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/isac.c linux/drivers/isdn/hisax/isac.c
--- v2.3.26/linux/drivers/isdn/hisax/isac.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/hisax/isac.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 @@
 				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_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 @@
 		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 @@
 			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 @@
 			/* 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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/isar.c linux/drivers/isdn/hisax/isar.c
--- v2.3.26/linux/drivers/isdn/hisax/isar.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/hisax/isar.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 @@
 			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 @@
 				} 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 @@
 			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 @@
 			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 @@
 					&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 @@
 		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 @@
 						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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/isar.h linux/drivers/isdn/hisax/isar.h
--- v2.3.26/linux/drivers/isdn/hisax/isar.h	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/hisax/isar.h	Sun Nov  7 16:34:00 1999
@@ -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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/isdnl1.c linux/drivers/isdn/hisax/isdnl1.c
--- v2.3.26/linux/drivers/isdn/hisax/isdnl1.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/hisax/isdnl1.c	Sun Nov  7 16:34:00 1999
@@ -318,12 +318,12 @@
 		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 @@
 					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 @@
 				} else
 					stptr = stptr->next;
 			if (!found)
-				idev_kfree_skb(skb, FREE_READ);
+				dev_kfree_skb(skb);
 		}
 	}
 }
diff -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/isdnl2.c linux/drivers/isdn/hisax/isdnl2.c
--- v2.3.26/linux/drivers/isdn/hisax/isdnl2.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/hisax/isdnl2.c	Sun Nov  7 16:34:00 1999
@@ -201,7 +201,7 @@
 	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 @@
 		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 @@
 		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 @@
 inline void
 FreeSkb(struct sk_buff *skb)
 {
-	idev_kfree_skb(skb, FREE_READ);
+	dev_kfree_skb(skb);
 }
 
 
@@ -970,7 +969,6 @@
 		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 @@
 	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 @@
 		"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 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/isdnl3.c linux/drivers/isdn/hisax/isdnl3.c
--- v2.3.26/linux/drivers/isdn/hisax/isdnl3.c	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/hisax/isdnl3.c	Sun Nov  7 16:34:00 1999
@@ -260,7 +260,6 @@
 		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 @@
 
 	HiSax_putstatus(st->l1.hardware, "L3", "no D protocol");
 	if (skb) {
-		idev_kfree_skb(skb, FREE_READ);
+		dev_kfree_skb(skb);
 	}
 }
 
diff -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/isurf.c linux/drivers/isdn/hisax/isurf.c
--- v2.3.26/linux/drivers/isdn/hisax/isurf.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/isurf.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/ix1_micro.c linux/drivers/isdn/hisax/ix1_micro.c
--- v2.3.26/linux/drivers/isdn/hisax/ix1_micro.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/ix1_micro.c	Sun Nov  7 16:34:00 1999
@@ -282,8 +282,8 @@
 }
 
 
-int __init
-setup_ix1micro(struct IsdnCard *card)
+__initfunc(int
+setup_ix1micro(struct IsdnCard *card))
 {
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
diff -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/jade.c linux/drivers/isdn/hisax/jade.c
--- v2.3.26/linux/drivers/isdn/hisax/jade.c	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/hisax/jade.c	Sun Nov  7 16:34:00 1999
@@ -214,7 +214,7 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/jade_irq.c linux/drivers/isdn/hisax/jade_irq.c
--- v2.3.26/linux/drivers/isdn/hisax/jade_irq.c	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/hisax/jade_irq.c	Sun Nov  7 16:34:00 1999
@@ -161,7 +161,6 @@
 				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 @@
 			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 @@
 				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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/l3_1tr6.c linux/drivers/isdn/hisax/l3_1tr6.c
--- v2.3.26/linux/drivers/isdn/hisax/l3_1tr6.c	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/hisax/l3_1tr6.c	Sun Nov  7 16:34:00 1999
@@ -94,14 +94,14 @@
 {
 	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 @@
 		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_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_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 @@
 {
 	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 @@
 		}
 	} 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 @@
 {
 	struct sk_buff *skb = arg;
 
-	idev_kfree_skb(skb, FREE_READ);
+	dev_kfree_skb(skb);
 }
 
 static void
@@ -386,7 +386,7 @@
 		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_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 @@
 {
 	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_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_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 @@
 			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 @@
 				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 @@
 			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 @@
 							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 @@
 				(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 @@
 						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 @@
 			    ((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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/l3dss1.c linux/drivers/isdn/hisax/l3dss1.c
--- v2.3.26/linux/drivers/isdn/hisax/l3dss1.c	Thu Aug 26 13:05:37 1999
+++ linux/drivers/isdn/hisax/l3dss1.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 @@
 
 	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 @@
 	}
 	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 @@
 				 (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 @@
 	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 @@
 				/* 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 @@
 				 * 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 @@
 					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 @@
 		}
 	}
 	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 @@
 		}
 		datastatelist[i].rout(proc, pr, skb);
 	}
-	idev_kfree_skb(skb, FREE_READ);
+	dev_kfree_skb(skb);
 	return;
 }
 
diff -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/md5sums.asc linux/drivers/isdn/hisax/md5sums.asc
--- v2.3.26/linux/drivers/isdn/hisax/md5sums.asc	Thu Aug 26 13:05:37 1999
+++ linux/drivers/isdn/hisax/md5sums.asc	Sun Nov  7 16:34:00 1999
@@ -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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/mic.c linux/drivers/isdn/hisax/mic.c
--- v2.3.26/linux/drivers/isdn/hisax/mic.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/mic.c	Sun Nov  7 16:34:00 1999
@@ -224,8 +224,8 @@
 	return(0);
 }
 
-int __init
-setup_mic(struct IsdnCard *card)
+__initfunc(int
+setup_mic(struct IsdnCard *card))
 {
 	int bytecnt;
 	struct IsdnCardState *cs = card->cs;
diff -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/netjet.c linux/drivers/isdn/hisax/netjet.c
--- v2.3.26/linux/drivers/isdn/hisax/netjet.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/netjet.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 @@
 							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 @@
 				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 @@
 	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 @@
 				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 @@
 	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 @@
 		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 @@
 }
 
  
-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 @@
 	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 @@
 	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 @@
 		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 @@
 			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 @@
 		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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/niccy.c linux/drivers/isdn/hisax/niccy.c
--- v2.3.26/linux/drivers/isdn/hisax/niccy.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/niccy.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 @@
 	} 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 @@
 				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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/s0box.c linux/drivers/isdn/hisax/s0box.c
--- v2.3.26/linux/drivers/isdn/hisax/s0box.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/s0box.c	Sun Nov  7 16:34:00 1999
@@ -212,8 +212,8 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/saphir.c linux/drivers/isdn/hisax/saphir.c
--- v2.3.26/linux/drivers/isdn/hisax/saphir.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/saphir.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 @@
 }
 
 
-int __init
-setup_saphir(struct IsdnCard *card)
+__initfunc(int
+setup_saphir(struct IsdnCard *card))
 {
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
diff -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/sedlbauer.c linux/drivers/isdn/hisax/sedlbauer.c
--- v2.3.26/linux/drivers/isdn/hisax/sedlbauer.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/sedlbauer.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 			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 @@
 			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 @@
 }
 
 #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 @@
 /* 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 @@
 				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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/sportster.c linux/drivers/isdn/hisax/sportster.c
--- v2.3.26/linux/drivers/isdn/hisax/sportster.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/sportster.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 @@
 	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 @@
 	}
 }
 
-int __init
-setup_sportster(struct IsdnCard *card)
+__initfunc(int
+setup_sportster(struct IsdnCard *card))
 {
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
diff -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/tei.c linux/drivers/isdn/hisax/tei.c
--- v2.3.26/linux/drivers/isdn/hisax/tei.c	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/hisax/tei.c	Sun Nov  7 16:34:00 1999
@@ -169,7 +169,6 @@
 		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 @@
 	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 @@
 		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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/teleint.c linux/drivers/isdn/hisax/teleint.c
--- v2.3.26/linux/drivers/isdn/hisax/teleint.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/teleint.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 @@
 		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 @@
 	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 @@
 		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 @@
 	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 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/teles0.c linux/drivers/isdn/hisax/teles0.c
--- v2.3.26/linux/drivers/isdn/hisax/teles0.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/teles0.c	Sun Nov  7 16:34:00 1999
@@ -295,8 +295,8 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/teles3.c linux/drivers/isdn/hisax/teles3.c
--- v2.3.26/linux/drivers/isdn/hisax/teles3.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/teles3.c	Sun Nov  7 16:34:00 1999
@@ -321,8 +321,8 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/telespci.c linux/drivers/isdn/hisax/telespci.c
--- v2.3.26/linux/drivers/isdn/hisax/telespci.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/isdn/hisax/telespci.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 @@
 			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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/w6692.c linux/drivers/isdn/hisax/w6692.c
--- v2.3.26/linux/drivers/isdn/hisax/w6692.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/w6692.c	Sun Nov  7 16:34:00 1999
@@ -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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/hisax/w6692.h linux/drivers/isdn/hisax/w6692.h
--- v2.3.26/linux/drivers/isdn/hisax/w6692.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/w6692.h	Sun Nov  7 16:34:00 1999
@@ -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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/icn/icn.c linux/drivers/isdn/icn/icn.c
--- v2.3.26/linux/drivers/isdn/icn/icn.c	Tue Aug 31 17:29:13 1999
+++ linux/drivers/isdn/icn/icn.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 			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 @@
 			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 @@
 #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 @@
 	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_id2 = sid2;
 		}
 	}
-#ifdef COMPAT_HAS_NEW_SETUP
 	return(1);
 }
 __setup("icn=", icn_setup);
-#else
-}
-#endif
 #endif /* MODULES */
 
 int
diff -u --recursive --new-file v2.3.26/linux/drivers/isdn/icn/icn.h linux/drivers/isdn/icn/icn.h
--- v2.3.26/linux/drivers/isdn/icn/icn.h	Sun May 23 10:03:41 1999
+++ linux/drivers/isdn/icn/icn.h	Sun Nov  7 16:34:00 1999
@@ -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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- v2.3.26/linux/drivers/isdn/isdn_common.c	Fri Oct 15 15:25:13 1999
+++ linux/drivers/isdn/isdn_common.c	Sun Nov  7 16:34:00 1999
@@ -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_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 @@
  * 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 @@
  * 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 @@
 	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 @@
 		/* 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 @@
 
 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 @@
 	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 @@
 
 	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 @@
 		}
 		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 @@
 	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 @@
 			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 @@
 		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 @@
 		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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/isdn_common.h linux/drivers/isdn/isdn_common.h
--- v2.3.26/linux/drivers/isdn/isdn_common.h	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/isdn_common.h	Sun Nov  7 16:34:00 1999
@@ -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 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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
--- v2.3.26/linux/drivers/isdn/isdn_net.c	Thu Aug 26 13:05:37 1999
+++ linux/drivers/isdn/isdn_net.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 @@
 				    (!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 @@
 							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 @@
 						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 @@
 							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 @@
 							lp->netdev->dev.tbusy = 0;
 							mark_bh(NET_BH);
 						}
+#endif /* ISDN_NEW_TBUSY */
 						return 1;
 				}
 				break;
@@ -1162,6 +1260,7 @@
 					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 @@
  * 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 @@
 	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 @@
 			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 @@
 #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 @@
    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 @@
 			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 @@
 					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 @@
 
 				/* 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 @@
 					}
 					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 @@
 				}
 				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_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 @@
 }
 
 /*
- * 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_phone *n;
 	ulong flags;
 	char nr[32];
-
 	/* Search name in netdev-chain */
 	save_flags(flags);
 	cli();
@@ -2258,10 +2407,15 @@
 					       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 @@
 			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 @@
 	if (dev->netdev == NULL)
 		isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
 	restore_flags(flags);
-
 	kfree(p->local);
 	kfree(p);
 
diff -u --recursive --new-file v2.3.26/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
--- v2.3.26/linux/drivers/isdn/isdn_ppp.c	Thu Aug 26 13:05:37 1999
+++ linux/drivers/isdn/isdn_ppp.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 				    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 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 @@
 		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 @@
 
 	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 @@
 		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 @@
 	}
 	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 @@
 	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 @@
 	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 @@
 			}
 			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 @@
 	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 @@
 			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_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 @@
 					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 @@
 		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_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 @@
 	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 @@
 	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 @@
 
 	/* 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 @@
 		 * 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 @@
 		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 @@
 
 	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 @@
 	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 @@
 {
 	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 @@
 	   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 @@
 			       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 @@
     }
 
 	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 @@
 	}
 
 	/* 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 @@
 	}
 }
 
-
 int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc)
 {
 	ipc->next = ipc_head;
@@ -2949,6 +2952,16 @@
 		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 @@
 	}
 	return -EINVAL;
 }
-
-
diff -u --recursive --new-file v2.3.26/linux/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c
--- v2.3.26/linux/drivers/isdn/isdn_tty.c	Tue Aug 31 17:29:13 1999
+++ linux/drivers/isdn/isdn_tty.c	Sun Nov  7 16:34:00 1999
@@ -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 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 @@
 isdn_tty_modem_hup(modem_info * info, int local)
 {
 	isdn_ctrl cmd;
-	int usage;
 
 	if (!info)
 		return;
@@ -1068,10 +1091,7 @@
 		}
 		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 @@
 	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 @@
 	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_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 @@
 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 @@
 		 */
 		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 @@
 	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 @@
 			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 @@
 		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 @@
 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 @@
 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 @@
 		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 @@
 				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 @@
 			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 @@
 			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 @@
 			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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/isdn_tty.h linux/drivers/isdn/isdn_tty.h
--- v2.3.26/linux/drivers/isdn/isdn_tty.h	Thu Aug 26 13:05:37 1999
+++ linux/drivers/isdn/isdn_tty.h	Sun Nov  7 16:34:00 1999
@@ -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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/isdn_ttyfax.c linux/drivers/isdn/isdn_ttyfax.c
--- v2.3.26/linux/drivers/isdn/isdn_ttyfax.c	Thu Aug 26 13:05:37 1999
+++ linux/drivers/isdn/isdn_ttyfax.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 			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 @@
                 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 @@
                 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 @@
                 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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/isdn_v110.c linux/drivers/isdn/isdn_v110.c
--- v2.3.26/linux/drivers/isdn/isdn_v110.c	Wed Apr  1 16:21:03 1998
+++ linux/drivers/isdn/isdn_v110.c	Sun Nov  7 16:34:00 1999
@@ -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_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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/isdn_v110.h linux/drivers/isdn/isdn_v110.h
--- v2.3.26/linux/drivers/isdn/isdn_v110.h	Wed Apr  1 16:21:03 1998
+++ linux/drivers/isdn/isdn_v110.h	Sun Nov  7 16:34:00 1999
@@ -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_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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/isdnloop/isdnloop.c linux/drivers/isdn/isdnloop/isdnloop.c
--- v2.3.26/linux/drivers/isdn/isdnloop/isdnloop.c	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/isdnloop/isdnloop.c	Sun Nov  7 16:34:00 1999
@@ -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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/isdnloop/isdnloop.h linux/drivers/isdn/isdnloop/isdnloop.h
--- v2.3.26/linux/drivers/isdn/isdnloop/isdnloop.h	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/isdnloop/isdnloop.h	Sun Nov  7 16:34:00 1999
@@ -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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/pcbit/drv.c linux/drivers/isdn/pcbit/drv.c
--- v2.3.26/linux/drivers/isdn/pcbit/drv.c	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/pcbit/drv.c	Sun Nov  7 16:34:00 1999
@@ -86,9 +86,7 @@
 
 	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 @@
 		       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 @@
 				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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/pcbit/layer2.c linux/drivers/isdn/pcbit/layer2.c
--- v2.3.26/linux/drivers/isdn/pcbit/layer2.c	Thu May 21 13:45:01 1998
+++ linux/drivers/isdn/pcbit/layer2.c	Sun Nov  7 16:34:00 1999
@@ -375,16 +375,11 @@
 
 		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 @@
 
 		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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/pcbit/module.c linux/drivers/isdn/pcbit/module.c
--- v2.3.26/linux/drivers/isdn/pcbit/module.c	Tue Aug 31 17:29:13 1999
+++ linux/drivers/isdn/pcbit/module.c	Sun Nov  7 16:34:00 1999
@@ -102,7 +102,6 @@
 }
 
 #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 @@
 	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 @@
 
 		i++;
 	}
-#ifdef COMPAT_HAS_NEW_SETUP
 	return(1);
 }
 __setup("pcbit=", pcbit_setup);
-#else
-}
-#endif
 #endif
 
 
diff -u --recursive --new-file v2.3.26/linux/drivers/isdn/pcbit/pcbit.h linux/drivers/isdn/pcbit/pcbit.h
--- v2.3.26/linux/drivers/isdn/pcbit/pcbit.h	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/pcbit/pcbit.h	Sun Nov  7 16:34:00 1999
@@ -68,11 +68,7 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/sc/init.c linux/drivers/isdn/sc/init.c
--- v2.3.26/linux/drivers/isdn/sc/init.c	Thu Nov  5 09:58:44 1998
+++ linux/drivers/isdn/sc/init.c	Sun Nov  7 16:34:00 1999
@@ -164,7 +164,7 @@
 		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 @@
 	 * 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 @@
 	 * 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 @@
 	 */
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/sc/ioctl.c linux/drivers/isdn/sc/ioctl.c
--- v2.3.26/linux/drivers/isdn/sc/ioctl.c	Thu May 29 21:53:06 1997
+++ linux/drivers/isdn/sc/ioctl.c	Sun Nov  7 16:34:00 1999
@@ -15,9 +15,6 @@
 
 extern board *adapter[];
 
-#if 0
-static char *ChannelStates[] = { "Idle", "Ready", "Connecting", "Connected", "Disconnecting" };
-#endif
 
 int GetStatus(int card, boardInfo *);
 
@@ -42,7 +39,7 @@
 
 		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 @@
 		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 @@
 	{
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 		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 @@
 
 		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 @@
 		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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/sc/message.c linux/drivers/isdn/sc/message.c
--- v2.3.26/linux/drivers/isdn/sc/message.c	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/sc/message.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 -u --recursive --new-file v2.3.26/linux/drivers/isdn/sc/packet.c linux/drivers/isdn/sc/packet.c
--- v2.3.26/linux/drivers/isdn/sc/packet.c	Wed Apr  1 16:21:04 1998
+++ linux/drivers/isdn/sc/packet.c	Sun Nov  7 16:34:00 1999
@@ -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 @@
 	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 @@
 		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 @@
 				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 @@
 			++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 @@
 	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 @@
 	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 @@
 		/*
 	 	 * 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 @@
 	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 @@
 	/*
 	 * 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 -u --recursive --new-file v2.3.26/linux/drivers/misc/Config.in linux/drivers/misc/Config.in
--- v2.3.26/linux/drivers/misc/Config.in	Sat Oct  9 11:47:50 1999
+++ linux/drivers/misc/Config.in	Mon Nov  8 17:59:15 1999
@@ -4,6 +4,6 @@
 mainmenu_option next_comment
 comment 'Misc devices'
 
-tristate 'Generic ACPI support' CONFIG_ACPI
+bool 'ACPI support' CONFIG_ACPI
 
 endmenu
diff -u --recursive --new-file v2.3.26/linux/drivers/misc/Makefile linux/drivers/misc/Makefile
--- v2.3.26/linux/drivers/misc/Makefile	Sat Oct  9 11:47:50 1999
+++ linux/drivers/misc/Makefile	Mon Nov  8 17:59:15 1999
@@ -19,11 +19,7 @@
 OX_OBJS  :=
 
 ifeq ($(CONFIG_ACPI),y)
-  O_OBJS += acpi.o
-else
-  ifeq ($(CONFIG_ACPI),m)
-    M_OBJS += acpi.o
-  endif
+  OX_OBJS += acpi.o
 endif
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.26/linux/drivers/misc/acpi.c linux/drivers/misc/acpi.c
--- v2.3.26/linux/drivers/misc/acpi.c	Mon Nov  1 13:56:26 1999
+++ linux/drivers/misc/acpi.c	Wed Nov 10 20:01:03 1999
@@ -54,6 +54,7 @@
 #define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue * x = NULL
 #endif
 
+static int acpi_idle_thread(void *context);
 static int acpi_do_ulong(ctl_table *ctl,
 			 int write,
 			 struct file *file,
@@ -69,6 +70,13 @@
 			 struct file *file,
 			 void *buffer,
 			 size_t *len);
+static int acpi_do_sleep_wake(ctl_table *ctl,
+			      int write,
+			      struct file *file,
+			      void *buffer,
+			      size_t *len);
+
+DECLARE_WAIT_QUEUE_HEAD(acpi_idle_wait);
 
 static struct ctl_table_header *acpi_sysctl = NULL;
 
@@ -84,6 +92,9 @@
 static volatile u32 acpi_gpe_level = 0;
 static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait);
 
+static spinlock_t acpi_devs_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(acpi_devs);
+
 /* Make it impossible to enter L2/L3 until after we've initialized */
 static unsigned long acpi_p_lvl2_lat = ~0UL;
 static unsigned long acpi_p_lvl3_lat = ~0UL;
@@ -147,6 +158,11 @@
 	 &acpi_slp_typ[5], sizeof(acpi_slp_typ[5]),
 	 0600, NULL, &acpi_do_ulong},
 
+#if 0
+	{123, "sleep", (void*) 1, 0, 0600, NULL, &acpi_do_sleep_wake},
+	{124, "wake", NULL, 0, 0600, NULL, &acpi_do_sleep_wake},
+#endif
+
 	{0}
 };
 
@@ -319,15 +335,23 @@
 	if (addr) {
 		// map table header to determine size
 		table = (struct acpi_table *)
-			ioremap_nocache((unsigned long) addr,
-					sizeof(struct acpi_table));
+			ioremap((unsigned long) addr,
+				sizeof(struct acpi_table));
 		if (table) {
 			unsigned long table_size = table->length;
 			iounmap(table);
 			// remap entire table
 			table = (struct acpi_table *)
-				ioremap_nocache((unsigned long) addr,
-						table_size);
+				ioremap((unsigned long) addr, table_size);
+		}
+
+		if (!table) {
+			/* ioremap is a pain, it returns NULL if the
+			 * table starts within mapped physical memory.
+			 * Hopefully, no table straddles a mapped/unmapped
+			 * physical memory boundary, ugh
+			 */
+			table = (struct acpi_table*) phys_to_virt(addr);
 		}
 	}
 	return table;
@@ -338,6 +362,7 @@
  */
 static void acpi_unmap_table(struct acpi_table *table)
 {
+	// iounmap ignores addresses within physical memory
 	if (table)
 		iounmap(table);
 }
@@ -380,8 +405,14 @@
 
 	// fetch RSDT from RSDP
 	rsdt = acpi_map_table(rsdp->rsdt);
-	if (!rsdt || rsdt->signature != ACPI_RSDT_SIG) {
-		printk(KERN_ERR "ACPI: missing RSDT\n");
+	if (!rsdt) {
+		printk(KERN_ERR "ACPI: missing RSDT at 0x%p\n",
+		       (void*) rsdp->rsdt);
+		return -ENODEV;
+	}
+	else if (rsdt->signature != ACPI_RSDT_SIG) {
+		printk(KERN_ERR "ACPI: bad RSDT at 0x%p (%08x)\n",
+		       (void*) rsdp->rsdt, (unsigned) rsdt->signature);
 		acpi_unmap_table(rsdt);
 		return -ENODEV;
 	}
@@ -396,9 +427,15 @@
 			acpi_facp_addr = *rsdt_entry;
 			acpi_dsdt_addr = acpi_facp->dsdt;
 
+			// map FACS if it exists
 			if (acpi_facp->facs) {
-				acpi_facs = (struct acpi_facs*)
-					acpi_map_table(acpi_facp->facs);
+				dt = acpi_map_table(acpi_facp->facs);
+				if (dt && dt->signature == ACPI_FACS_SIG) {
+					acpi_facs = (struct acpi_facs*) dt;
+				}
+				else {
+					acpi_unmap_table(dt);
+				}
 			}
 		}
 		else {
@@ -624,6 +661,34 @@
 }
 
 /*
+ * Put all devices into specified D-state
+ */
+static int acpi_enter_dx(acpi_dstate_t state)
+{
+	int status = 0;
+	struct list_head *i = acpi_devs.next;
+
+	while (i != &acpi_devs)	{
+		struct acpi_dev *dev = list_entry(i, struct acpi_dev, entry);
+		if (dev->state != state) {
+			int dev_status = 0;
+			if (dev->info.transition)
+				dev_status = dev->info.transition(dev, state);
+			if (!dev_status) {
+				// put hardware into D-state
+				dev->state = state;
+			}
+			if (dev_status)
+				status = dev_status;
+		}
+
+		i = i->next;
+	}
+
+	return status;
+}
+
+/*
  * Enter system sleep state
  */
 static void acpi_enter_sx(int state)
@@ -903,10 +968,41 @@
 }
 
 /*
+ * Sleep or wake system
+ */
+static int acpi_do_sleep_wake(ctl_table *ctl,
+			      int write,
+			      struct file *file,
+			      void *buffer,
+			      size_t *len)
+{
+	if (!write) {
+		if (file->f_pos) {
+			*len = 0;
+			return 0;
+		}
+	}
+	else
+	{
+		// just shutdown some devices for now
+		if (ctl->data) {
+			acpi_enter_dx(ACPI_D3);
+		}
+		else {
+			acpi_enter_dx(ACPI_D0);
+		}
+	}
+	file->f_pos += *len;
+	return 0;
+}
+
+/*
  * Initialize and enable ACPI
  */
 static int __init acpi_init(void)
 {
+	int pid;
+
 	if (acpi_find_tables() && acpi_find_piix4()) {
 		// no ACPI tables and not PIIX4
 		return -ENODEV;
@@ -917,7 +1013,7 @@
 			   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();
@@ -927,6 +1023,10 @@
 	acpi_claim_ioports(acpi_facp);
 	acpi_sysctl = register_sysctl_table(acpi_dir_table, 1);
 
+	pid = kernel_thread(acpi_idle_thread,
+			    NULL,
+			    CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+
 	/*
 	 * Set up the ACPI idle function. Note that we can't really
 	 * do this with multiple CPU's, we'd need a per-CPU ACPI
@@ -956,18 +1056,84 @@
 	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();
 }
 
-#ifdef MODULE
+/*
+ * Register a device with the ACPI subsystem
+ */
+struct acpi_dev* acpi_register(struct acpi_dev_info *info, unsigned long adr)
+{
+	struct acpi_dev *dev = NULL;
+	if (info) {
+		dev = kmalloc(sizeof(struct acpi_dev), GFP_KERNEL);
+		if (dev) {
+			unsigned long flags;
+			
+			memset(dev, 0, sizeof(*dev));
+			memcpy(&dev->info, info, sizeof(dev->info));
+			dev->adr = adr;
+			
+			spin_lock_irqsave(&acpi_devs_lock, flags);
+			list_add(&dev->entry, &acpi_devs);
+			spin_unlock_irqrestore(&acpi_devs_lock, flags);
+		}
+	}
+	return dev;
+}
 
-module_init(acpi_init)
-module_exit(acpi_exit)
+/*
+ * Unregister a device with ACPI
+ */
+void acpi_unregister(struct acpi_dev *dev)
+{
+	if (dev) {
+		unsigned long flags;
 
-#else
+		spin_lock_irqsave(&acpi_devs_lock, flags);
+		list_del(&dev->entry);
+		spin_unlock_irqrestore(&acpi_devs_lock, flags);
+
+		kfree(dev);
+	}
+}
+
+/*
+ * Wake up a device
+ */
+void acpi_wakeup(struct acpi_dev *dev)
+{
+	// run _PS0 or tell parent bus to wake device up
+}
+
+/*
+ * Manage idle devices
+ */
+static int acpi_idle_thread(void *context)
+{
+	exit_mm(current);
+	exit_files(current);
+	strcpy(current->comm, "acpi");
+	
+	for(;;) {
+		interruptible_sleep_on(&acpi_idle_wait);
+		if (signal_pending(current))
+			break;
+
+		// find all idle devices and set idle timer based on policy
+	}
+
+	return 0;
+}
 
 __initcall(acpi_init);
 
-#endif
+/*
+ * Module visible symbols
+ */
+EXPORT_SYMBOL(acpi_idle_wait);
+EXPORT_SYMBOL(acpi_register);
+EXPORT_SYMBOL(acpi_unregister);
+EXPORT_SYMBOL(acpi_wakeup);
diff -u --recursive --new-file v2.3.26/linux/drivers/net/3c507.c linux/drivers/net/3c507.c
--- v2.3.26/linux/drivers/net/3c507.c	Mon Nov  1 13:56:26 1999
+++ linux/drivers/net/3c507.c	Wed Nov 10 09:52:27 1999
@@ -781,7 +781,7 @@
 	isa_memcpy_toio(write_ptr+2, buf, length);
 
 	/* Set the old command link pointing to this send packet. */
-	isa_isa_writew(tx_block,dev->mem_start + lp->tx_cmd_link);
+	isa_writew(tx_block,dev->mem_start + lp->tx_cmd_link);
 	lp->tx_cmd_link = tx_block + 20;
 
 	/* Set the next free tx region. */
diff -u --recursive --new-file v2.3.26/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c
--- v2.3.26/linux/drivers/net/3c59x.c	Fri Sep 10 23:57:29 1999
+++ linux/drivers/net/3c59x.c	Tue Nov  9 08:20:12 1999
@@ -229,15 +229,13 @@
 	const char *name;
 	u16	vendor_id, device_id, device_id_mask, flags;
 	int drv_flags, io_size;
-	struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev,
-							 long ioaddr, int irq, int chip_idx, int fnd_cnt);
+	struct net_device *(*probe1)(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
 };
 
 enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4,
 	   HAS_PWR_CTRL=0x10, HAS_MII=0x20, HAS_NWAY=0x40, HAS_CB_FNS=0x80, };
-static struct net_device *vortex_probe1(int pci_bus, int pci_devfn,
-									struct net_device *dev, long ioaddr,
-									int irq, int dev_id, int card_idx);
+static struct net_device *vortex_probe1(int pci_bus, int pci_devfn, long ioaddr, int irq, int dev_id, int card_idx);
+
 static struct pci_id_info pci_tbl[] = {
 	{"3c590 Vortex 10Mbps",			0x10B7, 0x5900, 0xffff,
 	 PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
@@ -493,7 +491,7 @@
 };
 
 #ifndef CARDBUS
-static int vortex_scan(struct net_device *dev, struct pci_id_info pci_tbl[]);
+static int vortex_scan(struct pci_id_info pci_tbl[]);
 #endif
 static int vortex_open(struct net_device *dev);
 static void mdio_sync(long ioaddr, int bits);
@@ -563,7 +561,7 @@
 			   "vortex_attach().\n", vendor_id, dev_id);
 		return NULL;
 	}
-	dev = vortex_probe1(bus, devfn, NULL, io, irq, chip_idx, MAX_UNITS+1);
+	dev = vortex_probe1(bus, devfn, io, irq, chip_idx, MAX_UNITS+1);
 	if (dev) {
 		dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
 		strcpy(node->dev_name, dev->name);
@@ -614,25 +612,26 @@
 	register_driver(&vortex_ops);
 	return 0;
 #else
-	return vortex_scan(0, pci_tbl);
+	return vortex_scan(pci_tbl);
 #endif
 }
 
 #else
-int tc59x_probe(struct net_device *dev)
+int tc59x_probe(void)
 {
 	static int scanned=0;
 	if(scanned++)
 		return -ENODEV;
 	printk(KERN_INFO "%s", version);
-	return vortex_scan(dev, pci_tbl);
+	return vortex_scan(pci_tbl);
 }
 #endif  /* not MODULE */
 
 #ifndef CARDBUS
-static int vortex_scan(struct net_device *dev, struct pci_id_info pci_tbl[])
+static int vortex_scan(struct pci_id_info pci_tbl[])
 {
 	int cards_found = 0;
+	struct net_device *dev;
 
 	/* Allow an EISA-only driver. */
 #if defined(CONFIG_PCI) || (defined(MODULE) && !defined(NO_PCI))
@@ -712,7 +711,7 @@
 										  PCI_COMMAND, new_command);
 			}
 
-			dev = vortex_probe1(pci_bus, pci_device_fn, dev, ioaddr, irq,
+			dev = vortex_probe1(pci_bus, pci_device_fn, ioaddr, irq,
 								chip_idx, cards_found);
 
 			if (dev) {
@@ -753,9 +752,8 @@
 			device_id = (inb(ioaddr + 0xC82)<<8) + inb(ioaddr + 0xC83);
 			if ((device_id & 0xFF00) != 0x5900)
 				continue;
-			vortex_probe1(0, 0, dev, ioaddr, inw(ioaddr + 0xC88) >> 12,
+			vortex_probe1(0, 0, ioaddr, inw(ioaddr + 0xC88) >> 12,
 						  4, cards_found);
-			dev = 0;
 			cards_found++;
 		}
 	}
@@ -763,7 +761,7 @@
 #ifdef MODULE
 	/* Special code to work-around the Compaq PCI BIOS32 problem. */
 	if (compaq_ioaddr) {
-		vortex_probe1(0, 0, dev, compaq_ioaddr, compaq_irq,
+		vortex_probe1(0, 0, compaq_ioaddr, compaq_irq,
 					  compaq_device_id, cards_found++);
 		dev = 0;
 	}
@@ -774,15 +772,15 @@
 #endif  /* ! Cardbus */
 
 static struct net_device *vortex_probe1(int pci_bus, int pci_devfn,
-									struct net_device *dev, long ioaddr,
-									int irq, int chip_idx, int card_idx)
+					long ioaddr, int irq, int chip_idx, int card_idx)
 {
 	struct vortex_private *vp;
 	int option;
 	unsigned int eeprom[0x40], checksum = 0;		/* EEPROM contents */
 	int i;
+	struct net_device *dev;
 
-	dev = init_etherdev(dev, 0);
+	dev = init_etherdev(NULL, 0);
 
 	printk(KERN_INFO "%s: 3Com %s at 0x%lx, ",
 		   dev->name, pci_tbl[chip_idx].name, ioaddr);
diff -u --recursive --new-file v2.3.26/linux/drivers/net/82596.c linux/drivers/net/82596.c
--- v2.3.26/linux/drivers/net/82596.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/net/82596.c	Mon Nov  8 11:03:20 1999
@@ -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 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#include <asm/pgtable.h>	/*?? */
+#include <asm/pgtable.h>
 
-#ifdef CONFIG_MVME16x_NET
+#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 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 @@
 #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 @@
 #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 APRICOT_DEBUG 2
+#define I82596_DEBUG 1
 
-#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 @@
 	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_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 @@
 	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 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 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 @@
 }
 
 
-#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 @@
 }
 #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;
+	for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
+		struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ);
 
-		rfd->next = lp->scb.rfd;
-		lp->scb.rfd = WSWAPrfd(rfd);
+		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 @@
 
 	MPU_PORT(dev, PORT_ALTSCP, &lp->scp);
 
-#else
+#elif defined(ENABLE_APRICOT)
 
 	/* change the scp address */
 	outw(0, ioaddr);
@@ -431,15 +480,15 @@
 
 	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 @@
 	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 @@
 			     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 @@
 		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 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 @@
 
 		/* 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 @@
 				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 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 @@
 	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 @@
 		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 @@
 		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 @@
 
 			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 @@
 
 	return 0;
 }
-
 
 static void print_eth(char *add)
 {
@@ -879,14 +1010,15 @@
 	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 @@
 		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 @@
 		dev->irq = (unsigned) BVME_IRQ_I596;
 	}
 #endif
-#ifdef CONFIG_APRICOT_INTEL
+#ifdef ENABLE_APRICOT
 	int checksum = 0;
 	int ioaddr = 0x300;
 
@@ -953,22 +1085,28 @@
 	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 @@
 	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 @@
 					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 @@
 		}
 	lp->scb.command = ack_cmd;
 
-#ifdef CONFIG_MVME16x_NET
+#ifdef ENABLE_MVME16x_NET
 	if (MACH_IS_MVME16x) {
 		/* Ack the interrupt */
 
@@ -1150,7 +1287,7 @@
 		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 @@
 		*ethirq = 3;
 	}
 #endif
-#ifdef CONFIG_APRICOT_INTEL
+#ifdef ENABLE_APRICOT
 	(void) inb(ioaddr + 0x10);
 	outb(4, ioaddr + 0xf);
 #endif
@@ -1208,7 +1345,7 @@
 
 	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 @@
 		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 @@
 {
 	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 @@
 			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 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 -u --recursive --new-file v2.3.26/linux/drivers/net/8390.c linux/drivers/net/8390.c
--- v2.3.26/linux/drivers/net/8390.c	Fri Sep 10 23:57:29 1999
+++ linux/drivers/net/8390.c	Thu Nov 11 10:07:21 1999
@@ -1089,7 +1089,10 @@
 								int start_page)
 {
 	long e8390_base = dev->base_addr;
+#if defined(CONFIG_MAC) || defined(CONFIG_AMIGA_PCMCIA) || \
+    defined(CONFIG_ARIADNE2) || defined(CONFIG_ARIADNE2_MODULE)
  	struct ei_device *ei_local = (struct ei_device *) dev->priv;
+#endif
    
 	outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD);
     
diff -u --recursive --new-file v2.3.26/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.3.26/linux/drivers/net/Makefile	Wed Oct 27 16:34:12 1999
+++ linux/drivers/net/Makefile	Wed Nov 10 12:54:34 1999
@@ -3,8 +3,20 @@
 # Makefile for the Linux network (ethercard) device drivers.
 #
 
+O_OBJS          :=
+M_OBJS          :=
+MX_OBJS         :=
+
+# Object file lists.
+
+obj-y           :=
+obj-m           :=
+obj-n           :=
+obj-            :=
+
 SUB_DIRS     := 
-MOD_SUB_DIRS := $(SUB_DIRS)
+MOD_SUB_DIRS :=
+MOD_IN_SUB_DIRS :=
 ALL_SUB_DIRS := $(SUB_DIRS) fc hamradio irda pcmcia tokenring wan
 
 L_TARGET := net.a
@@ -12,18 +24,11 @@
 M_OBJS   :=
 MOD_LIST_NAME := NET_MODULES
 
-# Need these to keep track of whether the 7990 (LANCE), 8390, PPP and SLHC 
-# modules should really go in the kernel or a module.
-CONFIG_8390_BUILTIN :=
-CONFIG_8390_MODULE  :=
-CONFIG_SLHC_BUILTIN :=
-CONFIG_SLHC_MODULE  :=
-CONFIG_PPPDEF_BUILTIN :=
-CONFIG_PPPDEF_MODULE  :=
-CONFIG_7990_BUILTIN :=
-CONFIG_7990_MODULE :=
-CONFIG_82596_BUILTIN :=
-CONFIG_82596_MODULE :=
+# All of the (potential) objects that export symbols.
+# This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
+
+export-objs     :=	8390.o arcnet.o arlan.o ppp_async.o \
+			ppp_generic.o slhc.o
 
 ifeq ($(CONFIG_PCMCIA),y)
   SUB_DIRS += pcmcia
@@ -34,1072 +39,232 @@
   endif
 endif
 
-ifeq ($(CONFIG_ISDN),y)
-  ifeq ($(CONFIG_ISDN_PPP),y)
-    CONFIG_SLHC_BUILTIN = y
-    CONFIG_PPPDEF_BUILTIN = y
-  endif
-else
-  ifeq ($(CONFIG_ISDN),m)
-    ifeq ($(CONFIG_ISDN_PPP),y)
-      CONFIG_SLHC_MODULE = y
-      CONFIG_PPPDEF_MODULE = y
-    endif
-  endif
-endif
-
-ifeq ($(CONFIG_NET),y)
-L_OBJS += Space.o net_init.o loopback.o
-endif
-
-ifeq ($(CONFIG_SEEQ8005),y)
-L_OBJS += seeq8005.o
-endif
-
-ifeq ($(CONFIG_ETHERTAP),y)
-L_OBJS += ethertap.o
-else
-  ifeq ($(CONFIG_ETHERTAP),m)
-  M_OBJS += ethertap.o
-  endif
-endif
-
-ifeq ($(CONFIG_NET_SB1000),y)
-L_OBJS += sb1000.o
-else
-  ifeq ($(CONFIG_NET_SB1000),m)
-  M_OBJS += sb1000.o
-  endif
-endif
-
-ifeq ($(CONFIG_DAYNAPORT), y)
-L_OBJS += daynaport.o
-CONFIG_8390_BUILTIN = y
-endif
-
-ifeq ($(CONFIG_APNE),y)
-L_OBJS += apne.o
-CONFIG_8390_BUILTIN = y
-else
-  ifeq ($(CONFIG_APNE),m)
-  M_OBJS += apne.o
-  CONFIG_8390_MODULE = y
-  endif
-endif
-
-ifeq ($(CONFIG_PCMCIA_PCNET),y)
-CONFIG_8390_BUILTIN = y
-else
-  ifeq ($(CONFIG_PCMCIA_PCNET),m)
-  CONFIG_8390_MODULE = y
-  endif
-endif
-
-ifeq ($(CONFIG_SHAPER),y)
-L_OBJS += shaper.o
-else
-  ifeq ($(CONFIG_SHAPER),m)
-  M_OBJS += shaper.o
-  endif
-endif
-
-ifeq ($(CONFIG_SK_G16),y)
-L_OBJS += sk_g16.o
-endif
-
-ifeq ($(CONFIG_HP100),y)
-L_OBJS += hp100.o
-else
-  ifeq ($(CONFIG_HP100),m)
-  M_OBJS += hp100.o
-  endif
-endif
-
-ifeq ($(CONFIG_SMC9194),y)
-L_OBJS += smc9194.o
-else
-  ifeq ($(CONFIG_SMC9194),m)
-  M_OBJS += smc9194.o
-  endif
-endif
-
-ifeq ($(CONFIG_ARM_AM79C961A),y)
-L_OBJS += am79c961a.o
-else
-  ifeq ($(CONFIG_ARM_AM79C961A),m)
-  M_OBJS += am79c961a.o
-  endif
-endif
-
-ifeq ($(CONFIG_ARM_ETHERH),y)
-CONFIG_8390_BUILTIN = y
-else
-  ifeq ($(CONFIG_ARM_ETHERH),m)
-  CONFIG_8390_MODULE = y
-  endif
-endif
-
-ifeq ($(CONFIG_WD80x3),y)
-L_OBJS += wd.o
-CONFIG_8390_BUILTIN = y
-else
-  ifeq ($(CONFIG_WD80x3),m)
-  CONFIG_8390_MODULE = y
-  M_OBJS += wd.o
-  endif
-endif
-
-ifeq ($(CONFIG_EL2),y)
-L_OBJS += 3c503.o
-CONFIG_8390_BUILTIN = y
-else
-  ifeq ($(CONFIG_EL2),m)
-  CONFIG_8390_MODULE = y
-  M_OBJS += 3c503.o
-  endif
-endif
-
-ifeq ($(CONFIG_NE2K_PCI),y)
-L_OBJS += ne2k-pci.o
-CONFIG_8390_BUILTIN = y
-else
-  ifeq ($(CONFIG_NE2K_PCI),m)
-  CONFIG_8390_MODULE = y
-  M_OBJS += ne2k-pci.o
-  endif
-endif
-
-ifeq ($(CONFIG_NE2000),y)
-L_OBJS += ne.o
-CONFIG_8390_BUILTIN = y
-else
-  ifeq ($(CONFIG_NE2000),m)
-  CONFIG_8390_MODULE = y
-  M_OBJS += ne.o
-  endif
-endif
-
-ifeq ($(CONFIG_NE2_MCA),y)
-L_OBJS += ne2.o
-CONFIG_8390_BUILTIN = y
-else
-  ifeq ($(CONFIG_NE2_MCA),m)
-  CONFIG_8390_MODULE = y
-  M_OBJS += ne2.o
-  endif
-endif
-
-ifeq ($(CONFIG_HPLAN),y)
-L_OBJS += hp.o
-CONFIG_8390_BUILTIN = y
-else
-  ifeq ($(CONFIG_HPLAN),m)
-  CONFIG_8390_MODULE = y
-  M_OBJS += hp.o
-  endif
-endif
-
-ifeq ($(CONFIG_HPLAN_PLUS),y)
-L_OBJS += hp-plus.o
-CONFIG_8390_BUILTIN = y
-else
-  ifeq ($(CONFIG_HPLAN_PLUS),m)
-  CONFIG_8390_MODULE = y
-  M_OBJS += hp-plus.o
-  endif
-endif
-
-ifeq ($(CONFIG_ULTRA),y)
-L_OBJS += smc-ultra.o
-CONFIG_8390_BUILTIN = y
-else
-  ifeq ($(CONFIG_ULTRA),m)
-  CONFIG_8390_MODULE = y
-  M_OBJS += smc-ultra.o
-  endif
-endif
-
-ifeq ($(CONFIG_ULTRAMCA),y)
-L_OBJS += smc-mca.o
-CONFIG_8390_BUILTIN = y
+ifeq ($(CONFIG_IRDA),y)
+SUB_DIRS += irda
+MOD_IN_SUB_DIRS += irda
 else
-  ifeq ($(CONFIG_ULTRAMCA),m)
-  CONFIG_8390_MODULE = y
-  M_OBJS += smc-mca.o
+  ifeq ($(CONFIG_IRDA),m)
+  MOD_IN_SUB_DIRS += irda
   endif
 endif
 
-ifeq ($(CONFIG_ULTRA32),y)
-L_OBJS += smc-ultra32.o
-CONFIG_8390_BUILTIN = y
+ifeq ($(CONFIG_TR),y)
+SUB_DIRS += tokenring
+MOD_IN_SUB_DIRS += tokenring
 else
-  ifeq ($(CONFIG_ULTRA32),m)
-  CONFIG_8390_MODULE = y
-  M_OBJS += smc-ultra32.o
+  ifeq ($(CONFIG_TR),m)
+  MOD_IN_SUB_DIRS += tokenring
   endif
 endif
 
-ifeq ($(CONFIG_E2100),y)
-L_OBJS += e2100.o
-CONFIG_8390_BUILTIN = y
+ifeq ($(CONFIG_WAN),y)
+SUB_DIRS += wan
+MOD_IN_SUB_DIRS += wan
 else
-  ifeq ($(CONFIG_E2100),m)
-  CONFIG_8390_MODULE = y
-  M_OBJS += e2100.o
+  ifeq ($(CONFIG_WAN),m)
+  MOD_IN_SUB_DIRS += wan
   endif
 endif
 
-ifeq ($(CONFIG_ES3210),y)
-L_OBJS += es3210.o
-CONFIG_8390_BUILTIN = y
+ifeq ($(CONFIG_NET_FC),y)
+SUB_DIRS += fc
+MOD_IN_SUB_DIRS += fc
 else
-  ifeq ($(CONFIG_ES3210),m)
-  CONFIG_8390_MODULE = y
-  M_OBJS += es3210.o
+  ifeq ($(CONFIG_NET_FC),m)
+  MOD_IN_SUB_DIRS += fc
   endif
 endif
 
-ifeq ($(CONFIG_LNE390),y)
-L_OBJS += lne390.o
-CONFIG_8390_BUILTIN = y
-else
-  ifeq ($(CONFIG_LNE390),m)
-  CONFIG_8390_MODULE = y
-  M_OBJS += lne390.o
+ifeq ($(CONFIG_ISDN),y)
+  ifeq ($(CONFIG_ISDN_PPP),y)
+    obj-y += slhc.o ppp_deflate.o
   endif
-endif
-
-ifeq ($(CONFIG_NE3210),y)
-L_OBJS += ne3210.o
-CONFIG_8390_BUILTIN = y
 else
-  ifeq ($(CONFIG_NE3210),m)
-  CONFIG_8390_MODULE = y
-  M_OBJS += ne3210.o
+  ifeq ($(CONFIG_ISDN),m)
+    ifeq ($(CONFIG_ISDN_PPP),y)
+      obj-m += slhc.o ppp_deflate.o
+    endif
   endif
 endif
 
-ifeq ($(CONFIG_PLIP),y)
-L_OBJS += plip.o
-else
-  ifeq ($(CONFIG_PLIP),m)
-  M_OBJS += plip.o
-  endif
-endif
+obj-$(CONFIG_NET) += Space.o setup.o net_init.o loopback.o
+obj-$(CONFIG_SEEQ8005) += seeq8005.o
+obj-$(CONFIG_ETHERTAP) += ethertap.o
+obj-$(CONFIG_NET_SB1000) += sb1000.o
+obj-$(CONFIG_DAYNAPORT) += daynaport.o 8390.o
+obj-$(CONFIG_APNE) += apne.o 8390.o
+obj-$(CONFIG_PCMCIA_PCNET) += 8390.o
+obj-$(CONFIG_SHAPER) += shaper.o
+obj-$(CONFIG_SK_G16) += sk_g16.o
+obj-$(CONFIG_HP100) += hp100.o
+obj-$(CONFIG_SMC9194) += smc9194.o
+obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o
+obj-$(CONFIG_ARM_ETHERH) += 8390.o
+obj-$(CONFIG_WD80x3) += wd.o 8390.o
+obj-$(CONFIG_EL2) += 3c503.o 8390.o
+obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
+obj-$(CONFIG_NE2000) += ne.o 8390.o
+obj-$(CONFIG_NE2_MCA) += ne2.o 8390.o
+obj-$(CONFIG_HPLAN) += hp.o 8390.o
+obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390.o
+obj-$(CONFIG_ULTRA) += smc-ultra.o 8390.o
+obj-$(CONFIG_ULTRAMCA) += smc-mca.o 8390.o
+obj-$(CONFIG_ULTRA32) += smc-ultra32.o 8390.o
+obj-$(CONFIG_E2100) += e2100.o 8390.o
+obj-$(CONFIG_ES3210) += es3210.o 8390.o
+obj-$(CONFIG_LNE390) += lne390.o 8390.o
+obj-$(CONFIG_NE3210) += ne3210.o 8390.o
+obj-$(CONFIG_PLIP) += plip.o
 
 # bsd_comp.o is *always* a module, for some documented reason
 # (licensing).
 ifeq ($(CONFIG_PPP),y)
-LX_OBJS += ppp_generic.o
-CONFIG_SLHC_BUILTIN = y
-  ifeq ($(CONFIG_PPP_ASYNC),y)
-  LX_OBJS += ppp_async.o
-  else
-    ifeq ($(CONFIG_PPP_ASYNC),m)
-    MX_OBJS += ppp_async.o
-    endif
-  endif
-  ifeq ($(CONFIG_PPP_SYNC_TTY),y)
-  LX_OBJS += ppp_synctty.o
-  else
-    ifeq ($(CONFIG_PPP_SYNC_TTY),m)
-    MX_OBJS += ppp_synctty.o
-    endif
-  endif
-  ifeq ($(CONFIG_PPP_DEFLATE),y)
-  CONFIG_PPPDEF_BUILTIN = y
-  else
-    ifeq ($(CONFIG_PPP_DEFLATE),m)
-    CONFIG_PPPDEF_MODULE = y
-    endif
-  endif
+  obj-y += ppp_generic.o slhc.o
+  obj-$(CONFIG_PPP_ASYNC) += ppp_async.o
+  obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o
+  obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o
   ifeq ($(CONFIG_PPP_BSDCOMP),m)
-  M_OBJS += bsd_comp.o
+    obj-m += bsd_comp.o
   endif
 else
   ifeq ($(CONFIG_PPP),m)
-  MX_OBJS += ppp_generic.o
-  CONFIG_SLHC_MODULE = y
-    ifeq ($(CONFIG_PPP_ASYNC),m)
-    MX_OBJS += ppp_async.o
-    endif
-    ifeq ($(CONFIG_PPP_SYNC_TTY),m)
-    MX_OBJS += ppp_synctty.o
-    endif
-    ifeq ($(CONFIG_PPP_DEFLATE),m)
-    CONFIG_PPPDEF_MODULE = y
-    endif
+    obj-m += ppp_generic.o slhc.o
+    obj-$(CONFIG_PPP_ASYNC) += ppp_async.o
+    obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o
+    obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o
     ifeq ($(CONFIG_PPP_BSDCOMP),m)
-    M_OBJS += bsd_comp.o
+      obj-m += bsd_comp.o
     endif
   endif
 endif
 
+obj-$(CONFIG_SLIP) += slip.o
 ifeq ($(CONFIG_SLIP),y)
-L_OBJS += slip.o
-  ifeq ($(CONFIG_SLIP_COMPRESSED),y)
-  CONFIG_SLHC_BUILTIN = y
-  endif
+  obj-$(CONFIG_SLIP_COMPRESSED) += slhc.o
 else
   ifeq ($(CONFIG_SLIP),m)
-    ifeq ($(CONFIG_SLIP_COMPRESSED),y)
-    CONFIG_SLHC_MODULE = y
-  endif
-  M_OBJS += slip.o
-  endif
-endif
-
-ifeq ($(CONFIG_STRIP),y)
-L_OBJS += strip.o
-else
-  ifeq ($(CONFIG_STRIP),m)
-  M_OBJS += strip.o
-  endif
-endif
-
-ifeq ($(CONFIG_DE650),y)
-ETDRV_OBJS := $(L_OBJS) de650.o
-CONFIG_8390_BUILTIN = y
-endif
-
-ifeq ($(CONFIG_3C589),y)
-L_OBJS += 3c589.o
-endif
-
-ifeq ($(CONFIG_DUMMY),y)
-L_OBJS += dummy.o
-else
-  ifeq ($(CONFIG_DUMMY),m)
-  M_OBJS += dummy.o
-  endif
-endif
-
-ifeq ($(CONFIG_DE600),y)
-L_OBJS += de600.o
-else
-  ifeq ($(CONFIG_DE600),m)
-  M_OBJS += de600.o
-  endif
-endif
-
-ifeq ($(CONFIG_DE620),y)
-L_OBJS += de620.o
-else
-  ifeq ($(CONFIG_DE620),m)
-  M_OBJS += de620.o
-  endif
-endif
-
-ifeq ($(CONFIG_AT1500),y)
-L_OBJS += lance.o
-endif
-
-ifeq ($(CONFIG_LANCE),y)
-L_OBJS += lance.o
-else
-  ifeq ($(CONFIG_LANCE),m)
-  M_OBJS += lance.o
-  endif
-endif
-
-ifeq ($(CONFIG_SUN3LANCE),y)
-L_OBJS += sun3lance.o
-endif
-
-ifeq ($(CONFIG_PCNET32),y)
-L_OBJS += pcnet32.o
-else
-  ifeq ($(CONFIG_PCNET32),m)
-  M_OBJS += pcnet32.o
-  endif
-endif
-
-ifeq ($(CONFIG_DEFXX),y)
-L_OBJS += defxx.o
-endif
-
-ifeq ($(CONFIG_SUNLANCE),y)
-L_OBJS += sunlance.o
-else
-  ifeq ($(CONFIG_SUNLANCE),m)
-  M_OBJS += sunlance.o
-  endif
-endif
-
-ifeq ($(CONFIG_SGISEEQ), y)
-L_OBJS += sgiseeq.o
-endif
-
-ifeq ($(CONFIG_HAPPYMEAL),y)
-L_OBJS += sunhme.o
-else
-  ifeq ($(CONFIG_HAPPYMEAL),m)
-  M_OBJS += sunhme.o
-  endif
-endif
-
-ifeq ($(CONFIG_SUNQE),y)
-L_OBJS += sunqe.o
-else
-  ifeq ($(CONFIG_SUNQE),m)
-  M_OBJS += sunqe.o
-  endif
-endif
-
-ifeq ($(CONFIG_SUNBMAC),y)
-L_OBJS += sunbmac.o
-else
-  ifeq ($(CONFIG_SUNBMAC),m)
-  M_OBJS += sunbmac.o
-  endif
-endif
-
-ifeq ($(CONFIG_SUNBMAC),y)
-L_OBJS += sunbmac.o
-else
-  ifeq ($(CONFIG_SUNBMAC),m)
-  M_OBJS += sunbmac.o
+    obj-$(CONFIG_SLIP_COMPRESSED) += slhc.o
   endif
 endif
 
-ifeq ($(CONFIG_MYRI_SBUS),y)
-L_OBJS += myri_sbus.o
-else
-  ifeq ($(CONFIG_MYRI_SBUS),m)
-  M_OBJS += myri_sbus.o
-  endif
-endif
+obj-$(CONFIG_STRIP) += strip.o
+obj-$(CONFIG_DE650) += de650.o 8390.o
+obj-$(CONFIG_3C589) += 3c589.o
+obj-$(CONFIG_DUMMY) += dummy.o
+obj-$(CONFIG_DE600) += de600.o
+obj-$(CONFIG_DE620) += de620.o
+obj-$(CONFIG_AT1500) += lance.o
+obj-$(CONFIG_LANCE) += lance.o
+obj-$(CONFIG_SUN3LANCE) += sun3lance.o
+obj-$(CONFIG_PCNET32) += pcnet32.o
+obj-$(CONFIG_DEFXX) += defxx.o
+obj-$(CONFIG_SUNLANCE) += sunlance.o
+obj-$(CONFIG_SGISEEQ) += sgiseeq.o
+obj-$(CONFIG_HAPPYMEAL) += sunhme.o
+obj-$(CONFIG_SUNQE) += sunqe.o
+obj-$(CONFIG_SUNBMAC) += sunbmac.o
+obj-$(CONFIG_SUNBMAC) += sunbmac.o
+obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o
+obj-$(CONFIG_AT1700) += at1700.o
+obj-$(CONFIG_FMV18X) += fmv18x.o
+obj-$(CONFIG_EL1) += 3c501.o
+obj-$(CONFIG_EL16) += 3c507.o
+obj-$(CONFIG_ELMC) += 3c523.o
+obj-$(CONFIG_SKMC) += sk_mca.o
+obj-$(CONFIG_ELMC_II) += 3c527.o
+obj-$(CONFIG_EL3) += 3c509.o
+obj-$(CONFIG_3C515) += 3c515.o
+obj-$(CONFIG_VORTEX) += 3c59x.o
+obj-$(CONFIG_EEXPRESS) += eexpress.o
+obj-$(CONFIG_EEXPRESS_PRO) += eepro.o
+obj-$(CONFIG_EEXPRESS_PRO100) += eepro100.o
+obj-$(CONFIG_RTL8139) += rtl8139.o
+obj-$(CONFIG_SIS900) += sis900.o
+obj-$(CONFIG_DM9102) += dmfe.o
+obj-$(CONFIG_YELLOWFIN) += yellowfin.o
+obj-$(CONFIG_ACENIC) += acenic.o
+obj-$(CONFIG_WAVELAN) += wavelan.o
+obj-$(CONFIG_ARLAN) += arlan.o arlan-proc.o
+obj-$(CONFIG_TLAN) += tlan.o
+obj-$(CONFIG_VIA_RHINE) += via-rhine.o
+obj-$(CONFIG_ZNET) += znet.o
+obj-$(CONFIG_DEPCA) += depca.o
+obj-$(CONFIG_EWRK3) += ewrk3.o
+obj-$(CONFIG_ATP) += atp.o
+obj-$(CONFIG_DE4X5) += de4x5.o
+obj-$(CONFIG_NI5010) += ni5010.o
+obj-$(CONFIG_NI52) += ni52.o
+obj-$(CONFIG_NI65) += ni65.o
+obj-$(CONFIG_ELPLUS) += 3c505.o
+obj-$(CONFIG_AC3200) += ac3200.o 8390.o
+obj-$(CONFIG_APRICOT) += 82596.o
+obj-$(CONFIG_MVME16x_NET) += 82596.o
+obj-$(CONFIG_BVME6000_NET) += 82596.o
+obj-$(CONFIG_DEC_ELCP) += tulip.o
+obj-$(CONFIG_ARCNET) += arcnet.o
+obj-$(CONFIG_ARCNET_COM90xx) += com90xx.o
+obj-$(CONFIG_ARCNET_COM90xxIO) += com90io.o
+obj-$(CONFIG_ARCNET_RIM_I) += arc-rimi.o
+obj-$(CONFIG_ARCNET_COM20020) += com20020.o
+obj-$(CONFIG_ETH16I) += eth16i.o
+obj-$(CONFIG_EPIC100) += epic100.o
+obj-$(CONFIG_ARIADNE2) += ariadne2.o 8390.o
+obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
+obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
+obj-$(CONFIG_EQUALIZER) += eql.o
+obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
+obj-$(CONFIG_BAGETLANCE) += bagetlance.o
+obj-$(CONFIG_DECLANCE) += declance.o
+obj-$(CONFIG_ATARILANCE) += atarilance.o
+obj-$(CONFIG_ATARI_BIONET) += atari_bionet.o
+obj-$(CONFIG_ATARI_PAMSNET) += atari_pamsnet.o
+obj-$(CONFIG_A2065) += a2065.o
+obj-$(CONFIG_HYDRA) += hydra.o
+obj-$(CONFIG_ARIADNE) += ariadne.o
+obj-$(CONFIG_DGRS) += dgrs.o
+obj-$(CONFIG_CS89x0) += cs89x0.o
+obj-$(CONFIG_LTPC) += ltpc.o
+obj-$(CONFIG_COPS) += cops.o
+obj-$(CONFIG_IPDDP) += ipddp.o
+obj-$(CONFIG_RCPCI) += rcpci.o
+obj-$(CONFIG_MACE) += mace.o
+obj-$(CONFIG_MACSONIC) += macsonic.o
+obj-$(CONFIG_BMAC) += bmac.o
+obj-$(CONFIG_NCR885E) += ncr885e.o
+obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
 
-ifeq ($(CONFIG_AT1700),y)
-L_OBJS += at1700.o
-else
-  ifeq ($(CONFIG_AT1700),m)
-  M_OBJS += at1700.o
-  endif
-endif
-
-ifeq ($(CONFIG_FMV18X),y)
-L_OBJS += fmv18x.o
-else
-  ifeq ($(CONFIG_FMV18X),m)
-  M_OBJS += fmv18x.o
-  endif
-endif
-
-ifeq ($(CONFIG_EL1),y)
-L_OBJS += 3c501.o
-else
-  ifeq ($(CONFIG_EL1),m)
-  M_OBJS += 3c501.o
-  endif
-endif
-
-ifeq ($(CONFIG_EL16),y)
-L_OBJS += 3c507.o
-else
-  ifeq ($(CONFIG_EL16),m)
-  M_OBJS += 3c507.o
-  endif
-endif
-
-ifeq ($(CONFIG_ELMC),y)
-L_OBJS += 3c523.o
-else
-  ifeq ($(CONFIG_ELMC),m)
-  M_OBJS += 3c523.o
-  endif
-endif
-
-ifeq ($(CONFIG_SKMC),y)
-L_OBJS += sk_mca.o
-else
-  ifeq ($(CONFIG_SKMC),m)
-  M_OBJS += sk_mca.o
-  endif
-endif
-
-ifeq ($(CONFIG_ELMC_II),y)
-L_OBJS += 3c527.o
-else
-  ifeq ($(CONFIG_ELMC_II),m)
-  M_OBJS += 3c527.o
-  endif
-endif
-
-ifeq ($(CONFIG_EL3),y)
-L_OBJS += 3c509.o
-else
-  ifeq ($(CONFIG_EL3),m)
-  M_OBJS += 3c509.o
-  endif
-endif
-
-ifeq ($(CONFIG_3C515),y)
-L_OBJS += 3c515.o
-else
-  ifeq ($(CONFIG_3C515),m)
-  M_OBJS += 3c515.o
-  endif
-endif
-
-ifeq ($(CONFIG_VORTEX),y)
-L_OBJS += 3c59x.o
-else
-  ifeq ($(CONFIG_VORTEX),m)
-  M_OBJS += 3c59x.o
-  endif
-endif
-
-ifeq ($(CONFIG_EEXPRESS),y)
-L_OBJS += eexpress.o
-else
-  ifeq ($(CONFIG_EEXPRESS),m)
-  M_OBJS += eexpress.o
-  endif
-endif
-
-ifeq ($(CONFIG_EEXPRESS_PRO),y)
-L_OBJS += eepro.o
-else
-  ifeq ($(CONFIG_EEXPRESS_PRO),m)
-  M_OBJS += eepro.o
-  endif
-endif
-
-ifeq ($(CONFIG_EEXPRESS_PRO100),y)
-L_OBJS += eepro100.o
-else
-  ifeq ($(CONFIG_EEXPRESS_PRO100),m)
-  M_OBJS += eepro100.o
-  endif
-endif
-
-ifeq ($(CONFIG_RTL8139),y)
-L_OBJS += rtl8139.o
-else
-  ifeq ($(CONFIG_RTL8139),m)
-  M_OBJS += rtl8139.o
-  endif
-endif
-
-ifeq ($(CONFIG_SIS900),y)
-L_OBJS += sis900.o
-else
-  ifeq ($(CONFIG_SIS900),m)
-  M_OBJS += sis900.o
-  endif
-endif
-
-ifeq ($(CONFIG_DM9102),y) 
-L_OBJS += dmfe.o
-else
-  ifeq ($(CONFIG_DM9102),m)
-  M_OBJS += dmfe.o
-  endif
-endif
-
-
-ifeq ($(CONFIG_YELLOWFIN),y)
-L_OBJS += yellowfin.o
-else
-  ifeq ($(CONFIG_YELLOWFIN),m)
-  M_OBJS += yellowfin.o
-  endif
-endif
-
-ifeq ($(CONFIG_ACENIC),y)
-L_OBJS += acenic.o
-else
-  ifeq ($(CONFIG_ACENIC),m)
-  M_OBJS += acenic.o
-  endif
-endif
-
-ifeq ($(CONFIG_WAVELAN),y)
-L_OBJS += wavelan.o
-else
-  ifeq ($(CONFIG_WAVELAN),m)
-  M_OBJS += wavelan.o
-  endif
-endif
-
-ifeq ($(CONFIG_ARLAN),y)
-LX_OBJS += arlan.o arlan-proc.o
-else
-  ifeq ($(CONFIG_ARLAN),m)
-  MX_OBJS += arlan.o arlan-proc.o
-  endif
-endif
-
-ifeq ($(CONFIG_TLAN),y)
-L_OBJS += tlan.o
-else
-  ifeq ($(CONFIG_TLAN),m)
-  M_OBJS += tlan.o
-  endif
-endif
-
-ifeq ($(CONFIG_VIA_RHINE),y)
-L_OBJS += via-rhine.o
-else
-  ifeq ($(CONFIG_VIA_RHINE),m)
-  M_OBJS += via-rhine.o
-  endif
-endif
-
-ifeq ($(CONFIG_ZNET),y)
-L_OBJS += znet.o
-endif
-
-ifeq ($(CONFIG_DEPCA),y)
-L_OBJS += depca.o
-else
-  ifeq ($(CONFIG_DEPCA),m)
-  M_OBJS += depca.o
-  endif
-endif
-
-ifeq ($(CONFIG_EWRK3),y)
-L_OBJS += ewrk3.o
-else
-  ifeq ($(CONFIG_EWRK3),m)
-  M_OBJS += ewrk3.o
-  endif
-endif
-
-ifeq ($(CONFIG_ATP),y)
-L_OBJS += atp.o
-endif
-
-ifeq ($(CONFIG_DE4X5),y)
-L_OBJS += de4x5.o
-else
-  ifeq ($(CONFIG_DE4X5),m)
-  M_OBJS += de4x5.o
-  endif
-endif
-
-ifeq ($(CONFIG_NI5010),y)
-L_OBJS += ni5010.o
-else
-  ifeq ($(CONFIG_NI5010),m)
-  M_OBJS += ni5010.o
-  endif
-endif
-
-ifeq ($(CONFIG_NI52),y)
-L_OBJS += ni52.o
-else
-  ifeq ($(CONFIG_NI52),m)
-  M_OBJS += ni52.o
-  endif
-endif
-
-ifeq ($(CONFIG_NI65),y)
-L_OBJS += ni65.o
-else
-  ifeq ($(CONFIG_NI65),m)
-  M_OBJS += ni65.o
-  endif
-endif
-
-ifeq ($(CONFIG_ELPLUS),y)
-L_OBJS += 3c505.o
-else
-  ifeq ($(CONFIG_ELPLUS),m)
-  M_OBJS += 3c505.o
-  endif
-endif
-
-ifeq ($(CONFIG_AC3200),y)
-L_OBJS += ac3200.o
-CONFIG_8390_BUILTIN = y
-else
-  ifeq ($(CONFIG_AC3200),m)
-  CONFIG_8390_MODULE = y
-  M_OBJS += ac3200.o
-  endif
-endif
-
-ifeq ($(CONFIG_APRICOT),y)
-CONFIG_82596_BUILTIN = y
-else
-  ifeq ($(CONFIG_APRICOT),m)
-  CONFIG_82596_MODULE = y
-  endif
-endif
-
-ifeq ($(CONFIG_MVME16x_NET),y)
-CONFIG_82596_BUILTIN = y
-else
-  ifeq ($(CONFIG_MVME16x_NET),m)
-  CONFIG_82596_MODULE = y
-  endif
-endif
-
-ifeq ($(CONFIG_BVME6000_NET),y)
-CONFIG_82596_BUILTIN = y
-else
-  ifeq ($(CONFIG_BVME6000_NET),m)
-  CONFIG_82596_MODULE = y
-  endif
-endif
-
-ifeq ($(CONFIG_DEC_ELCP),y)
-L_OBJS += tulip.o
-else
-  ifeq ($(CONFIG_DEC_ELCP),m)
-  M_OBJS += tulip.o
-  endif
-endif
-
-ifeq ($(CONFIG_ARCNET),y)
-LX_OBJS += arcnet.o
-else
-  ifeq ($(CONFIG_ARCNET),m)
-  MX_OBJS += arcnet.o
-  endif
-endif
-
-ifeq ($(CONFIG_ARCNET_COM90xx),y)
-L_OBJS += com90xx.o
-else
-  ifeq ($(CONFIG_ARCNET_COM90xx),m)
-  M_OBJS += com90xx.o
-  endif
-endif
-
-ifeq ($(CONFIG_ARCNET_COM90xxIO),y)
-L_OBJS += com90io.o
-else
-  ifeq ($(CONFIG_ARCNET_COM90xxIO),m)
-  M_OBJS += com90io.o
-  endif
-endif
-
-ifeq ($(CONFIG_ARCNET_RIM_I),y)
-L_OBJS += arc-rimi.o
-else
-  ifeq ($(CONFIG_ARCNET_RIM_I),m)
-  M_OBJS += arc-rimi.o
-  endif
-endif
-
-ifeq ($(CONFIG_ARCNET_COM20020),y)
-L_OBJS += com20020.o
-else
-  ifeq ($(CONFIG_ARCNET_COM20020),m)
-  M_OBJS += com20020.o
-  endif
-endif
-
-ifeq ($(CONFIG_ETH16I),y)
-L_OBJS += eth16i.o
-else
-  ifeq ($(CONFIG_ETH16I),m)
-  M_OBJS += eth16i.o
-  endif
-endif
-
-ifeq ($(CONFIG_EPIC100),y)
-L_OBJS += epic100.o
-else
-  ifeq ($(CONFIG_EPIC100),m)
-  M_OBJS += epic100.o
-  endif
-endif
-
-# If anything built-in uses slhc, then build it into the kernel also.
-# If not, but a module uses it, build as a module.
-ifdef CONFIG_SLHC_BUILTIN
-LX_OBJS += slhc.o
-else
-  ifdef CONFIG_SLHC_MODULE
-  MX_OBJS += slhc.o
-  endif
-endif
-
-# if anything built-in uses ppp_deflate, then build it into the kernel also.
-# If not, but a module uses it, build as a module.
-ifdef CONFIG_PPPDEF_BUILTIN
-L_OBJS += ppp_deflate.o
-else
-  ifdef CONFIG_PPPDEF_MODULE
-  M_OBJS += ppp_deflate.o
-  endif
-endif
-
-ifeq ($(CONFIG_ARIADNE2),y)
-L_OBJS += ariadne2.o
-CONFIG_8390_BUILTIN = y
-else
-  ifeq ($(CONFIG_ARIADNE2),m)
-  M_OBJS += ariadne2.o
-  CONFIG_8390_MODULE = y
-  endif
-endif
-
-# If anything built-in uses the 8390, then build it into the kernel also.
-# If not, but a module uses it, build as a module.
-ifdef CONFIG_8390_BUILTIN
-L_OBJS += 8390.o
-else
-  ifdef CONFIG_8390_MODULE
-  MX_OBJS += 8390.o
-  endif
-endif
-
-ifeq ($(CONFIG_HPLANCE),y)
-L_OBJS += hplance.o
-CONFIG_7990_BUILTIN = y
-else
-  ifeq ($(CONFIG_HPLANCE),m)
-  CONFIG_7990_MODULE = y
-  M_OBJS += hplance.o
-  endif
-endif
-
-ifeq ($(CONFIG_MVME147_NET),y)
-L_OBJS += mvme147.o
-CONFIG_7990_BUILTIN = y
-else
-  ifeq ($(CONFIG_MVME147_NET),m)
-  CONFIG_7990_MODULE = y
-  M_OBJS += mvme147.o
-  endif
-endif
-
-# If we need generic LANCE support, either in the kernel or as a module,
-# build it in the appropriate way.
-ifdef CONFIG_7990_BUILTIN
-L_OBJS += 7990.o
-else
-  ifdef CONFIG_7990_MODULE
-  M_OBJS += 7990.o
-  endif
-endif
-
-# If anything built-in uses the 82596, then build it into the kernel also.
-# If not, but a module uses it, build as a module.
-ifdef CONFIG_82596_BUILTIN
-L_OBJS += 82596.o
-else
-  ifdef CONFIG_82596_MODULE
-  M_OBJS += 82596.o
-  endif
-endif
-
-ifeq ($(CONFIG_EQUALIZER),y)
-L_OBJS += eql.o
-else
-  ifeq ($(CONFIG_EQUALIZER),m)
-  M_OBJS += eql.o
-  endif
-endif
-
-ifeq ($(CONFIG_MIPS_JAZZ_SONIC),y)
-L_OBJS += jazzsonic.o
-else
-  ifeq ($(CONFIG_MIPS_JAZZ_SONIC),m)
-  M_OBJS += jazzsonic.o
-  endif
-endif
-
-ifeq ($(CONFIG_BAGETLANCE),y)
-L_OBJS += bagetlance.o
-else
-  ifeq ($(CONFIG_BAGETLANCE),m)
-  M_OBJS += bagetlance.o
-  endif
-endif
-
-ifeq ($(CONFIG_DECLANCE),y)
-L_OBJS += declance.o
-else
-  ifeq ($(CONFIG_DECLANCE),m)
-  M_OBJS += declance.o
-  endif
-endif
-
-ifeq ($(CONFIG_ATARILANCE),y)
-L_OBJS += atarilance.o
-else
-  ifeq ($(CONFIG_ATARILANCE),m)
-  M_OBJS += atarilance.o
-  endif
-endif
-
-ifeq ($(CONFIG_ATARI_BIONET),y)
-L_OBJS += atari_bionet.o
-else
-  ifeq ($(CONFIG_ATARI_BIONET),m)
-  M_OBJS += atari_bionet.o
-  endif
-endif
-
-ifeq ($(CONFIG_ATARI_PAMSNET),y)
-L_OBJS += atari_pamsnet.o
-else
-  ifeq ($(CONFIG_ATARI_PAMSNET),m)
-  M_OBJS += atari_pamsnet.o
-  endif
-endif
-
-ifeq ($(CONFIG_A2065),y)
-L_OBJS += a2065.o
-else
-  ifeq ($(CONFIG_A2065),m)
-  M_OBJS += a2065.o
-  endif
-endif
-
-ifeq ($(CONFIG_HYDRA),y)
-L_OBJS += hydra.o
-else
-  ifeq ($(CONFIG_HYDRA),m)
-  M_OBJS += hydra.o
-  endif
-endif
-
-ifeq ($(CONFIG_ARIADNE),y)
-L_OBJS += ariadne.o
-else
-  ifeq ($(CONFIG_ARIADNE),m)
-  M_OBJS += ariadne.o
-  endif
-endif
-
-ifeq ($(CONFIG_DGRS),y)
-L_OBJS += dgrs.o
-else
-  ifeq ($(CONFIG_DGRS),m)
-  M_OBJS += dgrs.o
-  endif
-endif
-
-ifeq ($(CONFIG_CS89x0),y)
-L_OBJS += cs89x0.o
-else
-  ifeq ($(CONFIG_CS89x0),m)
-  M_OBJS += cs89x0.o
-  endif
-endif
-
-ifeq ($(CONFIG_LTPC),y)
-L_OBJS += ltpc.o
-else
-  ifeq ($(CONFIG_LTPC),m)
-  M_OBJS += ltpc.o
-  endif
-endif
-
-ifeq ($(CONFIG_COPS),y)
-L_OBJS += cops.o
-else
-  ifeq ($(CONFIG_COPS),m)
-  M_OBJS += cops.o
-  endif
-endif
-
-ifeq ($(CONFIG_IPDDP),y)
-L_OBJS += ipddp.o
-else
-  ifeq ($(CONFIG_IPDDP),m)
-  M_OBJS += ipddp.o
-  endif
-endif
+#
+# HIPPI adapters
+#
 
-ifeq ($(CONFIG_RCPCI),y)
-L_OBJS += rcpci.o
-else
-  ifeq ($(CONFIG_RCPCI),m)
-  M_OBJS += rcpci.o
-  endif
-endif
+obj-$(CONFIG_ROADRUNNER) += rrunner.o
 
-ifeq ($(CONFIG_MACE),y)
-L_OBJS += mace.o
-else
-  ifeq ($(CONFIG_MACE),m)
-  M_OBJS += mace.o
-  endif
-endif
+# Extract lists of the multi-part drivers.
+# The 'int-*' lists are the intermediate files used to build the multi's.
 
-ifeq ($(CONFIG_MACSONIC),y)
-L_OBJS += macsonic.o
-endif
+multi-y         := $(filter $(list-multi), $(obj-y))
+multi-m         := $(filter $(list-multi), $(obj-m))
+int-y           := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
+int-m           := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
 
-ifeq ($(CONFIG_BMAC),y)
-L_OBJS += bmac.o
-else
-  ifeq ($(CONFIG_BMAC),m)
-  M_OBJS += bmac.o
-  endif
-endif
+# Files that are both resident and modular: remove from modular.
 
-ifeq ($(CONFIG_NCR885E),y)
-L_OBJS += ncr885e.o
-else
-  ifeq ($(CONFIG_NCR885E),m)
-  M_OBJS += ncr885e.o
-  endif
-endif
+obj-m           := $(filter-out $(obj-y), $(obj-m))
+int-m           := $(filter-out $(int-y), $(int-m))
 
-ifeq ($(CONFIG_ADAPTEC_STARFIRE),y)
-L_OBJS += starfire.o
-else
-  ifeq ($(CONFIG_ADAPTEC_STARFIRE),m)
-  M_OBJS += starfire.o
-  endif
-endif
+# Take multi-part drivers out of obj-y and put components in.
 
-#
-# HIPPI adapters
-#
+obj-y           := $(filter-out $(list-multi), $(obj-y)) $(int-y)
 
-ifeq ($(CONFIG_ROADRUNNER),y)
-L_OBJS += rrunner.o
-else
-  ifeq ($(CONFIG_ROADRUNNER),m)
-  M_OBJS += rrunner.o
-  endif
-endif
+# Translate to Rules.make lists.
 
-ifeq ($(CONFIG_IRDA),y)
-SUB_DIRS += irda
-MOD_IN_SUB_DIRS += irda
-else
-  ifeq ($(CONFIG_IRDA),m)
-  MOD_IN_SUB_DIRS += irda
-  endif
-endif
+O_OBJS          := $(filter-out $(export-objs), $(obj-y))
+OX_OBJS         := $(filter     $(export-objs), $(obj-y))
+M_OBJS          := $(sort $(filter-out $(export-objs), $(obj-m)))
+MX_OBJS         := $(sort $(filter     $(export-objs), $(obj-m)))
 
-ifeq ($(CONFIG_TR),y)
-SUB_DIRS += tokenring
-MOD_IN_SUB_DIRS += tokenring
-else
-  ifeq ($(CONFIG_TR),m)
-  MOD_IN_SUB_DIRS += tokenring
-  endif
-endif
-
-ifeq ($(CONFIG_WAN),y)
-SUB_DIRS += wan
-MOD_IN_SUB_DIRS += wan
-else
-  ifeq ($(CONFIG_WAN),m)
-  MOD_IN_SUB_DIRS += wan
-  endif
-endif
-
-ifeq ($(CONFIG_NET_FC),y)
-SUB_DIRS += fc
-MOD_IN_SUB_DIRS += fc
-else
-  ifeq ($(CONFIG_NET_FC),m)
-  MOD_IN_SUB_DIRS += fc
-  endif
-endif
+L_OBJS += $(O_OBJS)
+L_OBJS += $(OX_OBJS)
 
 include $(TOPDIR)/Rules.make
 
@@ -1108,3 +273,4 @@
 
 rcpci.o: rcpci45.o rclanmtl.o
 	$(LD) -r -o rcpci.o rcpci45.o rclanmtl.o
+
diff -u --recursive --new-file v2.3.26/linux/drivers/net/Space.c linux/drivers/net/Space.c
--- v2.3.26/linux/drivers/net/Space.c	Mon Oct 11 15:38:14 1999
+++ linux/drivers/net/Space.c	Tue Nov  9 08:20:12 1999
@@ -42,24 +42,20 @@
    */
 
 extern int ne2_probe(struct net_device *dev);
-extern int tulip_probe(struct net_device *dev);
 extern int hp100_probe(struct net_device *dev);
 extern int ultra_probe(struct net_device *dev);
 extern int ultra32_probe(struct net_device *dev);
 extern int ultramca_probe(struct net_device *dev);
 extern int wd_probe(struct net_device *dev);
 extern int el2_probe(struct net_device *dev);
-extern int ne2k_pci_probe(struct net_device *dev);
 extern int ne_probe(struct net_device *dev);
 extern int hp_probe(struct net_device *dev);
 extern int hp_plus_probe(struct net_device *dev);
 extern int znet_probe(struct net_device *);
 extern int express_probe(struct net_device *);
 extern int eepro_probe(struct net_device *);
-extern int eepro100_probe(struct net_device *);
 extern int el3_probe(struct net_device *);
 extern int at1500_probe(struct net_device *);
-extern int pcnet32_probe(struct net_device *);
 extern int at1700_probe(struct net_device *);
 extern int fmv18x_probe(struct net_device *);
 extern int eth16i_probe(struct net_device *);
@@ -85,14 +81,7 @@
 extern int sonic_probe(struct net_device *);
 extern int SK_init(struct net_device *);
 extern int seeq8005_probe(struct net_device *);
-extern int tc59x_probe(struct net_device *);
-extern int dgrs_probe(struct net_device *);
 extern int smc_init( struct net_device * );
-extern int sparc_lance_probe(struct net_device *);
-extern int happy_meal_probe(struct net_device *);
-extern int qec_probe(struct net_device *);
-extern int bigmac_probe(struct net_device *);
-extern int myri_sbus_probe(struct net_device *);
 extern int sgiseeq_probe(struct net_device *);
 extern int atarilance_probe(struct net_device *);
 extern int sun3lance_probe(struct net_device *);
@@ -104,33 +93,19 @@
 extern int bionet_probe(struct net_device *);
 extern int pamsnet_probe(struct net_device *);
 extern int tlan_probe(struct net_device *);
-extern int mace_probe(struct net_device *);
-extern int bmac_probe(struct net_device *);
-extern int ncr885e_probe(struct net_device *);
 extern int cs89x0_probe(struct net_device *dev);
 extern int ethertap_probe(struct net_device *dev);
 extern int ether1_probe (struct net_device *dev);
 extern int ether3_probe (struct net_device *dev);
 extern int etherh_probe (struct net_device *dev);
 extern int am79c961_probe(struct net_device *dev);
-extern int epic100_probe(struct net_device *dev);
-extern int rtl8139_probe(struct net_device *dev);
-extern int sis900_probe(struct net_device *dev);
 extern int hplance_probe(struct net_device *dev);
 extern int bagetlance_probe(struct net_device *);
 extern int dec_lance_probe(struct net_device *);
 extern int mvme147lance_probe(struct net_device *dev);
-extern int via_rhine_probe(struct net_device *dev);
 extern int tc515_probe(struct net_device *dev);
 extern int lance_probe(struct net_device *dev);
-extern int starfire_probe(struct net_device *dev);
-extern int rcpci_probe(struct net_device *);
 extern int mac_onboard_sonic_probe(struct net_device *dev);
-extern int dmfe_reg_board(struct net_device *);
-
-/* Gigabit Ethernet adapters */
-extern int yellowfin_probe(struct net_device *dev);
-extern int acenic_probe(struct net_device *dev);
 
 /* Detachable devices ("pocket adaptors") */
 extern int atp_init(struct net_device *);
@@ -141,9 +116,6 @@
 extern int dfx_probe(struct net_device *dev);
 extern int apfddi_init(struct net_device *dev);
 
-/* HIPPI boards */
-extern int rr_hippi_probe(struct net_device *);
-
 /* Fibre Channel adapters */
 extern int iph5526_probe(struct net_device *dev);
 
@@ -182,74 +154,15 @@
 }
 
 /*
- * If your probe touches ISA ports (<0x400) in addition to
- * looking for PCI cards, then put it in the isa_probes
- * list instead.
- */
-struct devprobe pci_probes[] __initdata = {
-#ifdef CONFIG_DGRS
-	{dgrs_probe, 0},
-#endif
-#ifdef CONFIG_RCPCI
-	{rcpci_probe, 0},
-#endif
-#ifdef CONFIG_VORTEX
-	{tc59x_probe, 0},
-#endif
-#ifdef CONFIG_NE2K_PCI
-	{ne2k_pci_probe, 0},
-#endif
-#ifdef CONFIG_PCNET32
-	{pcnet32_probe, 0},
-#endif	
-#ifdef CONFIG_EEXPRESS_PRO100	/* Intel EtherExpress Pro/100 */
-	{eepro100_probe, 0},
-#endif
-#ifdef CONFIG_DEC_ELCP 
-	{tulip_probe, 0},
-#endif
-#ifdef CONFIG_DE4X5             /* DEC DE425, DE434, DE435 adapters */
-	{de4x5_probe, 0},
-#endif
-#ifdef CONFIG_TLAN
-	{tlan_probe, 0},
-#endif
-#ifdef CONFIG_EPIC100
-	{epic100_probe, 0},
-#endif
-#ifdef CONFIG_RTL8139
-	{rtl8139_probe, 0},
-#endif
-#ifdef CONFIG_SIS900
-	{sis900_probe, 0},
-#endif
-
-#ifdef CONFIG_DM9102
-	{dmfe_reg_board, 0}, 
-#endif
-
-#ifdef CONFIG_YELLOWFIN
-	{yellowfin_probe, 0},
-#endif
-#ifdef CONFIG_ACENIC
-	{acenic_probe, 0},
-#endif
-#ifdef CONFIG_VIA_RHINE
-	{via_rhine_probe, 0},
-#endif
-#ifdef CONFIG_ADAPTEC_STARFIRE
-	{starfire_probe, 0},
-#endif
-	{NULL, 0},
-};
-
-/*
  * This is a bit of an artificial separation as there are PCI drivers
  * that also probe for EISA cards (in the PCI group) and there are ISA
  * drivers that probe for EISA cards (in the ISA group).  These are the
- * EISA only driver probes.
+ * EISA only driver probes, and also the legacy PCI probes
  */
 struct devprobe eisa_probes[] __initdata = {
+#ifdef CONFIG_TLAN
+	{tlan_probe, 0},
+#endif
 #ifdef CONFIG_ULTRA32 
 	{ultra32_probe, 0},	
 #endif
@@ -268,24 +181,6 @@
 	{NULL, 0},
 };
 
-struct devprobe sparc_probes[] __initdata = {
-#ifdef CONFIG_HAPPYMEAL
-	{happy_meal_probe, 0},
-#endif
-#ifdef CONFIG_SUNLANCE
-	{sparc_lance_probe, 0},
-#endif
-#ifdef CONFIG_SUNQE
-	{qec_probe, 0},
-#endif
-#ifdef CONFIG_SUNBMAC
-	{bigmac_probe, 0},
-#endif
-#ifdef CONFIG_MYRI_SBUS
-	{myri_sbus_probe, 0},
-#endif
-	{NULL, 0},
-};
 
 struct devprobe mca_probes[] __initdata = {
 #ifdef CONFIG_ULTRAMCA 
@@ -463,18 +358,6 @@
 	{NULL, 0},
 };
 
-struct devprobe ppc_probes[] __initdata = {
-#ifdef CONFIG_MACE
-	{mace_probe, 0},
-#endif
-#ifdef CONFIG_BMAC
-	{bmac_probe, 0},
-#endif
-#ifdef CONFIG_NCR885E
-	{ncr885e_probe, 0},
-#endif
-	{NULL, 0},
-};
 
 struct devprobe sgi_probes[] __initdata = {
 #ifdef CONFIG_SGISEEQ
@@ -514,8 +397,9 @@
 
 /*
  * Unified ethernet device probe, segmented per architecture and
- * per bus interface.
+ * per bus interface. This drives the legacy devices only for now.
  */
+ 
 static int __init ethif_probe(struct net_device *dev)
 {
 	unsigned long base_addr = dev->base_addr;
@@ -537,14 +421,8 @@
 		return 0;
 	if (probe_list(dev, mips_probes) == 0)
 		return 0;
-	if (probe_list(dev, ppc_probes) == 0)
-		return 0;
 	if (probe_list(dev, sgi_probes) == 0)
 		return 0;
-	if (probe_list(dev, sparc_probes) == 0)
-		return 0;
-	if (probe_list(dev, pci_probes) == 0)
-		return 0;
 	if (probe_list(dev, eisa_probes) == 0)
 		return 0;
 	if (probe_list(dev, mca_probes) == 0)
@@ -585,28 +463,6 @@
 }
 #endif
 
-#ifdef CONFIG_HIPPI
-static int hippi_probe(struct net_device *dev)
-{
-	/*
-	 * Damn this is ugly.
-	 *
-	 * Why the heck would we want to determine this from the base
-	 * address? Stupid PC'ism .... grrrrr.
-	 */
-	if (dev->base_addr == -1)
-		return 1;
-
-	if (1
-#ifdef CONFIG_ROADRUNNER
-	    && rr_hippi_probe(dev)
-#endif
-	    && 1 ) {
-		return 1; /* -ENODEV or -EAGAIN would be more accurate. */
-	}
-	return 0;
-}
-#endif
 
 /* Pad device name to IFNAMSIZ=16. F.e. __PAD6 is tring of 9 zeros. */
 #define __PAD6 "\0\0\0\0\0\0\0\0\0"
@@ -668,16 +524,6 @@
 #   define NEXT_DEV     (&cops0_dev)
 #endif  /* COPS */
 
-#if defined(CONFIG_IPDDP)
-    extern int ipddp_init(struct net_device *dev);
-    static struct net_device dev_ipddp = {
-        "ipddp0"  __PAD6,
-                0, 0, 0, 0,
-                0x0, 0,
-                0, 0, 0, NEXT_DEV, ipddp_init };
-#   undef NEXT_DEV
-#   define NEXT_DEV     (&dev_ipddp)
-#endif /* CONFIG_IPDDP */
 
 /* The first device defaults to I/O base '0', which means autoprobe. */
 #ifndef ETH0_ADDR
@@ -694,109 +540,33 @@
 #define ETH_NOPROBE_ADDR 0xffe0
 
 static struct net_device eth7_dev = {
-    "eth7" __PAD4, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, NEXT_DEV, ethif_probe };
+    "eth%d" __PAD5, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, NEXT_DEV, ethif_probe };
 static struct net_device eth6_dev = {
-    "eth6" __PAD4, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth7_dev, ethif_probe };
+    "eth%d" __PAD5, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth7_dev, ethif_probe };
 static struct net_device eth5_dev = {
-    "eth5" __PAD4, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth6_dev, ethif_probe };
+    "eth%d" __PAD5, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth6_dev, ethif_probe };
 static struct net_device eth4_dev = {
-    "eth4" __PAD4, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth5_dev, ethif_probe };
+    "eth%d" __PAD5, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth5_dev, ethif_probe };
 static struct net_device eth3_dev = {
-    "eth3" __PAD4, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth4_dev, ethif_probe };
+    "eth%d" __PAD5, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth4_dev, ethif_probe };
 static struct net_device eth2_dev = {
-    "eth2" __PAD4, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth3_dev, ethif_probe };
+    "eth%d" __PAD5, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth3_dev, ethif_probe };
 static struct net_device eth1_dev = {
-    "eth1" __PAD4, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth2_dev, ethif_probe };
+    "eth%d" __PAD5, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, &eth2_dev, ethif_probe };
 
 static struct net_device eth0_dev = {
-    "eth0" __PAD4, 0, 0, 0, 0, ETH0_ADDR, ETH0_IRQ, 0, 0, 0, &eth1_dev, ethif_probe };
+    "eth%d" __PAD5, 0, 0, 0, 0, ETH0_ADDR, ETH0_IRQ, 0, 0, 0, &eth1_dev, ethif_probe };
 
 #   undef NEXT_DEV
 #   define NEXT_DEV	(&eth0_dev)
 
-#if defined(SLIP) || defined(CONFIG_SLIP)
-	/* To be exact, this node just hooks the initialization
-	   routines to the device structures.			*/
-extern int slip_init_ctrl_dev(struct net_device *);
-static struct net_device slip_bootstrap = {
-  "slip_proto", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, slip_init_ctrl_dev, };
-#undef NEXT_DEV
-#define NEXT_DEV (&slip_bootstrap)
-#endif	/* SLIP */
-
-#if defined(X25_ASY) || defined(CONFIG_X25_ASY)
-	/* To be exact, this node just hooks the initialization
-	   routines to the device structures.			*/
-extern int x25_asy_init_ctrl_dev(struct net_device *);
-static struct net_device x25_asy_bootstrap = {
-  "x25_proto", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, x25_asy_init_ctrl_dev, };
-#undef NEXT_DEV
-#define NEXT_DEV (&x25_asy_bootstrap)
-#endif	/* X25_ASY */
-  
-#if defined(CONFIG_MKISS)
-	/* To be exact, this node just hooks the initialization
-	   routines to the device structures.			*/
-extern int mkiss_init_ctrl_dev(struct net_device *);
-static struct net_device mkiss_bootstrap = {
-  "mkiss_proto", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, mkiss_init_ctrl_dev, };
-#undef NEXT_DEV
-#define NEXT_DEV (&mkiss_bootstrap)
-#endif	/* MKISS */
-  
-#if defined(CONFIG_YAM)
-extern int yam_init(struct net_device *);
-static struct net_device yam_bootstrap = {
-  "yam", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, yam_init, };
-#undef NEXT_DEV
-#define NEXT_DEV (&yam_bootstrap)
-#endif	/* CONFIG_YAM */
-  
-#if defined(CONFIG_STRIP)
-extern int strip_init_ctrl_dev(struct net_device *);
-static struct net_device strip_bootstrap = {
-    "strip_proto", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, strip_init_ctrl_dev, };
-#undef NEXT_DEV
-#define NEXT_DEV (&strip_bootstrap)
-#endif   /* STRIP */
-
-#if defined(CONFIG_PPP)
-extern int ppp_init(struct net_device *);
-static struct net_device ppp_bootstrap = {
-    "ppp_proto", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, ppp_init, };
-#undef NEXT_DEV
-#define NEXT_DEV (&ppp_bootstrap)
-#endif   /* PPP */
-
-#ifdef CONFIG_DUMMY
-    extern int dummy_init(struct net_device *dev);
-    static struct net_device dummy_dev = {
-	"dummy" __PAD5, 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, dummy_init, };
-#   undef	NEXT_DEV
-#   define	NEXT_DEV	(&dummy_dev)
-#endif
-
-#ifdef CONFIG_EQUALIZER
-extern int eql_init(struct net_device *dev);
-struct net_device eql_dev = {
-  "eql" __PAD3,			/* Master device for IP traffic load 
-				   balancing */
-  0x0, 0x0, 0x0, 0x0,		/* recv end/start; mem end/start */
-  0,				/* base I/O address */
-  0,				/* IRQ */
-  0, 0, 0,			/* flags */
-  NEXT_DEV,			/* next device */
-  eql_init			/* set up the rest */
-};
-#   undef       NEXT_DEV
-#   define      NEXT_DEV        (&eql_dev)
-#endif
+
 
 #ifdef CONFIG_TR
 /* Token-ring device probe */
 extern int ibmtr_probe(struct net_device *);
 extern int olympic_probe(struct net_device *);
-extern int sktr_probe(struct net_device *);
+extern int tms380tr_probe(struct net_device *);
 
 static int
 trif_probe(struct net_device *dev)
@@ -809,7 +579,7 @@
 	&& olympic_probe(dev)
 #endif
 #ifdef CONFIG_SKTR
-	&& sktr_probe(dev)
+	&& tms380tr_probe(dev)
 #endif
 #ifdef CONFIG_SMCTR
 	&& smctr_probe(dev)
@@ -820,21 +590,21 @@
     return 0;
 }
 static struct net_device tr7_dev = {
-    "tr7" __PAD3,0,0,0,0,0,0,0,0,0, NEXT_DEV, trif_probe };
+    "tr%d" __PAD3,0,0,0,0,0,0,0,0,0, NEXT_DEV, trif_probe };
 static struct net_device tr6_dev = {
-    "tr6" __PAD3,0,0,0,0,0,0,0,0,0, &tr7_dev, trif_probe };
+    "tr%d" __PAD3,0,0,0,0,0,0,0,0,0, &tr7_dev, trif_probe };
 static struct net_device tr5_dev = {
-    "tr5" __PAD3,0,0,0,0,0,0,0,0,0, &tr6_dev, trif_probe };
+    "tr%d" __PAD3,0,0,0,0,0,0,0,0,0, &tr6_dev, trif_probe };
 static struct net_device tr4_dev = {
-    "tr4" __PAD3,0,0,0,0,0,0,0,0,0, &tr5_dev, trif_probe };
+    "tr%d" __PAD3,0,0,0,0,0,0,0,0,0, &tr5_dev, trif_probe };
 static struct net_device tr3_dev = {
-    "tr3" __PAD3,0,0,0,0,0,0,0,0,0, &tr4_dev, trif_probe };
+    "tr%d" __PAD3,0,0,0,0,0,0,0,0,0, &tr4_dev, trif_probe };
 static struct net_device tr2_dev = {
-    "tr2" __PAD3,0,0,0,0,0,0,0,0,0, &tr3_dev, trif_probe };
+    "tr%d" __PAD3,0,0,0,0,0,0,0,0,0, &tr3_dev, trif_probe };
 static struct net_device tr1_dev = {
-    "tr1" __PAD3,0,0,0,0,0,0,0,0,0, &tr2_dev, trif_probe };
+    "tr%d" __PAD3,0,0,0,0,0,0,0,0,0, &tr2_dev, trif_probe };
 static struct net_device tr0_dev = {
-    "tr0" __PAD3,0,0,0,0,0,0,0,0,0, &tr1_dev, trif_probe };
+    "tr%d" __PAD3,0,0,0,0,0,0,0,0,0, &tr1_dev, trif_probe };
 #   undef       NEXT_DEV
 #   define      NEXT_DEV        (&tr0_dev)
 
@@ -861,28 +631,6 @@
 #define	NEXT_DEV	(&fddi0_dev)
 #endif 
 
-#ifdef CONFIG_HIPPI
-	static struct net_device hip3_dev =
-		{"hip3" __PAD4, 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, hippi_probe};
-	static struct net_device hip2_dev =
-		{"hip2" __PAD4, 0, 0, 0, 0, 0, 0, 0, 0, 0, &hip3_dev, hippi_probe};
-	static struct net_device hip1_dev =
-		{"hip1" __PAD4, 0, 0, 0, 0, 0, 0, 0, 0, 0, &hip2_dev, hippi_probe};
-	static struct net_device hip0_dev =
-		{"hip0" __PAD4, 0, 0, 0, 0, 0, 0, 0, 0, 0, &hip1_dev, hippi_probe};
-
-#undef	NEXT_DEV
-#define	NEXT_DEV	(&hip0_dev)
-#endif 
-
-#ifdef CONFIG_APBIF
-    extern int bif_init(struct net_device *dev);
-    static struct net_device bif_dev = {
-        "bif" __PAD3, 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, bif_init };
-#   undef       NEXT_DEV
-#   define      NEXT_DEV        (&bif_dev)
-#endif
-
 
 #ifdef CONFIG_NET_FC
     static struct net_device fc1_dev = {
@@ -917,27 +665,7 @@
 #endif 
 	
 	
-#ifdef CONFIG_NET_SB1000
-    extern int sb1000_probe(struct net_device *dev);
-    static struct net_device sb1000_dev = {
-        "cm0", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, sb1000_probe };
-#   undef       NEXT_DEV
-#   define      NEXT_DEV        (&sb1000_dev)
-#endif
 	
-extern int loopback_init(struct net_device *dev);
-struct net_device loopback_dev = {
-	"lo" __PAD2,		/* Software Loopback interface		*/
-	0x0,			/* recv memory end			*/
-	0x0,			/* recv memory start			*/
-	0x0,			/* memory end				*/
-	0x0,			/* memory start				*/
-	0,			/* base I/O address			*/
-	0,			/* IRQ					*/
-	0, 0, 0,		/* flags				*/
-	NEXT_DEV,		/* next device				*/
-	loopback_init		/* loopback_init should set up the rest	*/
-};
-
-struct net_device *dev_base = &loopback_dev;
+struct net_device *dev_base = NEXT_DEV;
 rwlock_t dev_base_lock = RW_LOCK_UNLOCKED;
+
diff -u --recursive --new-file v2.3.26/linux/drivers/net/acenic.c linux/drivers/net/acenic.c
--- v2.3.26/linux/drivers/net/acenic.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/net/acenic.c	Tue Nov  9 08:20:12 1999
@@ -295,12 +295,13 @@
 static int probed __initdata = 0;
 
 
-int __init acenic_probe (struct net_device *dev)
+int __init acenic_probe(void)
 {
 	int boards_found = 0;
 	int version_disp;
 	struct ace_private *ap;
 	struct pci_dev *pdev = NULL;
+	struct net_device *dev;
 
 	if (probed)
 		return -ENODEV;
@@ -312,7 +313,6 @@
 	version_disp = 0;
 
 	while ((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET<<8, pdev))){
-		dev = NULL;
 
 		if (!((pdev->vendor == PCI_VENDOR_ID_ALTEON) &&
 		      (pdev->device == PCI_DEVICE_ID_ALTEON_ACENIC)) &&
@@ -330,10 +330,10 @@
 		      (pdev->device == PCI_DEVICE_ID_SGI_ACENIC)))
 			continue;
 
-		dev = init_etherdev(dev, sizeof(struct ace_private));
+		dev = init_etherdev(NULL, sizeof(struct ace_private));
 
 		if (dev == NULL){
-			printk(KERN_ERR "Unable to allocate etherdev "
+			printk(KERN_ERR "acenic: Unable to allocate net_device "
 			       "structure!\n");
 			break;
 		}
@@ -341,8 +341,10 @@
 		if (!dev->priv)
 			dev->priv = kmalloc(sizeof(*ap), GFP_KERNEL);
 		if (!dev->priv)
+		{
+			printk(KERN_ERR "acenic: Unable to allocate memory.\n");
 			return -ENOMEM;
-
+		}
 		ap = dev->priv;
 		ap->pdev = pdev;
 
@@ -487,7 +489,7 @@
 
 	root_dev = NULL;
 
-	cards = acenic_probe(NULL);
+	cards = acenic_probe();
 	return cards ? 0 : -ENODEV;
 }
 
diff -u --recursive --new-file v2.3.26/linux/drivers/net/bmac.c linux/drivers/net/bmac.c
--- v2.3.26/linux/drivers/net/bmac.c	Mon Nov  1 13:56:26 1999
+++ linux/drivers/net/bmac.c	Tue Nov  9 08:20:12 1999
@@ -1256,14 +1256,14 @@
 	return 1;
 }
 
-int
-bmac_probe(struct net_device *dev)
+int bmac_probe(void)
 {
 	int j, rev;
 	struct bmac_data *bp;
 	struct device_node *bmacs;
 	unsigned char *addr;
 	static struct device_node *all_bmacs = NULL, *next_bmac;
+	struct net_device *dev = NULL;
 
 	if (all_bmacs == NULL) {
 		all_bmacs = find_devices("bmac");
@@ -1292,14 +1292,8 @@
 		return -EINVAL;
 	}
 
-	if (dev == NULL) {
-		dev = init_etherdev(NULL, PRIV_BYTES);
-		bmac_devs = dev;  /*KLUDGE!!*/
-	} else {
-		/* XXX this doesn't look right (but it's never used :-) */
-		dev->priv = kmalloc(PRIV_BYTES, GFP_KERNEL);
-		if (dev->priv == 0) return -ENOMEM;
-	}
+	dev = init_etherdev(NULL, PRIV_BYTES);
+	bmac_devs = dev;  /*KLUDGE!!*/
 
 #ifdef MODULE
 	bmac_devs = dev;
@@ -1610,7 +1604,7 @@
    
     if(bmac_devs != NULL)
         return -EBUSY;
-    res = bmac_probe(NULL);
+    res = bmac_probe();
     return res;
 }
 
diff -u --recursive --new-file v2.3.26/linux/drivers/net/dgrs.c linux/drivers/net/dgrs.c
--- v2.3.26/linux/drivers/net/dgrs.c	Wed Aug 18 11:36:41 1999
+++ linux/drivers/net/dgrs.c	Tue Nov  9 08:20:12 1999
@@ -1241,7 +1241,6 @@
 
 static int __init 
 dgrs_found_device(
-	struct net_device	*dev,
 	int		io,
 	ulong		mem,
 	int		irq,
@@ -1250,108 +1249,74 @@
 )
 {
 	DGRS_PRIV	*priv;
+	struct net_device *dev;
 
-	#ifdef MODULE
-	{
-		/* Allocate and fill new device structure. */
-		int dev_size = sizeof(struct net_device) + sizeof(DGRS_PRIV);
-		int i;
-
-		dev = (struct net_device *) kmalloc(dev_size, GFP_KERNEL);
-		memset(dev, 0, dev_size);
-		dev->priv = ((void *)dev) + sizeof(struct net_device);
-		priv = (DGRS_PRIV *)dev->priv;
-
-		dev->name = priv->devname; /* An empty string. */
-		dev->base_addr = io;
-		dev->mem_start = mem;
-		dev->mem_end = mem + 2048 * 1024 - 1;
-		dev->irq = irq;
-		priv->plxreg = plxreg;
-		priv->plxdma = plxdma;
-		priv->vplxdma = NULL;
-
-		priv->chan = 1;
-		priv->devtbl[0] = dev;
-
-		dev->init = dgrs_probe1;
-
-		ether_setup(dev);
-		priv->next_dev = dgrs_root_dev;
-		dgrs_root_dev = dev;
-		if (register_netdev(dev) != 0)
-			return -EIO;
+	/* Allocate and fill new device structure. */
+	int dev_size = sizeof(struct net_device) + sizeof(DGRS_PRIV);
+	int i;
+
+	dev = (struct net_device *) kmalloc(dev_size, GFP_KERNEL);
+	memset(dev, 0, dev_size);
+	dev->priv = ((void *)dev) + sizeof(struct net_device);
+	priv = (DGRS_PRIV *)dev->priv;
+
+	dev->name = priv->devname; /* An empty string. */
+	dev->base_addr = io;
+	dev->mem_start = mem;
+	dev->mem_end = mem + 2048 * 1024 - 1;
+	dev->irq = irq;
+	priv->plxreg = plxreg;
+	priv->plxdma = plxdma;
+	priv->vplxdma = NULL;
+
+	priv->chan = 1;
+	priv->devtbl[0] = dev;
+
+	dev->init = dgrs_probe1;
+	ether_setup(dev);
+	priv->next_dev = dgrs_root_dev;
+	dgrs_root_dev = dev;
+	if (register_netdev(dev) != 0)
+		return -EIO;
 
-		if ( !dgrs_nicmode )
-			return (0);	/* Switch mode, we are done */
+	if ( !dgrs_nicmode )
+		return (0);	/* Switch mode, we are done */
 
-		/*
-		 * Operating card as N separate NICs
-		 */
-		priv->nports = priv->bcomm->bc_nports;
-		for (i = 1; i < priv->nports; ++i)
-		{
-			struct net_device	*devN;
-			DGRS_PRIV	*privN;
+	/*
+	 * Operating card as N separate NICs
+	 */
 
-			/* Allocate new dev and priv structures */
-			devN = (struct net_device *) kmalloc(dev_size, GFP_KERNEL);
+	priv->nports = priv->bcomm->bc_nports;
 
+	for (i = 1; i < priv->nports; ++i)
+	{
+		struct net_device	*devN;
+		DGRS_PRIV	*privN;
+			/* Allocate new dev and priv structures */
+		devN = (struct net_device *) kmalloc(dev_size, GFP_KERNEL);
 			/* Make it an exact copy of dev[0]... */
-			memcpy(devN, dev, dev_size);
-			devN->priv = ((void *)devN) + sizeof(struct net_device);
-			privN = (DGRS_PRIV *)devN->priv;
-
+		memcpy(devN, dev, dev_size);
+		devN->priv = ((void *)devN) + sizeof(struct net_device);
+		privN = (DGRS_PRIV *)devN->priv;
 			/* ... but seset devname to a NULL string */
-			privN->devname[0] = 0;
-			devN->name = privN->devname;
-
+		privN->devname[0] = 0;
+		devN->name = privN->devname;
 			/* ... and zero out VM areas */
-			privN->vmem = 0;
-			privN->vplxdma = 0;
-
+		privN->vmem = 0;
+		privN->vplxdma = 0;
 			/* ... and zero out IRQ */
-			devN->irq = 0;
-
+		devN->irq = 0;
 			/* ... and base MAC address off address of 1st port */
-			devN->dev_addr[5] += i;
-			privN->chan = i+1;
-
-			priv->devtbl[i] = devN;
-
-			devN->init = dgrs_initclone;
-			ether_setup(devN);
-			privN->next_dev = dgrs_root_dev;
-			dgrs_root_dev = devN;
-			if (register_netdev(devN) != 0)
-				return -EIO;
-		}
-	}
-	#else
-	{
-		if (dev)
-		{
-			dev->priv = kmalloc(sizeof (DGRS_PRIV), GFP_KERNEL);
-			memset(dev->priv, 0, sizeof (DGRS_PRIV));
-		}
-		dev = init_etherdev(dev, sizeof(DGRS_PRIV));
-		priv = (DGRS_PRIV *)dev->priv;
-
-		dev->base_addr = io;
-		dev->mem_start = mem;
-		dev->mem_end = mem + 2048 * 1024;
-		dev->irq = irq;
-		priv->plxreg = plxreg;
-		priv->plxdma = plxdma;
-		priv->vplxdma = NULL;
-
-		priv->chan = 1;
-		priv->devtbl[0] = dev;
-
-		dgrs_probe1(dev);
+		devN->dev_addr[5] += i;
+		privN->chan = i+1;
+		priv->devtbl[i] = devN;
+		devN->init = dgrs_initclone;
+		ether_setup(devN);
+		privN->next_dev = dgrs_root_dev;
+		dgrs_root_dev = devN;
+		if (register_netdev(devN) != 0)
+			return -EIO;
 	}
-	#endif
-
 	return (0);
 }
 
@@ -1360,8 +1325,7 @@
  */
 static int is2iv[8] __initdata = { 0, 3, 5, 7, 10, 11, 12, 15 };
 
-static int __init 
-dgrs_scan(struct net_device *dev)
+static int __init  dgrs_scan(void)
 {
 	int	cards_found = 0;
 	uint	io;
@@ -1452,9 +1416,8 @@
 						PCI_LATENCY_TIMER, 255);
 			}
 
-			dgrs_found_device(dev, io, mem, irq, plxreg, plxdma);
+			dgrs_found_device(io, mem, irq, plxreg, plxdma);
 
-			dev = 0;
 			cards_found++;
 		}
 	}
@@ -1479,9 +1442,8 @@
 
 			irq = is2iv[ inb(io+ES4H_IS) & ES4H_IS_INTMASK ];
 
-			dgrs_found_device(dev, io, mem, irq, 0L, 0L);
+			dgrs_found_device(io, mem, irq, 0L, 0L);
 
-			dev = 0;
 			++cards_found;
 		}
 	}
@@ -1564,7 +1526,7 @@
 	 *	Find and configure all the cards
 	 */
 	dgrs_root_dev = NULL;
-	cards_found = dgrs_scan(0);
+	cards_found = dgrs_scan();
 
 	return cards_found ? 0 : -ENODEV;
 }
@@ -1605,7 +1567,7 @@
 {
 	int	cards_found;
 
-	cards_found = dgrs_scan(dev);
+	cards_found = dgrs_scan();
 	if (dgrs_debug && cards_found)
 		printk("dgrs: SW=%s FW=Build %d %s\n",
 			version, dgrs_firmnum, dgrs_firmdate);
diff -u --recursive --new-file v2.3.26/linux/drivers/net/dmfe.c linux/drivers/net/dmfe.c
--- v2.3.26/linux/drivers/net/dmfe.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/net/dmfe.c	Wed Nov 10 09:52:30 1999
@@ -59,6 +59,7 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/init.h>
 #include <linux/version.h>
 
 #include <linux/delay.h>
@@ -275,7 +276,7 @@
 };
 
 /* function declaration ------------------------------------- */
-int dmfe_reg_board(struct net_device *);
+int dmfe_reg_board(void);
 static int dmfe_open(struct net_device *);
 static int dmfe_start_xmit(struct sk_buff *, struct net_device *);
 static int dmfe_stop(struct net_device *);
@@ -309,7 +310,7 @@
  *	Search DM910X board, allocate space and register it
  */
  
-int dmfe_reg_board(struct net_device *dev)
+int __init dmfe_reg_board(void)
 {
 	u32 pci_iobase;
 	u16 dm9102_count = 0;
@@ -318,6 +319,7 @@
 	struct dmfe_board_info *db;	/* Point a board information structure */
 	int i;
 	struct pci_dev *net_dev = NULL;
+	struct net_device *dev;
 
 	DMFE_DBUG(0, "dmfe_reg_board()", 0);
 
@@ -365,7 +367,7 @@
 		dm9102_count++;	/* Found a DM9102 card */
 
 		/* Init network device */
-		dev = init_etherdev(dev, 0);
+		dev = init_etherdev(NULL, 0);
 
 		/* Allocated board information structure */
 		db = (void *) (kmalloc(sizeof(*db), GFP_KERNEL | GFP_DMA));
@@ -402,7 +404,6 @@
 		for (i = 0; i < 6; i++)
 			dev->dev_addr[i] = db->srom[20 + i];
 
-		dev = 0;	/* NULL device */
 	}
 
 #ifdef MODULE
@@ -1488,7 +1489,7 @@
 		break;
 	}
 
-	return dmfe_reg_board(0);	/* search board and register */
+	return dmfe_reg_board();	/* search board and register */
 }
 
 /*
diff -u --recursive --new-file v2.3.26/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c
--- v2.3.26/linux/drivers/net/eepro100.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/net/eepro100.c	Tue Nov  9 08:20:12 1999
@@ -284,9 +284,7 @@
 */
 
 /* This table drives the PCI probe routines. */
-static struct net_device *
-speedo_found1(int pci_bus, int pci_devfn, struct net_device *dev,
-			  long ioaddr, int irq, int chip_idx, int fnd_cnt);
+static struct net_device *speedo_found1(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
 
 #ifdef USE_IO
 #define SPEEDO_IOTYPE   PCI_USES_MASTER|PCI_USES_IO|PCI_ADDR1
@@ -312,8 +310,7 @@
 	const char *name;
 	u16	vendor_id, device_id, device_id_mask, flags;
 	int io_size;
-	struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev,
-							 long ioaddr, int irq, int chip_idx, int fnd_cnt);
+	struct net_device *(*probe1)(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
 } static pci_tbl[] = {
 	{ "Intel PCI EtherExpress Pro100",
 	  0x8086, 0x1229, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 32, speedo_found1 },
@@ -534,7 +531,7 @@
 static struct net_device *root_speedo_dev = NULL;
 
 #if ! defined(HAS_PCI_NETIF)
-int eepro100_init(struct net_device *dev)
+int eepro100_init(void)
 {
 	int cards_found = 0;
 	static int pci_index = 0;
@@ -616,19 +613,18 @@
 		} else if (speedo_debug > 1)
 			printk("  PCI latency timer (CFLT) is %#x.\n", pci_latency);
 
-		speedo_found1(pci_bus, pci_device_fn, dev, ioaddr, irq, 0,cards_found);
-		dev = NULL;
-		cards_found++;
+		if(speedo_found1(pci_bus, pci_device_fn, ioaddr, irq, 0,cards_found))
+			cards_found++;
 	}
 
 	return cards_found;
 }
 #endif
 
-static struct net_device *
-speedo_found1(int pci_bus, int pci_devfn, struct net_device *dev,
+static struct net_device *speedo_found1(int pci_bus, int pci_devfn, 
 			  long ioaddr, int irq, int chip_idx, int card_idx)
 {
+	struct net_device *dev;
 	struct speedo_private *sp;
 	const char *product;
 	int i, option;
@@ -640,7 +636,7 @@
 		printk(version);
 #endif
 
-	dev = init_etherdev(dev, sizeof(struct speedo_private));
+	dev = init_etherdev(NULL, sizeof(struct speedo_private));
 
 	if (dev->mem_start > 0)
 		option = dev->mem_start;
@@ -1837,12 +1833,12 @@
 		printk(KERN_INFO "%s", version);
 
 #if defined(HAS_PCI_NETIF)
-	cards_found = netif_pci_probe(pci_tbl, NULL);
+	cards_found = netif_pci_probe(pci_tbl);
 	if (cards_found < 0)
 		printk(KERN_INFO "eepro100: No cards found, driver not installed.\n");
 	return cards_found;
 #else
-	cards_found = eepro100_init(NULL);
+	cards_found = eepro100_init();
 	if (cards_found <= 0) {
 		printk(KERN_INFO "eepro100: No cards found, driver not installed.\n");
 		return -ENODEV;
@@ -1877,11 +1873,11 @@
 
 #else   /* not MODULE */
 
-int eepro100_probe(struct net_device *dev)
+int eepro100_probe(void)
 {
 	int cards_found = 0;
 
-	cards_found = eepro100_init(dev);
+	cards_found = eepro100_init();
 
 	/* Only emit the version if the driver is being used. */
 	if (speedo_debug > 0  &&  cards_found)
diff -u --recursive --new-file v2.3.26/linux/drivers/net/epic100.c linux/drivers/net/epic100.c
--- v2.3.26/linux/drivers/net/epic100.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/epic100.c	Tue Nov  9 08:20:12 1999
@@ -151,9 +151,8 @@
 
 /* The rest of these values should never change. */
 
-static struct net_device *epic_probe1(int pci_bus, int pci_devfn,
-								  struct net_device *dev, long ioaddr, int irq,
-								  int chip_id, int card_idx);
+static struct net_device *epic_probe1(int pci_bus, int pci_devfn, long ioaddr, int irq,
+					  int chip_id, int card_idx);
 
 enum pci_flags_bit {
 	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
@@ -164,7 +163,7 @@
 	const char *name;
 	u16	vendor_id, device_id, device_id_mask, pci_flags;
 	int io_size, min_latency;
-	struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev,
+	struct net_device *(*probe1)(int pci_bus, int pci_devfn,
 							 long ioaddr, int irq, int chip_idx, int fnd_cnt);
 } chip_tbl[] = {
 	{"SMSC EPIC/100 83c170", 0x10B8, 0x0005, 0x7fff,
@@ -274,12 +273,13 @@
 static struct net_device *root_epic_dev = NULL;
 
 #ifndef CARDBUS
-int epic100_probe(struct net_device *dev)
+int epic100_probe(void)
 {
 	int cards_found = 0;
 	int chip_idx, irq;
 	u16 pci_command, new_command;
 	unsigned char pci_bus, pci_device_fn;
+	struct net_device *dev;
 
 #ifdef PCI_SUPPORT_VER2
 	struct pci_dev *pcidev = NULL;
@@ -356,7 +356,7 @@
 									  PCI_COMMAND, new_command);
 		}
 
-		dev = chip_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, pci_ioaddr,
+		dev = chip_tbl[chip_idx].probe1(pci_bus, pci_device_fn, pci_ioaddr,
 									   irq, chip_idx, cards_found);
 
 		/* Check the latency timer. */
@@ -381,24 +381,26 @@
 }
 #endif  /* not CARDBUS */
 
-static struct net_device *epic_probe1(int pci_bus, int pci_devfn,
-								  struct net_device *dev, long ioaddr, int irq,
+static struct net_device *epic_probe1(int pci_bus, int pci_devfn, long ioaddr, int irq,
 								  int chip_idx, int card_idx)
 {
 	struct epic_private *ep;
 	int i, option = 0, duplex = 0;
+	struct net_device *dev;
 
-	if (dev && dev->mem_start) {
-		option = dev->mem_start;
-		duplex = (dev->mem_start & 16) ? 1 : 0;
-	} else if (card_idx >= 0  &&  card_idx < MAX_UNITS) {
+// FIXME	if (dev && dev->mem_start) {
+//		option = dev->mem_start;
+//		duplex = (dev->mem_start & 16) ? 1 : 0;
+//	}
+//	else 
+	if (card_idx >= 0  &&  card_idx < MAX_UNITS) {
 		if (options[card_idx] >= 0)
 			option = options[card_idx];
 		if (full_duplex[card_idx] >= 0)
 			duplex = full_duplex[card_idx];
 	}
 
-	dev = init_etherdev(dev, 0);
+	dev = init_etherdev(NULL, 0);
 
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
@@ -1343,7 +1345,7 @@
 			   io == 0 ? "I/O address" : "IRQ");
 		return NULL;
 	}
-	dev = epic_probe1(bus, devfn, NULL, io, irq, 2, -1);
+	dev = epic_probe1(bus, devfn, io, irq, 2, -1);
 	if (dev) {
 		dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
 		strcpy(node->dev_name, dev->name);
@@ -1417,7 +1419,7 @@
 	register_driver(&epic_ops);
 	return 0;
 #else
-	return epic100_probe(0);
+	return epic100_probe();
 #endif
 }
 
diff -u --recursive --new-file v2.3.26/linux/drivers/net/es3210.c linux/drivers/net/es3210.c
--- v2.3.26/linux/drivers/net/es3210.c	Mon Nov  1 13:56:26 1999
+++ linux/drivers/net/es3210.c	Wed Nov 10 09:53:37 1999
@@ -344,7 +344,7 @@
 		isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
 	} else {
 		/* Packet is in one chunk. */
-		isa_eth_io_copy_and_csum(skb, xfer_start, count, 0);
+		isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
 	}
 }
 
diff -u --recursive --new-file v2.3.26/linux/drivers/net/fc/iph5526.c linux/drivers/net/fc/iph5526.c
--- v2.3.26/linux/drivers/net/fc/iph5526.c	Fri Sep 10 23:57:30 1999
+++ linux/drivers/net/fc/iph5526.c	Thu Nov 11 16:57:30 1999
@@ -3752,11 +3752,6 @@
 
 /* SCSI stuff starts here */
 
-static struct proc_dir_entry proc_scsi_iph5526 =  {
-	PROC_SCSI_IPH5526_FC, 7, "iph5526", S_IFDIR, S_IRUGO | S_IXUGO, 2
-};
-
-
 int iph5526_detect(Scsi_Host_Template *tmpt)
 {
 struct Scsi_Host *host = NULL;
@@ -3766,7 +3761,7 @@
 u_int pci_maddr = 0;
 struct pci_dev *pdev = NULL;
 
-	tmpt->proc_dir = &proc_scsi_iph5526;
+	tmpt->proc_name = "iph5526";
 	if (pci_present() == 0) {
 		printk("iph5526: PCI not present\n");
 		return 0;
diff -u --recursive --new-file v2.3.26/linux/drivers/net/hamradio/mkiss.c linux/drivers/net/hamradio/mkiss.c
--- v2.3.26/linux/drivers/net/hamradio/mkiss.c	Wed Aug 18 11:38:50 1999
+++ linux/drivers/net/hamradio/mkiss.c	Tue Nov  9 08:20:12 1999
@@ -972,15 +972,7 @@
 
 	mkiss_init();
 
-#ifdef MODULE
 	return status;
-#else
-	/*
-	 * Return "not found", so that dev_init() will unlink
-	 * the placeholder device entry for us.
-	 */
-	return ENODEV;
-#endif
 }
 
 
diff -u --recursive --new-file v2.3.26/linux/drivers/net/hamradio/yam.c linux/drivers/net/hamradio/yam.c
--- v2.3.26/linux/drivers/net/hamradio/yam.c	Mon Nov  1 13:56:26 1999
+++ linux/drivers/net/hamradio/yam.c	Tue Nov  9 08:20:12 1999
@@ -70,68 +70,13 @@
 #include <linux/kernel.h>
 #include <linux/proc_fs.h>
 
-#include <linux/yam.h>
-#include "yam9600.h"
-#include "yam1200.h"
-
-/* --------------------------------------------------------------------- */
-
-/*
- * currently this module is supposed to support both module styles, i.e.
- * the old one present up to about 2.1.9, and the new one functioning
- * starting with 2.1.21. The reason is I have a kit allowing to compile
- * this module also under 2.0.x which was requested by several people.
- * This will go in 2.2
- */
 #include <linux/version.h>
-
-#if LINUX_VERSION_CODE >= 0x20100
 #include <asm/uaccess.h>
-#else
-#include <asm/segment.h>
-#include <linux/mm.h>
-
-#undef put_user
-#undef get_user
-
-#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; })
-#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; })
-
-extern inline int copy_from_user(void *to, const void *from, unsigned long n)
-{
-	int i = verify_area(VERIFY_READ, from, n);
-	if (i)
-		return i;
-	memcpy_fromfs(to, from, n);
-	return 0;
-}
-
-extern inline int copy_to_user(void *to, const void *from, unsigned long n)
-{
-	int i = verify_area(VERIFY_WRITE, to, n);
-	if (i)
-		return i;
-	memcpy_tofs(to, from, n);
-	return 0;
-}
-#endif
-
-#if LINUX_VERSION_CODE < 0x20115
-extern __inline__ void dev_init_buffers(struct net_device *dev)
-{
-	int i;
-	for (i = 0; i < DEV_NUMBUFFS; i++) {
-		skb_queue_head_init(&dev->buffs[i]);
-	}
-}
-#endif
-
-#if LINUX_VERSION_CODE >= 0x20123
 #include <linux/init.h>
-#else
-#define __init
-#define __initdata
-#endif
+
+#include <linux/yam.h>
+#include "yam9600.h"
+#include "yam1200.h"
 
 /* --------------------------------------------------------------------- */
 
@@ -177,11 +122,8 @@
 
 	/* Stats section */
 
-#if LINUX_VERSION_CODE < 0x20119
-	struct enet_statistics stats;
-#else
 	struct net_device_stats stats;
-#endif
+
 	int nb_rxint;
 	int nb_mdint;
 
@@ -907,13 +849,7 @@
 
 /* --------------------------------------------------------------------- */
 
-#if LINUX_VERSION_CODE >= 0x20119
-static struct net_device_stats *
- yam_get_stats(struct net_device *dev)
-#else
-static struct enet_statistics *
- yam_get_stats(struct net_device *dev)
-#endif
+static struct net_device_stats *yam_get_stats(struct net_device *dev)
 {
 	struct yam_port *yp;
 
@@ -1195,8 +1131,9 @@
 
 /* --------------------------------------------------------------------- */
 
-int __init yam_init(struct net_device *dev)
+int __init yam_init(void)
 {
+	struct net_device *dev;
 	int i;
 
 	printk(yam_drvinfo);
@@ -1241,8 +1178,6 @@
 	add_timer(&yam_timer);
 
 	yam_net_procfs_init();
-
-	/* do not keep this device */
 	return 1;
 }
 
@@ -1254,16 +1189,13 @@
  * command line settable parameters
  */
 
-#if LINUX_VERSION_CODE >= 0x20115
 
 MODULE_AUTHOR("Frederic Rible F1OAT frible@teaser.fr");
 MODULE_DESCRIPTION("Yam amateur radio modem driver");
 
-#endif
-
 int init_module(void)
 {
-	int ret = yam_init(NULL);
+	int ret = yam_init();
 
 	return (ret == 1) ? 0 : ret;
 }
diff -u --recursive --new-file v2.3.26/linux/drivers/net/mace.c linux/drivers/net/mace.c
--- v2.3.26/linux/drivers/net/mace.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/mace.c	Wed Nov 10 19:55:03 1999
@@ -101,10 +101,10 @@
     return d;
 }
 
-int
-mace_probe(struct net_device *dev)
+int mace_probe(void)
 {
 	int j, rev;
+	struct net_device *dev;
 	struct mace_data *mp;
 	struct device_node *mace;
 	unsigned char *addr;
@@ -126,13 +126,7 @@
 		return -ENODEV;
 	}
 
-	if (dev == NULL)
-		dev = init_etherdev(0, PRIV_BYTES);
-	else {
-		dev->priv = kmalloc(PRIV_BYTES, GFP_KERNEL);
-		if (dev->priv == 0)
-			return -ENOMEM;
-	}
+	dev = init_etherdev(0, PRIV_BYTES);
 	memset(dev->priv, 0, PRIV_BYTES);
 
 	mp = (struct mace_data *) dev->priv;
@@ -913,7 +907,7 @@
 
     if(mace_devs != NULL)
 	return -EBUSY;
-    res = mace_probe(NULL);
+    res = mace_probe();
     return res;
 }
 
diff -u --recursive --new-file v2.3.26/linux/drivers/net/myri_sbus.c linux/drivers/net/myri_sbus.c
--- v2.3.26/linux/drivers/net/myri_sbus.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/myri_sbus.c	Tue Nov  9 08:20:12 1999
@@ -1074,8 +1074,9 @@
 	return 0;
 }
 
-int __init myri_sbus_probe(struct net_device *dev)
+int __init myri_sbus_probe(void)
 {
+	struct net_device *dev = NULL;
 	struct linux_sbus *bus;
 	struct linux_sbus_device *sdev = 0;
 	static int called = 0;
@@ -1108,7 +1109,7 @@
 init_module(void)
 {
 	root_myri_dev = NULL;
-	return myri_sbus_probe(NULL);
+	return myri_sbus_probe();
 }
 
 void
diff -u --recursive --new-file v2.3.26/linux/drivers/net/ncr885e.c linux/drivers/net/ncr885e.c
--- v2.3.26/linux/drivers/net/ncr885e.c	Mon Oct 11 15:38:14 1999
+++ linux/drivers/net/ncr885e.c	Wed Nov 10 10:00:48 1999
@@ -33,7 +33,6 @@
 #include <linux/malloc.h>
 #include <linux/netdevice.h>
 #include <linux/pci.h>
-#include <linux/malloc.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/errno.h>
@@ -134,8 +133,7 @@
 static int ncr885e_close( struct net_device *dev );
 static void ncr885e_rx( struct net_device *dev );
 static void ncr885e_tx( struct net_device *dev );
-static int ncr885e_probe1( struct net_device *dev, unsigned long ioaddr,
-			   unsigned char irq );
+static int ncr885e_probe1( unsigned long ioaddr, unsigned char irq );
 static int ncr885e_xmit_start( struct sk_buff *skb, struct net_device *dev );
 static struct net_device_stats *ncr885e_stats( struct net_device *dev );
 static void ncr885e_set_multicast( struct net_device *dev );
@@ -1162,15 +1160,16 @@
  */
 
 static int
-ncr885e_probe1( struct net_device *dev, unsigned long ioaddr, unsigned char irq )
+ncr885e_probe1(unsigned long ioaddr, unsigned char irq )
 
 {
+	struct net_device *dev;
 	struct ncr885e_private *sp;
 	unsigned short station_addr[3], val;
 	unsigned char *p;
 	int  i;
 
-	dev = init_etherdev( dev, 0 );
+	dev = init_etherdev(NULL, 0 );
 
 	/* construct private data for the 885 ethernet */
 	dev->priv = kmalloc( sizeof( struct ncr885e_private ), GFP_KERNEL );
@@ -1227,7 +1226,7 @@
  *  worry about the rest.
  */
 
-int __init ncr885e_probe( struct net_device *dev )
+int __init ncr885e_probe(void)
 {
 	struct pci_dev *pdev = NULL;
 	unsigned int ioaddr, chips = 0;
@@ -1257,7 +1256,7 @@
 			continue;
 
 		/* finish off the probe */
-		if ( !(ncr885e_probe1( dev, ioaddr, irq ))) {
+		if ( !(ncr885e_probe1(ioaddr, irq ))) {
 
 			chips++;
 
@@ -1432,7 +1431,7 @@
 	if ( debug >= 0)
 		ncr885e_debug = debug;
 
-	return ncr885e_probe( NULL );
+	return ncr885e_probe();
 }
 
 void
diff -u --recursive --new-file v2.3.26/linux/drivers/net/ne2k-pci.c linux/drivers/net/ne2k-pci.c
--- v2.3.26/linux/drivers/net/ne2k-pci.c	Fri Sep 10 23:57:30 1999
+++ linux/drivers/net/ne2k-pci.c	Tue Nov  9 08:20:12 1999
@@ -104,9 +104,8 @@
 #define NESM_START_PG	0x40	/* First page of TX buffer */
 #define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
 
-int ne2k_pci_probe(struct net_device *dev);
-static struct net_device *ne2k_pci_probe1(struct net_device *dev, long ioaddr, int irq,
-									  int chip_idx);
+int ne2k_pci_probe(void);
+static struct net_device *ne2k_pci_probe1(long ioaddr, int irq, int chip_idx);
 
 static int ne2k_pci_open(struct net_device *dev);
 static int ne2k_pci_close(struct net_device *dev);
@@ -139,7 +138,7 @@
 	if (debug)
 		printk(KERN_INFO "%s", version);
 
-	if (ne2k_pci_probe(0)) {
+	if (ne2k_pci_probe()) {
 		printk(KERN_NOTICE "ne2k-pci.c: No useable cards found, driver NOT installed.\n");
 		return -ENODEV;
 	}
@@ -186,11 +185,12 @@
 {"ne2k_pci", ne2k_pci_probe1, NE_IO_EXTENT, 0};
 #endif
 
-int __init ne2k_pci_probe(struct net_device *dev)
+int __init ne2k_pci_probe(void)
 {
 	struct pci_dev *pdev = NULL;
 	int cards_found = 0;
 	int i;
+	struct net_device *dev;
 
 	if ( ! pci_present())
 		return -ENODEV;
@@ -241,7 +241,7 @@
 #endif
 		printk("ne2k-pci.c: PCI NE2000 clone '%s' at I/O %#lx, IRQ %d.\n",
 			   pci_clone_list[i].name, pci_ioaddr, pci_irq_line);
-		dev = ne2k_pci_probe1(dev, pci_ioaddr, pci_irq_line, i);
+		dev = ne2k_pci_probe1(pci_ioaddr, pci_irq_line, i);
 		if (dev == 0) {
 			/* Should not happen. */
 			printk(KERN_ERR "ne2k-pci: Probe of PCI card at %#lx failed.\n",
@@ -255,7 +255,6 @@
 			ne2k_card->dev = dev;
 			ne2k_card->pci_dev = pdev;
 		}
-		dev = 0;
 
 		cards_found++;
 	}
@@ -263,8 +262,9 @@
 	return cards_found ? 0 : -ENODEV;
 }
 
-static struct net_device __init *ne2k_pci_probe1(struct net_device *dev, long ioaddr, int irq, int chip_idx)
+static struct net_device __init *ne2k_pci_probe1(long ioaddr, int irq, int chip_idx)
 {
+	struct net_device *dev;
 	int i;
 	unsigned char SA_prom[32];
 	int start_page, stop_page;
@@ -288,7 +288,7 @@
 		}
 	}
 
-	dev = init_etherdev(dev, 0);
+	dev = init_etherdev(NULL, 0);
 
 	/* Reset card. Who knows what dain-bramaged state it was left in. */
 	{
diff -u --recursive --new-file v2.3.26/linux/drivers/net/net_init.c linux/drivers/net/net_init.c
--- v2.3.26/linux/drivers/net/net_init.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/net/net_init.c	Tue Nov  9 08:23:04 1999
@@ -23,6 +23,10 @@
 	
 	14/06/96 - Paul Gortmaker:	Add generic eth_change_mtu() function. 
 	24/09/96 - Paul Norton: Add token-ring variants of the netdev functions. 
+	
+	08/11/99 - Alan Cox: Got fed up of the mess in this file and cleaned it
+			up. We now share common code and have regularised name
+			allocation setups. Abolished the 16 card limits.
 */
 
 #include <linux/config.h>
@@ -61,79 +65,66 @@
 	and a space waste]
 */
 
-/* The list of used and available "eth" slots (for "eth0", "eth1", etc.) */
-#define MAX_ETH_CARDS 16
-static struct net_device *ethdev_index[MAX_ETH_CARDS];
-
 
-/* Fill in the fields of the device structure with ethernet-generic values.
-
-   If no device structure is passed, a new one is constructed, complete with
-   a SIZEOF_PRIVATE private data area.
+static struct net_device *init_alloc_dev(int sizeof_priv)
+{
+	struct net_device *dev;
+	int alloc_size = sizeof(struct net_device) + IFNAMSIZ
+		+ sizeof_priv + 3;
+	alloc_size &= ~3;		/* Round to dword boundary. */
+	dev = (struct net_device *)kmalloc(alloc_size, GFP_KERNEL);
+	if(dev==NULL)
+	{
+		printk(KERN_ERR "alloc_dev: Unable to allocate device memory.\n");
+		return NULL;
+	}
+	memset(dev, 0, alloc_size);
+	if (sizeof_priv)
+		dev->priv = (void *) (dev + 1);
+	dev->name = sizeof_priv + (char *)(dev + 1);
+	return dev;
+}
 
-   If an empty string area is passed as dev->name, or a new structure is made,
-   a new name string is constructed.  The passed string area should be 8 bytes
-   long.
+/* 
+ *	Create and name a device from a prototype, then perform any needed
+ *	setup.
  */
 
-struct net_device *
-init_etherdev(struct net_device *dev, int sizeof_priv)
+static struct net_device *init_netdev(struct net_device *dev, int sizeof_priv, char *mask, void (*setup)(struct net_device *))
 {
 	int new_device = 0;
-	int i;
 
-	/* Use an existing correctly named device in Space.c:dev_base. */
+	/*
+	 *	Allocate a device if one is not provided.
+	 */
+	 
 	if (dev == NULL) {
-		int alloc_size = sizeof(struct net_device) + IFNAMSIZ
-			+ sizeof_priv + 3;
-		struct net_device *cur_dev;
-		char pname[8];		/* Putative name for the device.  */
-
-		for (i = 0; i < MAX_ETH_CARDS; ++i)
-			if (ethdev_index[i] == NULL) {
-				sprintf(pname, "eth%d", i);
-				read_lock_bh(&dev_base_lock);
-				for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next) {
-					if (strcmp(pname, cur_dev->name) == 0) {
-						dev = cur_dev;
-						read_unlock_bh(&dev_base_lock);
-						dev->init = NULL;
-						sizeof_priv = (sizeof_priv + 3) & ~3;
-						dev->priv = sizeof_priv
-							  ? kmalloc(sizeof_priv, GFP_KERNEL)
-							  :	NULL;
-						if (dev->priv) memset(dev->priv, 0, sizeof_priv);
-						goto found;
-					}
-				}
-				read_unlock_bh(&dev_base_lock);
-			}
-
-		alloc_size &= ~3;		/* Round to dword boundary. */
-
-		dev = (struct net_device *)kmalloc(alloc_size, GFP_KERNEL);
+		dev=init_alloc_dev(sizeof_priv);
 		if(dev==NULL)
 			return NULL;
-		memset(dev, 0, alloc_size);
-		if (sizeof_priv)
-			dev->priv = (void *) (dev + 1);
-		dev->name = sizeof_priv + (char *)(dev + 1);
 		new_device = 1;
 	}
 
-found:						/* From the double loop above. */
-
-	if (dev->name &&
-		((dev->name[0] == '\0') || (dev->name[0] == ' '))) {
-		for (i = 0; i < MAX_ETH_CARDS; ++i)
-			if (ethdev_index[i] == NULL) {
-				sprintf(dev->name, "eth%d", i);
-				ethdev_index[i] = dev;
-				break;
-			}
+	/*
+	 *	Allocate a name
+	 */
+	 
+	if (dev->name && (dev->name[0] == '\0' || dev->name[0] == ' '))
+	{
+		if(dev_alloc_name(dev, mask)<0)
+		{
+			if(new_device)
+				kfree(dev);
+			return NULL;
+		}
 	}
-
-	ether_setup(dev); 	/* Hmmm, should this be called here? */
+	
+	/*
+	 *	Configure via the caller provided setup function then
+	 *	register if needed.
+	 */
+	
+	setup(dev);
 	
 	if (new_device) {
 		rtnl_lock();
@@ -143,6 +134,21 @@
 	return dev;
 }
 
+/* Fill in the fields of the device structure with ethernet-generic values.
+
+   If no device structure is passed, a new one is constructed, complete with
+   a SIZEOF_PRIVATE private data area.
+
+   If an empty string area is passed as dev->name, or a new structure is made,
+   a new name string is constructed.  The passed string area should be 8 bytes
+   long.
+ */
+
+struct net_device *init_etherdev(struct net_device *dev, int sizeof_priv)
+{
+	return init_netdev(dev, sizeof_priv, "eth%d", ether_setup);
+}
+
 
 static int eth_mac_addr(struct net_device *dev, void *p)
 {
@@ -174,8 +180,6 @@
 #endif
 
 #ifdef CONFIG_HIPPI
-#define MAX_HIP_CARDS	4
-static struct net_device *hipdev_index[MAX_HIP_CARDS];
 
 static int hippi_change_mtu(struct net_device *dev, int new_mtu)
 {
@@ -205,82 +209,14 @@
 
 struct net_device *init_hippi_dev(struct net_device *dev, int sizeof_priv)
 {
-	int new_device = 0;
-	int i;
-
-	/* Use an existing correctly named device in Space.c:dev_base. */
-	if (dev == NULL) {
-		int alloc_size = sizeof(struct net_device) + IFNAMSIZ
-			+ sizeof_priv + 3;
-		struct net_device *cur_dev;
-		char pname[8];
-
-		for (i = 0; i < MAX_HIP_CARDS; ++i)
-			if (hipdev_index[i] == NULL) {
-				sprintf(pname, "hip%d", i);
-				read_lock_bh(&dev_base_lock);
-				for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next) {
-					if (strcmp(pname, cur_dev->name) == 0) {
-						dev = cur_dev;
-						read_unlock_bh(&dev_base_lock);
-						dev->init = NULL;
-						sizeof_priv = (sizeof_priv + 3) & ~3;
-						dev->priv = sizeof_priv
-							  ? kmalloc(sizeof_priv, GFP_KERNEL)
-							  :	NULL;
-						if (dev->priv) memset(dev->priv, 0, sizeof_priv);
-						goto hipfound;
-					}
-				}
-				read_unlock_bh(&dev_base_lock);
-			}
-
-		alloc_size &= ~3;		/* Round to dword boundary. */
-
-		dev = (struct net_device *)kmalloc(alloc_size, GFP_KERNEL);
-		if(dev==NULL)
-			return NULL;
-		memset(dev, 0, alloc_size);
-		if (sizeof_priv)
-			dev->priv = (void *) (dev + 1);
-		dev->name = sizeof_priv + (char *)(dev + 1);
-		new_device = 1;
-	}
-
-hipfound:				/* From the double loop above. */
-
-	if (dev->name &&
-		((dev->name[0] == '\0') || (dev->name[0] == ' '))) {
-		for (i = 0; i < MAX_HIP_CARDS; ++i)
-			if (hipdev_index[i] == NULL) {
-				sprintf(dev->name, "hip%d", i);
-				hipdev_index[i] = dev;
-				break;
-			}
-	}
-
-	hippi_setup(dev);
-	
-	if (new_device) {
-		rtnl_lock();
-		register_netdevice(dev);
-		rtnl_unlock();
-	}
-	return dev;
+	return init_netdev(dev, sizeof_priv, "hip%d", hippi_setup);
 }
 
 
 void unregister_hipdev(struct net_device *dev)
 {
-	int i;
 	rtnl_lock();
 	unregister_netdevice(dev);
-	for (i = 0; i < MAX_HIP_CARDS; ++i) {
-		if (hipdev_index[i] == dev) {
-			hipdev_index[i] = NULL;
-			break;
-		}
-	}
 	rtnl_unlock();
 }
 
@@ -303,23 +239,9 @@
 
 void ether_setup(struct net_device *dev)
 {
-	int i;
 	/* Fill in the fields of the device structure with ethernet-generic values.
 	   This should be in a common file instead of per-driver.  */
 	
-	/* register boot-defined "eth" devices */
-	if (dev->name && (strncmp(dev->name, "eth", 3) == 0)) {
-		i = simple_strtoul(dev->name + 3, NULL, 0);
-		if (ethdev_index[i] == NULL) {
-			ethdev_index[i] = dev;
-		}
-		else if (dev != ethdev_index[i]) {
-			/* Really shouldn't happen! */
-			printk("ether_setup: Ouch! Someone else took %s\n",
-				dev->name);
-		}
-	}
-
 	dev->change_mtu		= eth_change_mtu;
 	dev->hard_header	= eth_header;
 	dev->rebuild_header 	= eth_rebuild_header;
@@ -376,19 +298,6 @@
 #ifdef CONFIG_HIPPI
 void hippi_setup(struct net_device *dev)
 {
-	int i;
-
-	if (dev->name && (strncmp(dev->name, "hip", 3) == 0)) {
-		i = simple_strtoul(dev->name + 3, NULL, 0);
-		if (hipdev_index[i] == NULL) {
-			hipdev_index[i] = dev;
-		}
-		else if (dev != hipdev_index[i]) {
-			printk("hippi_setup: Ouch! Someone else took %s\n",
-				dev->name);
-		}
-	}
-
 	dev->set_multicast_list	= NULL;
 	dev->change_mtu			= hippi_change_mtu;
 	dev->hard_header		= hippi_header;
@@ -478,45 +387,33 @@
 	return 0;
 }
 
-static int etherdev_get_index(struct net_device *dev)
-{
-	int i=MAX_ETH_CARDS;
-
-	for (i = 0; i < MAX_ETH_CARDS; ++i)	{
-		if (ethdev_index[i] == NULL) {
-			sprintf(dev->name, "eth%d", i);
-/*			printk("loading device '%s'...\n", dev->name);*/
-			ethdev_index[i] = dev;
-			return i;
-		}
-	}
-	return -1;
-}
-
-static void etherdev_put_index(struct net_device *dev)
-{
-	int i;
-	for (i = 0; i < MAX_ETH_CARDS; ++i) {
-		if (ethdev_index[i] == dev) {
-			ethdev_index[i] = NULL;
-			break;
-		}
-	}
-}
-
 int register_netdev(struct net_device *dev)
 {
-	int i=-1;
-
 	rtnl_lock();
 
-	if (dev->name &&
-	    (dev->name[0] == '\0' || dev->name[0] == ' '))
-		i = etherdev_get_index(dev);
-
+	/*
+	 *	If the name is a format string the caller wants us to
+	 *	do a name allocation
+	 */
+	 
+	if (dev->name && strchr(dev->name, '%'))
+	{
+		if(dev_alloc_name(dev, dev->name)<0)
+			return -EBUSY;
+	}
+	
+	/*
+	 *	Back compatibility hook. Kill this one in 2.5
+	 */
+	
+	if (dev->name && (dev->name[0]==0 || dev->name[0]==' '))
+	{
+		if(dev_alloc_name(dev, "eth%d")<0)
+			return -EBUSY;
+	}
+		
+		
 	if (register_netdevice(dev)) {
-		if (i >= 0)
-			etherdev_put_index(dev);
 		rtnl_unlock();
 		return -EIO;
 	}
@@ -528,120 +425,40 @@
 {
 	rtnl_lock();
 	unregister_netdevice(dev);
-	etherdev_put_index(dev);
 	rtnl_unlock();
 }
 
 
 #ifdef CONFIG_TR
-/* The list of used and available "tr" slots */
-#define MAX_TR_CARDS 16
-static struct net_device *trdev_index[MAX_TR_CARDS];
 
-struct net_device *init_trdev(struct net_device *dev, int sizeof_priv)
+static void tr_configure(struct net_device *dev)
 {
-	int new_device = 0;
-	int i;
-
-	/* Use an existing correctly named device in Space.c:dev_base. */
-	if (dev == NULL) {
-		int alloc_size = sizeof(struct net_device) + IFNAMSIZ
-			+ sizeof_priv + 3;
-		struct net_device *cur_dev;
-		char pname[8];		/* Putative name for the device.  */
-
-		for (i = 0; i < MAX_TR_CARDS; ++i)
-			if (trdev_index[i] == NULL) {
-				sprintf(pname, "tr%d", i);
-				read_lock_bh(&dev_base_lock);
-				for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next) {
-					if (strcmp(pname, cur_dev->name) == 0) {
-						dev = cur_dev;
-						read_unlock_bh(&dev_base_lock);
-						dev->init = NULL;
-						sizeof_priv = (sizeof_priv + 3) & ~3;
-						dev->priv = sizeof_priv
-							  ? kmalloc(sizeof_priv, GFP_KERNEL)
-							  :	NULL;
-						if (dev->priv) memset(dev->priv, 0, sizeof_priv);
-						goto trfound;
-					}
-				}
-				read_unlock_bh(&dev_base_lock);
-			}
-
-		alloc_size &= ~3;		/* Round to dword boundary. */
-		dev = (struct net_device *)kmalloc(alloc_size, GFP_KERNEL);
-		if(dev==NULL)
-			return NULL;
-		memset(dev, 0, alloc_size);
-		if (sizeof_priv)
-			dev->priv = (void *) (dev + 1);
-		dev->name = sizeof_priv + (char *)(dev + 1);
-		new_device = 1;
-	}
-
-trfound:						/* From the double loop above. */
-
-	for (i = 0; i < MAX_TR_CARDS; ++i)
-		if (trdev_index[i] == NULL) {
-			sprintf(dev->name, "tr%d", i);
-			trdev_index[i] = dev;
-			break;
-		}
-
-
-	dev->hard_header	 = tr_header;
-	dev->rebuild_header  = tr_rebuild_header;
+	/*
+	 *	Configure and register
+	 */
+	
+	dev->hard_header	= tr_header;
+	dev->rebuild_header	= tr_rebuild_header;
 
-	dev->type		     = ARPHRD_IEEE802;
-	dev->hard_header_len = TR_HLEN;
-	dev->mtu		     = 2000; /* bug in fragmenter...*/
-	dev->addr_len		 = TR_ALEN;
-	dev->tx_queue_len	 = 100;	/* Long queues on tr */
+	dev->type		= ARPHRD_IEEE802_TR;
+	dev->hard_header_len	= TR_HLEN;
+	dev->mtu		= 2000;
+	dev->addr_len		= TR_ALEN;
+	dev->tx_queue_len	= 100;	/* Long queues on tr */
 	
 	memset(dev->broadcast,0xFF, TR_ALEN);
 
 	/* New-style flags. */
-	dev->flags		= IFF_BROADCAST;
-
-	if (new_device) {
-		rtnl_lock();
-		register_netdevice(dev);
-		rtnl_unlock();
-	}
-	return dev;
+	dev->flags		= IFF_BROADCAST | IFF_MULTICAST ;
 }
 
-void tr_setup(struct net_device *dev)
+struct net_device *init_trdev(struct net_device *dev, int sizeof_priv)
 {
-	int i;
-
-	/* register boot-defined "tr" devices */
-	if (dev->name && (strncmp(dev->name, "tr", 2) == 0)) {
-		i = simple_strtoul(dev->name + 2, NULL, 0);
-		if (trdev_index[i] == NULL) {
-			trdev_index[i] = dev;
-		}
-		else if (dev != trdev_index[i]) {
-			/* Really shouldn't happen! */
-			printk("tr_setup: Ouch! Someone else took %s\n",
-				dev->name);
-		}
-	}
+	return init_netdev(dev, sizeof_priv, "tr%d", tr_configure);
 }
 
-void tr_freedev(struct net_device *dev)
+void tr_setup(struct net_device *dev)
 {
-	int i;
-	for (i = 0; i < MAX_TR_CARDS; ++i) 
-	{
-		if (trdev_index[i] == dev) 
-		{
-			trdev_index[i] = NULL;
-			break;
-		}
-	}
 }
 
 int register_trdev(struct net_device *dev)
@@ -660,33 +477,14 @@
 	rtnl_lock();
 	unregister_netdevice(dev);
 	rtnl_unlock();
-	tr_freedev(dev);
 }
 #endif
 
 
 #ifdef CONFIG_NET_FC
 
-#define MAX_FC_CARDS 2
-static struct net_device *fcdev_index[MAX_FC_CARDS];
- 
 void fc_setup(struct net_device *dev)
 {
-int i;
-
-        /* register boot-defined "fc" devices */
-        if (dev->name && (strncmp(dev->name, "fc", 2) == 0)) {
-                i = simple_strtoul(dev->name + 2, NULL, 0);
-                if (fcdev_index[i] == NULL) {
-                        fcdev_index[i] = dev;
-                }
-                else if (dev != fcdev_index[i]) {
-                        /* Really shouldn't happen! */
-                        printk("fc_setup: Ouch! Someone else took %s\n",
-                                dev->name);
-                }
-        }
-		
 	dev->hard_header        =        fc_header;
         dev->rebuild_header  	=        fc_rebuild_header;
                 
@@ -700,76 +498,16 @@
 
         /* New-style flags. */
         dev->flags              =        IFF_BROADCAST;
-		dev_init_buffers(dev);
+	dev_init_buffers(dev);
         return;
 }
 
 
 struct net_device *init_fcdev(struct net_device *dev, int sizeof_priv)
 {
-int new_device = 0;
-int i;
-	/* Use an existing correctly named device in Space.c:dev_base. */
-     if (dev == NULL) {
-     int alloc_size = sizeof(struct net_device) + sizeof("fc%d  ") + sizeof_priv + 3; 
-     struct net_device *cur_dev;
-     char pname[8];          /* Putative name for the device.  */
-                 
-      	for (i = 0; i < MAX_FC_CARDS; ++i)
-        	if (fcdev_index[i] == NULL) {
-            	sprintf(pname, "fc%d", i);
-                for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next)
-                	if (strcmp(pname, cur_dev->name) == 0) {
-                        dev = cur_dev;
-                        dev->init = NULL;
-                        sizeof_priv = (sizeof_priv + 3) &~3;
-                        dev->priv = sizeof_priv 
-								? kmalloc(sizeof_priv, GFP_KERNEL)
-                                : NULL;
-                        if (dev->priv) memset(dev->priv, 0, sizeof_priv);
-                        goto fcfound;
-                     }
-               }
-
-        alloc_size &= ~3;               /* Round to dword boundary. */
-        dev = (struct net_device *)kmalloc(alloc_size, GFP_KERNEL);
-		memset(dev, 0, alloc_size);
-        if (sizeof_priv)
-        	dev->priv = (void *) (dev + 1);
-        dev->name = sizeof_priv + (char *)(dev + 1);
-        new_device = 1;
-      }        
-
-fcfound:                       /* From the double loop */
-                                
-        for (i = 0; i < MAX_FC_CARDS; ++i)
-                if (fcdev_index[i] == NULL) {
-                        sprintf(dev->name, "fc%d", i);
-                        fcdev_index[i] = dev;
-                        break;
-                }
-                                                
-        fc_setup(dev);                                 
-        if (new_device) {
-		rtnl_lock();
-                register_netdevice(dev);  
-		rtnl_unlock();
-	}                
-        return dev;
+	return init_netdev(dev, sizeof_priv, "fc%d", fc_setup);
 }
 
-void fc_freedev(struct net_device *dev)
-{                                               
-int i;
-	for (i = 0; i < MAX_FC_CARDS; ++i) {
-		if (fcdev_index[i] == dev) {
-			fcdev_index[i] = NULL;
-			break;
-		}
-	}
-}
-
-
 int register_fcdev(struct net_device *dev)
 {
         dev_init_buffers(dev);
@@ -785,7 +523,6 @@
         rtnl_lock();
 	unregister_netdevice(dev);
         rtnl_unlock();
-        fc_freedev(dev);
 }
 
 #endif /* CONFIG_NET_FC */
diff -u --recursive --new-file v2.3.26/linux/drivers/net/pcmcia/3c574_cs.c linux/drivers/net/pcmcia/3c574_cs.c
--- v2.3.26/linux/drivers/net/pcmcia/3c574_cs.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/net/pcmcia/3c574_cs.c	Thu Nov 11 16:03:36 1999
@@ -2,7 +2,7 @@
 
 	Written 1993-1998 by
 	Donald Becker, becker@cesdis.gsfc.nasa.gov, (driver core) and
-	David Hinds, dhinds@allegro.stanford.edu (derived from his PC card code).
+	David Hinds, dhinds@pcmcia.sourceforge.org (from his PC card code).
 
 	This software may be used and distributed according to the terms of
 	the GNU Public License, incorporated herein by reference.
@@ -322,7 +322,6 @@
 	link->release.data = (u_long)link;
 	link->io.NumPorts1 = 32;
 	link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-	link->io.IOAddrLines = 5;
 	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
 	link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
 	if (irq_list[0] == -1)
@@ -483,6 +482,7 @@
 	/* Configure card */
 	link->state |= DEV_CONFIG;
 
+	link->io.IOAddrLines = 16;
 	for (i = j = 0; j < 0x400; j += 0x20) {
 		link->io.BasePort1 = j ^ 0x300;
 		i = CardServices(RequestIO, link->handle, &link->io);
diff -u --recursive --new-file v2.3.26/linux/drivers/net/pcmcia/3c575_cb.c linux/drivers/net/pcmcia/3c575_cb.c
--- v2.3.26/linux/drivers/net/pcmcia/3c575_cb.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/pcmcia/3c575_cb.c	Thu Nov 11 16:03:36 1999
@@ -0,0 +1,2215 @@
+/* EtherLinkXL.c: A 3Com EtherLink PCI III/XL ethernet driver for linux. */
+/*
+	Written 1996-1999 by Donald Becker.
+
+	This software may be used and distributed according to the terms
+	of the GNU Public License, incorporated herein by reference.
+
+	This driver is for the 3Com "Vortex" and "Boomerang" series ethercards.
+	Members of the series include Fast EtherLink 3c590/3c592/3c595/3c597
+	and the EtherLink XL 3c900 and 3c905 cards.
+
+	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+	Center of Excellence in Space Data and Information Sciences
+	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+*/
+
+static char *version =
+"3c59x.c:v0.99L 5/28/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
+
+/* "Knobs" that adjust features and parameters. */
+/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
+   Setting to > 1512 effectively disables this feature. */
+static const int rx_copybreak = 200;
+/* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */
+static const int mtu = 1500;
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+static int max_interrupt_work = 20;
+
+/* Put out somewhat more debugging messages. (0: no msg, 1 minimal .. 6). */
+#define vortex_debug debug
+#ifdef VORTEX_DEBUG
+static int vortex_debug = VORTEX_DEBUG;
+#else
+static int vortex_debug = 1;
+#endif
+
+/* Some values here only for performance evaluation and path-coverage
+   debugging. */
+static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits;
+
+/* A few values that may be tweaked. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  (2*HZ)
+
+/* Keep the ring sizes a power of two for efficiency. */
+#define TX_RING_SIZE	16
+#define RX_RING_SIZE	32
+#define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
+
+#ifndef __OPTIMIZE__
+#warning  You must compile this file with the correct options!
+#warning  See the last lines of the source file.
+#error You must compile this driver with "-O".
+#endif
+
+#include <linux/config.h>
+#include <linux/version.h>
+#ifdef MODULE
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#include <linux/module.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <asm/irq.h>			/* For NR_IRQS only. */
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+/* Kernel compatibility defines, some common to David Hinds' PCMCIA package.
+   This is only in the support-all-kernels source code. */
+
+#define RUN_AT(x) (jiffies + (x))
+
+#include <linux/delay.h>
+
+#define PCI_SUPPORT_VER2
+#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
+#if ! defined(CAP_NET_ADMIN)
+#define capable(CAP_XXX) (suser())
+#endif
+
+#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
+MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
+MODULE_DESCRIPTION("3Com 3c590/3c900 series Vortex/Boomerang driver");
+MODULE_PARM(debug, "i");
+MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(max_interrupt_work, "i");
+MODULE_PARM(compaq_ioaddr, "i");
+MODULE_PARM(compaq_irq, "i");
+MODULE_PARM(compaq_device_id, "i");
+#endif
+
+/* Operational parameter that usually are not changed. */
+
+/* The Vortex size is twice that of the original EtherLinkIII series: the
+   runtime register window, window 1, is now always mapped in.
+   The Boomerang size is twice as large as the Vortex -- it has additional
+   bus master control registers. */
+#define VORTEX_TOTAL_SIZE 0x20
+#define BOOMERANG_TOTAL_SIZE 0x40
+
+/* Set iff a MII transceiver on any interface requires mdio preamble.
+   This only set with the original DP83840 on older 3c905 boards, so the extra
+   code size of a per-interface flag is not worthwhile. */
+static char mii_preamble_required = 0;
+
+/*
+				Theory of Operation
+
+I. Board Compatibility
+
+This device driver is designed for the 3Com FastEtherLink and FastEtherLink
+XL, 3Com's PCI to 10/100baseT adapters.  It also works with the 10Mbs
+versions of the FastEtherLink cards.  The supported product IDs are
+  3c590, 3c592, 3c595, 3c597, 3c900, 3c905
+
+The related ISA 3c515 is supported with a separate driver, 3c515.c, included
+with the kernel source or available from
+    cesdis.gsfc.nasa.gov:/pub/linux/drivers/3c515.html
+
+II. Board-specific settings
+
+PCI bus devices are configured by the system at boot time, so no jumpers
+need to be set on the board.  The system BIOS should be set to assign the
+PCI INTA signal to an otherwise unused system IRQ line.
+
+The EEPROM settings for media type and forced-full-duplex are observed.
+The EEPROM media type should be left at the default "autoselect" unless using
+10base2 or AUI connections which cannot be reliably detected.
+
+III. Driver operation
+
+The 3c59x series use an interface that's very similar to the previous 3c5x9
+series.  The primary interface is two programmed-I/O FIFOs, with an
+alternate single-contiguous-region bus-master transfer (see next).
+
+The 3c900 "Boomerang" series uses a full-bus-master interface with separate
+lists of transmit and receive descriptors, similar to the AMD LANCE/PCnet,
+DEC Tulip and Intel Speedo3.  The first chip version retains a compatible
+programmed-I/O interface that has been removed in 'B' and subsequent board
+revisions.
+
+One extension that is advertised in a very large font is that the adapters
+are capable of being bus masters.  On the Vortex chip this capability was
+only for a single contiguous region making it far less useful than the full
+bus master capability.  There is a significant performance impact of taking
+an extra interrupt or polling for the completion of each transfer, as well
+as difficulty sharing the single transfer engine between the transmit and
+receive threads.  Using DMA transfers is a win only with large blocks or
+with the flawed versions of the Intel Orion motherboard PCI controller.
+
+The Boomerang chip's full-bus-master interface is useful, and has the
+currently-unused advantages over other similar chips that queued transmit
+packets may be reordered and receive buffer groups are associated with a
+single frame.
+
+With full-bus-master support, this driver uses a "RX_COPYBREAK" scheme.
+Rather than a fixed intermediate receive buffer, this scheme allocates
+full-sized skbuffs as receive buffers.  The value RX_COPYBREAK is used as
+the copying breakpoint: it is chosen to trade-off the memory wasted by
+passing the full-sized skbuff to the queue layer for all frames vs. the
+copying cost of copying a frame to a correctly-sized skbuff.
+
+IIIC. Synchronization
+The driver runs as two independent, single-threaded flows of control.  One
+is the send-packet routine, which enforces single-threaded use by the
+dev->tbusy flag.  The other thread is the interrupt handler, which is single
+threaded by the hardware and other software.
+
+IV. Notes
+
+Thanks to Cameron Spitzer and Terry Murphy of 3Com for providing development
+3c590, 3c595, and 3c900 boards.
+The name "Vortex" is the internal 3Com project name for the PCI ASIC, and
+the EISA version is called "Demon".  According to Terry these names come
+from rides at the local amusement park.
+
+The new chips support both ethernet (1.5K) and FDDI (4.5K) packet sizes!
+This driver only supports ethernet packets because of the skbuff allocation
+limit of 4K.
+*/
+
+/* This table drives the PCI probe routines.  It's mostly boilerplate in all
+   of the drivers, and will likely be provided by some future kernel.
+*/
+enum pci_flags_bit {
+	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
+	PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
+};
+struct pci_id_info {
+	const char *name;
+	u16	vendor_id, device_id, device_id_mask, flags;
+	int drv_flags, io_size;
+	struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev,
+							 long ioaddr, int irq, int chip_idx, int fnd_cnt);
+};
+
+enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4,
+	   HAS_PWR_CTRL=0x10, HAS_MII=0x20, HAS_NWAY=0x40, HAS_CB_FNS=0x80, };
+static struct net_device *vortex_probe1(int pci_bus, int pci_devfn,
+									struct net_device *dev, long ioaddr,
+									int irq, int dev_id, int card_idx);
+static struct pci_id_info pci_tbl[] = {
+	{"3c590 Vortex 10Mbps",			0x10B7, 0x5900, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
+	{"3c595 Vortex 100baseTx",		0x10B7, 0x5950, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
+	{"3c595 Vortex 100baseT4",		0x10B7, 0x5951, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
+	{"3c595 Vortex 100base-MII",	0x10B7, 0x5952, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
+	{"3Com Vortex",					0x10B7, 0x5900, 0xff00,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
+	{"3c900 Boomerang 10baseT",		0x10B7, 0x9000, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
+	{"3c900 Boomerang 10Mbps Combo", 0x10B7, 0x9001, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
+	{"3c900 Cyclone 10Mbps Combo", 0x10B7, 0x9005, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
+	{"3c900B-FL Cyclone 10base-FL",	0x10B7, 0x900A, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
+	{"3c905 Boomerang 100baseTx",	0x10B7, 0x9050, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
+	{"3c905 Boomerang 100baseT4",	0x10B7, 0x9051, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
+	{"3c905B Cyclone 100baseTx",	0x10B7, 0x9055, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, vortex_probe1},
+	{"3c905B Cyclone 10/100/BNC",	0x10B7, 0x9058, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, vortex_probe1},
+	{"3c905B-FX Cyclone 100baseFx",	0x10B7, 0x905A, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
+	{"3c905C Tornado",	0x10B7, 0x9200, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
+	{"3c980 Cyclone",	0x10B7, 0x9800, 0xfff0,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
+	{"3cSOHO100-TX Hurricane",	0x10B7, 0x7646, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
+	{"3c555 Laptop Hurricane",	0x10B7, 0x5055, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
+	{"3c575 Boomerang CardBus",		0x10B7, 0x5057, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
+	{"3CCFE575 Cyclone CardBus",	0x10B7, 0x5157, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS,
+	 128, vortex_probe1},
+	{"3CCFE575CT Cyclone CardBus",	0x10B7, 0x5257, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS,
+	 128, vortex_probe1},
+	{"3CCFE656 Cyclone CardBus",	0x10B7, 0x6560, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS,
+	 128, vortex_probe1},
+	{"3CCFEM656 Cyclone CardBus",	0x10B7, 0x6562, 0xffff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS,
+	 128, vortex_probe1},
+	{"3c575 series CardBus (unknown version)", 0x10B7, 0x5057, 0xf0ff,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
+	{"3Com Boomerang (unknown version)",	0x10B7, 0x9000, 0xff00,
+	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
+	{0,},						/* 0 terminated list. */
+};
+
+/* Operational definitions.
+   These are not used by other compilation units and thus are not
+   exported in a ".h" file.
+
+   First the windows.  There are eight register windows, with the command
+   and status registers available in each.
+   */
+#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
+#define EL3_CMD 0x0e
+#define EL3_STATUS 0x0e
+
+/* The top five bits written to EL3_CMD are a command, the lower
+   11 bits are the parameter, if applicable.
+   Note that 11 parameters bits was fine for ethernet, but the new chip
+   can handle FDDI length frames (~4500 octets) and now parameters count
+   32-bit 'Dwords' rather than octets. */
+
+enum vortex_cmd {
+	TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
+	RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11,
+	UpStall = 6<<11, UpUnstall = (6<<11)+1,
+	DownStall = (6<<11)+2, DownUnstall = (6<<11)+3,
+	RxDiscard = 8<<11, TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
+	FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
+	SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
+	SetTxThreshold = 18<<11, SetTxStart = 19<<11,
+	StartDMAUp = 20<<11, StartDMADown = (20<<11)+1, StatsEnable = 21<<11,
+	StatsDisable = 22<<11, StopCoax = 23<<11, SetFilterBit = 25<<11,};
+
+/* The SetRxFilter command accepts the following classes: */
+enum RxFilter {
+	RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 };
+
+/* Bits in the general status register. */
+enum vortex_status {
+	IntLatch = 0x0001, HostError = 0x0002, TxComplete = 0x0004,
+	TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
+	IntReq = 0x0040, StatsFull = 0x0080,
+	DMADone = 1<<8, DownComplete = 1<<9, UpComplete = 1<<10,
+	DMAInProgress = 1<<11,			/* DMA controller is still busy.*/
+	CmdInProgress = 1<<12,			/* EL3_CMD is still busy.*/
+};
+
+/* Register window 1 offsets, the window used in normal operation.
+   On the Vortex this window is always mapped at offsets 0x10-0x1f. */
+enum Window1 {
+	TX_FIFO = 0x10,  RX_FIFO = 0x10,  RxErrors = 0x14,
+	RxStatus = 0x18,  Timer=0x1A, TxStatus = 0x1B,
+	TxFree = 0x1C, /* Remaining free bytes in Tx buffer. */
+};
+enum Window0 {
+	Wn0EepromCmd = 10,		/* Window 0: EEPROM command register. */
+	Wn0EepromData = 12,		/* Window 0: EEPROM results register. */
+	IntrStatus=0x0E,		/* Valid in all windows. */
+};
+enum Win0_EEPROM_bits {
+	EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0,
+	EEPROM_EWENB = 0x30,		/* Enable erasing/writing for 10 msec. */
+	EEPROM_EWDIS = 0x00,		/* Disable EWENB before 10 msec timeout. */
+};
+/* EEPROM locations. */
+enum eeprom_offset {
+	PhysAddr01=0, PhysAddr23=1, PhysAddr45=2, ModelID=3,
+	EtherLink3ID=7, IFXcvrIO=8, IRQLine=9,
+	NodeAddr01=10, NodeAddr23=11, NodeAddr45=12,
+	DriverTune=13, Checksum=15};
+
+enum Window2 {			/* Window 2. */
+	Wn2_ResetOptions=12,
+};
+enum Window3 {			/* Window 3: MAC/config bits. */
+	Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8,
+};
+union wn3_config {
+	int i;
+	struct w3_config_fields {
+		unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2;
+		int pad8:8;
+		unsigned int ram_split:2, pad18:2, xcvr:4, autoselect:1;
+		int pad24:7;
+	} u;
+};
+
+enum Window4 {		/* Window 4: Xcvr/media bits. */
+	Wn4_FIFODiag = 4, Wn4_NetDiag = 6, Wn4_PhysicalMgmt=8, Wn4_Media = 10,
+};
+enum Win4_Media_bits {
+	Media_SQE = 0x0008,		/* Enable SQE error counting for AUI. */
+	Media_10TP = 0x00C0,	/* Enable link beat and jabber for 10baseT. */
+	Media_Lnk = 0x0080,		/* Enable just link beat for 100TX/100FX. */
+	Media_LnkBeat = 0x0800,
+};
+enum Window7 {					/* Window 7: Bus Master control. */
+	Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,
+};
+/* Boomerang bus master control registers. */
+enum MasterCtrl {
+	PktStatus = 0x20, DownListPtr = 0x24, FragAddr = 0x28, FragLen = 0x2c,
+	TxFreeThreshold = 0x2f, UpPktStatus = 0x30, UpListPtr = 0x38,
+};
+
+/* The Rx and Tx descriptor lists.
+   Caution Alpha hackers: these types are 32 bits!  Note also the 8 byte
+   alignment contraint on tx_ring[] and rx_ring[]. */
+#define LAST_FRAG  0x80000000			/* Last Addr/Len pair in descriptor. */
+struct boom_rx_desc {
+	u32 next;					/* Last entry points to 0.   */
+	s32 status;
+	u32 addr;					/* Up to 63 addr/len pairs possible. */
+	s32 length;					/* Set LAST_FRAG to indicate last pair. */
+};
+/* Values for the Rx status entry. */
+enum rx_desc_status {
+	RxDComplete=0x00008000, RxDError=0x4000,
+	/* See boomerang_rx() for actual error bits */
+	IPChksumErr=1<<25, TCPChksumErr=1<<26, UDPChksumErr=1<<27,
+	IPChksumValid=1<<29, TCPChksumValid=1<<30, UDPChksumValid=1<<31,
+};
+
+struct boom_tx_desc {
+	u32 next;					/* Last entry points to 0.   */
+	s32 status;					/* bits 0:12 length, others see below.  */
+	u32 addr;
+	s32 length;
+};
+
+/* Values for the Tx status entry. */
+enum tx_desc_status {
+	CRCDisable=0x2000, TxDComplete=0x8000,
+	AddIPChksum=0x02000000, AddTCPChksum=0x04000000, AddUDPChksum=0x08000000,
+	TxIntrUploaded=0x80000000,		/* IRQ when in FIFO, but maybe not sent. */
+};
+
+/* Chip features we care about in vp->capabilities, read from the EEPROM. */
+enum ChipCaps { CapBusMaster=0x20, CapPwrMgmt=0x2000 };
+
+struct vortex_private {
+	/* The Rx and Tx rings should be quad-word-aligned. */
+	struct boom_rx_desc rx_ring[RX_RING_SIZE];
+	struct boom_tx_desc tx_ring[TX_RING_SIZE];
+	/* The addresses of transmit- and receive-in-place skbuffs. */
+	struct sk_buff* rx_skbuff[RX_RING_SIZE];
+	struct sk_buff* tx_skbuff[TX_RING_SIZE];
+	struct net_device *next_module;
+	void *priv_addr;
+	unsigned int cur_rx, cur_tx;		/* The next free ring entry */
+	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
+	struct net_device_stats stats;
+	struct sk_buff *tx_skb;		/* Packet being eaten by bus master ctrl.  */
+
+	/* PCI configuration space information. */
+	u8 pci_bus, pci_devfn;		/* PCI bus location, for power management. */
+	char *cb_fn_base;			/* CardBus function status addr space. */
+	int chip_id;
+
+	/* The remainder are related to chip state, mostly media selection. */
+	unsigned long in_interrupt;
+	struct timer_list timer;	/* Media selection timer. */
+	int options;				/* User-settable misc. driver options. */
+	unsigned int media_override:4, 			/* Passed-in media type. */
+		default_media:4,				/* Read from the EEPROM/Wn3_Config. */
+		full_duplex:1, force_fd:1, autoselect:1,
+		bus_master:1,				/* Vortex can only do a fragment bus-m. */
+		full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang  */
+		hw_csums:1,				/* Has hardware checksums. */
+		tx_full:1,
+		open:1;
+	u16 status_enable;
+	u16 intr_enable;
+	u16 available_media;				/* From Wn3_Options. */
+	u16 capabilities, info1, info2;		/* Various, from EEPROM. */
+	u16 advertising;					/* NWay media advertisement */
+	unsigned char phys[2];				/* MII device addresses. */
+};
+
+/* The action to take with a media selection timer tick.
+   Note that we deviate from the 3Com order by checking 10base2 before AUI.
+ */
+enum xcvr_types {
+	XCVR_10baseT=0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx,
+	XCVR_100baseFx, XCVR_MII=6, XCVR_NWAY=8, XCVR_ExtMII=9, XCVR_Default=10,
+};
+
+static struct media_table {
+	char *name;
+	unsigned int media_bits:16,		/* Bits to set in Wn4_Media register. */
+		mask:8,				/* The transceiver-present bit in Wn3_Config.*/
+		next:8;				/* The media type to try next. */
+	int wait;			/* Time before we check media status. */
+} media_tbl[] = {
+  {	"10baseT",   Media_10TP,0x08, XCVR_10base2, (14*HZ)/10},
+  { "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1*HZ)/10},
+  { "undefined", 0,			0x80, XCVR_10baseT, 10000},
+  { "10base2",   0,			0x10, XCVR_AUI,		(1*HZ)/10},
+  { "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx, (14*HZ)/10},
+  { "100baseFX", Media_Lnk, 0x04, XCVR_MII,		(14*HZ)/10},
+  { "MII",		 0,			0x41, XCVR_10baseT, 3*HZ },
+  { "undefined", 0,			0x01, XCVR_10baseT, 10000},
+  { "Autonegotiate", 0,		0x41, XCVR_10baseT, 3*HZ},
+  { "MII-External",	 0,		0x41, XCVR_10baseT, 3*HZ },
+  { "Default",	 0,			0xFF, XCVR_10baseT, 10000},
+};
+
+#ifndef CARDBUS
+static int vortex_scan(struct net_device *dev, struct pci_id_info pci_tbl[]);
+#endif
+static void vortex_up(struct net_device *dev);
+static void vortex_down(struct net_device *dev);
+static int vortex_open(struct net_device *dev);
+static void mdio_sync(long ioaddr, int bits);
+static int mdio_read(long ioaddr, int phy_id, int location);
+static void mdio_write(long ioaddr, int phy_id, int location, int value);
+static void vortex_timer(unsigned long arg);
+static int vortex_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int vortex_rx(struct net_device *dev);
+static int boomerang_rx(struct net_device *dev);
+static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static int vortex_close(struct net_device *dev);
+static void update_stats(long ioaddr, struct net_device *dev);
+static struct net_device_stats *vortex_get_stats(struct net_device *dev);
+static void set_rx_mode(struct net_device *dev);
+static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static void acpi_wake(int pci_bus, int pci_devfn);
+static void acpi_set_WOL(struct net_device *dev);
+
+/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
+/* Option count limit only -- unlimited interfaces are supported. */
+#define MAX_UNITS 8
+static int options[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1,};
+static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+/* A list of all installed Vortex devices, for removing the driver module. */
+static struct net_device *root_vortex_dev = NULL;
+
+#ifdef MODULE
+#ifndef CARDBUS
+/* Variables to work-around the Compaq PCI BIOS32 problem. */
+static int compaq_ioaddr = 0, compaq_irq = 0, compaq_device_id = 0x5900;
+#endif
+
+#ifdef CARDBUS
+
+#include <pcmcia/driver_ops.h>
+
+static dev_node_t *vortex_attach(dev_locator_t *loc)
+{
+	u16 dev_id, vendor_id;
+	u32 io;
+	u8 bus, devfn, irq;
+	struct net_device *dev;
+	int chip_idx;
+
+	if (loc->bus != LOC_PCI) return NULL;
+	bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
+	pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
+	pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
+	pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor_id);
+	pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
+	printk(KERN_INFO "vortex_attach(bus %d, function %d, device %4.4x)\n",
+		   bus, devfn, dev_id);
+	io &= ~3;
+	if (io == 0 || irq == 0) {
+		printk(KERN_ERR "The 3Com CardBus Ethernet interface was not "
+			   "assigned an %s.\n" KERN_ERR "  It will not be activated.\n",
+			   io == 0 ? "I/O address" : "IRQ");
+		return NULL;
+	}
+	for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
+		if (vendor_id == pci_tbl[chip_idx].vendor_id
+			&& (dev_id & pci_tbl[chip_idx].device_id_mask) ==
+			pci_tbl[chip_idx].device_id)
+			break;
+	if (pci_tbl[chip_idx].vendor_id == 0) { 		/* Compiled out! */
+		printk(KERN_INFO "Unable to match chip type %4.4x %4.4x in "
+			   "vortex_attach().\n", vendor_id, dev_id);
+		return NULL;
+	}
+	dev = vortex_probe1(bus, devfn, NULL, io, irq, chip_idx, MAX_UNITS+1);
+	if (dev) {
+		dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
+		strcpy(node->dev_name, dev->name);
+		node->major = node->minor = 0;
+		node->next = NULL;
+		MOD_INC_USE_COUNT;
+		return node;
+	}
+	return NULL;
+}
+
+static void vortex_detach(dev_node_t *node)
+{
+	struct net_device **devp, **next;
+	printk(KERN_INFO "vortex_detach(%s)\n", node->dev_name);
+	for (devp = &root_vortex_dev; *devp; devp = next) {
+		next = &((struct vortex_private *)(*devp)->priv)->next_module;
+		if (strcmp((*devp)->name, node->dev_name) == 0) break;
+	}
+	if (*devp) {
+		struct net_device *dev = *devp;
+		struct vortex_private *vp = dev->priv;
+		if (dev->flags & IFF_UP)
+			vortex_close(dev);
+		dev->flags &= ~(IFF_UP|IFF_RUNNING);
+		unregister_netdev(dev);
+		if (vp->cb_fn_base) iounmap(vp->cb_fn_base);
+		kfree(dev);
+		*devp = *next;
+		kfree(vp->priv_addr);
+		kfree(node);
+		MOD_DEC_USE_COUNT;
+	}
+}
+
+static void vortex_suspend(dev_node_t *node)
+{
+	struct net_device *dev, *next;
+	printk(KERN_INFO "vortex_suspend(%s)\n", node->dev_name);
+	for (dev = root_vortex_dev; dev; dev = next) {
+		next = ((struct vortex_private *)dev->priv)->next_module;
+		if (strcmp(dev->name, node->dev_name) == 0) break;
+	}
+	if (dev && dev->priv) {
+		struct vortex_private *vp = (struct vortex_private *)dev->priv;
+		if (vp->open) vortex_down(dev);
+	}
+}
+
+static void vortex_resume(dev_node_t *node)
+{
+	struct net_device *dev, *next;
+	printk(KERN_INFO "vortex_resume(%s)\n", node->dev_name);
+	for (dev = root_vortex_dev; dev; dev = next) {
+		next = ((struct vortex_private *)dev->priv)->next_module;
+		if (strcmp(dev->name, node->dev_name) == 0) break;
+	}
+	if (dev && dev->priv) {
+		struct vortex_private *vp = (struct vortex_private *)dev->priv;
+		if (vp->open) vortex_up(dev);
+	}
+}
+
+struct driver_operations vortex_ops = {
+	"3c575_cb", vortex_attach, vortex_suspend, vortex_resume, vortex_detach
+};
+
+#endif  /* Cardbus support */
+
+int init_module(void)
+{
+	if (vortex_debug)
+		printk(KERN_INFO "%s", version);
+#ifdef CARDBUS
+	register_driver(&vortex_ops);
+	return 0;
+#else
+	return vortex_scan(0, pci_tbl);
+#endif
+}
+
+#else
+int tc59x_probe(struct net_device *dev)
+{
+	static int did_version = -1;
+	if (++did_version <= 0)
+		printk(KERN_INFO "%s", version);
+	return vortex_scan(dev, pci_tbl);
+}
+#endif  /* not MODULE */
+
+#ifndef CARDBUS
+static int vortex_scan(struct net_device *dev, struct pci_id_info pci_tbl[])
+{
+	int cards_found = 0;
+
+	/* Allow an EISA-only driver. */
+#if defined(CONFIG_PCI) || (defined(MODULE) && !defined(NO_PCI))
+	/* Ideally we would detect all cards in slot order.  That would
+	   be best done a central PCI probe dispatch, which wouldn't work
+	   well with the current structure.  So instead we detect 3Com cards
+	   in slot order. */
+	if (pcibios_present()) {
+		static int pci_index = 0;
+		unsigned char pci_bus, pci_device_fn;
+
+		for (;pci_index < 0xff; pci_index++) {
+			u16 vendor, device, pci_command, new_command;
+			int chip_idx, irq;
+			long ioaddr;
+
+			if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index,
+									&pci_bus, &pci_device_fn)
+				!= PCIBIOS_SUCCESSFUL)
+				break;
+			pcibios_read_config_word(pci_bus, pci_device_fn,
+									 PCI_VENDOR_ID, &vendor);
+			pcibios_read_config_word(pci_bus, pci_device_fn,
+									 PCI_DEVICE_ID, &device);
+			for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
+				if (vendor == pci_tbl[chip_idx].vendor_id
+					&& (device & pci_tbl[chip_idx].device_id_mask) ==
+					pci_tbl[chip_idx].device_id)
+					break;
+			if (pci_tbl[chip_idx].vendor_id == 0) 		/* Compiled out! */
+				continue;
+
+			/* The Cyclone requires config space re-write if powered down. */
+			acpi_wake(pci_bus, pci_device_fn);
+
+			{
+				struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
+				ioaddr = pdev->resource[0].start;
+				irq = pdev->irq;
+#elif LINUX_VERSION_CODE >= 0x20155
+				struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
+				ioaddr = pdev->base_address[0] & ~3;
+				irq = pdev->irq;
+			}
+
+			if (ioaddr == 0) {
+				printk(KERN_WARNING "  A 3Com network adapter has been found, "
+					   "however it has not been assigned an I/O address.\n"
+					   "  You may need to power-cycle the machine for this "
+					   "device to work!\n");
+				continue;
+			}
+
+			/* Activate the card. */
+			pcibios_read_config_word(pci_bus, pci_device_fn,
+									 PCI_COMMAND, &pci_command);
+			new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
+			if (pci_command != new_command) {
+				printk(KERN_INFO "  The PCI BIOS has not enabled the device "
+					   "at %d/%d. Updating PCI command %4.4x->%4.4x.\n",
+					   pci_bus, pci_device_fn, pci_command, new_command);
+				pcibios_write_config_word(pci_bus, pci_device_fn,
+										  PCI_COMMAND, new_command);
+			}
+
+			dev = vortex_probe1(pci_bus, pci_device_fn, dev, ioaddr, irq,
+								chip_idx, cards_found);
+
+			if (dev) {
+				/* Get and check the latency values.  On the 3c590 series
+				   the latency timer must be set to the maximum value to avoid
+				   data corruption that occurs when the timer expires during
+				   a transfer -- a bug in the Vortex chip only. */
+				u8 pci_latency;
+				u8 new_latency = (device & 0xff00) == 0x5900 ? 248 : 32;
+				
+				pcibios_read_config_byte(pci_bus, pci_device_fn,
+										 PCI_LATENCY_TIMER, &pci_latency);
+				if (pci_latency < new_latency) {
+					printk(KERN_INFO "%s: Overriding PCI latency"
+						   " timer (CFLT) setting of %d, new value is %d.\n",
+						   dev->name, pci_latency, new_latency);
+					pcibios_write_config_byte(pci_bus, pci_device_fn,
+											  PCI_LATENCY_TIMER, new_latency);
+				}
+				dev = 0;
+				cards_found++;
+			}
+		}
+	}
+#endif /* NO_PCI */
+
+	/* Now check all slots of the EISA bus. */
+	if (EISA_bus) {
+		static long ioaddr = 0x1000;
+		for ( ; ioaddr < 0x9000; ioaddr += 0x1000) {
+			int device_id;
+			if (check_region(ioaddr, VORTEX_TOTAL_SIZE))
+				continue;
+			/* Check the standard EISA ID register for an encoded '3Com'. */
+			if (inw(ioaddr + 0xC80) != 0x6d50)
+				continue;
+			/* Check for a product that we support, 3c59{2,7} any rev. */
+			device_id = (inb(ioaddr + 0xC82)<<8) + inb(ioaddr + 0xC83);
+			if ((device_id & 0xFF00) != 0x5900)
+				continue;
+			vortex_probe1(0, 0, dev, ioaddr, inw(ioaddr + 0xC88) >> 12,
+						  4, cards_found);
+			dev = 0;
+			cards_found++;
+		}
+	}
+
+#ifdef MODULE
+	/* Special code to work-around the Compaq PCI BIOS32 problem. */
+	if (compaq_ioaddr) {
+		vortex_probe1(0, 0, dev, compaq_ioaddr, compaq_irq,
+					  compaq_device_id, cards_found++);
+		dev = 0;
+	}
+#endif
+
+	return cards_found ? 0 : -ENODEV;
+}
+#endif  /* ! Cardbus */
+
+static struct net_device *vortex_probe1(int pci_bus, int pci_devfn,
+									struct net_device *dev, long ioaddr,
+									int irq, int chip_idx, int card_idx)
+{
+	struct vortex_private *vp;
+	int option;
+	unsigned int eeprom[0x40], checksum = 0;		/* EEPROM contents */
+	int i;
+
+	dev = init_etherdev(dev, 0);
+
+	printk(KERN_INFO "%s: 3Com %s at 0x%lx, ",
+		   dev->name, pci_tbl[chip_idx].name, ioaddr);
+
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+	dev->mtu = mtu;
+
+	/* Make certain the descriptor lists are aligned. */
+	{
+		void *mem = kmalloc(sizeof(*vp) + 15, GFP_KERNEL);
+		vp =  (void *)(((long)mem + 15) & ~15);
+		vp->priv_addr = mem;
+	}
+	memset(vp, 0, sizeof(*vp));
+	dev->priv = vp;
+
+	vp->next_module = root_vortex_dev;
+	root_vortex_dev = dev;
+
+	vp->chip_id = chip_idx;
+	vp->pci_bus = pci_bus;
+	vp->pci_devfn = pci_devfn;
+
+	/* The lower four bits are the media type. */
+	if (dev->mem_start)
+		option = dev->mem_start;
+	else if (card_idx < MAX_UNITS)
+		option = options[card_idx];
+	else
+		option = -1;
+
+	if (option >= 0) {
+		vp->media_override = ((option & 7) == 2)  ?  0  :  option & 15;
+		vp->full_duplex = (option & 0x200) ? 1 : 0;
+		vp->bus_master = (option & 16) ? 1 : 0;
+	} else {
+		vp->media_override = 7;
+		vp->full_duplex = 0;
+		vp->bus_master = 0;
+	}
+	if (card_idx < MAX_UNITS  &&  full_duplex[card_idx] > 0)
+		vp->full_duplex = 1;
+
+	vp->force_fd = vp->full_duplex;
+	vp->options = option;
+
+	/* Read the station address from the EEPROM. */
+	EL3WINDOW(0);
+	for (i = 0; i < 0x40; i++) {
+		int timer;
+#ifdef CARDBUS
+		outw(0x230 + i, ioaddr + Wn0EepromCmd);
+#else
+		outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
+#endif
+		/* Pause for at least 162 us. for the read to take place. */
+		for (timer = 10; timer >= 0; timer--) {
+			udelay(162);
+			if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0)
+				break;
+		}
+		eeprom[i] = inw(ioaddr + Wn0EepromData);
+	}
+	for (i = 0; i < 0x18; i++)
+		checksum ^= eeprom[i];
+	checksum = (checksum ^ (checksum >> 8)) & 0xff;
+	if (checksum != 0x00) {		/* Grrr, needless incompatible change 3Com. */
+		while (i < 0x21)
+			checksum ^= eeprom[i++];
+		checksum = (checksum ^ (checksum >> 8)) & 0xff;
+	}
+	if (checksum != 0x00)
+		printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);
+
+	for (i = 0; i < 3; i++)
+		((u16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]);
+	for (i = 0; i < 6; i++)
+		printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]);
+	EL3WINDOW(2);
+	for (i = 0; i < 6; i++)
+		outb(dev->dev_addr[i], ioaddr + i);
+
+#ifdef __sparc__
+	printk(", IRQ %s\n", __irq_itoa(dev->irq));
+#else
+	printk(", IRQ %d\n", dev->irq);
+	/* Tell them about an invalid IRQ. */
+	if (vortex_debug && (dev->irq <= 0 || dev->irq >= NR_IRQS))
+		printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n",
+			   dev->irq);
+#endif
+
+	if (pci_tbl[vp->chip_id].drv_flags & HAS_CB_FNS) {
+		u32 fn_st_addr;			/* Cardbus function status space */
+		pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_2,
+								  &fn_st_addr);
+		if (fn_st_addr)
+			vp->cb_fn_base = ioremap(fn_st_addr & ~3, 128);
+		printk(KERN_INFO "%s: CardBus functions mapped %8.8x->%p\n",
+			   dev->name, fn_st_addr, vp->cb_fn_base);
+	}
+
+	/* Extract our information from the EEPROM data. */
+	vp->info1 = eeprom[13];
+	vp->info2 = eeprom[15];
+	vp->capabilities = eeprom[16];
+
+	if (vp->info1 & 0x8000)
+		vp->full_duplex = 1;
+
+	{
+		char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
+		union wn3_config config;
+		EL3WINDOW(3);
+		vp->available_media = inw(ioaddr + Wn3_Options);
+		if ((vp->available_media & 0xff) == 0)		/* Broken 3c916 */
+			vp->available_media = 0x40;
+		config.i = inl(ioaddr + Wn3_Config);
+		if (vortex_debug > 1)
+			printk(KERN_DEBUG "  Internal config register is %4.4x, "
+				   "transceivers %#x.\n", config.i, inw(ioaddr + Wn3_Options));
+		printk(KERN_INFO "  %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
+			   8 << config.u.ram_size,
+			   config.u.ram_width ? "word" : "byte",
+			   ram_split[config.u.ram_split],
+			   config.u.autoselect ? "autoselect/" : "",
+			   config.u.xcvr > XCVR_ExtMII ? "<invalid transceiver>" :
+			   media_tbl[config.u.xcvr].name);
+		vp->default_media = config.u.xcvr;
+		vp->autoselect = config.u.autoselect;
+	}
+
+	if (vp->media_override != 7) {
+		printk(KERN_INFO "  Media override to transceiver type %d (%s).\n",
+			   vp->media_override, media_tbl[vp->media_override].name);
+		dev->if_port = vp->media_override;
+	} else
+		dev->if_port = vp->default_media;
+
+	if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
+		int phy, phy_idx = 0;
+		EL3WINDOW(4);
+		mii_preamble_required++;
+		mii_preamble_required++;
+		mdio_read(ioaddr, 24, 1);
+		for (phy = 1; phy <= 32 && phy_idx < sizeof(vp->phys); phy++) {
+			int mii_status, phyx = phy & 0x1f;
+			mii_status = mdio_read(ioaddr, phyx, 1);
+			if (mii_status  &&  mii_status != 0xffff) {
+				vp->phys[phy_idx++] = phyx;
+				printk(KERN_INFO "  MII transceiver found at address %d,"
+					   " status %4x.\n", phyx, mii_status);
+				if ((mii_status & 0x0040) == 0)
+					mii_preamble_required++;
+			}
+		}
+		mii_preamble_required--;
+		if (phy_idx == 0) {
+			printk(KERN_WARNING"  ***WARNING*** No MII transceivers found!\n");
+			vp->phys[0] = 24;
+		} else {
+			vp->advertising = mdio_read(ioaddr, vp->phys[0], 4);
+			if (vp->full_duplex) {
+				/* Only advertise the FD media types. */
+				vp->advertising &= ~0x02A0;
+				mdio_write(ioaddr, vp->phys[0], 4, vp->advertising);
+			}
+		}
+	}
+
+	if (vp->capabilities & CapPwrMgmt)
+		acpi_set_WOL(dev);
+
+	if (vp->capabilities & CapBusMaster) {
+		vp->full_bus_master_tx = 1;
+		printk(KERN_INFO"  Enabling bus-master transmits and %s receives.\n",
+			   (vp->info2 & 1) ? "early" : "whole-frame" );
+		vp->full_bus_master_rx = (vp->info2 & 1) ? 1 : 2;
+	}
+
+	/* We do a request_region() to register /proc/ioports info. */
+	request_region(ioaddr, pci_tbl[chip_idx].io_size, dev->name);
+
+	/* The 3c59x-specific entries in the device structure. */
+	dev->open = &vortex_open;
+	dev->hard_start_xmit = &vortex_start_xmit;
+	dev->stop = &vortex_close;
+	dev->get_stats = &vortex_get_stats;
+	dev->do_ioctl = &vortex_ioctl;
+	dev->set_multicast_list = &set_rx_mode;
+
+	return dev;
+}
+
+static void wait_for_completion(struct net_device *dev, int cmd)
+{
+	int i = 2000;
+	outw(cmd, dev->base_addr + EL3_CMD);
+	while (--i > 0)
+		if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress))
+			break;
+	if (i == 0)
+		printk(KERN_NOTICE "%s: command 0x%04x did not complete!\n",
+			   dev->name, cmd);
+}
+
+static void
+vortex_up(struct net_device *dev)
+{
+	long ioaddr = dev->base_addr;
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	union wn3_config config;
+	int i;
+	
+	/* Should be if(HAS_ACPI) */
+	acpi_wake(vp->pci_bus, vp->pci_devfn);
+
+	/* Before initializing select the active media port. */
+	EL3WINDOW(3);
+	config.i = inl(ioaddr + Wn3_Config);
+
+	if (vp->media_override != 7) {
+		if (vortex_debug > 1)
+			printk(KERN_INFO "%s: Media override to transceiver %d (%s).\n",
+				   dev->name, vp->media_override,
+				   media_tbl[vp->media_override].name);
+		dev->if_port = vp->media_override;
+	} else if (vp->autoselect) {
+		if (pci_tbl[vp->chip_id].drv_flags & HAS_NWAY)
+			dev->if_port = XCVR_NWAY;
+		else {
+			/* Find first available media type, starting with 100baseTx. */
+			dev->if_port = XCVR_100baseTx;
+			while (! (vp->available_media & media_tbl[dev->if_port].mask))
+				dev->if_port = media_tbl[dev->if_port].next;
+		}
+	} else
+		dev->if_port = vp->default_media;
+
+	init_timer(&vp->timer);
+	vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
+	vp->timer.data = (unsigned long)dev;
+	vp->timer.function = &vortex_timer;		/* timer handler */
+	add_timer(&vp->timer);
+
+	if (vortex_debug > 1)
+		printk(KERN_DEBUG "%s: Initial media type %s.\n",
+			   dev->name, media_tbl[dev->if_port].name);
+
+	vp->full_duplex = vp->force_fd;
+	config.u.xcvr = dev->if_port;
+	if ( ! (pci_tbl[vp->chip_id].drv_flags & HAS_NWAY))
+		outl(config.i, ioaddr + Wn3_Config);
+
+	if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
+		int mii_reg1, mii_reg5;
+		EL3WINDOW(4);
+		/* Read BMSR (reg1) only to clear old status. */
+		mii_reg1 = mdio_read(ioaddr, vp->phys[0], 1);
+		mii_reg5 = mdio_read(ioaddr, vp->phys[0], 5);
+		if (mii_reg5 == 0xffff  ||  mii_reg5 == 0x0000)
+			;					/* No MII device or no link partner report */
+		else if ((mii_reg5 & 0x0100) != 0	/* 100baseTx-FD */
+				 || (mii_reg5 & 0x00C0) == 0x0040) /* 10T-FD, but not 100-HD */
+			vp->full_duplex = 1;
+		if (vortex_debug > 1)
+			printk(KERN_INFO "%s: MII #%d status %4.4x, link partner capability %4.4x,"
+				   " setting %s-duplex.\n", dev->name, vp->phys[0],
+				   mii_reg1, mii_reg5, vp->full_duplex ? "full" : "half");
+		EL3WINDOW(3);
+	}
+
+	/* Set the full-duplex bit. */
+	outb(((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
+		 (dev->mtu > 1500 ? 0x40 : 0), ioaddr + Wn3_MAC_Ctrl);
+
+	if (vortex_debug > 1) {
+		printk(KERN_DEBUG "%s: vortex_open() InternalConfig %8.8x.\n",
+			dev->name, config.i);
+	}
+
+	wait_for_completion(dev, TxReset);
+	wait_for_completion(dev, RxReset);
+
+	outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
+
+	if (vortex_debug > 1) {
+		EL3WINDOW(4);
+		printk(KERN_DEBUG "%s: vortex_open() irq %d media status %4.4x.\n",
+			   dev->name, dev->irq, inw(ioaddr + Wn4_Media));
+	}
+
+	/* Set the station address and mask in window 2 each time opened. */
+	EL3WINDOW(2);
+	for (i = 0; i < 6; i++)
+		outb(dev->dev_addr[i], ioaddr + i);
+	for (; i < 12; i+=2)
+		outw(0, ioaddr + i);
+	if (vp->cb_fn_base) {
+		u_short n = inw(ioaddr + Wn2_ResetOptions);
+		/* Inverted LED polarity */
+		if (pci_tbl[vp->chip_id].device_id != 0x5257)
+			n |= 0x0010;
+		/* Inverted polarity of MII power bit */
+		if ((pci_tbl[vp->chip_id].device_id == 0x6560) ||
+			(pci_tbl[vp->chip_id].device_id == 0x6562) ||
+			(pci_tbl[vp->chip_id].device_id == 0x5257))
+			n |= 0x4000;
+		outw(n, ioaddr + Wn2_ResetOptions);
+	}
+
+	if (dev->if_port == XCVR_10base2)
+		/* Start the thinnet transceiver. We should really wait 50ms...*/
+		outw(StartCoax, ioaddr + EL3_CMD);
+	if (dev->if_port != XCVR_NWAY) {
+		EL3WINDOW(4);
+		outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) |
+			 media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
+	}
+
+	/* Switch to the stats window, and clear all stats by reading. */
+	outw(StatsDisable, ioaddr + EL3_CMD);
+	EL3WINDOW(6);
+	for (i = 0; i < 10; i++)
+		inb(ioaddr + i);
+	inw(ioaddr + 10);
+	inw(ioaddr + 12);
+	/* New: On the Vortex we must also clear the BadSSD counter. */
+	EL3WINDOW(4);
+	inb(ioaddr + 12);
+	/* ..and on the Boomerang we enable the extra statistics bits. */
+	outw(0x0040, ioaddr + Wn4_NetDiag);
+
+	/* Switch to register set 7 for normal use. */
+	EL3WINDOW(7);
+
+	if (vp->full_bus_master_rx) { /* Boomerang bus master. */
+		vp->cur_rx = vp->dirty_rx = 0;
+		/* Initialize the RxEarly register as recommended. */
+		outw(SetRxThreshold + (1536>>2), ioaddr + EL3_CMD);
+		outl(0x0020, ioaddr + PktStatus);
+		outl(virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
+	}
+	if (vp->full_bus_master_tx) { 		/* Boomerang bus master Tx. */
+		dev->hard_start_xmit = &boomerang_start_xmit;
+		vp->cur_tx = vp->dirty_tx = 0;
+		outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */
+		/* Clear the Tx ring. */
+		for (i = 0; i < TX_RING_SIZE; i++)
+			vp->tx_skbuff[i] = 0;
+		outl(0, ioaddr + DownListPtr);
+	}
+	/* Set receiver mode: presumably accept b-case and phys addr only. */
+	set_rx_mode(dev);
+	outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
+
+	vp->in_interrupt = 0;
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
+	outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
+	/* Allow status bits to be seen. */
+	vp->status_enable = SetStatusEnb | HostError|IntReq|StatsFull|TxComplete|
+		(vp->full_bus_master_tx ? DownComplete : TxAvailable) |
+		(vp->full_bus_master_rx ? UpComplete : RxComplete) |
+		(vp->bus_master ? DMADone : 0);
+	vp->intr_enable = SetIntrEnb | IntLatch | TxAvailable | RxComplete |
+		StatsFull | HostError | TxComplete | IntReq
+		| (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete;
+	outw(vp->status_enable, ioaddr + EL3_CMD);
+	/* Ack all pending events, and set active indicator mask. */
+	outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
+		 ioaddr + EL3_CMD);
+	outw(vp->intr_enable, ioaddr + EL3_CMD);
+	if (vp->cb_fn_base)			/* The PCMCIA people are idiots.  */
+		writel(0x8000, vp->cb_fn_base + 4);
+}
+
+static int
+vortex_open(struct net_device *dev)
+{
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	int i;
+
+	/* Use the now-standard shared IRQ implementation. */
+	if (request_irq(dev->irq, &vortex_interrupt, SA_SHIRQ, dev->name, dev)) {
+		return -EAGAIN;
+	}
+
+	if (vp->full_bus_master_rx) { /* Boomerang bus master. */
+		if (vortex_debug > 2)
+			printk(KERN_DEBUG "%s:  Filling in the Rx ring.\n", dev->name);
+		for (i = 0; i < RX_RING_SIZE; i++) {
+			struct sk_buff *skb;
+			vp->rx_ring[i].next = cpu_to_le32(virt_to_bus(&vp->rx_ring[i+1]));
+			vp->rx_ring[i].status = 0;	/* Clear complete bit. */
+			vp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LAST_FRAG);
+			skb = dev_alloc_skb(PKT_BUF_SZ);
+			vp->rx_skbuff[i] = skb;
+			if (skb == NULL)
+				break;			/* Bad news!  */
+			skb->dev = dev;			/* Mark as being used by this device. */
+			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
+			vp->rx_ring[i].addr = cpu_to_le32(virt_to_bus(skb->tail));
+		}
+		/* Wrap the ring. */
+		vp->rx_ring[i-1].next = cpu_to_le32(virt_to_bus(&vp->rx_ring[0]));
+	}
+	if (vp->full_bus_master_tx)
+		dev->hard_start_xmit = &boomerang_start_xmit;
+
+	vortex_up(dev);
+	vp->open = 1;
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+static void vortex_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int next_tick = 60*HZ;
+	int ok = 0;
+	int media_status, mii_status, old_window;
+
+	if (vortex_debug > 1)
+		printk(KERN_DEBUG "%s: Media selection timer tick happened, %s.\n",
+			   dev->name, media_tbl[dev->if_port].name);
+
+	disable_irq(dev->irq);
+	old_window = inw(ioaddr + EL3_CMD) >> 13;
+	EL3WINDOW(4);
+	media_status = inw(ioaddr + Wn4_Media);
+	switch (dev->if_port) {
+	case XCVR_10baseT:  case XCVR_100baseTx:  case XCVR_100baseFx:
+		if (media_status & Media_LnkBeat) {
+			ok = 1;
+			if (vortex_debug > 1)
+				printk(KERN_DEBUG "%s: Media %s has link beat, %x.\n",
+					   dev->name, media_tbl[dev->if_port].name, media_status);
+		} else if (vortex_debug > 1)
+			printk(KERN_DEBUG "%s: Media %s is has no link beat, %x.\n",
+				   dev->name, media_tbl[dev->if_port].name, media_status);
+		break;
+	case XCVR_MII: case XCVR_NWAY:
+		  mii_status = mdio_read(ioaddr, vp->phys[0], 1);
+		  ok = 1;
+		  if (debug > 1)
+			  printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n",
+					 dev->name, mii_status);
+		  if (mii_status & 0x0004) {
+			  int mii_reg5 = mdio_read(ioaddr, vp->phys[0], 5);
+			  if (! vp->force_fd  &&  mii_reg5 != 0xffff) {
+				  int duplex = (mii_reg5&0x0100) ||
+					  (mii_reg5 & 0x01C0) == 0x0040;
+				  if (vp->full_duplex != duplex) {
+					  vp->full_duplex = duplex;
+					  printk(KERN_INFO "%s: Setting %s-duplex based on MII "
+							 "#%d link partner capability of %4.4x.\n",
+							 dev->name, vp->full_duplex ? "full" : "half",
+							 vp->phys[0], mii_reg5);
+					  /* Set the full-duplex bit. */
+					  EL3WINDOW(3);
+					  outb((vp->full_duplex ? 0x20 : 0) |
+						   (dev->mtu > 1500 ? 0x40 : 0),
+						   ioaddr + Wn3_MAC_Ctrl);
+				  }
+				  next_tick = 60*HZ;
+			  }
+		  }
+		  break;
+	  default:					/* Other media types handled by Tx timeouts. */
+		if (vortex_debug > 1)
+		  printk(KERN_DEBUG "%s: Media %s is has no indication, %x.\n",
+				 dev->name, media_tbl[dev->if_port].name, media_status);
+		ok = 1;
+	}
+	if ( ! ok) {
+		union wn3_config config;
+
+		do {
+			dev->if_port = media_tbl[dev->if_port].next;
+		} while ( ! (vp->available_media & media_tbl[dev->if_port].mask));
+		if (dev->if_port == XCVR_Default) { /* Go back to default. */
+		  dev->if_port = vp->default_media;
+		  if (vortex_debug > 1)
+			printk(KERN_DEBUG "%s: Media selection failing, using default "
+				   "%s port.\n",
+				   dev->name, media_tbl[dev->if_port].name);
+		} else {
+			if (vortex_debug > 1)
+				printk(KERN_DEBUG "%s: Media selection failed, now trying "
+					   "%s port.\n",
+					   dev->name, media_tbl[dev->if_port].name);
+			next_tick = media_tbl[dev->if_port].wait;
+		}
+		outw((media_status & ~(Media_10TP|Media_SQE)) |
+			 media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
+
+		EL3WINDOW(3);
+		config.i = inl(ioaddr + Wn3_Config);
+		config.u.xcvr = dev->if_port;
+		outl(config.i, ioaddr + Wn3_Config);
+
+		outw(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax,
+			 ioaddr + EL3_CMD);
+	}
+	EL3WINDOW(old_window);
+	enable_irq(dev->irq);
+
+	if (vortex_debug > 2)
+	  printk(KERN_DEBUG "%s: Media selection timer finished, %s.\n",
+			 dev->name, media_tbl[dev->if_port].name);
+
+	vp->timer.expires = RUN_AT(next_tick);
+	add_timer(&vp->timer);
+	return;
+}
+
+static void vortex_tx_timeout(struct net_device *dev)
+{
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+
+	printk(KERN_ERR "%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
+		   dev->name, inb(ioaddr + TxStatus),
+		   inw(ioaddr + EL3_STATUS));
+	/* Slight code bloat to be user friendly. */
+	if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)
+		printk(KERN_ERR "%s: Transmitter encountered 16 collisions --"
+			   " network cable problem?\n", dev->name);
+	if (inw(ioaddr + EL3_STATUS) & IntLatch) {
+		printk(KERN_ERR "%s: Interrupt posted but not delivered --"
+			   " IRQ blocked by another device?\n", dev->name);
+		/* Bad idea here.. but we might as well handle a few events. */
+		vortex_interrupt(dev->irq, dev, 0);
+	}
+
+#if ! defined(final_version) && LINUX_VERSION_CODE >= 0x10300
+	if (vp->full_bus_master_tx) {
+		int i;
+		printk(KERN_DEBUG "  Flags; bus-master %d, full %d; dirty %d "
+			   "current %d.\n",
+			   vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx, vp->cur_tx);
+		printk(KERN_DEBUG "  Transmit list %8.8x vs. %p.\n",
+			   inl(ioaddr + DownListPtr),
+			   &vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]);
+		for (i = 0; i < TX_RING_SIZE; i++) {
+			printk(KERN_DEBUG "  %d: @%p  length %8.8x status %8.8x\n", i,
+				   &vp->tx_ring[i],
+				   le32_to_cpu(vp->tx_ring[i].length),
+				   le32_to_cpu(vp->tx_ring[i].status));
+		}
+	}
+#endif
+	wait_for_completion(dev, TxReset);
+
+	vp->stats.tx_errors++;
+	if (vp->full_bus_master_tx) {
+		if (vortex_debug > 0)
+			printk(KERN_DEBUG "%s: Resetting the Tx ring pointer.\n",
+				   dev->name);
+		if (vp->cur_tx - vp->dirty_tx > 0  &&  inl(ioaddr + DownListPtr) == 0)
+			outl(virt_to_bus(&vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]),
+				 ioaddr + DownListPtr);
+		if (vp->tx_full && (vp->cur_tx - vp->dirty_tx <= TX_RING_SIZE - 1)) {
+			vp->tx_full = 0;
+			clear_bit(0, (void*)&dev->tbusy);
+		}
+		outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
+		outw(DownUnstall, ioaddr + EL3_CMD);
+	} else
+		vp->stats.tx_dropped++;
+	
+	/* Issue Tx Enable */
+	outw(TxEnable, ioaddr + EL3_CMD);
+	dev->trans_start = jiffies;
+	
+	/* Switch to register set 7 for normal use. */
+	EL3WINDOW(7);
+}
+
+/*
+ * Handle uncommon interrupt sources.  This is a separate routine to minimize
+ * the cache impact.
+ */
+static void
+vortex_error(struct net_device *dev, int status)
+{
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int do_tx_reset = 0;
+
+	if (status & TxComplete) {			/* Really "TxError" for us. */
+		unsigned char tx_status = inb(ioaddr + TxStatus);
+		/* Presumably a tx-timeout. We must merely re-enable. */
+		if (vortex_debug > 2
+			|| (tx_status != 0x88 && vortex_debug > 0))
+			printk(KERN_DEBUG"%s: Transmit error, Tx status register %2.2x.\n",
+				   dev->name, tx_status);
+		if (tx_status & 0x14)  vp->stats.tx_fifo_errors++;
+		if (tx_status & 0x38)  vp->stats.tx_aborted_errors++;
+		outb(0, ioaddr + TxStatus);
+		if (tx_status & 0x30)
+			do_tx_reset = 1;
+		else					/* Merely re-enable the transmitter. */
+			outw(TxEnable, ioaddr + EL3_CMD);
+	}
+	if (status & RxEarly) {				/* Rx early is unused. */
+		vortex_rx(dev);
+		outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
+	}
+	if (status & StatsFull) {			/* Empty statistics. */
+		static int DoneDidThat = 0;
+		if (vortex_debug > 4)
+			printk(KERN_DEBUG "%s: Updating stats.\n", dev->name);
+		update_stats(ioaddr, dev);
+		/* HACK: Disable statistics as an interrupt source. */
+		/* This occurs when we have the wrong media type! */
+		if (DoneDidThat == 0  &&
+			inw(ioaddr + EL3_STATUS) & StatsFull) {
+			printk(KERN_WARNING "%s: Updating statistics failed, disabling "
+				   "stats as an interrupt source.\n", dev->name);
+			EL3WINDOW(5);
+			outw(SetIntrEnb | (inw(ioaddr + 10) & ~StatsFull), ioaddr + EL3_CMD);
+			EL3WINDOW(7);
+			DoneDidThat++;
+		}
+	}
+	if (status & IntReq) {		/* Restore all interrupt sources.  */
+		outw(vp->status_enable, ioaddr + EL3_CMD);
+		outw(vp->intr_enable, ioaddr + EL3_CMD);
+	}
+	if (status & HostError) {
+		u16 fifo_diag;
+		EL3WINDOW(4);
+		fifo_diag = inw(ioaddr + Wn4_FIFODiag);
+		printk(KERN_ERR "%s: Host error, FIFO diagnostic register %4.4x.\n",
+			   dev->name, fifo_diag);
+		/* Adapter failure requires Tx/Rx reset and reinit. */
+		if (vp->full_bus_master_tx) {
+			wait_for_completion(dev, TotalReset | 0xff);
+			/* Re-enable the receiver. */
+			outw(RxEnable, ioaddr + EL3_CMD);
+			outw(TxEnable, ioaddr + EL3_CMD);
+		} else if (fifo_diag & 0x0400)
+			do_tx_reset = 1;
+		if (fifo_diag & 0x3000) {
+			wait_for_completion(dev, RxReset);
+			/* Set the Rx filter to the current state. */
+			set_rx_mode(dev);
+			outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
+			outw(AckIntr | HostError, ioaddr + EL3_CMD);
+		}
+	}
+	if (do_tx_reset) {
+		wait_for_completion(dev, TxReset);
+		outw(TxEnable, ioaddr + EL3_CMD);
+	}
+
+}
+
+static int
+vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+
+	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+		if (jiffies - dev->trans_start >= TX_TIMEOUT)
+			vortex_tx_timeout(dev);
+		return 1;
+	}
+
+	/* Put out the doubleword header... */
+	outl(skb->len, ioaddr + TX_FIFO);
+	if (vp->bus_master) {
+		/* Set the bus-master controller to transfer the packet. */
+		outl(virt_to_bus(skb->data), ioaddr + Wn7_MasterAddr);
+		outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
+		vp->tx_skb = skb;
+		outw(StartDMADown, ioaddr + EL3_CMD);
+		/* dev->tbusy will be cleared at the DMADone interrupt. */
+	} else {
+		/* ... and the packet rounded to a doubleword. */
+		outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+		DEV_FREE_SKB(skb);
+		if (inw(ioaddr + TxFree) > 1536) {
+			clear_bit(0, (void*)&dev->tbusy);
+		} else
+			/* Interrupt us when the FIFO has room for max-sized packet. */
+			outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
+	}
+
+	dev->trans_start = jiffies;
+
+	/* Clear the Tx status stack. */
+	{
+		int tx_status;
+		int i = 32;
+
+		while (--i > 0	&&	(tx_status = inb(ioaddr + TxStatus)) > 0) {
+			if (tx_status & 0x3C) {		/* A Tx-disabling error occurred.  */
+				if (vortex_debug > 2)
+				  printk(KERN_DEBUG "%s: Tx error, status %2.2x.\n",
+						 dev->name, tx_status);
+				if (tx_status & 0x04) vp->stats.tx_fifo_errors++;
+				if (tx_status & 0x38) vp->stats.tx_aborted_errors++;
+				if (tx_status & 0x30) {
+					wait_for_completion(dev, TxReset);
+				}
+				outw(TxEnable, ioaddr + EL3_CMD);
+			}
+			outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */
+		}
+	}
+	return 0;
+}
+
+static int
+boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+
+	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+		if (jiffies - dev->trans_start >= TX_TIMEOUT)
+			vortex_tx_timeout(dev);
+		return 1;
+	} else {
+		/* Calculate the next Tx descriptor entry. */
+		int entry = vp->cur_tx % TX_RING_SIZE;
+		struct boom_tx_desc *prev_entry =
+			&vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE];
+		unsigned long flags;
+
+		if (vortex_debug > 3)
+			printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n",
+				   dev->name, vp->cur_tx);
+		if (vp->tx_full) {
+			if (vortex_debug >0)
+				printk(KERN_WARNING "%s: Tx Ring full, refusing to send buffer.\n",
+					   dev->name);
+			return 1;
+		}
+		vp->tx_skbuff[entry] = skb;
+		vp->tx_ring[entry].next = 0;
+		vp->tx_ring[entry].addr = cpu_to_le32(virt_to_bus(skb->data));
+		vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG);
+		vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
+
+		save_flags(flags);
+		cli();
+		/* Wait for the stall to complete. */
+		wait_for_completion(dev, DownStall);
+		prev_entry->next = cpu_to_le32(virt_to_bus(&vp->tx_ring[entry]));
+		if (inl(ioaddr + DownListPtr) == 0) {
+			outl(virt_to_bus(&vp->tx_ring[entry]), ioaddr + DownListPtr);
+			queued_packet++;
+		}
+		outw(DownUnstall, ioaddr + EL3_CMD);
+		restore_flags(flags);
+
+		vp->cur_tx++;
+		if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1)
+			vp->tx_full = 1;
+		else {					/* Clear previous interrupt enable. */
+#if defined(tx_interrupt_mitigation)
+			prev_entry->status &= cpu_to_le32(~TxIntrUploaded);
+#endif
+			clear_bit(0, (void*)&dev->tbusy);
+		}
+		dev->trans_start = jiffies;
+		return 0;
+	}
+}
+
+/* The interrupt handler does all of the Rx thread work and cleans up
+   after the Tx thread. */
+static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = dev_id;
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	long ioaddr;
+	int latency, status;
+	int work_done = max_interrupt_work;
+
+#if defined(__i386__)
+	/* A lock to prevent simultaneous entry bug on Intel SMP machines. */
+	if (test_and_set_bit(0, (void*)&dev->interrupt)) {
+		printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
+			   dev->name);
+		dev->interrupt = 0;	/* Avoid halting machine. */
+		return;
+	}
+#else
+	if (dev->interrupt) {
+		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
+		return;
+	}
+	dev->interrupt = 1;
+#endif
+
+	dev->interrupt = 1;
+	ioaddr = dev->base_addr;
+	latency = inb(ioaddr + Timer);
+	status = inw(ioaddr + EL3_STATUS);
+
+	if (status == 0xffff)
+		goto handler_exit;
+	if (vortex_debug > 4)
+		printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n",
+			   dev->name, status, latency);
+	do {
+		if (vortex_debug > 5)
+				printk(KERN_DEBUG "%s: In interrupt loop, status %4.4x.\n",
+					   dev->name, status);
+		if (status & RxComplete)
+			vortex_rx(dev);
+		if (status & UpComplete) {
+			outw(AckIntr | UpComplete, ioaddr + EL3_CMD);
+			boomerang_rx(dev);
+		}
+
+		if (status & TxAvailable) {
+			if (vortex_debug > 5)
+				printk(KERN_DEBUG "	TX room bit was handled.\n");
+			/* There's room in the FIFO for a full-sized packet. */
+			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
+			clear_bit(0, (void*)&dev->tbusy);
+			mark_bh(NET_BH);
+		}
+
+		if (status & DownComplete) {
+			unsigned int dirty_tx = vp->dirty_tx;
+
+			outw(AckIntr | DownComplete, ioaddr + EL3_CMD);
+			while (vp->cur_tx - dirty_tx > 0) {
+				int entry = dirty_tx % TX_RING_SIZE;
+				if (inl(ioaddr + DownListPtr) ==
+					virt_to_bus(&vp->tx_ring[entry]))
+					break;			/* It still hasn't been processed. */
+				if (vp->tx_skbuff[entry]) {
+					DEV_FREE_SKB(vp->tx_skbuff[entry]);
+					vp->tx_skbuff[entry] = 0;
+				}
+				/* vp->stats.tx_packets++;  Counted below. */
+				dirty_tx++;
+			}
+			vp->dirty_tx = dirty_tx;
+			if (vp->tx_full && (vp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) {
+				vp->tx_full = 0;
+				clear_bit(0, (void*)&dev->tbusy);
+				mark_bh(NET_BH);
+			}
+		}
+		if (status & DMADone) {
+			if (inw(ioaddr + Wn7_MasterStatus) & 0x1000) {
+				outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
+				DEV_FREE_SKB(vp->tx_skb); /* Release the transfered buffer */
+				if (inw(ioaddr + TxFree) > 1536) {
+					clear_bit(0, (void*)&dev->tbusy);
+					mark_bh(NET_BH);
+				} else /* Interrupt when FIFO has room for max-sized packet. */
+					outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
+			}
+		}
+		/* Check for all uncommon interrupts at once. */
+		if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) {
+			if (status == 0xffff)
+				break;
+			vortex_error(dev, status);
+		}
+
+		if (--work_done < 0) {
+			if ((status & (0x7fe - (UpComplete | DownComplete))) == 0) {
+				/* Just ack these and return. */
+				outw(AckIntr | UpComplete | DownComplete, ioaddr + EL3_CMD);
+			} else {
+				printk(KERN_WARNING "%s: Too much work in interrupt, status "
+					   "%4.4x.  Temporarily disabling functions (%4.4x).\n",
+					   dev->name, status, SetStatusEnb | ((~status) & 0x7FE));
+				/* Disable all pending interrupts. */
+				outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD);
+				outw(AckIntr | 0x7FF, ioaddr + EL3_CMD);
+				/* The timer will reenable interrupts. */
+				break;
+			}
+		}
+		/* Acknowledge the IRQ. */
+		outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
+		if (vp->cb_fn_base)			/* The PCMCIA people are idiots.  */
+			writel(0x8000, vp->cb_fn_base + 4);
+
+	} while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
+
+	if (vortex_debug > 4)
+		printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n",
+			   dev->name, status);
+handler_exit:
+#if defined(__i386__)
+	clear_bit(0, (void*)&dev->interrupt);
+#else
+	dev->interrupt = 0;
+#endif
+	return;
+}
+
+static int vortex_rx(struct net_device *dev)
+{
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int i;
+	short rx_status;
+
+	if (vortex_debug > 5)
+		printk(KERN_DEBUG"   In rx_packet(), status %4.4x, rx_status %4.4x.\n",
+			   inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
+	while ((rx_status = inw(ioaddr + RxStatus)) > 0) {
+		if (rx_status & 0x4000) { /* Error, update stats. */
+			unsigned char rx_error = inb(ioaddr + RxErrors);
+			if (vortex_debug > 2)
+				printk(KERN_DEBUG " Rx error: status %2.2x.\n", rx_error);
+			vp->stats.rx_errors++;
+			if (rx_error & 0x01)  vp->stats.rx_over_errors++;
+			if (rx_error & 0x02)  vp->stats.rx_length_errors++;
+			if (rx_error & 0x04)  vp->stats.rx_frame_errors++;
+			if (rx_error & 0x08)  vp->stats.rx_crc_errors++;
+			if (rx_error & 0x10)  vp->stats.rx_length_errors++;
+		} else {
+			/* The packet length: up to 4.5K!. */
+			int pkt_len = rx_status & 0x1fff;
+			struct sk_buff *skb;
+
+			skb = dev_alloc_skb(pkt_len + 5);
+			if (vortex_debug > 4)
+				printk(KERN_DEBUG "Receiving packet size %d status %4.4x.\n",
+					   pkt_len, rx_status);
+			if (skb != NULL) {
+				skb->dev = dev;
+				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
+				/* 'skb_put()' points to the start of sk_buff data area. */
+				if (vp->bus_master &&
+					! (inw(ioaddr + Wn7_MasterStatus) & 0x8000)) {
+					outl(virt_to_bus(skb_put(skb, pkt_len)),
+						 ioaddr + Wn7_MasterAddr);
+					outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
+					outw(StartDMAUp, ioaddr + EL3_CMD);
+					while (inw(ioaddr + Wn7_MasterStatus) & 0x8000)
+						;
+				} else {
+					insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len),
+						 (pkt_len + 3) >> 2);
+				}
+				outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
+				skb->protocol = eth_type_trans(skb, dev);
+				netif_rx(skb);
+				dev->last_rx = jiffies;
+				vp->stats.rx_packets++;
+				/* Wait a limited time to go to next packet. */
+				for (i = 200; i >= 0; i--)
+					if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+						break;
+				continue;
+			} else if (vortex_debug)
+				printk(KERN_NOTICE "%s: No memory to allocate a sk_buff of "
+					   "size %d.\n", dev->name, pkt_len);
+		}
+		outw(RxDiscard, ioaddr + EL3_CMD);
+		vp->stats.rx_dropped++;
+		/* Wait a limited time to skip this packet. */
+		for (i = 200; i >= 0; i--)
+			if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+				break;
+	}
+
+	return 0;
+}
+
+static int
+boomerang_rx(struct net_device *dev)
+{
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	int entry = vp->cur_rx % RX_RING_SIZE;
+	long ioaddr = dev->base_addr;
+	int rx_status;
+	int rx_work_limit = vp->dirty_rx + RX_RING_SIZE - vp->cur_rx;
+
+	if (vortex_debug > 5)
+		printk(KERN_DEBUG "  In boomerang_rx(), status %4.4x, rx_status "
+			   "%4.4x.\n",
+			   inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
+	while ((rx_status = le32_to_cpu(vp->rx_ring[entry].status)) & RxDComplete){
+		if (--rx_work_limit < 0)
+			break;
+		if (rx_status & RxDError) { /* Error, update stats. */
+			unsigned char rx_error = rx_status >> 16;
+			if (vortex_debug > 2)
+				printk(KERN_DEBUG " Rx error: status %2.2x.\n", rx_error);
+			vp->stats.rx_errors++;
+			if (rx_error & 0x01)  vp->stats.rx_over_errors++;
+			if (rx_error & 0x02)  vp->stats.rx_length_errors++;
+			if (rx_error & 0x04)  vp->stats.rx_frame_errors++;
+			if (rx_error & 0x08)  vp->stats.rx_crc_errors++;
+			if (rx_error & 0x10)  vp->stats.rx_length_errors++;
+		} else {
+			/* The packet length: up to 4.5K!. */
+			int pkt_len = rx_status & 0x1fff;
+			struct sk_buff *skb;
+
+			if (vortex_debug > 4)
+				printk(KERN_DEBUG "Receiving packet size %d status %4.4x.\n",
+					   pkt_len, rx_status);
+
+			/* Check if the packet is long enough to just accept without
+			   copying to a properly sized skbuff. */
+			if (pkt_len < rx_copybreak
+				&& (skb = dev_alloc_skb(pkt_len + 2)) != 0) {
+				skb->dev = dev;
+				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
+				/* 'skb_put()' points to the start of sk_buff data area. */
+				memcpy(skb_put(skb, pkt_len),
+					   bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)),
+					   pkt_len);
+				rx_copy++;
+			} else {
+				void *temp;
+				/* Pass up the skbuff already on the Rx ring. */
+				skb = vp->rx_skbuff[entry];
+				vp->rx_skbuff[entry] = NULL;
+				temp = skb_put(skb, pkt_len);
+				/* Remove this checking code for final release. */
+				if (bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)) != temp)
+					printk(KERN_ERR "%s: Warning -- the skbuff addresses do not match"
+						   " in boomerang_rx: %p vs. %p.\n", dev->name,
+						   bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)),
+						   temp);
+				rx_nocopy++;
+			}
+			skb->protocol = eth_type_trans(skb, dev);
+			{					/* Use hardware checksum info. */
+				int csum_bits = rx_status & 0xee000000;
+				if (csum_bits &&
+					(csum_bits == (IPChksumValid | TCPChksumValid) ||
+					 csum_bits == (IPChksumValid | UDPChksumValid))) {
+					skb->ip_summed = CHECKSUM_UNNECESSARY;
+					rx_csumhits++;
+				}
+			}
+			netif_rx(skb);
+			dev->last_rx = jiffies;
+			vp->stats.rx_packets++;
+		}
+		entry = (++vp->cur_rx) % RX_RING_SIZE;
+	}
+	/* Refill the Rx ring buffers. */
+	for (; vp->dirty_rx < vp->cur_rx; vp->dirty_rx++) {
+		struct sk_buff *skb;
+		entry = vp->dirty_rx % RX_RING_SIZE;
+		if (vp->rx_skbuff[entry] == NULL) {
+			skb = dev_alloc_skb(PKT_BUF_SZ);
+			if (skb == NULL)
+				break;			/* Bad news!  */
+			skb->dev = dev;			/* Mark as being used by this device. */
+			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
+			vp->rx_ring[entry].addr = cpu_to_le32(virt_to_bus(skb->tail));
+			vp->rx_skbuff[entry] = skb;
+		}
+		vp->rx_ring[entry].status = 0;	/* Clear complete bit. */
+		outw(UpUnstall, ioaddr + EL3_CMD);
+	}
+	return 0;
+}
+
+static void
+vortex_down(struct net_device *dev)
+{
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+
+	dev->start = 0;
+	dev->tbusy = 1;
+
+	del_timer(&vp->timer);
+
+	/* Turn off statistics ASAP.  We update vp->stats below. */
+	outw(StatsDisable, ioaddr + EL3_CMD);
+
+	/* Disable the receiver and transmitter. */
+	outw(RxDisable, ioaddr + EL3_CMD);
+	outw(TxDisable, ioaddr + EL3_CMD);
+
+	if (dev->if_port == XCVR_10base2)
+		/* Turn off thinnet power.  Green! */
+		outw(StopCoax, ioaddr + EL3_CMD);
+
+	outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
+
+	update_stats(ioaddr, dev);
+	if (vp->full_bus_master_rx)
+		outl(0, ioaddr + UpListPtr);
+	if (vp->full_bus_master_tx)
+		outl(0, ioaddr + DownListPtr);
+
+	if (vp->capabilities & CapPwrMgmt)
+		acpi_set_WOL(dev);
+}
+
+static int
+vortex_close(struct net_device *dev)
+{
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int i;
+
+	if (dev->start)
+		vortex_down(dev);
+
+	if (vortex_debug > 1) {
+		printk(KERN_DEBUG"%s: vortex_close() status %4.4x, Tx status %2.2x.\n",
+			   dev->name, inw(ioaddr + EL3_STATUS), inb(ioaddr + TxStatus));
+		printk(KERN_DEBUG "%s: vortex close stats: rx_nocopy %d rx_copy %d"
+			   " tx_queued %d Rx pre-checksummed %d.\n",
+			   dev->name, rx_nocopy, rx_copy, queued_packet, rx_csumhits);
+	}
+
+	free_irq(dev->irq, dev);
+
+	if (vp->full_bus_master_rx) { /* Free Boomerang bus master Rx buffers. */
+		for (i = 0; i < RX_RING_SIZE; i++)
+			if (vp->rx_skbuff[i]) {
+				DEV_FREE_SKB(vp->rx_skbuff[i]);
+				vp->rx_skbuff[i] = 0;
+			}
+	}
+	if (vp->full_bus_master_tx) { /* Free Boomerang bus master Tx buffers. */
+		for (i = 0; i < TX_RING_SIZE; i++)
+			if (vp->tx_skbuff[i]) {
+				DEV_FREE_SKB(vp->tx_skbuff[i]);
+				vp->tx_skbuff[i] = 0;
+			}
+	}
+
+	MOD_DEC_USE_COUNT;
+	vp->open = 0;
+	return 0;
+}
+
+static struct net_device_stats *vortex_get_stats(struct net_device *dev)
+{
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	unsigned long flags;
+
+	if (dev->start) {
+		save_flags(flags);
+		cli();
+		update_stats(dev->base_addr, dev);
+		restore_flags(flags);
+	}
+	return &vp->stats;
+}
+
+/*  Update statistics.
+	Unlike with the EL3 we need not worry about interrupts changing
+	the window setting from underneath us, but we must still guard
+	against a race condition with a StatsUpdate interrupt updating the
+	table.  This is done by checking that the ASM (!) code generated uses
+	atomic updates with '+='.
+	*/
+static void update_stats(long ioaddr, struct net_device *dev)
+{
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	int old_window = inw(ioaddr + EL3_CMD);
+
+	if (old_window == 0xffff)	/* Chip suspended or ejected. */
+		return;
+	/* Unlike the 3c5x9 we need not turn off stats updates while reading. */
+	/* Switch to the stats window, and read everything. */
+	EL3WINDOW(6);
+	vp->stats.tx_carrier_errors		+= inb(ioaddr + 0);
+	vp->stats.tx_heartbeat_errors	+= inb(ioaddr + 1);
+	/* Multiple collisions. */		inb(ioaddr + 2);
+	vp->stats.collisions			+= inb(ioaddr + 3);
+	vp->stats.tx_window_errors		+= inb(ioaddr + 4);
+	vp->stats.rx_fifo_errors		+= inb(ioaddr + 5);
+	vp->stats.tx_packets			+= inb(ioaddr + 6);
+	vp->stats.tx_packets			+= (inb(ioaddr + 9)&0x30) << 4;
+	/* Rx packets	*/				inb(ioaddr + 7);   /* Must read to clear */
+	/* Tx deferrals */				inb(ioaddr + 8);
+	/* Don't bother with register 9, an extension of registers 6&7.
+	   If we do use the 6&7 values the atomic update assumption above
+	   is invalid. */
+	vp->stats.rx_bytes += inw(ioaddr + 10);
+	vp->stats.tx_bytes += inw(ioaddr + 12);
+	/* New: On the Vortex we must also clear the BadSSD counter. */
+	EL3WINDOW(4);
+	inb(ioaddr + 12);
+
+	{
+		u8 up = inb(ioaddr + 13);
+		vp->stats.rx_bytes += (up & 0x0f) << 16;
+		vp->stats.tx_bytes += (up & 0xf0) << 12;
+	}
+
+	/* We change back to window 7 (not 1) with the Vortex. */
+	EL3WINDOW(old_window >> 13);
+	return;
+}
+
+static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	u16 *data = (u16 *)&rq->ifr_data;
+	int phy = vp->phys[0] & 0x1f;
+
+	switch(cmd) {
+	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
+		data[0] = phy;
+	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
+		EL3WINDOW(4);
+		data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
+		return 0;
+	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		EL3WINDOW(4);
+		mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+		return 0;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+/* Pre-Cyclone chips have no documented multicast filter, so the only
+   multicast setting is to receive all multicast frames.  At least
+   the chip has a very clean way to set the mode, unlike many others. */
+static void set_rx_mode(struct net_device *dev)
+{
+	long ioaddr = dev->base_addr;
+	int new_mode;
+
+	if (dev->flags & IFF_PROMISC) {
+		if (vortex_debug > 0)
+			printk(KERN_NOTICE "%s: Setting promiscuous mode.\n", dev->name);
+		new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast|RxProm;
+	} else	if ((dev->mc_list)  ||  (dev->flags & IFF_ALLMULTI)) {
+		new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast;
+	} else
+		new_mode = SetRxFilter | RxStation | RxBroadcast;
+
+	outw(new_mode, ioaddr + EL3_CMD);
+}
+
+/* MII transceiver control section.
+   Read and write the MII registers using software-generated serial
+   MDIO protocol.  See the MII specifications or DP83840A data sheet
+   for details. */
+
+/* The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually
+   met by back-to-back PCI I/O cycles, but we insert a delay to avoid
+   "overclocking" issues. */
+#define mdio_delay() inl(mdio_addr)
+
+#define MDIO_SHIFT_CLK	0x01
+#define MDIO_DIR_WRITE	0x04
+#define MDIO_DATA_WRITE0 (0x00 | MDIO_DIR_WRITE)
+#define MDIO_DATA_WRITE1 (0x02 | MDIO_DIR_WRITE)
+#define MDIO_DATA_READ	0x02
+#define MDIO_ENB_IN		0x00
+
+/* Generate the preamble required for initial synchronization and
+   a few older transceivers. */
+static void mdio_sync(long ioaddr, int bits)
+{
+	long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+
+	/* Establish sync by sending at least 32 logic ones. */
+	while (-- bits >= 0) {
+		outw(MDIO_DATA_WRITE1, mdio_addr);
+		mdio_delay();
+		outw(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
+		mdio_delay();
+	}
+}
+
+static int mdio_read(long ioaddr, int phy_id, int location)
+{
+	int i;
+	int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+	unsigned int retval = 0;
+	long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+
+	if (mii_preamble_required)
+		mdio_sync(ioaddr, 32);
+
+	/* Shift the read command bits out. */
+	for (i = 14; i >= 0; i--) {
+		int dataval = (read_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+		outw(dataval, mdio_addr);
+		mdio_delay();
+		outw(dataval | MDIO_SHIFT_CLK, mdio_addr);
+		mdio_delay();
+	}
+	/* Read the two transition, 16 data, and wire-idle bits. */
+	for (i = 19; i > 0; i--) {
+		outw(MDIO_ENB_IN, mdio_addr);
+		mdio_delay();
+		retval = (retval << 1) | ((inw(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
+		outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+		mdio_delay();
+	}
+	return retval & 0x20000 ? 0xffff : retval>>1 & 0xffff;
+}
+
+static void mdio_write(long ioaddr, int phy_id, int location, int value)
+{
+	int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value;
+	long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+	int i;
+
+	if (mii_preamble_required)
+		mdio_sync(ioaddr, 32);
+
+	/* Shift the command bits out. */
+	for (i = 31; i >= 0; i--) {
+		int dataval = (write_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+		outw(dataval, mdio_addr);
+		mdio_delay();
+		outw(dataval | MDIO_SHIFT_CLK, mdio_addr);
+		mdio_delay();
+	}
+	/* Leave the interface idle. */
+	for (i = 1; i >= 0; i--) {
+		outw(MDIO_ENB_IN, mdio_addr);
+		mdio_delay();
+		outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+		mdio_delay();
+	}
+
+	return;
+}
+
+/* ACPI: Advanced Configuration and Power Interface. */
+/* Set Wake-On-LAN mode and put the board into D3 (power-down) state. */
+static void acpi_set_WOL(struct net_device *dev)
+{
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+
+	/* Power up on: 1==Downloaded Filter, 2==Magic Packets, 4==Link Status. */
+	EL3WINDOW(7);
+	outw(2, ioaddr + 0x0c);
+	/* The RxFilter must accept the WOL frames. */
+	outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
+	outw(RxEnable, ioaddr + EL3_CMD);
+	/* Change the power state to D3; RxEnable doesn't take effect. */
+	pcibios_write_config_word(vp->pci_bus, vp->pci_devfn, 0xe0, 0x8103);
+}
+/* Change from D3 (sleep) to D0 (active).
+   Problem: The Cyclone forgets all PCI config info during the transition! */
+static void acpi_wake(int bus, int devfn)
+{
+	u32 base0, base1, romaddr;
+	u16 pci_command, pwr_command;
+	u8  pci_latency, pci_cacheline, irq;
+
+	pcibios_read_config_word(bus, devfn, 0xe0, &pwr_command);
+	if ((pwr_command & 3) == 0)
+		return;
+	pcibios_read_config_word( bus, devfn, PCI_COMMAND, &pci_command);
+	pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &base0);
+	pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_1, &base1);
+	pcibios_read_config_dword(bus, devfn, PCI_ROM_ADDRESS, &romaddr);
+	pcibios_read_config_byte( bus, devfn, PCI_LATENCY_TIMER, &pci_latency);
+	pcibios_read_config_byte( bus, devfn, PCI_CACHE_LINE_SIZE, &pci_cacheline);
+	pcibios_read_config_byte( bus, devfn, PCI_INTERRUPT_LINE, &irq);
+
+	pcibios_write_config_word( bus, devfn, 0xe0, 0x0000);
+	pcibios_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, base0);
+	pcibios_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_1, base1);
+	pcibios_write_config_dword(bus, devfn, PCI_ROM_ADDRESS, romaddr);
+	pcibios_write_config_byte( bus, devfn, PCI_INTERRUPT_LINE, irq);
+	pcibios_write_config_byte( bus, devfn, PCI_LATENCY_TIMER, pci_latency);
+	pcibios_write_config_byte( bus, devfn, PCI_CACHE_LINE_SIZE, pci_cacheline);
+	pcibios_write_config_word( bus, devfn, PCI_COMMAND, pci_command | 5);
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+	struct net_device *next_dev;
+
+#ifdef CARDBUS
+	unregister_driver(&vortex_ops);
+#endif
+
+	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+	while (root_vortex_dev) {
+		struct vortex_private *vp=(void *)(root_vortex_dev->priv);
+		next_dev = vp->next_module;
+		unregister_netdev(root_vortex_dev);
+		outw(TotalReset, root_vortex_dev->base_addr + EL3_CMD);
+		release_region(root_vortex_dev->base_addr,
+					   pci_tbl[vp->chip_id].io_size);
+		kfree(root_vortex_dev);
+		kfree(vp->priv_addr);
+		root_vortex_dev = next_dev;
+	}
+}
+
+#endif  /* MODULE */
+
+/*
+ * Local variables:
+ *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ *  SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c"
+ *  cardbus-compile-command: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c -o 3c575_cb.o -I/usr/src/linux/pcmcia-cs-3.0.9/include/"
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
diff -u --recursive --new-file v2.3.26/linux/drivers/net/pcmcia/3c589_cs.c linux/drivers/net/pcmcia/3c589_cs.c
--- v2.3.26/linux/drivers/net/pcmcia/3c589_cs.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/net/pcmcia/3c589_cs.c	Thu Nov 11 16:03:36 1999
@@ -2,9 +2,9 @@
 
     A PCMCIA ethernet driver for the 3com 3c589 card.
     
-    Copyright (C) 1999 David A. Hinds -- dhinds@hyper.stanford.edu
+    Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org
 
-    3c589_cs.c 1.135 1999/10/07 20:14:54
+    3c589_cs.c 1.137 1999/11/08 20:46:17
 
     The network driver code is based on Donald Becker's 3c589 code:
     
@@ -115,7 +115,7 @@
 MODULE_PARM(pc_debug, "i");
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
-"3c589_cs.c 1.135 1999/10/07 20:14:54 (David Hinds)";
+"3c589_cs.c 1.137 1999/11/08 20:46:17 (David Hinds)";
 #else
 #define DEBUG(n, args...)
 #endif
@@ -226,7 +226,6 @@
     link->release.data = (u_long)link;
     link->io.NumPorts1 = 16;
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-    link->io.IOAddrLines = 4;
     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
     link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
     if (irq_list[0] == -1)
@@ -392,6 +391,7 @@
     link->state |= DEV_CONFIG;
 
     /* For the 3c562, the base address must be xx00-xx7f */
+    link->io.IOAddrLines = 16;
     for (i = j = 0; j < 0x400; j += 0x10) {
 	if (multi && (j & 0x80)) continue;
 	link->io.BasePort1 = j ^ 0x300;
diff -u --recursive --new-file v2.3.26/linux/drivers/net/pcmcia/Config.in linux/drivers/net/pcmcia/Config.in
--- v2.3.26/linux/drivers/net/pcmcia/Config.in	Fri Oct 22 13:21:49 1999
+++ linux/drivers/net/pcmcia/Config.in	Thu Nov 11 16:03:36 1999
@@ -15,11 +15,11 @@
    dep_tristate '  SMC 91Cxx PCMCIA support' CONFIG_PCMCIA_SMC91C92 $CONFIG_PCMCIA
    dep_tristate '  Xircom 16-bit PCMCIA support' CONFIG_PCMCIA_XIRC2PS $CONFIG_PCMCIA
 
-   # if [ "$CONFIG_CARDBUS" = "y" ]; then
-      # dep_tristate '  3Com 3c575 CardBus support' CONFIG_PCMCIA_3C575 $CONFIG_PCMCIA
-      # dep_tristate '  DEC Tulip CardBus support' CONFIG_PCMCIA_TULIP $CONFIG_PCMCIA
-      # dep_tristate '  SMC EPIC CardBus support' CONFIG_PCMCIA_EPIC100 $CONFIG_PCMCIA
-   # fi
+   if [ "$CONFIG_CARDBUS" = "y" ]; then
+      dep_tristate '  3Com 3c575 CardBus support' CONFIG_PCMCIA_3C575 m
+      dep_tristate '  DEC Tulip CardBus support' CONFIG_PCMCIA_TULIP m
+      dep_tristate '  SMC EPIC CardBus support' CONFIG_PCMCIA_EPIC100 m
+   fi
 
    dep_tristate '  Aviator/Raytheon 2.4MHz wireless support' CONFIG_PCMCIA_RAYCS $CONFIG_PCMCIA
    dep_tristate '  Xircom Netwave AirSurfer wireless support' CONFIG_PCMCIA_NETWAVE $CONFIG_PCMCIA
diff -u --recursive --new-file v2.3.26/linux/drivers/net/pcmcia/Makefile linux/drivers/net/pcmcia/Makefile
--- v2.3.26/linux/drivers/net/pcmcia/Makefile	Fri Oct 22 13:21:49 1999
+++ linux/drivers/net/pcmcia/Makefile	Thu Nov 11 16:03:36 1999
@@ -9,110 +9,44 @@
 ALL_SUB_DIRS := $(SUB_DIRS)
 
 O_TARGET := pcmcia_net.o
-O_OBJS   :=
-M_OBJS   :=
-MOD_LIST_NAME := PCMCIA_MODULES
-
-#CFLAGS_3c575_cb.o = -DCARDBUS
-#CFLAGS_tulip_cb.o = -DCARDBUS
-
-ifeq ($(CONFIG_PCMCIA_3C589),y)
-  O_OBJS += 3c589_cs.o
-else
-  ifeq ($(CONFIG_PCMCIA_3C589),m)
-    M_OBJS += 3c589_cs.o
-  endif
-endif
-
-ifeq ($(CONFIG_PCMCIA_3C574),y)
-  O_OBJS += 3c574_cs.o
-else
-  ifeq ($(CONFIG_PCMCIA_3C574),m)
-    M_OBJS += 3c574_cs.o
-  endif
-endif
-
-ifeq ($(CONFIG_PCMCIA_FMVJ18X),y)
-  O_OBJS += fmvj18x_cs.o
-else
-  ifeq ($(CONFIG_PCMCIA_FMVJ18X),m)
-    M_OBJS += fmvj18x_cs.o
-  endif
-endif
-
-ifeq ($(CONFIG_PCMCIA_NMCLAN),y)
-  O_OBJS += nmclan_cs.o
-else
-  ifeq ($(CONFIG_PCMCIA_NMCLAN),m)
-    M_OBJS += nmclan_cs.o
-  endif
-endif
-
-ifeq ($(CONFIG_PCMCIA_PCNET),y)
-  O_OBJS += pcnet_cs.o
-else
-  ifeq ($(CONFIG_PCMCIA_PCNET),m)
-    M_OBJS += pcnet_cs.o
-  endif
-endif
-
-ifeq ($(CONFIG_PCMCIA_SMC91C92),y)
-  O_OBJS += smc91c92_cs.o
-else
-  ifeq ($(CONFIG_PCMCIA_SMC91C92),m)
-    M_OBJS += smc91c92_cs.o
-  endif
-endif
-
-#ifeq ($(CONFIG_PCMCIA_3C575),y)
-#  O_OBJS += 3c575_cb.o
-#else
-#  ifeq ($(CONFIG_PCMCIA_3C575),m)
-#    M_OBJS += 3c575_cb.o
-#  endif
-#endif
-
-#ifeq ($(CONFIG_PCMCIA_TULIP),y)
-#  O_OBJS += tulip_cb.o
-#else
-#  ifeq ($(CONFIG_PCMCIA_TULIP),m)
-#    M_OBJS += tulip_cb.o
-#  endif
-#endif
-
-#ifeq ($(CONFIG_PCMCIA_EPIC100),y)
-#  O_OBJS += epic100_cb.o
-#else
-#  ifeq ($(CONFIG_PCMCIA_EPIC100),m)
-#    M_OBJS += epic100_cb.o
-#  endif
-#endif
-
-ifeq ($(CONFIG_PCMCIA_RAYCS),y)
-  OX_OBJS += ray_cs.o
-else
-  ifeq ($(CONFIG_PCMCIA_RAYCS),m)
-  MX_OBJS += ray_cs.o
-  endif
-endif
-
-ifeq ($(CONFIG_PCMCIA_NETWAVE),y)
-  OX_OBJS += netwave_cs.o
-else
-  ifeq ($(CONFIG_PCMCIA_NETWAVE),m)
-  M_OBJS += netwave_cs.o
-  endif
-endif
-
-ifeq ($(CONFIG_PCMCIA_WAVELAN),y)
-  OX_OBJS += wavelan_cs.o
-else
-  ifeq ($(CONFIG_PCMCIA_WAVELAN),m)
-  M_OBJS += wavelan_cs.o
-  endif
-endif
+MOD_LIST_NAME := PCMCIA_NET_MODULES
+
+obj-y		:=
+obj-m		:=
+obj-n		:=
+obj-		:=
+
+# Things that need to export symbols
+export-objs	:= ray_cs.o
+
+CFLAGS_3c575_cb.o = -DCARDBUS -DMODULE
+CFLAGS_tulip_cb.o = -DCARDBUS -DMODULE
+
+# 16-bit client drivers
+obj-$(CONFIG_PCMCIA_3C589)	+= 3c589_cs.o
+obj-$(CONFIG_PCMCIA_3C574)	+= 3c574_cs.o
+obj-$(CONFIG_PCMCIA_FMVJ18X)	+= fmvj18x_cs.o
+obj-$(CONFIG_PCMCIA_NMCLAN)	+= nmclan_cs.o
+obj-$(CONFIG_PCMCIA_PCNET)	+= pcnet_cs.o
+obj-$(CONFIG_PCMCIA_SMC91C92)	+= smc91c92_cs.o
+obj-$(CONFIG_PCMCIA_XIRC2PS)	+= xirc2ps_cs.o
+
+# 16-bit wireless client drivers
+obj-$(CONFIG_PCMCIA_RAYCS)	+= ray_cs.o
+obj-$(CONFIG_PCMCIA_NETWAVE)	+= netwave_cs.o
+obj-$(CONFIG_PCMCIA_WAVELAN)	+= wavelan_cs.o
+
+# Cardbus client drivers
+obj-$(CONFIG_PCMCIA_3C575)	+= 3c575_cb.o
+obj-$(CONFIG_PCMCIA_TULIP)	+= tulip_cb.o
+obj-$(CONFIG_PCMCIA_EPIC100)	+= epic100_cb.o
+
+O_OBJS		:= $(filter-out $(export-objs), $(obj-y))
+OX_OBJS		:= $(filter     $(export-objs), $(obj-y))
+M_OBJS		:= $(filter-out $(export-objs), $(obj-m))
+MX_OBJS		:= $(filter     $(export-objs), $(obj-m))
 
 include $(TOPDIR)/Rules.make
 
-#epic100_cb.o: ../epic100.c
-#	$(CC) $(CFLAGS) -DCARDBUS -c -o $@ ../epic100.c
+epic100_cb.o: ../epic100.c
+	$(CC) $(CFLAGS) -DMODULE -DCARDBUS -c -o $@ ../epic100.c
diff -u --recursive --new-file v2.3.26/linux/drivers/net/pcmcia/netwave_cs.c linux/drivers/net/pcmcia/netwave_cs.c
--- v2.3.26/linux/drivers/net/pcmcia/netwave_cs.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/net/pcmcia/netwave_cs.c	Thu Nov 11 16:03:37 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Authors:       John Markus Bjørndalen <johnm@cs.uit.no>
  *                Dag Brattli <dagb@cs.uit.no>
- *                David Hinds <dhinds@hyper.stanford.edu>
+ *                David Hinds <dhinds@pcmcia.sourceforge.org>
  * Created at:    A long time ago!
  * Modified at:   Mon Nov 10 11:54:37 1997
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
diff -u --recursive --new-file v2.3.26/linux/drivers/net/pcmcia/nmclan_cs.c linux/drivers/net/pcmcia/nmclan_cs.c
--- v2.3.26/linux/drivers/net/pcmcia/nmclan_cs.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/net/pcmcia/nmclan_cs.c	Thu Nov 11 16:03:37 1999
@@ -28,7 +28,7 @@
   Dean Siasoyco, New Media Corporation
   Ken Lesniak, Silicon Graphics, Inc. <lesniak@boston.sgi.com>
   Donald Becker <becker@cesdis1.gsfc.nasa.gov>
-  David Hinds <dhinds@hyper.stanford.edu>
+  David Hinds <dhinds@pcmcia.sourceforge.org>
 
   The Linux client driver is based on the 3c589_cs.c client driver by
   David Hinds.
diff -u --recursive --new-file v2.3.26/linux/drivers/net/pcmcia/pcnet_cs.c linux/drivers/net/pcmcia/pcnet_cs.c
--- v2.3.26/linux/drivers/net/pcmcia/pcnet_cs.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/net/pcmcia/pcnet_cs.c	Thu Nov 11 16:03:37 1999
@@ -9,9 +9,9 @@
     Conrad ethernet card, and the Kingston KNE-PCM/x in shared-memory
     mode.  It will also handle the Socket EA card in either mode.
 
-    Copyright (C) 1999 David A. Hinds -- dhinds@hyper.stanford.edu
+    Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org
 
-    pcnet_cs.c 1.101 1999/10/21 00:56:19
+    pcnet_cs.c 1.106 1999/11/09 21:53:13
     
     The network driver code is based on Donald Becker's NE2000 code:
 
@@ -72,7 +72,7 @@
 MODULE_PARM(pc_debug, "i");
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
-"pcnet_cs.c 1.101 1999/10/21 00:56:19 (David Hinds)";
+"pcnet_cs.c 1.106 1999/11/09 21:53:13 (David Hinds)";
 #else
 #define DEBUG(n, args...)
 #endif
@@ -187,6 +187,8 @@
       HAS_MISC_REG | HAS_IBM_MISC },
     { /* Kansai KLA-PCM/T */ 0x0ff0, 0x00, 0x60, 0x87,
       HAS_MISC_REG | HAS_IBM_MISC },
+    { /* NSC DP83903 */ 0x0374, 0x08, 0x00, 0x17,
+      HAS_MISC_REG | HAS_IBM_MISC },
     { /* NSC DP83903 */ 0x0374, 0x00, 0xc0, 0xa8,
       HAS_MISC_REG | HAS_IBM_MISC },
     { /* NSC DP83903 */ 0x0374, 0x00, 0xa0, 0xb0,
@@ -229,7 +231,7 @@
     u_long		flags;
     caddr_t		base;
     struct timer_list	watchdog;
-    int			stale;
+    int			stale, link;
     u_short		fast_poll;
 } pcnet_dev_t;
 
@@ -578,6 +580,7 @@
 	link->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
     }
     if (link->io.BasePort1 == 0) {
+	link->io.IOAddrLines = 16;
 	for (j = 0; j < 0x400; j += 0x20) {
 	    link->io.BasePort1 = j ^ 0x300;
 	    link->io.BasePort2 = (j ^ 0x300) + 0x10;
@@ -656,6 +659,7 @@
 		     (cfg->mem.win[0].len >= 0x4000));
 	link->io.BasePort1 = io->win[i].base;
 	link->io.NumPorts1 = io->win[i].len;
+	link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
 	if (link->io.NumPorts1 + link->io.NumPorts2 >= 32) {
 	    last_ret = try_io_port(link);
 	    if (last_ret == CS_SUCCESS) break;
@@ -681,10 +685,14 @@
     CS_CHECK(RequestConfiguration, handle, &link->conf);
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
-    if ((if_port == 1) || (if_port == 2))
-	dev->if_port = if_port;
-    else
-	printk(KERN_NOTICE "pcnet_cs: invalid if_port requested\n");
+    if (info->flags & HAS_MISC_REG) {
+	if ((if_port == 1) || (if_port == 2))
+	    dev->if_port = if_port;
+	else
+	    printk(KERN_NOTICE "pcnet_cs: invalid if_port requested\n");
+    } else {
+	dev->if_port = 0;
+    }
     dev->tbusy = 0;
     if (register_netdev(dev) != 0) {
 	printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n");
@@ -885,19 +893,11 @@
     link->open++;
     MOD_INC_USE_COUNT;
 
-    /* For D-Link EtherFast, wait for something(?) to happen */
-    if (info->flags & IS_DL10019A) {
-	int i;
-	for (i = 0; i < 20; i++) {
-	    if ((inb(dev->base_addr+0x1c) & 0x01) == 0) break;
-	    __set_current_state(TASK_UNINTERRUPTIBLE);
-	    schedule_timeout(HZ/10);
-	}
-    }
-    
     set_misc_reg(dev);
     request_irq(dev->irq, ei_irq_wrapper, SA_SHIRQ, dev_info, dev);
 
+    /* Start by assuming the link is bad */
+    info->link = 1;
     info->watchdog.function = &ei_watchdog;
     info->watchdog.data = (u_long)info;
     info->watchdog.expires = jiffies + HZ;
@@ -969,17 +969,14 @@
 {
     pcnet_dev_t *info = (pcnet_dev_t *)dev;
     if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
-	if ((map->port != 0) && !(info->flags & HAS_MISC_REG)) {
-	    printk(KERN_NOTICE "%s: transceiver selection not "
-		   "implemented\n", dev->name);
-	    return -EINVAL;
-	}
-	if ((map->port == 1) || (map->port == 2)) {
-	    dev->if_port = map->port;
-	    printk(KERN_INFO "%s: switched to %s port\n",
-		   dev->name, if_names[dev->if_port]);
-	} else
+	if (!(info->flags & HAS_MISC_REG))
+	    return -EOPNOTSUPP;
+	else if ((map->port < 1) || (map->port > 2))
 	    return -EINVAL;
+	dev->if_port = map->port;
+	printk(KERN_INFO "%s: switched to %s port\n",
+	       dev->name, if_names[dev->if_port]);
+	NS8390_init(dev, 1);
     }
     return 0;
 }
@@ -1015,6 +1012,17 @@
 	info->watchdog.expires = jiffies + 1;
 	add_timer(&info->watchdog);
 	return;
+    }
+
+    if (info->flags & IS_DL10019A) {
+	int state = inb(dev->base_addr+0x1c) & 0x01;
+	if (state != info->link) {
+	    printk(KERN_INFO "%s: %s link beat\n", dev->name,
+		   (state) ? "lost" : "found");
+	    if (!state)
+		NS8390_init(dev, 1);
+	    info->link = state;
+	}
     }
 
 reschedule:
diff -u --recursive --new-file v2.3.26/linux/drivers/net/pcmcia/ray_cs.c linux/drivers/net/pcmcia/ray_cs.c
--- v2.3.26/linux/drivers/net/pcmcia/ray_cs.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/net/pcmcia/ray_cs.c	Wed Nov 10 08:40:04 1999
@@ -147,7 +147,6 @@
 static void start_net(u_long local);
 /* void start_net(ray_dev_t *local); */
 
-static int ray_cs_proc_read(char *buf, char **start, off_t off, int len, int spare);
 /* Create symbol table for registering with kernel in init_module */
 EXPORT_SYMBOL(ray_dev_ioctl);
 EXPORT_SYMBOL(ray_rx);
@@ -308,18 +307,6 @@
 
 static char rcsid[] = "Raylink/WebGear wireless LAN - Corey <Thomas corey@world.std.com>";
 
-#ifdef CONFIG_PROC_FS
-struct proc_dir_entry ray_cs_proc_entry = {
-    0,                         /* Dynamic inode # */
-    6,"ray_cs",                /* name length and name */
-    S_IFREG | S_IRUGO,         /* mode */
-    1, 0, 0,                   /* nlinks, owner, group */
-    0,                         /* size (unused) */
-    NULL,                      /* operations (default) */
-    &ray_cs_proc_read,         /* function to read data */
-    /* The end ?? */
-};
-#endif
 /*===========================================================================*/
 static void cs_error(client_handle_t handle, int func, int ret)
 {
@@ -2695,7 +2682,8 @@
     rc = register_pcmcia_driver(&dev_info, &ray_attach, &ray_detach);
     DEBUG(1, "raylink init_module register_pcmcia_driver returns 0x%x\n",rc);
 #ifdef CONFIG_PROC_FS    
-    proc_register(&proc_root, &ray_cs_proc_entry);
+    /* [proc-namespace][fixme] It shouldn't be under root, damnit! */
+    create_proc_info_entry("ray_cs", 0, &proc_root, ray_cs_proc_read);
 #endif    
     if (translate != 0) translate = 1;
     return 0;
@@ -2726,7 +2714,7 @@
         ray_detach(dev_list);
     }
 #ifdef CONFIG_PROC_FS    
-    proc_unregister(&proc_root, ray_cs_proc_entry.low_ino);
+    remove_proc_entry("ray_cs", &proc_root);
 #endif   
 } /* exit_ray_cs */
 
diff -u --recursive --new-file v2.3.26/linux/drivers/net/pcmcia/smc91c92_cs.c linux/drivers/net/pcmcia/smc91c92_cs.c
--- v2.3.26/linux/drivers/net/pcmcia/smc91c92_cs.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/net/pcmcia/smc91c92_cs.c	Thu Nov 11 16:03:37 1999
@@ -6,13 +6,13 @@
     Megahertz, Motorola, Ositech, and Psion Dacom ethernet/modem
     multifunction cards.
 
-    Copyright (C) 1999 David A. Hinds -- dhinds@hyper.stanford.edu
+    Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org
 
-    smc91c92_cs.c 1.79 1999/10/19 00:38:29
+    smc91c92_cs.c 1.82 1999/11/08 20:46:17
     
     This driver contains code written by Donald Becker
     (becker@cesdis.gsfc.nasa.gov), Rowan Hughes (x-csrdh@jcu.edu.au),
-    David Hinds (dhinds@hyper.stanford.edu), and Erik Stahlman
+    David Hinds (dhinds@pcmcia.sourceforge.org), and Erik Stahlman
     (erik@vt.edu).  Donald wrote the SMC 91c92 code using parts of
     Erik's SMC 91c94 driver.  Rowan wrote a similar driver, and I've
     incorporated some parts of his driver here.  I (Dave) wrote most
@@ -717,6 +717,7 @@
 	if (i == CS_SUCCESS) {
 	    link->conf.ConfigIndex = cf->index;
 	    link->io.BasePort1 = cf->io.win[0].base;
+	    link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
 	    i = CardServices(RequestIO, link->handle, &link->io);
 	    if (i == CS_SUCCESS) break;
 	}
@@ -784,6 +785,7 @@
     link->io.NumPorts1 = 64;
     link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
     link->io.NumPorts2 = 8;
+    link->io.IOAddrLines = 16;
     
     /* Enable Hard Decode, LAN, Modem */
     link->conf.ConfigIndex = 0x23;
@@ -1799,15 +1801,17 @@
 
 static int s9k_config(struct net_device *dev, struct ifmap *map)
 {
+    struct smc_private *lp = dev->priv;
     if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
-	if (map->port <= 2) {
-	    dev->if_port = map->port;
-	    printk(KERN_INFO "%s: switched to %s port\n",
-		   dev->name, if_names[dev->if_port]);
-	} else
+	if (lp->cfg & CFG_MII_SELECT)
+	    return -EOPNOTSUPP;
+	else if (map->port > 2)
 	    return -EINVAL;
+	dev->if_port = map->port;
+	printk(KERN_INFO "%s: switched to %s port\n",
+	       dev->name, if_names[dev->if_port]);
+	smc_reset(dev);
     }
-    smc_reset(dev);
     return 0;
 }
 
diff -u --recursive --new-file v2.3.26/linux/drivers/net/pcmcia/tulip_cb.c linux/drivers/net/pcmcia/tulip_cb.c
--- v2.3.26/linux/drivers/net/pcmcia/tulip_cb.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/pcmcia/tulip_cb.c	Thu Nov 11 16:03:37 1999
@@ -0,0 +1,3383 @@
+/* tulip.c: A DEC 21040-family ethernet driver for Linux. */
+/*
+	Written/copyright 1994-1999 by Donald Becker.
+
+	This software may be used and distributed according to the terms
+	of the GNU Public License, incorporated herein by reference.
+
+	This driver is for the Digital "Tulip" Ethernet adapter interface.
+	It should work with most DEC 21*4*-based chips/ethercards, as well as
+	with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and ASIX.
+
+	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+	Center of Excellence in Space Data and Information Sciences
+	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+
+	Support and updates available at
+	http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html
+*/
+
+#define SMP_CHECK
+static const char version[] = "tulip.c:v0.91 4/14/99 becker@cesdis.gsfc.nasa.gov (modified by danilo@cs.uni-magdeburg.de for XIRCOM CBE, fixed by Doug Ledford)\n";
+
+/* A few user-configurable values. */
+
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+static int max_interrupt_work = 25;
+
+#define MAX_UNITS 8
+/* Used to pass the full-duplex flag, etc. */
+static int full_duplex[MAX_UNITS] = {0, };
+static int options[MAX_UNITS] = {0, };
+static int mtu[MAX_UNITS] = {0, };			/* Jumbo MTU for interfaces. */
+
+/*  The possible media types that can be set in options[] are: */
+static const char * const medianame[] = {
+	"10baseT", "10base2", "AUI", "100baseTx",
+	"10baseT-FD", "100baseTx-FD", "100baseT4", "100baseFx",
+	"100baseFx-FD", "MII 10baseT", "MII 10baseT-FD", "MII",
+	"10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FD", "MII 100baseT4",
+};
+
+/* Set if the PCI BIOS detects the chips on a multiport board backwards. */
+#ifdef REVERSE_PROBE_ORDER
+static int reverse_probe = 1;
+#else
+static int reverse_probe = 0;
+#endif
+
+/* Keep the ring sizes a power of two for efficiency.
+   Making the Tx ring too large decreases the effectiveness of channel
+   bonding and packet priority.
+   There are no ill effects from too-large receive rings. */
+#define TX_RING_SIZE	16
+#define RX_RING_SIZE	32
+
+/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
+#ifdef __alpha__
+static int rx_copybreak = 1518;
+#else
+static int rx_copybreak = 100;
+#endif
+
+/*
+  Set the bus performance register.
+	Typical: Set 16 longword cache alignment, no burst limit.
+	Cache alignment bits 15:14	     Burst length 13:8
+		0000	No alignment  0x00000000 unlimited		0800 8 longwords
+		4000	8  longwords		0100 1 longword		1000 16 longwords
+		8000	16 longwords		0200 2 longwords	2000 32 longwords
+		C000	32  longwords		0400 4 longwords
+	Warning: many older 486 systems are broken and require setting 0x00A04800
+	   8 longword cache alignment, 8 longword burst.
+	ToDo: Non-Intel setting could be better.
+*/
+
+#if defined(__alpha__)
+static int csr0 = 0x01A00000 | 0xE000;
+#elif defined(__powerpc__)
+static int csr0 = 0x01B00000 | 0x8000;
+#elif defined(__sparc__)
+static int csr0 = 0x01B00080 | 0x8000;
+#elif defined(__i386__)
+static int csr0 = 0x01A00000 | 0x8000;
+#else
+#warning Processor architecture undefined!
+static int csr0 = 0x00A00000 | 0x4800;
+#endif
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  (4*HZ)
+#define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
+/* This is a mysterious value that can be written to CSR11 in the 21040 (only)
+   to support a pre-NWay full-duplex signaling mechanism using short frames.
+   No one knows what it should be, but if left at its default value some
+   10base2(!) packets trigger a full-duplex-request interrupt. */
+#define FULL_DUPLEX_MAGIC	0x6969
+
+#if !defined(__OPTIMIZE__)  ||  !defined(__KERNEL__)
+#warning  You must compile this file with the correct options!
+#warning  See the last lines of the source file.
+#error You must compile this driver with "-O".
+#endif
+
+#include <linux/config.h>
+#include <linux/version.h>
+#ifdef MODULE
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#include <linux/module.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <asm/processor.h>		/* Processor type for cache alignment. */
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/unaligned.h>
+
+/* Kernel compatibility defines, some common to David Hinds' PCMCIA package.
+   This is only in the support-all-kernels source code. */
+
+#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
+MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
+MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver");
+MODULE_PARM(debug, "i");
+MODULE_PARM(max_interrupt_work, "i");
+MODULE_PARM(reverse_probe, "i");
+MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(csr0, "i");
+MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
+#endif
+
+#define RUN_AT(x) (jiffies + (x))
+
+#define NETSTATS_VER2
+#define PCI_SUPPORT_VER3
+#define dev_free_skb(skb) dev_kfree_skb(skb);
+
+#define tulip_debug debug
+#ifdef TULIP_DEBUG
+static int tulip_debug = TULIP_DEBUG;
+#else
+static int tulip_debug = 1;
+#endif
+
+/*
+				Theory of Operation
+
+I. Board Compatibility
+
+This device driver is designed for the DECchip "Tulip", Digital's
+single-chip ethernet controllers for PCI.  Supported members of the family
+are the 21040, 21041, 21140, 21140A, 21142, and 21143.  Similar work-alike
+chips from Lite-On, Macronics, ASIX, Compex and other listed below are also
+supported. 
+
+These chips are used on at least 140 unique PCI board designs.  The great
+number of chips and board designs supported is the reason for the
+driver size and complexity.  Almost of the increasing complexity is in the
+board configuration and media selection code.  There is very little
+increasing in the operational critical path length.
+
+II. Board-specific settings
+
+PCI bus devices are configured by the system at boot time, so no jumpers
+need to be set on the board.  The system BIOS preferably should assign the
+PCI INTA signal to an otherwise unused system IRQ line.
+
+Some boards have EEPROMs tables with default media entry.  The factory default
+is usually "autoselect".  This should only be overridden when using
+transceiver connections without link beat e.g. 10base2 or AUI, or (rarely!)
+for forcing full-duplex when used with old link partners that do not do
+autonegotiation. 
+
+III. Driver operation
+
+IIIa. Ring buffers
+
+The Tulip can use either ring buffers or lists of Tx and Rx descriptors.
+This driver uses statically allocated rings of Rx and Tx descriptors, set at
+compile time by RX/TX_RING_SIZE.  This version of the driver allocates skbuffs
+for the Rx ring buffers at open() time and passes the skb->data field to the
+Tulip as receive data buffers.  When an incoming frame is less than
+RX_COPYBREAK bytes long, a fresh skbuff is allocated and the frame is
+copied to the new skbuff.  When the incoming frame is larger, the skbuff is
+passed directly up the protocol stack and replaced by a newly allocated
+skbuff.
+
+The RX_COPYBREAK value is chosen to trade-off the memory wasted by
+using a full-sized skbuff for small frames vs. the copying costs of larger
+frames.  For small frames the copying cost is negligible (esp. considering
+that we are pre-loading the cache with immediately useful header
+information).  For large frames the copying cost is non-trivial, and the
+larger copy might flush the cache of useful data.  A subtle aspect of this
+choice is that the Tulip only receives into longword aligned buffers, thus
+the IP header at offset 14 isn't longword aligned for further processing.
+Copied frames are put into the new skbuff at an offset of "+2", thus copying
+has the beneficial effect of aligning the IP header and preloading the
+cache.
+
+IIIC. Synchronization
+The driver runs as two independent, single-threaded flows of control.  One
+is the send-packet routine, which enforces single-threaded use by the
+dev->tbusy flag.  The other thread is the interrupt handler, which is single
+threaded by the hardware and other software.
+
+The send packet thread has partial control over the Tx ring and 'dev->tbusy'
+flag.  It sets the tbusy flag whenever it's queuing a Tx packet. If the next
+queue slot is empty, it clears the tbusy flag when finished otherwise it sets
+the 'tp->tx_full' flag.
+
+The interrupt handler has exclusive control over the Rx ring and records stats
+from the Tx ring.  (The Tx-done interrupt can't be selectively turned off, so
+we can't avoid the interrupt overhead by having the Tx routine reap the Tx
+stats.)	 After reaping the stats, it marks the queue entry as empty by setting
+the 'base' to zero.	 Iff the 'tp->tx_full' flag is set, it clears both the
+tx_full and tbusy flags.
+
+IV. Notes
+
+Thanks to Duke Kamstra of SMC for long ago providing an EtherPower board.
+Greg LaPolla at Linksys provided PNIC and other Linksys boards.
+Znyx provided a four-port card for testing.
+
+IVb. References
+
+http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
+http://www.digital.com  (search for current 21*4* datasheets and "21X4 SROM")
+http://www.national.com/pf/DP/DP83840A.html
+http://www.asix.com.tw/pmac.htm
+http://www.admtek.com.tw/
+
+IVc. Errata
+
+The old DEC databooks were light on details.
+The 21040 databook claims that CSR13, CSR14, and CSR15 should each be the last
+register of the set CSR12-15 written.  Hmmm, now how is that possible?
+
+The DEC SROM format is very badly designed not precisely defined, leading to
+part of the media selection junkheap below.  Some boards do not have EEPROM
+media tables and need to be patched up.  Worse, other boards use the DEC
+design kit media table when it isn't correct for their board.
+
+We cannot use MII interrupts because there is no defined GPIO pin to attach
+them.  The MII transceiver status is polled using an kernel timer.
+
+*/
+
+static struct net_device *
+tulip_probe1(int pci_bus, int pci_devfn, struct net_device *dev, long ioaddr,
+			 int irq, int chip_idx, int board_idx);
+
+/* This table drives the PCI probe routines.  It's mostly boilerplate in all
+   of the drivers, and will likely be provided by some future kernel.
+   Note the matching code -- the first table entry matchs all 56** cards but
+   second only the 1234 card.
+*/
+enum pci_flags_bit {
+	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
+	PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
+};
+#define PCI_ADDR0_IO (PCI_USES_IO|PCI_ADDR0)
+
+struct pci_id_info {
+	const char *name;
+	u16	vendor_id, device_id, device_id_mask, flags;
+	int io_size, min_latency;
+	struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev,
+							 long ioaddr, int irq, int chip_idx, int fnd_cnt);
+};
+#ifndef CARDBUS
+static struct pci_id_info pci_tbl[] = {
+  { "Digital DC21040 Tulip",
+	0x1011, 0x0002, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 },
+  { "Digital DC21041 Tulip",
+	0x1011, 0x0014, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 },
+  { "Digital DS21140 Tulip",
+	0x1011, 0x0009, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 },
+  { "Digital DS21143 Tulip",
+	0x1011, 0x0019, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 },
+  { "Lite-On 82c168 PNIC",
+	0x11AD, 0x0002, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 },
+  { "Macronix 98713 PMAC",
+	0x10d9, 0x0512, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 },
+  { "Macronix 98715 PMAC",
+	0x10d9, 0x0531, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 },
+  { "Macronix 98725 PMAC",
+	0x10d9, 0x0531, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 },
+  { "ASIX AX88140",
+	0x125B, 0x1400, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 },
+  { "Lite-On LC82C115 PNIC-II",
+	0x11AD, 0xc115, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 },
+  { "ADMtek AN981 Comet",
+	0x1317, 0x0981, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 },
+  { "Compex RL100-TX",
+	0x11F6, 0x9881, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 },
+  {0},
+};
+#endif /* !CARD_BUS */
+
+/* This table use during operation for capabilities and media timer. */
+
+static void tulip_timer(unsigned long data);
+static void t21142_timer(unsigned long data);
+static void mxic_timer(unsigned long data);
+static void pnic_timer(unsigned long data);
+static void comet_timer(unsigned long data);
+
+enum tbl_flag {
+	HAS_MII=1, HAS_MEDIA_TABLE=2, CSR12_IN_SROM=4, ALWAYS_CHECK_MII=8,
+	HAS_ACPI=0x10, MC_HASH_ONLY=0x20, /* Hash-only multicast filter. */
+	HAS_NWAY143=0x40,			/* Uses 21143-like internal NWay. */
+};
+static struct tulip_chip_table {
+	char *chip_name;
+	int io_size;
+	int valid_intrs;			/* CSR7 interrupt enable settings */
+	int flags;
+	void (*media_timer)(unsigned long data);
+} tulip_tbl[] = {
+  { "Digital DC21040 Tulip", 128, 0x0001ebef, 0, tulip_timer },
+  { "Digital DC21041 Tulip", 128, 0x0001ebef, HAS_MEDIA_TABLE, tulip_timer },
+  { "Digital DS21140 Tulip", 128, 0x0001ebef,
+	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, tulip_timer },
+  { "Digital DS21143 Tulip", 128, 0x0801fbff,
+	HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI | HAS_NWAY143, t21142_timer },
+  { "Lite-On 82c168 PNIC", 256, 0x0001ebef,
+	HAS_MII, pnic_timer },
+  { "Macronix 98713 PMAC", 128, 0x0001ebef,
+	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer },
+  { "Macronix 98715 PMAC", 256, 0x0001ebef,
+	HAS_MEDIA_TABLE, mxic_timer },
+  { "Macronix 98725 PMAC", 256, 0x0001ebef,
+	HAS_MEDIA_TABLE, mxic_timer },
+  { "ASIX AX88140", 128, 0x0001fbff,
+	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY, tulip_timer },
+  { "Lite-On PNIC-II", 256, 0x0001ebef,
+	HAS_MII | HAS_NWAY143, pnic_timer },
+  { "ADMtek Comet", 256, 0x0001abef,
+	MC_HASH_ONLY, comet_timer },
+  { "Compex 9881 PMAC", 128, 0x0001ebef,
+	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer },
+  { "Xircom Cardbus Adapter (DEC 21143 compatible mode)", 128, 0x0801fbff,
+       HAS_MII | HAS_ACPI, tulip_timer }, 
+  {0},
+};
+/* This matches the table above.  Note 21142 == 21143. */
+enum chips {
+	DC21040=0, DC21041=1, DC21140=2, DC21142=3, DC21143=3,
+	LC82C168, MX98713, MX98715, MX98725, AX88140, PNIC2, COMET, COMPEX9881,
+	X3201_3,
+};
+
+/* A full-duplex map for media types. */
+enum MediaIs {
+	MediaIsFD = 1, MediaAlwaysFD=2, MediaIsMII=4, MediaIsFx=8,
+	MediaIs100=16};
+static const char media_cap[] =
+{0,0,0,16,  3,19,16,24,  27,4,7,5, 0,20,23,20 };
+static u8 t21040_csr13[] = {2,0x0C,8,4,  4,0,0,0, 0,0,0,0, 4,0,0,0};
+/* 21041 transceiver register settings: 10-T, 10-2, AUI, 10-T, 10T-FD*/
+static u16 t21041_csr13[] = { 0xEF05, 0xEF09, 0xEF09, 0xEF01, 0xEF09, };
+static u16 t21041_csr14[] = { 0x7F3F, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, };
+static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
+
+static u16 t21142_csr13[] = { 0x0001, 0x0009, 0x0009, 0x0000, 0x0001, };
+static u16 t21142_csr14[] = { 0xFFFF, 0x0705, 0x0705, 0x0000, 0x7F3D, };
+static u16 t21142_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
+
+/* Offsets to the Command and Status Registers, "CSRs".  All accesses
+   must be longword instructions and quadword aligned. */
+enum tulip_offsets {
+	CSR0=0,    CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28,
+	CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58,
+	CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78 };
+
+/* The bits in the CSR5 status registers, mostly interrupt sources. */
+enum status_bits {
+	TimerInt=0x800, TPLnkFail=0x1000, TPLnkPass=0x10,
+	NormalIntr=0x10000, AbnormalIntr=0x8000,
+	RxJabber=0x200, RxDied=0x100, RxNoBuf=0x80, RxIntr=0x40,
+	TxFIFOUnderflow=0x20, TxJabber=0x08, TxNoBuf=0x04, TxDied=0x02, TxIntr=0x01,
+};
+
+/* The Tulip Rx and Tx buffer descriptors. */
+struct tulip_rx_desc {
+	s32 status;
+	s32 length;
+	u32 buffer1, buffer2;
+};
+
+struct tulip_tx_desc {
+	s32 status;
+	s32 length;
+	u32 buffer1, buffer2;				/* We use only buffer 1.  */
+};
+
+enum desc_status_bits {
+	DescOwned=0x80000000, RxDescFatalErr=0x8000, RxWholePkt=0x0300,
+};
+
+/* Ring-wrap flag in length field, use for last ring entry.
+	0x01000000 means chain on buffer2 address,
+	0x02000000 means use the ring start address in CSR2/3.
+   Note: Some work-alike chips do not function correctly in chained mode.
+   The ASIX chip works only in chained mode.
+   Thus we indicates ring mode, but always write the 'next' field for
+   chained mode as well.
+*/
+#define DESC_RING_WRAP 0x02000000
+
+#ifdef CARDBUS
+#define EEPROM_ADDRLEN (chip_rev == 65 ? 8 : 6)
+#else
+#define EEPROM_ADDRLEN 6
+#endif
+#define EEPROM_SIZE 128 	/* 2 << EEPROM_ADDRLEN */
+
+struct medialeaf {
+	u8 type;
+	u8 media;
+	unsigned char *leafdata;
+};
+
+struct mediatable {
+	u16 defaultmedia;
+	u8 leafcount, csr12dir;				/* General purpose pin directions. */
+	unsigned has_mii:1, has_nonmii:1, has_reset:6;
+	u32 csr15dir, csr15val;				/* 21143 NWay setting. */
+	struct medialeaf mleaf[0];
+};
+
+struct mediainfo {
+	struct mediainfo *next;
+	int info_type;
+	int index;
+	unsigned char *info;
+};
+
+struct tulip_private {
+	char devname[8];			/* Used only for kernel debugging. */
+	const char *product_name;
+	struct net_device *next_module;
+	struct tulip_rx_desc rx_ring[RX_RING_SIZE];
+	struct tulip_tx_desc tx_ring[TX_RING_SIZE];
+	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
+	struct sk_buff* tx_skbuff[TX_RING_SIZE];
+#ifdef CARDBUS
+	/* The X3201-3 requires double word aligned tx bufs */
+	struct sk_buff* tx_aligned_skbuff[TX_RING_SIZE];
+#endif
+	/* The addresses of receive-in-place skbuffs. */
+	struct sk_buff* rx_skbuff[RX_RING_SIZE];
+	char *rx_buffs;				/* Address of temporary Rx buffers. */
+	u8 setup_buf[96*sizeof(u16) + 7];
+	u16 *setup_frame;		/* Pseudo-Tx frame to init address table. */
+	int chip_id;
+	int revision;
+	struct net_device_stats stats;
+	struct timer_list timer;	/* Media selection timer. */
+	int interrupt;				/* In-interrupt flag. */
+	unsigned int cur_rx, cur_tx;		/* The next free ring entry */
+	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
+	unsigned int tx_full:1;				/* The Tx queue is full. */
+	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
+	unsigned int full_duplex_lock:1;
+	unsigned int fake_addr:1;			/* Multiport board faked address. */
+	unsigned int default_port:4;		/* Last dev->if_port value. */
+	unsigned int media2:4;				/* Secondary monitored media port. */
+	unsigned int medialock:1;			/* Don't sense media type. */
+	unsigned int mediasense:1;			/* Media sensing in progress. */
+	unsigned int nway:1, nwayset:1;		/* 21143 internal NWay. */
+	unsigned int open:1;
+	unsigned int csr0;					/* CSR0 setting. */
+	unsigned int csr6;					/* Current CSR6 control settings. */
+	unsigned char eeprom[EEPROM_SIZE];	/* Serial EEPROM contents. */
+	u16 to_advertise;					/* NWay capabilities advertised.  */
+	u16 lpar;							/* 21143 Link partner ability. */
+	u16 advertising[4];
+	signed char phys[4], mii_cnt;		/* MII device addresses. */
+	struct mediatable *mtable;
+	int cur_index;						/* Current media index. */
+	int saved_if_port;
+	unsigned char pci_bus, pci_devfn;
+	int pad0, pad1;						/* Used for 8-byte alignment */
+};
+
+static void parse_eeprom(struct net_device *dev);
+static int read_eeprom(long ioaddr, int location, int addr_len);
+static int mdio_read(struct net_device *dev, int phy_id, int location);
+static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
+static void select_media(struct net_device *dev, int startup);
+static void tulip_up(struct net_device *dev);
+static void tulip_down(struct net_device *dev);
+static int tulip_open(struct net_device *dev);
+static void tulip_timer(unsigned long data);
+static void t21142_start_nway(struct net_device *dev);
+static void tulip_tx_timeout(struct net_device *dev);
+static void tulip_init_ring(struct net_device *dev);
+static int tulip_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int tulip_rx(struct net_device *dev);
+static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static int tulip_close(struct net_device *dev);
+static struct net_device_stats *tulip_get_stats(struct net_device *dev);
+#ifdef HAVE_PRIVATE_IOCTL
+static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+#endif
+static void set_rx_mode(struct net_device *dev);
+
+/* The Xircom cards are picky about when certain bits in CSR6 can be
+   manipulated.  Keith Owens <kaos@ocs.com.au>. */
+
+static void outl_CSR6 (u32 newcsr6, long ioaddr, int chip_idx)
+{
+	const int strict_bits = 0x0060e202;
+    int csr5, csr5_22_20, csr5_19_17, currcsr6, attempts = 200;
+    long flags;
+    save_flags(flags);
+    cli();
+    if (chip_idx != X3201_3) {
+		outl(newcsr6, ioaddr + CSR6);
+		restore_flags(flags);
+		return;
+    }
+    newcsr6 &= 0x726cfeca; /* mask out the reserved CSR6 bits that always */
+			   /* read 0 on the Xircom cards */
+    newcsr6 |= 0x320c0000; /* or in the reserved bits that always read 1 */
+    currcsr6 = inl(ioaddr + CSR6);
+    if (((newcsr6 & strict_bits) == (currcsr6 & strict_bits)) ||
+	((currcsr6 & ~0x2002) == 0)) {
+		outl(newcsr6, ioaddr + CSR6);	/* safe */
+		restore_flags(flags);
+		return;
+    }
+    /* make sure the transmitter and receiver are stopped first */
+    currcsr6 &= ~0x2002;
+    while (1) {
+		csr5 = inl(ioaddr + CSR5);
+		if (csr5 == 0xffffffff)
+			break;  /* cannot read csr5, card removed? */
+		csr5_22_20 = csr5 & 0x700000;
+		csr5_19_17 = csr5 & 0x0e0000;
+		if ((csr5_22_20 == 0 || csr5_22_20 == 0x600000) &&
+			(csr5_19_17 == 0 || csr5_19_17 == 0x80000 || csr5_19_17 == 0xc0000))
+			break;  /* both are stopped or suspended */
+		if (!--attempts) {
+			printk(KERN_INFO "tulip.c: outl_CSR6 too many attempts,"
+				   "csr5=0x%08x\n", csr5);
+			outl(newcsr6, ioaddr + CSR6);  /* unsafe but do it anyway */
+			restore_flags(flags);
+			return;
+		}
+		outl(currcsr6, ioaddr + CSR6);
+		udelay(1);
+    }
+    /* now it is safe to change csr6 */
+    outl(newcsr6, ioaddr + CSR6);
+    restore_flags(flags);
+}
+
+/* A list of all installed Tulip devices. */
+static struct net_device *root_tulip_dev = NULL;
+
+#ifndef CARDBUS
+int tulip_probe(struct net_device *dev)
+{
+	int cards_found = 0;
+	int pci_index = 0;
+	unsigned char pci_bus, pci_device_fn;
+
+	if ( ! pcibios_present())
+		return -ENODEV;
+
+	for (;pci_index < 0xff; pci_index++) {
+		u16 vendor, device, pci_command, new_command;
+		int chip_idx;
+		int irq;
+		long ioaddr;
+
+		if (pcibios_find_class
+			(PCI_CLASS_NETWORK_ETHERNET << 8,
+			 reverse_probe ? 0xfe - pci_index : pci_index,
+			 &pci_bus, &pci_device_fn) != PCIBIOS_SUCCESSFUL) {
+			if (reverse_probe)
+				continue;
+			else
+				break;
+		}
+		pcibios_read_config_word(pci_bus, pci_device_fn,
+								 PCI_VENDOR_ID, &vendor);
+		pcibios_read_config_word(pci_bus, pci_device_fn,
+								 PCI_DEVICE_ID, &device);
+
+		for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
+			if (vendor == pci_tbl[chip_idx].vendor_id
+				&& (device & pci_tbl[chip_idx].device_id_mask) ==
+				pci_tbl[chip_idx].device_id)
+				break;
+		if (pci_tbl[chip_idx].vendor_id == 0)
+			continue;
+
+		{
+#if defined(PCI_SUPPORT_VER2)
+			struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
+			ioaddr = pdev->base_address[0] & ~3;
+			irq = pdev->irq;
+#elif defined(PCI_SUPPORT_VER3)
+			struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
+			ioaddr = pdev->resource[0].start;
+			irq = pdev->irq;
+#else
+			u32 pci_ioaddr;
+			u8 pci_irq_line;
+			pcibios_read_config_dword(pci_bus, pci_device_fn,
+									  PCI_BASE_ADDRESS_0, &pci_ioaddr);
+			pcibios_read_config_byte(pci_bus, pci_device_fn,
+									 PCI_INTERRUPT_LINE, &pci_irq_line);
+			ioaddr = pci_ioaddr & ~3;
+			irq = pci_irq_line;
+#endif
+		}
+
+		if (debug > 2)
+			printk(KERN_INFO "Found %s at PCI I/O address %#lx.\n",
+				   pci_tbl[chip_idx].name, ioaddr);
+
+		pcibios_read_config_word(pci_bus, pci_device_fn,
+								 PCI_COMMAND, &pci_command);
+		new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
+		if (pci_command != new_command) {
+			printk(KERN_INFO "  The PCI BIOS has not enabled the"
+				   " device at %d/%d!  Updating PCI command %4.4x->%4.4x.\n",
+				   pci_bus, pci_device_fn, pci_command, new_command);
+			pcibios_write_config_word(pci_bus, pci_device_fn,
+									  PCI_COMMAND, new_command);
+		}
+
+		dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, ioaddr,
+									   irq, chip_idx, cards_found);
+
+		/* Get and check the bus-master and latency values. */
+		if (dev) {
+			u8 pci_latency;
+			pcibios_read_config_byte(pci_bus, pci_device_fn,
+									 PCI_LATENCY_TIMER, &pci_latency);
+			if (pci_latency < 10) {
+				printk(KERN_INFO "  PCI latency timer (CFLT) is "
+					   "unreasonably low at %d.  Setting to 64 clocks.\n",
+					   pci_latency);
+				pcibios_write_config_byte(pci_bus, pci_device_fn,
+										  PCI_LATENCY_TIMER, 64);
+			}
+		}
+		dev = 0;
+		cards_found++;
+	}
+
+	return cards_found ? 0 : -ENODEV;
+}
+#endif  /* not CARDBUS */
+
+static struct net_device *tulip_probe1(int pci_bus, int pci_devfn,
+								   struct net_device *dev, long ioaddr, int irq,
+								   int chip_idx, int board_idx)
+{
+	static int did_version = 0;			/* Already printed version info. */
+	struct tulip_private *tp;
+	/* See note below on the multiport cards. */
+	static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'};
+	static int last_irq = 0;
+	static int multiport_cnt = 0;		/* For four-port boards w/one EEPROM */
+	u8 chip_rev;
+	int i;
+	unsigned short sum;
+
+	if (tulip_debug > 0  &&  did_version++ == 0)
+		printk(KERN_INFO "%s", version);
+
+	dev = init_etherdev(dev, 0);
+
+	pcibios_read_config_byte(pci_bus, pci_devfn, PCI_REVISION_ID, &chip_rev);
+	/* Bring the 21143 out of sleep mode.
+	   Caution: Snooze mode does not work with some boards! */
+	if (tulip_tbl[chip_idx].flags & HAS_ACPI)
+		pcibios_write_config_dword(pci_bus, pci_devfn, 0x40, 0x00000000);
+
+	printk(KERN_INFO "%s: %s rev %d at %#3lx,",
+		   dev->name, tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr);
+
+	/* Stop the chip's Tx and Rx processes. */
+	outl_CSR6(inl(ioaddr + CSR6) & ~0x2002, ioaddr, chip_idx);
+	/* Clear the missed-packet counter. */
+	(volatile int)inl(ioaddr + CSR8);
+
+	if (chip_idx == DC21041) {
+		if (inl(ioaddr + CSR9) & 0x8000) {
+			printk(" 21040 compatible mode,");
+			chip_idx = DC21040;
+		} else {
+			printk(" 21041 mode,");
+		}
+	}
+
+	/* The station address ROM is read byte serially.  The register must
+	   be polled, waiting for the value to be read bit serially from the
+	   EEPROM.
+	   */
+	sum = 0;
+	if (chip_idx == DC21040) {
+		outl(0, ioaddr + CSR9);		/* Reset the pointer with a dummy write. */
+		for (i = 0; i < 6; i++) {
+			int value, boguscnt = 100000;
+			do
+				value = inl(ioaddr + CSR9);
+			while (value < 0  && --boguscnt > 0);
+			dev->dev_addr[i] = value;
+			sum += value & 0xff;
+		}
+	} else if (chip_idx == LC82C168) {
+		for (i = 0; i < 3; i++) {
+			int value, boguscnt = 100000;
+			outl(0x600 | i, ioaddr + 0x98);
+			do
+				value = inl(ioaddr + CSR9);
+			while (value < 0  && --boguscnt > 0);
+			put_unaligned(le16_to_cpu(value), ((u16*)dev->dev_addr) + i);
+			sum += value & 0xffff;
+		}
+	} else if (chip_idx == COMET) {
+		/* No need to read the EEPROM. */
+		put_unaligned(inl(ioaddr + 0xA4), (u32 *)dev->dev_addr);
+		put_unaligned(inl(ioaddr + 0xA8), (u16 *)(dev->dev_addr + 4));
+		for (i = 0; i < 6; i ++)
+			sum += dev->dev_addr[i];
+	} else if (chip_idx == X3201_3) {
+		/* Xircom has its address stored in the CIS
+		 * we access it through the boot rom interface for now
+		 * this might not work, as the CIS is not parsed but I
+		 * (danilo) use the offset I found on my card's CIS !!!
+		 * 
+		 * Doug Ledford: I changed this routine around so that it
+		 * walks the CIS memory space, parsing the config items, and
+		 * finds the proper lan_node_id tuple and uses the data
+		 * stored there.
+		 */
+		unsigned char j, tuple, link, data_id, data_count;
+		outl(1<<12, ioaddr + CSR9); /* enable boot rom access */
+		for (i = 0x100; i < 0x1f7; i += link+2) {
+			outl(i, ioaddr + CSR10);
+			tuple = inl(ioaddr + CSR9) & 0xff;
+			outl(i + 1, ioaddr + CSR10);
+			link = inl(ioaddr + CSR9) & 0xff;
+			outl(i + 2, ioaddr + CSR10);
+			data_id = inl(ioaddr + CSR9) & 0xff;
+			outl(i + 3, ioaddr + CSR10);
+			data_count = inl(ioaddr + CSR9) & 0xff;
+			if ( (tuple == 0x22) &&
+				 (data_id == 0x04) && (data_count == 0x06) ) {
+				/*
+				 * This is it.  We have the data we want.
+				 */
+				for (j = 0; j < 6; j++) {
+					outl(i + j + 4, ioaddr + CSR10);
+					dev->dev_addr[j] = inl(ioaddr + CSR9) & 0xff;
+				}
+				break;
+			} else if (link == 0) {
+				break;
+			}
+		}
+		sum = 1; // to make check below fail!
+	} else {	/* Must be a new chip, with a serial EEPROM interface. */
+		/* We read the whole EEPROM, and sort it out later.  DEC has a
+		   specification _Digital Semiconductor 21X4 Serial ROM Format_
+		   but early vendor boards just put the address in the first six
+		   EEPROM locations. */
+		unsigned char ee_data[EEPROM_SIZE];
+		int sa_offset = 0;
+
+		for (i = 0; i < sizeof(ee_data)/2; i++)
+			((u16 *)ee_data)[i] =
+				le16_to_cpu(read_eeprom(ioaddr, i, EEPROM_ADDRLEN));
+
+		/* Detect the simple EEPROM format by the duplicated station addr. */
+		for (i = 0; i < 8; i ++)
+			if (ee_data[i] != ee_data[16+i])
+				sa_offset = 20;
+		if (ee_data[0] == 0xff  &&  ee_data[1] == 0xff &&  ee_data[2] == 0) {
+			sa_offset = 2;		/* Grrr, damn Matrox boards. */
+			multiport_cnt = 4;
+		}
+		for (i = 0; i < 6; i ++) {
+			dev->dev_addr[i] = ee_data[i + sa_offset];
+			sum += ee_data[i + sa_offset];
+		}
+	}
+	/* Lite-On boards have the address byte-swapped. */
+	if ((dev->dev_addr[0] == 0xA0  ||  dev->dev_addr[0] == 0xC0)
+		&&  dev->dev_addr[1] == 0x00)
+		for (i = 0; i < 6; i+=2) {
+			char tmp = dev->dev_addr[i];
+			dev->dev_addr[i] = dev->dev_addr[i+1];
+			dev->dev_addr[i+1] = tmp;
+		}
+	/* On the Zynx 315 Etherarray and other multiport boards only the
+	   first Tulip has an EEPROM.
+	   The addresses of the subsequent ports are derived from the first.
+	   Many PCI BIOSes also incorrectly report the IRQ line, so we correct
+	   that here as well. */
+	if (sum == 0  || sum == 6*0xff) {
+		printk(" EEPROM not present,");
+		for (i = 0; i < 5; i++)
+			dev->dev_addr[i] = last_phys_addr[i];
+		dev->dev_addr[i] = last_phys_addr[i] + 1;
+#if defined(__i386__)		/* Patch up x86 BIOS bug. */
+		if (last_irq)
+			irq = last_irq;
+#endif
+	}
+
+	for (i = 0; i < 6; i++)
+		printk("%c%2.2X", i ? ':' : ' ', last_phys_addr[i] = dev->dev_addr[i]);
+	printk(", IRQ %d.\n", irq);
+	last_irq = irq;
+
+	/* We do a request_region() only to register /proc/ioports info. */
+	/* Note that proper size is tulip_tbl[chip_idx].chip_name, but... */
+	request_region(ioaddr, tulip_tbl[chip_idx].io_size, dev->name);
+
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+
+	/* Make certain the data structures are quadword aligned. */
+	tp = (void *)(((long)kmalloc(sizeof(*tp), GFP_KERNEL | GFP_DMA) + 7) & ~7);
+	memset(tp, 0, sizeof(*tp));
+	dev->priv = tp;
+
+	tp->next_module = root_tulip_dev;
+	root_tulip_dev = dev;
+
+	tp->pci_bus = pci_bus;
+	tp->pci_devfn = pci_devfn;
+	tp->chip_id = chip_idx;
+	tp->revision = chip_rev;
+	tp->csr0 = csr0;
+	tp->setup_frame = (u16 *)(((unsigned long)tp->setup_buf + 7) & ~7);
+
+	/* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles.
+	   And the ASIX must have a burst limit or horrible things happen. */
+	if ( (chip_idx == DC21143  &&  chip_rev == 65) ||
+	     (chip_idx == X3201_3) )
+		tp->csr0 &= ~0x01000000;
+	else if (chip_idx == AX88140)
+		tp->csr0 |= 0x2000;
+
+#ifdef TULIP_FULL_DUPLEX
+	tp->full_duplex = 1;
+	tp->full_duplex_lock = 1;
+#endif
+#ifdef TULIP_DEFAULT_MEDIA
+	tp->default_port = TULIP_DEFAULT_MEDIA;
+#endif
+#ifdef TULIP_NO_MEDIA_SWITCH
+	tp->medialock = 1;
+#endif
+
+	/* The lower four bits are the media type. */
+	if (board_idx >= 0  &&  board_idx < MAX_UNITS) {
+		tp->default_port = options[board_idx] & 15;
+		if ((options[board_idx] & 0x90) || full_duplex[board_idx] > 0)
+			tp->full_duplex = 1;
+		if (mtu[board_idx] > 0)
+			dev->mtu = mtu[board_idx];
+	}
+	if (dev->mem_start)
+		tp->default_port = dev->mem_start;
+	if (tp->default_port) {
+		tp->medialock = 1;
+		if (media_cap[tp->default_port] & MediaAlwaysFD)
+			tp->full_duplex = 1;
+	}
+	if (tp->full_duplex)
+		tp->full_duplex_lock = 1;
+
+	/* This is logically part of probe1(), but too complex to write inline. */
+	if (tulip_tbl[chip_idx].flags & HAS_MEDIA_TABLE)
+		parse_eeprom(dev);
+
+	if (media_cap[tp->default_port] & MediaIsMII) {
+		u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 };
+		tp->to_advertise = media2advert[tp->default_port - 9];
+	} else
+		tp->to_advertise = 0x03e1;
+
+	if ((tulip_tbl[chip_idx].flags & ALWAYS_CHECK_MII) ||
+		(tp->mtable  &&  tp->mtable->has_mii) ||
+		( ! tp->mtable  &&  (tulip_tbl[chip_idx].flags & HAS_MII))) {
+		int phy, phy_idx;
+		if (tp->mtable  &&  tp->mtable->has_mii) {
+			for (i = 0; i < tp->mtable->leafcount; i++)
+				if (tp->mtable->mleaf[i].media == 11) {
+					tp->cur_index = i;
+					tp->saved_if_port = dev->if_port;
+					select_media(dev, 1);
+					dev->if_port = tp->saved_if_port;
+					break;
+				}
+		}
+		/* Find the connected MII xcvrs.
+		   Doing this in open() would allow detecting external xcvrs later,
+		   but takes much time. */
+		for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);
+			 phy++) {
+			int mii_status = mdio_read(dev, phy, 1);
+			if ((mii_status & 0x8301) == 0x8001 ||
+				((mii_status & 0x8000) == 0  && (mii_status & 0x7800) != 0)) {
+				int mii_reg0 = mdio_read(dev, phy, 0);
+				int mii_advert = mdio_read(dev, phy, 4);
+				int reg4 = ((mii_status>>6) & tp->to_advertise) | 1;
+				tp->phys[phy_idx] = phy;
+				tp->advertising[phy_idx++] = reg4;
+				printk(KERN_INFO "%s:  MII transceiver #%d "
+					   "config %4.4x status %4.4x advertising %4.4x.\n",
+					   dev->name, phy, mii_reg0, mii_status, mii_advert);
+				/* Fixup for DLink with miswired PHY. */
+				if (mii_advert != reg4) {
+					printk(KERN_DEBUG "%s:  Advertising %4.4x on PHY %d,"
+						   " previously advertising %4.4x.\n",
+						   dev->name, reg4, phy, mii_advert);
+					mdio_write(dev, phy, 4, reg4);
+				}
+				/* Enable autonegotiation: some boards default to off. */
+				mdio_write(dev, phy, 0, mii_reg0 |
+						   (tp->full_duplex ? 0x1100 : 0x1000) |
+						   (media_cap[tp->default_port]&MediaIs100 ? 0x2000:0));
+			}
+		}
+		tp->mii_cnt = phy_idx;
+		if (tp->mtable  &&  tp->mtable->has_mii  &&  phy_idx == 0) {
+			printk(KERN_INFO "%s: ***WARNING***: No MII transceiver found!\n",
+				   dev->name);
+			tp->phys[0] = 1;
+		}
+	}
+
+	/* The Tulip-specific entries in the device structure. */
+	dev->open = &tulip_open;
+	dev->hard_start_xmit = &tulip_start_xmit;
+	dev->stop = &tulip_close;
+	dev->get_stats = &tulip_get_stats;
+#ifdef HAVE_PRIVATE_IOCTL
+	dev->do_ioctl = &private_ioctl;
+#endif
+#ifdef HAVE_MULTICAST
+	dev->set_multicast_list = &set_rx_mode;
+#endif
+
+	/* Reset the xcvr interface and turn on heartbeat. */
+	switch (chip_idx) {
+	case DC21041:
+		outl(0x00000000, ioaddr + CSR13);
+		outl(0xFFFFFFFF, ioaddr + CSR14);
+		outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */
+		outl_CSR6(inl(ioaddr + CSR6) | 0x0200, ioaddr, chip_idx);
+		outl(0x0000EF05, ioaddr + CSR13);
+		break;
+	case DC21040:
+		outl(0x00000000, ioaddr + CSR13);
+		outl(0x00000004, ioaddr + CSR13);
+		break;
+	case DC21140: default:
+		if (tp->mtable)
+			outl(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
+		break;
+	case DC21142:
+	case PNIC2:
+		if (tp->mii_cnt  ||  media_cap[dev->if_port] & MediaIsMII) {
+			outl_CSR6(0x82020000, ioaddr, chip_idx);
+			outl(0x0000, ioaddr + CSR13);
+			outl(0x0000, ioaddr + CSR14);
+			outl_CSR6(0x820E0000, ioaddr, chip_idx);
+		} else {
+			outl_CSR6(0x82420200, ioaddr, chip_idx);
+			outl(0x0001, ioaddr + CSR13);
+			outl(0x0003FFFF, ioaddr + CSR14);
+			outl(0x0008, ioaddr + CSR15);
+			outl(0x0001, ioaddr + CSR13);
+			outl(0x1301, ioaddr + CSR12); /* Start NWay. */
+		}
+		break;
+	case X3201_3:
+		outl(0x0008, ioaddr + CSR15);
+		udelay(5);  /* The delays are Xircom recommended to give the
+					 * chipset time to reset the actual hardware
+					 * on the PCMCIA card
+					 */
+		outl(0xa8050000, ioaddr + CSR15);
+		udelay(5);
+		outl(0xa00f0000, ioaddr + CSR15);
+		udelay(5);
+		outl_CSR6(0x32000200, ioaddr, chip_idx);
+		break;
+	case LC82C168:
+		if ( ! tp->mii_cnt) {
+			outl_CSR6(0x00420000, ioaddr, chip_idx);
+			outl(0x30, ioaddr + CSR12);
+			outl(0x0001F078, ioaddr + 0xB8);
+			outl(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */
+		}
+		break;
+	case MX98713: case COMPEX9881:
+		outl_CSR6(0x00000000, ioaddr, chip_idx);
+		outl(0x000711C0, ioaddr + CSR14); /* Turn on NWay. */
+		outl(0x00000001, ioaddr + CSR13);
+		break;
+	case MX98715: case MX98725:
+		outl_CSR6(0x01a80000, ioaddr, chip_idx);
+		outl(0xFFFFFFFF, ioaddr + CSR14);
+		outl(0x00001000, ioaddr + CSR12);
+		break;
+	case COMET:
+		/* No initialization necessary. */
+		break;
+	}
+
+	return dev;
+}
+
+/* Serial EEPROM section. */
+/* The main routine to parse the very complicated SROM structure.
+   Search www.digital.com for "21X4 SROM" to get details.
+   This code is very complex, and will require changes to support
+   additional cards, so I'll be verbose about what is going on.
+   */
+
+/* Known cards that have old-style EEPROMs. */
+static struct fixups {
+  char *name;
+  unsigned char addr0, addr1, addr2;
+  u16 newtable[32];				/* Max length below. */
+} eeprom_fixups[] = {
+  {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c,
+						  0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }},
+  {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x021f,
+							   0x0000, 0x009E, /* 10baseT */
+							   0x0903, 0x006D, /* 100baseTx */ }},
+  {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x033f,
+								 0x0107, 0x8021, /* 100baseFx */
+								 0x0108, 0x8021, /* 100baseFx-FD */
+								 0x0103, 0x006D, /* 100baseTx */ }},
+  {"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0313,
+							   0x1001, 0x009E, /* 10base2, CSR12 0x10*/
+							   0x0000, 0x009E, /* 10baseT */
+							   0x0303, 0x006D, /* 100baseTx, CSR12 0x03 */ }},
+  {"Accton EN1207", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x031F,
+							0x1B01, 0x0000, /* 10base2,   CSR12 0x1B */
+							0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */
+							0x0B00, 0x009E, /* 10baseT,   CSR12 0x0B */
+   }},
+  {0, 0, 0, 0, {}}};
+
+static const char * block_name[] = {"21140 non-MII", "21140 MII PHY",
+ "21142 Serial PHY", "21142 MII PHY", "21143 SYM PHY", "21143 reset method"};
+
+#if defined(__i386__)			/* AKA get_unaligned() */
+#define get_u16(ptr) (*(u16 *)(ptr))
+#else
+#define get_u16(ptr) (((u8*)(ptr))[0] + (((u8*)(ptr))[1]<<8))
+#endif
+
+static void parse_eeprom(struct net_device *dev)
+{
+	/* The last media info list parsed, for multiport boards.  */
+	static struct mediatable *last_mediatable = NULL;
+	static unsigned char *last_ee_data = NULL;
+	static int controller_index = 0;
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	unsigned char *ee_data = tp->eeprom;
+	int i;
+#ifdef CARDBUS
+	int chip_rev = tp->revision;
+#endif
+
+	tp->mtable = 0;
+	for (i = 0; i < EEPROM_SIZE/2; i++)
+		((u16 *)ee_data)[i] =
+			le16_to_cpu(read_eeprom(ioaddr, i, EEPROM_ADDRLEN));
+
+	/* Detect an old-style (SA only) EEPROM layout:
+	   memcmp(eedata, eedata+16, 8). */
+	for (i = 0; i < 8; i ++)
+		if (ee_data[i] != ee_data[16+i])
+			break;
+	if (i >= 8) {
+		if (ee_data[0] == 0xff) {
+			if (last_mediatable) {
+				controller_index++;
+				printk(KERN_INFO "%s:  Controller %d of multiport board.\n",
+					   dev->name, controller_index);
+				tp->mtable = last_mediatable;
+				ee_data = last_ee_data;
+				goto subsequent_board;
+			} else
+				printk(KERN_INFO "%s:  Missing EEPROM, this interface may "
+					   "not work correctly!\n",
+			   dev->name);
+			return;
+		}
+	  /* Do a fix-up based on the vendor half of the station address prefix. */
+	  for (i = 0; eeprom_fixups[i].name; i++) {
+		if (dev->dev_addr[0] == eeprom_fixups[i].addr0
+			&&  dev->dev_addr[1] == eeprom_fixups[i].addr1
+			&&  dev->dev_addr[2] == eeprom_fixups[i].addr2) {
+		  if (dev->dev_addr[2] == 0xE8  &&  ee_data[0x1a] == 0x55)
+			  i++;			/* An Accton EN1207, not an outlaw Maxtech. */
+		  memcpy(ee_data + 26, eeprom_fixups[i].newtable,
+				 sizeof(eeprom_fixups[i].newtable));
+		  printk(KERN_INFO "%s: Old format EEPROM on '%s' board.  Using"
+				 " substitute media control info.\n",
+				 dev->name, eeprom_fixups[i].name);
+		  break;
+		}
+	  }
+	  if (eeprom_fixups[i].name == NULL) { /* No fixup found. */
+		  printk(KERN_INFO "%s: Old style EEPROM with no media selection "
+				 "information.\n",
+			   dev->name);
+		return;
+	  }
+	}
+
+	controller_index = 0;
+	if (ee_data[19] > 1) {		/* Multiport board. */
+		last_ee_data = ee_data;
+	}
+subsequent_board:
+
+	if (ee_data[27] == 0) {		/* No valid media table. */
+	} else if (tp->chip_id == DC21041) {
+		unsigned char *p = (void *)ee_data + ee_data[27 + controller_index*3];
+		short media;
+		int count;
+
+		media = get_u16(p);
+		p += 2;
+		count = *p++;
+
+		printk(KERN_INFO "%s:21041 Media information at %d, default media "
+			   "%4.4x (%s).\n", dev->name, ee_data[27], media,
+			   media & 0x0800 ? "Autosense" : medianame[media & 15]);
+		for (i = 0; i < count; i++) {
+			unsigned char media_code = *p++;
+			u16 csrvals[3];
+			int idx;
+			for (idx = 0; idx < 3; idx++) {
+				csrvals[idx] = get_u16(p);
+				p += 2;
+			}
+			if (media_code & 0x40) {
+				printk(KERN_INFO "%s:  21041 media %2.2x (%s),"
+					   " csr13 %4.4x csr14 %4.4x csr15 %4.4x.\n",
+					   dev->name, media_code & 15, medianame[media_code & 15],
+					   csrvals[0], csrvals[1], csrvals[2]);
+			} else
+				printk(KERN_INFO "%s:  21041 media #%d, %s.\n",
+					   dev->name, media_code & 15, medianame[media_code & 15]);
+		}
+	} else {
+		unsigned char *p = (void *)ee_data + ee_data[27];
+		unsigned char csr12dir = 0;
+		int count;
+		struct mediatable *mtable;
+		u16 media = get_u16(p);
+
+		p += 2;
+		if (tulip_tbl[tp->chip_id].flags & CSR12_IN_SROM)
+			csr12dir = *p++;
+		count = *p++;
+		mtable = (struct mediatable *)
+			kmalloc(sizeof(struct mediatable) + count*sizeof(struct medialeaf),
+					GFP_KERNEL);
+		if (mtable == NULL)
+			return;				/* Horrible, impossible failure. */
+		last_mediatable = tp->mtable = mtable;
+		mtable->defaultmedia = media;
+		mtable->leafcount = count;
+		mtable->csr12dir = csr12dir;
+		mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;
+		mtable->csr15dir = mtable->csr15val = 0;
+
+		printk(KERN_INFO "%s:  EEPROM default media type %s.\n", dev->name,
+			   media & 0x0800 ? "Autosense" : medianame[media & 15]);
+		for (i = 0; i < count; i++) {
+			struct medialeaf *leaf = &mtable->mleaf[i];
+
+			if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */
+				leaf->type = 0;
+				leaf->media = p[0] & 0x3f;
+				leaf->leafdata = p;
+				if ((p[2] & 0x61) == 0x01)	/* Bogus, but Znyx boards do it. */
+					mtable->has_mii = 1;
+				p += 4;
+			} else {
+				leaf->type = p[1];
+				if (p[1] == 0x05) {
+					mtable->has_reset = i;
+					leaf->media = p[2] & 0x0f;
+				} else if (p[1] & 1) {
+					mtable->has_mii = 1;
+					leaf->media = 11;
+				} else {
+					mtable->has_nonmii = 1;
+					leaf->media = p[2] & 0x0f;
+					if (p[1] == 2) {
+						if (leaf->media == 0) {
+							mtable->csr15dir = get_unaligned((u16*)&p[3])<<16;
+							mtable->csr15val = get_unaligned((u16*)&p[5])<<16;
+						} else if (leaf->media == 0x40) {
+							u32 base15 = get_unaligned((u16*)&p[7]);
+							mtable->csr15dir =
+								(get_unaligned((u16*)&p[9])<<16) + base15;
+							mtable->csr15val =
+								(get_unaligned((u16*)&p[11])<<16) + base15;
+						}
+					}
+				}
+				leaf->leafdata = p + 2;
+				p += (p[0] & 0x3f) + 1;
+			}
+			if (tulip_debug > 1  &&  leaf->media == 11) {
+				unsigned char *bp = leaf->leafdata;
+				printk(KERN_INFO "%s:  MII interface PHY %d, setup/reset "
+					   "sequences %d/%d long, capabilities %2.2x %2.2x.\n",
+					   dev->name, bp[0], bp[1], bp[1 + bp[1]*2],
+					   bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]);
+			}
+			printk(KERN_INFO "%s:  Index #%d - Media %s (#%d) described "
+				   "by a %s (%d) block.\n",
+				   dev->name, i, medianame[leaf->media], leaf->media,
+				   block_name[leaf->type], leaf->type);
+		}
+	}
+}
+/* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/
+
+/*  EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK	0x02	/* EEPROM shift clock. */
+#define EE_CS			0x01	/* EEPROM chip select. */
+#define EE_DATA_WRITE	0x04	/* EEPROM chip data in. */
+#define EE_WRITE_0		0x01
+#define EE_WRITE_1		0x05
+#define EE_DATA_READ	0x08	/* EEPROM chip data out. */
+#define EE_ENB			(0x4800 | EE_CS)
+
+/* Delay between EEPROM clock transitions.
+   Even at 33Mhz current PCI implementations don't overrun the EEPROM clock.
+   We add a bus turn-around to insure that this remains true. */
+#define eeprom_delay()	inl(ee_addr)
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_WRITE_CMD	(5 << addr_len)
+#define EE_READ_CMD		(6 << addr_len)
+#define EE_ERASE_CMD	(7 << addr_len)
+
+static int read_eeprom(long ioaddr, int location, int addr_len)
+{
+	int i;
+	unsigned short retval = 0;
+	long ee_addr = ioaddr + CSR9;
+	int read_cmd = location | EE_READ_CMD;
+
+	outl(EE_ENB & ~EE_CS, ee_addr);
+	outl(EE_ENB, ee_addr);
+
+	/* Shift the read command bits out. */
+	for (i = 4 + addr_len; i >= 0; i--) {
+		short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+		outl(EE_ENB | dataval, ee_addr);
+		eeprom_delay();
+		outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+		eeprom_delay();
+	}
+	outl(EE_ENB, ee_addr);
+
+	for (i = 16; i > 0; i--) {
+		outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
+		eeprom_delay();
+		retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
+		outl(EE_ENB, ee_addr);
+		eeprom_delay();
+	}
+
+	/* Terminate the EEPROM access. */
+	outl(EE_ENB & ~EE_CS, ee_addr);
+	return retval;
+}
+
+/* MII transceiver control section.
+   Read and write the MII registers using software-generated serial
+   MDIO protocol.  See the MII specifications or DP83840A data sheet
+   for details. */
+
+/* The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually
+   met by back-to-back PCI I/O cycles, but we insert a delay to avoid
+   "overclocking" issues or future 66Mhz PCI. */
+#define mdio_delay() inl(mdio_addr)
+
+/* Read and write the MII registers using software-generated serial
+   MDIO protocol.  It is just different enough from the EEPROM protocol
+   to not share code.  The maxium data clock rate is 2.5 Mhz. */
+#define MDIO_SHIFT_CLK	0x10000
+#define MDIO_DATA_WRITE0 0x00000
+#define MDIO_DATA_WRITE1 0x20000
+#define MDIO_ENB		0x00000		/* Ignore the 0x02000 databook setting. */
+#define MDIO_ENB_IN		0x40000
+#define MDIO_DATA_READ	0x80000
+
+static int mdio_read(struct net_device *dev, int phy_id, int location)
+{
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	int i;
+	int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+	int retval = 0;
+	long ioaddr = dev->base_addr;
+	long mdio_addr = ioaddr + CSR9;
+
+	if (tp->chip_id == LC82C168) {
+		int i = 1000;
+		outl(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0);
+		inl(ioaddr + 0xA0);
+		inl(ioaddr + 0xA0);
+		while (--i > 0)
+			if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000))
+				return retval & 0xffff;
+		return 0xffff;
+	}
+
+	if (tp->chip_id == COMET) {
+		if (phy_id == 1) {
+			if (location < 7)
+				return inl(ioaddr + 0xB4 + (location<<2));
+			else if (location == 17)
+				return inl(ioaddr + 0xD0);
+			else if (location >= 29 && location <= 31)
+				return inl(ioaddr + 0xD4 + ((location-29)<<2));
+		}
+		return 0xffff;
+	}
+
+	/* Establish sync by sending at least 32 logic ones. */
+	for (i = 32; i >= 0; i--) {
+		outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
+		mdio_delay();
+		outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
+		mdio_delay();
+	}
+	/* Shift the read command bits out. */
+	for (i = 15; i >= 0; i--) {
+		int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
+
+		outl(MDIO_ENB | dataval, mdio_addr);
+		mdio_delay();
+		outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
+		mdio_delay();
+	}
+	/* Read the two transition, 16 data, and wire-idle bits. */
+	for (i = 19; i > 0; i--) {
+		outl(MDIO_ENB_IN, mdio_addr);
+		mdio_delay();
+		retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
+		outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+		mdio_delay();
+	}
+	return (retval>>1) & 0xffff;
+}
+
+static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
+{
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	int i;
+	int cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
+	long ioaddr = dev->base_addr;
+	long mdio_addr = ioaddr + CSR9;
+
+	if (tp->chip_id == LC82C168) {
+		int i = 1000;
+		outl(cmd, ioaddr + 0xA0);
+		do
+			if ( ! (inl(ioaddr + 0xA0) & 0x80000000))
+				break;
+		while (--i > 0);
+		return;
+	}
+
+	if (tp->chip_id == COMET) {
+		if (phy_id != 1)
+			return;
+		if (location < 7)
+			outl(value, ioaddr + 0xB4 + (location<<2));
+		else if (location == 17)
+			outl(value, ioaddr + 0xD0);
+		else if (location >= 29 && location <= 31)
+			outl(value, ioaddr + 0xD4 + ((location-29)<<2));
+		return;
+	}
+
+	/* Establish sync by sending 32 logic ones. */
+	for (i = 32; i >= 0; i--) {
+		outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
+		mdio_delay();
+		outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
+		mdio_delay();
+	}
+	/* Shift the command bits out. */
+	for (i = 31; i >= 0; i--) {
+		int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
+		outl(MDIO_ENB | dataval, mdio_addr);
+		mdio_delay();
+		outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
+		mdio_delay();
+	}
+	/* Clear out extra bits. */
+	for (i = 2; i > 0; i--) {
+		outl(MDIO_ENB_IN, mdio_addr);
+		mdio_delay();
+		outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+		mdio_delay();
+	}
+	return;
+}
+
+static void
+tulip_up(struct net_device *dev)
+{
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int i;
+
+	/* On some chip revs we must set the MII/SYM port before the reset!? */
+	if (tp->mii_cnt  ||  (tp->mtable  &&  tp->mtable->has_mii))
+		outl_CSR6(0x00040000, ioaddr, tp->chip_id);
+
+	/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
+	outl(0x00000001, ioaddr + CSR0);
+
+	/* Deassert reset. */
+	outl(tp->csr0, ioaddr + CSR0);
+	udelay(2);
+
+	/* Clear the tx ring */
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		tp->tx_skbuff[i] = 0;
+		tp->tx_ring[i].status = 0x00000000;
+	}
+
+	if (tulip_debug > 1)
+		printk(KERN_DEBUG "%s: tulip_open() irq %d.\n", dev->name, dev->irq);
+
+	if (tulip_tbl[tp->chip_id].flags & MC_HASH_ONLY) {
+		u32 addr_low = cpu_to_le32(get_unaligned((u32 *)dev->dev_addr));
+		u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(dev->dev_addr+4)));
+		if (tp->chip_id == AX88140) {
+			outl(0, ioaddr + CSR13);
+			outl(addr_low,  ioaddr + CSR14);
+			outl(1, ioaddr + CSR13);
+			outl(addr_high, ioaddr + CSR14);
+		} else if (tp->chip_id == COMET) {
+			outl(addr_low,  ioaddr + 0xA4);
+			outl(addr_high, ioaddr + 0xA8);
+			outl(0, ioaddr + 0xAC);
+			outl(0, ioaddr + 0xB0);
+		}
+	} else if (tp->chip_id != X3201_3) {
+		/* This is set_rx_mode(), but without starting the transmitter. */
+		u16 *eaddrs = (u16 *)dev->dev_addr;
+		u16 *setup_frm = &tp->setup_frame[15*6];
+
+		/* 21140 bug: you must add the broadcast address. */
+		memset(tp->setup_frame, 0xff, 96*sizeof(u16));
+		/* Fill the final entry of the table with our physical address. */
+		*setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];
+		*setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];
+		*setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];
+		/* Put the setup frame on the Tx list. */
+		tp->tx_ring[0].length = 0x08000000 | 192;
+		tp->tx_ring[0].buffer1 = virt_to_bus(tp->setup_frame);
+		tp->tx_ring[0].status = DescOwned;
+
+		tp->cur_tx++;
+	} else { /* X3201_3 */
+		u16 *eaddrs = (u16 *)dev->dev_addr;
+		u16 *setup_frm = &tp->setup_frame[0*6];
+		
+		/* fill the table with the broadcast address */
+		memset(tp->setup_frame, 0xff, 96*sizeof(u16));
+		/* re-fill the first 14 table entries with our address */
+		for(i=0; i<14; i++) {
+			*setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];
+			*setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];
+			*setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];
+		}
+
+		/* Put the setup frame on the Tx list. */
+		tp->tx_ring[0].length = 0x08000000 | 192;
+		/* Lie about the address of our setup frame to make the */
+		/* chip happy */
+		tp->tx_ring[0].buffer1 = (virt_to_bus(tp->setup_frame) + 4);
+		tp->tx_ring[0].status = DescOwned;
+
+		tp->cur_tx++;
+	}
+	outl(virt_to_bus(tp->rx_ring), ioaddr + CSR3);
+	outl(virt_to_bus(tp->tx_ring), ioaddr + CSR4);
+
+	tp->saved_if_port = dev->if_port;
+	if (dev->if_port == 0)
+		dev->if_port = tp->default_port;
+	if (tp->chip_id == DC21041  &&  dev->if_port > 4)
+		/* Invalid: Select initial TP, autosense, autonegotiate.  */
+		dev->if_port = 4;
+
+	/* Allow selecting a default media. */
+	i = 0;
+	if (tp->mtable == NULL)
+		goto media_picked;
+	if (dev->if_port) {
+		int looking_for = media_cap[dev->if_port] & MediaIsMII ? 11 :
+			(dev->if_port == 12 ? 0 : dev->if_port);
+		for (i = 0; i < tp->mtable->leafcount; i++)
+			if (tp->mtable->mleaf[i].media == looking_for) {
+				printk(KERN_INFO "%s: Using user-specified media %s.\n",
+					   dev->name, medianame[dev->if_port]);
+				goto media_picked;
+			}
+	}
+	if ((tp->mtable->defaultmedia & 0x0800) == 0) {
+		int looking_for = tp->mtable->defaultmedia & 15;
+		for (i = 0; i < tp->mtable->leafcount; i++)
+			if (tp->mtable->mleaf[i].media == looking_for) {
+				printk(KERN_INFO "%s: Using EEPROM-set media %s.\n",
+					   dev->name, medianame[looking_for]);
+				goto media_picked;
+			}
+	}
+	/* Start sensing first non-full-duplex media. */
+	for (i = tp->mtable->leafcount - 1;
+		 (media_cap[tp->mtable->mleaf[i].media] & MediaAlwaysFD) && i > 0; i--)
+		;
+media_picked:
+
+	tp->csr6 = 0;
+	tp->cur_index = i;
+	if (dev->if_port == 0  &&  tp->chip_id == DC21142) {
+		if (tp->mii_cnt) {
+			select_media(dev, 1);
+			if (tulip_debug > 1)
+				printk(KERN_INFO "%s: Using MII transceiver %d, status "
+					   "%4.4x.\n",
+					   dev->name, tp->phys[0], mdio_read(dev, tp->phys[0], 1));
+			outl_CSR6(0x82020000, ioaddr, tp->chip_id);
+			tp->csr6 = 0x820E0000;
+			dev->if_port = 11;
+			outl(0x0000, ioaddr + CSR13);
+			outl(0x0000, ioaddr + CSR14);
+		} else
+			t21142_start_nway(dev);
+	} else if ((tp->chip_id == LC82C168  || tp->chip_id == PNIC2)
+			   &&  tp->mii_cnt && ! tp->medialock) {
+		dev->if_port = 11;
+		tp->csr6 = 0x814C0000 | (tp->full_duplex ? 0x0200 : 0);
+		outl(0x0001, ioaddr + CSR15);
+	} else if ((tp->chip_id == MX98713 || tp->chip_id == COMPEX9881)
+			   && ! tp->medialock) {
+		dev->if_port = 0;
+		tp->csr6 = 0x01880000 | (tp->full_duplex ? 0x0200 : 0);
+		outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
+	} else if (tp->chip_id == MX98715 || tp->chip_id == MX98725) {
+		/* Provided by BOLO, Macronix - 12/10/1998. */
+		dev->if_port = 0;
+		tp->csr6 = 0x01880200;
+		outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
+		outl(0x11000 | inw(ioaddr + 0xa0), ioaddr + 0xa0);
+	} else if (tp->chip_id == DC21143  &&
+			   media_cap[dev->if_port] & MediaIsMII) {
+		/* We must reset the media CSRs when we force-select MII mode. */
+		outl(0x0000, ioaddr + CSR13);
+		outl(0x0000, ioaddr + CSR14);
+		outl(0x0008, ioaddr + CSR15);
+	} else if (tp->chip_id == X3201_3) {
+		outl(0x0008, ioaddr + CSR15);
+		udelay(5);
+		outl(0xa8050000, ioaddr + CSR15);
+		udelay(5);
+		outl(0xa00f0000, ioaddr + CSR15); 
+		udelay(5);
+		tp->csr6  = 0x32400000;
+	} else if (tp->chip_id == COMET) {
+		dev->if_port = 0;
+		tp->csr6 = 0x00040000;
+	} else
+		select_media(dev, 1);
+
+	/* Start the chip's Tx to process setup frame. */
+	outl_CSR6(tp->csr6, ioaddr, tp->chip_id);
+	outl_CSR6(tp->csr6 | 0x2000, ioaddr, tp->chip_id);
+
+	dev->tbusy = 0;
+	tp->interrupt = 0;
+	dev->start = 1;
+
+	/* Enable interrupts by setting the interrupt mask. */
+	outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5);
+	outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
+	outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id);
+	outl(0, ioaddr + CSR2);		/* Rx poll demand */
+
+	if (tulip_debug > 2) {
+		printk(KERN_DEBUG "%s: Done tulip_open(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n",
+			   dev->name, inl(ioaddr + CSR0), inl(ioaddr + CSR5),
+			   inl(ioaddr + CSR6));
+	}
+	/* Set the timer to switch to check for link beat and perhaps switch
+	   to an alternate media type. */
+	init_timer(&tp->timer);
+	tp->timer.expires = RUN_AT(5*HZ);
+	tp->timer.data = (unsigned long)dev;
+	tp->timer.function = tulip_tbl[tp->chip_id].media_timer;
+	add_timer(&tp->timer);
+}
+
+static int
+tulip_open(struct net_device *dev)
+{
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+
+	if (request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev))
+		return -EAGAIN;
+
+	tulip_init_ring(dev);
+
+	tulip_up(dev);
+	tp->open = 1;
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+/* Set up the transceiver control registers for the selected media type. */
+static void select_media(struct net_device *dev, int startup)
+{
+	long ioaddr = dev->base_addr;
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	struct mediatable *mtable = tp->mtable;
+	u32 new_csr6;
+	int i;
+
+	if (mtable) {
+		struct medialeaf *mleaf = &mtable->mleaf[tp->cur_index];
+		unsigned char *p = mleaf->leafdata;
+		switch (mleaf->type) {
+		case 0:					/* 21140 non-MII xcvr. */
+			if (tulip_debug > 1)
+				printk(KERN_DEBUG "%s: Using a 21140 non-MII transceiver"
+					   " with control setting %2.2x.\n",
+					   dev->name, p[1]);
+			dev->if_port = p[0];
+			if (startup)
+				outl(mtable->csr12dir | 0x100, ioaddr + CSR12);
+			outl(p[1], ioaddr + CSR12);
+			new_csr6 = 0x02000000 | ((p[2] & 0x71) << 18);
+			break;
+		case 2: case 4: {
+			u16 setup[5];
+			u32 csr13val, csr14val, csr15dir, csr15val;
+			for (i = 0; i < 5; i++)
+				setup[i] = get_u16(&p[i*2 + 1]);
+
+			dev->if_port = p[0] & 15;
+			if (media_cap[dev->if_port] & MediaAlwaysFD)
+				tp->full_duplex = 1;
+
+			if (startup && mtable->has_reset) {
+				struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset];
+				unsigned char *rst = rleaf->leafdata;
+				if (tulip_debug > 1)
+					printk(KERN_DEBUG "%s: Resetting the transceiver.\n",
+						   dev->name);
+				for (i = 0; i < rst[0]; i++)
+					outl(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15);
+			}
+			if (tulip_debug > 1)
+				printk(KERN_DEBUG "%s: 21143 non-MII %s transceiver control "
+					   "%4.4x/%4.4x.\n",
+					   dev->name, medianame[dev->if_port], setup[0], setup[1]);
+			if (p[0] & 0x40) {	/* SIA (CSR13-15) setup values are provided. */
+				csr13val = setup[0];
+				csr14val = setup[1];
+				csr15dir = (setup[3]<<16) | setup[2];
+				csr15val = (setup[4]<<16) | setup[2];
+				outl(0, ioaddr + CSR13);
+				outl(csr14val, ioaddr + CSR14);
+				outl(csr15dir, ioaddr + CSR15);	/* Direction */
+				outl(csr15val, ioaddr + CSR15);	/* Data */
+				outl(csr13val, ioaddr + CSR13);
+			} else {
+				csr13val = 1;
+				csr14val = 0x0003FF7F;
+				csr15dir = (setup[0]<<16) | 0x0008;
+				csr15val = (setup[1]<<16) | 0x0008;
+				if (dev->if_port <= 4)
+					csr14val = t21142_csr14[dev->if_port];
+				if (startup) {
+					outl(0, ioaddr + CSR13);
+					outl(csr14val, ioaddr + CSR14);
+				}
+				outl(csr15dir, ioaddr + CSR15);	/* Direction */
+				outl(csr15val, ioaddr + CSR15);	/* Data */
+				if (startup) outl(csr13val, ioaddr + CSR13);
+			}
+			if (tulip_debug > 1)
+				printk(KERN_DEBUG "%s:  Setting CSR15 to %8.8x/%8.8x.\n",
+					   dev->name, csr15dir, csr15val);
+			if (mleaf->type == 4)
+				new_csr6 = 0x82020000 | ((setup[2] & 0x71) << 18);
+			else
+				new_csr6 = 0x82420000;
+			break;
+		}
+		case 1: case 3: {
+			int phy_num = p[0];
+			int init_length = p[1];
+			u16 *misc_info;
+			u16 to_advertise;
+
+			dev->if_port = 11;
+			new_csr6 = 0x020E0000;
+			if (mleaf->type == 3) {	/* 21142 */
+				u16 *init_sequence = (u16*)(p+2);
+				u16 *reset_sequence = &((u16*)(p+3))[init_length];
+				int reset_length = p[2 + init_length*2];
+				misc_info = reset_sequence + reset_length;
+				if (startup)
+					for (i = 0; i < reset_length; i++)
+						outl(get_u16(&reset_sequence[i]) << 16, ioaddr + CSR15);
+				for (i = 0; i < init_length; i++)
+					outl(get_u16(&init_sequence[i]) << 16, ioaddr + CSR15);
+			} else {
+				u8 *init_sequence = p + 2;
+				u8 *reset_sequence = p + 3 + init_length;
+				int reset_length = p[2 + init_length];
+				misc_info = (u16*)(reset_sequence + reset_length);
+				if (startup) {
+					outl(mtable->csr12dir | 0x100, ioaddr + CSR12);
+					for (i = 0; i < reset_length; i++)
+						outl(reset_sequence[i], ioaddr + CSR12);
+				}
+				for (i = 0; i < init_length; i++)
+					outl(init_sequence[i], ioaddr + CSR12);
+			}
+			to_advertise = (get_u16(&misc_info[1]) & tp->to_advertise) | 1;
+			tp->advertising[phy_num] = to_advertise;
+			if (tulip_debug > 1)
+				printk(KERN_DEBUG "%s:  Advertising %4.4x on PHY %d (%d).\n",
+					   dev->name, to_advertise, phy_num, tp->phys[phy_num]);
+			/* Bogus: put in by a committee?  */
+			mdio_write(dev, tp->phys[phy_num], 4, to_advertise);
+			break;
+		}
+		default:
+			printk(KERN_DEBUG "%s:  Invalid media table selection %d.\n",
+					   dev->name, mleaf->type);
+			new_csr6 = 0x020E0000;
+		}
+		if (tulip_debug > 1)
+			printk(KERN_DEBUG "%s: Using media type %s, CSR12 is %2.2x.\n",
+				   dev->name, medianame[dev->if_port],
+				   inl(ioaddr + CSR12) & 0xff);
+	} else if (tp->chip_id == DC21041) {
+		if (tulip_debug > 1)
+			printk(KERN_DEBUG "%s: 21041 using media %s, CSR12 is %4.4x.\n",
+				   dev->name, medianame[dev->if_port & 15],
+				   inl(ioaddr + CSR12) & 0xffff);
+		outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */
+		outl(t21041_csr14[dev->if_port], ioaddr + CSR14);
+		outl(t21041_csr15[dev->if_port], ioaddr + CSR15);
+		outl(t21041_csr13[dev->if_port], ioaddr + CSR13);
+		new_csr6 = 0x80020000;
+	} else if (tp->chip_id == LC82C168 || tp->chip_id == PNIC2) {
+		if (startup && ! tp->medialock)
+			dev->if_port = tp->mii_cnt ? 11 : 0;
+		if (tulip_debug > 1)
+			printk(KERN_DEBUG "%s: PNIC PHY status is %3.3x, CSR12 %4.4x,"
+				   " media %s.\n",
+				   dev->name, inl(ioaddr + 0xB8), inl(ioaddr + CSR12),
+				   medianame[dev->if_port]);
+		if (tp->mii_cnt) {
+			new_csr6 = 0x810C0000;
+			outl(0x0001, ioaddr + CSR15);
+			outl(0x0201B07A, ioaddr + 0xB8);
+		} else if (startup) {
+			/* Start with 10mbps to do autonegotiation. */
+			outl(0x32, ioaddr + CSR12);
+			new_csr6 = 0x00420000;
+			outl(0x0001B078, ioaddr + 0xB8);
+			outl(0x0201B078, ioaddr + 0xB8);
+		} else if (dev->if_port == 3  ||  dev->if_port == 5) {
+			outl(0x33, ioaddr + CSR12);
+			new_csr6 = 0x01860000;
+			if (startup)
+				outl(0x0201F868, ioaddr + 0xB8); /* Trigger autonegotiation. */
+			else
+				outl(0x1F868, ioaddr + 0xB8);
+		} else {
+			outl(0x32, ioaddr + CSR12);
+			new_csr6 = 0x00420000;
+			outl(0x1F078, ioaddr + 0xB8);
+		}
+	} else if (tp->chip_id == DC21040) {					/* 21040 */
+		/* Turn on the xcvr interface. */
+		int csr12 = inl(ioaddr + CSR12);
+		if (tulip_debug > 1)
+			printk(KERN_DEBUG "%s: 21040 media type is %s, CSR12 is %2.2x.\n",
+				   dev->name, medianame[dev->if_port], csr12);
+		if (media_cap[dev->if_port] & MediaAlwaysFD)
+			tp->full_duplex = 1;
+		new_csr6 = 0x20000;
+		/* Set the full duplux match frame. */
+		outl(FULL_DUPLEX_MAGIC, ioaddr + CSR11);
+		outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */
+		if (t21040_csr13[dev->if_port] & 8) {
+			outl(0x0705, ioaddr + CSR14);
+			outl(0x0006, ioaddr + CSR15);
+		} else {
+			outl(0xffff, ioaddr + CSR14);
+			outl(0x0000, ioaddr + CSR15);
+		}
+		outl(0x8f01 | t21040_csr13[dev->if_port], ioaddr + CSR13);
+	} else if (tp->chip_id == X3201_3) {					/* Xircom */
+		if (tp->default_port == 0)
+			dev->if_port = tp->mii_cnt ? 11 : 3;
+/* Someone is on crack, the Xircom only does MII, no Fx */
+/*		if (media_cap[dev->if_port] & MediaIsMII) {
+			new_csr6 = 0x020E0000;
+		} else if (media_cap[dev->if_port] & MediaIsFx) {
+			new_csr6 = 0x028600000;
+		} else
+			new_csr6 = 0x038600000;*/
+		new_csr6 = 0x324c0000;
+		if (tulip_debug > 1)
+			printk(KERN_DEBUG "%s: Xircom CardBus Adapter: "
+				   "%s transceiver, CSR12 %2.2x.\n",
+				   dev->name, medianame[dev->if_port],
+				   inl(ioaddr + CSR12));
+	} else {					/* Unknown chip type with no media table. */
+		if (tp->default_port == 0)
+			dev->if_port = tp->mii_cnt ? 11 : 3;
+		if (media_cap[dev->if_port] & MediaIsMII) {
+			new_csr6 = 0x020E0000;
+		} else if (media_cap[dev->if_port] & MediaIsFx) {
+			new_csr6 = 0x028600000;
+		} else
+			new_csr6 = 0x038600000;
+		if (tulip_debug > 1)
+			printk(KERN_DEBUG "%s: No media description table, assuming "
+				   "%s transceiver, CSR12 %2.2x.\n",
+				   dev->name, medianame[dev->if_port],
+				   inl(ioaddr + CSR12));
+	}
+
+	tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0);
+	return;
+}
+
+/*
+  Check the MII negotiated duplex, and change the CSR6 setting if
+  required.
+  Return 0 if everything is OK.
+  Return < 0 if the transceiver is missing or has no link beat.
+  */
+static int check_duplex(struct net_device *dev)
+{
+	long ioaddr = dev->base_addr;
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	int mii_reg1, mii_reg5, negotiated, duplex;
+
+	if (tp->full_duplex_lock)
+		return 0;
+	mii_reg1 = mdio_read(dev, tp->phys[0], 1);
+	mii_reg5 = mdio_read(dev, tp->phys[0], 5);
+	if (tulip_debug > 1)
+		printk(KERN_INFO "%s: MII status %4.4x, Link partner report "
+			   "%4.4x.\n", dev->name, mii_reg1, mii_reg5);
+	if (mii_reg1 == 0xffff)
+		return -2;
+	if ((mii_reg1 & 0x0004) == 0) {
+		int new_reg1 = mdio_read(dev, tp->phys[0], 1);
+		if ((new_reg1 & 0x0004) == 0) {
+			if (tulip_debug  > 1)
+				printk(KERN_INFO "%s: No link beat on the MII interface,"
+					   " status %4.4x.\n", dev->name, new_reg1);
+			return -1;
+		}
+	}
+	negotiated = mii_reg5 & tp->advertising[0];
+	duplex = ((negotiated & 0x0300) == 0x0100
+			  || (negotiated & 0x00C0) == 0x0040);
+	/* 100baseTx-FD  or  10T-FD, but not 100-HD */
+	if (tp->full_duplex != duplex) {
+		tp->full_duplex = duplex;
+		if (tp->full_duplex) tp->csr6 |= 0x0200;
+		else				 tp->csr6 &= ~0x0200;
+		outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id);
+		outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id);
+		if (tulip_debug > 0)
+			printk(KERN_INFO "%s: Setting %s-duplex based on MII"
+				   "#%d link partner capability of %4.4x.\n",
+				   dev->name, tp->full_duplex ? "full" : "half",
+				   tp->phys[0], mii_reg5);
+	}
+	return 0;
+}
+
+static void tulip_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	u32 csr12 = inl(ioaddr + CSR12);
+	int next_tick = 2*HZ;
+
+	if (tulip_debug > 2) {
+		printk(KERN_DEBUG "%s: Media selection tick, status %8.8x mode %8.8x "
+			   "SIA %8.8x %8.8x %8.8x %8.8x.\n",
+			   dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR6),
+			   csr12, inl(ioaddr + CSR13),
+			   inl(ioaddr + CSR14), inl(ioaddr + CSR15));
+	}
+	switch (tp->chip_id) {
+	case DC21040:
+		if (!tp->medialock  &&  csr12 & 0x0002) { /* Network error */
+			printk(KERN_INFO "%s: No link beat found.\n",
+				   dev->name);
+			dev->if_port = (dev->if_port == 2 ? 0 : 2);
+			select_media(dev, 0);
+			dev->trans_start = jiffies;
+		}
+		break;
+	case DC21041:
+		if (tulip_debug > 2)
+			printk(KERN_DEBUG "%s: 21041 media tick  CSR12 %8.8x.\n",
+				   dev->name, csr12);
+		switch (dev->if_port) {
+		case 0: case 3: case 4:
+		  if (csr12 & 0x0004) { /*LnkFail */
+			/* 10baseT is dead.  Check for activity on alternate port. */
+			tp->mediasense = 1;
+			if (csr12 & 0x0200)
+				dev->if_port = 2;
+			else
+				dev->if_port = 1;
+			printk(KERN_INFO "%s: No 21041 10baseT link beat, Media switched to %s.\n",
+				   dev->name, medianame[dev->if_port]);
+			outl(0, ioaddr + CSR13); /* Reset */
+			outl(t21041_csr14[dev->if_port], ioaddr + CSR14);
+			outl(t21041_csr15[dev->if_port], ioaddr + CSR15);
+			outl(t21041_csr13[dev->if_port], ioaddr + CSR13);
+			next_tick = 10*HZ;			/* 2.4 sec. */
+		  } else
+			next_tick = 30*HZ;
+		  break;
+		case 1:					/* 10base2 */
+		case 2:					/* AUI */
+			if (csr12 & 0x0100) {
+				next_tick = (30*HZ);			/* 30 sec. */
+				tp->mediasense = 0;
+			} else if ((csr12 & 0x0004) == 0) {
+				printk(KERN_INFO "%s: 21041 media switched to 10baseT.\n",
+					   dev->name);
+				dev->if_port = 0;
+				select_media(dev, 0);
+				next_tick = (24*HZ)/10;				/* 2.4 sec. */
+			} else if (tp->mediasense || (csr12 & 0x0002)) {
+				dev->if_port = 3 - dev->if_port; /* Swap ports. */
+				select_media(dev, 0);
+				next_tick = 20*HZ;
+			} else {
+				next_tick = 20*HZ;
+			}
+			break;
+		}
+		break;
+	case DC21140:  case DC21142: case MX98713: case COMPEX9881: default: {
+		struct medialeaf *mleaf;
+		unsigned char *p;
+		if (tp->mtable == NULL) {	/* No EEPROM info, use generic code. */
+			/* Not much that can be done.
+			   Assume this a generic MII or SYM transceiver. */
+			next_tick = 60*HZ;
+			if (tulip_debug > 2)
+				printk(KERN_DEBUG "%s: network media monitor CSR6 %8.8x "
+					   "CSR12 0x%2.2x.\n",
+					   dev->name, inl(ioaddr + CSR6), csr12 & 0xff);
+			break;
+		}
+		mleaf = &tp->mtable->mleaf[tp->cur_index];
+		p = mleaf->leafdata;
+		switch (mleaf->type) {
+		case 0: case 4: {
+			/* Type 0 serial or 4 SYM transceiver.  Check the link beat bit. */
+			int offset = mleaf->type == 4 ? 5 : 2;
+			s8 bitnum = p[offset];
+			if (p[offset+1] & 0x80) {
+				if (tulip_debug > 1)
+					printk(KERN_DEBUG"%s: Transceiver monitor tick "
+						   "CSR12=%#2.2x, no media sense.\n",
+						   dev->name, csr12);
+				if (mleaf->type == 4) {
+					if (mleaf->media == 3 && (csr12 & 0x02))
+						goto select_next_media;
+				}
+				break;
+			}
+			if (tulip_debug > 2)
+				printk(KERN_DEBUG "%s: Transceiver monitor tick: CSR12=%#2.2x"
+					   " bit %d is %d, expecting %d.\n",
+					   dev->name, csr12, (bitnum >> 1) & 7,
+					   (csr12 & (1 << ((bitnum >> 1) & 7))) != 0,
+					   (bitnum >= 0));
+			/* Check that the specified bit has the proper value. */
+			if ((bitnum < 0) !=
+				((csr12 & (1 << ((bitnum >> 1) & 7))) != 0)) {
+				if (tulip_debug > 1)
+					printk(KERN_DEBUG "%s: Link beat detected for %s.\n", dev->name,
+						   medianame[mleaf->media]);
+				if ((p[2] & 0x61) == 0x01)	/* Bogus Znyx board. */
+					goto actually_mii;
+				break;
+			}
+			if (tp->medialock)
+				break;
+	  select_next_media:
+			if (--tp->cur_index < 0) {
+				/* We start again, but should instead look for default. */
+				tp->cur_index = tp->mtable->leafcount - 1;
+			}
+			dev->if_port = tp->mtable->mleaf[tp->cur_index].media;
+			if (media_cap[dev->if_port] & MediaIsFD)
+				goto select_next_media; /* Skip FD entries. */
+			if (tulip_debug > 1)
+				printk(KERN_DEBUG "%s: No link beat on media %s,"
+					   " trying transceiver type %s.\n",
+					   dev->name, medianame[mleaf->media & 15],
+					   medianame[tp->mtable->mleaf[tp->cur_index].media]);
+			select_media(dev, 0);
+			/* Restart the transmit process. */
+			outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id);
+			outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id);
+			next_tick = (24*HZ)/10;
+			break;
+		}
+		case 1:  case 3:		/* 21140, 21142 MII */
+		actually_mii:
+			check_duplex(dev);
+			next_tick = 60*HZ;
+			break;
+		case 2:					/* 21142 serial block has no link beat. */
+		default:
+			break;
+		}
+	}
+	break;
+	}
+	tp->timer.expires = RUN_AT(next_tick);
+	add_timer(&tp->timer);
+}
+
+/* Handle the 21143 uniquely: do autoselect with NWay, not the EEPROM list
+   of available transceivers.  */
+static void t21142_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int csr12 = inl(ioaddr + CSR12);
+	int next_tick = 60*HZ;
+	int new_csr6 = 0;
+
+	if ((tulip_debug > 2) && !(media_cap[dev->if_port] & MediaIsMII))
+		printk(KERN_INFO"%s: 21143 negotiation status %8.8x, %s.\n",
+			   dev->name, csr12, medianame[dev->if_port]);
+	if (media_cap[dev->if_port] & MediaIsMII) {
+		check_duplex(dev);
+		next_tick = 60*HZ;
+	} else if (tp->nwayset) {
+		/* Don't screw up a negotiated session! */
+		if (tulip_debug > 1)
+			printk(KERN_INFO"%s: Using NWay-set %s media, csr12 %8.8x.\n",
+				   dev->name, medianame[dev->if_port], csr12);
+	} else if (tp->medialock) {
+			;
+	} else if (dev->if_port == 3) {
+		if (csr12 & 2) {	/* No 100mbps link beat, revert to 10mbps. */
+			if (tulip_debug > 1)
+				printk(KERN_INFO"%s: No 21143 100baseTx link beat, %8.8x, "
+					   "trying NWay.\n", dev->name, csr12);
+			t21142_start_nway(dev);
+			next_tick = 3*HZ;
+		}
+	} else if (((csr12 & 0x7000) != 0x5000)
+			   && tp->chip_id != X3201_3) {
+		/* Negotiation failed.  Search media types. */
+		if (tulip_debug > 1)
+			printk(KERN_INFO"%s: 21143 negotiation failed, status %8.8x.\n",
+				   dev->name, csr12);
+		if (!(csr12 & 4)) {		/* 10mbps link beat good. */
+			new_csr6 = 0x82420000;
+			dev->if_port = 0;
+			outl(0, ioaddr + CSR13);
+			outl(0x0003FFFF, ioaddr + CSR14);
+			outw(t21142_csr15[dev->if_port], ioaddr + CSR15);
+			outl(t21142_csr13[dev->if_port], ioaddr + CSR13);
+		} else {
+			/* Select 100mbps port to check for link beat. */
+			new_csr6 = 0x83860000;
+			dev->if_port = 3;
+			outl(0, ioaddr + CSR13);
+			outl(0x0003FF7F, ioaddr + CSR14);
+			outw(8, ioaddr + CSR15);
+			outl(1, ioaddr + CSR13);
+		}
+		if (tulip_debug > 1)
+			printk(KERN_INFO"%s: Testing new 21143 media %s.\n",
+				   dev->name, medianame[dev->if_port]);
+		if (new_csr6 != (tp->csr6 & ~0x00D5)) {
+			tp->csr6 &= 0x00D5;
+			tp->csr6 |= new_csr6;
+			outl(0x0301, ioaddr + CSR12);
+			outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id);
+			outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id);
+		}
+		next_tick = 3*HZ;
+	}
+	if (tp->cur_tx - tp->dirty_tx > 0  &&
+		jiffies - dev->trans_start > TX_TIMEOUT) {
+		printk(KERN_WARNING "%s: Tx hung, %d vs. %d.\n",
+			   dev->name, tp->cur_tx, tp->dirty_tx);
+		tulip_tx_timeout(dev);
+	}
+
+	tp->timer.expires = RUN_AT(next_tick);
+	add_timer(&tp->timer);
+}
+
+static void t21142_start_nway(struct net_device *dev)
+{
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int csr14 = ((tp->to_advertise & 0x0180) << 9)  |
+		((tp->to_advertise&0x0020)<<1) | 0xffbf;
+
+	dev->if_port = 0;
+	tp->nway = tp->mediasense = 1;
+	tp->nwayset = tp->lpar = 0;
+	if (debug > 1)
+		printk(KERN_DEBUG "%s: Restarting 21143 autonegotiation, %8.8x.\n",
+			   dev->name, csr14);
+	outl(0x0001, ioaddr + CSR13);
+	outl(csr14, ioaddr + CSR14);
+	tp->csr6 = 0x82420000 | (tp->to_advertise & 0x0040 ? 0x0200 : 0);
+	outl_CSR6(tp->csr6, ioaddr, tp->chip_id);
+	if (tp->mtable  &&  tp->mtable->csr15dir) {
+		outl(tp->mtable->csr15dir, ioaddr + CSR15);
+		outl(tp->mtable->csr15val, ioaddr + CSR15);
+	} else
+		outw(0x0008, ioaddr + CSR15);
+	outl(0x1301, ioaddr + CSR12); 		/* Trigger NWAY. */
+}
+
+static void t21142_lnk_change(struct net_device *dev, int csr5)
+{
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int csr12 = inl(ioaddr + CSR12);
+
+	if (tulip_debug > 1)
+		printk(KERN_INFO"%s: 21143 link status interrupt %8.8x, CSR5 %x, "
+			   "%8.8x.\n", dev->name, csr12, csr5, inl(ioaddr + CSR14));
+
+	/* If NWay finished and we have a negotiated partner capability. */
+	if (tp->nway  &&  !tp->nwayset  &&  (csr12 & 0x7000) == 0x5000) {
+		int setup_done = 0;
+		tp->lpar = csr12 >> 16;
+		tp->nwayset = 1;
+		if (csr12 & 0x01000000)			dev->if_port = 5;
+		else if (csr12 & 0x00800000)	dev->if_port = 3;
+		else if (csr12 & 0x00400000)	dev->if_port = 4;
+		else if (csr12 & 0x00200000)	dev->if_port = 0;
+		else {
+			tp->nwayset = 0;
+			if ( ! (csr12 & 2))			dev->if_port = 3;
+			else if ( ! (csr12 & 4))	dev->if_port = 0;
+		}
+		tp->full_duplex = (media_cap[tp->default_port] & MediaAlwaysFD) ? 1:0;
+
+		if (tulip_debug > 1) {
+			if (tp->nwayset)
+				printk(KERN_INFO "%s: Switching to %s based on link partner "
+					   "advertisement %4.4x.\n",
+					   dev->name, medianame[dev->if_port], tp->lpar);
+			else
+				printk(KERN_INFO "%s: Switching to %s based on link beat "
+					   "status of %4.4x.\n",
+					   dev->name, medianame[dev->if_port], csr12);
+		}
+
+		if (tp->mtable) {
+			int i;
+			for (i = 0; i < tp->mtable->leafcount; i++)
+				if (tp->mtable->mleaf[i].media == dev->if_port) {
+					tp->cur_index = i;
+					select_media(dev, 0);
+					setup_done = 1;
+					break;
+				}
+		}
+		if ( ! setup_done) {
+			tp->csr6 = dev->if_port & 1 ? 0x83860000 : 0x82420000;
+			if (tp->full_duplex)
+				tp->csr6 |= 0x0200;
+			outw(0x0000, ioaddr + CSR13);
+			outw(0x0000, ioaddr + CSR14);
+		}
+		outl_CSR6(tp->csr6 | 0x0000, ioaddr, tp->chip_id);
+		if (debug > 2)
+			printk(KERN_DEBUG "%s:  Restarting Tx and Rx, CSR5 is %8.8x.\n",
+				   dev->name, inl(ioaddr + CSR5));
+		outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id);
+	} else if ((tp->nwayset  &&  (csr5 & 0x08000000)
+				&& (dev->if_port == 3  ||  dev->if_port == 5)
+				&& (csr12 & 2) == 2) ||
+			   (tp->nway && (csr5 & (TPLnkFail)))) {
+		/* Link blew? Maybe restart NWay. */
+		del_timer(&tp->timer);
+		t21142_start_nway(dev);
+		tp->timer.expires = RUN_AT(3*HZ);
+		add_timer(&tp->timer);
+	} else if (dev->if_port == 3  ||  dev->if_port == 5) {
+		if (tulip_debug > 1)
+			printk(KERN_INFO"%s: 21143 %s link beat %s.\n",
+				   dev->name, medianame[dev->if_port],
+				   (csr12 & 2) ? "failed" : "good");
+		if ((csr12 & 2)  &&  ! tp->medialock) {
+			del_timer(&tp->timer);
+			t21142_start_nway(dev);
+			tp->timer.expires = RUN_AT(3*HZ);
+			add_timer(&tp->timer);
+		}
+	} else if (dev->if_port == 0  ||  dev->if_port == 4) {
+		if ((csr12 & 4) == 0)
+			printk(KERN_INFO"%s: 21143 10baseT link beat good.\n",
+				   dev->name);
+	} else if (!(csr12 & 4)) {		/* 10mbps link beat good. */
+		if (tulip_debug)
+			printk(KERN_INFO"%s: 21143 10mbps sensed media.\n",
+				   dev->name);
+		dev->if_port = 0;
+	} else if (tp->nwayset) {
+		if (tulip_debug)
+			printk(KERN_INFO"%s: 21143 using NWay-set %s, csr6 %8.8x.\n",
+				   dev->name, medianame[dev->if_port], tp->csr6);
+	} else {		/* 100mbps link beat good. */
+		if (tulip_debug)
+			printk(KERN_INFO"%s: 21143 100baseTx sensed media.\n",
+				   dev->name);
+		dev->if_port = 3;
+		tp->csr6 = 0x83860000;
+		outl(0x0003FF7F, ioaddr + CSR14);
+		outl(0x0301, ioaddr + CSR12);
+		outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id);
+		outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id);
+	}
+}
+
+static void mxic_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int next_tick = 60*HZ;
+
+	if (tulip_debug > 3) {
+		printk(KERN_INFO"%s: MXIC negotiation status %8.8x.\n", dev->name,
+			   inl(ioaddr + CSR12));
+	}
+	if (next_tick) {
+		tp->timer.expires = RUN_AT(next_tick);
+		add_timer(&tp->timer);
+	}
+}
+
+static void pnic_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int csr12 = inl(ioaddr + CSR12);
+	int next_tick = 60*HZ;
+	int new_csr6 = tp->csr6 & ~0x40C40200;
+
+	if (media_cap[dev->if_port] & MediaIsMII) {
+		int negotiated = mdio_read(dev, tp->phys[0], 5) & tp->advertising[0];
+
+		if (tulip_debug > 1)
+			printk(KERN_DEBUG "%s: PNIC negotiated capability %8.8x, "
+				   "CSR5 %8.8x.\n",
+				   dev->name, negotiated, inl(ioaddr + CSR5));
+
+		if (negotiated & 0x0380) 				/* 10 vs 100mbps */
+			new_csr6 |= 0x810E0000;
+		else
+			new_csr6 |= 0x814E0000;
+		if (((negotiated & 0x0300) == 0x0100)			/* Duplex */
+			|| (negotiated & 0x00C0) == 0x0040
+			|| tp->full_duplex_lock) {
+			tp->full_duplex = 1;
+			new_csr6 |= 0x0200;
+		}
+		if (tulip_debug > 1)
+			printk(KERN_DEBUG "%s: PNIC MII PHY status %4.4x, Link "
+				   "partner report %4.4x, csr6 %8.8x/%8.8x.\n",
+			   dev->name, mdio_read(dev, tp->phys[0], 1), negotiated,
+				   tp->csr6, inl(ioaddr + CSR6));
+	} else {
+		int phy_reg = inl(ioaddr + 0xB8);
+		int csr5 = inl(ioaddr + CSR5);
+
+		if (tulip_debug > 1)
+			printk(KERN_DEBUG "%s: PNIC PHY status %8.8x, CSR5 %8.8x.\n",
+				   dev->name, phy_reg, csr5);
+
+		if (phy_reg & 0x04000000) {	/* Remote link fault */
+			/*outl(0x0201F078, ioaddr + 0xB8);*/
+			next_tick = 3*HZ;
+		}
+		if (inl(ioaddr + CSR5) & TPLnkFail) { /* 100baseTx link beat */
+			if (tulip_debug > 1)
+				printk(KERN_DEBUG "%s: %s link beat failed, CSR12 %4.4x, "
+					   "CSR5 %8.8x, PHY %3.3x.\n",
+					   dev->name, medianame[dev->if_port], csr12,
+					   inl(ioaddr + CSR5), inl(ioaddr + 0xB8));
+			if (tp->medialock) {
+			} else if (dev->if_port == 0) {
+				dev->if_port = 3;
+				outl(0x33, ioaddr + CSR12);
+				new_csr6 = 0x01860000;
+				outl(0x1F868, ioaddr + 0xB8);
+			} else {
+				dev->if_port = 0;
+				outl(0x32, ioaddr + CSR12);
+				new_csr6 = 0x00420000;
+				outl(0x1F078, ioaddr + 0xB8);
+			}
+			new_csr6 |= (tp->csr6 & 0xfdff);
+			next_tick = 3*HZ;
+		} else
+			new_csr6 = tp->csr6;
+		if (tp->full_duplex_lock  ||  (phy_reg & 0x30000000) != 0) {
+			tp->full_duplex = 1;
+			new_csr6 |= 0x00000200;
+		}
+	}
+	if (tp->csr6 != new_csr6) {
+		tp->csr6 = new_csr6;
+		outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id);	/* Restart Tx */
+		outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id);
+		dev->trans_start = jiffies;
+		if (tulip_debug > 1)
+			printk(KERN_INFO "%s: Changing PNIC configuration to %s-duplex, "
+				   "CSR6 %8.8x.\n",
+				   dev->name, tp->full_duplex ? "full" : "half", new_csr6);
+	}
+	tp->timer.expires = RUN_AT(next_tick);
+	add_timer(&tp->timer);
+}
+
+static void comet_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int next_tick = 60*HZ;
+
+	if (tulip_debug > 1)
+		printk(KERN_DEBUG "%s: Comet link status %4.4x partner capability "
+			   "%4.4x.\n",
+			   dev->name, inl(ioaddr + 0xB8), inl(ioaddr + 0xC8));
+	tp->timer.expires = RUN_AT(next_tick);
+	add_timer(&tp->timer);
+}
+
+static void tulip_tx_timeout(struct net_device *dev)
+{
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+
+	if (media_cap[dev->if_port] & MediaIsMII) {
+		/* Do nothing -- the media monitor should handle this. */
+		if (tulip_debug > 1)
+			printk(KERN_WARNING "%s: Transmit timeout using MII device.\n",
+				   dev->name);
+	} else if (tp->chip_id == DC21040) {
+		if ( !tp->medialock  &&  inl(ioaddr + CSR12) & 0x0002) {
+			dev->if_port = (dev->if_port == 2 ? 0 : 2);
+			printk(KERN_INFO "%s: transmit timed out, switching to "
+				   "%s.\n",
+				   dev->name, medianame[dev->if_port]);
+			select_media(dev, 0);
+		}
+		dev->trans_start = jiffies;
+		return;
+	} else if (tp->chip_id == DC21041) {
+		int csr12 = inl(ioaddr + CSR12);
+
+		printk(KERN_WARNING "%s: 21041 transmit timed out, status %8.8x, "
+			   "CSR12 %8.8x, CSR13 %8.8x, CSR14 %8.8x, resetting...\n",
+			   dev->name, inl(ioaddr + CSR5), csr12,
+			   inl(ioaddr + CSR13), inl(ioaddr + CSR14));
+		tp->mediasense = 1;
+		if ( ! tp->medialock) {
+			if (dev->if_port == 1 || dev->if_port == 2)
+				if (csr12 & 0x0004) {
+					dev->if_port = 2 - dev->if_port;
+				} else
+					dev->if_port = 0;
+			else
+				dev->if_port = 1;
+			select_media(dev, 0);
+		}
+	} else if (tp->chip_id == DC21140 || tp->chip_id == DC21142
+			   || tp->chip_id == MX98713 || tp->chip_id == COMPEX9881) {
+		printk(KERN_WARNING "%s: 21140 transmit timed out, status %8.8x, "
+			   "SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n",
+			   dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR12),
+			   inl(ioaddr + CSR13), inl(ioaddr + CSR14), inl(ioaddr + CSR15));
+		if ( ! tp->medialock  &&  tp->mtable) {
+			do
+				--tp->cur_index;
+			while (tp->cur_index >= 0
+				   && (media_cap[tp->mtable->mleaf[tp->cur_index].media]
+					   & MediaIsFD));
+			if (--tp->cur_index < 0) {
+				/* We start again, but should instead look for default. */
+				tp->cur_index = tp->mtable->leafcount - 1;
+			}
+			select_media(dev, 0);
+			printk(KERN_WARNING "%s: transmit timed out, switching to %s "
+				   "media.\n", dev->name, medianame[dev->if_port]);
+		}
+	} else {
+		printk(KERN_WARNING "%s: Transmit timed out, status %8.8x, CSR12 "
+			   "%8.8x, resetting...\n",
+			   dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR12));
+		dev->if_port = 0;
+	}
+
+#if defined(way_too_many_messages)
+	if (tulip_debug > 3) {
+		int i;
+		for (i = 0; i < RX_RING_SIZE; i++) {
+			u8 *buf = (u8 *)(tp->rx_ring[i].buffer1);
+			int j;
+			printk(KERN_DEBUG "%2d: %8.8x %8.8x %8.8x %8.8x  "
+				   "%2.2x %2.2x %2.2x.\n",
+				   i, (unsigned int)tp->rx_ring[i].status,
+				   (unsigned int)tp->rx_ring[i].length,
+				   (unsigned int)tp->rx_ring[i].buffer1,
+				   (unsigned int)tp->rx_ring[i].buffer2,
+				   buf[0], buf[1], buf[2]);
+			for (j = 0; buf[j] != 0xee && j < 1600; j++)
+				if (j < 100) printk(" %2.2x", buf[j]);
+			printk(" j=%d.\n", j);
+		}
+		printk(KERN_DEBUG "  Rx ring %8.8x: ", (int)tp->rx_ring);
+		for (i = 0; i < RX_RING_SIZE; i++)
+			printk(" %8.8x", (unsigned int)tp->rx_ring[i].status);
+		printk("\n" KERN_DEBUG "  Tx ring %8.8x: ", (int)tp->tx_ring);
+		for (i = 0; i < TX_RING_SIZE; i++)
+			printk(" %8.8x", (unsigned int)tp->tx_ring[i].status);
+		printk("\n");
+	}
+#endif
+
+	/* Stop and restart the chip's Tx processes . */
+	outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id);
+	outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id);
+	/* Trigger an immediate transmit demand. */
+	outl(0, ioaddr + CSR1);
+
+	dev->trans_start = jiffies;
+	tp->stats.tx_errors++;
+	return;
+}
+
+/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+static void tulip_init_ring(struct net_device *dev)
+{
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	int i;
+
+	tp->tx_full = 0;
+	tp->cur_rx = tp->cur_tx = 0;
+	tp->dirty_rx = tp->dirty_tx = 0;
+
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		tp->rx_ring[i].status = 0x00000000;
+		tp->rx_ring[i].length = PKT_BUF_SZ;
+		tp->rx_ring[i].buffer2 = virt_to_bus(&tp->rx_ring[i+1]);
+		tp->rx_skbuff[i] = NULL;
+	}
+	/* Mark the last entry as wrapping the ring. */
+	tp->rx_ring[i-1].length = PKT_BUF_SZ | DESC_RING_WRAP;
+	tp->rx_ring[i-1].buffer2 = virt_to_bus(&tp->rx_ring[0]);
+
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		/* Note the receive buffer must be longword aligned.
+		   dev_alloc_skb() provides 16 byte alignment.  But do *not*
+		   use skb_reserve() to align the IP header! */
+		struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ);
+		tp->rx_skbuff[i] = skb;
+		if (skb == NULL)
+			break;
+		skb->dev = dev;			/* Mark as being used by this device. */
+		tp->rx_ring[i].status = DescOwned;	/* Owned by Tulip chip */
+		tp->rx_ring[i].buffer1 = virt_to_bus(skb->tail);
+	}
+	tp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
+
+	/* The Tx buffer descriptor is filled in as needed, but we
+	   do need to clear the ownership bit. */
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		tp->tx_skbuff[i] = 0;
+		tp->tx_ring[i].status = 0x00000000;
+		tp->tx_ring[i].buffer2 = virt_to_bus(&tp->tx_ring[i+1]);
+#ifdef CARDBUS
+		if (tp->chip_id == X3201_3)
+			tp->tx_aligned_skbuff[i] = dev_alloc_skb(PKT_BUF_SZ);
+#endif CARDBUS
+	}
+	tp->tx_ring[i-1].buffer2 = virt_to_bus(&tp->tx_ring[0]);
+}
+
+static int
+tulip_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	int entry;
+	u32 flag;
+
+	/* Block a timer-based transmit from overlapping.  This could better be
+	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+		if (jiffies - dev->trans_start < TX_TIMEOUT)
+			return 1;
+		tulip_tx_timeout(dev);
+		return 1;
+	}
+
+	/* Caution: the write order is important here, set the base address
+	   with the "ownership" bits last. */
+
+	/* Calculate the next Tx descriptor entry. */
+	entry = tp->cur_tx % TX_RING_SIZE;
+
+	tp->tx_skbuff[entry] = skb;
+#ifdef CARDBUS
+	if (tp->chip_id == X3201_3) {
+		memcpy(tp->tx_aligned_skbuff[entry]->data,skb->data,skb->len);
+		tp->tx_ring[entry].buffer1 = virt_to_bus(tp->tx_aligned_skbuff[entry]->data);
+	} else
+#endif
+		tp->tx_ring[entry].buffer1 = virt_to_bus(skb->data);
+
+	if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
+		flag = 0x60000000; /* No interrupt */
+	} else if (tp->cur_tx - tp->dirty_tx == TX_RING_SIZE/2) {
+		flag = 0xe0000000; /* Tx-done intr. */
+	} else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) {
+		flag = 0x60000000; /* No Tx-done intr. */
+	} else {
+		/* Leave room for set_rx_mode() to fill entries. */
+		flag = 0xe0000000; /* Tx-done intr. */
+		tp->tx_full = 1;
+	}
+	if (entry == TX_RING_SIZE-1)
+		flag |= 0xe0000000 | DESC_RING_WRAP;
+
+	tp->tx_ring[entry].length = skb->len | flag;
+	tp->tx_ring[entry].status = DescOwned;	/* Pass ownership to the chip. */
+	tp->cur_tx++;
+	if ( ! tp->tx_full)
+		clear_bit(0, (void*)&dev->tbusy);
+
+	/* Trigger an immediate transmit demand. */
+	outl(0, dev->base_addr + CSR1);
+
+	dev->trans_start = jiffies;
+
+	return 0;
+}
+
+/* The interrupt handler does all of the Rx thread work and cleans up
+   after the Tx thread. */
+static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *)dev_instance;
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int csr5, work_budget = max_interrupt_work;
+
+#if defined(__i386__) && defined(SMP_CHECK)
+	if (test_and_set_bit(0, (void*)&dev->interrupt)) {
+		printk(KERN_ERR "%s: Duplicate entry of the interrupt handler by "
+			   "processor %d.\n",
+			   dev->name, hard_smp_processor_id());
+		dev->interrupt = 0;
+		return;
+	}
+#else
+	if (dev->interrupt) {
+		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
+		return;
+	}
+	dev->interrupt = 1;
+#endif
+
+	do {
+		csr5 = inl(ioaddr + CSR5);
+		/* Acknowledge all of the current interrupt sources ASAP. */
+		outl(csr5 & 0x0001ffff, ioaddr + CSR5);
+
+		if (tulip_debug > 4)
+			printk(KERN_DEBUG "%s: interrupt  csr5=%#8.8x new csr5=%#8.8x.\n",
+				   dev->name, csr5, inl(dev->base_addr + CSR5));
+
+		if (csr5 == 0xffffffff)
+			break;	/* all bits set, assume PCMCIA card removed */
+
+		if ((csr5 & (NormalIntr|AbnormalIntr)) == 0)
+			break;
+
+		if (csr5 & (RxIntr | RxNoBuf))
+			work_budget -= tulip_rx(dev);
+
+		if (csr5 & (TxNoBuf | TxDied | TxIntr)) {
+			unsigned int dirty_tx;
+
+			for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0;
+				 dirty_tx++) {
+				int entry = dirty_tx % TX_RING_SIZE;
+				int status = tp->tx_ring[entry].status;
+
+				if (status < 0)
+					break;			/* It still hasn't been Txed */
+				/* Check for Rx filter setup frames. */
+				if (tp->tx_skbuff[entry] == NULL)
+				  continue;
+
+				if (status & 0x8000) {
+					/* There was an major error, log it. */
+#ifndef final_version
+					if (tulip_debug > 1)
+						printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",
+							   dev->name, status);
+#endif
+					tp->stats.tx_errors++;
+					if (status & 0x4104) tp->stats.tx_aborted_errors++;
+					if (status & 0x0C00) tp->stats.tx_carrier_errors++;
+					if (status & 0x0200) tp->stats.tx_window_errors++;
+					if (status & 0x0002) tp->stats.tx_fifo_errors++;
+					if ((status & 0x0080) && tp->full_duplex == 0)
+						tp->stats.tx_heartbeat_errors++;
+#ifdef ETHER_STATS
+					if (status & 0x0100) tp->stats.collisions16++;
+#endif
+				} else {
+#ifdef ETHER_STATS
+					if (status & 0x0001) tp->stats.tx_deferred++;
+#endif
+					tp->stats.tx_bytes += tp->tx_ring[entry].length & 0x7ff;
+					tp->stats.collisions += (status >> 3) & 15;
+					tp->stats.tx_packets++;
+				}
+
+				/* Free the original skb. */
+				dev_free_skb(tp->tx_skbuff[entry]);
+				tp->tx_skbuff[entry] = 0;
+			}
+
+#ifndef final_version
+			if (tp->cur_tx - dirty_tx > TX_RING_SIZE) {
+				printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
+					   dev->name, dirty_tx, tp->cur_tx, tp->tx_full);
+				dirty_tx += TX_RING_SIZE;
+			}
+#endif
+
+			if (tp->tx_full && dev->tbusy
+				&& tp->cur_tx - dirty_tx  < TX_RING_SIZE - 2) {
+				/* The ring is no longer full, clear tbusy. */
+				tp->tx_full = 0;
+				dev->tbusy = 0;
+				mark_bh(NET_BH);
+			}
+
+			tp->dirty_tx = dirty_tx;
+			if (csr5 & TxDied) {
+				if (tulip_debug > 2)
+					printk(KERN_WARNING "%s: The transmitter stopped."
+						   "  CSR5 is %x, CSR6 %x, new CSR6 %x.\n",
+						   dev->name, csr5, inl(ioaddr + CSR6), tp->csr6);
+				outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id);
+				outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id);
+			}
+		}
+
+		/* Log errors. */
+		if (csr5 & AbnormalIntr) {	/* Abnormal error summary bit. */
+			if (csr5 == 0xffffffff)
+				break;
+			if (csr5 & TxJabber) tp->stats.tx_errors++;
+			if (csr5 & TxFIFOUnderflow) {
+				if ((tp->csr6 & 0xC000) != 0xC000)
+					tp->csr6 += 0x4000;	/* Bump up the Tx threshold */
+				else
+					tp->csr6 |= 0x00200000;  /* Store-n-forward. */
+				/* Restart the transmit process. */
+				outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id);
+				outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id);
+			}
+			if (csr5 & RxDied) {		/* Missed a Rx frame. */
+				tp->stats.rx_errors++;
+				tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
+				outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id);
+			}
+			if (csr5 & TimerInt) {
+				if (tulip_debug > 2)
+					printk(KERN_ERR "%s: Re-enabling interrupts, %8.8x.\n",
+						   dev->name, csr5);
+				outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
+			}
+			if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) {
+				if ( tp->chip_id == DC21142)
+					t21142_lnk_change(dev, csr5);
+			}
+			/* Clear all error sources, included undocumented ones! */
+			outl(0x0800f7ba, ioaddr + CSR5);
+		}
+		if (--work_budget < 0) {
+			if (tulip_debug > 1)
+				printk(KERN_WARNING "%s: Too much work during an interrupt, "
+					   "csr5=0x%8.8x.\n", dev->name, csr5);
+			/* Acknowledge all interrupt sources. */
+			outl(0x8001ffff, ioaddr + CSR5);
+#ifdef notdef
+			/* Clear all but standard interrupt sources. */
+			outl((~csr5) & 0x0001ebef, ioaddr + CSR7);
+#endif
+			break;
+		}
+	} while (1);
+
+	if (tulip_debug > 3)
+		printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n",
+			   dev->name, inl(ioaddr + CSR5));
+
+#if defined(__i386__)
+	clear_bit(0, (void*)&dev->interrupt);
+#else
+	dev->interrupt = 0;
+#endif
+	return;
+}
+
+static int
+tulip_rx(struct net_device *dev)
+{
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	int entry = tp->cur_rx % RX_RING_SIZE;
+	int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx;
+	int work_done = 0;
+
+	if (tulip_debug > 4)
+		printk(KERN_DEBUG " In tulip_rx(), entry %d %8.8x.\n", entry,
+			   tp->rx_ring[entry].status);
+	/* If we own the next entry, it's a new packet. Send it up. */
+	while (tp->rx_ring[entry].status >= 0) {
+		s32 status = tp->rx_ring[entry].status;
+
+		if (tulip_debug > 5)
+			printk(KERN_DEBUG " In tulip_rx(), entry %d %8.8x.\n", entry,
+				   tp->rx_ring[entry].status);
+		if (--rx_work_limit < 0)
+			break;
+		if ((status & 0x38008300) != 0x0300) {
+			if ((status & 0x38000300) != 0x0300) {
+				/* Ingore earlier buffers. */
+				if ((status & 0xffff) != 0x7fff) {
+					if (tulip_debug > 1)
+						printk(KERN_WARNING "%s: Oversized Ethernet frame "
+							   "spanned multiple buffers, status %8.8x!\n",
+							   dev->name, status);
+					tp->stats.rx_length_errors++;
+				}
+			} else if (status & RxDescFatalErr) {
+				/* There was a fatal error. */
+				if (tulip_debug > 2)
+					printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n",
+						   dev->name, status);
+				tp->stats.rx_errors++; /* end of a packet.*/
+				if (status & 0x0890) tp->stats.rx_length_errors++;
+				if (status & 0x0004) tp->stats.rx_frame_errors++;
+				if (status & 0x0002) tp->stats.rx_crc_errors++;
+				if (status & 0x0001) tp->stats.rx_fifo_errors++;
+			}
+		} else {
+			/* Omit the four octet CRC from the length. */
+			short pkt_len = ((status >> 16) & 0x7ff) - 4;
+			struct sk_buff *skb;
+
+#ifndef final_version
+			if (pkt_len > 1518) {
+				printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",
+					   dev->name, pkt_len, pkt_len);
+				pkt_len = 1518;
+				tp->stats.rx_length_errors++;
+			}
+#endif
+			/* Check if the packet is long enough to accept without copying
+			   to a minimally-sized skbuff. */
+			if (pkt_len < rx_copybreak
+				&& (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+				skb->dev = dev;
+				skb_reserve(skb, 2);	/* 16 byte align the IP header */
+#if ! defined(__alpha__)
+				eth_copy_and_sum(skb, bus_to_virt(tp->rx_ring[entry].buffer1),
+								 pkt_len, 0);
+				skb_put(skb, pkt_len);
+#else
+				memcpy(skb_put(skb, pkt_len),
+					   bus_to_virt(tp->rx_ring[entry].buffer1), pkt_len);
+#endif
+				work_done++;
+			} else { 	/* Pass up the skb already on the Rx ring. */
+				char *temp = skb_put(skb = tp->rx_skbuff[entry], pkt_len);
+				tp->rx_skbuff[entry] = NULL;
+#ifndef final_version
+				if (bus_to_virt(tp->rx_ring[entry].buffer1) != temp)
+					printk(KERN_ERR "%s: Internal fault: The skbuff addresses "
+						   "do not match in tulip_rx: %p vs. %p / %p.\n",
+						   dev->name, bus_to_virt(tp->rx_ring[entry].buffer1),
+						   skb->head, temp);
+#endif
+			}
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
+			dev->last_rx = jiffies;
+			tp->stats.rx_packets++;
+			tp->stats.rx_bytes += pkt_len;
+		}
+		entry = (++tp->cur_rx) % RX_RING_SIZE;
+	}
+
+	/* Refill the Rx ring buffers. */
+	for (; tp->cur_rx - tp->dirty_rx > 0; tp->dirty_rx++) {
+		entry = tp->dirty_rx % RX_RING_SIZE;
+		if (tp->rx_skbuff[entry] == NULL) {
+			struct sk_buff *skb;
+			skb = tp->rx_skbuff[entry] = dev_alloc_skb(PKT_BUF_SZ);
+			if (skb == NULL)
+				break;
+			skb->dev = dev;			/* Mark as being used by this device. */
+			tp->rx_ring[entry].buffer1 = virt_to_bus(skb->tail);
+			work_done++;
+		}
+		tp->rx_ring[entry].status = DescOwned;
+	}
+
+	return work_done;
+}
+
+static void
+tulip_down(struct net_device *dev)
+{
+	long ioaddr = dev->base_addr;
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+
+	dev->start = 0;
+	dev->tbusy = 1;
+
+	/* Disable interrupts by clearing the interrupt mask. */
+	outl(0x00000000, ioaddr + CSR7);
+	/* Stop the chip's Tx and Rx processes. */
+	outl_CSR6(inl(ioaddr + CSR6) & ~0x2002, ioaddr, tp->chip_id);
+	/* 21040 -- Leave the card in 10baseT state. */
+	if (tp->chip_id == DC21040)
+		outl(0x00000004, ioaddr + CSR13);
+
+	if (inl(ioaddr + CSR6) != 0xffffffff)
+		tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
+
+	del_timer(&tp->timer);
+
+	dev->if_port = tp->saved_if_port;
+}
+
+static int
+tulip_close(struct net_device *dev)
+{
+	long ioaddr = dev->base_addr;
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	int i;
+
+	if (tulip_debug > 1)
+		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
+			   dev->name, inl(ioaddr + CSR5));
+
+	if (dev->start)
+		tulip_down(dev);
+
+	free_irq(dev->irq, dev);
+
+	/* Free all the skbuffs in the Rx queue. */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		struct sk_buff *skb = tp->rx_skbuff[i];
+		tp->rx_skbuff[i] = 0;
+		tp->rx_ring[i].status = 0;		/* Not owned by Tulip chip. */
+		tp->rx_ring[i].length = 0;
+		tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */
+		if (skb) {
+			dev_free_skb(skb);
+		}
+	}
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		if (tp->tx_skbuff[i])
+			dev_free_skb(tp->tx_skbuff[i]);
+		tp->tx_skbuff[i] = 0;
+	}
+
+	MOD_DEC_USE_COUNT;
+	tp->open = 0;
+	return 0;
+}
+
+static struct net_device_stats *tulip_get_stats(struct net_device *dev)
+{
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+
+	if (dev->start)
+		tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
+
+	return &tp->stats;
+}
+
+#ifdef HAVE_PRIVATE_IOCTL
+/* Provide ioctl() calls to examine the MII xcvr state. */
+static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	u16 *data = (u16 *)&rq->ifr_data;
+	int phy = tp->phys[0] & 0x1f;
+	long flags;
+
+	switch(cmd) {
+	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
+		if (tp->mii_cnt)
+			data[0] = phy;
+		else if (tp->chip_id == DC21142)	/* 21142 pseudo-MII */
+			data[0] = 32;
+		else if (tp->chip_id == PNIC2)
+			data[0] = 32;
+		else if (tp->chip_id == COMET)
+			data[0] = 1;
+		else
+			return -ENODEV;
+		return 0;
+	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
+		if (data[0] == 32  &&
+			(tp->chip_id == DC21142 || tp->chip_id == PNIC2)) {
+			int csr12 = inl(ioaddr + CSR12);
+			int csr14 = inl(ioaddr + CSR14);
+			switch (data[1]) {
+			case 0: {
+				data[3] = (csr14<<5) & 0x1000;
+				break; }
+			case 1:
+				data[3] = 0x7848 + ((csr12&0x7000) == 0x5000 ? 0x20 : 0)
+					+ (csr12&0x06 ? 0x04 : 0);
+				break;
+			case 4: {
+				data[3] = ((csr14>>9)&0x0380) +
+					((inl(ioaddr + CSR6)>>3)&0x0040) +((csr14>>1)&0x20) + 1;
+				break;
+			}
+			case 5: data[3] = csr12 >> 16; break;
+			default: data[3] = 0; break;
+			}
+		} else {
+			save_flags(flags);
+			cli();
+			data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
+			restore_flags(flags);
+		}
+		return 0;
+	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+#if defined(CAP_NET_ADMIN)
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+#else
+		if (!suser())
+			return -EPERM;
+#endif
+		if (data[0] == 32  &&  tp->chip_id == DC21142) {
+			if (data[1] == 5)
+				tp->to_advertise = data[2];
+		} else {
+			save_flags(flags);
+			cli();
+			mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+			restore_flags(flags);
+		}
+		return 0;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return -EOPNOTSUPP;
+}
+#endif  /* HAVE_PRIVATE_IOCTL */
+
+/* Set or clear the multicast filter for this adaptor.
+   Note that we only use exclusion around actually queueing the
+   new frame, not around filling tp->setup_frame.  This is non-deterministic
+   when re-entered but still correct. */
+
+/* The little-endian AUTODIN32 ethernet CRC calculation.
+   N.B. Do not use for bulk data, use a table-based routine instead.
+   This is common code and should be moved to net/core/crc.c */
+static unsigned const ethernet_polynomial_le = 0xedb88320U;
+static inline u32 ether_crc_le(int length, unsigned char *data)
+{
+	u32 crc = 0xffffffff;	/* Initial value. */
+	while(--length >= 0) {
+		unsigned char current_octet = *data++;
+		int bit;
+		for (bit = 8; --bit >= 0; current_octet >>= 1) {
+			if ((crc ^ current_octet) & 1) {
+				crc >>= 1;
+				crc ^= ethernet_polynomial_le;
+			} else
+				crc >>= 1;
+		}
+	}
+	return crc;
+}
+static unsigned const ethernet_polynomial = 0x04c11db7U;
+static inline u32 ether_crc(int length, unsigned char *data)
+{
+    int crc = -1;
+
+    while(--length >= 0) {
+		unsigned char current_octet = *data++;
+		int bit;
+		for (bit = 0; bit < 8; bit++, current_octet >>= 1)
+			crc = (crc << 1) ^
+				((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);
+    }
+    return crc;
+}
+
+static void set_rx_mode(struct net_device *dev)
+{
+	long ioaddr = dev->base_addr;
+	int csr6 = inl(ioaddr + CSR6) & ~0x00D5;
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+
+	tp->csr6 &= ~0x00D5;
+	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
+		tp->csr6 |= 0x00C0;
+		csr6 |= 0x00C0;
+		/* Unconditionally log net taps. */
+		printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);
+	} else if ((dev->mc_count > 1000)  ||  (dev->flags & IFF_ALLMULTI)) {
+		/* Too many to filter well -- accept all multicasts. */
+		tp->csr6 |= 0x0080;
+		csr6 |= 0x0080;
+	} else	if (tulip_tbl[tp->chip_id].flags & MC_HASH_ONLY) {
+		/* Some work-alikes have only a 64-entry hash filter table. */
+		/* Should verify correctness on big-endian/__powerpc__ */
+		struct dev_mc_list *mclist;
+		int i;
+		u32 mc_filter[2];		 /* Multicast hash filter */
+		if (dev->mc_count > 64) {		/* Arbitrary non-effective limit. */
+			tp->csr6 |= 0x0080;
+			csr6 |= 0x0080;
+		} else {
+			mc_filter[1] = mc_filter[0] = 0;
+			for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+				 i++, mclist = mclist->next)
+				set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr)>>26, mc_filter);
+			if (tp->chip_id == AX88140) {
+				outl(2, ioaddr + CSR13);
+				outl(mc_filter[0], ioaddr + CSR14);
+				outl(3, ioaddr + CSR13);
+				outl(mc_filter[1], ioaddr + CSR14);
+			} else if (tp->chip_id == COMET) { /* Has a simple hash filter. */
+				outl(mc_filter[0], ioaddr + 0xAC);
+				outl(mc_filter[1], ioaddr + 0xB0);
+			}
+		}
+	} else {
+		u16 *eaddrs, *setup_frm = tp->setup_frame;
+		struct dev_mc_list *mclist;
+		u32 tx_flags = 0x08000000 | 192;
+		int i;
+
+		/* Note that only the low-address shortword of setup_frame is valid!
+		   The values are doubled for big-endian architectures. */
+		if ((dev->mc_count > 14) || ((dev->mc_count > 6) && (tp->chip_id == X3201_3))) { /* Must use a multicast hash table. */
+			u16 hash_table[32];
+			tx_flags = 0x08400000 | 192;		/* Use hash filter. */
+			memset(hash_table, 0, sizeof(hash_table));
+			set_bit(255, hash_table); 			/* Broadcast entry */
+			/* This should work on big-endian machines as well. */
+			for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+				 i++, mclist = mclist->next)
+				set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff,
+						hash_table);
+			for (i = 0; i < 32; i++) {
+				*setup_frm++ = hash_table[i];
+				*setup_frm++ = hash_table[i];
+			}
+			setup_frm = &tp->setup_frame[13*6];
+		} else if(tp->chip_id != X3201_3) {
+			/* We have <= 14 addresses so we can use the wonderful
+			   16 address perfect filtering of the Tulip. */
+			for (i = 0, mclist = dev->mc_list; i < dev->mc_count;
+				 i++, mclist = mclist->next) {
+				eaddrs = (u16 *)mclist->dmi_addr;
+				*setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];
+				*setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];
+				*setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];
+			}
+			/* Fill the unused entries with the broadcast address. */
+			memset(setup_frm, 0xff, (15-i)*12);
+			setup_frm = &tp->setup_frame[15*6];
+		} else {
+			/* fill the first two table entries with our address */
+			eaddrs = (u16 *)dev->dev_addr;
+			for(i=0; i<2; i++) {
+				*setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];
+				*setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];
+				*setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];
+			}
+			/* Double fill each entry to accomodate chips that */
+			/* don't like to parse these correctly */
+			for (i=0, mclist=dev->mc_list; i<dev->mc_count;
+				 i++, mclist=mclist->next) {
+				eaddrs = (u16 *)mclist->dmi_addr;
+				*setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];
+				*setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];
+				*setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];
+				*setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];
+				*setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];
+				*setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];
+			}
+			i=((i+1)*2);
+			/* Fill the unused entries with the broadcast address. */
+			memset(setup_frm, 0xff, (15-i)*12);
+			setup_frm = &tp->setup_frame[15*6];
+		}
+
+		/* Fill the final entry with our physical address. */
+		eaddrs = (u16 *)dev->dev_addr;
+		*setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];
+		*setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];
+		*setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];
+		/* Now add this frame to the Tx list. */
+		if (tp->cur_tx - tp->dirty_tx > TX_RING_SIZE - 2) {
+			/* Same setup recently queued, we need not add it. */
+		} else {
+			unsigned long flags;
+			unsigned int entry, dummy = -1;
+
+			save_flags(flags); cli();
+			entry = tp->cur_tx++ % TX_RING_SIZE;
+
+			if (entry != 0) {
+				/* Avoid a chip errata by prefixing a dummy entry. */
+				tp->tx_skbuff[entry] = 0;
+				tp->tx_ring[entry].length =
+					(entry == TX_RING_SIZE-1) ? DESC_RING_WRAP : 0;
+				tp->tx_ring[entry].buffer1 = 0;
+				/* race with chip, set DescOwned later */
+				dummy = entry;
+				entry = tp->cur_tx++ % TX_RING_SIZE;
+			}
+
+			tp->tx_skbuff[entry] = 0;
+			/* Put the setup frame on the Tx list. */
+			if (entry == TX_RING_SIZE-1)
+				tx_flags |= DESC_RING_WRAP;		/* Wrap ring. */
+			tp->tx_ring[entry].length = tx_flags;
+			if(tp->chip_id == X3201_3)
+				tp->tx_ring[entry].buffer1 = (virt_to_bus(tp->setup_frame) + 4);
+			else
+				tp->tx_ring[entry].buffer1 = virt_to_bus(tp->setup_frame);
+			tp->tx_ring[entry].status = DescOwned;
+			if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) {
+				set_bit(0, (void*)&dev->tbusy);
+				tp->tx_full = 1;
+			}
+			if (dummy >= 0)
+				tp->tx_ring[dummy].status = DescOwned;
+			restore_flags(flags);
+			/* Trigger an immediate transmit demand. */
+			outl(0, ioaddr + CSR1);
+		}
+	}
+	outl_CSR6(csr6 | 0x0000, ioaddr, tp->chip_id);
+}
+
+#ifdef CARDBUS
+
+#include <pcmcia/driver_ops.h>
+
+static dev_node_t *tulip_attach(dev_locator_t *loc)
+{
+	struct net_device *dev;
+	u16 dev_id;
+	u16 vendor_id;
+	u32 io;
+	u8 bus, devfn, irq;
+
+	if (loc->bus != LOC_PCI) return NULL;
+	bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
+	printk(KERN_INFO "tulip_attach(bus %d, function %d)\n", bus, devfn);
+	pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
+	pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
+	pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
+	pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor_id);
+	if (dev_id == 0x0003 && vendor_id == 0x115d) 
+		dev = tulip_probe1(bus, devfn, NULL, io & ~3, irq, X3201_3, 0);
+	else
+		dev = tulip_probe1(bus, devfn, NULL, io & ~3, irq, DC21142, 0);
+	if (dev) {
+		dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
+		strcpy(node->dev_name, dev->name);
+		node->major = node->minor = 0;
+		node->next = NULL;
+		MOD_INC_USE_COUNT;
+		return node;
+	}
+	return NULL;
+}
+
+static void tulip_suspend(dev_node_t *node)
+{
+	struct net_device *dev, *next;
+	printk(KERN_INFO "tulip_suspend(%s)\n", node->dev_name);
+	for (dev = root_tulip_dev; dev; dev = next) {
+		next = ((struct tulip_private *)dev->priv)->next_module;
+		if (strcmp(dev->name, node->dev_name) == 0) break;
+	}
+	if (dev) {
+		struct tulip_private *tp = (struct tulip_private *)dev->priv;
+		if (tp->open) tulip_down(dev);
+	}
+}
+
+static void tulip_resume(dev_node_t *node)
+{
+	struct net_device *dev, *next;
+	printk(KERN_INFO "tulip_resume(%s)\n", node->dev_name);
+	for (dev = root_tulip_dev; dev; dev = next) {
+		next = ((struct tulip_private *)dev->priv)->next_module;
+		if (strcmp(dev->name, node->dev_name) == 0) break;
+	}
+	if (dev) {
+		struct tulip_private *tp = (struct tulip_private *)dev->priv;
+		if (tp->open) tulip_up(dev);
+	}
+}
+
+static void tulip_detach(dev_node_t *node)
+{
+	struct net_device **devp, **next;
+	printk(KERN_INFO "tulip_detach(%s)\n", node->dev_name);
+	for (devp = &root_tulip_dev; *devp; devp = next) {
+		next = &((struct tulip_private *)(*devp)->priv)->next_module;
+		if (strcmp((*devp)->name, node->dev_name) == 0) break;
+	}
+	if (*devp) {
+		struct net_device *dev = *devp;
+		struct tulip_private *tp = dev->priv;
+		unregister_netdev(dev);
+		kfree(dev);
+		kfree(tp);
+		*devp = *next;
+		kfree(node);
+		MOD_DEC_USE_COUNT;
+	}
+}
+
+struct driver_operations tulip_ops = {
+	"tulip_cb", tulip_attach, tulip_suspend, tulip_resume, tulip_detach
+};
+
+#endif  /* Cardbus support */
+
+#ifdef MODULE
+int init_module(void)
+{
+#ifdef CARDBUS
+	reverse_probe = 0;			/* Not used. */
+	register_driver(&tulip_ops);
+	return 0;
+#else
+	return tulip_probe(NULL);
+#endif
+}
+
+void cleanup_module(void)
+{
+	struct net_device *next_dev;
+
+#ifdef CARDBUS
+	unregister_driver(&tulip_ops);
+#endif
+
+	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+	while (root_tulip_dev) {
+		struct tulip_private *tp = (struct tulip_private *)root_tulip_dev->priv;
+		next_dev = tp->next_module;
+		unregister_netdev(root_tulip_dev);
+		release_region(root_tulip_dev->base_addr,
+					   tulip_tbl[tp->chip_id].io_size);
+		kfree(root_tulip_dev);
+		root_tulip_dev = next_dev;
+	}
+}
+
+#endif  /* MODULE */
+
+/*
+ * Local variables:
+ *  SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c tulip.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c tulip.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ *  cardbus-compile-command: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c tulip.c -o tulip_cb.o -I/usr/src/pcmcia-cs-3.0.9/include/"
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
diff -u --recursive --new-file v2.3.26/linux/drivers/net/pcmcia/wavelan_cs.h linux/drivers/net/pcmcia/wavelan_cs.h
--- v2.3.26/linux/drivers/net/pcmcia/wavelan_cs.h	Fri Oct 22 13:21:49 1999
+++ linux/drivers/net/pcmcia/wavelan_cs.h	Thu Nov 11 16:03:37 1999
@@ -122,7 +122,7 @@
  * Yunzhou Li <yunzhou@strat.iol.unh.edu> finished is work.
  * Joe Finney <joe@comp.lancs.ac.uk> patched the driver to start
  * correctly 2.00 cards (2.4 GHz with frequency selection).
- * David Hinds <dhinds@hyper.stanford.edu> integrated the whole in his
+ * David Hinds <dhinds@pcmcia.sourceforge.org> integrated the whole in his
  * Pcmcia package (+ bug corrections).
  *
  * I (Jean Tourrilhes - jt@hplb.hpl.hp.com) then started to make some
@@ -174,7 +174,7 @@
  *	Matthew Geier (matthew@cs.su.oz.au),
  *	Remo di Giovanni (remo@cs.su.oz.au),
  *	Mark Hagan (mhagan@wtcpost.daytonoh.NCR.COM),
- *	David Hinds <dhinds@hyper.stanford.edu>,
+ *	David Hinds <dhinds@pcmcia.sourceforge.org>,
  *	Jan Hoogendoorn (c/o marteijn@lucent.com),
  *      Bruce Janson <bruce@cs.usyd.edu.au>,
  *	Anthony D. Joseph <adj@lcs.mit.edu>,
diff -u --recursive --new-file v2.3.26/linux/drivers/net/pcmcia/xirc2ps_cs.c linux/drivers/net/pcmcia/xirc2ps_cs.c
--- v2.3.26/linux/drivers/net/pcmcia/xirc2ps_cs.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/net/pcmcia/xirc2ps_cs.c	Thu Nov 11 16:03:37 1999
@@ -83,10 +83,6 @@
 /* Enable the bug fix for CEM56 to use modem and ethernet simultaneously */
 #define CEM56_FIX
 
-#if !defined(PCMCIA_DEBUG) && 0
-  #define PCMCIA_DEBUG 4
-#endif
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -250,6 +246,9 @@
 #ifdef PCMCIA_DEBUG
 static int pc_debug = PCMCIA_DEBUG;
 MODULE_PARM(pc_debug, "i");
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KDBG_XIRC args)
+#else
+#define DEBUG(n, args...)
 #endif
 static char *version =
 "xirc2ps_cs.c 1.31 1998/12/09 19:32:55 (dd9jn+kvh)";
@@ -313,11 +312,11 @@
 /* MII management prototypes */
 static void mii_idle(ioaddr_t ioaddr);
 static void mii_putbit(ioaddr_t ioaddr, unsigned data);
-static int  mii_getbit( ioaddr_t ioaddr );
+static int  mii_getbit(ioaddr_t ioaddr);
 static void mii_wbits(ioaddr_t ioaddr, unsigned data, int len);
 static unsigned mii_rd(ioaddr_t ioaddr,	u_char phyaddr, u_char phyreg);
 static void mii_wr(ioaddr_t ioaddr, u_char phyaddr, u_char phyreg,
-				   unsigned data, int len);
+		   unsigned data, int len);
 
 /*
  * The event() function is this driver's Card Services event handler.
@@ -396,6 +395,7 @@
     int silicon; /* silicon revision. 0=old CE2, 1=Scipper, 4=Mohawk */
     int mohawk;  /* a CE3 type card */
     int dingo;	 /* a CEM56 type card */
+    int new_mii; /* has full 10baseT/100baseT MII */
     int modem;	 /* is a multi function card (i.e with a modem) */
     caddr_t dingo_ccr; /* only used for CEM56 cards */
     int suspended;
@@ -411,7 +411,7 @@
 static void set_addresses(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 static int do_init(struct net_device *dev);
-static int set_card_type( dev_link_t *link, const void *s );
+static int set_card_type(dev_link_t *link, const void *s);
 static int do_config(struct net_device *dev, struct ifmap *map);
 static int do_open(struct net_device *dev);
 static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -441,11 +441,11 @@
 }
 
 static int
-get_tuple_data(int fn, client_handle_t handle, tuple_t *tuple )
+get_tuple_data(int fn, client_handle_t handle, tuple_t *tuple)
 {
     int err;
 
-    if( (err=CardServices(fn, handle, tuple)) )
+    if ((err=CardServices(fn, handle, tuple)))
 	return err;
     return CardServices(GetTupleData, handle, tuple);
 }
@@ -455,7 +455,7 @@
 {
     int err;
 
-    if( (err=get_tuple_data(fn, handle, tuple)) )
+    if ((err=get_tuple_data(fn, handle, tuple)))
 	return err;
     return CardServices(ParseTuple, handle, tuple, parse);
 }
@@ -477,7 +477,7 @@
 
     save_flags(flags);
     sti();
-    while(timeout >= jiffies)
+    while (timeout >= jiffies)
 	;
     restore_flags(flags);
 }
@@ -489,27 +489,27 @@
 {
     ioaddr_t ioaddr = dev->base_addr;
 
-    if(pc_debug > 1) {
+    if (pc_debug > 1) {
 	int i, page;
 
 	printk(KDBG_XIRC "Register  common: ");
-	for(i = 0; i < 8; i++ )
-	    printk(" %2.2x", GetByte(i) );
+	for (i = 0; i < 8; i++)
+	    printk(" %2.2x", GetByte(i));
 	printk("\n");
-	for(page = 0; page <= 8; page++) {
+	for (page = 0; page <= 8; page++) {
 	    printk(KDBG_XIRC "Register page %2x: ", page);
 	    SelectPage(page);
-	    for(i = 8; i < 16; i++)
+	    for (i = 8; i < 16; i++)
 		printk(" %2.2x", GetByte(i));
 	    printk("\n");
 	}
-	for(page=0x40 ; page <= 0x5f; page++) {
-	    if( page == 0x43 || (page >= 0x46 && page <= 0x4f)
-		|| (page >= 0x51 && page <=0x5e) )
+	for (page=0x40 ; page <= 0x5f; page++) {
+	    if (page == 0x43 || (page >= 0x46 && page <= 0x4f)
+		|| (page >= 0x51 && page <=0x5e))
 		continue;
 	    printk(KDBG_XIRC "Register page %2x: ", page);
 	    SelectPage(page);
-	    for(i = 8; i < 16; i++)
+	    for (i = 8; i < 16; i++)
 		printk(" %2.2x", GetByte(i));
 	    printk("\n");
 	}
@@ -525,9 +525,9 @@
 static void
 mii_idle(ioaddr_t ioaddr)
 {
-    PutByte(XIRCREG2_GPR2, 0x04|0 ); /* drive MDCK low */
+    PutByte(XIRCREG2_GPR2, 0x04|0); /* drive MDCK low */
     udelay(1);
-    PutByte(XIRCREG2_GPR2, 0x04|1 ); /* and drive MDCK high */
+    PutByte(XIRCREG2_GPR2, 0x04|1); /* and drive MDCK high */
     udelay(1);
 }
 
@@ -538,29 +538,27 @@
 mii_putbit(ioaddr_t ioaddr, unsigned data)
 {
   #if 1
-    if( data ) {
-	PutByte(XIRCREG2_GPR2, 0x0c|2|0 ); /* set MDIO */
+    if (data) {
+	PutByte(XIRCREG2_GPR2, 0x0c|2|0); /* set MDIO */
 	udelay(1);
-	PutByte(XIRCREG2_GPR2, 0x0c|2|1 ); /* and drive MDCK high */
+	PutByte(XIRCREG2_GPR2, 0x0c|2|1); /* and drive MDCK high */
 	udelay(1);
-    }
-    else {
-	PutByte(XIRCREG2_GPR2, 0x0c|0|0 ); /* clear MDIO */
+    } else {
+	PutByte(XIRCREG2_GPR2, 0x0c|0|0); /* clear MDIO */
 	udelay(1);
-	PutByte(XIRCREG2_GPR2, 0x0c|0|1 ); /* and drive MDCK high */
+	PutByte(XIRCREG2_GPR2, 0x0c|0|1); /* and drive MDCK high */
 	udelay(1);
     }
   #else
-    if( data ) {
-	PutWord(XIRCREG2_GPR2-1, 0x0e0e );
+    if (data) {
+	PutWord(XIRCREG2_GPR2-1, 0x0e0e);
 	udelay(1);
-	PutWord(XIRCREG2_GPR2-1, 0x0f0f );
+	PutWord(XIRCREG2_GPR2-1, 0x0f0f);
 	udelay(1);
-    }
-    else {
-	PutWord(XIRCREG2_GPR2-1, 0x0c0c );
+    } else {
+	PutWord(XIRCREG2_GPR2-1, 0x0c0c);
 	udelay(1);
-	PutWord(XIRCREG2_GPR2-1, 0x0d0d );
+	PutWord(XIRCREG2_GPR2-1, 0x0d0d);
 	udelay(1);
     }
   #endif
@@ -570,14 +568,14 @@
  * Get a bit from MDI/O
  */
 static int
-mii_getbit( ioaddr_t ioaddr )
+mii_getbit(ioaddr_t ioaddr)
 {
     unsigned d;
 
-    PutByte(XIRCREG2_GPR2, 4|0 ); /* drive MDCK low */
+    PutByte(XIRCREG2_GPR2, 4|0); /* drive MDCK low */
     udelay(1);
     d = GetByte(XIRCREG2_GPR2); /* read MDIO */
-    PutByte(XIRCREG2_GPR2, 4|1 ); /* drive MDCK high again */
+    PutByte(XIRCREG2_GPR2, 4|1); /* drive MDCK high again */
     udelay(1);
     return d & 0x20; /* read MDIO */
 }
@@ -586,8 +584,8 @@
 mii_wbits(ioaddr_t ioaddr, unsigned data, int len)
 {
     unsigned m = 1 << (len-1);
-    for( ; m; m >>= 1)
-	mii_putbit( ioaddr, data & m );
+    for (; m; m >>= 1)
+	mii_putbit(ioaddr, data & m);
 }
 
 static unsigned
@@ -597,16 +595,16 @@
     unsigned data=0, m;
 
     SelectPage(2);
-    for( i=0; i < 32; i++ )		/* 32 bit preamble */
+    for (i=0; i < 32; i++)		/* 32 bit preamble */
 	mii_putbit(ioaddr, 1);
     mii_wbits(ioaddr, 0x06, 4); 	/* Start and opcode for read */
     mii_wbits(ioaddr, phyaddr, 5);	/* PHY address to be accessed */
     mii_wbits(ioaddr, phyreg, 5);	/* PHY register to read */
     mii_idle(ioaddr);			/* turn around */
-    mii_getbit( ioaddr);
+    mii_getbit(ioaddr);
 
-    for( m = 1<<15; m; m >>= 1 )
-	if( mii_getbit( ioaddr ) )
+    for (m = 1<<15; m; m >>= 1)
+	if (mii_getbit(ioaddr))
 	    data |= m;
     mii_idle(ioaddr);
     return data;
@@ -618,7 +616,7 @@
     int i;
 
     SelectPage(2);
-    for( i=0; i < 32; i++ )		/* 32 bit preamble */
+    for (i=0; i < 32; i++)		/* 32 bit preamble */
 	mii_putbit(ioaddr, 1);
     mii_wbits(ioaddr, 0x05, 4); 	/* Start and opcode for write */
     mii_wbits(ioaddr, phyaddr, 5);	/* PHY address to be accessed */
@@ -640,13 +638,13 @@
      * not be read according to the DP83840A specs.
      */
     printk(KERN_DEBUG "%s: MII register dump:\n", dev->name);
-    for(i=0; i < 32; i++ ) {
-	if( !(i % 8) ) {
-	    if( i )
+    for (i=0; i < 32; i++) {
+	if (!(i % 8)) {
+	    if (i)
 		printk("\n");
-	    printk(KERN_DEBUG "%s:", dev->name );
+	    printk(KERN_DEBUG "%s:", dev->name);
 	}
-	printk(" %04x", mii_rd(ioaddr, 0, i) );
+	printk(" %04x", mii_rd(ioaddr, 0, i));
     }
     printk("\n");
 }
@@ -673,10 +671,7 @@
     local_info_t *local;
     int err;
 
-  #ifdef PCMCIA_DEBUG
-    if(pc_debug)
-	printk(KDBG_XIRC "attach()\n");
-  #endif
+    DEBUG(0, "attach()\n");
     flush_stale_links();
 
     /* Initialize the dev_link_t structure */
@@ -725,7 +720,7 @@
     client_reg.event_handler = &xirc2ps_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
-    if( (err = CardServices(RegisterClient, &link->handle, &client_reg)) ) {
+    if ((err = CardServices(RegisterClient, &link->handle, &client_reg))) {
 	cs_error(link->handle, RegisterClient, err);
 	xirc2ps_detach(link);
 	return NULL;
@@ -747,25 +742,20 @@
     dev_link_t **linkp;
     long flags;
 
-  #ifdef PCMCIA_DEBUG
-    if(pc_debug)
-	printk(KDBG_XIRC "detach(0x%p)\n", link);
-  #endif
+    DEBUG(0, "detach(0x%p)\n", link);
 
     /* Locate device structure */
-    for( linkp = &dev_list; *linkp; linkp = &(*linkp)->next )
-	if( *linkp == link)
+    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+	if (*linkp == link)
 	    break;
-    if( !*linkp ) {
-      #ifdef PCMCIA_DEBUG
-	printk(KDBG_XIRC "detach(0x%p): dev_link lost\n", link );
-      #endif
+    if (!*linkp) {
+	DEBUG(0, "detach(0x%p): dev_link lost\n", link);
 	return;
     }
 
     save_flags(flags);
     cli();
-    if( link->state & DEV_RELEASE_PENDING ) {
+    if (link->state & DEV_RELEASE_PENDING) {
 	del_timer(&link->release);
 	link->state &= ~DEV_RELEASE_PENDING;
     }
@@ -777,26 +767,24 @@
      * the release() function is called, that will trigger a proper
      * detach().
      */
-    if(link->state & DEV_CONFIG) {
-      #ifdef PCMCIA_DEBUG
-	printk(KDBG_XIRC "detach postponed, '%s' "
-			  "still locked\n", link->dev->dev_name);
-      #endif
+    if (link->state & DEV_CONFIG) {
+	DEBUG(0, "detach postponed, '%s' still locked\n",
+	      link->dev->dev_name);
 	link->state |= DEV_STALE_LINK;
 	return;
     }
 
     /* Break the link with Card Services */
-    if(link->handle)
+    if (link->handle)
 	CardServices(DeregisterClient, link->handle);
 
     /* Unlink device structure, free pieces */
     *linkp = link->next;
-    if(link->priv) {
+    if (link->priv) {
 	struct net_device *dev = link->priv;
 	if (link->dev != NULL)
 	    unregister_netdev(dev);
-	if( dev->priv )
+	if (dev->priv)
 	    kfree(dev->priv);
 	kfree(link->priv);
     }
@@ -823,7 +811,7 @@
  *
  */
 static int
-set_card_type( dev_link_t *link, const void *s )
+set_card_type(dev_link_t *link, const void *s)
 {
     struct net_device *dev = link->priv;
     local_info_t *local = dev->priv;
@@ -833,27 +821,24 @@
     unsigned mediaid= ((const unsigned char *)s)[3];
     unsigned prodid = ((const unsigned char *)s)[4];
 
-  #ifdef PCMCIA_DEBUG
-    if(pc_debug)
-	printk(KDBG_XIRC "cisrev=%02x mediaid=%02x prodid=%02x\n",
-			  cisrev, mediaid, prodid );
-  #endif
+    DEBUG(0, "cisrev=%02x mediaid=%02x prodid=%02x\n",
+	  cisrev, mediaid, prodid);
 
     local->mohawk = 0;
     local->dingo = 0;
     local->modem = 0;
     local->card_type = XIR_UNKNOWN;
-    if( !(prodid & 0x40) ) {
+    if (!(prodid & 0x40)) {
 	printk(KNOT_XIRC "Ooops: Not a creditcard\n");
 	return 0;
     }
-    if( !(mediaid & 0x01) ) {
+    if (!(mediaid & 0x01)) {
 	printk(KNOT_XIRC "Not an Ethernet card\n");
 	return 0;
     }
-    if( mediaid & 0x10 ) {
+    if (mediaid & 0x10) {
 	local->modem = 1;
-	switch( prodid & 15 ) {
+	switch(prodid & 15) {
 	  case 1: local->card_type = XIR_CEM   ; break;
 	  case 2: local->card_type = XIR_CEM2  ; break;
 	  case 3: local->card_type = XIR_CEM3  ; break;
@@ -868,9 +853,8 @@
 		  local->dingo = 1;
 		  break;
 	}
-    }
-    else {
-	switch( prodid & 15 ) {
+    } else {
+	switch(prodid & 15) {
 	  case 1: local->card_type = has_ce2_string(link)? XIR_CE2 : XIR_CE ;
 		  break;
 	  case 2: local->card_type = XIR_CE2; break;
@@ -879,13 +863,13 @@
 		  break;
 	}
     }
-    if( local->card_type == XIR_CE || local->card_type == XIR_CEM ) {
+    if (local->card_type == XIR_CE || local->card_type == XIR_CEM) {
 	printk(KNOT_XIRC "Sorry, this is an old CE card\n");
 	return 0;
     }
-    if( local->card_type == XIR_UNKNOWN )
-	printk(KNOT_XIRC "Warning: Unknown card (mediaid=%02x prodid=%02x)\n",
-				  mediaid, prodid );
+    if (local->card_type == XIR_UNKNOWN)
+	printk(KNOT_XIRC "unknown card (mediaid=%02x prodid=%02x)\n",
+	       mediaid, prodid);
 
     return 1;
 }
@@ -908,8 +892,8 @@
     tuple.TupleDataMax = 254;
     tuple.TupleOffset = 0;
     tuple.DesiredTuple = CISTPL_VERS_1;
-    if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 2 ) {
-	if( strstr(parse.version_1.str + parse.version_1.ofs[2], "CE2") )
+    if (!first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 2) {
+	if (strstr(parse.version_1.str + parse.version_1.ofs[2], "CE2"))
 	    return 1;
     }
     return 0;
@@ -939,10 +923,7 @@
     local = dev->priv;
     local->dingo_ccr = 0;
 
-  #ifdef PCMCIA_DEBUG
-    if(pc_debug)
-	printk(KDBG_XIRC "config(0x%p)\n", link);
-  #endif
+    DEBUG(0, "config(0x%p)\n", link);
 
     /*
      * This reads the card's CONFIG tuple to find its configuration
@@ -955,101 +936,89 @@
 
     /* Is this a valid	card */
     tuple.DesiredTuple = CISTPL_MANFID;
-    if( (err=first_tuple(handle, &tuple, &parse))) {
+    if ((err=first_tuple(handle, &tuple, &parse))) {
 	printk(KNOT_XIRC "manfid not found in CIS\n");
 	goto failure;
     }
 
-    switch( parse.manfid.manf ) {
+    switch(parse.manfid.manf) {
       case MANFID_XIRCOM:
 	local->manf_str = "Xircom";
-	#ifdef PCMCIA_DEBUG
-	  if(pc_debug)
-	    printk(KDBG_XIRC "found xircom card\n");
-	#endif
+	DEBUG(0, "found xircom card\n");
 	break;
       case MANFID_ACCTON:
 	local->manf_str = "Accton";
-	#ifdef PCMCIA_DEBUG
-	  if(pc_debug)
-	    printk(KDBG_XIRC "found Accton card\n");
-	#endif
+	DEBUG(0, "found Accton card\n");
 	break;
       case MANFID_COMPAQ:
       case MANFID_COMPAQ2:
 	local->manf_str = "Compaq";
-	#ifdef PCMCIA_DEBUG
-	  if(pc_debug)
-	    printk(KDBG_XIRC "found Compaq card\n");
-	#endif
+	DEBUG(0, "found Compaq card\n");
 	break;
       case MANFID_INTEL:
 	local->manf_str = "Intel";
-	#ifdef PCMCIA_DEBUG
-	  if(pc_debug)
-	    printk(KDBG_XIRC "found Intel card\n");
-	#endif
+	DEBUG(0, "found Intel card\n");
 	break;
       default:
 	printk(KNOT_XIRC "Unknown Card Manufacturer ID: 0x%04x\n",
-						 (unsigned)parse.manfid.manf);
+	       (unsigned)parse.manfid.manf);
 	goto failure;
     }
 
-    if( !set_card_type(link, buf ) ) {
+    if (!set_card_type(link, buf)) {
 	printk(KNOT_XIRC "this card is not supported\n");
 	goto failure;
     }
 
     /* get configuration stuff */
     tuple.DesiredTuple = CISTPL_CONFIG;
-    if( (err=first_tuple(handle, &tuple, &parse)))
+    if ((err=first_tuple(handle, &tuple, &parse)))
 	goto cis_error;
     link->conf.ConfigBase = parse.config.base;
     link->conf.Present =    parse.config.rmask[0];
 
     /* get the ethernet address from the CIS */
     tuple.DesiredTuple = CISTPL_FUNCE;
-    for( err = first_tuple(handle, &tuple, &parse); !err;
-			     err = next_tuple(handle, &tuple, &parse) ) {
+    for (err = first_tuple(handle, &tuple, &parse); !err;
+			     err = next_tuple(handle, &tuple, &parse)) {
 	/* Once I saw two CISTPL_FUNCE_LAN_NODE_ID entries:
 	 * the first one with a length of zero the second correct -
 	 * so I skip all entries with length 0 */
-	if( parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID
-	    && ((cistpl_lan_node_id_t *)parse.funce.data)->nb )
+	if (parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID
+	    && ((cistpl_lan_node_id_t *)parse.funce.data)->nb)
 	    break;
     }
-    if( err ) { /* not found: try to get the node-id from tuple 0x89 */
+    if (err) { /* not found: try to get the node-id from tuple 0x89 */
 	tuple.DesiredTuple = 0x89;  /* data layout looks like tuple 0x22 */
-	if( !(err = get_tuple_data(GetFirstTuple, handle, &tuple )) ) {
-	    if( tuple.TupleDataLen == 8 && *buf == CISTPL_FUNCE_LAN_NODE_ID )
-		memcpy( &parse, buf, 8 );
+	if (!(err = get_tuple_data(GetFirstTuple, handle, &tuple))) {
+	    if (tuple.TupleDataLen == 8 && *buf == CISTPL_FUNCE_LAN_NODE_ID)
+		memcpy(&parse, buf, 8);
 	    else
 		err = -1;
 	}
     }
-    if( err ) { /* another try	(James Lehmer's CE2 version 4.1)*/
+    if (err) { /* another try	(James Lehmer's CE2 version 4.1)*/
 	tuple.DesiredTuple = CISTPL_FUNCE;
-	for( err = first_tuple(handle, &tuple, &parse); !err;
-				 err = next_tuple(handle, &tuple, &parse) ) {
-	    if( parse.funce.type == 0x02 && parse.funce.data[0] == 1
-		&& parse.funce.data[1] == 6 && tuple.TupleDataLen == 13 ) {
+	for (err = first_tuple(handle, &tuple, &parse); !err;
+				 err = next_tuple(handle, &tuple, &parse)) {
+	    if (parse.funce.type == 0x02 && parse.funce.data[0] == 1
+		&& parse.funce.data[1] == 6 && tuple.TupleDataLen == 13) {
 		buf[1] = 4;
-		memcpy( &parse, buf+1, 8 );
+		memcpy(&parse, buf+1, 8);
 		break;
 	    }
 	}
     }
-    if( err ) {
+    if (err) {
 	printk(KNOT_XIRC "node-id not found in CIS\n");
 	goto failure;
     }
     node_id = (cistpl_lan_node_id_t *)parse.funce.data;
-    if( node_id->nb != 6 ) {
+    if (node_id->nb != 6) {
 	printk(KNOT_XIRC "malformed node-id in CIS\n");
 	goto failure;
     }
-    for( i=0; i < 6; i++ )
+    for (i=0; i < 6; i++)
 	dev->dev_addr[i] = node_id->id[i];
 
     /* Configure card */
@@ -1059,61 +1028,60 @@
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
     link->irq.Attributes = IRQ_HANDLE_PRESENT;
     link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
-    if( irq_list[0] == -1 )
+    if (irq_list[0] == -1)
 	link->irq.IRQInfo2 = irq_mask;
     else {
-	for( i = 0; i < 4; i++)
+	for (i = 0; i < 4; i++)
 	    link->irq.IRQInfo2 |= 1 << irq_list[i];
     }
     link->irq.Handler = xirc2ps_interrupt;
     link->irq.Instance = dev;
-    if( local->modem ) {
+    if (local->modem) {
 	int pass;
 
-	if( do_sound ) {
+	if (do_sound) {
 	    link->conf.Attributes |= CONF_ENABLE_SPKR;
 	    link->conf.Status |= CCSR_AUDIO_ENA;
 	}
 	link->irq.Attributes |= IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED ;
 	link->io.NumPorts2 = 8;
 	link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
-	if( local->dingo ) {
+	if (local->dingo) {
 	    /* Take the Modem IO port from the CIS and scan for a free
 	     * Ethernet port */
 	    link->io.NumPorts1 = 16; /* no Mako stuff anymore */
 	    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-	    for( err = first_tuple(handle, &tuple, &parse); !err;
-				 err = next_tuple(handle, &tuple, &parse) ) {
-		if( cf->io.nwin > 0  &&  (cf->io.win[0].base & 0xf) == 8 ) {
-		    for(ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
+	    for (err = first_tuple(handle, &tuple, &parse); !err;
+				 err = next_tuple(handle, &tuple, &parse)) {
+		if (cf->io.nwin > 0  &&  (cf->io.win[0].base & 0xf) == 8) {
+		    for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
 			link->conf.ConfigIndex = cf->index ;
 			link->io.BasePort2 = cf->io.win[0].base;
 			link->io.BasePort1 = ioaddr;
-			if( !(err=CardServices(RequestIO, link->handle,
-								&link->io)) )
+			if (!(err=CardServices(RequestIO, link->handle,
+								&link->io)))
 			    goto port_found;
 		    }
 		}
 	    }
-	}
-	else {
+	} else {
 	    link->io.NumPorts1 = 18;
 	    /* We do 2 passes here: The first one uses the regular mapping and
 	     * the second tries again, thereby considering that the 32 ports are
 	     * mirrored every 32 bytes. Actually we use a mirrored port for
 	     * the Mako if (on the first pass) the COR bit 5 is set.
 	     */
-	    for( pass=0; pass < 2; pass++ ) {
+	    for (pass=0; pass < 2; pass++) {
 		tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-		for( err = first_tuple(handle, &tuple, &parse); !err;
-				     err = next_tuple(handle, &tuple, &parse) ){
-		    if( cf->io.nwin > 0  &&  (cf->io.win[0].base & 0xf) == 8 ){
+		for (err = first_tuple(handle, &tuple, &parse); !err;
+				     err = next_tuple(handle, &tuple, &parse)){
+		    if (cf->io.nwin > 0  &&  (cf->io.win[0].base & 0xf) == 8){
 			link->conf.ConfigIndex = cf->index ;
 			link->io.BasePort2 = cf->io.win[0].base;
 			link->io.BasePort1 = link->io.BasePort2
-				    + (pass ? ( cf->index & 0x20 ? -24:8 )
-					    : ( cf->index & 0x20 ?   8:-24) );
-			if( !(err=CardServices(RequestIO, link->handle,
+				    + (pass ? (cf->index & 0x20 ? -24:8)
+					    : (cf->index & 0x20 ?   8:-24));
+			if (!(err=CardServices(RequestIO, link->handle,
 								&link->io)))
 			    goto port_found;
 		    }
@@ -1124,30 +1092,29 @@
 	     * .... */
 	}
 	printk(KNOT_XIRC "no ports available\n");
-    }
-    else {
+    } else {
 	link->irq.Attributes |= IRQ_TYPE_EXCLUSIVE;
 	link->io.NumPorts1 = 16;
-	for(ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
+	for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
 	    link->io.BasePort1 = ioaddr;
-	    if( !(err=CardServices(RequestIO, link->handle, &link->io)) )
+	    if (!(err=CardServices(RequestIO, link->handle, &link->io)))
 		goto port_found;
 	}
 	link->io.BasePort1 = 0; /* let CS decide */
-	if( (err=CardServices(RequestIO, link->handle, &link->io)) ) {
+	if ((err=CardServices(RequestIO, link->handle, &link->io))) {
 	    cs_error(link->handle, RequestIO, err);
 	    goto config_error;
 	}
     }
   port_found:
-    if( err )
+    if (err)
 	 goto config_error;
 
     /****************
      * Now allocate an interrupt line.	Note that this does not
      * actually assign a handler to the interrupt.
      */
-    if( (err=CardServices(RequestIRQ, link->handle, &link->irq))) {
+    if ((err=CardServices(RequestIRQ, link->handle, &link->irq))) {
 	cs_error(link->handle, RequestIRQ, err);
 	goto config_error;
     }
@@ -1156,13 +1123,13 @@
      * This actually configures the PCMCIA socket -- setting up
      * the I/O windows and the interrupt mapping.
      */
-    if( (err=CardServices(RequestConfiguration,
-					link->handle, &link->conf)) ) {
+    if ((err=CardServices(RequestConfiguration,
+					link->handle, &link->conf))) {
 	cs_error(link->handle, RequestConfiguration, err);
 	goto config_error;
     }
 
-    if( local->dingo ) {
+    if (local->dingo) {
       #ifdef CEM56_FIX
 	conf_reg_t reg;
       #endif
@@ -1178,16 +1145,16 @@
 	reg.Action = CS_WRITE;
 	reg.Offset = CISREG_IOBASE_0;
 	reg.Value = link->io.BasePort2 & 0xff;
-	if( (err = CardServices(AccessConfigurationRegister, link->handle,
-							     &reg )) ) {
+	if ((err = CardServices(AccessConfigurationRegister, link->handle,
+							     &reg))) {
 	    cs_error(link->handle, AccessConfigurationRegister, err);
 	    goto config_error;
 	}
 	reg.Action = CS_WRITE;
 	reg.Offset = CISREG_IOBASE_1;
 	reg.Value = (link->io.BasePort2 >> 8) & 0xff;
-	if( (err = CardServices(AccessConfigurationRegister, link->handle,
-							      &reg )) ) {
+	if ((err = CardServices(AccessConfigurationRegister, link->handle,
+							      &reg))) {
 	    cs_error(link->handle, AccessConfigurationRegister, err);
 	    goto config_error;
 	}
@@ -1202,14 +1169,14 @@
 	req.Size = 0x1000; /* 4k window */
 	req.AccessSpeed = 0;
 	link->win = (window_handle_t)link->handle;
-	if( (err = CardServices(RequestWindow, &link->win, &req )) ) {
+	if ((err = CardServices(RequestWindow, &link->win, &req))) {
 	    cs_error(link->handle, RequestWindow, err);
 	    goto config_error;
 	}
 	local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800;
 	mem.CardOffset = 0x0;
 	mem.Page = 0;
-	if( (err = CardServices(MapMemPage, link->win, &mem) ) ) {
+	if ((err = CardServices(MapMemPage, link->win, &mem))) {
 	    cs_error(link->handle, MapMemPage, err);
 	    goto config_error;
 	}
@@ -1217,72 +1184,72 @@
 	/* Setup the CCRs; there are no infos in the CIS about the Ethernet
 	 * part.
 	 */
-	writeb(0x47, local->dingo_ccr + CISREG_COR );
+	writeb(0x47, local->dingo_ccr + CISREG_COR);
 	ioaddr = link->io.BasePort1;
-	writeb( ioaddr & 0xff	  , local->dingo_ccr + CISREG_IOBASE_0 );
-	writeb((ioaddr >> 8)&0xff , local->dingo_ccr + CISREG_IOBASE_1 );
+	writeb(ioaddr & 0xff	  , local->dingo_ccr + CISREG_IOBASE_0);
+	writeb((ioaddr >> 8)&0xff , local->dingo_ccr + CISREG_IOBASE_1);
 
       #if 0
 	{
 	    u_char tmp;
-	    printk(KERN_INFO "ECOR:" );
-	    for(i=0; i < 7; i++ ) {
-		tmp = readb(local->dingo_ccr + i*2 );
-		printk(" %02x", tmp );
+	    printk(KERN_INFO "ECOR:");
+	    for (i=0; i < 7; i++) {
+		tmp = readb(local->dingo_ccr + i*2);
+		printk(" %02x", tmp);
 	    }
-	    printk("\n" );
-	    printk(KERN_INFO "DCOR:" );
-	    for(i=0; i < 4; i++ ) {
-		tmp = readb(local->dingo_ccr + 0x20 + i*2 );
-		printk(" %02x", tmp );
+	    printk("\n");
+	    printk(KERN_INFO "DCOR:");
+	    for (i=0; i < 4; i++) {
+		tmp = readb(local->dingo_ccr + 0x20 + i*2);
+		printk(" %02x", tmp);
 	    }
-	    printk("\n" );
-	    printk(KERN_INFO "SCOR:" );
-	    for(i=0; i < 10; i++ ) {
-		tmp = readb(local->dingo_ccr + 0x40 + i*2 );
-		printk(" %02x", tmp );
+	    printk("\n");
+	    printk(KERN_INFO "SCOR:");
+	    for (i=0; i < 10; i++) {
+		tmp = readb(local->dingo_ccr + 0x40 + i*2);
+		printk(" %02x", tmp);
 	    }
-	    printk("\n" );
+	    printk("\n");
 	}
       #endif
 
-	writeb( 0x01		  , local->dingo_ccr + 0x20 );
-	writeb( 0x0c		  , local->dingo_ccr + 0x22 );
-	writeb( 0x00		  , local->dingo_ccr + 0x24 );
-	writeb( 0x00		  , local->dingo_ccr + 0x26 );
-	writeb( 0x00		  , local->dingo_ccr + 0x28 );
+	writeb(0x01		  , local->dingo_ccr + 0x20);
+	writeb(0x0c		  , local->dingo_ccr + 0x22);
+	writeb(0x00		  , local->dingo_ccr + 0x24);
+	writeb(0x00		  , local->dingo_ccr + 0x26);
+	writeb(0x00		  , local->dingo_ccr + 0x28);
     }
 
     /* The if_port symbol can be set when the module is loaded */
     local->probe_port=0;
-    if( !if_port ) {
+    if (!if_port) {
 	local->probe_port=1;
 	dev->if_port = 1;
     }
-    else if( (if_port >= 1 && if_port <= 2) || (local->mohawk && if_port==4) )
+    else if ((if_port >= 1 && if_port <= 2) || (local->mohawk && if_port==4))
 	dev->if_port = if_port;
     else
-	printk(KERN_NOTICE "xirc2ps_cs: invalid if_port requested\n");
+	printk(KNOT_XIRC "invalid if_port requested\n");
 
     /* we can now register the device with the net subsystem */
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
     dev->tbusy = 0;
-    if( (err=register_netdev(dev)) ) {
-	printk(KERN_NOTICE "xirc2ps_cs: register_netdev() failed\n");
+    if ((err=register_netdev(dev))) {
+	printk(KNOT_XIRC "register_netdev() failed\n");
 	goto config_error;
     }
 
     link->state &= ~DEV_CONFIG_PENDING;
     link->dev = &local->node;
 
-    if( local->dingo )
+    if (local->dingo)
 	do_reset(dev, 1); /* a kludge to make the cem56 work */
 
     /* give some infos about the hardware */
     printk(KERN_INFO "%s: %s: port %#3lx, irq %d, hwaddr",
-	 dev->name, local->manf_str,(u_long)dev->base_addr, (int)dev->irq );
-    for(i = 0; i < 6; i++)
+	 dev->name, local->manf_str,(u_long)dev->base_addr, (int)dev->irq);
+    for (i = 0; i < 6; i++)
 	printk("%c%02X", i?':':' ', dev->dev_addr[i]);
     printk("\n");
 
@@ -1294,7 +1261,7 @@
     return;
 
   cis_error:
-    printk(KERN_NOTICE "xirc2ps_cs: unable to parse CIS\n");
+    printk(KNOT_XIRC "unable to parse CIS\n");
   failure:
     link->state &= ~DEV_CONFIG_PENDING;
 } /* xirc2ps_config */
@@ -1305,35 +1272,29 @@
  * still open, this will be postponed until it is closed.
  */
 static void
-xirc2ps_release( u_long arg)
+xirc2ps_release(u_long arg)
 {
     dev_link_t *link = (dev_link_t *) arg;
     struct net_device *dev = link->priv;
 
-  #ifdef PCMCIA_DEBUG
-    if(pc_debug)
-	printk(KDBG_XIRC "release(0x%p)\n", link);
-  #endif
+    DEBUG(0, "release(0x%p)\n", link);
 
     /*
      * If the device is currently in use, we won't release until it
      * is actually closed.
      */
-    if(link->open) {
-      #ifdef PCMCIA_DEBUG
-	if(pc_debug)
-	    printk(KDBG_XIRC "release postponed, '%s' "
-			      "still open\n", link->dev->dev_name);
-      #endif
+    if (link->open) {
+	DEBUG(0, "release postponed, '%s' "
+	      "still open\n", link->dev->dev_name);
 	link->state |= DEV_STALE_CONFIG;
 	return;
     }
 
-    if( link->win ) {
+    if (link->win) {
 	local_info_t *local = dev->priv;
-	if( local->dingo )
-	    iounmap( local->dingo_ccr - 0x0800 );
-	CardServices(ReleaseWindow, link->win );
+	if (local->dingo)
+	    iounmap(local->dingo_ccr - 0x0800);
+	CardServices(ReleaseWindow, link->win);
     }
     CardServices(ReleaseConfiguration, link->handle);
     CardServices(ReleaseIO, link->handle, &link->io);
@@ -1364,21 +1325,15 @@
     struct net_device *dev = link->priv;
     local_info_t *lp = dev? dev->priv : NULL;
 
-  #ifdef PCMCIA_DEBUG
-    if(pc_debug)
-	printk(KDBG_XIRC "event(%d)\n", (int)event );
-  #endif
+    DEBUG(0, "event(%d)\n", (int)event);
 
     switch (event) {
       case CS_EVENT_REGISTRATION_COMPLETE:
-	 #ifdef PCMCIA_DEBUG
-	  if(pc_debug)
-	      printk(KDBG_XIRC "registration complete\n");
-	 #endif
+	  DEBUG(0, "registration complete\n");
 	  break;
       case CS_EVENT_CARD_REMOVAL:
 	  link->state &= ~DEV_PRESENT;
-	  if(link->state & DEV_CONFIG) {
+	  if (link->state & DEV_CONFIG) {
 	      dev->tbusy = 1; dev->start = 0;
 	      link->release.expires = jiffies + HZ / 20;
 	      add_timer(&link->release);
@@ -1392,8 +1347,8 @@
 	  link->state |= DEV_SUSPEND;
 	  /* Fall through... */
       case CS_EVENT_RESET_PHYSICAL:
-	  if(link->state & DEV_CONFIG) {
-	      if(link->open) {
+	  if (link->state & DEV_CONFIG) {
+	      if (link->open) {
 		  dev->tbusy = 1; dev->start = 0;
 		  lp->suspended=1;
 		  do_powerdown(dev);
@@ -1405,9 +1360,9 @@
 	  link->state &= ~DEV_SUSPEND;
 	  /* Fall through... */
       case CS_EVENT_CARD_RESET:
-	  if(link->state & DEV_CONFIG) {
+	  if (link->state & DEV_CONFIG) {
 	     CardServices(RequestConfiguration, link->handle, &link->conf);
-	     if( link->open) {
+	     if (link->open) {
 		 do_reset(dev,1);
 		 lp->suspended=0;
 		 dev->tbusy = 0; dev->start = 1;
@@ -1438,24 +1393,21 @@
 				  * -- on a laptop?
 				  */
 
-    if( !dev->start )
+    if (!dev->start)
        return;
 
-    if( dev->interrupt ) {
+    if (dev->interrupt) {
 	printk(KERR_XIRC "re-entering isr on irq %d (dev=%p)\n", irq, dev);
 	return;
     }
     dev->interrupt = 1;
     lp = dev->priv;
     ioaddr = dev->base_addr;
-    if( lp->mohawk ) { /* must disable the interrupt */
-	PutByte(XIRCREG_CR, 0 );
+    if (lp->mohawk) { /* must disable the interrupt */
+	PutByte(XIRCREG_CR, 0);
     }
 
-  #ifdef PCMCIA_DEBUG
-    if(pc_debug > 6 )
-	printk(KERN_DEBUG "%s: interrupt %d at %#x.\n", dev->name, irq, ioaddr);
-  #endif
+    DEBUG(6, "%s: interrupt %d at %#x.\n", dev->name, irq, ioaddr);
 
     saved_page = GetByte(XIRCREG_PR);
     /* Read the ISR to see whats the cause for the interrupt.
@@ -1464,91 +1416,74 @@
     int_status = GetByte(XIRCREG_ISR);
     bytes_rcvd = 0;
   loop_entry:
-    if( int_status == 0xff ) { /* card may be ejected */
-      #ifdef PCMCIA_DEBUG
-	if( pc_debug > 3 )
-	    printk(KERN_DEBUG "%s: interrupt %d for dead card\n", dev->name, irq );
-      #endif
+    if (int_status == 0xff) { /* card may be ejected */
+	DEBUG(3, "%s: interrupt %d for dead card\n", dev->name, irq);
 	goto leave;
     }
     eth_status = GetByte(XIRCREG_ESR);
 
     SelectPage(0x40);
     rx_status  = GetByte(XIRCREG40_RXST0);
-    PutByte(XIRCREG40_RXST0, (~rx_status & 0xff) );
+    PutByte(XIRCREG40_RXST0, (~rx_status & 0xff));
     tx_status = GetByte(XIRCREG40_TXST0);
     tx_status |= GetByte(XIRCREG40_TXST1) << 8;
-    PutByte(XIRCREG40_TXST0, 0 );
-    PutByte(XIRCREG40_TXST1, 0 );
+    PutByte(XIRCREG40_TXST0, 0);
+    PutByte(XIRCREG40_TXST1, 0);
 
-  #ifdef PCMCIA_DEBUG
-    if( pc_debug > 3 )
-	printk(KERN_DEBUG "%s: ISR=%#2.2x ESR=%#2.2x RSR=%#2.2x TSR=%#4.4x\n",
-		    dev->name, int_status, eth_status, rx_status, tx_status );
-  #endif
+    DEBUG(3, "%s: ISR=%#2.2x ESR=%#2.2x RSR=%#2.2x TSR=%#4.4x\n",
+	  dev->name, int_status, eth_status, rx_status, tx_status);
 
     /***** receive section ******/
     SelectPage(0);
-    while( eth_status & FullPktRcvd ) {
+    while (eth_status & FullPktRcvd) {
 	rsr = GetByte(XIRCREG0_RSR);
-	if( bytes_rcvd > maxrx_bytes && (rsr & PktRxOk) ) {
+	if (bytes_rcvd > maxrx_bytes && (rsr & PktRxOk)) {
 	    /* too many bytes received during this int, drop the rest of the
 	     * packets */
 	    lp->stats.rx_dropped++;
-	  #ifdef PCMCIA_DEBUG
-	    if( pc_debug > 3 )
-		printk(KNOT_XIRC "%s: RX drop, too much done\n", dev->name);
-	  #endif
-	    PutWord(XIRCREG0_DO, 0x8000 ); /* issue cmd: skip_rx_packet */
-	}
-	else if( rsr & PktRxOk ) {
+	    printk(KINF_XIRC "%s: RX drop, too much done\n", dev->name);
+	    PutWord(XIRCREG0_DO, 0x8000); /* issue cmd: skip_rx_packet */
+	} else if (rsr & PktRxOk) {
 	    struct sk_buff *skb;
 
 	    pktlen = GetWord(XIRCREG0_RBC);
 	    bytes_rcvd += pktlen;
 
-	  #ifdef PCMCIA_DEBUG
-	    if( pc_debug > 5 )
-		printk(KDBG_XIRC "rsr=%#02x packet_length=%u\n", rsr, pktlen );
-	  #endif
+	    DEBUG(5, "rsr=%#02x packet_length=%u\n", rsr, pktlen);
 
 	    skb = dev_alloc_skb(pktlen+3); /* 1 extra so we can use insw */
-	    if( !skb ) {
-	      #ifdef PCMCIA_DEBUG
-		if( pc_debug )
-		    printk(KNOT_XIRC "low memory, packet dropped (size=%u)\n",
-								     pktlen );
-	      #endif
+	    if (!skb) {
+		printk(KNOT_XIRC "low memory, packet dropped (size=%u)\n",
+		       pktlen);
 		lp->stats.rx_dropped++;
-	    }
-	    else { /* okay get the packet */
+	    } else { /* okay get the packet */
 		skb_reserve(skb, 2);
-		if( lp->silicon == 0  ) { /* work around a hardware bug */
+		if (lp->silicon == 0 ) { /* work around a hardware bug */
 		    unsigned rhsa; /* receive start address */
 
 		    SelectPage(5);
 		    rhsa = GetWord(XIRCREG5_RHSA0);
 		    SelectPage(0);
 		    rhsa += 3; /* skip control infos */
-		    if( rhsa >= 0x8000 )
+		    if (rhsa >= 0x8000)
 			rhsa = 0;
-		    if( rhsa + pktlen > 0x8000 ) {
+		    if (rhsa + pktlen > 0x8000) {
 			unsigned i;
 			u_char *buf = skb_put(skb, pktlen);
-			for(i=0; i < pktlen ; i++, rhsa++ ) {
+			for (i=0; i < pktlen ; i++, rhsa++) {
 			    buf[i] = GetByte(XIRCREG_EDP);
-			    if( rhsa == 0x8000 ) {
+			    if (rhsa == 0x8000) {
 				rhsa = 0;
 				i--;
 			    }
 			}
 		    } else {
 			insw(ioaddr+XIRCREG_EDP,
-				skb_put(skb, pktlen), (pktlen+1)>>1 );
+				skb_put(skb, pktlen), (pktlen+1)>>1);
 		    }
 		}
 	      #if 0
-		else if( lp->mohawk ) {
+		else if (lp->mohawk) {
 		    /* To use this 32 bit access we should use
 		     * a manual optimized loop
 		     * Also the words are swapped, we can get more
@@ -1561,7 +1496,7 @@
 		    u_long *p = skb_put(skb, pktlen);
 		    register u_long a;
 		    ioaddr_t edpreg = ioaddr+XIRCREG_EDP-2;
-		    for(i=0; i < len ; i += 4, p++ ) {
+		    for (i=0; i < len ; i += 4, p++) {
 			a = inl(edpreg);
 			__asm__("rorl $16,%0\n\t"
 				:"=q" (a)
@@ -1572,129 +1507,100 @@
 	      #endif
 		else {
 		    insw(ioaddr+XIRCREG_EDP, skb_put(skb, pktlen),
-			    (pktlen+1)>>1 );
+			    (pktlen+1)>>1);
 		}
 		skb->protocol = eth_type_trans(skb, dev);
 		skb->dev = dev;
 		netif_rx(skb);
 		lp->stats.rx_packets++;
 		lp->stats.rx_bytes += pktlen;
-		if( !(rsr & PhyPkt) )
+		if (!(rsr & PhyPkt))
 		    lp->stats.multicast++;
 	    }
-	    PutWord(XIRCREG0_DO, 0x8000 ); /* issue cmd: skip_rx_packet */
-	}
-	else {
-	  #ifdef PCMCIA_DEBUG
-	    if( pc_debug > 5 )
-		printk("rsr=%#02x\n", rsr );
-	  #endif
+	    PutWord(XIRCREG0_DO, 0x8000); /* issue cmd: skip_rx_packet */
+	} else {
+	    DEBUG(5, "rsr=%#02x\n", rsr);
 	}
-	if( rsr & PktTooLong ) {
+	if (rsr & PktTooLong) {
 	    lp->stats.rx_frame_errors++;
-	  #ifdef PCMCIA_DEBUG
-	    if( pc_debug > 3 )
-		printk(KNOT_XIRC "%s: Packet too long\n", dev->name);
-	  #endif
+	    DEBUG(3, "%s: Packet too long\n", dev->name);
 	}
-	if( rsr & CRCErr ) {
+	if (rsr & CRCErr) {
 	    lp->stats.rx_crc_errors++;
-	  #ifdef PCMCIA_DEBUG
-	    if( pc_debug > 3 )
-		printk(KNOT_XIRC "%s: CRC error\n", dev->name);
-	  #endif
+	    DEBUG(3, "%s: CRC error\n", dev->name);
 	}
-	if( rsr & AlignErr ) {
+	if (rsr & AlignErr) {
 	    lp->stats.rx_fifo_errors++; /* okay ? */
-	  #ifdef PCMCIA_DEBUG
-	    if( pc_debug > 3 )
-		printk(KNOT_XIRC "%s: Alignment error\n", dev->name);
-	  #endif
+	    DEBUG(3, "%s: Alignment error\n", dev->name);
 	}
 
 	/* get the new ethernet status */
 	eth_status = GetByte(XIRCREG_ESR);
     }
-    if( rx_status & 0x10 ) { /* Receive overrun */
+    if (rx_status & 0x10) { /* Receive overrun */
 	lp->stats.rx_over_errors++;
 	PutByte(XIRCREG_CR, ClearRxOvrun);
-      #ifdef PCMCIA_DEBUG
-	if( pc_debug > 3 )
-	    printk(KDBG_XIRC "receive overrun cleared\n" );
-      #endif
+	DEBUG(3, "receive overrun cleared\n");
     }
 
     /***** transmit section ******/
-    if( int_status & PktTxed ) {
+    if (int_status & PktTxed) {
 	unsigned n, nn;
 
 	n = lp->last_ptr_value;
 	nn = GetByte(XIRCREG0_PTR);
 	lp->last_ptr_value = nn;
-	if( nn < n ) /* rollover */
+	if (nn < n) /* rollover */
 	    lp->stats.tx_packets += 256 - n;
-	else if( n == nn ) { /* happens sometimes - don't know why */
-	  #ifdef PCMCIA_DEBUG
-	    if( pc_debug )
-		printk(KDBG_XIRC "PTR not changed?\n" );
-	  #endif
-	}
-	else
+	else if (n == nn) { /* happens sometimes - don't know why */
+	    DEBUG(0, "PTR not changed?\n");
+	} else
 	    lp->stats.tx_packets += lp->last_ptr_value - n;
 	dev->tbusy = 0;
 	mark_bh(NET_BH);  /* Inform upper layers. */
     }
-    if( tx_status & 0x0002 ) {	/* Execessive collissions */
-      #ifdef PCMCIA_DEBUG
-	if( pc_debug )
-	    printk(KDBG_XIRC "tx restarted due to execssive collissions\n" );
-      #endif
-	PutByte(XIRCREG_CR, RestartTx );  /* restart transmitter process */
+    if (tx_status & 0x0002) {	/* Execessive collissions */
+	DEBUG(0, "tx restarted due to execssive collissions\n");
+	PutByte(XIRCREG_CR, RestartTx);  /* restart transmitter process */
     }
-    if( tx_status & 0x0040 )
+    if (tx_status & 0x0040)
 	lp->stats.tx_aborted_errors++;
 
     /* recalculate our work chunk so that we limit the duration of this
      * ISR to about 1/10 of a second.
      * Calculate only if we received a reasonable amount of bytes.
      */
-    if( bytes_rcvd > 1000 ) {
+    if (bytes_rcvd > 1000) {
 	u_long duration = jiffies - start_ticks;
 
-	if( duration >= HZ/10 ) { /* if more than about 1/10 second */
+	if (duration >= HZ/10) { /* if more than about 1/10 second */
 	    maxrx_bytes = (bytes_rcvd * (HZ/10)) / duration;
-	    if( maxrx_bytes < 2000 )
+	    if (maxrx_bytes < 2000)
 		maxrx_bytes = 2000;
-	    else if( maxrx_bytes > 22000 )
+	    else if (maxrx_bytes > 22000)
 		maxrx_bytes = 22000;
-	  #ifdef PCMCIA_DEBUG
-	    if( pc_debug > 1)
-		printk(KDBG_XIRC "set maxrx=%u (rcvd=%u ticks=%lu)\n",
-				  maxrx_bytes, bytes_rcvd, duration  );
-	  #endif
-	}
-	else if( !duration && maxrx_bytes < 22000 ) { /* now much faster*/
+	    DEBUG(1, "set maxrx=%u (rcvd=%u ticks=%lu)\n",
+		  maxrx_bytes, bytes_rcvd, duration);
+	} else if (!duration && maxrx_bytes < 22000) {
+	    /* now much faster */
 	    maxrx_bytes += 2000;
-	    if( maxrx_bytes > 22000 )
+	    if (maxrx_bytes > 22000)
 		maxrx_bytes = 22000;
-	  #ifdef PCMCIA_DEBUG
-	    if( pc_debug > 1 )
-		printk(KDBG_XIRC "set maxrx=%u\n", maxrx_bytes );
-	  #endif
+	    DEBUG(1, "set maxrx=%u\n", maxrx_bytes);
 	}
     }
 
   leave:
-    if( lockup_hack ) {
-	if( int_status != 0xff && (int_status = GetByte(XIRCREG_ISR)) != 0 )
+    if (lockup_hack) {
+	if (int_status != 0xff && (int_status = GetByte(XIRCREG_ISR)) != 0)
 	    goto loop_entry;
     }
     SelectPage(saved_page);
     dev->interrupt = 0;
-    PutByte(XIRCREG_CR, EnableIntr );  /* re-enable interrupts */
+    PutByte(XIRCREG_CR, EnableIntr);  /* re-enable interrupts */
     /* Instead of dropping packets during a receive, we could
      * force an interrupt with this command:
-     *	  PutByte(XIRCREG_CR, EnableIntr|ForceIntr );
+     *	  PutByte(XIRCREG_CR, EnableIntr|ForceIntr);
      */
 } /* xirc2ps_interrupt */
 
@@ -1709,26 +1615,23 @@
     unsigned freespace;
     unsigned pktlen = skb? skb->len : 0;
 
-  #ifdef PCMCIA_DEBUG
-    if(pc_debug>1 )
-	printk(KDBG_XIRC "do_start_xmit(skb=%p, dev=%p) len=%u\n",
-						    skb, dev, pktlen );
-  #endif
+    DEBUG(1, "do_start_xmit(skb=%p, dev=%p) len=%u\n",
+	  skb, dev, pktlen);
 
     /* Transmitter timeout, serious problems */
-    if( dev->tbusy ) {
+    if (dev->tbusy) {
 	int tickssofar = jiffies - dev->trans_start;
 
-	if( lp->suspended ) {
+	if (lp->suspended) {
 	    dev_kfree_skb (skb);
 	    dev->trans_start = jiffies;
 	    lp->stats.tx_dropped++;
 	    return 0;
 	}
-	if( tickssofar < TX_TIMEOUT )
+	if (tickssofar < TX_TIMEOUT)
 	    return 1;
 
-	printk(KERN_NOTICE "%s: transmit timed out\n", dev->name );
+	printk(KERN_NOTICE "%s: transmit timed out\n", dev->name);
 	lp->stats.tx_errors++;
 	/* reset the card */
 	do_reset(dev,1);
@@ -1736,7 +1639,7 @@
 	dev->tbusy = 0;
     }
 
-    if( test_and_set_bit(0, (void*)&dev->tbusy ) ) {
+    if (test_and_set_bit(0, (void*)&dev->tbusy)) {
 	printk(KWRN_XIRC "transmitter access conflict\n");
 	dev_kfree_skb (skb);
 	return 0;
@@ -1749,33 +1652,30 @@
      * a larger packetlen than we actually have; the chip will
      * pad this in his buffer with random bytes
      */
-    if( pktlen < ETH_ZLEN )
+    if (pktlen < ETH_ZLEN)
 	pktlen = ETH_ZLEN;
 
     SelectPage(0);
-    PutWord(XIRCREG0_TRS, (u_short)pktlen+2 );
+    PutWord(XIRCREG0_TRS, (u_short)pktlen+2);
     freespace = GetWord(XIRCREG0_TSO);
     okay = freespace & 0x8000;
     freespace &= 0x7fff;
     /* TRS doesn't work - (indeed it is eliminated with sil-rev 1) */
     okay = pktlen +2 < freespace;
-  #ifdef PCMCIA_DEBUG
-    if(pc_debug > 2  + ( okay ? 2 : 0) )
-	printk(KERN_DEBUG "%s: avail. tx space=%u%s\n", dev->name, freespace,
-				okay? " (okay)":" (not enough)" );
-  #endif
-    if( !okay ) { /* not enough space */
+    DEBUG(2 + (okay ? 2 : 0), "%s: avail. tx space=%u%s\n",
+	  dev->name, freespace, okay ? " (okay)":" (not enough)");
+    if (!okay) { /* not enough space */
 	dev->tbusy = 1;
 	return 1;  /* upper layer may decide to requeue this packet */
     }
     /* send the packet */
-    PutWord(XIRCREG_EDP, (u_short)pktlen );
-    outsw(ioaddr+XIRCREG_EDP, skb->data, pktlen>>1 );
-    if( pktlen & 1 )
-	PutByte(XIRCREG_EDP, skb->data[pktlen-1] );
+    PutWord(XIRCREG_EDP, (u_short)pktlen);
+    outsw(ioaddr+XIRCREG_EDP, skb->data, pktlen>>1);
+    if (pktlen & 1)
+	PutByte(XIRCREG_EDP, skb->data[pktlen-1]);
 
-    if( lp->mohawk )
-	PutByte(XIRCREG_CR, TransmitPacket|EnableIntr );
+    if (lp->mohawk)
+	PutByte(XIRCREG_CR, TransmitPacket|EnableIntr);
 
     dev_kfree_skb (skb);
     dev->trans_start = jiffies;
@@ -1808,29 +1708,28 @@
     int i,j,k,n;
 
     SelectPage(k=0x50);
-    for(i=0,j=8,n=0; ; i++, j++) {
-	if( i > 5 ) {
-	    if( ++n > 9 )
+    for (i=0,j=8,n=0; ; i++, j++) {
+	if (i > 5) {
+	    if (++n > 9)
 		break;
 	    i = 0;
 	}
-	if( j > 15 ) {
+	if (j > 15) {
 	    j = 8;
 	    k++;
 	    SelectPage(k);
 	}
 
-	if( n && n <= dev->mc_count && dmi ) {
+	if (n && n <= dev->mc_count && dmi) {
 	    addr = dmi->dmi_addr;
 	    dmi = dmi->next;
-	}
-	else
+	} else
 	    addr = dev->dev_addr;
 
-	if( lp->mohawk )
-	    PutByte( j, addr[5-i] );
+	if (lp->mohawk)
+	    PutByte(j, addr[5-i]);
 	else
-	    PutByte( j, addr[i] );
+	    PutByte(j, addr[i]);
     }
     SelectPage(0);
 }
@@ -1847,21 +1746,19 @@
     ioaddr_t ioaddr = dev->base_addr;
 
     SelectPage(0x42);
-    if( dev->flags & IFF_PROMISC ) { /* snoop */
+    if (dev->flags & IFF_PROMISC) { /* snoop */
 	PutByte(XIRCREG42_SWC1, 0x06); /* set MPE and PME */
-    }
-    else if( dev->mc_count > 9 || (dev->flags & IFF_ALLMULTI) ) {
+    } else if (dev->mc_count > 9 || (dev->flags & IFF_ALLMULTI)) {
 	PutByte(XIRCREG42_SWC1, 0x06); /* set MPE */
-    }
-    else if( dev->mc_count ) { /* the chip can filter 9 addresses perfectly */
+    } else if (dev->mc_count) {
+	/* the chip can filter 9 addresses perfectly */
 	PutByte(XIRCREG42_SWC1, 0x00);
 	SelectPage(0x40);
-	PutByte(XIRCREG40_CMD0, Offline );
+	PutByte(XIRCREG40_CMD0, Offline);
 	set_addresses(dev);
 	SelectPage(0x40);
-	PutByte(XIRCREG40_CMD0, EnableRecv | Online );
-    }
-    else { /* standard usage */
+	PutByte(XIRCREG40_CMD0, EnableRecv | Online);
+    } else { /* standard usage */
 	PutByte(XIRCREG42_SWC1, 0x00);
     }
     SelectPage(0);
@@ -1874,10 +1771,7 @@
 static int
 do_init(struct net_device *dev)
 {
-  #ifdef PCMCIA_DEBUG
-    if(pc_debug)
-	printk(KDBG_XIRC "do_init(%p)\n", dev );
-  #endif
+    DEBUG(0, "do_init(%p)\n", dev);
     return 0;
 }
 
@@ -1886,30 +1780,25 @@
 {
     local_info_t *local = dev->priv;
 
-  #ifdef PCMCIA_DEBUG
-    if(pc_debug)
-	printk(KDBG_XIRC "do_config(%p)\n", dev );
-  #endif
-
-    if( map->port != 255 && map->port != dev->if_port ) {
-	if( map->port <= 4 ) {
-	    if( !map->port ) {
-		local->probe_port = 1;
-		dev->if_port = 1;
-	    }
-	    else {
-		local->probe_port = 0;
-		dev->if_port = map->port;
-	    }
-	    printk(KERN_INFO "%s: switching to %s port\n",
-			      dev->name, if_names[dev->if_port]);
-	    do_reset(dev,1);  /* not the fine way :-) */
-	}
-	else
+    DEBUG(0, "do_config(%p)\n", dev);
+    if (map->port != 255 && map->port != dev->if_port) {
+	if (local->new_mii)
+	    return -EOPNOTSUPP;
+	if (map->port > 4)
 	    return -EINVAL;
+	if (!map->port) {
+	    local->probe_port = 1;
+	    dev->if_port = 1;
+	} else {
+	    local->probe_port = 0;
+	    dev->if_port = map->port;
+	}
+	printk(KERN_INFO "%s: switching to %s port\n",
+	       dev->name, if_names[dev->if_port]);
+	do_reset(dev,1);  /* not the fine way :-) */
     }
   #ifdef PCMCIA_DEBUG
-    else if( map->port == dev->if_port && local->mohawk ) {
+    else if (local->mohawk) {
 	/* kludge to print the mii regsiters */
 	mii_dump(dev);
     }
@@ -1926,17 +1815,14 @@
     local_info_t *lp = dev->priv;
     dev_link_t *link;
 
-  #ifdef PCMCIA_DEBUG
-    if(pc_debug)
-	printk(KDBG_XIRC "do_open(%p)\n", dev );
-  #endif
+    DEBUG(0, "do_open(%p)\n", dev);
 
     /* Check that the PCMCIA card is still here. */
-    for( link = dev_list; link; link = link->next )
-	if( link->priv == dev )
+    for (link = dev_list; link; link = link->next)
+	if (link->priv == dev)
 	    break;
     /* Physical device present signature. */
-    if( !DEV_OK(link) )
+    if (!DEV_OK(link))
 	return -ENODEV;
 
     /* okay */
@@ -1957,25 +1843,22 @@
     ioaddr_t ioaddr = dev->base_addr;
     u16 *data = (u16 *)&rq->ifr_data;
 
-  #ifdef PCMCIA_DEBUG
-    if(pc_debug > 1)
-	printk(KERN_DEBUG "%s: ioctl(%-.6s, %#04x) %04x %04x %04x %04x\n",
-			   dev->name, rq->ifr_ifrn.ifrn_name, cmd,
-			   data[0], data[1], data[2], data[3] );
-  #endif
+    DEBUG(1, "%s: ioctl(%-.6s, %#04x) %04x %04x %04x %04x\n",
+	  dev->name, rq->ifr_ifrn.ifrn_name, cmd,
+	  data[0], data[1], data[2], data[3]);
 
-    if( !local->mohawk )
+    if (!local->mohawk)
 	return -EOPNOTSUPP;
 
-    switch( cmd ) {
+    switch(cmd) {
       case SIOCDEVPRIVATE:	/* Get the address of the PHY in use. */
 	data[0] = 0;		/* we have only this address */
 	/* fall trough */
       case SIOCDEVPRIVATE+1:	/* Read the specified MII register. */
-	data[3] = mii_rd( ioaddr, data[0] & 0x1f, data[1] & 0x1f);
+	data[3] = mii_rd(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
 	break;
       case SIOCDEVPRIVATE+2:	/* Write the specified MII register */
-	if( !suser() )
+	if (!suser())
 	    return -EPERM;
 	mii_wr(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2], 16);
 	break;
@@ -1995,7 +1878,7 @@
     udelay(1);
     PutByte(XIRCREG4_GPR1, 0);	     /* clear bit 0: power down */
     busy_loop(HZ/25);		     /* wait 40 msec */
-    if( local->mohawk )
+    if (local->mohawk)
 	PutByte(XIRCREG4_GPR1, 1);	 /* set bit 0: power up */
     else
 	PutByte(XIRCREG4_GPR1, 1 | 4);	 /* set bit 0: power up, bit 2: AIC */
@@ -2009,18 +1892,14 @@
     ioaddr_t ioaddr = dev->base_addr;
     unsigned value;
 
-  #ifdef PCMCIA_DEBUG
-    if(pc_debug)
-	printk(KERN_DEBUG "%s: do_reset(%p,%d)\n",
-					  dev? dev->name:"eth?", dev, full );
-  #endif
+    DEBUG(0, "%s: do_reset(%p,%d)\n", dev? dev->name:"eth?", dev, full);
 
     hardreset(dev);
-    PutByte(XIRCREG_CR, SoftReset ); /* set */
+    PutByte(XIRCREG_CR, SoftReset); /* set */
     busy_loop(HZ/50);		     /* wait 20 msec */
-    PutByte(XIRCREG_CR, 0 );	     /* clear */
+    PutByte(XIRCREG_CR, 0);	     /* clear */
     busy_loop(HZ/25);		     /* wait 40 msec */
-    if( local->mohawk ) {
+    if (local->mohawk) {
 	SelectPage(4);
 	/* set pin GP1 and GP2 to output  (0x0c)
 	 * set GP1 to low to power up the ML6692 (0x00)
@@ -2036,25 +1915,23 @@
     local->silicon = local->mohawk ? (GetByte(XIRCREG4_BOV) & 0x70) >> 4
 				   : (GetByte(XIRCREG4_BOV) & 0x30) >> 4;
 
-    if( local->probe_port ) {
-	if( !local->mohawk ) {
+    if (local->probe_port) {
+	if (!local->mohawk) {
 	    SelectPage(4);
 	    PutByte(XIRCREG4_GPR0, 4);
 	    local->probe_port = 0;
 	}
-    }
-    else if( dev->if_port == 2 ) { /* enable 10Base2 */
+    } else if (dev->if_port == 2) { /* enable 10Base2 */
 	SelectPage(0x42);
 	PutByte(XIRCREG42_SWC1, 0xC0);
-    }
-    else { /* enable 10BaseT */
+    } else { /* enable 10BaseT */
 	SelectPage(0x42);
 	PutByte(XIRCREG42_SWC1, 0x80);
     }
     busy_loop(HZ/25);		     /* wait 40 msec to let it complete */
 
   #ifdef PCMCIA_DEBUG
-    if(pc_debug) {
+    if (pc_debug) {
 	SelectPage(0);
 	value = GetByte(XIRCREG_ESR);	 /* read the ESR */
 	printk(KERN_DEBUG "%s: ESR is: %#02x\n", dev->name, value);
@@ -2063,33 +1940,30 @@
 
     /* setup the ECR */
     SelectPage(1);
-    PutByte(XIRCREG1_IMR0, 0xff ); /* allow all ints */
+    PutByte(XIRCREG1_IMR0, 0xff); /* allow all ints */
     PutByte(XIRCREG1_IMR1, 1	); /* and Set TxUnderrunDetect */
     value = GetByte(XIRCREG1_ECR);
   #if 0
-    if( local->mohawk )
+    if (local->mohawk)
 	value |= DisableLinkPulse;
     PutByte(XIRCREG1_ECR, value);
   #endif
-  #ifdef PCMCIA_DEBUG
-    if(pc_debug)
-	printk(KERN_DEBUG "%s: ECR is: %#02x\n", dev->name, value);
-  #endif
+    DEBUG(0, "%s: ECR is: %#02x\n", dev->name, value);
 
     SelectPage(0x42);
     PutByte(XIRCREG42_SWC0, 0x20); /* disable source insertion */
 
-    if( local->silicon != 1 ) {
+    if (local->silicon != 1) {
 	/* set the local memory dividing line.
 	 * The comments in the sample code say that this is only
 	 * settable with the scipper version 2 which is revision 0.
 	 * Always for CE3 cards
 	 */
 	SelectPage(2);
-	PutWord(XIRCREG2_RBS, 0x2000 );
+	PutWord(XIRCREG2_RBS, 0x2000);
     }
 
-    if( full )
+    if (full)
 	set_addresses(dev);
 
     /* Hardware workaround:
@@ -2097,7 +1971,7 @@
      * to move the offset pointer back to 0.
      */
     SelectPage(0);
-    PutWord(XIRCREG0_DO, 0x2000 ); /* change offset command, off=0 */
+    PutWord(XIRCREG0_DO, 0x2000); /* change offset command, off=0 */
 
     /* setup MAC IMRs and clear status registers */
     SelectPage(0x40);		     /* Bit 7 ... bit 0 */
@@ -2108,36 +1982,23 @@
     PutByte(XIRCREG40_TXST0,  0x00); /* TOK, TAB, SQE, LL, TU, JAB, EXC, CRS */
     PutByte(XIRCREG40_TXST1,  0x00); /* TEN, rsv, PTD, EXT, retry_counter:4  */
 
-    if( full && local->mohawk && init_mii(dev) ) {
-	if( dev->if_port == 4 || local->dingo ) { /* and use it */
-	    SelectPage(2);
-	    value = GetByte(XIRCREG2_MSR);
-	    value |= 0x08;     /* Select MII */
-	    PutByte(XIRCREG2_MSR, value);
-	    busy_loop(HZ/50);	/* wait 20 msec */
-	  #ifdef PCMCIA_DEBUG
-	    if(pc_debug)
-		printk(KERN_DEBUG "%s: MII selected\n", dev->name);
-	  #endif
-	}
-	else {
+    if (full && local->mohawk && init_mii(dev)) {
+	if (dev->if_port == 4 || local->dingo || local->new_mii) {
+	    printk(KERN_INFO "%s: MII selected\n", dev->name);
 	    SelectPage(2);
 	    PutByte(XIRCREG2_MSR, GetByte(XIRCREG2_MSR) | 0x08);
 	    busy_loop(HZ/50);
-	  #ifdef PCMCIA_DEBUG
-	    if(pc_debug)
-		printk(KERN_DEBUG "%s: MII detected; using 10mbs\n",
-								dev->name);
-	  #endif
+	} else {
+	    printk(KERN_INFO "%s: MII detected; using 10mbs\n",
+		   dev->name);
 	    SelectPage(0x42);
-	    if( dev->if_port == 2 ) /* enable 10Base2 */
+	    if (dev->if_port == 2) /* enable 10Base2 */
 		PutByte(XIRCREG42_SWC1, 0xC0);
 	    else  /* enable 10BaseT */
 		PutByte(XIRCREG42_SWC1, 0x80);
 	    busy_loop(HZ/25);	/* wait 40 msec to let it complete */
 	}
-    }
-    else {  /* No MII */
+    } else {  /* No MII */
 	SelectPage(0);
 	value = GetByte(XIRCREG_ESR);	 /* read the ESR */
 	dev->if_port = (value & MediaSelect) ? 1 : 2;
@@ -2145,34 +2006,34 @@
 
     /* configure the LEDs */
     SelectPage(2);
-    if( dev->if_port == 1 || dev->if_port == 4 ) /* TP: Link and Activity */
-	PutByte(XIRCREG2_LED, 0x3b );
+    if (dev->if_port == 1 || dev->if_port == 4) /* TP: Link and Activity */
+	PutByte(XIRCREG2_LED, 0x3b);
     else			      /* Coax: Not-Collision and Activity */
-	PutByte(XIRCREG2_LED, 0x3a );
+	PutByte(XIRCREG2_LED, 0x3a);
 
     if (local->dingo)
-	PutByte( 0x0b, 0x04 ); /* 100 Mbit LED */
+	PutByte(0x0b, 0x04); /* 100 Mbit LED */
 
     /* enable receiver and put the mac online */
-    if( full ) {
+    if (full) {
 	SelectPage(0x40);
-	PutByte(XIRCREG40_CMD0, EnableRecv | Online );
+	PutByte(XIRCREG40_CMD0, EnableRecv | Online);
     }
 
     /* setup Ethernet IMR and enable interrupts */
     SelectPage(1);
-    PutByte(XIRCREG1_IMR0, 0xff );
+    PutByte(XIRCREG1_IMR0, 0xff);
     udelay(1);
     SelectPage(0);
-    PutByte(XIRCREG_CR, EnableIntr );
-    if( local->modem && !local->dingo ) { /* do some magic */
-	if( !(GetByte( 0x10 ) & 0x01 ) )
-	    PutByte( 0x10, 0x11 ); /* unmask master-int bit */
+    PutByte(XIRCREG_CR, EnableIntr);
+    if (local->modem && !local->dingo) { /* do some magic */
+	if (!(GetByte(0x10) & 0x01))
+	    PutByte(0x10, 0x11); /* unmask master-int bit */
     }
 
-    if( full )
-	printk(KERN_INFO "%s: media %s, silicon revision %d\n", dev->name,
-				      if_names[dev->if_port], local->silicon);
+    if (full)
+	printk(KERN_INFO "%s: media %s, silicon revision %d\n",
+	       dev->name, if_names[dev->if_port], local->silicon);
     /* We should switch back to page 0 to avoid a bug in revision 0
      * where regs with offset below 8 can't be read after an access
      * to the MAC registers */
@@ -2192,68 +2053,70 @@
     int i;
 
   #ifdef PCMCIA_DEBUG
-    if(pc_debug>1) {
+    if (pc_debug>1) {
 	mii_dump(dev);
     }
   #endif
 
-    status = mii_rd(ioaddr,  0, 1 );
-    if( (status & 0xff00) != 0x7800 )
+    status = mii_rd(ioaddr,  0, 1);
+    if ((status & 0xff00) != 0x7800)
 	return 0; /* No MII */
 
-    if( local->probe_port )
+    local->new_mii = (mii_rd(ioaddr, 0, 2) != 0xffff);
+    
+    if (local->new_mii || local->probe_port)
 	control = 0x1000; /* auto neg */
-    else if( dev->if_port == 4 )
+    else if (dev->if_port == 4)
 	control = 0x2000; /* no auto neg, 100mbs mode */
     else
 	control = 0x0000; /* no auto neg, 10mbs mode */
-    mii_wr(ioaddr,  0, 0, control, 16 );
+    mii_wr(ioaddr,  0, 0, control, 16);
     udelay(100);
-    control = mii_rd(ioaddr, 0, 0 );
+    control = mii_rd(ioaddr, 0, 0);
 
-    if( control & 0x0400 ) {
+    if (control & 0x0400) {
 	printk(KERN_NOTICE "%s can't take PHY out of isolation mode\n",
-								dev->name);
+	       dev->name);
 	local->probe_port = 0;
 	return 0;
     }
 
-    if( local->probe_port ) {
+    if (local->new_mii || local->probe_port) {
 	/* according to the DP83840A specs the auto negotation process
 	 * may take up to 3.5 sec, so we use this also for our ML6692
 	 * Fixme: Better to use a timer here!
 	 */
-	for(i=0; i < 35; i++ ) {
+	for (i=0; i < 35; i++) {
 	    busy_loop(HZ/10);	 /* wait 100 msec */
-	    status = mii_rd(ioaddr,  0, 1 );
-	    if( (status & 0x0020) && (status & 0x0004) )
+	    status = mii_rd(ioaddr,  0, 1);
+	    if ((status & 0x0020) && (status & 0x0004))
 		break;
 	}
 
-	if( !(status & 0x0020) ) {
-	    printk(KERN_NOTICE "%s: auto negotation failed;"
-			       " using 10mbs\n", dev->name );
-	    control = 0x0000;
-	    mii_wr(ioaddr,  0, 0, control, 16 );
-	    udelay(100);
-	    SelectPage(0);
-	    dev->if_port = (GetByte(XIRCREG_ESR) & MediaSelect) ? 1 : 2;
-	}
-	else {
-	    linkpartner = mii_rd(ioaddr, 0, 5 );
-	    printk(KERN_INFO "%s: MII link partner: %04x\n", dev->name,
-							linkpartner );
-	    if( linkpartner & 0x0080 ) { /* 100BaseTx capability */
-		dev->if_port = 4;
+	if (!(status & 0x0020)) {
+	    printk(KERN_INFO "%s: auto negotation failed;"
+		   " using 10mbs\n", dev->name);
+	    if (!local->new_mii) {
+		control = 0x0000;
+		mii_wr(ioaddr,  0, 0, control, 16);
+		udelay(100);
+		SelectPage(0);
+		dev->if_port = (GetByte(XIRCREG_ESR) & MediaSelect) ? 1 : 2;
 	    }
-	    else
+	} else {
+	    linkpartner = mii_rd(ioaddr, 0, 5);
+	    printk(KERN_INFO "%s: MII link partner: %04x\n",
+		   dev->name, linkpartner);
+	    if (linkpartner & 0x0080) {
+		dev->if_port = 4;
+	    } else
 		dev->if_port = 1;
 	}
 	local->probe_port = 0;
     }
 
   #ifdef PCMCIA_DEBUG
-    if( pc_debug )
+    if (pc_debug)
 	mii_dump(dev);
   #endif
 
@@ -2266,10 +2129,7 @@
 
     ioaddr_t ioaddr = dev->base_addr;
 
-  #ifdef PCMCIA_DEBUG
-    if(pc_debug)
-	printk(KDBG_XIRC "do_powerdown(%p)\n", dev );
-  #endif
+    DEBUG(0, "do_powerdown(%p)\n", dev);
 
     SelectPage(4);
     PutByte(XIRCREG4_GPR1, 0);	     /* clear bit 0: power down */
@@ -2277,33 +2137,26 @@
 }
 
 static int
-do_stop( struct net_device *dev)
+do_stop(struct net_device *dev)
 {
     ioaddr_t ioaddr = dev->base_addr;
     dev_link_t *link;
 
-  #ifdef PCMCIA_DEBUG
-    if(pc_debug)
-	printk(KDBG_XIRC "do_stop(%p)\n", dev );
-  #endif
+    DEBUG(0, "do_stop(%p)\n", dev);
 
-    for(link = dev_list; link; link = link->next)
-	if(link->priv == dev)
+    for (link = dev_list; link; link = link->next)
+	if (link->priv == dev)
 	    break;
-    if( !link )
+    if (!link)
 	return -ENODEV;
 
-  #ifdef PCMCIA_DEBUG
-    if(pc_debug)
-	printk(KDBG_XIRC "shutting down\n");
-  #endif
     dev->tbusy = 1;
     dev->start = 0;
 
     SelectPage(0);
-    PutByte(XIRCREG_CR, 0 );  /* disable interrupts */
+    PutByte(XIRCREG_CR, 0);  /* disable interrupts */
     SelectPage(0x01);
-    PutByte(XIRCREG1_IMR0, 0x00 ); /* forbid all ints */
+    PutByte(XIRCREG1_IMR0, 0x00); /* forbid all ints */
     SelectPage(4);
     PutByte(XIRCREG4_GPR1, 0);	/* clear bit 0: power down */
     SelectPage(0);
@@ -2326,19 +2179,16 @@
     servinfo_t serv;
 
     printk(KERN_INFO "%s\n", version);
-    if( card_type )
+    if (card_type)
 	printk(KINF_XIRC "option card_type is obsolete\n");
-    if( lockup_hack )
+    if (lockup_hack)
 	printk(KINF_XIRC "lockup hack is enabled\n");
     CardServices(GetCardServicesInfo, &serv);
-    if( serv.Revision != CS_RELEASE_CODE ) {
+    if (serv.Revision != CS_RELEASE_CODE) {
 	printk(KNOT_XIRC "Card Services release does not match!\n");
 	return -1;
     }
-  #ifdef PCMCIA_DEBUG
-    if( pc_debug )
-	printk(KDBG_XIRC "pc_debug=%d\n", pc_debug);
-  #endif
+    DEBUG(0, "pc_debug=%d\n", pc_debug);
     register_pccard_driver(&dev_info, &xirc2ps_attach, &xirc2ps_detach);
     return 0;
 }
@@ -2346,16 +2196,13 @@
 static void __exit
 exit_xirc2ps_cs(void)
 {
-  #ifdef PCMCIA_DEBUG
-    if(pc_debug)
-	printk(KDBG_XIRC "unloading\n");
-  #endif
+    DEBUG(0, "unloading\n");
     unregister_pccard_driver(&dev_info);
-    while( dev_list ) {
-	if( dev_list->state & DEV_CONFIG )
-	    xirc2ps_release( (u_long)dev_list );
-	if( dev_list )	/* xirc2ps_release() might already have detached... */
-	    xirc2ps_detach( dev_list );
+    while (dev_list) {
+	if (dev_list->state & DEV_CONFIG)
+	    xirc2ps_release((u_long)dev_list);
+	if (dev_list)	/* xirc2ps_release() might already have detached... */
+	    xirc2ps_detach(dev_list);
     }
 }
 
diff -u --recursive --new-file v2.3.26/linux/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c
--- v2.3.26/linux/drivers/net/pcnet32.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/net/pcnet32.c	Tue Nov  9 08:20:12 1999
@@ -268,8 +268,8 @@
 #endif    
 };
 
-int  pcnet32_probe(struct net_device *);
-static int  pcnet32_probe1(struct net_device *, unsigned long, unsigned char, int, int);
+int  pcnet32_probe(void);
+static int  pcnet32_probe1(unsigned long, unsigned char, int, int);
 static int  pcnet32_open(struct net_device *);
 static int  pcnet32_init_ring(struct net_device *);
 static int  pcnet32_start_xmit(struct sk_buff *, struct net_device *);
@@ -291,7 +291,7 @@
     const char *name;
     u16 vendor_id, device_id, svid, sdid, flags;
     int io_size;
-    int (*probe1) (struct net_device *, unsigned long, unsigned char, int, int);
+    int (*probe1) (unsigned long, unsigned char, int, int);
 };
 
 static struct pcnet32_pci_id_info pcnet32_tbl[] = {
@@ -419,10 +419,10 @@
 
 
 
-int __init pcnet32_probe (struct net_device *dev)
+int __init pcnet32_probe(void)
 {
-    unsigned long ioaddr = dev ? dev->base_addr: 0;
-    unsigned int  irq_line = dev ? dev->irq : 0;
+    unsigned long ioaddr = 0; // FIXME dev ? dev->base_addr: 0;
+    unsigned int  irq_line = 0; // FIXME dev ? dev->irq : 0;
     int *port;
     int cards_found = 0;
     
@@ -430,7 +430,7 @@
 #ifndef __powerpc__
     if (ioaddr > 0x1ff) {
 	if (check_region(ioaddr, PCNET32_TOTAL_SIZE) == 0)
-	    return pcnet32_probe1(dev, ioaddr, irq_line, 0, 0);
+	    return pcnet32_probe1(ioaddr, irq_line, 0, 0);
 	else
 	    return ENODEV;
     } else
@@ -481,9 +481,8 @@
 	    }
 	    printk("Found PCnet/PCI at %#lx, irq %d.\n", ioaddr, irq_line);
 	    
-	    if (pcnet32_tbl[chip_idx].probe1(dev, ioaddr, irq_line, 1, cards_found) == 0) {
+	    if (pcnet32_tbl[chip_idx].probe1(ioaddr, irq_line, 1, cards_found) == 0) {
 		cards_found++;
-		dev = NULL;
 	    }
 	}
     } else 
@@ -497,7 +496,7 @@
     	    /* check if there is really a pcnet chip on that ioaddr */
     	    if ((inb(ioaddr + 14) == 0x57) &&
 		(inb(ioaddr + 15) == 0x57) &&
-	        (pcnet32_probe1(dev, ioaddr, 0, 0, 0) == 0))
+	        (pcnet32_probe1(ioaddr, 0, 0, 0) == 0))
 		cards_found++;
 	}
     }
@@ -507,13 +506,14 @@
 
 /* pcnet32_probe1 */
 static int __init
-pcnet32_probe1(struct net_device *dev, unsigned long ioaddr, unsigned char irq_line, int shared, int card_idx)
+pcnet32_probe1(unsigned long ioaddr, unsigned char irq_line, int shared, int card_idx)
 {
     struct pcnet32_private *lp;
     int i,media,fdx = 0, mii = 0, fset = 0;
     int chip_version;
     char *chipname;
     char *priv;
+    struct net_device *dev;
     struct pcnet32_access *a;
 
     /* reset the chip */
@@ -602,7 +602,9 @@
 	a->write_csr(ioaddr, 80, a->read_csr(ioaddr, 80) | 0x0c00);
     }
     
-    dev = init_etherdev(dev, 0);
+    dev = init_etherdev(NULL, 0);
+    if(dev==NULL)
+    	return ENOMEM;
 
     printk(KERN_INFO "%s: %s at %#3lx,", dev->name, chipname, ioaddr);
 
@@ -1399,7 +1401,7 @@
 	pcnet32_debug = debug;
     
     pcnet32_dev = NULL;
-    return pcnet32_probe(NULL);
+    return pcnet32_probe();
 }
 
 void
diff -u --recursive --new-file v2.3.26/linux/drivers/net/ppp_async.c linux/drivers/net/ppp_async.c
--- v2.3.26/linux/drivers/net/ppp_async.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/net/ppp_async.c	Wed Nov 10 19:55:03 1999
@@ -64,6 +64,7 @@
 
 	struct ppp_channel chan;	/* interface to generic ppp layer */
 	int		connected;
+	int	index;
 	unsigned char	obuf[OBUFSIZE];
 };
 
@@ -387,6 +388,7 @@
 		if (err != 0)
 			break;
 		ap->connected = 1;
+		ap->index = val;
 		break;
 	case PPPIOCDETACH:
 		err = -ENXIO;
@@ -394,6 +396,14 @@
 			break;
 		ppp_unregister_channel(&ap->chan);
 		ap->connected = 0;
+		err = 0;
+		break;
+	case PPPIOCGUNIT:
+		err = -ENXIO;
+		if (!ap->connected)
+			break;
+		if (put_user(ap->index, (int *) arg))
+			break;
 		err = 0;
 		break;
 
diff -u --recursive --new-file v2.3.26/linux/drivers/net/ppp_generic.c linux/drivers/net/ppp_generic.c
--- v2.3.26/linux/drivers/net/ppp_generic.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/net/ppp_generic.c	Tue Nov  9 11:50:49 1999
@@ -28,6 +28,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/kmod.h>
+#include <linux/init.h>
 #include <linux/list.h>
 #include <linux/netdevice.h>
 #include <linux/poll.h>
@@ -554,8 +555,7 @@
 
 /* Called at boot time if ppp is compiled into the kernel,
    or at module load time (from init_module) if compiled as a module. */
-int
-ppp_init(struct net_device *dev)
+int __init ppp_init(void)
 {
 	int err;
 #ifndef MODULE
@@ -1614,7 +1614,7 @@
 int
 init_module(void)
 {
-	ppp_init(0);
+	ppp_init();
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.26/linux/drivers/net/rcpci45.c linux/drivers/net/rcpci45.c
--- v2.3.26/linux/drivers/net/rcpci45.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/rcpci45.c	Tue Nov  9 08:20:12 1999
@@ -158,8 +158,8 @@
 
 
 static int RCinit(struct net_device *dev);
-static int RCscan(struct net_device *dev);
-static int RCfound_device(struct net_device *, int, int, int, int, int, int);
+static int RCscan(void);
+static int RCfound_device(int, int, int, int, int, int);
 
 static int RCopen(struct net_device *);
 static int RC_xmit_packet(struct sk_buff *, struct net_device *);
@@ -181,22 +181,18 @@
 #ifdef MODULE
 int init_module(void)
 #else
-int rcpci_probe(struct net_device *dev)
+int rcpci_probe(void)
 #endif
 {
     int cards_found;
 
-#ifdef MODULE
-    cards_found = RCscan(NULL);
-#else
-    cards_found = RCscan(dev);
-#endif
+    cards_found = RCscan();
     if (cards_found)
         printk(version);
     return cards_found ? 0 : -ENODEV;
 }
 
-static int RCscan(struct net_device *dev)
+static int RCscan(void)
 {
     int cards_found = 0;
     static int pci_index = 0;
@@ -237,13 +233,10 @@
 
 	pci_set_master(pdev);
 
-        if (!RCfound_device(dev, pci_ioaddr, pci_irq_line,
+        if (!RCfound_device(pci_ioaddr, pci_irq_line,
                           pci_bus, pci_device_fn,
                           board_index++, cards_found))
-        {
-            dev = 0;
             cards_found++;
-        }
     }
 #ifdef RCDEBUG
     printk("rc: found %d cards \n", cards_found);
@@ -263,7 +256,7 @@
 }
 
 static int
-RCfound_device(struct net_device *dev, int memaddr, int irq, 
+RCfound_device(int memaddr, int irq, 
                int bus, int function, int product_index, int card_idx)
 {
     int dev_size = 32768;        
@@ -271,6 +264,8 @@
     PDPA pDpa;
     int init_status;
 
+    struct net_device *dev;
+    
     /* 
      * Allocate and fill new device structure. 
      * We need enough for struct net_device plus DPA plus the LAN API private
@@ -280,7 +275,6 @@
      * the LAN API layer.
      */
 
-#ifdef MODULE
     dev = (struct net_device *) kmalloc(dev_size, GFP_DMA | GFP_KERNEL |GFP_ATOMIC);
     if (!dev)
     {
@@ -292,16 +286,6 @@
      * dev->priv will point to the start of DPA.
      */
     dev->priv = (void *)(((long)dev + sizeof(struct net_device) + 15) & ~15);
-#else
-    dev->priv = 0;
-    dev->priv = (struct net_device *) kmalloc(dev_size, GFP_DMA | GFP_KERNEL |GFP_ATOMIC);
-    if (!dev->priv)
-    {
-        printk("rc: unable to kmalloc private area\n");
-        return 1;  
-    }
-    memset(dev->priv, 0, dev_size);
-#endif
 
 #ifdef RCDEBUG
     printk("rc: dev = 0x%x, dev->priv = 0x%x\n", (uint)dev, (uint)dev->priv);
@@ -386,7 +370,6 @@
     pDpa->next = root_RCdev;
     root_RCdev = dev;
 
-#ifdef MODULE
     if (register_netdev(dev) != 0) /* linux kernel interface */
     {
         printk("rc: unable to register device \n");
@@ -395,9 +378,6 @@
         kfree(dev);
         return 1;
     }
-#else
-    RCinit(dev);
-#endif
     printk("%s: RedCreek Communications IPSEC VPN adapter\n",
         dev->name);
 
diff -u --recursive --new-file v2.3.26/linux/drivers/net/rrunner.c linux/drivers/net/rrunner.c
--- v2.3.26/linux/drivers/net/rrunner.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/rrunner.c	Tue Nov  9 08:20:12 1999
@@ -72,10 +72,11 @@
 
 static int probed __initdata = 0;
 
-int __init rr_hippi_probe (struct net_device *dev)
+int __init rr_hippi_probe (void)
 {
 	int boards_found = 0;
 	int version_disp;	/* was version info already displayed? */
+	struct net_device *dev;
 	struct pci_dev *pdev = NULL;
 	struct pci_dev *opdev = NULL;
 	u8 pci_latency;
@@ -101,7 +102,7 @@
 		 * So we found our HIPPI ... time to tell the system.
 		 */
 
-		dev = init_hippi_dev(dev, sizeof(struct rr_private));
+		dev = init_hippi_dev(NULL, sizeof(struct rr_private));
 
 		if (!dev)
 			break;
@@ -192,14 +193,7 @@
 	 * 1 or more boards. Otherwise, return failure (-ENODEV).
 	 */
 
-#ifdef MODULE
 	return boards_found;
-#else
-	if (boards_found > 0)
-		return 0;
-	else
-		return -ENODEV;
-#endif
 }
 
 static struct net_device *root_dev = NULL;
@@ -213,12 +207,7 @@
 
 int init_module(void)
 {
-	int cards;
-
-	root_dev = NULL;
-
-	cards = rr_hippi_probe(NULL);
-	return cards ? 0 : -ENODEV;
+	return rr_hippi_probe()? 0 : -ENODEV;
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.3.26/linux/drivers/net/rtl8139.c linux/drivers/net/rtl8139.c
--- v2.3.26/linux/drivers/net/rtl8139.c	Fri Sep 10 23:57:30 1999
+++ linux/drivers/net/rtl8139.c	Tue Nov  9 08:20:12 1999
@@ -165,12 +165,10 @@
 	const char *name;
 	u16	vendor_id, device_id, device_id_mask, flags;
 	int io_size;
-	struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev,
-							 long ioaddr, int irq, int chip_idx, int fnd_cnt);
+	struct net_device *(*probe1)(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
 };
 
-static struct net_device * rtl8129_probe1(int pci_bus, int pci_devfn,
-									  struct net_device *dev, long ioaddr,
+static struct net_device * rtl8129_probe1(int pci_bus, int pci_devfn, long ioaddr,
 									  int irq, int chp_idx, int fnd_cnt);
 
 static struct pci_id_info pci_tbl[] =
@@ -319,11 +317,12 @@
    well when dynamically adding drivers.  So instead we detect just the
    Rtl81*9 cards in slot order. */
 
-int rtl8139_probe(struct net_device *dev)
+int rtl8139_probe(void)
 {
 	int cards_found = 0;
 	int pci_index = 0;
 	unsigned char pci_bus, pci_device_fn;
+	struct net_device *dev;
 
 	if ( ! pcibios_present())
 		return -ENODEV;
@@ -383,8 +382,7 @@
 									  PCI_COMMAND, new_command);
 		}
 
-		dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, ioaddr,
-									   irq, chip_idx, cards_found);
+		dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, ioaddr, irq, chip_idx, cards_found);
 
 		if (dev  && (pci_tbl[chip_idx].flags & PCI_COMMAND_MASTER)) {
 			u8 pci_latency;
@@ -405,18 +403,18 @@
 	return cards_found ? 0 : -ENODEV;
 }
 
-static struct net_device *rtl8129_probe1(int pci_bus, int pci_devfn,
-									 struct net_device *dev, long ioaddr,
+static struct net_device *rtl8129_probe1(int pci_bus, int pci_devfn, long ioaddr,
 									 int irq, int chip_idx, int found_cnt)
 {
 	static int did_version = 0;			/* Already printed version info. */
 	struct rtl8129_private *tp;
 	int i, option = found_cnt < MAX_UNITS ? options[found_cnt] : 0;
+	struct net_device *dev;
 
 	if (rtl8129_debug > 0  &&  did_version++ == 0)
 		printk(KERN_INFO "%s", version);
 
-	dev = init_etherdev(dev, 0);
+	dev = init_etherdev(NULL, 0);
 
 	printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ",
 		   dev->name, pci_tbl[chip_idx].name, ioaddr, irq);
@@ -1429,7 +1427,7 @@
 #ifdef MODULE
 int init_module(void)
 {
-	return rtl8139_probe(0);
+	return rtl8139_probe();
 }
 
 void
diff -u --recursive --new-file v2.3.26/linux/drivers/net/seeq8005.c linux/drivers/net/seeq8005.c
--- v2.3.26/linux/drivers/net/seeq8005.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/seeq8005.c	Wed Nov 10 20:02:27 1999
@@ -30,6 +30,7 @@
   	0.48	Receive working
 */
 
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/types.h>
@@ -780,7 +781,7 @@
 	/*
 	 *	If we don't do this, we can't re-insmod it later.
 	 */
-	release_region(dev_seeq.base_addr, EL1_IO_EXTENT);
+	release_region(dev_seeq.base_addr, SEEQ8005_IO_EXTENT);
 }
 
 #endif /* MODULE */
diff -u --recursive --new-file v2.3.26/linux/drivers/net/setup.c linux/drivers/net/setup.c
--- v2.3.26/linux/drivers/net/setup.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/setup.c	Wed Nov 10 19:55:55 1999
@@ -0,0 +1,371 @@
+/*
+ *	New style setup code for the network devices
+ */
+ 
+#include <linux/config.h>
+#include <linux/netdevice.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/netlink.h>
+
+extern int mkiss_init_ctrl_dev(void);
+extern int ppp_init(void);
+extern int slip_init_ctrl_dev(void);
+extern int strip_init_ctrl_dev(void);
+extern int x25_asy_init_ctrl_dev(void);
+  
+extern int bpq_init(void);
+extern int dmascc_init(void);
+extern int scc_init(void);
+extern int yam_init(void);
+
+extern int acenic_probe(void); 
+extern int arcnet_init(void); 
+extern int bigmac_probe(void); 
+extern int bmac_probe(void); 
+extern int cpm_enet_init(void); 
+extern int dlci_setup(void); 
+extern int dgrs_probe(void); 
+extern int dmfe_reg_board(void); 
+extern int eepro100_probe(void); 
+extern int epic100_probe(void); 
+extern int happy_meal_probe(void); 
+extern int lapbeth_init(void);
+extern int mace_probe(void); 
+extern int myri_sbus_probe(void); 
+extern int ncr885e_probe(void); 
+extern int ne2k_pci_probe(void); 
+extern int pcnet32_probe(void); 
+extern int qec_probe(void); 
+extern int rcpci_probe(void); 
+extern int rr_hippi_probe(void); 
+extern int rtl8139_probe(void); 
+extern int sdla_setup(void); 
+extern int sis900_probe(void); 
+extern int sparc_lance_probe(void); 
+extern int starfire_probe(void); 
+extern int tc59x_probe(void); 
+extern int tulip_probe(void); 
+extern int via_rhine_probe(void); 
+extern int yellowfin_probe(void);
+
+/* Pad device name to IFNAMSIZ=16. F.e. __PAD6 is tring of 9 zeros. */
+#define __PAD6 "\0\0\0\0\0\0\0\0\0"
+#define __PAD5 __PAD6 "\0"
+#define __PAD4 __PAD5 "\0"
+#define __PAD3 __PAD4 "\0"
+#define __PAD2 __PAD3 "\0"
+
+
+/*
+ *	Devices in this list must do new style probing. That is they must
+ *	allocate their own device objects and do their own bus scans.
+ */
+
+struct net_probe
+{
+	int (*probe)(void);
+	int status;	/* non-zero if autoprobe has failed */
+};
+ 
+struct net_probe pci_probes[] __initdata = {
+	/*
+	 *	Early setup devices
+	 */
+
+#if defined(CONFIG_SCC)
+	{scc_init, 0},
+#endif
+#if defined(CONFIG_DMASCC)
+	{dmascc_init, 0},
+#endif	
+#if defined(CONFIG_BPQETHER)
+	{bpq_init, 0},
+#endif
+#if defined(CONFIG_DLCI)
+	{dlci_setup, 0},
+#endif
+#if defined(CONFIG_SDLA)
+	{sdla_setup, 0},
+#endif
+#if defined(CONFIG_LAPBETHER)
+	{lapbeth_init, 0},
+#endif
+#if defined(CONFIG_PLIP)
+	{plip_init, 0},
+#endif
+#if defined(CONFIG_ARCNET)
+	{arcnet_init, 0},
+#endif
+#if defined(CONFIG_8xx)
+        {cpm_enet_init, 0},
+#endif
+	/*
+	 *	SLHC if present needs attaching so other people see it
+	 *	even if not opened.
+	 */
+	 
+#ifdef CONFIG_INET	 
+#if (defined(CONFIG_SLIP) && defined(CONFIG_SLIP_COMPRESSED)) \
+	 || defined(CONFIG_PPP) \
+    || (defined(CONFIG_ISDN) && defined(CONFIG_ISDN_PPP))
+	{slhc_install, 0},
+#endif	
+#endif
+/*
+ *	HIPPI
+ */
+#ifdef CONFIG_ROADRUNNER
+	{rr_hippi_probe, 0},
+#endif
+
+/*
+ *	ETHERNET
+ */
+ 
+/*
+ *	SBUS Ethernet
+ */
+
+#ifdef CONFIG_HAPPYMEAL
+	{happy_meal_probe, 0},
+#endif
+#ifdef CONFIG_SUNLANCE
+	{sparc_lance_probe, 0},
+#endif
+#ifdef CONFIG_SUNQE
+	{qec_probe, 0},
+#endif
+#ifdef CONFIG_SUNBMAC
+	{bigmac_probe, 0},
+#endif
+#ifdef CONFIG_MYRI_SBUS
+	{myri_sbus_probe, 0},
+#endif
+
+/*
+ *	PowerPC Mainboard
+ */
+
+#ifdef CONFIG_MACE
+	{mace_probe, 0},
+#endif
+#ifdef CONFIG_BMAC
+	{bmac_probe, 0},
+#endif
+#ifdef CONFIG_NCR885E
+	{ncr885e_probe, 0},
+#endif
+
+/*
+ *	PCI Ethernet
+ */
+#ifdef CONFIG_DGRS
+	{dgrs_probe, 0},
+#endif
+#ifdef CONFIG_RCPCI
+	{rcpci_probe, 0},
+#endif
+#ifdef CONFIG_VORTEX
+	{tc59x_probe, 0},
+#endif
+#ifdef CONFIG_NE2K_PCI
+	{ne2k_pci_probe, 0},
+#endif
+#ifdef CONFIG_PCNET32
+	{pcnet32_probe, 0},
+#endif	
+#ifdef CONFIG_EEXPRESS_PRO100	/* Intel EtherExpress Pro/100 */
+	{eepro100_probe, 0},
+#endif
+#ifdef CONFIG_DEC_ELCP 
+	{tulip_probe, 0},
+#endif
+#ifdef CONFIG_DE4X5             /* DEC DE425, DE434, DE435 adapters */
+	{de4x5_probe, 0},
+#endif
+#ifdef CONFIG_EPIC100
+	{epic100_probe, 0},
+#endif
+#ifdef CONFIG_RTL8139
+	{rtl8139_probe, 0},
+#endif
+#ifdef CONFIG_SIS900
+	{sis900_probe, 0},
+#endif
+
+#ifdef CONFIG_DM9102
+	{dmfe_reg_board, 0}, 
+#endif
+
+#ifdef CONFIG_YELLOWFIN
+	{yellowfin_probe, 0},
+#endif
+#ifdef CONFIG_ACENIC
+	{acenic_probe, 0},
+#endif
+#ifdef CONFIG_VIA_RHINE
+	{via_rhine_probe, 0},
+#endif
+#ifdef CONFIG_ADAPTEC_STARFIRE
+	{starfire_probe, 0},
+#endif
+
+/*
+ *	Amateur Radio Drivers
+ */	
+
+#ifdef CONFIG_YAM
+	{yam_init, 0},
+#endif	/* CONFIG_YAM */
+  
+ 
+	{NULL, 0},
+};
+
+
+/*
+ *	Run the updated device probes. These do not need a device passed
+ *	into them.
+ */
+ 
+static void __init network_probe(void)
+{
+	struct net_probe *p = pci_probes;
+
+	while (p->probe != NULL)
+	{
+		p->status = p->probe();
+		p++;
+	}
+}
+
+
+/*
+ *	Initialise the line discipline drivers
+ */
+ 
+static void __init network_ldisc_init(void)
+{
+#if defined(CONFIG_SLIP)
+	slip_init_ctrl_dev();
+#endif
+#if defined(CONFIG_X25_ASY)
+	x25_asy_init_ctrl_dev();
+#endif
+#if defined(CONFIG_MKISS)
+	mkiss_init_ctrl_dev();
+#endif
+#if defined(CONFIG_STRIP)
+	strip_init_ctrl_dev();
+#endif
+#if defined(CONFIG_PPP)
+	ppp_init();
+#endif
+}
+
+
+static void __init appletalk_device_init(void)
+{
+#if defined(CONFIG_IPDDP)
+	extern int ipddp_init(struct net_device *dev);
+	static struct net_device dev_ipddp = {
+				"ipddp0"  __PAD6,
+				0, 0, 0, 0,
+				0x0, 0,
+				0, 0, 0, NULL, ipddp_init 
+	};
+	
+	dev_ipddp.init(&dev_ipddp);
+#endif /* CONFIG_IPDDP */
+}
+
+
+/*
+ *	The loopback device is global so it can be directly referenced
+ *	by the network code.
+ */
+ 
+extern int loopback_init(struct net_device *dev);
+struct net_device loopback_dev = 
+{
+	"lo" __PAD2,		/* Software Loopback interface		*/
+	0x0,			/* recv memory end			*/
+	0x0,			/* recv memory start			*/
+	0x0,			/* memory end				*/
+	0x0,			/* memory start				*/
+	0,			/* base I/O address			*/
+	0,			/* IRQ					*/
+	0, 0, 0,		/* flags				*/
+	NULL,			/* next device				*/
+	loopback_init		/* loopback_init should set up the rest	*/
+};
+
+static void special_device_init(void)
+{
+#ifdef CONFIG_DUMMY
+	{
+		extern int dummy_init(struct net_device *dev);
+		static struct net_device dummy_dev = {
+			"dummy" __PAD5, 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, dummy_init, 
+		};
+		register_netdev(&sb1000_dev);
+	}
+#endif	
+#ifdef CONFIG_EQUALIZER
+	{
+		extern int eql_init(struct net_device *dev);
+		static struct net_device eql_dev = 
+		{
+			"eql" __PAD3,			/* Master device for IP traffic load balancing */
+			0x0, 0x0, 0x0, 0x0,		/* recv end/start; mem end/start */
+			0,				/* base I/O address */
+			0,				/* IRQ */
+			0, 0, 0,			/* flags */
+			NULL,				/* next device */
+			eql_init			/* set up the rest */
+		};
+		register_netdev(&sb1000_dev);
+	}
+#endif	
+#ifdef CONFIG_APBIF
+	{
+		extern int bif_init(struct net_device *dev);
+		static struct net_device bif_dev = 
+		{
+        		"bif" __PAD3, 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, bif_init 
+        	};
+		register_netdev(&sb1000_dev);
+        }
+#endif
+#ifdef CONFIG_NET_SB1000
+	{
+		extern int sb1000_probe(struct net_device *dev);
+		static struct net_device sb1000_dev = 
+		{
+			"cm0", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, sb1000_probe 
+		};
+		register_netdev(&sb1000_dev);
+	}
+#endif
+	register_netdev(&loopback_dev);
+}
+
+/*
+ *	Initialise network devices
+ */
+ 
+void __init net_device_init(void)
+{
+	/* Devices supporting the new probing API */
+	network_probe();
+	/* Line disciplines */
+	network_ldisc_init();
+	/* Appletalk */
+	appletalk_device_init();
+	/* Special devices */
+	special_device_init();
+	/* That kicks off the legacy init functions */
+}
+
+	 
diff -u --recursive --new-file v2.3.26/linux/drivers/net/sk_mca.c linux/drivers/net/sk_mca.c
--- v2.3.26/linux/drivers/net/sk_mca.c	Mon Nov  1 13:56:26 1999
+++ linux/drivers/net/sk_mca.c	Wed Nov 10 10:00:48 1999
@@ -71,7 +71,6 @@
 #include <linux/version.h>
 
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
diff -u --recursive --new-file v2.3.26/linux/drivers/net/slhc.c linux/drivers/net/slhc.c
--- v2.3.26/linux/drivers/net/slhc.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/net/slhc.c	Tue Nov  9 08:20:12 1999
@@ -759,6 +759,7 @@
 #endif /* MODULE */
 #else /* CONFIG_INET */
 
+
 int
 slhc_toss(struct slcompress *comp)
 {
diff -u --recursive --new-file v2.3.26/linux/drivers/net/slip.c linux/drivers/net/slip.c
--- v2.3.26/linux/drivers/net/slip.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/net/slip.c	Tue Nov  9 08:20:12 1999
@@ -1318,11 +1318,8 @@
 /* VSV changes end */
 
 /* Initialize SLIP control device -- register SLIP line discipline */
-#ifdef MODULE
-static int slip_init_ctrl_dev(void)
-#else	/* !MODULE */
-int __init slip_init_ctrl_dev(struct net_device *dummy)
-#endif	/* !MODULE */
+
+int __init slip_init_ctrl_dev(void)
 {
 	int status;
 
@@ -1371,15 +1368,8 @@
 	}
 
 
-#ifdef MODULE
 	return status;
-#else
-	/* Return "not found", so that dev_init() will unlink
-	 * the placeholder device entry for us.
-	 */
-	return ENODEV;
-#endif
-      }
+}
 
 
 
diff -u --recursive --new-file v2.3.26/linux/drivers/net/starfire.c linux/drivers/net/starfire.c
--- v2.3.26/linux/drivers/net/starfire.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/net/starfire.c	Tue Nov  9 08:20:12 1999
@@ -213,12 +213,10 @@
 	const char *name;
 	u16	vendor_id, device_id, device_id_mask, flags;
 	int io_size;
-	struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev,
-								 long ioaddr, int irq, int chip_idx, int fnd_cnt);
+	struct net_device *(*probe1)(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
 };
 
-static struct net_device *starfire_probe1(int pci_bus, int pci_devfn,
-									  struct net_device *dev, long ioaddr,
+static struct net_device *starfire_probe1(int pci_bus, int pci_devfn, long ioaddr,
 									  int irq, int chp_idx, int fnd_cnt);
 
 #if 0
@@ -392,11 +390,12 @@
    well when dynamically adding drivers.  So instead we detect just the
    cards we know about in slot order. */
 
-static int pci_etherdev_probe(struct net_device *dev, struct pci_id_info pci_tbl[])
+static int pci_etherdev_probe(struct pci_id_info pci_tbl[])
 {
 	int cards_found = 0;
 	int pci_index = 0;
 	unsigned char pci_bus, pci_device_fn;
+	struct net_device *dev;
 
 	if ( ! pcibios_present())
 		return -ENODEV;
@@ -459,7 +458,7 @@
 									  PCI_COMMAND, new_command);
 		}
 
-		dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, ioaddr,
+		dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, ioaddr,
 									   irq, chip_idx, cards_found);
 
 		if (dev  && (pci_tbl[chip_idx].flags & PCI_COMMAND_MASTER)) {
@@ -474,16 +473,15 @@
 										  PCI_LATENCY_TIMER, min_pci_latency);
 			}
 		}
-		dev = 0;
 		cards_found++;
 	}
 
 	return cards_found ? 0 : -ENODEV;
 }
 
-int starfire_probe(struct net_device *dev)
+int starfire_probe(void)
 {
-	if (pci_etherdev_probe(dev, pci_tbl) < 0)
+	if (pci_etherdev_probe(pci_tbl) < 0)
 		return -ENODEV;
 	printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
 	return 0;
@@ -491,13 +489,11 @@
 
 
 static struct net_device *
-starfire_probe1(int pci_bus, int pci_devfn, struct net_device *dev,
-				long ioaddr, int irq, int chip_id, int card_idx)
+starfire_probe1(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_id, int card_idx)
 {
 	struct netdev_private *np;
 	int i, option = card_idx < MAX_UNITS ? options[card_idx] : 0;
-
-	dev = init_etherdev(dev, sizeof(struct netdev_private));
+	struct net_device *dev = init_etherdev(NULL, sizeof(struct netdev_private));
 
 	printk(KERN_INFO "%s: %s at 0x%lx, ",
 		   dev->name, skel_netdrv_tbl[chip_id].chip_name, ioaddr);
@@ -1388,7 +1384,7 @@
 	register_driver(&etherdev_ops);
 	return 0;
 #else
-	if (pci_etherdev_probe(NULL, pci_tbl)) {
+	if (pci_etherdev_probe(pci_tbl)) {
 		printk(KERN_INFO " No Starfire adapters detected, driver not loaded.\n");
 		return -ENODEV;
 	}
diff -u --recursive --new-file v2.3.26/linux/drivers/net/strip.c linux/drivers/net/strip.c
--- v2.3.26/linux/drivers/net/strip.c	Mon Nov  1 13:56:26 1999
+++ linux/drivers/net/strip.c	Tue Nov  9 08:20:12 1999
@@ -2831,9 +2831,6 @@
  * STRIP driver
  */
 
-#ifdef MODULE
-static
-#endif
 int strip_init_ctrl_dev(struct net_device *dummy)
 {
     static struct tty_ldisc strip_ldisc;
diff -u --recursive --new-file v2.3.26/linux/drivers/net/sunbmac.c linux/drivers/net/sunbmac.c
--- v2.3.26/linux/drivers/net/sunbmac.c	Wed Aug 18 11:36:43 1999
+++ linux/drivers/net/sunbmac.c	Tue Nov  9 08:20:12 1999
@@ -1492,8 +1492,9 @@
 	return res;	/* Return error code. */
 }
 
-int __init bigmac_probe(struct net_device *dev)
+int __init bigmac_probe(void)
 {
+	struct net_device *dev = NULL;
 	struct linux_sbus *bus;
 	struct linux_sbus_device *sdev = 0;
 	static int called = 0;
@@ -1529,7 +1530,7 @@
 init_module(void)
 {
 	root_bigmac_dev = NULL;
-	return bigmac_probe(NULL);
+	return bigmac_probe();
 }
 
 void
diff -u --recursive --new-file v2.3.26/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c
--- v2.3.26/linux/drivers/net/sunhme.c	Fri Sep 10 23:57:30 1999
+++ linux/drivers/net/sunhme.c	Tue Nov  9 08:20:12 1999
@@ -3459,8 +3459,9 @@
 }
 #endif
 
-int __init happy_meal_probe(struct net_device *dev)
+int __init happy_meal_probe(void)
 {
+	struct net_device *dev = NULL;
 	struct linux_sbus *bus;
 	struct linux_sbus_device *sdev = 0;
 	static int called = 0;
diff -u --recursive --new-file v2.3.26/linux/drivers/net/sunlance.c linux/drivers/net/sunlance.c
--- v2.3.26/linux/drivers/net/sunlance.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/net/sunlance.c	Tue Nov  9 08:20:12 1999
@@ -1157,7 +1157,7 @@
 #include <asm/sun4paddr.h>
 
 /* Find all the lance cards on the system and initialize them */
-int __init sparc_lance_probe (struct net_device *dev)
+int __init sparc_lance_probe(void)
 {
 	static struct linux_sbus_device sdev;
 	static int called = 0;
@@ -1171,7 +1171,7 @@
 		memset (&sdev, 0, sizeof(sdev));
 		sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr;
 		sdev.irqs[0] = 6;
-		return sparc_lance_init(dev, &sdev, 0, 0);
+		return sparc_lance_init(NULL, &sdev, 0, 0);
 	}
 	return ENODEV;
 }
@@ -1179,10 +1179,11 @@
 #else /* !CONFIG_SUN4 */
 
 /* Find all the lance cards on the system and initialize them */
-int __init sparc_lance_probe (struct net_device *dev)
+int __init sparc_lance_probe (void)
 {
 	struct linux_sbus *bus;
 	struct linux_sbus_device *sdev = 0;
+	struct net_device *dev = NULL;
 	struct Linux_SBus_DMA *ledma = 0;
 	static int called = 0;
 	int cards = 0, v;
@@ -1229,7 +1230,7 @@
 init_module(void)
 {
 	root_lance_dev = NULL;
-	return sparc_lance_probe(NULL);
+	return sparc_lance_probe();
 }
 
 void
diff -u --recursive --new-file v2.3.26/linux/drivers/net/sunqe.c linux/drivers/net/sunqe.c
--- v2.3.26/linux/drivers/net/sunqe.c	Fri Sep 10 23:57:30 1999
+++ linux/drivers/net/sunqe.c	Tue Nov  9 08:20:12 1999
@@ -926,8 +926,9 @@
 	return res;
 }
 
-int __init qec_probe(struct net_device *dev)
+int __init qec_probe(void)
 {
+	struct net_device *dev = NULL;
 	struct linux_sbus *bus;
 	struct linux_sbus_device *sdev = 0;
 	static int called = 0;
@@ -969,7 +970,7 @@
 init_module(void)
 {
 	root_qec_dev = NULL;
-	return qec_probe(NULL);
+	return qec_probe();
 }
 
 void
diff -u --recursive --new-file v2.3.26/linux/drivers/net/tulip.c linux/drivers/net/tulip.c
--- v2.3.26/linux/drivers/net/tulip.c	Wed Aug 18 11:36:43 1999
+++ linux/drivers/net/tulip.c	Tue Nov  9 08:20:12 1999
@@ -410,7 +410,6 @@
 };
 
 static struct net_device *tulip_probe1(int pci_bus, int pci_devfn,
-								   struct net_device *dev,
 								   int chip_id, int options);
 static void parse_eeprom(struct net_device *dev);
 static int read_eeprom(long ioaddr, int location);
@@ -446,7 +445,7 @@
    This allows the probe routine to use the old driver initialization
    interface. */
 
-int tulip_probe(struct net_device *dev)
+int tulip_probe(void)
 {
 	int cards_found = 0;
 	static int pci_index = 0;	/* Static, for multiple probe calls. */
@@ -523,10 +522,9 @@
 									  PCI_COMMAND, new_command);
 		}
 
-		dev = tulip_probe1(pci_bus, pci_device_fn, dev, chip_idx, cards_found);
-
-		/* Get and check the bus-master and latency values. */
-		if (dev) {
+		if(tulip_probe1(pci_bus, pci_device_fn, chip_idx, cards_found))
+		{
+			/* Get and check the bus-master and latency values. */
 			unsigned char pci_latency;
 			pcibios_read_config_byte(pci_bus, pci_device_fn,
 									 PCI_LATENCY_TIMER, &pci_latency);
@@ -544,7 +542,6 @@
 			if (device == PCI_DEVICE_ID_DEC_TULIP_21142)
 				pcibios_write_config_dword(pci_bus, pci_device_fn,
 										   0x40, 0x40000000);
-			dev = 0;
 			cards_found++;
 		}
 	}
@@ -553,9 +550,9 @@
 }
 
 static struct net_device *tulip_probe1(int pci_bus, int pci_device_fn,
-								   struct net_device *dev,
 								   int chip_id, int board_idx)
 {
+	struct net_device *dev;
 	static int did_version = 0;			/* Already printed version info. */
 	struct tulip_private *tp;
 	long ioaddr;
@@ -570,7 +567,7 @@
 	if (tulip_debug > 0  &&  did_version++ == 0)
 		printk(KERN_INFO "%s", version);
 
-	dev = init_etherdev(dev, 0);
+	dev = init_etherdev(NULL, 0);
 
 	irq = pci_find_slot(pci_bus, pci_device_fn)->irq;
 	ioaddr = pci_find_slot(pci_bus, pci_device_fn)->resource[0].start;
@@ -2745,7 +2742,7 @@
 	pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
 	pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
 	io &= ~3;
-	dev = tulip_probe1(bus, devfn, NULL, DC21142, -1);
+	dev = tulip_probe1(bus, devfn, DC21142, -1);
 	if (dev) {
 		dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
 		strcpy(node->dev_name, dev->name);
@@ -2806,7 +2803,7 @@
 	register_driver(&tulip_ops);
 	return 0;
 #else
-	return tulip_probe(NULL);
+	return tulip_probe();
 #endif
 }
 
diff -u --recursive --new-file v2.3.26/linux/drivers/net/via-rhine.c linux/drivers/net/via-rhine.c
--- v2.3.26/linux/drivers/net/via-rhine.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/net/via-rhine.c	Tue Nov  9 08:20:12 1999
@@ -248,12 +248,10 @@
 	const char *name;
 	u16	vendor_id, device_id, device_id_mask, flags;
 	int io_size;
-	struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev,
-							 long ioaddr, int irq, int chip_idx, int fnd_cnt);
+	struct net_device *(*probe1)(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
 };
 
-static struct net_device *via_probe1(int pci_bus, int pci_devfn,
-								 struct net_device *dev, long ioaddr, int irq,
+static struct net_device *via_probe1(int pci_bus, int pci_devfn, long ioaddr, int irq,
 								 int chp_idx, int fnd_cnt);
 
 static struct pci_id_info pci_tbl[] = {
@@ -393,11 +391,12 @@
    well when dynamically adding drivers.  So instead we detect just the
    cards we know about in slot order. */
 
-static int pci_etherdev_probe(struct net_device *dev, struct pci_id_info pci_tbl[])
+static int pci_etherdev_probe(struct pci_id_info pci_tbl[])
 {
 	int cards_found = 0;
 	int pci_index = 0;
 	unsigned char pci_bus, pci_device_fn;
+	struct net_device *dev;
 
 	if ( ! pcibios_present())
 		return -ENODEV;
@@ -478,7 +477,7 @@
 									  PCI_COMMAND, new_command);
 		}
 
-		dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, ioaddr,
+		dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, ioaddr,
 									   irq, chip_idx, cards_found);
 
 		if (dev  && (pci_tbl[chip_idx].flags & PCI_COMMAND_MASTER)) {
@@ -501,21 +500,24 @@
 }
 
 #ifndef MODULE
-int via_rhine_probe(struct net_device *dev)
+int via_rhine_probe(void)
 {
 	printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
-	return pci_etherdev_probe(dev, pci_tbl);
+	return pci_etherdev_probe(pci_tbl);
 }
 #endif
 
 static struct net_device *via_probe1(int pci_bus, int pci_devfn,
-								 struct net_device *dev, long ioaddr, int irq,
+								 long ioaddr, int irq,
 								 int chip_id, int card_idx)
 {
+	struct net_device *dev;
 	struct netdev_private *np;
 	int i, option = card_idx < MAX_UNITS ? options[card_idx] : 0;
 
-	dev = init_etherdev(dev, 0);
+	dev = init_etherdev(NULL, 0);
+	if(dev==NULL)
+		return NULL;
 
 	printk(KERN_INFO "%s: %s at 0x%lx, ",
 		   dev->name, pci_tbl[chip_id].name, ioaddr);
@@ -539,6 +541,7 @@
 
 	/* Make certain the descriptor lists are cache-aligned. */
 	np = (void *)(((long)kmalloc(sizeof(*np), GFP_KERNEL) + 31) & ~31);
+	/* FIXME! check return !!! */		
 	memset(np, 0, sizeof(*np));
 	dev->priv = np;
 
@@ -1264,7 +1267,7 @@
 	register_driver(&etherdev_ops);
 	return 0;
 #else
-	return pci_etherdev_probe(NULL, pci_tbl);
+	return pci_etherdev_probe(pci_tbl);
 #endif
 }
 
diff -u --recursive --new-file v2.3.26/linux/drivers/net/wan/sdla.c linux/drivers/net/wan/sdla.c
--- v2.3.26/linux/drivers/net/wan/sdla.c	Mon Oct 11 15:38:15 1999
+++ linux/drivers/net/wan/sdla.c	Tue Nov  9 08:20:12 1999
@@ -1666,10 +1666,11 @@
 	return(0);
 }
 
-void __init sdla_setup(void)
+int __init sdla_setup(void)
 {
 	printk("%s.\n", version);
 	register_frad(devname);
+	return 0;
 }
 
 #ifdef MODULE
diff -u --recursive --new-file v2.3.26/linux/drivers/net/wan/x25_asy.c linux/drivers/net/wan/x25_asy.c
--- v2.3.26/linux/drivers/net/wan/x25_asy.c	Mon Oct 11 15:38:15 1999
+++ linux/drivers/net/wan/x25_asy.c	Tue Nov  9 08:20:12 1999
@@ -813,11 +813,8 @@
 }
 
 /* Initialize X.25 control device -- register X.25 line discipline */
-#ifdef MODULE
-static int x25_asy_init_ctrl_dev(void)
-#else	/* !MODULE */
-int __init x25_asy_init_ctrl_dev(struct net_device *dummy)
-#endif	/* !MODULE */
+
+int __init x25_asy_init_ctrl_dev(void)
 {
 	int status;
 
@@ -854,15 +851,8 @@
 		printk("X.25 async: can't register line discipline (err = %d)\n", status);
 	}
 
-#ifdef MODULE
 	return status;
-#else
-	/* Return "not found", so that dev_init() will unlink
-	 * the placeholder device entry for us.
-	 */
-	return ENODEV;
-#endif
-      }
+}
 
 
 /* Initialise the X.25 driver.  Called by the device init code */
diff -u --recursive --new-file v2.3.26/linux/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c
--- v2.3.26/linux/drivers/net/yellowfin.c	Wed Aug 18 11:36:43 1999
+++ linux/drivers/net/yellowfin.c	Tue Nov  9 08:20:12 1999
@@ -316,8 +316,7 @@
 
 #endif
 
-static struct net_device *yellowfin_probe1(struct net_device *dev, long ioaddr,
-									   int irq, int chip_id, int options);
+static struct net_device *yellowfin_probe1(long ioaddr, int irq, int chip_id, int options);
 static int read_eeprom(long ioaddr, int location);
 static int mdio_read(long ioaddr, int phy_id, int location);
 static void mdio_write(long ioaddr, int phy_id, int location, int value);
@@ -341,7 +340,7 @@
 /* A list of all installed Yellowfin devices, for removing the driver module. */
 static struct net_device *root_yellowfin_dev = NULL;
 
-int yellowfin_probe(struct net_device *dev)
+int yellowfin_probe(void)
 {
 	int cards_found = 0;
 	int pci_index = 0;
@@ -400,9 +399,8 @@
 									  PCI_COMMAND, new_command);
 		}
 
-		dev = yellowfin_probe1(dev, ioaddr, irq, chip_idx, cards_found);
-
-		if (dev) {
+		if(yellowfin_probe1(ioaddr, irq, chip_idx, cards_found))
+		{
 			/* Get and check the bus-master and latency values. */
 			pcibios_read_config_byte(pci_bus, pci_device_fn,
 									 PCI_LATENCY_TIMER, &pci_latency);
@@ -415,7 +413,6 @@
 			} else if (yellowfin_debug > 1)
 				printk(KERN_INFO "  PCI latency timer (CFLT) is %#x.\n",
 					   pci_latency);
-			dev = 0;
 			cards_found++;
 		}
 	}
@@ -423,17 +420,17 @@
 	return cards_found ? 0 : -ENODEV;
 }
 
-static struct net_device *yellowfin_probe1(struct net_device *dev, long ioaddr,
-									   int irq, int chip_id, int card_idx)
+static struct net_device *yellowfin_probe1(long ioaddr, int irq, int chip_id, int card_idx)
 {
 	static int did_version = 0;			/* Already printed version info. */
 	struct yellowfin_private *yp;
 	int option, i;
+	struct net_device *dev;
 
 	if (yellowfin_debug > 0  &&  did_version++ == 0)
 		printk(version);
 
-	dev = init_etherdev(dev, sizeof(struct yellowfin_private));
+	dev = init_etherdev(NULL, sizeof(struct yellowfin_private));
 
 	printk(KERN_INFO "%s: %s type %8x at 0x%lx, ",
 		   dev->name, chip_tbl[chip_id].name, inl(ioaddr + ChipRev), ioaddr);
@@ -1372,7 +1369,7 @@
 	if (debug >= 0)
 		yellowfin_debug = debug;
 
-	return yellowfin_probe(0);
+	return yellowfin_probe();
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.3.26/linux/drivers/parport/ieee1284.c linux/drivers/parport/ieee1284.c
--- v2.3.26/linux/drivers/parport/ieee1284.c	Fri Oct 15 15:25:13 1999
+++ linux/drivers/parport/ieee1284.c	Mon Nov  8 10:40:40 1999
@@ -80,19 +80,42 @@
  * 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 @@
 	 * 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 @@
 			/* 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 @@
 				      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 -u --recursive --new-file v2.3.26/linux/drivers/parport/ieee1284_ops.c linux/drivers/parport/ieee1284_ops.c
--- v2.3.26/linux/drivers/parport/ieee1284_ops.c	Sat Oct  9 11:47:50 1999
+++ linux/drivers/parport/ieee1284_ops.c	Mon Nov  8 10:18:45 1999
@@ -95,7 +95,7 @@
                            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 @@
 			/* 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 -u --recursive --new-file v2.3.26/linux/drivers/parport/init.c linux/drivers/parport/init.c
--- v2.3.26/linux/drivers/parport/init.c	Sat Oct  9 11:47:50 1999
+++ linux/drivers/parport/init.c	Mon Nov  8 10:40:40 1999
@@ -181,6 +181,7 @@
 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 -u --recursive --new-file v2.3.26/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c
--- v2.3.26/linux/drivers/parport/parport_pc.c	Mon Nov  1 13:56:26 1999
+++ linux/drivers/parport/parport_pc.c	Mon Nov  8 10:18:45 1999
@@ -122,7 +122,7 @@
 				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 -u --recursive --new-file v2.3.26/linux/drivers/pci/Makefile linux/drivers/pci/Makefile
--- v2.3.26/linux/drivers/pci/Makefile	Sat Oct  9 11:47:50 1999
+++ linux/drivers/pci/Makefile	Mon Nov  8 11:14:41 1999
@@ -32,3 +32,11 @@
 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 -u --recursive --new-file v2.3.26/linux/drivers/pci/devlist.h linux/drivers/pci/devlist.h
--- v2.3.26/linux/drivers/pci/devlist.h	Mon Nov  1 13:56:26 1999
+++ linux/drivers/pci/devlist.h	Wed Dec 31 16:00:00 1969
@@ -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 -u --recursive --new-file v2.3.26/linux/drivers/pci/gen-devlist.c linux/drivers/pci/gen-devlist.c
--- v2.3.26/linux/drivers/pci/gen-devlist.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/pci/gen-devlist.c	Mon Nov  8 11:20:49 1999
@@ -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 -u --recursive --new-file v2.3.26/linux/drivers/pci/names.c linux/drivers/pci/names.c
--- v2.3.26/linux/drivers/pci/names.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/pci/names.c	Mon Nov  8 11:19:53 1999
@@ -39,11 +39,11 @@
 
 #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 -u --recursive --new-file v2.3.26/linux/drivers/pci/pci.ids linux/drivers/pci/pci.ids
--- v2.3.26/linux/drivers/pci/pci.ids	Wed Dec 31 16:00:00 1969
+++ linux/drivers/pci/pci.ids	Mon Nov  8 17:04:22 1999
@@ -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 -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/bulkmem.c linux/drivers/pcmcia/bulkmem.c
--- v2.3.26/linux/drivers/pcmcia/bulkmem.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/pcmcia/bulkmem.c	Thu Nov 11 16:03:37 1999
@@ -2,7 +2,7 @@
 
     PCMCIA Bulk Memory Services
 
-    bulkmem.c 1.32 1999/09/15 15:32:19
+    bulkmem.c 1.33 1999/10/25 20:03:33
 
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
@@ -15,7 +15,7 @@
     rights and limitations under the License.
 
     The initial developer of the original code is David A. Hinds
-    <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+    <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/cardbus.c linux/drivers/pcmcia/cardbus.c
--- v2.3.26/linux/drivers/pcmcia/cardbus.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/pcmcia/cardbus.c	Thu Nov 11 16:03:37 1999
@@ -2,7 +2,7 @@
   
     Cardbus device configuration
     
-    cardbus.c 1.61 1999/10/20 22:36:57
+    cardbus.c 1.63 1999/11/08 20:47:02
 
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
@@ -15,7 +15,7 @@
     rights and limitations under the License.
 
     The initial developer of the original code is David A. Hinds
-    <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+    <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
@@ -190,7 +190,7 @@
     sz &= PCI_BASE_ADDRESS_MEM_MASK;
     sz = FIND_FIRST_BIT(sz);
     if (sz < PAGE_SIZE) sz = PAGE_SIZE;
-    if (find_mem_region(&base, sz, "cb_enabler", sz, 0) != 0) {
+    if (find_mem_region(&base, sz, sz, 0, "cb_enabler") != 0) {
 	printk(KERN_NOTICE "cs: could not allocate %dK memory for"
 	       " CardBus socket %d\n", sz/1024, s->sock);
 	return CS_OUT_OF_RESOURCE;
@@ -413,7 +413,8 @@
     s->io[0].NumPorts = num[B_IO];
     s->io[0].BasePort = 0;
     if (num[B_IO]) {
-	if (find_io_region(&s->io[0].BasePort, num[B_IO], name) != 0) {
+	if (find_io_region(&s->io[0].BasePort, num[B_IO],
+			   num[B_IO], name) != 0) {
 	    printk(KERN_NOTICE "cs: could not allocate %d IO ports for"
 		   " CardBus socket %d\n", num[B_IO], s->sock);
 	    goto failed;
@@ -423,8 +424,8 @@
     s->win[0].size = num[B_M1];
     s->win[0].base = 0;
     if (num[B_M1]) {
-	if (find_mem_region(&s->win[0].base, num[B_M1],
-			    name, num[B_M1], 0) != 0) {
+	if (find_mem_region(&s->win[0].base, num[B_M1], num[B_M1],
+			    0, name) != 0) {
 	    printk(KERN_NOTICE "cs: could not allocate %dK memory for"
 		   " CardBus socket %d\n", num[B_M1]/1024, s->sock);
 	    goto failed;
@@ -434,8 +435,8 @@
     s->win[1].size = num[B_M2];
     s->win[1].base = 0;
     if (num[B_M2]) {
-	if (find_mem_region(&s->win[1].base, num[B_M2],
-			    name, num[B_M2], 0) != 0) {
+	if (find_mem_region(&s->win[1].base, num[B_M2], num[B_M2],
+			    0, name) != 0) {
 	    printk(KERN_NOTICE "cs: could not allocate %dK memory for"
 		   " CardBus socket %d\n", num[B_M2]/1024, s->sock);
 	    goto failed;
diff -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/cb_enabler.c linux/drivers/pcmcia/cb_enabler.c
--- v2.3.26/linux/drivers/pcmcia/cb_enabler.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/pcmcia/cb_enabler.c	Thu Nov 11 16:03:37 1999
@@ -2,7 +2,7 @@
 
     Cardbus device enabler
 
-    cb_enabler.c 1.24 1999/10/20 00:19:09
+    cb_enabler.c 1.25 1999/10/25 20:03:33
 
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
@@ -15,7 +15,7 @@
     rights and limitations under the License.
 
     The initial developer of the original code is David A. Hinds
-    <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+    <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
@@ -58,7 +58,7 @@
 MODULE_PARM(pc_debug, "i");
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
-"cb_enabler.c 1.24 1999/10/20 00:19:09 (David Hinds)";
+"cb_enabler.c 1.25 1999/10/25 20:03:33 (David Hinds)";
 #else
 #define DEBUG(n, args...) do { } while (0)
 #endif
diff -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/cirrus.h linux/drivers/pcmcia/cirrus.h
--- v2.3.26/linux/drivers/pcmcia/cirrus.h	Tue Sep  7 12:14:06 1999
+++ linux/drivers/pcmcia/cirrus.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * cirrus.h 1.3 1999/08/28 04:01:46
+ * cirrus.h 1.4 1999/10/25 20:03:34
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/cistpl.c linux/drivers/pcmcia/cistpl.c
--- v2.3.26/linux/drivers/pcmcia/cistpl.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/pcmcia/cistpl.c	Thu Nov 11 16:03:37 1999
@@ -2,7 +2,7 @@
 
     PCMCIA Card Information Structure parser
 
-    cistpl.c 1.72 1999/09/15 15:32:19
+    cistpl.c 1.74 1999/11/08 20:47:02
 
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
@@ -15,7 +15,7 @@
     rights and limitations under the License.
 
     The initial developer of the original code is David A. Hinds
-    <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+    <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
@@ -206,7 +206,7 @@
 	s->cis_mem.sys_start = 0;
 	vs = NULL;
 	if (find_mem_region(&s->cis_mem.sys_start, s->cap.map_size,
-			    "card services", s->cap.map_size, low)) {
+			    s->cap.map_size, low, "card services")) {
 	    printk(KERN_NOTICE "cs: unable to map card memory!\n");
 	    return CS_OUT_OF_RESOURCE;
 	}
diff -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c
--- v2.3.26/linux/drivers/pcmcia/cs.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/pcmcia/cs.c	Thu Nov 11 16:03:37 1999
@@ -2,7 +2,7 @@
 
     PCMCIA Card Services -- core services
 
-    cs.c 1.232 1999/10/20 22:17:24
+    cs.c 1.235 1999/11/11 17:52:05
     
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
@@ -15,7 +15,7 @@
     rights and limitations under the License.
 
     The initial developer of the original code is David A. Hinds
-    <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+    <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
@@ -70,7 +70,7 @@
 int pc_debug = PCMCIA_DEBUG;
 MODULE_PARM(pc_debug, "i");
 static const char *version =
-"cs.c 1.232 1999/10/20 22:17:24 (David Hinds)";
+"cs.c 1.235 1999/11/11 17:52:05 (David Hinds)";
 #endif
 
 static const char *release = "Linux PCMCIA Card Services " CS_RELEASE;
@@ -100,7 +100,7 @@
 static int setup_delay		= HZ/20;	/* ticks */
 static int resume_delay		= HZ/5;		/* ticks */
 static int shutdown_delay	= HZ/40;	/* ticks */
-static int vcc_settle		= HZ*3/10;	/* ticks */
+static int vcc_settle		= HZ*4/10;	/* ticks */
 static int reset_time		= 10;		/* usecs */
 static int unreset_delay	= HZ/10;	/* ticks */
 static int unreset_check	= HZ/10;	/* ticks */
@@ -268,8 +268,8 @@
 /*====================================================================*/
 
 #if defined(CONFIG_PROC_FS) && defined(PCMCIA_DEBUG)
-int proc_read_clients(char *buf, char **start, off_t pos,
-		      int count, int *eof, void *data)
+static int proc_read_clients(char *buf, char **start, off_t pos,
+			     int count, int *eof, void *data)
 {
     socket_info_t *s = data;
     client_handle_t c;
@@ -708,14 +708,28 @@
 ======================================================================*/
 
 static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base,
-			  ioaddr_t num, char *name)
+			  ioaddr_t num, u_int lines, char *name)
 {
     int i;
-    ioaddr_t try;
-    
+    ioaddr_t try, align;
+
+    align = (*base) ? (1<<lines) : 1;
+    if (align && (align < num)) {
+	printk(KERN_INFO "odd IO request: num %04x align %04x\n",
+	       num, align);
+	if (*base)
+	    align = 0;
+	else
+	    while (align && (align < num)) align <<= 1;
+    }
+    if (*base & ~(align-1)) {
+	printk(KERN_INFO "odd IO request: base %04x align %04x\n",
+	       *base, align);
+	align = 0;
+    }
     for (i = 0; i < MAX_IO_WIN; i++) {
 	if (s->io[i].NumPorts == 0) {
-	    if (find_io_region(base, num, name) == 0) {
+	    if (find_io_region(base, num, align, name) == 0) {
 		s->io[i].Attributes = attr;
 		s->io[i].BasePort = *base;
 		s->io[i].NumPorts = s->io[i].InUse = num;
@@ -727,7 +741,7 @@
 	/* Try to extend top of window */
 	try = s->io[i].BasePort + s->io[i].NumPorts;
 	if ((*base == 0) || (*base == try))
-	    if (find_io_region(&try, num, name) == 0) {
+	    if (find_io_region(&try, num, 0, name) == 0) {
 		*base = try;
 		s->io[i].NumPorts += num;
 		s->io[i].InUse += num;
@@ -736,7 +750,7 @@
 	/* Try to extend bottom of window */
 	try = s->io[i].BasePort - num;
 	if ((*base == 0) || (*base == try))
-	    if (find_io_region(&try, num, name) == 0) {
+	    if (find_io_region(&try, num, 0, name) == 0) {
 		s->io[i].BasePort = *base = try;
 		s->io[i].NumPorts += num;
 		s->io[i].InUse += num;
@@ -1699,12 +1713,14 @@
 	return CS_BAD_ATTRIBUTE;
 
     if (alloc_io_space(s, req->Attributes1, &req->BasePort1,
-		       req->NumPorts1, handle->dev_info))
+		       req->NumPorts1, req->IOAddrLines,
+		       handle->dev_info))
 	return CS_IN_USE;
 
     if (req->NumPorts2) {
 	if (alloc_io_space(s, req->Attributes2, &req->BasePort2,
-			   req->NumPorts2, handle->dev_info)) {
+			   req->NumPorts2, req->IOAddrLines,
+			   handle->dev_info)) {
 	    release_io_space(s, req->BasePort1, req->NumPorts1);
 	    return CS_IN_USE;
 	}
@@ -1836,10 +1852,11 @@
     win->size = req->Size;
     align = ((s->cap.features & SS_CAP_MEM_ALIGN) ||
 	     (req->Attributes & WIN_STRICT_ALIGN));
-    if (find_mem_region(&win->base, win->size, (*handle)->dev_info,
+    if (find_mem_region(&win->base, win->size,
 			(align ? req->Size : s->cap.map_size),
 			(req->Attributes & WIN_MAP_BELOW_1MB) ||
-			!(s->cap.features & SS_CAP_PAGE_REGS)))
+			!(s->cap.features & SS_CAP_PAGE_REGS),
+			(*handle)->dev_info))
 	return CS_IN_USE;
     req->Base = win->base;
     (*handle)->state |= CLIENT_WIN_REQ(w);
@@ -2202,6 +2219,9 @@
 EXPORT_SYMBOL(unregister_ss_entry);
 EXPORT_SYMBOL(CardServices);
 EXPORT_SYMBOL(MTDHelperEntry);
+#ifdef CONFIG_PROC_FS
+EXPORT_SYMBOL(proc_pccard);
+#endif
 
 static int __init init_pcmcia_cs(void)
 {
diff -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/cs_internal.h linux/drivers/pcmcia/cs_internal.h
--- v2.3.26/linux/drivers/pcmcia/cs_internal.h	Mon Oct  4 15:49:29 1999
+++ linux/drivers/pcmcia/cs_internal.h	Thu Nov 11 17:03:09 1999
@@ -1,5 +1,5 @@
 /*
- * cs_internal.h 1.43 1999/09/07 15:19:04
+ * cs_internal.h 1.46 1999/11/08 20:46:49
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  *  are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  */
 
@@ -241,9 +241,10 @@
 /* In rsrc_mgr */
 void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
 		  int force_low);
-int find_io_region(ioaddr_t *base, ioaddr_t num, char *name);
-int find_mem_region(u_long *base, u_long num, char *name,
-		    u_long align, int force_low);
+int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align,
+		   char *name);
+int find_mem_region(u_long *base, u_long num, u_long align,
+		    int force_low, char *name);
 int try_irq(u_int Attributes, int irq, int specific);
 void undo_irq(u_int Attributes, int irq);
 int adjust_resource_info(client_handle_t handle, adjust_t *adj);
@@ -252,15 +253,6 @@
 		 int count, int *eof, void *data);
 int proc_read_mem(char *buf, char **start, off_t pos,
 		  int count, int *eof, void *data);
-
-/* in pnp components */
-int proc_read_irq(char *buf, char **start, off_t pos,
-		  int count, int *eof, void *data);
-void pnp_bios_init(void);
-void pnp_proc_init(void);
-void pnp_proc_done(void);
-void pnp_rsrc_init(void);
-void pnp_rsrc_done(void);
 
 #define MAX_SOCK 8
 extern socket_t sockets;
diff -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/ds.c linux/drivers/pcmcia/ds.c
--- v2.3.26/linux/drivers/pcmcia/ds.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/pcmcia/ds.c	Thu Nov 11 16:03:37 1999
@@ -2,7 +2,7 @@
 
     PC Card Driver Services
     
-    ds.c 1.98 1999/09/15 15:32:19
+    ds.c 1.100 1999/11/08 20:47:02
     
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
@@ -15,7 +15,7 @@
     rights and limitations under the License.
 
     The initial developer of the original code is David A. Hinds
-    <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+    <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
@@ -43,6 +43,7 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/ioctl.h>
+#include <linux/proc_fs.h>
 #include <linux/poll.h>
 
 #include <pcmcia/version.h>
@@ -57,7 +58,7 @@
 MODULE_PARM(pc_debug, "i");
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static const char *version =
-"ds.c 1.98 1999/09/15 15:32:19 (David Hinds)";
+"ds.c 1.100 1999/11/08 20:47:02 (David Hinds)";
 #else
 #define DEBUG(n, args...)
 #endif
@@ -66,7 +67,7 @@
 
 typedef struct driver_info_t {
     dev_info_t		dev_info;
-    int			use_count;
+    int			use_count, status;
     dev_link_t		*(*attach)(void);
     void		(*detach)(dev_link_t *);
     struct driver_info_t *next;
@@ -116,6 +117,11 @@
 static int sockets = 0, major_dev = -1;
 static socket_info_t *socket_table = NULL;
 
+extern struct proc_dir_entry *proc_pccard;
+
+/* We use this to distinguish in-kernel from modular drivers */
+static int init_status = 1;
+
 /*====================================================================*/
 
 static void cs_error(client_handle_t handle, int func, int ret)
@@ -149,6 +155,7 @@
 	driver = kmalloc(sizeof(driver_info_t), GFP_KERNEL);
 	strncpy(driver->dev_info, (char *)dev_info, DEV_NAME_LEN);
 	driver->use_count = 0;
+	driver->status = init_status;
 	driver->next = root_driver;
 	root_driver = driver;
     }
@@ -200,6 +207,21 @@
     return 0;
 } /* unregister_pccard_driver */
 
+/*====================================================================*/
+
+#ifdef CONFIG_PROC_FS
+static int proc_read_drivers(char *buf, char **start, off_t pos,
+			     int count, int *eof, void *data)
+{
+    driver_info_t *d;
+    char *p = buf;
+    for (d = root_driver; d; d = d->next)
+	p += sprintf(p, "%-24.24s %d %d\n", d->dev_info,
+		     d->status, d->use_count);
+    return (p - buf);
+}
+#endif
+
 /*======================================================================
 
     These manage a ring buffer of events pending for one user process
@@ -874,7 +896,15 @@
 	       "Driver Services\n");
     else
 	major_dev = i;
-    
+
+#ifdef CONFIG_PROC_FS
+    if (proc_pccard) {
+	struct proc_dir_entry *ent;
+	ent = create_proc_entry("drivers", 0, proc_pccard);
+	ent->read_proc = proc_read_drivers;
+    }
+    init_status = 0;
+#endif
     return 0;
 }
 
@@ -888,6 +918,10 @@
 void __exit cleanup_module(void)
 {
     int i;
+#ifdef CONFIG_PROC_FS
+    if (proc_pccard)
+	remove_proc_entry("drivers", proc_pccard);
+#endif
     if (major_dev != -1)
 	unregister_chrdev(major_dev, "pcmcia");
     for (i = 0; i < sockets; i++)
diff -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/i82365.c linux/drivers/pcmcia/i82365.c
--- v2.3.26/linux/drivers/pcmcia/i82365.c	Fri Oct 22 13:21:50 1999
+++ linux/drivers/pcmcia/i82365.c	Thu Nov 11 16:03:37 1999
@@ -3,7 +3,7 @@
     Device driver for Intel 82365 and compatible PC Card controllers,
     and Yenta-compatible PCI-to-CardBus controllers.
 
-    i82365.c 1.260 1999/10/21 00:56:07
+    i82365.c 1.265 1999/11/10 18:36:21
 
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
@@ -16,7 +16,7 @@
     rights and limitations under the License.
 
     The initial developer of the original code is David A. Hinds
-    <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+    <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
@@ -76,7 +76,7 @@
 MODULE_PARM(pc_debug, "i");
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static const char *version =
-"i82365.c 1.260 1999/10/21 00:56:07 (David Hinds)";
+"i82365.c 1.265 1999/11/10 18:36:21 (David Hinds)";
 #else
 #define DEBUG(n, args...) do { } while (0)
 #endif
@@ -189,7 +189,7 @@
 #ifdef CONFIG_ISA
 #ifdef CONFIG_PCI
 /* PCI card status change interrupts? */
-static int pci_csc = 1;
+static int pci_csc = 0;
 /* PCI IO card functional interrupts? */
 static int pci_int = 0;
 MODULE_PARM(pci_csc, "i");
@@ -903,7 +903,8 @@
 {
     socket_info_t *t = &socket[s];
     o2micro_state_t *p = &socket[s].state.o2micro;
-    if ((t->revision == 0x34) || (t->revision == 0x62)) {
+    if ((t->revision == 0x34) || (t->revision == 0x62) ||
+	(t->type == IS_OZ6812)) {
 	p->mode_a = i365_get(s, O2_MODE_A_2);
 	p->mode_b = i365_get(s, O2_MODE_B_2);
     } else {
@@ -923,7 +924,8 @@
 {
     socket_info_t *t = &socket[s];
     o2micro_state_t *p = &socket[s].state.o2micro;
-    if ((t->revision == 0x34) || (t->revision == 0x62)) {
+    if ((t->revision == 0x34) || (t->revision == 0x62) ||
+	(t->type == IS_OZ6812)) {
 	i365_set(s, O2_MODE_A_2, p->mode_a);
 	i365_set(s, O2_MODE_B_2, p->mode_b);
     } else {
@@ -1007,6 +1009,7 @@
 	flip(p->ccr, TOPIC97_ICR_IRQSEL, pcsc);
 	return 0;
     } else {
+	/* no ISA card status change irq */
 	return !pcsc;
     }
 }
@@ -1541,7 +1544,8 @@
 #ifdef CONFIG_ISA
     /* Poll if only two interrupts available */
     if (!use_pci && !poll_interval) {
-	u_int tmp = (mask & (mask-1));
+	u_int tmp = (mask & 0xff20);
+	tmp = tmp & (tmp-1);
 	if ((tmp & (tmp-1)) == 0)
 	    poll_interval = HZ;
     }
@@ -1627,7 +1631,7 @@
 				 u_short v, u_short d0)
 {
     socket_info_t *s = &socket[sockets];
-    u_short d, ns;
+    u_short d, ns, i;
     u_char a, b, r, max;
     
     /* PCI bus enumeration is broken on some systems */
@@ -1666,7 +1670,6 @@
 	pci_writel(bus, devfn, CB_LEGACY_MODE_BASE, 0);
 	pci_readl(bus, devfn, PCI_BASE_ADDRESS_0, &s->cb_phys);
 	if (s->cb_phys == 0) {
-	    int i;
 	    pci_writew(bus, devfn, PCI_COMMAND, CMD_DFLT);
 	    for (i = 0; i < sizeof(cb_mem_base)/sizeof(u_int); i++) {
 		s->cb_phys = cb_mem_base[i];
@@ -1710,10 +1713,21 @@
     }
     add_pcic(ns, type);
 
-    /* Re-do card type & voltage detection */
-    cb_writel(sockets-ns, CB_SOCKET_FORCE, CB_SF_CVSTEST);
-    __set_current_state(TASK_UNINTERRUPTIBLE);
-    schedule_timeout(HZ/5);
+    /* Re-do card voltage detection, if needed: this checks for
+       card presence with no voltage detect bits set */
+    for (a = sockets-ns; a < sockets; a++)
+	if (!(cb_readl(a, CB_SOCKET_STATE) & 0x3c86))
+	    cb_writel(a, CB_SOCKET_FORCE, CB_SF_CVSTEST);
+    for (i = 0; i < 200; i++) {
+	for (a = sockets-ns; a < sockets; a++)
+	    if (!(cb_readl(a, CB_SOCKET_STATE) & 0x3c86)) break;
+	if (a == sockets) break;
+	__set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(HZ/20);
+    }
+    if (i == 200)
+	printk(KERN_NOTICE "i82365: card voltage interrogation"
+	       " timed out!\n");
 
     /* Set up PCI bus bridge structures if needed */
     for (a = 0; a < ns; a++) {
diff -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/i82365.h linux/drivers/pcmcia/i82365.h
--- v2.3.26/linux/drivers/pcmcia/i82365.h	Tue Sep  7 12:14:06 1999
+++ linux/drivers/pcmcia/i82365.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * i82365.h 1.14 1999/08/28 04:01:47
+ * i82365.h 1.15 1999/10/25 20:03:34
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/o2micro.h linux/drivers/pcmcia/o2micro.h
--- v2.3.26/linux/drivers/pcmcia/o2micro.h	Fri Oct 22 13:21:50 1999
+++ linux/drivers/pcmcia/o2micro.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * o2micro.h 1.12 1999/10/16 01:43:24
+ * o2micro.h 1.13 1999/10/25 20:03:34
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/ricoh.h linux/drivers/pcmcia/ricoh.h
--- v2.3.26/linux/drivers/pcmcia/ricoh.h	Tue Sep  7 12:14:06 1999
+++ linux/drivers/pcmcia/ricoh.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * ricoh.h 1.8 1999/08/28 04:01:47
+ * ricoh.h 1.9 1999/10/25 20:03:34
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/rsrc_mgr.c linux/drivers/pcmcia/rsrc_mgr.c
--- v2.3.26/linux/drivers/pcmcia/rsrc_mgr.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/pcmcia/rsrc_mgr.c	Thu Nov 11 16:03:37 1999
@@ -2,7 +2,7 @@
 
     Resource management routines
 
-    rsrc_mgr.c 1.73 1999/10/19 00:54:04
+    rsrc_mgr.c 1.76 1999/11/08 20:47:02
 
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
@@ -15,7 +15,7 @@
     rights and limitations under the License.
 
     The initial developer of the original code is David A. Hinds
-    <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+    <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
@@ -100,6 +100,14 @@
 
 /*======================================================================
 
+    Linux resource management extensions
+    
+======================================================================*/
+
+#define check_io_region(b,n) (0)
+
+/*======================================================================
+
     These manage the internal databases of available resources.
     
 ======================================================================*/
@@ -180,7 +188,7 @@
     b = kmalloc(256, GFP_KERNEL);
     memset(b, 0, 256);
     for (i = base, most = 0; i < base+num; i += 8) {
-	if (check_region(i, 8))
+	if (check_region(i, 8) || check_io_region(i, 8))
 	    continue;
 	hole = inb(i);
 	for (j = 1; j < 8; j++)
@@ -193,7 +201,7 @@
 
     bad = any = 0;
     for (i = base; i < base+num; i += 8) {
-	if (check_region(i, 8))
+	if (check_region(i, 8) || check_io_region(i, 8))
 	    continue;
 	for (j = 0; j < 8; j++)
 	    if (inb(i+j) != most) break;
@@ -344,67 +352,59 @@
 
     These find ranges of I/O ports or memory addresses that are not
     currently allocated by other devices.
+
+    The 'align' field should reflect the number of bits of address
+    that need to be preserved from the initial value of *base.  It
+    should be a power of two, greater than or equal to 'num'.  A value
+    of 0 means that all bits of *base are significant.  *base should
+    also be strictly less than 'align'.
     
 ======================================================================*/
 
-int find_io_region(ioaddr_t *base, ioaddr_t num, char *name)
+int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align,
+		   char *name)
 {
-    ioaddr_t align;
+    ioaddr_t try;
     resource_map_t *m;
     
-    if (*base != 0) {
-	for (m = io_db.next; m != &io_db; m = m->next) {
-	    if ((*base >= m->base) && (*base+num <= m->base+m->num)) {
-		if (check_region(*base, num)) {
-		    return -1;
-		} else {
-		    request_region(*base, num, name);
-		    return 0;
-		}
-	    }
-	}
-	return -1;
-    }
-    
-    for (align = 1; align < num; align *= 2) ;
     for (m = io_db.next; m != &io_db; m = m->next) {
-	for (*base = (m->base + align - 1) & (~(align-1));
-	     *base+align <= m->base + m->num;
-	     *base += align)
-	    if (check_region(*base, num) == 0) {
-		request_region(*base, num, name);
+	try = (m->base & ~(align-1)) + *base;
+	for (try = (try >= m->base) ? try : try+align;
+	     (try >= m->base) && (try+num <= m->base+m->num);
+	     try += align) {
+	    if ((check_region(try, num) == 0) &&
+		(check_io_region(try, num) == 0)) {
+		*base = try;
+		request_region(try, num, name);
 		return 0;
 	    }
+	    if (!align) break;
+	}
     }
     return -1;
 } /* find_io_region */
 
-int find_mem_region(u_long *base, u_long num, char *name,
-		    u_long align, int force_low)
+int find_mem_region(u_long *base, u_long num, u_long align,
+		    int force_low, char *name)
 {
+    u_long try;
     resource_map_t *m;
 
-    if (*base != 0) {
-	for (m = mem_db.next; m != &mem_db; m = m->next) {
-	    if ((*base >= m->base) && (*base+num <= m->base+m->num))
-		if (check_mem_region(*base, num) == 0) {
-		    request_mem_region(*base, num, name);
-		    return 0;
-		}
-	}
-	return -1;
-    }
-    
     while (1) {
 	for (m = mem_db.next; m != &mem_db; m = m->next) {
 	    /* first pass >1MB, second pass <1MB */
 	    if ((force_low != 0) ^ (m->base < 0x100000)) continue;
-	    for (*base = (m->base + align - 1) & (~(align-1));
-		 *base+num <= m->base+m->num; *base += align)
-		if (check_mem_region(*base, num) == 0) {
-		    request_mem_region(*base, num, name);
+	    try = (m->base & ~(align-1)) + *base;
+	    for (try = (try >= m->base) ? try : try+align;
+		 (try >= m->base) && (try+num <= m->base+m->num);
+		 try += align) {
+		if (check_mem_region(try, num) == 0) {
+		    request_mem_region(try, num, name);
+		    *base = try;
 		    return 0;
 		}
+		if (!align) break;
+	    }
 	}
 	if (force_low) break;
 	force_low++;
diff -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/rsrc_mgr.h linux/drivers/pcmcia/rsrc_mgr.h
--- v2.3.26/linux/drivers/pcmcia/rsrc_mgr.h	Fri Oct 22 13:21:50 1999
+++ linux/drivers/pcmcia/rsrc_mgr.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * rsrc_mgr.h 1.18 1999/08/28 04:01:47
+ * rsrc_mgr.h 1.19 1999/10/25 20:03:34
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/smc34c90.h linux/drivers/pcmcia/smc34c90.h
--- v2.3.26/linux/drivers/pcmcia/smc34c90.h	Tue Sep  7 12:14:06 1999
+++ linux/drivers/pcmcia/smc34c90.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * smc34c90.h 1.6 1999/08/28 04:01:47
+ * smc34c90.h 1.7 1999/10/25 20:03:34
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/tcic.c linux/drivers/pcmcia/tcic.c
--- v2.3.26/linux/drivers/pcmcia/tcic.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/pcmcia/tcic.c	Thu Nov 11 16:03:37 1999
@@ -2,7 +2,7 @@
 
     Device driver for Databook TCIC-2 PCMCIA controller
 
-    tcic.c 1.106 1999/09/15 15:32:19
+    tcic.c 1.107 1999/10/25 20:03:34
 
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
@@ -15,7 +15,7 @@
     rights and limitations under the License.
 
     The initial developer of the original code is David A. Hinds
-    <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+    <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
@@ -60,7 +60,7 @@
 static int pc_debug = PCMCIA_DEBUG;
 MODULE_PARM(pc_debug, "i");
 static const char *version =
-"tcic.c 1.106 1999/09/15 15:32:19 (David Hinds)";
+"tcic.c 1.107 1999/10/25 20:03:34 (David Hinds)";
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 #else
 #define DEBUG(n, args...)
diff -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/tcic.h linux/drivers/pcmcia/tcic.h
--- v2.3.26/linux/drivers/pcmcia/tcic.h	Tue Sep  7 12:14:06 1999
+++ linux/drivers/pcmcia/tcic.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * tcic.h 1.12 1999/08/28 04:01:47
+ * tcic.h 1.13 1999/10/25 20:03:34
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/ti113x.h linux/drivers/pcmcia/ti113x.h
--- v2.3.26/linux/drivers/pcmcia/ti113x.h	Tue Sep  7 12:14:06 1999
+++ linux/drivers/pcmcia/ti113x.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * ti113x.h 1.15 1999/09/03 16:43:35
+ * ti113x.h 1.16 1999/10/25 20:03:34
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/vg468.h linux/drivers/pcmcia/vg468.h
--- v2.3.26/linux/drivers/pcmcia/vg468.h	Tue Sep  7 12:14:06 1999
+++ linux/drivers/pcmcia/vg468.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * vg468.h 1.10 1999/08/28 04:01:47
+ * vg468.h 1.11 1999/10/25 20:03:34
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/drivers/pcmcia/yenta.h linux/drivers/pcmcia/yenta.h
--- v2.3.26/linux/drivers/pcmcia/yenta.h	Tue Sep  7 12:14:06 1999
+++ linux/drivers/pcmcia/yenta.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * yenta.h 1.15 1999/08/28 04:01:47
+ * yenta.h 1.16 1999/10/25 20:03:34
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/drivers/pnp/isapnp_proc.c linux/drivers/pnp/isapnp_proc.c
--- v2.3.26/linux/drivers/pnp/isapnp_proc.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/pnp/isapnp_proc.c	Tue Nov  9 19:39:02 1999
@@ -247,7 +247,7 @@
 static int isapnp_proc_done(void)
 {
 	if (isapnp_proc_entry)
-		proc_unregister(&proc_root, isapnp_proc_entry->low_ino);
+		remove_proc_entry("isapnp",&proc_root);
 	return 0;
 }
 #endif /* MODULE */
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/53c7,8xx.c linux/drivers/scsi/53c7,8xx.c
--- v2.3.26/linux/drivers/scsi/53c7,8xx.c	Fri Sep 10 23:57:30 1999
+++ linux/drivers/scsi/53c7,8xx.c	Thu Nov 11 16:57:30 1999
@@ -263,13 +263,6 @@
 #include <linux/stat.h>
 #include <linux/stddef.h>
 
-#ifndef LINUX_1_2
-struct proc_dir_entry proc_scsi_ncr53c7xx = {
-    PROC_SCSI_NCR53C7xx, 9, "ncr53c7xx",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-#endif
-
 static int check_address (unsigned long addr, int size);
 static void dump_events (struct Scsi_Host *host, int count);
 static Scsi_Cmnd * return_outstanding_commands (struct Scsi_Host *host, 
@@ -1568,9 +1561,7 @@
     unsigned char pci_bus, pci_device_fn;
     static short pci_index=0;	/* Device index to PCI BIOS calls */
 
-#ifndef LINUX_1_2
-    tpnt->proc_dir = &proc_scsi_ncr53c7xx;
-#endif
+    tpnt->proc_name = "ncr53c7xx";
 
     for (current_override = count = 0; current_override < OVERRIDE_LIMIT; 
 	 ++current_override) {
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/AM53C974.c linux/drivers/scsi/AM53C974.c
--- v2.3.26/linux/drivers/scsi/AM53C974.c	Fri Sep 10 23:57:31 1999
+++ linux/drivers/scsi/AM53C974.c	Thu Nov 11 16:57:30 1999
@@ -390,12 +390,6 @@
 {
 	{-1, 0, 0, 0},};	/* LILO overrides */
 
-struct proc_dir_entry proc_scsi_am53c974 =
-{
-	PROC_SCSI_AM53C974, 8, "am53c974",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 #ifdef AM53C974_DEBUG
 static int deb_stop = 1;
 
@@ -664,7 +658,7 @@
 {
 	int count = 0;		/* number of boards detected */
 
-	tpnt->proc_dir = &proc_scsi_am53c974;
+	tpnt->proc_name = "am53c974";
 
 #if defined (CONFIG_PCI)
 	if (pci_present())
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/AM53C974.h linux/drivers/scsi/AM53C974.h
--- v2.3.26/linux/drivers/scsi/AM53C974.h	Wed Jun 16 19:29:26 1999
+++ linux/drivers/scsi/AM53C974.h	Thu Nov 11 16:57:30 1999
@@ -50,10 +50,8 @@
 	unsigned char max_offset[8];	/* max. sync. offset (setup), only valid if corresponding sync_en is nonzero */
 };
 
-extern struct proc_dir_entry proc_scsi_am53c974;
-
 #define AM53C974 {				  \
-    proc_dir:       &proc_scsi_am53c974,          \
+    proc_name:      "am53c974",    	          \
     name:           "AM53C974",        		  \
     detect:         AM53C974_detect,   		  \
     release:        AM53C974_release,		  \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/BusLogic.c linux/drivers/scsi/BusLogic.c
--- v2.3.26/linux/drivers/scsi/BusLogic.c	Fri Sep 10 23:57:31 1999
+++ linux/drivers/scsi/BusLogic.c	Thu Nov 11 16:57:30 1999
@@ -140,16 +140,6 @@
 static char
   *BusLogic_CommandFailureReason;
 
-
-/*
-  BusLogic_ProcDirectoryEntry is the BusLogic /proc/scsi directory entry.
-*/
-
-PROC_DirectoryEntry_T
-  BusLogic_ProcDirectoryEntry =
-    { PROC_SCSI_BUSLOGIC, 8, "BusLogic", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
-
-
 /*
   BusLogic_AnnounceDriver announces the Driver Version and Date, Author's
   Name, Copyright Notice, and Electronic Mail Address.
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/BusLogic.h linux/drivers/scsi/BusLogic.h
--- v2.3.26/linux/drivers/scsi/BusLogic.h	Wed Aug 18 16:44:20 1999
+++ linux/drivers/scsi/BusLogic.h	Thu Nov 11 17:03:45 1999
@@ -52,7 +52,6 @@
   Define prototypes for the BusLogic Driver Interface Functions.
 */
 
-extern PROC_DirectoryEntry_T BusLogic_ProcDirectoryEntry;
 extern const char *BusLogic_DriverInfo(SCSI_Host_T *);
 extern int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *);
 extern int BusLogic_ReleaseHostAdapter(SCSI_Host_T *);
@@ -69,7 +68,7 @@
 */
 
 #define BUSLOGIC							       \
-  { proc_dir:       &BusLogic_ProcDirectoryEntry, /* ProcFS Directory Entry */ \
+  { proc_name:      "BusLogic",			  /* ProcFS Directory Entry */ \
     proc_info:      BusLogic_ProcDirectoryInfo,	  /* ProcFS Info Function   */ \
     name:           "BusLogic",			  /* Driver Name            */ \
     detect:         BusLogic_DetectHostAdapter,	  /* Detect Host Adapter    */ \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v2.3.26/linux/drivers/scsi/Makefile	Sat Oct  9 11:47:50 1999
+++ linux/drivers/scsi/Makefile	Wed Nov 10 08:40:04 1999
@@ -58,7 +58,7 @@
 endif
 
 ifeq ($(CONFIG_BLK_DEV_SD),y)
-L_OBJS += sd.o sd_ioctl.o
+L_OBJS += sd.o
 else
   ifeq ($(CONFIG_BLK_DEV_SD),m)
   M_OBJS += sd_mod.o
@@ -265,14 +265,22 @@
   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
@@ -721,5 +729,5 @@
 sr_mod.o: sr.o sr_ioctl.o sr_vendor.o
 	$(LD) $(LD_RFLAG) -r -o $@ sr.o sr_ioctl.o sr_vendor.o
 
-sd_mod.o: sd.o sd_ioctl.o
-	$(LD) $(LD_RFLAG) -r -o $@ sd.o sd_ioctl.o
+sd_mod.o: sd.o
+	$(LD) $(LD_RFLAG) -r -o $@ sd.o
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/NCR53C9x.c linux/drivers/scsi/NCR53C9x.c
--- v2.3.26/linux/drivers/scsi/NCR53C9x.c	Thu Aug 12 10:28:34 1999
+++ linux/drivers/scsi/NCR53C9x.c	Thu Nov 11 16:57:30 1999
@@ -94,11 +94,6 @@
 /*5*/	do_intr_end
 };
 
-struct proc_dir_entry proc_scsi_esp = {
-	PROC_SCSI_ESP, 3, "esp",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 /* The master ring of all esp hosts we are managing in this driver. */
 struct NCR_ESP *espchain = 0;
 int nesps = 0, esps_in_use = 0, esps_running = 0;
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/NCR53C9x.h linux/drivers/scsi/NCR53C9x.h
--- v2.3.26/linux/drivers/scsi/NCR53C9x.h	Thu Aug 12 10:28:34 1999
+++ linux/drivers/scsi/NCR53C9x.h	Thu Nov 11 16:57:30 1999
@@ -625,8 +625,6 @@
 #define ESP_TICK(ccf, cycle)  ((7682 * (ccf) * (cycle) / 1000))
 
 
-extern struct proc_dir_entry proc_scsi_esp;
-
 /* UGLY, UGLY, UGLY! */
 extern int nesps, esps_in_use, esps_running;
 
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/NCR53c406a.c linux/drivers/scsi/NCR53c406a.c
--- v2.3.26/linux/drivers/scsi/NCR53c406a.c	Fri Sep 10 23:57:31 1999
+++ linux/drivers/scsi/NCR53c406a.c	Thu Nov 11 16:57:30 1999
@@ -212,10 +212,6 @@
 static volatile int internal_done_errcode = 0;
 static char info_msg[256];
 
-struct proc_dir_entry proc_scsi_NCR53c406a = {
-    PROC_SCSI_NCR53C406A, 7, "NCR53c406a",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
 /* ================================================================= */
 
 /* possible BIOS locations */
@@ -571,7 +567,7 @@
 #endif USE_DMA 
     
     tpnt->present = 1;
-    tpnt->proc_dir = &proc_scsi_NCR53c406a;
+    tpnt->proc_name = "NCR53c406a";
     
     shpnt = scsi_register(tpnt, 0);
     shpnt->irq = irq_level;
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/NCR53c406a.h linux/drivers/scsi/NCR53c406a.h
--- v2.3.26/linux/drivers/scsi/NCR53c406a.h	Sun Dec 21 17:04:48 1997
+++ linux/drivers/scsi/NCR53c406a.h	Thu Nov 11 16:57:30 1999
@@ -26,7 +26,7 @@
  * Use SG_NONE if DMA mode is enabled!
  */
 #define NCR53c406a { \
-     proc_dir:          &proc_scsi_NCR53c406a   /* proc_dir */,         \
+     proc_name:         "NCR53c406a"		/* proc_name */,        \
      name:              "NCR53c406a"		/* name */,             \
      detect:            NCR53c406a_detect	/* detect */,           \
      info:              NCR53c406a_info		/* info */,             \
@@ -42,8 +42,6 @@
      unchecked_isa_dma: 1			/* unchecked_isa_dma */, \
      use_clustering:    ENABLE_CLUSTERING                               \
 }
-
-extern struct proc_dir_entry proc_scsi_NCR53c406a;
 
 int NCR53c406a_detect(Scsi_Host_Template *);
 const char* NCR53c406a_info(struct Scsi_Host *);
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/a2091.c linux/drivers/scsi/a2091.c
--- v2.3.26/linux/drivers/scsi/a2091.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/scsi/a2091.c	Thu Nov 11 16:57:30 1999
@@ -21,11 +21,6 @@
 
 #include<linux/stat.h>
 
-struct proc_dir_entry proc_scsi_a2091 = {
-    PROC_SCSI_A2091, 5, "A2091",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 #define DMA(ptr) ((a2091_scsiregs *)((ptr)->base))
 #define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata))
 
@@ -201,7 +196,7 @@
 	return 0;
     called = 1;
 
-    tpnt->proc_dir = &proc_scsi_a2091;
+    tpnt->proc_name = "A2091";
     tpnt->proc_info = &wd33c93_proc_info;
 
     while ((key = zorro_find(ZORRO_PROD_CBM_A590_A2091_1, 0, 0)) ||
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/a2091.h linux/drivers/scsi/a2091.h
--- v2.3.26/linux/drivers/scsi/a2091.h	Sun Dec 27 22:19:11 1998
+++ linux/drivers/scsi/a2091.h	Thu Nov 11 16:57:30 1999
@@ -31,9 +31,7 @@
 
 #ifdef HOSTS_C
 
-extern struct proc_dir_entry proc_scsi_a2091;
-
-#define A2091_SCSI {  proc_dir:		   &proc_scsi_a2091, \
+#define A2091_SCSI {  proc_name:	   "A2901", \
 		      name:                "Commodore A2091/A590 SCSI", \
 		      detect:              a2091_detect,    \
 		      release:             a2091_release,   \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/a3000.c linux/drivers/scsi/a3000.c
--- v2.3.26/linux/drivers/scsi/a3000.c	Fri Sep 10 23:57:31 1999
+++ linux/drivers/scsi/a3000.c	Thu Nov 11 16:57:30 1999
@@ -20,11 +20,6 @@
 
 #include<linux/stat.h>
 
-struct proc_dir_entry proc_scsi_a3000 = {
-    PROC_SCSI_A3000, 5, "A3000",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 #define DMA(ptr) ((a3000_scsiregs *)((ptr)->base))
 #define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata))
 
@@ -176,7 +171,7 @@
     if  (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(A3000_SCSI))
 	return 0;
 
-    tpnt->proc_dir = &proc_scsi_a3000;
+    tpnt->proc_name = "A3000";
     tpnt->proc_info = &wd33c93_proc_info;
 
     a3000_host = scsi_register (tpnt, sizeof(struct WD33C93_hostdata));
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/a3000.h linux/drivers/scsi/a3000.h
--- v2.3.26/linux/drivers/scsi/a3000.h	Sun Dec 27 22:19:11 1998
+++ linux/drivers/scsi/a3000.h	Thu Nov 11 16:57:30 1999
@@ -31,9 +31,7 @@
 
 #ifdef HOSTS_C
 
-extern struct proc_dir_entry proc_scsi_a3000;
-
-#define A3000_SCSI {  proc_dir:		   &proc_scsi_a3000,		\
+#define A3000_SCSI {  proc_name:	   "A3000",			\
 		      proc_info:           NULL,			\
 		      name:                "Amiga 3000 built-in SCSI",	\
 		      detect:              a3000_detect,		\
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c
--- v2.3.26/linux/drivers/scsi/advansys.c	Fri Sep 10 23:57:31 1999
+++ linux/drivers/scsi/advansys.c	Thu Nov 11 16:57:30 1999
@@ -4011,19 +4011,6 @@
  * --- Driver Data
  */
 
-/* Note: All driver global data should be initialized. */
-
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
-struct proc_dir_entry proc_scsi_advansys =
-{
-    PROC_SCSI_ADVANSYS,              /* unsigned short low_ino */
-    8,                               /* unsigned short namelen */
-    "advansys",                      /* const char *name */
-    S_IFDIR | S_IRUGO | S_IXUGO,     /* mode_t mode */
-    2                                /* nlink_t nlink */
-};
-#endif /* version >= v1.3.0 */
-
 /* Number of boards detected in system. */
 STATIC int asc_board_count = 0;
 STATIC struct Scsi_Host    *asc_host[ASC_NUM_BOARD_SUPPORTED] = { 0 };
@@ -4481,9 +4468,7 @@
 
     ASC_DBG(1, "advansys_detect: begin\n");
 
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
-    tpnt->proc_dir = &proc_scsi_advansys;
-#endif /* version >= v1.3.0 */
+    tpnt->proc_name = "advansys";
 
     asc_board_count = 0;
 
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/advansys.h linux/drivers/scsi/advansys.h
--- v2.3.26/linux/drivers/scsi/advansys.h	Wed Aug 18 16:44:17 1999
+++ linux/drivers/scsi/advansys.h	Thu Nov 11 17:03:43 1999
@@ -40,18 +40,9 @@
 int advansys_command(Scsi_Cmnd *);
 int advansys_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
 int advansys_abort(Scsi_Cmnd *);
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
-int advansys_reset(Scsi_Cmnd *);
-#else /* version >= v1.3.89 */
 int advansys_reset(Scsi_Cmnd *, unsigned int);
-#endif /* version >= v1.3.89 */
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
-int advansys_biosparam(Disk *, int, int[]);
-#else /* version >= v1.3.0 */
 int advansys_biosparam(Disk *, kdev_t, int[]);
-extern struct proc_dir_entry proc_scsi_advansys;
 int advansys_proc_info(char *, char **, off_t, int, int, int);
-#endif /* version >= v1.3.0 */
 
 /* init/main.c setup function */
 void advansys_setup(char *, int *);
@@ -59,92 +50,8 @@
 /*
  * AdvanSys Host Driver Scsi_Host_Template (struct SHT) from hosts.h.
  */
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
 #define ADVANSYS { \
-    NULL,                     /* struct SHT *next */ \
-    NULL,                     /* int *usage_count */ \
-    "advansys",               /* char *name */ \
-    advansys_detect,          /* int (*detect)(struct SHT *) */ \
-    advansys_release,         /* int (*release)(struct Scsi_Host *) */ \
-    advansys_info,            /* const char *(*info)(struct Scsi_Host *) */ \
-    advansys_command,         /* int (*command)(Scsi_Cmnd *) */ \
-    advansys_queuecommand, \
-            /* int (*queuecommand)(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ \
-    advansys_abort,           /* int (*abort)(Scsi_Cmnd *) */ \
-    advansys_reset,           /* int (*reset)(Scsi_Cmnd *) */ \
-    NULL,                     /* int (*slave_attach)(int, int) */ \
-    advansys_biosparam,       /* int (* bios_param)(Disk *, int, int []) */ \
-    /* \
-     * The following fields are set per adapter in advansys_detect(). \
-     */ \
-    0,                        /* int can_queue */ \
-    0,                        /* int this_id */ \
-    0,                        /* short unsigned int sg_tablesize */ \
-    0,                        /* short cmd_per_lun */ \
-    0,                        /* unsigned char present */    \
-    /* \
-     * Because the driver may control an ISA adapter 'unchecked_isa_dma' \
-     * must be set. The flag will be cleared in advansys_detect for non-ISA \
-     * adapters. Refer to the comment in scsi_module.c for more information. \
-     */ \
-    1,                        /* unsigned unchecked_isa_dma:1 */ \
-    /* \
-     * All adapters controlled by this driver are capable of large \
-     * scatter-gather lists. According to the mid-level SCSI documentation \
-     * this obviates any performance gain provided by setting \
-     * 'use_clustering'. But empirically while CPU utilization is increased \
-     * by enabling clustering, I/O throughput increases as well. \
-     */ \
-    ENABLE_CLUSTERING,        /* unsigned use_clustering:1 */ \
-}
-#elif LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,75)
-#define ADVANSYS { \
-    NULL,                    /* struct SHT *next */ \
-    NULL, \
-        /* version < v2.1.23 long *usage_count */ \
-        /* version >= v2.1.23 struct module * */ \
-    &proc_scsi_advansys,     /* struct proc_dir_entry *proc_dir */ \
-    advansys_proc_info,    \
-        /* int (*proc_info)(char *, char **, off_t, int, int, int) */ \
-    "advansys",              /* const char *name */ \
-    advansys_detect,         /* int (*detect)(struct SHT *) */ \
-    advansys_release,        /* int (*release)(struct Scsi_Host *) */ \
-    advansys_info,           /* const char *(*info)(struct Scsi_Host *) */ \
-    advansys_command,        /* int (*command)(Scsi_Cmnd *) */ \
-    advansys_queuecommand, \
-        /* int (*queuecommand)(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ \
-    advansys_abort,          /* int (*abort)(Scsi_Cmnd *) */ \
-    advansys_reset, \
-        /* version < v1.3.89 int (*reset)(Scsi_Cmnd *) */ \
-        /* version >= v1.3.89 int (*reset)(Scsi_Cmnd *, unsigned int) */ \
-    NULL,                    /* int (*slave_attach)(int, int) */ \
-    advansys_biosparam,      /* int (* bios_param)(Disk *, kdev_t, int []) */ \
-    /* \
-     * The following fields are set per adapter in advansys_detect(). \
-     */ \
-    0,                        /* int can_queue */ \
-    0,                        /* int this_id */ \
-    0,                        /* short unsigned int sg_tablesize */ \
-    0,                        /* short cmd_per_lun */ \
-    0,                        /* unsigned char present */    \
-    /* \
-     * Because the driver may control an ISA adapter 'unchecked_isa_dma' \
-     * must be set. The flag will be cleared in advansys_detect for non-ISA \
-     * adapters. Refer to the comment in scsi_module.c for more information. \
-     */ \
-    1,                        /* unsigned unchecked_isa_dma:1 */ \
-    /* \
-     * All adapters controlled by this driver are capable of large \
-     * scatter-gather lists. According to the mid-level SCSI documentation \
-     * this obviates any performance gain provided by setting \
-     * 'use_clustering'. But empirically while CPU utilization is increased \
-     * by enabling clustering, I/O throughput increases as well. \
-     */ \
-    ENABLE_CLUSTERING,        /* unsigned use_clustering:1 */ \
-}
-#else /* version >= v2.1.75 */
-#define ADVANSYS { \
-    proc_dir:     &proc_scsi_advansys, \
+    proc_name:    "advansys", \
     proc_info:    advansys_proc_info, \
     name:         "advansys", \
     detect:       advansys_detect, \
@@ -170,5 +77,4 @@
      */ \
     use_clustering: ENABLE_CLUSTERING, \
 }
-#endif /* version >= v2.1.75 */
 #endif /* _ADVANSYS_H */
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c
--- v2.3.26/linux/drivers/scsi/aha152x.c	Fri Oct 15 15:25:14 1999
+++ linux/drivers/scsi/aha152x.c	Thu Nov 11 16:57:30 1999
@@ -352,12 +352,6 @@
 
 #include <scsi/scsicam.h>
 
-struct proc_dir_entry proc_scsi_aha152x =
-{
-	PROC_SCSI_AHA152X, 7, "aha152x",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 /* DEFINES */
 
 /* For PCMCIA cards, always use AUTOCONF */
@@ -716,8 +710,7 @@
 	}
 }
 
-#if 0
-/* called from init/main.c */
+#ifdef PCMCIA
 void aha152x_setup(char *str, int *ints)
 {
 	if (setup_count > 2)
@@ -745,8 +738,9 @@
 	} else
 		setup_count++;
 }
-#endif
+#endif /* PCMCIA */
 
+#ifndef MODULE
 static int __init do_aha152x_setup (char * str)
 {
 	if (setup_count > 2) {
@@ -765,10 +759,9 @@
 	return 1;
 }
 
-#ifndef MODULE
 __setup("aha152x=",do_aha152x_setup);
 #endif
-
+ 
 /*
  * Test, if port_base is valid.
  */
@@ -843,7 +836,7 @@
 	aha152x_config conf;
 #endif
 
-	tpnt->proc_dir = &proc_scsi_aha152x;
+	tpnt->proc_name = "aha152x";
 
 	for (i = 0; i < IRQS; i++)
 		aha152x_host[i] = (struct Scsi_Host *) NULL;
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/aha152x.h linux/drivers/scsi/aha152x.h
--- v2.3.26/linux/drivers/scsi/aha152x.h	Wed Aug 18 16:44:56 1999
+++ linux/drivers/scsi/aha152x.h	Thu Nov 11 17:04:12 1999
@@ -26,10 +26,8 @@
 
 #define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 1.7 $"
 
-extern struct proc_dir_entry proc_scsi_aha152x;
-
 /* Initial value of Scsi_Host entry */
-#define AHA152X { proc_dir:           &proc_scsi_aha152x, \
+#define AHA152X { proc_name:          "a152x",		  \
                   proc_info:          aha152x_proc_info,  \
                   name:               AHA152X_REVID,	  \
                   detect:             aha152x_detect,	  \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c
--- v2.3.26/linux/drivers/scsi/aha1542.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/scsi/aha1542.c	Thu Nov 11 16:57:30 1999
@@ -54,11 +54,6 @@
 
 #include<linux/stat.h>
 
-struct proc_dir_entry proc_scsi_aha1542 = {
-    PROC_SCSI_AHA1542, 7, "aha1542",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 #ifdef DEBUG
 #define DEB(x) x
 #else
@@ -967,7 +962,7 @@
 
     DEB(printk("aha1542_detect: \n"));
 
-    tpnt->proc_dir = &proc_scsi_aha1542;
+    tpnt->proc_name = "aha1542";
 
 #ifdef MODULE
     bases[0]        = aha1542[0];              
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/aha1542.h linux/drivers/scsi/aha1542.h
--- v2.3.26/linux/drivers/scsi/aha1542.h	Sun Dec 27 22:19:14 1998
+++ linux/drivers/scsi/aha1542.h	Thu Nov 11 16:57:30 1999
@@ -149,9 +149,7 @@
 	#define NULL 0
 #endif
 
-extern struct proc_dir_entry proc_scsi_aha1542;
-
-#define AHA1542 {    proc_dir:			&proc_scsi_aha1542,	\
+#define AHA1542 {    proc_name:			"aha1542",		\
 		     name:			"Adaptec 1542", 	\
 		     detect:			aha1542_detect,		\
 		     command:			aha1542_command,	\
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/aha1740.c linux/drivers/scsi/aha1740.c
--- v2.3.26/linux/drivers/scsi/aha1740.c	Wed Sep  9 08:56:58 1998
+++ linux/drivers/scsi/aha1740.c	Thu Nov 11 16:57:30 1999
@@ -44,11 +44,6 @@
 #include "aha1740.h"
 #include<linux/stat.h>
 
-struct proc_dir_entry proc_scsi_aha1740 = {
-    PROC_SCSI_AHA1740, 7, "aha1740",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 /* IF YOU ARE HAVING PROBLEMS WITH THIS DRIVER, AND WANT TO WATCH
    IT WORK, THEN:
 #define DEBUG
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/aha1740.h linux/drivers/scsi/aha1740.h
--- v2.3.26/linux/drivers/scsi/aha1740.h	Sun Dec 27 22:19:14 1998
+++ linux/drivers/scsi/aha1740.h	Thu Nov 11 16:57:30 1999
@@ -170,9 +170,7 @@
 	#define NULL 0
 #endif
 
-extern struct proc_dir_entry proc_scsi_aha1740;
-
-#define AHA1740 {  proc_dir:       &proc_scsi_aha1740,			\
+#define AHA1740 {  proc_name:      "aha1740",				\
 		   proc_info:      aha1740_proc_info,	                \
 		   name:           "Adaptec 174x (EISA)",		\
 		   detect:         aha1740_detect,			\
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
--- v2.3.26/linux/drivers/scsi/aic7xxx.c	Sat Oct  9 11:47:50 1999
+++ linux/drivers/scsi/aic7xxx.c	Thu Nov 11 16:57:30 1999
@@ -263,12 +263,6 @@
  */
 #define VIRT_TO_BUS(a) (unsigned int)virt_to_bus((void *)(a))
 
-struct proc_dir_entry proc_scsi_aic7xxx = {
-    PROC_SCSI_AIC7XXX, 7, "aic7xxx",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2,
-    0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
-};
-
 #define AIC7XXX_C_VERSION  "5.1.20"
 
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
@@ -9076,7 +9070,7 @@
       "aic7xxx: insmod or else it might trash certain memory areas.\n");
 #endif
 
-  template->proc_dir = &proc_scsi_aic7xxx;
+  template->proc_name = "aic7xxx";
   template->sg_tablesize = AIC7XXX_MAX_SG;
 
 
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/aic7xxx.h linux/drivers/scsi/aic7xxx.h
--- v2.3.26/linux/drivers/scsi/aic7xxx.h	Wed Aug 18 16:44:20 1999
+++ linux/drivers/scsi/aic7xxx.h	Thu Nov 11 17:03:44 1999
@@ -43,11 +43,9 @@
  * Scsi_Host_Template (see hosts.h) for AIC-7xxx - some fields
  * to do with card config are filled in after the card is detected.
  */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,65)
 #define AIC7XXX	{						\
 	next: NULL,						\
 	module: NULL,						\
-	proc_dir: NULL,						\
 	proc_info: aic7xxx_proc_info,				\
 	name: NULL,						\
 	detect: aic7xxx_detect,					\
@@ -73,31 +71,6 @@
 	use_clustering: ENABLE_CLUSTERING,			\
 	use_new_eh_code: 0					\
 }
-#else
-#define AIC7XXX	{						\
-	next: NULL,						\
-	usage_count: NULL,					\
-	proc_dir: NULL, 					\
-	proc_info: aic7xxx_proc_info,				\
-	name: NULL,						\
-	detect: aic7xxx_detect,					\
-	release: aic7xxx_release,				\
-	info: aic7xxx_info,					\
-	command: NULL,						\
-	queuecommand: aic7xxx_queue,				\
-	abort: aic7xxx_abort,					\
-	reset: aic7xxx_reset,					\
-	slave_attach: NULL,					\
-	bios_param: AIC7XXX_BIOSPARAM,				\
-	can_queue: 255,		/* max simultaneous cmds      */\
-	this_id: -1,		/* scsi id of host adapter    */\
-	sg_tablesize: 0,	/* max scatter-gather cmds    */\
-	cmd_per_lun: 3,		/* cmds per lun (linked cmds) */\
-	present: 0,		/* number of 7xxx's present   */\
-	unchecked_isa_dma: 0,	/* no memory DMA restrictions */\
-	use_clustering: ENABLE_CLUSTERING			\
-}
-#endif
 
 extern int aic7xxx_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
 extern int aic7xxx_biosparam(Disk *, kdev_t, int[]);
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/amiga7xx.c linux/drivers/scsi/amiga7xx.c
--- v2.3.26/linux/drivers/scsi/amiga7xx.c	Wed Aug 18 10:00:52 1999
+++ linux/drivers/scsi/amiga7xx.c	Thu Nov 11 16:57:30 1999
@@ -31,11 +31,6 @@
 
 #include<linux/stat.h>
 
-struct proc_dir_entry proc_scsi_amiga7xx = {
-    PROC_SCSI_AMIGA7XX, 8, "Amiga7xx",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 extern int ncr53c7xx_init (Scsi_Host_Template *tpnt, int board, int chip, 
 			   u32 base, int io_port, int irq, int dma,
 			   long long options, int clock);
@@ -51,7 +46,7 @@
     if (called || !MACH_IS_AMIGA)
 	return 0;
 
-    tpnt->proc_dir = &proc_scsi_amiga7xx;
+    tpnt->proc_name = "Amiga7xx";
 
 #ifdef CONFIG_BLZ603EPLUS_SCSI
     if ((key = zorro_find(ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS, 0, 0)))
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/amiga7xx.h linux/drivers/scsi/amiga7xx.h
--- v2.3.26/linux/drivers/scsi/amiga7xx.h	Wed Jun 16 19:29:21 1999
+++ linux/drivers/scsi/amiga7xx.h	Thu Nov 11 16:57:30 1999
@@ -25,8 +25,6 @@
 #if defined(HOSTS_C) || defined(MODULE)
 #include <scsi/scsicam.h>
 
-extern struct proc_dir_entry proc_scsi_amiga7xx;
-
 #define AMIGA7XX_SCSI {name:                "Amiga NCR53c710 SCSI", \
 		       detect:              amiga7xx_detect,    \
 		       queuecommand:        NCR53c7xx_queue_command, \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/atari_scsi.c linux/drivers/scsi/atari_scsi.c
--- v2.3.26/linux/drivers/scsi/atari_scsi.c	Wed Aug 18 10:00:52 1999
+++ linux/drivers/scsi/atari_scsi.c	Thu Nov 11 16:57:30 1999
@@ -112,11 +112,6 @@
 
 #include <linux/stat.h>
 
-struct proc_dir_entry proc_scsi_atari = {
-    PROC_SCSI_ATARI, 5, "Atari",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 #define	IS_A_TT()	ATARIHW_PRESENT(TT_SCSI)
 
 #define	SCSI_DMA_WRITE_P(elt,val)				\
@@ -616,7 +611,7 @@
 	    called)
 		return( 0 );
 
-	host->proc_dir = &proc_scsi_atari;
+	host->proc_name = "Atari";
 
 	atari_scsi_reg_read  = IS_A_TT() ? atari_scsi_tt_reg_read :
 					   atari_scsi_falcon_reg_read;
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/atp870u.c linux/drivers/scsi/atp870u.c
--- v2.3.26/linux/drivers/scsi/atp870u.c	Fri Oct 22 13:21:50 1999
+++ linux/drivers/scsi/atp870u.c	Thu Nov 11 16:57:30 1999
@@ -30,12 +30,6 @@
 
 #include<linux/stat.h>
 
-struct proc_dir_entry proc_scsi_atp870u =
-{
-	PROC_SCSI_ATP870U, 7, "atp870u",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 void mydlyu(unsigned int);
 
 /*
@@ -1457,7 +1451,7 @@
 		printk("   NO BIOS32 SUPPORT.\n");
 		return count;
 	}
-	tpnt->proc_dir = &proc_scsi_atp870u;
+	tpnt->proc_name = "atp870u";
 
 	for (h = 0; h < 2; h++) {
 		active_idu[h] = 0;
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/atp870u.h linux/drivers/scsi/atp870u.h
--- v2.3.26/linux/drivers/scsi/atp870u.h	Fri Oct 22 13:21:50 1999
+++ linux/drivers/scsi/atp870u.h	Thu Nov 11 16:57:30 1999
@@ -34,16 +34,12 @@
 #define NULL 0
 #endif
 
-extern struct proc_dir_entry proc_scsi_atp870u;
-
 extern const char *atp870u_info(struct Scsi_Host *);
 
 extern int atp870u_proc_info(char *, char **, off_t, int, int, int);
 
 #define ATP870U {  						\
-	next:				NULL, 			\
-	module:				NULL, 			\
-	proc_dir:			&proc_scsi_atp870u,	\
+	proc_name:			"atp870u",		\
 	proc_info:			atp870u_proc_info,      \
 	name:				NULL,			\
 	detect:                 	atp870u_detect,		\
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/blz1230.h linux/drivers/scsi/blz1230.h
--- v2.3.26/linux/drivers/scsi/blz1230.h	Wed Aug 18 10:00:52 1999
+++ linux/drivers/scsi/blz1230.h	Thu Nov 11 16:57:30 1999
@@ -57,7 +57,7 @@
 extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
 			 int hostno, int inout);
 
-#define SCSI_BLZ1230      { proc_dir:		&proc_scsi_esp, \
+#define SCSI_BLZ1230      { proc_name:		"esp-blz1230", \
 			    proc_info:		esp_proc_info, \
 			    name:		"Blizzard1230 SCSI IV", \
 			    detect:		blz1230_esp_detect, \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/blz2060.h linux/drivers/scsi/blz2060.h
--- v2.3.26/linux/drivers/scsi/blz2060.h	Wed Aug 18 10:00:52 1999
+++ linux/drivers/scsi/blz2060.h	Thu Nov 11 16:57:30 1999
@@ -53,7 +53,7 @@
 extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
 			 int hostno, int inout);
 
-#define SCSI_BLZ2060      { proc_dir:		&proc_scsi_esp, \
+#define SCSI_BLZ2060      { proc_name:		"esp-blz2060", \
 			    proc_info:		esp_proc_info, \
 			    name:		"Blizzard2060 SCSI", \
 			    detect:		blz2060_esp_detect, \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/bvme6000.c linux/drivers/scsi/bvme6000.c
--- v2.3.26/linux/drivers/scsi/bvme6000.c	Sat Aug  1 11:33:50 1998
+++ linux/drivers/scsi/bvme6000.c	Thu Nov 11 16:57:30 1999
@@ -23,11 +23,6 @@
 
 #include<linux/stat.h>
 
-struct proc_dir_entry proc_scsi_bvme6000 = {
-    PROC_SCSI_BVME6000, 8, "BVME6000",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 extern ncr53c7xx_init (Scsi_Host_Template *tpnt, int board, int chip,
 			u32 base, int io_port, int irq, int dma,
 			long long options, int clock);
@@ -43,7 +38,7 @@
     if (!MACH_IS_BVME6000)
 	return 0;
 
-    tpnt->proc_dir = &proc_scsi_bvme6000;
+    tpnt->proc_name = "BVME6000";
 
     options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT;
 
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/bvme6000.h linux/drivers/scsi/bvme6000.h
--- v2.3.26/linux/drivers/scsi/bvme6000.h	Wed Jun 16 19:29:22 1999
+++ linux/drivers/scsi/bvme6000.h	Thu Nov 11 16:57:30 1999
@@ -26,8 +26,6 @@
 #if defined(HOSTS_C) || defined(MODULE)
 #include <scsi/scsicam.h>
 
-extern struct proc_dir_entry proc_scsi_mvme16x;
-
 #define BVME6000_SCSI  {name:                "BVME6000 NCR53c710 SCSI", \
 		       detect:              bvme6000_scsi_detect,    \
 		       queuecommand:        NCR53c7xx_queue_command, \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/cyberstorm.h linux/drivers/scsi/cyberstorm.h
--- v2.3.26/linux/drivers/scsi/cyberstorm.h	Wed Aug 18 10:00:52 1999
+++ linux/drivers/scsi/cyberstorm.h	Thu Nov 11 16:57:30 1999
@@ -56,7 +56,7 @@
 			 int hostno, int inout);
 
 
-#define SCSI_CYBERSTORM   { proc_dir:		&proc_scsi_esp, \
+#define SCSI_CYBERSTORM   { proc_name:		"esp-cyberstorm", \
 			    proc_info:		esp_proc_info, \
 			    name:		"CyberStorm SCSI", \
 			    detect:		cyber_esp_detect, \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/cyberstormII.h linux/drivers/scsi/cyberstormII.h
--- v2.3.26/linux/drivers/scsi/cyberstormII.h	Wed Aug 18 10:00:52 1999
+++ linux/drivers/scsi/cyberstormII.h	Thu Nov 11 16:57:30 1999
@@ -43,7 +43,7 @@
 extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
 			 int hostno, int inout);
 
-#define SCSI_CYBERSTORMII { proc_dir:		&proc_scsi_esp, \
+#define SCSI_CYBERSTORMII { proc_name:		"esp-cyberstormII", \
 			    proc_info:		esp_proc_info, \
 			    name:		"CyberStorm Mk II SCSI", \
 			    detect:		cyberII_esp_detect, \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/dc390.h linux/drivers/scsi/dc390.h
--- v2.3.26/linux/drivers/scsi/dc390.h	Wed Aug 18 16:44:24 1999
+++ linux/drivers/scsi/dc390.h	Thu Nov 11 17:03:48 1999
@@ -34,11 +34,10 @@
 # define DC390_release NULL
 #endif
 
-extern struct proc_dir_entry DC390_proc_scsi_tmscsim;
 extern int DC390_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout);
 
 #define DC390_T    {					\
-   proc_dir:       &DC390_proc_scsi_tmscsim,		\
+   proc_name:      "tmscsim",				\
    proc_info:      DC390_proc_info,			\
    name:           DC390_BANNER " V" DC390_VERSION,	\
    detect:         DC390_detect,			\
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/dec_esp.h linux/drivers/scsi/dec_esp.h
--- v2.3.26/linux/drivers/scsi/dec_esp.h	Fri Oct 15 15:25:14 1999
+++ linux/drivers/scsi/dec_esp.h	Thu Nov 11 16:57:30 1999
@@ -24,7 +24,7 @@
 			 int hostno, int inout);
 
 #define SCSI_DEC_ESP {                                         \
-		proc_dir:       &proc_scsi_esp,			\
+		proc_name:      "esp",				\
 		proc_info:      &esp_proc_info,			\
 		name:           "PMAZ-AA",			\
 		detect:         dec_esp_detect,			\
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/dtc.c linux/drivers/scsi/dtc.c
--- v2.3.26/linux/drivers/scsi/dtc.c	Thu Aug 26 13:05:39 1999
+++ linux/drivers/scsi/dtc.c	Thu Nov 11 16:57:30 1999
@@ -134,13 +134,6 @@
 /*!!!! for dtc, it's a 128 byte buffer at 3900 !!! */
 #define DTC_DATA_BUF		0x3900  /* rw 128 bytes long */
 
-
-struct proc_dir_entry proc_scsi_dtc = {
-   PROC_SCSI_T128, 7, "dtc3x80",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2
-     };
-
-
 static struct override {
    unsigned int address;
    int irq;
@@ -214,7 +207,7 @@
    unsigned int base;
    int sig, count;
 
-   tpnt->proc_dir = &proc_scsi_dtc;
+   tpnt->proc_name = "dtc3x80";
    tpnt->proc_info = &dtc_proc_info;
 
    for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/eata.c linux/drivers/scsi/eata.c
--- v2.3.26/linux/drivers/scsi/eata.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/scsi/eata.c	Thu Nov 11 16:57:30 1999
@@ -424,11 +424,6 @@
 #define SPIN_UNLOCK_RESTORE \
                   spin_unlock_irqrestore(&io_request_lock, spin_flags);
 
-struct proc_dir_entry proc_scsi_eata2x = {
-    PROC_SCSI_EATA2X, 6, "eata2x",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 /* Subversion values */
 #define ISA  0
 #define ESA 1
@@ -1257,7 +1252,7 @@
 int eata2x_detect(Scsi_Host_Template *tpnt) {
    unsigned int j = 0, k;
 
-   tpnt->proc_dir = &proc_scsi_eata2x;
+   tpnt->proc_name = "eata2x";
 
    if(boot_options) option_setup(boot_options);
 
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/eata_dma.c linux/drivers/scsi/eata_dma.c
--- v2.3.26/linux/drivers/scsi/eata_dma.c	Fri Sep 10 23:57:31 1999
+++ linux/drivers/scsi/eata_dma.c	Thu Nov 11 16:57:30 1999
@@ -92,11 +92,6 @@
 #include <linux/stat.h>
 #include <linux/config.h>	/* for CONFIG_PCI */
 
-struct proc_dir_entry proc_scsi_eata_dma = {
-    PROC_SCSI_EATA, 8, "eata_dma",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 static u32 ISAbases[] =
 {0x1F0, 0x170, 0x330, 0x230};
 static unchar EISAbases[] =
@@ -1472,7 +1467,7 @@
     DBG((DBG_PROBE && DBG_DELAY) || DPT_DEBUG,
 	printk("Using lots of delays to let you read the debugging output\n"));
 
-    tpnt->proc_dir = &proc_scsi_eata_dma;
+    tpnt->proc_name = "eata_dma";
 
     status = scsi_init_malloc(512, GFP_ATOMIC | GFP_DMA);
     dma_scratch = scsi_init_malloc(1024, GFP_ATOMIC | GFP_DMA);
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/eata_pio.c linux/drivers/scsi/eata_pio.c
--- v2.3.26/linux/drivers/scsi/eata_pio.c	Fri Sep 10 23:57:31 1999
+++ linux/drivers/scsi/eata_pio.c	Thu Nov 11 16:57:30 1999
@@ -58,11 +58,6 @@
 #include <linux/blk.h>
 #include <linux/spinlock.h>
 
-struct proc_dir_entry proc_scsi_eata_pio = {
-    PROC_SCSI_EATA_PIO, 9, "eata_pio",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 static uint ISAbases[MAXISA] =
 {0x1F0, 0x170, 0x330, 0x230};
 static uint ISAirqs[MAXISA] =
@@ -946,7 +941,7 @@
     DBG((DBG_PROBE && DBG_DELAY) || DPT_DEBUG,
 	printk("Using lots of delays to let you read the debugging output\n"));
     
-    tpnt->proc_dir = &proc_scsi_eata_pio;
+    tpnt->proc_name = "eata_pio";
 
     find_pio_PCI(&gc, tpnt);
 
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/esp.c linux/drivers/scsi/esp.c
--- v2.3.26/linux/drivers/scsi/esp.c	Fri Sep 10 23:57:31 1999
+++ linux/drivers/scsi/esp.c	Thu Nov 11 16:57:30 1999
@@ -173,11 +173,6 @@
 /*5*/	do_intr_end
 };
 
-struct proc_dir_entry proc_scsi_esp = {
-	PROC_SCSI_ESP, 3, "esp",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 /* The master ring of all esp hosts we are managing in this driver. */
 static struct Sparc_ESP *espchain;
 static int esps_running = 0;
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/esp.h linux/drivers/scsi/esp.h
--- v2.3.26/linux/drivers/scsi/esp.h	Wed Aug 18 16:44:24 1999
+++ linux/drivers/scsi/esp.h	Thu Nov 11 17:03:50 1999
@@ -414,10 +414,8 @@
 extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
 			 int hostno, int inout);
 
-extern struct proc_dir_entry proc_scsi_esp;
-
 #define SCSI_SPARC_ESP {                                        \
-		proc_dir:       &proc_scsi_esp,			\
+		proc_name:      "esp",				\
 		proc_info:      &esp_proc_info,			\
 		name:           "Sun ESP 100/100a/200",		\
 		detect:         esp_detect,			\
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/fastlane.h linux/drivers/scsi/fastlane.h
--- v2.3.26/linux/drivers/scsi/fastlane.h	Wed Aug 18 10:00:52 1999
+++ linux/drivers/scsi/fastlane.h	Thu Nov 11 16:57:30 1999
@@ -48,7 +48,7 @@
 extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
 			 int hostno, int inout);
 
-#define SCSI_FASTLANE     { proc_dir:		&proc_scsi_esp, \
+#define SCSI_FASTLANE     { proc_name:		"esp-fastlane", \
 			    proc_info:		esp_proc_info, \
 			    name:		"Fastlane SCSI", \
 			    detect:		fastlane_esp_detect, \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/fcal.c linux/drivers/scsi/fcal.c
--- v2.3.26/linux/drivers/scsi/fcal.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/scsi/fcal.c	Thu Nov 11 16:57:30 1999
@@ -68,11 +68,6 @@
 0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17, 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01, 0x00
 };
 
-struct proc_dir_entry proc_scsi_fcal = {
-	PROC_SCSI_FCAL, 4, "fcal",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 static int fcal_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd);
 
 static void fcal_select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist)
@@ -97,7 +92,7 @@
 	int fcalcount;
 	int i;
 
-	tpnt->proc_dir = &proc_scsi_fcal;
+	tpnt->proc_name = "fcal";
 	fcalcount = 0;
 	for_each_online_fc_channel(fc)
 		if (fc->posmap)
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/fd_mcs.c linux/drivers/scsi/fd_mcs.c
--- v2.3.26/linux/drivers/scsi/fd_mcs.c	Fri Sep 10 23:57:31 1999
+++ linux/drivers/scsi/fd_mcs.c	Thu Nov 11 16:57:30 1999
@@ -98,11 +98,6 @@
 #include "fd_mcs.h"
 
 #define DRIVER_VERSION "v0.2 by ZP Gu<zpg@castle.net>"
-
-struct proc_dir_entry proc_scsi_fd_mcs = {
-  PROC_SCSI_FD_MCS, 6, "fd_mcs",
-  S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
   
 /* START OF USER DEFINABLE OPTIONS */
 
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/fd_mcs.h linux/drivers/scsi/fd_mcs.h
--- v2.3.26/linux/drivers/scsi/fd_mcs.h	Sun Nov  8 13:50:47 1998
+++ linux/drivers/scsi/fd_mcs.h	Thu Nov 11 16:57:30 1999
@@ -32,10 +32,8 @@
 extern int fd_mcs_proc_info( char *, char **, off_t, int, int, int );
 extern const char *fd_mcs_info(struct Scsi_Host *);
 
-extern struct proc_dir_entry proc_scsi_fd_mcs;
-
 #define FD_MCS {\
-                    proc_dir:       &proc_scsi_fd_mcs,          \
+                    proc_name:      "fd_mcs",                   \
                     proc_info:      fd_mcs_proc_info,           \
 		    detect:         fd_mcs_detect,              \
 		    release:        fd_mcs_release,             \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c
--- v2.3.26/linux/drivers/scsi/fdomain.c	Fri Sep 10 23:57:31 1999
+++ linux/drivers/scsi/fdomain.c	Thu Nov 11 16:57:30 1999
@@ -274,9 +274,7 @@
 #define MODULE
 #endif
 
-#ifdef MODULE
 #include <linux/module.h>
-#endif
 
 #ifdef PCMCIA
 #undef MODULE
@@ -299,11 +297,6 @@
 #include <linux/delay.h>
 
 #include <linux/config.h>	/* for CONFIG_PCI */
-
-struct proc_dir_entry proc_scsi_fdomain = {
-    PROC_SCSI_FDOMAIN, 7, "fdomain",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
   
 #define VERSION          "$Revision: 5.50 $"
 
@@ -884,7 +877,7 @@
    unsigned char    buf[buflen];
 #endif
 
-   tpnt->proc_dir = &proc_scsi_fdomain;
+   tpnt->proc_name = "fdomain";
 
 #ifdef MODULE
    if (fdomain[0] || fdomain[1] || fdomain[2]) {
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/fdomain.h linux/drivers/scsi/fdomain.h
--- v2.3.26/linux/drivers/scsi/fdomain.h	Thu Jun  4 15:52:21 1998
+++ linux/drivers/scsi/fdomain.h	Thu Nov 11 16:57:30 1999
@@ -35,8 +35,6 @@
 int        fdomain_16x0_proc_info( char *buffer, char **start, off_t offset,
 				   int length, int hostno, int inout );
 
-extern struct proc_dir_entry proc_scsi_fdomain;
-
 #define FDOMAIN_16X0 { proc_info:      fdomain_16x0_proc_info,           \
 		       detect:         fdomain_16x0_detect,              \
 		       info:           fdomain_16x0_info,                \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/g_NCR5380.c linux/drivers/scsi/g_NCR5380.c
--- v2.3.26/linux/drivers/scsi/g_NCR5380.c	Mon Aug  9 10:25:01 1999
+++ linux/drivers/scsi/g_NCR5380.c	Thu Nov 11 16:57:30 1999
@@ -119,11 +119,6 @@
 #include <linux/init.h>
 #include<linux/ioport.h>
 
-struct proc_dir_entry proc_scsi_g_ncr5380 = {
-    PROC_SCSI_GENERIC_NCR5380, 9, "g_NCR5380",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 #define NCR_NOT_SET 0
 static int ncr_irq=NCR_NOT_SET;
 static int ncr_dma=NCR_NOT_SET;
@@ -285,7 +280,7 @@
     else if (dtc_3181e != NCR_NOT_SET)
         overrides[0].board=BOARD_DTC3181E;
 
-    tpnt->proc_dir = &proc_scsi_g_ncr5380;
+    tpnt->proc_name = "g_NCR5380";
 
     for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
 	if (!(overrides[current_override].NCR5380_map_name))
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/gdth.c linux/drivers/scsi/gdth.c
--- v2.3.26/linux/drivers/scsi/gdth.c	Fri Sep 10 23:57:31 1999
+++ linux/drivers/scsi/gdth.c	Thu Nov 11 16:57:30 1999
@@ -181,24 +181,13 @@
 #include <linux/proc_fs.h>
 #include <linux/time.h>
 #include <linux/timer.h>
-#if LINUX_VERSION_CODE >= 0x020100
 #include <linux/reboot.h>
-#else
-#include <linux/bios32.h>
-#endif
 
 #include <asm/dma.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#if LINUX_VERSION_CODE >= 0x02015F
 #include <linux/spinlock.h>
-#endif
-
-#if LINUX_VERSION_CODE >= 0x010300
 #include <linux/blk.h>
-#else
-#include "../block/blk.h"
-#endif
 #include "scsi.h"
 #include "hosts.h"
 #include "sd.h"
@@ -207,11 +196,7 @@
 
 static void gdth_delay(int milliseconds);
 static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs);
-#if LINUX_VERSION_CODE >= 0x010346
 static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs);
-#else
-static void gdth_interrupt(int irq,struct pt_regs *regs);
-#endif
 static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp);
 static int gdth_async_event(int hanum,int service);
 static void gdth_log_event(gdth_evt_data *dvr, char *buffer);
@@ -254,15 +239,8 @@
 
 static const char *gdth_ctr_name(int hanum);
 
-#if LINUX_VERSION_CODE >= 0x010300
 static void gdth_flush(int hanum);
-#if LINUX_VERSION_CODE >= 0x020100
 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
-#else
-static int halt_called = FALSE;
-void gdth_halt(void);
-#endif
-#endif
 
 #ifdef DEBUG_GDTH
 static unchar   DebugState = DEBUG_GDTH;
@@ -363,64 +341,6 @@
 
 #define BUS_L2P(a,b)    ((b)>(a)->virt_bus ? (b-1):(b))
 
-#if LINUX_VERSION_CODE < 0x010300
-static void *gdth_mmap(ulong paddr, ulong size) 
-{
-    if (paddr >= high_memory)
-        return NULL; 
-    else
-        return (void *)paddr;
-}
-static void gdth_munmap(void *addr) 
-{
-}
-inline ulong32 virt_to_phys(volatile void *addr)
-{
-    return (ulong32)addr;
-}
-inline void *phys_to_virt(ulong32 addr)
-{
-    return (void *)addr;
-}
-#define virt_to_bus             virt_to_phys
-#define bus_to_virt             phys_to_virt
-#define gdth_readb(addr)        (*(volatile unchar *)(addr))
-#define gdth_readw(addr)        (*(volatile ushort *)(addr))
-#define gdth_readl(addr)        (*(volatile ulong32 *)(addr))
-#define gdth_writeb(b,addr)     (*(volatile unchar *)(addr) = (b))
-#define gdth_writew(b,addr)     (*(volatile ushort *)(addr) = (b))
-#define gdth_writel(b,addr)     (*(volatile ulong32 *)(addr) = (b))
-#define memset_io(a,b,c)        memset((void *)(a),(b),(c))
-#define memcpy_fromio(a,b,c)    memcpy((a),(void *)(b),(c))
-#define memcpy_toio(a,b,c)      memcpy((void *)(a),(b),(c))
-
-#define PCI_SLOT(devfn)         ((devfn >> 3) & 0x1f)
-
-#elif LINUX_VERSION_CODE < 0x020100
-static int remapped = FALSE;
-static void *gdth_mmap(ulong paddr, ulong size) 
-{
-    if ( paddr >= high_memory) {
-        remapped = TRUE;
-        return vremap(paddr, size);
-    } else {
-        return (void *)paddr; 
-    }
-}
-static void gdth_munmap(void *addr) 
-{
-    if (remapped)
-        vfree(addr);
-    remapped = FALSE;
-}
-#define gdth_readb(addr)        readb((ulong)(addr))
-#define gdth_readw(addr)        readw((ulong)(addr))
-#define gdth_readl(addr)        (ulong32)readl((ulong)(addr))
-#define gdth_writeb(b,addr)     writeb((b),(ulong)(addr))
-#define gdth_writew(b,addr)     writew((b),(ulong)(addr))
-#define gdth_writel(b,addr)     writel((b),(ulong)(addr))
-
-#else
 static void *gdth_mmap(ulong paddr, ulong size) 
 { 
     return ioremap(paddr, size); 
@@ -435,8 +355,6 @@
 #define gdth_writeb(b,addr)     writeb((b),(ulong)(addr))
 #define gdth_writew(b,addr)     writew((b),(ulong)(addr))
 #define gdth_writel(b,addr)     writel((b),(ulong)(addr))
-#endif
-
 
 static unchar   gdth_drq_tab[4] = {5,6,7,7};            /* DRQ table */
 static unchar   gdth_irq_tab[6] = {0,10,11,12,14,0};    /* IRQ table */
@@ -477,15 +395,8 @@
 };
 
 /* __initfunc, __initdata macros */
-#if LINUX_VERSION_CODE >= 0x020126
 #include <linux/init.h>
-#else
-#define __initfunc(A) A
-#define __initdata
-#define __init
-#endif
 
-#if LINUX_VERSION_CODE >= 0x02015F
 #define GDTH_INIT_LOCK_HA(ha)           spin_lock_init(&(ha)->smp_lock)
 #define GDTH_LOCK_HA(ha,flags)          spin_lock_irqsave(&(ha)->smp_lock,flags)
 #define GDTH_UNLOCK_HA(ha,flags)        spin_unlock_irqrestore(&(ha)->smp_lock,flags)
@@ -494,16 +405,6 @@
 #define GDTH_UNLOCK_SCSI_DONE(flags)    spin_unlock_irqrestore(&io_request_lock,flags)
 #define GDTH_LOCK_SCSI_DOCMD()          spin_lock_irq(&io_request_lock)
 #define GDTH_UNLOCK_SCSI_DOCMD()        spin_unlock_irq(&io_request_lock)
-#else
-#define GDTH_INIT_LOCK_HA(ha)           do {} while (0)
-#define GDTH_LOCK_HA(ha,flags)          do {save_flags(flags); cli();} while (0)
-#define GDTH_UNLOCK_HA(ha,flags)        do {restore_flags(flags);} while (0)
-
-#define GDTH_LOCK_SCSI_DONE(flags)      do {} while (0)
-#define GDTH_UNLOCK_SCSI_DONE(flags)    do {} while (0)
-#define GDTH_LOCK_SCSI_DOCMD()          do {} while (0)
-#define GDTH_UNLOCK_SCSI_DOCMD()        do {} while (0)
-#endif
 
 /* LILO and modprobe/insmod parameters */
 /* IRQ list for GDT3000/3020 EISA controllers */
@@ -529,7 +430,6 @@
 static int rescan = 0;
 
 #ifdef MODULE
-#if LINUX_VERSION_CODE >= 0x02011A
 /* parameters for modprobe/insmod */
 MODULE_PARM(irq, "i");
 MODULE_PARM(disable, "i");
@@ -541,39 +441,23 @@
 MODULE_PARM(rescan, "i");
 MODULE_AUTHOR("Achim Leubner");
 #endif
-#endif
 
 /* /proc support */
-#if LINUX_VERSION_CODE >= 0x010300
 #include <linux/stat.h> 
-struct proc_dir_entry proc_scsi_gdth = {
-    PROC_SCSI_GDTH, 4, "gdth",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
 #include "gdth_proc.h"
 #include "gdth_proc.c"
-#endif
 
-#if LINUX_VERSION_CODE >= 0x020100
 /* notifier block to get a notify on system shutdown/halt/reboot */
 static struct notifier_block gdth_notifier = {
     gdth_halt, NULL, 0
 };
-#endif
-
 
 static void gdth_delay(int milliseconds)
 {
     if (milliseconds == 0) {
         udelay(1);
     } else {
-#if LINUX_VERSION_CODE >= 0x020168
         mdelay(milliseconds);
-#else
-        int i;
-        for (i = 0; i < milliseconds; ++i) 
-            udelay(1000);
-#endif
     }
 }
 
@@ -636,12 +520,7 @@
 {
     ulong32 base0, base1, base2;
     ushort device_id, cnt;
-#if LINUX_VERSION_CODE >= 0x2015C
     struct pci_dev *pdev;
-#else
-    int error;
-    ushort idx;
-#endif
     
     TRACE(("gdth_search_pci()\n"));
 
@@ -1099,13 +978,8 @@
                     continue;
                 }
                 gdth_munmap(ha->brd);
-#if LINUX_VERSION_CODE >= 0x2015C
                 pci_write_config_dword(pcistr->pdev, 
                                        PCI_BASE_ADDRESS_0, i);
-#else
-                pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
-                                           PCI_BASE_ADDRESS_0, i);
-#endif
                 ha->brd = gdth_mmap(i, sizeof(gdt6m_dpram_str)); 
                 if (ha->brd == NULL) {
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
@@ -1436,11 +1310,7 @@
 
     gdth_from_wait = TRUE;
     do {
-#if LINUX_VERSION_CODE >= 0x010346
         gdth_interrupt((int)ha->irq,ha,NULL);
-#else
-        gdth_interrupt((int)ha->irq,NULL);
-#endif
         if (wait_hanum==hanum && wait_index==index) {
             answer_found = TRUE;
             break;
@@ -1821,13 +1691,8 @@
     GDTH_LOCK_HA(ha, flags);
 
     scp->SCp.this_residual = (int)priority;
-#if LINUX_VERSION_CODE >= 0x020000
     b = scp->channel;
-#else
-    b = NUMDATA(nscp->host)->busnum;
-#endif
     t = scp->target;
-#if LINUX_VERSION_CODE >= 0x010300
     if (priority >= DEFAULT_PRI) {
         if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
             (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) {
@@ -1835,7 +1700,6 @@
             scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
         }
     }
-#endif
 
     if (ha->req_first==NULL) {
         ha->req_first = scp;                    /* queue was empty */
@@ -1886,11 +1750,7 @@
     for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) {
         if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr)
             pscp = (Scsi_Cmnd *)pscp->SCp.ptr;
-#if LINUX_VERSION_CODE >= 0x020000
         b = nscp->channel;
-#else
-        b = NUMDATA(nscp->host)->busnum;
-#endif
         t = nscp->target;
         if (nscp->SCp.this_residual >= DEFAULT_PRI) {
             if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
@@ -1911,9 +1771,7 @@
             firsttime = FALSE;
         }
 
-#if LINUX_VERSION_CODE >= 0x010300
         if (nscp->done != gdth_scsi_done) 
-#endif
         {
         if (nscp->SCp.phase == -1) {
             nscp->SCp.phase = SCSIRAWSERVICE;           /* default: raw svc. */ 
@@ -1958,13 +1816,11 @@
             }
         } else
 
-#if LINUX_VERSION_CODE >= 0x010300
         if (nscp->done == gdth_scsi_done) {
             if (!(cmd_index=gdth_special_cmd(hanum,nscp)))
                 this_cmd = FALSE;
             next_cmd = FALSE;
         } else
-#endif
         if (b != ha->virt_bus) {
             if (ha->raw[BUS_L2P(ha,b)].io_cnt[t] >= GDTH_MAX_RAW ||
                 !(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b)))) 
@@ -2591,11 +2447,7 @@
 
 /* SCSI interface functions */
 
-#if LINUX_VERSION_CODE >= 0x010346
 static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
-#else
-static void gdth_interrupt(int irq,struct pt_regs *regs)
-#endif
 {
     register gdth_ha_str *ha;
     gdt6m_dpram_str *dp6m_ptr;
@@ -2913,9 +2765,7 @@
                 scp->sense_buffer[2] = NOT_READY;
                 scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
 
-#if LINUX_VERSION_CODE >= 0x010300
                 if (scp->done != gdth_scsi_done)
-#endif 
                 {
                     dvr.size = sizeof(dvr.eu.sync);
                     dvr.eu.sync.ionode  = hanum;
@@ -3282,11 +3132,7 @@
             printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n",
                    isa_bios,ha->irq,ha->drq);
 
-#if LINUX_VERSION_CODE >= 0x010346 
             if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha))
-#else
-            if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) 
-#endif
             {
                 printk("GDT-ISA: Unable to allocate IRQ\n");
                 scsi_unregister(shp);
@@ -3294,11 +3140,7 @@
             }
             if (request_dma(ha->drq,"gdth")) {
                 printk("GDT-ISA: Unable to allocate DMA channel\n");
-#if LINUX_VERSION_CODE >= 0x010346 
                 free_irq(ha->irq,NULL);
-#else
-                free_irq(ha->irq);
-#endif
                 scsi_unregister(shp);
                 continue;
             }
@@ -3331,11 +3173,7 @@
                 --gdth_ctr_vcount;
                 if (ha->pscratch != NULL)
                     scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
-#if LINUX_VERSION_CODE >= 0x010346 
                 free_irq(ha->irq,NULL);
-#else
-                free_irq(ha->irq);
-#endif
                 scsi_unregister(shp);
                 continue;
             }
@@ -3343,22 +3181,9 @@
                 hdr_channel = ha->bus_cnt;
             ha->virt_bus = hdr_channel;
 
-#if LINUX_VERSION_CODE >= 0x020000
             shp->max_id      = ha->tid_cnt;
             shp->max_lun     = MAXLUN;
             shp->max_channel = ha->bus_cnt;
-#else
-            /* register addit. SCSI channels as virtual controllers */
-            for (b=1; b<ha->bus_cnt+1; ++b) {
-                shp = scsi_register(shtp,sizeof(gdth_num_str));
-                shp->unchecked_isa_dma = 1;
-                shp->irq = ha->irq;
-                shp->dma_channel = ha->drq;
-                gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
-                NUMDATA(shp)->hanum = (ushort)hanum;
-                NUMDATA(shp)->busnum = b;
-            }
-#endif
             GDTH_INIT_LOCK_HA(ha);
             gdth_enable_int(hanum);
         }
@@ -3379,11 +3204,7 @@
             printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n",
                    eisa_slot>>12,ha->irq);
 
-#if LINUX_VERSION_CODE >= 0x010346 
             if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha))
-#else
-            if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) 
-#endif
             {
                 printk("GDT-EISA: Unable to allocate IRQ\n");
                 scsi_unregister(shp);
@@ -3418,11 +3239,7 @@
                 --gdth_ctr_vcount;
                 if (ha->pscratch != NULL)
                     scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
-#if LINUX_VERSION_CODE >= 0x010346 
                 free_irq(ha->irq,NULL);
-#else
-                free_irq(ha->irq);
-#endif
                 scsi_unregister(shp);
                 continue;
             }
@@ -3430,36 +3247,16 @@
                 hdr_channel = ha->bus_cnt;
             ha->virt_bus = hdr_channel;
 
-#if LINUX_VERSION_CODE >= 0x020000
             shp->max_id      = ha->tid_cnt;
             shp->max_lun     = MAXLUN;
             shp->max_channel = ha->bus_cnt;
-#else
-            /* register addit. SCSI channels as virtual controllers */
-            for (b=1; b<ha->bus_cnt+1; ++b) {
-                shp = scsi_register(shtp,sizeof(gdth_num_str));
-                shp->unchecked_isa_dma = 0;
-                shp->irq = ha->irq;
-                shp->dma_channel = 0xff;
-                gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
-                NUMDATA(shp)->hanum = (ushort)hanum;
-                NUMDATA(shp)->busnum = b;
-                TRACE2(("EISA detect Bus %d: shp %x hanum %d\n",
-                        NUMDATA(shp)->busnum,(ulong32)shp,
-                        NUMDATA(shp)->hanum));
-            }
-#endif
             GDTH_INIT_LOCK_HA(ha);
             gdth_enable_int(hanum);
         }
     }
 
     /* scanning for PCI controllers */
-#if LINUX_VERSION_CODE >= 0x2015C
     if (pci_present())
-#else
-    if (pcibios_present())
-#endif
     {
         gdth_pci_str pcistr[MAXHA];
 
@@ -3478,13 +3275,8 @@
             printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n",
                    pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq);
 
-#if LINUX_VERSION_CODE >= 0x010346 
             if (request_irq(ha->irq, gdth_interrupt,
                             SA_INTERRUPT|SA_SHIRQ, "gdth", ha))
-#else
-            if (request_irq(ha->irq, gdth_interrupt,
-                            SA_INTERRUPT|SA_SHIRQ, "gdth")) 
-#endif
             {
                 printk("GDT-PCI: Unable to allocate IRQ\n");
                 scsi_unregister(shp);
@@ -3517,11 +3309,7 @@
                 --gdth_ctr_vcount;
                 if (ha->pscratch != NULL)
                     scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
-#if LINUX_VERSION_CODE >= 0x010346 
                 free_irq(ha->irq,NULL);
-#else
-                free_irq(ha->irq);
-#endif
                 scsi_unregister(shp);
                 continue;
             }
@@ -3529,22 +3317,9 @@
                 hdr_channel = ha->bus_cnt;
             ha->virt_bus = hdr_channel;
 
-#if LINUX_VERSION_CODE >= 0x020000
             shp->max_id      = ha->tid_cnt;
             shp->max_lun     = MAXLUN;
             shp->max_channel = ha->bus_cnt;
-#else
-            /* register addit. SCSI channels as virtual controllers */
-            for (b=1; b<ha->bus_cnt+1; ++b) {
-                shp = scsi_register(shtp,sizeof(gdth_num_str));
-                shp->unchecked_isa_dma = 0;
-                shp->irq = ha->irq;
-                shp->dma_channel = 0xff;
-                gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
-                NUMDATA(shp)->hanum = (ushort)hanum;
-                NUMDATA(shp)->busnum = b;
-            }
-#endif
             GDTH_INIT_LOCK_HA(ha);
             gdth_enable_int(hanum);
         }
@@ -3560,9 +3335,7 @@
         gdth_timer.function = gdth_timeout;
         add_timer(&gdth_timer);
 #endif
-#if LINUX_VERSION_CODE >= 0x020100
         register_reboot_notifier(&gdth_notifier);
-#endif
     }
     gdth_polling = FALSE;
     return gdth_ctr_vcount;
@@ -3578,16 +3351,10 @@
     if (NUMDATA(shp)->busnum == 0) {
         hanum = NUMDATA(shp)->hanum;
         ha    = HADATA(gdth_ctr_tab[hanum]);
-#if LINUX_VERSION_CODE >= 0x010300
         gdth_flush(hanum);
-#endif
 
         if (shp->irq) {
-#if LINUX_VERSION_CODE >= 0x010346
             free_irq(shp->irq,NULL);
-#else
-            free_irq(shp->irq);
-#endif
         }
         if (shp->dma_channel != 0xff) {
             free_dma(shp->dma_channel);
@@ -3601,9 +3368,7 @@
 #ifdef GDTH_STATISTICS
             del_timer(&gdth_timer);
 #endif
-#if LINUX_VERSION_CODE >= 0x020100
             unregister_reboot_notifier(&gdth_notifier);
-#endif
         }
     }
 
@@ -3663,17 +3428,12 @@
     return SCSI_ABORT_SNOOZE;
 }
 
-#if LINUX_VERSION_CODE >= 0x010346
 int gdth_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
-#else
-int gdth_reset(Scsi_Cmnd *scp)
-#endif
 {
     TRACE2(("gdth_reset()\n"));
     return SCSI_RESET_PUNT;
 }
 
-#if LINUX_VERSION_CODE >= 0x02015F
 /* new error handling */
 int gdth_eh_abort(Scsi_Cmnd *scp)
 {
@@ -3723,13 +3483,8 @@
     TRACE2(("gdth_eh_host_reset()\n"));
     return FAILED;
 }
-#endif
 
-#if LINUX_VERSION_CODE >= 0x010300
 int gdth_bios_param(Disk *disk,kdev_t dev,int *ip)
-#else
-int gdth_bios_param(Disk *disk,int dev,int *ip)
-#endif
 {
     unchar t;
     int hanum;
@@ -3793,17 +3548,14 @@
 #endif
 
     priority = DEFAULT_PRI;
-#if LINUX_VERSION_CODE >= 0x010300
     if (scp->done == gdth_scsi_done)
         priority = scp->SCp.this_residual;
-#endif
     gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6);
     gdth_putq( hanum, scp, priority );
     gdth_next( hanum );
     return 0;
 }
 
-#if LINUX_VERSION_CODE >= 0x010300
 /* flush routine */
 static void gdth_flush(int hanum)
 {
@@ -3840,11 +3592,7 @@
 }
 
 /* shutdown routine */
-#if LINUX_VERSION_CODE >= 0x020100
 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
-#else
-void gdth_halt(void)
-#endif
 {
     int             hanum;
 #ifndef __alpha__
@@ -3853,18 +3601,9 @@
     gdth_cmd_str    gdtcmd;
 #endif
 
-#if LINUX_VERSION_CODE >= 0x020100
     TRACE2(("gdth_halt() event %d\n",event));
     if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
         return NOTIFY_DONE;
-#else
-    TRACE2(("gdth_halt()\n"));
-    if (halt_called) {
-        TRACE2(("already called\n"));
-        return;
-    }
-    halt_called = TRUE;
-#endif
     printk("GDT: Flushing all host drives .. ");
     for (hanum = 0; hanum < gdth_ctr_count; ++hanum) {
         gdth_flush(hanum);
@@ -3893,13 +3632,9 @@
 #ifdef GDTH_STATISTICS
     del_timer(&gdth_timer);
 #endif
-#if LINUX_VERSION_CODE >= 0x020100
     unregister_reboot_notifier(&gdth_notifier);
     return NOTIFY_OK;
-#endif
 }
-#endif
-
 
 /* called from init/main.c */
 void __init gdth_setup(char *str,int *ints)
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/gdth.h linux/drivers/scsi/gdth.h
--- v2.3.26/linux/drivers/scsi/gdth.h	Wed Aug 18 16:44:26 1999
+++ linux/drivers/scsi/gdth.h	Thu Nov 11 17:03:50 1999
@@ -814,9 +814,7 @@
 
 /* PCI resources */
 typedef struct {
-#if LINUX_VERSION_CODE >= 0x02015C
     struct pci_dev      *pdev;
-#endif
     ushort              device_id;              /* device ID (0,..,9) */
     unchar              bus;                    /* PCI bus */
     unchar              device_fn;              /* PCI device/function no. */
@@ -888,9 +886,7 @@
     gdth_cpar_str       cpar;                   /* controller cache par. */
     gdth_bfeat_str      bfeat;                  /* controller features */
     gdth_binfo_str      binfo;                  /* controller info */
-#if LINUX_VERSION_CODE >= 0x02015F
     spinlock_t          smp_lock;
-#endif
 } gdth_ha_str;
 
 /* structure for scsi_register(), SCSI bus != 0 */
@@ -971,22 +967,16 @@
 int gdth_command(Scsi_Cmnd *);
 int gdth_queuecommand(Scsi_Cmnd *,void (*done)(Scsi_Cmnd *));
 int gdth_abort(Scsi_Cmnd *);
-#if LINUX_VERSION_CODE >= 0x010346
 int gdth_reset(Scsi_Cmnd *, unsigned int reset_flags);
-#else
-int gdth_reset(Scsi_Cmnd *);
-#endif
 const char *gdth_info(struct Scsi_Host *);
 
-#if LINUX_VERSION_CODE >= 0x02015F
 int gdth_bios_param(Disk *,kdev_t,int *);
-extern struct proc_dir_entry proc_scsi_gdth;
 int gdth_proc_info(char *,char **,off_t,int,int,int);
 int gdth_eh_abort(Scsi_Cmnd *scp);
 int gdth_eh_device_reset(Scsi_Cmnd *scp);
 int gdth_eh_bus_reset(Scsi_Cmnd *scp);
 int gdth_eh_host_reset(Scsi_Cmnd *scp);
-#define GDTH { proc_dir:        &proc_scsi_gdth,                 \
+#define GDTH { proc_name:       "gdth",                          \
                proc_info:       gdth_proc_info,                  \
                name:            "GDT SCSI Disk Array Controller",\
                detect:          gdth_detect,                     \
@@ -1009,51 +999,5 @@
                unchecked_isa_dma: 1,                             \
                use_clustering:  ENABLE_CLUSTERING,               \
                use_new_eh_code: 1       /* use new error code */ }    
-#elif LINUX_VERSION_CODE >= 0x010300
-int gdth_bios_param(Disk *,kdev_t,int *);
-extern struct proc_dir_entry proc_scsi_gdth;
-int gdth_proc_info(char *,char **,off_t,int,int,int);
-#define GDTH { NULL, NULL,                              \
-                   &proc_scsi_gdth,                     \
-                   gdth_proc_info,                      \
-                   "GDT SCSI Disk Array Controller",    \
-                   gdth_detect,                         \
-                   gdth_release,                        \
-                   gdth_info,                           \
-                   gdth_command,                        \
-                   gdth_queuecommand,                   \
-                   gdth_abort,                          \
-                   gdth_reset,                          \
-                   NULL,                                \
-                   gdth_bios_param,                     \
-                   GDTH_MAXCMDS,                        \
-                   -1,                                  \
-                   GDTH_MAXSG,                          \
-                   GDTH_MAXC_P_L,                       \
-                   0,                                   \
-                   1,                                   \
-                   ENABLE_CLUSTERING}
-#else
-int gdth_bios_param(Disk *,int,int *);
-#define GDTH { NULL, NULL,                              \
-                   "GDT SCSI Disk Array Controller",    \
-                   gdth_detect,                         \
-                   gdth_release,                        \
-                   gdth_info,                           \
-                   gdth_command,                        \
-                   gdth_queuecommand,                   \
-                   gdth_abort,                          \
-                   gdth_reset,                          \
-                   NULL,                                \
-                   gdth_bios_param,                     \
-                   GDTH_MAXCMDS,                        \
-                   -1,                                  \
-                   GDTH_MAXSG,                          \
-                   GDTH_MAXC_P_L,                       \
-                   0,                                   \
-                   1,                                   \
-                   ENABLE_CLUSTERING}
-#endif
-
 #endif
 
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/gvp11.c linux/drivers/scsi/gvp11.c
--- v2.3.26/linux/drivers/scsi/gvp11.c	Fri Sep 10 23:57:31 1999
+++ linux/drivers/scsi/gvp11.c	Thu Nov 11 16:57:30 1999
@@ -21,11 +21,6 @@
 
 #include<linux/stat.h>
 
-struct proc_dir_entry proc_scsi_gvp11 = {
-    PROC_SCSI_GVP11, 5, "GVP11",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 #define DMA(ptr) ((gvp11_scsiregs *)((ptr)->base))
 #define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata))
 
@@ -200,7 +195,7 @@
 	return 0;
     called = 1;
 
-    tpnt->proc_dir = &proc_scsi_gvp11;
+    tpnt->proc_name = "GVP11";
     tpnt->proc_info = &wd33c93_proc_info;
 
     while (1) {
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/gvp11.h linux/drivers/scsi/gvp11.h
--- v2.3.26/linux/drivers/scsi/gvp11.h	Sun Dec 27 22:19:11 1998
+++ linux/drivers/scsi/gvp11.h	Thu Nov 11 16:57:30 1999
@@ -32,9 +32,7 @@
 
 #ifdef HOSTS_C
 
-extern struct proc_dir_entry proc_scsi_gvp11;
-
-#define GVP11_SCSI {  proc_dir:		   &proc_scsi_gvp11, \
+#define GVP11_SCSI {  proc_name:	   "GVP11", \
 		      name:                "GVP Series II SCSI", \
 		      detect:              gvp11_detect,    \
 		      release:             gvp11_release,   \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c
--- v2.3.26/linux/drivers/scsi/hosts.c	Sat Oct  9 11:47:50 1999
+++ linux/drivers/scsi/hosts.c	Thu Nov 11 16:57:30 1999
@@ -107,12 +107,12 @@
 #include "atari_scsi.h"
 #endif
 
-#ifdef CONFIG_MAC_SCSI_OLD
+#if defined(CONFIG_MAC_SCSI) || defined(CONFIG_MAC_SCSI_OLD)
 #include "mac_scsi.h"
 #endif
 
-#ifdef CONFIG_MAC_SCSI
-#include "mac_scsinew.h"
+#ifdef CONFIG_SUN3_SCSI
+#include "sun3_scsi.h"
 #endif
 
 #ifdef CONFIG_SCSI_MAC_ESP
@@ -445,6 +445,10 @@
 #endif
 #endif
 
+#ifdef CONFIG_SUN3_SCSI
+	SUN3_NCR5380,
+#endif
+
 #ifdef CONFIG_MVME16x_SCSI
 	MVME16x_SCSI,
 #endif
@@ -699,6 +703,8 @@
     retval->loaded_as_module = scsi_loadable_module_flag;
     retval->host_no = max_scsi_hosts++; /* never reuse host_no (DB) */
     next_scsi_host++;
+    /* FIXME: what with overflows? Old code suffered from the same, BTW */
+    sprintf(retval->proc_name, "%d", retval->host_no);
     retval->host_queue = NULL;
     init_waitqueue_head(&retval->host_wait);
     retval->resetting = 0;
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h
--- v2.3.26/linux/drivers/scsi/hosts.h	Wed Aug 18 16:44:17 1999
+++ linux/drivers/scsi/hosts.h	Thu Nov 11 17:03:43 1999
@@ -277,6 +277,11 @@
      */
     unsigned emulated:1;
 
+    /*
+     * Name of proc directory
+     */
+    char *proc_name;
+
 } Scsi_Host_Template;
 
 /*
@@ -322,6 +327,7 @@
 /* public: */
     unsigned short extra_bytes;
     unsigned short host_no;  /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */
+    char proc_name[4];
     int resetting; /* if set, it means that last_reset is a valid value */
     unsigned long last_reset;
 
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/ibmmca.c linux/drivers/scsi/ibmmca.c
--- v2.3.26/linux/drivers/scsi/ibmmca.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/scsi/ibmmca.c	Thu Nov 11 16:57:30 1999
@@ -275,15 +275,6 @@
   {0x8efe, "IBM SCSI Adapter"}, /* special = 4 */
 };
 
-/*for /proc filesystem */
-struct proc_dir_entry proc_scsi_ibmmca =
-{
-  PROC_SCSI_IBMMCA, 6, "ibmmca",
-  S_IFDIR | S_IRUGO | S_IXUGO, 2,
-  0, 0, 0, NULL, NULL, NULL, NULL,
-  NULL, NULL, NULL
-};
-
 /* Max number of logical devices (can be up from 0 to 14).  15 is the address
 of the adapter itself. */
 #define MAX_LOG_DEV  15
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/ibmmca.h linux/drivers/scsi/ibmmca.h
--- v2.3.26/linux/drivers/scsi/ibmmca.h	Wed Aug 18 16:44:21 1999
+++ linux/drivers/scsi/ibmmca.h	Thu Nov 11 17:03:48 1999
@@ -27,11 +27,7 @@
 extern int ibmmca_biosparam (Disk *, kdev_t, int *);
 
 /*structure for /proc filesystem */
-extern struct proc_dir_entry proc_scsi_ibmmca;
 
-#if LINUX_VERSION_CODE >= ibmmca_header_linux_version(2,1,0)
-/* Stuff for Linux >= 2.1.0: */
-/*initialization for Scsi_host_template type (Linux >= 2.1.0) */
 /*
  * 2/8/98
  * Note to maintainer of IBMMCA.  Do not change this initializer back to
@@ -39,7 +35,7 @@
  * about this, but it will break things in the future.
  */
 #define IBMMCA {						      \
-          proc_dir:       &proc_scsi_ibmmca,    /*proc_dir*/          \
+          proc_name:      "ibmmca",             /*proc_name*/         \
 	  proc_info:	  ibmmca_proc_info,     /*proc info fn*/      \
           name:           "IBM SCSI-Subsystem", /*name*/              \
           detect:         ibmmca_detect,        /*detect fn*/         \
@@ -56,34 +52,5 @@
           unchecked_isa_dma: 0,                 /*32-Bit Busmaster */ \
           use_clustering: ENABLE_CLUSTERING     /*use_clustering*/    \
           }
-
-#else
-/* Stuff for Linux < 2.1.0: */
-
-/*initialization for Scsi_host_template type (Linux < 2.1.0) */
-#define IBMMCA {                                      \
-          NULL,                 /*next*/              \
-          NULL,                 /*usage_count*/       \
-          &proc_scsi_ibmmca,    /*proc_dir*/          \
-          ibmmca_proc_info,     /*proc info fn*/      \
-          "IBM SCSI-Subsystem", /*name*/              \
-          ibmmca_detect,        /*detect fn*/         \
-          ibmmca_release,       /*release fn*/        \
-          NULL,                 /*info fn*/           \
-          ibmmca_command,       /*command fn*/        \
-          ibmmca_queuecommand,  /*queuecommand fn*/   \
-          ibmmca_abort,         /*abort fn*/          \
-          ibmmca_reset,         /*reset fn*/          \
-          NULL,                 /*slave_attach fn*/   \
-          ibmmca_biosparam,     /*bios fn*/           \
-          16,                   /*can_queue*/         \
-          7,                    /*set by detect*/     \
-          16,                   /*sg_tablesize*/      \
-          1,                    /*cmd_per_lun*/       \
-          0,                    /*present*/           \
-          0,                    /*unchecked_isa_dma*/ \
-          ENABLE_CLUSTERING     /*use_clustering*/    \
-        }
-#endif /* kernelversion selection */
 
 #endif /* _IBMMCA_H */
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c
--- v2.3.26/linux/drivers/scsi/ide-scsi.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/scsi/ide-scsi.c	Thu Nov 11 16:57:30 1999
@@ -558,8 +558,6 @@
 	NULL
 };
 
-static struct proc_dir_entry idescsi_proc_dir = {PROC_SCSI_IDESCSI, 8, "ide-scsi", S_IFDIR | S_IRUGO | S_IXUGO, 2};
-
 /*
  *	idescsi_init will register the driver for each scsi.
  */
@@ -603,7 +601,7 @@
 	struct Scsi_Host *host;
 	int id;
 
-	host_template->proc_dir = &idescsi_proc_dir;
+	host_template->proc_name = "ide-scsi";
 	host = scsi_register(host_template, 0);
 	for (id = 0; id < MAX_HWIFS * MAX_DRIVES && idescsi_drives[id]; id++);
 	host->max_id = id;
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/imm.h linux/drivers/scsi/imm.h
--- v2.3.26/linux/drivers/scsi/imm.h	Wed Aug 18 16:45:00 1999
+++ linux/drivers/scsi/imm.h	Thu Nov 11 17:04:13 1999
@@ -146,10 +146,7 @@
 static void imm_interrupt(void *);
 static int imm_out(int, char *, int);
 
-struct proc_dir_entry proc_scsi_imm =
-{PROC_SCSI_PPA, 3, "imm", S_IFDIR | S_IRUGO | S_IXUGO, 2};
 #else
-extern struct proc_dir_entry proc_scsi_imm;
 #define imm_release 0
 #endif
 
@@ -162,7 +159,7 @@
 int imm_proc_info(char *, char **, off_t, int, int, int);
 int imm_biosparam(Disk *, kdev_t, int *);
 
-#define IMM {	proc_dir:			&proc_scsi_imm,		\
+#define IMM {	proc_name:			"imm",			\
 		proc_info:			imm_proc_info,		\
 		name:				"Iomega VPI2 (imm) interface",\
 		detect:				imm_detect,		\
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/in2000.c linux/drivers/scsi/in2000.c
--- v2.3.26/linux/drivers/scsi/in2000.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/scsi/in2000.c	Thu Nov 11 16:57:30 1999
@@ -2023,7 +2023,7 @@
  * initialize it.
  */
 
-      tpnt->proc_dir = &proc_scsi_in2000; /* done more than once? harmless. */
+      tpnt->proc_name = "in2000";
       detect_count++;
       instance  = scsi_register(tpnt, sizeof(struct IN2000_hostdata));
       if (!instance_list)
@@ -2186,13 +2186,6 @@
       }
     return 0;
 }
-
-
-
-struct proc_dir_entry proc_scsi_in2000 = {
-   PROC_SCSI_IN2000, 6, "in2000",
-   S_IFDIR | S_IRUGO | S_IXUGO, 2
-   };
 
 
 int in2000_proc_info(char *buf, char **start, off_t off, int len, int hn, int in)
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/in2000.h linux/drivers/scsi/in2000.h
--- v2.3.26/linux/drivers/scsi/in2000.h	Mon Oct  4 15:49:29 1999
+++ linux/drivers/scsi/in2000.h	Thu Nov 11 17:03:46 1999
@@ -384,13 +384,6 @@
 
 #include <linux/version.h>
 
-#if LINUX_VERSION_CODE < 0x020100   /* 2.0.xx */
-# define in2000__INITFUNC(function) function
-# define in2000__INIT
-# define in2000__INITDATA
-# define CLISPIN_LOCK(flags)   do { save_flags(flags); cli(); } while(0)
-# define CLISPIN_UNLOCK(flags) restore_flags(flags)
-#else                               /* 2.1.xxx */
 # include <linux/init.h>
 # include <linux/spinlock.h>
 # define in2000__INITFUNC(function) __initfunc(function)
@@ -398,15 +391,12 @@
 # define in2000__INITDATA __initdata
 # define CLISPIN_LOCK(flags)   spin_lock_irqsave(&io_request_lock, flags)
 # define CLISPIN_UNLOCK(flags) spin_unlock_irqrestore(&io_request_lock, flags)
-#endif
-
 
 int in2000_detect(Scsi_Host_Template *) in2000__INIT;
 int in2000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int in2000_abort(Scsi_Cmnd *);
 void in2000_setup(char *, int *) in2000__INIT;
 int in2000_proc_info(char *, char **, off_t, int, int, int);
-struct proc_dir_entry proc_scsi_in2000;
 int in2000_biosparam(struct scsi_disk *, kdev_t, int *);
 int in2000_reset(Scsi_Cmnd *, unsigned int);
 
@@ -416,34 +406,7 @@
 #define IN2000_CPL      2
 #define IN2000_HOST_ID  7
 
-#if LINUX_VERSION_CODE < 0x020100   /* 2.0.xx */
-
-#define IN2000 {  NULL,                /* link pointer for modules */ \
-                  NULL,                /* usage_count for modules */ \
-                  &proc_scsi_in2000,   /* pointer to /proc/scsi directory entry */ \
-                  in2000_proc_info,    /* pointer to proc info function */ \
-                  "Always IN2000",     /* device name */ \
-                  in2000_detect,       /* returns number of in2000's found */ \
-                  NULL,                /* optional unload function for modules */ \
-                  NULL,                /* optional misc info function */ \
-                  NULL,                /* send scsi command, wait for completion */ \
-                  in2000_queuecommand, /* queue scsi command, don't wait */ \
-                  in2000_abort,        /* abort current command */ \
-                  in2000_reset,        /* reset scsi bus */ \
-                  NULL,                /* slave_attach - unused */ \
-                  in2000_biosparam,    /* figures out BIOS parameters for lilo, etc */ \
-                  IN2000_CAN_Q,        /* max commands we can queue up */ \
-                  IN2000_HOST_ID,      /* host-adapter scsi id */ \
-                  IN2000_SG,           /* scatter-gather table size */ \
-                  IN2000_CPL,          /* commands per lun */ \
-                  0,                   /* board counter */ \
-                  0,                   /* unchecked dma */ \
-                  DISABLE_CLUSTERING \
-               }
-
-#else       /* 2.1.xxx */
-
-#define IN2000 {  proc_dir:        &proc_scsi_in2000,   /* pointer to /proc/scsi directory entry */ \
+#define IN2000 {  proc_name:       "in2000",		/* name of /proc/scsi directory entry */ \
                   proc_info:       in2000_proc_info,    /* pointer to proc info function */ \
                   name:            "Always IN2000",     /* device name */ \
                   detect:          in2000_detect,       /* returns number of in2000's found */ \
@@ -458,8 +421,5 @@
                   use_clustering:  DISABLE_CLUSTERING,  /* ENABLE_CLUSTERING may speed things up */ \
                   use_new_eh_code: 0                    /* new error code - not using it yet */ \
                 }
-
-#endif
-
 
 #endif /* IN2000_H */
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/ini9100u.c linux/drivers/scsi/ini9100u.c
--- v2.3.26/linux/drivers/scsi/ini9100u.c	Fri Sep 10 23:57:31 1999
+++ linux/drivers/scsi/ini9100u.c	Thu Nov 11 16:57:30 1999
@@ -116,33 +116,17 @@
 #include <linux/module.h>
 #endif
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 #include <stdarg.h>
 #include <asm/irq.h>
 #include <linux/errno.h>
-#if LINUX_VERSION_CODE <= CVT_LINUX_VERSION(2,1,92)
-#include <linux/bios32.h>
-#endif
 #include <linux/delay.h>
 #include <linux/pci.h>
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,23)
 #include <linux/init.h>
-#endif
 #include <linux/blk.h>
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 #include <linux/spinlock.h>
-#endif
 #include <linux/stat.h>
 #include <linux/config.h>
 
-#else
-
-#include <linux/head.h>
-#include <linux/types.h>
-#include <asm/system.h>
-#include "../block/blk.h"
-#endif
-
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
@@ -169,15 +153,6 @@
 char *i91uProductName = "INI-9X00U/UW";
 char *i91uVersion = "v1.03g";
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
-struct proc_dir_entry proc_scsi_ini9100u =
-{
-	PROC_SCSI_INI9100U, 7, "INI9100U",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2,
-	0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
-};
-#endif
-
 #define TULSZ(sz)     (sizeof(sz) / sizeof(sz[0]))
 #define TUL_RDWORD(x,y)         (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
 
@@ -195,7 +170,6 @@
 
 static char *setup_str = (char *) NULL;
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 static void i91u_intr0(int irq, void *dev_id, struct pt_regs *);
 static void i91u_intr1(int irq, void *dev_id, struct pt_regs *);
 static void i91u_intr2(int irq, void *dev_id, struct pt_regs *);
@@ -204,16 +178,6 @@
 static void i91u_intr5(int irq, void *dev_id, struct pt_regs *);
 static void i91u_intr6(int irq, void *dev_id, struct pt_regs *);
 static void i91u_intr7(int irq, void *dev_id, struct pt_regs *);
-#else
-static void i91u_intr0(int irq, struct pt_regs *);
-static void i91u_intr1(int irq, struct pt_regs *);
-static void i91u_intr2(int irq, struct pt_regs *);
-static void i91u_intr3(int irq, struct pt_regs *);
-static void i91u_intr4(int irq, struct pt_regs *);
-static void i91u_intr5(int irq, struct pt_regs *);
-static void i91u_intr6(int irq, struct pt_regs *);
-static void i91u_intr7(int irq, struct pt_regs *);
-#endif
 
 static void i91u_panic(char *msg);
 
@@ -261,12 +225,7 @@
 static void i91uAppendSRBToQueue(HCS * pHCB, Scsi_Cmnd * pSRB)
 {
 	ULONG flags;
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_lock_irqsave(&(pHCB->pSRB_lock), flags);
-#else
-	save_flags(flags);
-	cli();
-#endif
 
 	pSRB->next = NULL;	/* Pointer to next              */
 
@@ -276,11 +235,7 @@
 		pHCB->pSRB_tail->next = pSRB;	/* Pointer to next              */
 	pHCB->pSRB_tail = pSRB;
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags);
-#else
-	restore_flags(flags);
-#endif
 	return;
 }
 
@@ -296,22 +251,13 @@
 	Scsi_Cmnd *pSRB;
 	ULONG flags;
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_lock_irqsave(&(pHCB->pSRB_lock), flags);
-#else
-	save_flags(flags);
-	cli();
-#endif
 
 	if ((pSRB = pHCB->pSRB_head) != NULL) {
 		pHCB->pSRB_head = pHCB->pSRB_head->next;
 		pSRB->next = NULL;
 	}
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags);
-#else
-	restore_flags(flags);
-#endif
 
 	return (pSRB);
 }
@@ -331,7 +277,6 @@
 #endif
 }
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,93)
 int tul_NewReturnNumberOfAdapters(void)
 {
 	struct pci_dev *pDev = NULL;	/* Start from none              */
@@ -363,102 +308,6 @@
 	return (iAdapters);
 }
 
-#else				/* <01> */
-
-/*****************************************************************************
- Function name	: tul_ReturnNumberOfAdapters
- Description	: This function will scan PCI bus to get all Orchid card
- Input		: None.
- Output		: None.
- Return		: SUCCESSFUL	- Successful scan
-		  ohterwise	- No drives founded
-*****************************************************************************/
-int tul_ReturnNumberOfAdapters(void)
-{
-	unsigned int i, iAdapters;
-	unsigned int dRegValue;
-	unsigned short command;
-	WORD wBIOS, wBASE;
-	BYTE bPCIBusNum, bInterrupt, bPCIDeviceNum;
-
-	iAdapters = 0;
-	/*
-	 * PCI-bus probe.
-	 */
-	if (pcibios_present()) {
-#ifdef MMAPIO
-		unsigned long page_offset, base;
-#endif
-
-		int index;
-		unsigned char pci_bus, pci_devfn;
-
-		bPCIBusNum = 0;
-		bPCIDeviceNum = 0;
-		init_i91uAdapter_table();
-		for (i = 0; i < TULSZ(i91u_pci_devices); i++) {
-			index = 0;
-			while (!(pcibios_find_device(i91u_pci_devices[i].vendor_id,
-					   i91u_pci_devices[i].device_id,
-					 index++, &pci_bus, &pci_devfn)))
-			{
-				if (i == 2) {
-					   printk("i91u: The RAID controller is not supported by\n");
-					   printk("i91u:         this driver, we are ignoring it.\n");
-				} else {
-					/*
-					 * Read sundry information from PCI BIOS.
-					 */
-					bPCIBusNum = pci_bus;
-					bPCIDeviceNum = pci_devfn;
-					pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_0,
-							     &dRegValue);
-					if (dRegValue == -1) {	/* Check return code            */
-						printk("\n\ri91u: tulip read configuration error.\n");
-						return (0);	/* Read configuration space error  */
-					}
-					/* <02> read from base address + 0x50 offset to get the wBIOS balue. */
-					wBASE = (WORD) dRegValue;
-
-					/* Now read the interrupt line  */
-					pcibios_read_config_dword(pci_bus, pci_devfn, PCI_INTERRUPT_LINE,
-							     &dRegValue);
-					bInterrupt = dRegValue & 0xFF;	/* Assign interrupt line      */
-					pcibios_read_config_word(pci_bus, pci_devfn, PCI_COMMAND, &command);
-					pcibios_write_config_word(pci_bus, pci_devfn, PCI_COMMAND,
-								  command | PCI_COMMAND_MASTER | PCI_COMMAND_IO);
-					wBASE &= PCI_BASE_ADDRESS_IO_MASK;
-					wBIOS = TUL_RDWORD(wBASE, 0x50);
-
-#ifdef MMAPIO
-					base = wBASE & PAGE_MASK;
-					page_offset = wBASE - base;
-
-					/*
-					 * replace the next line with this one if you are using 2.1.x:
-					 * temp_p->maddr = ioremap(base, page_offset + 256);
-					 */
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,0)
-					wBASE = ioremap(base, page_offset + 256);
-#else
-					wBASE = (WORD) vremap(base, page_offset + 256);
-#endif
-					if (wBASE) {
-						wBASE += page_offset;
-					}
-#endif
-
-					if (Addi91u_into_Adapter_table(wBIOS, wBASE, bInterrupt, bPCIBusNum,
-						   bPCIDeviceNum) == 0x0)
-						iAdapters++;
-				}
-			}	/* while(pdev=....) */
-		}		/* for PCI_DEVICES */
-	}			/* PCI BIOS present */
-	return (iAdapters);
-}
-#endif
-
 int i91u_detect(Scsi_Host_Template * tpnt)
 {
 	SCB *pSCB;
@@ -469,9 +318,7 @@
 	ULONG dBiosAdr;
 	BYTE *pbBiosAdr;
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
-	tpnt->proc_dir = &proc_scsi_ini9100u;
-#endif
+	tpnt->proc_name = "INI9100U";
 
 	if (setup_called) {	/* Setup by i91u_setup          */
 		printk("i91u: processing commandline: ");
@@ -486,15 +333,11 @@
 #endif
 	}
 	/* Get total number of adapters in the motherboard */
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,93)
 #ifdef CONFIG_PCI
 	iAdapters = tul_NewReturnNumberOfAdapters();
 #else
 	iAdapters = tul_ReturnNumberOfAdapters();
 #endif
-#else
-	iAdapters = tul_ReturnNumberOfAdapters();
-#endif
 
 	if (iAdapters == 0)	/* If no tulip founded, return */
 		return (0);
@@ -512,16 +355,11 @@
 	memset((unsigned char *) &tul_hcs[0], 0, i);	/* Initialize tul_hcs 0 */
 	/* Get total memory needed for SCB */
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 	for (; tul_num_scb >= MAX_TARGETS + 3; tul_num_scb--) {
 		i = tul_num_ch * tul_num_scb * sizeof(SCB);
 		if ((tul_scb = (SCB *) kmalloc(i, GFP_ATOMIC | GFP_DMA)) != NULL)
 			break;
 	}
-#else
-	i = tul_num_ch * tul_num_scb * sizeof(SCB);
-	tul_scb = (SCB *) scsi_init_malloc(i, GFP_ATOMIC | GFP_DMA);
-#endif
 	if (tul_scb == NULL) {
 		printk("i91u: SCB memory allocation error\n");
 		return (0);
@@ -530,11 +368,7 @@
 
 	pSCB = tul_scb;
 	for (i = 0; i < tul_num_ch * tul_num_scb; i++, pSCB++) {
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 		pSCB->SCB_SGPAddr = (U32) VIRT_TO_BUS(&pSCB->SCB_SGList[0]);
-#else
-		pSCB->SCB_SGPAddr = (U32) (&pSCB->SCB_SGList[0]);
-#endif
 	}
 
 	for (i = 0, pHCB = &tul_hcs[0];		/* Get pointer for control block */
@@ -542,9 +376,7 @@
 	     i++, pHCB++) {
 		pHCB->pSRB_head = NULL;		/* Initial SRB save queue       */
 		pHCB->pSRB_tail = NULL;		/* Initial SRB save queue       */
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 		pHCB->pSRB_lock = SPIN_LOCK_UNLOCKED;	/* SRB save queue lock */
-#endif
 		request_region(pHCB->HCS_Base, 0x100, "i91u");	/* Register */
 
 		get_tulipPCIConfig(pHCB, i);
@@ -552,9 +384,7 @@
 		dBiosAdr = pHCB->HCS_BIOS;
 		dBiosAdr = (dBiosAdr << 4);
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 		pbBiosAdr = phys_to_virt(dBiosAdr);
-#endif
 
 		init_tulip(pHCB, tul_scb + (i * tul_num_scb), tul_num_scb, pbBiosAdr, 10);
 		pHCB->HCS_Index = i;	/* 7/29/98 */
@@ -562,10 +392,8 @@
 		hreg->io_port = pHCB->HCS_Base;
 		hreg->n_io_port = 0xff;
 		hreg->can_queue = tul_num_scb;	/* 03/05/98                      */
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 		hreg->unique_id = pHCB->HCS_Base;
 		hreg->max_id = pHCB->HCS_MaxTar;
-#endif
 		hreg->max_lun = 32;	/* 10/21/97                     */
 		hreg->irq = pHCB->HCS_Intr;
 		hreg->this_id = pHCB->HCS_SCSI_ID;	/* Assign HCS index           */
@@ -574,7 +402,6 @@
 
 		/* Initial tulip chip           */
 		switch (i) {
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 		case 0:
 			ok = request_irq(pHCB->HCS_Intr, i91u_intr0, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
 			break;
@@ -617,7 +444,6 @@
 			}
 			i91u_panic("i91u: driver needs an IRQ.\n");
 		}
-#endif
 	}
 
 	tpnt->this_id = -1;
@@ -642,11 +468,7 @@
 	pSCB->SCB_Ident = SCpnt->lun | DISC_ALLOW;
 	pSCB->SCB_Flags |= SCF_SENSE;	/* Turn on auto request sense   */
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 	pSCB->SCB_SensePtr = (U32) VIRT_TO_BUS(SCpnt->sense_buffer);
-#else
-	pSCB->SCB_SensePtr = (U32) (SCpnt->sense_buffer);
-#endif
 
 	pSCB->SCB_SenseLen = SENSE_SIZE;
 
@@ -664,11 +486,7 @@
 	if (SCpnt->use_sg) {
 		pSrbSG = (struct scatterlist *) SCpnt->request_buffer;
 		if (SCpnt->use_sg == 1) {	/* If only one entry in the list *//*      treat it as regular I/O */
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 			pSCB->SCB_BufPtr = (U32) VIRT_TO_BUS(pSrbSG->address);
-#else
-			pSCB->SCB_BufPtr = (U32) (pSrbSG->address);
-#endif
 			TotalLen = pSrbSG->length;
 			pSCB->SCB_SGLen = 0;
 		} else {	/* Assign SG physical address   */
@@ -677,11 +495,7 @@
 			for (i = 0, TotalLen = 0, pSG = &pSCB->SCB_SGList[0];	/* 1.01g */
 			     i < SCpnt->use_sg;
 			     i++, pSG++, pSrbSG++) {
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 				pSG->SG_Ptr = (U32) VIRT_TO_BUS(pSrbSG->address);
-#else
-				pSG->SG_Ptr = (U32) (pSrbSG->address);
-#endif
 				TotalLen += pSG->SG_Len = pSrbSG->length;
 			}
 			pSCB->SCB_SGLen = i;
@@ -689,11 +503,7 @@
 		pSCB->SCB_BufLen = (SCpnt->request_bufflen > TotalLen) ?
 		    TotalLen : SCpnt->request_bufflen;
 	} else {		/* Non SG                       */
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 		pSCB->SCB_BufPtr = (U32) VIRT_TO_BUS(SCpnt->request_buffer);
-#else
-		pSCB->SCB_BufPtr = (U32) (SCpnt->request_buffer);
-#endif
 		pSCB->SCB_BufLen = SCpnt->request_bufflen;
 		pSCB->SCB_SGLen = 0;
 	}
@@ -768,11 +578,7 @@
 /*
  * Return the "logical geometry"
  */
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 int i91u_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array)
-#else
-int i91u_biosparam(Scsi_Disk * disk, int dev, int *info_array)
-#endif
 {
 	HCS *pHcb;		/* Point to Host adapter control block */
 	TCS *pTcb;
@@ -887,196 +693,116 @@
 /*
  * Interrupts handler (main routine of the driver)
  */
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 static void i91u_intr0(int irqno, void *dev_id, struct pt_regs *regs)
-#else
-static void i91u_intr0(int irqno, struct pt_regs *regs)
-#endif
 {
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	unsigned long flags;
-#endif
 
 	if (tul_hcs[0].HCS_Intr != irqno)
 		return;
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_lock_irqsave(&io_request_lock, flags);
-#endif
 
 	tul_isr(&tul_hcs[0]);
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_unlock_irqrestore(&io_request_lock, flags);
-#endif
 }
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 static void i91u_intr1(int irqno, void *dev_id, struct pt_regs *regs)
-#else
-static void i91u_intr1(int irqno, struct pt_regs *regs)
-#endif
 {
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	unsigned long flags;
-#endif
 
 	if (tul_hcs[1].HCS_Intr != irqno)
 		return;
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_lock_irqsave(&io_request_lock, flags);
-#endif
 
 	tul_isr(&tul_hcs[1]);
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_unlock_irqrestore(&io_request_lock, flags);
-#endif
 }
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 static void i91u_intr2(int irqno, void *dev_id, struct pt_regs *regs)
-#else
-static void i91u_intr2(int irqno, struct pt_regs *regs)
-#endif
 {
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	unsigned long flags;
-#endif
 
 	if (tul_hcs[2].HCS_Intr != irqno)
 		return;
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_lock_irqsave(&io_request_lock, flags);
-#endif
 
 	tul_isr(&tul_hcs[2]);
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_unlock_irqrestore(&io_request_lock, flags);
-#endif
 }
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 static void i91u_intr3(int irqno, void *dev_id, struct pt_regs *regs)
-#else
-static void i91u_intr3(int irqno, struct pt_regs *regs)
-#endif
 {
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	unsigned long flags;
-#endif
 
 	if (tul_hcs[3].HCS_Intr != irqno)
 		return;
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_lock_irqsave(&io_request_lock, flags);
-#endif
 
 	tul_isr(&tul_hcs[3]);
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_unlock_irqrestore(&io_request_lock, flags);
-#endif
 }
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 static void i91u_intr4(int irqno, void *dev_id, struct pt_regs *regs)
-#else
-static void i91u_intr4(int irqno, struct pt_regs *regs)
-#endif
 {
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	unsigned long flags;
-#endif
 
 	if (tul_hcs[4].HCS_Intr != irqno)
 		return;
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_lock_irqsave(&io_request_lock, flags);
-#endif
 
 	tul_isr(&tul_hcs[4]);
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_unlock_irqrestore(&io_request_lock, flags);
-#endif
 }
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 static void i91u_intr5(int irqno, void *dev_id, struct pt_regs *regs)
-#else
-static void i91u_intr5(int irqno, struct pt_regs *regs)
-#endif
 {
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	unsigned long flags;
-#endif
 
 	if (tul_hcs[5].HCS_Intr != irqno)
 		return;
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_lock_irqsave(&io_request_lock, flags);
-#endif
 
 	tul_isr(&tul_hcs[5]);
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_unlock_irqrestore(&io_request_lock, flags);
-#endif
 }
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 static void i91u_intr6(int irqno, void *dev_id, struct pt_regs *regs)
-#else
-static void i91u_intr6(int irqno, struct pt_regs *regs)
-#endif
 {
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	unsigned long flags;
-#endif
 
 	if (tul_hcs[6].HCS_Intr != irqno)
 		return;
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_lock_irqsave(&io_request_lock, flags);
-#endif
 
 	tul_isr(&tul_hcs[6]);
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_unlock_irqrestore(&io_request_lock, flags);
-#endif
 }
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 static void i91u_intr7(int irqno, void *dev_id, struct pt_regs *regs)
-#else
-static void i91u_intr7(int irqno, struct pt_regs *regs)
-#endif
 {
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	unsigned long flags;
-#endif
 
 	if (tul_hcs[7].HCS_Intr != irqno)
 		return;
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_lock_irqsave(&io_request_lock, flags);
-#endif
 
 	tul_isr(&tul_hcs[7]);
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_unlock_irqrestore(&io_request_lock, flags);
-#endif
 }
 
 /* 
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/ini9100u.h linux/drivers/scsi/ini9100u.h
--- v2.3.26/linux/drivers/scsi/ini9100u.h	Thu Aug 26 13:05:39 1999
+++ linux/drivers/scsi/ini9100u.h	Thu Nov 11 17:04:12 1999
@@ -83,68 +83,16 @@
 extern int i91u_abort(Scsi_Cmnd *);
 extern int i91u_reset(Scsi_Cmnd *, unsigned int);
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1, 3, 0)
 extern int i91u_biosparam(Scsi_Disk *, kdev_t, int *);	/*for linux v2.0 */
 extern struct proc_dir_entry proc_scsi_ini9100u;
-#else
-extern int i91u_biosparam(Disk *, int, int *);	/*for linux v1.13 */
 #endif
 
 #define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.03g"
 
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(1, 3, 0)
-#define INI9100U	{ \
-		NULL, \
-		NULL, \
-		i91u_REVID, \
-		i91u_detect, \
-		NULL, \
-		NULL, \
-		i91u_command, \
-		i91u_queue, \
-		i91u_abort, \
-		i91u_reset, \
-		NULL, \
-		i91u_biosparam, \
-		1, \
-		7, \
-		SG_ALL, \
-		1, \
-		0, \
-		0, \
-		ENABLE_CLUSTERING \
-}
-#else
-
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2, 1, 75)
-#define INI9100U	{ \
-		NULL, \
-		NULL, \
-		&proc_scsi_ini9100u, \
-		NULL, \
-		i91u_REVID, \
-		i91u_detect, \
-		NULL, \
-		NULL, \
-		i91u_command, \
-		i91u_queue, \
-		i91u_abort, \
-		i91u_reset, \
-		NULL, \
-		i91u_biosparam, \
-		1, \
-		7, \
-		SG_ALL, \
-		1, \
-		0, \
-		0, \
-		ENABLE_CLUSTERING \
-}
-#else				/* Version >= 2.1.75 */
 #define INI9100U	{ \
 	next:		NULL,						\
 	module:		NULL,						\
-	proc_dir:	&proc_scsi_ini9100u, \
+	proc_name:	"INI9100U", \
 	proc_info:	NULL,				\
 	name:		i91u_REVID, \
 	detect:		i91u_detect, \
@@ -170,9 +118,6 @@
 	use_clustering:	ENABLE_CLUSTERING, \
  use_new_eh_code: 0 \
 }
-#endif
-#endif
-
 
 #define VIRT_TO_BUS(i)  (unsigned int) virt_to_bus((void *)(i))
 #define ULONG   unsigned long
@@ -330,11 +275,9 @@
 	TCS HCS_Tcs[16];	/* 78 -> 16 Targets */
 	Scsi_Cmnd *pSRB_head;	/* SRB save queue header     */
 	Scsi_Cmnd *pSRB_tail;	/* SRB save queue tail       */
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spinlock_t HCS_AvailLock;
 	spinlock_t HCS_SemaphLock;
 	spinlock_t pSRB_lock;
-#endif
 } HCS;
 
 /* Bit Definition for HCB_Flags */
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/inia100.c linux/drivers/scsi/inia100.c
--- v2.3.26/linux/drivers/scsi/inia100.c	Fri Sep 10 23:57:31 1999
+++ linux/drivers/scsi/inia100.c	Thu Nov 11 16:57:30 1999
@@ -71,56 +71,27 @@
 #include <linux/module.h>
 #endif
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 #include <stdarg.h>
-#include <asm/io.h>
 #include <asm/irq.h>
-#include <linux/string.h>
 #include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
 #include <linux/delay.h>
-#include <linux/sched.h>
-#if LINUX_VERSION_CODE <= CVT_LINUX_VERSION(2,1,92)
-#include <linux/bios32.h>
-#endif
 #include <linux/pci.h>
-#include <linux/proc_fs.h>
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,23)
 #include <linux/init.h>
-#endif
 #include <linux/blk.h>
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 #include <linux/spinlock.h>
-#endif
-#include "sd.h"
-#include "scsi.h"
-#include "hosts.h"
-#include "inia100.h"
 #include <linux/stat.h>
-#include <linux/malloc.h>
 #include <linux/config.h>
-
-
-#else
-
 #include <linux/kernel.h>
-#include <linux/head.h>
-#include <linux/types.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
-
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
-#include <asm/system.h>
 #include <asm/io.h>
-#include "../block/blk.h"
 #include "scsi.h"
 #include "sd.h"
 #include "hosts.h"
 #include <linux/malloc.h>
 #include "inia100.h"
-#endif
 
 #ifdef MODULE
 Scsi_Host_Template driver_template = INIA100;
@@ -134,15 +105,6 @@
 char *inia100_ProductName = "INI-A100U2W";
 char *inia100_Version = "v1.02c";
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
-struct proc_dir_entry proc_scsi_inia100 =
-{
-	PROC_SCSI_INIA100, 7, "INIA100",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2,
-	0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
-};
-#endif
-
 /* set by inia100_setup according to the command line */
 static int setup_called = 0;
 static int orc_num_ch = MAX_SUPPORTED_ADAPTERS;		/* Maximum 4 adapters           */
@@ -151,7 +113,6 @@
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
 static char *setup_str = (char *) NULL;
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 static void inia100_intr0(int irq, void *dev_id, struct pt_regs *);
 static void inia100_intr1(int irq, void *dev_id, struct pt_regs *);
 static void inia100_intr2(int irq, void *dev_id, struct pt_regs *);
@@ -160,16 +121,6 @@
 static void inia100_intr5(int irq, void *dev_id, struct pt_regs *);
 static void inia100_intr6(int irq, void *dev_id, struct pt_regs *);
 static void inia100_intr7(int irq, void *dev_id, struct pt_regs *);
-#else
-static void inia100_intr0(int irq, struct pt_regs *);
-static void inia100_intr1(int irq, struct pt_regs *);
-static void inia100_intr2(int irq, struct pt_regs *);
-static void inia100_intr3(int irq, struct pt_regs *);
-static void inia100_intr4(int irq, struct pt_regs *);
-static void inia100_intr5(int irq, struct pt_regs *);
-static void inia100_intr6(int irq, struct pt_regs *);
-static void inia100_intr7(int irq, struct pt_regs *);
-#endif
 
 static void inia100_panic(char *msg);
 void inia100SCBPost(BYTE * pHcb, BYTE * pScb);
@@ -203,12 +154,7 @@
 {
 	ULONG flags;
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_lock_irqsave(&(pHCB->pSRB_lock), flags);
-#else
-	save_flags(flags);
-	cli();
-#endif
 
 	pSRB->next = NULL;	/* Pointer to next */
 	if (pHCB->pSRB_head == NULL)
@@ -216,11 +162,7 @@
 	else
 		pHCB->pSRB_tail->next = pSRB;	/* Pointer to next */
 	pHCB->pSRB_tail = pSRB;
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags);
-#else
-	restore_flags(flags);
-#endif
 	return;
 }
 
@@ -235,22 +177,12 @@
 {
 	Scsi_Cmnd *pSRB;
 	ULONG flags;
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_lock_irqsave(&(pHCB->pSRB_lock), flags);
-#else
-	save_flags(flags);
-	cli();
-#endif
-
 	if ((pSRB = (Scsi_Cmnd *) pHCB->pSRB_head) != NULL) {
 		pHCB->pSRB_head = pHCB->pSRB_head->next;
 		pSRB->next = NULL;
 	}
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags);
-#else
-	restore_flags(flags);
-#endif
 	return (pSRB);
 }
 
@@ -305,28 +237,16 @@
 		unsigned long page_offset, base;
 #endif
 
-#if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92)
 		struct pci_dev *pdev = NULL;
-#else
-		int index;
-		unsigned char pci_bus, pci_devfn;
-#endif
 
 		bPCIBusNum = 0;
 		bPCIDeviceNum = 0;
 		init_inia100Adapter_table();
 		for (i = 0; i < NUMBER(inia100_pci_devices); i++) {
-#if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92)
 			pdev = NULL;
 			while ((pdev = pci_find_device(inia100_pci_devices[i].vendor_id,
 					inia100_pci_devices[i].device_id,
 						       pdev)))
-#else
-			index = 0;
-			while (!(pcibios_find_device(inia100_pci_devices[i].vendor_id,
-					inia100_pci_devices[i].device_id,
-					 index++, &pci_bus, &pci_devfn)))
-#endif
 			{
 				if (iAdapters >= MAX_SUPPORTED_ADAPTERS)
 					break;	/* Never greater than maximum   */
@@ -340,7 +260,6 @@
 					/*
 					 * Read sundry information from PCI BIOS.
 					 */
-#if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92)
 					bPCIBusNum = pdev->bus->number;
 					bPCIDeviceNum = pdev->devfn;
 					dRegValue = pdev->resource[0].start;
@@ -358,26 +277,6 @@
 					pci_write_config_word(pdev, PCI_COMMAND,
 							      command | PCI_COMMAND_MASTER | PCI_COMMAND_IO);
 
-#else
-					bPCIBusNum = pci_bus;
-					bPCIDeviceNum = pci_devfn;
-					pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_0,
-							     &dRegValue);
-					if (dRegValue == -1) {	/* Check return code            */
-						printk("\n\rinia100: Orchid read configuration error.\n");
-						return (0);	/* Read configuration space error  */
-					}
-					/* <02> read from base address + 0x50 offset to get the wBIOS balue. */
-					wBASE = (WORD) dRegValue;
-
-					/* Now read the interrupt line  */
-					pcibios_read_config_dword(pci_bus, pci_devfn, PCI_INTERRUPT_LINE,
-							     &dRegValue);
-					bInterrupt = dRegValue & 0xFF;	/* Assign interrupt line      */
-					pcibios_read_config_word(pci_bus, pci_devfn, PCI_COMMAND, &command);
-					pcibios_write_config_word(pci_bus, pci_devfn, PCI_COMMAND,
-								  command | PCI_COMMAND_MASTER | PCI_COMMAND_IO);
-#endif
 					wBASE &= PCI_BASE_ADDRESS_IO_MASK;
 					wBIOS = ORC_RDWORD(wBASE, 0x50);
 
@@ -389,11 +288,7 @@
 					 * replace the next line with this one if you are using 2.1.x:
 					 * temp_p->maddr = ioremap(base, page_offset + 256);
 					 */
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,0)
 					wBASE = ioremap(base, page_offset + 256);
-#else
-					wBASE = (WORD) vremap(base, page_offset + 256);
-#endif
 					if (wBASE) {
 						wBASE += page_offset;
 					}
@@ -426,9 +321,7 @@
 	ULONG dBiosAdr;
 	BYTE *pbBiosAdr;
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
-	tpnt->proc_dir = &proc_scsi_inia100;
-#endif
+	tpnt->proc_name = "INIA100";
 	if (setup_called) {
 		/* Setup by inia100_setup          */
 		printk("inia100: processing commandline: ");
@@ -458,9 +351,7 @@
 
 		pHCB->pSRB_head = NULL;		/* Initial SRB save queue       */
 		pHCB->pSRB_tail = NULL;		/* Initial SRB save queue       */
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 		pHCB->pSRB_lock = SPIN_LOCK_UNLOCKED; /* SRB save queue lock */
-#endif
 		/* Get total memory needed for SCB */
 		sz = orc_num_scb * sizeof(ORC_SCB);
 		if ((pHCB->HCS_virScbArray = (PVOID) kmalloc(sz, GFP_ATOMIC | GFP_DMA)) == NULL) {
@@ -485,9 +376,7 @@
 		dBiosAdr = pHCB->HCS_BIOS;
 		dBiosAdr = (dBiosAdr << 4);
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 		pbBiosAdr = phys_to_virt(dBiosAdr);
-#endif
 
 		if (init_orchid(pHCB)) {	/* Initial orchid chip    */
 			printk("inia100: initial orchid fail!!\n");
@@ -501,10 +390,8 @@
 		hreg->n_io_port = 0xff;
 		hreg->can_queue = orc_num_scb;	/* 03/05/98                   */
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 		hreg->unique_id = pHCB->HCS_Base;
 		hreg->max_id = pHCB->HCS_MaxTar;
-#endif
 
 		hreg->max_lun = 32;	/* 10/21/97                     */
 /*
@@ -523,7 +410,6 @@
 
 		/* Initial orc chip           */
 		switch (i) {
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 		case 0:
 			ok = request_irq(pHCB->HCS_Intr, inia100_intr0, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL);
 			break;
@@ -568,7 +454,6 @@
 			}
 			inia100_panic("inia100: driver needs an IRQ.\n");
 		}
-#endif
 	}
 
 	tpnt->this_id = -1;
@@ -610,21 +495,13 @@
 			pSCB->SCB_SGLen = (U32) (SCpnt->use_sg * 8);
 			pSrbSG = (struct scatterlist *) SCpnt->request_buffer;
 			for (i = 0; i < SCpnt->use_sg; i++, pSG++, pSrbSG++) {
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 				pSG->SG_Ptr = (U32) (VIRT_TO_BUS(pSrbSG->address));
-#else
-				pSG->SG_Ptr = (U32) pSrbSG->address;
-#endif
 				pSG->SG_Len = (U32) pSrbSG->length;
 				TotalLen += (U32) pSrbSG->length;
 			}
 		} else {	/* Non SG                       */
 			pSCB->SCB_SGLen = 0x8;
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 			pSG->SG_Ptr = (U32) (VIRT_TO_BUS(SCpnt->request_buffer));
-#else
-			pSG->SG_PTR = (U32) SCpnt->request_buffer;
-#endif
 			pSG->SG_Len = (U32) SCpnt->request_bufflen;
 		}
 	}
@@ -814,11 +691,7 @@
  Output         : None.
  Return         : pSRB  -       Pointer to SCSI request block.
 *****************************************************************************/
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 int inia100_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array)
-#else
-int inia100_biosparam(Scsi_Disk * disk, int dev, int *info_array)
-#endif
 {
 	ORC_HCS *pHcb;		/* Point to Host adapter control block */
 	ORC_TCS *pTcb;
@@ -847,96 +720,58 @@
 
 static void subIntr(ORC_HCS * pHCB, int irqno)
 {
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	unsigned long flags;
 
 	spin_lock_irqsave(&io_request_lock, flags);
-#endif
 
 	if (pHCB->HCS_Intr != irqno) {
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 		spin_unlock_irqrestore(&io_request_lock, flags);
-#endif
 		return;
 	}
 	orc_interrupt(pHCB);
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spin_unlock_irqrestore(&io_request_lock, flags);
-#endif
 }
 
 /*
  * Interrupts handler (main routine of the driver)
  */
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 static void inia100_intr0(int irqno, void *dev_id, struct pt_regs *regs)
-#else
-static void inia100_intr0(int irqno, struct pt_regs *regs)
-#endif
 {
 	subIntr(&orc_hcs[0], irqno);
 }
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 static void inia100_intr1(int irqno, void *dev_id, struct pt_regs *regs)
-#else
-static void inia100_intr1(int irqno, struct pt_regs *regs)
-#endif
 {
 	subIntr(&orc_hcs[1], irqno);
 }
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 static void inia100_intr2(int irqno, void *dev_id, struct pt_regs *regs)
-#else
-static void inia100_intr2(int irqno, struct pt_regs *regs)
-#endif
 {
 	subIntr(&orc_hcs[2], irqno);
 }
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 static void inia100_intr3(int irqno, void *dev_id, struct pt_regs *regs)
-#else
-static void inia100_intr3(int irqno, struct pt_regs *regs)
-#endif
 {
 	subIntr(&orc_hcs[3], irqno);
 }
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 static void inia100_intr4(int irqno, void *dev_id, struct pt_regs *regs)
-#else
-static void inia100_intr4(int irqno, struct pt_regs *regs)
-#endif
 {
 	subIntr(&orc_hcs[4], irqno);
 }
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 static void inia100_intr5(int irqno, void *dev_id, struct pt_regs *regs)
-#else
-static void inia100_intr5(int irqno, struct pt_regs *regs)
-#endif
 {
 	subIntr(&orc_hcs[5], irqno);
 }
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 static void inia100_intr6(int irqno, void *dev_id, struct pt_regs *regs)
-#else
-static void inia100_intr6(int irqno, struct pt_regs *regs)
-#endif
 {
 	subIntr(&orc_hcs[6], irqno);
 }
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
 static void inia100_intr7(int irqno, void *dev_id, struct pt_regs *regs)
-#else
-static void inia100_intr7(int irqno, struct pt_regs *regs)
-#endif
 {
 	subIntr(&orc_hcs[7], irqno);
 }
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/inia100.h linux/drivers/scsi/inia100.h
--- v2.3.26/linux/drivers/scsi/inia100.h	Fri Oct 22 13:21:50 1999
+++ linux/drivers/scsi/inia100.h	Thu Nov 11 17:04:12 1999
@@ -76,69 +76,14 @@
 extern int inia100_abort(Scsi_Cmnd *);
 extern int inia100_reset(Scsi_Cmnd *, unsigned int);
 
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1, 3, 0)
 extern int inia100_biosparam(Scsi_Disk *, kdev_t, int *);	/*for linux v2.0 */
-extern struct proc_dir_entry proc_scsi_inia100;
-#else
-extern int inia100_biosparam(Disk *, int, int *);	/*for linux v1.13 */
-#endif
 
 #define inia100_REVID "Initio INI-A100U2W SCSI device driver; Revision: 1.02c"
 
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(1, 3, 0)
-#define INIA100	{ \
-		NULL, \
-		NULL, \
-		inia100_REVID, \
-		inia100_detect, \
-		NULL, \
-		NULL, \
-		inia100_command, \
-		inia100_queue, \
-		inia100_abort, \
-		inia100_reset, \
-		NULL, \
-		inia100_biosparam, \
-		1, \
-7, \
-SG_ALL, \
-1, \
-0, \
-0, \
-ENABLE_CLUSTERING \
-}
-
-#else
-
-#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2, 1, 75)
-#define INIA100	{ \
-		NULL, \
-		NULL, \
-		&proc_scsi_inia100, \
-		NULL, \
-		inia100_REVID, \
-		inia100_detect, \
-		NULL, \
-		NULL, \
-		inia100_command, \
-		inia100_queue, \
-		inia100_abort, \
-		inia100_reset, \
-		NULL, \
-		inia100_biosparam, \
-		1, \
-		7, \
-		0, \
-		1, \
-		0, \
-		0, \
-		ENABLE_CLUSTERING \
-}
-#else				/* Version >= 2.1.75 */
 #define INIA100	{ \
 	next:		NULL,						\
 	module:		NULL,						\
-	proc_dir:	&proc_scsi_inia100, \
+	proc_name:	"INIA100", \
 	proc_info:	NULL,				\
 	name:		inia100_REVID, \
 	detect:		inia100_detect, \
@@ -164,8 +109,6 @@
 	use_clustering:	ENABLE_CLUSTERING, \
  use_new_eh_code: 0 \
 }
-#endif
-#endif
 
 #define VIRT_TO_BUS(i)  (unsigned int) virt_to_bus((void *)(i))
 #define ULONG   unsigned long
@@ -441,14 +384,10 @@
 	UBYTE ActiveTags[16][16];	/* 50 */
 	ORC_TCS HCS_Tcs[16];	/* 28 */
 	U32 BitAllocFlag[MAX_CHANNELS][8];	/* Max STB is 256, So 256/32 */
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spinlock_t BitAllocFlagLock;
-#endif
 	Scsi_Cmnd *pSRB_head;
 	Scsi_Cmnd *pSRB_tail;
-#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 	spinlock_t pSRB_lock;
-#endif
 } ORC_HCS;
 
 /* Bit Definition for HCS_Flags */
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/ips.c linux/drivers/scsi/ips.c
--- v2.3.26/linux/drivers/scsi/ips.c	Fri Oct 22 13:21:50 1999
+++ linux/drivers/scsi/ips.c	Thu Nov 11 16:57:30 1999
@@ -113,20 +113,6 @@
 #define IPS_VERSION_HIGH        "1.00"  /* MUST be 4 chars */
 #define IPS_VERSION_LOW         ".00 "  /* MUST be 4 chars */
 
-struct proc_dir_entry proc_scsi_ips = {
-#if !defined(PROC_SCSI_IPS)
-   0,                                /* Use dynamic inode allocation */
-#else
-   PROC_SCSI_IPS,
-#endif
-   3, "ips",
-   S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,93)
-   #include <linux/bios32.h>
-#endif
-
 #if !defined(__i386__)
    #error "This driver has only been tested on the x86 platform"
 #endif
@@ -262,7 +248,7 @@
    DBG("ips_detect");
 
    SHT->proc_info = ips_proc_info;
-   SHT->proc_dir = &proc_scsi_ips;
+   SHT->proc_name = "ips";
 
 #if defined(CONFIG_PCI)
 
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/ips.h linux/drivers/scsi/ips.h
--- v2.3.26/linux/drivers/scsi/ips.h	Fri Oct 22 13:21:50 1999
+++ linux/drivers/scsi/ips.h	Thu Nov 11 17:03:45 1999
@@ -271,7 +271,6 @@
  #define IPS {                            \
     next : NULL,                          \
     module : NULL,                        \
-    proc_dir : NULL,                      \
     proc_info : NULL,                     \
     name : NULL,                          \
     detect : ips_detect,                  \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/jazz_esp.h linux/drivers/scsi/jazz_esp.h
--- v2.3.26/linux/drivers/scsi/jazz_esp.h	Fri Aug 13 15:07:07 1999
+++ linux/drivers/scsi/jazz_esp.h	Thu Nov 11 16:57:30 1999
@@ -21,7 +21,7 @@
 			 int hostno, int inout);
 
 #define SCSI_JAZZ_ESP {                                         \
-		proc_dir:       &proc_scsi_esp,			\
+		proc_name:      "esp",				\
 		proc_info:      &esp_proc_info,			\
 		name:           "ESP 100/100a/200",		\
 		detect:         jazz_esp_detect,		\
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/mac53c94.c linux/drivers/scsi/mac53c94.c
--- v2.3.26/linux/drivers/scsi/mac53c94.c	Fri Oct 15 15:25:14 1999
+++ linux/drivers/scsi/mac53c94.c	Thu Nov 11 16:57:30 1999
@@ -26,11 +26,6 @@
 #include "hosts.h"
 #include "mac53c94.h"
 
-struct proc_dir_entry proc_scsi_mac53c94 = {
-	PROC_SCSI_53C94, 5, "53c94",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 enum fsc_phase {
 	idle,
 	selecting,
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/mac53c94.h linux/drivers/scsi/mac53c94.h
--- v2.3.26/linux/drivers/scsi/mac53c94.h	Fri Oct 15 15:25:14 1999
+++ linux/drivers/scsi/mac53c94.h	Thu Nov 11 16:57:30 1999
@@ -7,8 +7,6 @@
 #ifndef _MAC53C94_H
 #define _MAC53C94_H
 
-extern struct proc_dir_entry proc_scsi_mac53c94;
-
 int mac53c94_detect(Scsi_Host_Template *);
 int mac53c94_command(Scsi_Cmnd *);
 int mac53c94_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
@@ -16,7 +14,7 @@
 int mac53c94_reset(Scsi_Cmnd *, unsigned int);
 
 #define SCSI_MAC53C94 {					\
-	proc_dir:	&proc_scsi_mac53c94,		\
+	proc_name:	"53c94",			\
 	name:		"53C94",			\
 	detect:		mac53c94_detect,		\
 	command:	mac53c94_command,		\
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/mac_esp.c linux/drivers/scsi/mac_esp.c
--- v2.3.26/linux/drivers/scsi/mac_esp.c	Wed Aug 18 10:00:52 1999
+++ linux/drivers/scsi/mac_esp.c	Mon Nov  8 11:03:21 1999
@@ -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);
 
@@ -235,6 +238,8 @@
 #endif
 #endif
 }
+
+__setup("mac53c9x=", mac_esp_setup);
 
 /*
  * ESP address 'detection'
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/mac_esp.h linux/drivers/scsi/mac_esp.h
--- v2.3.26/linux/drivers/scsi/mac_esp.h	Fri Aug 13 15:06:58 1999
+++ linux/drivers/scsi/mac_esp.h	Thu Nov 11 16:57:30 1999
@@ -21,7 +21,7 @@
 extern int esp_reset(Scsi_Cmnd *, unsigned int);
 
 
-#define SCSI_MAC_ESP      { proc_dir:		&proc_scsi_esp, \
+#define SCSI_MAC_ESP      { proc_name:		"esp", \
 			    name:		"Mac 53C9x SCSI", \
 			    detect:		mac_esp_detect, \
 			    release:		NULL, \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/mac_scsi.c linux/drivers/scsi/mac_scsi.c
--- v2.3.26/linux/drivers/scsi/mac_scsi.c	Wed Aug 18 10:00:52 1999
+++ linux/drivers/scsi/mac_scsi.c	Thu Nov 11 16:57:30 1999
@@ -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 @@
 #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,35 @@
 #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;
-#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",
+#define	AFTER_RESET_DELAY	(HZ/2)
 #endif
-			instance->hostt->this_id );
-	NCR5380_print_options (instance);
-	printk ("\n");
 
-	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 +214,145 @@
 			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;
-
-	/* 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;
+    int count = 0;
+    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 );
+
+    tpnt->proc_name = "Mac 5380 SCSI";
+
+    /* 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 +376,7 @@
 	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 +384,359 @@
 
 	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 );
+#ifndef RBV_HACK
+	unsigned long flags;
+#endif
 
-	DMA_PRINTK("scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, "
-		   "dir = %d\n", instance->host_no, data, addr, count, dir);
+#ifdef RBV_HACK
+	mac_turnoff_irq( IRQ_MAC_SCSI );
+#else
+	mac_disable_irq( IRQ_MAC_SCSI );
+#endif
 
-	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;
+	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_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 );
-
-	if (count == 0)
-		printk(KERN_NOTICE "SCSI warning: DMA programmed for 0 bytes !\n");
 
-	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;
+    }
+
+    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 inline int NCR5380_pread(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 *)((int)mac_scsi_nodrq);
+#endif
 
-#define	CMD_SURELY_BLOCK_MODE	0
-#define	CMD_SURELY_BYTE_MODE	1
-#define	CMD_MODE_UNKNOWN		2
+  if(!len) return 0;
 
-static int mac_classify_cmd( Scsi_Cmnd *cmd )
-{
-	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 );
+  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;
+  int iobase = instance->io_port;
+  int i;
+  int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
 
-#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.
-	 */
+  CTRL(iobase, 0);
+#if 0
+  i = inb(iobase + 64 + reg);
+#else
+  i = inb(iobase + reg<<4);
+#endif
+  CTRL(iobase, 0x40);
 
-	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;
-			}
-		}
-	}
+  return i;
+}
 
-	/* 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;
-
-	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
-     */
-
-#if 0	/* done in transfer_dma */
-    p = PHASE_DATAIN;
-    NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
-#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;
-	}
-
-	/* 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--;
-    }
+	unsigned long flags;
+	NCR5380_local_declare();
 
-#if (NDEBUG & NDEBUG_PSEUDO_DMA)
-    printk("pdma_read: read at %d bytes to %p\n", i, dst);
+	if (default_instance) {
+#if 0
+		NCR5380_setup(default_instance);
+		if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ)
 #endif
-
-    if (mac_pdma_residual)
-      printk("pread: leaving with residual %ld of %ld\n", 
-      		mac_pdma_residual, len);
-    mac_pdma_active = 0;
-
-    /* ?? */
+			save_flags(flags);
+			cli();
+			NCR5380_print_status(default_instance);
+			restore_flags(flags);
+	}
 #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;
-
-#if (NDEBUG & NDEBUG_PSEUDO_DMA)
-    printk("pdma_write: writing %d bytes from %p\n", len, src);
-#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));
-#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);
+/*
+ * Helper function for interrupt trouble. More ugly side effects here.
+ */
 
-	s++;
+void scsi_mac_polled (void)
+{
+	unsigned long flags;
+	NCR5380_local_declare();
+	struct Scsi_Host *instance;
 	
-	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);
+#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
+		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
+			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 -u --recursive --new-file v2.3.26/linux/drivers/scsi/mac_scsi.h linux/drivers/scsi/mac_scsi.h
--- v2.3.26/linux/drivers/scsi/mac_scsi.h	Thu Jul 30 11:17:10 1998
+++ linux/drivers/scsi/mac_scsi.h	Mon Nov  8 11:03:21 1999
@@ -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
+ * 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
  */
 
 /*
- * atari_scsi.h -- Header file for the Atari native SCSI driver
- *
- * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
- *
- * (Loosely based on the work of Robert De Vries' team)
- *
- * 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.
- *
+ * $Log: cumana_NCR5380.h,v $
  */
 
+#ifndef MAC_NCR5380_H
+#define MAC_NCR5380_H
 
-#ifndef MAC_SCSI_H
-#define MAC_SCSI_H
+#define MACSCSI_PUBLIC_RELEASE 1
 
-/* (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
-
-
-#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 }
+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 -u --recursive --new-file v2.3.26/linux/drivers/scsi/mca_53c9x.h linux/drivers/scsi/mca_53c9x.h
--- v2.3.26/linux/drivers/scsi/mca_53c9x.h	Fri Aug 13 15:07:03 1999
+++ linux/drivers/scsi/mca_53c9x.h	Thu Nov 11 16:57:30 1999
@@ -31,7 +31,7 @@
 			 int hostno, int inout);
 
 
-#define MCA_53C9X         { proc_dir:		&proc_scsi_esp, \
+#define MCA_53C9X         { proc_name:		"esp", \
 			    name:		"NCR 53c9x SCSI", \
 			    detect:		mca_esp_detect, \
 			    release:		mca_esp_release, \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c
--- v2.3.26/linux/drivers/scsi/megaraid.c	Fri Sep 10 23:57:31 1999
+++ linux/drivers/scsi/megaraid.c	Thu Nov 11 16:57:30 1999
@@ -133,13 +133,11 @@
 #include <linux/modversions.h>
 #include <linux/module.h>
 
-#if LINUX_VERSION_CODE >= 0x20100
 char kernel_version[] = UTS_RELEASE;
 
 MODULE_AUTHOR ("American Megatrends Inc.");
 MODULE_DESCRIPTION ("AMI MegaRAID driver");
 #endif
-#endif
 
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -157,11 +155,7 @@
 #include <linux/interrupt.h>
 
 #include <linux/stat.h>
-#if LINUX_VERSION_CODE < 0x20100
-#include <linux/bios32.h>
-#else
 #include <linux/spinlock.h>
-#endif
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -180,27 +174,8 @@
  *================================================================
  */
 
-#if LINUX_VERSION_CODE < 0x020100
-#define ioremap vremap
-#define iounmap vfree
-
-/* simulate spin locks */
-typedef struct {
-  volatile char lock;
-} spinlock_t;
-
-#define spin_lock_init(x) { (x)->lock = 0;}
-#define spin_lock_irqsave(x,flags) { while ((x)->lock) barrier();\
-                                        (x)->lock=1; save_flags(flags);\
-                                        cli();}
-#define spin_unlock_irqrestore(x,flags) { (x)->lock=0; restore_flags(flags);}
-
-#endif
-
-#if LINUX_VERSION_CODE >= 0x020100
 #define queue_task_irq(a,b)     queue_task(a,b)
 #define queue_task_irq_off(a,b) queue_task(a,b)
-#endif
 
 #define MAX_SERBUF 160
 #define COM_BASE 0x2f8
@@ -294,11 +269,9 @@
     XX scsi id on each channel.  Used for Madrona motherboard, where SAF_TE
     processor id cannot be scanned */
 static char *megaraid;
-#if LINUX_VERSION_CODE > 0x20100
 #ifdef MODULE
 MODULE_PARM(megaraid, "s");
 #endif
-#endif
 static int skip_id;
 
 static int numCtlrs = 0;
@@ -318,12 +291,6 @@
 #endif
 volatile static spinlock_t mega_lock;
 
-struct proc_dir_entry proc_scsi_megaraid =
-{
-  PROC_SCSI_MEGARAID, 8, "megaraid",
-  S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 #if SERDEBUG
 static char strbuf[MAX_SERBUF + 1];
 
@@ -930,9 +897,7 @@
   megaCfg = (mega_host_config *) devp;
   mbox = (mega_mailbox *)tmpBox;
 
-#if LINUX_VERSION_CODE >= 0x20100
   spin_lock_irqsave (&io_request_lock, flags);
-#endif
 
   while (megaCfg->host->irq == irq) {
 
@@ -1028,9 +993,7 @@
 
   }
 
-#if LINUX_VERSION_CODE >= 0x20100
   spin_unlock_irqrestore (&io_request_lock, flags);
-#endif
 }
 
 /*==================================================*/
@@ -1450,20 +1413,11 @@
   u16 pciIdx = 0;
   u16 numFound = 0;
 
-#if LINUX_VERSION_CODE < 0x20100
-  while (!pcibios_find_device (pciVendor, pciDev, pciIdx, &pciBus, &pciDevFun)) {
-
-#if 0
-  } /* keep auto-indenters happy */
-#endif
-#else
-  
   struct pci_dev *pdev = pci_devices;
   
   while ((pdev = pci_find_device (pciVendor, pciDev, pdev))) {
     pciBus = pdev->bus->number;
     pciDevFun = pdev->devfn;
-#endif
     if ((flag & BOARD_QUARTZ) && (skip_id == -1)) {
       u16 magic;
       pcibios_read_config_word (pciBus, pciDevFun,
@@ -1555,14 +1509,8 @@
 {
   int count = 0;
 
-  pHostTmpl->proc_dir = &proc_scsi_megaraid;
+  pHostTmpl->proc_name = "megaraid";
 
-#if LINUX_VERSION_CODE < 0x20100
-  if (!pcibios_present ()) {
-    printk (KERN_WARNING "megaraid: PCI bios not present." CRLFSTR);
-    return 0;
-  }
-#endif
   skip_id = -1;
   if (megaraid && !strncmp(megaraid,"skip",strlen("skip"))) {
       if (megaraid[4] != '\0') {
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/megaraid.h linux/drivers/scsi/megaraid.h
--- v2.3.26/linux/drivers/scsi/megaraid.h	Thu Aug 26 13:05:39 1999
+++ linux/drivers/scsi/megaraid.h	Thu Nov 11 17:03:50 1999
@@ -605,8 +605,6 @@
     mega_scb scbList[MAX_COMMANDS];
 } mega_host_config;
 
-extern struct proc_dir_entry proc_scsi_megaraid;
-
 const char *megaraid_info(struct Scsi_Host *);
 int megaraid_detect(Scsi_Host_Template *);
 int megaraid_release(struct Scsi_Host *);
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/mesh.c linux/drivers/scsi/mesh.c
--- v2.3.26/linux/drivers/scsi/mesh.c	Fri Sep 10 23:57:31 1999
+++ linux/drivers/scsi/mesh.c	Thu Nov 11 16:57:30 1999
@@ -65,11 +65,6 @@
 #define ALLOW_DEBUG(tgt)	((mesh_debug_targets >> (tgt)) & 1)
 #define DEBUG_TARGET(cmd)	((cmd) && ALLOW_DEBUG((cmd)->target))
 
-struct proc_dir_entry proc_scsi_mesh = {
-	PROC_SCSI_MESH, 4, "mesh",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 #undef MESH_DBG
 #define N_DBG_LOG	50
 #define N_DBG_SLOG	20
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/mesh.h linux/drivers/scsi/mesh.h
--- v2.3.26/linux/drivers/scsi/mesh.h	Tue Aug 31 17:29:14 1999
+++ linux/drivers/scsi/mesh.h	Thu Nov 11 16:57:30 1999
@@ -7,8 +7,6 @@
 #ifndef _MESH_H
 #define _MESH_H
 
-extern struct proc_dir_entry proc_scsi_mesh;
-
 int mesh_detect(Scsi_Host_Template *);
 int mesh_command(Scsi_Cmnd *);
 int mesh_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
@@ -16,7 +14,7 @@
 int mesh_reset(Scsi_Cmnd *, unsigned int);
 
 #define SCSI_MESH {					\
-	proc_dir:	&proc_scsi_mesh,		\
+	proc_name:	"mesh",				\
 	name:		"MESH",				\
 	detect:		mesh_detect,			\
 	command:	mesh_command,			\
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/mvme16x.c linux/drivers/scsi/mvme16x.c
--- v2.3.26/linux/drivers/scsi/mvme16x.c	Mon Jul  5 20:35:18 1999
+++ linux/drivers/scsi/mvme16x.c	Thu Nov 11 16:57:30 1999
@@ -21,11 +21,6 @@
 
 #include<linux/stat.h>
 
-struct proc_dir_entry proc_scsi_mvme16x = {
-    PROC_SCSI_MVME16x, 7, "MVME16x",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 extern ncr53c7xx_init (Scsi_Host_Template *tpnt, int board, int chip,
 			u32 base, int io_port, int irq, int dma,
 			long long options, int clock);
@@ -45,7 +40,7 @@
     if (called)
 	return 0;
 
-    tpnt->proc_dir = &proc_scsi_mvme16x;
+    tpnt->proc_name = "MVME16x"
 
     options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT;
 
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/mvme16x.h linux/drivers/scsi/mvme16x.h
--- v2.3.26/linux/drivers/scsi/mvme16x.h	Wed Jun 16 19:29:21 1999
+++ linux/drivers/scsi/mvme16x.h	Thu Nov 11 16:57:30 1999
@@ -26,8 +26,6 @@
 #if defined(HOSTS_C) || defined(MODULE)
 #include <scsi/scsicam.h>
 
-extern struct proc_dir_entry proc_scsi_mvme16x;
-
 #define MVME16x_SCSI  {name:                "MVME16x NCR53c710 SCSI", \
 		       detect:              mvme16x_scsi_detect,    \
 		       queuecommand:        NCR53c7xx_queue_command, \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
--- v2.3.26/linux/drivers/scsi/ncr53c8xx.c	Sat Oct  9 11:47:50 1999
+++ linux/drivers/scsi/ncr53c8xx.c	Thu Nov 11 16:57:30 1999
@@ -733,10 +733,6 @@
 **	/proc directory entry and proc_info function
 */
 
-static struct proc_dir_entry proc_scsi_ncr53c8xx = {
-    PROC_SCSI_NCR53C8XX, 9, "ncr53c8xx",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
 #ifdef SCSI_NCR_PROC_INFO_SUPPORT
 static int ncr53c8xx_proc_info(char *buffer, char **start, off_t offset,
 			int length, int hostno, int func);
@@ -9383,7 +9379,7 @@
 	ncr_debug = driver_setup.debug;
 #endif
 
-     tpnt->proc_dir = &proc_scsi_ncr53c8xx;
+     tpnt->proc_name = "ncr53c8xx";
 #ifdef SCSI_NCR_PROC_INFO_SUPPORT
      tpnt->proc_info = ncr53c8xx_proc_info;
 #endif
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/oktagon_esp.h linux/drivers/scsi/oktagon_esp.h
--- v2.3.26/linux/drivers/scsi/oktagon_esp.h	Thu Aug 12 10:28:34 1999
+++ linux/drivers/scsi/oktagon_esp.h	Thu Nov 11 16:57:30 1999
@@ -40,7 +40,7 @@
 			int hostno, int inout);
 
 #define SCSI_OKTAGON_ESP {                       \
-   proc_dir:            &proc_scsi_esp,          \
+   proc_name:           "esp-oktagon",           \
    proc_info:           &esp_proc_info,          \
    name:                "BSC Oktagon SCSI",      \
    detect:              oktagon_esp_detect,      \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/pas16.c linux/drivers/scsi/pas16.c
--- v2.3.26/linux/drivers/scsi/pas16.c	Thu Aug 12 11:10:58 1999
+++ linux/drivers/scsi/pas16.c	Thu Nov 11 16:57:30 1999
@@ -131,10 +131,6 @@
 #include <linux/stat.h>
 #include <linux/init.h>
 
-struct proc_dir_entry proc_scsi_pas16 = {
-    PROC_SCSI_PAS16, 5, "pas16",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
 static int pas_maxi = 0;
 static int pas_wmaxi = 0;
 static unsigned short pas16_addr = 0;
@@ -392,7 +388,7 @@
     unsigned short io_port;
     int  count;
 
-    tpnt->proc_dir = &proc_scsi_pas16;
+    tpnt->proc_name = "pas16";
     tpnt->proc_info = &pas16_proc_info;
 
     if (pas16_addr != 0) {
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/pci2000.c linux/drivers/scsi/pci2000.c
--- v2.3.26/linux/drivers/scsi/pci2000.c	Fri Sep 10 23:57:32 1999
+++ linux/drivers/scsi/pci2000.c	Thu Nov 11 16:57:30 1999
@@ -53,15 +53,7 @@
 #include "pci2000.h"
 #include "psi_roy.h"
 
-#if LINUX_VERSION_CODE >= LINUXVERSION(2,1,95)
 #include <linux/spinlock.h>
-#endif
-#if LINUX_VERSION_CODE < LINUXVERSION(2,1,93)
-#include <linux/bios32.h>
-#endif
-
-struct proc_dir_entry Proc_Scsi_Pci2000 =
-	{ PROC_SCSI_PCI2000, 7, "pci2000", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
 
 //#define DEBUG 1
 
@@ -240,23 +232,13 @@
 	int					pun;
 	int					bus;
 	int					z;
-#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
-    int					flags;
-#else /* version >= v2.1.95 */
     unsigned long		flags;
-#endif /* version >= v2.1.95 */
 
-#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
-    /* Disable interrupts, if they aren't already disabled. */
-    save_flags (flags);
-    cli ();
-#else /* version >= v2.1.95 */
     /*
      * Disable interrupts, if they aren't already disabled and acquire
      * the I/O spinlock.
      */
     spin_lock_irqsave (&io_request_lock, flags);
-#endif /* version >= v2.1.95 */
 
 	DEB(printk ("\npci2000 recieved interrupt "));
 	for ( z = 0; z < NumAdapters;  z++ )										// scan for interrupt to process
@@ -345,20 +327,12 @@
 	OpDone (SCpnt, DID_OK << 16);
 
 irq_return:;
-#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
-    /*
-     * Restore the original flags which will enable interrupts
-     * if and only if they were enabled on entry.
-     */
-    restore_flags (flags);
-#else /* version >= v2.1.95 */
     /*
      * Release the I/O spinlock and restore the original flags
      * which will enable interrupts if and only if they were
      * enabled on entry.
      */
     spin_unlock_irqrestore (&io_request_lock, flags);
-#endif /* version >= v2.1.95 */
 	}
 /****************************************************************
  *	Name:	Pci2000_QueueCommand
@@ -615,27 +589,15 @@
 	PADAPTER2000	    padapter;
 	int					z, zz;
 	int					setirq;
-#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
 	struct pci_dev	   *pdev = NULL;
-#else
-	UCHAR	pci_bus, pci_device_fn;
-#endif
 
-#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
 	if ( !pci_present () )
-#else
-	if ( !pcibios_present () )
-#endif
 		{
 		printk ("pci2000: PCI BIOS not present\n");
 		return 0;
 		}
 
-#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
 	while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_ROY_1, pdev)) != NULL )
-#else
-	while ( !pcibios_find_device (VENDOR_PSI, DEVICE_ROY_1, found, &pci_bus, &pci_device_fn) )
-#endif
 		{
 		pshost = scsi_register (tpnt, sizeof(ADAPTER2000));
 		padapter = HOSTDATA(pshost);
@@ -658,11 +620,7 @@
 		if ( WaitReady (padapter) )
 			goto unregister;
 
-#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
 		pshost->irq = pdev->irq;
-#else
-		pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq);
-#endif
 		setirq = 1;
 		padapter->irqOwned = 0;
 		for ( z = 0;  z < installed;  z++ )									// scan for shared interrupts
@@ -756,11 +714,7 @@
     PADAPTER2000	padapter = HOSTDATA (pshost);
 
 	if ( padapter->irqOwned )
-#if LINUX_VERSION_CODE < LINUXVERSION(1,3,70)
-	    free_irq (pshost->irq);
-#else /* version >= v1.3.70 */
 		free_irq (pshost->irq, padapter);
-#endif /* version >= v1.3.70 */
     release_region (pshost->io_port, pshost->n_io_port);
     scsi_unregister(pshost);
     return 0;
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/pci2000.h linux/drivers/scsi/pci2000.h
--- v2.3.26/linux/drivers/scsi/pci2000.h	Wed Aug 18 16:44:26 1999
+++ linux/drivers/scsi/pci2000.h	Thu Nov 11 17:03:50 1999
@@ -200,13 +200,10 @@
 	#define NULL 0
 #endif
 
-extern struct proc_dir_entry Proc_Scsi_Pci2000;
-
-#if LINUX_VERSION_CODE >= LINUXVERSION(2,1,75)
 #define PCI2000 {																\
 		next:						NULL,										\
 		module:						NULL,										\
-		proc_dir:					&Proc_Scsi_Pci2000,							\
+		proc_name:					"pci2000",							\
 		proc_info:					NULL,	/* let's not bloat the kernel */	\
 		name:						"PCI-2000 SCSI Intelligent Disk Controller",\
 		detect:						Pci2000_Detect,								\
@@ -232,27 +229,4 @@
 		use_clustering:				DISABLE_CLUSTERING,							\
 		use_new_eh_code:			0											\
 		}
-#else
-#define PCI2000 { NULL, NULL,							\
-			&Proc_Scsi_Pci2000,/* proc_dir_entry */		\
-			NULL,		                				\
-			"PCI-2000 SCSI Intelligent Disk Controller",\
-			Pci2000_Detect,								\
-			Pci2000_Release,							\
-			NULL,	 									\
-			Pci2000_Command,							\
-			Pci2000_QueueCommand,						\
-			Pci2000_Abort,								\
-			Pci2000_Reset,								\
-			NULL,										\
-			Pci2000_BiosParam,                 			\
-			16, 										\
-			-1, 										\
-			16,		 									\
-			1, 											\
-			0, 											\
-			0, 											\
-			DISABLE_CLUSTERING }
-#endif
-
 #endif
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/pci2220i.c linux/drivers/scsi/pci2220i.c
--- v2.3.26/linux/drivers/scsi/pci2220i.c	Fri Sep 10 23:57:32 1999
+++ linux/drivers/scsi/pci2220i.c	Thu Nov 11 16:57:30 1999
@@ -47,12 +47,7 @@
 #include "hosts.h"
 #include "pci2220i.h"
 
-#if LINUX_VERSION_CODE >= LINUXVERSION(2,1,95)
 #include <linux/spinlock.h>
-#endif
-#if LINUX_VERSION_CODE < LINUXVERSION(2,1,93)
-#include <linux/bios32.h>
-#endif
 
 #define	PCI2220I_VERSION		"1.11"
 //#define	READ_CMD				IDE_COMMAND_READ
@@ -62,10 +57,6 @@
 #define	WRITE_CMD				IDE_CMD_WRITE_MULTIPLE
 #define	MAX_BUS_MASTER_BLOCKS	SECTORSXFER		// This is the maximum we can bus master
 
-
-struct proc_dir_entry Proc_Scsi_Pci2220i =
-	{ PROC_SCSI_PCI2220I, 8, "pci2220i", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
-
 //#define DEBUG 1
 
 #ifdef DEBUG
@@ -725,23 +716,13 @@
 	POUR_DEVICE		pdev = padapter->pdev;
 	UCHAR			status = IDE_STATUS_BUSY;
 	UCHAR			temp, temp1;
-#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
-    int					flags;
-#else /* version >= v2.1.95 */
     unsigned long		flags;
-#endif /* version >= v2.1.95 */
 
-#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
-    /* Disable interrupts, if they aren't already disabled. */
-    save_flags (flags);
-    cli ();
-#else /* version >= v2.1.95 */
     /*
      * Disable interrupts, if they aren't already disabled and acquire
      * the I/O spinlock.
      */
     spin_lock_irqsave (&io_request_lock, flags);
-#endif /* version >= v2.1.95 */
 	DEB (printk ("\nPCI2220I: Timeout expired "));
 
 	if ( padapter->failinprog )
@@ -866,20 +847,12 @@
 	OpDone (padapter, DecodeError (padapter, status));
 
 timerExpiryDone:;
-#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
-    /*
-     * Restore the original flags which will enable interrupts
-     * if and only if they were enabled on entry.
-     */
-    restore_flags (flags);
-#else /* version >= v2.1.95 */
     /*
      * Release the I/O spinlock and restore the original flags
      * which will enable interrupts if and only if they were
      * enabled on entry.
      */
     spin_unlock_irqrestore (&io_request_lock, flags);
-#endif /* version >= v2.1.95 */
 	}
 /****************************************************************
  *	Name:			SetReconstruct	:LOCAL
@@ -920,23 +893,13 @@
 	USHORT			minmode;
 	ULONG			zl;
 	UCHAR			zc;
-#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
-    int				flags;
-#else /* version >= v2.1.95 */
     unsigned long	flags;
-#endif /* version >= v2.1.95 */
 
-#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
-    /* Disable interrupts, if they aren't already disabled. */
-    save_flags (flags);
-    cli ();
-#else /* version >= v2.1.95 */
     /*
      * Disable interrupts, if they aren't already disabled and acquire
      * the I/O spinlock.
      */
     spin_lock_irqsave (&io_request_lock, flags);
-#endif /* version >= v2.1.95 */
 
 	padapter = (PADAPTER2220I)data;
 	if ( padapter->SCpnt )
@@ -1132,20 +1095,12 @@
 	padapter->reconPhase = RECON_PHASE_LAST;
 
 reconTimerExpiry:;
-#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
-    /*
-     * Restore the original flags which will enable interrupts
-     * if and only if they were enabled on entry.
-     */
-    restore_flags (flags);
-#else /* version >= v2.1.95 */
     /*
      * Release the I/O spinlock and restore the original flags
      * which will enable interrupts if and only if they were
      * enabled on entry.
      */
     spin_unlock_irqrestore (&io_request_lock, flags);
-#endif /* version >= v2.1.95 */
 	}
 /****************************************************************
  *	Name:	Irq_Handler	:LOCAL
@@ -1169,23 +1124,13 @@
 	UCHAR				status1;
 	int					z;
 	ULONG				zl;
-#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
-    int					flags;
-#else /* version >= v2.1.95 */
     unsigned long		flags;
-#endif /* version >= v2.1.95 */
 
-#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
-    /* Disable interrupts, if they aren't already disabled. */
-    save_flags (flags);
-    cli ();
-#else /* version >= v2.1.95 */
     /*
      * Disable interrupts, if they aren't already disabled and acquire
      * the I/O spinlock.
      */
     spin_lock_irqsave (&io_request_lock, flags);
-#endif /* version >= v2.1.95 */
 
 //	DEB (printk ("\npci2220i recieved interrupt\n"));
 
@@ -1513,20 +1458,12 @@
 
 	OpDone (padapter, zl);
 irq_return:;
-#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
-    /*
-     * Restore the original flags which will enable interrupts
-     * if and only if they were enabled on entry.
-     */
-    restore_flags (flags);
-#else /* version >= v2.1.95 */
     /*
      * Release the I/O spinlock and restore the original flags
      * which will enable interrupts if and only if they were
      * enabled on entry.
      */
     spin_unlock_irqrestore (&io_request_lock, flags);
-#endif /* version >= v2.1.95 */
 	}
 /****************************************************************
  *	Name:	Pci2220i_QueueCommand
@@ -1796,27 +1733,15 @@
 	int					setirq;
 	UCHAR				spigot1 = FALSE;
 	UCHAR				spigot2 = FALSE;
-#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
 	struct pci_dev	   *pdev = NULL;
-#else
-	UCHAR				pci_bus, pci_device_fn;
-#endif
 
-#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
 	if ( !pci_present () )
-#else
-	if ( !pcibios_present () )
-#endif
 		{
 		printk ("pci2220i: PCI BIOS not present\n");
 		return 0;
 		}
 
-#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
 	while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_DALE_1, pdev)) != NULL )
-#else
-	while ( !pcibios_find_device (VENDOR_PSI, DEVICE_DALE_1, found, &pci_bus, &pci_device_fn) )
-#endif
 		{
 		pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
 		padapter = HOSTDATA(pshost);
@@ -1854,11 +1779,7 @@
 		if ( !inb_p (padapter->regScratchPad + DALE_NUM_DRIVES) )	// if no devices on this board
 			goto unregister;
 
-#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
 		pshost->irq = pdev->irq;
-#else
-		pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq);
-#endif
 		setirq = 1;
 		for ( z = 0;  z < installed;  z++ )							// scan for shared interrupts
 			{
@@ -1881,11 +1802,7 @@
 		if ( !padapter->kBuffer )
 			{
 			printk ("Unable to allocate DMA buffer for PCI-2220I controller.\n");
-#if LINUX_VERSION_CODE < LINUXVERSION(1,3,70)
-			free_irq (pshost->irq);
-#else /* version >= v1.3.70 */
 			free_irq (pshost->irq, padapter);
-#endif /* version >= v1.3.70 */
 			goto unregister;
 			}
 		PsiHost[installed]	= pshost;								// save SCSI_HOST pointer
@@ -2068,11 +1985,7 @@
 	outb_p (DiskMirror[1].status, padapter->regScratchPad + DALE_RAID_1_STATUS);		
 
 	if ( padapter->irqOwned )
-#if LINUX_VERSION_CODE < LINUXVERSION(1,3,70)
-		free_irq (pshost->irq);
-#else /* version >= v1.3.70 */
 		free_irq (pshost->irq, padapter);
-#endif /* version >= v1.3.70 */
     release_region (pshost->io_port, pshost->n_io_port);
 	kfree (padapter->kBuffer);
     scsi_unregister(pshost);
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/pci2220i.h linux/drivers/scsi/pci2220i.h
--- v2.3.26/linux/drivers/scsi/pci2220i.h	Wed Aug 18 16:44:27 1999
+++ linux/drivers/scsi/pci2220i.h	Thu Nov 11 17:03:51 1999
@@ -293,13 +293,10 @@
 	#define NULL 0
 #endif
 
-extern struct proc_dir_entry Proc_Scsi_Pci2220i;
-
-#if LINUX_VERSION_CODE >= LINUXVERSION(2,1,75)
 #define PCI2220I {															\
 		next:						NULL,									\
 		module:						NULL,									\
-		proc_dir:					&Proc_Scsi_Pci2220i,					\
+		proc_name:					"pci2220i",					\
 		proc_info:					NULL,	/* let's not bloat the kernel */\
 		name:						"PCI-2220I EIDE Disk Controller",		\
 		detect:						Pci2220i_Detect,						\
@@ -325,27 +322,4 @@
 		use_clustering:				DISABLE_CLUSTERING,						\
 		use_new_eh_code:			0										\
 		}
-#else
-#define PCI2220I { NULL, NULL,						\
-			&Proc_Scsi_Pci2220i,/* proc_dir_entry */\
-			NULL,		                			\
-			"PCI-2220I EIDE Disk Controller",		\
-			Pci2220i_Detect,						\
-			Pci2220i_Release,						\
-			NULL,	 								\
-			Pci2220i_Command,						\
-			Pci2220i_QueueCommand,					\
-			Pci2220i_Abort,							\
-			Pci2220i_Reset,							\
-			NULL,									\
-			Pci2220i_BiosParam,                 	\
-			1, 										\
-			-1, 									\
-			SG_NONE,		 						\
-			1, 										\
-			0, 										\
-			0, 										\
-			DISABLE_CLUSTERING }
-#endif
-
 #endif
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/pluto.c linux/drivers/scsi/pluto.c
--- v2.3.26/linux/drivers/scsi/pluto.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/scsi/pluto.c	Thu Nov 11 16:57:30 1999
@@ -39,11 +39,6 @@
 #define PLND(x)
 #endif
 
-struct proc_dir_entry proc_scsi_pluto = {
-	PROC_SCSI_PLUTO, 5, "pluto",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 static struct ctrl_inquiry {
 	struct Scsi_Host host;
 	struct pluto pluto;
@@ -98,7 +93,7 @@
 	fc_channel *fc;
 	Scsi_Device dev;
 
-	tpnt->proc_dir = &proc_scsi_pluto;
+	tpnt->proc_name = "pluto";
 	fcscount = 0;
 	for_each_online_fc_channel(fc) {
 		if (!fc->posmap)
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/ppa.h linux/drivers/scsi/ppa.h
--- v2.3.26/linux/drivers/scsi/ppa.h	Wed Aug 18 16:44:59 1999
+++ linux/drivers/scsi/ppa.h	Thu Nov 11 17:04:13 1999
@@ -138,10 +138,7 @@
 static void ppa_interrupt(void *);
 static int ppa_out(int, char *, int);
 
-struct proc_dir_entry proc_scsi_ppa =
-{PROC_SCSI_PPA, 3, "ppa", S_IFDIR | S_IRUGO | S_IXUGO, 2};
 #else
-extern struct proc_dir_entry proc_scsi_ppa;
 #define ppa_release 0
 #endif
 
@@ -154,7 +151,7 @@
 int ppa_proc_info(char *, char **, off_t, int, int, int);
 int ppa_biosparam(Disk *, kdev_t, int *);
 
-#define PPA {	proc_dir:			&proc_scsi_ppa,		\
+#define PPA {	proc_name:			"ppa",		\
 		proc_info:			ppa_proc_info,		\
 		name:				"Iomega VPI0 (ppa) interface",\
 		detect:				ppa_detect,		\
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/psi240i.c linux/drivers/scsi/psi240i.c
--- v2.3.26/linux/drivers/scsi/psi240i.c	Fri Sep 10 23:57:32 1999
+++ linux/drivers/scsi/psi240i.c	Thu Nov 11 16:57:30 1999
@@ -46,9 +46,6 @@
 
 #include<linux/stat.h>
 
-struct proc_dir_entry Proc_Scsi_Psi240i =
-	{ PROC_SCSI_PSI240I, 7, "psi240i", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
-
 //#define DEBUG 1
 
 #ifdef DEBUG
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/psi240i.h linux/drivers/scsi/psi240i.h
--- v2.3.26/linux/drivers/scsi/psi240i.h	Sun Dec 27 22:19:22 1998
+++ linux/drivers/scsi/psi240i.h	Thu Nov 11 16:57:30 1999
@@ -318,9 +318,7 @@
 	#define NULL 0
 #endif
 
-extern struct proc_dir_entry Proc_Scsi_Psi240i;
-
-#define PSI240I { proc_dir:       &Proc_Scsi_Psi240i,/* proc_dir_entry */ \
+#define PSI240I { proc_name:      "psi240i", \
 		  name:           "PSI-240I EIDE Disk Controller",\
 		  detect:         Psi240i_Detect,			\
 		  command:	  Psi240i_Command,			\
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/qlogicfas.c linux/drivers/scsi/qlogicfas.c
--- v2.3.26/linux/drivers/scsi/qlogicfas.c	Fri Sep 10 23:57:32 1999
+++ linux/drivers/scsi/qlogicfas.c	Thu Nov 11 16:57:30 1999
@@ -131,11 +131,6 @@
 #include "qlogicfas.h"
 #include<linux/stat.h>
 
-static struct proc_dir_entry proc_scsi_qlogicfas = {
-    PROC_SCSI_QLOGICFAS, 6, "qlogicfas",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 /*----------------------------------------------------------------*/
 /* driver state info, local to driver */
 static int	    qbase = 0;	/* Port */
@@ -550,7 +545,7 @@
 struct	Scsi_Host	*hreg;	/* registered host structure */
 unsigned long	flags;
 
-host->proc_dir =  &proc_scsi_qlogicfas;
+host->proc_name =  "qlogicfas";
 
 /* Qlogic Cards only exist at 0x230 or 0x330 (the chip itself decodes the
    address - I check 230 first since MIDI cards are typically at 330
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/qlogicfc.c linux/drivers/scsi/qlogicfc.c
--- v2.3.26/linux/drivers/scsi/qlogicfc.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/scsi/qlogicfc.c	Thu Nov 11 16:57:30 1999
@@ -698,13 +698,6 @@
 static void isp2x00_print_status_entry(struct Status_Entry *);
 #endif
 
-static struct proc_dir_entry proc_scsi_isp2x00 =
-{
-	PROC_SCSI_QLOGICFC, 7, "isp2x00",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
-
 static inline void isp2x00_enable_irqs(struct Scsi_Host *host)
 {
 	outw(ISP_EN_INT | ISP_EN_RISC, host->io_port + PCI_INTER_CTL);
@@ -733,7 +726,7 @@
        	device_ids[0] = PCI_DEVICE_ID_QLOGIC_ISP2100;
 	device_ids[1] = PCI_DEVICE_ID_QLOGIC_ISP2200;
 
-	tmpt->proc_dir = &proc_scsi_isp2x00;
+	tmpt->proc_name = "isp2x00";
 
 	if (pci_present() == 0) {
 		printk("qlogicfc : PCI not present\n");
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/qlogicisp.c linux/drivers/scsi/qlogicisp.c
--- v2.3.26/linux/drivers/scsi/qlogicisp.c	Fri Sep 10 23:57:32 1999
+++ linux/drivers/scsi/qlogicisp.c	Thu Nov 11 16:57:30 1999
@@ -535,12 +535,6 @@
 static void	isp1020_print_status_entry(struct Status_Entry *);
 #endif
 
-static struct proc_dir_entry proc_scsi_isp1020 = {
-	PROC_SCSI_QLOGICISP, 7, "isp1020",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
-
 static inline void isp1020_enable_irqs(struct Scsi_Host *host)
 {
 	outw(ISP_EN_INT|ISP_EN_RISC, host->io_port + PCI_INTF_CTL);
@@ -562,7 +556,7 @@
 
 	ENTER("isp1020_detect");
 
-	tmpt->proc_dir = &proc_scsi_isp1020;
+	tmpt->proc_name = "isp1020";
 
 	if (pci_present() == 0) {
 		printk("qlogicisp : PCI not present\n");
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/qlogicpti.c linux/drivers/scsi/qlogicpti.c
--- v2.3.26/linux/drivers/scsi/qlogicpti.c	Fri Sep 10 23:57:32 1999
+++ linux/drivers/scsi/qlogicpti.c	Thu Nov 11 16:57:30 1999
@@ -132,11 +132,6 @@
 						    QLOGICISP_REQ_QUEUE_LEN)
 #define RES_QUEUE_DEPTH(in, out)	QUEUE_DEPTH(in, out, RES_QUEUE_LEN)
 
-static struct proc_dir_entry proc_scsi_qlogicpti = {
-	PROC_SCSI_QLOGICPTI, 7, "qlogicpti",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 static inline void qlogicpti_enable_irqs(struct qlogicpti_regs *qregs)
 {
 	qregs->sbus_ctrl = SBUS_CTRL_ERIRQ | SBUS_CTRL_GENAB;
@@ -596,7 +591,7 @@
 	int qpti_node;
 	int is_pti;
 
-	tpnt->proc_dir = &proc_scsi_qlogicpti;
+	tpnt->proc_name = "qlogicpti";
 	qptichain = 0;
 	if(!SBus_chain)
 		return 0;
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.3.26/linux/drivers/scsi/scsi.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/scsi/scsi.c	Thu Nov 11 16:57:30 1999
@@ -70,6 +70,14 @@
 
 #undef USE_STATIC_SCSI_MEMORY
 
+struct proc_dir_entry *proc_scsi = NULL;
+
+#ifdef CONFIG_PROC_FS
+static int scsi_proc_info(char *buffer, char **start, off_t offset,
+			  int length, int inout);
+static void scsi_dump_status(int level);
+#endif
+
 /*
    static const char RCSid[] = "$Header: /vger/u4/cvs/linux/drivers/scsi/scsi.c,v 1.38 1997/01/19 23:07:18 davem Exp $";
  */
@@ -141,21 +149,6 @@
 
 volatile struct Scsi_Host *host_active = NULL;
 
-#if CONFIG_PROC_FS
-/* 
- * This is the pointer to the /proc/scsi code.
- * It is only initialized to !=0 if the scsi code is present
- */
-struct proc_dir_entry proc_scsi_scsi =
-{
-	PROC_SCSI_SCSI, 4, "scsi",
-	S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0, 0,
-	NULL,
-	NULL, NULL,
-	NULL, NULL, NULL
-};
-#endif
-
 
 const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] =
 {
@@ -194,20 +187,12 @@
 extern void scsi_old_done(Scsi_Cmnd * SCpnt);
 extern void scsi_old_times_out(Scsi_Cmnd * SCpnt);
 
-#if CONFIG_PROC_FS
-extern int (*dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
-				    off_t offset, int length, int inout);
-extern int dispatch_scsi_info(int ino, char *buffer, char **start,
-			      off_t offset, int length, int inout);
-#endif
-
 #define SCSI_BLOCK(DEVICE, HOST)                                                \
                 ((HOST->block && host_active && HOST != host_active)            \
 		  || ((HOST)->can_queue && HOST->host_busy >= HOST->can_queue)    \
                   || ((HOST)->host_blocked)                                       \
                   || ((DEVICE) != NULL && (DEVICE)->device_blocked) )
 
-static void scsi_dump_status(int level);
 
 
 struct dev_info {
@@ -1997,18 +1982,23 @@
 #endif
 
 	/* Yes we're here... */
-#if CONFIG_PROC_FS
-	dispatch_scsi_info_ptr = dispatch_scsi_info;
+
+	/*
+	 * This makes /proc/scsi and /proc/scsi/scsi visible.
+	 */
+#ifdef CONFIG_PROC_FS
+	proc_scsi = create_proc_entry ("scsi", S_IFDIR, 0);
+	if (!proc_scsi) {
+		printk (KERN_ERR "cannot init /proc/scsi\n");
+		return -ENOMEM;
+	}
+	
+	create_proc_info_entry ("scsi/scsi", 0, 0, scsi_proc_info);
 #endif
 
 	/* Init a few things so we can "malloc" memory. */
 	scsi_loadable_module_flag = 0;
 
-	/* Register the /proc/scsi/scsi entry */
-#if CONFIG_PROC_FS
-	proc_scsi_register(0, &proc_scsi_scsi);
-#endif
-
 	/* initialize all hosts */
 	scsi_init();
 
@@ -2114,8 +2104,8 @@
 
 
 #ifdef CONFIG_PROC_FS
-int scsi_proc_info(char *buffer, char **start, off_t offset, int length,
-		   int hostno, int inout)
+static int scsi_proc_info(char *buffer, char **start, off_t offset,
+			  int length, int inout)
 {
 	Scsi_Cmnd *SCpnt;
 	struct Scsi_Device_Template *SDTpnt;
@@ -2191,7 +2181,7 @@
 	 * where token is one of [error,scan,mlqueue,mlcomplete,llqueue,
 	 * llcomplete,hlqueue,hlcomplete]
 	 */
-#if CONFIG_SCSI_LOGGING		/* { */
+#ifdef CONFIG_SCSI_LOGGING		/* { */
 
 	if (!strncmp("log", buffer + 5, 3)) {
 		char *token;
@@ -2627,7 +2617,7 @@
 		scsi_hosts = tpnt;
 
 		/* Add the new driver to /proc/scsi */
-#if CONFIG_PROC_FS
+#ifdef CONFIG_PROC_FS
 		build_proc_dir_entries(tpnt);
 #endif
 
@@ -2893,33 +2883,28 @@
 
 	for (shpnt = scsi_hostlist; shpnt; shpnt = sh1) {
 		sh1 = shpnt->next;
-		if (shpnt->hostt == tpnt) {
-			if (shpnt->loaded_as_module) {
-				pcount = next_scsi_host;
-				/* Remove the /proc/scsi directory entry */
-#if CONFIG_PROC_FS
-				proc_scsi_unregister(tpnt->proc_dir,
-					shpnt->host_no + PROC_SCSI_FILE);
-#endif
-				if (tpnt->release)
-					(*tpnt->release) (shpnt);
-				else {
-					/* This is the default case for the release function.
-					 * It should do the right thing for most correctly
-					 * written host adapters.
-					 */
-					if (shpnt->irq)
-						free_irq(shpnt->irq, NULL);
-					if (shpnt->dma_channel != 0xff)
-						free_dma(shpnt->dma_channel);
-					if (shpnt->io_port && shpnt->n_io_port)
-						release_region(shpnt->io_port, shpnt->n_io_port);
-				}
-				if (pcount == next_scsi_host)
-					scsi_unregister(shpnt);
-				tpnt->present--;
-			}
-		}
+		if (shpnt->hostt != tpnt || !shpnt->loaded_as_module)
+			continue;
+		pcount = next_scsi_host;
+		/* Remove the /proc/scsi directory entry */
+		remove_proc_entry(shpnt->proc_name, tpnt->proc_dir);
+		if (tpnt->release)
+			(*tpnt->release) (shpnt);
+		else {
+			/* This is the default case for the release function.
+			 * It should do the right thing for most correctly
+			 * written host adapters.
+			 */
+			if (shpnt->irq)
+			free_irq(shpnt->irq, NULL);
+			if (shpnt->dma_channel != 0xff)
+				free_dma(shpnt->dma_channel);
+			if (shpnt->io_port && shpnt->n_io_port)
+				release_region(shpnt->io_port, shpnt->n_io_port);
+		}
+		if (pcount == next_scsi_host)
+			scsi_unregister(shpnt);
+		tpnt->present--;
 	}
 
 	/*
@@ -2959,9 +2944,7 @@
 			break;
 		}
 	/* Rebuild the /proc/scsi directory entries */
-#if CONFIG_PROC_FS
-	proc_scsi_unregister(tpnt->proc_dir, tpnt->proc_dir->low_ino);
-#endif
+	remove_proc_entry(tpnt->proc_name, proc_scsi);
 	MOD_DEC_USE_COUNT;
 }
 
@@ -3146,6 +3129,7 @@
 
 #endif				/* CONFIG_MODULES */
 
+#ifdef CONFIG_PROC_FS
 /*
  * Function:    scsi_dump_status
  *
@@ -3166,8 +3150,7 @@
  */
 static void scsi_dump_status(int level)
 {
-#if CONFIG_PROC_FS
-#if CONFIG_SCSI_LOGGING		/* { */
+#ifdef CONFIG_SCSI_LOGGING		/* { */
 	int i;
 	struct Scsi_Host *shpnt;
 	Scsi_Cmnd *SCpnt;
@@ -3246,8 +3229,8 @@
 	}
 	/* printk("wait_for_request = %p\n", &wait_for_request); */
 #endif	/* CONFIG_SCSI_LOGGING */ /* } */
-#endif				/* CONFIG_PROC_FS */
 }
+#endif				/* CONFIG_PROC_FS */
 
 #ifdef MODULE
 
@@ -3257,19 +3240,19 @@
 	int has_space = 0;
 
 	/*
-	 * This makes /proc/scsi visible.
+	 * This makes /proc/scsi and /proc/scsi/scsi visible.
 	 */
-#if CONFIG_PROC_FS
-	dispatch_scsi_info_ptr = dispatch_scsi_info;
+#ifdef CONFIG_PROC_FS
+	proc_scsi = create_proc_entry ("scsi", S_IFDIR, 0);
+	if (!proc_scsi) {
+		printk (KERN_ERR "cannot init /proc/scsi\n");
+		return -ENOMEM;
+	}
+	create_proc_info_entry ("scsi/scsi", 0, 0, scsi_proc_info);
 #endif
 
 	scsi_loadable_module_flag = 1;
 
-	/* Register the /proc/scsi/scsi entry */
-#if CONFIG_PROC_FS
-	proc_scsi_register(0, &proc_scsi_scsi);
-#endif
-
 	dma_sectors = PAGE_SIZE / SECTOR_SIZE;
 	scsi_dma_free_sectors = dma_sectors;
 	/*
@@ -3316,13 +3299,12 @@
 {
 	remove_bh(SCSI_BH);
 
-#if CONFIG_PROC_FS
-	proc_scsi_unregister(0, PROC_SCSI_SCSI);
-
+#ifdef CONFIG_PROC_FS
 	/* No, we're not here anymore. Don't show the /proc/scsi files. */
-	dispatch_scsi_info_ptr = 0L;
+	remove_proc_entry ("scsi/scsi", 0);
+	remove_proc_entry ("scsi", 0);
 #endif
-
+	
 	/*
 	 * Free up the DMA pool.
 	 */
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
--- v2.3.26/linux/drivers/scsi/scsi.h	Mon Oct  4 15:49:30 1999
+++ linux/drivers/scsi/scsi.h	Thu Nov 11 17:03:44 1999
@@ -16,6 +16,7 @@
 #define _SCSI_H
 
 #include <linux/config.h>	/* for CONFIG_SCSI_LOGGING */
+#include <linux/proc_fs.h>
 
 /*
  * Some of the public constants are being moved to this file.
@@ -404,6 +405,7 @@
 extern int max_scsi_hosts;
 
 extern void proc_print_scsidevice(Scsi_Device *, char *, int *, int);
+extern struct proc_dir_entry *proc_scsi;
 
 extern void print_command(unsigned char *);
 extern void print_sense(const char *, Scsi_Cmnd *);
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/scsi_debug.c linux/drivers/scsi/scsi_debug.c
--- v2.3.26/linux/drivers/scsi/scsi_debug.c	Mon Oct  4 15:49:30 1999
+++ linux/drivers/scsi/scsi_debug.c	Thu Nov 11 16:57:30 1999
@@ -30,13 +30,6 @@
 
 #include<linux/stat.h>
 
-struct proc_dir_entry proc_scsi_scsi_debug =
-{
-	PROC_SCSI_SCSI_DEBUG, 10, "scsi_debug",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
-
 /* A few options that we want selected */
 
 #define NR_HOSTS_PRESENT 20
@@ -558,7 +551,7 @@
 	int i;
 
 	for (i = 0; i < NR_HOSTS_PRESENT; i++) {
-		tpnt->proc_dir = &proc_scsi_scsi_debug;
+		tpnt->proc_name = "scsi_debug";	/* Huh? In the loop??? */
 		scsi_register(tpnt, 0);
 	}
 	return NR_HOSTS_PRESENT;
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c
--- v2.3.26/linux/drivers/scsi/scsi_ioctl.c	Sat Oct  9 11:47:50 1999
+++ linux/drivers/scsi/scsi_ioctl.c	Thu Nov 11 16:57:30 1999
@@ -404,7 +404,7 @@
 		put_user(dev->id
 			 + (dev->lun << 8)
 			 + (dev->channel << 16)
-		  + ((dev->host->hostt->proc_dir->low_ino & 0xff) << 24),
+			 + ((dev->host->host_no & 0xff) << 24),
 			 &((Scsi_Idlun *) arg)->dev_id);
 		put_user(dev->host->unique_id, &((Scsi_Idlun *) arg)->host_unique_id);
 		return 0;
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/scsi_proc.c linux/drivers/scsi/scsi_proc.c
--- v2.3.26/linux/drivers/scsi/scsi_proc.c	Tue Sep  7 12:14:06 1999
+++ linux/drivers/scsi/scsi_proc.c	Thu Nov 11 16:57:30 1999
@@ -27,6 +27,9 @@
 #include <linux/errno.h>
 #include <linux/stat.h>
 #include <linux/blk.h>
+
+#include <asm/uaccess.h>
+
 #include "scsi.h"
 #include "hosts.h"
 
@@ -36,27 +39,16 @@
 #endif
 
 #ifdef CONFIG_PROC_FS
-extern int scsi_proc_info(char *, char **, off_t, int, int, int);
-
-struct scsi_dir {
-	struct proc_dir_entry entry;
-	char name[4];
-};
-
 
 /* generic_proc_info
  * Used if the driver currently has no own support for /proc/scsi
  */
-int generic_proc_info(char *buffer, char **start, off_t offset,
-		      int length, int inode, int inout,
+int generic_proc_info(char *buffer, char **start, off_t offset, int length, 
 		      const char *(*info) (struct Scsi_Host *),
 		      struct Scsi_Host *sh)
 {
 	int len, pos, begin;
 
-	if (inout == TRUE)
-		return (-ENOSYS);	/* This is a no-op */
-
 	begin = 0;
 	if (info && sh) {
 		pos = len = sprintf(buffer, "%s\n", info(sh));
@@ -79,70 +71,70 @@
 /* dispatch_scsi_info is the central dispatcher 
  * It is the interface between the proc-fs and the SCSI subsystem code
  */
-extern int dispatch_scsi_info(int ino, char *buffer, char **start,
-			      off_t offset, int length, int func)
+static int proc_scsi_read(char *buffer, char **start, off_t offset,
+	int length, int *eof, void *data)
 {
-	struct Scsi_Host *hpnt = scsi_hostlist;
+	struct Scsi_Host *hpnt = data;
+	int n;
 
-	if (ino == PROC_SCSI_SCSI) {
-		/*
-		 * This is for the scsi core, rather than any specific
-		 * lowlevel driver.
-		 */
-		return (scsi_proc_info(buffer, start, offset, length, 0, func));
-	}
-	while (hpnt) {
-		if (ino == (hpnt->host_no + PROC_SCSI_FILE)) {
-			if (hpnt->hostt->proc_info == NULL)
-				return generic_proc_info(buffer, start, offset, length,
-						     hpnt->host_no, func,
-						       hpnt->hostt->info,
-							 hpnt);
-			else
-				return (hpnt->hostt->proc_info(buffer, start, offset,
-					   length, hpnt->host_no, func));
-		}
-		hpnt = hpnt->next;
-	}
-	return (-EBADF);
+	if (hpnt->hostt->proc_info == NULL)
+		n = generic_proc_info(buffer, start, offset, length,
+				      hpnt->hostt->info, hpnt);
+	else
+		n = (hpnt->hostt->proc_info(buffer, start, offset,
+					   length, hpnt->host_no, 0));
+	*eof = (n<length);
+	return n;
 }
 
-static void scsi_proc_fill_inode(struct inode *inode, int fill)
+#define PROC_BLOCK_SIZE (3*1024)     /* 4K page size, but our output routines 
+				      * use some slack for overruns 
+				      */
+
+static ssize_t proc_scsi_write(struct file * file, const char * buf,
+                              unsigned long count, void *data)
 {
-	Scsi_Host_Template *shpnt;
+	struct Scsi_Host *hpnt = data;
+	ssize_t ret = 0;
+	char * page;
+	char *start;
+    
+	if (count > PROC_BLOCK_SIZE)
+		return -EOVERFLOW;
+
+	if (!(page = (char *) __get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+	copy_from_user(page, buf, count);
 
-	shpnt = scsi_hosts;
-	while (shpnt && shpnt->proc_dir->low_ino != inode->i_ino)
-		shpnt = shpnt->next;
-	if (!shpnt || !shpnt->module)
-		return;
-	if (fill)
-		__MOD_INC_USE_COUNT(shpnt->module);
+	if (hpnt->hostt->proc_info == NULL)
+		ret = -ENOSYS;
 	else
-		__MOD_DEC_USE_COUNT(shpnt->module);
+		ret = hpnt->hostt->proc_info(page, &start, 0, count,
+						hpnt->host_no, 1);
+	free_page((ulong) page);
+	return(ret);
 }
 
 void build_proc_dir_entries(Scsi_Host_Template * tpnt)
 {
 	struct Scsi_Host *hpnt;
-	struct scsi_dir *scsi_hba_dir;
 
-	proc_scsi_register(0, tpnt->proc_dir);
-	tpnt->proc_dir->fill_inode = &scsi_proc_fill_inode;
+	tpnt->proc_dir = create_proc_entry(tpnt->proc_name, S_IFDIR, proc_scsi);
+	tpnt->proc_dir->owner = tpnt->module;
 
 	hpnt = scsi_hostlist;
 	while (hpnt) {
 		if (tpnt == hpnt->hostt) {
-			scsi_hba_dir = scsi_init_malloc(sizeof(struct scsi_dir), GFP_KERNEL);
-			if (scsi_hba_dir == NULL)
+			struct proc_dir_entry *p;
+			p = create_proc_read_entry(hpnt->proc_name,
+					S_IFREG | S_IRUGO | S_IWUSR,
+					tpnt->proc_dir,
+					proc_scsi_read,
+					(void *)hpnt);
+			if (!p)
 				panic("Not enough memory to register SCSI HBA in /proc/scsi !\n");
-			memset(scsi_hba_dir, 0, sizeof(struct scsi_dir));
-			scsi_hba_dir->entry.low_ino = PROC_SCSI_FILE + hpnt->host_no;
-			scsi_hba_dir->entry.namelen = sprintf(scsi_hba_dir->name, "%d",
-							  hpnt->host_no);
-			scsi_hba_dir->entry.name = scsi_hba_dir->name;
-			scsi_hba_dir->entry.mode = S_IFREG | S_IRUGO | S_IWUSR;
-			proc_scsi_register(tpnt->proc_dir, &scsi_hba_dir->entry);
+			p->write_proc=proc_scsi_write;
+			p->owner = tpnt->module;
 		}
 		hpnt = hpnt->next;
 	}
@@ -178,28 +170,28 @@
 	 cmdNum;		/* cmd number      */
 } parseHandle;
 
-
 inline int parseFree(parseHandle * handle)
 {				/* free memory     */
 	kfree(handle->cmdPos);
 	kfree(handle);
 
-	return (-1);
+	return -1;
 }
 
-
 parseHandle *parseInit(char *buf, char *cmdList, int cmdNum)
 {
 	char *ptr;		/* temp pointer    */
 	parseHandle *handle;	/* new handle      */
 
 	if (!buf || !cmdList)	/* bad input ?     */
-		return (NULL);
-	if ((handle = (parseHandle *) kmalloc(sizeof(parseHandle), GFP_KERNEL)) == 0)
-		return (NULL);	/* out of memory   */
-	if ((handle->cmdPos = (char **) kmalloc(sizeof(int) * cmdNum, GFP_KERNEL)) == 0) {
+		return NULL;
+	handle = (parseHandle *) kmalloc(sizeof(parseHandle), GFP_KERNEL);
+	if (!handle)
+		return NULL;	/* out of memory   */
+	handle->cmdPos = (char **) kmalloc(sizeof(int) * cmdNum, GFP_KERNEL);
+	if (!handle->cmdPos) {
 		kfree(handle);
-		return (NULL);	/* out of memory   */
+		return NULL;	/* out of memory   */
 	}
 	handle->buf = handle->bufPos = buf;	/* init handle     */
 	handle->cmdList = cmdList;
@@ -212,10 +204,9 @@
 			handle->cmdPos[++cmdNum] = ptr++;
 		}
 	}
-	return (handle);
+	return handle;
 }
 
-
 int parseOpt(parseHandle * handle, char **param)
 {
 	int cmdIndex = 0, cmdLen = 0;
@@ -299,7 +290,7 @@
 	return;
 }
 
-#else
+#else				/* if !CONFIG_PROC_FS */
 
 void proc_print_scsidevice(Scsi_Device * scd, char *buffer, int *size, int len)
 {
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/scsi_syms.c linux/drivers/scsi/scsi_syms.c
--- v2.3.26/linux/drivers/scsi/scsi_syms.c	Mon Oct  4 15:49:30 1999
+++ linux/drivers/scsi/scsi_syms.c	Thu Nov 11 16:57:30 1999
@@ -73,6 +73,8 @@
 EXPORT_SYMBOL(scsi_sleep);
 
 EXPORT_SYMBOL(proc_print_scsidevice);
+EXPORT_SYMBOL(proc_scsi);
+
 /*
  * These are here only while I debug the rest of the scsi stuff.
  */
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.3.26/linux/drivers/scsi/sd.c	Mon Oct  4 15:49:30 1999
+++ linux/drivers/scsi/sd.c	Wed Nov 10 20:02:02 1999
@@ -36,21 +36,25 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/string.h>
+#include <linux/hdreg.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 
 #include <linux/smp.h>
 
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/io.h>
 
 #define MAJOR_NR SCSI_DISK0_MAJOR
 #include <linux/blk.h>
+#include <linux/blkpg.h>
 #include "scsi.h"
 #include "hosts.h"
 #include "sd.h"
 #include <scsi/scsi_ioctl.h>
 #include "constants.h"
+#include <scsi/scsicam.h>	/* must follow "hosts.h" */
 
 #include <linux/genhd.h>
 
@@ -87,8 +91,6 @@
 static int *sd_blocksizes;
 static int *sd_hardsizes;	/* Hardware sector size */
 
-extern int sd_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
-
 static int check_scsidisk_media_change(kdev_t);
 static int fop_revalidate_scsidisk(kdev_t);
 
@@ -102,6 +104,80 @@
 static int sd_detect(Scsi_Device *);
 static void sd_detach(Scsi_Device *);
 
+static int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg)
+{
+	kdev_t dev = inode->i_rdev;
+	struct Scsi_Host * host;
+	Scsi_Device * SDev;
+	int diskinfo[4];
+	struct hd_geometry *loc = (struct hd_geometry *) arg;
+    
+	SDev = rscsi_disks[DEVICE_NR(dev)].device;
+	/*
+	 * If we are in the middle of error recovery, don't let anyone
+	 * else try and use this device.  Also, if error recovery fails, it
+	 * may try and take the device offline, in which case all further
+	 * access to the device is prohibited.
+	 */
+
+	if( !scsi_block_when_processing_errors(SDev) )
+	{
+		return -ENODEV;
+	}
+
+	switch (cmd) 
+	{
+		case HDIO_GETGEO:   /* Return BIOS disk parameters */
+			if(!loc)
+				return -EINVAL;
+
+			host = rscsi_disks[DEVICE_NR(dev)].device->host;
+	
+			/* default to most commonly used values */
+	
+		        diskinfo[0] = 0x40;
+	        	diskinfo[1] = 0x20;
+	        	diskinfo[2] = rscsi_disks[DEVICE_NR(dev)].capacity >> 11;
+	
+			/* override with calculated, extended default, or driver values */
+	
+			if(host->hostt->bios_param != NULL)
+				host->hostt->bios_param(&rscsi_disks[DEVICE_NR(dev)],
+					    dev,
+					    &diskinfo[0]);
+			else scsicam_bios_param(&rscsi_disks[DEVICE_NR(dev)],
+					dev, &diskinfo[0]);
+
+			if (put_user(diskinfo[0], &loc->heads) ||
+				put_user(diskinfo[1], &loc->sectors) ||
+				put_user(diskinfo[2], &loc->cylinders) ||
+				put_user(sd[SD_PARTITION(inode->i_rdev)].start_sect, &loc->start))
+				return -EFAULT;
+			return 0;
+		case BLKGETSIZE:   /* Return device size */
+			if (!arg)
+				return -EINVAL;
+			return put_user(sd[SD_PARTITION(inode->i_rdev)].nr_sects, (long *) arg);
+
+		case BLKROSET:
+		case BLKROGET:
+		case BLKRASET:
+		case BLKRAGET:
+		case BLKFLSBUF:
+		case BLKSSZGET:
+		case BLKPG:
+			return blk_ioctl(inode->i_rdev, cmd, arg);
+
+		case BLKRRPART: /* Re-read partition tables */
+		        if (!capable(CAP_SYS_ADMIN))
+		                return -EACCES;
+			return revalidate_scsidisk(dev, 1);
+
+		default:
+			return scsi_ioctl(rscsi_disks[DEVICE_NR(dev)].device , cmd, (void *) arg);
+	}
+}
+
 static void sd_devname(unsigned int disknum, char *buffer)
 {
 	if (disknum < 26)
@@ -119,11 +195,11 @@
 	}
 }
 
-struct Scsi_Device_Template sd_template =
-{NULL, "disk", "sd", NULL, TYPE_DISK,
- SCSI_DISK0_MAJOR, 0, 0, 0, 1,
- sd_detect, sd_init,
- sd_finish, sd_attach, sd_detach
+struct Scsi_Device_Template sd_template = {
+	NULL, "disk", "sd", NULL, TYPE_DISK,
+	SCSI_DISK0_MAJOR, 0, 0, 0, 1,
+	sd_detect, sd_init,
+	sd_finish, sd_attach, sd_detach
 };
 
 static int sd_open(struct inode *inode, struct file *filp)
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/sd_ioctl.c linux/drivers/scsi/sd_ioctl.c
--- v2.3.26/linux/drivers/scsi/sd_ioctl.c	Sat May 15 23:43:04 1999
+++ linux/drivers/scsi/sd_ioctl.c	Wed Dec 31 16:00:00 1969
@@ -1,119 +0,0 @@
-/*
- * drivers/scsi/sd_ioctl.c
- *
- * ioctl handling for SCSI disks
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/hdreg.h>
-#include <linux/errno.h>
-
-#include <asm/uaccess.h>
-
-#define MAJOR_NR	SCSI_DISK0_MAJOR
-#include <linux/blk.h>
-#include <linux/blkpg.h>
-#include "scsi.h"
-#include <scsi/scsi_ioctl.h>
-#include "hosts.h"
-#include "sd.h"
-#include <scsi/scsicam.h>     /* must follow "hosts.h" */
-
-int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg)
-{
-    kdev_t dev = inode->i_rdev;
-    int error;
-    struct Scsi_Host * host;
-    Scsi_Device * SDev;
-    int diskinfo[4];
-    struct hd_geometry *loc = (struct hd_geometry *) arg;
-    
-    SDev = rscsi_disks[DEVICE_NR(dev)].device;
-    /*
-     * If we are in the middle of error recovery, don't let anyone
-     * else try and use this device.  Also, if error recovery fails, it
-     * may try and take the device offline, in which case all further
-     * access to the device is prohibited.
-     */
-    if( !scsi_block_when_processing_errors(SDev) )
-      {
-        return -ENODEV;
-      }
-
-    switch (cmd) {
-    case HDIO_GETGEO:   /* Return BIOS disk parameters */
-	if (!loc)  return -EINVAL;
-	error = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
-	if (error)
-	    return error;
-	host = rscsi_disks[DEVICE_NR(dev)].device->host;
-
-/* default to most commonly used values */
-
-        diskinfo[0] = 0x40;
-        diskinfo[1] = 0x20;
-        diskinfo[2] = rscsi_disks[DEVICE_NR(dev)].capacity >> 11;
-
-/* override with calculated, extended default, or driver values */
-
-	if(host->hostt->bios_param != NULL)
-	    host->hostt->bios_param(&rscsi_disks[DEVICE_NR(dev)],
-				    dev,
-				    &diskinfo[0]);
-        else scsicam_bios_param(&rscsi_disks[DEVICE_NR(dev)],
-				dev, &diskinfo[0]);
-
-	put_user(diskinfo[0], &loc->heads);
-	put_user(diskinfo[1], &loc->sectors);
-	put_user(diskinfo[2], &loc->cylinders);
-	put_user(sd[SD_PARTITION(inode->i_rdev)].start_sect, &loc->start);
-	return 0;
-    case BLKGETSIZE:   /* Return device size */
-	if (!arg)  return -EINVAL;
-	error = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
-	if (error)
-	    return error;
-	put_user(sd[SD_PARTITION(inode->i_rdev)].nr_sects,
-		 (long *) arg);
-	return 0;
-
-    case BLKROSET:
-    case BLKROGET:
-    case BLKRASET:
-    case BLKRAGET:
-    case BLKFLSBUF:
-    case BLKSSZGET:
-    case BLKPG:
-	return blk_ioctl(inode->i_rdev, cmd, arg);
-
-    case BLKRRPART: /* Re-read partition tables */
-        if (!capable(CAP_SYS_ADMIN))
-                return -EACCES;
-	return revalidate_scsidisk(dev, 1);
-
-    default:
-	return scsi_ioctl(rscsi_disks[DEVICE_NR(dev)].device , cmd, (void *) arg);
-    }
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/seagate.c linux/drivers/scsi/seagate.c
--- v2.3.26/linux/drivers/scsi/seagate.c	Mon Oct  4 15:49:30 1999
+++ linux/drivers/scsi/seagate.c	Thu Nov 11 16:57:30 1999
@@ -108,12 +108,6 @@
 #endif
 #define DANY( msg... ) DPRINTK( 0xffff, msg );
 
-static struct proc_dir_entry proc_scsi_seagate =
-{
-  PROC_SCSI_SEAGATE, 7, "seagate",
-  S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 #ifndef IRQ
 #define IRQ 5
 #endif
@@ -418,7 +412,7 @@
   struct Scsi_Host *instance;
   int i, j;
 
-  tpnt->proc_dir = &proc_scsi_seagate;
+  tpnt->proc_name = "seagate";
 /*
  *    First, we try for the manual override.  */
   DANY ("Autodetecting ST0x / TMC-8xx\n");
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/sgiwd93.c linux/drivers/scsi/sgiwd93.c
--- v2.3.26/linux/drivers/scsi/sgiwd93.c	Fri Oct 15 15:25:14 1999
+++ linux/drivers/scsi/sgiwd93.c	Thu Nov 11 16:57:30 1999
@@ -37,11 +37,6 @@
 	unsigned long padding;
 };
 
-struct proc_dir_entry proc_scsi_sgiwd93 = {
-	PROC_SCSI_SGIWD93, 5, "SGIWD93",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 struct Scsi_Host *sgiwd93_host = NULL;
 
 /* Wuff wuff, wuff, wd33c93.c, wuff wuff, object oriented, bow wow. */
@@ -272,7 +267,7 @@
 	if(called)
 		return 0; /* Should bitch on the console about this... */
 
-	HPsUX->proc_dir = &proc_scsi_sgiwd93;
+	HPsUX->proc_name = "SGIWD93";
 
 	sgiwd93_host = scsi_register(HPsUX, sizeof(struct WD33C93_hostdata));
 	sgiwd93_host->base = (unsigned char *) hregs;
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/sgiwd93.h linux/drivers/scsi/sgiwd93.h
--- v2.3.26/linux/drivers/scsi/sgiwd93.h	Fri Oct 15 15:25:14 1999
+++ linux/drivers/scsi/sgiwd93.h	Thu Nov 11 16:57:30 1999
@@ -25,9 +25,7 @@
 int wd33c93_abort(Scsi_Cmnd *);
 int wd33c93_reset(Scsi_Cmnd *, unsigned int);
 
-extern struct proc_dir_entry proc_scsi_sgiwd93;
-
-#define SGIWD93_SCSI {proc_dir:		   &proc_scsi_sgiwd93, \
+#define SGIWD93_SCSI {proc_name:	   "SGIWD93", \
 		      name:                "SGI WD93", \
 		      detect:              sgiwd93_detect,    \
 		      release:             sgiwd93_release,   \
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/sim710.c linux/drivers/scsi/sim710.c
--- v2.3.26/linux/drivers/scsi/sim710.c	Sat Oct  9 11:47:50 1999
+++ linux/drivers/scsi/sim710.c	Thu Nov 11 16:57:30 1999
@@ -172,12 +172,6 @@
 #define offsetof(t, m)      ((size_t) (&((t *)0)->m))
 #endif
 
-
-struct proc_dir_entry proc_scsi_sim710 = {
-    PROC_SCSI_SIM710, 6, "sim710",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 #define STATE_INITIALISED	0
 #define STATE_HALTED		1
 #define STATE_IDLE		2
@@ -1441,7 +1435,7 @@
     DEB(DEB_ANY, printk("sim710: hostdata %d bytes, size %d, order %d\n",
 	sizeof(struct sim710_hostdata), size, order));
 
-    tpnt->proc_dir = &proc_scsi_sim710;
+    tpnt->proc_name = "sim710";
 
     for(indx = 0; indx < no_of_boards; indx++) {
 	host = scsi_register(tpnt, 4);
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/sim710.h linux/drivers/scsi/sim710.h
--- v2.3.26/linux/drivers/scsi/sim710.h	Sat Oct  9 11:47:50 1999
+++ linux/drivers/scsi/sim710.h	Thu Nov 11 16:57:30 1999
@@ -24,9 +24,7 @@
 #if defined(HOSTS_C) || defined(MODULE)
 #include <scsi/scsicam.h>
 
-extern struct proc_dir_entry proc_scsi_sim710;
-
-#define SIM710_SCSI { proc_dir:			&proc_scsi_sim710,	\
+#define SIM710_SCSI { proc_name:		"sim710",	\
 		      name:			"Simple 53c710", 	\
 		      detect:			sim710_detect,		\
 		      release:			sim710_release,		\
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/sun3_scsi.c linux/drivers/scsi/sun3_scsi.c
--- v2.3.26/linux/drivers/scsi/sun3_scsi.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sun3_scsi.c	Thu Nov 11 16:57:30 1999
@@ -0,0 +1,416 @@
+/*
+ * 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 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_name = "Sun3 5380 SCSI"; /* Could you spell "ewww..."? */
+
+	/* 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 -u --recursive --new-file v2.3.26/linux/drivers/scsi/sun3_scsi.h linux/drivers/scsi/sun3_scsi.h
--- v2.3.26/linux/drivers/scsi/sun3_scsi.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sun3_scsi.h	Mon Nov  8 11:03:21 1999
@@ -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 -u --recursive --new-file v2.3.26/linux/drivers/scsi/sun3x_esp.h linux/drivers/scsi/sun3x_esp.h
--- v2.3.26/linux/drivers/scsi/sun3x_esp.h	Thu Aug 12 10:28:34 1999
+++ linux/drivers/scsi/sun3x_esp.h	Thu Nov 11 16:57:30 1999
@@ -18,12 +18,10 @@
 extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
 			 int hostno, int inout);
 
-extern struct proc_dir_entry proc_scsi_esp;
-
 #define DMA_PORTS_P        (dregs->cond_reg & DMA_INT_ENAB)
 
 #define SCSI_SUN3X_ESP {                                        \
-		proc_dir:       &proc_scsi_esp,			\
+		proc_name:      "esp",  			\
 		proc_info:      &esp_proc_info,			\
 		name:           "Sun ESP 100/100a/200",		\
 		detect:         sun3x_esp_detect,		\
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/sym53c416.c linux/drivers/scsi/sym53c416.c
--- v2.3.26/linux/drivers/scsi/sym53c416.c	Fri Sep 10 23:57:32 1999
+++ linux/drivers/scsi/sym53c416.c	Thu Nov 11 16:57:30 1999
@@ -170,7 +170,7 @@
 #define PIO_MODE                  0x80
 
 #define IO_RANGE 0x20         /* 0x00 - 0x1F                   */
-#define ID       "sym53c416"
+#define ID       "sym53c416"	/* Attention: copied to the sym53c416.h */
 #define PIO_SIZE 128          /* Size of PIO fifo is 128 bytes */
 
 #define READ_TIMEOUT              150
@@ -237,8 +237,6 @@
 
 static Scsi_Cmnd *current_command = NULL;
 
-struct proc_dir_entry proc_scsi_sym53c416 = {PROC_SCSI_SYM53C416, 7, ID, S_IFDIR | S_IRUGO | S_IXUGO, 2};
-
 int fastpio = 1;
 
 int probeaddrs[] = {0x200, 0x220, 0x240, 0};
@@ -809,13 +807,11 @@
 /* Loadable module support */
 #ifdef MODULE
 
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,26)
 MODULE_AUTHOR("Lieven Willems");
 MODULE_PARM(sym53c416, "1-2i");
 MODULE_PARM(sym53c416_1, "1-2i");
 MODULE_PARM(sym53c416_2, "1-2i");
 MODULE_PARM(sym53c416_3, "1-2i");
-#endif
 
 Scsi_Host_Template driver_template = SYM53C416;
 
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/sym53c416.h linux/drivers/scsi/sym53c416.h
--- v2.3.26/linux/drivers/scsi/sym53c416.h	Wed Aug 18 16:44:23 1999
+++ linux/drivers/scsi/sym53c416.h	Thu Nov 11 17:03:48 1999
@@ -29,8 +29,6 @@
 
 #define SYM53C416_SCSI_ID 7
 
-extern struct proc_dir_entry proc_scsi_sym53c416;
-
 extern int sym53c416_detect(Scsi_Host_Template *);
 extern const char *sym53c416_info(struct Scsi_Host *);
 extern int sym53c416_command(Scsi_Cmnd *);
@@ -40,10 +38,8 @@
 extern int sym53c416_bios_param(Disk *, kdev_t, int *);
 extern void sym53c416_setup(char *str, int *ints);
 
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,75)
-
 #define SYM53C416 {                                          \
-                  proc_dir:          &proc_scsi_sym53c416,   \
+                  proc_name:         "sym53c416",   \
                   name:              "Symbios Logic 53c416", \
                   detect:            sym53c416_detect,       \
                   info:              sym53c416_info,         \
@@ -59,33 +55,4 @@
                   unchecked_isa_dma: 1,                      \
                   use_clustering:    ENABLE_CLUSTERING       \
                   }
-
-#else
-
-#define SYM53C416 {                       \
-                  NULL,                   \
-                  NULL,                   \
-                  &proc_scsi_sym53c416,   \
-                  NULL,                   \
-                  "Symbios Logic 53c416", \
-                  sym53c416_detect,       \
-                  NULL,                   \
-                  sym53c416_info,         \
-                  sym53c416_command,      \
-                  sym53c416_queuecommand, \
-                  sym53c416_abort,        \
-                  sym53c416_reset,        \
-                  NULL,                   \
-                  sym53c416_bios_param,   \
-                  1,                      \
-                  SYM53C416_SCSI_ID,      \
-                  32, /* ???? */          \
-                  1,                      \
-                  0,                      \
-                  1,                      \
-                  ENABLE_CLUSTERING       \
-                  }
-
-#endif
-
 #endif
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/sym53c8xx.c linux/drivers/scsi/sym53c8xx.c
--- v2.3.26/linux/drivers/scsi/sym53c8xx.c	Fri Oct 15 15:25:14 1999
+++ linux/drivers/scsi/sym53c8xx.c	Thu Nov 11 16:57:30 1999
@@ -635,9 +635,9 @@
 #endif
 
 #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,0)
-#define get_pages(order) __get_free_pages(GFP_ATOMIC | GFP_DMA_32BIT, order)
+#define sym53c8xx_get_pages(order) __get_free_pages(GFP_ATOMIC | GFP_DMA_32BIT, order)
 #else
-#define get_pages(order) __get_free_pages(GFP_ATOMIC | GFP_DMA_32BIT, order, 0)
+#define sym53c8xx_get_pages(order) __get_free_pages(GFP_ATOMIC | GFP_DMA_32BIT, order, 0)
 #endif
 
 /*
@@ -668,7 +668,7 @@
 	j = i;
 	while (!h[j].next) {
 		if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {
-			h[j].next = (struct m_link *)get_pages(MEMO_PAGE_ORDER);
+			h[j].next = (struct m_link *)sym53c8xx_get_pages(MEMO_PAGE_ORDER);
 			if (h[j].next)
 				h[j].next->next = 0;
 			break;
@@ -828,10 +828,6 @@
 **	/proc directory entry and proc_info function
 */
 
-static struct proc_dir_entry proc_scsi_sym53c8xx = {
-    PROC_SCSI_SYM53C8XX, 9, NAME53C8XX,
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
 #ifdef SCSI_NCR_PROC_INFO_SUPPORT
 static int sym53c8xx_proc_info(char *buffer, char **start, off_t offset,
 			int length, int hostno, int func);
@@ -11382,7 +11378,7 @@
 	**    Initialize driver general stuff.
 	*/
 #ifdef SCSI_NCR_PROC_INFO_SUPPORT
-     tpnt->proc_dir  = &proc_scsi_sym53c8xx;
+     tpnt->proc_name  = NAME53C8XX;
      tpnt->proc_info = sym53c8xx_proc_info;
 #endif
 
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/t128.c linux/drivers/scsi/t128.c
--- v2.3.26/linux/drivers/scsi/t128.c	Mon Aug  9 10:25:01 1999
+++ linux/drivers/scsi/t128.c	Thu Nov 11 16:57:31 1999
@@ -121,12 +121,6 @@
 #include <linux/stat.h>
 #include <linux/init.h>
 
-struct proc_dir_entry proc_scsi_t128 = {
-    PROC_SCSI_T128, 4, "t128",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
-
 static struct override {
     unsigned char *address;
     int irq;
@@ -205,7 +199,7 @@
     unsigned char *base;
     int sig, count;
 
-    tpnt->proc_dir = &proc_scsi_t128;
+    tpnt->proc_name = "t128";
     tpnt->proc_info = &t128_proc_info;
 
     for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/tmscsim.c linux/drivers/scsi/tmscsim.c
--- v2.3.26/linux/drivers/scsi/tmscsim.c	Fri Sep 10 23:57:35 1999
+++ linux/drivers/scsi/tmscsim.c	Thu Nov 11 16:57:31 1999
@@ -482,12 +482,6 @@
 UCHAR  dc390_eepromBuf[MAX_ADAPTER_NUM][EE_LEN];
 UCHAR  dc390_clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20};
 
-struct proc_dir_entry	DC390_proc_scsi_tmscsim ={
-       PROC_SCSI_DC390T, 7 ,"tmscsim",
-       S_IFDIR | S_IRUGO | S_IXUGO, 2
-       };
-
-
 /***********************************************************************
  * Functions for access to DC390 EEPROM
  * and some to emulate it
@@ -2024,7 +2018,7 @@
 	printk (KERN_ERR "DC390: No PCI BIOS found!\n");
    
     if (dc390_adapterCnt)
-	psht->proc_dir = &DC390_proc_scsi_tmscsim;
+	psht->proc_name = "tmscsim";
 
     printk(KERN_INFO "DC390: %i adapters found\n", dc390_adapterCnt);
     DC390_UNLOCK_DRV;
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c
--- v2.3.26/linux/drivers/scsi/u14-34f.c	Mon Oct  4 15:49:30 1999
+++ linux/drivers/scsi/u14-34f.c	Thu Nov 11 16:57:31 1999
@@ -374,11 +374,6 @@
 #define SPIN_UNLOCK_RESTORE \
                   spin_unlock_irqrestore(&io_request_lock, spin_flags);
 
-struct proc_dir_entry proc_scsi_u14_34f = {
-    PROC_SCSI_U14_34F, 6, "u14_34f",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 /* Values for the PRODUCT_ID ports for the 14/34F */
 #define PRODUCT_ID1  0x56
 #define PRODUCT_ID2  0x40        /* NOTE: Only upper nibble is used */
@@ -955,7 +950,7 @@
 {
    unsigned int j = 0, k;
 
-   tpnt->proc_dir = &proc_scsi_u14_34f;
+   tpnt->proc_name = "u14-34f";
 
    if(boot_options) option_setup(boot_options);
 
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/ultrastor.c linux/drivers/scsi/ultrastor.c
--- v2.3.26/linux/drivers/scsi/ultrastor.c	Fri Sep 10 23:57:35 1999
+++ linux/drivers/scsi/ultrastor.c	Thu Nov 11 16:57:31 1999
@@ -148,11 +148,6 @@
 #include "sd.h"
 #include<linux/stat.h>
 
-struct proc_dir_entry proc_scsi_ultrastor = {
-    PROC_SCSI_ULTRASTOR, 9, "ultrastor",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
 #define FALSE 0
 #define TRUE 1
 
@@ -631,7 +626,7 @@
 
 int ultrastor_detect(Scsi_Host_Template * tpnt)
 {
-    tpnt->proc_dir = &proc_scsi_ultrastor;
+    tpnt->proc_name = "ultrastor";
   return ultrastor_14f_detect(tpnt) || ultrastor_24f_detect(tpnt);
 }
 
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/wd7000.c linux/drivers/scsi/wd7000.c
--- v2.3.26/linux/drivers/scsi/wd7000.c	Fri Sep 10 23:57:35 1999
+++ linux/drivers/scsi/wd7000.c	Thu Nov 11 16:57:31 1999
@@ -171,17 +171,6 @@
 #include "wd7000.h"
 #include <linux/stat.h>
 
-
-struct proc_dir_entry proc_scsi_wd7000 =
-{
-    PROC_SCSI_7000FASST,
-    6,
-    "wd7000",
-    S_IFDIR | S_IRUGO | S_IXUGO,
-    2
-};
-
-
 /*
  *  Mailbox structure sizes.
  *  I prefer to keep the number of ICMBs much larger than the number of
@@ -1542,7 +1531,7 @@
     for (i = 0; i < IRQS; wd7000_host[i++] = NULL) ;
     for (i = 0; i < NUM_CONFIGS; biosptr[i++] = -1) ;
 
-    tpnt->proc_dir = &proc_scsi_wd7000;
+    tpnt->proc_name = "wd7000";
     tpnt->proc_info = &wd7000_proc_info;
 
     /*
diff -u --recursive --new-file v2.3.26/linux/drivers/scsi/wd7000.h linux/drivers/scsi/wd7000.h
--- v2.3.26/linux/drivers/scsi/wd7000.h	Sun Dec 27 22:19:19 1998
+++ linux/drivers/scsi/wd7000.h	Thu Nov 11 16:57:31 1999
@@ -14,9 +14,6 @@
 #include <linux/types.h>
 #include <linux/kdev_t.h>
 
-extern struct proc_dir_entry proc_scsi_wd7000;
-
-
 int wd7000_set_info (char *buffer, int length, struct Scsi_Host *host);
 int wd7000_proc_info (char *buffer, char **start, off_t offset, int length, int hostno, int inout);
 int wd7000_detect (Scsi_Host_Template *);
@@ -45,7 +42,7 @@
 #define WD7000_SG   16
 
 #define WD7000 {						\
-	proc_dir:		&proc_scsi_wd7000,		\
+	proc_name:		"wd7000",			\
 	proc_info:		wd7000_proc_info,		\
 	name:			"Western Digital WD-7000",	\
 	detect:			wd7000_detect,			\
diff -u --recursive --new-file v2.3.26/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c
--- v2.3.26/linux/drivers/sound/sb_card.c	Mon Oct  4 15:49:30 1999
+++ linux/drivers/sound/sb_card.c	Wed Nov 10 19:54:58 1999
@@ -16,6 +16,8 @@
 #include <linux/mca.h>
 #endif
 #include <linux/module.h>
+#include <linux/init.h>
+#include <linux/isapnp.h>
 
 #include "sound_config.h"
 #include "soundmodule.h"
@@ -138,6 +140,7 @@
 int support = 0;	/* Set support to load this as a support module */
 int sm_games = 0;	/* Mixer - see sb_mixer.c */
 int acer = 0;		/* Do acer notebook init */
+int isapnp = 0;
 
 MODULE_PARM(io, "i");
 MODULE_PARM(irq, "i");
@@ -151,24 +154,91 @@
 MODULE_PARM(pas2, "i");
 MODULE_PARM(sm_games, "i");
 MODULE_PARM(esstype, "i");
+MODULE_PARM(isapnp, "i");
 
 void *smw_free = NULL;
 
+static struct { unsigned short vendor, function; char *name; }
+isapnp_sb_list[] __initdata = {
+	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), "Sound Blaster 16" },
+	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), "Sound Blaster 16" },
+	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), "Sound Blaster 16" },
+	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), "Sound Blaster 16" },
+	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043), "Sound Blaster 16" },
+	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044), "Sound Blaster 16" },
+	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), "Sound Blaster 16" },
+	{ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868), "ESS 1868" },
+	{ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611), "ESS 1868" },
+	{ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869), "ESS 1869" },
+	{ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878), "ESS 1878" },
+	{ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879), "ESS 1879" },
+	{0,}
+};
+
+
+static int __init sb_probe_isapnp(struct address_info *hw_config, struct address_info *mpu_config) {
+	int i;
+	
+	for (i = 0; isapnp_sb_list[i].vendor != 0; i++) {
+		struct pci_dev *idev = NULL;
+			
+		while ((idev = isapnp_find_dev(NULL,
+					       isapnp_sb_list[i].vendor,
+					       isapnp_sb_list[i].function,
+					       idev))) {
+			idev->prepare(idev);
+			idev->activate(idev);
+			if (!idev->resource[0].start || check_region(idev->resource[0].start,16))
+			  continue;
+			hw_config->io_base = idev->resource[0].start;
+			hw_config->irq = idev->irq_resource[0].start;
+			hw_config->dma = idev->dma_resource[0].start;
+			hw_config->dma2 = idev->dma_resource[1].start;
+#ifdef CONFIG_MIDI
+			if (isapnp_sb_list[i].vendor == ISAPNP_VENDOR('E','S','S'))
+			  mpu_config->io_base = idev->resource[2].start;
+			else
+			  mpu_config->io_base = idev->resource[1].start;
+#endif
+			break;
+		}
+		if (!idev)
+		  continue;
+		printk(KERN_INFO "ISAPnP reports %s at i/o %#x, irq %d, dma %d, %d\n",
+		       isapnp_sb_list[i].name,
+		       hw_config->io_base, hw_config->irq, hw_config->dma,
+		       hw_config->dma2);
+		return 0;
+	}
+	return -ENODEV;
+}
+
 int init_module(void)
 {
 	printk(KERN_INFO "Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
 
 	if (mad16 == 0 && trix == 0 && pas2 == 0 && support == 0)
 	{
-		if (io == -1 || dma == -1 || irq == -1)
+		if (isapnp == 1)
+		{
+			if (sb_probe_isapnp(&config, &config_mpu)<0)
+			{
+				printk(KERN_ERR "sb_card: No ISAPnP cards found\n");
+				return -EINVAL;
+			}
+		} 
+		else 
 		{
-			printk(KERN_ERR "sb_card: I/O, IRQ, and DMA are mandatory\n");
-			return -EINVAL;
+			if (io == -1 || dma == -1 || irq == -1)
+			{
+				printk(KERN_ERR "sb_card: I/O, IRQ, and DMA are mandatory\n");
+				return -EINVAL;
+			}
+			config.io_base = io;
+			config.irq = irq;
+			config.dma = dma;
+			config.dma2 = dma16;
 		}
-		config.io_base = io;
-		config.irq = irq;
-		config.dma = dma;
-		config.dma2 = dma16;
 		config.card_subtype = type;
 
 		if (!probe_sb(&config))
@@ -178,7 +248,8 @@
 		if(config.slots[0]==-1)
 			return -ENODEV;
 #ifdef CONFIG_MIDI
-		config_mpu.io_base = mpu_io;
+		if (isapnp == 0) 
+		  config_mpu.io_base = mpu_io;
 		if (probe_sbmpu(&config_mpu))
 			sbmpu = 1;
 		if (sbmpu)
diff -u --recursive --new-file v2.3.26/linux/drivers/usb/Makefile linux/drivers/usb/Makefile
--- v2.3.26/linux/drivers/usb/Makefile	Sun Nov  7 16:37:34 1999
+++ linux/drivers/usb/Makefile	Wed Nov 10 09:49:51 1999
@@ -37,7 +37,7 @@
 
 ifeq ($(CONFIG_USB_UHCI),m)
       M_OBJS += usb-uhci.o
-    MIX_OBJS += uhci.o uhci-debug.o
+      MI_OBJS += uhci.o uhci-debug.o
 endif
 
 ifeq ($(CONFIG_USB_OHCI),y)
@@ -45,7 +45,7 @@
 endif
 ifeq ($(CONFIG_USB_OHCI),m)
       M_OBJS += usb-ohci.o
-      MIX_OBJS += ohci.o ohci-debug.o
+      MI_OBJS += ohci.o ohci-debug.o
 endif
 
 ifeq ($(CONFIG_USB_OHCI_HCD),y)
@@ -53,7 +53,7 @@
 endif
 ifeq ($(CONFIG_USB_OHCI_HCD),m)
       M_OBJS += usb-ohci-hcd.o
-      MIX_OBJS += ohci-hcd.o ohci-root-hub.o
+      MI_OBJS += ohci-hcd.o ohci-root-hub.o
 endif
 
 ifeq ($(CONFIG_USB_MOUSE),y)
@@ -61,7 +61,7 @@
 endif
 ifeq ($(CONFIG_USB_MOUSE),m)
   M_OBJS += mouse.o	
-  MIX_OBJS += mouse.o
+  MI_OBJS += mouse.o
 endif
 
 ifeq ($(CONFIG_USB_HP_SCANNER),y)
@@ -69,7 +69,7 @@
 endif
 ifeq ($(CONFIG_USB_HP_SCANNER),m)
   M_OBJS  +=hp_scanner.o
-  MIX_OBJS +=hp_scanner.o
+  MI_OBJS +=hp_scanner.o
 endif
 
 ifeq ($(CONFIG_USB_HUB),y)
@@ -77,7 +77,7 @@
 endif
 ifeq ($(CONFIG_USB_HUB),m)
   M_OBJS += hub.o
-  MIX_OBJS += hub.o	
+  MI_OBJS += hub.o	
 endif
 
 ifeq ($(CONFIG_USB_ACM),y)
@@ -85,7 +85,7 @@
 endif
 ifeq ($(CONFIG_USB_ACM),m)
   M_OBJS += acm.o
-  MIX_OBJS += acm.o
+  MI_OBJS += acm.o
 endif
 
 ifeq ($(CONFIG_USB_PRINTER),y)
@@ -94,7 +94,7 @@
 
 ifeq ($(CONFIG_USB_PRINTER),m)
   M_OBJS += printer.o
-  MIX_OBJS += printer.o  
+  MI_OBJS += printer.o  
 endif
 
 ifeq ($(CONFIG_USB_SERIAL),y)
@@ -103,7 +103,7 @@
 
 ifeq ($(CONFIG_USB_SERIAL),m)
   M_OBJS += usb-serial.o
-  MIX_OBJS += usb-serial.o  
+  MI_OBJS += usb-serial.o  
 endif
 
 ifneq ($(CONFIG_ADB_KEYBOARD),y)
@@ -118,7 +118,7 @@
 
 ifeq ($(CONFIG_USB_KBD),m)
   M_OBJS += usb-keyboard.o
-  MIX_OBJS += keyboard.o $(KEYMAP).o
+  MI_OBJS += keyboard.o $(KEYMAP).o
 endif
 
 ifeq ($(CONFIG_USB_AUDIO),y)
@@ -127,7 +127,7 @@
 
 ifeq ($(CONFIG_USB_AUDIO),m)
   M_OBJS += audio.o
-  MIX_OBJS += audio.o
+  MI_OBJS += audio.o
 endif
 
 ifeq ($(CONFIG_USB_CPIA),y)
@@ -136,7 +136,7 @@
 
 ifeq ($(CONFIG_USB_CPIA),m)
   M_OBJS += cpia.o
-  MIX_OBJS += cpia.o
+  MI_OBJS += cpia.o
 endif
 
 ifeq ($(CONFIG_USB_DC2XX),y)
@@ -144,7 +144,7 @@
 endif
 ifeq ($(CONFIG_USB_DC2XX),m)
   M_OBJS += dc2xx.o
-  MIX_OBJS += dc2xx.o
+  MI_OBJS += dc2xx.o
 endif
 
 ifeq ($(CONFIG_USB_SCSI),y)
@@ -156,9 +156,9 @@
 
 ifeq ($(CONFIG_USB_SCSI),m)
   M_OBJS += usb-scsi.o
-  MIX_OBJS += usb_scsi.o
+  MI_OBJS += usb_scsi.o
   ifeq ($(CONFIG_USB_SCSI_DEBUG),y)
-    MIX_OBJS += usb_scsi_debug.o
+    MI_OBJS += usb_scsi_debug.o
   endif
 endif
 
@@ -168,7 +168,7 @@
 
 ifeq ($(CONFIG_USB_EZUSB),m)
   M_OBJS += ezusb.o
-  MIX_OBJS += ezusb.o
+  MI_OBJS += ezusb.o
 endif
 
 ifeq ($(CONFIG_USB_USS720),y)
@@ -177,7 +177,7 @@
 
 ifeq ($(CONFIG_USB_USS720),m)
   M_OBJS += uss720.o
-  MIX_OBJS += uss720.o
+  MI_OBJS += uss720.o
 endif
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.26/linux/drivers/usb/README.serial linux/drivers/usb/README.serial
--- v2.3.26/linux/drivers/usb/README.serial	Sat Oct  9 11:47:50 1999
+++ linux/drivers/usb/README.serial	Wed Nov 10 08:32:53 1999
@@ -3,14 +3,23 @@
 not know the vendor id, and device id of that device (if anyone does, 
 please let me know.)
 
+If your device is not compatible with the above models, you can try
+out the "generic" interface. This interface does not provide any type
+of control messages sent to the device, and does not support any kind
+of device flow control. All that is required of your device is that
+it has at least one bulk in endpoint, or one bulk out endpoint.
+To enable the driver to recognize your device, build the driver as
+a module and load it by the following invocation:
+	insmod usb-serial.o vendor=0x#### product=0x####
+where the #### is replaced with the hex representation of your device's
+vendor id and product id.
+
 The driver can handle enumerating the device, and sending and receiving
-data from the converter. However, since I do not have a spec for this
-device, and the raw dumps from the Win98 driver are confusing, no control
-signals are handled, and the data will most likely come through on a baud
+data from the converter. However, since I do not have a spec for the Belkin,
+Peracom, and eTek devices, and the raw dumps from the Win98 driver are 
+confusing, and eTek keeps giving me the run around, no control signals are 
+currently handled, and the data will most likely come through on a baud
 rate that you are not expecting.
-
-But I am working on figuring the control settings out. This release is to
-let others try it out, and give some feedback.
 
 The major number that the driver uses is 240 (in the local/experimental
 range.) It will stay there until some agreements are reached on how to
diff -u --recursive --new-file v2.3.26/linux/drivers/usb/proc_usb.c linux/drivers/usb/proc_usb.c
--- v2.3.26/linux/drivers/usb/proc_usb.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/usb/proc_usb.c	Thu Nov 11 10:35:19 1999
@@ -119,6 +119,7 @@
 	{USB_CLASS_HUB,			"hub"},
 	{USB_CLASS_PRINTER,		"print"},
 	{USB_CLASS_MASS_STORAGE,	"stor."},
+	{USB_CLASS_DATA,		"data"},
 	{USB_CLASS_VENDOR_SPEC,		"vend."},
 	{-1,				"unk."}		/* leave as last */
 };
diff -u --recursive --new-file v2.3.26/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c
--- v2.3.26/linux/drivers/usb/uhci.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/usb/uhci.c	Mon Nov  8 12:04:40 1999
@@ -156,7 +156,7 @@
 			if (rval)
 				*rval += actlength;
 
-			if (explength != actlength) {
+			if (explength != actlength && tmp->pipetype == PIPE_BULK) {
 				/* If the packet is short, none of the */
 				/*  packets after this were processed, so */
 				/*  fix the DT accordingly */
diff -u --recursive --new-file v2.3.26/linux/drivers/usb/usb-serial.c linux/drivers/usb/usb-serial.c
--- v2.3.26/linux/drivers/usb/usb-serial.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/usb/usb-serial.c	Wed Nov 10 08:32:53 1999
@@ -1,32 +1,41 @@
 /*
  * USB Serial Converter driver
  *
- * Greg Kroah-Hartman (greg@kroah.com)
+ *	(C) Copyright (C) 1999
+ *	    Greg Kroah-Hartman (greg@kroah.com)
  *
- * This was based on the ACM driver by Armin Fuerst (which was based
- * on a driver by Brad Keryan)
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
  *
- * Currently only works for the Belkin and Peracom Serial converters.
- * Should also work on the Etek serial converter, if anyone knows the
- * vendor and device ids for that device.
+ * This driver was originally based on the ACM driver by Armin Fuerst (which was 
+ * based on a driver by Brad Keryan)
  *
+ * See README.serial for more information on using this driver.
  * 
+ * version 0.2.0 (11/10/99) gkh
+ *	Split up internals to make it easier to add different types of serial 
+ *	converters to the code.
+ *	Added a "generic" driver that gets it's vendor and product id
+ *	from when the module is loaded. Thanks to David E. Nelson (dnelson@jump.net)
+ *	for the idea and sample code (from the usb scanner driver.)
+ *	Cleared up any licensing questions by releasing it under the GNU GPL.
+ *
  * version 0.1.2 (10/25/99) gkh
- *  Fixed bug in detecting device.
+ * 	Fixed bug in detecting device.
  *
  * version 0.1.1 (10/05/99) gkh
- *  Changed the major number to not conflict with anything else.
+ * 	Changed the major number to not conflict with anything else.
  *
  * version 0.1 (09/28/99) gkh
- *  Can recognize the two different devices and start up a read from
- * device when asked to. Writes also work. No control signals yet, this
- * all is vendor specific data (i.e. no spec), also no control for
- * different baud rates or other bit settings.
- * Currently we are using the same devid as the acm driver. This needs
- * to change.
+ * 	Can recognize the two different devices and start up a read from
+ *	device when asked to. Writes also work. No control signals yet, this
+ *	all is vendor specific data (i.e. no spec), also no control for
+ *	different baud rates or other bit settings.
+ *	Currently we are using the same devid as the acm driver. This needs
+ *	to change.
  * 
- * (C) Copyright 1999 Greg Kroah-Hartman (greg@kroah.com)
- *
  */
 
 #include <linux/kernel.h>
@@ -43,8 +52,8 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 
-
 #include "usb.h"
+
 /*#define SERIAL_DEBUG 1*/
 
 #ifdef SERIAL_DEBUG
@@ -54,6 +63,19 @@
 #endif
 
 
+/* Module information */
+MODULE_AUTHOR("Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/");
+MODULE_DESCRIPTION("USB Serial Driver");
+
+static __u16	vendor	= 0;
+static __u16	product	= 0;
+MODULE_PARM(vendor, "i");
+MODULE_PARM_DESC(vendor, "User specified USB idVendor");
+
+MODULE_PARM(product, "i");
+MODULE_PARM_DESC(product, "User specified USB idProduct");
+
+
 /* USB Serial devices vendor ids and device ids that this driver supports */
 #define BELKIN_VENDOR_ID		0x056c
 #define BELKIN_SERIAL_CONVERTER		0x8007
@@ -70,41 +92,171 @@
 static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum);
 static void usb_serial_disconnect(struct usb_device *dev, void *ptr);
 
-typedef enum {
-	unknown = 0,
-	Belkin = 1,
-	Peracom = 2
-	} SERIAL_TYPE;
+
+#define MUST_HAVE_NOT	0x01
+#define MUST_HAVE	0x02
+#define DONT_CARE	0x03
+
+#define	HAS		0x02
+#define HAS_NOT		0x01
+
+
+/* local function prototypes */
+static int serial_open (struct tty_struct *tty, struct file * filp);
+static void serial_close (struct tty_struct *tty, struct file * filp);
+static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
+static void serial_put_char (struct tty_struct *tty, unsigned char ch);
+static int serial_write_room (struct tty_struct *tty);
+static int serial_chars_in_buffer (struct tty_struct *tty);
+static void serial_throttle (struct tty_struct * tty);
+static void serial_unthrottle (struct tty_struct * tty);
+
+
+/* function prototypes for the eTek type converters (this included Belkin and Peracom) */
+static int etek_serial_open (struct tty_struct *tty, struct file * filp);
+static void etek_serial_close (struct tty_struct *tty, struct file * filp);
+static int etek_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
+static void etek_serial_put_char (struct tty_struct *tty, unsigned char ch);
+static int etek_write_room (struct tty_struct *tty);
+static int etek_chars_in_buffer (struct tty_struct *tty);
+static void etek_throttle (struct tty_struct * tty);
+static void etek_unthrottle (struct tty_struct * tty);
+
+
+/* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */
+static int generic_serial_open (struct tty_struct *tty, struct file * filp);
+static void generic_serial_close (struct tty_struct *tty, struct file * filp);
+static int generic_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
+static void generic_serial_put_char (struct tty_struct *tty, unsigned char ch);
+static int generic_write_room (struct tty_struct *tty);
+static int generic_chars_in_buffer (struct tty_struct *tty);
+
+
+/* This structure defines the individual serial converter. */
+struct usb_serial_device_type {
+	char	*name;
+	__u16	*idVendor;
+	__u16	*idProduct;
+	char	needs_interrupt_in;
+	char	needs_bulk_in;
+	char	needs_bulk_out;
+	// add function calls
+
+	int  (*open)(struct tty_struct * tty, struct file * filp);
+	void (*close)(struct tty_struct * tty, struct file * filp);
+	int  (*write)(struct tty_struct * tty, int from_user,const unsigned char *buf, int count);
+	void (*put_char)(struct tty_struct *tty, unsigned char ch);
+	int  (*write_room)(struct tty_struct *tty);
+	int  (*chars_in_buffer)(struct tty_struct *tty);
+	void (*throttle)(struct tty_struct * tty);
+	void (*unthrottle)(struct tty_struct * tty);
+
+};
+
+
+/* All of the device info needed for the Belkin Serial Converter */
+static __u16	belkin_vendor_id	= BELKIN_VENDOR_ID;
+static __u16	belkin_product_id	= BELKIN_SERIAL_CONVERTER;
+static struct usb_serial_device_type belkin_device = {
+	"Belkin",
+	&belkin_vendor_id,	/* the Belkin vendor id */
+	&belkin_product_id,	/* the Belkin serial converter product id */
+	MUST_HAVE,		/* this device must have an interrupt in endpoint */
+	MUST_HAVE,		/* this device must have a bulk in endpoint */
+	MUST_HAVE,		/* this device must have a bulk out endpoint */
+	etek_serial_open,
+	etek_serial_close,
+	etek_serial_write,
+	etek_serial_put_char,
+	etek_write_room,
+	etek_chars_in_buffer,
+	etek_throttle,
+	etek_unthrottle
+};
+
+/* All of the device info needed for the Peracom Serial Converter */
+static __u16	peracom_vendor_id	= PERACOM_VENDOR_ID;
+static __u16	peracom_product_id	= PERACOM_SERIAL_CONVERTER;
+static struct usb_serial_device_type peracom_device = {
+	"Peracom",
+	&peracom_vendor_id,	/* the Peracom vendor id */
+	&peracom_product_id,	/* the Peracom serial converter product id */
+	MUST_HAVE,		/* this device must have an interrupt in endpoint */
+	MUST_HAVE,		/* this device must have a bulk in endpoint */
+	MUST_HAVE,		/* this device must have a bulk out endpoint */
+	etek_serial_open,
+	etek_serial_close,
+	etek_serial_write,
+	etek_serial_put_char,
+	etek_write_room,
+	etek_chars_in_buffer,
+	etek_throttle,
+	etek_unthrottle
+};
+
+/* All of the device info needed for the Generic Serial Converter */
+static struct usb_serial_device_type generic_device = {
+	"Generic",
+	&vendor,		/* use the user specified vendor id */
+	&product,		/* use the user specified product id */
+	DONT_CARE,		/* don't have to have an interrupt in endpoint */
+	DONT_CARE,		/* don't have to have a bulk in endpoint */
+	DONT_CARE,		/* don't have to have a bulk out endpoint */
+	generic_serial_open,
+	generic_serial_close,
+	generic_serial_write,
+	generic_serial_put_char,
+	generic_write_room,
+	generic_chars_in_buffer,
+	NULL,			/* generic driver does not implement any flow control */
+	NULL			/* generic driver does not implement any flow control */
+};
+
+
+/* To add support for another serial converter, create a usb_serial_device_type
+   structure for that device, and add it to this list, making sure that the last
+   entry is NULL. */
+static struct usb_serial_device_type *usb_serial_devices[] = {
+	&generic_device,
+	&belkin_device,
+	&peracom_device,
+	NULL
+};
+
+
 
 struct usb_serial_state {
-	struct usb_device *	dev;
-	SERIAL_TYPE		type;		/* what manufacturer's type of converter */
-	void *			irq_handle;
-	unsigned int		irqpipe;
-	struct tty_struct	*tty;		/* the coresponding tty for this device */
-	char			present;
-	char			active;
+	struct usb_device *		dev;
+	struct usb_serial_device_type *	type;
+	void *				irq_handle;
+	unsigned int			irqpipe;
+	struct tty_struct *		tty;		/* the coresponding tty for this device */
+	char				present;
+	char				active;
 
-	char			interrupt_in_inuse;
+	char			has_interrupt_in;	/* if this device has an interrupt in pipe or not */
+	char			interrupt_in_inuse;	/* if the interrupt in endpoint is in use */
 	__u8			interrupt_in_endpoint;
 	__u8			interrupt_in_interval;
-	__u16			interrupt_in_size;
+	__u16			interrupt_in_size;	/* the size of the interrupt in endpoint */
 	unsigned int		interrupt_in_pipe;
 	unsigned char *		interrupt_in_buffer;
 	void *			interrupt_in_transfer;
 
-	char			bulk_in_inuse;
+	char			has_bulk_in;		/* if thie device has a bulk in pipe or not */
+	char			bulk_in_inuse;		/* if the bulk in endpoint is in use */
 	__u8			bulk_in_endpoint;
 	__u8			bulk_in_interval;
-	__u16			bulk_in_size;
+	__u16			bulk_in_size;		/* the size of the bulk in endpoint */
 	unsigned int		bulk_in_pipe;
 	unsigned char *		bulk_in_buffer;
 	void *			bulk_in_transfer;
 
-	char			bulk_out_inuse;
+	char			has_bulk_out;		/* if this device has a bulk out pipe or not */
+	char			bulk_out_inuse;		/* if the bulk out endpoint is in use */
 	__u8			bulk_out_endpoint;
 	__u8			bulk_out_interval;
-	__u16			bulk_out_size;
+	__u16			bulk_out_size;		/* the size of the bulk out endpoint */
 	unsigned int		bulk_out_pipe;
 	unsigned char *		bulk_out_buffer;
 	void *			bulk_out_transfer;
@@ -197,36 +349,25 @@
 
 
 
-
-/* tty interface functions */
+/*****************************************************************************
+ * Driver tty interface functions
+ *****************************************************************************/
 static int serial_open (struct tty_struct *tty, struct file * filp)
 {
 	struct usb_serial_state *serial;
 	
 	debug_info("USB: serial_open\n");
 
+	/* assign a serial object to the tty pointer */
 	serial = &serial_state_table [MINOR(tty->device)-tty->driver.minor_start];
 	tty->driver_data = serial;
 	serial->tty = tty;
 	 
-	if (!serial->present) {
-		debug_info("USB Serial: no device registered\n");
-		return -EINVAL;
+	/* pass on to the driver specific version of this function */
+	if (serial->type->open) {
+		return (serial->type->open(tty, filp));
 	}
-
-	if (serial->active) {
-		debug_info ("USB Serial: device already open\n");
-		return -EINVAL;
-	}
-	serial->active = 1;
- 
-	/*Start reading from the device*/
-	serial->bulk_in_inuse = 1;
-	serial->bulk_in_transfer = usb_request_bulk (serial->dev, serial->bulk_in_pipe, serial_read_irq, serial->bulk_in_buffer, serial->bulk_in_size, serial);
-
-	/* Need to do device specific setup here (control lines, baud rate, etc.) */
-	/* FIXME!!! */
-				                  
+		
 	return (0);
 }
 
@@ -246,28 +387,16 @@
 		return;
 	}
 
-	/* Need to change the control lines here */
-	/* FIXME */
-	
-	if (serial->bulk_out_inuse){
-		usb_terminate_bulk (serial->dev, serial->bulk_out_transfer);
-		serial->bulk_out_inuse = 0;
-	}
-	if (serial->bulk_in_inuse){
-		usb_terminate_bulk (serial->dev, serial->bulk_in_transfer);
-		serial->bulk_in_inuse = 0;
+	/* pass on to the driver specific version of this function */
+	if (serial->type->close) {
+		serial->type->close(tty, filp);
 	}
-
-	/* release the irq? */
-	
-	serial->active = 0;
-}
+}	
 
 
 static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
-	int written;
 	
 	debug_info("USB Serial: serial_write\n");
 
@@ -281,26 +410,14 @@
 		return (-EINVAL);
 	}
 	
-	if (serial->bulk_out_inuse) {
-		debug_info ("USB Serial: already writing\n");
-		return (0);
+	/* pass on to the driver specific version of this function */
+	if (serial->type->write) {
+		return (serial->type->write(tty, from_user, buf, count));
 	}
 
-	written = (count > serial->bulk_out_size) ? serial->bulk_out_size : count;
-	  
-	if (from_user) {
-		copy_from_user(serial->bulk_out_buffer, buf, written);
-	}
-	else {
-		memcpy (serial->bulk_out_buffer, buf, written);
-	}  
-
-	/* send the data out the bulk port */
-	serial->bulk_out_inuse = 1;
-	serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, written, serial);
-
-	return (written);
-} 
+	/* no specific driver, so return that we didn't write anything */
+	return (0);
+}
 
 
 static void serial_put_char (struct tty_struct *tty, unsigned char ch)
@@ -319,18 +436,13 @@
 		return;
 	}
 
-	if (serial->bulk_out_inuse) {
-		debug_info ("USB Serial: already writing\n");
-		return;
+	/* pass on to the driver specific version of this function */
+	if (serial->type->put_char) {
+		serial->type->put_char(tty, ch);
 	}
 
-	/* send the single character out the bulk port */
-	serial->bulk_out_buffer[0] = ch;
-	serial->bulk_out_inuse = 1;
-	serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, 1, serial);
-
 	return;
-}                   
+}	
 
 
 static int serial_write_room (struct tty_struct *tty) 
@@ -349,11 +461,12 @@
 		return (-EINVAL);
 	}
 	
-	if (serial->bulk_out_inuse) {
-		return (0);
+	/* pass on to the driver specific version of this function */
+	if (serial->type->write_room) {
+		return (serial->type->write_room(tty));
 	}
 
-	return serial->bulk_out_size;
+	return (0);
 }
 
 
@@ -373,8 +486,9 @@
 		return (-EINVAL);
 	}
 	
-	if (serial->bulk_out_inuse) {
-		return (serial->bulk_out_size);
+	/* pass on to the driver specific version of this function */
+	if (serial->type->chars_in_buffer) {
+		return (serial->type->chars_in_buffer(tty));
 	}
 
 	return (0);
@@ -397,9 +511,10 @@
 		return;
 	}
 
-
-	/* Change the control signals */
-	/* FIXME!!! */
+	/* pass on to the driver specific version of this function */
+	if (serial->type->throttle) {
+		serial->type->throttle(tty);
+	}
 
 	return;
 }
@@ -422,6 +537,153 @@
 	}
 
 
+	/* pass on to the driver specific version of this function */
+	if (serial->type->unthrottle) {
+		serial->type->unthrottle(tty);
+	}
+
+	return;
+}
+
+
+/*****************************************************************************
+ * eTek specific driver functions
+ *****************************************************************************/
+static int etek_serial_open (struct tty_struct *tty, struct file *filp)
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
+
+	debug_info("USB: etek_serial_open\n");
+
+	if (!serial->present) {
+		debug_info("USB Serial: no device registered\n");
+		return -EINVAL;
+	}
+
+	if (serial->active) {
+		debug_info ("USB Serial: device already open\n");
+		return -EINVAL;
+	}
+	serial->active = 1;
+ 
+	/*Start reading from the device*/
+	serial->bulk_in_inuse = 1;
+	serial->bulk_in_transfer = usb_request_bulk (serial->dev, serial->bulk_in_pipe, serial_read_irq, serial->bulk_in_buffer, serial->bulk_in_size, serial);
+
+	/* Need to do device specific setup here (control lines, baud rate, etc.) */
+	/* FIXME!!! */
+				                  
+	return (0);
+}
+
+
+static void etek_serial_close(struct tty_struct *tty, struct file * filp)
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
+	debug_info("USB: etek_serial_close\n");
+	
+	/* Need to change the control lines here */
+	/* FIXME */
+	
+	/* shutdown our bulk reads and writes */
+	if (serial->bulk_out_inuse){
+		usb_terminate_bulk (serial->dev, serial->bulk_out_transfer);
+		serial->bulk_out_inuse = 0;
+	}
+	if (serial->bulk_in_inuse){
+		usb_terminate_bulk (serial->dev, serial->bulk_in_transfer);
+		serial->bulk_in_inuse = 0;
+	}
+
+	/* release the irq? */
+	
+	serial->active = 0;
+}
+
+
+static int etek_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
+	int written;
+	
+	debug_info("USB Serial: etek_serial_write\n");
+
+	if (serial->bulk_out_inuse) {
+		debug_info ("USB Serial: already writing\n");
+		return (0);
+	}
+
+	written = (count > serial->bulk_out_size) ? serial->bulk_out_size : count;
+	  
+	if (from_user) {
+		copy_from_user(serial->bulk_out_buffer, buf, written);
+	}
+	else {
+		memcpy (serial->bulk_out_buffer, buf, written);
+	}  
+
+	/* send the data out the bulk port */
+	serial->bulk_out_inuse = 1;
+	serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, written, serial);
+
+	return (written);
+} 
+
+
+static void etek_serial_put_char (struct tty_struct *tty, unsigned char ch)
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
+	
+	debug_info("USB Serial: etek_serial_put_char\n");
+	
+	if (serial->bulk_out_inuse) {
+		debug_info ("USB Serial: already writing\n");
+		return;
+	}
+
+	/* send the single character out the bulk port */
+	serial->bulk_out_buffer[0] = ch;
+	serial->bulk_out_inuse = 1;
+	serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, 1, serial);
+
+	return;
+}                   
+
+
+static int etek_write_room (struct tty_struct *tty) 
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
+
+	debug_info("USB Serial: etek_write_room\n");
+	
+	if (serial->bulk_out_inuse) {
+		return (0);
+	}
+
+	return (serial->bulk_out_size);
+}
+
+
+static int etek_chars_in_buffer (struct tty_struct *tty) 
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
+
+	debug_info("USB Serial: etek_chars_in_buffer\n");
+	
+	if (serial->bulk_out_inuse) {
+		return (serial->bulk_out_size);
+	}
+
+	return (0);
+}
+
+
+static void etek_throttle (struct tty_struct * tty)
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
+
+	debug_info("USB Serial: etek_throttle\n");
+	
 	/* Change the control signals */
 	/* FIXME!!! */
 
@@ -429,136 +691,340 @@
 }
 
 
-static int Get_Free_Serial (void)
+static void etek_unthrottle (struct tty_struct * tty)
 {
-	int i;
+	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
+
+	debug_info("USB Serial: etek_unthrottle\n");
+	
+	/* Change the control signals */
+	/* FIXME!!! */
+
+	return;
+}
+
+
+/*****************************************************************************
+ * generic devices specific driver functions
+ *****************************************************************************/
+static int generic_serial_open (struct tty_struct *tty, struct file *filp)
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
+
+	debug_info("USB: generic_serial_open\n");
+
+	if (!serial->present) {
+		debug_info("USB Serial: no device registered\n");
+		return -EINVAL;
+	}
+
+	if (serial->active) {
+		debug_info ("USB Serial: device already open\n");
+		return -EINVAL;
+	}
+	serial->active = 1;
  
-	for (i=0; i < NUM_PORTS; ++i) {
-		if (!serial_state_table[i].present)
-			return (i);
+	/* if we have a bulk interrupt, start reading from it */
+	if (serial->has_bulk_in) {
+		/*Start reading from the device*/
+		serial->bulk_in_inuse = 1;
+		serial->bulk_in_transfer = usb_request_bulk (serial->dev, serial->bulk_in_pipe, serial_read_irq, serial->bulk_in_buffer, serial->bulk_in_size, serial);
 	}
-	return (-1);
+				                  
+	return (0);
 }
 
 
-static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
+static void generic_serial_close(struct tty_struct *tty, struct file * filp)
 {
-	struct usb_serial_state *serial;
-	struct usb_interface_descriptor *interface;
-	struct usb_endpoint_descriptor *endpoint;
-	SERIAL_TYPE type;
-	int serial_num;
-//	int ret;
-	int i;
+	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
+	debug_info("USB: generic_serial_close\n");
 	
-	/* look at the device descriptor to see if it is a type that we	recognize */
-	type = unknown;
-	if ((dev->descriptor.idVendor == BELKIN_VENDOR_ID) &&
-	    (dev->descriptor.idProduct == BELKIN_SERIAL_CONVERTER)) {
-		/* This is the Belkin serial convertor */
-		type = Belkin;
-		}
+	/* shutdown any bulk reads that might be going on */
+	if (serial->bulk_out_inuse){
+		usb_terminate_bulk (serial->dev, serial->bulk_out_transfer);
+		serial->bulk_out_inuse = 0;
+	}
+	if (serial->bulk_in_inuse){
+		usb_terminate_bulk (serial->dev, serial->bulk_in_transfer);
+		serial->bulk_in_inuse = 0;
+	}
+
+	serial->active = 0;
+}
+
+
+static int generic_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
+	int written;
 	
-	if ((dev->descriptor.idVendor == PERACOM_VENDOR_ID) &&
-	    (dev->descriptor.idProduct == PERACOM_SERIAL_CONVERTER)) {
-		/* This is the Peracom serial convertor */
-		type = Peracom;
+	debug_info("USB Serial: generic_serial_write\n");
+
+	/* only do something if we have a bulk out endpoint */
+	if (serial->has_bulk_out) {
+		if (serial->bulk_out_inuse) {
+			debug_info ("USB Serial: already writing\n");
+			return (0);
 		}
 
-	if (type == unknown)
-		return NULL;	
+		written = (count > serial->bulk_out_size) ? serial->bulk_out_size : count;
+	  
+		if (from_user) {
+			copy_from_user(serial->bulk_out_buffer, buf, written);
+		}
+		else {
+			memcpy (serial->bulk_out_buffer, buf, written);
+		}  
 
-	printk (KERN_INFO "USB serial converter detected.\n");
+		/* send the data out the bulk port */
+		serial->bulk_out_inuse = 1;
+		serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, written, serial);
 
-	if (0>(serial_num = Get_Free_Serial())) {
-		debug_info("USB Serial: Too many devices connected\n");
-		return NULL;
+		return (written);
 	}
 	
-	serial = &serial_state_table[serial_num];
+	/* no bulk out, so return 0 bytes written */
+	return (0);
+} 
 
-       	memset(serial, 0, sizeof(serial));
-       	serial->dev = dev;
-	serial->type = type;
 
-	/* we should have 1 bulk in, 1 bulk out, and 1 interrupt in endpoints */
-	interface = &dev->actconfig->interface[ifnum].altsetting[0];
-	for (i = 0; i < interface->bNumEndpoints; ++i) {
-		endpoint = &interface->endpoint[i];
-		
-		if ((endpoint->bEndpointAddress & 0x80) &&
-		    ((endpoint->bmAttributes & 3) == 0x02)) {
-			/* we found the bulk in endpoint */
-			serial->bulk_in_inuse = 0;
-			serial->bulk_in_endpoint = endpoint->bEndpointAddress;
-			serial->bulk_in_size = endpoint->wMaxPacketSize;
-			serial->bulk_in_interval = endpoint->bInterval;
-			serial->bulk_in_pipe = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint);
-			serial->bulk_in_buffer = kmalloc (serial->bulk_in_size, GFP_KERNEL);
-			if (!serial->bulk_in_buffer) {
-				printk("USB Serial: Couldn't allocate bulk_in_buffer\n");
-				goto probe_error;
-			}
+static void generic_serial_put_char (struct tty_struct *tty, unsigned char ch)
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
+	
+	debug_info("USB Serial: generic_serial_put_char\n");
+	
+	/* if we have a bulk out endpoint, then shove a character out it */
+	if (serial->has_bulk_out) {
+		if (serial->bulk_out_inuse) {
+			debug_info ("USB Serial: already writing\n");
+			return;
 		}
 
-		if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
-		    ((endpoint->bmAttributes & 3) == 0x02)) {
-			/* we found the bulk out endpoint */
-			serial->bulk_out_inuse = 0;
-			serial->bulk_out_endpoint = endpoint->bEndpointAddress;
-			serial->bulk_out_size = endpoint->wMaxPacketSize;
-			serial->bulk_out_interval = endpoint->bInterval;
-			serial->bulk_out_pipe = usb_rcvbulkpipe (dev, serial->bulk_out_endpoint);
-			serial->bulk_out_buffer = kmalloc (serial->bulk_out_size, GFP_KERNEL);
-			if (!serial->bulk_out_buffer) {
-				printk("USB Serial: Couldn't allocate bulk_out_buffer\n");
-				goto probe_error;
-			}
+		/* send the single character out the bulk port */
+		serial->bulk_out_buffer[0] = ch;
+		serial->bulk_out_inuse = 1;
+		serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, 1, serial);
+	}
+
+	return;
+}                   
+
+
+static int generic_write_room (struct tty_struct *tty) 
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
+
+	debug_info("USB Serial: generic_write_room\n");
+	
+	if (serial->has_bulk_out) {
+		if (serial->bulk_out_inuse) {
+			return (0);
 		}
-		
-		if ((endpoint->bEndpointAddress & 0x80) &&
-		    ((endpoint->bmAttributes & 3) == 0x03)) {
-			/* we found the interrupt in endpoint */
-			serial->interrupt_in_inuse = 0;
-			serial->interrupt_in_endpoint = endpoint->bEndpointAddress;
-			serial->interrupt_in_size = endpoint->wMaxPacketSize;
-			serial->interrupt_in_interval = endpoint->bInterval;
-			/* serial->interrupt_in_pipe = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint); */
-			serial->interrupt_in_buffer = kmalloc (serial->bulk_in_size, GFP_KERNEL);
-			if (!serial->interrupt_in_buffer) {
-				printk("USB Serial: Couldn't allocate interrupt_in_buffer\n");
-				goto probe_error;
-			}
+		return (serial->bulk_out_size);
+	}
+	
+	return (0);
+}
+
+
+static int generic_chars_in_buffer (struct tty_struct *tty) 
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
+
+	debug_info("USB Serial: generic_chars_in_buffer\n");
+	
+	if (serial->has_bulk_out) {
+		if (serial->bulk_out_inuse) {
+			return (serial->bulk_out_size);
 		}
+	}
 
+	return (0);
+}
+
+
+static int Get_Free_Serial (void)
+{
+	int i;
+ 
+	for (i=0; i < NUM_PORTS; ++i) {
+		if (!serial_state_table[i].present)
+			return (i);
 	}
+	return (-1);
+}
+
+
+static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
+{
+	struct usb_serial_state *serial = NULL;
+	struct usb_interface_descriptor *interface;
+	struct usb_endpoint_descriptor *endpoint;
+	struct usb_endpoint_descriptor *interrupt_in_endpoint = NULL;
+	struct usb_endpoint_descriptor *bulk_in_endpoint = NULL;
+	struct usb_endpoint_descriptor *bulk_out_endpoint = NULL;
+//	SERIAL_TYPE type;
+	struct usb_serial_device_type *type;
+	int device_num;
+	int serial_num;
+//	int ret;
+	int i;
+	char interrupt_pipe;
+	char bulk_in_pipe;
+	char bulk_out_pipe;
+	
+	/* loop through our list of known serial converters, and see if this device matches */
+	device_num = 0;
+	while (usb_serial_devices[device_num] != NULL) {
+		type = usb_serial_devices[device_num];
+		#ifdef SERIAL_DEBUG
+			printk ("Looking at %s\nVendor id=%.4x\nProduct id=%.4x", type->name, *(type->idVendor), *(type->idProduct));
+		#endif		
+
+		/* look at the device descriptor */
+		if ((dev->descriptor.idVendor == *(type->idVendor)) &&
+		    (dev->descriptor.idProduct == *(type->idProduct))) {
+
+			debug_info("descriptor matches...looking at the endpoints\n")
+
+			/* descriptor matches, let's try to find the endpoints needed */
+			interrupt_pipe = bulk_in_pipe = bulk_out_pipe = HAS_NOT;
+			
+			/* check out the endpoints */
+			interface = &dev->actconfig->interface[ifnum].altsetting[0];
+			for (i = 0; i < interface->bNumEndpoints; ++i) {
+				endpoint = &interface->endpoint[i];
+		
+				if ((endpoint->bEndpointAddress & 0x80) &&
+				    ((endpoint->bmAttributes & 3) == 0x02)) {
+					/* we found a bulk in endpoint */
+					debug_info("found bulk in\n");
+					if (bulk_in_pipe == HAS) {
+						printk("USB Serial: can't have more than one bulk in endpoint\n");
+						goto probe_error;
+						}
+					bulk_in_pipe = HAS;
+					bulk_in_endpoint = endpoint;
+				}
+
+				if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
+				    ((endpoint->bmAttributes & 3) == 0x02)) {
+					/* we found a bulk out endpoint */
+					debug_info("found bulk out\n");
+					if (bulk_out_pipe == HAS) {
+						printk("USB Serial: can't have more than one bulk out endpoint\n");
+						goto probe_error;
+						}
+					bulk_out_pipe = HAS;
+					bulk_out_endpoint = endpoint;
+				}
+		
+				if ((endpoint->bEndpointAddress & 0x80) &&
+				    ((endpoint->bmAttributes & 3) == 0x03)) {
+					/* we found a interrupt in endpoint */
+					debug_info("found interrupt in\n");
+					if (interrupt_pipe == HAS) {
+						printk("USB Serial: can't have more than one interrupt in endpoint\n");
+						goto probe_error;
+						}
+					interrupt_pipe = HAS;
+					interrupt_in_endpoint = endpoint;
+				}
+
+			}
 	
+			/* verify that we found all of the endpoints that we need */
+			if ((interrupt_pipe & type->needs_interrupt_in) &&
+			    (bulk_in_pipe & type->needs_bulk_in) &&
+			    (bulk_out_pipe & type->needs_bulk_out)) {
+				/* found all that we need */
+				printk (KERN_INFO "USB serial converter detected.\n");
+
+				if (0>(serial_num = Get_Free_Serial())) {
+					debug_info("USB Serial: Too many devices connected\n");
+					return NULL;
+				}
+	
+				serial = &serial_state_table[serial_num];
+
+			       	memset(serial, 0, sizeof(struct usb_serial_state));
+			       	serial->dev = dev;
+				serial->type = type;
+
+				/* set up the endpoint information */
+				if (bulk_in_endpoint) {
+					serial->has_bulk_in = 1;
+					serial->bulk_in_inuse = 0;
+					serial->bulk_in_endpoint = bulk_in_endpoint->bEndpointAddress;
+					serial->bulk_in_size = bulk_in_endpoint->wMaxPacketSize;
+					serial->bulk_in_interval = bulk_in_endpoint->bInterval;
+					serial->bulk_in_pipe = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint);
+					serial->bulk_in_buffer = kmalloc (serial->bulk_in_size, GFP_KERNEL);
+					if (!serial->bulk_in_buffer) {
+						printk("USB Serial: Couldn't allocate bulk_in_buffer\n");
+						goto probe_error;
+					}
+				}
+
+				if (bulk_out_endpoint) {
+					serial->has_bulk_out = 1;
+					serial->bulk_out_inuse = 0;
+					serial->bulk_out_endpoint = bulk_out_endpoint->bEndpointAddress;
+					serial->bulk_out_size = bulk_out_endpoint->wMaxPacketSize;
+					serial->bulk_out_interval = bulk_out_endpoint->bInterval;
+					serial->bulk_out_pipe = usb_rcvbulkpipe (dev, serial->bulk_out_endpoint);
+					serial->bulk_out_buffer = kmalloc (serial->bulk_out_size, GFP_KERNEL);
+					if (!serial->bulk_out_buffer) {
+						printk("USB Serial: Couldn't allocate bulk_out_buffer\n");
+						goto probe_error;
+					}
+				}
+
+				if (interrupt_in_endpoint) {
+					serial->has_interrupt_in = 1;
+					serial->interrupt_in_inuse = 0;
+					serial->interrupt_in_endpoint = interrupt_in_endpoint->bEndpointAddress;
+					serial->interrupt_in_size = interrupt_in_endpoint->wMaxPacketSize;
+					serial->interrupt_in_interval = interrupt_in_endpoint->bInterval;
+					/* serial->interrupt_in_pipe = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint); */
+					serial->interrupt_in_buffer = kmalloc (serial->bulk_in_size, GFP_KERNEL);
+					if (!serial->interrupt_in_buffer) {
+						printk("USB Serial: Couldn't allocate interrupt_in_buffer\n");
+						goto probe_error;
+					}
+				}
+
+				#if 0
+				/* set up an interrupt for out bulk in pipe */
+				/* ask for a bulk read */
+				serial->bulk_in_inuse = 1;
+				serial->bulk_in_transfer = usb_request_bulk (serial->dev, serial->bulk_in_pipe, serial_read_irq, serial->bulk_in_buffer, serial->bulk_in_size, serial);
+
+				/* set up our interrupt to be the time for the bulk in read */
+				ret = usb_request_irq (dev, serial->bulk_in_pipe, usb_serial_irq, serial->bulk_in_interval, serial, &serial->irq_handle);
+				if (ret) {
+					printk(KERN_INFO "USB Serial failed usb_request_irq (0x%x)\n", ret);
+					goto probe_error;
+				}
+				#endif
+
+				serial->present = 1;
+				MOD_INC_USE_COUNT;
+
+				return serial;
+			} else {
+				printk(KERN_INFO "USB Serial, descriptors matched, but endpoints did not\n");
+			}
+		}
 
-	/* verify that we found all of the endpoints that we need */
-	if ((!serial->bulk_in_buffer) || 
-	    (!serial->bulk_out_buffer) ||
-	    (!serial->interrupt_in_buffer)) {
-		printk("USB Serial: did not find all of the required endpoints\n");
-		goto probe_error;
+		/* look at the next type in our list */
+		++device_num;
 	}
-		
 
-	/* set up an interrupt for out bulk in pipe */
-	/* ask for a bulk read */
-//	serial->bulk_in_inuse = 1;
-//	serial->bulk_in_transfer = usb_request_bulk (serial->dev, serial->bulk_in_pipe, serial_read_irq, serial->bulk_in_buffer, serial->bulk_in_size, serial);
 
-	/* set up our interrupt to be the time for the bulk in read */
-//	ret = usb_request_irq (dev, serial->bulk_in_pipe, usb_serial_irq, serial->bulk_in_interval, serial, &serial->irq_handle);
-//	if (ret) {
-//		printk(KERN_INFO "USB Serial failed usb_request_irq (0x%x)\n", ret);
-//		goto probe_error;
-//	}
-	
-	serial->present = 1;
-	MOD_INC_USE_COUNT;
 
-	return serial;
 
 probe_error:
 	if (serial) {
@@ -636,6 +1102,8 @@
 	serial_tty_driver.flags			= TTY_DRIVER_REAL_RAW;
 	serial_tty_driver.refcount		= &serial_refcount;
 	serial_tty_driver.table			= serial_tty;
+	serial_tty_driver.proc_entry		= NULL;
+	serial_tty_driver.other			= NULL;
 	serial_tty_driver.termios		= serial_termios;
 	serial_tty_driver.termios_locked	= serial_termios_locked;
 	
diff -u --recursive --new-file v2.3.26/linux/drivers/usb/usb.c linux/drivers/usb/usb.c
--- v2.3.26/linux/drivers/usb/usb.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/usb/usb.c	Tue Nov  9 08:24:32 1999
@@ -720,7 +720,7 @@
 	}
 
 	memset(config->interface, 0,
-	       config->bNumInterfaces*sizeof(struct usb_interface_descriptor));
+	       config->bNumInterfaces * sizeof(struct usb_interface));
 
 	buffer += config->bLength;
 	size -= config->bLength;
@@ -1140,13 +1140,16 @@
 	}
 
 	if (usb_get_string(dev, dev->string_langid, index, u.buffer, 4) < 0 ||
-	    usb_get_string(dev, dev->string_langid, index, u.buffer,
-			      u.desc.bLength) < 0) {
+	    ((ret = usb_get_string(dev, dev->string_langid, index, u.buffer,
+			      u.desc.bLength)) < 0)) {
 		printk(KERN_ERR "usb: error retrieving string\n");
 		return NULL;
 	}
 
+	if (ret > 0) ret /= 2;		/* going from 16-bit chars to 8-bit */
 	len = u.desc.bLength / 2;	/* includes terminating null */
+					/* after removing bLength & bDescType */
+	if (ret < len) len = ret;	/* use min of (ret, len) */
 
 	ptr = kmalloc(len, GFP_KERNEL);
 	if (!ptr) {
diff -u --recursive --new-file v2.3.26/linux/drivers/usb/usb_scsi.c linux/drivers/usb/usb_scsi.c
--- v2.3.26/linux/drivers/usb/usb_scsi.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/usb/usb_scsi.c	Thu Nov 11 16:57:31 1999
@@ -108,7 +108,7 @@
 
 static struct proc_dir_entry proc_usb_scsi =
 {
-    PROC_SCSI_USB_SCSI,
+    PROC_SCSI_USB_SCSI,		/* It's currently b0rken */
     0,
     NULL,
     S_IFDIR | S_IRUGO | S_IXUGO,
diff -u --recursive --new-file v2.3.26/linux/drivers/video/atafb.c linux/drivers/video/atafb.c
--- v2.3.26/linux/drivers/video/atafb.c	Thu Aug 12 10:22:33 1999
+++ linux/drivers/video/atafb.c	Mon Nov  8 11:03:21 1999
@@ -464,7 +464,7 @@
 	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 @@
 							  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 @@
 	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 @@
 
 {
 	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_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 -u --recursive --new-file v2.3.26/linux/fs/bfs/inode.c linux/fs/bfs/inode.c
--- v2.3.26/linux/fs/bfs/inode.c	Sun Nov  7 16:37:34 1999
+++ linux/fs/bfs/inode.c	Tue Nov  9 10:02:33 1999
@@ -263,7 +263,7 @@
 	struct buffer_head * bh;
 	struct bfs_super_block * bfs_sb;
 	struct inode * inode;
-	int i, imap_len;
+	int i, imap_len, bmap_len;
 
 	MOD_INC_USE_COUNT;
 	lock_super(s);
@@ -295,9 +295,11 @@
 	s->su_lasti = (bfs_sb->s_start - BFS_BSIZE)/sizeof(struct bfs_inode) 
 			+ BFS_ROOT_INO - 1;
 
-	s->su_bmap = kmalloc(sizeof(struct bfs_bmap) * s->su_lasti, GFP_KERNEL);
+	bmap_len = sizeof(struct bfs_bmap) * s->su_lasti;
+	s->su_bmap = kmalloc(bmap_len, GFP_KERNEL);
 	if (!s->su_bmap)
 		goto out;
+	memset(s->su_bmap, 0, bmap_len);
 	imap_len = s->su_lasti/8 + 1;
 	s->su_imap = kmalloc(imap_len, GFP_KERNEL);
 	if (!s->su_imap) {
diff -u --recursive --new-file v2.3.26/linux/fs/binfmt_misc.c linux/fs/binfmt_misc.c
--- v2.3.26/linux/fs/binfmt_misc.c	Fri Sep 10 23:57:36 1999
+++ linux/fs/binfmt_misc.c	Thu Nov 11 16:57:31 1999
@@ -471,24 +471,6 @@
 	return 0;
 }
 
-#ifdef MODULE
-/*
- * This is called as the fill_inode function when an inode
- * is going into (fill = 1) or out of service (fill = 0).
- * We use it here to manage the module use counts.
- *
- * Note: only the top-level directory needs to do this; if
- * a lower level is referenced, the parent will be as well.
- */
-static void bm_modcount(struct inode *inode, int fill)
-{
-	if (fill)
-		MOD_INC_USE_COUNT;
-	else
-		MOD_DEC_USE_COUNT;
-}
-#endif
-
 static int __init init_misc_binfmt(void)
 {
 	int error = -ENOENT;
@@ -497,9 +479,7 @@
 	bm_dir = create_proc_entry("sys/fs/binfmt_misc", S_IFDIR, NULL);
 	if (!bm_dir)
 		goto out;
-#ifdef MODULE
-	bm_dir->fill_inode = bm_modcount;
-#endif
+	bm_dir->owner = THIS_MODULE;
 
 	status = create_proc_entry("status", S_IFREG | S_IRUGO | S_IWUSR,
 					bm_dir);
diff -u --recursive --new-file v2.3.26/linux/fs/buffer.c linux/fs/buffer.c
--- v2.3.26/linux/fs/buffer.c	Sun Nov  7 16:37:34 1999
+++ linux/fs/buffer.c	Thu Nov 11 10:33:42 1999
@@ -91,7 +91,7 @@
 };
 static struct bh_free_head free_list[NR_SIZES];
 
-static kmem_cache_t *bh_cachep;
+kmem_cache_t *bh_cachep;
 
 static int grow_buffers(int size);
 
@@ -130,8 +130,6 @@
 int bdflush_min[N_PARAM] = {  0,  10,    5,   25,  0,   1*HZ,   1*HZ, 1, 1};
 int bdflush_max[N_PARAM] = {100,50000, 20000, 20000,600*HZ, 6000*HZ, 6000*HZ, 2047, 5};
 
-void wakeup_bdflush(int);
-
 /*
  * Rewrote the wait-routines to use the "new" wait-queue functionality,
  * and getting rid of the cli-sti pairs. The wait-queue routines still
@@ -707,7 +705,7 @@
 	mark_buffer_uptodate(bh, uptodate);
 
 	/* This is a temporary buffer used for page I/O. */
-	page = mem_map + MAP_NR(bh->b_data);
+	page = bh->b_page;
 
 	if (!uptodate)
 		SetPageError(page);
@@ -760,7 +758,6 @@
 	return;
 }
 
-
 /*
  * Ok, this is getblk, and it isn't very clear, again to hinder
  * race-conditions. Most of the code is seldom used, (ie repeating),
@@ -823,7 +820,7 @@
 	unsigned long dirty, tot, hard_dirty_limit, soft_dirty_limit;
 
 	dirty = size_buffers_type[BUF_DIRTY] >> PAGE_SHIFT;
-	tot = nr_lru_pages + nr_free_pages - nr_free_highpages;
+	tot = nr_free_buffer_pages();
 	hard_dirty_limit = tot * bdf_prm.b_un.nfract / 100;
 	soft_dirty_limit = hard_dirty_limit >> 1;
 
@@ -1092,6 +1089,20 @@
 	return NULL;
 }
 
+void set_bh_page (struct buffer_head *bh, struct page *page, unsigned int offset)
+{
+	bh->b_page = page;
+	if (offset >= PAGE_SIZE)
+		BUG();
+	if (PageHighMem(page))
+		/*
+		 * This catches illegal uses and preserves the offset:
+		 */
+		bh->b_data = (char *)(0 + offset);
+	else
+		bh->b_data = (char *)(page_address(page) + offset);
+}
+
 /*
  * Create the appropriate buffers when given a page for data area and
  * the size of each buffer.. Use the bh->b_this_page linked list to
@@ -1101,7 +1112,7 @@
  * from ordinary buffer allocations, and only async requests are allowed
  * to sleep waiting for buffer heads. 
  */
-static struct buffer_head * create_buffers(unsigned long page, unsigned long size, int async)
+static struct buffer_head * create_buffers(struct page * page, unsigned long size, int async)
 {
 	struct buffer_head *bh, *head;
 	long offset;
@@ -1124,7 +1135,8 @@
 		atomic_set(&bh->b_count, 0);
 		bh->b_size = size;
 
-		bh->b_data = (char *) (page+offset);
+		set_bh_page(bh, page, offset);
+
 		bh->b_list = BUF_CLEAN;
 		bh->b_end_io = end_buffer_io_bad;
 	}
@@ -1183,7 +1195,7 @@
 	 * They don't show up in the buffer hash table, but they *are*
 	 * registered in page->buffers.
 	 */
-	head = create_buffers(page_address(page), size, 1);
+	head = create_buffers(page, size, 1);
 	if (page->buffers)
 		BUG();
 	if (!head)
@@ -1273,7 +1285,7 @@
 {
 	struct buffer_head *bh, *head, *tail;
 
-	head = create_buffers(page_address(page), blocksize, 1);
+	head = create_buffers(page, blocksize, 1);
 	if (page->buffers)
 		BUG();
 
@@ -1377,10 +1389,11 @@
 	unsigned long start_offset, start_bytes, end_bytes;
 	unsigned long bbits, blocks, i, len;
 	struct buffer_head *bh, *head;
-	char * target_buf;
+	char *target_buf, *kaddr;
 	int need_balance_dirty;
 
-	target_buf = (char *)page_address(page) + offset;
+	kaddr = (char *)kmap(page);
+	target_buf = kaddr + offset;
 
 	if (!PageLocked(page))
 		BUG();
@@ -1445,7 +1458,7 @@
 
 		if (!buffer_uptodate(bh) && (start_offset || (end_bytes && (i == end_block)))) {
 			if (buffer_new(bh)) {
-				memset(bh->b_data, 0, bh->b_size);
+				memset(kaddr + i*blocksize, 0, blocksize);
 			} else {
 				ll_rw_block(READ, 1, &bh);
 				wait_on_buffer(bh);
@@ -1463,6 +1476,10 @@
 			len = end_bytes;
 			end_bytes = 0;
 		}
+		if (target_buf >= kaddr + PAGE_SIZE)
+			BUG();
+		if (target_buf+len-1 >= kaddr + PAGE_SIZE)
+			BUG();
 		err = copy_from_user(target_buf, buf, len);
 		target_buf += len;
 		buf += len;
@@ -1511,9 +1528,11 @@
 	 */
 	if (!partial)
 		SetPageUptodate(page);
+	kunmap(page);
 	return bytes;
 out:
 	ClearPageUptodate(page);
+	kunmap(page);
 	return err;
 }
 
@@ -1714,8 +1733,6 @@
  * for them to complete.  Clean up the buffer_heads afterwards.  
  */
 
-#define dprintk(x...) 
-
 static int do_kio(struct kiobuf *kiobuf,
 		  int rw, int nr, struct buffer_head *bh[], int size)
 {
@@ -1726,8 +1743,6 @@
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
 
-	dprintk ("do_kio start %d\n", rw);
-
 	if (rw == WRITE)
 		rw = WRITERAW;
 	atomic_add(nr, &kiobuf->io_count);
@@ -1753,8 +1768,6 @@
 	
 	spin_unlock(&unused_list_lock);
 
-	dprintk ("do_kio end %d %d\n", iosize, err);
-	
 	if (iosize)
 		return iosize;
 	if (kiobuf->errno)
@@ -1808,12 +1821,6 @@
 			panic("brw_kiovec: iobuf not initialised");
 	}
 
-	/* DEBUG */
-#if 0
-	return iobuf->length;
-#endif
-	dprintk ("brw_kiovec: start\n");
-	
 	/* 
 	 * OK to walk down the iovec doing page IO on each page we find. 
 	 */
@@ -1822,7 +1829,6 @@
 		iobuf = iovec[i];
 		offset = iobuf->offset;
 		length = iobuf->length;
-		dprintk ("iobuf %d %d %d\n", offset, length, size);
 
 		for (pageind = 0; pageind < iobuf->nr_pages; pageind++) {
 			map  = iobuf->maplist[pageind];
@@ -1842,7 +1848,7 @@
 				
 				tmp->b_dev = B_FREE;
 				tmp->b_size = size;
-				tmp->b_data = (char *) (page + offset);
+				set_bh_page(tmp, map, offset);
 				tmp->b_this_page = tmp;
 
 				init_buffer(tmp, end_buffer_io_kiobuf, NULL);
@@ -1856,8 +1862,6 @@
 					set_bit(BH_Dirty, &tmp->b_state);
 				}
 
-				dprintk ("buffer %d (%d) at %p\n", 
-					 bhind, tmp->b_blocknr, tmp->b_data);
 				bh[bhind++] = tmp;
 				length -= size;
 				offset += size;
@@ -1892,7 +1896,6 @@
 	}
 
  finished:
-	dprintk ("brw_kiovec: end (%d, %d)\n", transferred, err);
 	if (transferred)
 		return transferred;
 	return err;
@@ -2002,7 +2005,8 @@
 	unsigned long iblock;
 	struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
 	unsigned int blocksize, blocks;
-	int nr;
+	unsigned long kaddr = 0;
+	int nr, i;
 
 	if (!PageLocked(page))
 		PAGE_BUG(page);
@@ -2015,6 +2019,7 @@
 	iblock = page->index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
 	bh = head;
 	nr = 0;
+	i = 0;
 
 	do {
 		if (buffer_uptodate(bh))
@@ -2023,7 +2028,9 @@
 		if (!buffer_mapped(bh)) {
 			inode->i_op->get_block(inode, iblock, bh, 0);
 			if (!buffer_mapped(bh)) {
-				memset(bh->b_data, 0, blocksize);
+				if (!kaddr)
+					kaddr = kmap(page);
+				memset((char *)(kaddr + i*blocksize), 0, blocksize);
 				set_bit(BH_Uptodate, &bh->b_state);
 				continue;
 			}
@@ -2033,7 +2040,7 @@
 		atomic_inc(&bh->b_count);
 		arr[nr] = bh;
 		nr++;
-	} while (iblock++, (bh = bh->b_this_page) != head);
+	} while (i++, iblock++, (bh = bh->b_this_page) != head);
 
 	++current->maj_flt;
 	if (nr) {
@@ -2048,6 +2055,8 @@
 		SetPageUptodate(page);
 		UnlockPage(page);
 	}
+	if (kaddr)
+		kunmap(page);
 	return 0;
 }
 
@@ -2057,8 +2066,7 @@
  */
 static int grow_buffers(int size)
 {
-	unsigned long page;
-	struct page * page_map;
+	struct page * page;
 	struct buffer_head *bh, *tmp;
 	struct buffer_head * insert_point;
 	int isize;
@@ -2068,8 +2076,9 @@
 		return 0;
 	}
 
-	if (!(page = __get_free_page(GFP_BUFFER)))
-		return 0;
+	page = alloc_page(GFP_BUFFER);
+	if (!page)
+		goto out;
 	bh = create_buffers(page, size, 0);
 	if (!bh)
 		goto no_buffer_head;
@@ -2099,14 +2108,14 @@
 	free_list[isize].list = bh;
 	spin_unlock(&free_list[isize].lock);
 
-	page_map = mem_map + MAP_NR(page);
-	page_map->buffers = bh;
-	lru_cache_add(page_map);
+	page->buffers = bh;
+	lru_cache_add(page);
 	atomic_inc(&buffermem_pages);
 	return 1;
 
 no_buffer_head:
-	free_page(page);
+	__free_page(page);
+out:
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.26/linux/fs/coda/sysctl.c linux/fs/coda/sysctl.c
--- v2.3.26/linux/fs/coda/sysctl.c	Mon Nov  1 13:56:27 1999
+++ linux/fs/coda/sysctl.c	Thu Nov 11 16:57:31 1999
@@ -478,15 +478,6 @@
 
 struct proc_dir_entry* proc_fs_coda;
 
-static void coda_proc_modcount(struct inode *inode, int fill)
-{
-	if (fill)
-		MOD_INC_USE_COUNT;
-	else
-		MOD_DEC_USE_COUNT;
-			
-}
-
 #endif
 
 #define coda_proc_create(name,get_info) \
@@ -502,7 +493,7 @@
 
 #ifdef CONFIG_PROC_FS
 	proc_fs_coda = create_proc_entry("coda", S_IFDIR, proc_root_fs);
-	proc_fs_coda->fill_inode = &coda_proc_modcount;
+	proc_fs_coda->owner = THIS_MODULE;
 	coda_proc_create("vfs_stats", coda_vfs_stats_get_info);
 	coda_proc_create("upcall_stats", coda_upcall_stats_get_info);
 	coda_proc_create("permission_stats", coda_permission_stats_get_info);
diff -u --recursive --new-file v2.3.26/linux/fs/exec.c linux/fs/exec.c
--- v2.3.26/linux/fs/exec.c	Mon Nov  1 13:56:27 1999
+++ linux/fs/exec.c	Thu Nov 11 10:33:42 1999
@@ -225,17 +225,13 @@
 			page = bprm->page[i];
 			new = 0;
 			if (!page) {
-				/*
-				 * Cannot yet use highmem page because
-				 * we cannot sleep with a kmap held.
-				 */
-				page = __get_pages(GFP_USER, 0);
+				page = alloc_page(GFP_HIGHUSER);
 				bprm->page[i] = page;
 				if (!page)
 					return -ENOMEM;
 				new = 1;
 			}
-			kaddr = (char *)kmap(page, KM_WRITE);
+			kaddr = (char *)kmap(page);
 
 			if (new && offset)
 				memset(kaddr, 0, offset);
@@ -247,7 +243,7 @@
 			}
 			err = copy_from_user(kaddr + offset, str, bytes_to_copy);
 			flush_page_to_ram(page);
-			kunmap((unsigned long)kaddr, KM_WRITE);
+			kunmap(page);
 
 			if (err)
 				return -EFAULT; 
@@ -462,6 +458,7 @@
 	/*
 	 * 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 +497,7 @@
 			
 	flush_signal_handlers(current);
 	flush_old_files(current->files);
+	task_unlock(current);
 
 	return 0;
 
@@ -508,6 +506,7 @@
 		kfree(current->sig);
 flush_failed:
 	current->sig = oldsig;
+	task_unlock(current);
 	return retval;
 }
 
@@ -681,12 +680,12 @@
 			if (offset != PAGE_SIZE)
 				continue;
 			offset = 0;
-			kunmap((unsigned long)kaddr, KM_WRITE);
+			kunmap(page);
 inside:
 			page = bprm->page[bprm->p/PAGE_SIZE];
-			kaddr = (char *)kmap(page, KM_WRITE);
+			kaddr = (char *)kmap(page);
 		}
-		kunmap((unsigned long)kaddr, KM_WRITE);
+		kunmap(page);
 		bprm->argc--;
 	}
 }
diff -u --recursive --new-file v2.3.26/linux/fs/ext2/file.c linux/fs/ext2/file.c
--- v2.3.26/linux/fs/ext2/file.c	Sun Nov  7 16:37:34 1999
+++ linux/fs/ext2/file.c	Tue Nov  9 10:05:44 1999
@@ -62,6 +62,8 @@
 		case 1:
 			offset += file->f_pos;
 	}
+	if (offset<0)
+		return -EINVAL;
 	if (((unsigned long long) offset >> 32) != 0) {
 		if (offset > ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(inode->i_sb)])
 			return -EINVAL;
diff -u --recursive --new-file v2.3.26/linux/fs/ext2/ioctl.c linux/fs/ext2/ioctl.c
--- v2.3.26/linux/fs/ext2/ioctl.c	Mon Nov  1 13:56:27 1999
+++ linux/fs/ext2/ioctl.c	Mon Nov  8 10:42:35 1999
@@ -23,7 +23,7 @@
 	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 -u --recursive --new-file v2.3.26/linux/fs/minix/bitmap.c linux/fs/minix/bitmap.c
--- v2.3.26/linux/fs/minix/bitmap.c	Mon Aug  9 12:29:00 1999
+++ linux/fs/minix/bitmap.c	Tue Nov  9 15:02:01 1999
@@ -251,13 +251,15 @@
 	struct buffer_head * bh;
 	int i,j;
 
-	if (!dir || !(inode = get_empty_inode()))
+	inode = get_empty_inode();
+	if (!inode)
 		return NULL;
 	sb = dir->i_sb;
 	inode->i_sb = sb;
 	inode->i_flags = 0;
 	j = 8192;
 	bh = NULL;
+	lock_super(sb);
 	for (i = 0; i < sb->u.minix_sb.s_imap_blocks; i++) {
 		bh = inode->i_sb->u.minix_sb.s_imap[i];
 		if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192)
@@ -265,17 +267,20 @@
 	}
 	if (!bh || j >= 8192) {
 		iput(inode);
+		unlock_super(sb);
 		return NULL;
 	}
 	if (minix_set_bit(j,bh->b_data)) {	/* shouldn't happen */
 		printk("new_inode: bit already set");
 		iput(inode);
+		unlock_super(sb);
 		return NULL;
 	}
 	mark_buffer_dirty(bh, 1);
 	j += i*8192;
 	if (!j || j > inode->i_sb->u.minix_sb.s_ninodes) {
 		iput(inode);
+		unlock_super(sb);
 		return NULL;
 	}
 	inode->i_nlink = 1;
diff -u --recursive --new-file v2.3.26/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
--- v2.3.26/linux/fs/ncpfs/dir.c	Mon Nov  1 13:56:27 1999
+++ linux/fs/ncpfs/dir.c	Mon Nov  8 18:01:12 1999
@@ -405,14 +405,13 @@
 {
 	unsigned long dent_addr = (unsigned long) dentry;
 	unsigned long min_addr = PAGE_OFFSET;
-	unsigned long max_addr = min_addr + (max_mapnr << PAGE_SHIFT);
 	unsigned long align_mask = 0x0F;
 	unsigned int len;
 	int valid = 0;
 
 	if (dent_addr < min_addr)
 		goto bad_addr;
-	if (dent_addr > max_addr - sizeof(struct dentry))
+	if (dent_addr > (unsigned long)high_memory - sizeof(struct dentry))
 		goto bad_addr;
 	if ((dent_addr & ~align_mask) != dent_addr)
 		goto bad_align;
diff -u --recursive --new-file v2.3.26/linux/fs/ncpfs/mmap.c linux/fs/ncpfs/mmap.c
--- v2.3.26/linux/fs/ncpfs/mmap.c	Sun Nov  7 16:37:34 1999
+++ linux/fs/ncpfs/mmap.c	Thu Nov 11 10:33:42 1999
@@ -43,7 +43,7 @@
 	int bufsize;
 	int pos;
 
-	page = __get_pages(GFP_KERNEL, 0);
+	page = alloc_page(GFP_KERNEL);
 	if (!page)
 		return page;
 	pg_addr = page_address(page);
diff -u --recursive --new-file v2.3.26/linux/fs/nfsd/nfsctl.c linux/fs/nfsd/nfsctl.c
--- v2.3.26/linux/fs/nfsd/nfsctl.c	Sun Nov  7 16:37:34 1999
+++ linux/fs/nfsd/nfsctl.c	Thu Nov 11 16:57:31 1999
@@ -257,21 +257,6 @@
 extern int (*do_nfsservctl)(int, void *, void *);
 
 /*
- * This is called as the fill_inode function when an inode
- * is going into (fill = 1) or out of service (fill = 0).
- *
- * We use it here to make sure the module can't be unloaded
- * while a /proc inode is in use.
- */
-void nfsd_modcount(struct inode *inode, int fill)
-{
-	if (fill)
-		MOD_INC_USE_COUNT;
-	else
-		MOD_DEC_USE_COUNT;
-}
-
-/*
  * Initialize the module
  */
 int
diff -u --recursive --new-file v2.3.26/linux/fs/nfsd/stats.c linux/fs/nfsd/stats.c
--- v2.3.26/linux/fs/nfsd/stats.c	Thu Jan  7 09:28:47 1999
+++ linux/fs/nfsd/stats.c	Thu Nov 11 16:57:31 1999
@@ -17,6 +17,7 @@
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
+#include <linux/module.h>
 
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/stats.h>
@@ -77,9 +78,7 @@
 
 	if ((ent = svc_proc_register(&nfsd_svcstats)) != 0) {
 		ent->read_proc = nfsd_proc_read;
-#ifdef MODULE
-		ent->fill_inode = nfsd_modcount;
-#endif
+		ent->owner = THIS_MODULE;
 	}
 }
 
diff -u --recursive --new-file v2.3.26/linux/fs/proc/Makefile linux/fs/proc/Makefile
--- v2.3.26/linux/fs/proc/Makefile	Sun Nov  7 16:37:34 1999
+++ linux/fs/proc/Makefile	Tue Nov  9 11:56:37 1999
@@ -8,8 +8,8 @@
 # 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 \
-		kmsg.o scsi.o proc_tty.o sysvipc.o proc_misc.o kcore.o
+O_OBJS   := inode.o root.o base.o generic.o array.o \
+		kmsg.o proc_tty.o proc_misc.o kcore.o
 ifdef CONFIG_OMIRR
 O_OBJS   := $(O_OBJS) omirr.o
 endif
diff -u --recursive --new-file v2.3.26/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.3.26/linux/fs/proc/array.c	Sun Nov  7 16:37:34 1999
+++ linux/fs/proc/array.c	Tue Nov  9 19:39:07 1999
@@ -46,6 +46,10 @@
  *
  * Gerhard Wichert   :  added BIGMEM support
  * Siemens AG           <Gerhard.Wichert@pdb.siemens.de>
+ *
+ * Al Viro & Jeff Garzik :  moved most of the thing into base.c and
+ *			 :  proc_misc.c. The rest may eventually go into
+ *			 :  base.c too.
  */
 
 #include <linux/types.h>
@@ -70,401 +74,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 +264,27 @@
 }
 
 
-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 +292,7 @@
 	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 +302,55 @@
 			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 +360,15 @@
 		 * 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;
 }
 		
@@ -813,9 +403,9 @@
 		++*pages;
 		if (pte_dirty(page))
 			++*dirty;
-		if (MAP_NR(pte_page(page)) >= max_mapnr)
+		if (pte_pagenr(page) >= max_mapnr)
 			continue;
-		if (page_count(mem_map + MAP_NR(pte_page(page))) > 1)
+		if (page_count(pte_page(page)) > 1)
 			++*shared;
 	} while (address < end);
 }
@@ -855,9 +445,9 @@
 	}
 }
 
-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 +474,6 @@
 			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 +512,10 @@
 #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 +531,19 @@
 	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 +602,9 @@
 		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 +623,34 @@
 		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 -u --recursive --new-file v2.3.26/linux/fs/proc/base.c linux/fs/proc/base.c
--- v2.3.26/linux/fs/proc/base.c	Tue Aug 31 17:29:14 1999
+++ linux/fs/proc/base.c	Mon Nov  8 14:28:34 1999
@@ -4,6 +4,13 @@
  *  Copyright (C) 1991, 1992 Linus Torvalds
  *
  *  proc base directory handling functions
+ *
+ *  1999, Al Viro. Rewritten. Now it covers the whole per-process part.
+ *  Instead of using magical inumbers to determine the kind of object
+ *  we allocate and fill in-core inodes upon lookup. They don't even
+ *  go into icache. We cache the reference to task_struct upon lookup too.
+ *  Eventually it should become a filesystem in its own. We don't use the
+ *  rest of procfs anymore.
  */
 
 #include <asm/uaccess.h>
@@ -14,28 +21,336 @@
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/init.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 */
-};
+#include <linux/file.h>
 
 /*
- * proc directories can do almost nothing..
+ * For hysterical raisins we keep the same inumbers as in the old procfs.
+ * Feel free to change the macro below - just keep the range distinct from
+ * inumbers of the rest of procfs (currently those are in 0x0000--0xffff).
+ * As soon as we'll get a separate superblock we will be able to forget
+ * about magical ranges too.
  */
-static struct inode_operations proc_base_inode_operations = {
-	&proc_base_operations,	/* default base directory file-ops */
+
+#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,
+};
+
+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	   */
+};
+
+static 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 +365,653 @@
 	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;
+
+	/* 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;
+}
 
-	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;
+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 */
 };
 
+/* 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;
+};
+
+enum pid_directory_inos {
+	PROC_PID_INO = 2,
+	PROC_PID_STATUS,
+	PROC_PID_MEM,
+	PROC_PID_CWD,
+	PROC_PID_ROOT,
+	PROC_PID_EXE,
+	PROC_PID_FD,
+	PROC_PID_ENVIRON,
+	PROC_PID_CMDLINE,
+	PROC_PID_STAT,
+	PROC_PID_STATM,
+	PROC_PID_MAPS,
 #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,
+	PROC_PID_RINGBUF,
+#endif
+	PROC_PID_CPU,
+	PROC_PID_FD_DIR = 0x8000,	/* 0x8000-0xffff */
 };
+
+#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
+
+#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_make_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;
+}
 
-#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,
+/* 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 *) */
+};
+
+/* 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_make_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 */
 };
-#endif
 
-void __init proc_base_init(void)
+/*
+ * 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_make_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_make_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);
+}
 
+#define PROC_NUMBUF 10
+#define PROC_MAXPIDS 20
 
+/*
+ * Get a few pid's to return for filldir - we need to hold the
+ * tasklist lock while doing this, and we must release it before
+ * we actually do the filldir itself, so we use a temp buffer..
+ */
+static int get_pid_list(int index, unsigned int *pids)
+{
+	struct task_struct *p;
+	int nr_pids = 0;
 
+	index -= FIRST_PROCESS_ENTRY;
+	read_lock(&tasklist_lock);
+	for_each_task(p) {
+		int pid = p->pid;
+		if (!pid)
+			continue;
+		if (--index >= 0)
+			continue;
+		pids[nr_pids] = pid;
+		nr_pids++;
+		if (nr_pids >= PROC_MAXPIDS)
+			break;
+	}
+	read_unlock(&tasklist_lock);
+	return nr_pids;
+}
+
+int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
+{
+	unsigned int pid_array[PROC_MAXPIDS];
+	char buf[PROC_NUMBUF];
+	unsigned int nr = filp->f_pos;
+	unsigned int nr_pids, i;
+
+	nr_pids = get_pid_list(nr, pid_array);
+
+	for (i = 0; i < nr_pids; i++) {
+		int pid = pid_array[i];
+		ino_t ino = fake_ino(pid,PROC_PID_INO);
+		unsigned long j = PROC_NUMBUF;
+
+		do {
+			j--;
+			buf[j] = '0' + (pid % 10);
+			pid /= 10;
+		} while (pid);
+
+		if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino) < 0)
+			break;
+		filp->f_pos++;
+	}
+	return 0;
+}
diff -u --recursive --new-file v2.3.26/linux/fs/proc/fd.c linux/fs/proc/fd.c
--- v2.3.26/linux/fs/proc/fd.c	Mon Oct  4 15:49:30 1999
+++ linux/fs/proc/fd.c	Wed Dec 31 16:00:00 1969
@@ -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 -u --recursive --new-file v2.3.26/linux/fs/proc/inode-alloc.txt linux/fs/proc/inode-alloc.txt
--- v2.3.26/linux/fs/proc/inode-alloc.txt	Fri May  8 18:10:30 1998
+++ linux/fs/proc/inode-alloc.txt	Thu Nov 11 16:57:31 1999
@@ -1,50 +1,14 @@
-Inode allocations in the proc-fs (hex-numbers):
+Current inode allocations in the proc-fs (hex-numbers):
 
   00000000		reserved
-  00000001-00000fff	static entries
+  00000001-00000fff	static entries	(goners)
        001		root-ino
-       002		load-avg
-       003		uptime
-       ...
-       080		net/*
-       ...
-       100		scsi/*
-       ...
-       xxx		mca/*
-       ...
-       yyy		bus/*
-       ...
-       fff		end
 
   00001000-00001fff	dynamic entries
-
   00002000-00002fff	openprom entries
-
   0001xxxx-7fffxxxx	pid-dir entries for pid 1-7fff
-      0000		unused
-      0001		unused
-      0002		pid
-      0003		pid/status
-       ...
-      0008		pid/fd
-       ...
-      00xx-00ff		unused
-      01xx		pid/fd/* for fd 0-ff
-       ...
-      01ff		end
-      0200-ffff		unused
-
   80000000-ffffffff	unused
 
-
-
-New allocation:
-
-  00000000-0000ffff	unchanged
-
-  0001xxxx-7fffxxxx	pid-dir entries for pid 1-7fff
-      0000-00ff		unchanged
-      0100-7fff		unused
-      8000-ffff		pid/fd/* for fd 0-7fff
-
-  80000000-ffffffff	unchanged
+Goal:
+	a) once we'll split the thing into several virtual filesystems we
+	will get rid of magical ranges (and this file, BTW).
diff -u --recursive --new-file v2.3.26/linux/fs/proc/inode.c linux/fs/proc/inode.c
--- v2.3.26/linux/fs/proc/inode.c	Sun Jul  4 10:18:52 1999
+++ linux/fs/proc/inode.c	Thu Nov 11 16:57:31 1999
@@ -14,6 +14,7 @@
 #include <linux/locks.h>
 #include <linux/limits.h>
 #include <linux/config.h>
+#include <linux/module.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -51,9 +52,7 @@
 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,18 +70,16 @@
 {
 	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) {
-		/*
-		 * Call the fill_inode hook to release module counts.
-		 */
-		if (de->fill_inode)
-			de->fill_inode(inode, 0);
+		if (de->owner)
+			__MOD_DEC_USE_COUNT(de->owner);
 		de_put(de);
 	}
 }
@@ -142,113 +139,6 @@
 	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 +159,9 @@
 		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) {
@@ -291,12 +176,8 @@
 			inode->i_op = de->ops;
 		if (de->nlink)
 			inode->i_nlink = de->nlink;
-		/*
-		 * The fill_inode routine should use this call 
-		 * to increment module counts, if necessary.
-		 */
-		if (de->fill_inode)
-			de->fill_inode(inode, 1);
+		if (de->owner)
+			__MOD_INC_USE_COUNT(de->owner);
 	}
 	/*
 	 * Fixup the root inode's nlink value
@@ -366,63 +247,7 @@
 
 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 -u --recursive --new-file v2.3.26/linux/fs/proc/kcore.c linux/fs/proc/kcore.c
--- v2.3.26/linux/fs/proc/kcore.c	Sun Nov  7 16:37:34 1999
+++ linux/fs/proc/kcore.c	Wed Nov 10 19:47:57 1999
@@ -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 vmalloc'd data structures (ELF only), Tigran Aivazian <tigran@sco.com>
  */
 
 #include <linux/config.h>
@@ -14,13 +15,38 @@
 #include <linux/a.out.h>
 #include <linux/elf.h>
 #include <linux/elfcore.h>
+#include <linux/vmalloc.h>
+#include <linux/proc_fs.h>
 #include <asm/uaccess.h>
 
+
+static int open_kcore(struct inode * inode, struct file * filp)
+{
+	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
+}
+
+static 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,
+};
+
 #ifdef CONFIG_KCORE_AOUT
-ssize_t read_kcore(struct file * file, char * buf,
+static ssize_t read_kcore(struct file * file, char * buf,
 			 size_t count, loff_t *ppos)
 {
-	unsigned long p = *ppos, memsize;
+	unsigned long long p = *ppos, memsize;
 	ssize_t read;
 	ssize_t count1;
 	char * pnt;
@@ -77,8 +103,7 @@
 	*ppos += read;
 	return read;
 }
-#else
-
+#else /* CONFIG_KCORE_AOUT */
 
 #define roundup(x, y)  ((((x)+((y)-1))/(y))*(y))
 
@@ -93,6 +118,31 @@
 
 extern char saved_command_line[];
 
+static size_t get_kcore_size(int *num_vma, int *elf_buflen)
+{
+	size_t try, size = 0;
+	struct vm_struct *m;
+
+	*num_vma = 0;
+	if (!vmlist) {
+		*elf_buflen = PAGE_SIZE;
+		return ((size_t)high_memory - PAGE_OFFSET + PAGE_SIZE);
+	}
+
+	for (m=vmlist; m; m=m->next) {
+		try = (size_t)m->addr + m->size;
+		if (try > size)
+			size = try;
+		*num_vma = *num_vma + 1;
+	}
+	*elf_buflen =	sizeof(struct elfhdr) + 
+			(*num_vma + 2)*sizeof(struct elf_phdr) + 
+			3 * sizeof(struct memelfnote);
+	*elf_buflen = PAGE_ALIGN(*elf_buflen);
+	return (size - PAGE_OFFSET + *elf_buflen);
+}
+
+
 /*****************************************************************************/
 /*
  * determine size of ELF note
@@ -135,118 +185,124 @@
 	return bufp;
 } /* end storenote() */
 
-/*****************************************************************************/
 /*
  * store an ELF coredump header in the supplied buffer
- * - assume the memory image is the size specified
+ * num_vma is the number of elements in vmlist
  */
-static void elf_kcore_store_hdr(char *bufp, size_t size, off_t dataoff)
+static void elf_kcore_store_hdr(char *bufp, int num_vma, int elf_buflen)
 {
 	struct elf_prstatus prstatus;	/* NT_PRSTATUS */
-	struct elf_prpsinfo psinfo;	/* NT_PRPSINFO */
-	struct elf_phdr *nhdr, *dhdr;
+	struct elf_prpsinfo prpsinfo;	/* NT_PRPSINFO */
+	struct elf_phdr *nhdr, *phdr;
 	struct elfhdr *elf;
 	struct memelfnote notes[3];
 	off_t offset = 0;
+	struct vm_struct *m;
 
-	/* acquire an ELF header block from the buffer */
+	/* setup ELF header */
 	elf = (struct elfhdr *) bufp;
-	bufp += sizeof(*elf);
-	offset += sizeof(*elf);
-
-	/* set up header */
-	memcpy(elf->e_ident,ELFMAG,SELFMAG);
+	bufp += sizeof(struct elfhdr);
+	offset += sizeof(struct elfhdr);
+	memcpy(elf->e_ident, ELFMAG, SELFMAG);
 	elf->e_ident[EI_CLASS]	= ELF_CLASS;
 	elf->e_ident[EI_DATA]	= ELF_DATA;
 	elf->e_ident[EI_VERSION]= EV_CURRENT;
-	memset(elf->e_ident+EI_PAD,0,EI_NIDENT-EI_PAD);
-
+	memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
 	elf->e_type	= ET_CORE;
 	elf->e_machine	= ELF_ARCH;
 	elf->e_version	= EV_CURRENT;
 	elf->e_entry	= 0;
-	elf->e_phoff	= sizeof(*elf);
+	elf->e_phoff	= sizeof(struct elfhdr);
 	elf->e_shoff	= 0;
 	elf->e_flags	= 0;
-	elf->e_ehsize	= sizeof(*elf);
+	elf->e_ehsize	= sizeof(struct elfhdr);
 	elf->e_phentsize= sizeof(struct elf_phdr);
-	elf->e_phnum	= 2;			/* no. of segments */
+	elf->e_phnum	= 2 + num_vma;
 	elf->e_shentsize= 0;
 	elf->e_shnum	= 0;
 	elf->e_shstrndx	= 0;
 
-	/* acquire an ELF program header blocks from the buffer for notes */
+	/* setup ELF PT_NOTE program header */
 	nhdr = (struct elf_phdr *) bufp;
-	bufp += sizeof(*nhdr);
-	offset += sizeof(*nhdr);
-
-	/* store program headers for notes dump */
+	bufp += sizeof(struct elf_phdr);
+	offset += sizeof(struct elf_phdr);
 	nhdr->p_type	= PT_NOTE;
 	nhdr->p_offset	= 0;
 	nhdr->p_vaddr	= 0;
 	nhdr->p_paddr	= 0;
+	nhdr->p_filesz	= 0;
 	nhdr->p_memsz	= 0;
 	nhdr->p_flags	= 0;
 	nhdr->p_align	= 0;
 
-	/* acquire an ELF program header blocks from the buffer for data */
-	dhdr = (struct elf_phdr *) bufp;
-	bufp += sizeof(*dhdr);
-	offset += sizeof(*dhdr);
-
-	/* store program headers for data dump */
-	dhdr->p_type	= PT_LOAD;
-	dhdr->p_flags	= PF_R|PF_W|PF_X;
-	dhdr->p_offset	= dataoff;
-	dhdr->p_vaddr	= PAGE_OFFSET;
-	dhdr->p_paddr	= __pa(PAGE_OFFSET);
-	dhdr->p_filesz	= size;
-	dhdr->p_memsz	= size;
-	dhdr->p_align	= PAGE_SIZE;
+	/* setup ELF PT_LOAD program header */
+	phdr = (struct elf_phdr *) bufp;
+	bufp += sizeof(struct elf_phdr);
+	offset += sizeof(struct elf_phdr);
+	phdr->p_type	= PT_LOAD;
+	phdr->p_flags	= PF_R|PF_W|PF_X;
+	phdr->p_offset	= elf_buflen;
+	phdr->p_vaddr	= PAGE_OFFSET;
+	phdr->p_paddr	= __pa(PAGE_OFFSET);
+	phdr->p_filesz	= phdr->p_memsz = ((unsigned long)high_memory - PAGE_OFFSET);
+	phdr->p_align	= PAGE_SIZE;
+
+	for (m=vmlist; m; m=m->next) {
+		phdr = (struct elf_phdr *) bufp;
+		bufp += sizeof(struct elf_phdr);
+		offset += sizeof(struct elf_phdr);
+
+		phdr->p_type	= PT_LOAD;
+		phdr->p_flags	= PF_R|PF_W|PF_X;
+		phdr->p_offset	= (size_t)m->addr - PAGE_OFFSET + elf_buflen;
+		phdr->p_vaddr	= (size_t)m->addr;
+		phdr->p_paddr	= __pa(m);
+		phdr->p_filesz	= phdr->p_memsz	= m->size;
+		phdr->p_align	= PAGE_SIZE;
+	}
 
 	/*
 	 * Set up the notes in similar form to SVR4 core dumps made
 	 * with info from their /proc.
 	 */
 	nhdr->p_offset	= offset;
-	nhdr->p_filesz	= 0;
 
 	/* set up the process status */
 	notes[0].name = "CORE";
 	notes[0].type = NT_PRSTATUS;
-	notes[0].datasz = sizeof(prstatus);
+	notes[0].datasz = sizeof(struct elf_prstatus);
 	notes[0].data = &prstatus;
 
-	memset(&prstatus,0,sizeof(prstatus));
+	memset(&prstatus, 0, sizeof(struct elf_prstatus));
 
 	nhdr->p_filesz	= notesize(&notes[0]);
-	bufp = storenote(&notes[0],bufp);
+	bufp = storenote(&notes[0], bufp);
 
 	/* set up the process info */
 	notes[1].name	= "CORE";
 	notes[1].type	= NT_PRPSINFO;
-	notes[1].datasz	= sizeof(psinfo);
-	notes[1].data	= &psinfo;
+	notes[1].datasz	= sizeof(struct elf_prpsinfo);
+	notes[1].data	= &prpsinfo;
 
-	memset(&psinfo,0,sizeof(psinfo));
-	psinfo.pr_state	= 0;
-	psinfo.pr_sname	= 'R';
-	psinfo.pr_zomb	= 0;
+	memset(&prpsinfo, 0, sizeof(struct elf_prpsinfo));
+	prpsinfo.pr_state	= 0;
+	prpsinfo.pr_sname	= 'R';
+	prpsinfo.pr_zomb	= 0;
 
-	strcpy(psinfo.pr_fname,"vmlinux");
-	strncpy(psinfo.pr_psargs,saved_command_line,ELF_PRARGSZ);
+	strcpy(prpsinfo.pr_fname, "vmlinux");
+	strncpy(prpsinfo.pr_psargs, saved_command_line, ELF_PRARGSZ);
 
 	nhdr->p_filesz	= notesize(&notes[1]);
-	bufp = storenote(&notes[1],bufp);
+	bufp = storenote(&notes[1], bufp);
 
 	/* set up the task structure */
 	notes[2].name	= "CORE";
 	notes[2].type	= NT_TASKSTRUCT;
-	notes[2].datasz	= sizeof(*current);
+	notes[2].datasz	= sizeof(struct task_struct);
 	notes[2].data	= current;
 
 	nhdr->p_filesz	= notesize(&notes[2]);
-	bufp = storenote(&notes[2],bufp);
+	bufp = storenote(&notes[2], bufp);
 
 } /* end elf_kcore_store_hdr() */
 
@@ -254,85 +310,79 @@
 /*
  * read from the ELF header and then kernel memory
  */
-ssize_t read_kcore(struct file *file, char *buffer, size_t buflen,
+static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen,
 			      loff_t *fpos)
 {
-	ssize_t acc;
+	ssize_t acc = 0;
 	size_t size, tsz;
-	char *page;
-
-	/* work out how much file we allow to be read */
-	size = ((size_t)high_memory - PAGE_OFFSET) + PAGE_SIZE;
-	acc = 0;
+	char * elf_buffer;
+	int elf_buflen = 0, num_vma = 0;
 
-	/* see if file pointer already beyond EOF */
-	if (buflen==0 || *fpos>=size)
+	/* XXX we need to somehow lock vmlist between here
+	 * and after elf_kcore_store_hdr() returns.
+	 * For now assume that num_vma does not change (TA)
+	 */
+	proc_root_kcore.size = size = get_kcore_size(&num_vma, &elf_buflen);
+	if (buflen == 0 || *fpos >= size)
 		return 0;
 
 	/* trim buflen to not go beyond EOF */
-	if (buflen > size-*fpos)
+	if (buflen > size - *fpos)
 		buflen = size - *fpos;
 
 	/* construct an ELF core header if we'll need some of it */
-	if (*fpos<PAGE_SIZE) {
-		/* get a buffer */
-		page = (char*) __get_free_page(GFP_KERNEL);
-		if (!page)
-			return -ENOMEM;
-
-		tsz = PAGE_SIZE-*fpos;
+	if (*fpos < elf_buflen) {
+		tsz = elf_buflen - *fpos;
 		if (buflen < tsz)
 			tsz = buflen;
-
-		/* create a header */
-		memset(page,0,PAGE_SIZE);
-		elf_kcore_store_hdr(page,size-PAGE_SIZE,PAGE_SIZE);
-
-		/* copy data to the users buffer */
-		copy_to_user(buffer,page,tsz);
+		elf_buffer = kmalloc(elf_buflen, GFP_KERNEL);
+		if (!elf_buffer)
+			return -ENOMEM;
+		memset(elf_buffer, 0, elf_buflen);
+		elf_kcore_store_hdr(elf_buffer, num_vma, elf_buflen);
+		copy_to_user(buffer, elf_buffer, tsz);
+		kfree(elf_buffer);
 		buflen -= tsz;
 		*fpos += tsz;
 		buffer += tsz;
 		acc += tsz;
 
-		free_page((unsigned long) page);
-
 		/* leave now if filled buffer already */
-		if (buflen==0)
+		if (buflen == 0)
 			return tsz;
 	}
 
 	/* where page 0 not mapped, write zeros into buffer */
 #if defined (__i386__) || defined (__mc68000__)
-	if (*fpos < PAGE_SIZE*2) {
+	if (*fpos < PAGE_SIZE + elf_buflen) {
 		/* work out how much to clear */
-		tsz = PAGE_SIZE*2 - *fpos;
+		tsz = PAGE_SIZE + elf_buflen - *fpos;
 		if (buflen < tsz)
 			tsz = buflen;
 
 		/* write zeros to buffer */
-		clear_user(buffer,tsz);
+		clear_user(buffer, tsz);
 		buflen -= tsz;
 		*fpos += tsz;
 		buffer += tsz;
 		acc += tsz;
 
 		/* leave now if filled buffer already */
-		if (buflen==0)
+		if (buflen == 0)
 			return tsz;
 	}
 #endif
 
 	/* fill the remainder of the buffer from kernel VM space */
 #if defined (__i386__) || defined (__mc68000__)
-	copy_to_user(buffer,__va(*fpos-PAGE_SIZE),buflen);
+	copy_to_user(buffer, __va(*fpos - PAGE_SIZE), buflen);
 #else
-	copy_to_user(buffer,__va(*fpos),buflen);
+	copy_to_user(buffer, __va(*fpos), buflen);
 #endif
 	acc += buflen;
 	*fpos += buflen;
 
 	return acc;
 
-} /* end read_kcore() */
-#endif
+}
+#endif /* CONFIG_KCORE_AOUT */
diff -u --recursive --new-file v2.3.26/linux/fs/proc/link.c linux/fs/proc/link.c
--- v2.3.26/linux/fs/proc/link.c	Wed Jul 28 10:45:39 1999
+++ linux/fs/proc/link.c	Wed Dec 31 16:00:00 1969
@@ -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 -u --recursive --new-file v2.3.26/linux/fs/proc/mem.c linux/fs/proc/mem.c
--- v2.3.26/linux/fs/proc/mem.c	Mon Nov  1 13:56:27 1999
+++ linux/fs/proc/mem.c	Wed Dec 31 16:00:00 1969
@@ -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 -u --recursive --new-file v2.3.26/linux/fs/proc/net.c linux/fs/proc/net.c
--- v2.3.26/linux/fs/proc/net.c	Sat Jun 26 12:04:40 1999
+++ linux/fs/proc/net.c	Wed Dec 31 16:00:00 1969
@@ -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 -u --recursive --new-file v2.3.26/linux/fs/proc/proc_misc.c linux/fs/proc/proc_misc.c
--- v2.3.26/linux/fs/proc/proc_misc.c	Mon Nov  1 13:56:27 1999
+++ linux/fs/proc/proc_misc.c	Thu Nov 11 10:33:42 1999
@@ -17,8 +17,6 @@
 #include <linux/kernel.h>
 #include <linux/kernel_stat.h>
 #include <linux/tty.h>
-#include <linux/user.h>
-#include <linux/a.out.h>
 #include <linux/string.h>
 #include <linux/mman.h>
 #include <linux/proc_fs.h>
@@ -30,6 +28,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>
@@ -163,6 +162,8 @@
                 "Cached:    %8u kB\n"
                 "HighTotal: %8lu kB\n"
                 "HighFree:  %8lu kB\n"
+                "LowTotal:  %8lu kB\n"
+                "LowFree:   %8lu kB\n"
                 "SwapTotal: %8lu kB\n"
                 "SwapFree:  %8lu kB\n",
                 K(i.totalram),
@@ -172,6 +173,8 @@
                 K(atomic_read(&page_cache_size)),
                 K(i.totalhigh),
                 K(i.freehigh),
+                K(i.totalram-i.totalhigh),
+                K(i.freeram-i.freehigh),
                 K(i.totalswap),
                 K(i.freeswap));
 
@@ -545,12 +548,80 @@
 	return len;
 }
 
+/*
+ * 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 +684,7 @@
 	/* 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 = (size_t)high_memory - PAGE_OFFSET + PAGE_SIZE;
 	if (prof_shift) {
 		proc_register(&proc_root, &proc_root_profile);
 		proc_root_profile.size = (1+prof_len) * sizeof(unsigned int);
diff -u --recursive --new-file v2.3.26/linux/fs/proc/procfs_syms.c linux/fs/proc/procfs_syms.c
--- v2.3.26/linux/fs/proc/procfs_syms.c	Mon Nov  1 13:56:27 1999
+++ linux/fs/proc/procfs_syms.c	Thu Nov 11 16:57:31 1999
@@ -3,14 +3,6 @@
 #include <linux/fs.h>
 #include <linux/proc_fs.h>
 
-/*
- * This is all required so that if we load all of scsi as a module,
- * that the scsi code will be able to talk to the /proc/scsi handling
- * in the procfs.
- */
-extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
-				       off_t offset, int length, int inout);
-extern struct inode_operations proc_scsi_inode_operations;
 extern struct proc_dir_entry *proc_sys_root;
 
 #ifdef CONFIG_SYSCTL
@@ -26,14 +18,6 @@
 EXPORT_SYMBOL(proc_dir_inode_operations);
 EXPORT_SYMBOL(proc_net);
 EXPORT_SYMBOL(proc_bus);
-
-/*
- * This is required so that if we load scsi later, that the
- * scsi code can attach to /proc/scsi in the correct manner.
- */
-EXPORT_SYMBOL(proc_scsi);
-EXPORT_SYMBOL(proc_scsi_inode_operations);
-EXPORT_SYMBOL(dispatch_scsi_info_ptr);
 
 #if defined(CONFIG_SUN_OPENPROMFS_MODULE)
 EXPORT_SYMBOL(proc_openprom_register);
diff -u --recursive --new-file v2.3.26/linux/fs/proc/root.c linux/fs/proc/root.c
--- v2.3.26/linux/fs/proc/root.c	Mon Nov  1 13:56:27 1999
+++ linux/fs/proc/root.c	Thu Nov 11 16:57:31 1999
@@ -22,11 +22,6 @@
 #include <linux/zorro.h>
 #endif
 
-/*
- * Offset of the first process in the /proc root directory..
- */
-#define FIRST_PROCESS_ENTRY 256
-
 static int proc_root_readdir(struct file *, void *, filldir_t);
 static struct dentry *proc_root_lookup(struct inode *,struct dentry *);
 static int proc_unlink(struct inode *, struct dentry *);
@@ -37,22 +32,12 @@
  * These are the generic /proc directory operations. They
  * use the in-memory "struct proc_dir_entry" tree to parse
  * the /proc directory.
- *
- * NOTE! The /proc/scsi directory currently does not correctly
- * build up the proc_dir_entry tree, and will show up empty.
  */
 static struct file_operations proc_dir_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 */
 };
 
 /*
@@ -62,23 +47,6 @@
 	&proc_dir_operations,	/* default net directory file-ops */
 	NULL,			/* create */
 	proc_lookup,		/* 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 */
 };
 
 /*
@@ -90,21 +58,6 @@
 	proc_lookup,		/* lookup */
 	NULL,			/* link	*/
 	proc_unlink,		/* unlink(struct inode *, struct dentry *) */
-	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 */
 };
 
 /*
@@ -117,13 +70,6 @@
 	NULL,			/* read - bad */
 	NULL,			/* write - bad */
 	proc_root_readdir,	/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	NULL			/* no fsync */
 };
 
 /*
@@ -133,23 +79,6 @@
 	&proc_root_operations,	/* default base directory file-ops */
 	NULL,			/* create */
 	proc_root_lookup,	/* 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 */
 };
 
 /*
@@ -164,8 +93,7 @@
 	&proc_root, NULL
 };
 
-struct proc_dir_entry *proc_net, *proc_scsi, *proc_bus, *proc_sysvipc,
-		      *proc_root_fs, *proc_root_driver;
+struct proc_dir_entry *proc_net, *proc_bus, *proc_root_fs, *proc_root_driver;
 
 #ifdef CONFIG_MCA
 struct proc_dir_entry *proc_mca;
@@ -268,36 +196,12 @@
 	NULL,			/* read - bad */
 	NULL,			/* write - bad */
 	OPENPROM_DEFREADDIR,	/* 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 */
 };
 
 struct inode_operations proc_openprom_inode_operations = {
 	&proc_openprom_operations,/* default net directory file-ops */
 	NULL,			/* create */
 	OPENPROM_DEFLOOKUP,	/* 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 */
 };
 
 struct proc_dir_entry proc_openprom = {
@@ -321,6 +225,73 @@
 	return PROC_DYNAMIC_FIRST + i;
 }
 
+int proc_readlink(struct dentry * dentry, char * buffer, int buflen)
+{
+	struct inode *inode = dentry->d_inode;
+	struct proc_dir_entry * de;
+	char 	*page;
+	int len = 0;
+
+	de = (struct proc_dir_entry *) inode->u.generic_ip;
+	if (!de)
+		return -ENOENT;
+	if (!(page = (char*) __get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+
+	if (de->readlink_proc)
+		len = de->readlink_proc(de, page);
+
+	if (len > buflen)
+		len = buflen;
+
+	copy_to_user(buffer, page, len);
+	free_page((unsigned long) page);
+	return len;
+}
+
+struct dentry * proc_follow_link(struct dentry * dentry, struct dentry *base, unsigned int follow)
+{
+	struct inode *inode = dentry->d_inode;
+	struct proc_dir_entry * de;
+	char 	*page;
+	struct dentry *d;
+	int len = 0;
+
+	de = (struct proc_dir_entry *) inode->u.generic_ip;
+	if (!(page = (char*) __get_free_page(GFP_KERNEL)))
+		return NULL;
+
+	if (de->readlink_proc)
+		len = de->readlink_proc(de, page);
+
+	d = lookup_dentry(page, base, follow);
+	free_page((unsigned long) page);
+	return d;
+}
+
+static struct inode_operations proc_link_inode_operations = {
+	NULL,			/* no file-ops */
+	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 */
+	NULL,			/* permission */
+	NULL,			/* smap */
+	NULL			/* revalidate */
+};
+
 int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
 {
 	int	i;
@@ -433,50 +404,6 @@
 	return lookup_dentry(tmp, base, follow);
 }	
 
-int proc_readlink(struct dentry * dentry, char * buffer, int buflen)
-{
-	struct inode *inode = dentry->d_inode;
-	struct proc_dir_entry * de;
-	char 	*page;
-	int len = 0;
-
-	de = (struct proc_dir_entry *) inode->u.generic_ip;
-	if (!de)
-		return -ENOENT;
-	if (!(page = (char*) __get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
-
-	if (de->readlink_proc)
-		len = de->readlink_proc(de, page);
-
-	if (len > buflen)
-		len = buflen;
-
-	copy_to_user(buffer, page, len);
-	free_page((unsigned long) page);
-	return len;
-}
-
-struct dentry * proc_follow_link(struct dentry * dentry, struct dentry *base, unsigned int follow)
-{
-	struct inode *inode = dentry->d_inode;
-	struct proc_dir_entry * de;
-	char 	*page;
-	struct dentry *d;
-	int len = 0;
-
-	de = (struct proc_dir_entry *) inode->u.generic_ip;
-	if (!(page = (char*) __get_free_page(GFP_KERNEL)))
-		return NULL;
-
-	if (de->readlink_proc)
-		len = de->readlink_proc(de, page);
-
-	d = lookup_dentry(page, base, follow);
-	free_page((unsigned long) page);
-	return d;
-}
-
 static struct inode_operations proc_self_inode_operations = {
 	NULL,			/* no file-ops */
 	NULL,			/* create */
@@ -500,29 +427,6 @@
 	NULL			/* revalidate */
 };
 
-static struct inode_operations proc_link_inode_operations = {
-	NULL,			/* no file-ops */
-	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 */
-	NULL,			/* permission */
-	NULL,			/* smap */
-	NULL			/* revalidate */
-};
-
 static struct proc_dir_entry proc_root_self = {
 	0, 4, "self",
 	S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, 1, 0, 0,
@@ -533,21 +437,16 @@
 	0, 8, "ppc_htab",
 	S_IFREG | S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 1, 0, 0,
 	0, &proc_ppc_htab_inode_operations,
-	NULL, NULL,                		/* get_info, fill_inode */
-	NULL,					/* next */
-	NULL, NULL				/* parent, subdir */
 };
 #endif
 
 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);
-	proc_scsi = create_proc_entry("scsi", S_IFDIR, 0);
 #ifdef CONFIG_SYSVIPC
-	proc_sysvipc = create_proc_entry("sysvipc", S_IFDIR, 0);
+	create_proc_entry("sysvipc", S_IFDIR, 0);
 #endif
 #ifdef CONFIG_SYSCTL
 	proc_sys_root = create_proc_entry("sys", S_IFDIR, 0);
@@ -613,7 +512,7 @@
 			if (de->namelen != dentry->d_name.len)
 				continue;
 			if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
-				int ino = de->low_ino | (dir->i_ino & ~(0xffff));
+				int ino = de->low_ino;
 				error = -EINVAL;
 				inode = proc_get_inode(dir->i_sb, ino, de);
 				break;
@@ -631,11 +530,7 @@
 
 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 +561,7 @@
 	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);
 }
 
 /*
@@ -738,7 +600,6 @@
 			filp->f_pos++;
 			/* fall through */
 		default:
-			ino &= ~0xffff;
 			de = de->subdir;
 			i -= 2;
 			for (;;) {
@@ -751,7 +612,7 @@
 			}
 
 			do {
-				if (filldir(dirent, de->name, de->namelen, filp->f_pos, ino | de->low_ino) < 0)
+				if (filldir(dirent, de->name, de->namelen, filp->f_pos, de->low_ino) < 0)
 					return 0;
 				filp->f_pos++;
 				de = de->next;
@@ -760,69 +621,19 @@
 	return 1;
 }
 
-#define PROC_NUMBUF 10
-#define PROC_MAXPIDS 20
-
-/*
- * Get a few pid's to return for filldir - we need to hold the
- * tasklist lock while doing this, and we must release it before
- * we actually do the filldir itself, so we use a temp buffer..
- */
-static int get_pid_list(int index, unsigned int *pids)
-{
-	struct task_struct *p;
-	int nr_pids = 0;
-
-	index -= FIRST_PROCESS_ENTRY;
-	read_lock(&tasklist_lock);
-	for_each_task(p) {
-		int pid = p->pid;
-		if (!pid)
-			continue;
-		if (--index >= 0)
-			continue;
-		pids[nr_pids] = pid;
-		nr_pids++;
-		if (nr_pids >= PROC_MAXPIDS)
-			break;
-	}
-	read_unlock(&tasklist_lock);
-	return nr_pids;
-}
-
 static int proc_root_readdir(struct file * filp,
 	void * dirent, filldir_t filldir)
 {
-	unsigned int pid_array[PROC_MAXPIDS];
-	char buf[PROC_NUMBUF];
 	unsigned int nr = filp->f_pos;
-	unsigned int nr_pids, i;
 
 	if (nr < FIRST_PROCESS_ENTRY) {
 		int error = proc_readdir(filp, dirent, filldir);
 		if (error <= 0)
 			return error;
-		filp->f_pos = nr = FIRST_PROCESS_ENTRY;
+		filp->f_pos = FIRST_PROCESS_ENTRY;
 	}
 
-	nr_pids = get_pid_list(nr, pid_array);
-
-	for (i = 0; i < nr_pids; i++) {
-		int pid = pid_array[i];
-		ino_t ino = (pid << 16) + PROC_PID_INO;
-		unsigned long j = PROC_NUMBUF;
-
-		do {
-			j--;
-			buf[j] = '0' + (pid % 10);
-			pid /= 10;
-		} while (pid);
-
-		if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino) < 0)
-			break;
-		filp->f_pos++;
-	}
-	return 0;
+	return proc_pid_readdir(filp, dirent, filldir);
 }
 
 static int proc_unlink(struct inode *dir, struct dentry *dentry)
diff -u --recursive --new-file v2.3.26/linux/fs/proc/scsi.c linux/fs/proc/scsi.c
--- v2.3.26/linux/fs/proc/scsi.c	Sat Jun 26 12:04:40 1999
+++ linux/fs/proc/scsi.c	Wed Dec 31 16:00:00 1969
@@ -1,219 +0,0 @@
-/*
- *  linux/fs/proc/scsi.c  
- *  (c) 1995 Michael Neuffer neuffer@goofy.zdv.uni-mainz.de
- *
- *  The original version was derived from linux/fs/proc/net.c,
- *  which is Copyright (C) 1991, 1992 Linus Torvalds. 
- *  Much has been rewritten, but some of the code still remains.
- *
- *  /proc/scsi directory handling functions
- *
- *  last change: 95/07/04    
- *
- *  Initial version: March '95
- *  95/05/15 Added subdirectories for each driver and show every
- *	     registered HBA as a single file. 
- *  95/05/30 Added rudimentary write support for parameter passing
- *  95/07/04 Fixed bugs in directory handling
- *  95/09/13 Update to support the new proc-dir tree
- *
- *  TODO: Improve support to write to the driver files
- *	  Add some more comments
- */
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/mm.h>
-
-#include <asm/uaccess.h>
-
-/* forward references */
-static ssize_t proc_readscsi(struct file * file, char * buf,
-                             size_t count, loff_t *ppos);
-static ssize_t proc_writescsi(struct file * file, const char * buf,
-                              size_t count, loff_t *ppos);
-static long long proc_scsilseek(struct file *, long long, int);
-
-extern void build_proc_dir_hba_entries(uint);
-
-/* the *_get_info() functions are in the respective scsi driver code */
-int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
-				off_t offset, int length, int inout) = 0;
-
-static struct file_operations proc_scsi_operations = {
-    proc_scsilseek,	/* lseek   */
-    proc_readscsi,	/* read	   */
-    proc_writescsi,	/* write   */
-    proc_readdir,	/* readdir */
-    NULL,		/* poll    */
-    NULL,		/* ioctl   */
-    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_scsi_inode_operations = {
-&proc_scsi_operations,  /* default scsi directory file-ops */
-	NULL,			/* create */
-	proc_lookup,		/* 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 */
-};
-
-int get_not_present_info(char *buffer, char **start, off_t offset, int length)
-{
-    int len, pos, begin;
-    
-    begin = 0;
-    pos = len = sprintf(buffer, 
-			"No low-level scsi modules are currently present\n");
-    if(pos < offset) {
-	len = 0;
-	begin = pos;
-    }
-    
-    *start = buffer + (offset - begin);	  /* Start of wanted data */
-    len -= (offset - begin);
-    if(len > length)
-	len = length;
-    
-    return(len);
-}
-
-#define PROC_BLOCK_SIZE (3*1024)     /* 4K page size, but our output routines 
-				      * use some slack for overruns 
-				      */
-
-static ssize_t proc_readscsi(struct file * file, char * buf,
-                             size_t count, loff_t *ppos)
-{
-    struct inode * inode = file->f_dentry->d_inode; 
-    ssize_t length;
-    ssize_t bytes = count;
-    ssize_t copied = 0;
-    ssize_t thistime;
-    char * page;
-    char * start;
-    
-    if (!(page = (char *) __get_free_page(GFP_KERNEL)))
-	return(-ENOMEM);
-    
-    while (bytes > 0) {	
-	thistime = bytes;
-	if(bytes > PROC_BLOCK_SIZE)
-	    thistime = PROC_BLOCK_SIZE;
-	
-	if(dispatch_scsi_info_ptr)
-	    length = dispatch_scsi_info_ptr(inode->i_ino, page, &start, 
-					    *ppos, thistime, 0);
-	else
-	    length = get_not_present_info(page, &start, *ppos, thistime);
-	if(length < 0) {
-	    free_page((ulong) page);
-	    return(length);
-	}
-	
-	/*
-	 *  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);
-	*ppos += length;	/* Move down the file */
-	bytes -= length;
-	copied += length;
-	
-	if(length < thistime)
-	    break;  /* End of file */
-	
-    }
-    
-    free_page((ulong) page);
-    return(copied);
-}
-
-
-static ssize_t proc_writescsi(struct file * file, const char * buf,
-                              size_t count, loff_t *ppos)
-{
-    struct inode * inode = file->f_dentry->d_inode;
-    ssize_t ret = 0;
-    char * page;
-    
-    if(count > PROC_BLOCK_SIZE) {
-	return(-EOVERFLOW);
-    }
-
-    if(dispatch_scsi_info_ptr != NULL) {
-        if (!(page = (char *) __get_free_page(GFP_KERNEL)))
-            return(-ENOMEM);
-	copy_from_user(page, buf, count);
-	ret = dispatch_scsi_info_ptr(inode->i_ino, page, 0, 0, count, 1);
-    } else 
-	return(-ENOPKG);	  /* Nothing here */
-    
-    free_page((ulong) page);
-    return(ret);
-}
-
-
-static long long proc_scsilseek(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);
-    case 2:
-	return(-EINVAL);
-    default:
-	return(-EINVAL);
-    }
-}
-
-/*
- * Overrides for Emacs so that we almost follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */
diff -u --recursive --new-file v2.3.26/linux/fs/proc/sysvipc.c linux/fs/proc/sysvipc.c
--- v2.3.26/linux/fs/proc/sysvipc.c	Sat Jun 26 12:04:40 1999
+++ linux/fs/proc/sysvipc.c	Wed Dec 31 16:00:00 1969
@@ -1,141 +0,0 @@
-/*
- *  linux/fs/proc/sysvipc.c
- *
- *  Copyright (c) 1999 Dragos Acostachioaie
- *
- *  This code is derived from linux/fs/proc/generic.c,
- *  which is Copyright (C) 1991, 1992 Linus Torvalds.
- *
- *  /proc/sysvipc directory handling functions
- */
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/mm.h>
-
-#include <asm/uaccess.h>
-
-#ifndef MIN
-#define MIN(a,b) (((a) < (b)) ? (a) : (b))
-#endif
-
-/* 4K page size but our output routines use some slack for overruns */
-#define PROC_BLOCK_SIZE	(3*1024)
-
-static ssize_t
-proc_sysvipc_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos)
-{
-	struct inode * inode = file->f_dentry->d_inode;
-	char 	*page;
-	ssize_t	retval=0;
-	int	eof=0;
-	ssize_t	n, count;
-	char	*start;
-	struct proc_dir_entry * dp;
-
-	dp = (struct proc_dir_entry *) inode->u.generic_ip;
-	if (!(page = (char*) __get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
-
-	while ((nbytes > 0) && !eof)
-	{
-		count = MIN(PROC_BLOCK_SIZE, nbytes);
-
-		start = NULL;
-		if (dp->get_info) {
-			/*
-			 * Handle backwards compatibility with the old net
-			 * routines.
-			 * 
-			 * XXX What gives with the file->f_flags & O_ACCMODE
-			 * test?  Seems stupid to me....
-			 */
-			n = dp->get_info(page, &start, *ppos, count,
-				 (file->f_flags & O_ACCMODE) == O_RDWR);
-			if (n < count)
-				eof = 1;
-		} else if (dp->read_proc) {
-			n = dp->read_proc(page, &start, *ppos,
-					  count, &eof, dp->data);
-		} else
-			break;
-			
-		if (!start) {
-			/*
-			 * For proc files that are less than 4k
-			 */
-			start = page + *ppos;
-			n -= *ppos;
-			if (n <= 0)
-				break;
-			if (n > count)
-				n = count;
-		}
-		if (n == 0)
-			break;	/* End of file */
-		if (n < 0) {
-			if (retval == 0)
-				retval = n;
-			break;
-		}
-		
-		/* This is a hack to allow mangling of file pos independent
- 		 * of actual bytes read.  Simply place the data at page,
- 		 * return the bytes, and set `start' to the desired offset
- 		 * as an unsigned int. - Paul.Russell@rustcorp.com.au
-		 */
- 		n -= copy_to_user(buf, start < page ? page : start, n);
-		if (n == 0) {
-			if (retval == 0)
-				retval = -EFAULT;
-			break;
-		}
-
-		*ppos += start < page ? (long)start : n; /* Move down the file */
-		nbytes -= n;
-		buf += n;
-		retval += n;
-	}
-	free_page((unsigned long) page);
-	return retval;
-}
-
-static struct file_operations proc_sysvipc_operations = {
-    NULL,		/* lseek   */
-    proc_sysvipc_read,	/* read	   */
-    NULL,		/* write   */
-    NULL,		/* readdir */
-    NULL,		/* poll    */
-    NULL,		/* ioctl   */
-    NULL,		/* mmap	   */
-    NULL,		/* no special open code	   */
-    NULL,		/* no special release code */
-    NULL		/* can't fsync */
-};
-
-/*
- * proc directories can do almost nothing..
- */
-struct inode_operations proc_sysvipc_inode_operations = {
-	&proc_sysvipc_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 -u --recursive --new-file v2.3.26/linux/fs/romfs/inode.c linux/fs/romfs/inode.c
--- v2.3.26/linux/fs/romfs/inode.c	Wed Oct 27 16:34:12 1999
+++ linux/fs/romfs/inode.c	Tue Nov  9 10:04:29 1999
@@ -34,6 +34,21 @@
  *					  exposed a problem in readdir
  *			2.1.107		code-freeze spellchecker run
  *	Aug 1998			2.1.118+ VFS changes
+ *	Sep 1998	2.1.122		another VFS change (follow_link)
+ *	Apr 1999	2.2.7		no more EBADF checking in
+ *					  lookup/readdir, use ERR_PTR
+ *	Jun 1999	2.3.6		d_alloc_root use changed
+ *			2.3.9		clean up usage of ENOENT/negative
+ *					  dentries in lookup
+ *					clean up page flags setting
+ *					  (error, uptodate, locking) in
+ *					  in readpage
+ *					use init_special_inode for
+ *					  fifos/sockets (and streamline) in
+ *					  read_inode, fix _ops table order
+ *	Aug 1999	2.3.16		__initfunc() => __init change
+ *	Oct 1999	2.3.24		page->owner hack obsoleted
+ *	Nov 1999	2.3.27		2.3.25+ page->offset => index change
  */
 
 /* todo:
@@ -404,7 +419,8 @@
 	get_page(page);
 	buf = page_address(page);
 
-	offset = page->offset;
+	/* 32 bit warning -- but not for us :) */
+	offset = page->index << PAGE_CACHE_SHIFT;
 	if (offset < inode->i_size) {
 		avail = inode->i_size-offset;
 		readlen = min(avail, PAGE_SIZE);
diff -u --recursive --new-file v2.3.26/linux/fs/udf/misc.c linux/fs/udf/misc.c
--- v2.3.26/linux/fs/udf/misc.c	Mon Nov  1 13:56:27 1999
+++ linux/fs/udf/misc.c	Wed Nov 10 10:00:48 1999
@@ -24,11 +24,10 @@
  *  04/19/99 blf  partial support for reading/writing specific EA's
  */
 
+#include "udfdecl.h"
 
 #if defined(__linux__) && defined(__KERNEL__)
 
-#include "udfdecl.h"
-
 #include "udf_sb.h"
 #include "udf_i.h"
 
@@ -38,7 +37,6 @@
 
 #else
 
-#include "udfdecl.h"
 #include <sys/types.h>
 #include <stdio.h>
 #include <unistd.h>
diff -u --recursive --new-file v2.3.26/linux/fs/udf/udfdecl.h linux/fs/udf/udfdecl.h
--- v2.3.26/linux/fs/udf/udfdecl.h	Mon Nov  1 13:56:27 1999
+++ linux/fs/udf/udfdecl.h	Thu Nov 11 10:07:21 1999
@@ -3,10 +3,11 @@
 
 #define UDF_VERSION_NOTICE "v0.8.9.3"
 
+#include <linux/udf_udf.h>
+
 #ifdef __KERNEL__
 
 #include <linux/types.h>
-#include <linux/udf_udf.h>
 #include <linux/udf_fs.h>
 #include <linux/config.h>
 
@@ -18,16 +19,14 @@
 #error "The UDF Module Current Requires Kernel Version 2.3.7 or greater"
 #endif
 
+#include <linux/fs.h>
 /* if we're not defined, we must be compiling outside of the kernel tree */
 #if !defined(CONFIG_UDF_FS) && !defined(CONFIG_UDF_FS_MODULE)
 /* ... so override config */
 #define CONFIG_UDF_FS_MODULE
-#include <linux/fs.h>
 /* explicitly include udf_fs_sb.h and udf_fs_i.h */
 #include <linux/udf_fs_sb.h>
 #include <linux/udf_fs_i.h>
-#else
-#include <linux/fs.h> /* also gets udf_fs_i.h and udf_fs_sb.h */
 #endif
 
 struct dentry;
@@ -113,7 +112,6 @@
 #else
 
 #include <sys/types.h>
-#include <linux/udf_udf.h>
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.3.26/linux/fs/ufs/balloc.c linux/fs/ufs/balloc.c
--- v2.3.26/linux/fs/ufs/balloc.c	Mon Jul  5 19:59:55 1999
+++ linux/fs/ufs/balloc.c	Thu Nov 11 10:07:21 1999
@@ -676,7 +676,7 @@
 	else
 		start = ucpi->c_frotor >> 3;
 		
-	length = howmany(uspi->s_fpg, 8) - start;
+	length = ((uspi->s_fpg + 7) >> 3) - start;
 	location = ubh_scanc(UCPI_UBH, ucpi->c_freeoff + start, length,
 		(uspi->s_fpb == 8) ? ufs_fragtable_8fpb : ufs_fragtable_other,
 		1 << (count - 1 + (uspi->s_fpb & 7))); 
diff -u --recursive --new-file v2.3.26/linux/fs/ufs/dir.c linux/fs/ufs/dir.c
--- v2.3.26/linux/fs/ufs/dir.c	Sun Jun 27 10:10:41 1999
+++ linux/fs/ufs/dir.c	Thu Nov 11 10:07:21 1999
@@ -168,7 +168,7 @@
 		error_msg = "inode out of bounds";
 
 	if (error_msg != NULL)
-		ufs_error (sb, function, "bad entry in directory #%lu, size %lu: %s - "
+		ufs_error (sb, function, "bad entry in directory #%lu, size %Lu: %s - "
 			    "offset=%lu, inode=%lu, reclen=%d, namlen=%d",
 			    dir->i_ino, dir->i_size, error_msg, offset,
 			    (unsigned long) SWAB32(de->d_ino),
diff -u --recursive --new-file v2.3.26/linux/fs/ufs/inode.c linux/fs/ufs/inode.c
--- v2.3.26/linux/fs/ufs/inode.c	Sun Jun 27 10:10:41 1999
+++ linux/fs/ufs/inode.c	Thu Nov 11 10:07:21 1999
@@ -610,7 +610,7 @@
 	inode->u.ufs_i.i_gen = SWAB32(ufs_inode->ui_gen);
 	inode->u.ufs_i.i_shadow = SWAB32(ufs_inode->ui_u3.ui_sun.ui_shadow);
 	inode->u.ufs_i.i_oeftflag = SWAB32(ufs_inode->ui_u3.ui_sun.ui_oeftflag);
-	inode->u.ufs_i.i_lastfrag = howmany (inode->i_size, uspi->s_fsize);
+	inode->u.ufs_i.i_lastfrag = (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift;
 	
 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
 		;
diff -u --recursive --new-file v2.3.26/linux/fs/ufs/super.c linux/fs/ufs/super.c
--- v2.3.26/linux/fs/ufs/super.c	Tue Aug 31 17:29:14 1999
+++ linux/fs/ufs/super.c	Thu Nov 11 10:07:21 1999
@@ -328,7 +328,7 @@
 	 * on the device. 
 	 */
 	size = uspi->s_cssize;
-	blks = howmany(size, uspi->s_fsize);
+	blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift;
 	base = space = kmalloc(size, GFP_KERNEL);
 	if (!base)
 		goto failed; 
@@ -405,7 +405,7 @@
 	uspi = sb->u.ufs_sb.s_uspi;
 
 	size = uspi->s_cssize;
-	blks = howmany(size, uspi->s_fsize);
+	blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift;
 	base = space = (char*) sb->u.ufs_sb.s_csp[0];
 	for (i = 0; i < blks; i += uspi->s_fpb) {
 		size = uspi->s_bsize;
diff -u --recursive --new-file v2.3.26/linux/fs/ufs/truncate.c linux/fs/ufs/truncate.c
--- v2.3.26/linux/fs/ufs/truncate.c	Wed Aug 18 10:15:19 1999
+++ linux/fs/ufs/truncate.c	Thu Nov 11 10:07:21 1999
@@ -59,8 +59,8 @@
  *		Linus
  */
 
-#define DIRECT_BLOCK howmany (inode->i_size, uspi->s_bsize)
-#define DIRECT_FRAGMENT howmany (inode->i_size, uspi->s_fsize)
+#define DIRECT_BLOCK ((inode->i_size + uspi->s_bsize - 1) >> uspi->s_bshift)
+#define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift)
 
 #define DATA_BUFFER_USED(bh) \
 	(atomic_read(&bh->b_count) || buffer_locked(bh))
@@ -312,7 +312,7 @@
 	uspi = sb->u.ufs_sb.s_uspi;
 
 	dindirect_block = (DIRECT_BLOCK > offset) 
-		? ((DIRECT_BLOCK - offset) / uspi->s_apb) : 0;
+		? ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0;
 	retry = 0;
 	
 	tmp = SWAB32(*p);
@@ -382,7 +382,7 @@
 	retry = 0;
 	
 	tindirect_block = (DIRECT_BLOCK > (UFS_NDADDR + uspi->s_apb + uspi->s_2apb))
-		? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) / uspi->s_2apb) : 0;
+		? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) >> uspi->s_2apbshift) : 0;
 	p = inode->u.ufs_i.i_u1.i_data + UFS_TIND_BLOCK;
 	if (!(tmp = SWAB32(*p)))
 		return 0;
@@ -471,7 +471,7 @@
 		}
 	}
 	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	inode->u.ufs_i.i_lastfrag = howmany (inode->i_size, uspi->s_fsize);
+	inode->u.ufs_i.i_lastfrag = DIRECT_FRAGMENT;
 	mark_inode_dirty(inode);
 	UFSD(("EXIT\n"))
 }
diff -u --recursive --new-file v2.3.26/linux/fs/ufs/util.h linux/fs/ufs/util.h
--- v2.3.26/linux/fs/ufs/util.h	Mon Apr 12 09:53:45 1999
+++ linux/fs/ufs/util.h	Thu Nov 11 10:07:21 1999
@@ -14,7 +14,6 @@
  * some useful macros
  */
 #define in_range(b,first,len)	((b)>=(first)&&(b)<(first)+(len))
-#define howmany(x,y)		(((x)+(y)-1)/(y))
 #define min(x,y)		((x)<(y)?(x):(y))
 #define max(x,y)		((x)>(y)?(x):(y))
 
diff -u --recursive --new-file v2.3.26/linux/include/asm-alpha/div64.h linux/include/asm-alpha/div64.h
--- v2.3.26/linux/include/asm-alpha/div64.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-alpha/div64.h	Mon Nov  8 16:01:59 1999
@@ -0,0 +1,14 @@
+#ifndef __ALPHA_DIV64
+#define __ALPHA_DIV64
+
+/*
+ * Hey, we're already 64-bit, no
+ * need to play games..
+ */
+#define do_div(n,base) ({ \
+	int __res; \
+	__res = ((unsigned long) n) % (unsigned) base; \
+	n = ((unsigned long) n) / (unsigned) base; \
+	__res; })
+
+#endif
diff -u --recursive --new-file v2.3.26/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h
--- v2.3.26/linux/include/asm-alpha/processor.h	Fri Oct 15 15:25:14 1999
+++ linux/include/asm-alpha/processor.h	Mon Nov  8 14:28:34 1999
@@ -126,6 +126,16 @@
 #define release_segments(mm)		do { } while (0)
 #define forget_segments()		do { } while (0)
 
+unsigned long get_wchan(struct task_struct *p);
+/*
+* 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 -u --recursive --new-file v2.3.26/linux/include/asm-arm/processor.h linux/include/asm-arm/processor.h
--- v2.3.26/linux/include/asm-arm/processor.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/processor.h	Mon Nov  8 14:28:34 1999
@@ -107,6 +107,16 @@
 #define release_segments(mm)		do { } while (0)
 #define forget_segments()		do { } while (0)
 
+unsigned long get_wchan(struct task_struct *p);
+
+#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 -u --recursive --new-file v2.3.26/linux/include/asm-i386/div64.h linux/include/asm-i386/div64.h
--- v2.3.26/linux/include/asm-i386/div64.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-i386/div64.h	Mon Nov  8 15:58:38 1999
@@ -0,0 +1,17 @@
+#ifndef __I386_DIV64
+#define __I386_DIV64
+
+#define do_div(n,base) ({ \
+	unsigned long __upper, __low, __high, __mod; \
+	asm("":"=a" (__low), "=d" (__high):"A" (n)); \
+	__upper = __high; \
+	if (__high) { \
+		__upper = __high % (base); \
+		__high = __high / (base); \
+	} \
+	asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (base), "0" (__low), "1" (__upper)); \
+	asm("":"=A" (n):"a" (__low),"d" (__high)); \
+	__mod; \
+})
+
+#endif
diff -u --recursive --new-file v2.3.26/linux/include/asm-i386/highmem.h linux/include/asm-i386/highmem.h
--- v2.3.26/linux/include/asm-i386/highmem.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-i386/highmem.h	Thu Nov 11 17:02:09 1999
@@ -18,7 +18,12 @@
 #ifndef _ASM_HIGHMEM_H
 #define _ASM_HIGHMEM_H
 
+#ifdef __KERNEL__
+
 #include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/kmap_types.h>
+#include <asm/pgtable.h>
 
 /* undef for production */
 #define HIGHMEM_DEBUG 1
@@ -28,58 +33,79 @@
 
 extern pte_t *kmap_pte;
 extern pgprot_t kmap_prot;
+extern pte_t *pkmap_page_table;
 
 extern void kmap_init(void) __init;
 
-/* kmap helper functions necessary to access the highmem pages in kernel */
-#include <asm/pgtable.h>
-#include <asm/kmap_types.h>
+#define PKMAP_BASE (0xff000000UL)
+
+extern unsigned long FASTCALL(kmap_high(struct page *page));
+extern void FASTCALL(kunmap_high(struct page *page));
 
-extern inline unsigned long kmap(struct page *page, enum km_type type)
+extern inline unsigned long kmap(struct page *page)
 {
+	if (in_interrupt())
+		BUG();
 	if (page < highmem_start_page)
 		return page_address(page);
-	{
-		enum fixed_addresses idx = type+KM_TYPE_NR*smp_processor_id();
-		unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN+idx);
-
-#if HIGHMEM_DEBUG
-		if (!pte_none(*(kmap_pte-idx)))
-		{
-			__label__ here;
-		here:
-			printk(KERN_ERR "not null pte on CPU %d from %p\n",
-			       smp_processor_id(), &&here);
-		}
-#endif
-		set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
-		__flush_tlb_one(vaddr);
+	return kmap_high(page);
+}
 
-		return vaddr;
-	}
+extern inline void kunmap(struct page *page)
+{
+	if (in_interrupt())
+		BUG();
+	if (page < highmem_start_page)
+		return;
+	kunmap_high(page);
 }
 
-extern inline void kunmap(unsigned long vaddr, enum km_type type)
+/*
+ * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap
+ * gives a more generic (and caching) interface. But kmap_atomic can
+ * be used in IRQ contexts, so in some (very limited) cases we need
+ * it.
+ */
+extern inline unsigned long kmap_atomic(struct page *page, enum km_type type)
 {
+	enum fixed_addresses idx;
+	unsigned long vaddr;
+
+	if (page < highmem_start_page)
+		return page_address(page);
+
+	idx = type + KM_TYPE_NR*smp_processor_id();
+	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 #if HIGHMEM_DEBUG
-	enum fixed_addresses idx = type+KM_TYPE_NR*smp_processor_id();
-	if ((vaddr & PAGE_MASK) == __fix_to_virt(FIX_KMAP_BEGIN+idx))
-	{
-		/* force other mappings to Oops if they'll try to access
-		   this pte without first remap it */
-		pte_clear(kmap_pte-idx);
-		__flush_tlb_one(vaddr);
-	}
+	if (!pte_none(*(kmap_pte-idx)))
+		BUG();
 #endif
+	set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
+	__flush_tlb_one(vaddr);
+
+	return vaddr;
 }
 
-extern inline void kmap_check(void)
+extern inline void kunmap_atomic(unsigned long vaddr, enum km_type type)
 {
 #if HIGHMEM_DEBUG
-	int idx_base = KM_TYPE_NR*smp_processor_id(), i;
-	for (i = idx_base; i < idx_base+KM_TYPE_NR; i++)
-		if (!pte_none(*(kmap_pte-i)))
-			BUG();
+	enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
+
+	if (vaddr < FIXADDR_START) // FIXME
+		return;
+
+	if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx))
+		BUG();
+
+	/*
+	 * force other mappings to Oops if they'll try to access
+	 * this pte without first remap it
+	 */
+	pte_clear(kmap_pte-idx);
+	__flush_tlb_one(vaddr);
 #endif
 }
+
+#endif /* __KERNEL__ */
+
 #endif /* _ASM_HIGHMEM_H */
diff -u --recursive --new-file v2.3.26/linux/include/asm-i386/io.h linux/include/asm-i386/io.h
--- v2.3.26/linux/include/asm-i386/io.h	Mon Nov  1 13:56:27 1999
+++ linux/include/asm-i386/io.h	Thu Nov 11 17:02:20 1999
@@ -103,9 +103,8 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
-#include <linux/vmalloc.h>
 #include <asm/page.h>
+#include <linux/vmalloc.h>
 
 /*
  * Temporary debugging check to catch old code using
diff -u --recursive --new-file v2.3.26/linux/include/asm-i386/kmap_types.h linux/include/asm-i386/kmap_types.h
--- v2.3.26/linux/include/asm-i386/kmap_types.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-i386/kmap_types.h	Thu Nov 11 10:33:42 1999
@@ -2,9 +2,9 @@
 #define _ASM_KMAP_TYPES_H
 
 enum km_type {
-	KM_READ,
-	KM_WRITE,
-	KM_TYPE_NR,
+	KM_BOUNCE_READ,
+	KM_BOUNCE_WRITE,
+	KM_TYPE_NR
 };
 
 #endif
diff -u --recursive --new-file v2.3.26/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- v2.3.26/linux/include/asm-i386/processor.h	Wed Oct 27 16:34:12 1999
+++ linux/include/asm-i386/processor.h	Thu Nov 11 17:02:06 1999
@@ -406,6 +406,10 @@
 	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 -u --recursive --new-file v2.3.26/linux/include/asm-m68k/processor.h linux/include/asm-m68k/processor.h
--- v2.3.26/linux/include/asm-m68k/processor.h	Tue Sep  7 12:14:07 1999
+++ linux/include/asm-m68k/processor.h	Mon Nov  8 14:28:34 1999
@@ -134,6 +134,17 @@
 		return sw->retpc;
 }
 
+unsigned long get_wchan(struct task_struct *p);
+
+#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 -u --recursive --new-file v2.3.26/linux/include/asm-mips/processor.h linux/include/asm-mips/processor.h
--- v2.3.26/linux/include/asm-mips/processor.h	Mon Jul 19 13:12:47 1999
+++ linux/include/asm-mips/processor.h	Mon Nov  8 14:28:34 1999
@@ -206,6 +206,14 @@
  */
 extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp);
 
+unsigned long get_wchan(struct task_struct *p);
+
+#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 -u --recursive --new-file v2.3.26/linux/include/asm-ppc/div64.h linux/include/asm-ppc/div64.h
--- v2.3.26/linux/include/asm-ppc/div64.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/div64.h	Wed Nov 10 10:55:31 1999
@@ -0,0 +1,10 @@
+#ifndef __PPC_DIV64
+#define __PPC_DIV64
+
+#define do_div(n,base) ({ \
+int __res; \
+__res = ((unsigned long) n) % (unsigned) base; \
+n = ((unsigned long) n) / (unsigned) base; \
+__res; })
+
+#endif
diff -u --recursive --new-file v2.3.26/linux/include/asm-ppc/fcntl.h linux/include/asm-ppc/fcntl.h
--- v2.3.26/linux/include/asm-ppc/fcntl.h	Wed Oct 21 13:31:06 1998
+++ linux/include/asm-ppc/fcntl.h	Thu Nov 11 15:59:26 1999
@@ -3,21 +3,23 @@
 
 /* open/fcntl - O_SYNC is only implemented on blocks devices and on files
    located on an ext2 file system */
-#define O_ACCMODE	  0003
-#define O_RDONLY	    00
-#define O_WRONLY	    01
-#define O_RDWR		    02
-#define O_CREAT		  0100	/* not fcntl */
-#define O_EXCL		  0200	/* not fcntl */
-#define O_NOCTTY	  0400	/* not fcntl */
-#define O_TRUNC		 01000	/* not fcntl */
-#define O_APPEND	 02000
-#define O_NONBLOCK	 04000
+#define O_ACCMODE	   0003
+#define O_RDONLY	     00
+#define O_WRONLY	     01
+#define O_RDWR		     02
+#define O_CREAT		   0100	/* not fcntl */
+#define O_EXCL		   0200	/* not fcntl */
+#define O_NOCTTY	   0400	/* not fcntl */
+#define O_TRUNC		  01000	/* not fcntl */
+#define O_APPEND	  02000
+#define O_NONBLOCK	  04000
 #define O_NDELAY	O_NONBLOCK
-#define O_SYNC		010000
-#define FASYNC		020000	/* fcntl, for BSD compatibility */
-#define O_DIRECTORY	040000	/* must be a directory */
-#define O_NOFOLLOW	0100000	/* don't follow links */
+#define O_SYNC		 010000
+#define FASYNC		 020000	/* fcntl, for BSD compatibility */
+#define O_DIRECTORY      040000	/* must be a directory */
+#define O_NOFOLLOW      0100000	/* don't follow links */
+#define O_LARGEFILE     0200000
+#define O_DIRECT	0400000	/* direct disk access hint - currently ignored */
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get f_flags */
diff -u --recursive --new-file v2.3.26/linux/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h
--- v2.3.26/linux/include/asm-ppc/processor.h	Sun Nov  7 16:37:34 1999
+++ linux/include/asm-ppc/processor.h	Wed Nov 10 10:55:31 1999
@@ -316,6 +316,11 @@
 #define release_segments(mm)		do { } while (0)
 #define forget_segments()		do { } while (0)
 
+unsigned long get_wchan(struct task_struct *p);
+
+#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 -u --recursive --new-file v2.3.26/linux/include/asm-sh/processor.h linux/include/asm-sh/processor.h
--- v2.3.26/linux/include/asm-sh/processor.h	Wed Oct 27 16:34:12 1999
+++ linux/include/asm-sh/processor.h	Mon Nov  8 10:19:19 1999
@@ -189,6 +189,17 @@
 	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 -u --recursive --new-file v2.3.26/linux/include/asm-sparc/processor.h linux/include/asm-sparc/processor.h
--- v2.3.26/linux/include/asm-sparc/processor.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-sparc/processor.h	Mon Nov  8 14:28:34 1999
@@ -161,6 +161,11 @@
 #define release_segments(mm)		do { } while (0)
 #define forget_segments()		do { } while (0)
 
+unsigned long get_wchan(struct task_struct *p);
+
+#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 -u --recursive --new-file v2.3.26/linux/include/asm-sparc64/processor.h linux/include/asm-sparc64/processor.h
--- v2.3.26/linux/include/asm-sparc64/processor.h	Wed Aug  4 15:39:46 1999
+++ linux/include/asm-sparc64/processor.h	Mon Nov  8 14:28:34 1999
@@ -209,6 +209,11 @@
 #define release_segments(mm)		do { } while (0)
 #define forget_segments()		do { } while (0)
 
+unsigned long get_wchan(struct task_struct *p);
+
+#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 -u --recursive --new-file v2.3.26/linux/include/linux/acpi.h linux/include/linux/acpi.h
--- v2.3.26/linux/include/linux/acpi.h	Mon Nov  1 13:56:27 1999
+++ linux/include/linux/acpi.h	Thu Nov 11 17:03:57 1999
@@ -24,6 +24,158 @@
 #include <linux/types.h>
 #include <linux/ioctl.h>
 
+#ifdef __KERNEL__
+
+#include <linux/sched.h>
+#include <linux/wait.h>
+
+/*
+ * Device types
+ */
+enum
+{
+	ACPI_SYS_DEV,	/* system device (fan, KB controller, ...) */
+	ACPI_PCI_DEV,	/* generic PCI device */
+	ACPI_PCI_BUS,	/* PCI bus */
+	ACPI_ISA_DEV,	/* generic ISA device */
+	ACPI_ISA_BUS,	/* ISA bus */
+	ACPI_USB_DEV,	/* generic USB device */
+	ACPI_USB_HUB,	/* USB hub device */
+	ACPI_USB_CTRL,	/* USB controller */
+	ACPI_SCSI_DEV,	/* generic SCSI device */
+	ACPI_SCSI_CTRL, /* SCSI controller */
+};
+
+typedef int acpi_dev_t;
+
+/*
+ * Device addresses
+ */
+#define ACPI_PCI_ADR(dev) ((dev)->bus->number << 16 | (dev)->devfn)
+
+/*
+ * HID (PnP) values
+ */
+enum
+{
+	ACPI_UNKNOWN_HID =  0x00000000, /* generic */
+	ACPI_KBC_HID =	    0x41d00303, /* keyboard controller */
+	ACPI_COM_HID =	    0x41d00500, /* serial port */
+	ACPI_FDC_HID =	    0x41d00700, /* floppy controller */
+	ACPI_VGA_HID =	    0x41d00900, /* VGA controller */
+	ACPI_ISA_HID =	    0x41d00a00, /* ISA bus */
+	ACPI_EISA_HID =	    0x41d00a01, /* EISA bus */
+	ACPI_PCI_HID =	    0x41d00a03, /* PCI bus */
+};
+
+typedef int acpi_hid_t;
+
+/*
+ * Device states
+ */
+enum
+{
+	ACPI_D0, /* fully-on */
+	ACPI_D1, /* partial-on */
+	ACPI_D2, /* partial-on */
+	ACPI_D3, /* fully-off */
+};
+
+typedef int acpi_dstate_t;
+
+struct acpi_dev;
+
+/*
+ * Device state transition function
+ */
+typedef int (*acpi_transition)(struct acpi_dev *dev, acpi_dstate_t state);
+
+/*
+ * Static device information
+ */
+struct acpi_dev_info
+{
+	acpi_dev_t	 type;	     /* device type */
+	acpi_hid_t	 hid;	     /* PnP identifier */
+	acpi_transition	 transition; /* state transition callback */
+
+	/* other information like D-states supported,
+	 * D-state latencies, and in-rush current needs
+	 * will go here
+	 */
+};
+
+/*
+ * Dynamic device information
+ */
+struct acpi_dev
+{
+	struct acpi_dev_info info;     /* static device info */
+	unsigned long	     adr;      /* bus address or unique id */
+	acpi_dstate_t	     state;    /* current D-state */
+	unsigned long	     accessed; /* last access time */
+	unsigned long	     idle;     /* last idle time */
+	struct list_head     entry;    /* linked list entry */
+};
+
+#ifdef CONFIG_ACPI
+
+extern wait_queue_head_t acpi_idle_wait;
+
+/*
+ * Register a device with the ACPI subsystem
+ */
+struct acpi_dev *acpi_register(struct acpi_dev_info *info, unsigned long adr);
+
+/*
+ * Unregister a device with ACPI
+ */
+void acpi_unregister(struct acpi_dev *dev);
+
+/*
+ * Update device access time and wake up device, if necessary
+ */
+extern inline void acpi_access(struct acpi_dev *dev)
+{
+	extern void acpi_wakeup(struct acpi_dev*);
+	if (dev) {
+		if (dev->state != ACPI_D0)
+			acpi_wakeup(dev);
+		dev->accessed = jiffies;
+	}
+}
+
+/*
+ * Identify device as currently being idle
+ */
+extern inline void acpi_dev_idle(struct acpi_dev *dev)
+{
+	if (dev) {
+		dev->idle = jiffies;
+		if (waitqueue_active(&acpi_idle_wait))
+			wake_up(&acpi_idle_wait);
+	}
+}
+
+#else /* CONFIG_ACPI */
+
+extern inline struct acpi_dev*
+acpi_register(struct acpi_dev_info *info, unsigned long adr)
+{
+	return 0;
+}
+
+extern inline void acpi_unregister(struct acpi_dev *dev) {}
+extern inline void acpi_access(struct acpi_dev *dev) {}
+extern inline void acpi_dev_idle(struct acpi_dev *dev) {}
+
+#endif /* CONFIG_ACPI */
+
+extern void (*acpi_idle)(void);
+extern void (*acpi_power_off)(void);
+
+#endif /* __KERNEL__ */
+
 /* RSDP location */
 #define ACPI_BIOS_ROM_BASE (0x0e0000)
 #define ACPI_BIOS_ROM_END  (0x100000)
@@ -34,6 +186,7 @@
 #define ACPI_RSDT_SIG  0x54445352 /* 'RSDT' */
 #define ACPI_FACP_SIG  0x50434146 /* 'FACP' */
 #define ACPI_DSDT_SIG  0x54445344 /* 'DSDT' */
+#define ACPI_FACS_SIG  0x53434146 /* 'FACS' */
 
 /* PM1_STS/EN flags */
 #define ACPI_TMR    0x0001
@@ -94,7 +247,7 @@
 	__u8 oem[6];
 	__u8 reserved;
 	__u32 rsdt;
-};
+} __attribute__ ((packed));
 
 struct acpi_table {
 	__u32 signature;
@@ -106,7 +259,7 @@
 	__u32 oem_rev;
 	__u32 creator;
 	__u32 creator_rev;
-};
+} __attribute__ ((packed));
 
 struct acpi_facp {
 	struct acpi_table hdr;
@@ -149,7 +302,7 @@
 	__u8 reserved5;
 	__u8 reserved6;
 	__u32 flags;
-};
+} __attribute__ ((packed));
 
 struct acpi_facs {
 	__u32 signature;
@@ -158,7 +311,7 @@
 	__u32 fw_wake_vector;
 	__u32 global_lock;
 	__u32 flags;
-};
+} __attribute__ ((packed));
 
 /*
  * Sysctl declarations
@@ -181,7 +334,7 @@
 	ACPI_P_LVL3,
 	ACPI_P_LVL2_LAT,
 	ACPI_P_LVL3_LAT,
-	ACPI_S5_SLP_TYP
+	ACPI_S5_SLP_TYP,
 };
 
 #define ACPI_P_LVL_DISABLED	0x80
@@ -223,12 +376,5 @@
 
 #define ACPI_PIIX4_PMREGMISC	0x80
 #define	  ACPI_PIIX4_PMIOSE	0x01
-
-#ifdef __KERNEL__
-
-extern void (*acpi_idle)(void);
-extern void (*acpi_power_off)(void);
-
-#endif
 
 #endif /* _LINUX_ACPI_H */
diff -u --recursive --new-file v2.3.26/linux/include/linux/bootmem.h linux/include/linux/bootmem.h
--- v2.3.26/linux/include/linux/bootmem.h	Fri Oct 22 13:21:55 1999
+++ linux/include/linux/bootmem.h	Thu Nov 11 17:03:07 1999
@@ -1,7 +1,6 @@
 #ifndef _LINUX_BOOTMEM_H
 #define _LINUX_BOOTMEM_H
 
-#include <linux/config.h>
 #include <asm/pgtable.h>
 #include <asm/dma.h>
 
diff -u --recursive --new-file v2.3.26/linux/include/linux/concap.h linux/include/linux/concap.h
--- v2.3.26/linux/include/linux/concap.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/concap.h	Sun Nov  7 16:34:00 1999
@@ -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 -u --recursive --new-file v2.3.26/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.3.26/linux/include/linux/fs.h	Sun Nov  7 16:37:34 1999
+++ linux/include/linux/fs.h	Thu Nov 11 17:02:09 1999
@@ -224,7 +224,8 @@
 	struct buffer_head *b_reqnext;	/* request queue */
 
 	struct buffer_head **b_pprev;	/* doubly linked list of hash-queue */
-	char *b_data;			/* pointer to data block (1024 bytes) */
+	char * b_data;			/* pointer to data block (512 byte) */
+	struct page *b_page;		/* the page this bh is mapped to */
 	void (*b_end_io)(struct buffer_head *bh, int uptodate); /* I/O completion */
 	void *b_dev_id;
 
@@ -246,8 +247,11 @@
 #define buffer_new(bh)		__buffer_state(bh,New)
 #define buffer_protected(bh)	__buffer_state(bh,Protected)
 
-#define buffer_page(bh)		(mem_map + MAP_NR((bh)->b_data))
-#define touch_buffer(bh)	set_bit(PG_referenced, &buffer_page(bh)->flags)
+#define bh_offset(bh)		((unsigned long)(bh)->b_data & ~PAGE_MASK)
+
+extern void set_bh_page(struct buffer_head *bh, struct page *page, unsigned int offset);
+
+#define touch_buffer(bh)	set_bit(PG_referenced, &bh->b_page->flags)
 
 #include <linux/pipe_fs_i.h>
 #include <linux/minix_fs_i.h>
@@ -271,6 +275,7 @@
 #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 +400,7 @@
 		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;
@@ -933,6 +939,7 @@
 extern unsigned int get_hardblocksize(kdev_t);
 extern struct buffer_head * bread(kdev_t, int, int);
 extern struct buffer_head * breada(kdev_t, int, int, unsigned int, unsigned int);
+extern void wakeup_bdflush(int wait);
 
 extern int brw_page(int, struct page *, kdev_t, int [], int);
 
diff -u --recursive --new-file v2.3.26/linux/include/linux/highmem.h linux/include/linux/highmem.h
--- v2.3.26/linux/include/linux/highmem.h	Sun Nov  7 16:37:34 1999
+++ linux/include/linux/highmem.h	Thu Nov 11 17:02:56 1999
@@ -13,18 +13,19 @@
 
 /* declarations for linux/mm/highmem.c */
 extern unsigned long highmem_mapnr;
-extern unsigned long nr_free_highpages;
+FASTCALL(unsigned int nr_free_highpages(void));
 
 extern struct page * prepare_highmem_swapout(struct page *);
 extern struct page * replace_with_highmem(struct page *);
+extern struct buffer_head * create_bounce(int rw, struct buffer_head * bh_orig);
 
 #else /* CONFIG_HIGHMEM */
 
+extern inline unsigned int nr_free_highpages(void) { return 0; }
 #define prepare_highmem_swapout(page) page
 #define replace_with_highmem(page) page
-#define kmap(page, type) page_address(page)
-#define kunmap(vaddr, type) do { } while (0)
-#define nr_free_highpages 0UL
+#define kmap(page) page_address(page)
+#define kunmap(page) do { } while (0)
 
 #endif /* CONFIG_HIGHMEM */
 
@@ -33,9 +34,9 @@
 {
 	unsigned long kaddr;
 
-	kaddr = kmap(page, KM_WRITE);
+	kaddr = kmap(page);
 	clear_page((void *)kaddr);
-	kunmap(kaddr, KM_WRITE);
+	kunmap(page);
 }
 
 extern inline void memclear_highpage(struct page *page, unsigned int offset, unsigned int size)
@@ -44,9 +45,9 @@
 
 	if (offset + size > PAGE_SIZE)
 		BUG();
-	kaddr = kmap(page, KM_WRITE);
+	kaddr = kmap(page);
 	memset((void *)(kaddr + offset), 0, size);
-	kunmap(kaddr, KM_WRITE);
+	kunmap(page);
 }
 
 /*
@@ -58,21 +59,21 @@
 
 	if (offset + size > PAGE_SIZE)
 		BUG();
-	kaddr = kmap(page, KM_WRITE);
+	kaddr = kmap(page);
 	memset((void *)(kaddr + offset), 0, size);
 	flush_page_to_ram(page);
-	kunmap(kaddr, KM_WRITE);
+	kunmap(page);
 }
 
 extern inline void copy_highpage(struct page *to, struct page *from)
 {
 	unsigned long vfrom, vto;
 
-	vfrom = kmap(from, KM_READ);
-	vto = kmap(to, KM_WRITE);
+	vfrom = kmap(from);
+	vto = kmap(to);
 	copy_page((void *)vto, (void *)vfrom);
-	kunmap(vfrom, KM_READ);
-	kunmap(vto, KM_WRITE);
+	kunmap(from);
+	kunmap(to);
 }
 
 #endif /* _LINUX_HIGHMEM_H */
diff -u --recursive --new-file v2.3.26/linux/include/linux/i2o.h linux/include/linux/i2o.h
--- v2.3.26/linux/include/linux/i2o.h	Sun Nov  7 16:37:34 1999
+++ linux/include/linux/i2o.h	Wed Nov 10 09:52:18 1999
@@ -100,40 +100,40 @@
 	u8 reserved;
 	u16 PciVendorID;
 	u16 PciDeviceID;
-} i2o_pci_bus, *pi2o_pci_bus;
+} i2o_pci_bus;
 
 typedef struct _i2o_local_bus {
 	u16 LbBaseIOPort;
 	u16 reserved;
 	u32 LbBaseMemoryAddress;
-} i2o_local_bus, *pi2o_local_bus;
+} i2o_local_bus;
 
 typedef struct _i2o_isa_bus {
 	u16 IsaBaseIOPort;
 	u8 CSN;
 	u8 reserved;
 	u32 IsaBaseMemoryAddress;
-} i2o_isa_bus, *pi2o_isa_bus;
+} i2o_isa_bus;
 
 typedef struct _i2o_eisa_bus_info {
 	u16 EisaBaseIOPort;
 	u8 reserved;
 	u8 EisaSlotNumber;
 	u32 EisaBaseMemoryAddress;
-} i2o_eisa_bus, *pi2o_eisa_bus;
+} i2o_eisa_bus;
 
 typedef struct _i2o_mca_bus {
 	u16 McaBaseIOPort;
 	u8 reserved;
 	u8 McaSlotNumber;
 	u32 McaBaseMemoryAddress;
-} i2o_mca_bus, *pi2o_mca_bus;
+} i2o_mca_bus;
 
 typedef struct _i2o_other_bus {
 	u16 BaseIOPort;
 	u16 reserved;
 	u32 BaseMemoryAddress;
-} i2o_other_bus, *pi2o_other_bus;
+} i2o_other_bus;
 
 typedef struct _i2o_hrt_entry {
 	u32 adapter_id;
@@ -149,7 +149,7 @@
 		i2o_mca_bus mca_bus;
 		i2o_other_bus other_bus;
 	} bus;
-} i2o_hrt_entry, *pi2o_hrt_entry;
+} i2o_hrt_entry;
 
 typedef struct _i2o_hrt {
 	u16 num_entries;
@@ -157,7 +157,7 @@
 	u8 hrt_version;
 	u32 change_ind;
 	i2o_hrt_entry hrt_entry[1];
-} i2o_hrt, *pi2o_hrt;
+} i2o_hrt;
 
 typedef struct _i2o_lct_entry {
 	u32 entry_size:16;
@@ -174,7 +174,7 @@
 	u32 bios_info:8;
 	u8 identity_tag[8];
 	u32 event_capabilities;
-} i2o_lct_entry, *pi2o_lct_entry;
+} i2o_lct_entry;
 
 typedef struct _i2o_lct {
 	u32 table_size:16;
@@ -183,7 +183,7 @@
 	u32 iop_flags;
 	u32 current_change_ind;
 	i2o_lct_entry lct_entry[1];
-} i2o_lct, *pi2o_lct;
+} i2o_lct;
 
 typedef struct _i2o_status_block {
 	u16 org_id;
@@ -199,6 +199,7 @@
 	u8 init_code;	
 	u8 reserved2;
 	u32 max_inbound_frames;
+	u32 cur_inbound_frames;
 	u32 max_outbound_frames;
 	char product_id[24];	
 	u32 expected_lct_size;
@@ -211,9 +212,38 @@
 	u32 current_io_base;
 	u32 reserved3:24;
 	u32 cmd_status:8;
-} i2o_status_block, *pi2o_status_block;
+} i2o_status_block;
  
+/* Event indicator mask flags */
+#define I2O_EVT_IND_STATE_CHANGE		0x80000000
+#define I2O_EVT_IND_GENERAL_WARNING		0x40000000
+#define I2O_EVT_IND_CONFIGURATION_FLAG		0x20000000
+#define I2O_EVT_IND_LOCK_RELEASE		0x10000000
+#define I2O_EVT_IND_CAPABILITY_CHANGE		0x08000000
+#define I2O_EVT_IND_DEVICE_RESET		0x04000000
+#define I2O_EVT_IND_EVT_MASK_MODIFIED		0x02000000
+#define I2O_EVT_IND_FIELD_MODIFIED		0x01000000
+#define I2O_EVT_IND_VENDOR_EVT			0x00800000
+#define I2O_EVT_IND_DEVICE_STATE		0x00400000
+
+/* Event data for generic events */
+#define I2O_EVT_STATE_CHANGE_NORMAL		0x00
+#define I2O_EVT_STATE_CHANGE_SUSPENDED		0x01
+#define I2O_EVT_STATE_CHANGE_RESTART		0x02
+#define I2O_EVT_STATE_CHANGE_NA_RECOVER		0x03
+#define I2O_EVT_STATE_CHANGE_NA_NO_RECOVER	0x04
+#define I2O_EVT_STATE_CHANGE_QUIESCE_REQUEST	0x05
+#define I2O_EVT_STATE_CHANGE_FAILED		0x10
+#define I2O_EVT_STATE_CHANGE_FAULTED		0x11
+
+#define I2O_EVT_GEN_WARNING_NORMAL		0x00
+#define I2O_EVT_GEN_WARNING_ERROR_THRESHOLD	0x01
+#define I2O_EVT_GEN_WARNING_MEDIA_FAULT		0x02
 
+#define I2O_EVT_CAPABILITY_OTHER		0x01
+#define I2O_EVT_CAPABILITY_CHANGED		0x02
+
+#define I2O_EVT_SENSOR_STATE_CHANGED		0x01
 
 #ifdef __KERNEL__   /* ioctl stuff only thing exported to users */
 
@@ -246,7 +276,7 @@
  
 struct i2o_device
 {
-	pi2o_lct_entry lct_data;/* Device LCT information */
+	i2o_lct_entry *lct_data;/* Device LCT information */
 	u32 flags;		
 	int i2oversion;		/* I2O version supported. Actually there
 				 * should be high and low version */
@@ -286,7 +316,7 @@
 	char name[16];
 	int unit;
 	int type;
-	int enabled;				/* Bus level enable */
+	int enabled;
 
 #define I2O_TYPE_PCI		0x01		/* PCI I2O controller */	
 
@@ -298,9 +328,9 @@
 	volatile u32 *reply_port;
 	volatile u32 *irq_mask;			/* Interrupt port */
 
-	pi2o_status_block status_block;		/* IOP status block */
-	pi2o_lct lct;
-	pi2o_hrt hrt;
+	i2o_status_block *status_block;		/* IOP status block */
+	i2o_lct *lct;
+	i2o_hrt *hrt;
 
 	u32 mem_offset;				/* MFA offset */
 	u32 mem_phys;				/* MFA physical */
@@ -464,22 +494,22 @@
 
 extern int i2o_post_this(struct i2o_controller *, u32 *, int);
 extern int i2o_post_wait(struct i2o_controller *, u32 *, int, int);
-extern int i2o_issue_claim(struct i2o_controller *, int, int, int, int *, u32);
 extern int i2o_issue_params(int, struct i2o_controller *, int, void *,
 			    int, void *, int); 
 
-extern int i2o_query_scalar(struct i2o_controller *, int, int, int, 
-			void *, int);
-extern int i2o_set_scalar(struct i2o_controller *, int, int, int, 
-			void *, int);
+extern int i2o_query_scalar(struct i2o_controller *, int, int, int, void *, int);
+extern int i2o_set_scalar(struct i2o_controller *, int, int, int, void *, int);
 
-extern int i2o_query_table(int, struct i2o_controller *, int, int, int, 
-			void *, int, void *, int);
+extern int i2o_query_table(int, struct i2o_controller *, int, int, int, void *,
+			   int, void *, int);
 extern int i2o_clear_table(struct i2o_controller *, int, int); 
-extern int i2o_row_add_table(struct i2o_controller *, int, int, int,
-			void *, int);
-extern int i2o_row_delete_table(struct i2o_controller *, int, int, int,
-			void *, int);
+extern int i2o_row_add_table(struct i2o_controller *, int, int, int, void *,
+			     int);
+extern int i2o_row_delete_table(struct i2o_controller *, int, int, int, void *,
+				int);
+
+extern int i2o_event_register(struct i2o_controller *, int, int, u32); 
+extern int i2o_event_ack(struct i2o_controller *, int, int, u32, void *, int);
 
 extern void i2o_run_queue(struct i2o_controller *);
 extern void i2o_report_status(const char *, const char *, u32 *);
@@ -615,7 +645,7 @@
 #define I2O_CMD_UTIL_PARAMS_GET		0x06
 #define I2O_CMD_UTIL_PARAMS_SET		0x05
 #define I2O_CMD_UTIL_EVT_REGISTER	0x13
-#define I2O_CMD_UTIL_ACK		0x14
+#define I2O_CMD_UTIL_EVT_ACK		0x14
 #define I2O_CMD_UTIL_CONFIG_DIALOG	0x10
 #define I2O_CMD_UTIL_DEVICE_RESERVE	0x0D
 #define I2O_CMD_UTIL_DEVICE_RELEASE	0x0F
diff -u --recursive --new-file v2.3.26/linux/include/linux/ipc.h linux/include/linux/ipc.h
--- v2.3.26/linux/include/linux/ipc.h	Mon Nov  1 13:56:27 1999
+++ linux/include/linux/ipc.h	Tue Nov  9 10:02:36 1999
@@ -42,6 +42,8 @@
 #define IPC_UNUSED	((void *) -1)
 #define IPC_NOID	((void *) -2)		/* being allocated/destroyed */
 
+#define IPCMNI 32768  /* <= MAX_INT limit for ipc arrays (including sysctl changes) */
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_IPC_H */
diff -u --recursive --new-file v2.3.26/linux/include/linux/isdn.h linux/include/linux/isdn.h
--- v2.3.26/linux/include/linux/isdn.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/isdn.h	Sun Nov  7 16:34:00 1999
@@ -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 @@
   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 @@
 
 #include <linux/isdnif.h>
 
-
 #define ISDN_DRVIOCTL_MASK       0x7f  /* Mask for Device-ioctl */
 
 /* Until now unused */
@@ -504,12 +561,6 @@
 #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 @@
   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 @@
   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 @@
 	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 @@
 	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 @@
 	/*  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    */
@@ -892,6 +925,7 @@
 } isdn_dev;
 
 extern isdn_dev *dev;
+
 
 
 /* Utility-Macros */
diff -u --recursive --new-file v2.3.26/linux/include/linux/isdn_compat.h linux/include/linux/isdn_compat.h
--- v2.3.26/linux/include/linux/isdn_compat.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/isdn_compat.h	Wed Dec 31 16:00:00 1969
@@ -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 -u --recursive --new-file v2.3.26/linux/include/linux/isdn_ppp.h linux/include/linux/isdn_ppp.h
--- v2.3.26/linux/include/linux/isdn_ppp.h	Sun Aug 15 11:49:08 1999
+++ linux/include/linux/isdn_ppp.h	Sun Nov  7 16:34:00 1999
@@ -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_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 -u --recursive --new-file v2.3.26/linux/include/linux/isdnif.h linux/include/linux/isdnif.h
--- v2.3.26/linux/include/linux/isdnif.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/isdnif.h	Sun Nov  7 16:34:00 1999
@@ -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 -u --recursive --new-file v2.3.26/linux/include/linux/kernelcapi.h linux/include/linux/kernelcapi.h
--- v2.3.26/linux/include/linux/kernelcapi.h	Thu Aug 12 09:42:34 1999
+++ linux/include/linux/kernelcapi.h	Sun Nov  7 16:34:00 1999
@@ -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 @@
 #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_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 -u --recursive --new-file v2.3.26/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.3.26/linux/include/linux/mm.h	Sun Nov  7 16:37:34 1999
+++ linux/include/linux/mm.h	Thu Nov 11 17:02:14 1999
@@ -138,6 +138,7 @@
 	wait_queue_head_t wait;
 	struct page **pprev_hash;
 	struct buffer_head * buffers;
+	unsigned long virtual; /* nonzero if kmapped */
 } mem_map_t;
 
 #define get_page(p)		atomic_inc(&(p)->count)
@@ -285,12 +286,16 @@
  * This is timing-critical - most of the time in getting a new page
  * goes to clearing the page. If you want a page without the clearing
  * overhead, just use __get_free_page() directly..
+ *
+ * We have two allocation namespaces - the *get*page*() variants
+ * return virtual kernel addresses to the allocated page(s), the
+ * alloc_page*() variants return 'struct page *'.
  */
-extern struct page * __get_pages(int gfp_mask, unsigned long order);
 #define __get_free_page(gfp_mask) __get_free_pages((gfp_mask),0)
 #define __get_dma_pages(gfp_mask, order) __get_free_pages((gfp_mask) | GFP_DMA,(order))
-extern unsigned long FASTCALL(__get_free_pages(int gfp_mask, unsigned long gfp_order));
-extern struct page * get_free_highpage(int gfp_mask);
+extern unsigned long FASTCALL(__get_free_pages(int gfp_mask, unsigned long order));
+extern struct page * FASTCALL(alloc_pages(int gfp_mask, unsigned long order));
+#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)
 
 extern inline unsigned long get_zeroed_page(int gfp_mask)
 {
@@ -335,7 +340,7 @@
 extern int check_pgt_cache(void);
 
 extern void paging_init(void);
-extern void free_area_init(unsigned long);
+extern void free_area_init(unsigned int * zones_size);
 extern void mem_init(void);
 extern void show_mem(void);
 extern void oom(struct task_struct * tsk);
diff -u --recursive --new-file v2.3.26/linux/include/linux/module.h linux/include/linux/module.h
--- v2.3.26/linux/include/linux/module.h	Wed Aug 18 16:43:29 1999
+++ linux/include/linux/module.h	Thu Nov 11 17:02:07 1999
@@ -8,6 +8,7 @@
 #define _LINUX_MODULE_H
 
 #include <linux/config.h>
+#include <linux/spinlock.h>
 
 #ifdef __GENKSYMS__
 #  define _set_ver(sym) sym
diff -u --recursive --new-file v2.3.26/linux/include/linux/msg.h linux/include/linux/msg.h
--- v2.3.26/linux/include/linux/msg.h	Sat Oct  9 11:47:50 1999
+++ linux/include/linux/msg.h	Tue Nov  9 10:02:36 1999
@@ -45,9 +45,9 @@
 	unsigned short  msgseg; 
 };
 
-#define MSGMNI   128   /* <= 32768 */     /* max # of msg queue identifiers */
-#define MSGMAX  4056   /* <= 4056 (?)*/   /* max size of message (bytes) */
-#define MSGMNB 16384   /* <= MAX_INT */   /* default max size of a message queue */
+#define MSGMNI   128   /* <= IPCMNI */     /* max # of msg queue identifiers */
+#define MSGMAX  8192   /* <= INT_MAX */   /* max size of message (bytes) */
+#define MSGMNB 16384   /* <= INT_MAX */   /* default max size of a message queue */
 
 /* unused */
 #define MSGPOOL (MSGMNI*MSGMNB/1024)  /* size in kilobytes of message pool */
diff -u --recursive --new-file v2.3.26/linux/include/linux/nbd.h linux/include/linux/nbd.h
--- v2.3.26/linux/include/linux/nbd.h	Mon Mar  8 13:05:11 1999
+++ linux/include/linux/nbd.h	Wed Nov 10 12:38:13 1999
@@ -1,3 +1,9 @@
+/*
+ * 1999 Copyright (C) Pavel Machek, pavel@ucw.cz. This code is GPL.
+ * 1999/11/04 Copyright (C) 1999 VMware, Inc. (Regis "HPReg" Duchesne)
+ *            Made nbd_end_request() use the io_request_lock
+ */
+
 #ifndef LINUX_NBD_H
 #define LINUX_NBD_H
 
@@ -27,12 +33,19 @@
 static void 
 nbd_end_request(struct request *req)
 {
+	unsigned long flags;
+
 #ifdef PARANOIA
 	requests_out++;
 #endif
+	spin_lock_irqsave(&io_request_lock, flags);
 	if (end_that_request_first( req, !req->errors, "nbd" ))
-		return;
+		goto out;
 	end_that_request_last( req );
+
+out:
+	spin_unlock_irqrestore(&io_request_lock, flags);
+	return;
 }
 
 #define MAX_NBD 128
diff -u --recursive --new-file v2.3.26/linux/include/linux/pagemap.h linux/include/linux/pagemap.h
--- v2.3.26/linux/include/linux/pagemap.h	Sun Nov  7 16:37:34 1999
+++ linux/include/linux/pagemap.h	Thu Nov 11 17:02:17 1999
@@ -27,7 +27,7 @@
 #define PAGE_CACHE_MASK		PAGE_MASK
 #define PAGE_CACHE_ALIGN(addr)	(((addr)+PAGE_CACHE_SIZE-1)&PAGE_CACHE_MASK)
 
-#define page_cache_alloc()	__get_pages(GFP_USER, 0)
+#define page_cache_alloc()	alloc_pages(GFP_HIGHUSER, 0)
 #define page_cache_free(x)	__free_page(x)
 #define page_cache_release(x)	__free_page(x)
 
diff -u --recursive --new-file v2.3.26/linux/include/linux/parport.h linux/include/linux/parport.h
--- v2.3.26/linux/include/linux/parport.h	Fri Oct 15 15:25:14 1999
+++ linux/include/linux/parport.h	Thu Nov 11 17:02:57 1999
@@ -422,6 +422,10 @@
 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 -u --recursive --new-file v2.3.26/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.3.26/linux/include/linux/proc_fs.h	Mon Nov  1 13:56:27 1999
+++ linux/include/linux/proc_fs.h	Thu Nov 11 17:02:19 1999
@@ -9,6 +9,12 @@
  */
 
 /*
+ * Offset of the first process in the /proc root directory..
+ */
+#define FIRST_PROCESS_ENTRY 256
+
+
+/*
  * We always define these enumerators
  */
 
@@ -16,111 +22,6 @@
 	PROC_ROOT_INO = 1,
 };
 
-enum pid_directory_inos {
-	PROC_PID_INO = 2,
-	PROC_PID_STATUS,
-	PROC_PID_MEM,
-	PROC_PID_CWD,
-	PROC_PID_ROOT,
-	PROC_PID_EXE,
-	PROC_PID_FD,
-	PROC_PID_ENVIRON,
-	PROC_PID_CMDLINE,
-	PROC_PID_STAT,
-	PROC_PID_STATM,
-	PROC_PID_MAPS,
-#if CONFIG_AP1000
-	PROC_PID_RINGBUF,
-#endif
-	PROC_PID_CPU,
-};
-
-enum pid_subdirectory_inos {
-	PROC_PID_FD_DIR = 0x8000,	/* 0x8000-0xffff */
-};
-
-enum net_directory_inos {
-	PROC_NET_LAST
-};
-
-enum scsi_directory_inos {
-	PROC_SCSI_SCSI = 256,
-	PROC_SCSI_ADVANSYS,
-	PROC_SCSI_PCI2000,
-	PROC_SCSI_PCI2220I,
-	PROC_SCSI_PSI240I,
-	PROC_SCSI_EATA,
-	PROC_SCSI_EATA_PIO,
-	PROC_SCSI_AHA152X,
-	PROC_SCSI_AHA1542,
-	PROC_SCSI_AHA1740,
-	PROC_SCSI_AIC7XXX,
-	PROC_SCSI_BUSLOGIC,
-	PROC_SCSI_U14_34F,
-	PROC_SCSI_FDOMAIN,
-	PROC_SCSI_GDTH,
-	PROC_SCSI_GENERIC_NCR5380,
-	PROC_SCSI_IN2000,
-	PROC_SCSI_PAS16,
-	PROC_SCSI_QLOGICFAS,
-	PROC_SCSI_QLOGICISP,
-	PROC_SCSI_QLOGICFC,
-	PROC_SCSI_SEAGATE,
-	PROC_SCSI_T128,
-	PROC_SCSI_NCR53C7xx,
-	PROC_SCSI_SYM53C8XX,
-	PROC_SCSI_NCR53C8XX,
-	PROC_SCSI_ULTRASTOR,
-	PROC_SCSI_7000FASST,
-	PROC_SCSI_IBMMCA,
-	PROC_SCSI_FD_MCS,
-	PROC_SCSI_EATA2X,
-	PROC_SCSI_DC390T,
-	PROC_SCSI_AM53C974,
-	PROC_SCSI_SSC,
-	PROC_SCSI_NCR53C406A,
-	PROC_SCSI_SYM53C416,
-	PROC_SCSI_MEGARAID,
-	PROC_SCSI_PPA,
-	PROC_SCSI_ATP870U,
-	PROC_SCSI_ESP,
-	PROC_SCSI_QLOGICPTI,
-	PROC_SCSI_AMIGA7XX,
-	PROC_SCSI_MVME147,
-	PROC_SCSI_MVME16x,
-	PROC_SCSI_BVME6000,
-	PROC_SCSI_SIM710,
-	PROC_SCSI_A3000,
-	PROC_SCSI_A2091,
-	PROC_SCSI_GVP11,
-	PROC_SCSI_ATARI,
-	PROC_SCSI_MAC,
-	PROC_SCSI_IDESCSI,
-	PROC_SCSI_SGIWD93,
-	PROC_SCSI_MESH,
-	PROC_SCSI_53C94,
-	PROC_SCSI_PLUTO,
-	PROC_SCSI_INI9100U,
-	PROC_SCSI_INIA100,
- 	PROC_SCSI_IPH5526_FC,
-	PROC_SCSI_FCAL,
-	PROC_SCSI_I2O,
-	PROC_SCSI_USB_SCSI,
-	PROC_SCSI_SCSI_DEBUG,	
-	PROC_SCSI_NOT_PRESENT,
-	PROC_SCSI_FILE,                        /* I'm assuming here that we */
-	PROC_SCSI_LAST = (PROC_SCSI_FILE + 16) /* won't ever see more than */
-};                                             /* 16 HBAs in one machine   */
-
-enum mca_directory_inos {
-	PROC_MCA_MACHINE = (PROC_SCSI_LAST+1),
-	PROC_MCA_REGISTERS,
-	PROC_MCA_VIDEO,
-	PROC_MCA_SCSI,
-	PROC_MCA_SLOT,	/* the 8 adapter slots */
-	PROC_MCA_LAST = (PROC_MCA_SLOT + 8)
-};
-
 /* Finally, the dynamically allocatable proc entries are reserved: */
 
 #define PROC_DYNAMIC_FIRST 4096
@@ -144,9 +45,8 @@
  * /proc file has a parent, but "subdir" is NULL for all
  * non-directory entries).
  *
- * "get_info" is called at "read", while "fill_inode" is used to
- * fill in file type/protection/owner information specific to the
- * particular /proc file.
+ * "get_info" is called at "read", while "owner" is used to protect module
+ * from unloading while proc_dir_entry is in use
  */
 
 typedef	int (read_proc_t)(char *page, char **start, off_t off,
@@ -166,7 +66,7 @@
 	unsigned long size;
 	struct inode_operations * ops;
 	get_info_t *get_info;
-	void (*fill_inode)(struct inode *, int);
+	struct module *owner;
 	struct proc_dir_entry *next, *parent, *subdir;
 	void *data;
 	read_proc_t *read_proc;
@@ -176,30 +76,30 @@
 	int deleted;		/* delete flag */
 };
 
-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;
 extern struct proc_dir_entry *proc_root_fs;
 extern struct proc_dir_entry *proc_net;
-extern struct proc_dir_entry *proc_scsi;
 extern struct proc_dir_entry proc_sys;
 extern struct proc_dir_entry proc_openprom;
-extern struct proc_dir_entry proc_pid;
-extern struct proc_dir_entry proc_pid_fd;
 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 inode_operations proc_scsi_inode_operations;
+extern struct proc_dir_entry proc_root_kcore;
 
 extern void proc_root_init(void);
-extern void proc_base_init(void);
 extern void proc_misc_init(void);
 
+struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry);
+void proc_pid_delete_inode(struct inode *inode);
+int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
+
 extern int proc_register(struct proc_dir_entry *, struct proc_dir_entry *);
 extern int proc_unregister(struct proc_dir_entry *, int);
 
@@ -208,39 +108,6 @@
 extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
 
 
-extern inline int proc_scsi_register(struct proc_dir_entry *driver, 
-				     struct proc_dir_entry *x)
-{
-    x->ops = &proc_scsi_inode_operations;
-    if(x->low_ino < PROC_SCSI_FILE){
-	return(proc_register(proc_scsi, x));
-    }else{
-	return(proc_register(driver, x));
-    }
-}
-
-extern inline int proc_scsi_unregister(struct proc_dir_entry *driver, int x)
-{
-    extern void scsi_init_free(char *ptr, unsigned int size);
-
-    if(x < PROC_SCSI_FILE)
-	return(proc_unregister(proc_scsi, x));
-    else {
-	struct proc_dir_entry **p = &driver->subdir, *dp;
-	int ret;
-
-	while ((dp = *p) != NULL) {
-		if (dp->low_ino == x) 
-		    break;
-		p = &dp->next;
-	}
-	ret = proc_unregister(driver, x);
-	scsi_init_free((char *) dp, sizeof(struct proc_dir_entry) + 4);
-	return(ret);
-    }
-}
-
-
 /*
  * retrieve the proc_dir_entry associated with /proc/driver/$module_name
  */
@@ -282,8 +149,6 @@
         return (p == NULL) ? -1 : 0;
 }
 
-
-
 extern struct super_block *proc_super_blocks;
 extern struct dentry_operations proc_dentry_operations;
 extern struct super_block *proc_read_super(struct super_block *,void *,int);
@@ -292,7 +157,6 @@
 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 *);
 
@@ -326,23 +190,16 @@
   
 extern struct inode_operations proc_dir_inode_operations;
 extern struct inode_operations proc_file_inode_operations;
-extern struct inode_operations proc_netdir_inode_operations;
 extern struct inode_operations proc_openprom_inode_operations;
-extern struct inode_operations proc_mem_inode_operations;
 extern struct inode_operations proc_sys_inode_operations;
-extern struct inode_operations proc_array_inode_operations;
-extern struct inode_operations proc_arraylong_inode_operations;
 extern struct inode_operations proc_kcore_inode_operations;
 extern struct inode_operations proc_profile_inode_operations;
 extern struct inode_operations proc_kmsg_inode_operations;
-extern struct inode_operations proc_link_inode_operations;
-extern struct inode_operations proc_fd_inode_operations;
 #if CONFIG_AP1000
 extern struct inode_operations proc_ringbuf_inode_operations;
 #endif
 extern struct inode_operations proc_omirr_inode_operations;
 extern struct inode_operations proc_ppc_htab_inode_operations;
-extern struct inode_operations proc_sysvipc_inode_operations;
 
 /*
  * proc_tty.c
@@ -387,16 +244,6 @@
 	remove_proc_entry(name,proc_net);
 }
 
-extern inline int proc_net_register(struct proc_dir_entry * x)
-{
-	return proc_register(proc_net, x);
-}
-
-extern inline int proc_net_unregister(int x)
-{
-	return proc_unregister(proc_net, x);
-}
-
 #else
 
 extern inline int proc_register(struct proc_dir_entry *a, struct proc_dir_entry *b) { return 0; }
@@ -404,10 +251,6 @@
 extern inline struct proc_dir_entry *proc_net_create(const char *name, mode_t mode, 
 	get_info_t *get_info) {return NULL;}
 extern inline void proc_net_remove(const char *name) {}
-extern inline int proc_net_register(struct proc_dir_entry * x) { return 0; }
-extern inline int proc_net_unregister(int x) { return 0; }
-extern inline int proc_scsi_register(struct proc_dir_entry *b, struct proc_dir_entry *c) { return 0; }
-extern inline int proc_scsi_unregister(struct proc_dir_entry *a, int x) { return 0; }
 
 extern inline struct proc_dir_entry *create_proc_entry(const char *name,
 	mode_t mode, struct proc_dir_entry *parent) { return NULL; }
diff -u --recursive --new-file v2.3.26/linux/include/linux/proc_fs_i.h linux/include/linux/proc_fs_i.h
--- v2.3.26/linux/include/linux/proc_fs_i.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/proc_fs_i.h	Mon Nov  8 10:19:19 1999
@@ -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 -u --recursive --new-file v2.3.26/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.3.26/linux/include/linux/sched.h	Fri Oct 22 13:21:55 1999
+++ linux/include/linux/sched.h	Thu Nov 11 17:02:14 1999
@@ -361,6 +361,8 @@
 /* Thread group tracking */
    	u32 parent_exec_id;
    	u32 self_exec_id;
+/* Protection of fields allocatio/deallocation */
+	struct semaphore exit_sem;
 };
 
 /*
@@ -427,6 +429,7 @@
 /* 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
@@ -835,6 +838,21 @@
 	unhash_pid(p);
 	REMOVE_LINKS(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__ */
diff -u --recursive --new-file v2.3.26/linux/include/linux/sem.h linux/include/linux/sem.h
--- v2.3.26/linux/include/linux/sem.h	Mon Nov  1 13:56:27 1999
+++ linux/include/linux/sem.h	Tue Nov  9 10:02:36 1999
@@ -60,10 +60,10 @@
 	int semaem;
 };
 
-#define SEMMNI  128             /* <= 32767  max # of semaphore identifiers */
-#define SEMMSL  250             /* <= 512 max num of semaphores per id */
-#define SEMMNS  (SEMMNI*SEMMSL) /* <= MAX_INT max # of semaphores in system */
-#define SEMOPM  32	        /* <= 160 max num of ops per semop call */
+#define SEMMNI  128             /* <= IPCMNI  max # of semaphore identifiers */
+#define SEMMSL  250             /* <= 8 000 max num of semaphores per id */
+#define SEMMNS  (SEMMNI*SEMMSL) /* <= INT_MAX max # of semaphores in system */
+#define SEMOPM  32	        /* <= 1 000 max num of ops per semop call */
 #define SEMVMX  32767           /* <= 32767 semaphore maximum value */
 
 /* unused */
diff -u --recursive --new-file v2.3.26/linux/include/linux/swap.h linux/include/linux/swap.h
--- v2.3.26/linux/include/linux/swap.h	Sun Nov  7 16:37:34 1999
+++ linux/include/linux/swap.h	Thu Nov 11 17:02:07 1999
@@ -61,7 +61,9 @@
 };
 
 extern int nr_swap_pages;
-extern int nr_free_pages;
+FASTCALL(unsigned int nr_free_pages(void));
+FASTCALL(unsigned int nr_free_buffer_pages(void));
+FASTCALL(unsigned int nr_free_highpages(void));
 extern int nr_lru_pages;
 extern struct list_head lru_cache;
 extern atomic_t nr_async_pages;
@@ -112,8 +114,10 @@
 extern struct swap_info_struct swap_info[];
 extern int is_swap_partition(kdev_t);
 extern void si_swapinfo(struct sysinfo *);
-extern swp_entry_t get_swap_page(void);
-extern void swap_free(swp_entry_t);
+extern swp_entry_t __get_swap_page(unsigned short);
+#define get_swap_page() __get_swap_page(1)
+extern void __swap_free(swp_entry_t, unsigned short);
+#define swap_free(entry) __swap_free((entry), 1)
 struct swap_list_t {
 	int head;	/* head of priority-ordered swapfile list */
 	int next;	/* swapfile to be used next */
diff -u --recursive --new-file v2.3.26/linux/include/linux/sysctl.h linux/include/linux/sysctl.h
--- v2.3.26/linux/include/linux/sysctl.h	Sun Nov  7 16:37:34 1999
+++ linux/include/linux/sysctl.h	Tue Nov  9 10:03:57 1999
@@ -102,8 +102,11 @@
 	KERN_MSGMNB=36,         /* int: Maximum message queue size */
 	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_MAX_THREADS=39,	/* int: Maximum nr of threads in the system */
+ 	KERN_RANDOM=40,		/* Random driver */
+ 	KERN_SHMALL=41,		/* int: Maximum size of shared memory */
+ 	KERN_MSGMNI=42,		/* int: msg queue identifiers */
+ 	KERN_SEM=43		/* int: sysv semaphore limits */
 };
 
 
diff -u --recursive --new-file v2.3.26/linux/include/linux/videodev.h linux/include/linux/videodev.h
--- v2.3.26/linux/include/linux/videodev.h	Mon Oct  4 15:49:30 1999
+++ linux/include/linux/videodev.h	Wed Nov 10 20:01:22 1999
@@ -55,6 +55,10 @@
 #define VID_TYPE_SCALES		128	/* Scalable */
 #define VID_TYPE_MONOCHROME	256	/* Monochrome only */
 #define VID_TYPE_SUBCAPTURE	512	/* Can capture subareas of the image */
+#define VID_TYPE_MPEG_DECODER	1024	/* Can decode MPEG streams */
+#define VID_TYPE_MPEG_ENCODER	2048	/* Can encode MPEG streams */
+#define VID_TYPE_MJPEG_DECODER	4096	/* Can decode MJPEG streams */
+#define VID_TYPE_MJPEG_ENCODER	8192	/* Can encode MJPEG streams */
 
 struct video_capability
 {
@@ -230,6 +234,36 @@
 	int	teletext;	/* Teletext minor */
 };
 
+/* video_info is biased towards hardware mpeg encode/decode */
+/* but it could apply generically to any hardware compressor/decompressor */
+struct video_info
+{
+	__u32	frame_count;	/* frames output since decode/encode began */
+	__u32	h_size;		/* current unscaled horizontal size */
+	__u32	v_size;		/* current unscaled veritcal size */
+	__u32	smpte_timecode;	/* current SMPTE timecode (for current GOP) */
+	__u32	picture_type;	/* current picture type */
+	__u32	temporal_reference;	/* current temporal reference */
+	__u8	user_data[256];	/* user data last found in compressed stream */
+	/* user_data[0] contains user data flags, user_data[1] has count */
+};
+
+/* generic structure for setting playback modes */
+struct video_play_mode
+{
+	int	mode;
+	int	p1;
+	int	p2;
+};
+
+/* for loading microcode / fpga programming */
+struct video_code
+{
+	char	loadwhat[16];	/* name or tag of file being passed */
+	int	datasize;
+	__u8	*data;
+};
+
 #define VIDIOCGCAP		_IOR('v',1,struct video_capability)	/* Get capabilities */
 #define VIDIOCGCHAN		_IOWR('v',2,struct video_channel)	/* Get channel info (sources) */
 #define VIDIOCSCHAN		_IOW('v',3,struct video_channel)	/* Set channel 	*/
@@ -253,9 +287,47 @@
 #define VIDIOCGUNIT		_IOR('v', 21, struct video_unit)	/* Get attached units */
 #define VIDIOCGCAPTURE		_IOR('v',22, struct video_capture)	/* Get frame buffer */
 #define VIDIOCSCAPTURE		_IOW('v',23, struct video_capture)	/* Set frame buffer - root only */
+#define VIDIOCSPLAYMODE		_IOW('v',24, struct video_play_mode)	/* Set output video mode/feature */
+#define VIDIOCSWRITEMODE	_IOW('v',25, int)			/* Set write mode */
+#define VIDIOCGPLAYINFO		_IOR('v',26, struct video_info)		/* Get current playback info from hardware */
+#define VIDIOCSMICROCODE	_IOW('v',27, struct video_code)		/* Load microcode into hardware */
 
 #define BASE_VIDIOCPRIVATE	192		/* 192-255 are private */
 
+/* VIDIOCSWRITEMODE */
+#define VID_WRITE_MPEG_AUD		0
+#define VID_WRITE_MPEG_VID		1
+#define VID_WRITE_OSD			2
+#define VID_WRITE_TTX			3
+#define VID_WRITE_CC			4
+#define VID_WRITE_MJPEG			5
+
+/* VIDIOCSPLAYMODE */
+#define VID_PLAY_VID_OUT_MODE		0
+	/* p1: = VIDEO_MODE_PAL, VIDEO_MODE_NTSC, etc ... */
+#define VID_PLAY_GENLOCK		1
+	/* p1: 0 = OFF, 1 = ON */
+	/* p2: GENLOCK FINE DELAY value */ 
+#define VID_PLAY_NORMAL			2
+#define VID_PLAY_PAUSE			3
+#define VID_PLAY_SINGLE_FRAME		4
+#define VID_PLAY_FAST_FORWARD		5
+#define VID_PLAY_SLOW_MOTION		6
+#define VID_PLAY_IMMEDIATE_NORMAL	7
+#define VID_PLAY_SWITCH_CHANNELS	8
+#define VID_PLAY_FREEZE_FRAME		9
+#define VID_PLAY_STILL_MODE		10
+#define VID_PLAY_MASTER_MODE		11
+	/* p1: see below */
+#define		VID_PLAY_MASTER_NONE	1
+#define		VID_PLAY_MASTER_VIDEO	2
+#define		VID_PLAY_MASTER_AUDIO	3
+#define VID_PLAY_ACTIVE_SCANLINES	12
+	/* p1 = first active; p2 = last active */
+#define VID_PLAY_RESET			13
+#define VID_PLAY_END_MARK		14
+
+
 
 #define VID_HARDWARE_BT848	1
 #define VID_HARDWARE_QCAM_BW	2
@@ -276,7 +348,7 @@
 #define VID_HARDWARE_BROADWAY	17	/* Broadway project */
 #define VID_HARDWARE_GEMTEK	18
 #define VID_HARDWARE_TYPHOON	19
-#define VID_HARDWARE_VINO	20	/* Reserved for SGI Indy Vino */
+#define VID_HARDWARE_VINO	20	/* SGI Indy Vino */
 #define VID_HARDWARE_CADET	21	/* Cadet radio */
 #define VID_HARDWARE_TRUST	22	/* Trust FM Radio */
 #define VID_HARDWARE_TERRATEC	23	/* TerraTec ActiveRadio */
diff -u --recursive --new-file v2.3.26/linux/include/linux/vmalloc.h linux/include/linux/vmalloc.h
--- v2.3.26/linux/include/linux/vmalloc.h	Wed Aug 18 16:43:52 1999
+++ linux/include/linux/vmalloc.h	Thu Nov 11 17:02:16 1999
@@ -20,5 +20,6 @@
 void vmfree_area_pages(unsigned long address, unsigned long size);
 int vmalloc_area_pages(unsigned long address, unsigned long size);
 
+extern struct vm_struct * vmlist;
 #endif
 
diff -u --recursive --new-file v2.3.26/linux/include/pcmcia/bulkmem.h linux/include/pcmcia/bulkmem.h
--- v2.3.26/linux/include/pcmcia/bulkmem.h	Tue Sep  7 12:14:07 1999
+++ linux/include/pcmcia/bulkmem.h	Thu Nov 11 16:03:37 1999
@@ -1,7 +1,7 @@
 /*
  * Definitions for bulk memory services
  *
- * bulkmem.h 1.10 1999/08/28 04:12:33
+ * bulkmem.h 1.11 1999/10/25 20:23:16
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -14,7 +14,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/include/pcmcia/bus_ops.h linux/include/pcmcia/bus_ops.h
--- v2.3.26/linux/include/pcmcia/bus_ops.h	Mon Oct  4 15:49:30 1999
+++ linux/include/pcmcia/bus_ops.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * bus_ops.h 1.7 1999/09/10 06:22:33
+ * bus_ops.h 1.8 1999/10/25 20:23:16
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/include/pcmcia/ciscode.h linux/include/pcmcia/ciscode.h
--- v2.3.26/linux/include/pcmcia/ciscode.h	Tue Sep  7 12:14:07 1999
+++ linux/include/pcmcia/ciscode.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * ciscode.h 1.38 1999/08/28 04:12:32
+ * ciscode.h 1.39 1999/10/25 20:23:17
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/include/pcmcia/cisreg.h linux/include/pcmcia/cisreg.h
--- v2.3.26/linux/include/pcmcia/cisreg.h	Tue Sep  7 12:14:07 1999
+++ linux/include/pcmcia/cisreg.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * cisreg.h 1.13 1999/08/28 04:12:32
+ * cisreg.h 1.14 1999/10/25 20:23:17
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/include/pcmcia/cistpl.h linux/include/pcmcia/cistpl.h
--- v2.3.26/linux/include/pcmcia/cistpl.h	Tue Sep  7 12:14:07 1999
+++ linux/include/pcmcia/cistpl.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * cistpl.h 1.30 1999/08/28 04:12:32
+ * cistpl.h 1.31 1999/10/25 20:23:17
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/include/pcmcia/cs.h linux/include/pcmcia/cs.h
--- v2.3.26/linux/include/pcmcia/cs.h	Fri Oct 22 13:21:55 1999
+++ linux/include/pcmcia/cs.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * cs.h 1.68 1999/10/20 18:59:32
+ * cs.h 1.69 1999/10/25 20:23:17
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/include/pcmcia/cs_types.h linux/include/pcmcia/cs_types.h
--- v2.3.26/linux/include/pcmcia/cs_types.h	Fri Oct 22 13:21:55 1999
+++ linux/include/pcmcia/cs_types.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * cs_types.h 1.15 1999/08/28 04:12:32
+ * cs_types.h 1.16 1999/10/25 20:23:17
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/include/pcmcia/driver_ops.h linux/include/pcmcia/driver_ops.h
--- v2.3.26/linux/include/pcmcia/driver_ops.h	Fri Oct 22 13:21:55 1999
+++ linux/include/pcmcia/driver_ops.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * driver_ops.h 1.13 1999/08/28 04:12:33
+ * driver_ops.h 1.14 1999/10/25 20:23:17
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/include/pcmcia/ds.h linux/include/pcmcia/ds.h
--- v2.3.26/linux/include/pcmcia/ds.h	Fri Oct 22 13:21:55 1999
+++ linux/include/pcmcia/ds.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * ds.h 1.54 1999/09/03 16:44:49
+ * ds.h 1.55 1999/10/25 20:23:17
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/include/pcmcia/ftl.h linux/include/pcmcia/ftl.h
--- v2.3.26/linux/include/pcmcia/ftl.h	Tue Sep  7 12:14:07 1999
+++ linux/include/pcmcia/ftl.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * ftl.h 1.6 1999/08/28 04:12:33
+ * ftl.h 1.7 1999/10/25 20:23:17
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/include/pcmcia/mem_op.h linux/include/pcmcia/mem_op.h
--- v2.3.26/linux/include/pcmcia/mem_op.h	Mon Oct  4 15:49:30 1999
+++ linux/include/pcmcia/mem_op.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * mem_op.h 1.11 1999/09/15 07:14:03
+ * mem_op.h 1.12 1999/10/25 20:23:17
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/include/pcmcia/memory.h linux/include/pcmcia/memory.h
--- v2.3.26/linux/include/pcmcia/memory.h	Tue Sep  7 12:14:07 1999
+++ linux/include/pcmcia/memory.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * memory.h 1.5 1999/08/28 04:12:33
+ * memory.h 1.6 1999/10/25 20:23:17
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/include/pcmcia/ss.h linux/include/pcmcia/ss.h
--- v2.3.26/linux/include/pcmcia/ss.h	Tue Sep  7 12:14:07 1999
+++ linux/include/pcmcia/ss.h	Thu Nov 11 16:03:37 1999
@@ -1,5 +1,5 @@
 /*
- * ss.h 1.24 1999/08/28 04:12:33
+ * ss.h 1.25 1999/10/25 20:23:17
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -12,7 +12,7 @@
  * limitations under the License. 
  *
  * The initial developer of the original code is David A. Hinds
- * <dhinds@hyper.stanford.edu>.  Portions created by David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
diff -u --recursive --new-file v2.3.26/linux/include/pcmcia/version.h linux/include/pcmcia/version.h
--- v2.3.26/linux/include/pcmcia/version.h	Fri Oct 22 13:21:55 1999
+++ linux/include/pcmcia/version.h	Thu Nov 11 16:03:37 1999
@@ -1,4 +1,4 @@
-/* version.h 1.74 1999/09/29 20:41:44 (David Hinds) */
+/* version.h 1.76 1999/10/26 18:55:56 (David Hinds) */
 
-#define CS_RELEASE "3.1.2"
-#define CS_RELEASE_CODE 0x3102
+#define CS_RELEASE "3.1.4"
+#define CS_RELEASE_CODE 0x3104
diff -u --recursive --new-file v2.3.26/linux/ipc/msg.c linux/ipc/msg.c
--- v2.3.26/linux/ipc/msg.c	Mon Nov  1 13:56:27 1999
+++ linux/ipc/msg.c	Tue Nov  9 10:02:36 1999
@@ -11,6 +11,7 @@
  * /proc/sysvipc/msg support (c) 1999 Dragos Acostachioaie <dragos@iname.com>
  *
  * mostly rewritten, threaded and wake-one semantics added
+ * MSGMAX limit removed, sysctl's added
  * (c) 1999 Manfred Spraul <manfreds@colorfullife.com>
  */
 
@@ -21,11 +22,15 @@
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 #include <linux/list.h>
-
 #include <asm/uaccess.h>
+#include "util.h"
+
+/* sysctl: */
+int msg_ctlmax = MSGMAX;
+int msg_ctlmnb = MSGMNB;
+int msg_ctlmni = MSGMNI;
 
-#define USHRT_MAX	0xffff
-/* one ms_receiver structure for each sleeping receiver */
+/* one msg_receiver structure for each sleeping receiver */
 struct msg_receiver {
 	struct list_head r_list;
 	struct task_struct* r_tsk;
@@ -37,14 +42,27 @@
 	struct msg_msg* volatile r_msg;
 };
 
+/* one msg_sender for each sleeping sender */
+struct msg_sender {
+	struct list_head list;
+	struct task_struct* tsk;
+};
+
+struct msg_msgseg {
+	struct msg_msgseg* next;
+	/* the next part of the message follows immediately */
+};
 /* one msg_msg structure for each message */
 struct msg_msg {
 	struct list_head m_list; 
 	long  m_type;          
 	int m_ts;           /* message text size */
+	struct msg_msgseg* next;
 	/* the actual message follows immediately */
 };
 
+#define DATALEN_MSG	(PAGE_SIZE-sizeof(struct msg_msg))
+#define DATALEN_SEG	(PAGE_SIZE-sizeof(struct msg_msgseg))
 
 /* one msq_queue structure for each present queue on the system */
 struct msg_queue {
@@ -60,13 +78,7 @@
 
 	struct list_head q_messages;
 	struct list_head q_receivers;
-	wait_queue_head_t q_rwait;
-};
-
-/* one msq_array structure for each possible queue on the system */
-struct msg_array {
-	spinlock_t lock;
-	struct msg_queue* q;
+	struct list_head q_senders;
 };
 
 #define SEARCH_ANY		1
@@ -74,99 +86,181 @@
 #define SEARCH_NOTEQUAL		3
 #define SEARCH_LESSEQUAL	4
 
-static DECLARE_MUTEX(msg_lock);
-static struct msg_array msg_que[MSGMNI];
-
-static unsigned short msg_seq = 0;
-static int msg_used_queues = 0;
-static int msg_max_id = -1;
-
 static atomic_t msg_bytes = ATOMIC_INIT(0);
 static atomic_t msg_hdrs = ATOMIC_INIT(0);
 
+static struct ipc_ids msg_ids;
+
+#define msg_lock(id)	((struct msg_queue*)ipc_lock(&msg_ids,id))
+#define msg_unlock(id)	ipc_unlock(&msg_ids,id)
+#define msg_rmid(id)	((struct msg_queue*)ipc_rmid(&msg_ids,id))
+#define msg_checkid(msq, msgid)	\
+	ipc_checkid(&msg_ids,&msq->q_perm,msgid)
+#define msg_buildid(id, seq) \
+	ipc_buildid(&msg_ids, id, seq)
+
 static void freeque (int id);
 static int newque (key_t key, int msgflg);
-static int findkey (key_t key);
 #ifdef CONFIG_PROC_FS
 static int sysvipc_msg_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
 #endif
 
-/* implemented in ipc/util.c, thread-safe */
-extern int ipcperms (struct ipc_perm *ipcp, short msgflg);
-
 void __init msg_init (void)
 {
-	int id;
+	ipc_init_ids(&msg_ids,msg_ctlmni);
 
-	for (id = 0; id < MSGMNI; id++) {
-		msg_que[id].lock = SPIN_LOCK_UNLOCKED;
-		msg_que[id].q = NULL;
-	}
 #ifdef CONFIG_PROC_FS
 	create_proc_read_entry("sysvipc/msg", 0, 0, sysvipc_msg_read_proc, NULL);
 #endif
 }
 
-static int findkey (key_t key)
-{
-	int id;
-	struct msg_queue *msq;
-	
-	for (id = 0; id <= msg_max_id; id++) {
-		msq = msg_que[id].q;
-		if(msq == NULL)
-			continue;
-		if (key == msq->q_perm.key)
-			return id;
-	}
-	return -1;
-}
-
 static int newque (key_t key, int msgflg)
 {
 	int id;
 	struct msg_queue *msq;
-	struct ipc_perm *ipcp;
-
-	for (id = 0; id < MSGMNI; id++) {
-		if (msg_que[id].q == NULL)
-			break;
-	}
-	if(id == MSGMNI)
-		return -ENOSPC;
 
 	msq  = (struct msg_queue *) kmalloc (sizeof (*msq), GFP_KERNEL);
 	if (!msq) 
 		return -ENOMEM;
-
-	ipcp = &msq->q_perm;
-	ipcp->mode = (msgflg & S_IRWXUGO);
-	ipcp->key = key;
-	ipcp->cuid = ipcp->uid = current->euid;
-	ipcp->gid = ipcp->cgid = current->egid;
-
-	/* ipcp->seq*MSGMNI must be a positive integer.
-	 * this limits MSGMNI to 32768
-	 */
-	ipcp->seq = msg_seq++;
+	id = ipc_addid(&msg_ids, &msq->q_perm, msg_ctlmni);
+	if(id == -1) {
+		kfree(msq);
+		return -ENOSPC;
+	}
+	msq->q_perm.mode = (msgflg & S_IRWXUGO);
+	msq->q_perm.key = key;
 
 	msq->q_stime = msq->q_rtime = 0;
 	msq->q_ctime = CURRENT_TIME;
 	msq->q_cbytes = msq->q_qnum = 0;
-	msq->q_qbytes = MSGMNB;
+	msq->q_qbytes = msg_ctlmnb;
 	msq->q_lspid = msq->q_lrpid = 0;
 	INIT_LIST_HEAD(&msq->q_messages);
 	INIT_LIST_HEAD(&msq->q_receivers);
-	init_waitqueue_head(&msq->q_rwait);
+	INIT_LIST_HEAD(&msq->q_senders);
+	msg_unlock(id);
+
+	return msg_buildid(id,msq->q_perm.seq);
+}
+
+static void free_msg(struct msg_msg* msg)
+{
+	struct msg_msgseg* seg;
+	seg = msg->next;
+	kfree(msg);
+	while(seg != NULL) {
+		struct msg_msgseg* tmp = seg->next;
+		kfree(seg);
+		seg = tmp;
+	}
+}
+
+static struct msg_msg* load_msg(void* src, int len)
+{
+	struct msg_msg* msg;
+	struct msg_msgseg** pseg;
+	int err;
+	int alen;
+
+	alen = len;
+	if(alen > DATALEN_MSG)
+		alen = DATALEN_MSG;
+
+	msg = (struct msg_msg *) kmalloc (sizeof(*msg) + alen, GFP_KERNEL);
+	if(msg==NULL)
+		return ERR_PTR(-ENOMEM);
+
+	msg->next = NULL;
+
+	if (copy_from_user(msg+1, src, alen)) {
+		err = -EFAULT;
+		goto out_err;
+	}
+
+	len -= alen;
+	src = ((char*)src)+alen;
+	pseg = &msg->next;
+	while(len > 0) {
+		struct msg_msgseg* seg;
+		alen = len;
+		if(alen > DATALEN_SEG)
+			alen = DATALEN_SEG;
+		seg = (struct msg_msgseg *) kmalloc (sizeof(*seg) + alen, GFP_KERNEL);
+		if(seg==NULL) {
+			err=-ENOMEM;
+			goto out_err;
+		}
+		*pseg = seg;
+		seg->next = NULL;
+		if(copy_from_user (seg+1, src, alen)) {
+			err = -EFAULT;
+			goto out_err;
+		}
+		pseg = &seg->next;
+		len -= alen;
+		src = ((char*)src)+alen;
+	}
+	return msg;
+
+out_err:
+	free_msg(msg);
+	return ERR_PTR(err);
+}
+
+static int store_msg(void* dest, struct msg_msg* msg, int len)
+{
+	int alen;
+	struct msg_msgseg *seg;
+
+	alen = len;
+	if(alen > DATALEN_MSG)
+		alen = DATALEN_MSG;
+	if(copy_to_user (dest, msg+1, alen))
+		return -1;
+
+	len -= alen;
+	dest = ((char*)dest)+alen;
+	seg = msg->next;
+	while(len > 0) {
+		alen = len;
+		if(alen > DATALEN_SEG)
+			alen = DATALEN_SEG;
+		if(copy_to_user (dest, seg+1, alen))
+			return -1;
+		len -= alen;
+		dest = ((char*)dest)+alen;
+		seg=seg->next;
+	}
+	return 0;
+}
+
+static inline void ss_add(struct msg_queue* msq, struct msg_sender* mss)
+{
+	mss->tsk=current;
+	current->state=TASK_INTERRUPTIBLE;
+	list_add_tail(&mss->list,&msq->q_senders);
+}
+
+static inline void ss_del(struct msg_sender* mss)
+{
+	if(mss->list.next != NULL)
+		list_del(&mss->list);
+}
 
-	if (id > msg_max_id)
-		msg_max_id = id;
-	spin_lock(&msg_que[id].lock);
-	msg_que[id].q = msq;
-	spin_unlock(&msg_que[id].lock);
-	msg_used_queues++;
+static void ss_wakeup(struct list_head* h, int kill)
+{
+	struct list_head *tmp;
 
-	return (int)msq->q_perm.seq * MSGMNI + id;
+	tmp = h->next;
+	while (tmp != h) {
+		struct msg_sender* mss;
+		
+		mss = list_entry(tmp,struct msg_sender,list);
+		tmp = tmp->next;
+		if(kill)
+			mss->list.next=NULL;
+		wake_up_process(mss->tsk);
+	}
 }
 
 static void expunge_all(struct msg_queue* msq, int res)
@@ -189,48 +283,32 @@
 	struct msg_queue *msq;
 	struct list_head *tmp;
 
-	msq=msg_que[id].q;
-	msg_que[id].q = NULL;
-	if (id == msg_max_id) {
-		while ((msg_que[msg_max_id].q == NULL)) {
-			if(msg_max_id--== 0)
-				break;
-		}
-	}
-	msg_used_queues--;
+	msq = msg_rmid(id);
 
 	expunge_all(msq,-EIDRM);
-
-	while(waitqueue_active(&msq->q_rwait)) {
-		wake_up(&msq->q_rwait);
-		spin_unlock(&msg_que[id].lock);
-		current->policy |= SCHED_YIELD;
-		schedule();
-		spin_lock(&msg_que[id].lock);
-	}
-	spin_unlock(&msg_que[id].lock);
+	ss_wakeup(&msq->q_senders,1);
+	msg_unlock(id);
 		
 	tmp = msq->q_messages.next;
 	while(tmp != &msq->q_messages) {
 		struct msg_msg* msg = list_entry(tmp,struct msg_msg,m_list);
 		tmp = tmp->next;
 		atomic_dec(&msg_hdrs);
-		kfree(msg);
+		free_msg(msg);
 	}
 	atomic_sub(msq->q_cbytes, &msg_bytes);
 	kfree(msq);
 }
 
-
 asmlinkage long sys_msgget (key_t key, int msgflg)
 {
 	int id, ret = -EPERM;
 	struct msg_queue *msq;
 	
-	down(&msg_lock);
+	down(&msg_ids.sem);
 	if (key == IPC_PRIVATE) 
 		ret = newque(key, msgflg);
-	else if ((id = findkey (key)) == -1) { /* key not used */
+	else if ((id = ipc_findkey(&msg_ids, key)) == -1) { /* key not used */
 		if (!(msgflg & IPC_CREAT))
 			ret = -ENOENT;
 		else
@@ -238,55 +316,62 @@
 	} else if (msgflg & IPC_CREAT && msgflg & IPC_EXCL) {
 		ret = -EEXIST;
 	} else {
-		msq = msg_que[id].q;
+		msq = msg_lock(id);
+		if(msq==NULL)
+			BUG();
 		if (ipcperms(&msq->q_perm, msgflg))
 			ret = -EACCES;
 		else
-			ret = (unsigned int) msq->q_perm.seq * MSGMNI + id;
+			ret = msg_buildid(id, msq->q_perm.seq);
+		msg_unlock(id);
 	}
-	up(&msg_lock);
+	up(&msg_ids.sem);
 	return ret;
 }
 
 asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
 {
-	int id, err;
+	int err;
 	struct msg_queue *msq;
 	struct msqid_ds tbuf;
 	struct ipc_perm *ipcp;
 	
 	if (msqid < 0 || cmd < 0)
 		return -EINVAL;
-	id = msqid % MSGMNI;
+
 	switch (cmd) {
 	case IPC_INFO: 
 	case MSG_INFO: 
 	{ 
 		struct msginfo msginfo;
+		int max_id;
 		if (!buf)
 			return -EFAULT;
 		/* We must not return kernel stack data.
-		 * due to variable alignment, it's not enough
+		 * due to padding, it's not enough
 		 * to set all member fields.
 		 */
 		memset(&msginfo,0,sizeof(msginfo));	
-		msginfo.msgmni = MSGMNI;
-		msginfo.msgmax = MSGMAX;
-		msginfo.msgmnb = MSGMNB;
-		msginfo.msgmap = MSGMAP;
-		msginfo.msgpool = MSGPOOL;
-		msginfo.msgtql = MSGTQL;
+		msginfo.msgmni = msg_ctlmni;
+		msginfo.msgmax = msg_ctlmax;
+		msginfo.msgmnb = msg_ctlmnb;
 		msginfo.msgssz = MSGSSZ;
 		msginfo.msgseg = MSGSEG;
+		down(&msg_ids.sem);
 		if (cmd == MSG_INFO) {
-			msginfo.msgpool = msg_used_queues;
+			msginfo.msgpool = msg_ids.in_use;
 			msginfo.msgmap = atomic_read(&msg_hdrs);
 			msginfo.msgtql = atomic_read(&msg_bytes);
+		} else {
+			msginfo.msgmap = MSGMAP;
+			msginfo.msgpool = MSGPOOL;
+			msginfo.msgtql = MSGTQL;
 		}
-
+		max_id = msg_ids.max_id;
+		up(&msg_ids.sem);
 		if (copy_to_user (buf, &msginfo, sizeof(struct msginfo)))
 			return -EFAULT;
-		return (msg_max_id < 0) ? 0: msg_max_id;
+		return (max_id < 0) ? 0: max_id;
 	}
 	case MSG_STAT:
 	case IPC_STAT:
@@ -294,19 +379,18 @@
 		int success_return;
 		if (!buf)
 			return -EFAULT;
-		if(cmd == MSG_STAT && msqid > MSGMNI)
+		if(cmd == MSG_STAT && msqid > msg_ids.size)
 			return -EINVAL;
 
-		spin_lock(&msg_que[id].lock);
-		msq = msg_que[id].q;
-		err = -EINVAL;
+		msq = msg_lock(msqid);
 		if (msq == NULL)
-			goto out_unlock;
+			return -EINVAL;
+
 		if(cmd == MSG_STAT) {
-			success_return = (unsigned int) msq->q_perm.seq * MSGMNI + msqid;
+			success_return = msg_buildid(msqid, msq->q_perm.seq);
 		} else {
 			err = -EIDRM;
-			if (msq->q_perm.seq != (unsigned int) msqid / MSGMNI)
+			if (msg_checkid(msq,msqid))
 				goto out_unlock;
 			success_return = 0;
 		}
@@ -339,7 +423,7 @@
 
 		tbuf.msg_lspid  = msq->q_lspid;
 		tbuf.msg_lrpid  = msq->q_lrpid;
-		spin_unlock(&msg_que[id].lock);
+		msg_unlock(msqid);
 		if (copy_to_user (buf, &tbuf, sizeof(*buf)))
 			return -EFAULT;
 		return success_return;
@@ -356,32 +440,31 @@
 		return  -EINVAL;
 	}
 
-	down(&msg_lock);
-	spin_lock(&msg_que[id].lock);
-	msq = msg_que[id].q;
-	err = -EINVAL;
+	down(&msg_ids.sem);
+	msq = msg_lock(msqid);
+	err=-EINVAL;
 	if (msq == NULL)
-		goto out_unlock_up;
+		goto out_up;
+
 	err = -EIDRM;
-	if (msq->q_perm.seq != (unsigned int) msqid / MSGMNI)
+	if (msg_checkid(msq,msqid))
 		goto out_unlock_up;
 	ipcp = &msq->q_perm;
+	err = -EPERM;
+	if (current->euid != ipcp->cuid && 
+	    current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
+	    /* We _could_ check for CAP_CHOWN above, but we don't */
+		goto out_unlock_up;
 
 	switch (cmd) {
 	case IPC_SET:
 	{
 		int newqbytes;
-		err = -EPERM;
-		if (current->euid != ipcp->cuid && 
-		    current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
-		    /* We _could_ check for CAP_CHOWN above, but we don't */
-			goto out_unlock_up;
-
 		if(tbuf.msg_qbytes == 0)
 			newqbytes = tbuf.msg_lqbytes;
 		 else
 		 	newqbytes = tbuf.msg_qbytes;
-		if (newqbytes > MSGMNB && !capable(CAP_SYS_RESOURCE))
+		if (newqbytes > msg_ctlmnb && !capable(CAP_SYS_RESOURCE))
 			goto out_unlock_up;
 		msq->q_qbytes = newqbytes;
 
@@ -397,27 +480,23 @@
 		/* sleeping senders might be able to send
 		 * due to a larger queue size.
 		 */
-		wake_up(&msq->q_rwait);
-		spin_unlock(&msg_que[id].lock);
+		ss_wakeup(&msq->q_senders,0);
+		msg_unlock(msqid);
 		break;
 	}
 	case IPC_RMID:
-		err = -EPERM;
-		if (current->euid != ipcp->cuid && 
-		    current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
-			goto out_unlock;
-		freeque (id); 
+		freeque (msqid); 
 		break;
 	}
 	err = 0;
 out_up:
-	up(&msg_lock);
+	up(&msg_ids.sem);
 	return err;
 out_unlock_up:
-	spin_unlock(&msg_que[id].lock);
+	msg_unlock(msqid);
 	goto out_up;
 out_unlock:
-	spin_unlock(&msg_que[id].lock);
+	msg_unlock(msqid);
 	return err;
 }
 
@@ -471,67 +550,61 @@
 
 asmlinkage long sys_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg)
 {
-	int id;
 	struct msg_queue *msq;
 	struct msg_msg *msg;
 	long mtype;
 	int err;
 	
-	if (msgsz > MSGMAX || (long) msgsz < 0 || msqid < 0)
+	if (msgsz > msg_ctlmax || (long) msgsz < 0 || msqid < 0)
 		return -EINVAL;
 	if (get_user(mtype, &msgp->mtype))
 		return -EFAULT; 
 	if (mtype < 1)
 		return -EINVAL;
 
-	msg = (struct msg_msg *) kmalloc (sizeof(*msg) + msgsz, GFP_KERNEL);
-	if(msg==NULL)
-		return -ENOMEM;
+	msg = load_msg(msgp->mtext, msgsz);
+	if(IS_ERR(msg))
+		return PTR_ERR(msg);
 
-	if (copy_from_user(msg+1, msgp->mtext, msgsz)) {
-		kfree(msg);
-		return -EFAULT;
-	}	
 	msg->m_type = mtype;
 	msg->m_ts = msgsz;
 
-	id = (unsigned int) msqid % MSGMNI;
-	spin_lock(&msg_que[id].lock);
-	err= -EINVAL;
-retry:
-	msq = msg_que[id].q;
-	if (msq == NULL)
+	msq = msg_lock(msqid);
+	err=-EINVAL;
+	if(msq==NULL)
 		goto out_free;
-
+retry:
 	err= -EIDRM;
-	if (msq->q_perm.seq != (unsigned int) msqid / MSGMNI) 
-		goto out_free;
+	if (msg_checkid(msq,msqid))
+		goto out_unlock_free;
 
 	err=-EACCES;
 	if (ipcperms(&msq->q_perm, S_IWUGO)) 
-		goto out_free;
+		goto out_unlock_free;
 
-	if(msgsz + msq->q_cbytes > msq->q_qbytes) {
-		DECLARE_WAITQUEUE(wait,current);
+	if(msgsz + msq->q_cbytes > msq->q_qbytes ||
+		1 + msq->q_qnum > msq->q_qbytes) {
+		struct msg_sender s;
 
 		if(msgflg&IPC_NOWAIT) {
 			err=-EAGAIN;
-			goto out_free;
+			goto out_unlock_free;
 		}
-		current->state = TASK_INTERRUPTIBLE;
-		add_wait_queue(&msq->q_rwait,&wait);
-		spin_unlock(&msg_que[id].lock);
+		ss_add(msq, &s);
+		msg_unlock(msqid);
 		schedule();
 		current->state= TASK_RUNNING;
+
+		msq = msg_lock(msqid);
+		err = -EIDRM;
+		if(msq==NULL)
+			goto out_free;
+		ss_del(&s);
 		
-		remove_wait_queue(&msq->q_rwait,&wait);
 		if (signal_pending(current)) {
-			kfree(msg);
-			return -EINTR;
+			err=-EINTR;
+			goto out_unlock_free;
 		}
-
-		spin_lock(&msg_que[id].lock);
-		err = -EIDRM;
 		goto retry;
 	}
 
@@ -549,10 +622,11 @@
 	msq->q_lspid = current->pid;
 	msq->q_stime = CURRENT_TIME;
 
+out_unlock_free:
+	msg_unlock(msqid);
 out_free:
 	if(msg!=NULL)
-		kfree(msg);
-	spin_unlock(&msg_que[id].lock);
+		free_msg(msg);
 	return err;
 }
 
@@ -582,7 +656,6 @@
 	struct msg_receiver msr_d;
 	struct list_head* tmp;
 	struct msg_msg* msg, *found_msg;
-	int id;
 	int err;
 	int mode;
 
@@ -590,13 +663,10 @@
 		return -EINVAL;
 	mode = convert_mode(&msgtyp,msgflg);
 
-	id = (unsigned int) msqid % MSGMNI;
-	spin_lock(&msg_que[id].lock);
+	msq = msg_lock(msqid);
+	if(msq==NULL)
+		return -EINVAL;
 retry:
-	msq = msg_que[id].q;
-	err=-EINVAL;
-	if (msq == NULL)
-		goto out_unlock;
 	err=-EACCES;
 	if (ipcperms (&msq->q_perm, S_IRUGO))
 		goto out_unlock;
@@ -630,21 +700,19 @@
 		msq->q_cbytes -= msg->m_ts;
 		atomic_sub(msg->m_ts,&msg_bytes);
 		atomic_dec(&msg_hdrs);
-		if(waitqueue_active(&msq->q_rwait))
-			wake_up(&msq->q_rwait);
-out_success_unlock:
-		spin_unlock(&msg_que[id].lock);
+		ss_wakeup(&msq->q_senders,0);
+		msg_unlock(msqid);
 out_success:
 		msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz;
 		if (put_user (msg->m_type, &msgp->mtype) ||
-			    copy_to_user (msgp->mtext, msg+1, msgsz))
-		{
+		    store_msg(msgp->mtext, msg, msgsz)) {
 			    msgsz = -EFAULT;
 		}
-		kfree(msg);
+		free_msg(msg);
 		return msgsz;
 	} else
 	{
+		struct msg_queue *t;
 		/* no message waiting. Prepare for pipelined
 		 * receive.
 		 */
@@ -657,12 +725,13 @@
 		msr_d.r_msgtype = msgtyp;
 		msr_d.r_mode = mode;
 		if(msgflg & MSG_NOERROR)
-			msr_d.r_maxsize = MSGMAX;
+			msr_d.r_maxsize = INT_MAX;
 		 else
 		 	msr_d.r_maxsize = msgsz;
 		msr_d.r_msg = ERR_PTR(-EAGAIN);
 		current->state = TASK_INTERRUPTIBLE;
-		spin_unlock(&msg_que[id].lock);
+		msg_unlock(msqid);
+
 		schedule();
 		current->state = TASK_RUNNING;
 
@@ -670,16 +739,22 @@
 		if(!IS_ERR(msg)) 
 			goto out_success;
 
-		spin_lock(&msg_que[id].lock);
+		t = msg_lock(msqid);
+		if(t==NULL)
+			msqid=-1;
 		msg = (struct msg_msg*)msr_d.r_msg;
 		if(!IS_ERR(msg)) {
 			/* our message arived while we waited for
 			 * the spinlock. Process it.
 			 */
-			goto out_success_unlock;
+			if(msqid!=-1)
+				msg_unlock(msqid);
+			goto out_success;
 		}
 		err = PTR_ERR(msg);
 		if(err == -EAGAIN) {
+			if(msqid==-1)
+				BUG();
 			list_del(&msr_d.r_list);
 			if (signal_pending(current))
 				err=-EINTR;
@@ -688,7 +763,8 @@
 		}
 	}
 out_unlock:
-	spin_unlock(&msg_que[id].lock);
+	if(msqid!=-1)
+		msg_unlock(msqid);
 	return err;
 }
 
@@ -699,28 +775,29 @@
 	off_t begin = 0;
 	int i, len = 0;
 
-	down(&msg_lock);
+	down(&msg_ids.sem);
 	len += sprintf(buffer, "       key      msqid perms cbytes  qnum lspid lrpid   uid   gid  cuid  cgid      stime      rtime      ctime\n");
 
-	for(i = 0; i <= msg_max_id; i++) {
-		spin_lock(&msg_que[i].lock);
-		if(msg_que[i].q != NULL) {
+	for(i = 0; i <= msg_ids.max_id; i++) {
+		struct msg_queue * msq;
+		msq = msg_lock(i);
+		if(msq != NULL) {
 			len += sprintf(buffer + len, "%10d %10d  %4o  %5u %5u %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n",
-				msg_que[i].q->q_perm.key,
-				msg_que[i].q->q_perm.seq * MSGMNI + i,
-				msg_que[i].q->q_perm.mode,
-				msg_que[i].q->q_cbytes,
-				msg_que[i].q->q_qnum,
-				msg_que[i].q->q_lspid,
-				msg_que[i].q->q_lrpid,
-				msg_que[i].q->q_perm.uid,
-				msg_que[i].q->q_perm.gid,
-				msg_que[i].q->q_perm.cuid,
-				msg_que[i].q->q_perm.cgid,
-				msg_que[i].q->q_stime,
-				msg_que[i].q->q_rtime,
-				msg_que[i].q->q_ctime);
-			spin_unlock(&msg_que[i].lock);
+				msq->q_perm.key,
+				msg_buildid(i,msq->q_perm.seq),
+				msq->q_perm.mode,
+				msq->q_cbytes,
+				msq->q_qnum,
+				msq->q_lspid,
+				msq->q_lrpid,
+				msq->q_perm.uid,
+				msq->q_perm.gid,
+				msq->q_perm.cuid,
+				msq->q_perm.cgid,
+				msq->q_stime,
+				msq->q_rtime,
+				msq->q_ctime);
+			msg_unlock(i);
 
 			pos += len;
 			if(pos < offset) {
@@ -729,13 +806,12 @@
 			}
 			if(pos > offset + length)
 				goto done;
-		} else {
-			spin_unlock(&msg_que[i].lock);
 		}
+
 	}
 	*eof = 1;
 done:
-	up(&msg_lock);
+	up(&msg_ids.sem);
 	*start = buffer + (offset - begin);
 	len -= (offset - begin);
 	if(len > length)
@@ -745,4 +821,3 @@
 	return len;
 }
 #endif
-
diff -u --recursive --new-file v2.3.26/linux/ipc/sem.c linux/ipc/sem.c
--- v2.3.26/linux/ipc/sem.c	Mon Nov  1 13:56:27 1999
+++ linux/ipc/sem.c	Tue Nov  9 10:02:36 1999
@@ -51,7 +51,8 @@
  *
  * /proc/sysvipc/sem support (c) 1999 Dragos Acostachioaie <dragos@iname.com>
  *
- * SMP-threaded (c) 1999 Manfred Spraul <manfreds@colorfullife.com>
+ * SMP-threaded, sysctl's added
+ * (c) 1999 Manfred Spraul <manfreds@colorfullife.com>
  */
 
 #include <linux/config.h>
@@ -59,120 +60,91 @@
 #include <linux/spinlock.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
-
 #include <asm/uaccess.h>
+#include "util.h"
+
+
+#define sem_lock(id)	((struct semid_ds*)ipc_lock(&sem_ids,id))
+#define sem_unlock(id)	ipc_unlock(&sem_ids,id)
+#define sem_rmid(id)	((struct semid_ds*)ipc_rmid(&sem_ids,id))
+#define sem_checkid(sma, semid)	\
+	ipc_checkid(&sem_ids,&sma->sem_perm,semid)
+#define sem_buildid(id, seq) \
+	ipc_buildid(&sem_ids, id, seq)
+static struct ipc_ids sem_ids;
 
-extern int ipcperms (struct ipc_perm *ipcp, short semflg);
 static int newary (key_t, int, int);
-static int findkey (key_t key);
 static void freeary (int id);
 #ifdef CONFIG_PROC_FS
 static int sysvipc_sem_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
 #endif
 
-struct semid_ary
-{
-	spinlock_t lock;
-	struct semid_ds* s;
-};
-
-static struct semid_ary semary[SEMMNI];
-
-static DECLARE_MUTEX(sem_lock);
-static int max_semid = 0;
-static int used_sems = 0;
-static int used_semids = 0;
-
-static unsigned short sem_seq = 0;
+#define SEMMSL_FAST	256 /* 512 bytes on stack */
+#define SEMOPM_FAST	64  /* ~ 372 bytes on stack */
 
-/* anti-deadlock ordering:
- *	sem_lock < semary[].lock
+/*
  * linked list protection:
  *	sem_undo.id_next,
  *	semid_ds.sem_pending{,last},
- *	semid_ds.sem_undo: semary[].lock for read/write
+ *	semid_ds.sem_undo: sem_lock() for read/write
  *	sem_undo.proc_next: only "current" is allowed to read/write that field.
  *	
  */
 
+int sem_ctls[4] = {SEMMSL, SEMMNS, SEMOPM, SEMMNI};
+#define sc_semmsl	(sem_ctls[0])
+#define sc_semmns	(sem_ctls[1])
+#define sc_semopm	(sem_ctls[2])
+#define sc_semmni	(sem_ctls[3])
+
+static int used_sems = 0;
+
 void __init sem_init (void)
 {
-	int i;
+	used_sems = 0;
+	ipc_init_ids(&sem_ids,sc_semmni);
 
-	used_sems = used_semids = max_semid = sem_seq = 0;
-	for (i = 0; i < SEMMNI; i++) {
-		semary[i].lock = SPIN_LOCK_UNLOCKED;
-		semary[i].s = NULL;
-	}
 #ifdef CONFIG_PROC_FS
 	create_proc_read_entry("sysvipc/sem", 0, 0, sysvipc_sem_read_proc, NULL);
 #endif
-	return;
-}
-
-static int findkey (key_t key)
-{
-	int id;
-	struct semid_ds *sma;
-
-	for (id = 0; id <= max_semid; id++) {
-		sma = semary[id].s;
-		if(sma==NULL)
-			continue;
-
-		if (key == sma->sem_perm.key)
-			return id;
-	}
-	return -1;
 }
 
 static int newary (key_t key, int nsems, int semflg)
 {
 	int id;
 	struct semid_ds *sma;
-	struct ipc_perm *ipcp;
 	int size;
 
 	if (!nsems)
 		return -EINVAL;
-	if (used_sems + nsems > SEMMNS)
+	if (used_sems + nsems > sc_semmns)
 		return -ENOSPC;
-	for (id = 0; id < SEMMNI; id++) {
-		if(semary[id].s == NULL)
-			goto found;
-	}
-	return -ENOSPC;
-found:
+
 	size = sizeof (*sma) + nsems * sizeof (struct sem);
-	used_sems += nsems;
-	sma = (struct semid_ds *) kmalloc (size, GFP_KERNEL);
+	sma = (struct semid_ds *) ipc_alloc(size);
 	if (!sma) {
-		used_sems -= nsems;
 		return -ENOMEM;
 	}
 	memset (sma, 0, size);
+	id = ipc_addid(&sem_ids, &sma->sem_perm, sc_semmni);
+	if(id == -1) {
+		ipc_free(sma, size);
+		return -ENOSPC;
+	}
+	used_sems += nsems;
+
+	sma->sem_perm.mode = (semflg & S_IRWXUGO);
+	sma->sem_perm.key = key;
+
 	sma->sem_base = (struct sem *) &sma[1];
-	ipcp = &sma->sem_perm;
-	ipcp->mode = (semflg & S_IRWXUGO);
-	ipcp->key = key;
-	ipcp->cuid = ipcp->uid = current->euid;
-	ipcp->gid = ipcp->cgid = current->egid;
-	/* sma->sem_perm.seq*MSGMNI must be a positive integer.
-	 * this limits MSGMNI to 32768
-	 */
-	sma->sem_perm.seq = sem_seq++;
 	/* sma->sem_pending = NULL; */
 	sma->sem_pending_last = &sma->sem_pending;
 	/* sma->undo = NULL; */
 	sma->sem_nsems = nsems;
 	sma->sem_ctime = CURRENT_TIME;
-	if (id > max_semid)
-		max_semid = id;
-	used_semids++;
-	spin_lock(&semary[id].lock);
-	semary[id].s = sma;
-	spin_unlock(&semary[id].lock);
-	return (unsigned int) sma->sem_perm.seq * SEMMNI + id;
+	sem_unlock(id);
+
+	return sem_buildid(id, sma->sem_perm.seq);
 }
 
 asmlinkage long sys_semget (key_t key, int nsems, int semflg)
@@ -180,13 +152,13 @@
 	int id, err = -EINVAL;
 	struct semid_ds *sma;
 
-	if (nsems < 0 || nsems > SEMMSL)
+	if (nsems < 0 || nsems > sc_semmsl)
 		return -EINVAL;
-	down(&sem_lock);
+	down(&sem_ids.sem);
 	
 	if (key == IPC_PRIVATE) {
 		err = newary(key, nsems, semflg);
-	} else if ((id = findkey (key)) == -1) {  /* key not used */
+	} else if ((id = ipc_findkey(&sem_ids, key)) == -1) {  /* key not used */
 		if (!(semflg & IPC_CREAT))
 			err = -ENOENT;
 		else
@@ -194,19 +166,46 @@
 	} else if (semflg & IPC_CREAT && semflg & IPC_EXCL) {
 		err = -EEXIST;
 	} else {
-		sma = semary[id].s;
+		sma = sem_lock(id);
+		if(sma==NULL)
+			BUG();
 		if (nsems > sma->sem_nsems)
 			err = -EINVAL;
 		else if (ipcperms(&sma->sem_perm, semflg))
 			err = -EACCES;
 		else
-			err = (int) sma->sem_perm.seq * SEMMNI + id;
+			err = sem_buildid(id, sma->sem_perm.seq);
+		sem_unlock(id);
 	}
 
-	up(&sem_lock);
+	up(&sem_ids.sem);
 	return err;
 }
 
+/* doesn't acquire the sem_lock on error! */
+static int sem_revalidate(int semid, struct semid_ds* sma, int nsems, short flg)
+{
+	struct semid_ds* smanew;
+
+	smanew = sem_lock(semid);
+	if(smanew==NULL)
+		return -EIDRM;
+	if(smanew != sma)
+		goto out_EIDRM;
+	if(sem_checkid(sma,semid))
+		goto out_EIDRM;
+	if(sma->sem_nsems != nsems) {
+out_EIDRM:
+		sem_unlock(semid);
+		return -EIDRM;
+	}
+
+	if (ipcperms(&sma->sem_perm, flg)) {
+		sem_unlock(semid);
+		return -EACCES;
+	}
+	return 0;
+}
 /* Manage the doubly linked list sma->sem_pending as a FIFO:
  * insert new queue elements at the tail sma->sem_pending_last.
  */
@@ -387,15 +386,9 @@
 	struct semid_ds *sma;
 	struct sem_undo *un;
 	struct sem_queue *q;
+	int size;
 
-	/* we own both locks, noone can get in */
-	sma = semary[id].s;
-	semary[id].s = NULL;
-
-	used_sems -= sma->sem_nsems;
-	if (id == max_semid)
-		while (max_semid && (semary[--max_semid].s == NULL));
-	used_semids--;
+	sma = sem_rmid(id);
 
 	/* Invalidate the existing undo structures for this semaphore set.
 	 * (They will be freed without any further action in sem_exit()
@@ -410,40 +403,46 @@
 		q->prev = NULL;
 		wake_up_process(q->sleeper); /* doesn't sleep */
 	}
+	sem_unlock(id);
 
-	kfree(sma);
+	used_sems -= sma->sem_nsems;
+	size = sizeof (*sma) + sma->sem_nsems * sizeof (struct sem);
+	ipc_free(sma, size);
 }
 
 int semctl_nolock(int semid, int semnum, int cmd, union semun arg)
 {
 	int err = -EINVAL;
-	int lid = semid % SEMMNI;
 
 	switch(cmd) {
 	case IPC_INFO:
 	case SEM_INFO:
 	{
 		struct seminfo seminfo;
+		int max_id;
 
-		seminfo.semmni = SEMMNI;
-		seminfo.semmns = SEMMNS;
-		seminfo.semmsl = SEMMSL;
-		seminfo.semopm = SEMOPM;
+		memset(&seminfo,0,sizeof(seminfo));
+		seminfo.semmni = sc_semmni;
+		seminfo.semmns = sc_semmns;
+		seminfo.semmsl = sc_semmsl;
+		seminfo.semopm = sc_semopm;
 		seminfo.semvmx = SEMVMX;
 		seminfo.semmnu = SEMMNU;
 		seminfo.semmap = SEMMAP;
 		seminfo.semume = SEMUME;
-		seminfo.semusz = SEMUSZ;
-		seminfo.semaem = SEMAEM;
+		down(&sem_ids.sem);
 		if (cmd == SEM_INFO) {
-			down(&sem_lock);
-			seminfo.semusz = used_semids;
+			seminfo.semusz = sem_ids.in_use;
 			seminfo.semaem = used_sems;
-			up(&sem_lock);
+		} else {
+			seminfo.semusz = SEMUSZ;
+			seminfo.semaem = SEMAEM;
 		}
+		max_id = sem_ids.max_id;
+		up(&sem_ids.sem);
 		if (copy_to_user (arg.__buf, &seminfo, sizeof(struct seminfo))) 
 			return -EFAULT;
-		return max_semid;
+		return (max_id < 0) ? 0: max_id;
 	}
 	case SEM_STAT:
 	{
@@ -451,24 +450,24 @@
 		struct semid_ds tbuf;
 		int id;
 
-		if (semid > max_semid)
+		if(semid > sem_ids.size)
+			return -EINVAL;
+
+		sma = sem_lock(semid);
+		if(sma == NULL)
 			return -EINVAL;
 
-		spin_lock(&semary[lid].lock);
-		err = -EINVAL;
-		sma = semary[semid].s;
-		if (sma ==  NULL)
-			goto out_unlock;
 		err = -EACCES;
 		if (ipcperms (&sma->sem_perm, S_IRUGO))
 			goto out_unlock;
-		id = (unsigned int) sma->sem_perm.seq * SEMMNI + semid;
+		id = sem_buildid(semid, sma->sem_perm.seq);
+
 		memset(&tbuf,0,sizeof(tbuf));
 		tbuf.sem_perm   = sma->sem_perm;
 		tbuf.sem_otime  = sma->sem_otime;
 		tbuf.sem_ctime  = sma->sem_ctime;
 		tbuf.sem_nsems  = sma->sem_nsems;
-		spin_unlock(&semary[lid].lock);
+		sem_unlock(semid);
 		if (copy_to_user (arg.buf, &tbuf, sizeof(tbuf)))
 			return -EFAULT;
 		return id;
@@ -478,99 +477,136 @@
 	}
 	return err;
 out_unlock:
-	spin_unlock(&semary[lid].lock);
+	sem_unlock(semid);
 	return err;
 }
 
-int semctl_locked_unlock(int semid, int semnum, int cmd, union semun arg)
+int semctl_main(int semid, int semnum, int cmd, union semun arg)
 {
 	struct semid_ds *sma;
-	struct semid_ds tbuf;
+	struct sem* curr;
 	int err;
-	int lid = semid % SEMMNI;
+	ushort fast_sem_io[SEMMSL_FAST];
+	ushort* sem_io = fast_sem_io;
+	int nsems;
+
+	sma = sem_lock(semid);
+	if(sma==NULL)
+		return -EINVAL;
 
-	sma = semary[lid].s;
-	err=-EINVAL;
-	if (sma == NULL)
-		goto out_unlock;
 	err=-EIDRM;
-	if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
+	if (sem_checkid(sma,semid))
 		goto out_unlock;
 
 	err = -EACCES;
-	if (ipcperms(&sma->sem_perm, S_IRUGO))
-			goto out_unlock;	
-	
+	if (ipcperms (&sma->sem_perm, (cmd==SETVAL||cmd==SETALL)?S_IWUGO:S_IRUGO))
+		goto out_unlock;
+
+	nsems = sma->sem_nsems;
 	switch (cmd) {
 	case GETALL:
 	{
 		ushort *array = arg.array;
-		ushort sem_io[SEMMSL];
 		int i;
-		int nsems = sma->sem_nsems;
+
+		if(nsems > SEMMSL_FAST) {
+			sem_unlock(semid);			
+			sem_io = ipc_alloc(sizeof(ushort)*nsems);
+			if(sem_io == NULL)
+				return -ENOMEM;
+			err = sem_revalidate(semid, sma, nsems, S_IRUGO);
+			if(err)
+				goto out_free;
+		}
 
 		for (i = 0; i < sma->sem_nsems; i++)
 			sem_io[i] = sma->sem_base[i].semval;
-		spin_unlock(&semary[lid].lock);
-		if (copy_to_user (array, sem_io, nsems*sizeof(ushort)))
-			return -EFAULT;
-		return 0;
+		sem_unlock(semid);
+		err = 0;
+		if(copy_to_user(array, sem_io, nsems*sizeof(ushort)))
+			err = -EFAULT;
+		goto out_free;
+	}
+	case SETALL:
+	{
+		int i;
+		struct sem_undo *un;
+
+		sem_unlock(semid);
+
+		if(nsems > SEMMSL_FAST) {
+			sem_io = ipc_alloc(sizeof(ushort)*nsems);
+			if(sem_io == NULL)
+				return -ENOMEM;
+		}
+
+		if (copy_from_user (sem_io, arg.array, nsems*sizeof(ushort))) {
+			err = -EFAULT;
+			goto out_free;
+		}
+
+		for (i = 0; i < nsems; i++) {
+			if (sem_io[i] > SEMVMX) {
+				err = -ERANGE;
+				goto out_free;
+			}
+		}
+		err = sem_revalidate(semid, sma, nsems, S_IWUGO);
+		if(err)
+			goto out_free;
+
+		for (i = 0; i < nsems; i++)
+			sma->sem_base[i].semval = sem_io[i];
+		for (un = sma->undo; un; un = un->id_next)
+			for (i = 0; i < nsems; i++)
+				un->semadj[i] = 0;
+		sma->sem_ctime = CURRENT_TIME;
+		/* maybe some queued-up processes were waiting for this */
+		update_queue(sma);
+		err = 0;
+		goto out_unlock;
 	}
 	case IPC_STAT:
+	{
+		struct semid_ds tbuf;
 		memset(&tbuf,0,sizeof(tbuf));
 		tbuf.sem_perm   = sma->sem_perm;
 		tbuf.sem_otime  = sma->sem_otime;
 		tbuf.sem_ctime  = sma->sem_ctime;
 		tbuf.sem_nsems  = sma->sem_nsems;
-		spin_unlock(&semary[lid].lock);
+		sem_unlock(semid);
 		if (copy_to_user (arg.buf, &tbuf, sizeof(tbuf)))
 			return -EFAULT;
 		return 0;
-default:
-		err = -EINVAL;
 	}
-out_unlock:
-	spin_unlock(&semary[lid].lock);
-	return err;
-
-}
-
-int semctl_locked(int semid, int semnum, int cmd, union semun arg)
-{
-	struct semid_ds *sma;
-	int lid = semid % SEMMNI;
-	struct sem *curr;
-
-	sma = semary[lid].s;
-	if (sma == NULL)
-		return -EINVAL;
-
-	if (ipcperms (&sma->sem_perm, (cmd==SETVAL)?S_IWUGO:S_IRUGO))
-		return -EACCES;
-
-	if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
-		return -EIDRM;
-
-	if (semnum >= sma->sem_nsems)
-		return -EINVAL;
+	/* GETVAL, GETPID, GETNCTN, GETZCNT, SETVAL: fall-through */
+	}
+	err = -EINVAL;
+	if(semnum < 0 || semnum >= nsems)
+		goto out_unlock;
 
 	curr = &sma->sem_base[semnum];
 
 	switch (cmd) {
 	case GETVAL:
-		return curr->semval;
+		err = curr->semval;
+		goto out_unlock;
 	case GETPID:
-		return curr->sempid & 0xffff;
+		err = curr->sempid & 0xffff;
+		goto out_unlock;
 	case GETNCNT:
-		return count_semncnt(sma,semnum);
+		err = count_semncnt(sma,semnum);
+		goto out_unlock;
 	case GETZCNT:
-		return count_semzcnt(sma,semnum);
+		err = count_semzcnt(sma,semnum);
+		goto out_unlock;
 	case SETVAL:
 	{
 		int val = arg.val;
 		struct sem_undo *un;
+		err = -ERANGE;
 		if (val > SEMVMX || val < 0)
-			return -ERANGE;
+			goto out_unlock;
 
 		for (un = sma->undo; un; un = un->id_next)
 			un->semadj[semnum] = 0;
@@ -578,17 +614,22 @@
 		sma->sem_ctime = CURRENT_TIME;
 		/* maybe some queued-up processes were waiting for this */
 		update_queue(sma);
-		return 0;
+		err = 0;
+		goto out_unlock;
 	}
 	}
-	return -EINVAL;
+out_unlock:
+	sem_unlock(semid);
+out_free:
+	if(sem_io != fast_sem_io)
+		ipc_free(sem_io, sizeof(ushort)*nsems);
+	return err;
 }
 
 int semctl_down(int semid, int semnum, int cmd, union semun arg)
 {
 	struct semid_ds *sma;
 	int err;
-	int lid = semid % SEMMNI;
 	struct semid_ds tbuf;
 	struct ipc_perm *ipcp;
 
@@ -596,66 +637,25 @@
 		if(copy_from_user (&tbuf, arg.buf, sizeof (tbuf)))
 			return -EFAULT;
 	}
-	spin_lock(&semary[lid].lock);
-	sma = semary[lid].s;
-	err=-EINVAL;
-	if (sma == NULL)
+	sma = sem_lock(semid);
+	if(sma==NULL)
+		return -EINVAL;
+
+	if (sem_checkid(sma,semid)) {
+		err=-EIDRM;
 		goto out_unlock;
+	}	
 	ipcp = &sma->sem_perm;
 	
-	if(cmd == SETALL) {
-		int i;
-		struct sem_undo *un;
-		unsigned int nsems;
-		ushort sem_io[SEMMSL];
-		/* SETALL doesn't belong into this
-		 * group, but I need the semaphore
-		 * for atomically reading nsems
-		 * and changing the semaphore values
-		 */
-		err=-EACCES;
-		if (ipcperms (ipcp, S_IWUGO))
-			goto out_unlock;
-		nsems=sma->sem_nsems;
-		spin_unlock(&semary[lid].lock);
-
-		if (copy_from_user (sem_io, arg.array, nsems*sizeof(ushort)))
-			return -EFAULT;
-		for (i = 0; i < nsems; i++) {
-			if (sem_io[i] > SEMVMX) {
-				return -ERANGE;
-			}
-		}
-		/* we still own sem_lock, ie neither ownership
-		 * nor permissions of the sem array could
-		 * have changed. Just continue.
-		 */
-		spin_lock(&semary[lid].lock);
-		for (i = 0; i < nsems; i++)
-			sma->sem_base[i].semval = sem_io[i];
-		for (un = sma->undo; un; un = un->id_next)
-			for (i = 0; i < nsems; i++)
-				un->semadj[i] = 0;
-		sma->sem_ctime = CURRENT_TIME;
-		/* maybe some queued-up processes were waiting for this */
-		update_queue(sma);
-		err = 0;
-		goto out_unlock;
-	}
-
 	if (current->euid != ipcp->cuid && 
 	    current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
 	    	err=-EPERM;
 		goto out_unlock;
 	}
-		
-	if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI) {
-		err=-EIDRM;
-		goto out_unlock;
-	}	
+
 	switch(cmd){
 	case IPC_RMID:
-		freeary(lid);
+		freeary(semid);
 		err = 0;
 		break;
 	case IPC_SET:
@@ -664,27 +664,28 @@
 		ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
 				| (tbuf.sem_perm.mode & S_IRWXUGO);
 		sma->sem_ctime = CURRENT_TIME;
+		sem_unlock(semid);
 		err = 0;
 		break;
 	default:
+		sem_unlock(semid);
 		err = -EINVAL;
+		break;
 	}
+	return err;
 
 out_unlock:
-	spin_unlock(&semary[lid].lock);
+	sem_unlock(semid);
 	return err;
 }
 
 asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
 {
-	int lid; /* lock id */
 	int err = -EINVAL;
 
-	if (semid < 0 || semnum < 0 || cmd < 0)
+	if (semid < 0)
 		return -EINVAL;
 
-	lid = semid % SEMMNI;
-
 	switch(cmd) {
 	case IPC_INFO:
 	case SEM_INFO:
@@ -692,25 +693,20 @@
 		err = semctl_nolock(semid,semnum,cmd,arg);
 		return err;
 	case GETALL:
-	case IPC_STAT:
-		spin_lock(&semary[lid].lock);
-		err = semctl_locked_unlock(semid,semnum,cmd,arg);
-		return err;
 	case GETVAL:
 	case GETPID:
 	case GETNCNT:
 	case GETZCNT:
+	case IPC_STAT:
 	case SETVAL:
-		spin_lock(&semary[lid].lock);
-		err= semctl_locked(semid,semnum,cmd,arg);
-		spin_unlock(&semary[lid].lock);
-		return err;
 	case SETALL:
+		err = semctl_main(semid,semnum,cmd,arg);
+		return err;
 	case IPC_RMID:
 	case IPC_SET:
-		down(&sem_lock);
-		err= semctl_down(semid,semnum,cmd,arg);
-		up(&sem_lock);
+		down(&sem_ids.sem);
+		err = semctl_down(semid,semnum,cmd,arg);
+		up(&sem_ids.sem);
 		return err;
 	default:
 		return -EINVAL;
@@ -734,33 +730,27 @@
 	return un->proc_next;
 }
 
+/* returns without sem_lock on error! */
 static int alloc_undo(struct semid_ds *sma, struct sem_undo** unp, int semid, int alter)
 {
-	int size;
+	int size, nsems, error;
 	struct sem_undo *un;
-	int error,id;
-	id = (unsigned int) semid % SEMMNI;
-	size = sizeof(struct sem_undo) + sizeof(short)*sma->sem_nsems;
-	spin_unlock(&semary[id].lock);
+
+	nsems = sma->sem_nsems;
+	size = sizeof(struct sem_undo) + sizeof(short)*nsems;
+	sem_unlock(semid);
 
 	un = (struct sem_undo *) kmalloc(size, GFP_KERNEL);
-	spin_lock(&semary[id].lock);
-	if (!un) {
+	if (!un)
 		return -ENOMEM;
-	}
-	sma = semary[id].s;
-	error = -EIDRM;
-	if (sma == NULL)
-		goto out;
-	if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
-		goto out;
-	if (size != sizeof(struct sem_undo) + sizeof(short)*sma->sem_nsems)
-		goto out;
 
-	error = -EACCES;
-	if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
-		goto out;
 	memset(un, 0, size);
+	error = sem_revalidate(semid, sma, nsems, alter ? S_IWUGO : S_IRUGO);
+	if(error) {
+		kfree(un);
+		return error;
+	}
+
 	un->semadj = (short *) &un[1];
 	un->semid = semid;
 	un->proc_next = current->semundo;
@@ -769,42 +759,42 @@
 	sma->undo = un;
 	*unp = un;
 	return 0;
-out:
-	kfree(un);
-	return error;
 }
 
 asmlinkage long sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
 {
-	int id, error = -EINVAL;
+	int error = -EINVAL;
 	struct semid_ds *sma;
-	struct sembuf sops[SEMOPM], *sop;
+	struct sembuf fast_sops[SEMOPM_FAST];
+	struct sembuf* sops = fast_sops, *sop;
 	struct sem_undo *un;
 	int undos = 0, decrease = 0, alter = 0;
 	struct sem_queue queue;
 
 	if (nsops < 1 || semid < 0)
 		return -EINVAL;
-
-	if (nsops > SEMOPM)
+	if (nsops > sc_semopm)
 		return -E2BIG;
-	if (copy_from_user (sops, tsops, nsops * sizeof(*tsops)))
-		return -EFAULT;
-
-	id = (unsigned int) semid % SEMMNI;
-	spin_lock(&semary[id].lock);
-	sma = semary[id].s;
-	error = -EINVAL;
-	if (sma == NULL)
-		goto out;
+	if(nsops > SEMOPM_FAST) {
+		sops = kmalloc(sizeof(*sops)*nsops,GFP_KERNEL);
+		if(sops==NULL)
+			return -ENOMEM;
+	}
+	if (copy_from_user (sops, tsops, nsops * sizeof(*tsops))) {
+		error=-EFAULT;
+		goto out_free;
+	}
+	sma = sem_lock(semid);
+	error=-EINVAL;
+	if(sma==NULL)
+		goto out_free;
 	error = -EIDRM;
-	if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
-		goto out;
-
+	if (sem_checkid(sma,semid))
+		goto out_unlock_free;
 	error = -EFBIG;
 	for (sop = sops; sop < sops + nsops; sop++) {
 		if (sop->sem_num >= sma->sem_nsems)
-			goto out;
+			goto out_unlock_free;
 		if (sop->sem_flg & SEM_UNDO)
 			undos++;
 		if (sop->sem_op < 0)
@@ -816,7 +806,7 @@
 
 	error = -EACCES;
 	if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
-		goto out;
+		goto out_unlock_free;
 	if (undos) {
 		/* Make sure we have an undo structure
 		 * for this process and this semaphore set.
@@ -832,8 +822,8 @@
 		}
 		if (!un) {
 			error = alloc_undo(sma,&un,semid,alter);
-			if(error<0)
-				goto out;
+			if(error)
+				goto out_free;
 		}
 	} else
 		un = NULL;
@@ -852,25 +842,30 @@
 	queue.undo = un;
 	queue.pid = current->pid;
 	queue.alter = decrease;
-	queue.id = id;
-	current->semsleeping = &queue;
+	queue.id = semid;
 	if (alter)
 		append_to_queue(sma ,&queue);
 	else
 		prepend_to_queue(sma ,&queue);
+	current->semsleeping = &queue;
 
 	for (;;) {
+		struct semid_ds* tmp;
 		queue.status = -EINTR;
 		queue.sleeper = current;
 		current->state = TASK_INTERRUPTIBLE;
-		spin_unlock(&semary[id].lock);
+		sem_unlock(semid);
 
 		schedule();
 
-		/* we can lock the semary even if it was
-		 * deleted.
-		 */
-		spin_lock(&semary[id].lock);
+		tmp = sem_lock(semid);
+		if(tmp==NULL) {
+			if(queue.status != -EIDRM)
+				BUG();
+			current->semsleeping = NULL;
+			error = -EIDRM;
+			goto out_free;
+		}
 		/*
 		 * If queue.status == 1 we where woken up and
 		 * have to retry else we simply return.
@@ -890,7 +885,7 @@
 				break;
 			/* Everything done by update_queue */
 			current->semsleeping = NULL;
-			goto out;
+			goto out_unlock_free;
 		}
 	}
 	current->semsleeping = NULL;
@@ -898,8 +893,11 @@
 update:
 	if (alter)
 		update_queue (sma);
-out:
-	spin_unlock(&semary[id].lock);
+out_unlock_free:
+	sem_unlock(semid);
+out_free:
+	if(sops != fast_sops)
+		kfree(sops);
 	return error;
 }
 
@@ -925,34 +923,32 @@
 	/* If the current process was sleeping for a semaphore,
 	 * remove it from the queue.
 	 */
-	/* semsleeping is part of "current", and it
-	 * is never modified by another thread.
-	 * No synchronization required.
-	 */
 	if ((q = current->semsleeping)) {
-		spin_lock(&semary[current->semsleeping->id].lock);
+		int semid = q->id;
+		sma = sem_lock(semid);
+		current->semsleeping = NULL;
 
-		if (q->prev)
+		if (q->prev) {
+			if(sma==NULL)
+				BUG();
 			remove_from_queue(q->sma,q);
-		current->semsleeping = NULL;
-		spin_unlock(&semary[current->semsleeping->id].lock);
+		}
+		if(sma!=NULL)
+			sem_unlock(semid);
 	}
 
 	for (up = &current->semundo; (u = *up); *up = u->proc_next, kfree(u)) {
 		int semid = u->semid;
-		int lid;
 		if(semid == -1)
 			continue;
-		lid = semid % SEMMNI;
-		spin_lock(&semary[lid].lock);
+		sma = sem_lock(semid);
+		if (sma == NULL)
+			continue;
 
 		if (u->semid == -1)
 			goto next_entry;
 
-		sma = semary[lid].s;
-		if (sma == NULL)
-			goto next_entry;
-		if (sma->sem_perm.seq != (unsigned int) u->semid / SEMMNI)
+		if (sem_checkid(sma,u->semid))
 			goto next_entry;
 
 		/* remove u from the sma->undo list */
@@ -977,7 +973,7 @@
 		/* maybe some queued-up processes were waiting for this */
 		update_queue(sma);
 next_entry:
-		spin_unlock(&semary[lid].lock);
+		sem_unlock(semid);
 	}
 	current->semundo = NULL;
 }
@@ -990,35 +986,37 @@
 	int i, len = 0;
 
 	len += sprintf(buffer, "       key      semid perms nsems   uid   gid  cuid  cgid      otime      ctime\n");
-	down(&sem_lock);
+	down(&sem_ids.sem);
 
-	for(i = 0; i < SEMMNI; i++)
-		if(semary[i].s != NULL) {
-			spin_lock(&semary[i].lock);
+	for(i = 0; i <= sem_ids.max_id; i++) {
+		struct semid_ds *sma;
+		sma = sem_lock(i);
+		if(sma) {
 			len += sprintf(buffer + len, "%10d %10d  %4o %5u %5u %5u %5u %5u %10lu %10lu\n",
-				semary[i].s->sem_perm.key,
-				semary[i].s->sem_perm.seq * SEMMNI + i,
-				semary[i].s->sem_perm.mode,
-				semary[i].s->sem_nsems,
-				semary[i].s->sem_perm.uid,
-				semary[i].s->sem_perm.gid,
-				semary[i].s->sem_perm.cuid,
-				semary[i].s->sem_perm.cgid,
-				semary[i].s->sem_otime,
-				semary[i].s->sem_ctime);
-			spin_unlock(&semary[i].lock);
+				sma->sem_perm.key,
+				sem_buildid(i,sma->sem_perm.seq),
+				sma->sem_perm.mode,
+				sma->sem_nsems,
+				sma->sem_perm.uid,
+				sma->sem_perm.gid,
+				sma->sem_perm.cuid,
+				sma->sem_perm.cgid,
+				sma->sem_otime,
+				sma->sem_ctime);
+			sem_unlock(i);
 
 			pos += len;
 			if(pos < offset) {
 				len = 0;
-	    		begin = pos;
+	    			begin = pos;
 			}
 			if(pos > offset + length)
 				goto done;
 		}
+	}
 	*eof = 1;
 done:
-	up(&sem_lock);
+	up(&sem_ids.sem);
 	*start = buffer + (offset - begin);
 	len -= (offset - begin);
 	if(len > length)
diff -u --recursive --new-file v2.3.26/linux/ipc/shm.c linux/ipc/shm.c
--- v2.3.26/linux/ipc/shm.c	Sun Nov  7 16:37:34 1999
+++ linux/ipc/shm.c	Thu Nov 11 16:45:25 1999
@@ -36,6 +36,7 @@
 	pte_t			**shm_dir;  /* ptr to array of ptrs to frames -> SHMMAX */ 
 	struct vm_area_struct	*attaches;  /* descriptors for attaches */
 	int                     id; /* backreference to id for shm_close */
+	struct semaphore sem;
 };
 
 static int findkey (key_t key);
@@ -61,6 +62,9 @@
 static unsigned int num_segs = 0;
 static unsigned short shm_seq = 0; /* incremented, for recognizing stale ids */
 
+/* locks order:
+	shm_lock -> pagecache_lock (end of shm_swap)
+	shp->sem -> other spinlocks (shm_nopage) */
 spinlock_t shm_lock = SPIN_LOCK_UNLOCKED;
 
 /* some statistics */
@@ -260,6 +264,7 @@
 	shp->u.shm_ctime = CURRENT_TIME;
 	shp->shm_npages = numpages;
 	shp->id = id;
+	init_MUTEX(&shp->sem);
 
 	spin_lock(&shm_lock);
 
@@ -770,19 +775,20 @@
 	idx = (address - shmd->vm_start) >> PAGE_SHIFT;
 	idx += shmd->vm_pgoff;
 
+	down(&shp->sem);
 	spin_lock(&shm_lock);
-again:
 	pte = SHM_ENTRY(shp,idx);
 	if (!pte_present(pte)) {
+		/* page not present so shm_swap can't race with us
+		   and the semaphore protects us by other tasks that
+		   could potentially fault on our pte under us */
 		if (pte_none(pte)) {
 			spin_unlock(&shm_lock);
-			page = get_free_highpage(GFP_HIGHUSER);
+			page = alloc_page(GFP_HIGHUSER);
 			if (!page)
 				goto oom;
 			clear_highpage(page);
 			spin_lock(&shm_lock);
-			if (pte_val(pte) != pte_val(SHM_ENTRY(shp, idx)))
-				goto changed;
 		} else {
 			swp_entry_t entry = pte_to_swp_entry(pte);
 
@@ -803,9 +809,6 @@
 			unlock_kernel();
 			spin_lock(&shm_lock);
 			shm_swp--;
-			pte = SHM_ENTRY(shp, idx);
-			if (pte_present(pte))
-				goto present;
 		}
 		shm_rss++;
 		pte = pte_mkdirty(mk_pte(page, PAGE_SHARED));
@@ -813,21 +816,15 @@
 	} else
 		--current->maj_flt;  /* was incremented in do_no_page */
 
-done:
 	/* pte_val(pte) == SHM_ENTRY (shp, idx) */
 	get_page(pte_page(pte));
 	spin_unlock(&shm_lock);
+	up(&shp->sem);
 	current->min_flt++;
 	return pte_page(pte);
 
-changed:
-	__free_page(page);
-	goto again;
-present:
-	if (page)
-		free_page_and_swap_cache(page);
-	goto done;
 oom:
+	up(&shp->sem);
 	return NOPAGE_OOM;
 }
 
@@ -851,7 +848,11 @@
 	if (!counter)
 		return 0;
 	lock_kernel();
-	swap_entry = get_swap_page();
+	/* subtle: preload the swap count for the swap cache. We can't
+	   increase the count inside the critical section as we can't release
+	   the shm_lock there. And we can't acquire the big lock with the
+	   shm_lock held (otherwise we would deadlock too easily). */
+	swap_entry = __get_swap_page(2);
 	if (!swap_entry.val) {
 		unlock_kernel();
 		return 0;
@@ -893,7 +894,7 @@
 failed:
 		spin_unlock(&shm_lock);
 		lock_kernel();
-		swap_free(swap_entry);
+		__swap_free(swap_entry, 2);
 		unlock_kernel();
 		return 0;
 	}
@@ -905,11 +906,16 @@
 	swap_successes++;
 	shm_swp++;
 	shm_rss--;
+
+	/* add the locked page to the swap cache before allowing
+	   the swapin path to run lookup_swap_cache(). This avoids
+	   reading a not yet uptodate block from disk.
+	   NOTE: we just accounted the swap space reference for this
+	   swap cache page at __get_swap_page() time. */
+	add_to_swap_cache(page_map, swap_entry);
 	spin_unlock(&shm_lock);
 
 	lock_kernel();
-	swap_duplicate(swap_entry);
-	add_to_swap_cache(page_map, swap_entry);
 	rw_swap_page(WRITE, page_map, 0);
 	unlock_kernel();
 
diff -u --recursive --new-file v2.3.26/linux/ipc/util.c linux/ipc/util.c
--- v2.3.26/linux/ipc/util.c	Sun Nov  7 16:37:34 1999
+++ linux/ipc/util.c	Tue Nov  9 10:02:36 1999
@@ -6,6 +6,8 @@
  *            get BSD style process accounting right.
  *            Occurs in several places in the IPC code.
  *            Chris Evans, <chris@ferret.lmh.ox.ac.uk>
+ * Nov 1999 - ipc helper functions, unified SMP locking
+ *	      Manfred Spraul <manfreds@colorfullife.com>
  */
 
 #include <linux/config.h>
@@ -13,12 +15,13 @@
 #include <linux/shm.h>
 #include <linux/init.h>
 #include <linux/msg.h>
-
-#include "util.h"
+#include <linux/smp_lock.h>
+#include <linux/vmalloc.h>
+#include <linux/malloc.h>
 
 #if defined(CONFIG_SYSVIPC)
 
-extern void sem_init (void), msg_init (void), shm_init (void);
+#include "util.h"
 
 void __init ipc_init (void)
 {
@@ -26,6 +29,157 @@
 	msg_init();
 	shm_init();
 	return;
+}
+
+void __init ipc_init_ids(struct ipc_ids* ids, int size)
+{
+	int i;
+	sema_init(&ids->sem,1);
+	ids->size = size;
+	if(size == 0)
+		return;
+	if(size > IPCMNI)
+		size = IPCMNI;
+
+	ids->in_use = 0;
+	ids->max_id = -1;
+	ids->seq = 0;
+	{
+		int seq_limit = INT_MAX/SEQ_MULTIPLIER;
+		if(seq_limit > USHRT_MAX)
+			ids->seq_max = USHRT_MAX;
+		 else
+		 	ids->seq_max = seq_limit;
+	}
+
+	ids->entries = ipc_alloc(sizeof(struct ipc_id)*size);
+
+	if(ids->entries == NULL) {
+		printk(KERN_ERR "ipc_init_ids() failed, ipc service disabled.\n");
+		ids->size = 0;
+	}
+	ids->ary = SPIN_LOCK_UNLOCKED;
+	for(i=0;i<size;i++) {
+		ids->entries[i].p = NULL;
+	}
+}
+
+int ipc_findkey(struct ipc_ids* ids, key_t key)
+{
+	int id;
+	struct ipc_perm* p;
+
+	for (id = 0; id <= ids->max_id; id++) {
+		p = ids->entries[id].p;
+		if(p==NULL)
+			continue;
+		if (key == p->key)
+			return id;
+	}
+	return -1;
+}
+
+static int grow_ary(struct ipc_ids* ids, int newsize)
+{
+	struct ipc_id* new;
+	struct ipc_id* old;
+	int i;
+
+	if(newsize > IPCMNI)
+		newsize = IPCMNI;
+	if(newsize <= ids->size)
+		return newsize;
+
+	new = ipc_alloc(sizeof(struct ipc_id)*newsize);
+	if(new == NULL)
+		return ids->size;
+	memcpy(new, ids->entries, sizeof(struct ipc_id)*ids->size);
+	for(i=ids->size;i<newsize;i++) {
+		new[i].p = NULL;
+	}
+	spin_lock(&ids->ary);
+
+	old = ids->entries;
+	ids->entries = new;
+	i = ids->size;
+	ids->size = newsize;
+	spin_unlock(&ids->ary);
+	ipc_free(old, sizeof(struct ipc_id)*i);
+	return ids->size;
+}
+
+int ipc_addid(struct ipc_ids* ids, struct ipc_perm* new, int size)
+{
+	int id;
+
+	size = grow_ary(ids,size);
+	for (id = 0; id < size; id++) {
+		if(ids->entries[id].p == NULL)
+			goto found;
+	}
+	return -1;
+found:
+	ids->in_use++;
+	if (id > ids->max_id)
+		ids->max_id = id;
+
+	new->cuid = new->uid = current->euid;
+	new->gid = new->cgid = current->egid;
+
+	new->seq = ids->seq++;
+	if(ids->seq > ids->seq_max)
+		ids->seq = 0;
+
+	ipc_lock(ids,id);
+	ids->entries[id].p = new;
+	return id;
+}
+
+struct ipc_perm* ipc_rmid(struct ipc_ids* ids, int id)
+{
+	struct ipc_perm* p;
+	int lid = id % SEQ_MULTIPLIER;
+	if(lid > ids->size)
+		BUG();
+	p = ids->entries[lid].p;
+	ids->entries[lid].p = NULL;
+	if(p==NULL)
+		BUG();
+	ids->in_use--;
+
+	if (lid == ids->max_id) {
+		do {
+			lid--;
+			if(lid == -1)
+				break;
+		} while (ids->entries[lid].p == NULL);
+		ids->max_id = lid;
+	}
+	return p;
+}
+
+void* ipc_alloc(int size)
+{
+	void* out;
+	if(size > PAGE_SIZE) {
+		lock_kernel();
+		out = vmalloc(size);
+		unlock_kernel();
+	} else {
+		out = kmalloc(size, GFP_KERNEL);
+	}
+	return out;
+}
+
+void ipc_free(void* ptr, int size)
+{
+	if(size > PAGE_SIZE) {
+		lock_kernel();
+		vfree(ptr);
+		unlock_kernel();
+	} else {
+		kfree(ptr);
+	}
 }
 
 /* 
diff -u --recursive --new-file v2.3.26/linux/ipc/util.h linux/ipc/util.h
--- v2.3.26/linux/ipc/util.h	Sun Nov  7 16:37:34 1999
+++ linux/ipc/util.h	Tue Nov  9 10:02:36 1999
@@ -1,12 +1,78 @@
 /*
  * linux/ipc/util.h
  * Copyright (C) 1999 Christoph Rohland
+ *
+ * ipc helper functions (c) 1999 Manfred Spraul <manfreds@colorfullife.com>
  */
 
-/*
- * IPCMNI is the absolute maximum for ipc identifier. This is used to
- * detect stale identifiers
+#define USHRT_MAX 0xffff
+#define SEQ_MULTIPLIER	(IPCMNI)
+
+void sem_init (void);
+void msg_init (void);
+void shm_init (void);
+
+struct ipc_ids {
+	int size;
+	int in_use;
+	int max_id;
+	unsigned short seq;
+	unsigned short seq_max;
+	struct semaphore sem;	
+	spinlock_t ary;
+	struct ipc_id* entries;
+};
+
+struct ipc_id {
+	struct ipc_perm* p;
+};
+
+
+void __init ipc_init_ids(struct ipc_ids* ids, int size);
+
+/* must be called with ids->sem acquired.*/
+int ipc_findkey(struct ipc_ids* ids, key_t key);
+int ipc_addid(struct ipc_ids* ids, struct ipc_perm* new, int size);
+
+/* must be called with both locks acquired. */
+struct ipc_perm* ipc_rmid(struct ipc_ids* ids, int id);
+
+int ipcperms (struct ipc_perm *ipcp, short flg);
+
+/* for rare, potentially huge allocations.
+ * both function can sleep
  */
-#define IPCMNI (1<<15)          
+void* ipc_alloc(int size);
+void ipc_free(void* ptr, int size);
+
+extern inline struct ipc_perm* ipc_lock(struct ipc_ids* ids, int id)
+{
+	struct ipc_perm* out;
+	int lid = id % SEQ_MULTIPLIER;
+	if(lid > ids->size)
+		return NULL;
+
+	spin_lock(&ids->ary);
+	out = ids->entries[lid].p;
+	if(out==NULL)
+		spin_unlock(&ids->ary);
+	return out;
+}
+
+extern inline void ipc_unlock(struct ipc_ids* ids, int id)
+{
+	spin_unlock(&ids->ary);
+}
+
+extern inline int ipc_buildid(struct ipc_ids* ids, int id, int seq)
+{
+	return SEQ_MULTIPLIER*seq + id;
+}
+
+extern inline int ipc_checkid(struct ipc_ids* ids, struct ipc_perm* ipcp, int uid)
+{
+	if(uid/SEQ_MULTIPLIER != ipcp->seq)
+		return 1;
+	return 0;
+}
 
-extern int ipcperms (struct ipc_perm *ipcp, short shmflg);
diff -u --recursive --new-file v2.3.26/linux/kernel/exit.c linux/kernel/exit.c
--- v2.3.26/linux/kernel/exit.c	Mon Nov  1 13:56:27 1999
+++ linux/kernel/exit.c	Mon Nov  8 10:19:19 1999
@@ -402,6 +402,7 @@
 #ifdef CONFIG_BSD_PROCESS_ACCT
 	acct_process(code);
 #endif
+	task_lock(tsk);
 	sem_exit();
 	__exit_mm(tsk);
 #if CONFIG_AP1000
@@ -414,6 +415,7 @@
 	tsk->state = TASK_ZOMBIE;
 	tsk->exit_code = code;
 	exit_notify();
+	task_unlock(tsk);
 #ifdef DEBUG_PROC_TREE
 	audit_ptree();
 #endif
diff -u --recursive --new-file v2.3.26/linux/kernel/fork.c linux/kernel/fork.c
--- v2.3.26/linux/kernel/fork.c	Wed Oct 27 16:34:12 1999
+++ linux/kernel/fork.c	Mon Nov  8 10:19:19 1999
@@ -650,6 +650,7 @@
 	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 -u --recursive --new-file v2.3.26/linux/kernel/kmod.c linux/kernel/kmod.c
--- v2.3.26/linux/kernel/kmod.c	Thu Nov 12 09:58:32 1998
+++ linux/kernel/kmod.c	Wed Nov 10 10:00:11 1999
@@ -23,22 +23,36 @@
 char modprobe_path[256] = "/sbin/modprobe";
 
 static inline void
-use_init_file_context(void)
+use_init_fs_context(void)
 {
-	struct fs_struct * fs;
-
-	lock_kernel();
+	struct fs_struct *our_fs, *init_fs;
 
 	/*
-	 * Don't use the user's root, use init's root instead.
-	 * Note that we can use "init_task" (which is not actually
-	 * the same as the user-level "init" process) because we
-	 * started "init" with a CLONE_FS
+	 * Make modprobe's fs context be a copy of init's.
+	 *
+	 * We cannot use the user's fs context, because it
+	 * may have a different root than init.
+	 * Since init was created with CLONE_FS, we can grab
+	 * its fs context from "init_task".
+	 *
+	 * The fs context has to be a copy. If it is shared
+	 * with init, then any chdir() call in modprobe will
+	 * also affect init and the other threads sharing
+	 * init_task's fs context.
+	 *
+	 * We created the exec_modprobe thread without CLONE_FS,
+	 * so we can update the fields in our fs context freely.
 	 */
-	exit_fs(current);	/* current->fs->count--; */
-	fs = init_task.fs;
-	current->fs = fs;
-	atomic_inc(&fs->count);
+	lock_kernel();
+
+	our_fs = current->fs;
+	dput(our_fs->root);
+	dput(our_fs->pwd);
+
+	init_fs = init_task.fs;
+	our_fs->umask = init_fs->umask;
+	our_fs->root = dget(init_fs->root);
+	our_fs->pwd = dget(init_fs->pwd);
 
 	unlock_kernel();
 }
@@ -49,7 +63,10 @@
 	char *argv[] = { modprobe_path, "-s", "-k", (char*)module_name, NULL };
 	int i;
 
-	use_init_file_context();
+	current->session = 1;
+	current->pgrp = 1;
+
+	use_init_fs_context();
 
 	/* Prevent parent user process from sending signals to child.
 	   Otherwise, if the modprobe program does not exist, it might
@@ -104,7 +121,7 @@
 		return -EPERM;
 	}
 
-	pid = kernel_thread(exec_modprobe, (void*) module_name, CLONE_FS);
+	pid = kernel_thread(exec_modprobe, (void*) module_name, 0);
 	if (pid < 0) {
 		printk(KERN_ERR "request_module[%s]: fork failed, errno %d\n", module_name, -pid);
 		return pid;
@@ -126,8 +143,8 @@
 	spin_unlock_irq(&current->sigmask_lock);
 
 	if (waitpid_result != pid) {
-		printk (KERN_ERR "kmod: waitpid(%d,NULL,0) failed, returning %d.\n",
-			pid, waitpid_result);
+		printk(KERN_ERR "request_module[%s]: waitpid(%d,...) failed, errno %d\n",
+		       module_name, pid, -waitpid_result);
 	}
 	return 0;
 }
diff -u --recursive --new-file v2.3.26/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.3.26/linux/kernel/ksyms.c	Sun Nov  7 16:37:34 1999
+++ linux/kernel/ksyms.c	Wed Nov 10 10:24:21 1999
@@ -93,7 +93,6 @@
 
 /* internal kernel memory management */
 EXPORT_SYMBOL(__get_free_pages);
-EXPORT_SYMBOL(__get_pages);
 EXPORT_SYMBOL(free_pages);
 EXPORT_SYMBOL(__free_page);
 EXPORT_SYMBOL(kmem_find_general_cachep);
diff -u --recursive --new-file v2.3.26/linux/kernel/ptrace.c linux/kernel/ptrace.c
--- v2.3.26/linux/kernel/ptrace.c	Fri Oct 22 13:21:55 1999
+++ linux/kernel/ptrace.c	Thu Nov 11 10:33:42 1999
@@ -50,15 +50,15 @@
 	flush_cache_page(vma, addr);
 
 	if (write) {
-		maddr = kmap(page, KM_WRITE);
+		maddr = kmap(page);
 		memcpy((char *)maddr + (addr & ~PAGE_MASK), buf, len);
 		flush_page_to_ram(page);
-		kunmap(maddr, KM_WRITE);
+		kunmap(page);
 	} else {
-		maddr = kmap(page, KM_READ);
+		maddr = kmap(page);
 		memcpy(buf, (char *)maddr + (addr & ~PAGE_MASK), len);
 		flush_page_to_ram(page);
-		kunmap(maddr, KM_READ);
+		kunmap(page);
 	}
 	return len;
 
diff -u --recursive --new-file v2.3.26/linux/kernel/resource.c linux/kernel/resource.c
--- v2.3.26/linux/kernel/resource.c	Fri Sep 10 23:57:37 1999
+++ linux/kernel/resource.c	Tue Nov  9 10:02:33 1999
@@ -20,7 +20,7 @@
 static rwlock_t resource_lock = RW_LOCK_UNLOCKED;
 
 /*
- * This generates reports for /proc/ioports and /proc/memory
+ * This generates reports for /proc/ioports and /proc/iomem
  */
 static char * do_resource_list(struct resource *entry, const char *fmt, int offset, char *buf, char *end)
 {
diff -u --recursive --new-file v2.3.26/linux/kernel/sysctl.c linux/kernel/sysctl.c
--- v2.3.26/linux/kernel/sysctl.c	Sun Nov  7 16:37:34 1999
+++ linux/kernel/sysctl.c	Tue Nov  9 10:02:36 1999
@@ -50,6 +50,10 @@
 #endif
 #ifdef CONFIG_SYSVIPC
 extern size_t shm_prm[];
+extern int msg_ctlmax;
+extern int msg_ctlmnb;
+extern int msg_ctlmni;
+extern int sem_ctls[];
 #endif
 
 #ifdef __sparc__
@@ -215,6 +219,14 @@
 #ifdef CONFIG_SYSVIPC
 	{KERN_SHMMAX, "shmmax", &shm_prm, 3*sizeof (size_t),
 	 0644, NULL, &proc_doulongvec_minmax},
+	{KERN_MSGMAX, "msgmax", &msg_ctlmax, sizeof (int),
+	 0644, NULL, &proc_dointvec},
+	{KERN_MSGMNI, "msgmni", &msg_ctlmni, sizeof (int),
+	 0644, NULL, &proc_dointvec},
+	{KERN_MSGMNB, "msgmnb", &msg_ctlmnb, sizeof (int),
+	 0644, NULL, &proc_dointvec},
+	{KERN_SEM, "sem", &sem_ctls, 4*sizeof (int),
+	 0644, NULL, &proc_dointvec},
 #endif
 #ifdef CONFIG_MAGIC_SYSRQ
 	{KERN_SYSRQ, "sysrq", &sysrq_enabled, sizeof (int),
diff -u --recursive --new-file v2.3.26/linux/lib/vsprintf.c linux/lib/vsprintf.c
--- v2.3.26/linux/lib/vsprintf.c	Sat Jul 24 16:42:01 1999
+++ linux/lib/vsprintf.c	Mon Nov  8 17:03:01 1999
@@ -14,6 +14,8 @@
 #include <linux/string.h>
 #include <linux/ctype.h>
 
+#include <asm/div64.h>
+
 unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
 {
 	unsigned long result = 0,value;
@@ -66,14 +68,7 @@
 #define SPECIAL	32		/* 0x */
 #define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */
 
-#define do_div(n,base) ({ \
-int __res; \
-__res = ((unsigned long) n) % (unsigned) base; \
-n = ((unsigned long) n) / (unsigned) base; \
-__res; })
-
-static char * number(char * str, long num, int base, int size, int precision
-	,int type)
+static char * number(char * str, long long num, int base, int size, int precision, int type)
 {
 	char c,sign,tmp[66];
 	const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
@@ -145,7 +140,7 @@
 int vsprintf(char *buf, const char *fmt, va_list args)
 {
 	int len;
-	unsigned long num;
+	unsigned long long num;
 	int i, base;
 	char * str;
 	const char *s;
@@ -295,18 +290,23 @@
 				--fmt;
 			continue;
 		}
-		if (qualifier == 'l')
+		if (qualifier == 'L')
+			num = va_arg(args, long long);
+		else if (qualifier == 'l') {
 			num = va_arg(args, unsigned long);
-		else if (qualifier == 'z')
+			if (flags & SIGN)
+				num = (signed long) num;
+		} else if (qualifier == 'z') {
 			num = va_arg(args, size_t);
-		else if (qualifier == 'h') {
+		} else if (qualifier == 'h') {
 			num = (unsigned short) va_arg(args, int);
 			if (flags & SIGN)
-				num = (short) num;
-		} else if (flags & SIGN)
-			num = va_arg(args, int);
-		else
+				num = (signed short) num;
+		} else {
 			num = va_arg(args, unsigned int);
+			if (flags & SIGN)
+				num = (signed int) num;
+		}
 		str = number(str, num, base, field_width, precision, flags);
 	}
 	*str = '\0';
diff -u --recursive --new-file v2.3.26/linux/mm/filemap.c linux/mm/filemap.c
--- v2.3.26/linux/mm/filemap.c	Sun Nov  7 16:37:34 1999
+++ linux/mm/filemap.c	Thu Nov 11 10:33:42 1999
@@ -21,11 +21,13 @@
 #include <linux/swapctl.h>
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/highmem.h>
+#include <linux/mm.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 
+#include <linux/highmem.h>
+
 /*
  * Shared mappings implemented 30.11.1994. It's not fully working yet,
  * though.
@@ -1142,12 +1144,10 @@
 
 	if (size > count)
 		size = count;
-	/*
-	 * FIXME: We cannot yet sleep with kmaps held.
-	 */
-	kaddr = kmap(page, KM_READ);
-	left = __copy_to_user(desc->buf, (void *)(kaddr+offset), size);
-	kunmap(kaddr, KM_READ);
+
+	kaddr = kmap(page);
+	left = __copy_to_user(desc->buf, (void *)(kaddr + offset), size);
+	kunmap(page);
 	
 	if (left) {
 		size -= left;
@@ -1200,9 +1200,11 @@
 		size = count;
 	old_fs = get_fs();
 	set_fs(KERNEL_DS);
-	kaddr = kmap(page, KM_READ);
-	written = file->f_op->write(file, (char *)kaddr + offset, size, &file->f_pos);
-	kunmap(kaddr, KM_READ);
+
+	kaddr = kmap(page);
+	written = file->f_op->write(file, (char *)kaddr + offset,
+						 size, &file->f_pos);
+	kunmap(page);
 	set_fs(old_fs);
 	if (written < 0) {
 		desc->error = written;
@@ -1347,8 +1349,6 @@
 		struct page *new_page = page_cache_alloc();
 
 		if (new_page) {
-			if (PageHighMem(new_page) || PageHighMem(old_page))
-				BUG();
 			copy_highpage(new_page, old_page);
 			flush_page_to_ram(new_page);
 		} else
@@ -1530,8 +1530,6 @@
 			return 0;
 		}
 	}
-	if (PageHighMem(page))
-		BUG();
 	pgoff = (address - vma->vm_start) >> PAGE_CACHE_SHIFT;
 	pgoff += vma->vm_pgoff;
 	if (page->index != pgoff) {
diff -u --recursive --new-file v2.3.26/linux/mm/highmem.c linux/mm/highmem.c
--- v2.3.26/linux/mm/highmem.c	Mon Nov  1 13:56:27 1999
+++ linux/mm/highmem.c	Thu Nov 11 10:33:42 1999
@@ -4,19 +4,25 @@
  * (C) 1999 Andrea Arcangeli, SuSE GmbH, andrea@suse.de
  *          Gerhard Wichert, Siemens AG, Gerhard.Wichert@pdb.siemens.de
  *
+ *
  * Redesigned the x86 32-bit VM architecture to deal with
  * 64-bit physical space. With current x86 CPUs this
  * means up to 64 Gigabytes physical RAM.
  *
+ * Rewrote high memory support to move the page cache into
+ * high memory. Implemented permanent (schedulable) kmaps
+ * based on Linus' idea.
+ *
  * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
  */
 
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/highmem.h>
+#include <linux/swap.h>
+#include <linux/slab.h>
 
 unsigned long highmem_mapnr;
-unsigned long nr_free_highpages = 0;
 
 struct page * prepare_highmem_swapout(struct page * page)
 {
@@ -34,9 +40,9 @@
 	if (!regular_page)
 		return NULL;
 
-	vaddr = kmap(page, KM_READ);
+	vaddr = kmap(page);
 	copy_page((void *)regular_page, (void *)vaddr);
-	kunmap(vaddr, KM_READ);
+	kunmap(page);
 
 	/*
 	 * ok, we can just forget about our highmem page since 
@@ -52,10 +58,10 @@
 	struct page *highpage;
 	unsigned long vaddr;
 
-	if (PageHighMem(page) || !nr_free_highpages)
+	if (PageHighMem(page) || !nr_free_highpages())
 		return page;
 
-	highpage = get_free_highpage(GFP_ATOMIC|__GFP_HIGHMEM);
+	highpage = alloc_page(GFP_ATOMIC|__GFP_HIGHMEM);
 	if (!highpage)
 		return page;
 	if (!PageHighMem(highpage)) {
@@ -63,9 +69,9 @@
 		return page;
 	}
 
-	vaddr = kmap(highpage, KM_WRITE);
+	vaddr = kmap(page);
 	copy_page((void *)vaddr, (void *)page_address(page));
-	kunmap(vaddr, KM_WRITE);
+	kunmap(page);
 
 	/* Preserve the caching of the swap_entry. */
 	highpage->index = page->index;
@@ -79,3 +85,275 @@
 
 	return highpage;
 }
+
+/*
+ * Right now we initialize only a single pte table. It can be extended
+ * easily, subsequent pte tables have to be allocated in one physical
+ * chunk of RAM.
+ */
+#ifdef CONFIG_X86_PAE
+#define LAST_PKMAP 2048
+#else
+#define LAST_PKMAP 4096
+#endif
+#define LAST_PKMAP_MASK (LAST_PKMAP-1)
+#define PKMAP_NR(virt)	((virt-PKMAP_BASE) >> PAGE_SHIFT)
+#define PKMAP_ADDR(nr)	(PKMAP_BASE + ((nr) << PAGE_SHIFT))
+
+/*
+ * Virtual_count is not a pure "count".
+ *  0 means that it is not mapped, and has not been mapped
+ *    since a TLB flush - it is usable.
+ *  1 means that there are no users, but it has been mapped
+ *    since the last TLB flush - so we can't use it.
+ *  n means that there are (n-1) current users of it.
+ */
+static int pkmap_count[LAST_PKMAP];
+static unsigned int last_pkmap_nr = 0;
+static spinlock_t kmap_lock;
+
+pte_t * pkmap_page_table;
+
+static DECLARE_WAIT_QUEUE_HEAD(pkmap_map_wait);
+
+static void flush_all_zero_pkmaps(void)
+{
+	int i;
+
+	for (i = 0; i < LAST_PKMAP; i++) {
+		struct page *page;
+		pte_t pte;
+		/*
+		 * zero means we don't have anything to do,
+		 * >1 means that it is still in use. Only
+		 * a count of 1 means that it is free but
+		 * needs to be unmapped
+		 */
+		if (pkmap_count[i] != 1)
+			continue;
+		pkmap_count[i] = 0;
+		pte = pkmap_page_table[i];
+		if (pte_none(pte))
+			continue;
+		pte_clear(pkmap_page_table+i);
+		page = pte_page(pte);
+		page->virtual = 0;
+	}
+	flush_tlb_all();
+}
+
+static unsigned long map_new_virtual(struct page *page)
+{
+	unsigned long vaddr;
+	int count = LAST_PKMAP;
+
+	/* Find an empty entry */
+	for (;;) {
+		last_pkmap_nr = (last_pkmap_nr + 1) & LAST_PKMAP_MASK;
+		if (!last_pkmap_nr)
+			flush_all_zero_pkmaps();
+		if (!pkmap_count[last_pkmap_nr])
+			break;	/* Found a usable entry */
+		if (--count)
+			continue;
+
+		/*
+		 * Sleep for somebody else to unmap their entries
+		 */
+		{
+			DECLARE_WAITQUEUE(wait, current);
+
+			current->state = TASK_UNINTERRUPTIBLE;
+			add_wait_queue(&pkmap_map_wait, &wait);
+			spin_unlock(&kmap_lock);
+			// it's not quite possible to saturate the
+			// pkmap pool right now.
+			BUG();
+			schedule();
+			remove_wait_queue(&pkmap_map_wait, &wait);
+			spin_lock(&kmap_lock);
+		}
+
+		/* Somebody else might have mapped it while we slept */
+		if (page->virtual)
+			return page->virtual;
+
+		/* Re-start */
+		count = LAST_PKMAP;
+	}
+	vaddr = PKMAP_ADDR(last_pkmap_nr);
+	pkmap_page_table[last_pkmap_nr] = mk_pte(page, kmap_prot);
+
+	/*
+	 * Subtle! For some reason if we dont do this TLB flush then
+	 * we get data corruption and weird behavior in dbench runs.
+	 * But invlpg this should not be necessery ... Any ideas?
+	 */
+	__flush_tlb_one(vaddr);
+	pkmap_count[last_pkmap_nr] = 1;
+	page->virtual = vaddr;
+
+	return vaddr;
+}
+
+unsigned long kmap_high(struct page *page)
+{
+	unsigned long vaddr;
+
+	if (!PageHighMem(page))
+		BUG();
+	/*
+	 * For highmem pages, we can't trust "virtual" until
+	 * after we have the lock.
+	 *
+	 * We cannot call this from interrupts, as it may block
+	 */
+	spin_lock(&kmap_lock);
+	vaddr = page->virtual;
+	if (!vaddr)
+		vaddr = map_new_virtual(page);
+	pkmap_count[PKMAP_NR(vaddr)]++;
+	if (pkmap_count[PKMAP_NR(vaddr)] < 2)
+		BUG();
+	spin_unlock(&kmap_lock);
+	return vaddr;
+}
+
+void kunmap_high(struct page *page)
+{
+	unsigned long vaddr;
+	unsigned long nr;
+
+	spin_lock(&kmap_lock);
+	vaddr = page->virtual;
+	if (!vaddr)
+		BUG();
+	nr = PKMAP_NR(vaddr);
+
+	/*
+	 * A count must never go down to zero
+	 * without a TLB flush!
+	 */
+	switch (--pkmap_count[nr]) {
+	case 0:
+		BUG();
+	case 1:
+		wake_up(&pkmap_map_wait);
+	}
+	spin_unlock(&kmap_lock);
+}
+
+/*
+ * Simple bounce buffer support for highmem pages.
+ * This will be moved to the block layer in 2.5.
+ */
+
+extern kmem_cache_t *bh_cachep;
+
+static inline void copy_from_high_bh (struct buffer_head *to,
+			 struct buffer_head *from)
+{
+	struct page *p_from;
+	unsigned long vfrom;
+
+	p_from = from->b_page;
+	vfrom = kmap_atomic(p_from, KM_BOUNCE_WRITE);
+	memcpy(to->b_data, (char *)vfrom + bh_offset(from), to->b_size);
+	kunmap_atomic(vfrom, KM_BOUNCE_WRITE);
+}
+
+static inline void copy_to_high_bh_irq (struct buffer_head *to,
+			 struct buffer_head *from)
+{
+	struct page *p_to;
+	unsigned long vto;
+
+	p_to = to->b_page;
+	vto = kmap_atomic(p_to, KM_BOUNCE_WRITE);
+	memcpy((char *)vto + bh_offset(to), from->b_data, to->b_size);
+	kunmap_atomic(vto, KM_BOUNCE_WRITE);
+}
+
+static inline void bounce_end_io (struct buffer_head *bh, int uptodate)
+{
+	struct buffer_head *bh_orig = (struct buffer_head *)(bh->b_dev_id);
+
+	bh_orig->b_end_io(bh_orig, uptodate);
+	__free_page(bh->b_page);
+	kmem_cache_free(bh_cachep, bh);
+}
+
+static void bounce_end_io_write (struct buffer_head *bh, int uptodate)
+{
+	bounce_end_io(bh, uptodate);
+}
+
+static void bounce_end_io_read (struct buffer_head *bh, int uptodate)
+{
+	struct buffer_head *bh_orig = (struct buffer_head *)(bh->b_dev_id);
+
+	if (uptodate)
+		copy_to_high_bh_irq(bh_orig, bh);
+	bounce_end_io(bh, uptodate);
+}
+
+struct buffer_head * create_bounce(int rw, struct buffer_head * bh_orig)
+{
+	struct page *page;
+	struct buffer_head *bh;
+
+	if (!PageHighMem(bh_orig->b_page))
+		return bh_orig;
+
+repeat_bh:
+	bh = kmem_cache_alloc(bh_cachep, SLAB_BUFFER);
+	if (!bh) {
+		wakeup_bdflush(1);
+		current->policy |= SCHED_YIELD;
+		schedule();
+		goto repeat_bh;
+	}
+	/*
+	 * This is wasteful for 1k buffers, but this is a stopgap measure
+	 * and we are being ineffective anyway. This approach simplifies
+	 * things immensly. On boxes with more than 4GB RAM this should
+	 * not be an issue anyway.
+	 */
+repeat_page:
+	page = alloc_page(GFP_BUFFER);
+	if (!page) {
+		wakeup_bdflush(1);
+		current->policy |= SCHED_YIELD;
+		schedule();
+		goto repeat_page;
+	}
+	set_bh_page(bh, page, 0);
+
+	bh->b_next = NULL;
+	bh->b_blocknr = bh_orig->b_blocknr;
+	bh->b_size = bh_orig->b_size;
+	bh->b_list = -1;
+	bh->b_dev = bh_orig->b_dev;
+	bh->b_count = bh_orig->b_count;
+	bh->b_rdev = bh_orig->b_rdev;
+	bh->b_state = bh_orig->b_state;
+	bh->b_flushtime = 0;
+	bh->b_next_free = NULL;
+	bh->b_prev_free = NULL;
+	/* bh->b_this_page */
+	bh->b_reqnext = NULL;
+	bh->b_pprev = NULL;
+	/* bh->b_page */
+	if (rw == WRITE) {
+		bh->b_end_io = bounce_end_io_write;
+		copy_from_high_bh(bh, bh_orig);
+	} else
+		bh->b_end_io = bounce_end_io_read;
+	bh->b_dev_id = (void *)bh_orig;
+	bh->b_rsector = -1;
+	memset(&bh->b_wait, -1, sizeof(bh->b_wait));
+	bh->b_kiobuf = NULL;
+
+	return bh;
+}
+
diff -u --recursive --new-file v2.3.26/linux/mm/memory.c linux/mm/memory.c
--- v2.3.26/linux/mm/memory.c	Sun Nov  7 16:37:34 1999
+++ linux/mm/memory.c	Thu Nov 11 10:33:42 1999
@@ -808,7 +808,7 @@
 	 * Ok, we need to copy. Oh, well..
 	 */
 	spin_unlock(&tsk->mm->page_table_lock);
-	new_page = get_free_highpage(GFP_HIGHUSER);
+	new_page = alloc_page(GFP_HIGHUSER);
 	if (!new_page)
 		return -1;
 	spin_lock(&tsk->mm->page_table_lock);
@@ -1025,7 +1025,7 @@
 	struct page *page = NULL;
 	pte_t entry = pte_wrprotect(mk_pte(ZERO_PAGE(addr), vma->vm_page_prot));
 	if (write_access) {
-		page = get_free_highpage(GFP_HIGHUSER);
+		page = alloc_page(GFP_HIGHUSER);
 		if (!page)
 			return -1;
 		if (PageHighMem(page))
diff -u --recursive --new-file v2.3.26/linux/mm/mmap.c linux/mm/mmap.c
--- v2.3.26/linux/mm/mmap.c	Mon Nov  1 13:56:27 1999
+++ linux/mm/mmap.c	Wed Nov 10 09:13:07 1999
@@ -64,7 +64,7 @@
 
 	free = atomic_read(&buffermem_pages);
 	free += atomic_read(&page_cache_size);
-	free += nr_free_pages;
+	free += nr_free_pages();
 	free += nr_swap_pages;
 	return free > pages;
 }
diff -u --recursive --new-file v2.3.26/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.3.26/linux/mm/page_alloc.c	Sun Nov  7 16:37:34 1999
+++ linux/mm/page_alloc.c	Thu Nov 11 10:33:42 1999
@@ -4,6 +4,7 @@
  *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
  *  Swap reorganised 29.12.95, Stephen Tweedie
  *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+ *  Reshaped it to be a zoned allocator, Ingo Molnar, Red Hat, 1999
  */
 
 #include <linux/config.h>
@@ -22,7 +23,6 @@
 #include <asm/pgtable.h>
 
 int nr_swap_pages = 0;
-int nr_free_pages = 0;
 int nr_lru_pages;
 LIST_HEAD(lru_cache);
 
@@ -36,30 +36,46 @@
 #if CONFIG_AP1000
 /* the AP+ needs to allocate 8MB contiguous, aligned chunks of ram
    for the ring buffers */
-#define NR_MEM_LISTS 12
+#define MAX_ORDER 12
 #else
-#define NR_MEM_LISTS 10
+#define MAX_ORDER 10
 #endif
 
-struct free_area_struct {
+typedef struct free_area_struct {
 	struct list_head free_list;
 	unsigned int * map;
-	unsigned long count;
-};
+} free_area_t;
 
-#define MEM_TYPE_DMA		0
-#define MEM_TYPE_NORMAL		1
-#define MEM_TYPE_HIGH		2
-
-static const char *mem_type_strs[] = {"DMA", "Normal", "High"};
+#define ZONE_DMA		0
+#define ZONE_NORMAL		1
 
 #ifdef CONFIG_HIGHMEM
-#define NR_MEM_TYPES		3
+# define ZONE_HIGHMEM		2
+# define NR_ZONES		3
 #else
-#define NR_MEM_TYPES		2
+# define NR_ZONES		2
 #endif
 
-static struct free_area_struct free_area[NR_MEM_TYPES][NR_MEM_LISTS];
+typedef struct zone_struct {
+	spinlock_t lock;
+	unsigned long offset;
+	unsigned long size;
+	free_area_t free_area[MAX_ORDER];
+
+	unsigned long free_pages;
+	unsigned long pages_low, pages_high;
+	int low_on_memory;
+	char * name;
+} zone_t;
+
+static zone_t zones[NR_ZONES] =
+	{
+		{ name: "DMA" },
+		{ name: "Normal" },
+#ifdef CONFIG_HIGHMEM
+		{ name: "HighMem" }
+#endif
+	};
 
 /*
  * Free_page() adds the page to the free lists. This is optimized for
@@ -73,13 +89,6 @@
  * for the normal case, giving better asm-code.
  */
 
-/*
- * Buddy system. Hairy. You really aren't expected to understand this
- *
- * Hint: -mask = 1+~mask
- */
-spinlock_t page_alloc_lock = SPIN_LOCK_UNLOCKED;
-
 #define memlist_init(x) INIT_LIST_HEAD(x)
 #define memlist_add_head list_add
 #define memlist_add_tail list_add_tail
@@ -88,35 +97,54 @@
 #define memlist_next(x) ((x)->next)
 #define memlist_prev(x) ((x)->prev)
 
-static inline void free_pages_ok(struct page *page, unsigned long map_nr, unsigned long order)
+/*
+ * Temporary debugging check.
+ */
+#define BAD_RANGE(zone,x) ((((x)-mem_map) < zone->offset) || (((x)-mem_map) >= zone->offset+zone->size))
+
+/*
+ * Buddy system. Hairy. You really aren't expected to understand this
+ *
+ * Hint: -mask = 1+~mask
+ */
+
+static inline void free_pages_ok (struct page *page, unsigned long map_nr, unsigned long order)
 {
 	struct free_area_struct *area;
-	unsigned long index = map_nr >> (1 + order);
-	unsigned long mask = (~0UL) << order;
+	unsigned long index, page_idx, mask, offset;
 	unsigned long flags;
 	struct page *buddy;
+	zone_t *zone;
+	int i;
 
-	spin_lock_irqsave(&page_alloc_lock, flags);
-
-#define list(x) (mem_map+(x))
-
-#ifdef CONFIG_HIGHMEM
-	if (map_nr >= highmem_mapnr) {
-		area = free_area[MEM_TYPE_HIGH];
-		nr_free_highpages -= mask;
-	} else
-#endif
-	if (PageDMA(page))
-		area = free_area[MEM_TYPE_DMA];
-	else
-		area = free_area[MEM_TYPE_NORMAL];
+	/*
+	 * Which zone is this page belonging to.
+	 *
+	 * (NR_ZONES is low, and we do not want (yet) to introduce
+	 * put page->zone, it increases the size of mem_map[]
+	 * unnecesserily. This small loop is basically equivalent
+	 * to the previous #ifdef jungle, speed-wise.)
+	 */
+	i = NR_ZONES-1;
+	zone = zones + i;
+	for ( ; i >= 0; i--, zone--)
+		if (map_nr >= zone->offset)
+			break;
 
+	mask = (~0UL) << order;
+	offset = zone->offset;
+	area = zone->free_area;
 	area += order;
+	page_idx = map_nr - zone->offset;
+	page_idx &= mask;
+	index = page_idx >> (1 + order);
+	mask = (~0UL) << order;
+
+	spin_lock_irqsave(&zone->lock, flags);
 
-	map_nr &= mask;
-	nr_free_pages -= mask;
+	zone->free_pages -= mask;
 
-	while (mask + (1 << (NR_MEM_LISTS-1))) {
+	while (mask + (1 << (MAX_ORDER-1))) {
 		if (!test_and_change_bit(index, area->map))
 			/*
 			 * the buddy page is still allocated.
@@ -125,21 +153,22 @@
 		/*
 		 * Move the buddy up one level.
 		 */
-		buddy = list(map_nr ^ -mask);
-		page = list(map_nr);
+		buddy = mem_map + offset + (page_idx ^ -mask);
+		page = mem_map + offset + page_idx;
+		if (BAD_RANGE(zone,buddy))
+			BUG();
+		if (BAD_RANGE(zone,page))
+			BUG();
 
-		area->count--;
 		memlist_del(&buddy->list);
 		mask <<= 1;
 		area++;
 		index >>= 1;
-		map_nr &= mask;
+		page_idx &= mask;
 	}
-	area->count++;
-	memlist_add_head(&(list(map_nr))->list, &area->free_list);
-#undef list
+	memlist_add_head(&mem_map[offset + page_idx].list, &area->free_list);
 
-	spin_unlock_irqrestore(&page_alloc_lock, flags);
+	spin_unlock_irqrestore(&zone->lock, flags);
 }
 
 /*
@@ -147,10 +176,9 @@
  */
 #define MARK_USED(index, order, area) \
 	change_bit((index) >> (1+(order)), (area)->map)
-#define CAN_DMA(x) (PageDMA(x))
 #define ADDRESS(x) (PAGE_OFFSET + ((x) << PAGE_SHIFT))
 
-int __free_page(struct page *page)
+int __free_page (struct page *page)
 {
 	if (!PageReserved(page) && put_page_testzero(page)) {
 		if (PageSwapCache(page))
@@ -164,7 +192,7 @@
 	return 0;
 }
 
-int free_pages(unsigned long addr, unsigned long order)
+int free_pages (unsigned long addr, unsigned long order)
 {
 	unsigned long map_nr = MAP_NR(addr);
 
@@ -182,16 +210,17 @@
 	return 0;
 }
 
-static inline unsigned long EXPAND (struct page *map, unsigned long index,
+static inline unsigned long EXPAND (zone_t *zone, struct page *map, unsigned long index,
 		 int low, int high, struct free_area_struct * area)
 {
 	unsigned long size = 1 << high;
 
 	while (high > low) {
+		if (BAD_RANGE(zone,map))
+			BUG();
 		area--;
 		high--;
 		size >>= 1;
-		area->count++;
 		memlist_add_head(&(map)->list, &(area)->free_list);
 		MARK_USED(index, high, area);
 		index += size;
@@ -201,79 +230,62 @@
 	return index;
 }
 
-static inline struct page * rmqueue (int order, unsigned type)
+static inline struct page * rmqueue (zone_t *zone, unsigned long order)
 {
-	struct free_area_struct * area = free_area[type]+order;
+	struct free_area_struct * area = zone->free_area + order;
 	unsigned long curr_order = order, map_nr;
-	struct page *page;
 	struct list_head *head, *curr;
+	unsigned long flags;
+	struct page *page;
 
+	spin_lock_irqsave(&zone->lock, flags);
 	do {
 		head = &area->free_list;
 		curr = memlist_next(head);
 
 		if (curr != head) {
+			unsigned int index;
+
 			page = memlist_entry(curr, struct page, list);
 			memlist_del(curr);
-			area->count--;
-			map_nr = page - mem_map;	
-			MARK_USED(map_nr, curr_order, area);
-			nr_free_pages -= 1 << order;
-			map_nr = EXPAND(page, map_nr, order, curr_order, area);
+			map_nr = page - mem_map;
+			index = map_nr - zone->offset;
+			MARK_USED(index, curr_order, area);
+			zone->free_pages -= 1 << order;
+			map_nr = zone->offset + EXPAND(zone, page, index, order, curr_order, area);
+			spin_unlock_irqrestore(&zone->lock, flags);
+
 			page = mem_map + map_nr;
+			if (BAD_RANGE(zone,page))
+				BUG();
 			return page;	
 		}
 		curr_order++;
 		area++;
-	} while (curr_order < NR_MEM_LISTS);
+	} while (curr_order < MAX_ORDER);
+	spin_unlock_irqrestore(&zone->lock, flags);
 
 	return NULL;
 }
 
-static inline int balance_lowmemory (int gfp_mask)
+static inline int balance_memory (zone_t *zone, int gfp_mask)
 {
 	int freed;
-	static int low_on_memory = 0;
 
-#ifndef CONFIG_HIGHMEM
-	if (nr_free_pages > freepages.min) {
-		if (!low_on_memory)
+	if (zone->free_pages > zone->pages_low) {
+		if (!zone->low_on_memory)
 			return 1;
-		if (nr_free_pages >= freepages.high) {
-			low_on_memory = 0;
+		/*
+		 * Simple hysteresis: exit 'low memory mode' if
+		 * the upper limit has been reached:
+		 */
+		if (zone->free_pages >= zone->pages_high) {
+			zone->low_on_memory = 0;
 			return 1;
 		}
 	}
+	zone->low_on_memory = 1;
 
-	low_on_memory = 1;
-#else
-	static int low_on_highmemory = 0;
-
-	if (gfp_mask & __GFP_HIGHMEM)
-	{
-		if (nr_free_pages > freepages.min) {
-			if (!low_on_highmemory) {
-				return 1;
-			}
-			if (nr_free_pages >= freepages.high) {
-				low_on_highmemory = 0;
-				return 1;
-			}
-		}
-		low_on_highmemory = 1;
-	} else {
-		if (nr_free_pages-nr_free_highpages > freepages.min) {
-			if (!low_on_memory) {
-				return 1;
-			}
-			if (nr_free_pages-nr_free_highpages >= freepages.high) {
-				low_on_memory = 0;
-				return 1;
-			}
-		}
-		low_on_memory = 1;
-	}
-#endif
 	current->flags |= PF_MEMALLOC;
 	freed = try_to_free_pages(gfp_mask);
 	current->flags &= ~PF_MEMALLOC;
@@ -283,13 +295,12 @@
 	return 1;
 }
 
-struct page * __get_pages(int gfp_mask, unsigned long order)
+static inline struct page * __get_pages (zone_t *zone, unsigned int gfp_mask,
+			unsigned long order)
 {
-	unsigned long flags;
 	struct page *page;
-	unsigned type;
 
-	if (order >= NR_MEM_LISTS)
+	if (order >= MAX_ORDER)
 		goto nopage;
 
 	/*
@@ -303,32 +314,20 @@
 	 * further thought.
 	 */
 	if (!(current->flags & PF_MEMALLOC))
-		goto lowmemory;
-
-ok_to_allocate:
-#ifdef CONFIG_HIGHMEM
-	if (gfp_mask & __GFP_HIGHMEM)
-		type = MEM_TYPE_HIGH;
-	else
-#endif
-	if (gfp_mask & __GFP_DMA)
-		type = MEM_TYPE_DMA;
-	else
-		type = MEM_TYPE_NORMAL;
-
-	spin_lock_irqsave(&page_alloc_lock, flags);
+		if (!balance_memory(zone, gfp_mask))
+			goto nopage;
+	/*
+	 * We are falling back to lower-level zones if allocation
+	 * in a higher zone fails. This assumes a hierarchical
+	 * dependency between zones, which is true currently. If
+	 * you need something else then move this loop outside
+	 * this function, into the zone-specific allocator.
+	 */
 	do {
-		page = rmqueue(order, type);
-		if (page) {
-#ifdef CONFIG_HIGHMEM
-			if (type == MEM_TYPE_HIGH)
-				nr_free_highpages -= 1 << order;
-#endif
-			spin_unlock_irqrestore(&page_alloc_lock, flags);
+		page = rmqueue(zone, order);
+		if (page)
 			return page;
-		}
-	} while (type-- > 0) ;
-	spin_unlock_irqrestore(&page_alloc_lock, flags);
+	} while (zone-- != zones) ;
 
 	/*
 	 * If we can schedule, do so, and make sure to yield.
@@ -342,26 +341,73 @@
 
 nopage:
 	return NULL;
+}
 
-lowmemory:
-	if (balance_lowmemory(gfp_mask))
-		goto ok_to_allocate;
-	goto nopage;
+static inline zone_t * gfp_mask_to_zone (int gfp_mask)
+{
+	zone_t *zone;
+
+#if CONFIG_HIGHMEM
+	if (gfp_mask & __GFP_HIGHMEM)
+		zone = zones + ZONE_HIGHMEM;
+	else
+#endif
+		if (gfp_mask & __GFP_DMA)
+			zone = zones + ZONE_DMA;
+		else
+			zone = zones + ZONE_NORMAL;
+	return zone;
 }
 
-unsigned long __get_free_pages(int gfp_mask, unsigned long order)
+unsigned long __get_free_pages (int gfp_mask, unsigned long order)
 {
 	struct page *page;
-	page = __get_pages(gfp_mask, order);
+
+	page = __get_pages(gfp_mask_to_zone(gfp_mask), gfp_mask, order);
 	if (!page)
 		return 0;
 	return page_address(page);
 }
 
-struct page * get_free_highpage(int gfp_mask)
+struct page * alloc_pages (int gfp_mask, unsigned long order)
+{
+	return __get_pages(gfp_mask_to_zone(gfp_mask), gfp_mask, order);
+}
+
+/*
+ * Total amount of free (allocatable) RAM:
+ */
+unsigned int nr_free_pages (void)
+{
+	unsigned int sum;
+	zone_t *zone;
+
+	sum = 0;
+	for (zone = zones; zone < zones+NR_ZONES; zone++)
+		sum += zone->free_pages;
+	return sum;
+}
+
+/*
+ * Amount of free RAM allocatable as buffer memory:
+ */
+unsigned int nr_free_buffer_pages (void)
+{
+	unsigned int sum;
+	zone_t *zone;
+
+	sum = nr_lru_pages;
+	for (zone = zones; zone <= zones+ZONE_NORMAL; zone++)
+		sum += zone->free_pages;
+	return sum;
+}
+
+#if CONFIG_HIGHMEM
+unsigned int nr_free_highpages (void)
 {
-	return __get_pages(gfp_mask, 0);
+	return zones[ZONE_HIGHMEM].free_pages;
 }
+#endif
 
 /*
  * Show free area list (used inside shift_scroll-lock stuff)
@@ -370,32 +416,39 @@
  */
 void show_free_areas(void)
 {
- 	unsigned long order, flags;
+ 	unsigned long order;
 	unsigned type;
 
-	spin_lock_irqsave(&page_alloc_lock, flags);
-	printk("Free pages:      %6dkB (%6ldkB HighMem)\n",
-		nr_free_pages<<(PAGE_SHIFT-10),
-		nr_free_highpages<<(PAGE_SHIFT-10));
+	printk("Free pages:      %6dkB (%6dkB HighMem)\n",
+		nr_free_pages()<<(PAGE_SHIFT-10),
+		nr_free_highpages()<<(PAGE_SHIFT-10));
 	printk("( Free: %d, lru_cache: %d (%d %d %d) )\n",
-		nr_free_pages,
+		nr_free_pages(),
 		nr_lru_pages,
 		freepages.min,
 		freepages.low,
 		freepages.high);
 
-	for (type = 0; type < NR_MEM_TYPES; type++) {
+	for (type = 0; type < NR_ZONES; type++) {
+		zone_t *zone = zones + type;
  		unsigned long total = 0;
-		printk("  %s: ", mem_type_strs[type]);
-	 	for (order = 0; order < NR_MEM_LISTS; order++) {
-			unsigned long nr = free_area[type][order].count;
 
+		printk("  %s: ", zone->name);
+	 	for (order = 0; order < MAX_ORDER; order++) {
+			unsigned long i, nr;
+
+			nr = 0;
+			for (i = 0; i < zone->size; i += 1<<order) {
+				struct page * page;
+				page = mem_map + zone->offset + i;
+				if (!page_count(page))
+					nr++;
+			}
 			total += nr * ((PAGE_SIZE>>10) << order);
 			printk("%lu*%lukB ", nr, (unsigned long)((PAGE_SIZE>>10) << order));
 		}
 		printk("= %lukB)\n", total);
 	}
-	spin_unlock_irqrestore(&page_alloc_lock, flags);
 
 #ifdef SWAP_CACHE_INFO
 	show_swap_cache_info();
@@ -405,18 +458,24 @@
 #define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1))
 
 /*
- * set up the free-area data structures:
+ * Set up the zone data structures:
  *   - mark all pages reserved
  *   - mark all memory queues empty
  *   - clear the memory bitmaps
  */
-volatile int data;
-void __init free_area_init(unsigned long end_mem_pages)
+void __init free_area_init(unsigned int *zones_size)
 {
 	mem_map_t * p;
 	unsigned long i, j;
 	unsigned long map_size;
+	unsigned int totalpages, offset;
+
+	totalpages = 0;
+	for (i = 0; i < NR_ZONES; i++)
+		totalpages += zones_size[i];
+	printk("totalpages: %08x\n", totalpages);
 
+	i = totalpages >> 7;
 	/*
 	 * Select nr of pages we try to keep free for important stuff
 	 * with a minimum of 10 pages and a maximum of 256 pages, so
@@ -424,7 +483,7 @@
 	 * This is fairly arbitrary, but based on some behaviour
 	 * analysis.
 	 */
-	i = end_mem_pages >> 7;
+	i = totalpages >> 7;
 	if (i < 10)
 		i = 10;
 	if (i > 256)
@@ -434,11 +493,10 @@
 	freepages.high = i * 3;
 
 	/*
-	 * Most architectures just pick 'start_mem'. Some architectures
-	 * (with lots of mem and discontinous memory maps) have to search
-	 * for a good area.
+	 * Some architectures (with lots of mem and discontinous memory
+	 * maps) have to search for a good mem_map area:
 	 */
-	map_size = end_mem_pages*sizeof(struct page);
+	map_size = totalpages*sizeof(struct page);
 	mem_map = (struct page *) alloc_bootmem(map_size);
 	memset(mem_map, 0, map_size);
 
@@ -447,27 +505,39 @@
 	 * up by free_all_bootmem() once the early boot process is
 	 * done.
 	 */
-	for (p = mem_map; p < mem_map + end_mem_pages; p++) {
+	for (p = mem_map; p < mem_map + totalpages; p++) {
 		set_page_count(p, 0);
 		p->flags = (1 << PG_DMA);
 		SetPageReserved(p);
 		init_waitqueue_head(&p->wait);
 		memlist_init(&p->list);
 	}
-	
-	for (j = 0 ; j < NR_MEM_TYPES ; j++) {
+
+	offset = 0;	
+	for (j = 0; j < NR_ZONES; j++) {
+		zone_t *zone = zones + j;
 		unsigned long mask = -1;
-		for (i = 0 ; i < NR_MEM_LISTS ; i++) {
+		unsigned long size;
+
+		size = zones_size[j];
+		zone->size = size;
+		zone->offset = offset;
+		zone->pages_low = freepages.low;
+		zone->pages_high = freepages.high;
+		zone->low_on_memory = 0;
+
+		offset += size;
+		for (i = 0; i < MAX_ORDER; i++) {
 			unsigned long bitmap_size;
 			unsigned int * map;
-			memlist_init(&free_area[j][i].free_list);
+			memlist_init(&zone->free_area[i].free_list);
 			mask += mask;
-			end_mem_pages = (end_mem_pages + ~mask) & mask;
-			bitmap_size = end_mem_pages >> i;
+			size = (size + ~mask) & mask;
+			bitmap_size = size >> i;
 			bitmap_size = (bitmap_size + 7) >> 3;
 			bitmap_size = LONG_ALIGN(bitmap_size);
 			map = (unsigned int *) alloc_bootmem(bitmap_size);
-			free_area[j][i].map = map;
+			zone->free_area[i].map = map;
 			memset((void *) map, 0, bitmap_size);
 		}
 	}
diff -u --recursive --new-file v2.3.26/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.3.26/linux/mm/swapfile.c	Sun Nov  7 16:37:34 1999
+++ linux/mm/swapfile.c	Thu Nov 11 15:57:27 1999
@@ -25,7 +25,7 @@
 
 #define SWAPFILE_CLUSTER 256
 
-static inline int scan_swap_map(struct swap_info_struct *si)
+static inline int scan_swap_map(struct swap_info_struct *si, unsigned short count)
 {
 	unsigned long offset;
 	/* 
@@ -73,7 +73,7 @@
 			si->lowest_bit++;
 		if (offset == si->highest_bit)
 			si->highest_bit--;
-		si->swap_map[offset] = 1;
+		si->swap_map[offset] = count;
 		nr_swap_pages--;
 		si->cluster_next = offset+1;
 		return offset;
@@ -81,7 +81,7 @@
 	return 0;
 }
 
-swp_entry_t get_swap_page(void)
+swp_entry_t __get_swap_page(unsigned short count)
 {
 	struct swap_info_struct * p;
 	unsigned long offset;
@@ -94,11 +94,13 @@
 		goto out;
 	if (nr_swap_pages == 0)
 		goto out;
+	if (count >= SWAP_MAP_MAX)
+		goto bad_count;
 
 	while (1) {
 		p = &swap_info[type];
 		if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) {
-			offset = scan_swap_map(p);
+			offset = scan_swap_map(p, count);
 			if (offset) {
 				entry = SWP_ENTRY(type,offset);
 				type = swap_info[type].next;
@@ -123,10 +125,15 @@
 	}
 out:
 	return entry;
+
+bad_count:
+	printk(KERN_ERR "get_swap_page: bad count %hd from %p\n",
+	       count, __builtin_return_address(0));
+	goto out;
 }
 
 
-void swap_free(swp_entry_t entry)
+void __swap_free(swp_entry_t entry, unsigned short count)
 {
 	struct swap_info_struct * p;
 	unsigned long offset, type;
@@ -148,7 +155,9 @@
 	if (!p->swap_map[offset])
 		goto bad_free;
 	if (p->swap_map[offset] < SWAP_MAP_MAX) {
-		if (!--p->swap_map[offset]) {
+		if (p->swap_map[offset] < count)
+			goto bad_count;
+		if (!(p->swap_map[offset] -= count)) {
 			if (offset < p->lowest_bit)
 				p->lowest_bit = offset;
 			if (offset > p->highest_bit)
@@ -170,6 +179,9 @@
 	goto out;
 bad_free:
 	printk("VM: Bad swap entry %08lx\n", entry.val);
+	goto out;
+bad_count:
+	printk(KERN_ERR "VM: Bad count %hd current count %hd\n", count, p->swap_map[offset]);
 	goto out;
 }
 
diff -u --recursive --new-file v2.3.26/linux/mm/vmalloc.c linux/mm/vmalloc.c
--- v2.3.26/linux/mm/vmalloc.c	Wed Oct 27 16:34:12 1999
+++ linux/mm/vmalloc.c	Thu Nov 11 10:33:42 1999
@@ -10,7 +10,7 @@
 
 #include <asm/uaccess.h>
 
-static struct vm_struct * vmlist = NULL;
+struct vm_struct * vmlist = NULL;
 
 static inline void free_area_pte(pmd_t * pmd, unsigned long address, unsigned long size)
 {
@@ -97,7 +97,7 @@
 		struct page * page;
 		if (!pte_none(*pte))
 			printk(KERN_ERR "alloc_area_pte: page already exists\n");
-		page = get_free_highpage(GFP_KERNEL|__GFP_HIGHMEM);
+		page = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
 		if (!page)
 			return -ENOMEM;
 		set_pte(pte, mk_pte(page, PAGE_KERNEL));
@@ -204,7 +204,7 @@
 	struct vm_struct *area;
 
 	size = PAGE_ALIGN(size);
-	if (!size || size > (max_mapnr << PAGE_SHIFT)) {
+	if (!size || (size >> PAGE_SHIFT) > max_mapnr) {
 		BUG();
 		return NULL;
 	}
diff -u --recursive --new-file v2.3.26/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.3.26/linux/mm/vmscan.c	Mon Nov  1 13:56:27 1999
+++ linux/mm/vmscan.c	Wed Nov 10 09:13:07 1999
@@ -503,7 +503,7 @@
 		do {
 			/* kswapd is critical to provide GFP_ATOMIC
 			   allocations (not GFP_HIGHMEM ones). */
-			if (nr_free_pages - nr_free_highpages >= freepages.high)
+			if (nr_free_buffer_pages() >= freepages.high)
 				break;
 
 			if (!do_try_to_free_pages(GFP_KSWAPD))
diff -u --recursive --new-file v2.3.26/linux/net/core/dev.c linux/net/core/dev.c
--- v2.3.26/linux/net/core/dev.c	Mon Nov  1 13:56:27 1999
+++ linux/net/core/dev.c	Tue Nov  9 11:55:53 1999
@@ -354,14 +354,18 @@
 int dev_alloc_name(struct net_device *dev, const char *name)
 {
 	int i;
+	char buf[32];
 	/*
 	 *	If you need over 100 please also fix the algorithm...
 	 */
 	for(i=0;i<100;i++)
 	{
-		sprintf(dev->name,name,i);
-		if(__dev_get_by_name(dev->name)==NULL)
+		sprintf(buf,name,i);
+		if(__dev_get_by_name(buf)==NULL)
+		{
+			strcpy(dev->name, buf);
 			return i;
+		}
 	}
 	return -ENFILE;	/* Over 100 of the things .. bail out! */
 }
@@ -1994,19 +1998,9 @@
  *	present) and leaves us with a valid list of present and active devices.
  *
  */
-extern int lance_init(void);
-extern int bpq_init(void);
-extern int scc_init(void);
-extern void sdla_setup(void);
-extern void dlci_setup(void);
-extern int dmascc_init(void);
 
-extern int lapbeth_init(void);
-extern void arcnet_init(void);
+extern void net_device_init(void);
 extern void ip_auto_config(void);
-#ifdef CONFIG_8xx
-extern int cpm_enet_init(void);
-#endif /* CONFIG_8xx */
 
 int __init net_dev_init(void)
 {
@@ -2030,51 +2024,6 @@
 	br_init();
 #endif	
 	
-	/*
-	 * This is Very Ugly(tm).
-	 *
-	 * Some devices want to be initialized early..
-	 */
-
-#if defined(CONFIG_SCC)
-	scc_init();
-#endif
-#if defined(CONFIG_DMASCC)
-	dmascc_init();
-#endif	
-#if defined(CONFIG_BPQETHER)
-	bpq_init();
-#endif
-#if defined(CONFIG_DLCI)
-	dlci_setup();
-#endif
-#if defined(CONFIG_SDLA)
-	sdla_setup();
-#endif
-#if defined(CONFIG_LAPBETHER)
-	lapbeth_init();
-#endif
-#if defined(CONFIG_PLIP)
-	plip_init();
-#endif
-#if defined(CONFIG_ARCNET)
-	arcnet_init();
-#endif
-#if defined(CONFIG_8xx)
-        cpm_enet_init();
-#endif
-	/*
-	 *	SLHC if present needs attaching so other people see it
-	 *	even if not opened.
-	 */
-	 
-#ifdef CONFIG_INET	 
-#if (defined(CONFIG_SLIP) && defined(CONFIG_SLIP_COMPRESSED)) \
-	 || defined(CONFIG_PPP) \
-    || (defined(CONFIG_ISDN) && defined(CONFIG_ISDN_PPP))
-	slhc_install();
-#endif	
-#endif
 
 #ifdef CONFIG_NET_PROFILE
 	net_profile_init();
@@ -2101,6 +2050,12 @@
 		dev->xmit_lock_owner = -1;
 		dev->iflink = -1;
 		dev_hold(dev);
+		/*
+		 *	We can allocate the name ahead of time. If the
+		 *	init fails the name will be reissued correctly.
+		 */
+		if (strchr(dev->name, '%'))
+			dev_alloc_name(dev, dev->name);
 		if (dev->init && dev->init(dev)) {
 			/*
 			 *	It failed to come up. Unhook it.
@@ -2135,6 +2090,12 @@
 
 	dst_init();
 	dev_mcast_init();
+
+	/*
+	 *	Initialise network devices
+	 */
+	 
+	net_device_init();
 
 #ifdef CONFIG_IP_PNP
 	ip_auto_config();
diff -u --recursive --new-file v2.3.26/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.3.26/linux/net/ipv4/tcp_input.c	Mon Oct 11 15:38:15 1999
+++ linux/net/ipv4/tcp_input.c	Thu Nov 11 15:48:50 1999
@@ -1401,11 +1401,6 @@
 
 	tcp_send_ack(sk);
 
-	if (!sk->dead) {
-		wake_up_interruptible(sk->sleep);
-		sock_wake_async(sk->socket, 1, POLL_HUP);
-	}
-
 	switch(sk->state) {
 		case TCP_SYN_RECV:
 		case TCP_ESTABLISHED:
@@ -1440,7 +1435,11 @@
 			 */
 			printk("tcp_fin: Impossible, sk->state=%d\n", sk->state);
 			break;
-	};
+	}
+	if (!sk->dead) {
+		wake_up_interruptible(sk->sleep);
+		sock_wake_async(sk->socket, 1, POLL_HUP);
+	}
 }
 
 /* These routines update the SACK block as out-of-order packets arrive or
diff -u --recursive --new-file v2.3.26/linux/net/irda/irmod.c linux/net/irda/irmod.c
--- v2.3.26/linux/net/irda/irmod.c	Sun Nov  7 16:37:34 1999
+++ linux/net/irda/irmod.c	Thu Nov 11 16:57:31 1999
@@ -525,24 +525,6 @@
 #endif
 }
 
-/*
- * Function irda_proc_modcount (inode, fill)
- *
- *    Use by the proc file system functions to prevent the irda module
- *    being removed while the use is standing in the net/irda directory
- */
-void irda_proc_modcount(struct inode *inode, int fill)
-{
-#ifdef MODULE
-#ifdef CONFIG_PROC_FS
-	if (fill)
-		MOD_INC_USE_COUNT;
-	else
-		MOD_DEC_USE_COUNT;
-#endif /* CONFIG_PROC_FS */
-#endif /* MODULE */
-}
-
 #ifdef MODULE
 
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
diff -u --recursive --new-file v2.3.26/linux/net/irda/irproc.c linux/net/irda/irproc.c
--- v2.3.26/linux/net/irda/irproc.c	Mon Nov  1 13:56:27 1999
+++ linux/net/irda/irproc.c	Thu Nov 11 16:57:31 1999
@@ -25,6 +25,7 @@
 
 #include <linux/miscdevice.h>
 #include <linux/proc_fs.h>
+#include <linux/module.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
@@ -70,9 +71,7 @@
 	int i;
 
 	proc_irda = create_proc_entry("net/irda", S_IFDIR, NULL);
-#ifdef MODULE
-	proc_irda->fill_inode = &irda_proc_modcount;
-#endif /* MODULE */
+	proc_irda->owner = THIS_MODULE;
 
 	for (i=0;i<IRDA_ENTRIES_NUM;i++)
 		create_proc_info_entry(dir[i].name,0,proc_irda,dir[i].fn);
diff -u --recursive --new-file v2.3.26/linux/net/sunrpc/stats.c linux/net/sunrpc/stats.c
--- v2.3.26/linux/net/sunrpc/stats.c	Mon Nov  1 13:56:27 1999
+++ linux/net/sunrpc/stats.c	Thu Nov 11 16:57:31 1999
@@ -164,9 +164,7 @@
 		struct proc_dir_entry *ent;
 		ent = create_proc_entry("net/rpc", S_IFDIR, 0);
 		if (ent) {
-#ifdef MODULE
-			ent->fill_inode = rpc_modcount;
-#endif
+			ent->owner = THIS_MODULE;
 			proc_net_rpc = ent;
 		}
 	}
@@ -183,21 +181,6 @@
 }
 
 #ifdef MODULE
-/*
- * This is called as the proc_dir_entry fill_inode function
- * when an inode is going into or out of service (fill == 1
- * or 0 respectively).
- *
- * We use it here to keep the module from being unloaded
- * while /proc inodes are in use.
- */
-void rpc_modcount(struct inode *inode, int fill)
-{
-	if (fill)
-		MOD_INC_USE_COUNT;
-	else
-		MOD_DEC_USE_COUNT;
-}
 
 int
 init_module(void)
diff -u --recursive --new-file v2.3.26/linux/net/sunrpc/sysctl.c linux/net/sunrpc/sysctl.c
--- v2.3.26/linux/net/sunrpc/sysctl.c	Thu Jan  7 09:28:47 1999
+++ linux/net/sunrpc/sysctl.c	Thu Nov 11 16:57:31 1999
@@ -14,6 +14,7 @@
 #include <linux/ctype.h>
 #include <linux/fs.h>
 #include <linux/sysctl.h>
+#include <linux/module.h>
 
 #include <asm/uaccess.h>
 #include <linux/sunrpc/types.h>
@@ -38,11 +39,9 @@
 {
 	if (!sunrpc_table_header) {
 		sunrpc_table_header = register_sysctl_table(sunrpc_table, 1);
-#ifdef MODULE
 #ifdef CONFIG_PROC_FS
 		if (sunrpc_table[0].de)
-			sunrpc_table[0].de->fill_inode = rpc_modcount;
-#endif
+			sunrpc_table[0].de->owner = THIS_MODULE;
 #endif
 	}
 			
diff -u --recursive --new-file v2.3.26/linux/scripts/usb/procusb linux/scripts/usb/procusb
--- v2.3.26/linux/scripts/usb/procusb	Wed Dec 31 16:00:00 1969
+++ linux/scripts/usb/procusb	Wed Nov 10 15:11:35 1999
@@ -0,0 +1,44 @@
+#!/usr/bin/perl
+
+# Reads /proc/bus/usb/devices and selectively lists and/or
+# interprets it.
+
+$DEVFILENAME = "/proc/bus/usb/devices";
+$PROGNAME = $0;
+
+print "\n";
+
+$TAGS = $ARGV[0];		# save user TAGS
+if (length ($TAGS) == 0)
+{
+	print "usage: $PROGNAME tags\n";
+	print "  where 'tags' can be any number of 'TBDPCIE' or 'A(LL)'\n";
+	exit 1;
+}
+
+$ALL = ($TAGS =~ /all/i) || ($TAGS =~ /a/i);
+
+# TBD: Check that $TAGS is valid.
+if (! $ALL)
+{
+}
+
+if (! open (DEVNUM, "<$DEVFILENAME"))
+{
+	print "$PROGNAME: cannot open '$DEVFILENAME'\n";
+	exit 1;
+}
+
+while ($line = <DEVNUM>)	# read a text line from DEVNUM
+{
+	if (($ALL) || ($line =~ /^[$TAGS]:/i))	# any of TAGS at beg. of line?
+	{
+		print "$line";	# still has newline char on it
+				# TBD: add more/paging functionality.
+	}
+} # end while DEVNUM
+
+close (DEVNUM);
+print "\n";
+
+# END.
diff -u --recursive --new-file v2.3.26/linux/scripts/usb/usbtree linux/scripts/usb/usbtree
--- v2.3.26/linux/scripts/usb/usbtree	Wed Dec 31 16:00:00 1969
+++ linux/scripts/usb/usbtree	Mon Nov  8 13:27:10 1999
@@ -0,0 +1,90 @@
+#!/usr/bin/perl
+
+# Reads /proc/bus/usb/devices and selectively lists and/or
+# interprets it.
+
+$DEVFILENAME = "/proc/bus/usb/devices";
+$PROGNAME = $0;
+
+print "\n";
+
+$TAGS = $ARGV[0];		# save user TAGS
+if (length ($TAGS) == 0)
+{
+}
+
+if (! open (DEVNUM, "<$DEVFILENAME"))
+{
+	print "$PROGNAME: cannot open '$DEVFILENAME'\n";
+	exit 1;
+}
+
+while ($line = <DEVNUM>)	# read a text line from DEVNUM
+{
+	# skip all lines except those that begin with "T:" or "D:" or "I:".
+	if (($line !~ "^T:") && ($line !~ "^I:") && ($line !~ "^D:"))
+	{
+		next;	# to the next line
+	}
+
+	chomp $line;		# remove line endings
+
+	# First convert '=' signs to spaces.
+	$line =~ tr/=/ /;
+
+	# and convert all ( and ) to spaces.
+	$line =~ tr/(/ /;
+	$line =~ tr/)/ /;
+
+	# split the line at spaces.
+	@fields = split / +/, $line;
+
+	if ($line =~ "^T:")
+	{
+		# split yields: $level, $port, $devnum, $speed, $maxchild.
+
+		$level  = @fields [2];
+		$port   = @fields [6];
+		$devnum = @fields [10];
+		$speed  = @fields [12];
+		$maxchild = @fields [14];
+		$devclass = "?";
+		$intclass = "?";
+		$driver   = "?";
+
+		if (($devnum == -1) && ($level == 0))
+		{
+			print "/:  Dev# -1, root hub/$maxchild ports, $speed Mbps\n";
+		}
+		next;
+	} # end T: line
+	elsif ($line =~ "^D:")
+	{ # for D: line
+		$devclass = @fields [5];
+		next;
+	}
+	else
+	{ # for I: line
+		$intclass = @fields [9];
+		$ifnum    = @fields [2];
+		$driver   = @fields [15];
+	} # end I: line
+
+	if ($level > 1)
+	{
+		$temp = $level;
+		while ($temp > 1)
+		{
+			print "    ";
+			$temp--;
+		}
+	}
+	
+	print sprintf ("|__ Port# $port: Dev# $devnum, If# $ifnum, Class=$devclass, Ifc=$intclass, Driver=$driver%s, $speed Mbps\n",
+		($maxchild == 0) ? "" : ("/" . $maxchild . " ports"));
+} # end while DEVNUM
+
+close (DEVNUM);
+print "\n";
+
+# END.
